X-Git-Url: http://git.osdn.net/view?p=bytom%2Fvapor.git;a=blobdiff_plain;f=vendor%2Fgithub.com%2Fwhyrusleeping%2Ftar-utils%2Fextractor.go;fp=vendor%2Fgithub.com%2Fwhyrusleeping%2Ftar-utils%2Fextractor.go;h=0000000000000000000000000000000000000000;hp=0088c7121dc6c54dbb6391fc5bd044655c7e6916;hb=54373c1a3efe0e373ec1605840a4363e4b246c46;hpb=ee01d543fdfe1fd0a4d548965c66f7923ea7b062 diff --git a/vendor/github.com/whyrusleeping/tar-utils/extractor.go b/vendor/github.com/whyrusleeping/tar-utils/extractor.go deleted file mode 100644 index 0088c712..00000000 --- a/vendor/github.com/whyrusleeping/tar-utils/extractor.go +++ /dev/null @@ -1,217 +0,0 @@ -package tar - -import ( - "archive/tar" - "fmt" - "io" - "os" - gopath "path" - fp "path/filepath" - "strings" -) - -type Extractor struct { - Path string - Progress func(int64) int64 - - // SanitizePathFunc can be provided if you wish to inspect and/or modify the source path - // returning an error from this function will abort extraction - SanitizePathFunc func(path string) (saferPath string, userDefined error) - - // LinkFunc can be provided for user specified handling of filesystem links - // returning an error from this function aborts extraction - LinkFunc func(Link) error -} - -// Link represents a filesystem link where Name is the link's destination path, -// Target is what the link actually points to, -// and Root is the extraction root -type Link struct { - Root, Name, Target string -} - -func (te *Extractor) Extract(reader io.Reader) error { - if isNullDevice(te.Path) { - return nil - } - - tarReader := tar.NewReader(reader) - - // Check if the output path already exists, so we know whether we should - // create our output with that name, or if we should put the output inside - // a preexisting directory - rootExists := true - rootIsDir := false - if stat, err := os.Stat(te.Path); err != nil && os.IsNotExist(err) { - rootExists = false - } else if err != nil { - return err - } else if stat.IsDir() { - rootIsDir = true - } - - // files come recursively in order (i == 0 is root directory) - for i := 0; ; i++ { - header, err := tarReader.Next() - if err != nil && err != io.EOF { - return err - } - if header == nil || err == io.EOF { - break - } - - switch header.Typeflag { - case tar.TypeDir: - if err := te.extractDir(header, i); err != nil { - return err - } - case tar.TypeReg: - if err := te.extractFile(header, tarReader, i, rootExists, rootIsDir); err != nil { - return err - } - case tar.TypeSymlink: - if err := te.extractSymlink(header); err != nil { - return err - } - default: - return fmt.Errorf("unrecognized tar header type: %d", header.Typeflag) - } - } - return nil -} - -// Sanitize sets up the extractor to use built in sanitation functions -// (Modify paths to be platform legal, symlinks may not escape extraction root) -// or unsets any previously set sanitation functions on the extractor -// (no special rules are applied when extracting) -func (te *Extractor) Sanitize(toggle bool) { - if toggle { - te.SanitizePathFunc = sanitizePath - te.LinkFunc = func(inLink Link) error { - if err := childrenOnly(inLink); err != nil { - return err - } - if err := platformLink(inLink); err != nil { - return err - } - return os.Symlink(inLink.Target, inLink.Name) - } - } else { - te.SanitizePathFunc = nil - te.LinkFunc = nil - } -} - -// outputPath returns the path at which to place tarPath -func (te *Extractor) outputPath(tarPath string) (outPath string, err error) { - elems := strings.Split(tarPath, "/") // break into elems - elems = elems[1:] // remove original root - outPath = strings.Join(elems, "/") // join elems - outPath = gopath.Join(te.Path, outPath) // rebase on to extraction target root - // sanitize path to be platform legal - if te.SanitizePathFunc != nil { - outPath, err = te.SanitizePathFunc(outPath) - } else { - outPath = fp.FromSlash(outPath) - } - return -} - -func (te *Extractor) extractDir(h *tar.Header, depth int) error { - path, err := te.outputPath(h.Name) - if err != nil { - return err - } - - if depth == 0 { - // if this is the root directory, use it as the output path for remaining files - te.Path = path - } - - return os.MkdirAll(path, 0755) -} - -func (te *Extractor) extractSymlink(h *tar.Header) error { - path, err := te.outputPath(h.Name) - if err != nil { - return err - } - - if te.LinkFunc != nil { - return te.LinkFunc(Link{Root: te.Path, Name: h.Name, Target: h.Linkname}) - } - - return os.Symlink(h.Linkname, path) -} - -func (te *Extractor) extractFile(h *tar.Header, r *tar.Reader, depth int, rootExists bool, rootIsDir bool) error { - path, err := te.outputPath(h.Name) - if err != nil { - return err - } - - if depth == 0 { // if depth is 0, this is the only file (we aren't extracting a directory) - if rootExists && rootIsDir { - // putting file inside of a root dir. - fnameo := gopath.Base(h.Name) - fnamen := fp.Base(path) - // add back original name if lost. - if fnameo != fnamen { - path = fp.Join(path, fnameo) - } - } // else if old file exists, just overwrite it. - } - - file, err := os.Create(path) - if err != nil { - return err - } - defer file.Close() - - return copyWithProgress(file, r, te.Progress) -} - -func copyWithProgress(to io.Writer, from io.Reader, cb func(int64) int64) error { - buf := make([]byte, 4096) - for { - n, err := from.Read(buf) - if n != 0 { - if cb != nil { - cb(int64(n)) - } - _, err2 := to.Write(buf[:n]) - if err2 != nil { - return err2 - } - } - if err != nil { - if err == io.EOF { - return nil - } - return err - } - } -} - -// childrenOnly will return an error if link targets escape their root -func childrenOnly(inLink Link) error { - if fp.IsAbs(inLink.Target) { - return fmt.Errorf("Link target %q is an absolute path (forbidden)", inLink.Target) - } - - resolvedTarget := fp.Join(inLink.Name, inLink.Target) - rel, err := fp.Rel(inLink.Root, resolvedTarget) - if err != nil { - return err - } - //disallow symlinks from climbing out of the target root - if strings.HasPrefix(rel, "..") { - return fmt.Errorf("Symlink target %q escapes root %q", inLink.Target, inLink.Root) - } - //disallow pointing to your own root from above as well - if strings.HasPrefix(resolvedTarget, inLink.Root) { - return fmt.Errorf("Symlink target %q escapes and re-enters its own root %q (forbidden)", inLink.Target, inLink.Root) - } - - return nil -}