mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-24 06:14:01 +08:00
Preserve Windows errors when following filesystem links
This commit is contained in:
@@ -4243,8 +4243,21 @@ static ScrStats *scr_stats_of_path(const ScrStr *path, const char *op,
|
||||
HANDLE h = CreateFileW(wide, FILE_READ_ATTRIBUTES,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
NULL, OPEN_EXISTING, flags, NULL);
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
DWORD error = GetLastError();
|
||||
DWORD attributes = GetFileAttributesW(wide);
|
||||
free(wide);
|
||||
/* CRT stat can report the link entry when its target cannot be opened,
|
||||
* hiding dangling links and Windows file/directory type mismatches.
|
||||
* libuv preserves the failed follow operation for reparse points. */
|
||||
if (!no_follow && attributes != INVALID_FILE_ATTRIBUTES &&
|
||||
(attributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
|
||||
scr_fs_throw(scr_fs_win_errno(error), op, path);
|
||||
return NULL;
|
||||
}
|
||||
return scr_stats_crt_fallback(path, op);
|
||||
}
|
||||
free(wide);
|
||||
if (h == INVALID_HANDLE_VALUE) return scr_stats_crt_fallback(path, op);
|
||||
|
||||
DWORD file_type = GetFileType(h);
|
||||
if (file_type != FILE_TYPE_DISK) {
|
||||
@@ -4423,9 +4436,7 @@ void scr_fs_symlink(ScrStr *target, ScrStr *destination, int kind) {
|
||||
free(text);
|
||||
}
|
||||
scr_str_release(absolute);
|
||||
/* Node's binding namespaces the link path before passing it to libuv.
|
||||
* In particular, Windows can reject a file link to a directory differently
|
||||
* when the destination uses the extended-length path syntax. */
|
||||
/* Node's binding namespaces the link path before passing it to libuv. */
|
||||
ScrStr *link_path = scr_path_win32_to_namespaced_path(destination);
|
||||
WCHAR *from = scr_fs_win_wide(stored), *to = scr_fs_win_wide(link_path);
|
||||
DWORD error = !from || !to ? GetLastError() : 0;
|
||||
|
||||
@@ -38,7 +38,9 @@ async function main() {
|
||||
// Buffer paths bypass that probe and use the file-link fallback.
|
||||
try {
|
||||
await call(fs.symlink, "dir", Buffer.from(join(root, "inferred")));
|
||||
console.log("inferred", fs.statSync(join(root, "inferred")).isDirectory());
|
||||
console.log("inferred link", fs.lstatSync(join(root, "inferred")).isSymbolicLink());
|
||||
try { console.log("inferred stat", fs.statSync(join(root, "inferred")).isDirectory()); }
|
||||
catch (e) { console.log("inferred stat", e.name, e.code, e.message.includes("stat")); }
|
||||
} catch (e) { if (process.platform === "win32" && e.code === "EPERM") console.log("symlink privilege boundary"); else throw e; }
|
||||
let synchronous = true;
|
||||
await new Promise(resolve => {
|
||||
|
||||
@@ -32,8 +32,17 @@ try {
|
||||
console.log("absolute", fs.readlinkSync(join(root, "absolute")) === file);
|
||||
fs.symlinkSync("missing-target", join(root, "dangling"), null);
|
||||
console.log("dangling", fs.readlinkSync(join(root, "dangling")), fs.lstatSync(join(root, "dangling")).isSymbolicLink());
|
||||
try { fs.statSync(join(root, "dangling")); } catch (e) { const err = e as NodeJS.ErrnoException; console.log("dangling stat", err.name, err.code); }
|
||||
fs.symlinkSync("nested", join(root, "directory"), "dir");
|
||||
console.log("directory", fs.statSync(join(root, "directory")).isDirectory());
|
||||
fs.symlinkSync("nested", join(root, "file-directory"), "file");
|
||||
console.log("file-directory link", fs.lstatSync(join(root, "file-directory")).isSymbolicLink(), fs.readlinkSync(join(root, "file-directory")) === "nested");
|
||||
try { console.log("file-directory stat", fs.statSync(join(root, "file-directory")).isDirectory()); }
|
||||
catch (e) { const err = e as NodeJS.ErrnoException; console.log("file-directory stat", err.name, err.code); }
|
||||
fs.symlinkSync("target.txt", join(root, "directory-file"), "dir");
|
||||
console.log("directory-file link", fs.lstatSync(join(root, "directory-file")).isSymbolicLink());
|
||||
try { console.log("directory-file stat", fs.statSync(join(root, "directory-file")).isFile()); }
|
||||
catch (e) { const err = e as NodeJS.ErrnoException; console.log("directory-file stat", err.name, err.code); }
|
||||
if (process.platform !== "win32") {
|
||||
fs.symlinkSync("x".repeat(600), join(root, "long"), "file");
|
||||
console.log("long", fs.readlinkSync(join(root, "long")).length);
|
||||
|
||||
Reference in New Issue
Block a user