Skip to content
This repository has been archived by the owner on May 4, 2018. It is now read-only.

Commit

Permalink
Bring inline with node common.gypi.
Browse files Browse the repository at this point in the history
Win32 readlink()
  • Loading branch information
DrPizza authored and Igor Zinkovsky committed Sep 4, 2011
1 parent 37cfb5e commit d59baae
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 60 deletions.
102 changes: 51 additions & 51 deletions 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
Expand Down Expand Up @@ -87,6 +88,11 @@
'DataExecutionPrevention': 2, # enable DEP
'AllowIsolation': 'true',
'SuppressStartupBanner': 'true',
'target_conditions': [
['_type=="executable"', {
'SubSystem': 1, # console executable
}],
],
},
},
'conditions': [
Expand All @@ -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']},
}],
],
}],
],
},
Expand Down
96 changes: 87 additions & 9 deletions src/win/fs.c
Expand Up @@ -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);
}
Expand Down
27 changes: 27 additions & 0 deletions src/win/winapi.h
Expand Up @@ -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;
Expand Down
26 changes: 26 additions & 0 deletions test/test-fs.c
Expand Up @@ -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;

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -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);
Expand All @@ -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.
Expand All @@ -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;
}

0 comments on commit d59baae

Please sign in to comment.