github.com/damirazo/docker@v1.9.0/pkg/chrootarchive/archive.go (about)

     1  package chrootarchive
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"io/ioutil"
     7  	"os"
     8  	"path/filepath"
     9  
    10  	"github.com/docker/docker/pkg/archive"
    11  	"github.com/docker/docker/pkg/system"
    12  )
    13  
    14  var chrootArchiver = &archive.Archiver{Untar: Untar}
    15  
    16  // Untar reads a stream of bytes from `archive`, parses it as a tar archive,
    17  // and unpacks it into the directory at `dest`.
    18  // The archive may be compressed with one of the following algorithms:
    19  //  identity (uncompressed), gzip, bzip2, xz.
    20  func Untar(tarArchive io.Reader, dest string, options *archive.TarOptions) error {
    21  	return untarHandler(tarArchive, dest, options, true)
    22  }
    23  
    24  // UntarUncompressed reads a stream of bytes from `archive`, parses it as a tar archive,
    25  // and unpacks it into the directory at `dest`.
    26  // The archive must be an uncompressed stream.
    27  func UntarUncompressed(tarArchive io.Reader, dest string, options *archive.TarOptions) error {
    28  	return untarHandler(tarArchive, dest, options, false)
    29  }
    30  
    31  // Handler for teasing out the automatic decompression
    32  func untarHandler(tarArchive io.Reader, dest string, options *archive.TarOptions, decompress bool) error {
    33  
    34  	if tarArchive == nil {
    35  		return fmt.Errorf("Empty archive")
    36  	}
    37  	if options == nil {
    38  		options = &archive.TarOptions{}
    39  	}
    40  	if options.ExcludePatterns == nil {
    41  		options.ExcludePatterns = []string{}
    42  	}
    43  
    44  	dest = filepath.Clean(dest)
    45  	if _, err := os.Stat(dest); os.IsNotExist(err) {
    46  		if err := system.MkdirAll(dest, 0777); err != nil {
    47  			return err
    48  		}
    49  	}
    50  
    51  	r := ioutil.NopCloser(tarArchive)
    52  	if decompress {
    53  		decompressedArchive, err := archive.DecompressStream(tarArchive)
    54  		if err != nil {
    55  			return err
    56  		}
    57  		defer decompressedArchive.Close()
    58  		r = decompressedArchive
    59  	}
    60  
    61  	return invokeUnpack(r, dest, options)
    62  }
    63  
    64  // TarUntar is a convenience function which calls Tar and Untar, with the output of one piped into the other.
    65  // If either Tar or Untar fails, TarUntar aborts and returns the error.
    66  func TarUntar(src, dst string) error {
    67  	return chrootArchiver.TarUntar(src, dst)
    68  }
    69  
    70  // CopyWithTar creates a tar archive of filesystem path `src`, and
    71  // unpacks it at filesystem path `dst`.
    72  // The archive is streamed directly with fixed buffering and no
    73  // intermediary disk IO.
    74  func CopyWithTar(src, dst string) error {
    75  	return chrootArchiver.CopyWithTar(src, dst)
    76  }
    77  
    78  // CopyFileWithTar emulates the behavior of the 'cp' command-line
    79  // for a single file. It copies a regular file from path `src` to
    80  // path `dst`, and preserves all its metadata.
    81  //
    82  // If `dst` ends with a trailing slash '/' ('\' on Windows), the final
    83  // destination path will be `dst/base(src)` or `dst\base(src)`
    84  func CopyFileWithTar(src, dst string) (err error) {
    85  	return chrootArchiver.CopyFileWithTar(src, dst)
    86  }
    87  
    88  // UntarPath is a convenience function which looks for an archive
    89  // at filesystem path `src`, and unpacks it at `dst`.
    90  func UntarPath(src, dst string) error {
    91  	return chrootArchiver.UntarPath(src, dst)
    92  }