diff --git a/docs/src/fs.rst b/docs/src/fs.rst index 61c7f3fc..b8b3dc0e 100644 --- a/docs/src/fs.rst +++ b/docs/src/fs.rst @@ -92,6 +92,7 @@ Data types UV_FS_READLINK, UV_FS_CHOWN, UV_FS_FCHOWN, + UV_FS_LCHOWN, UV_FS_REALPATH, UV_FS_COPYFILE } uv_fs_type; @@ -358,14 +359,17 @@ API .. c:function:: int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb) .. c:function:: int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_os_fd_t file, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb) +.. c:function:: int uv_fs_lchown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb) - Equivalent to :man:`chown(2)` and :man:`fchown(2)` respectively. + Equivalent to :man:`chown(2)`, :man:`fchown(2)` and :man:`lchown(2)` respectively. .. note:: These functions are not implemented on Windows. .. versionchanged:: 2.0.0 replace uv_file with uv_os_fd_t + .. versionchanged:: 2.0.0 implemented uv_fs_lchown + .. c:function:: uv_fs_type uv_fs_get_type(const uv_fs_t* req) Returns `req->fs_type`. diff --git a/include/uv.h b/include/uv.h index 7fe8a842..cee3d8dd 100644 --- a/include/uv.h +++ b/include/uv.h @@ -1200,6 +1200,7 @@ typedef enum { UV_FS_READLINK, UV_FS_CHOWN, UV_FS_FCHOWN, + UV_FS_LCHOWN, UV_FS_REALPATH, UV_FS_COPYFILE } uv_fs_type; @@ -1406,6 +1407,12 @@ UV_EXTERN int uv_fs_fchown(uv_loop_t* loop, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb); +UV_EXTERN int uv_fs_lchown(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + uv_uid_t uid, + uv_gid_t gid, + uv_fs_cb cb); enum uv_fs_event { diff --git a/src/unix/fs.c b/src/unix/fs.c index e1229bf0..1e4327c2 100644 --- a/src/unix/fs.c +++ b/src/unix/fs.c @@ -1146,6 +1146,7 @@ static void uv__fs_work(struct uv__work* w) { X(COPYFILE, uv__fs_copyfile(req)); X(FCHMOD, fchmod(req->file, 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)); X(FSTAT, uv__fs_fstat(req->file, &req->statbuf)); X(FSYNC, uv__fs_fsync(req)); @@ -1272,6 +1273,20 @@ int uv_fs_fchown(uv_loop_t* loop, } +int uv_fs_lchown(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + uv_uid_t uid, + uv_gid_t gid, + uv_fs_cb cb) { + INIT(LCHOWN); + PATH; + req->uid = uid; + req->gid = gid; + POST; +} + + int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_os_fd_t file, uv_fs_cb cb) { INIT(FDATASYNC); req->file = file; diff --git a/src/win/fs.c b/src/win/fs.c index d8649951..8152aacd 100644 --- a/src/win/fs.c +++ b/src/win/fs.c @@ -1913,6 +1913,10 @@ static void fs__fchown(uv_fs_t* req) { } +static void fs__lchown(uv_fs_t* req) { + req->result = 0; +} + static void uv__fs_work(struct uv__work* w) { uv_fs_t* req; @@ -1950,6 +1954,7 @@ static void uv__fs_work(struct uv__work* w) { XX(REALPATH, realpath) XX(CHOWN, chown) XX(FCHOWN, fchown); + XX(LCHOWN, lchown); default: assert(!"bad uv_fs_type"); } @@ -2236,6 +2241,19 @@ int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_os_fd_t hFile, uv_uid_t uid, } +int uv_fs_lchown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, + uv_gid_t gid, uv_fs_cb cb) { + int err; + + INIT(UV_FS_LCHOWN); + err = fs__capture_path(req, path, NULL, cb != NULL); + if (err) { + return uv_translate_sys_error(err); + } + POST; +} + + int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { int err; diff --git a/test/test-fs.c b/test/test-fs.c index 4e3e96c7..5f0b341a 100644 --- a/test/test-fs.c +++ b/test/test-fs.c @@ -86,6 +86,7 @@ static int chmod_cb_count; static int fchmod_cb_count; static int chown_cb_count; static int fchown_cb_count; +static int lchown_cb_count; static int link_cb_count; static int symlink_cb_count; static int readlink_cb_count; @@ -245,6 +246,13 @@ static void chown_cb(uv_fs_t* req) { uv_fs_req_cleanup(req); } +static void lchown_cb(uv_fs_t* req) { + ASSERT(req->fs_type == UV_FS_LCHOWN); + ASSERT(req->result == 0); + lchown_cb_count++; + uv_fs_req_cleanup(req); +} + static void chown_root_cb(uv_fs_t* req) { ASSERT(req->fs_type == UV_FS_CHOWN); #if defined(_WIN32) || defined(__MSYS__) @@ -1524,6 +1532,7 @@ TEST_IMPL(fs_chown) { /* Setup. */ unlink("test_file"); + unlink("test_file_link"); loop = uv_default_loop(); @@ -1567,6 +1576,24 @@ TEST_IMPL(fs_chown) { uv_run(loop, UV_RUN_DEFAULT); ASSERT(fchown_cb_count == 1); + /* sync 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 lchown */ + r = uv_fs_lchown(NULL, &req, "test_file_link", -1, -1, NULL); + ASSERT(r == 0); + ASSERT(req.result == 0); + uv_fs_req_cleanup(&req); + + /* async lchown */ + r = uv_fs_lchown(loop, &req, "test_file_link", -1, -1, lchown_cb); + ASSERT(r == 0); + uv_run(loop, UV_RUN_DEFAULT); + ASSERT(lchown_cb_count == 1); + /* Close file */ r = uv_fs_close(NULL, &req, file, NULL); ASSERT(r == 0); @@ -1581,6 +1608,7 @@ TEST_IMPL(fs_chown) { /* Cleanup. */ unlink("test_file"); + unlink("test_file_link"); MAKE_VALGRIND_HAPPY(); return 0;