rardecode

repository·main·Indexed 40 days ago

https://github.com/nwaples/rardecode

A Go library for decoding RAR archives, supporting versions 1.5 and 5.0, multi-volume archives, and encrypted volumes. It provides a RarFS implementation of the standard io/fs.FS interface for programmatic access to archive contents, as well as a Reader for sequential access.

Tokens
2.8K
Snippets
12
Records
16
Agent score
50%

What's inside rardecode

  1. Use FileSystem for custom volume access

    main

    By default, rardecode uses the standard OS filesystem. You can provide a custom fs.FS implementation using the FileSystem option. This is useful if your RAR volumes are stored in memory, in a cloud bucket, or within a virtual filesystem.

    Note: The provided fs.FS must be able to resolve the paths constructed by the volumeManager (which combines the directory and the volume filename).

    // Example using a custom filesystem
    myFS := myCustomFSImplementation{}
    opts := []rardecode.Option{
        rardecode.FileSystem(myFS),
    }
  2. Configure rardecode with Options

    main

    The rardecode package uses a functional options pattern to configure archive extraction settings. You can pass multiple Option functions to the archive opening functions to customize behavior such as buffer size, dictionary size, file size limits, filesystem access, and passwords.

    Available options:

    • BufferSize(size int): Sets the size of the bufio.Reader used during reading.
    • MaxDictionarySize(size int64): Sets the maximum dictionary size in bytes. Defaults to DefaultMaxDictionarySize (4GB). Sizes above 64GB are ignored; sizes below 256kB prevent decoding.
    • MaxReadFileSize(size int64): Sets the maximum file size allowed for RarFS.ReadFile(). Setting this to <= 0 ignores file size limits. Defaults to DefaultMaxReadFileSize (4GB).
    • FileSystem(fs fs.FS): Sets the fs.FS implementation used to open archive volumes.
    • Password(pass string): Sets the password for decrypting encrypted volumes.
    • SkipCheck(): Disables checksum verification for archive files.
    • OpenFSCheck(): Flags archive files to be checked during Open or List operations.
    import "github.com/nwaples/nwaples/rardecode"
    
    // Example of configuring options
    opts := []rardecode.Option{
        rardecode.Password("my-secret-password"),
        rardecode.MaxDictionarySize(1 << 30), // 1GB
        rardecode.SkipCheck(),
        rardecode.BufferSize(64 * 1024),
    }
  3. Handle ErrFileTooLargeForReadFile

    main

    When using RarFS.ReadFile(name), the library enforces a maximum file size to prevent excessive memory consumption. If the file being read is larger than the configured limit, the method returns ErrFileTooLargeForReadFile.

    To increase this limit, you must configure the MaxReadFileSize() option when calling OpenFS.

    var ErrFileTooLargeForReadFile = errors.New("rardecode: file too large for ReadFile")
  4. Access file contents with File.Open()

    main

    For non-solid files, you can call Open() on a File object (obtained via List) to get an io.ReadCloser for the file's contents.

    Warning: Open() is not supported for Solid files because their contents depend on the decoding of preceding files. To access contents of Solid files, use OpenReader and iterate using Next().

    files, _ := rardecode.List("archive.rar")
    for _, f := range files {
        if !f.Solid {
            rc, err := f.Open()
            if err != nil {
                // handle error
            }
            // Read from rc...
            rc.Close()
        }
    }
  5. List files in a RAR archive

    main

    Use List to retrieve a slice of *File objects representing all files within a RAR archive specified by name. This is useful for inspecting archive contents without manually iterating through the reader.

    files, err := rardecode.List("archive.rar")
    if err != nil {
        // handle error
    }
    for _, f := range files {
        fmt.Println(f.Name)
    }
  6. Create a Reader for single-volume RAR archives

    main

    Use NewReader to create a Reader for sequential access to files in a single-volume RAR archive. Note that NewReader does not support multi-volume archives; for multi-volume support, use OpenReader instead.

    // r is an io.Reader containing the RAR archive data
    rdr, err := rardecode.NewReader(r)
    if err != nil {
        // handle error
    }
    // Use rdr.Next() to iterate through files
  7. Open a RAR archive by filename with OpenReader

    main

    Use OpenReader to open a RAR archive specified by its name. This returns a ReadCloser, which supports multi-volume archives and allows you to close the underlying resources. Use the Volumes() method on the returned ReadCloser to see which volume filenames have been used during decoding.

    // name is the path to the RAR file
    rc, err := rardecode.OpenReader("archive.rar")
    if err != nil {
        // handle error
    }
    defer rc.Close()
    
    // Access volumes used so far
    volumes := rc.Volumes()
  8. Create a sub-filesystem with Sub

    main

    The Sub(dir string) (fs.FS, error) method returns a new fs.FS that is rooted at the specified directory. This is useful for scoping operations to a specific subdirectory within the RAR archive.

    subFS, err := rfs.Sub("folder/subfolder")
    if err != nil {
        log.Fatal(err)
    }
    // subFS is now rooted at "folder/subfolder"
  9. Open a RAR archive as a filesystem with OpenFS

    main

    Use OpenFS to create a RarFS instance, which implements the standard Go io/fs.FS interface. This allows you to interact with the contents of a RAR archive using standard library filesystem functions. You can pass optional Option arguments to configure the opening process.

    Returns a pointer to RarFS or an error if the archive cannot be opened or parsed.

    fs, err := rardecode.OpenFS("archive.rar")
    if err != nil {
        log.Fatal(err)
    }
    // Use fs as a standard io/fs.FS
  10. Read files from a RAR archive using RarFS

    main

    The RarFS type provides several methods to interact with the archive contents:

    • Open(name string) (fs.File, error): Opens a file within the archive for reading. Returns a standard fs.File.
    • ReadFile(name string) ([]byte, error): A convenience method to read the entire content of a file into a byte slice.
      • Note: The maximum file size allowed for ReadFile is controlled by the MaxReadFileSize() option. If a file exceeds this limit, it returns ErrFileTooLargeForReadFile.
    • Stat(name string) (fs.FileInfo, error): Returns metadata about the file (size, mode, modification time, etc.).
    • ReadDir(name string) ([]fs.DirEntry, error): Returns a list of directory entries within the specified directory, sorted by filename.
    // Open and read a file
    file, err := rfs.Open("path/to/file.txt")
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close()
    
    // Or use the convenience ReadFile method
    content, err := rfs.ReadFile("path/to/file.txt")
  11. Reference: HostOS and LinkType constants

    main

    The following constants define the Host Operating System and Link Types used in FileHeader.

    // HostOS types
    const (
    	HostOSUnknown = 0
    	HostOSMSDOS   = 1
    	HostOSOS2     = 2
    	HostOSWindows = 3
    	HostOSUnix    = 4
    	HostOSMacOS   = 5
    	HostOSBeOS    = 6
    )
    
    // Link types
    const (
    	LinkTypeNone            = 0
    	LinkTypeUnixSymlink     = 1
    	LinkTypeWindowsSymlink  = 2
    	LinkTypeWindowsJunction = 3
    	LinkTypeHardLink        = 4
    	LinkTypeFileCopy        = 5
    )