dotcloud/docker

View on GitHub
pkg/chrootarchive/archive_unix.go

Summary

Maintainability
A
0 mins
Test Coverage
//go:build !windows

package chrootarchive // import "github.com/docker/docker/pkg/chrootarchive"

import (
    "io"
    "net"
    "os/user"
    "path/filepath"
    "strings"

    "github.com/docker/docker/pkg/archive"
    "github.com/pkg/errors"
)

func init() {
    // initialize nss libraries in Glibc so that the dynamic libraries are loaded in the host
    // environment not in the chroot from untrusted files.
    _, _ = user.Lookup("docker")
    _, _ = net.LookupHost("localhost")
}

func invokeUnpack(decompressedArchive io.Reader, dest string, options *archive.TarOptions, root string) error {
    relDest, err := resolvePathInChroot(root, dest)
    if err != nil {
        return err
    }

    return doUnpack(decompressedArchive, relDest, root, options)
}

func invokePack(srcPath string, options *archive.TarOptions, root string) (io.ReadCloser, error) {
    relSrc, err := resolvePathInChroot(root, srcPath)
    if err != nil {
        return nil, err
    }

    // make sure we didn't trim a trailing slash with the call to `resolvePathInChroot`
    if strings.HasSuffix(srcPath, "/") && !strings.HasSuffix(relSrc, "/") {
        relSrc += "/"
    }

    return doPack(relSrc, root, options)
}

// resolvePathInChroot returns the equivalent to path inside a chroot rooted at root.
// The returned path always begins with '/'.
//
//   - resolvePathInChroot("/a/b", "/a/b/c/d") -> "/c/d"
//   - resolvePathInChroot("/a/b", "/a/b")     -> "/"
//
// The implementation is buggy, and some bugs may be load-bearing.
// Here be dragons.
func resolvePathInChroot(root, path string) (string, error) {
    if root == "" {
        return "", errors.New("root path must not be empty")
    }
    rel, err := filepath.Rel(root, path)
    if err != nil {
        return "", err
    }
    if rel == "." {
        rel = "/"
    }
    if rel[0] != '/' {
        rel = "/" + rel
    }
    return rel, nil
}