Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Bring inline with node common.gypi.

Win32 readlink()
  • Loading branch information...
commit d59baae646fa27cf308f9f19a41339e922ac022e 1 parent 37cfb5e
@DrPizza DrPizza authored Igor Zinkovsky committed
Showing with 191 additions and 60 deletions.
  1. +51 −51 common.gypi
  2. +87 −9 src/win/fs.c
  3. +27 −0 src/win/winapi.h
  4. +26 −0 test/test-fs.c
View
102 common.gypi
@@ -1,5 +1,6 @@
{
'variables': {
+ 'visibility%': 'hidden', # V8's visibility setting
'target_arch%': 'ia32', # set v8's target architecture
'host_arch%': 'ia32', # set v8's host architecture
'library%': 'static_library', # allow override to 'shared_library' for DLL/.so builds
@@ -87,6 +88,11 @@
'DataExecutionPrevention': 2, # enable DEP
'AllowIsolation': 'true',
'SuppressStartupBanner': 'true',
+ 'target_conditions': [
+ ['_type=="executable"', {
+ 'SubSystem': 1, # console executable
+ }],
+ ],
},
},
'conditions': [
@@ -103,61 +109,55 @@
],
}],
[ 'OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"', {
- 'target_defaults': {
- 'cflags': [ '-Wall', '-pthread', '-fno-rtti', '-fno-exceptions' ],
- 'ldflags': [ '-pthread', ],
- 'conditions': [
- [ 'target_arch=="ia32"', {
- 'cflags': [ '-m32' ],
- 'ldflags': [ '-m32' ],
- }],
- [ 'OS=="linux"', {
- 'cflags': [ '-ansi' ],
- }],
- [ 'visibility=="hidden"', {
- 'cflags': [ '-fvisibility=hidden' ],
- }],
- ],
- },
+ 'cflags': [ '-Wall', '-pthread', ],
+ 'cflags_cc': [ '-fno-rtti', '-fno-exceptions' ],
+ 'ldflags': [ '-pthread', ],
+ 'conditions': [
+ [ 'target_arch=="ia32"', {
+ 'cflags': [ '-m32' ],
+ 'ldflags': [ '-m32' ],
+ }],
+ [ 'OS=="linux"', {
+ 'cflags': [ '-ansi' ],
+ }],
+ [ 'visibility=="hidden"', {
+ 'cflags': [ '-fvisibility=hidden' ],
+ }],
+ ],
}],
['OS=="mac"', {
- 'target_defaults': {
- 'xcode_settings': {
- 'ALWAYS_SEARCH_USER_PATHS': 'NO',
- 'GCC_C_LANGUAGE_STANDARD': 'ansi', # -ansi
- 'GCC_CW_ASM_SYNTAX': 'NO', # No -fasm-blocks
- 'GCC_DYNAMIC_NO_PIC': 'NO', # No -mdynamic-no-pic
- # (Equivalent to -fPIC)
- 'GCC_ENABLE_CPP_EXCEPTIONS': 'NO', # -fno-exceptions
- 'GCC_ENABLE_CPP_RTTI': 'NO', # -fno-rtti
- 'GCC_ENABLE_PASCAL_STRINGS': 'NO', # No -mpascal-strings
- # GCC_INLINES_ARE_PRIVATE_EXTERN maps to -fvisibility-inlines-hidden
- 'GCC_INLINES_ARE_PRIVATE_EXTERN': 'YES',
- 'GCC_SYMBOLS_PRIVATE_EXTERN': 'YES', # -fvisibility=hidden
- 'GCC_THREADSAFE_STATICS': 'NO', # -fno-threadsafe-statics
- 'GCC_TREAT_WARNINGS_AS_ERRORS': 'YES', # -Werror
- 'GCC_VERSION': '4.2',
- 'GCC_WARN_ABOUT_MISSING_NEWLINE': 'YES', # -Wnewline-eof
- 'MACOSX_DEPLOYMENT_TARGET': '10.4', # -mmacosx-version-min=10.4
- 'PREBINDING': 'NO', # No -Wl,-prebind
- 'USE_HEADERMAP': 'NO',
- 'OTHER_CFLAGS': [
- '-fno-strict-aliasing',
- ],
- 'WARNING_CFLAGS': [
- '-Wall',
- '-Wendif-labels',
- '-W',
- '-Wno-unused-parameter',
- '-Wnon-virtual-dtor',
- ],
- },
- 'target_conditions': [
- ['_type!="static_library"', {
- 'xcode_settings': {'OTHER_LDFLAGS': ['-Wl,-search_paths_first']},
- }],
+ 'xcode_settings': {
+ 'ALWAYS_SEARCH_USER_PATHS': 'NO',
+ 'GCC_CW_ASM_SYNTAX': 'NO', # No -fasm-blocks
+ 'GCC_DYNAMIC_NO_PIC': 'NO', # No -mdynamic-no-pic
+ # (Equivalent to -fPIC)
+ 'GCC_ENABLE_CPP_EXCEPTIONS': 'NO', # -fno-exceptions
+ 'GCC_ENABLE_CPP_RTTI': 'NO', # -fno-rtti
+ 'GCC_ENABLE_PASCAL_STRINGS': 'NO', # No -mpascal-strings
+ # GCC_INLINES_ARE_PRIVATE_EXTERN maps to -fvisibility-inlines-hidden
+ 'GCC_INLINES_ARE_PRIVATE_EXTERN': 'YES',
+ 'GCC_SYMBOLS_PRIVATE_EXTERN': 'YES', # -fvisibility=hidden
+ 'GCC_THREADSAFE_STATICS': 'NO', # -fno-threadsafe-statics
+ 'GCC_VERSION': '4.2',
+ 'GCC_WARN_ABOUT_MISSING_NEWLINE': 'YES', # -Wnewline-eof
+ 'MACOSX_DEPLOYMENT_TARGET': '10.4', # -mmacosx-version-min=10.4
+ 'PREBINDING': 'NO', # No -Wl,-prebind
+ 'USE_HEADERMAP': 'NO',
+ 'OTHER_CFLAGS': [
+ '-fno-strict-aliasing',
+ ],
+ 'WARNING_CFLAGS': [
+ '-Wall',
+ '-Wendif-labels',
+ '-W',
+ '-Wno-unused-parameter',
],
},
+ 'target_conditions': [
+ ['_type!="static_library"', {
+ 'xcode_settings': {'OTHER_LDFLAGS': ['-Wl,-search_paths_first']},
+ }],
+ ],
}],
],
},
View
96 src/win/fs.c
@@ -430,15 +430,93 @@ void fs__symlink(uv_fs_t* req, const char* path, const char* new_path,
void fs__readlink(uv_fs_t* req, const char* path) {
int result = -1;
- assert(0 && "implement me");
-
- /* TODO: the link path must be returned in a req->ptr buffer,
- * which need to be alloce'd here.
- * Just do this (it'll take care of freeing the buffer).
- * req->ptr = malloc(...);
- * req->flags |= UV_FS_FREE_PTR;
- * Also result needs to contain the length of the string.
- */
+ BOOL rv;
+ HANDLE symlink;
+ void* buffer;
+ DWORD bytes_returned;
+ REPARSE_DATA_BUFFER* reparse_data;
+ int utf8size;
+
+ symlink = CreateFileA(path,
+ 0,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
+ NULL);
+
+ if (INVALID_HANDLE_VALUE == symlink) {
+ result = -1;
+ SET_REQ_LAST_ERROR(req, GetLastError());
+ goto done;
+ }
+
+ buffer = malloc(MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
+ if (!buffer) {
+ uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
+ }
+
+ rv = DeviceIoControl(symlink,
+ FSCTL_GET_REPARSE_POINT,
+ NULL,
+ 0,
+ buffer,
+ MAXIMUM_REPARSE_DATA_BUFFER_SIZE,
+ &bytes_returned,
+ NULL);
+
+ if (!rv) {
+ result = -1;
+ SET_REQ_LAST_ERROR(req, GetLastError());
+ goto done;
+ }
+
+ reparse_data = buffer;
+ if (reparse_data->ReparseTag != IO_REPARSE_TAG_SYMLINK) {
+ result = -1;
+ /* something is seriously wrong */
+ SET_REQ_LAST_ERROR(req, GetLastError());
+ goto done;
+ }
+
+ utf8size = uv_utf16_to_utf8(reparse_data->SymbolicLinkReparseBuffer.PathBuffer + (reparse_data->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(wchar_t)),
+ reparse_data->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t),
+ NULL,
+ 0);
+ if (!utf8size) {
+ result = -1;
+ SET_REQ_LAST_ERROR(req, GetLastError());
+ goto done;
+ }
+
+ req->ptr = malloc(utf8size + 1);
+ if (!req->ptr) {
+ uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
+ }
+
+ req->flags |= UV_FS_FREE_PTR;
+
+ utf8size = uv_utf16_to_utf8(reparse_data->SymbolicLinkReparseBuffer.PathBuffer + (reparse_data->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(wchar_t)),
+ reparse_data->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t),
+ req->ptr,
+ utf8size);
+ if (!utf8size) {
+ result = -1;
+ SET_REQ_LAST_ERROR(req, GetLastError());
+ goto done;
+ }
+
+ ((char*)req->ptr)[utf8size] = '\0';
+ result = 0;
+
+done:
+ if (buffer) {
+ free(buffer);
+ }
+
+ if (symlink != INVALID_HANDLE_VALUE) {
+ CloseHandle(symlink);
+ }
SET_REQ_RESULT(req, result);
}
View
27 src/win/winapi.h
@@ -4075,6 +4075,33 @@
(FACILITY_NTWIN32 << 16) | ERROR_SEVERITY_ERROR)))
#endif
+/* from ntifs.h */
+typedef struct _REPARSE_DATA_BUFFER {
+ ULONG ReparseTag;
+ USHORT ReparseDataLength;
+ USHORT Reserved;
+ union {
+ struct {
+ USHORT SubstituteNameOffset;
+ USHORT SubstituteNameLength;
+ USHORT PrintNameOffset;
+ USHORT PrintNameLength;
+ ULONG Flags;
+ WCHAR PathBuffer[1];
+ } SymbolicLinkReparseBuffer;
+ struct {
+ USHORT SubstituteNameOffset;
+ USHORT SubstituteNameLength;
+ USHORT PrintNameOffset;
+ USHORT PrintNameLength;
+ WCHAR PathBuffer[1];
+ } MountPointReparseBuffer;
+ struct {
+ UCHAR DataBuffer[1];
+ } GenericReparseBuffer;
+ } DUMMYUNIONNAME;
+} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
+
typedef struct _IO_STATUS_BLOCK {
union {
NTSTATUS Status;
View
26 test/test-fs.c
@@ -65,6 +65,7 @@ static int chown_cb_count;
static int fchown_cb_count;
static int link_cb_count;
static int symlink_cb_count;
+static int readlink_cb_count;
static uv_loop_t* loop;
@@ -127,6 +128,13 @@ static void symlink_cb(uv_fs_t* req) {
uv_fs_req_cleanup(req);
}
+static void readlink_cb(uv_fs_t* req) {
+ ASSERT(req->fs_type == UV_FS_READLINK);
+ ASSERT(req->result == 0);
+ ASSERT(strcmp(req->ptr, "test_file_symlink2") == 0);
+ readlink_cb_count++;
+ uv_fs_req_cleanup(req);
+}
static void fchmod_cb(uv_fs_t* req) {
ASSERT(req->fs_type == UV_FS_FCHMOD);
@@ -936,6 +944,8 @@ TEST_IMPL(fs_symlink) {
unlink("test_file");
unlink("test_file_symlink");
unlink("test_file_symlink2");
+ unlink("test_file_symlink_symlink");
+ unlink("test_file_symlink2_symlink");
uv_init();
@@ -992,6 +1002,13 @@ TEST_IMPL(fs_symlink) {
close(link);
+ r = uv_fs_symlink(loop, &req, "test_file_symlink", "test_file_symlink_symlink", 0, NULL);
+ ASSERT(r == 0);
+ r = uv_fs_readlink(loop, &req, "test_file_symlink_symlink", NULL);
+ ASSERT(r == 0);
+ ASSERT(strcmp(req.ptr, "test_file_symlink") == 0);
+ uv_fs_req_cleanup(&req);
+
/* async link */
r = uv_fs_symlink(loop, &req, "test_file", "test_file_symlink2", 0, symlink_cb);
ASSERT(r == 0);
@@ -1012,6 +1029,13 @@ TEST_IMPL(fs_symlink) {
close(link);
+ r = uv_fs_symlink(loop, &req, "test_file_symlink2", "test_file_symlink2_symlink", 0, NULL);
+ ASSERT(r == 0);
+ r = uv_fs_readlink(loop, &req, "test_file_symlink2_symlink", readlink_cb);
+ ASSERT(r == 0);
+ uv_run(loop);
+ ASSERT(readlink_cb_count == 1);
+
/*
* Run the loop just to check we don't have make any extraneous uv_ref()
* calls. This should drop out immediately.
@@ -1021,7 +1045,9 @@ TEST_IMPL(fs_symlink) {
/* Cleanup. */
unlink("test_file");
unlink("test_file_symlink");
+ unlink("test_file_symlink_symlink");
unlink("test_file_symlink2");
+ unlink("test_file_symlink2_symlink");
return 0;
}
Please sign in to comment.
Something went wrong with that request. Please try again.