asar

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Sep 29, 2026 License: MIT Imports: 15 Imported by: 0

README

asar

Go Reference Go Report Card MIT License discord

Read and write Go library for Electron ASAR archives.

An ASAR file is an 8-byte Chromium pickle, a JSON index pickle, and concatenated uncompressed file bytes. Open returns io.SectionReader values over packed files. Pack and WriteArchive build the same layout, including shared offsets for identical contents and SHA-256 integrity blocks. Hashes are not verified on read.

Unpacked entries (unpacked: true) live in a sibling {archive}.unpacked directory. The reader records the flag; callers copy those files themselves.

Integration tests pack archives with @electron/asar 4.3.0 and read them back:

npm ci --prefix integration
go test -tags integration -race ./...
package main

import (
	"fmt"
	"io"
	"os"

	"golift.io/asar"
)

func main() {
	reader, err := asar.Open("app.asar")
	if err != nil {
		panic(err)
	}
	defer reader.Close()

	for _, file := range reader.Files {
		if !file.Packed() {
			continue
		}

		src, err := file.Open()
		if err != nil {
			panic(err)
		}

		fmt.Println(file.Name, file.Size)
		_, _ = io.Copy(os.Stdout, src)
	}
}

Documentation

Overview

Package asar reads and writes Electron ASAR archives.

An ASAR file is an 8-byte size pickle, a JSON index pickle, and concatenated uncompressed file bytes. Offsets in the index are relative to the start of those bytes. Files with identical contents may share one offset. Entries marked unpacked live in a sibling directory named {archive}.unpacked. Integrity hashes are stored by the writer and parsed, not verified, by the reader.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrInvalidHeader is returned when the pickle header or JSON index is malformed.
	ErrInvalidHeader = errors.New("invalid asar header")
	// ErrTruncated is returned when the archive ends before the header or a file payload.
	ErrTruncated = errors.New("truncated asar archive")
	// ErrNotPacked is returned when File.Open is called on a directory, symlink, or unpacked entry.
	ErrNotPacked = errors.New("asar entry is not packed file data")
	// ErrHeaderTooLarge is returned when the header pickle exceeds maxHeaderPickle.
	ErrHeaderTooLarge = errors.New("asar header exceeds maximum size")
	// ErrLinkOutside is returned when a symlink target leaves the archive root.
	ErrLinkOutside = errors.New("asar symlink points outside the archive")
	// ErrFileTooLarge is returned when a packed file is larger than an ASAR entry allows.
	ErrFileTooLarge = errors.New("asar file exceeds maximum size")
	// ErrOutputInside is returned when the archive path is inside the source tree.
	ErrOutputInside = errors.New("asar output is inside the source tree")
)

Package-level errors returned while reading or writing an ASAR archive.

Functions

func Pack

func Pack(dest, src string, opts Options) error

Pack writes the directory src to dest as an ASAR archive. Symlinks become package-relative links and must stay inside src. Unpacked files are copied to dest+".unpacked". dest must not be inside src. A symlink to a directory is packed as that directory. A previous archive is replaced only after the new archive and sibling tree have both been installed.

func WriteArchive

func WriteArchive(writer io.Writer, entries []Entry) error

WriteArchive writes an ASAR image of entries to w. Identical packed contents are stored once. Unpacked entries are only recorded in the header; the caller supplies any sibling files.

Types

type Entry

type Entry struct {
	Name       string
	Data       []byte
	Link       string
	Dir        bool
	Executable bool
	Unpacked   bool
}

Entry is one file, directory, or symlink written into a new archive. Name is a slash-separated path with no leading slash. A non-empty Link makes the entry a symlink and Data is ignored. Dir writes a directory node. Unpacked entries are omitted from the archive body.

type File

type File struct {
	Name       string
	Offset     int64 // Absolute archive offset of packed data. Zero when Unpacked, a directory, or a link.
	Size       int64
	Executable bool
	Unpacked   bool
	Link       string // Package-relative symlink target when this entry is a link.
	Integrity  *Integrity
	// contains filtered or unexported fields
}

File is one directory, symlink, packed file, or unpacked file in the index. Directories are listed before their children. Name uses forward slashes and has no leading slash.

func (*File) IsDir

func (f *File) IsDir() bool

IsDir reports whether f is a directory node.

func (f *File) IsLink() bool

IsLink reports whether f is a symlink.

func (*File) Open

func (f *File) Open() (*io.SectionReader, error)

Open returns a SectionReader over the packed bytes. Directories, symlinks, and unpacked entries return ErrNotPacked.

func (*File) Packed

func (f *File) Packed() bool

Packed reports whether f is stored in the archive body.

type Integrity

type Integrity struct {
	Algorithm string   `json:"algorithm"`
	Hash      string   `json:"hash"`
	BlockSize int      `json:"blockSize"`
	Blocks    []string `json:"blocks"`
}

Integrity is the optional SHA-256 checksum Electron stores on a file entry.

type Options

type Options struct {
	// Unpack reports whether a slash-separated path should be copied to
	// dest+".unpacked" instead of the archive body. Children of an unpacked
	// directory are unpacked too.
	Unpack func(name string) bool
}

Options controls Pack. The zero value packs every regular file.

type Reader

type Reader struct {
	Files      []*File
	HeaderSize int64 // Length of the header pickle, not including the 8-byte size pickle.
	DataOffset int64 // Absolute offset of the first packed byte (8 + HeaderSize).
	// contains filtered or unexported fields
}

Reader is a parsed ASAR archive. Files is the depth-first index.

func NewReader

func NewReader(reader io.ReaderAt, size int64) (*Reader, error)

NewReader parses an ASAR image from reader, which must cover size bytes.

func Open

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

Open opens path as an ASAR archive. The caller must Close the Reader.

func (*Reader) Close

func (r *Reader) Close() error

Close closes the file opened by Open. It is a no-op for Readers from NewReader.

Jump to

Keyboard shortcuts

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