Skip to content

Commit

Permalink
fs: implement uv_fs_lchmod
Browse files Browse the repository at this point in the history
It uses `lchmod()` or `fchmodat()` where supported. Otherwise it returns
`UV_ENOTSUP`.

Refs: nodejs/node#23736
  • Loading branch information
santigimeno committed Oct 24, 2018
1 parent b901e26 commit 69e6fed
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 3 deletions.
12 changes: 10 additions & 2 deletions docs/src/fs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ Data types
UV_FS_FCHOWN,
UV_FS_REALPATH,
UV_FS_COPYFILE,
UV_FS_LCHOWN
UV_FS_LCHOWN,
UV_FS_LCHMOD
} uv_fs_type;

.. c:type:: uv_dirent_t
Expand Down Expand Up @@ -284,8 +285,15 @@ API
.. c:function:: int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb)
.. c:function:: int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file file, int mode, uv_fs_cb cb)
.. c:function:: int uv_fs_lchmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb)
Equivalent to :man:`chmod(2)` and :man:`fchmod(2)` respectively.
Equivalent to :man:`chmod(2)`, :man:`fchmod(2)` and :man:`lchmod(2)` respectively.
.. note::
`uv_fs_lchmod` is not supported on many platforms such as `glibc Linux`,
`Windows` and `OpenBSD`. In such cases it returns ``UV_ENOTSUP``.
.. versionchanged:: 1.24.0 implemented uv_fs_lchmod
.. 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)
Expand Down
8 changes: 7 additions & 1 deletion include/uv.h
Original file line number Diff line number Diff line change
Expand Up @@ -1157,7 +1157,8 @@ typedef enum {
UV_FS_FCHOWN,
UV_FS_REALPATH,
UV_FS_COPYFILE,
UV_FS_LCHOWN
UV_FS_LCHOWN,
UV_FS_LCHMOD
} uv_fs_type;

