package extract import ( "context" "errors" "os" "path/filepath" ) var ( ErrUnsupportedFormat = errors.New("unsupported archive format") ErrUnsafeEntry = errors.New("archive contains an unsafe path") ErrTooLarge = errors.New("archive exceeds the extraction size limit") ErrTooManyEntries = errors.New("archive contains too many entries") ) type Limits struct { MaxBytes int64 MaxEntries int } type Progress interface { SetTotal(total int64) Add(delta int64) } func Archive(ctx context.Context, archivePath, destination string, limits Limits, progress Progress) error { archiveFormat, _ := detect(filepath.Base(archivePath)) if archiveFormat == formatNone { return ErrUnsupportedFormat } if err := os.Mkdir(destination, 0o755); err != nil { return err } writer := &entryWriter{ctx: ctx, root: destination, limits: limits, progress: progress} var err error if archiveFormat == formatZip { err = extractZip(archivePath, writer) } else { err = extractTar(archivePath, archiveFormat, writer) } if err != nil { os.RemoveAll(destination) } return err }