win32.c: support known reparse points only

* 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]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51644 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2015-08-19 23:31:19 +00:00
Родитель 126eb641e3
Коммит 82da3da5ac
3 изменённых файлов: 33 добавлений и 4 удалений

Просмотреть файл

@ -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

5
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;

Просмотреть файл

@ -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;