unix,win: accept NAN/INFINITY as file timestamps (#4702)
Extend uv_fs_utime, uv_fs_futime and uv_fs_lutime to accept NAN and INFINITY, with NAN meaning "don't touch the timestamp" and INFINITY meaning "set to the current timestamp." Ugly, but it avoids having to add uv_fs_utime2, etc. UV_FS_UTIME_NOW and UV_FS_UTIME_OMIT constants have been added to make it more palatable. Fixes: https://github.com/libuv/libuv/issues/4665
This commit is contained in:
parent
8a94b7b2ec
commit
85b526f56a
@ -430,6 +430,12 @@ API
|
||||
|
||||
Equivalent to :man:`utime(2)`, :man:`futimes(3)` and :man:`lutimes(3)` respectively.
|
||||
|
||||
Passing `UV_FS_UTIME_NOW` as the atime or mtime sets the timestamp to the
|
||||
current time.
|
||||
|
||||
Passing `UV_FS_UTIME_OMIT` as the atime or mtime leaves the timestamp
|
||||
untouched.
|
||||
|
||||
.. note::
|
||||
z/OS: `uv_fs_lutime()` is not implemented for z/OS. It can still be called but will return
|
||||
``UV_ENOSYS``.
|
||||
|
||||
@ -58,6 +58,7 @@ extern "C" {
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
/* Internal type, do not use. */
|
||||
struct uv__queue {
|
||||
@ -1585,6 +1586,8 @@ UV_EXTERN int uv_fs_chmod(uv_loop_t* loop,
|
||||
const char* path,
|
||||
int mode,
|
||||
uv_fs_cb cb);
|
||||
#define UV_FS_UTIME_NOW (INFINITY)
|
||||
#define UV_FS_UTIME_OMIT (NAN)
|
||||
UV_EXTERN int uv_fs_utime(uv_loop_t* loop,
|
||||
uv_fs_t* req,
|
||||
const char* path,
|
||||
|
||||
@ -203,8 +203,23 @@ static ssize_t uv__fs_fdatasync(uv_fs_t* req) {
|
||||
}
|
||||
|
||||
|
||||
UV_UNUSED(static struct timespec uv__fs_to_timespec(double time)) {
|
||||
#if defined(__APPLE__) \
|
||||
|| defined(_AIX71) \
|
||||
|| defined(__DragonFly__) \
|
||||
|| defined(__FreeBSD__) \
|
||||
|| defined(__HAIKU__) \
|
||||
|| defined(__NetBSD__) \
|
||||
|| defined(__OpenBSD__) \
|
||||
|| defined(__linux__) \
|
||||
|| defined(__sun)
|
||||
static struct timespec uv__fs_to_timespec(double time) {
|
||||
struct timespec ts;
|
||||
|
||||
if (uv__isinf(time))
|
||||
return (struct timespec){UTIME_NOW, UTIME_NOW};
|
||||
if (uv__isnan(time))
|
||||
return (struct timespec){UTIME_OMIT, UTIME_OMIT};
|
||||
|
||||
ts.tv_sec = time;
|
||||
ts.tv_nsec = (time - ts.tv_sec) * 1e9;
|
||||
|
||||
@ -221,41 +236,23 @@ UV_UNUSED(static struct timespec uv__fs_to_timespec(double time)) {
|
||||
}
|
||||
return ts;
|
||||
}
|
||||
#endif
|
||||
|
||||
UV_UNUSED(static struct timeval uv__fs_to_timeval(double time)) {
|
||||
struct timeval tv;
|
||||
tv.tv_sec = time;
|
||||
tv.tv_usec = (time - tv.tv_sec) * 1e6;
|
||||
if (tv.tv_usec < 0) {
|
||||
tv.tv_usec += 1e6;
|
||||
tv.tv_sec -= 1;
|
||||
}
|
||||
return tv;
|
||||
}
|
||||
|
||||
static ssize_t uv__fs_futime(uv_fs_t* req) {
|
||||
#if defined(__linux__) \
|
||||
#if defined(__APPLE__) \
|
||||
|| defined(_AIX71) \
|
||||
|| defined(__DragonFly__) \
|
||||
|| defined(__FreeBSD__) \
|
||||
|| defined(__HAIKU__) \
|
||||
|| defined(__GNU__)
|
||||
|| defined(__NetBSD__) \
|
||||
|| defined(__OpenBSD__) \
|
||||
|| defined(__linux__) \
|
||||
|| defined(__sun)
|
||||
struct timespec ts[2];
|
||||
ts[0] = uv__fs_to_timespec(req->atime);
|
||||
ts[1] = uv__fs_to_timespec(req->mtime);
|
||||
return futimens(req->file, ts);
|
||||
#elif defined(__APPLE__) \
|
||||
|| defined(__DragonFly__) \
|
||||
|| defined(__FreeBSD__) \
|
||||
|| defined(__NetBSD__) \
|
||||
|| defined(__OpenBSD__) \
|
||||
|| defined(__sun)
|
||||
struct timeval tv[2];
|
||||
tv[0] = uv__fs_to_timeval(req->atime);
|
||||
tv[1] = uv__fs_to_timeval(req->mtime);
|
||||
# if defined(__sun)
|
||||
return futimesat(req->file, NULL, tv);
|
||||
# else
|
||||
return futimes(req->file, tv);
|
||||
# endif
|
||||
#elif defined(__MVS__)
|
||||
attrib_t atr;
|
||||
memset(&atr, 0, sizeof(atr));
|
||||
@ -1142,25 +1139,20 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
|
||||
|
||||
|
||||
static ssize_t uv__fs_utime(uv_fs_t* req) {
|
||||
#if defined(__linux__) \
|
||||
#if defined(__APPLE__) \
|
||||
|| defined(_AIX71) \
|
||||
|| defined(__sun) \
|
||||
|| defined(__HAIKU__)
|
||||
|| defined(__DragonFly__) \
|
||||
|| defined(__FreeBSD__) \
|
||||
|| defined(__HAIKU__) \
|
||||
|| defined(__NetBSD__) \
|
||||
|| defined(__OpenBSD__) \
|
||||
|| defined(__linux__) \
|
||||
|| defined(__sun)
|
||||
struct timespec ts[2];
|
||||
ts[0] = uv__fs_to_timespec(req->atime);
|
||||
ts[1] = uv__fs_to_timespec(req->mtime);
|
||||
return utimensat(AT_FDCWD, req->path, ts, 0);
|
||||
#elif defined(__APPLE__) \
|
||||
|| defined(__DragonFly__) \
|
||||
|| defined(__FreeBSD__) \
|
||||
|| defined(__NetBSD__) \
|
||||
|| defined(__OpenBSD__)
|
||||
struct timeval tv[2];
|
||||
tv[0] = uv__fs_to_timeval(req->atime);
|
||||
tv[1] = uv__fs_to_timeval(req->mtime);
|
||||
return utimes(req->path, tv);
|
||||
#elif defined(_AIX) \
|
||||
&& !defined(_AIX71)
|
||||
#elif defined(_AIX) && !defined(_AIX71)
|
||||
struct utimbuf buf;
|
||||
buf.actime = req->atime;
|
||||
buf.modtime = req->mtime;
|
||||
@ -1181,24 +1173,19 @@ static ssize_t uv__fs_utime(uv_fs_t* req) {
|
||||
|
||||
|
||||
static ssize_t uv__fs_lutime(uv_fs_t* req) {
|
||||
#if defined(__linux__) || \
|
||||
defined(_AIX71) || \
|
||||
defined(__sun) || \
|
||||
defined(__HAIKU__) || \
|
||||
defined(__GNU__) || \
|
||||
defined(__OpenBSD__)
|
||||
#if defined(__APPLE__) \
|
||||
|| defined(_AIX71) \
|
||||
|| defined(__DragonFly__) \
|
||||
|| defined(__FreeBSD__) \
|
||||
|| defined(__HAIKU__) \
|
||||
|| defined(__NetBSD__) \
|
||||
|| defined(__OpenBSD__) \
|
||||
|| defined(__linux__) \
|
||||
|| defined(__sun)
|
||||
struct timespec ts[2];
|
||||
ts[0] = uv__fs_to_timespec(req->atime);
|
||||
ts[1] = uv__fs_to_timespec(req->mtime);
|
||||
return utimensat(AT_FDCWD, req->path, ts, AT_SYMLINK_NOFOLLOW);
|
||||
#elif defined(__APPLE__) || \
|
||||
defined(__DragonFly__) || \
|
||||
defined(__FreeBSD__) || \
|
||||
defined(__NetBSD__)
|
||||
struct timeval tv[2];
|
||||
tv[0] = uv__fs_to_timeval(req->atime);
|
||||
tv[1] = uv__fs_to_timeval(req->mtime);
|
||||
return lutimes(req->path, tv);
|
||||
#else
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
|
||||
@ -31,6 +31,7 @@
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "uv.h"
|
||||
#include "uv/tree.h"
|
||||
@ -448,4 +449,22 @@ struct uv__loop_internal_fields_s {
|
||||
# define UV_PTHREAD_MAX_NAMELEN_NP 16
|
||||
#endif
|
||||
|
||||
/* Open-coded so downstream users don't have to link libm. */
|
||||
static inline int uv__isinf(double d) {
|
||||
uint64_t v;
|
||||
|
||||
STATIC_ASSERT(sizeof(v) == sizeof(d));
|
||||
memcpy(&v, &d, sizeof(v));
|
||||
return (v << 1 >> 53) == 2047 && !(v << 12);
|
||||
}
|
||||
|
||||
/* Open-coded so downstream users don't have to link libm. */
|
||||
static inline int uv__isnan(double d) {
|
||||
uint64_t v;
|
||||
|
||||
STATIC_ASSERT(sizeof(v) == sizeof(d));
|
||||
memcpy(&v, &d, sizeof(v));
|
||||
return (v << 1 >> 53) == 2047 && !!(v << 12);
|
||||
}
|
||||
|
||||
#endif /* UV_COMMON_H_ */
|
||||
|
||||
25
src/win/fs.c
25
src/win/fs.c
@ -2580,14 +2580,29 @@ fchmod_cleanup:
|
||||
|
||||
|
||||
INLINE static int fs__utime_handle(HANDLE handle, double atime, double mtime) {
|
||||
FILETIME filetime_a, filetime_m;
|
||||
FILETIME filetime_as, *filetime_a = &filetime_as;
|
||||
FILETIME filetime_ms, *filetime_m = &filetime_ms;
|
||||
FILETIME now;
|
||||
|
||||
TIME_T_TO_FILETIME(atime, &filetime_a);
|
||||
TIME_T_TO_FILETIME(mtime, &filetime_m);
|
||||
if (uv__isinf(atime) || uv__isinf(mtime))
|
||||
GetSystemTimeAsFileTime(&now);
|
||||
|
||||
if (!SetFileTime(handle, NULL, &filetime_a, &filetime_m)) {
|
||||
if (uv__isinf(atime))
|
||||
filetime_a = &now;
|
||||
else if (uv__isnan(atime))
|
||||
filetime_a = NULL;
|
||||
else
|
||||
TIME_T_TO_FILETIME(atime, filetime_a);
|
||||
|
||||
if (uv__isinf(mtime))
|
||||
filetime_m = &now;
|
||||
else if (uv__isnan(mtime))
|
||||
filetime_m = NULL;
|
||||
else
|
||||
TIME_T_TO_FILETIME(mtime, filetime_m);
|
||||
|
||||
if (!SetFileTime(handle, NULL, filetime_a, filetime_m))
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
199
test/test-fs.c
199
test/test-fs.c
@ -59,6 +59,18 @@
|
||||
#define TOO_LONG_NAME_LENGTH 65536
|
||||
#define PATHMAX 4096
|
||||
|
||||
#ifdef _WIN32
|
||||
static const int is_win32 = 1;
|
||||
#else
|
||||
static const int is_win32 = 0;
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__) || defined(__SUNPRO_C)
|
||||
static const int is_apple_or_sunpro_c = 1;
|
||||
#else
|
||||
static const int is_apple_or_sunpro_c = 0;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
const char* path;
|
||||
double atime;
|
||||
@ -827,44 +839,71 @@ static void check_utime(const char* path,
|
||||
ASSERT_OK(req.result);
|
||||
s = &req.statbuf;
|
||||
|
||||
if (s->st_atim.tv_nsec == 0 && s->st_mtim.tv_nsec == 0) {
|
||||
/*
|
||||
* Test sub-second timestamps only when supported (such as Windows with
|
||||
if (isfinite(atime)) {
|
||||
/* Test sub-second timestamps only when supported (such as Windows with
|
||||
* 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. But kernels may round or truncate in
|
||||
* either direction, so we may accept either possible answer.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
if (s->st_atim.tv_nsec == 0) {
|
||||
if (is_win32)
|
||||
ASSERT_DOUBLE_EQ(atime, (long) atime);
|
||||
ASSERT_DOUBLE_EQ(mtime, (long) atime);
|
||||
#endif
|
||||
if (atime > 0 || (long) atime == atime)
|
||||
ASSERT_EQ(s->st_atim.tv_sec, (long) atime);
|
||||
if (mtime > 0 || (long) mtime == mtime)
|
||||
ASSERT_EQ(s->st_mtim.tv_sec, (long) mtime);
|
||||
ASSERT_GE(s->st_atim.tv_sec, (long) atime - 1);
|
||||
ASSERT_GE(s->st_mtim.tv_sec, (long) mtime - 1);
|
||||
ASSERT_LE(s->st_atim.tv_sec, (long) atime);
|
||||
ASSERT_LE(s->st_mtim.tv_sec, (long) mtime);
|
||||
} else {
|
||||
double st_atim;
|
||||
double st_mtim;
|
||||
#if !defined(__APPLE__) && !defined(__SUNPRO_C)
|
||||
/* TODO(vtjnash): would it be better to normalize this? */
|
||||
if (!is_apple_or_sunpro_c)
|
||||
ASSERT_DOUBLE_GE(s->st_atim.tv_nsec, 0);
|
||||
ASSERT_DOUBLE_GE(s->st_mtim.tv_nsec, 0);
|
||||
#endif
|
||||
st_atim = s->st_atim.tv_sec + s->st_atim.tv_nsec / 1e9;
|
||||
st_mtim = s->st_mtim.tv_sec + s->st_mtim.tv_nsec / 1e9;
|
||||
/*
|
||||
* Linux does not allow reading reliably the atime of a symlink
|
||||
/* Linux does not allow reading reliably the atime of a symlink
|
||||
* since readlink() can update it
|
||||
*/
|
||||
if (!test_lutime)
|
||||
ASSERT_DOUBLE_EQ(st_atim, atime);
|
||||
}
|
||||
} else if (isinf(atime)) {
|
||||
/* We test with timestamps that are in the distant past
|
||||
* (if you're a Gen Z-er) so check it's more recent than that.
|
||||
*/
|
||||
ASSERT_GT(s->st_atim.tv_sec, 1739710000);
|
||||
} else {
|
||||
ASSERT_OK(0);
|
||||
}
|
||||
|
||||
if (isfinite(mtime)) {
|
||||
/* Test sub-second timestamps only when supported (such as Windows with
|
||||
* 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. But kernels may round or truncate in
|
||||
* either direction, so we may accept either possible answer.
|
||||
*/
|
||||
if (s->st_mtim.tv_nsec == 0) {
|
||||
if (is_win32)
|
||||
ASSERT_DOUBLE_EQ(mtime, (long) atime);
|
||||
if (mtime > 0 || (long) mtime == mtime)
|
||||
ASSERT_EQ(s->st_mtim.tv_sec, (long) mtime);
|
||||
ASSERT_GE(s->st_mtim.tv_sec, (long) mtime - 1);
|
||||
ASSERT_LE(s->st_mtim.tv_sec, (long) mtime);
|
||||
} else {
|
||||
double st_mtim;
|
||||
/* TODO(vtjnash): would it be better to normalize this? */
|
||||
if (!is_apple_or_sunpro_c)
|
||||
ASSERT_DOUBLE_GE(s->st_mtim.tv_nsec, 0);
|
||||
st_mtim = s->st_mtim.tv_sec + s->st_mtim.tv_nsec / 1e9;
|
||||
ASSERT_DOUBLE_EQ(st_mtim, mtime);
|
||||
}
|
||||
} else if (isinf(mtime)) {
|
||||
/* We test with timestamps that are in the distant past
|
||||
* (if you're a Gen Z-er) so check it's more recent than that.
|
||||
*/
|
||||
ASSERT_GT(s->st_mtim.tv_sec, 1739710000);
|
||||
} else {
|
||||
ASSERT_OK(0);
|
||||
}
|
||||
|
||||
uv_fs_req_cleanup(&req);
|
||||
}
|
||||
@ -2728,13 +2767,46 @@ TEST_IMPL(fs_utime) {
|
||||
|
||||
atime = mtime = 400497753.25; /* 1982-09-10 11:22:33.25 */
|
||||
|
||||
r = uv_fs_utime(NULL, &req, path, atime, mtime, NULL);
|
||||
ASSERT_OK(r);
|
||||
ASSERT_OK(uv_fs_utime(NULL, &req, path, atime, mtime, NULL));
|
||||
ASSERT_OK(req.result);
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
check_utime(path, atime, mtime, /* test_lutime */ 0);
|
||||
|
||||
ASSERT_OK(uv_fs_utime(NULL,
|
||||
&req,
|
||||
path,
|
||||
UV_FS_UTIME_OMIT,
|
||||
UV_FS_UTIME_OMIT,
|
||||
NULL));
|
||||
ASSERT_OK(req.result);
|
||||
uv_fs_req_cleanup(&req);
|
||||
check_utime(path, atime, mtime, /* test_lutime */ 0);
|
||||
|
||||
ASSERT_OK(uv_fs_utime(NULL,
|
||||
&req,
|
||||
path,
|
||||
UV_FS_UTIME_NOW,
|
||||
UV_FS_UTIME_OMIT,
|
||||
NULL));
|
||||
ASSERT_OK(req.result);
|
||||
uv_fs_req_cleanup(&req);
|
||||
check_utime(path, UV_FS_UTIME_NOW, mtime, /* test_lutime */ 0);
|
||||
|
||||
ASSERT_OK(uv_fs_utime(NULL, &req, path, atime, mtime, NULL));
|
||||
ASSERT_OK(req.result);
|
||||
uv_fs_req_cleanup(&req);
|
||||
check_utime(path, atime, mtime, /* test_lutime */ 0);
|
||||
|
||||
ASSERT_OK(uv_fs_utime(NULL,
|
||||
&req,
|
||||
path,
|
||||
UV_FS_UTIME_OMIT,
|
||||
UV_FS_UTIME_NOW,
|
||||
NULL));
|
||||
ASSERT_OK(req.result);
|
||||
uv_fs_req_cleanup(&req);
|
||||
check_utime(path, atime, UV_FS_UTIME_NOW, /* test_lutime */ 0);
|
||||
|
||||
atime = mtime = 1291404900.25; /* 2010-12-03 20:35:00.25 - mees <3 */
|
||||
checkme.path = path;
|
||||
checkme.atime = atime;
|
||||
@ -2868,9 +2940,43 @@ TEST_IMPL(fs_futime) {
|
||||
ASSERT_OK(req.result);
|
||||
#endif
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
check_utime(path, atime, mtime, /* test_lutime */ 0);
|
||||
|
||||
ASSERT_OK(uv_fs_futime(NULL,
|
||||
&req,
|
||||
file,
|
||||
UV_FS_UTIME_OMIT,
|
||||
UV_FS_UTIME_OMIT,
|
||||
NULL));
|
||||
ASSERT_OK(req.result);
|
||||
uv_fs_req_cleanup(&req);
|
||||
check_utime(path, atime, mtime, /* test_lutime */ 0);
|
||||
|
||||
ASSERT_OK(uv_fs_futime(NULL,
|
||||
&req,
|
||||
file,
|
||||
UV_FS_UTIME_NOW,
|
||||
UV_FS_UTIME_OMIT,
|
||||
NULL));
|
||||
ASSERT_OK(req.result);
|
||||
uv_fs_req_cleanup(&req);
|
||||
check_utime(path, UV_FS_UTIME_NOW, mtime, /* test_lutime */ 0);
|
||||
|
||||
ASSERT_OK(uv_fs_futime(NULL, &req, file, atime, mtime, NULL));
|
||||
ASSERT_OK(req.result);
|
||||
uv_fs_req_cleanup(&req);
|
||||
check_utime(path, atime, mtime, /* test_lutime */ 0);
|
||||
|
||||
ASSERT_OK(uv_fs_futime(NULL,
|
||||
&req,
|
||||
file,
|
||||
UV_FS_UTIME_OMIT,
|
||||
UV_FS_UTIME_NOW,
|
||||
NULL));
|
||||
ASSERT_OK(req.result);
|
||||
uv_fs_req_cleanup(&req);
|
||||
check_utime(path, atime, UV_FS_UTIME_NOW, /* test_lutime */ 0);
|
||||
|
||||
atime = mtime = 1291404900; /* 2010-12-03 20:35:00 - mees <3 */
|
||||
|
||||
checkme.atime = atime;
|
||||
@ -2932,20 +3038,50 @@ TEST_IMPL(fs_lutime) {
|
||||
/* Test the synchronous version. */
|
||||
atime = mtime = 400497753.25; /* 1982-09-10 11:22:33.25 */
|
||||
|
||||
checkme.atime = atime;
|
||||
checkme.mtime = mtime;
|
||||
checkme.path = symlink_path;
|
||||
req.data = &checkme;
|
||||
|
||||
r = uv_fs_lutime(NULL, &req, symlink_path, atime, mtime, NULL);
|
||||
#if (defined(_AIX) && !defined(_AIX71)) || \
|
||||
defined(__MVS__)
|
||||
#if (defined(_AIX) && !defined(_AIX71)) || defined(__MVS__)
|
||||
ASSERT_EQ(r, UV_ENOSYS);
|
||||
RETURN_SKIP("lutime is not implemented for z/OS and AIX versions below 7.1");
|
||||
#endif
|
||||
ASSERT_OK(r);
|
||||
lutime_cb(&req);
|
||||
ASSERT_EQ(1, lutime_cb_count);
|
||||
ASSERT_OK(req.result);
|
||||
uv_fs_req_cleanup(&req);
|
||||
check_utime(symlink_path, atime, mtime, /* test_lutime */ 1);
|
||||
|
||||
ASSERT_OK(uv_fs_lutime(NULL,
|
||||
&req,
|
||||
symlink_path,
|
||||
UV_FS_UTIME_OMIT,
|
||||
UV_FS_UTIME_OMIT,
|
||||
NULL));
|
||||
ASSERT_OK(req.result);
|
||||
uv_fs_req_cleanup(&req);
|
||||
check_utime(symlink_path, atime, mtime, /* test_lutime */ 1);
|
||||
|
||||
ASSERT_OK(uv_fs_lutime(NULL,
|
||||
&req,
|
||||
symlink_path,
|
||||
UV_FS_UTIME_NOW,
|
||||
UV_FS_UTIME_OMIT,
|
||||
NULL));
|
||||
ASSERT_OK(req.result);
|
||||
uv_fs_req_cleanup(&req);
|
||||
check_utime(symlink_path, UV_FS_UTIME_NOW, mtime, /* test_lutime */ 1);
|
||||
|
||||
ASSERT_OK(uv_fs_lutime(NULL, &req, symlink_path, atime, mtime, NULL));
|
||||
ASSERT_OK(req.result);
|
||||
uv_fs_req_cleanup(&req);
|
||||
check_utime(symlink_path, atime, mtime, /* test_lutime */ 1);
|
||||
|
||||
ASSERT_OK(uv_fs_lutime(NULL,
|
||||
&req,
|
||||
symlink_path,
|
||||
UV_FS_UTIME_OMIT,
|
||||
UV_FS_UTIME_NOW,
|
||||
NULL));
|
||||
ASSERT_OK(req.result);
|
||||
uv_fs_req_cleanup(&req);
|
||||
check_utime(symlink_path, atime, UV_FS_UTIME_NOW, /* test_lutime */ 1);
|
||||
|
||||
/* Test the asynchronous version. */
|
||||
atime = mtime = 1291404900; /* 2010-12-03 20:35:00 */
|
||||
@ -2953,11 +3089,12 @@ TEST_IMPL(fs_lutime) {
|
||||
checkme.atime = atime;
|
||||
checkme.mtime = mtime;
|
||||
checkme.path = symlink_path;
|
||||
req.data = &checkme;
|
||||
|
||||
r = uv_fs_lutime(loop, &req, symlink_path, atime, mtime, lutime_cb);
|
||||
ASSERT_OK(r);
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
ASSERT_EQ(2, lutime_cb_count);
|
||||
ASSERT_EQ(1, lutime_cb_count);
|
||||
|
||||
/* Cleanup. */
|
||||
unlink(path);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user