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.
|
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::
|
.. note::
|
||||||
z/OS: `uv_fs_lutime()` is not implemented for z/OS. It can still be called but will return
|
z/OS: `uv_fs_lutime()` is not implemented for z/OS. It can still be called but will return
|
||||||
``UV_ENOSYS``.
|
``UV_ENOSYS``.
|
||||||
|
|||||||
@ -58,6 +58,7 @@ extern "C" {
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
/* Internal type, do not use. */
|
/* Internal type, do not use. */
|
||||||
struct uv__queue {
|
struct uv__queue {
|
||||||
@ -1585,6 +1586,8 @@ UV_EXTERN int uv_fs_chmod(uv_loop_t* loop,
|
|||||||
const char* path,
|
const char* path,
|
||||||
int mode,
|
int mode,
|
||||||
uv_fs_cb cb);
|
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_EXTERN int uv_fs_utime(uv_loop_t* loop,
|
||||||
uv_fs_t* req,
|
uv_fs_t* req,
|
||||||
const char* path,
|
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;
|
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_sec = time;
|
||||||
ts.tv_nsec = (time - ts.tv_sec) * 1e9;
|
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;
|
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) {
|
static ssize_t uv__fs_futime(uv_fs_t* req) {
|
||||||
#if defined(__linux__) \
|
#if defined(__APPLE__) \
|
||||||
|| defined(_AIX71) \
|
|| defined(_AIX71) \
|
||||||
|
|| defined(__DragonFly__) \
|
||||||
|
|| defined(__FreeBSD__) \
|
||||||
|| defined(__HAIKU__) \
|
|| defined(__HAIKU__) \
|
||||||
|| defined(__GNU__)
|
|| defined(__NetBSD__) \
|
||||||
|
|| defined(__OpenBSD__) \
|
||||||
|
|| defined(__linux__) \
|
||||||
|
|| defined(__sun)
|
||||||
struct timespec ts[2];
|
struct timespec ts[2];
|
||||||
ts[0] = uv__fs_to_timespec(req->atime);
|
ts[0] = uv__fs_to_timespec(req->atime);
|
||||||
ts[1] = uv__fs_to_timespec(req->mtime);
|
ts[1] = uv__fs_to_timespec(req->mtime);
|
||||||
return futimens(req->file, ts);
|
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__)
|
#elif defined(__MVS__)
|
||||||
attrib_t atr;
|
attrib_t atr;
|
||||||
memset(&atr, 0, sizeof(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) {
|
static ssize_t uv__fs_utime(uv_fs_t* req) {
|
||||||
#if defined(__linux__) \
|
#if defined(__APPLE__) \
|
||||||
|| defined(_AIX71) \
|
|| defined(_AIX71) \
|
||||||
|| defined(__sun) \
|
|| defined(__DragonFly__) \
|
||||||
|| defined(__HAIKU__)
|
|| defined(__FreeBSD__) \
|
||||||
|
|| defined(__HAIKU__) \
|
||||||
|
|| defined(__NetBSD__) \
|
||||||
|
|| defined(__OpenBSD__) \
|
||||||
|
|| defined(__linux__) \
|
||||||
|
|| defined(__sun)
|
||||||
struct timespec ts[2];
|
struct timespec ts[2];
|
||||||
ts[0] = uv__fs_to_timespec(req->atime);
|
ts[0] = uv__fs_to_timespec(req->atime);
|
||||||
ts[1] = uv__fs_to_timespec(req->mtime);
|
ts[1] = uv__fs_to_timespec(req->mtime);
|
||||||
return utimensat(AT_FDCWD, req->path, ts, 0);
|
return utimensat(AT_FDCWD, req->path, ts, 0);
|
||||||
#elif defined(__APPLE__) \
|
#elif defined(_AIX) && !defined(_AIX71)
|
||||||
|| 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)
|
|
||||||
struct utimbuf buf;
|
struct utimbuf buf;
|
||||||
buf.actime = req->atime;
|
buf.actime = req->atime;
|
||||||
buf.modtime = req->mtime;
|
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) {
|
static ssize_t uv__fs_lutime(uv_fs_t* req) {
|
||||||
#if defined(__linux__) || \
|
#if defined(__APPLE__) \
|
||||||
defined(_AIX71) || \
|
|| defined(_AIX71) \
|
||||||
defined(__sun) || \
|
|| defined(__DragonFly__) \
|
||||||
defined(__HAIKU__) || \
|
|| defined(__FreeBSD__) \
|
||||||
defined(__GNU__) || \
|
|| defined(__HAIKU__) \
|
||||||
defined(__OpenBSD__)
|
|| defined(__NetBSD__) \
|
||||||
|
|| defined(__OpenBSD__) \
|
||||||
|
|| defined(__linux__) \
|
||||||
|
|| defined(__sun)
|
||||||
struct timespec ts[2];
|
struct timespec ts[2];
|
||||||
ts[0] = uv__fs_to_timespec(req->atime);
|
ts[0] = uv__fs_to_timespec(req->atime);
|
||||||
ts[1] = uv__fs_to_timespec(req->mtime);
|
ts[1] = uv__fs_to_timespec(req->mtime);
|
||||||
return utimensat(AT_FDCWD, req->path, ts, AT_SYMLINK_NOFOLLOW);
|
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
|
#else
|
||||||
errno = ENOSYS;
|
errno = ENOSYS;
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@ -31,6 +31,7 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "uv.h"
|
#include "uv.h"
|
||||||
#include "uv/tree.h"
|
#include "uv/tree.h"
|
||||||
@ -448,4 +449,22 @@ struct uv__loop_internal_fields_s {
|
|||||||
# define UV_PTHREAD_MAX_NAMELEN_NP 16
|
# define UV_PTHREAD_MAX_NAMELEN_NP 16
|
||||||
#endif
|
#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_ */
|
#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) {
|
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);
|
if (uv__isinf(atime) || uv__isinf(mtime))
|
||||||
TIME_T_TO_FILETIME(mtime, &filetime_m);
|
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 -1;
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
227
test/test-fs.c
227
test/test-fs.c
@ -59,6 +59,18 @@
|
|||||||
#define TOO_LONG_NAME_LENGTH 65536
|
#define TOO_LONG_NAME_LENGTH 65536
|
||||||
#define PATHMAX 4096
|
#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 {
|
typedef struct {
|
||||||
const char* path;
|
const char* path;
|
||||||
double atime;
|
double atime;
|
||||||
@ -827,43 +839,70 @@ static void check_utime(const char* path,
|
|||||||
ASSERT_OK(req.result);
|
ASSERT_OK(req.result);
|
||||||
s = &req.statbuf;
|
s = &req.statbuf;
|
||||||
|
|
||||||
if (s->st_atim.tv_nsec == 0 && s->st_mtim.tv_nsec == 0) {
|
if (isfinite(atime)) {
|
||||||
/*
|
/* Test sub-second timestamps only when supported (such as Windows with
|
||||||
* Test sub-second timestamps only when supported (such as Windows with
|
|
||||||
* NTFS). Some other platforms support sub-second timestamps, but that
|
* NTFS). Some other platforms support sub-second timestamps, but that
|
||||||
* support is filesystem-dependent. Notably OS X (HFS Plus) does NOT
|
* support is filesystem-dependent. Notably OS X (HFS Plus) does NOT
|
||||||
* support sub-second timestamps. But kernels may round or truncate in
|
* support sub-second timestamps. But kernels may round or truncate in
|
||||||
* either direction, so we may accept either possible answer.
|
* either direction, so we may accept either possible answer.
|
||||||
*/
|
*/
|
||||||
#ifdef _WIN32
|
if (s->st_atim.tv_nsec == 0) {
|
||||||
ASSERT_DOUBLE_EQ(atime, (long) atime);
|
if (is_win32)
|
||||||
ASSERT_DOUBLE_EQ(mtime, (long) atime);
|
ASSERT_DOUBLE_EQ(atime, (long) atime);
|
||||||
#endif
|
if (atime > 0 || (long) atime == atime)
|
||||||
if (atime > 0 || (long) atime == atime)
|
ASSERT_EQ(s->st_atim.tv_sec, (long) atime);
|
||||||
ASSERT_EQ(s->st_atim.tv_sec, (long) atime);
|
ASSERT_GE(s->st_atim.tv_sec, (long) atime - 1);
|
||||||
if (mtime > 0 || (long) mtime == mtime)
|
ASSERT_LE(s->st_atim.tv_sec, (long) atime);
|
||||||
ASSERT_EQ(s->st_mtim.tv_sec, (long) mtime);
|
} else {
|
||||||
ASSERT_GE(s->st_atim.tv_sec, (long) atime - 1);
|
double st_atim;
|
||||||
ASSERT_GE(s->st_mtim.tv_sec, (long) mtime - 1);
|
/* TODO(vtjnash): would it be better to normalize this? */
|
||||||
ASSERT_LE(s->st_atim.tv_sec, (long) atime);
|
if (!is_apple_or_sunpro_c)
|
||||||
ASSERT_LE(s->st_mtim.tv_sec, (long) mtime);
|
ASSERT_DOUBLE_GE(s->st_atim.tv_nsec, 0);
|
||||||
} else {
|
st_atim = s->st_atim.tv_sec + s->st_atim.tv_nsec / 1e9;
|
||||||
double st_atim;
|
/* Linux does not allow reading reliably the atime of a symlink
|
||||||
double st_mtim;
|
* since readlink() can update it
|
||||||
#if !defined(__APPLE__) && !defined(__SUNPRO_C)
|
*/
|
||||||
/* TODO(vtjnash): would it be better to normalize this? */
|
if (!test_lutime)
|
||||||
ASSERT_DOUBLE_GE(s->st_atim.tv_nsec, 0);
|
ASSERT_DOUBLE_EQ(st_atim, atime);
|
||||||
ASSERT_DOUBLE_GE(s->st_mtim.tv_nsec, 0);
|
}
|
||||||
#endif
|
} else if (isinf(atime)) {
|
||||||
st_atim = s->st_atim.tv_sec + s->st_atim.tv_nsec / 1e9;
|
/* We test with timestamps that are in the distant past
|
||||||
st_mtim = s->st_mtim.tv_sec + s->st_mtim.tv_nsec / 1e9;
|
* (if you're a Gen Z-er) so check it's more recent than that.
|
||||||
/*
|
|
||||||
* Linux does not allow reading reliably the atime of a symlink
|
|
||||||
* since readlink() can update it
|
|
||||||
*/
|
*/
|
||||||
if (!test_lutime)
|
ASSERT_GT(s->st_atim.tv_sec, 1739710000);
|
||||||
ASSERT_DOUBLE_EQ(st_atim, atime);
|
} else {
|
||||||
ASSERT_DOUBLE_EQ(st_mtim, mtime);
|
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);
|
uv_fs_req_cleanup(&req);
|
||||||
@ -2728,13 +2767,46 @@ TEST_IMPL(fs_utime) {
|
|||||||
|
|
||||||
atime = mtime = 400497753.25; /* 1982-09-10 11:22:33.25 */
|
atime = mtime = 400497753.25; /* 1982-09-10 11:22:33.25 */
|
||||||
|
|
||||||
r = uv_fs_utime(NULL, &req, path, atime, mtime, NULL);
|
ASSERT_OK(uv_fs_utime(NULL, &req, path, atime, mtime, NULL));
|
||||||
ASSERT_OK(r);
|
|
||||||
ASSERT_OK(req.result);
|
ASSERT_OK(req.result);
|
||||||
uv_fs_req_cleanup(&req);
|
uv_fs_req_cleanup(&req);
|
||||||
|
|
||||||
check_utime(path, atime, mtime, /* test_lutime */ 0);
|
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 */
|
atime = mtime = 1291404900.25; /* 2010-12-03 20:35:00.25 - mees <3 */
|
||||||
checkme.path = path;
|
checkme.path = path;
|
||||||
checkme.atime = atime;
|
checkme.atime = atime;
|
||||||
@ -2868,9 +2940,43 @@ TEST_IMPL(fs_futime) {
|
|||||||
ASSERT_OK(req.result);
|
ASSERT_OK(req.result);
|
||||||
#endif
|
#endif
|
||||||
uv_fs_req_cleanup(&req);
|
uv_fs_req_cleanup(&req);
|
||||||
|
|
||||||
check_utime(path, atime, mtime, /* test_lutime */ 0);
|
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 */
|
atime = mtime = 1291404900; /* 2010-12-03 20:35:00 - mees <3 */
|
||||||
|
|
||||||
checkme.atime = atime;
|
checkme.atime = atime;
|
||||||
@ -2932,20 +3038,50 @@ TEST_IMPL(fs_lutime) {
|
|||||||
/* Test the synchronous version. */
|
/* Test the synchronous version. */
|
||||||
atime = mtime = 400497753.25; /* 1982-09-10 11:22:33.25 */
|
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);
|
r = uv_fs_lutime(NULL, &req, symlink_path, atime, mtime, NULL);
|
||||||
#if (defined(_AIX) && !defined(_AIX71)) || \
|
#if (defined(_AIX) && !defined(_AIX71)) || defined(__MVS__)
|
||||||
defined(__MVS__)
|
|
||||||
ASSERT_EQ(r, UV_ENOSYS);
|
ASSERT_EQ(r, UV_ENOSYS);
|
||||||
RETURN_SKIP("lutime is not implemented for z/OS and AIX versions below 7.1");
|
RETURN_SKIP("lutime is not implemented for z/OS and AIX versions below 7.1");
|
||||||
#endif
|
#endif
|
||||||
ASSERT_OK(r);
|
ASSERT_OK(r);
|
||||||
lutime_cb(&req);
|
ASSERT_OK(req.result);
|
||||||
ASSERT_EQ(1, lutime_cb_count);
|
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. */
|
/* Test the asynchronous version. */
|
||||||
atime = mtime = 1291404900; /* 2010-12-03 20:35:00 */
|
atime = mtime = 1291404900; /* 2010-12-03 20:35:00 */
|
||||||
@ -2953,11 +3089,12 @@ TEST_IMPL(fs_lutime) {
|
|||||||
checkme.atime = atime;
|
checkme.atime = atime;
|
||||||
checkme.mtime = mtime;
|
checkme.mtime = mtime;
|
||||||
checkme.path = symlink_path;
|
checkme.path = symlink_path;
|
||||||
|
req.data = &checkme;
|
||||||
|
|
||||||
r = uv_fs_lutime(loop, &req, symlink_path, atime, mtime, lutime_cb);
|
r = uv_fs_lutime(loop, &req, symlink_path, atime, mtime, lutime_cb);
|
||||||
ASSERT_OK(r);
|
ASSERT_OK(r);
|
||||||
uv_run(loop, UV_RUN_DEFAULT);
|
uv_run(loop, UV_RUN_DEFAULT);
|
||||||
ASSERT_EQ(2, lutime_cb_count);
|
ASSERT_EQ(1, lutime_cb_count);
|
||||||
|
|
||||||
/* Cleanup. */
|
/* Cleanup. */
|
||||||
unlink(path);
|
unlink(path);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user