summaryrefslogtreecommitdiffstats
path: root/Utilities/cmlibuv/src/win/fs.c
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmlibuv/src/win/fs.c')
-rw-r--r--Utilities/cmlibuv/src/win/fs.c279
1 files changed, 231 insertions, 48 deletions
diff --git a/Utilities/cmlibuv/src/win/fs.c b/Utilities/cmlibuv/src/win/fs.c
index 8502b07..9577bc0 100644
--- a/Utilities/cmlibuv/src/win/fs.c
+++ b/Utilities/cmlibuv/src/win/fs.c
@@ -257,6 +257,7 @@ INLINE static void uv_fs_req_init(uv_loop_t* loop, uv_fs_t* req,
req->loop = loop;
req->flags = 0;
req->fs_type = fs_type;
+ req->sys_errno_ = 0;
req->result = 0;
req->ptr = NULL;
req->path = NULL;
@@ -321,6 +322,8 @@ INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr,
WCHAR* w_target;
DWORD w_target_len;
DWORD bytes;
+ size_t i;
+ size_t len;
if (!DeviceIoControl(handle,
FSCTL_GET_REPARSE_POINT,
@@ -405,6 +408,38 @@ INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr,
w_target += 4;
w_target_len -= 4;
+ } else if (reparse_data->ReparseTag == IO_REPARSE_TAG_APPEXECLINK) {
+ /* String #3 in the list has the target filename. */
+ if (reparse_data->AppExecLinkReparseBuffer.StringCount < 3) {
+ SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
+ return -1;
+ }
+ w_target = reparse_data->AppExecLinkReparseBuffer.StringList;
+ /* The StringList buffer contains a list of strings separated by "\0", */
+ /* with "\0\0" terminating the list. Move to the 3rd string in the list: */
+ for (i = 0; i < 2; ++i) {
+ len = wcslen(w_target);
+ if (len == 0) {
+ SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
+ return -1;
+ }
+ w_target += len + 1;
+ }
+ w_target_len = wcslen(w_target);
+ if (w_target_len == 0) {
+ SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
+ return -1;
+ }
+ /* Make sure it is an absolute path. */
+ if (!(w_target_len >= 3 &&
+ ((w_target[0] >= L'a' && w_target[0] <= L'z') ||
+ (w_target[0] >= L'A' && w_target[0] <= L'Z')) &&
+ w_target[1] == L':' &&
+ w_target[2] == L'\\')) {
+ SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
+ return -1;
+ }
+
} else {
/* Reparse tag does not indicate a symlink. */
SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
@@ -2225,34 +2260,68 @@ INLINE static int fs__utime_handle(HANDLE handle, double atime, double mtime) {
return 0;
}
-
-static void fs__utime(uv_fs_t* req) {
+INLINE static DWORD fs__utime_impl_from_path(WCHAR* path,
+ double atime,
+ double mtime,
+ int do_lutime) {
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_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
- FILE_FLAG_BACKUP_SEMANTICS,
+ flags,
NULL);
if (handle == INVALID_HANDLE_VALUE) {
- SET_REQ_WIN32_ERROR(req, GetLastError());
- return;
+ ret = GetLastError();
+ } else if (fs__utime_handle(handle, atime, mtime) != 0) {
+ ret = GetLastError();
+ } else {
+ ret = 0;
}
- if (fs__utime_handle(handle, req->fs.time.atime, req->fs.time.mtime) != 0) {
- SET_REQ_WIN32_ERROR(req, GetLastError());
- 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;
}
- CloseHandle(handle);
-
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) {
int fd = req->file.fd;
@@ -2274,6 +2343,10 @@ static void fs__futime(uv_fs_t* req) {
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) {
DWORD r = CreateHardLinkW(req->fs.info.new_pathw, req->file.pathw, NULL);
@@ -2621,14 +2694,62 @@ static void fs__statfs(uv_fs_t* req) {
DWORD bytes_per_sector;
DWORD free_clusters;
DWORD total_clusters;
+ WCHAR* pathw;
- if (0 == GetDiskFreeSpaceW(req->file.pathw,
+ pathw = req->file.pathw;
+retry_get_disk_free_space:
+ if (0 == GetDiskFreeSpaceW(pathw,
&sectors_per_cluster,
&bytes_per_sector,
&free_clusters,
&total_clusters)) {
- SET_REQ_WIN32_ERROR(req, GetLastError());
- return;
+ DWORD err;
+ WCHAR* fpart;
+ size_t len;
+ DWORD ret;
+ BOOL is_second;
+
+ err = GetLastError();
+ is_second = pathw != req->file.pathw;
+ if (err != ERROR_DIRECTORY || is_second) {
+ if (is_second)
+ uv__free(pathw);
+
+ SET_REQ_WIN32_ERROR(req, err);
+ return;
+ }
+
+ len = MAX_PATH + 1;
+ pathw = uv__malloc(len * sizeof(*pathw));
+ if (pathw == NULL) {
+ SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
+ return;
+ }
+retry_get_full_path_name:
+ ret = GetFullPathNameW(req->file.pathw,
+ len,
+ pathw,
+ &fpart);
+ if (ret == 0) {
+ uv__free(pathw);
+ SET_REQ_WIN32_ERROR(req, err);
+ return;
+ } else if (ret > len) {
+ len = ret;
+ pathw = uv__reallocf(pathw, len * sizeof(*pathw));
+ if (pathw == NULL) {
+ SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
+ return;
+ }
+ goto retry_get_full_path_name;
+ }
+ if (fpart != 0)
+ *fpart = L'\0';
+
+ goto retry_get_disk_free_space;
+ }
+ if (pathw != req->file.pathw) {
+ uv__free(pathw);
}
stat_fs = uv__malloc(sizeof(*stat_fs));
@@ -2670,6 +2791,7 @@ static void uv__fs_work(struct uv__work* w) {
XX(FTRUNCATE, ftruncate)
XX(UTIME, utime)
XX(FUTIME, futime)
+ XX(LUTIME, lutime)
XX(ACCESS, access)
XX(CHMOD, chmod)
XX(FCHMOD, fchmod)
@@ -2753,7 +2875,8 @@ int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
INIT(UV_FS_OPEN);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
- return uv_translate_sys_error(err);
+ SET_REQ_WIN32_ERROR(req, err);
+ return req->result;
}
req->fs.info.file_flags = flags;
@@ -2778,8 +2901,10 @@ int uv_fs_read(uv_loop_t* loop,
uv_fs_cb cb) {
INIT(UV_FS_READ);
- if (bufs == NULL || nbufs == 0)
+ if (bufs == NULL || nbufs == 0) {
+ SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
return UV_EINVAL;
+ }
req->file.fd = fd;
@@ -2788,8 +2913,10 @@ int uv_fs_read(uv_loop_t* loop,
if (nbufs > ARRAY_SIZE(req->fs.info.bufsml))
req->fs.info.bufs = uv__malloc(nbufs * sizeof(*bufs));
- if (req->fs.info.bufs == NULL)
+ if (req->fs.info.bufs == NULL) {
+ SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
return UV_ENOMEM;
+ }
memcpy(req->fs.info.bufs, bufs, nbufs * sizeof(*bufs));
@@ -2807,8 +2934,10 @@ int uv_fs_write(uv_loop_t* loop,
uv_fs_cb cb) {
INIT(UV_FS_WRITE);
- if (bufs == NULL || nbufs == 0)
+ if (bufs == NULL || nbufs == 0) {
+ SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
return UV_EINVAL;
+ }
req->file.fd = fd;
@@ -2817,8 +2946,10 @@ int uv_fs_write(uv_loop_t* loop,
if (nbufs > ARRAY_SIZE(req->fs.info.bufsml))
req->fs.info.bufs = uv__malloc(nbufs * sizeof(*bufs));
- if (req->fs.info.bufs == NULL)
+ if (req->fs.info.bufs == NULL) {
+ SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
return UV_ENOMEM;
+ }
memcpy(req->fs.info.bufs, bufs, nbufs * sizeof(*bufs));
@@ -2834,7 +2965,8 @@ int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
INIT(UV_FS_UNLINK);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
- return uv_translate_sys_error(err);
+ SET_REQ_WIN32_ERROR(req, err);
+ return req->result;
}
POST;
@@ -2848,7 +2980,8 @@ int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode,
INIT(UV_FS_MKDIR);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
- return uv_translate_sys_error(err);
+ SET_REQ_WIN32_ERROR(req, err);
+ return req->result;
}
req->fs.info.mode = mode;
@@ -2864,8 +2997,10 @@ int uv_fs_mkdtemp(uv_loop_t* loop,
INIT(UV_FS_MKDTEMP);
err = fs__capture_path(req, tpl, NULL, TRUE);
- if (err)
- return uv_translate_sys_error(err);
+ if (err) {
+ SET_REQ_WIN32_ERROR(req, err);
+ return req->result;
+ }
POST;
}
@@ -2879,8 +3014,10 @@ int uv_fs_mkstemp(uv_loop_t* loop,
INIT(UV_FS_MKSTEMP);
err = fs__capture_path(req, tpl, NULL, TRUE);
- if (err)
- return uv_translate_sys_error(err);
+ if (err) {
+ SET_REQ_WIN32_ERROR(req, err);
+ return req->result;
+ }
POST;
}
@@ -2892,7 +3029,8 @@ int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
INIT(UV_FS_RMDIR);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
- return uv_translate_sys_error(err);
+ SET_REQ_WIN32_ERROR(req, err);
+ return req->result;
}
POST;
@@ -2906,7 +3044,8 @@ int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
INIT(UV_FS_SCANDIR);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
- return uv_translate_sys_error(err);
+ SET_REQ_WIN32_ERROR(req, err);
+ return req->result;
}
req->fs.info.file_flags = flags;
@@ -2921,8 +3060,10 @@ int uv_fs_opendir(uv_loop_t* loop,
INIT(UV_FS_OPENDIR);
err = fs__capture_path(req, path, NULL, cb != NULL);
- if (err)
- return uv_translate_sys_error(err);
+ if (err) {
+ SET_REQ_WIN32_ERROR(req, err);
+ return req->result;
+ }
POST;
}
@@ -2935,6 +3076,7 @@ int uv_fs_readdir(uv_loop_t* loop,
if (dir == NULL ||
dir->dirents == NULL ||
dir->dir_handle == INVALID_HANDLE_VALUE) {
+ SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
return UV_EINVAL;
}
@@ -2947,8 +3089,10 @@ int uv_fs_closedir(uv_loop_t* loop,
uv_dir_t* dir,
uv_fs_cb cb) {
INIT(UV_FS_CLOSEDIR);
- if (dir == NULL)
+ if (dir == NULL) {
+ SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
return UV_EINVAL;
+ }
req->ptr = dir;
POST;
}
@@ -2960,7 +3104,8 @@ int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path,
INIT(UV_FS_LINK);
err = fs__capture_path(req, path, new_path, cb != NULL);
if (err) {
- return uv_translate_sys_error(err);
+ SET_REQ_WIN32_ERROR(req, err);
+ return req->result;
}
POST;
@@ -2974,7 +3119,8 @@ int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
INIT(UV_FS_SYMLINK);
err = fs__capture_path(req, path, new_path, cb != NULL);
if (err) {
- return uv_translate_sys_error(err);
+ SET_REQ_WIN32_ERROR(req, err);
+ return req->result;
}
req->fs.info.file_flags = flags;
@@ -2989,7 +3135,8 @@ int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
INIT(UV_FS_READLINK);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
- return uv_translate_sys_error(err);
+ SET_REQ_WIN32_ERROR(req, err);
+ return req->result;
}
POST;
@@ -3003,12 +3150,14 @@ int uv_fs_realpath(uv_loop_t* loop, uv_fs_t* req, const char* path,
INIT(UV_FS_REALPATH);
if (!path) {
+ SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
return UV_EINVAL;
}
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
- return uv_translate_sys_error(err);
+ SET_REQ_WIN32_ERROR(req, err);
+ return req->result;
}
POST;
@@ -3022,7 +3171,8 @@ int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid,
INIT(UV_FS_CHOWN);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
- return uv_translate_sys_error(err);
+ SET_REQ_WIN32_ERROR(req, err);
+ return req->result;
}
POST;
@@ -3043,8 +3193,10 @@ int uv_fs_lchown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid,
INIT(UV_FS_LCHOWN);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
- return uv_translate_sys_error(err);
+ SET_REQ_WIN32_ERROR(req, err);
+ return req->result;
}
+
POST;
}
@@ -3055,7 +3207,8 @@ int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
INIT(UV_FS_STAT);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
- return uv_translate_sys_error(err);
+ SET_REQ_WIN32_ERROR(req, err);
+ return req->result;
}
POST;
@@ -3068,7 +3221,8 @@ int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
INIT(UV_FS_LSTAT);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
- return uv_translate_sys_error(err);
+ SET_REQ_WIN32_ERROR(req, err);
+ return req->result;
}
POST;
@@ -3089,7 +3243,8 @@ int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path,
INIT(UV_FS_RENAME);
err = fs__capture_path(req, path, new_path, cb != NULL);
if (err) {
- return uv_translate_sys_error(err);
+ SET_REQ_WIN32_ERROR(req, err);
+ return req->result;
}
POST;
@@ -3132,13 +3287,15 @@ int uv_fs_copyfile(uv_loop_t* loop,
if (flags & ~(UV_FS_COPYFILE_EXCL |
UV_FS_COPYFILE_FICLONE |
UV_FS_COPYFILE_FICLONE_FORCE)) {
+ SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
return UV_EINVAL;
}
err = fs__capture_path(req, path, new_path, cb != NULL);
-
- if (err)
- return uv_translate_sys_error(err);
+ if (err) {
+ SET_REQ_WIN32_ERROR(req, err);
+ return req->result;
+ }
req->fs.info.file_flags = flags;
POST;
@@ -3165,8 +3322,10 @@ int uv_fs_access(uv_loop_t* loop,
INIT(UV_FS_ACCESS);
err = fs__capture_path(req, path, NULL, cb != NULL);
- if (err)
- return uv_translate_sys_error(err);
+ if (err) {
+ SET_REQ_WIN32_ERROR(req, err);
+ return req->result;
+ }
req->fs.info.mode = flags;
POST;
@@ -3180,7 +3339,8 @@ int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode,
INIT(UV_FS_CHMOD);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
- return uv_translate_sys_error(err);
+ SET_REQ_WIN32_ERROR(req, err);
+ return req->result;
}
req->fs.info.mode = mode;
@@ -3204,7 +3364,8 @@ int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime,
INIT(UV_FS_UTIME);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
- return uv_translate_sys_error(err);
+ SET_REQ_WIN32_ERROR(req, err);
+ return req->result;
}
req->fs.time.atime = atime;
@@ -3222,6 +3383,22 @@ int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file fd, double atime,
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) {
+ SET_REQ_WIN32_ERROR(req, err);
+ return req->result;
+ }
+
+ req->fs.time.atime = atime;
+ req->fs.time.mtime = mtime;
+ POST;
+}
+
int uv_fs_statfs(uv_loop_t* loop,
uv_fs_t* req,
@@ -3231,8 +3408,14 @@ int uv_fs_statfs(uv_loop_t* loop,
INIT(UV_FS_STATFS);
err = fs__capture_path(req, path, NULL, cb != NULL);
- if (err)
- return uv_translate_sys_error(err);
+ if (err) {
+ SET_REQ_WIN32_ERROR(req, err);
+ return req->result;
+ }
POST;
}
+
+int uv_fs_get_system_error(const uv_fs_t* req) {
+ return req->sys_errno_;
+}