aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--dir.c5
-rw-r--r--win32/win32.c26
3 files changed, 33 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index 6e2d813d85..bda3d75a66 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Thu Aug 20 08:31:17 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * dir.c (replace_real_basename), win32/win32.c (opendir_internal):
+ check reparse point tags and treat supported tags only as
+ symbolic links. [ruby-core:70454] [Bug #11462]
+
Wed Aug 19 23:59:28 2015 Aaron Patterson <tenderlove@ruby-lang.org>
* ext/openssl/lib/openssl/ssl.rb (module OpenSSL): add OP_ALL to
diff --git a/dir.c b/dir.c
index b75e6d63c5..abb5295dc8 100644
--- a/dir.c
+++ b/dir.c
@@ -1512,6 +1512,7 @@ replace_real_basename(char *path, long base, rb_encoding *enc, int norm_p, int f
}
#elif defined _WIN32
VALUE rb_w32_conv_from_wchar(const WCHAR *wstr, rb_encoding *enc);
+int rb_w32_reparse_symlink_p(const WCHAR *path);
static char *
replace_real_basename(char *path, long base, rb_encoding *enc, int norm_p, int flags, rb_pathtype_t *type)
@@ -1539,6 +1540,10 @@ replace_real_basename(char *path, long base, rb_encoding *enc, int norm_p, int f
h = FindFirstFileW(wplain, &fd);
e = rb_w32_map_errno(GetLastError());
}
+ if (fa.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
+ if (!rb_w32_reparse_symlink_p(wplain))
+ fa.dwFileAttributes &= ~FILE_ATTRIBUTE_REPARSE_POINT;
+ }
free(wplain);
if (h == INVALID_HANDLE_VALUE) {
*type = path_noent;
diff --git a/win32/win32.c b/win32/win32.c
index a6ee83ec41..4576a47aff 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -105,6 +105,8 @@ static char *w32_getenv(const char *name, UINT cp);
#define TO_SOCKET(x) _get_osfhandle(x)
+int rb_w32_reparse_symlink_p(const WCHAR *path);
+
static struct ChildRecord *CreateChild(const WCHAR *, const WCHAR *, SECURITY_ATTRIBUTES *, HANDLE, HANDLE, HANDLE, DWORD);
static int has_redirection(const char *, UINT);
int rb_w32_wait_events(HANDLE *events, int num, DWORD timeout);
@@ -1873,6 +1875,7 @@ opendir_internal(WCHAR *wpath, const char *filename)
WIN32_FIND_DATAW fd;
HANDLE fh;
DIR *p;
+ long pathlen;
long len;
long altlen;
long idx;
@@ -1885,6 +1888,7 @@ opendir_internal(WCHAR *wpath, const char *filename)
if (wstati64(wpath, &sbuf) < 0) {
return NULL;
}
+ pathlen = lstrlenW(wpath);
if (!(sbuf.st_mode & S_IFDIR) &&
(!ISALPHA(filename[0]) || filename[1] != ':' || filename[2] != '\0' ||
((1 << ((filename[0] & 0x5f) - 'A')) & GetLogicalDrives()) == 0)) {
@@ -1941,8 +1945,15 @@ opendir_internal(WCHAR *wpath, const char *filename)
}
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
SetBit(p->bits, BitOfIsDir(p->nfiles));
- if (fd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
- SetBit(p->bits, BitOfIsRep(p->nfiles));
+ if (fd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
+ WCHAR *tmppath = malloc((pathlen + len + 1) * sizeof(WCHAR));
+ memcpy(tmppath, wpath, pathlen * sizeof(WCHAR));
+ tmppath[pathlen] = L'\\';
+ memcpy(tmppath + pathlen, fd.cFileName, len * sizeof(WCHAR));
+ if (rb_w32_reparse_symlink_p(tmppath))
+ SetBit(p->bits, BitOfIsRep(p->nfiles));
+ free(tmppath);
+ }
p->nfiles++;
idx += len + altlen;
@@ -4720,6 +4731,14 @@ reparse_symlink(const WCHAR *path, reparse_buffer_t *rp)
return e;
}
+/* License: Ruby's */
+int
+rb_w32_reparse_symlink_p(const WCHAR *path)
+{
+ reparse_buffer_t rp;
+ return reparse_symlink(path, &rp) == 0;
+}
+
ssize_t
rb_w32_wreadlink(const WCHAR *path, WCHAR *buf, size_t bufsize)
{
@@ -5288,10 +5307,9 @@ 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? */
- if (reparse_symlink(path, &rp) == 0)
+ if (rb_w32_reparse_symlink_p(path))
st->st_size = 0;
else
wfa.dwFileAttributes &= ~FILE_ATTRIBUTE_REPARSE_POINT;