github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/pkg/chrootarchive/archive_unix.go (about)

     1  //go:build !windows
     2  // +build !windows
     3  
     4  package chrootarchive // import "github.com/docker/docker/pkg/chrootarchive"
     5  
     6  import (
     7  	"io"
     8  	"path/filepath"
     9  	"strings"
    10  
    11  	"github.com/docker/docker/pkg/archive"
    12  	"github.com/pkg/errors"
    13  )
    14  
    15  func invokeUnpack(decompressedArchive io.Reader, dest string, options *archive.TarOptions, root string) error {
    16  	relDest, err := resolvePathInChroot(root, dest)
    17  	if err != nil {
    18  		return err
    19  	}
    20  
    21  	done := make(chan error)
    22  	err = goInChroot(root, func() { done <- archive.Unpack(decompressedArchive, relDest, options) })
    23  	if err != nil {
    24  		return err
    25  	}
    26  	return <-done
    27  }
    28  
    29  func invokePack(srcPath string, options *archive.TarOptions, root string) (io.ReadCloser, error) {
    30  	relSrc, err := resolvePathInChroot(root, srcPath)
    31  	if err != nil {
    32  		return nil, err
    33  	}
    34  
    35  	// make sure we didn't trim a trailing slash with the call to `resolvePathInChroot`
    36  	if strings.HasSuffix(srcPath, "/") && !strings.HasSuffix(relSrc, "/") {
    37  		relSrc += "/"
    38  	}
    39  
    40  	tb, err := archive.NewTarballer(relSrc, options)
    41  	if err != nil {
    42  		return nil, errors.Wrap(err, "error processing tar file")
    43  	}
    44  	err = goInChroot(root, tb.Do)
    45  	if err != nil {
    46  		return nil, errors.Wrap(err, "could not chroot")
    47  	}
    48  	return tb.Reader(), nil
    49  }
    50  
    51  // resolvePathInChroot returns the equivalent to path inside a chroot rooted at root.
    52  // The returned path always begins with '/'.
    53  //
    54  //   - resolvePathInChroot("/a/b", "/a/b/c/d") -> "/c/d"
    55  //   - resolvePathInChroot("/a/b", "/a/b")     -> "/"
    56  //
    57  // The implementation is buggy, and some bugs may be load-bearing.
    58  // Here be dragons.
    59  func resolvePathInChroot(root, path string) (string, error) {
    60  	if root == "" {
    61  		return "", errors.New("root path must not be empty")
    62  	}
    63  	rel, err := filepath.Rel(root, path)
    64  	if err != nil {
    65  		return "", err
    66  	}
    67  	if rel == "." {
    68  		rel = "/"
    69  	}
    70  	if rel[0] != '/' {
    71  		rel = "/" + rel
    72  	}
    73  	return rel, nil
    74  }