fs: add uv_fs_realpath()
Equivalent to realpath(3), returns the full resolved absolute path of a file or directory. PR-URL: https://github.com/libuv/libuv/pull/531 Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com>
This commit is contained in:
parent
176fdc7352
commit
e76b8838e5
@ -279,6 +279,16 @@ API
|
||||
|
||||
Equivalent to :man:`readlink(2)`.
|
||||
|
||||
.. c:function:: int uv_fs_realpath(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb)
|
||||
|
||||
Equivalent to :man:`realpath(3)` on Unix. Windows uses ``GetFinalPathNameByHandle()``.
|
||||
|
||||
.. note::
|
||||
This function is not implemented on Windows XP and Windows Server 2003.
|
||||
On these systems, UV_ENOSYS is returned.
|
||||
|
||||
.. versionadded:: 1.8.0
|
||||
|
||||
.. 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_file file, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb)
|
||||
|
||||
|
||||
@ -1088,7 +1088,8 @@ typedef enum {
|
||||
UV_FS_SYMLINK,
|
||||
UV_FS_READLINK,
|
||||
UV_FS_CHOWN,
|
||||
UV_FS_FCHOWN
|
||||
UV_FS_FCHOWN,
|
||||
UV_FS_REALPATH
|
||||
} uv_fs_type;
|
||||
|
||||
/* uv_fs_t is a subclass of uv_req_t. */
|
||||
@ -1240,6 +1241,10 @@ UV_EXTERN int uv_fs_readlink(uv_loop_t* loop,
|
||||
uv_fs_t* req,
|
||||
const char* path,
|
||||
uv_fs_cb cb);
|
||||
UV_EXTERN int uv_fs_realpath(uv_loop_t* loop,
|
||||
uv_fs_t* req,
|
||||
const char* path,
|
||||
uv_fs_cb cb);
|
||||
UV_EXTERN int uv_fs_fchmod(uv_loop_t* loop,
|
||||
uv_fs_t* req,
|
||||
uv_file file,
|
||||
|
||||
@ -374,20 +374,27 @@ out:
|
||||
}
|
||||
|
||||
|
||||
static ssize_t uv__fs_pathmax_size(const char* path) {
|
||||
ssize_t pathmax;
|
||||
|
||||
pathmax = pathconf(path, _PC_PATH_MAX);
|
||||
|
||||
if (pathmax == -1) {
|
||||
#if defined(PATH_MAX)
|
||||
return PATH_MAX;
|
||||
#else
|
||||
return 4096;
|
||||
#endif
|
||||
}
|
||||
|
||||
return pathmax;
|
||||
}
|
||||
|
||||
static ssize_t uv__fs_readlink(uv_fs_t* req) {
|
||||
ssize_t len;
|
||||
char* buf;
|
||||
|
||||
len = pathconf(req->path, _PC_PATH_MAX);
|
||||
|
||||
if (len == -1) {
|
||||
#if defined(PATH_MAX)
|
||||
len = PATH_MAX;
|
||||
#else
|
||||
len = 4096;
|
||||
#endif
|
||||
}
|
||||
|
||||
len = uv__fs_pathmax_size(req->path);
|
||||
buf = uv__malloc(len + 1);
|
||||
|
||||
if (buf == NULL) {
|
||||
@ -408,6 +415,27 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t uv__fs_realpath(uv_fs_t* req) {
|
||||
ssize_t len;
|
||||
char* buf;
|
||||
|
||||
len = uv__fs_pathmax_size(req->path);
|
||||
buf = uv__malloc(len + 1);
|
||||
|
||||
if (buf == NULL) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (realpath(req->path, buf) == NULL) {
|
||||
uv__free(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
req->ptr = buf;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t uv__fs_sendfile_emul(uv_fs_t* req) {
|
||||
struct pollfd pfd;
|
||||
@ -874,6 +902,7 @@ static void uv__fs_work(struct uv__work* w) {
|
||||
X(READ, uv__fs_buf_iter(req, uv__fs_read));
|
||||
X(SCANDIR, uv__fs_scandir(req));
|
||||
X(READLINK, uv__fs_readlink(req));
|
||||
X(REALPATH, uv__fs_realpath(req));
|
||||
X(RENAME, rename(req->path, req->new_path));
|
||||
X(RMDIR, rmdir(req->path));
|
||||
X(SENDFILE, uv__fs_sendfile(req));
|
||||
@ -1144,6 +1173,16 @@ int uv_fs_readlink(uv_loop_t* loop,
|
||||
}
|
||||
|
||||
|
||||
int uv_fs_realpath(uv_loop_t* loop,
|
||||
uv_fs_t* req,
|
||||
const char * path,
|
||||
uv_fs_cb cb) {
|
||||
INIT(REALPATH);
|
||||
PATH;
|
||||
POST;
|
||||
}
|
||||
|
||||
|
||||
int uv_fs_rename(uv_loop_t* loop,
|
||||
uv_fs_t* req,
|
||||
const char* path,
|
||||
|
||||
205
src/win/fs.c
205
src/win/fs.c
@ -110,6 +110,9 @@ const WCHAR JUNCTION_PREFIX_LEN = 4;
|
||||
const WCHAR LONG_PATH_PREFIX[] = L"\\\\?\\";
|
||||
const WCHAR LONG_PATH_PREFIX_LEN = 4;
|
||||
|
||||
const WCHAR UNC_PATH_PREFIX[] = L"\\\\?\\UNC\\";
|
||||
const WCHAR UNC_PATH_PREFIX_LEN = 8;
|
||||
|
||||
|
||||
void uv_fs_init() {
|
||||
_fmode = _O_BINARY;
|
||||
@ -233,14 +236,61 @@ INLINE static void uv_fs_req_init(uv_loop_t* loop, uv_fs_t* req,
|
||||
}
|
||||
|
||||
|
||||
static int fs__wide_to_utf8(WCHAR* w_source_ptr,
|
||||
DWORD w_source_len,
|
||||
char** target_ptr,
|
||||
uint64_t* target_len_ptr) {
|
||||
int r;
|
||||
int target_len;
|
||||
char* target;
|
||||
target_len = WideCharToMultiByte(CP_UTF8,
|
||||
0,
|
||||
w_source_ptr,
|
||||
w_source_len,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (target_len == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (target_len_ptr != NULL) {
|
||||
*target_len_ptr = target_len;
|
||||
}
|
||||
|
||||
if (target_ptr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
target = uv__malloc(target_len + 1);
|
||||
if (target == NULL) {
|
||||
SetLastError(ERROR_OUTOFMEMORY);
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = WideCharToMultiByte(CP_UTF8,
|
||||
0,
|
||||
w_source_ptr,
|
||||
w_source_len,
|
||||
target,
|
||||
target_len,
|
||||
NULL,
|
||||
NULL);
|
||||
assert(r == target_len);
|
||||
target[target_len] = '\0';
|
||||
*target_ptr = target;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr,
|
||||
uint64_t* target_len_ptr) {
|
||||
char buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
|
||||
REPARSE_DATA_BUFFER* reparse_data = (REPARSE_DATA_BUFFER*) buffer;
|
||||
WCHAR *w_target;
|
||||
WCHAR* w_target;
|
||||
DWORD w_target_len;
|
||||
char* target;
|
||||
int target_len;
|
||||
DWORD bytes;
|
||||
|
||||
if (!DeviceIoControl(handle,
|
||||
@ -333,50 +383,7 @@ INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If needed, compute the length of the target. */
|
||||
if (target_ptr != NULL || target_len_ptr != NULL) {
|
||||
/* Compute the length of the target. */
|
||||
target_len = WideCharToMultiByte(CP_UTF8,
|
||||
0,
|
||||
w_target,
|
||||
w_target_len,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
if (target_len == 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* If requested, allocate memory and convert to UTF8. */
|
||||
if (target_ptr != NULL) {
|
||||
int r;
|
||||
target = (char*) uv__malloc(target_len + 1);
|
||||
if (target == NULL) {
|
||||
SetLastError(ERROR_OUTOFMEMORY);
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = WideCharToMultiByte(CP_UTF8,
|
||||
0,
|
||||
w_target,
|
||||
w_target_len,
|
||||
target,
|
||||
target_len,
|
||||
NULL,
|
||||
NULL);
|
||||
assert(r == target_len);
|
||||
target[target_len] = '\0';
|
||||
|
||||
*target_ptr = target;
|
||||
}
|
||||
|
||||
if (target_len_ptr != NULL) {
|
||||
*target_len_ptr = target_len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return fs__wide_to_utf8(w_target, w_target_len, target_ptr, target_len_ptr);
|
||||
}
|
||||
|
||||
|
||||
@ -1707,6 +1714,84 @@ static void fs__readlink(uv_fs_t* req) {
|
||||
}
|
||||
|
||||
|
||||
static size_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) {
|
||||
int r;
|
||||
DWORD w_realpath_len;
|
||||
WCHAR* w_realpath_ptr;
|
||||
WCHAR* w_finalpath_ptr = NULL;
|
||||
|
||||
w_realpath_len = pGetFinalPathNameByHandleW(handle, NULL, 0, VOLUME_NAME_DOS);
|
||||
if (w_realpath_len == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
w_realpath_ptr = uv__malloc((w_realpath_len + 1) * sizeof(WCHAR));
|
||||
if (w_realpath_ptr == NULL) {
|
||||
SetLastError(ERROR_OUTOFMEMORY);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pGetFinalPathNameByHandleW(handle,
|
||||
w_realpath_ptr,
|
||||
w_realpath_len,
|
||||
VOLUME_NAME_DOS) == 0) {
|
||||
uv__free(w_realpath_ptr);
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* convert UNC path to long path */
|
||||
if (wcsncmp(w_realpath_ptr,
|
||||
UNC_PATH_PREFIX,
|
||||
UNC_PATH_PREFIX_LEN) == 0) {
|
||||
w_finalpath_ptr = w_realpath_ptr + 6;
|
||||
*w_finalpath_ptr = L'\\';
|
||||
} else if (wcsncmp(w_realpath_ptr,
|
||||
LONG_PATH_PREFIX,
|
||||
LONG_PATH_PREFIX_LEN) == 0) {
|
||||
w_finalpath_ptr = w_realpath_ptr + 4;
|
||||
} else {
|
||||
uv__free(w_realpath_ptr);
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = fs__wide_to_utf8(w_finalpath_ptr, w_realpath_len, realpath_ptr, NULL);
|
||||
uv__free(w_realpath_ptr);
|
||||
return r;
|
||||
}
|
||||
|
||||
static void fs__realpath(uv_fs_t* req) {
|
||||
HANDLE handle;
|
||||
|
||||
if (!pGetFinalPathNameByHandleW) {
|
||||
SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED);
|
||||
return;
|
||||
}
|
||||
|
||||
handle = CreateFileW(req->file.pathw,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
|
||||
NULL);
|
||||
if (handle == INVALID_HANDLE_VALUE) {
|
||||
SET_REQ_WIN32_ERROR(req, GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
if (fs__realpath_handle(handle, (char**) &req->ptr) == -1) {
|
||||
CloseHandle(handle);
|
||||
SET_REQ_WIN32_ERROR(req, GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
CloseHandle(handle);
|
||||
req->flags |= UV_FS_FREE_PTR;
|
||||
SET_REQ_RESULT(req, 0);
|
||||
}
|
||||
|
||||
|
||||
static void fs__chown(uv_fs_t* req) {
|
||||
req->result = 0;
|
||||
@ -1751,6 +1836,7 @@ static void uv__fs_work(struct uv__work* w) {
|
||||
XX(LINK, link)
|
||||
XX(SYMLINK, symlink)
|
||||
XX(READLINK, readlink)
|
||||
XX(REALPATH, realpath)
|
||||
XX(CHOWN, chown)
|
||||
XX(FCHOWN, fchown);
|
||||
default:
|
||||
@ -2075,6 +2161,31 @@ int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
|
||||
}
|
||||
|
||||
|
||||
int uv_fs_realpath(uv_loop_t* loop, uv_fs_t* req, const char* path,
|
||||
uv_fs_cb cb) {
|
||||
int err;
|
||||
|
||||
if (!req || !path) {
|
||||
return UV_EINVAL;
|
||||
}
|
||||
|
||||
uv_fs_req_init(loop, req, UV_FS_REALPATH, cb);
|
||||
|
||||
err = fs__capture_path(req, path, NULL, cb != NULL);
|
||||
if (err) {
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
|
||||
if (cb) {
|
||||
QUEUE_FS_TP_JOB(loop, req);
|
||||
return 0;
|
||||
} else {
|
||||
fs__realpath(req);
|
||||
return req->result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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) {
|
||||
int err;
|
||||
|
||||
@ -46,6 +46,7 @@ sSleepConditionVariableSRW pSleepConditionVariableSRW;
|
||||
sWakeAllConditionVariable pWakeAllConditionVariable;
|
||||
sWakeConditionVariable pWakeConditionVariable;
|
||||
sCancelSynchronousIo pCancelSynchronousIo;
|
||||
sGetFinalPathNameByHandleW pGetFinalPathNameByHandleW;
|
||||
|
||||
|
||||
void uv_winapi_init() {
|
||||
@ -139,4 +140,7 @@ void uv_winapi_init() {
|
||||
|
||||
pCancelSynchronousIo = (sCancelSynchronousIo)
|
||||
GetProcAddress(kernel32_module, "CancelSynchronousIo");
|
||||
|
||||
pGetFinalPathNameByHandleW = (sGetFinalPathNameByHandleW)
|
||||
GetProcAddress(kernel32_module, "GetFinalPathNameByHandleW");
|
||||
}
|
||||
|
||||
@ -4678,6 +4678,12 @@ typedef VOID (WINAPI* sWakeConditionVariable)
|
||||
typedef BOOL (WINAPI* sCancelSynchronousIo)
|
||||
(HANDLE hThread);
|
||||
|
||||
typedef DWORD (WINAPI* sGetFinalPathNameByHandleW)
|
||||
(HANDLE hFile,
|
||||
LPWSTR lpszFilePath,
|
||||
DWORD cchFilePath,
|
||||
DWORD dwFlags);
|
||||
|
||||
/* Ntdll function pointers */
|
||||
extern sRtlNtStatusToDosError pRtlNtStatusToDosError;
|
||||
extern sNtDeviceIoControlFile pNtDeviceIoControlFile;
|
||||
@ -4699,5 +4705,6 @@ extern sSleepConditionVariableSRW pSleepConditionVariableSRW;
|
||||
extern sWakeAllConditionVariable pWakeAllConditionVariable;
|
||||
extern sWakeConditionVariable pWakeConditionVariable;
|
||||
extern sCancelSynchronousIo pCancelSynchronousIo;
|
||||
extern sGetFinalPathNameByHandleW pGetFinalPathNameByHandleW;
|
||||
|
||||
#endif /* UV_WIN_WINAPI_H_ */
|
||||
|
||||
142
test/test-fs.c
142
test/test-fs.c
@ -83,6 +83,7 @@ static int fchown_cb_count;
|
||||
static int link_cb_count;
|
||||
static int symlink_cb_count;
|
||||
static int readlink_cb_count;
|
||||
static int realpath_cb_count;
|
||||
static int utime_cb_count;
|
||||
static int futime_cb_count;
|
||||
|
||||
@ -168,6 +169,35 @@ static void readlink_cb(uv_fs_t* req) {
|
||||
}
|
||||
|
||||
|
||||
static void realpath_cb(uv_fs_t* req) {
|
||||
char test_file_abs_buf[PATHMAX];
|
||||
size_t test_file_abs_size = sizeof(test_file_abs_buf);
|
||||
ASSERT(req->fs_type == UV_FS_REALPATH);
|
||||
#ifdef _WIN32
|
||||
/*
|
||||
* Windows XP and Server 2003 don't support GetFinalPathNameByHandleW()
|
||||
*/
|
||||
if (req->result == UV_ENOSYS) {
|
||||
realpath_cb_count++;
|
||||
uv_fs_req_cleanup(req);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
ASSERT(req->result == 0);
|
||||
|
||||
uv_cwd(test_file_abs_buf, &test_file_abs_size);
|
||||
#ifdef _WIN32
|
||||
strcat(test_file_abs_buf, "\\test_file");
|
||||
ASSERT(stricmp(req->ptr, test_file_abs_buf) == 0);
|
||||
#else
|
||||
strcat(test_file_abs_buf, "/test_file");
|
||||
ASSERT(strcmp(req->ptr, test_file_abs_buf) == 0);
|
||||
#endif
|
||||
realpath_cb_count++;
|
||||
uv_fs_req_cleanup(req);
|
||||
}
|
||||
|
||||
|
||||
static void access_cb(uv_fs_t* req) {
|
||||
ASSERT(req->fs_type == UV_FS_ACCESS);
|
||||
access_cb_count++;
|
||||
@ -1565,11 +1595,43 @@ TEST_IMPL(fs_readlink) {
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(fs_realpath) {
|
||||
uv_fs_t req;
|
||||
|
||||
loop = uv_default_loop();
|
||||
ASSERT(0 == uv_fs_realpath(loop, &req, "no_such_file", dummy_cb));
|
||||
ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
|
||||
ASSERT(dummy_cb_count == 1);
|
||||
ASSERT(req.ptr == NULL);
|
||||
#ifdef _WIN32
|
||||
/*
|
||||
* Windows XP and Server 2003 don't support GetFinalPathNameByHandleW()
|
||||
*/
|
||||
if (req.result == UV_ENOSYS) {
|
||||
uv_fs_req_cleanup(&req);
|
||||
RETURN_SKIP("realpath is not supported on Windows XP");
|
||||
}
|
||||
#endif
|
||||
ASSERT(req.result == UV_ENOENT);
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
ASSERT(UV_ENOENT == uv_fs_realpath(NULL, &req, "no_such_file", NULL));
|
||||
ASSERT(req.ptr == NULL);
|
||||
ASSERT(req.result == UV_ENOENT);
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(fs_symlink) {
|
||||
int r;
|
||||
uv_fs_t req;
|
||||
uv_file file;
|
||||
uv_file link;
|
||||
char test_file_abs_buf[PATHMAX];
|
||||
size_t test_file_abs_size;
|
||||
|
||||
/* Setup. */
|
||||
unlink("test_file");
|
||||
@ -1577,6 +1639,14 @@ TEST_IMPL(fs_symlink) {
|
||||
unlink("test_file_symlink2");
|
||||
unlink("test_file_symlink_symlink");
|
||||
unlink("test_file_symlink2_symlink");
|
||||
test_file_abs_size = sizeof(test_file_abs_buf);
|
||||
#ifdef _WIN32
|
||||
uv_cwd(test_file_abs_buf, &test_file_abs_size);
|
||||
strcat(test_file_abs_buf, "\\test_file");
|
||||
#else
|
||||
uv_cwd(test_file_abs_buf, &test_file_abs_size);
|
||||
strcat(test_file_abs_buf, "/test_file");
|
||||
#endif
|
||||
|
||||
loop = uv_default_loop();
|
||||
|
||||
@ -1647,6 +1717,24 @@ TEST_IMPL(fs_symlink) {
|
||||
ASSERT(strcmp(req.ptr, "test_file_symlink") == 0);
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
r = uv_fs_realpath(NULL, &req, "test_file_symlink_symlink", NULL);
|
||||
#ifdef _WIN32
|
||||
/*
|
||||
* Windows XP and Server 2003 don't support GetFinalPathNameByHandleW()
|
||||
*/
|
||||
if (r == UV_ENOSYS) {
|
||||
uv_fs_req_cleanup(&req);
|
||||
RETURN_SKIP("realpath is not supported on Windows XP");
|
||||
}
|
||||
#endif
|
||||
ASSERT(r == 0);
|
||||
#ifdef _WIN32
|
||||
ASSERT(stricmp(req.ptr, test_file_abs_buf) == 0);
|
||||
#else
|
||||
ASSERT(strcmp(req.ptr, test_file_abs_buf) == 0);
|
||||
#endif
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
/* async link */
|
||||
r = uv_fs_symlink(loop,
|
||||
&req,
|
||||
@ -1687,6 +1775,20 @@ TEST_IMPL(fs_symlink) {
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
ASSERT(readlink_cb_count == 1);
|
||||
|
||||
r = uv_fs_realpath(loop, &req, "test_file", realpath_cb);
|
||||
#ifdef _WIN32
|
||||
/*
|
||||
* Windows XP and Server 2003 don't support GetFinalPathNameByHandleW()
|
||||
*/
|
||||
if (r == UV_ENOSYS) {
|
||||
uv_fs_req_cleanup(&req);
|
||||
RETURN_SKIP("realpath is not supported on Windows XP");
|
||||
}
|
||||
#endif
|
||||
ASSERT(r == 0);
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
ASSERT(realpath_cb_count == 1);
|
||||
|
||||
/*
|
||||
* Run the loop just to check we don't have make any extraneous uv_ref()
|
||||
* calls. This should drop out immediately.
|
||||
@ -1710,12 +1812,15 @@ TEST_IMPL(fs_symlink_dir) {
|
||||
int r;
|
||||
char* test_dir;
|
||||
uv_dirent_t dent;
|
||||
static char test_dir_abs_buf[PATHMAX];
|
||||
size_t test_dir_abs_size;
|
||||
|
||||
/* set-up */
|
||||
unlink("test_dir/file1");
|
||||
unlink("test_dir/file2");
|
||||
rmdir("test_dir");
|
||||
rmdir("test_dir_symlink");
|
||||
test_dir_abs_size = sizeof(test_dir_abs_buf);
|
||||
|
||||
loop = uv_default_loop();
|
||||
|
||||
@ -1723,16 +1828,16 @@ TEST_IMPL(fs_symlink_dir) {
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
#ifdef _WIN32
|
||||
{
|
||||
static char src_path_buf[PATHMAX];
|
||||
size_t size;
|
||||
size = sizeof(src_path_buf);
|
||||
strcpy(src_path_buf, "\\\\?\\");
|
||||
uv_cwd(src_path_buf + 4, &size);
|
||||
strcat(src_path_buf, "\\test_dir\\");
|
||||
test_dir = src_path_buf;
|
||||
}
|
||||
strcpy(test_dir_abs_buf, "\\\\?\\");
|
||||
uv_cwd(test_dir_abs_buf + 4, &test_dir_abs_size);
|
||||
test_dir_abs_size += 4;
|
||||
strcat(test_dir_abs_buf, "\\test_dir\\");
|
||||
test_dir_abs_size += strlen("\\test_dir\\");
|
||||
test_dir = test_dir_abs_buf;
|
||||
#else
|
||||
uv_cwd(test_dir_abs_buf, &test_dir_abs_size);
|
||||
strcat(test_dir_abs_buf, "/test_dir");
|
||||
test_dir_abs_size += strlen("/test_dir");
|
||||
test_dir = "test_dir";
|
||||
#endif
|
||||
|
||||
@ -1767,6 +1872,25 @@ TEST_IMPL(fs_symlink_dir) {
|
||||
#endif
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
r = uv_fs_realpath(NULL, &req, "test_dir_symlink", NULL);
|
||||
#ifdef _WIN32
|
||||
/*
|
||||
* Windows XP and Server 2003 don't support GetFinalPathNameByHandleW()
|
||||
*/
|
||||
if (r == UV_ENOSYS) {
|
||||
uv_fs_req_cleanup(&req);
|
||||
RETURN_SKIP("realpath is not supported on Windows XP");
|
||||
}
|
||||
#endif
|
||||
ASSERT(r == 0);
|
||||
#ifdef _WIN32
|
||||
ASSERT(strlen(req.ptr) == test_dir_abs_size - 5);
|
||||
ASSERT(strnicmp(req.ptr, test_dir + 4, test_dir_abs_size - 5) == 0);
|
||||
#else
|
||||
ASSERT(strcmp(req.ptr, test_dir_abs_buf) == 0);
|
||||
#endif
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
r = uv_fs_open(NULL, &open_req1, "test_dir/file1", O_WRONLY | O_CREAT,
|
||||
S_IWUSR | S_IRUSR, NULL);
|
||||
ASSERT(r >= 0);
|
||||
|
||||
@ -254,6 +254,7 @@ TEST_DECLARE (fs_unlink_readonly)
|
||||
TEST_DECLARE (fs_chown)
|
||||
TEST_DECLARE (fs_link)
|
||||
TEST_DECLARE (fs_readlink)
|
||||
TEST_DECLARE (fs_realpath)
|
||||
TEST_DECLARE (fs_symlink)
|
||||
TEST_DECLARE (fs_symlink_dir)
|
||||
TEST_DECLARE (fs_utime)
|
||||
@ -675,6 +676,7 @@ TASK_LIST_START
|
||||
TEST_ENTRY (fs_utime)
|
||||
TEST_ENTRY (fs_futime)
|
||||
TEST_ENTRY (fs_readlink)
|
||||
TEST_ENTRY (fs_realpath)
|
||||
TEST_ENTRY (fs_symlink)
|
||||
TEST_ENTRY (fs_symlink_dir)
|
||||
TEST_ENTRY (fs_stat_missing_path)
|
||||
|
||||
@ -276,7 +276,7 @@ TEST_IMPL(threadpool_cancel_work) {
|
||||
|
||||
TEST_IMPL(threadpool_cancel_fs) {
|
||||
struct cancel_info ci;
|
||||
uv_fs_t reqs[25];
|
||||
uv_fs_t reqs[26];
|
||||
uv_loop_t* loop;
|
||||
unsigned n;
|
||||
uv_buf_t iov;
|
||||
@ -305,6 +305,7 @@ TEST_IMPL(threadpool_cancel_fs) {
|
||||
ASSERT(0 == uv_fs_read(loop, reqs + n++, 0, &iov, 1, 0, fs_cb));
|
||||
ASSERT(0 == uv_fs_scandir(loop, reqs + n++, "/", 0, fs_cb));
|
||||
ASSERT(0 == uv_fs_readlink(loop, reqs + n++, "/", fs_cb));
|
||||
ASSERT(0 == uv_fs_realpath(loop, reqs + n++, "/", fs_cb));
|
||||
ASSERT(0 == uv_fs_rename(loop, reqs + n++, "/", "/", fs_cb));
|
||||
ASSERT(0 == uv_fs_mkdir(loop, reqs + n++, "/", 0, fs_cb));
|
||||
ASSERT(0 == uv_fs_sendfile(loop, reqs + n++, 0, 0, 0, 0, fs_cb));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user