In my windows environment (x64), fs.stat
function for symlink
pointing to directory brings an error.
On the other hand, in appveyor (ia32), fs.stat
function for symlink
pointing to directory works well.
This is why? and which behavior is correct?
A part of my test code is
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();
});
Please see https://github.com/knight9999/WindowsSymbolicLinkCheck for all codes.
The result in my local environment is
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
The result in appveyor is
Started
target :C:\Users\appveyor\AppData\Local\Temp\1\appveyor-tests-winSymlinkTests-NsaPyJ\sample1
link :C:\Users\appveyor\AppData\Local\Temp\1\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 }
.
Please see https://ci.appveyor.com/project/knight9999/windowssymboliclinkcheck .
Note:
I know that the symlinkd
or junction
is appropriate for directory in windows.
However fs.copy
for a junction
pointing to directory creates new symlink
(neither symlinkd
nor junction
) automatically.
I found this issue in detail by myself.
For Windows 10, fs.statSync
calls nodejs internal function
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;
}
...
in deps/uv/src/win/fs.c
.
See https://github.com/nodejs/node/blob/9b292272ff3d71a0ebabe46d040346dbd34585db/deps/uv/src/win/fs.c#L1252 .
CreateFileW
returns INVALID_HANDLE_VALUE
for a symlink
pointing to other directory.
But for Windows Server 2012 R2 (same as in appveyor), this function works well.
Therefore
node -e "console.log(fs.statSync('/path/to/symlink/pointing/other/directory`));"
brings error for Windows 10, works well for Windows Server 2012 R2.
I conclude we should avoid symlink
which points to other directory in Windows 10. A junction
is better.