diff --git a/src/unix/fs.c b/src/unix/fs.c index 51919ce9..b6d9732c 100644 --- a/src/unix/fs.c +++ b/src/unix/fs.c @@ -23,6 +23,7 @@ #include "internal.h" #include "eio.h" +#include #include #include #include @@ -30,6 +31,9 @@ static void uv_fs_req_init(uv_fs_t* req, uv_fs_type fs_type, uv_fs_cb cb) { + /* Make sure the thread pool is initialized. */ + uv_eio_init(); + uv__req_init((uv_req_t*) req); req->type = UV_FS; req->fs_type = fs_type; @@ -42,7 +46,6 @@ static void uv_fs_req_init(uv_fs_t* req, uv_fs_type fs_type, uv_fs_cb cb) { void uv_fs_req_cleanup(uv_fs_t* req) { - assert(0 && "implement me"); } @@ -51,6 +54,9 @@ static int uv__fs_after(eio_req* eio) { assert(req->cb); req->result = req->eio->result; + req->errorno = req->eio->errorno; + + uv_unref(); req->eio = NULL; /* Freed by libeio */ req->cb(req); @@ -62,6 +68,7 @@ int uv_fs_close(uv_fs_t* req, uv_file file, uv_fs_cb cb) { uv_fs_req_init(req, UV_FS_CLOSE, cb); if (cb) { /* async */ + uv_ref(); req->eio = eio_close(file, EIO_PRI_DEFAULT, uv__fs_after, req); if (!req->eio) { uv_err_new(NULL, ENOMEM); @@ -85,6 +92,7 @@ int uv_fs_open(uv_fs_t* req, const char* path, int flags, int mode, if (cb) { /* async */ + uv_ref(); req->eio = eio_open(path, flags, mode, EIO_PRI_DEFAULT, uv__fs_after, req); if (!req->eio) { uv_err_new(NULL, ENOMEM); @@ -112,6 +120,7 @@ int uv_fs_read(uv_fs_t* req, uv_file fd, void* buf, size_t length, if (cb) { /* async */ + uv_ref(); req->eio = eio_read(fd, buf, length, offset, EIO_PRI_DEFAULT, uv__fs_after, req); @@ -141,6 +150,7 @@ int uv_fs_unlink(uv_fs_t* req, const char* path, uv_fs_cb cb) { if (cb) { /* async */ + uv_ref(); req->eio = eio_unlink(path, EIO_PRI_DEFAULT, uv__fs_after, req); if (!req->eio) { uv_err_new(NULL, ENOMEM); @@ -161,9 +171,33 @@ int uv_fs_unlink(uv_fs_t* req, const char* path, uv_fs_cb cb) { } -int uv_fs_write(uv_fs_t* req, uv_file file, void* buf, size_t length, off_t offset, uv_fs_cb cb) { - assert(0 && "implement me"); - return -1; +int uv_fs_write(uv_fs_t* req, uv_file file, void* buf, size_t length, + off_t offset, uv_fs_cb cb) { + uv_fs_req_init(req, UV_FS_WRITE, cb); + + if (cb) { + /* async */ + uv_ref(); + req->eio = eio_write(file, buf, length, offset, EIO_PRI_DEFAULT, + uv__fs_after, req); + if (!req->eio) { + uv_err_new(NULL, ENOMEM); + return -1; + } + + } else { + /* sync */ + req->result = offset < 0 ? + write(file, buf, length) : + pwrite(file, buf, length, offset); + + if (req->result < 0) { + uv_err_new(NULL, errno); + return -1; + } + } + + return 0; } @@ -197,27 +231,108 @@ int uv_fs_fstat(uv_fs_t* req, uv_file file, uv_fs_cb cb) { } -int uv_fs_rename(uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb) { - assert(0 && "implement me"); - return -1; +int uv_fs_rename(uv_fs_t* req, const char* path, const char* new_path, + uv_fs_cb cb) { + uv_fs_req_init(req, UV_FS_RENAME, cb); + + if (cb) { + /* async */ + uv_ref(); + req->eio = eio_rename(path, new_path, EIO_PRI_DEFAULT, uv__fs_after, req); + if (!req->eio) { + uv_err_new(NULL, ENOMEM); + return -1; + } + + } else { + /* sync */ + req->result = rename(path, new_path); + + if (req->result) { + uv_err_new(NULL, errno); + return -1; + } + } + + return 0; } int uv_fs_fsync(uv_fs_t* req, uv_file file, uv_fs_cb cb) { - assert(0 && "implement me"); - return -1; + uv_fs_req_init(req, UV_FS_FSYNC, cb); + + if (cb) { + /* async */ + uv_ref(); + req->eio = eio_fsync(file, EIO_PRI_DEFAULT, uv__fs_after, req); + if (!req->eio) { + uv_err_new(NULL, ENOMEM); + return -1; + } + + } else { + /* sync */ + req->result = fsync(file); + + if (req->result) { + uv_err_new(NULL, errno); + return -1; + } + } + + return 0; } int uv_fs_fdatasync(uv_fs_t* req, uv_file file, uv_fs_cb cb) { - assert(0 && "implement me"); - return -1; + uv_fs_req_init(req, UV_FS_FDATASYNC, cb); + + if (cb) { + /* async */ + uv_ref(); + req->eio = eio_fdatasync(file, EIO_PRI_DEFAULT, uv__fs_after, req); + if (!req->eio) { + uv_err_new(NULL, ENOMEM); + return -1; + } + + } else { + /* sync */ + req->result = fdatasync(file); + + if (req->result) { + uv_err_new(NULL, errno); + return -1; + } + } + + return 0; } int uv_fs_ftruncate(uv_fs_t* req, uv_file file, off_t offset, uv_fs_cb cb) { - assert(0 && "implement me"); - return -1; + uv_fs_req_init(req, UV_FS_FTRUNCATE, cb); + + if (cb) { + /* async */ + uv_ref(); + req->eio = eio_ftruncate(file, offset, EIO_PRI_DEFAULT, uv__fs_after, req); + if (!req->eio) { + uv_err_new(NULL, ENOMEM); + return -1; + } + + } else { + /* sync */ + req->result = ftruncate(file, offset); + + if (req->result) { + uv_err_new(NULL, errno); + return -1; + } + } + + return 0; } diff --git a/test/test-fs.c b/test/test-fs.c index 9be09e46..d7f77b11 100644 --- a/test/test-fs.c +++ b/test/test-fs.c @@ -25,15 +25,18 @@ #include "uv.h" #include "task.h" -#if !UNIX -# include -# include -#endif - #include /* memset */ #include #include + +#if !UNIX +# include +# include +# define unlink _unlink +# define rmdir _rmdir +#endif + static int close_cb_count; static int create_cb_count; static int open_cb_count; @@ -124,7 +127,11 @@ static void open_cb(uv_fs_t* req) { int r; ASSERT(req == &open_req1); ASSERT(req->fs_type == UV_FS_OPEN); - ASSERT(req->result != -1); + if (req->result < 0) { + /* TODO get error with uv_last_error() */ + fprintf(stderr, "async open error: %d\n", req->errorno); + ASSERT(0); + } open_cb_count++; uv_fs_req_cleanup(req); memset(buf, 0, sizeof(buf)); @@ -172,7 +179,8 @@ static void create_cb(uv_fs_t* req) { ASSERT(req->result != -1); create_cb_count++; uv_fs_req_cleanup(req); - r = uv_fs_write(&write_req, req->result, test_buf, sizeof(test_buf), -1, write_cb); + r = uv_fs_write(&write_req, req->result, test_buf, sizeof(test_buf), -1, + write_cb); } @@ -240,16 +248,13 @@ TEST_IMPL(fs_file_async) { int r; /* Setup. */ -#if UNIX - ASSERT(0 && "implement me"); -#else - _unlink("test_file"); - _unlink("test_file2"); -#endif + unlink("test_file"); + unlink("test_file2"); uv_init(); - r = uv_fs_open(&open_req1, "test_file", O_WRONLY | O_CREAT, S_IWRITE, create_cb); + r = uv_fs_open(&open_req1, "test_file", O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR, + create_cb); ASSERT(r == 0); uv_run(); @@ -293,13 +298,9 @@ TEST_IMPL(fs_file_async) { ASSERT(write_cb_count == 1); ASSERT(ftruncate_cb_count == 1); -#if UNIX - ASSERT(0 && "implement me"); -#else /* Cleanup. */ - _unlink("test_file"); - _unlink("test_file2"); -#endif + unlink("test_file"); + unlink("test_file2"); return 0; } @@ -308,22 +309,20 @@ TEST_IMPL(fs_file_async) { TEST_IMPL(fs_file_sync) { int r; -#if UNIX - ASSERT(0 && "implement me"); -#else /* Setup. */ - _unlink("test_file"); - _unlink("test_file2"); -#endif + unlink("test_file"); + unlink("test_file2"); uv_init(); - r = uv_fs_open(&open_req1, "test_file", O_WRONLY | O_CREAT, S_IWRITE | S_IREAD, NULL); + r = uv_fs_open(&open_req1, "test_file", O_WRONLY | O_CREAT, + S_IWRITE | S_IREAD, NULL); ASSERT(r == 0); ASSERT(open_req1.result != -1); uv_fs_req_cleanup(&open_req1); - r = uv_fs_write(&write_req, open_req1.result, test_buf, sizeof(test_buf), -1, NULL); + r = uv_fs_write(&write_req, open_req1.result, test_buf, sizeof(test_buf), -1, + NULL); ASSERT(r == 0); ASSERT(write_req.result != -1); uv_fs_req_cleanup(&write_req); @@ -382,12 +381,8 @@ TEST_IMPL(fs_file_sync) { uv_fs_req_cleanup(&unlink_req); /* Cleanup */ -#if UNIX - ASSERT(0 && "implement me"); -#else - _unlink("test_file"); - _unlink("test_file2"); -#endif + unlink("test_file"); + unlink("test_file2"); return 0; } @@ -397,13 +392,9 @@ TEST_IMPL(fs_async_dir) { int r; /* Setup */ -#if UNIX - ASSERT(0 && "implement me"); -#else - _unlink("test_dir/file1"); - _unlink("test_dir/file2"); - _rmdir("test_dir"); -#endif + unlink("test_dir/file1"); + unlink("test_dir/file2"); + rmdir("test_dir"); uv_init(); @@ -414,14 +405,16 @@ TEST_IMPL(fs_async_dir) { ASSERT(mkdir_cb_count == 1); /* Create 2 files synchronously. */ - r = uv_fs_open(&open_req1, "test_dir/file1", O_WRONLY | O_CREAT, S_IWRITE | S_IREAD, NULL); + r = uv_fs_open(&open_req1, "test_dir/file1", O_WRONLY | O_CREAT, + S_IWRITE | S_IREAD, NULL); ASSERT(r == 0); uv_fs_req_cleanup(&open_req1); r = uv_fs_close(&close_req, open_req1.result, NULL); ASSERT(r == 0); uv_fs_req_cleanup(&close_req); - r = uv_fs_open(&open_req1, "test_dir/file2", O_WRONLY | O_CREAT, S_IWRITE | S_IREAD, NULL); + r = uv_fs_open(&open_req1, "test_dir/file2", O_WRONLY | O_CREAT, + S_IWRITE | S_IREAD, NULL); ASSERT(r == 0); uv_fs_req_cleanup(&open_req1); r = uv_fs_close(&close_req, open_req1.result, NULL); @@ -459,13 +452,9 @@ TEST_IMPL(fs_async_dir) { ASSERT(rmdir_cb_count == 1); /* Cleanup */ -#if UNIX - ASSERT(0 && "implement me"); -#else - _unlink("test_dir/file1"); - _unlink("test_dir/file2"); - _rmdir("test_dir"); -#endif + unlink("test_dir/file1"); + unlink("test_dir/file2"); + rmdir("test_dir"); return 0; }