Windows: fix problems with junctions and symlinks
Racket wasn't reparsing correctly; the strategy worked ok for links created by `mklink`, but not with other tools that leave the "printed name" field blank. A consequence of various fixes is that reparse points like "My Documents" (in a typical configuration) correctly resolve to actual paths like "Documents". Finally, `directory-exists?` didn't handle root directories like "C:/" correctly. The query would actually report properties of the OS-level current working directory, and when junctions are involved, the current directory can be a link instead of a directory. Relevant to PR 14950 and PR 14912
This commit is contained in:
parent
d3383e3e35
commit
f30b3a50fd
|
@ -2241,7 +2241,7 @@ static char *UNC_readlink(const char *fn)
|
||||||
|
|
||||||
if (!DeviceIoControlProc) return NULL;
|
if (!DeviceIoControlProc) return NULL;
|
||||||
|
|
||||||
h = CreateFileW(WIDE_PATH(fn), GENERIC_READ,
|
h = CreateFileW(WIDE_PATH(fn), FILE_READ_ATTRIBUTES,
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
|
||||||
OPEN_EXISTING,
|
OPEN_EXISTING,
|
||||||
FILE_FLAG_BACKUP_SEMANTICS | mzFILE_FLAG_OPEN_REPARSE_POINT,
|
FILE_FLAG_BACKUP_SEMANTICS | mzFILE_FLAG_OPEN_REPARSE_POINT,
|
||||||
|
@ -2276,13 +2276,42 @@ static char *UNC_readlink(const char *fn)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
off = rp->u.SymbolicLinkReparseBuffer.PrintNameOffset;
|
if (rp->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
|
||||||
len = rp->u.SymbolicLinkReparseBuffer.PrintNameLength;
|
off = rp->u.SymbolicLinkReparseBuffer.SubstituteNameOffset;
|
||||||
|
len = rp->u.SymbolicLinkReparseBuffer.SubstituteNameLength;
|
||||||
|
if (!len) {
|
||||||
|
off = rp->u.SymbolicLinkReparseBuffer.PrintNameOffset;
|
||||||
|
len = rp->u.SymbolicLinkReparseBuffer.PrintNameLength;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
off = rp->u.MountPointReparseBuffer.SubstituteNameOffset;
|
||||||
|
len = rp->u.MountPointReparseBuffer.SubstituteNameLength;
|
||||||
|
if (!len) {
|
||||||
|
off = rp->u.MountPointReparseBuffer.PrintNameOffset;
|
||||||
|
len = rp->u.MountPointReparseBuffer.PrintNameLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
lk = (wchar_t *)scheme_malloc_atomic(len + 2);
|
lk = (wchar_t *)scheme_malloc_atomic(len + 2);
|
||||||
|
|
||||||
memcpy(lk, (char *)rp->u.SymbolicLinkReparseBuffer.PathBuffer + off, len);
|
if (rp->ReparseTag == IO_REPARSE_TAG_SYMLINK)
|
||||||
|
memcpy(lk, (char *)rp->u.SymbolicLinkReparseBuffer.PathBuffer + off, len);
|
||||||
|
else
|
||||||
|
memcpy(lk, (char *)rp->u.MountPointReparseBuffer.PathBuffer + off, len);
|
||||||
|
|
||||||
lk[len>>1] = 0;
|
lk[len>>1] = 0;
|
||||||
|
|
||||||
|
if ((lk[0] == '\\') && (lk[1] == '?') && (lk[2] == '?') && (lk[3] == '\\')) {
|
||||||
|
/* "?\\" is a prefix that means "unparsed", or something like that */
|
||||||
|
memmove(lk, lk+4, len - 8);
|
||||||
|
len -= 8;
|
||||||
|
lk[len>>1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure it's not empty, because that would form a bad path: */
|
||||||
|
if (!lk[0])
|
||||||
|
return NULL;
|
||||||
|
|
||||||
return NARROW_PATH(lk);
|
return NARROW_PATH(lk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2434,6 +2463,15 @@ static int UNC_stat(char *dirname, int len, int *flags, int *isdir, int *islink,
|
||||||
drive_end -= 5;
|
drive_end -= 5;
|
||||||
copy[len] = 0;
|
copy[len] = 0;
|
||||||
}
|
}
|
||||||
|
/* If we ended up with "X:[/]", then add a "." at the end so that we get information
|
||||||
|
for the drive, not the current directory of the drive: */
|
||||||
|
if (is_drive_letter(copy[0]) && (copy[1] == ':')
|
||||||
|
&& (!copy[2]
|
||||||
|
|| (IS_A_DOS_SEP(copy[2]) && !copy[3]))) {
|
||||||
|
copy[2] = '\\';
|
||||||
|
copy[3] = '.';
|
||||||
|
copy[4] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!GetFileAttributesExW(WIDE_PATH(copy), GetFileExInfoStandard, &fd)) {
|
if (!GetFileAttributesExW(WIDE_PATH(copy), GetFileExInfoStandard, &fd)) {
|
||||||
errno = -1;
|
errno = -1;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user