summaryrefslogtreecommitdiff
path: root/win32
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-08-19 14:48:09 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-08-19 14:48:09 +0000
commit006fad3fe3c46d3286bfd85d6daf0b8db87e24b4 (patch)
tree1bdd01714a2dffae15de175ab73feb4d97249cfe /win32
parenteb2d0cf8cdada19b3482b8956cdff99d3dc821a2 (diff)
win32.c: support known reparse points only
* win32/win32.c (winnt_lstat): 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@51640 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'win32')
-rw-r--r--win32/win32.c87
1 files changed, 50 insertions, 37 deletions
diff --git a/win32/win32.c b/win32/win32.c
index a045f89..a6ee83e 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;
}