summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--win32/win32.c87
2 files changed, 56 insertions, 37 deletions
diff --git a/ChangeLog b/ChangeLog
index ae4f8a24aa..37e4b9007b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Wed Aug 19 23:48:06 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * win32/win32.c (winnt_lstat): check reparse point tags and treat
+ supported tags only as symbolic links.
+ [ruby-core:70454] [Bug #11462]
+
Tue Aug 18 20:05:49 2015 NARUSE, Yui <naruse@ruby-lang.org>
* thread_pthread.c (reserve_stack): ensure the memory is really
diff --git a/win32/win32.c b/win32/win32.c
index a045f898c0..a6ee83ec41 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -4656,31 +4656,33 @@ link(const char *from, const char *to)
#endif
/* License: Ruby's */
-ssize_t
-rb_w32_wreadlink(const WCHAR *path, WCHAR *buf, size_t bufsize)
+typedef struct {
+ ULONG ReparseTag;
+ USHORT ReparseDataLength;
+ USHORT Reserved;
+ union {
+ struct {
+ USHORT SubstituteNameOffset;
+ USHORT SubstituteNameLength;
+ USHORT PrintNameOffset;
+ USHORT PrintNameLength;
+ ULONG Flags;
+ WCHAR PathBuffer[MAXPATHLEN * 2];
+ } SymbolicLinkReparseBuffer;
+ struct {
+ USHORT SubstituteNameOffset;
+ USHORT SubstituteNameLength;
+ USHORT PrintNameOffset;
+ USHORT PrintNameLength;
+ WCHAR PathBuffer[MAXPATHLEN * 2];
+ } MountPointReparseBuffer;
+ };
+} reparse_buffer_t;
+
+/* License: Ruby's */
+static int
+reparse_symlink(const WCHAR *path, reparse_buffer_t *rp)
{
- struct {
- ULONG ReparseTag;
- USHORT ReparseDataLength;
- USHORT Reserved;
- union {
- struct {
- USHORT SubstituteNameOffset;
- USHORT SubstituteNameLength;
- USHORT PrintNameOffset;
- USHORT PrintNameLength;
- ULONG Flags;
- WCHAR PathBuffer[MAXPATHLEN * 2];
- } SymbolicLinkReparseBuffer;
- struct {
- USHORT SubstituteNameOffset;
- USHORT SubstituteNameLength;
- USHORT PrintNameOffset;
- USHORT PrintNameLength;
- WCHAR PathBuffer[MAXPATHLEN * 2];
- } MountPointReparseBuffer;
- };
- } rp;
HANDLE f;
DWORD ret;
int e = 0;
@@ -4695,8 +4697,7 @@ rb_w32_wreadlink(const WCHAR *path, WCHAR *buf, size_t bufsize)
get_proc_address("kernel32", "DeviceIoControl", NULL);
}
if (!device_io_control) {
- errno = ENOSYS;
- return -1;
+ return ENOSYS;
}
f = CreateFileW(path, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
@@ -4704,19 +4705,29 @@ rb_w32_wreadlink(const WCHAR *path, WCHAR *buf, size_t bufsize)
FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OPEN_REPARSE_POINT,
NULL);
if (f == INVALID_HANDLE_VALUE) {
- errno = map_errno(GetLastError());
- return -1;
+ return map_errno(GetLastError());
}
if (!device_io_control(f, FSCTL_GET_REPARSE_POINT, NULL, 0,
- &rp, sizeof(rp), &ret, NULL)) {
+ rp, sizeof(*rp), &ret, NULL)) {
e = map_errno(GetLastError());
}
- else if (rp.ReparseTag != IO_REPARSE_TAG_SYMLINK &&
- rp.ReparseTag != IO_REPARSE_TAG_MOUNT_POINT){
+ else if (rp->ReparseTag != IO_REPARSE_TAG_SYMLINK &&
+ rp->ReparseTag != IO_REPARSE_TAG_MOUNT_POINT){
e = EINVAL;
}
- else {
+ CloseHandle(f);
+ return e;
+}
+
+ssize_t
+rb_w32_wreadlink(const WCHAR *path, WCHAR *buf, size_t bufsize)
+{
+ reparse_buffer_t rp;
+ int e = reparse_symlink(path, &rp);
+ DWORD ret;
+
+ if (!e) {
void *name;
if (rp.ReparseTag == IO_REPARSE_TAG_SYMLINK) {
name = ((char *)rp.SymbolicLinkReparseBuffer.PathBuffer +
@@ -4736,9 +4747,7 @@ rb_w32_wreadlink(const WCHAR *path, WCHAR *buf, size_t bufsize)
bufsize *= sizeof(WCHAR);
memcpy(buf, name, ret > bufsize ? bufsize : ret);
}
-
- CloseHandle(f);
- if (e) {
+ else {
errno = e;
return -1;
}
@@ -5279,11 +5288,15 @@ winnt_lstat(const WCHAR *path, struct stati64 *st)
return -1;
}
if (GetFileAttributesExW(path, GetFileExInfoStandard, (void*)&wfa)) {
+ reparse_buffer_t rp;
if (wfa.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
/* TODO: size in which encoding? */
- st->st_size = 0;
+ if (reparse_symlink(path, &rp) == 0)
+ st->st_size = 0;
+ else
+ wfa.dwFileAttributes &= ~FILE_ATTRIBUTE_REPARSE_POINT;
}
- else if (wfa.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ if (wfa.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
if (check_valid_dir(path)) return -1;
st->st_size = 0;
}