Skip to content

Commit b12e46f

Browse files
committed
fs: fix cp handle existing symlinks
1 parent ea79891 commit b12e46f

File tree

2 files changed

+22
-1
lines changed

2 files changed

+22
-1
lines changed

lib/internal/fs/cp/cp.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ const {
5454
resolve,
5555
sep,
5656
} = require('path');
57+
const fsBinding = internalBinding('fs');
5758

5859
async function cpFn(src, dest, opts) {
5960
// Warn about using preserveTimestamps on 32-bit node
@@ -341,10 +342,14 @@ async function onLink(destStat, src, dest, opts) {
341342
}
342343
throw err;
343344
}
345+
344346
if (!isAbsolute(resolvedDest)) {
345347
resolvedDest = resolve(dirname(dest), resolvedDest);
346348
}
347-
if (isSrcSubdir(resolvedSrc, resolvedDest)) {
349+
350+
const srcIsDir = fsBinding.internalModuleStat(src) === 1;
351+
352+
if (srcIsDir && isSrcSubdir(resolvedSrc, resolvedDest)) {
348353
throw new ERR_FS_CP_EINVAL({
349354
message: `cannot copy ${resolvedSrc} to a subdirectory of self ` +
350355
`${resolvedDest}`,

test/parallel/test-fs-cp.mjs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,22 @@ function nextdir(dirname) {
259259
cpSync(src, dest, mustNotMutateObjectDeep({ recursive: true }));
260260
}
261261

262+
{
263+
const src = nextdir();
264+
const dest = nextdir();
265+
mkdirSync(src, mustNotMutateObjectDeep({ recursive: true }));
266+
writeFileSync(`${src}/test.txt`, 'test');
267+
symlinkSync(resolve(`${src}/test.txt`), join(src, 'link.txt'));
268+
cp(src, dest, { recursive: true },
269+
mustCall((err) => {
270+
assert.strictEqual(err, null);
271+
272+
cp(src, dest, { recursive: true }, mustCall((err) => {
273+
assert.strictEqual(err, null);
274+
}));
275+
}));
276+
}
277+
262278
// It throws error if symlink in dest points to location in src.
263279
{
264280
const src = nextdir();

0 commit comments

Comments
 (0)