nodejs / nodejs/node

fs.cp and fs.cpSync fail to repeatedly copy directory with symlinks

Offen
#65,097 1 Kommentar 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

fs
Vorherrschende Sprache
JavaScript
Sterne
122k
Forks
37.3k
Ø Merge
4 T. 2 Std.
Gemergte PRs (30 T.)
283

Beschreibung

Version

v24.16.0

Platform
Linux machine 7.1.3-cachyos-lto #1-NixOS SMP PREEMPT_DYNAMIC Tue Jan  1 00:00:00 UTC 1980 x86_64 GNU/Linux
Subsystem

fs

What steps will reproduce the bug?

This script reproduces the issue:

root="$(mktemp -d)"
trap 'rm -rf "$root"' EXIT

mkdir "$root/dir" "$root/foo"
ln -s "$root/dir" "$root/foo/link"

ROOT="$root" node <<'NODE'
const fs = require("node:fs");
const root = process.env.ROOT;

fs.cpSync(`${root}/foo`, `${root}/bar`, { recursive: true }); // succeeds
fs.cpSync(`${root}/foo`, `${root}/bar`, { recursive: true }); // throws
NODE
How often does it reproduce? Is there a required condition?

Requires a copying repeatedly a dir containing a symlink to another dir.

What is the expected behavior? Why is that the expected behavior?

The second copy should succeed, replacing bar/link or leaving it unchanged.

What do you see instead?
node:internal/fs/cp/cp-sync:145
    return fsBinding.cpSyncCopyDir(src, dest,
                     ^

Error: Cannot copy /tmp/tmp.61ap1tNPej/dir to a subdirectory of self /tmp/tmp.61ap1tNPej/dir
    at copyDir (node:internal/fs/cp/cp-sync:145:22)
    at onDir (node:internal/fs/cp/cp-sync:137:10)
    at getStats (node:internal/fs/cp/cp-sync:68:12)
    at cpSyncFn (node:internal/fs/cp/cp-sync:58:10)
    at Object.cpSync (node:fs:3158:3)
    at [stdin]:5:4
    at runScriptInThisContext (node:internal/vm:219:10)
    at node:internal/process/execution:451:12
    at [stdin]-wrapper:6:24
    at runScriptInContext (node:internal/process/execution:449:60) {
  code: 'ERR_FS_CP_EINVAL'
}

Node.js v24.16.0
Additional information

Also recreated in:

  • Node.js v22.23.1
  • Node.js v26.7.0
  • Node.js v27.0.0-nightly20260806de333e856d

The result is the same with force: true, force: false, or errorOnExist. fs.cp() and fs.promises.cp() are also affected.

Modifying bar/link, or pointing it to a different directory, makes the second copy succeed.

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Beginnen Sie mit der Reproduktion unter Verwendung von node:fs und folgen Sie den Stack-Einträgen in node:internal/fs/cp/cp-sync, insbesondere copyDir, onDir und getStats. Prüfen Sie den wiederholten rekursiven Kopiervorgang mit einem Verzeichnis-Symlink und verifizieren Sie anschließend, dass fs.cpSync, fs.cp und fs.promises.cp die zweite Kopie erfolgreich abschließen, ohne das gemeldete Verhalten für ein Selbstunterverzeichnis zu ändern.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
javascript, nodejs
Bereich
backend, operating-systems
Issue-Typ
Bug
Schwierigkeit
3/5
Geschätzter Aufwand
1-2 Tage
Aktivitätsstatus
Ruhig
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
68/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.