zarchive

package module
v0.0.0-...-b108004 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 14, 2026 License: MIT-0 Imports: 10 Imported by: 0

README

zarchive-go

Pure Go implementation of ZArchive - a file archive format with random-access reads and zstd compression.

Originally created for Wii U game dumps (.wua files), ZArchive is a general-purpose archive format optimized for random access.

Features

  • Random-access reads within stored files
  • zstd compression (64KiB blocks)
  • Case-insensitive path lookup (Windows-1252 encoding)
  • Big-endian format (platform independent)
  • SHA256 integrity verification
  • Scales to multiple terabytes with millions of files

Installation

go get github.com/Xpl0itU/zarchive-go

Usage

Writing Archives
package main

import (
    "os"
    zarchive "github.com/Xpl0itU/zarchive-go"
)

func main() {
    f, _ := os.Create("archive.zar")
    defer f.Close()

    writer, _ := zarchive.NewSimpleWriter(f)
    defer writer.Close()

    writer.MakeDir("documents", false)
    writer.StartNewFile("documents/readme.txt")
    writer.AppendData([]byte("Hello, ZArchive!"))

    writer.MakeDir("data/nested", true)
    writer.StartNewFile("data/nested/file.txt")
    writer.AppendData([]byte("Nested content"))

    writer.Finalize()
}
Reading Archives
package main

import (
    "fmt"
    zarchive "github.com/Xpl0itU/zarchive-go"
)

func main() {
    reader, _ := zarchive.OpenFromFile("archive.zar")
    defer reader.Close()

    fileHandle := reader.LookUp("documents/readme.txt", true, false)
    if fileHandle != zarchive.InvalidNode {
        size := reader.GetFileSize(fileHandle)
        buf := make([]byte, size)
        n, _ := reader.ReadFromFile(fileHandle, 0, size, buf)
        fmt.Printf("Content: %s\n", buf[:n])
    }
}

Wii U Archives (.wua)

ZArchive was originally designed for Wii U game dumps. To create .wua files:

  1. Place each title in a subfolder: {titleId}_v{version} (e.g., 0005000e10102000_v32)
  2. Use .wua extension instead of .zar
writer.MakeDir("0005000e10102000_v32", false)
writer.StartNewFile("0005000e10102000_v32/code/app.rpx")
// ... add game files

API

Writer
  • NewSimpleWriter(w io.Writer) (*Writer, error) - Create writer
  • MakeDir(path string, recursive bool) error - Create directory
  • StartNewFile(path string) error - Start new file
  • AppendData(data []byte) error - Append data to current file
  • Finalize() error - Finalize archive
  • Close() error - Close writer
Reader
  • OpenFromFile(path string) (*Reader, error) - Open from file
  • OpenFromStream(stream io.ReadSeeker) (*Reader, error) - Open from stream
  • LookUp(path string, allowFile, allowDirectory bool) uint32 - Lookup node
  • IsFile(nodeHandle uint32) bool - Check if node is file
  • IsDirectory(nodeHandle uint32) bool - Check if node is directory
  • GetFileSize(nodeHandle uint32) uint64 - Get file size
  • ReadFromFile(nodeHandle uint32, offset, length uint64, buffer []byte) (uint64, error) - Read file data
  • GetDirEntryCount(nodeHandle uint32) uint32 - Get directory entry count
  • GetDirEntry(nodeHandle uint32, index uint32) (DirEntry, bool) - Get directory entry
  • VerifyIntegrity() error - Verify SHA256 integrity
  • Close() error - Close reader

Testing

go test -v

Format Compatibility

Fully compatible with original C++ ZArchive implementation. Archives created with Go can be read by C++ version and vice versa.

License

MIT No Attribution (same as original ZArchive)

Documentation

Index

Constants

View Source
const (
	CompressedBlockSize           = 64 * 1024
	EntriesPerOffsetRecord        = 16
	FooterMagic            uint32 = 0x169f52d6
	FooterVersion          uint32 = 0x61bf3a01
)
View Source
const InvalidNode uint32 = 0xFFFFFFFF

Variables

This section is empty.

Functions

func CompareNodeName

func CompareNodeName(n1, n2 string) int

func CompareNodeNameBool

func CompareNodeNameBool(n1, n2 string) bool

func GetName

func GetName(nameTable []byte, offset uint32) string

func GetNextPathNode

func GetNextPathNode(path string) (node string, remaining string, ok bool)

func SplitFilenameFromPath

func SplitFilenameFromPath(path string) (dir string, filename string)

func WriteCompressionOffsetRecord

func WriteCompressionOffsetRecord(rec CompressionOffsetRecord) []byte

func WriteFileDirectoryEntry

func WriteFileDirectoryEntry(entry FileDirectoryEntry) []byte

func WriteFooter

func WriteFooter(footer Footer) []byte

Types

type CompressionOffsetRecord

type CompressionOffsetRecord struct {
	BaseOffset uint64
	Size       [EntriesPerOffsetRecord]uint16
}

