Skip to content

cp -r breaks when the directory contains a softlink #193

@crjobson

Description

@crjobson

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions