github.com/endophage/docker@v1.4.2-0.20161027011718-242853499895/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/idtools" 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 rootUID, rootGID, err := idtools.GetRootUIDGID(options.UIDMaps, options.GIDMaps) 45 if err != nil { 46 return err 47 } 48 49 dest = filepath.Clean(dest) 50 if _, err := os.Stat(dest); os.IsNotExist(err) { 51 if err := idtools.MkdirAllNewAs(dest, 0755, rootUID, rootGID); err != nil { 52 return err 53 } 54 } 55 56 r := ioutil.NopCloser(tarArchive) 57 if decompress { 58 decompressedArchive, err := archive.DecompressStream(tarArchive) 59 if err != nil { 60 return err 61 } 62 defer decompressedArchive.Close() 63 r = decompressedArchive 64 } 65 66 return invokeUnpack(r, dest, options) 67 } 68 69 // TarUntar is a convenience function which calls Tar and Untar, with the output of one piped into the other. 70 // If either Tar or Untar fails, TarUntar aborts and returns the error. 71 func TarUntar(src, dst string) error { 72 return chrootArchiver.TarUntar(src, dst) 73 } 74 75 // CopyWithTar creates a tar archive of filesystem path `src`, and 76 // unpacks it at filesystem path `dst`. 77 // The archive is streamed directly with fixed buffering and no 78 // intermediary disk IO. 79 func CopyWithTar(src, dst string) error { 80 return chrootArchiver.CopyWithTar(src, dst) 81 } 82 83 // CopyFileWithTar emulates the behavior of the 'cp' command-line 84 // for a single file. It copies a regular file from path `src` to 85 // path `dst`, and preserves all its metadata. 86 // 87 // If `dst` ends with a trailing slash '/' ('\' on Windows), the final 88 // destination path will be `dst/base(src)` or `dst\base(src)` 89 func CopyFileWithTar(src, dst string) (err error) { 90 return chrootArchiver.CopyFileWithTar(src, dst) 91 } 92 93 // UntarPath is a convenience function which looks for an archive 94 // at filesystem path `src`, and unpacks it at `dst`. 95 func UntarPath(src, dst string) error { 96 return chrootArchiver.UntarPath(src, dst) 97 }