func ReadCompressionOffsetRecord

func ReadCompressionOffsetRecord(data []byte) CompressionOffsetRecord

type DirEntry

type DirEntry struct {
	Name        string
	IsFile      bool
	IsDirectory bool
	Size        uint64
}

type FileDirectoryEntry

type FileDirectoryEntry struct {
	NameOffsetAndTypeFlag uint32
	FileOffsetLow         uint32
	FileSizeLow           uint32
	FileOffsetAndSizeHigh uint32
}

func ReadFileDirectoryEntry

func ReadFileDirectoryEntry(data []byte) FileDirectoryEntry

func (*FileDirectoryEntry) GetDirCount

func (e *FileDirectoryEntry) GetDirCount() uint32

func (*FileDirectoryEntry) GetDirStartIndex

func (e *FileDirectoryEntry) GetDirStartIndex() uint32

func (*FileDirectoryEntry) GetFileOffset

func (e *FileDirectoryEntry) GetFileOffset() uint64

func (*FileDirectoryEntry) GetFileSize

func (e *FileDirectoryEntry) GetFileSize() uint64

func (*FileDirectoryEntry) GetNameOffset

func (e *FileDirectoryEntry) GetNameOffset() uint32

func (*FileDirectoryEntry) IsFile

func (e *FileDirectoryEntry) IsFile() bool

func (*FileDirectoryEntry) SetDirCount

func (e *FileDirectoryEntry) SetDirCount(count uint32)

func (*FileDirectoryEntry) SetDirStartIndex

func (e *FileDirectoryEntry) SetDirStartIndex(idx uint32)

func (*FileDirectoryEntry) SetFileOffset

func (e *FileDirectoryEntry) SetFileOffset(offset uint64)

func (*FileDirectoryEntry) SetFileSize

func (e *FileDirectoryEntry) SetFileSize(size uint64)

func (*FileDirectoryEntry) SetTypeAndNameOffset

func (e *FileDirectoryEntry) SetTypeAndNameOffset(isFile bool, nameOffset uint32)
type Footer struct {
	SectionCompressedData OffsetInfo
	SectionOffsetRecords  OffsetInfo
	SectionNames          OffsetInfo
	SectionFileTree       OffsetInfo
	SectionMetaDirectory  OffsetInfo
	SectionMetaData       OffsetInfo
	IntegrityHash         [32]byte
	TotalSize             uint64
	Version               uint32
	Magic                 uint32
}

func ReadFooter

func ReadFooter(data []byte) Footer

type OffsetInfo

type OffsetInfo struct {
	Offset uint64
	Size   uint64
}

func (*OffsetInfo) IsWithinValidRange

func (o *OffsetInfo) IsWithinValidRange(fileSize uint64) bool

type PathNode

type PathNode struct {
	// contains filtered or unexported fields
}

type Reader

type Reader struct {
	// contains filtered or unexported fields
}

func OpenFromFile

func OpenFromFile(path string) (*Reader, error)

func OpenFromStream

func OpenFromStream(stream io.ReadSeeker) (*Reader, error)

func (*Reader) Close

func (r *Reader) Close() error

func (*Reader) GetDirEntry

func (r *Reader) GetDirEntry(nodeHandle uint32, index uint32) (DirEntry, bool)

func (*Reader) GetDirEntryCount

func (r *Reader) GetDirEntryCount(nodeHandle uint32) uint32

func (*Reader) GetFileSize

func (r *Reader) GetFileSize(nodeHandle uint32) uint64

func (*Reader) IsDirectory

func (r *Reader) IsDirectory(nodeHandle uint32) bool

func (*Reader) IsFile

func (r *Reader) IsFile(nodeHandle uint32) bool

func (*Reader) LookUp

func (r *Reader) LookUp(path string, allowFile, allowDirectory bool) uint32

func (*Reader) ReadFromFile

func (r *Reader) ReadFromFile(nodeHandle uint32, offset uint64, length uint64, buffer []byte) (uint64, error)

func (*Reader) VerifyIntegrity

func (r *Reader) VerifyIntegrity() error

type SimpleWriter

type SimpleWriter struct {
	// contains filtered or unexported fields
}

type Writer

type Writer struct {
	// contains filtered or unexported fields
}

func NewSimpleWriter

func NewSimpleWriter(w io.Writer) (*Writer, error)

func NewWriter

func NewWriter(cbNewOutputFile func(partIndex int32), cbWriteOutputData func(data []byte)) (*Writer, error)

func (*Writer) AppendData

func (w *Writer) AppendData(data []byte) error

func (*Writer) Close

func (w *Writer) Close() error

func (*Writer) Finalize

func (w *Writer) Finalize() error

func (*Writer) MakeDir

func (w *Writer) MakeDir(path string, recursive bool) error

func (*Writer) StartNewFile

func (w *Writer) StartNewFile(path string) error

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL