From 79d9f818815b48b5277cd83bb30aa81be1141618 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Tue, 6 Sep 2011 02:52:23 +0200 Subject: [PATCH] unix: implement uv_fs_futime, add tests for uv_fs_utime and uv_fs_futime --- src/unix/fs.c | 26 ++++++++- test/test-fs.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++ test/test-list.h | 6 +- 3 files changed, 169 insertions(+), 2 deletions(-) diff --git a/src/unix/fs.c b/src/unix/fs.c index 506367cd..85cfbfba 100644 --- a/src/unix/fs.c +++ b/src/unix/fs.c @@ -472,10 +472,34 @@ int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, } +#if defined(HAVE_FUTIMES) +static int _futime(const uv_file file, double atime, double mtime) { + struct timeval tv[2]; + + /* FIXME possible loss of precision in floating-point arithmetic? */ + tv[0].tv_sec = atime; + tv[0].tv_usec = (unsigned long)(atime * 1000000) % 1000000; + + tv[1].tv_sec = mtime; + tv[1].tv_usec = (unsigned long)(mtime * 1000000) % 1000000; + + return futimes(file, tv); +} +#endif + + int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, double atime, double mtime, uv_fs_cb cb) { - assert(0 && "implement me"); + const char* path = NULL; + + uv_fs_req_init(loop, req, UV_FS_FUTIME, path, cb); + +#if defined(HAVE_FUTIMES) + WRAP_EIO(UV_FS_FUTIME, eio_futime, _futime, ARGS3(file, atime, mtime)) +#else + uv_err_new(loop, ENOSYS); return -1; +#endif } diff --git a/test/test-fs.c b/test/test-fs.c index c3712def..dfa664ff 100644 --- a/test/test-fs.c +++ b/test/test-fs.c @@ -43,6 +43,14 @@ # define close _close #endif + +typedef struct { + const char* path; + double atime; + double mtime; +} utime_check_t; + + static int close_cb_count; static int create_cb_count; static int open_cb_count; @@ -66,6 +74,8 @@ static int fchown_cb_count; static int link_cb_count; static int symlink_cb_count; static int readlink_cb_count; +static int utime_cb_count; +static int futime_cb_count; static uv_loop_t* loop; @@ -84,6 +94,8 @@ static uv_fs_t fsync_req; static uv_fs_t fdatasync_req; static uv_fs_t ftruncate_req; static uv_fs_t sendfile_req; +static uv_fs_t utime_req; +static uv_fs_t futime_req; static char buf[32]; static char test_buf[] = "test-buffer\n"; @@ -395,6 +407,40 @@ TEST_IMPL(fs_file_noent) { } +static void check_utime(uv_fs_t* req) { + utime_check_t* checkme; + int r; + + ASSERT(req->result == 0); + + checkme = req->data; + uv_fs_req_cleanup(req); + + r = uv_fs_stat(loop, req, checkme->path, NULL); + ASSERT(r == 0); + ASSERT(req->result == 0); + ASSERT(req->statbuf.st_atim.tv_sec == checkme->atime); + ASSERT(req->statbuf.st_atim.tv_nsec == 0); /* FIXME check sub-second precision */ + ASSERT(req->statbuf.st_mtim.tv_sec == checkme->mtime); + ASSERT(req->statbuf.st_mtim.tv_nsec == 0); /* FIXME check sub-second precision */ + uv_fs_req_cleanup(req); +} + + +static void utime_cb(uv_fs_t* req) { + ASSERT(req == &utime_req); + ASSERT(req->fs_type == UV_FS_UTIME); + utime_cb_count++; +} + + +static void futime_cb(uv_fs_t* req) { + ASSERT(req == &futime_req); + ASSERT(req->fs_type == UV_FS_FUTIME); + futime_cb_count++; +} + + TEST_IMPL(fs_file_async) { int r; @@ -1103,3 +1149,96 @@ TEST_IMPL(fs_symlink) { return 0; } + + +TEST_IMPL(fs_utime) { + utime_check_t checkme; + const char* path = "."; + double atime; + double mtime; + uv_fs_t req; + int r; + + uv_init(); + loop = uv_default_loop(); + + atime = mtime = 400497753; /* 1982-09-10 11:22:33 */ + + r = uv_fs_utime(loop, &req, path, atime, mtime, NULL); + ASSERT(r == 0); + ASSERT(utime_req.result == 0); + uv_fs_req_cleanup(&req); + + r = uv_fs_stat(loop, &req, path, NULL); + ASSERT(r == 0); + ASSERT(req.result == 0); + ASSERT(req.statbuf.st_atim.tv_sec == atime); + ASSERT(req.statbuf.st_atim.tv_nsec == 0); + ASSERT(req.statbuf.st_mtim.tv_sec == mtime); + ASSERT(req.statbuf.st_mtim.tv_nsec == 0); + uv_fs_req_cleanup(&req); + + atime = mtime = 1291404900; /* 2010-12-03 20:35:00 - mees <3 */ + checkme.path = path; + checkme.atime = atime; + checkme.mtime = mtime; + + /* async utime */ + utime_req.data = &checkme; + r = uv_fs_utime(loop, &utime_req, path, atime, mtime, utime_cb); + ASSERT(r == 0); + uv_run(loop); + ASSERT(utime_cb_count == 1); + + return 0; +} + + +TEST_IMPL(fs_futime) { + utime_check_t checkme; + const char* path = "."; + double atime; + double mtime; + uv_file file; + uv_fs_t req; + int r; + + uv_init(); + loop = uv_default_loop(); + + atime = mtime = 400497753; /* 1982-09-10 11:22:33 */ + + r = uv_fs_open(loop, &req, path, O_RDONLY, 0, NULL); + ASSERT(r == 0); + ASSERT(req.result != -1); + file = req.result; /* FIXME probably not how it's supposed to be used */ + uv_fs_req_cleanup(&req); + + r = uv_fs_futime(loop, &req, file, atime, mtime, NULL); + ASSERT(r == 0); + ASSERT(req.result == 0); + uv_fs_req_cleanup(&req); + + r = uv_fs_stat(loop, &req, path, NULL); + ASSERT(r == 0); + ASSERT(req.result == 0); + ASSERT(req.statbuf.st_atim.tv_sec == atime); + ASSERT(req.statbuf.st_atim.tv_nsec == 0); /* FIXME check sub-second precision */ + ASSERT(req.statbuf.st_mtim.tv_sec == mtime); + ASSERT(req.statbuf.st_mtim.tv_nsec == 0); /* FIXME check sub-second precision */ + uv_fs_req_cleanup(&req); + + atime = mtime = 1291404900; /* 2010-12-03 20:35:00 - mees <3 */ + checkme.path = path; + checkme.atime = atime; + checkme.mtime = mtime; + + /* async futime */ + futime_req.data = &checkme; + r = uv_fs_futime(loop, &futime_req, file, atime, mtime, futime_cb); + ASSERT(r == 0); + uv_run(loop); + ASSERT(futime_cb_count == 1); + + return 0; +} diff --git a/test/test-list.h b/test/test-list.h index 9d4a57f6..0c743105 100644 --- a/test/test-list.h +++ b/test/test-list.h @@ -82,6 +82,8 @@ TEST_DECLARE (fs_chmod) TEST_DECLARE (fs_chown) TEST_DECLARE (fs_link) TEST_DECLARE (fs_symlink) +TEST_DECLARE (fs_utime) +TEST_DECLARE (fs_futime) TEST_DECLARE (threadpool_queue_work_simple) #ifdef _WIN32 TEST_DECLARE (spawn_detect_pipe_name_collisions_on_windows) @@ -189,7 +191,9 @@ TASK_LIST_START TEST_ENTRY (fs_fstat) TEST_ENTRY (fs_chmod) TEST_ENTRY (fs_chown) - TEST_ENTRY (fs_link) + TEST_ENTRY (fs_utime) + TEST_ENTRY (fs_futime) + TEST_ENTRY (fs_symlink) TEST_ENTRY (fs_symlink) TEST_ENTRY (threadpool_queue_work_simple)