/* uv_fs_t is a subclass of uv_req_t. */
Expand Down Expand Up @@ -1348,6 +1349,11 @@ UV_EXTERN int uv_fs_fchmod(uv_loop_t* loop,
uv_file file,
int mode,
uv_fs_cb cb);
UV_EXTERN int uv_fs_lchmod(uv_loop_t* loop,
uv_fs_t* req,
const char* path,
int mode,
uv_fs_cb cb);
UV_EXTERN int uv_fs_chown(uv_loop_t* loop,
uv_fs_t* req,
const char* path,
Expand Down
33 changes: 33 additions & 0 deletions src/unix/fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,27 @@ static ssize_t uv__fs_fsync(uv_fs_t* req) {
}


static int uv__fs_lchmod(const char *path, mode_t mode) {
#if defined(__APPLE__) \
|| defined(__DragonFly__) \
|| defined(__FreeBSD__) \
|| defined(__FreeBSD_kernel__) \
|| defined(__NetBSD__)
return lchmod(path, mode);
#elif defined(AT_SYMLINK_NOFOLLOW)
int r;
r = fchmodat(AT_FDCWD, path, mode, AT_SYMLINK_NOFOLLOW);
if (r == -1 && errno == EOPNOTSUPP)
errno = ENOTSUP;

return r;
#else
errno = ENOTSUP;
return -1;
#endif
}


static ssize_t uv__fs_fdatasync(uv_fs_t* req) {
#if defined(__linux__) || defined(__sun) || defined(__NetBSD__)
return fdatasync(req->file);
Expand Down Expand Up @@ -1140,6 +1161,7 @@ static void uv__fs_work(struct uv__work* w) {
X(CLOSE, close(req->file));
X(COPYFILE, uv__fs_copyfile(req));
X(FCHMOD, fchmod(req->file, req->mode));
X(LCHMOD, uv__fs_lchmod(req->path, req->mode));
X(FCHOWN, fchown(req->file, req->uid, req->gid));
X(LCHOWN, lchown(req->path, req->uid, req->gid));
X(FDATASYNC, uv__fs_fdatasync(req));
Expand Down Expand Up @@ -1253,6 +1275,17 @@ int uv_fs_fchmod(uv_loop_t* loop,
POST;
}

int uv_fs_lchmod(uv_loop_t* loop,
uv_fs_t* req,
const char* path,
int mode,
uv_fs_cb cb) {
INIT(LCHMOD);
PATH;
req->mode = mode;
POST;
}


int uv_fs_fchown(uv_loop_t* loop,
uv_fs_t* req,
Expand Down
19 changes: 19 additions & 0 deletions src/win/fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1577,6 +1577,11 @@ static void fs__fchmod(uv_fs_t* req) {
}


static void fs__lchmod(uv_fs_t* req) {
SET_REQ_RESULT(req, UV_ENOTSUP);
}


INLINE static int fs__utime_handle(HANDLE handle, double atime, double mtime) {
FILETIME filetime_a, filetime_m;

Expand Down Expand Up @@ -2002,6 +2007,7 @@ static void uv__fs_work(struct uv__work* w) {
XX(ACCESS, access)
XX(CHMOD, chmod)
XX(FCHMOD, fchmod)
XX(LCHMOD, lchmod)
XX(FSYNC, fsync)
XX(FDATASYNC, fdatasync)
XX(UNLINK, unlink)
Expand Down Expand Up @@ -2462,6 +2468,19 @@ int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file fd, int mode,
POST;
}

int uv_fs_lchmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode,
uv_fs_cb cb) {
int err;

INIT(UV_FS_LCHMOD);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
}

POST;
}


int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime,
double mtime, uv_fs_cb cb) {
Expand Down
28 changes: 28 additions & 0 deletions test/test-fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ static int fstat_cb_count;
static int access_cb_count;
static int chmod_cb_count;
static int fchmod_cb_count;
static int lchmod_cb_count;
static int chown_cb_count;
static int fchown_cb_count;
static int lchown_cb_count;
Expand Down Expand Up @@ -264,6 +265,13 @@ static void chmod_cb(uv_fs_t* req) {
check_permission("test_file", *(int*)req->data);
}

static void lchmod_cb(uv_fs_t* req) {
ASSERT(req->fs_type == UV_FS_LCHMOD);
ASSERT(req->result == 0 || req->result == UV_ENOTSUP);
lchmod_cb_count++;
uv_fs_req_cleanup(req);
}


static void fchown_cb(uv_fs_t* req) {
ASSERT(req->fs_type == UV_FS_FCHOWN);
Expand Down Expand Up @@ -1436,6 +1444,25 @@ TEST_IMPL(fs_chmod) {

close(file);

/* sync link */
unlink("test_file_link");
r = uv_fs_link(NULL, &req, "test_file", "test_file_link", NULL);
ASSERT(r == 0);
ASSERT(req.result == 0);
uv_fs_req_cleanup(&req);

/* sync lchmod */
r = uv_fs_lchmod(NULL, &req, "test_file_link", 0400, NULL);
ASSERT(r == 0 || r == UV_ENOTSUP);
ASSERT(req.result == 0 || req.result == UV_ENOTSUP);
uv_fs_req_cleanup(&req);

/* async lchmod */
r = uv_fs_lchmod(loop, &req, "test_file_link", 0600, lchmod_cb);
ASSERT(r == 0);
uv_run(loop, UV_RUN_DEFAULT);
ASSERT(lchmod_cb_count == 1);

/*
* Run the loop just to check we don't have make any extraneous uv_ref()
* calls. This should drop out immediately.
Expand All @@ -1444,6 +1471,7 @@ TEST_IMPL(fs_chmod) {

/* Cleanup. */
unlink("test_file");
unlink("test_file_link");

MAKE_VALGRIND_HAPPY();
return 0;
Expand Down

0 comments on commit 69e6fed

Please sign in to comment.