//go:build linux || freebsd // +build linux freebsd package archive import ( "fmt" "io" "strings" "sync" ) type registry struct { mu sync.RWMutex extractors map[string]Extractor } var globalRegistry = ®istry{extractors: make(map[string]Extractor)} func Register(e Extractor) error { globalRegistry.mu.Lock() defer globalRegistry.mu.Unlock() name := strings.ToLower(e.Name()) if name == "" { return fmt.Errorf("extractor name cannot be empty") } if _, exists := globalRegistry.extractors[name]; exists { return fmt.Errorf("extractor already registered: %s", name) } globalRegistry.extractors[name] = e return nil } func Get(format string) (Extractor, error) { globalRegistry.mu.RLock() defer globalRegistry.mu.RUnlock() e, exists := globalRegistry.extractors[strings.ToLower(format)] if !exists { return nil, fmt.Errorf("unsupported archive format: %s", format) } return e, nil } func GetByFilename(filename string) (Extractor, error) { format := DetectArchiveFormat(filename) if format == "" { return nil, fmt.Errorf("unknown archive format for: %s", filename) } return Get(format) } func Extract(format string, src io.Reader, destDir string) error { e, err := Get(format) if err != nil { return err } return e.Extract(src, destDir) } func ExtractByFilename(filename string, src io.Reader, destDir string) error { e, err := GetByFilename(filename) if err != nil { return err } return e.Extract(src, destDir) } func AutoExtract(filename string, src io.Reader, destDir string) error { return ExtractByFilename(filename, src, destDir) } func Supports(format string) bool { globalRegistry.mu.RLock() defer globalRegistry.mu.RUnlock() _, exists := globalRegistry.extractors[strings.ToLower(format)] return exists } func ListSupported() []string { globalRegistry.mu.RLock() defer globalRegistry.mu.RUnlock() names := make([]string, 0, len(globalRegistry.extractors)) for name := range globalRegistry.extractors { names = append(names, name) } return names }