예제 #1
0
파일: volumes.go 프로젝트: beginnor/docker
func (v *Volume) initialize(container *Container) error {
	var err error
	v.VolPath = filepath.Clean(v.VolPath)

	// Do not initialize an existing volume
	if _, exists := container.Volumes[v.VolPath]; exists {
		return nil
	}

	// If it's not a bindmount we need to create the dir on the host
	if !v.isBindMount {
		v.HostPath, err = createVolumeHostPath(container)
		if err != nil {
			return err
		}
	}

	hostPath, err := filepath.EvalSymlinks(v.HostPath)
	if err != nil {
		return err
	}

	// Create the mountpoint
	// This is the path to the volume within the container FS
	// This differs from `hostPath` in that `hostPath` refers to the place where
	// the volume data is actually stored on the host
	fullVolPath, err := symlink.FollowSymlinkInScope(filepath.Join(container.basefs, v.VolPath), container.basefs)
	if err != nil {
		return err
	}

	container.Volumes[v.VolPath] = hostPath
	container.VolumesRW[v.VolPath] = v.isRw()

	volIsDir, err := v.isDir()
	if err != nil {
		return err
	}
	if err := createIfNotExists(fullVolPath, volIsDir); err != nil {
		return err
	}

	// Do not copy or change permissions if we are mounting from the host
	if v.isRw() && !v.isBindMount {
		return copyExistingContents(fullVolPath, hostPath)
	}
	return nil
}
예제 #2
0
파일: init.go 프로젝트: beginnor/docker
func setupBindmounts(rootfs string, mountConfig *MountConfig) error {
	bindMounts := mountConfig.Mounts
	for _, m := range bindMounts.OfType("bind") {
		var (
			flags = syscall.MS_BIND | syscall.MS_REC
			dest  = filepath.Join(rootfs, m.Destination)
		)
		if !m.Writable {
			flags = flags | syscall.MS_RDONLY
		}

		stat, err := os.Stat(m.Source)
		if err != nil {
			return err
		}

		dest, err = symlink.FollowSymlinkInScope(dest, rootfs)
		if err != nil {
			return err
		}

		if err := createIfNotExists(dest, stat.IsDir()); err != nil {
			return fmt.Errorf("Creating new bind-mount target, %s", err)
		}

		if err := syscall.Mount(m.Source, dest, "bind", uintptr(flags), ""); err != nil {
			return fmt.Errorf("mounting %s into %s %s", m.Source, dest, err)
		}
		if !m.Writable {
			if err := syscall.Mount(m.Source, dest, "bind", uintptr(flags|syscall.MS_REMOUNT), ""); err != nil {
				return fmt.Errorf("remounting %s into %s %s", m.Source, dest, err)
			}
		}
		if m.Relabel != "" {
			if err := label.Relabel(m.Source, mountConfig.MountLabel, m.Relabel); err != nil {
				return fmt.Errorf("relabeling %s to %s %s", m.Source, mountConfig.MountLabel, err)
			}
		}
		if m.Private {
			if err := syscall.Mount("", dest, "none", uintptr(syscall.MS_PRIVATE), ""); err != nil {
				return fmt.Errorf("mounting %s private %s", dest, err)
			}
		}
	}
	return nil
}
예제 #3
0
func (container *Container) getRootResourcePath(path string) (string, error) {
	cleanPath := filepath.Join("/", path)
	return symlink.FollowSymlinkInScope(filepath.Join(container.root, cleanPath), container.root)
}
예제 #4
0
파일: build.go 프로젝트: beginnor/docker
func (b *buildFile) addContext(container *Container, orig, dest string, decompress bool) error {
	var (
		err        error
		destExists = true
		origPath   = path.Join(b.contextPath, orig)
		destPath   = path.Join(container.RootfsPath(), dest)
	)

	if destPath != container.RootfsPath() {
		destPath, err = symlink.FollowSymlinkInScope(destPath, container.RootfsPath())
		if err != nil {
			return err
		}
	}

	// Preserve the trailing '/'
	if strings.HasSuffix(dest, "/") || dest == "." {
		destPath = destPath + "/"
	}

	destStat, err := os.Stat(destPath)
	if err != nil {
		if !os.IsNotExist(err) {
			return err
		}
		destExists = false
	}

	fi, err := os.Stat(origPath)
	if err != nil {
		if os.IsNotExist(err) {
			return fmt.Errorf("%s: no such file or directory", orig)
		}
		return err
	}

	if fi.IsDir() {
		return copyAsDirectory(origPath, destPath, destExists)
	}

	// If we are adding a remote file (or we've been told not to decompress), do not try to untar it
	if decompress {
		// 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 / .
		tarDest := destPath
		if strings.HasSuffix(tarDest, "/") {
			tarDest = filepath.Dir(destPath)
		}

		// try to successfully untar the orig
		if err := archive.UntarPath(origPath, tarDest); err == nil {
			return nil
		} else if err != io.EOF {
			log.Debugf("Couldn't untar %s to %s: %s", origPath, tarDest, err)
		}
	}

	if err := os.MkdirAll(path.Dir(destPath), 0755); err != nil {
		return err
	}
	if err := archive.CopyWithTar(origPath, destPath); err != nil {
		return err
	}

	resPath := destPath
	if destExists && destStat.IsDir() {
		resPath = path.Join(destPath, path.Base(origPath))
	}

	return fixPermissions(resPath, 0, 0)
}