From 0e8ae9185573f01b2c80ddf3d271e4a3383e440c Mon Sep 17 00:00:00 2001 From: Yuesong Jake Li Date: Tue, 27 May 2025 12:16:11 +0930 Subject: [PATCH] fs: fix cpSync handle existing symlinks PR-URL: https://github.com/nodejs/node/pull/58476 Fixes: https://github.com/nodejs/node/issues/58468 Reviewed-By: Dario Piotrowicz --- lib/internal/fs/cp/cp-sync.js | 4 +++- test/parallel/test-fs-cp.mjs | 13 ++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/internal/fs/cp/cp-sync.js b/lib/internal/fs/cp/cp-sync.js index 9e67ae6335e..1b562b7d239 100644 --- a/lib/internal/fs/cp/cp-sync.js +++ b/lib/internal/fs/cp/cp-sync.js @@ -196,7 +196,9 @@ function onLink(destStat, src, dest, verbatimSymlinks) { if (!isAbsolute(resolvedDest)) { resolvedDest = resolve(dirname(dest), resolvedDest); } - if (isSrcSubdir(resolvedSrc, resolvedDest)) { + const srcIsDir = fsBinding.internalModuleStat(src) === 1; + + if (srcIsDir && isSrcSubdir(resolvedSrc, resolvedDest)) { throw new ERR_FS_CP_EINVAL({ message: `cannot copy ${resolvedSrc} to a subdirectory of self ` + `${resolvedDest}`, diff --git a/test/parallel/test-fs-cp.mjs b/test/parallel/test-fs-cp.mjs index 260a1449d1a..dbdb0b7b19e 100644 --- a/test/parallel/test-fs-cp.mjs +++ b/test/parallel/test-fs-cp.mjs @@ -15,7 +15,7 @@ const { writeFileSync, } = fs; import net from 'net'; -import { join } from 'path'; +import { join, resolve } from 'path'; import { pathToFileURL } from 'url'; import { setTimeout } from 'timers/promises'; @@ -248,6 +248,17 @@ function nextdir(dirname) { ); } +// It allows copying when is not a directory +{ + const src = nextdir(); + const dest = nextdir(); + mkdirSync(src, mustNotMutateObjectDeep({ recursive: true })); + writeFileSync(`${src}/test.txt`, 'test'); + symlinkSync(resolve(`${src}/test.txt`), join(src, 'link.txt')); + cpSync(src, dest, mustNotMutateObjectDeep({ recursive: true })); + cpSync(src, dest, mustNotMutateObjectDeep({ recursive: true })); +} + // It throws error if symlink in dest points to location in src. { const src = nextdir();