### Install sevenzip-go Package Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/getting-started.md Use the go get command to install the sevenzip-go package. This is a standard Go package and can be imported directly into your project. ```bash go get github.com/itchio/sevenzip-go/sz ``` -------------------------------- ### Complete Extraction Example with Custom Callback Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/api-reference/extractcallback.md This example demonstrates a full archive extraction process using a custom ExtractCallbackImpl. It shows how to implement SetProgress for progress updates and GetStream for handling file creation and directory creation. Ensure the archive file and output directory are accessible. ```go package main import ( "errors" "fmt" "log" "os" "path/filepath" "strings" "github.com/itchio/sevenzip-go/sz" ) type ExtractCallbackImpl struct { outputDir string total int64 } func (ec *ExtractCallbackImpl) SetProgress(completed, total int64) { if total > 0 { pct := 100 * completed / total fmt.Printf("Progress: %d%% (%d / %d bytes)\n", pct, completed, total) } } func (ec *ExtractCallbackImpl) GetStream(item *sz.Item) (*sz.OutStream, error) { // Get item path path, ok := item.GetStringProperty(sz.PidPath) if !ok { return nil, errors.New("could not get item path") } // Check if directory isDir, _ := item.GetBoolProperty(sz.PidIsDir) if isDir { fullPath := filepath.Join(ec.outputDir, path) if err := os.MkdirAll(fullPath, 0755); err != nil { return nil, err } return nil, nil // Return nil for directories } // Create file fullPath := filepath.Join(ec.outputDir, path) // Ensure parent directory exists if err := os.MkdirAll(filepath.Dir(fullPath), 0755); err != nil { return nil, err } // Create the file f, err := os.Create(fullPath) if err != nil { return nil, err } // Wrap in OutStream outStream, err := sz.NewOutStream(f) if err != nil { f.Close() return nil, err } return outStream, nil } func main() { // Initialize library lib, err := sz.NewLib() if err != nil { log.Fatal(err) } defer lib.Free() // Open archive f, err := os.Open("archive.7z") if err != nil { log.Fatal(err) } defer f.Close() stats, err := f.Stat() if err != nil { log.Fatal(err) } inStream, err := sz.NewInStream(f, "7z", stats.Size()) if err != nil { log.Fatal(err) } defer inStream.Free() archive, err := lib.OpenArchive(inStream, false) if err != nil { log.Fatal(err) } defer archive.Free() defer archive.Close() // Get item count count, err := archive.GetItemCount() if err != nil { log.Fatal(err) } // Create callback callback := &ExtractCallbackImpl{ outputDir: "./extracted", total: stats.Size(), } ec, err := sz.NewExtractCallback(callback) if err != nil { log.Fatal(err) } defer ec.Free() // Extract all items indices := make([]int64, count) for i := int64(0); i < count; i++ { indices[i] = i } if err := archive.ExtractSeveral(indices, ec); err != nil { log.Fatalf("Extraction failed: %v", err) } // Check for errors errs := ec.Errors() if len(errs) > 0 { log.Printf("Extraction completed with %d errors:", len(errs)) for _, itemErr := range errs { log.Printf(" - %v", itemErr) } } else { log.Println("Extraction completed successfully") } } ``` -------------------------------- ### Custom ExtractCallback Implementation Example Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/api-reference/extractcallback.md Example of implementing the ExtractCallbackFuncs interface to handle progress reporting and file/directory creation during extraction. This example creates files in a specified output directory. ```go type MyExtractCallback struct { outputDir string } func (ec *MyExtractCallback) SetProgress(completed, total int64) { pct := 100 * completed / total fmt.Printf("Progress: %d%%\n", pct) } func (ec *MyExtractCallback) GetStream(item *sz.Item) (*sz.OutStream, error) { path, ok := item.GetStringProperty(sz.PidPath) if !ok { return nil, errors.New("could not get item path") } isDir, _ := item.GetBoolProperty(sz.PidIsDir) if isDir { // Create directory, return nil for stream os.MkdirAll(filepath.Join(ec.outputDir, path), 0755) return nil, nil } // Create file fullPath := filepath.Join(ec.outputDir, path) os.MkdirAll(filepath.Dir(fullPath), 0755) f, err := os.Create(fullPath) if err != nil { return nil, err } return sz.NewOutStream(f) } // Create callback myCallback := &MyExtractCallback{outputDir: "./extracted"} ec, err := sz.NewExtractCallback(myCallback) if err != nil { log.Fatal(err) } deffer ec.Free() // Use with ExtractSeveral... ``` -------------------------------- ### Get 7-Zip Library Version Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/api-reference/lib.md Retrieves the version string of the loaded 7-zip library. This is useful for checking compatibility or logging purposes. ```go lib, err := sz.NewLib() if err != nil { log.Fatal(err) } def lib.Free() version := lib.GetVersion() fmt.Printf("7-zip version: %s\n", version) ``` -------------------------------- ### Accessing Numeric Properties Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/architecture.md Example of retrieving a uint64 property from an archive item using its PropertyIndex. The second return value indicates if the property was available. ```go import ( "github.com/gen-spa/sevenzip/archive" ) // Assuming 'item' is an archive item and 'archive.PropertyIndex.Size' is the desired property size, ok := item.GetUInt64Property(archive.PropertyIndex.Size) if ok { // Use the size } ``` -------------------------------- ### Accessing String Properties Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/architecture.md Example of retrieving a string property from an archive item using its PropertyIndex. The second return value indicates if the property was available. ```go import ( "github.com/gen-spa/sevenzip/archive" ) // Assuming 'item' is an archive item and 'archive.PropertyIndex.Path' is the desired property path, ok := item.GetStringProperty(archive.PropertyIndex.Path) if ok { // Use the path } ``` -------------------------------- ### Example Usage of coalesceErrors in Archive.GetItemCount Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/errors.md Demonstrates using coalesceErrors to check for errors from InStream I/O, library errors, and a generic fallback in Archive.GetItemCount. ```go res := int64(C.libc7zip_archive_get_item_count(a.arch)) if res < 0 { err := coalesceErrors(a.in.Error(), a.lib.Error(), ErrUnknownError) return 0, err } ``` -------------------------------- ### Accessing Boolean Properties Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/architecture.md Example of retrieving a boolean property from an archive item using its PropertyIndex. The second return value indicates if the property was available. ```go import ( "github.com/gen-spa/sevenzip/archive" ) // Assuming 'item' is an archive item and 'archive.PropertyIndex.IsDir' is the desired property isDir, ok := item.GetBoolProperty(archive.PropertyIndex.IsDir) if ok { // Use the isDir boolean } ``` -------------------------------- ### Handle Unsupported Archive Type Errors Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/errors.md Catch ErrNotSupportedArchive if the archive format is not recognized by the 7-zip library. The example shows retrying with signature detection if the initial attempt fails. ```go archive, err := lib.OpenArchive(inStream, false) if err == sz.ErrNotSupportedArchive { log.Println("Archive format not supported, trying by signature detection...") // Reset stream position and retry with signature detection inStream.Seek(0, io.SeekStart) archive, err = lib.OpenArchive(inStream, true) if err != nil { log.Fatalf("Failed even with signature detection: %v", err) } } else if err != nil { log.Fatalf("Failed to open archive: %v", err) } ``` -------------------------------- ### Get Archive Format Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/api-reference/archive.md Retrieves the format of the archive, such as 'zip' or '7z'. The format is determined from the archive's signature or file extension. This method is useful for identifying the archive type before processing its contents. ```go lib, err := sz.NewLib() if err != nil { log.Fatal(err) } deffer lib.Free() inStream, err := sz.NewInStream(reader, "7z", size) if err != nil { log.Fatal(err) } deffer inStream.Free() archive, err := lib.OpenArchive(inStream, false) if err != nil { log.Fatal(err) } deffer archive.Free() deffer archive.Close() format := archive.GetArchiveFormat() fmt.Printf("Archive format: %s\n", format) ``` -------------------------------- ### Batch Extraction vs. Individual Extraction in Go Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/getting-started.md Use ExtractSeveral() for batch extraction of multiple archive items for better performance compared to repeated individual Extract() calls. This example shows the efficient batch method. ```go // Good: Batch extraction indices := make([]int64, count) for i := int64(0); i < count; i++ { indices[i] = i } archive.ExtractSeveral(indices, ec) // Avoid: Repeated individual extractions for i := int64(0); i < count; i++ { item := archive.GetItem(i) archive.Extract(item, outStream) item.Free() } ``` -------------------------------- ### Initialize SevenZip-Go Library and Open Archive Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/INDEX.md Demonstrates how to initialize the sevenzip-go library and open a new archive. Ensure CGO is enabled and native 7-zip libraries are accessible. ```go import "github.com/itchio/sevenzip-go/sz" lib, _ := sz.NewLib() inStream, _ := sz.NewInStream(file, "zip", size) archive, _ := lib.OpenArchive(inStream, false) ``` -------------------------------- ### Initialize and Open Archive Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/getting-started.md This Go code snippet demonstrates how to initialize the 7-zip library, open an archive file, and retrieve basic information such as version, format, and item count. Ensure the native libraries are correctly placed. ```go package main import ( "log" "os" "github.com/itchio/sevenzip-go/sz" ) func main() { // Initialize the library lib, err := sz.NewLib() if err != nil { log.Fatalf("Failed to initialize 7-zip: %v", err) } defer lib.Free() log.Printf("7-zip version: %s", lib.GetVersion()) // Open archive file f, err := os.Open("archive.7z") if err != nil { log.Fatal(err) } defer f.Close() // Get file size stats, err := f.Stat() if err != nil { log.Fatal(err) } // Create input stream inStream, err := sz.NewInStream(f, "7z", stats.Size()) if err != nil { log.Fatal(err) } defer inStream.Free() // Open archive archive, err := lib.OpenArchive(inStream, false) if err != nil { log.Fatal(err) } defer archive.Close() defer archive.Free() // Get archive format format := archive.GetArchiveFormat() log.Printf("Archive format: %s", format) // Count items count, err := archive.GetItemCount() if err != nil { log.Fatal(err) } log.Printf("Archive contains %d items", count) } ``` -------------------------------- ### Initialize SevenZip Library Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/api-reference/lib.md Creates and initializes a new Lib instance. This function performs lazy initialization of the 7-zip C library, loading the appropriate native library based on the operating system. Ensure to call Free() on the returned Lib instance to release resources. ```go lib, err := sz.NewLib() if err != nil { log.Fatalf("Failed to initialize 7-zip: %v", err) } def lib.Free() version := lib.GetVersion() log.Printf("7-zip version: %s", version) ``` -------------------------------- ### Main Entry Point Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/INDEX.md Functions for library initialization, version retrieval, error handling, resource cleanup, and opening archives. ```APIDOC ## Main Entry Point ### Description Provides functions for initializing the 7-zip library, retrieving its version, handling errors, cleaning up resources, and opening archives. ### Functions - `NewLib()`: Create and initialize the 7-zip library. - `GetVersion()`: Get the 7-zip version string. - `Error()`: Get the last library error. - `Free()`: Clean up library resources. - `OpenArchive(filePath string)`: Open and parse an archive file. ``` -------------------------------- ### Archive Object Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/INDEX.md Represents an opened archive, providing methods to get archive format, item count, individual items, and to extract items. ```APIDOC ## Archive Object ### Description Represents an opened archive, allowing retrieval of its format, the number of items it contains, individual items by index, and extraction of single or multiple items. It also provides methods for closing the archive and cleaning up resources. ### Methods - `GetArchiveFormat()`: Get the format of the archive (e.g., zip, 7z, rar). - `GetItemCount()`: Get the total number of items within the archive. - `GetItem(index int)`: Get the item at the specified index. - `Extract(itemIndex int, outStream OutStream)`: Extract a single item to the provided output stream. - `ExtractSeveral(itemIndices []int, outStreams []OutStream)`: Extract multiple items to their respective output streams. - `Close()`: Close the archive. - `Free()`: Clean up archive resources. ``` -------------------------------- ### Define Lib Structure Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/types.md Represents the main entry point for 7-zip functionality. It should be created with NewLib() and freed with Free(). ```go type Lib struct { lib *C.lib // Opaque pointer to C library structure } ``` -------------------------------- ### Lib Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/types.md Represents the main entry point for 7-zip functionality. It should be created using NewLib() and freed with Free(). ```APIDOC ## Lib ### Description Represents the main entry point for 7-zip functionality. Should be created with NewLib() and freed with Free(). ### Fields - **lib** (*C.lib) - Opaque pointer to C library structure. ``` -------------------------------- ### NewLib Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/api-reference/lib.md Creates and initializes a new Lib instance. This function performs lazy initialization of the 7-zip C library, loading the appropriate native library based on the operating system. ```APIDOC ## NewLib ### Description Creates and initializes a new Lib instance. This function performs lazy initialization of the 7-zip C library, loading the appropriate native library based on the operating system. ### Method `NewLib` ### Parameters No parameters. ### Returns `(*Lib, error)` — A new Lib instance, or an error if initialization fails. ### Throws/Rejects - Error | Library not found in executable directory - Error | libc7zip initialization failed ### Example ```go lib, err := sz.NewLib() if err != nil { log.Fatalf("Failed to initialize 7-zip: %v", err) } def lib.Free() version := lib.GetVersion() log.Printf("7-zip version: %s", version) ``` ``` -------------------------------- ### Get Extraction Errors from ExtractCallback Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/api-reference/extractcallback.md Retrieves a slice of errors encountered during individual item extraction. Use this after an extraction operation to identify specific failures. ```go ec, err := sz.NewExtractCallback(myCallback) if err != nil { log.Fatal(err) } defer ec.Free() indices := []int64{0, 1, 2} err = archive.ExtractSeveral(indices, ec) if err != nil { log.Printf("Extraction aborted: %v", err) } // Check for per-item errors errors := ec.Errors() if len(errors) > 0 { log.Printf("Extraction completed with %d errors:", len(errors)) for _, itemErr := range errors { log.Printf(" - %v", itemErr) } } ``` -------------------------------- ### Archive Format Detection Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/architecture.md Demonstrates how to configure archive format detection using file extension or signature. Signature-based detection is more reliable but slower. ```go import ( "github.com/gen-spa/sevenzip/archive" ) // Extension-based detection (faster, less reliable) archive.OpenReader("file.zip", archive.OpenOptions{bySignature: false}) // Signature-based detection (slower, more reliable) archive.OpenReader("file.zip", archive.OpenOptions{bySignature: true}) ``` -------------------------------- ### Get Archive Index of an Item Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/api-reference/item.md Retrieves the zero-based index of an item within the archive's item list. Ensure the archive and item are properly opened and managed. ```go archive, err := lib.OpenArchive(inStream, false) if err != nil { log.Fatal(err) } defers archive.Free() defers archive.Close() item := archive.GetItem(0) if item != nil { defer item.Free() index := item.GetArchiveIndex() fmt.Printf("Item archive index: %d\n", index) } ``` -------------------------------- ### Detect Archive Format by Signature Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/getting-started.md Attempt to open an archive first with an extension hint, and if that fails, fall back to signature-based detection. Ensure the stream is reset before the second attempt. ```go // First, try with extension hint archive, err := lib.OpenArchive(inStream, false) if err == sz.ErrNotSupportedArchive { // If that fails, try signature-based detection inStream.Seek(0, io.SeekStart) archive, err = lib.OpenArchive(inStream, true) if err != nil { log.Fatal(err) } } ``` -------------------------------- ### OutStream Error Retrieval Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/errors.md Shows how to get an error from an OutStream after write operations. This is crucial for identifying issues like writer I/O errors, disk space problems, or permission issues. ```go func (out *OutStream) Error() error ``` ```go outStream, err := sz.NewOutStream(writer) if err != nil { log.Fatal(err) } deffer func() { outStream.Close() outStream.Free() }() // Use stream... if writeErr := outStream.Error(); writeErr != nil { log.Printf("OutStream I/O error: %v", writeErr) } ``` -------------------------------- ### SevenZip-Go Archive Processing Workflow Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/INDEX.md This snippet outlines the typical steps for opening an archive, retrieving item information, and freeing resources. Ensure all resources are freed in the reverse order of their acquisition. ```go 1. NewLib() → *Lib 2. NewInStream(file, ext, size) → *InStream 3. Lib.OpenArchive(inStream, bySignature) → *Archive 4. Archive.GetItemCount() → count 5. Archive.GetItem(index) → *Item 6. Item.GetStringProperty(PidPath) → path 7. Item.GetUInt64Property(PidSize) → size 8. Item.GetBoolProperty(PidIsDir) → isDir 9. Item.Free() 10. Archive.Close() 11. Archive.Free() 12. InStream.Free() 13. Lib.Free() ``` -------------------------------- ### Configure SevenZip-Go Tests with Environment Variables Source: https://github.com/itchio/sevenzip-go/blob/master/README.md Use environment variables to override the default channel and version for downloading native libraries during testing. This allows for testing against specific platforms or development builds. ```bash # Use a specific channel LIBC7ZIP_CHANNEL=darwin-arm64-head go test -v ./sz/ ``` ```bash # Use a specific version LIBC7ZIP_VERSION=6d8a0456c76c573ff5ba3bf5bda1c86bd34f4394 go test -v ./sz/ ``` ```bash # Use both LIBC7ZIP_CHANNEL=linux-amd64 LIBC7ZIP_VERSION=1.9.0 go test -v ./sz/ ``` -------------------------------- ### Get Bool Property of an Item Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/api-reference/item.md Retrieves a boolean property for an item using its identifier. Returns the property value and a boolean indicating success. Useful for checking if an item is a directory or encrypted. ```go item := archive.GetItem(0) if item != nil { defer item.Free() // Check if item is a directory isDir, ok := item.GetBoolProperty(sz.PidIsDir) if ok { if isDir { fmt.Println("Item is a directory") } else { fmt.Println("Item is a file") } } // Check if item is encrypted encrypted, ok := item.GetBoolProperty(sz.PidEncrypted) if ok && encrypted { fmt.Println("Item is encrypted") }} ``` -------------------------------- ### NewInStream Constructor Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/api-reference/instream.md Creates a new InStream for the 7-zip library. It wraps an existing io.ReaderAt and io.Closer, taking the file extension and total archive size as parameters. The stream manages its position for seeking. ```go func NewInStream(reader ReaderAtCloser, ext string, size int64) (*InStream, error) ``` ```go f, err := os.Open("archive.zip") if err != nil { log.Fatal(err) } deffer f.Close() stats, err := f.Stat() if err != nil { log.Fatal(err) } inStream, err := sz.NewInStream(f, "zip", stats.Size()) if err != nil { log.Fatal(err) } defer inStream.Free() // Use inStream with lib.OpenArchive(inStream, false)... ``` -------------------------------- ### Get String Property of an Item Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/api-reference/item.md Retrieves a string-based property for an item using its identifier. Returns the property value and a boolean indicating success. Useful for properties like path or comments. ```go item := archive.GetItem(0) if item != nil { defer item.Free() // Get item path path, ok := item.GetStringProperty(sz.PidPath) if ok { fmt.Printf("Path: %s\n", path) } // Get comment if available comment, ok := item.GetStringProperty(sz.PidComment) if ok { fmt.Printf("Comment: %s\n", comment) }} ``` -------------------------------- ### Get Item by Index Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/api-reference/archive.md Retrieves a specific item from the archive using its zero-based index. Returns nil if the index is out of bounds. This method is often used in conjunction with GetItemCount to iterate through archive contents. ```go archive, err := lib.OpenArchive(inStream, false) if err != nil { log.Fatal(err) } deffer archive.Free() deffer archive.Close() count, err := archive.GetItemCount() if err != nil { log.Fatal(err) } for i := int64(0); i < count; i++ { item := archive.GetItem(i) if item == nil { log.Printf("Could not get item at index %d", i) continue } path, ok := item.GetStringProperty(sz.PidPath) if ok { fmt.Printf("Item %d: %s\n", i, path) } item.Free() } ``` -------------------------------- ### Handle 7-Zip Initialization Errors Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/errors.md Catch ErrNotInitialize if the native 7-zip libraries are not found or fail to initialize. This typically occurs when required DLLs/SOs are missing or incompatible. ```go lib, err := sz.NewLib() if err == sz.ErrNotInitialize { log.Println("7-zip libraries not found or failed to initialize") log.Println("Required files: c7zip.dll/libc7zip.so/libc7zip.dylib") } else if err != nil { log.Fatalf("Unexpected error: %v", err) } ``` -------------------------------- ### SevenZip-Go Layered Architecture Diagram Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/architecture.md Illustrates the flow of control from a Go application down through the various layers of abstraction to the 7-zip core library. ```text Go Application Code ↓ sevenzip-go Go API (sz package) ↓ CGO Bindings (calls C functions) ↓ libc7zip C Library (ships separately) ↓ lib7zip C++ Library (ships separately) ↓ 7-zip C++/COM Core Library (ships separately) ``` -------------------------------- ### Get Item Count Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/api-reference/archive.md Returns the total number of items (files and directories) within an archive. This is useful for iterating through all contents or for pre-allocating resources. Errors can occur if there are issues reading the archive's metadata. ```go archive, err := lib.OpenArchive(inStream, false) if err != nil { log.Fatal(err) } deffer archive.Free() deffer archive.Close() count, err := archive.GetItemCount() if err != nil { log.Fatalf("Failed to get item count: %v", err) } fmt.Printf("Archive contains %d items\n", count) ``` -------------------------------- ### Visualize Access Patterns Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/api-reference/readstats.md This code snippet illustrates how to visualize archive read patterns by creating an image where each pixel represents a read operation. The color of the pixel indicates the read size, and the position reflects the offset and size. ```go // Create image with one pixel per read operation width := len(inStream.Stats.Reads) height := 800 // Plot reads on image for visualization for x, op := range inStream.Stats.Reads { ymin := int(math.Floor(float64(op.Offset) * scale)) ymax := int(math.Ceil(float64(op.Offset+op.Size) * scale)) // Color represents read size intensity := uint8(float64(op.Size) / float64(maxReadSize) * 255) for y := ymin; y <= ymax; y++ { img.Set(x, y, &color.RGBA{R: 255, G: intensity, B: 0, A: 255}) } } // Save as PNG png.Encode(file, img) ``` -------------------------------- ### Get UInt64 Property of an Item Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/api-reference/item.md Retrieves a 64-bit unsigned integer property for an item using its identifier. Returns the property value and a boolean indicating success. Use for properties like size or POSIX attributes. ```go item := archive.GetItem(0) if item != nil { defer item.Free() // Get uncompressed size size, ok := item.GetUInt64Property(sz.PidSize) if ok { fmt.Printf("Uncompressed size: %d bytes\n", size) } // Get packed (compressed) size packSize, ok := item.GetUInt64Property(sz.PidPackSize) if ok { fmt.Printf("Packed size: %d bytes\n", packSize) } // Get POSIX attributes posixAttrib, ok := item.GetUInt64Property(sz.PidPosixAttrib) if ok { fmt.Printf("POSIX attributes: %%#o\n", posixAttrib) }} ``` -------------------------------- ### SevenZip-Go Batch Extraction Workflow Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/INDEX.md This snippet details the process for performing batch extractions from an archive, including setting up an extraction callback and handling per-item errors. Remember to free all allocated resources. ```go 1. NewLib() → *Lib 2. NewInStream(file, ext, size) → *InStream 3. Lib.OpenArchive(inStream, bySignature) → *Archive 4. NewExtractCallback(myImpl) → *ExtractCallback 5. Archive.ExtractSeveral(indices, ec) → error 6. ec.Errors() → []error (per-item errors) 7. ec.Free() 8. Archive.Close() 9. Archive.Free() 10. InStream.Free() 11. Lib.Free() ``` -------------------------------- ### Open Archive from Input Stream Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/api-reference/lib.md Opens and parses an archive from the provided input stream. The archive format can be detected either by file extension or by reading the file signature. Ensure to call Free() and Close() on the returned Archive instance. ```go lib, err := sz.NewLib() if err != nil { log.Fatal(err) } def lib.Free() f, err := os.Open("archive.7z") if err != nil { log.Fatal(err) } def f.Close() stats, err := f.Stat() if err != nil { log.Fatal(err) } inStream, err := sz.NewInStream(f, "7z", stats.Size()) if err != nil { log.Fatal(err) } def inStream.Free() archive, err := lib.OpenArchive(inStream, false) if err != nil { log.Fatal(err) } def archive.Free() def archive.Close() // Use archive... ``` -------------------------------- ### GetVersion Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/api-reference/lib.md Returns the version string of the 7-zip library. ```APIDOC ## GetVersion ### Description Returns the version string of the 7-zip library. ### Method `(l *Lib) GetVersion()` ### Parameters - `l` (*Lib) - (receiver) ### Returns `string` — The version string of the loaded 7-zip library ### Example ```go lib, err := sz.NewLib() if err != nil { log.Fatal(err) } def lib.Free() version := lib.GetVersion() fmt.Printf("7-zip version: %s\n", version) ``` ``` -------------------------------- ### Lib Interface Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/README.md Documentation for the main library interface, including initialization, version retrieval, error handling, and archive opening. ```APIDOC ## Lib Interface ### Description Provides the main interface for interacting with the 7-zip library, including initialization, retrieving library version, handling errors, and opening archives. ### Methods - `NewLib()`: Constructor for initializing the library. - `GetVersion()`: Retrieves the version of the 7-zip library. - `Error()`: Returns any error encountered during library operations. - `OpenArchive(filePath string)`: Opens a 7-zip archive file for reading. ``` -------------------------------- ### NewInStream Constructor Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/api-reference/instream.md Creates a new input stream that wraps a reader and provides it to the 7-zip library. The stream maintains position state for seeking operations. ```APIDOC ## NewInStream Constructor ### Description Creates a new input stream that wraps a reader and provides it to the 7-zip library. The stream maintains position state for seeking operations. ### Signature ```go func NewInStream(reader ReaderAtCloser, ext string, size int64) (*InStream, error) ``` ### Parameters #### Path Parameters * None #### Query Parameters * None #### Request Body * None ### Parameters - **reader** (`ReaderAtCloser`) - Required - Reader providing archive data (implements io.ReaderAt and io.Closer) - **ext** (`string`) - Required - File extension hint for format detection (e.g., "7z", "zip", "rar", "tar") - **size** (`int64`) - Required - Total size of the archive in bytes ### Returns - `(*InStream, error)` - A new InStream instance, or an error if creation fails ### Throws/Rejects - Error | Could not create underlying C stream structure ### Example ```go f, err := os.Open("archive.zip") if err != nil { log.Fatal(err) } defer f.Close() stats, err := f.Stat() if err != nil { log.Fatal(err) } inStream, err := sz.NewInStream(f, "zip", stats.Size()) if err != nil { log.Fatal(err) } defer inStream.Free() // Use inStream with lib.OpenArchive(inStream, false)... ``` ``` -------------------------------- ### Platform-Specific Library Loading Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/architecture.md Determines the correct native library file name based on the operating system. The library is loaded from the executable's directory. ```go switch runtime.GOOS { case "windows": libPath = "c7zip.dll" case "linux": libPath = "libc7zip.so" case "darwin": libPath = "libc7zip.dylib" } ``` -------------------------------- ### Extract Multiple Items with Progress Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/getting-started.md This Go code demonstrates how to extract multiple items from a 7z archive while displaying extraction progress. It defines a custom callback to handle file creation and directory structure, and reports progress updates. Ensure you have an 'archive.7z' file in the same directory and the 'extracted' directory will be created. ```go package main import ( "errors" "fmt" "log" "os" "path/filepath" "github.com/itchio/sevenzip-go/sz" ) type MyExtractCallback struct { outputDir string } func (ec *MyExtractCallback) SetProgress(completed, total int64) { if total > 0 { pct := 100 * completed / total fmt.Printf("Progress: %d%% (%d / %d bytes)\r", pct, completed, total) } } func (ec *MyExtractCallback) GetStream(item *sz.Item) (*sz.OutStream, error) { path, ok := item.GetStringProperty(sz.PidPath) if !ok { return nil, errors.New("could not get item path") } isDir, _ := item.GetBoolProperty(sz.PidIsDir) if isDir { // Create directory fullPath := filepath.Join(ec.outputDir, path) os.MkdirAll(fullPath, 0755) return nil, nil } // Create file fullPath := filepath.Join(ec.outputDir, path) os.MkdirAll(filepath.Dir(fullPath), 0755) f, err := os.Create(fullPath) if err != nil { return nil, err } return sz.NewOutStream(f) } func main() { lib, err := sz.NewLib() if err != nil { log.Fatal(err) } defer lib.Free() // Open archive f, err := os.Open("archive.7z") if err != nil { log.Fatal(err) } defer f.Close() stats, err := f.Stat() if err != nil { log.Fatal(err) } inStream, err := sz.NewInStream(f, "7z", stats.Size()) if err != nil { log.Fatal(err) } defer inStream.Free() archive, err := lib.OpenArchive(inStream, false) if err != nil { log.Fatal(err) } defer archive.Close() defer archive.Free() // Count items count, err := archive.GetItemCount() if err != nil { log.Fatal(err) } // Create callback callback := &MyExtractCallback{ outputDir: "./extracted", } ec, err := sz.NewExtractCallback(callback) if err != nil { log.Fatal(err) } defer ec.Free() // Create indices for all items indices := make([]int64, count) for i := int64(0); i < count; i++ { indices[i] = i } // Extract all if err := archive.ExtractSeveral(indices, ec); err != nil { log.Fatalf("Extraction failed: %v", err) } // Check for errors if itemErrors := ec.Errors(); len(itemErrors) > 0 { log.Printf("\nExtraction completed with %d errors:", len(itemErrors)) for _, itemErr := range itemErrors { log.Printf(" - %v", itemErr) } } else { log.Println("\nExtraction completed successfully!") } } ``` -------------------------------- ### Querying Item Properties in a SevenZip Archive Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/api-reference/item.md This Go snippet shows how to open a SevenZip archive, iterate through its items, and retrieve various properties for each item, including its path, uncompressed size, compressed size, and whether it is a directory. Use this when you need to inspect the contents of an archive without extracting files. ```go archive, err := lib.OpenArchive(inStream, false) if err != nil { log.Fatal(err) } defers archive.Free() defers archive.Close() count, err := archive.GetItemCount() if err != nil { log.Fatal(err) } for i := int64(0); i < count; i++ { item := archive.GetItem(i) if item == nil { log.Printf("Could not get item %d", i) continue } defer item.Free() path, _ := item.GetStringProperty(sz.PidPath) size, _ := item.GetUInt64Property(sz.PidSize) packSize, _ := item.GetUInt64Property(sz.PidPackSize) isDir, _ := item.GetBoolProperty(sz.PidIsDir) itemType := "file" if isDir { itemType = "dir" } fmt.Printf("[%s] %s - %d bytes (packed: %d)\n", itemType, path, size, packSize) } ``` -------------------------------- ### Manage Archive Resources in Go Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/getting-started.md Ensure all resources (streams and archives) are freed using defer statements. Free resources in the reverse order of their creation. Calling Free() multiple times is safe. ```go // Most important: Free in reverse order of creation defer outStream.Close() defer outStream.Free() defer archive.Close() defer archive.Free() defer inStream.Free() defer lib.Free() // Calling Free() multiple times is safe ``` -------------------------------- ### Free Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/api-reference/extractcallback.md Releases all resources associated with the extract callback. Must be called to properly clean up C allocations. ```APIDOC ## Free ### Description Releases all resources associated with the extract callback. Must be called to properly clean up C allocations. ### Method Signature ```go func (ec *ExtractCallback) Free() ``` ### Parameters (receiver) ### Returns None ### Example ```go ec, err := sz.NewExtractCallback(myCallback) if err != nil { log.Fatal(err) } deffer ec.Free() // Use callback... ``` ``` -------------------------------- ### Release 7-Zip Library Resources Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/api-reference/lib.md Releases all resources associated with the Lib instance. This must be called to properly clean up C allocations. It is safe to call Free() multiple times. ```go lib, err := sz.NewLib() if err != nil { log.Fatal(err) } def lib.Free() // Ensure cleanup happens // Use lib... ``` -------------------------------- ### Free Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/api-reference/instream.md Releases all resources associated with the input stream. Must be called to properly clean up C allocations. Safe to call multiple times. ```APIDOC ## Free ### Description Releases all resources associated with the input stream. Must be called to properly clean up C allocations. Safe to call multiple times. ### Method func (in *InStream) Free() ### Returns None ### Request Example ```go inStream, err := sz.NewInStream(reader, "zip", size) if err != nil { log.Fatal(err) } defer inStream.Free() // Use inStream... ``` ``` -------------------------------- ### Registering Go Callback Functions with C Library Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/architecture.md This snippet shows how Go callback functions are registered with the C library using CGO. The C library then calls these registered pointers during archive operations. ```python def.read_cb = (C.read_cb_t)(unsafe.Pointer(C.inReadGo_cgo)) def.seek_cb = (C.seek_cb_t)(unsafe.Pointer(C.inSeekGo_cgo)) ``` -------------------------------- ### Lib Methods Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/SUMMARY.txt Methods available on the main library interface for initialization, version retrieval, error handling, resource cleanup, and archive operations. ```APIDOC ## Lib Methods ### Description Methods for initializing the library, getting its version, handling errors, freeing resources, and opening archives. ### Methods - **NewLib()**: Initialize library - **GetVersion()**: Get version string - **Error()**: Get last error - **Free()**: Cleanup resources - **OpenArchive(path string, password string)**: Open archive ``` -------------------------------- ### Implement Custom Archive Extraction Callback Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/getting-started.md Create a custom callback by implementing the `ExtractCallbackFuncs` interface to handle progress reporting and custom output stream creation during extraction. ```go type CustomCallback struct { // Custom state here } func (cc *CustomCallback) SetProgress(completed, total int64) { // Handle progress } func (cc *CustomCallback) GetStream(item *sz.Item) (*sz.OutStream, error) { // Custom logic to create output stream } // Use it ec, err := sz.NewExtractCallback(cc) ``` -------------------------------- ### Update File Extension Hint with SetExt Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/api-reference/instream.md Use SetExt to change the file extension hint for an InStream after its creation. This is useful for format detection. ```go inStream, err := sz.NewInStream(reader, "bin", size) if err != nil { log.Fatal(err) } defer inStream.Free() // Later, update extension hint inStream.SetExt("7z") ``` -------------------------------- ### Retry Archive Open with Signature Detection Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/errors.md Attempts to open an archive. If it fails with ErrNotSupportedArchive, it resets the stream and retries with signature detection enabled. ```go archive, err := lib.OpenArchive(inStream, false) if err == sz.ErrNotSupportedArchive { // Reset stream position if _, seekErr := inStream.Seek(0, io.SeekStart); seekErr != nil { return seekErr } // Try with signature detection archive, err = lib.OpenArchive(inStream, true) if err != nil { return err } } ``` -------------------------------- ### Free Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/api-reference/lib.md Releases all resources associated with the Lib instance. This must be called to properly clean up C allocations. It is safe to call Free() multiple times. ```APIDOC ## Free ### Description Releases all resources associated with the Lib instance. This must be called to properly clean up C allocations. It is safe to call Free() multiple times. ### Method `(l *Lib) Free()` ### Parameters - `l` (*Lib) - (receiver) ### Returns None ### Example ```go lib, err := sz.NewLib() if err != nil { log.Fatal(err) } def lib.Free() // Ensure cleanup happens // Use lib... ``` ``` -------------------------------- ### SetExt Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/api-reference/instream.md Updates the file extension hint for the stream. This is useful when you need to change the format detection hint after stream creation. ```APIDOC ## SetExt ### Description Updates the file extension hint for the stream. This is useful when you need to change the format detection hint after stream creation. ### Method func (in *InStream) SetExt(ext string) ### Parameters #### Path Parameters - **ext** (string) - Required - New file extension hint ### Request Example ```go inStream, err := sz.NewInStream(reader, "bin", size) if err != nil { log.Fatal(err) } defer inStream.Free() // Later, update extension hint inStream.SetExt("7z") ``` ``` -------------------------------- ### Analyze Archive Access Patterns Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/api-reference/readstats.md After enabling ReadStats, analyze the collected read operations to understand archive access patterns. This includes calculating total reads, total bytes read, and average read size, as well as listing individual read operations. ```go inStream.Stats = &sz.ReadStats{} // Extract archive... archive.ExtractSeveral(indices, ec) // Analyze read patterns totalReads := len(inStream.Stats.Reads) var totalBytes int64 for _, op := range inStream.Stats.Reads { totalBytes += op.Size } avgReadSize := totalBytes / int64(totalReads) fmt.Printf("Total reads: %d\n", totalReads) fmt.Printf("Total bytes read: %d\n", totalBytes) fmt.Printf("Average read size: %d\n", avgReadSize) // Check for sequential vs random access fmt.Println("\nRead pattern:") for _, op := range inStream.Stats.Reads { fmt.Printf(" Offset: %10d, Size: %8d\n", op.Offset, op.Size) } ``` -------------------------------- ### Detect Sequential vs Random Access Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/api-reference/readstats.md Implement a function to analyze ReadStats and determine if archive access was sequential. It checks if each read operation's offset follows the previous operation's offset plus size, printing a message if non-sequential access is detected. ```go func analyzeAccessPattern(stats *sz.ReadStats) { if len(stats.Reads) == 0 { return } sequential := true for i := 1; i < len(stats.Reads); i++ { prevOp := stats.Reads[i-1] currOp := stats.Reads[i] expectedOffset := prevOp.Offset + prevOp.Size if currOp.Offset != expectedOffset { sequential = false fmt.Printf("Non-sequential: expected offset %d, got %d\n", expectedOffset, currOp.Offset) } } if sequential { fmt.Println("Archive accessed sequentially") } } ``` -------------------------------- ### Archive Interface Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/README.md Documentation for the opened archive interface, allowing retrieval of archive information and extraction of items. ```APIDOC ## Archive Interface ### Description Provides an interface to an opened 7-zip archive, enabling access to archive details and extraction of its contents. ### Methods - `GetArchiveFormat()`: Retrieves the format of the archive. - `GetItemCount()`: Returns the total number of items (files/directories) in the archive. - `GetItem(index int)`: Retrieves a specific item from the archive by its index. - `Extract(destPath string, itemIndices []int, callback ExtractCallback)`: Extracts specified items to a destination path with a callback for progress. - `ExtractSeveral(destPath string, itemIndices []int, callback ExtractCallback)`: Similar to `Extract`, for extracting multiple items. ``` -------------------------------- ### Release InStream Resources with Free Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/api-reference/instream.md Call Free to release all resources associated with an InStream, ensuring proper cleanup of C allocations. It is safe to call multiple times. ```go inStream, err := sz.NewInStream(reader, "zip", size) if err != nil { log.Fatal(err) } defer inStream.Free() // Use inStream... ``` -------------------------------- ### Exported Functions Source: https://github.com/itchio/sevenzip-go/blob/master/_autodocs/SUMMARY.txt Top-level functions available for initializing library components and recording read operations. ```APIDOC ## Exported Functions ### Description Top-level functions for initializing library components and recording read operations. ### Functions - **NewLib()**: Initialize library - **NewInStream(path string)**: Create input stream - **NewOutStream()**: Create output stream - **NewExtractCallback()**: Create extraction callback - **RecordRead(bytesRead int)**: Record read operation ```