in commands/helpers/archive/tarzstd/tarzstd_extractor.go [33:125]
func (e *extractor) Extract(ctx context.Context) error {
zr, err := zstd.NewReader(io.NewSectionReader(e.r, 0, e.size), zstd.WithDecoderLowmem(true))
if err != nil {
return err
}
defer zr.Close()
tr := tar.NewReader(zr)
deferred := map[string]*tar.Header{}
for {
hdr, err := tr.Next()
if err == io.EOF {
break
}
if err != nil {
return err
}
fi := hdr.FileInfo()
if fi.Mode()&irregularModes != 0 {
continue
}
var path string
path, err = filepath.Abs(filepath.Join(e.dir, hdr.Name))
if err != nil {
return err
}
if !strings.HasPrefix(path, e.dir+string(filepath.Separator)) && path != e.dir {
return fmt.Errorf("%s cannot be extracted outside of chroot (%s)", path, e.dir)
}
if err := os.MkdirAll(filepath.Dir(path), 0777); err != nil {
return err
}
if ctx.Err() != nil {
return ctx.Err()
}
switch {
case fi.Mode()&os.ModeSymlink != 0:
deferred[path] = hdr
continue
case fi.Mode().IsDir():
deferred[path] = hdr
err := os.Mkdir(path, 0777)
if err != nil && !os.IsExist(err) {
return err
}
case fi.Mode().IsRegular():
f, err := os.Create(path)
if err != nil {
return err
}
if _, err := io.Copy(f, tr); err != nil {
f.Close()
return err
}
if err := f.Close(); err != nil {
return err
}
if err := e.updateFileMetadata(path, hdr); err != nil {
return err
}
}
}
for path, hdr := range deferred {
fi := hdr.FileInfo()
if fi.Mode()&os.ModeSymlink == 0 && !fi.Mode().IsDir() {
continue
}
if fi.Mode()&os.ModeSymlink != 0 {
if err := os.Symlink(hdr.Linkname, path); err != nil {
return err
}
}
if err := e.updateFileMetadata(path, hdr); err != nil {
return err
}
}
return nil
}