Skip to content

Commit

Permalink
generator: Handle symlinks when copying from a container (#90)
Browse files Browse the repository at this point in the history
`docker cp` tries to avoid creating simlinks which would break out
of the directory it is creating.   In #88, when copying
`/usr/lib/x86_64-linux-gnu` from a running container, a symlink
pointing back 4 layers is rejected:

    invalid symlink: <dest>/usr/lib/x86_64-linux-gnu/hdf5/serial/include" -> "../../../../include/hdf5/serial"

The intended target of the symlink is in `<dest>/usr/include` which is
outside the path being copied.    The error message is generated
here:

    https://github.com/moby/moby/blob/dd146571ea458082c499c647ba36580bb7277131/pkg/archive/archive.go#L753

Symlinks which point inside the directory tree being copied
do not cause errors:

    <dest>/usr/lib/x86_64-linux-gnu/libxcb-render.so.0 -> libxcb-render.so.0.0.0

The "hdf5 include" error does not occur if we copy the whole of the
`/usr` directory from the container, making the symlink no longer break
out of the copied directory:

    % docker cp <container>:/usr <dest>
    Successfully copied 3.24GB to <dest>

This commit avoids the error by asking `docker cp' to print a 'tar'
stream to standard output and piping it to a local `tar` process.
The local `tar` does not complain about creating potential dangling
symlinks.

The performance of piping to 'tar' should be similar to using
"normal" `docker cp` because `dockerd` always sends a `tar` stream
to the `docker` CLI.   In the normal case, `docker cp` unarchives
the `tar` stream, using the library which checks for symlinks which
break out of the tree.  In the "tar stream" case, `docker cp` just
prints the stream to standard output.

Co-authored-by: @t089
Fixes #88
  • Loading branch information
euanh committed Mar 19, 2024
1 parent e40e1fb commit aa28983
Show file tree
Hide file tree
Showing 2 changed files with 2 additions and 2 deletions.
Expand Up @@ -18,7 +18,6 @@ extension SwiftSDKGenerator {
try await withDockerContainer(fromImage: baseDockerImage) { containerID in
try await inTemporaryDirectory { generator, _ in
let sdkUsrPath = sdkDirPath.appending("usr")
let sdkUsrLibPath = sdkUsrPath.appending("lib")
try await generator.createDirectoryIfNeeded(at: sdkUsrPath)
try await generator.copyFromDockerContainer(
id: containerID,
Expand Down Expand Up @@ -57,6 +56,7 @@ extension SwiftSDKGenerator {
try await createSymlink(at: sdkDirPath.appending("lib64"), pointingTo: "./usr/lib64")
}

let sdkUsrLibPath = sdkUsrPath.appending("lib")
try await generator.createDirectoryIfNeeded(at: sdkUsrLibPath)
var subpaths: [(subpath: String, failIfNotExists: Bool)] = [
("clang", true), ("gcc", true), ("swift", true), ("swift_static", true)
Expand Down
Expand Up @@ -122,7 +122,7 @@ public actor SwiftSDKGenerator {
else { return }
}
try await Shell.run(
"\(Self.dockerCommand) cp \(id):\(containerPath) \(localPath)",
"\(Self.dockerCommand) cp \(id):\(containerPath) - | tar x -C \(localPath.removingLastComponent())",
shouldLogCommands: self.isVerbose
)
}
Expand Down

0 comments on commit aa28983

Please sign in to comment.