unix, windows: add uv_fs_access()
This commit is contained in:
parent
416b7335fc
commit
c18205a1c5
@ -76,6 +76,7 @@ Data types
|
||||
UV_FS_FTRUNCATE,
|
||||
UV_FS_UTIME,
|
||||
UV_FS_FUTIME,
|
||||
UV_FS_ACCESS,
|
||||
UV_FS_CHMOD,
|
||||
UV_FS_FCHMOD,
|
||||
UV_FS_FSYNC,
|
||||
@ -228,6 +229,10 @@ API
|
||||
|
||||
Limited equivalent to ``sendfile(2)``.
|
||||
|
||||
.. c:function:: int uv_fs_access(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, uv_fs_cb cb)
|
||||
|
||||
Equivalent to ``access(2)`` on Unix. Windows uses ``GetFileAttributesW()``.
|
||||
|
||||
.. 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)
|
||||
|
||||
|
||||
@ -639,3 +639,15 @@ int uv_utf16_to_utf8(const WCHAR* utf16Buffer, size_t utf16Size,
|
||||
int uv_utf8_to_utf16(const char* utf8Buffer, WCHAR* utf16Buffer,
|
||||
size_t utf16Size);
|
||||
|
||||
#ifndef F_OK
|
||||
#define F_OK 0
|
||||
#endif
|
||||
#ifndef R_OK
|
||||
#define R_OK 4
|
||||
#endif
|
||||
#ifndef W_OK
|
||||
#define W_OK 2
|
||||
#endif
|
||||
#ifndef X_OK
|
||||
#define X_OK 1
|
||||
#endif
|
||||
|
||||
@ -1022,6 +1022,7 @@ typedef enum {
|
||||
UV_FS_FTRUNCATE,
|
||||
UV_FS_UTIME,
|
||||
UV_FS_FUTIME,
|
||||
UV_FS_ACCESS,
|
||||
UV_FS_CHMOD,
|
||||
UV_FS_FCHMOD,
|
||||
UV_FS_FSYNC,
|
||||
@ -1134,6 +1135,11 @@ UV_EXTERN int uv_fs_sendfile(uv_loop_t* loop,
|
||||
int64_t in_offset,
|
||||
size_t length,
|
||||
uv_fs_cb cb);
|
||||
UV_EXTERN int uv_fs_access(uv_loop_t* loop,
|
||||
uv_fs_t* req,
|
||||
const char* path,
|
||||
int flags,
|
||||
uv_fs_cb cb);
|
||||
UV_EXTERN int uv_fs_chmod(uv_loop_t* loop,
|
||||
uv_fs_t* req,
|
||||
const char* path,
|
||||
|
||||
@ -763,6 +763,7 @@ static void uv__fs_work(struct uv__work* w) {
|
||||
break;
|
||||
|
||||
switch (req->fs_type) {
|
||||
X(ACCESS, access(req->path, req->flags));
|
||||
X(CHMOD, chmod(req->path, req->mode));
|
||||
X(CHOWN, chown(req->path, req->uid, req->gid));
|
||||
X(CLOSE, close(req->file));
|
||||
@ -853,6 +854,18 @@ static void uv__fs_done(struct uv__work* w, int status) {
|
||||
}
|
||||
|
||||
|
||||
int uv_fs_access(uv_loop_t* loop,
|
||||
uv_fs_t* req,
|
||||
const char* path,
|
||||
int flags,
|
||||
uv_fs_cb cb) {
|
||||
INIT(ACCESS);
|
||||
PATH;
|
||||
req->flags = flags;
|
||||
POST;
|
||||
}
|
||||
|
||||
|
||||
int uv_fs_chmod(uv_loop_t* loop,
|
||||
uv_fs_t* req,
|
||||
const char* path,
|
||||
|
||||
45
src/win/fs.c
45
src/win/fs.c
@ -1220,6 +1220,25 @@ static void fs__sendfile(uv_fs_t* req) {
|
||||
}
|
||||
|
||||
|
||||
static void fs__access(uv_fs_t* req) {
|
||||
DWORD attr = GetFileAttributesW(req->pathw);
|
||||
|
||||
if (attr == INVALID_FILE_ATTRIBUTES) {
|
||||
SET_REQ_WIN32_ERROR(req, GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
if ((req->flags & W_OK) &&
|
||||
((attr & FILE_ATTRIBUTE_READONLY) ||
|
||||
(attr & FILE_ATTRIBUTE_DIRECTORY))) {
|
||||
SET_REQ_WIN32_ERROR(req, UV_EPERM);
|
||||
return;
|
||||
}
|
||||
|
||||
SET_REQ_RESULT(req, 0);
|
||||
}
|
||||
|
||||
|
||||
static void fs__chmod(uv_fs_t* req) {
|
||||
int result = _wchmod(req->pathw, req->mode);
|
||||
SET_REQ_RESULT(req, result);
|
||||
@ -1595,6 +1614,7 @@ static void uv__fs_work(struct uv__work* w) {
|
||||
XX(FTRUNCATE, ftruncate)
|
||||
XX(UTIME, utime)
|
||||
XX(FUTIME, futime)
|
||||
XX(ACCESS, access)
|
||||
XX(CHMOD, chmod)
|
||||
XX(FCHMOD, fchmod)
|
||||
XX(FSYNC, fsync)
|
||||
@ -2102,6 +2122,31 @@ int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file fd_out,
|
||||
}
|
||||
|
||||
|
||||
int uv_fs_access(uv_loop_t* loop,
|
||||
uv_fs_t* req,
|
||||
const char* path,
|
||||
int flags,
|
||||
uv_fs_cb cb) {
|
||||
int err;
|
||||
|
||||
uv_fs_req_init(loop, req, UV_FS_ACCESS, cb);
|
||||
|
||||
err = fs__capture_path(loop, req, path, NULL, cb != NULL);
|
||||
if (err)
|
||||
return uv_translate_sys_error(err);
|
||||
|
||||
req->flags = flags;
|
||||
|
||||
if (cb) {
|
||||
QUEUE_FS_TP_JOB(loop, req);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fs__access(req);
|
||||
return req->result;
|
||||
}
|
||||
|
||||
|
||||
int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode,
|
||||
uv_fs_cb cb) {
|
||||
int err;
|
||||
|
||||
@ -75,6 +75,7 @@ static int fdatasync_cb_count;
|
||||
static int ftruncate_cb_count;
|
||||
static int sendfile_cb_count;
|
||||
static int fstat_cb_count;
|
||||
static int access_cb_count;
|
||||
static int chmod_cb_count;
|
||||
static int fchmod_cb_count;
|
||||
static int chown_cb_count;
|
||||
@ -164,6 +165,14 @@ static void readlink_cb(uv_fs_t* req) {
|
||||
uv_fs_req_cleanup(req);
|
||||
}
|
||||
|
||||
|
||||
static void access_cb(uv_fs_t* req) {
|
||||
ASSERT(req->fs_type == UV_FS_ACCESS);
|
||||
access_cb_count++;
|
||||
uv_fs_req_cleanup(req);
|
||||
}
|
||||
|
||||
|
||||
static void fchmod_cb(uv_fs_t* req) {
|
||||
ASSERT(req->fs_type == UV_FS_FCHMOD);
|
||||
ASSERT(req->result == 0);
|
||||
@ -1119,6 +1128,70 @@ TEST_IMPL(fs_fstat) {
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(fs_access) {
|
||||
int r;
|
||||
uv_fs_t req;
|
||||
uv_file file;
|
||||
|
||||
/* Setup. */
|
||||
unlink("test_file");
|
||||
|
||||
loop = uv_default_loop();
|
||||
|
||||
/* File should not exist */
|
||||
r = uv_fs_access(loop, &req, "test_file", F_OK, NULL);
|
||||
ASSERT(r < 0);
|
||||
ASSERT(req.result < 0);
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
/* File should not exist */
|
||||
r = uv_fs_access(loop, &req, "test_file", F_OK, access_cb);
|
||||
ASSERT(r == 0);
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
ASSERT(access_cb_count == 1);
|
||||
access_cb_count = 0; /* reset for the next test */
|
||||
|
||||
/* Create file */
|
||||
r = uv_fs_open(loop, &req, "test_file", O_RDWR | O_CREAT,
|
||||
S_IWUSR | S_IRUSR, NULL);
|
||||
ASSERT(r >= 0);
|
||||
ASSERT(req.result >= 0);
|
||||
file = req.result;
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
/* File should exist */
|
||||
r = uv_fs_access(loop, &req, "test_file", F_OK, NULL);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(req.result == 0);
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
/* File should exist */
|
||||
r = uv_fs_access(loop, &req, "test_file", F_OK, access_cb);
|
||||
ASSERT(r == 0);
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
ASSERT(access_cb_count == 1);
|
||||
access_cb_count = 0; /* reset for the next test */
|
||||
|
||||
/* Close file */
|
||||
r = uv_fs_close(loop, &req, file, NULL);
|
||||
ASSERT(r == 0);
|
||||
ASSERT(req.result == 0);
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
/*
|
||||
* Run the loop just to check we don't have make any extraneous uv_ref()
|
||||
* calls. This should drop out immediately.
|
||||
*/
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
/* Cleanup. */
|
||||
unlink("test_file");
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(fs_chmod) {
|
||||
int r;
|
||||
uv_fs_t req;
|
||||
|
||||
@ -218,6 +218,7 @@ TEST_DECLARE (fs_async_dir)
|
||||
TEST_DECLARE (fs_async_sendfile)
|
||||
TEST_DECLARE (fs_mkdtemp)
|
||||
TEST_DECLARE (fs_fstat)
|
||||
TEST_DECLARE (fs_access)
|
||||
TEST_DECLARE (fs_chmod)
|
||||
TEST_DECLARE (fs_chown)
|
||||
TEST_DECLARE (fs_link)
|
||||
@ -590,6 +591,7 @@ TASK_LIST_START
|
||||
TEST_ENTRY (fs_async_sendfile)
|
||||
TEST_ENTRY (fs_mkdtemp)
|
||||
TEST_ENTRY (fs_fstat)
|
||||
TEST_ENTRY (fs_access)
|
||||
TEST_ENTRY (fs_chmod)
|
||||
TEST_ENTRY (fs_chown)
|
||||
TEST_ENTRY (fs_utime)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user