Version
main
Platform
Subsystem
vfs
What steps will reproduce the bug?
import fs from 'node:fs/promises';
import path from 'node:path';
import vfs from 'node:vfs';
const mountPoint = path.resolve(`/tmp/vfs-lchmod-${process.pid}`);
const virtualFs = vfs.create({ emitExperimentalWarning: false });
virtualFs.writeFileSync('/target.txt', 'target');
virtualFs.symlinkSync('/target.txt', '/link.txt');
virtualFs.mount(mountPoint);
await fs.lchmod(path.join(mountPoint, 'link.txt'), 0o700);
virtualFs.unmount();
const targetStats = virtualFs.lstatSync('/target.txt');
const linkStats = virtualFs.lstatSync('/link.txt');
console.log({
targetMode: targetStats.mode & 0o777,
linkMode: linkStats.mode & 0o777,
});
How often does it reproduce? Is there a required condition?
Always
What is the expected behavior? Why is that the expected behavior?
{ targetMode: 420, linkMode: 448 }
lchmod should operate on the symlink itself and leave the target metadata unchanged.
What do you see instead?
{ targetMode: 448, linkMode: 420 }
fs.promises.lchmod() changes the target file’s mode while the symlink’s own mode is unchanged.
Additional information
fs equivalent
import fs from 'node:fs/promises';
import os from 'node:os';
import path from 'node:path';
const dir = await fs.mkdtemp(path.join(os.tmpdir(), 'fs-lchmod-'));
const target = path.join(dir, 'target.txt');
const link = path.join(dir, 'link.txt');
await fs.writeFile(target, 'target');
await fs.symlink(target, link);
await fs.lchmod(link, 0o700);
const targetStats = await fs.lstat(target);
const linkStats = await fs.lstat(link);
console.log({
targetMode: targetStats.mode & 0o777,
linkMode: linkStats.mode & 0o777,
});
await fs.rm(dir, { recursive: true, force: true });
Version
main
Platform
Subsystem
vfs
What steps will reproduce the bug?
How often does it reproduce? Is there a required condition?
Always
What is the expected behavior? Why is that the expected behavior?
{ targetMode: 420, linkMode: 448 }lchmodshould operate on the symlink itself and leave the target metadata unchanged.What do you see instead?
{ targetMode: 448, linkMode: 420 }fs.promises.lchmod()changes the target file’s mode while the symlink’s own mode is unchanged.Additional information
fs equivalent