func()

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
}