fs: add uv_fs_utime_ex and uv_fs_futime_ex
These new functions behave identicaly to uv_fs_utime and uv_fs_futime respectively for every OS except macOS and Windows. For macOS and Windows, these new APIs will allow the birth/creation time to be set. Fixes: https://github.com/libuv/libuv/issues/499 PR-URL: https://github.com/libuv/libuv/pull/590 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
This commit is contained in:
parent
d5870c71ea
commit
c51ead5c70
@ -298,9 +298,18 @@ API
|
||||
AIX: This function only works for AIX 7.1 and newer. It can still be called on older
|
||||
versions but will return ``UV_ENOSYS``.
|
||||
|
||||
.. versionchanged:: 1.10.0 sub-second precission is supported on Windows
|
||||
.. versionchanged:: 1.10.0 sub-second precision is supported on Windows
|
||||
.. versionchanged:: 2.0.0 replace uv_file with uv_os_fd_t
|
||||
|
||||
.. c:function:: int uv_fs_utime_ex(uv_loop_t* loop, uv_fs_t* req, const char* path, double btime, double atime, double mtime, uv_fs_cb cb)
|
||||
.. c:function:: int uv_fs_futime_ex(uv_loop_t* loop, uv_fs_t* req, uv_file file, double btime, double atime, double mtime, uv_fs_cb cb)
|
||||
|
||||
Equivalent to :c:func:`uv_fs_utime` and :c:func:`uv_fs_futime` except on
|
||||
macOS and Windows, in which case these variants also allow the
|
||||
birth/creation time to be set.
|
||||
|
||||
.. versionadded:: 2.0.0
|
||||
|
||||
.. c:function:: int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb)
|
||||
|
||||
Equivalent to :man:`link(2)`.
|
||||
|
||||
14
include/uv.h
14
include/uv.h
@ -1333,12 +1333,26 @@ UV_EXTERN int uv_fs_utime(uv_loop_t* loop,
|
||||
double atime,
|
||||
double mtime,
|
||||
uv_fs_cb cb);
|
||||
UV_EXTERN int uv_fs_utime_ex(uv_loop_t* loop,
|
||||
uv_fs_t* req,
|
||||
const char* path,
|
||||
double btime,
|
||||
double atime,
|
||||
double mtime,
|
||||
uv_fs_cb cb);
|
||||
UV_EXTERN int uv_fs_futime(uv_loop_t* loop,
|
||||
uv_fs_t* req,
|
||||
uv_os_fd_t file,
|
||||
double atime,
|
||||
double mtime,
|
||||
uv_fs_cb cb);
|
||||
UV_EXTERN int uv_fs_futime_ex(uv_loop_t* loop,
|
||||
uv_fs_t* req,
|
||||
uv_os_fd_t file,
|
||||
double btime,
|
||||
double atime,
|
||||
double mtime,
|
||||
uv_fs_cb cb);
|
||||
UV_EXTERN int uv_fs_lstat(uv_loop_t* loop,
|
||||
uv_fs_t* req,
|
||||
const char* path,
|
||||
|
||||
@ -339,6 +339,7 @@ typedef struct {
|
||||
off_t off; \
|
||||
uv_uid_t uid; \
|
||||
uv_gid_t gid; \
|
||||
double btime; \
|
||||
double atime; \
|
||||
double mtime; \
|
||||
struct uv__work work_req; \
|
||||
|
||||
@ -468,6 +468,7 @@ typedef struct {
|
||||
uv_buf_t bufsml[4]; \
|
||||
} info; \
|
||||
struct { \
|
||||
double btime; \
|
||||
double atime; \
|
||||
double mtime; \
|
||||
} time; \
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
#include "internal.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -62,6 +63,49 @@
|
||||
|
||||
#if defined(__APPLE__)
|
||||
# include <copyfile.h>
|
||||
# include <sys/attr.h>
|
||||
|
||||
static void uv__prepare_setattrlist_args(uv_fs_t* req,
|
||||
struct attrlist* attr_list,
|
||||
struct timespec (*times)[3],
|
||||
unsigned int* size) {
|
||||
memset(attr_list, 0, sizeof(*attr_list));
|
||||
memset(times, 0, sizeof(*times));
|
||||
|
||||
attr_list->bitmapcount = ATTR_BIT_MAP_COUNT;
|
||||
|
||||
*size = 0;
|
||||
|
||||
if (!isnan(req->btime)) {
|
||||
attr_list->commonattr |= ATTR_CMN_CRTIME;
|
||||
|
||||
(*times)[*size].tv_sec = req->btime;
|
||||
(*times)[*size].tv_nsec =
|
||||
(unsigned long)(req->btime * 1000000) % 1000000 * 1000;
|
||||
|
||||
++*size;
|
||||
}
|
||||
|
||||
if (!isnan(req->mtime)) {
|
||||
attr_list->commonattr |= ATTR_CMN_MODTIME;
|
||||
|
||||
(*times)[*size].tv_sec = req->mtime;
|
||||
(*times)[*size].tv_nsec =
|
||||
(unsigned long)(req->mtime * 1000000) % 1000000 * 1000;
|
||||
|
||||
++*size;
|
||||
}
|
||||
|
||||
if (!isnan(req->atime)) {
|
||||
attr_list->commonattr |= ATTR_CMN_ACCTIME;
|
||||
|
||||
(*times)[*size].tv_sec = req->atime;
|
||||
(*times)[*size].tv_nsec =
|
||||
(unsigned long)(req->atime * 1000000) % 1000000 * 1000;
|
||||
|
||||
++*size;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#define INIT(subtype) \
|
||||
@ -230,9 +274,15 @@ skip:
|
||||
}
|
||||
|
||||
return r;
|
||||
#elif defined(__APPLE__)
|
||||
struct attrlist attr_list;
|
||||
unsigned i;
|
||||
struct timespec times[3];
|
||||
|
||||
#elif defined(__APPLE__) \
|
||||
|| defined(__DragonFly__) \
|
||||
uv__prepare_setattrlist_args(req, &attr_list, ×, &i);
|
||||
|
||||
return fsetattrlist(req->file, &attr_list, ×, i * sizeof(times[0]), 0);
|
||||
#elif defined(__DragonFly__) \
|
||||
|| defined(__FreeBSD__) \
|
||||
|| defined(__FreeBSD_kernel__) \
|
||||
|| defined(__NetBSD__) \
|
||||
@ -704,10 +754,20 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
|
||||
|
||||
|
||||
static ssize_t uv__fs_utime(uv_fs_t* req) {
|
||||
#if defined(__APPLE__)
|
||||
struct attrlist attr_list;
|
||||
unsigned i;
|
||||
struct timespec times[3];
|
||||
|
||||
uv__prepare_setattrlist_args(req, &attr_list, ×, &i);
|
||||
|
||||
return setattrlist(req->path, &attr_list, ×, i * sizeof(times[0]), 0);
|
||||
#else
|
||||
struct utimbuf buf;
|
||||
buf.actime = req->atime;
|
||||
buf.modtime = req->mtime;
|
||||
return utime(req->path, &buf); /* TODO use utimes() where available */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -1251,8 +1311,20 @@ int uv_fs_futime(uv_loop_t* loop,
|
||||
double atime,
|
||||
double mtime,
|
||||
uv_fs_cb cb) {
|
||||
return uv_fs_futime_ex(loop, req, file, NAN, atime, mtime, cb);
|
||||
}
|
||||
|
||||
|
||||
int uv_fs_futime_ex(uv_loop_t* loop,
|
||||
uv_fs_t* req,
|
||||
uv_os_fd_t file,
|
||||
double btime,
|
||||
double atime,
|
||||
double mtime,
|
||||
uv_fs_cb cb) {
|
||||
INIT(FUTIME);
|
||||
req->file = file;
|
||||
req->btime = btime;
|
||||
req->atime = atime;
|
||||
req->mtime = mtime;
|
||||
POST;
|
||||
@ -1442,8 +1514,20 @@ int uv_fs_utime(uv_loop_t* loop,
|
||||
double atime,
|
||||
double mtime,
|
||||
uv_fs_cb cb) {
|
||||
return uv_fs_utime_ex(loop, req, path, NAN, atime, mtime, cb);
|
||||
}
|
||||
|
||||
|
||||
int uv_fs_utime_ex(uv_loop_t* loop,
|
||||
uv_fs_t* req,
|
||||
const char* path,
|
||||
double btime,
|
||||
double atime,
|
||||
double mtime,
|
||||
uv_fs_cb cb) {
|
||||
INIT(UTIME);
|
||||
PATH;
|
||||
req->btime = btime;
|
||||
req->atime = atime;
|
||||
req->mtime = mtime;
|
||||
POST;
|
||||
|
||||
52
src/win/fs.c
52
src/win/fs.c
@ -25,7 +25,10 @@
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <fcntl.h> /* file constants */
|
||||
#include <math.h>
|
||||
#include <sys/stat.h> /* stat constants */
|
||||
#include <sys/utime.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "uv.h"
|
||||
#include "internal.h"
|
||||
@ -1497,13 +1500,28 @@ static void fs__fchmod(uv_fs_t* req) {
|
||||
}
|
||||
|
||||
|
||||
INLINE static int fs__utime_handle(HANDLE handle, double atime, double mtime) {
|
||||
FILETIME filetime_a, filetime_m;
|
||||
INLINE static int fs__utime_handle(HANDLE handle,
|
||||
double btime,
|
||||
double atime,
|
||||
double mtime) {
|
||||
FILETIME filetime_b;
|
||||
FILETIME filetime_a;
|
||||
FILETIME filetime_m;
|
||||
|
||||
if (isnan(btime)) {
|
||||
filetime_b.dwHighDateTime = 0;
|
||||
filetime_b.dwLowDateTime = 0;
|
||||
} else {
|
||||
TIME_T_TO_FILETIME(btime, &filetime_b);
|
||||
}
|
||||
|
||||
TIME_T_TO_FILETIME(atime, &filetime_a);
|
||||
TIME_T_TO_FILETIME(mtime, &filetime_m);
|
||||
|
||||
if (!SetFileTime(handle, NULL, &filetime_a, &filetime_m)) {
|
||||
if (!SetFileTime(handle,
|
||||
&filetime_b,
|
||||
&filetime_a,
|
||||
&filetime_m)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1527,7 +1545,10 @@ static void fs__utime(uv_fs_t* req) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (fs__utime_handle(handle, req->fs.time.atime, req->fs.time.mtime) != 0) {
|
||||
if (fs__utime_handle(handle,
|
||||
req->fs.time.btime,
|
||||
req->fs.time.atime,
|
||||
req->fs.time.mtime) != 0) {
|
||||
SET_REQ_WIN32_ERROR(req, GetLastError());
|
||||
CloseHandle(handle);
|
||||
return;
|
||||
@ -1543,7 +1564,10 @@ static void fs__futime(uv_fs_t* req) {
|
||||
HANDLE handle = req->file.hFile;
|
||||
VERIFY_HANDLE(handle, req);
|
||||
|
||||
if (fs__utime_handle(handle, req->fs.time.atime, req->fs.time.mtime) != 0) {
|
||||
if (fs__utime_handle(handle,
|
||||
req->fs.time.btime,
|
||||
req->fs.time.atime,
|
||||
req->fs.time.mtime) != 0) {
|
||||
SET_REQ_WIN32_ERROR(req, GetLastError());
|
||||
return;
|
||||
}
|
||||
@ -1964,7 +1988,8 @@ void uv_fs_req_cleanup(uv_fs_t* req) {
|
||||
uv__free(req->ptr);
|
||||
}
|
||||
|
||||
if (req->fs.info.bufs != req->fs.info.bufsml)
|
||||
if (req->fs.info.bufs != req->fs.info.bufsml &&
|
||||
ARRAY_SIZE(req->fs.info.bufs) > 0)
|
||||
uv__free(req->fs.info.bufs);
|
||||
|
||||
req->path = NULL;
|
||||
@ -2357,7 +2382,12 @@ int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_os_fd_t handle, int mode,
|
||||
|
||||
|
||||
int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime,
|
||||
double mtime, uv_fs_cb cb) {
|
||||
double mtime, uv_fs_cb cb) {
|
||||
return uv_fs_utime_ex(loop, req, path, NAN, atime, mtime, cb);
|
||||
}
|
||||
|
||||
int uv_fs_utime_ex(uv_loop_t* loop, uv_fs_t* req, const char* path,
|
||||
double btime, double atime, double mtime, uv_fs_cb cb) {
|
||||
int err;
|
||||
|
||||
INIT(UV_FS_UTIME);
|
||||
@ -2366,6 +2396,7 @@ int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime,
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
|
||||
req->fs.time.btime = btime;
|
||||
req->fs.time.atime = atime;
|
||||
req->fs.time.mtime = mtime;
|
||||
POST;
|
||||
@ -2374,8 +2405,15 @@ int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime,
|
||||
|
||||
int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_os_fd_t handle, double atime,
|
||||
double mtime, uv_fs_cb cb) {
|
||||
return uv_fs_futime_ex(loop, req, handle, NAN, atime, mtime, cb);
|
||||
}
|
||||
|
||||
|
||||
int uv_fs_futime_ex(uv_loop_t* loop, uv_fs_t* req, uv_os_fd_t handle,
|
||||
double btime, double atime, double mtime, uv_fs_cb cb) {
|
||||
INIT(UV_FS_FUTIME);
|
||||
req->file.hFile = handle;
|
||||
req->fs.time.btime = btime;
|
||||
req->fs.time.atime = atime;
|
||||
req->fs.time.mtime = mtime;
|
||||
POST;
|
||||
|
||||
190
test/test-fs.c
190
test/test-fs.c
@ -23,8 +23,9 @@
|
||||
#include "task.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h> /* memset */
|
||||
#include <fcntl.h>
|
||||
#include <math.h>
|
||||
#include <string.h> /* memset */
|
||||
#include <sys/stat.h>
|
||||
|
||||
/* FIXME we shouldn't need to branch in this file */
|
||||
@ -56,6 +57,7 @@
|
||||
|
||||
typedef struct {
|
||||
const char* path;
|
||||
double btime;
|
||||
double atime;
|
||||
double mtime;
|
||||
} utime_check_t;
|
||||
@ -687,17 +689,36 @@ TEST_IMPL(fs_file_loop) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void check_utime(const char* path, double atime, double mtime) {
|
||||
|
||||
static void check_utime_ex(const char* path,
|
||||
double btime,
|
||||
double atime,
|
||||
double mtime) {
|
||||
uv_stat_t* s;
|
||||
uv_fs_t req;
|
||||
int r;
|
||||
|
||||
r = uv_fs_stat(loop, &req, path, NULL);
|
||||
ASSERT(r == 0);
|
||||
|
||||
ASSERT(req.result == 0);
|
||||
s = &req.statbuf;
|
||||
|
||||
#if defined(__APPLE__) || defined(_WIN32)
|
||||
/* When check_utime_ex is called with a btime of NAN, this means that we are
|
||||
* checking uv_fs_utime and uv_fs_futime results, which SHOULD NOT allow the
|
||||
* caller to alter the btime. Well some utime implementations, like FreeBSD,
|
||||
* have conditions where btime can be altered via utime even though btime is
|
||||
* not an argument. The conditions to identify this are impossible to check
|
||||
* at test time so we will not check that btime is unaltered when checking
|
||||
* the results of uv_fs_utime and uv_fs_futime.
|
||||
*/
|
||||
if (!isnan(btime)) {
|
||||
/* Make sure the birth/creation time was altered as expected. */
|
||||
ASSERT(s->st_birthtim.tv_sec + (s->st_birthtim.tv_nsec / 1000000000.0) ==
|
||||
btime);
|
||||
}
|
||||
#endif
|
||||
|
||||
ASSERT(s->st_atim.tv_sec + (s->st_atim.tv_nsec / 1000000000.0) == atime);
|
||||
ASSERT(s->st_mtim.tv_sec + (s->st_mtim.tv_nsec / 1000000000.0) == mtime);
|
||||
|
||||
@ -705,6 +726,11 @@ static void check_utime(const char* path, double atime, double mtime) {
|
||||
}
|
||||
|
||||
|
||||
static void check_utime(const char* path, double atime, double mtime) {
|
||||
check_utime_ex(path, NAN, atime, mtime);
|
||||
}
|
||||
|
||||
|
||||
static void utime_cb(uv_fs_t* req) {
|
||||
utime_check_t* c;
|
||||
|
||||
@ -2136,7 +2162,7 @@ TEST_IMPL(fs_non_symlink_reparse_point) {
|
||||
|
||||
TEST_IMPL(fs_utime) {
|
||||
utime_check_t checkme;
|
||||
const char* path = "test_file";
|
||||
const char path[] = "test_file";
|
||||
double atime;
|
||||
double mtime;
|
||||
uv_fs_t req;
|
||||
@ -2200,6 +2226,74 @@ TEST_IMPL(fs_utime) {
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(fs_utime_ex) {
|
||||
utime_check_t checkme;
|
||||
const char path[] = "test_file";
|
||||
double atime;
|
||||
double btime;
|
||||
double mtime;
|
||||
uv_fs_t req;
|
||||
uv_os_fd_t file;
|
||||
int r;
|
||||
|
||||
/* Setup. */
|
||||
loop = uv_default_loop();
|
||||
unlink(path);
|
||||
r = uv_fs_open(NULL, &req, path, O_RDWR | O_CREAT, S_IWUSR | S_IRUSR, NULL);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(req.result >= 0);
|
||||
file = (uv_os_fd_t)req.result;
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
/* Close file */
|
||||
r = uv_fs_close(NULL, &req, file, NULL);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(req.result == 0);
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
atime = btime = mtime = 400497753; /* 1982-09-10 11:22:33 */
|
||||
|
||||
/*
|
||||
* Test sub-second timestamps only on Windows (assuming NTFS). Some other
|
||||
* platforms support sub-second timestamps, but that support is filesystem-
|
||||
* dependent. Notably OS X (HFS Plus) does NOT support sub-second timestamps.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
mtime += 0.444; /* 1982-09-10 11:22:33.444 */
|
||||
#endif
|
||||
|
||||
r = uv_fs_utime_ex(NULL, &req, path, btime, atime, mtime, NULL);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(req.result == 0);
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
r = uv_fs_stat(NULL, &req, path, NULL);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(req.result == 0);
|
||||
check_utime_ex(path, btime, atime, mtime);
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
atime = btime = mtime = 1291404900; /* 2010-12-03 20:35:00 - mees <3 */
|
||||
checkme.path = path;
|
||||
checkme.atime = atime;
|
||||
checkme.btime = btime;
|
||||
checkme.mtime = mtime;
|
||||
|
||||
/* async utime */
|
||||
utime_req.data = &checkme;
|
||||
r = uv_fs_utime_ex(loop, &utime_req, path, btime, atime, mtime, utime_cb);
|
||||
ASSERT(r == 0);
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
ASSERT(utime_cb_count == 1);
|
||||
|
||||
/* Cleanup. */
|
||||
unlink(path);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
TEST_IMPL(fs_stat_root) {
|
||||
int r;
|
||||
@ -2237,7 +2331,7 @@ TEST_IMPL(fs_futime) {
|
||||
RETURN_SKIP("futime is not implemented for AIX versions below 7.1");
|
||||
#else
|
||||
utime_check_t checkme;
|
||||
const char* path = "test_file";
|
||||
const char path[] = "test_file";
|
||||
double atime;
|
||||
double mtime;
|
||||
uv_os_fd_t file;
|
||||
@ -2273,7 +2367,7 @@ TEST_IMPL(fs_futime) {
|
||||
r = uv_fs_open(NULL, &req, path, O_RDWR, 0, NULL);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(req.result >= 0);
|
||||
file = (uv_os_fd_t)req.result; /* FIXME probably not how it's supposed to be used */
|
||||
file = (uv_os_fd_t)req.result;
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
r = uv_fs_futime(NULL, &req, file, atime, mtime, NULL);
|
||||
@ -2314,6 +2408,90 @@ TEST_IMPL(fs_futime) {
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(fs_futime_ex) {
|
||||
#if defined(_AIX) && !defined(_AIX71)
|
||||
RETURN_SKIP("futime is not implemented for AIX versions below 7.1");
|
||||
#else
|
||||
utime_check_t checkme;
|
||||
const char path[] = "test_file";
|
||||
double atime;
|
||||
double btime;
|
||||
double mtime;
|
||||
uv_os_fd_t file;
|
||||
uv_fs_t req;
|
||||
int r;
|
||||
|
||||
/* Setup. */
|
||||
loop = uv_default_loop();
|
||||
unlink(path);
|
||||
r = uv_fs_open(NULL, &req, path, O_RDWR | O_CREAT, S_IWUSR | S_IRUSR, NULL);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(req.result >= 0);
|
||||
file = (uv_os_fd_t)req.result;
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
/* Close file */
|
||||
r = uv_fs_close(NULL, &req, file, NULL);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(req.result == 0);
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
atime = btime = mtime = 400497753; /* 1982-09-10 11:22:33 */
|
||||
|
||||
/*
|
||||
* Test sub-second timestamps only on Windows (assuming NTFS). Some other
|
||||
* platforms support sub-second timestamps, but that support is filesystem-
|
||||
* dependent. Notably OS X (HFS Plus) does NOT support sub-second timestamps.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
mtime += 0.444; /* 1982-09-10 11:22:33.444 */
|
||||
#endif
|
||||
|
||||
r = uv_fs_open(NULL, &req, path, O_RDWR, 0, NULL);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(req.result >= 0);
|
||||
file = (uv_os_fd_t)req.result;
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
r = uv_fs_futime_ex(NULL, &req, file, btime, atime, mtime, NULL);
|
||||
#if defined(__CYGWIN__) || defined(__MSYS__)
|
||||
ASSERT(r == UV_ENOSYS);
|
||||
RETURN_SKIP("futime not supported on Cygwin");
|
||||
#else
|
||||
ASSERT(r == 0);
|
||||
ASSERT(req.result == 0);
|
||||
#endif
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
r = uv_fs_stat(NULL, &req, path, NULL);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(req.result == 0);
|
||||
check_utime_ex(path, btime, atime, mtime);
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
atime = btime = mtime = 1291404900; /* 2010-12-03 20:35:00 - mees <3 */
|
||||
|
||||
checkme.atime = atime;
|
||||
checkme.btime = btime;
|
||||
checkme.mtime = mtime;
|
||||
checkme.path = path;
|
||||
|
||||
/* async futime */
|
||||
futime_req.data = &checkme;
|
||||
r = uv_fs_futime_ex(loop, &futime_req, file, btime, atime, mtime, futime_cb);
|
||||
ASSERT(r == 0);
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
ASSERT(futime_cb_count == 1);
|
||||
|
||||
/* Cleanup. */
|
||||
unlink(path);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(fs_stat_missing_path) {
|
||||
uv_fs_t req;
|
||||
int r;
|
||||
|
||||
@ -305,7 +305,9 @@ TEST_DECLARE (fs_symlink_junction)
|
||||
TEST_DECLARE (fs_non_symlink_reparse_point)
|
||||
#endif
|
||||
TEST_DECLARE (fs_utime)
|
||||
TEST_DECLARE (fs_utime_ex)
|
||||
TEST_DECLARE (fs_futime)
|
||||
TEST_DECLARE (fs_futime_ex)
|
||||
TEST_DECLARE (fs_file_open_append)
|
||||
TEST_DECLARE (fs_stat_missing_path)
|
||||
TEST_DECLARE (fs_read_file_eof)
|
||||
@ -836,7 +838,9 @@ TASK_LIST_START
|
||||
TEST_ENTRY (fs_unlink_readonly)
|
||||
TEST_ENTRY (fs_chown)
|
||||
TEST_ENTRY (fs_utime)
|
||||
TEST_ENTRY (fs_utime_ex)
|
||||
TEST_ENTRY (fs_futime)
|
||||
TEST_ENTRY (fs_futime_ex)
|
||||
TEST_ENTRY (fs_readlink)
|
||||
TEST_ENTRY (fs_realpath)
|
||||
TEST_ENTRY (fs_symlink)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user