示例#1
0
// 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)
}
示例#2
0
文件: pod.go 项目: juito/hyper
// 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)
}