-
Notifications
You must be signed in to change notification settings - Fork 744
cp -r breaks when the directory contains a softlink #193
Description
Assuming you have the following folder structure:
.
+-- foo/
+-- bar # softlink to ../bar
+-- baz
+-- qux # softlink to ../../qux
+-- quux # softlink to ../../quux
+--- bar/
+--- file1
+--- file2
+--- qux/
+--- quux/
+--- ...
When you do:
cp('-rf', 'foo/*', 'out/');The code for cp looks at the first argument, and realizes this is a list, so expands it. For each item, it uses ‘lstat()’ to determine the file type – and if the file is a soft link, what the actual target type of the file is. So for my case, I have a folder under 'foo' called ‘bar’, which is soft linked to a target 'bar' dir, so in this case shell.cp calls lstat which returns a directory. This is then recursively copied. Hence the 'bar' softlink ends up being copied as a full dir tree.
Now, also under foo is a directory (called baz). This has two child directories (qux and quux), which are both soft links to some other target folders. So baz is a dir, so that gets recursively copied. But the recursive copy here is now done in the cpdirSyncRecursive function. This looks at the contents of the dir – and now uses stat instead of lstat to determine file type. Here it sees qux, quux etc. and sees this is a softlink – and simply copies the softlink. As qux refers to ../../qux that’s what gets created in the target out folder – but that relative link is not a valid location in the new place. But the link is created anyway.
So as a result, ‘bar’ is copied OK but qux and quux are not.
I can’t see how copying symlinks directly can ever work – unless the target is an absolute dir (not a relative one). In general though, I would prefer the prepare step to make full copies not simply copy the symlink.