`fs.stat` 符号链接函数指向 Windows 中的目录
`fs.stat` function for symlink pointing to directory in Windows
在我的 windows 环境 (x64) 中,指向目录的 symlink
的 fs.stat
函数会出错。
另一方面,在 appveyor (ia32) 中,fs.stat
指向目录的 symlink
函数运行良好。
这是为什么呢?哪种行为是正确的?
我的部分测试代码是
it('Test 001 : fs.stat for symlink', function () {
var target = path.resolve(workDir, 'sample1');
console.log('target :' + target);
fs.mkdirSync(target); // create directory
var link = path.resolve(workDir, 'link1');
console.log('link :' + link);
fs.symlinkSync(target, link); // create symlink to directory
expect(function() {
var stat = fs.statSync(link); // checking symlink stat
console.log(stat);
}).not.toThrow();
});
所有代码请参阅https://github.com/knight9999/WindowsSymbolicLinkCheck。
我本地环境下的结果是
Failures:
1) win symlink tests Test 001 : fs.stat for symlink
Message:
Expected function not to throw, but it threw Error: EPERM: operation not permitted, stat 'C:\Users\knaito\AppData\Local\Temp\appveyor-tests-winSymlinkTests-VcfaRo\link1'.
Stack:
Error: Expected function not to throw, but it threw Error: EPERM: operation not permitted, stat 'C:\Users\knaito\AppData\Local\Temp\appveyor-tests-winSymlinkTests-VcfaRo\link1'.
at <Jasmine>
at UserContext.<anonymous> (C:\Users\knaito\Documents\work\cordova-develop\WindowsSymbolicLinkCheck\spec\winSymlink.spec.js:24:12)
at <Jasmine>
1 spec, 1 failure
appveyor 中的结果是
Started
target :C:\Users\appveyor\AppData\Local\Temp\appveyor-tests-winSymlinkTests-NsaPyJ\sample1
link :C:\Users\appveyor\AppData\Local\Temp\appveyor-tests-winSymlinkTests-NsaPyJ\link1
Stats {
dev: 3567992900,
mode: 16822,
nlink: 1,
uid: 0,
gid: 0,
rdev: 0,
blksize: undefined,
ino: 844424934502125,
size: 0,
blocks: undefined,
atimeMs: 1537164694047.7703,
mtimeMs: 1537164694047.7703,
ctimeMs: 1537164694047.7703,
birthtimeMs: 1537164694047.7703,
atime: 2018-09-17T06:11:34.048Z,
mtime: 2018-09-17T06:11:34.048Z,
ctime: 2018-09-17T06:11:34.048Z,
birthtime: 2018-09-17T06:11:34.048Z }
.
请参阅https://ci.appveyor.com/project/knight9999/windowssymboliclinkcheck。
注意:
我知道 symlinkd
或 junction
适用于 windows 中的目录。
然而 fs.copy
对于指向目录的 junction
会自动创建新的 symlink
(既不是 symlinkd
也不是 junction
)。
这个问题是我自己详细发现的
对于Windows10,fs.statSync
调用nodejs内部函数
INLINE static void fs__stat_impl(uv_fs_t* req, int do_lstat) {
HANDLE handle;
DWORD flags;
flags = FILE_FLAG_BACKUP_SEMANTICS;
if (do_lstat) {
flags |= FILE_FLAG_OPEN_REPARSE_POINT;
}
handle = CreateFileW(req->file.pathw,
FILE_READ_ATTRIBUTES,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
flags,
NULL);
if (handle == INVALID_HANDLE_VALUE) {
SET_REQ_WIN32_ERROR(req, GetLastError());
return;
}
...
在 deps/uv/src/win/fs.c
中。
参见 https://github.com/nodejs/node/blob/9b292272ff3d71a0ebabe46d040346dbd34585db/deps/uv/src/win/fs.c#L1252。
CreateFileW
returns INVALID_HANDLE_VALUE
对于指向其他目录的 symlink
。
但对于Windows Server 2012 R2(与appveyor中相同),此功能运行良好。
因此
node -e "console.log(fs.statSync('/path/to/symlink/pointing/other/directory`));"
为 Windows 10 带来错误,适用于 Windows Server 2012 R2。
我的结论是我们应该避免 symlink
指向 Windows 10 中的其他目录。junction
更好。
如果执行文件在ex文件夹中:src/webpack/然后将文件移动到src/,然后在package.json中的脚本中执行命令,就可以了。
在我的 windows 环境 (x64) 中,指向目录的 symlink
的 fs.stat
函数会出错。
另一方面,在 appveyor (ia32) 中,fs.stat
指向目录的 symlink
函数运行良好。
这是为什么呢?哪种行为是正确的?
我的部分测试代码是
it('Test 001 : fs.stat for symlink', function () {
var target = path.resolve(workDir, 'sample1');
console.log('target :' + target);
fs.mkdirSync(target); // create directory
var link = path.resolve(workDir, 'link1');
console.log('link :' + link);
fs.symlinkSync(target, link); // create symlink to directory
expect(function() {
var stat = fs.statSync(link); // checking symlink stat
console.log(stat);
}).not.toThrow();
});
所有代码请参阅https://github.com/knight9999/WindowsSymbolicLinkCheck。
我本地环境下的结果是
Failures:
1) win symlink tests Test 001 : fs.stat for symlink
Message:
Expected function not to throw, but it threw Error: EPERM: operation not permitted, stat 'C:\Users\knaito\AppData\Local\Temp\appveyor-tests-winSymlinkTests-VcfaRo\link1'.
Stack:
Error: Expected function not to throw, but it threw Error: EPERM: operation not permitted, stat 'C:\Users\knaito\AppData\Local\Temp\appveyor-tests-winSymlinkTests-VcfaRo\link1'.
at <Jasmine>
at UserContext.<anonymous> (C:\Users\knaito\Documents\work\cordova-develop\WindowsSymbolicLinkCheck\spec\winSymlink.spec.js:24:12)
at <Jasmine>
1 spec, 1 failure
appveyor 中的结果是
Started
target :C:\Users\appveyor\AppData\Local\Temp\appveyor-tests-winSymlinkTests-NsaPyJ\sample1
link :C:\Users\appveyor\AppData\Local\Temp\appveyor-tests-winSymlinkTests-NsaPyJ\link1
Stats {
dev: 3567992900,
mode: 16822,
nlink: 1,
uid: 0,
gid: 0,
rdev: 0,
blksize: undefined,
ino: 844424934502125,
size: 0,
blocks: undefined,
atimeMs: 1537164694047.7703,
mtimeMs: 1537164694047.7703,
ctimeMs: 1537164694047.7703,
birthtimeMs: 1537164694047.7703,
atime: 2018-09-17T06:11:34.048Z,
mtime: 2018-09-17T06:11:34.048Z,
ctime: 2018-09-17T06:11:34.048Z,
birthtime: 2018-09-17T06:11:34.048Z }
.
请参阅https://ci.appveyor.com/project/knight9999/windowssymboliclinkcheck。
注意:
我知道 symlinkd
或 junction
适用于 windows 中的目录。
然而 fs.copy
对于指向目录的 junction
会自动创建新的 symlink
(既不是 symlinkd
也不是 junction
)。
这个问题是我自己详细发现的
对于Windows10,fs.statSync
调用nodejs内部函数
INLINE static void fs__stat_impl(uv_fs_t* req, int do_lstat) {
HANDLE handle;
DWORD flags;
flags = FILE_FLAG_BACKUP_SEMANTICS;
if (do_lstat) {
flags |= FILE_FLAG_OPEN_REPARSE_POINT;
}
handle = CreateFileW(req->file.pathw,
FILE_READ_ATTRIBUTES,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
flags,
NULL);
if (handle == INVALID_HANDLE_VALUE) {
SET_REQ_WIN32_ERROR(req, GetLastError());
return;
}
...
在 deps/uv/src/win/fs.c
中。
参见 https://github.com/nodejs/node/blob/9b292272ff3d71a0ebabe46d040346dbd34585db/deps/uv/src/win/fs.c#L1252。
CreateFileW
returns INVALID_HANDLE_VALUE
对于指向其他目录的 symlink
。
但对于Windows Server 2012 R2(与appveyor中相同),此功能运行良好。
因此
node -e "console.log(fs.statSync('/path/to/symlink/pointing/other/directory`));"
为 Windows 10 带来错误,适用于 Windows Server 2012 R2。
我的结论是我们应该避免 symlink
指向 Windows 10 中的其他目录。junction
更好。
如果执行文件在ex文件夹中:src/webpack/然后将文件移动到src/,然后在package.json中的脚本中执行命令,就可以了。