fs: add uv_fs_lutime()
PR-URL: https://github.com/libuv/libuv/pull/2723 Reviewed-By: Bartosz Sosnowski <bartosz@janeasystems.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
This commit is contained in:
parent
dc7c874660
commit
bd4292385f
@ -100,7 +100,8 @@ Data types
|
|||||||
UV_FS_OPENDIR,
|
UV_FS_OPENDIR,
|
||||||
UV_FS_READDIR,
|
UV_FS_READDIR,
|
||||||
UV_FS_CLOSEDIR,
|
UV_FS_CLOSEDIR,
|
||||||
UV_FS_MKSTEMP
|
UV_FS_MKSTEMP,
|
||||||
|
UV_FS_LUTIME
|
||||||
} uv_fs_type;
|
} uv_fs_type;
|
||||||
|
|
||||||
.. c:type:: uv_statfs_t
|
.. c:type:: uv_statfs_t
|
||||||
@ -402,12 +403,17 @@ API
|
|||||||
|
|
||||||
.. c:function:: int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, double mtime, uv_fs_cb cb)
|
.. c:function:: int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, double mtime, uv_fs_cb cb)
|
||||||
.. c:function:: int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, double atime, double mtime, uv_fs_cb cb)
|
.. c:function:: int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, double atime, double mtime, uv_fs_cb cb)
|
||||||
|
.. c:function:: int uv_fs_lutime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, double mtime, uv_fs_cb cb)
|
||||||
|
|
||||||
Equivalent to :man:`utime(2)` and :man:`futimes(3)` respectively.
|
Equivalent to :man:`utime(2)`, :man:`futimes(3)` and :man:`lutimes(3)` respectively.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
AIX: This function only works for AIX 7.1 and newer. It can still be called on older
|
z/OS: `uv_fs_lutime()` is not implemented for z/OS. It can still be called but will return
|
||||||
versions but will return ``UV_ENOSYS``.
|
``UV_ENOSYS``.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
AIX: `uv_fs_futime()` and `uv_fs_lutime()` functions only work for AIX 7.1 and newer.
|
||||||
|
They 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 precission is supported on Windows
|
||||||
|
|
||||||
|
|||||||
@ -1274,7 +1274,8 @@ typedef enum {
|
|||||||
UV_FS_READDIR,
|
UV_FS_READDIR,
|
||||||
UV_FS_CLOSEDIR,
|
UV_FS_CLOSEDIR,
|
||||||
UV_FS_STATFS,
|
UV_FS_STATFS,
|
||||||
UV_FS_MKSTEMP
|
UV_FS_MKSTEMP,
|
||||||
|
UV_FS_LUTIME
|
||||||
} uv_fs_type;
|
} uv_fs_type;
|
||||||
|
|
||||||
struct uv_dir_s {
|
struct uv_dir_s {
|
||||||
@ -1447,6 +1448,12 @@ UV_EXTERN int uv_fs_futime(uv_loop_t* loop,
|
|||||||
double atime,
|
double atime,
|
||||||
double mtime,
|
double mtime,
|
||||||
uv_fs_cb cb);
|
uv_fs_cb cb);
|
||||||
|
UV_EXTERN int uv_fs_lutime(uv_loop_t* loop,
|
||||||
|
uv_fs_t* req,
|
||||||
|
const char* path,
|
||||||
|
double atime,
|
||||||
|
double mtime,
|
||||||
|
uv_fs_cb cb);
|
||||||
UV_EXTERN int uv_fs_lstat(uv_loop_t* loop,
|
UV_EXTERN int uv_fs_lstat(uv_loop_t* loop,
|
||||||
uv_fs_t* req,
|
uv_fs_t* req,
|
||||||
const char* path,
|
const char* path,
|
||||||
|
|||||||
@ -205,6 +205,20 @@ static ssize_t uv__fs_fdatasync(uv_fs_t* req) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
UV_UNUSED(static struct timespec uv__fs_to_timespec(double time)) {
|
||||||
|
struct timespec ts;
|
||||||
|
ts.tv_sec = time;
|
||||||
|
ts.tv_nsec = (uint64_t)(time * 1000000) % 1000000 * 1000;
|
||||||
|
return ts;
|
||||||
|
}
|
||||||
|
|
||||||
|
UV_UNUSED(static struct timeval uv__fs_to_timeval(double time)) {
|
||||||
|
struct timeval tv;
|
||||||
|
tv.tv_sec = time;
|
||||||
|
tv.tv_usec = (uint64_t)(time * 1000000) % 1000000;
|
||||||
|
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(__linux__) \
|
||||||
|| defined(_AIX71) \
|
|| defined(_AIX71) \
|
||||||
@ -213,10 +227,8 @@ static ssize_t uv__fs_futime(uv_fs_t* req) {
|
|||||||
* for the sake of consistency with other platforms.
|
* for the sake of consistency with other platforms.
|
||||||
*/
|
*/
|
||||||
struct timespec ts[2];
|
struct timespec ts[2];
|
||||||
ts[0].tv_sec = req->atime;
|
ts[0] = uv__fs_to_timespec(req->atime);
|
||||||
ts[0].tv_nsec = (uint64_t)(req->atime * 1000000) % 1000000 * 1000;
|
ts[1] = uv__fs_to_timespec(req->mtime);
|
||||||
ts[1].tv_sec = req->mtime;
|
|
||||||
ts[1].tv_nsec = (uint64_t)(req->mtime * 1000000) % 1000000 * 1000;
|
|
||||||
#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
|
#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
|
||||||
return utimensat(req->file, NULL, ts, 0);
|
return utimensat(req->file, NULL, ts, 0);
|
||||||
#else
|
#else
|
||||||
@ -230,10 +242,8 @@ static ssize_t uv__fs_futime(uv_fs_t* req) {
|
|||||||
|| defined(__OpenBSD__) \
|
|| defined(__OpenBSD__) \
|
||||||
|| defined(__sun)
|
|| defined(__sun)
|
||||||
struct timeval tv[2];
|
struct timeval tv[2];
|
||||||
tv[0].tv_sec = req->atime;
|
tv[0] = uv__fs_to_timeval(req->atime);
|
||||||
tv[0].tv_usec = (uint64_t)(req->atime * 1000000) % 1000000;
|
tv[1] = uv__fs_to_timeval(req->mtime);
|
||||||
tv[1].tv_sec = req->mtime;
|
|
||||||
tv[1].tv_usec = (uint64_t)(req->mtime * 1000000) % 1000000;
|
|
||||||
# if defined(__sun)
|
# if defined(__sun)
|
||||||
return futimesat(req->file, NULL, tv);
|
return futimesat(req->file, NULL, tv);
|
||||||
# else
|
# else
|
||||||
@ -972,10 +982,8 @@ static ssize_t uv__fs_utime(uv_fs_t* req) {
|
|||||||
* for the sake of consistency with other platforms.
|
* for the sake of consistency with other platforms.
|
||||||
*/
|
*/
|
||||||
struct timespec ts[2];
|
struct timespec ts[2];
|
||||||
ts[0].tv_sec = req->atime;
|
ts[0] = uv__fs_to_timespec(req->atime);
|
||||||
ts[0].tv_nsec = (uint64_t)(req->atime * 1000000) % 1000000 * 1000;
|
ts[1] = uv__fs_to_timespec(req->mtime);
|
||||||
ts[1].tv_sec = req->mtime;
|
|
||||||
ts[1].tv_nsec = (uint64_t)(req->mtime * 1000000) % 1000000 * 1000;
|
|
||||||
return utimensat(AT_FDCWD, req->path, ts, 0);
|
return utimensat(AT_FDCWD, req->path, ts, 0);
|
||||||
#elif defined(__APPLE__) \
|
#elif defined(__APPLE__) \
|
||||||
|| defined(__DragonFly__) \
|
|| defined(__DragonFly__) \
|
||||||
@ -984,10 +992,8 @@ static ssize_t uv__fs_utime(uv_fs_t* req) {
|
|||||||
|| defined(__NetBSD__) \
|
|| defined(__NetBSD__) \
|
||||||
|| defined(__OpenBSD__)
|
|| defined(__OpenBSD__)
|
||||||
struct timeval tv[2];
|
struct timeval tv[2];
|
||||||
tv[0].tv_sec = req->atime;
|
tv[0] = uv__fs_to_timeval(req->atime);
|
||||||
tv[0].tv_usec = (uint64_t)(req->atime * 1000000) % 1000000;
|
tv[1] = uv__fs_to_timeval(req->mtime);
|
||||||
tv[1].tv_sec = req->mtime;
|
|
||||||
tv[1].tv_usec = (uint64_t)(req->mtime * 1000000) % 1000000;
|
|
||||||
return utimes(req->path, tv);
|
return utimes(req->path, tv);
|
||||||
#elif defined(_AIX) \
|
#elif defined(_AIX) \
|
||||||
&& !defined(_AIX71)
|
&& !defined(_AIX71)
|
||||||
@ -1010,6 +1016,31 @@ 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__)
|
||||||
|
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(__FreeBSD_kernel__) || \
|
||||||
|
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;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static ssize_t uv__fs_write(uv_fs_t* req) {
|
static ssize_t uv__fs_write(uv_fs_t* req) {
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
static int no_pwritev;
|
static int no_pwritev;
|
||||||
@ -1523,6 +1554,7 @@ static void uv__fs_work(struct uv__work* w) {
|
|||||||
X(FSYNC, uv__fs_fsync(req));
|
X(FSYNC, uv__fs_fsync(req));
|
||||||
X(FTRUNCATE, ftruncate(req->file, req->off));
|
X(FTRUNCATE, ftruncate(req->file, req->off));
|
||||||
X(FUTIME, uv__fs_futime(req));
|
X(FUTIME, uv__fs_futime(req));
|
||||||
|
X(LUTIME, uv__fs_lutime(req));
|
||||||
X(LSTAT, uv__fs_lstat(req->path, &req->statbuf));
|
X(LSTAT, uv__fs_lstat(req->path, &req->statbuf));
|
||||||
X(LINK, link(req->path, req->new_path));
|
X(LINK, link(req->path, req->new_path));
|
||||||
X(MKDIR, mkdir(req->path, req->mode));
|
X(MKDIR, mkdir(req->path, req->mode));
|
||||||
@ -1709,6 +1741,19 @@ int uv_fs_futime(uv_loop_t* loop,
|
|||||||
POST;
|
POST;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int uv_fs_lutime(uv_loop_t* loop,
|
||||||
|
uv_fs_t* req,
|
||||||
|
const char* path,
|
||||||
|
double atime,
|
||||||
|
double mtime,
|
||||||
|
uv_fs_cb cb) {
|
||||||
|
INIT(LUTIME);
|
||||||
|
PATH;
|
||||||
|
req->atime = atime;
|
||||||
|
req->mtime = mtime;
|
||||||
|
POST;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
|
int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
|
||||||
INIT(LSTAT);
|
INIT(LSTAT);
|
||||||
|
|||||||
78
src/win/fs.c
78
src/win/fs.c
@ -2225,34 +2225,68 @@ INLINE static int fs__utime_handle(HANDLE handle, double atime, double mtime) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INLINE static DWORD fs__utime_impl_from_path(WCHAR* path,
|
||||||
static void fs__utime(uv_fs_t* req) {
|
double atime,
|
||||||
|
double mtime,
|
||||||
|
int do_lutime) {
|
||||||
HANDLE handle;
|
HANDLE handle;
|
||||||
|
DWORD flags;
|
||||||
|
DWORD ret;
|
||||||
|
|
||||||
handle = CreateFileW(req->file.pathw,
|
flags = FILE_FLAG_BACKUP_SEMANTICS;
|
||||||
|
if (do_lutime) {
|
||||||
|
flags |= FILE_FLAG_OPEN_REPARSE_POINT;
|
||||||
|
}
|
||||||
|
|
||||||
|
handle = CreateFileW(path,
|
||||||
FILE_WRITE_ATTRIBUTES,
|
FILE_WRITE_ATTRIBUTES,
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
NULL,
|
NULL,
|
||||||
OPEN_EXISTING,
|
OPEN_EXISTING,
|
||||||
FILE_FLAG_BACKUP_SEMANTICS,
|
flags,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
if (handle == INVALID_HANDLE_VALUE) {
|
if (handle == INVALID_HANDLE_VALUE) {
|
||||||
SET_REQ_WIN32_ERROR(req, GetLastError());
|
ret = GetLastError();
|
||||||
return;
|
} else if (fs__utime_handle(handle, atime, mtime) != 0) {
|
||||||
}
|
ret = GetLastError();
|
||||||
|
} else {
|
||||||
if (fs__utime_handle(handle, req->fs.time.atime, req->fs.time.mtime) != 0) {
|
ret = 0;
|
||||||
SET_REQ_WIN32_ERROR(req, GetLastError());
|
|
||||||
CloseHandle(handle);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseHandle(handle);
|
CloseHandle(handle);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
INLINE static void fs__utime_impl(uv_fs_t* req, int do_lutime) {
|
||||||
|
DWORD error;
|
||||||
|
|
||||||
|
error = fs__utime_impl_from_path(req->file.pathw,
|
||||||
|
req->fs.time.atime,
|
||||||
|
req->fs.time.mtime,
|
||||||
|
do_lutime);
|
||||||
|
|
||||||
|
if (error != 0) {
|
||||||
|
if (do_lutime &&
|
||||||
|
(error == ERROR_SYMLINK_NOT_SUPPORTED ||
|
||||||
|
error == ERROR_NOT_A_REPARSE_POINT)) {
|
||||||
|
/* Opened file is a reparse point but not a symlink. Try again. */
|
||||||
|
fs__utime_impl(req, 0);
|
||||||
|
} else {
|
||||||
|
/* utime failed. */
|
||||||
|
SET_REQ_WIN32_ERROR(req, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
req->result = 0;
|
req->result = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void fs__utime(uv_fs_t* req) {
|
||||||
|
fs__utime_impl(req, /* do_lutime */ 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void fs__futime(uv_fs_t* req) {
|
static void fs__futime(uv_fs_t* req) {
|
||||||
int fd = req->file.fd;
|
int fd = req->file.fd;
|
||||||
@ -2274,6 +2308,10 @@ static void fs__futime(uv_fs_t* req) {
|
|||||||
req->result = 0;
|
req->result = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void fs__lutime(uv_fs_t* req) {
|
||||||
|
fs__utime_impl(req, /* do_lutime */ 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void fs__link(uv_fs_t* req) {
|
static void fs__link(uv_fs_t* req) {
|
||||||
DWORD r = CreateHardLinkW(req->fs.info.new_pathw, req->file.pathw, NULL);
|
DWORD r = CreateHardLinkW(req->fs.info.new_pathw, req->file.pathw, NULL);
|
||||||
@ -2670,6 +2708,7 @@ static void uv__fs_work(struct uv__work* w) {
|
|||||||
XX(FTRUNCATE, ftruncate)
|
XX(FTRUNCATE, ftruncate)
|
||||||
XX(UTIME, utime)
|
XX(UTIME, utime)
|
||||||
XX(FUTIME, futime)
|
XX(FUTIME, futime)
|
||||||
|
XX(LUTIME, lutime)
|
||||||
XX(ACCESS, access)
|
XX(ACCESS, access)
|
||||||
XX(CHMOD, chmod)
|
XX(CHMOD, chmod)
|
||||||
XX(FCHMOD, fchmod)
|
XX(FCHMOD, fchmod)
|
||||||
@ -3222,6 +3261,21 @@ int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file fd, double atime,
|
|||||||
POST;
|
POST;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int uv_fs_lutime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime,
|
||||||
|
double mtime, uv_fs_cb cb) {
|
||||||
|
int err;
|
||||||
|
|
||||||
|
INIT(UV_FS_LUTIME);
|
||||||
|
err = fs__capture_path(req, path, NULL, cb != NULL);
|
||||||
|
if (err) {
|
||||||
|
return uv_translate_sys_error(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
req->fs.time.atime = atime;
|
||||||
|
req->fs.time.mtime = mtime;
|
||||||
|
POST;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int uv_fs_statfs(uv_loop_t* loop,
|
int uv_fs_statfs(uv_loop_t* loop,
|
||||||
uv_fs_t* req,
|
uv_fs_t* req,
|
||||||
|
|||||||
110
test/test-fs.c
110
test/test-fs.c
@ -95,6 +95,7 @@ static int readlink_cb_count;
|
|||||||
static int realpath_cb_count;
|
static int realpath_cb_count;
|
||||||
static int utime_cb_count;
|
static int utime_cb_count;
|
||||||
static int futime_cb_count;
|
static int futime_cb_count;
|
||||||
|
static int lutime_cb_count;
|
||||||
static int statfs_cb_count;
|
static int statfs_cb_count;
|
||||||
|
|
||||||
static uv_loop_t* loop;
|
static uv_loop_t* loop;
|
||||||
@ -806,12 +807,19 @@ TEST_IMPL(fs_file_loop) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void check_utime(const char* path, double atime, double mtime) {
|
static void check_utime(const char* path,
|
||||||
|
double atime,
|
||||||
|
double mtime,
|
||||||
|
int test_lutime) {
|
||||||
uv_stat_t* s;
|
uv_stat_t* s;
|
||||||
uv_fs_t req;
|
uv_fs_t req;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
if (test_lutime)
|
||||||
|
r = uv_fs_lstat(loop, &req, path, NULL);
|
||||||
|
else
|
||||||
r = uv_fs_stat(loop, &req, path, NULL);
|
r = uv_fs_stat(loop, &req, path, NULL);
|
||||||
|
|
||||||
ASSERT(r == 0);
|
ASSERT(r == 0);
|
||||||
|
|
||||||
ASSERT(req.result == 0);
|
ASSERT(req.result == 0);
|
||||||
@ -832,7 +840,7 @@ static void utime_cb(uv_fs_t* req) {
|
|||||||
ASSERT(req->fs_type == UV_FS_UTIME);
|
ASSERT(req->fs_type == UV_FS_UTIME);
|
||||||
|
|
||||||
c = req->data;
|
c = req->data;
|
||||||
check_utime(c->path, c->atime, c->mtime);
|
check_utime(c->path, c->atime, c->mtime, /* test_lutime */ 0);
|
||||||
|
|
||||||
uv_fs_req_cleanup(req);
|
uv_fs_req_cleanup(req);
|
||||||
utime_cb_count++;
|
utime_cb_count++;
|
||||||
@ -847,13 +855,27 @@ static void futime_cb(uv_fs_t* req) {
|
|||||||
ASSERT(req->fs_type == UV_FS_FUTIME);
|
ASSERT(req->fs_type == UV_FS_FUTIME);
|
||||||
|
|
||||||
c = req->data;
|
c = req->data;
|
||||||
check_utime(c->path, c->atime, c->mtime);
|
check_utime(c->path, c->atime, c->mtime, /* test_lutime */ 0);
|
||||||
|
|
||||||
uv_fs_req_cleanup(req);
|
uv_fs_req_cleanup(req);
|
||||||
futime_cb_count++;
|
futime_cb_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void lutime_cb(uv_fs_t* req) {
|
||||||
|
utime_check_t* c;
|
||||||
|
|
||||||
|
ASSERT(req->result == 0);
|
||||||
|
ASSERT(req->fs_type == UV_FS_LUTIME);
|
||||||
|
|
||||||
|
c = req->data;
|
||||||
|
check_utime(c->path, c->atime, c->mtime, /* test_lutime */ 1);
|
||||||
|
|
||||||
|
uv_fs_req_cleanup(req);
|
||||||
|
lutime_cb_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_IMPL(fs_file_async) {
|
TEST_IMPL(fs_file_async) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -2470,7 +2492,7 @@ TEST_IMPL(fs_utime) {
|
|||||||
r = uv_fs_stat(NULL, &req, path, NULL);
|
r = uv_fs_stat(NULL, &req, path, NULL);
|
||||||
ASSERT(r == 0);
|
ASSERT(r == 0);
|
||||||
ASSERT(req.result == 0);
|
ASSERT(req.result == 0);
|
||||||
check_utime(path, atime, mtime);
|
check_utime(path, atime, mtime, /* test_lutime */ 0);
|
||||||
uv_fs_req_cleanup(&req);
|
uv_fs_req_cleanup(&req);
|
||||||
|
|
||||||
atime = mtime = 1291404900; /* 2010-12-03 20:35:00 - mees <3 */
|
atime = mtime = 1291404900; /* 2010-12-03 20:35:00 - mees <3 */
|
||||||
@ -2576,7 +2598,7 @@ TEST_IMPL(fs_futime) {
|
|||||||
r = uv_fs_stat(NULL, &req, path, NULL);
|
r = uv_fs_stat(NULL, &req, path, NULL);
|
||||||
ASSERT(r == 0);
|
ASSERT(r == 0);
|
||||||
ASSERT(req.result == 0);
|
ASSERT(req.result == 0);
|
||||||
check_utime(path, atime, mtime);
|
check_utime(path, atime, mtime, /* test_lutime */ 0);
|
||||||
uv_fs_req_cleanup(&req);
|
uv_fs_req_cleanup(&req);
|
||||||
|
|
||||||
atime = mtime = 1291404900; /* 2010-12-03 20:35:00 - mees <3 */
|
atime = mtime = 1291404900; /* 2010-12-03 20:35:00 - mees <3 */
|
||||||
@ -2600,6 +2622,84 @@ TEST_IMPL(fs_futime) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_IMPL(fs_lutime) {
|
||||||
|
utime_check_t checkme;
|
||||||
|
const char* path = "test_file";
|
||||||
|
const char* symlink_path = "test_file_symlink";
|
||||||
|
double atime;
|
||||||
|
double mtime;
|
||||||
|
uv_fs_t req;
|
||||||
|
int r, s;
|
||||||
|
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
uv_fs_req_cleanup(&req);
|
||||||
|
uv_fs_close(loop, &req, r, NULL);
|
||||||
|
|
||||||
|
unlink(symlink_path);
|
||||||
|
s = uv_fs_symlink(NULL, &req, path, symlink_path, 0, NULL);
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (s == UV_EPERM) {
|
||||||
|
/*
|
||||||
|
* Creating a symlink before Windows 10 Creators Update was only allowed
|
||||||
|
* when running elevated console (with admin rights)
|
||||||
|
*/
|
||||||
|
RETURN_SKIP(
|
||||||
|
"Symlink creation requires elevated console (with admin rights)");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
ASSERT(s == 0);
|
||||||
|
ASSERT(req.result == 0);
|
||||||
|
uv_fs_req_cleanup(&req);
|
||||||
|
|
||||||
|
/* Test the synchronous version. */
|
||||||
|
atime = mtime = 400497753; /* 1982-09-10 11:22:33 */
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
mtime += 0.444; /* 1982-09-10 11:22:33.444 */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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__)
|
||||||
|
ASSERT(r == UV_ENOSYS);
|
||||||
|
RETURN_SKIP("lutime is not implemented for z/OS and AIX versions below 7.1");
|
||||||
|
#endif
|
||||||
|
ASSERT(r == 0);
|
||||||
|
lutime_cb(&req);
|
||||||
|
ASSERT(lutime_cb_count == 1);
|
||||||
|
|
||||||
|
/* Test the asynchronous version. */
|
||||||
|
atime = mtime = 1291404900; /* 2010-12-03 20:35:00 */
|
||||||
|
|
||||||
|
checkme.atime = atime;
|
||||||
|
checkme.mtime = mtime;
|
||||||
|
checkme.path = symlink_path;
|
||||||
|
|
||||||
|
r = uv_fs_lutime(loop, &req, symlink_path, atime, mtime, lutime_cb);
|
||||||
|
ASSERT(r == 0);
|
||||||
|
uv_run(loop, UV_RUN_DEFAULT);
|
||||||
|
ASSERT(lutime_cb_count == 2);
|
||||||
|
|
||||||
|
/* Cleanup. */
|
||||||
|
unlink(path);
|
||||||
|
unlink(symlink_path);
|
||||||
|
|
||||||
|
MAKE_VALGRIND_HAPPY();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_IMPL(fs_stat_missing_path) {
|
TEST_IMPL(fs_stat_missing_path) {
|
||||||
uv_fs_t req;
|
uv_fs_t req;
|
||||||
int r;
|
int r;
|
||||||
|
|||||||
@ -353,6 +353,7 @@ TEST_DECLARE (fs_fd_hash)
|
|||||||
#endif
|
#endif
|
||||||
TEST_DECLARE (fs_utime)
|
TEST_DECLARE (fs_utime)
|
||||||
TEST_DECLARE (fs_futime)
|
TEST_DECLARE (fs_futime)
|
||||||
|
TEST_DECLARE (fs_lutime)
|
||||||
TEST_DECLARE (fs_file_open_append)
|
TEST_DECLARE (fs_file_open_append)
|
||||||
TEST_DECLARE (fs_statfs)
|
TEST_DECLARE (fs_statfs)
|
||||||
TEST_DECLARE (fs_stat_missing_path)
|
TEST_DECLARE (fs_stat_missing_path)
|
||||||
@ -969,6 +970,7 @@ TASK_LIST_START
|
|||||||
TEST_ENTRY (fs_chown)
|
TEST_ENTRY (fs_chown)
|
||||||
TEST_ENTRY (fs_utime)
|
TEST_ENTRY (fs_utime)
|
||||||
TEST_ENTRY (fs_futime)
|
TEST_ENTRY (fs_futime)
|
||||||
|
TEST_ENTRY (fs_lutime)
|
||||||
TEST_ENTRY (fs_readlink)
|
TEST_ENTRY (fs_readlink)
|
||||||
TEST_ENTRY (fs_realpath)
|
TEST_ENTRY (fs_realpath)
|
||||||
TEST_ENTRY (fs_symlink)
|
TEST_ENTRY (fs_symlink)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user