// BuilderCopy copies/extracts a source FileInfo to a destination path inside a container // specified by a container object. // TODO: make sure callers don't unnecessarily convert destPath with filepath.FromSlash (Copy does it already). // BuilderCopy should take in abstract paths (with slashes) and the implementation should convert it to OS-specific paths. func (d Docker) BuilderCopy(cID string, destPath string, src builder.FileInfo, decompress bool) error { srcPath := src.Path() destExists := true destDir := false rootUID, rootGID := d.Daemon.GetRemappedUIDGID() // Work in daemon-local OS specific file paths destPath = filepath.FromSlash(destPath) c, err := d.Daemon.GetContainer(cID) if err != nil { return err } err = d.Daemon.Mount(c) if err != nil { return err } defer d.Daemon.Unmount(c) dest, err := c.GetResourcePath(destPath) if err != nil { return err } // Preserve the trailing slash // TODO: why are we appending another path separator if there was already one? if strings.HasSuffix(destPath, string(os.PathSeparator)) || destPath == "." { destDir = true dest += string(os.PathSeparator) } destPath = dest destStat, err := os.Stat(destPath) if err != nil { if !os.IsNotExist(err) { logrus.Errorf("Error performing os.Stat on %s. %s", destPath, err) return err } destExists = false } if src.IsDir() { // copy as directory if err := d.Archiver.CopyWithTar(srcPath, destPath); err != nil { return err } return fixPermissions(srcPath, destPath, rootUID, rootGID, destExists) } if decompress && archive.IsArchivePath(srcPath) { // Only try to untar if it is a file and that we've been told to decompress (when ADD-ing a remote file) // First try to unpack the source as an archive // to support the untar feature we need to clean up the path a little bit // because tar is very forgiving. First we need to strip off the archive's // filename from the path but this is only added if it does not end in slash tarDest := destPath if strings.HasSuffix(tarDest, string(os.PathSeparator)) { tarDest = filepath.Dir(destPath) } // try to successfully untar the orig err := d.Archiver.UntarPath(srcPath, tarDest) if err != nil { logrus.Errorf("Couldn't untar to %s: %v", tarDest, err) } return err } // only needed for fixPermissions, but might as well put it before CopyFileWithTar if destDir || (destExists && destStat.IsDir()) { destPath = filepath.Join(destPath, src.Name()) } if err := idtools.MkdirAllNewAs(filepath.Dir(destPath), 0755, rootUID, rootGID); err != nil { return err } if err := d.Archiver.CopyFileWithTar(srcPath, destPath); err != nil { return err } return fixPermissions(srcPath, destPath, rootUID, rootGID, destExists) }
// BuilderCopy copies/extracts a source FileInfo to a destination path inside a container // specified by a container object. // TODO: make sure callers don't unnecessarily convert destPath with filepath.FromSlash (Copy does it already). // BuilderCopy should take in abstract paths (with slashes) and the implementation should convert it to OS-specific paths. func (d Docker) BuilderCopy(cId string, destPath string, src builder.FileInfo, decompress bool) error { // add copy item to exec-copy.sh podId, ok := d.hyper.CopyPods[cId] if !ok { return fmt.Errorf("%s is not a copy pod", cId) } copyshell, err := os.OpenFile(filepath.Join("/var/run/hyper/shell", podId, "exec-copy.sh"), os.O_RDWR|os.O_APPEND, 0755) if err != nil { glog.Errorf(err.Error()) return err } fmt.Fprintf(copyshell, fmt.Sprintf("cp -r /tmp/src/%s %s\n", src.Name(), destPath)) copyshell.Close() srcPath := src.Path() destExists := true destDir := false rootUID, rootGID := d.Daemon.GetRemappedUIDGID() // Work in daemon-local OS specific file paths destPath = filepath.Join("/var/run/hyper/temp/", podId, filepath.FromSlash(src.Name())) // Preserve the trailing slash // TODO: why are we appending another path separator if there was already one? if strings.HasSuffix(destPath, string(os.PathSeparator)) || destPath == "." { destDir = true } destStat, err := os.Stat(destPath) if err != nil { if !os.IsNotExist(err) { glog.Errorf("Error performing os.Stat on %s. %s", destPath, err) return err } destExists = false } uidMaps, gidMaps := d.Daemon.GetUIDGIDMaps() archiver := &archive.Archiver{ Untar: chrootarchive.Untar, UIDMaps: uidMaps, GIDMaps: gidMaps, } if src.IsDir() { // copy as directory if err := archiver.CopyWithTar(srcPath, destPath); err != nil { return err } return fixPermissions(srcPath, destPath, rootUID, rootGID, destExists) } if decompress && archive.IsArchivePath(srcPath) { // Only try to untar if it is a file and that we've been told to decompress (when ADD-ing a remote file) // First try to unpack the source as an archive // to support the untar feature we need to clean up the path a little bit // because tar is very forgiving. First we need to strip off the archive's // filename from the path but this is only added if it does not end in slash tarDest := destPath if strings.HasSuffix(tarDest, string(os.PathSeparator)) { tarDest = filepath.Dir(destPath) } // try to successfully untar the orig err := archiver.UntarPath(srcPath, tarDest) if err != nil { glog.Errorf("Couldn't untar to %s: %v", tarDest, err) } return err } // only needed for fixPermissions, but might as well put it before CopyFileWithTar if destDir || (destExists && destStat.IsDir()) { destPath = filepath.Join(destPath, src.Name()) } if err := idtools.MkdirAllNewAs(filepath.Dir(destPath), 0755, rootUID, rootGID); err != nil { return err } if err := archiver.CopyFileWithTar(srcPath, destPath); err != nil { return err } return fixPermissions(srcPath, destPath, rootUID, rootGID, destExists) }