erofs

package module
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Apr 17, 2026 License: Apache-2.0 Imports: 20 Imported by: 1

README

go-erofs

A Go library for reading and creating EROFS filesystem images using the standard fs.FS interface.

Features

  • Read EROFS images through Go's fs.FS interface
  • Create EROFS images from directories or any fs.FS
  • Merge multiple filesystem sources with overlay whiteout support
  • Metadata-only mode for container layer indexing (chunk-based references to original data)
  • Pure Go, no CGO — uses only the standard library
Status
  • Read erofs files created with default mkfs.erofs options
  • Read chunk-based erofs files with indexes
  • Xattr support including long xattr prefixes
  • Extra devices for chunked data
  • Create erofs files from any fs.FS
  • Directory to erofs packing
  • AUFS whiteout to overlayfs conversion
  • Merge multiple filesystem layers with whiteout processing
  • Read erofs files with compression

Reading an EROFS image

f, err := os.Open("image.erofs")
if err != nil {
    log.Fatal(err)
}
defer f.Close()

img, err := erofs.Open(f)
if err != nil {
    log.Fatal(err)
}

fs.WalkDir(img, ".", func(path string, d fs.DirEntry, err error) error {
    fmt.Println(path)
    return nil
})

Merging multiple layers

Combine multiple filesystem sources into one image. The Merge option enables overlay semantics — AUFS-style whiteout files (.wh.<name>) delete entries from prior layers:

outFile, _ := os.Create("merged.erofs")
w := erofs.Create(outFile)

w.CopyFrom(baseLayer)
w.CopyFrom(overlayLayer, erofs.Merge())
w.Close()

Merge can also be combined with MetadataOnly to build a merged index without copying data:

w := erofs.Create(outFile)
w.CopyFrom(layer1, erofs.MetadataOnly())
w.CopyFrom(layer2, erofs.MetadataOnly(), erofs.Merge())
w.Close()

Building an image programmatically

outFile, _ := os.Create("image.erofs")
w := erofs.Create(outFile)

f, _ := w.Create("/hello.txt")
f.Write([]byte("hello world\n"))
f.Close()

w.Mkdir("/dir", 0o755)
w.Symlink("hello.txt", "/link")

w.Close()
outFile.Close()

Documentation

Overview

Package erofs reads and creates EROFS filesystem images.

Reading

Use Open to read an existing EROFS image through Go's standard fs.FS interface:

img, err := erofs.Open(f)
data, err := fs.ReadFile(img, "etc/hostname")

Writing

Use Create to build a new EROFS image. Entries can be added one at a time, or bulk-copied from any fs.FS via Writer.CopyFrom:

w := erofs.Create(outFile)
w.CopyFrom(srcFS)
w.Close()

For metadata-only images that reference data in an external source (e.g. for container layer indexing), pass MetadataOnly to CopyFrom:

w := erofs.Create(outFile)
w.CopyFrom(srcFS, erofs.MetadataOnly())
w.Close()

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrInvalid occurs when an invalid value is detected in the erofs data.
	// Whether this invalid data is the result of corruption or bad input
	// is up to the caller to decide.
	// This error may be wrapped with more details.
	ErrInvalid = fs.ErrInvalid

	// ErrInvalidSuperblock occurs when the super block could not be validated
	// when initially loading the erofs input. Unlike other corruption cases,
	// invalid super block should be returned immediately
	ErrInvalidSuperblock = fmt.Errorf("invalid super block: %w", ErrInvalid)

	// ErrNotImplemented is returned when a feature is known but not implemented
	// yet by this library
	ErrNotImplemented = errors.New("not implemented")

	// ErrNotDirectory is returned when a path component is not a directory.
	ErrNotDirectory = errors.New("not a directory")

	// ErrIsDirectory is returned when an operation expected a file but found
	// a directory.
	ErrIsDirectory = errors.New("is a directory")

	// ErrLoop is returned when too many symlinks are encountered during
	// path resolution.
	ErrLoop = fmt.Errorf("too many symlinks: %w", ErrInvalid)
)

Errors

Functions

func EroFS deprecated

func EroFS(r io.ReaderAt, opts ...Opt) (fs.FS, error)

Deprecated: Use Open instead, will be removed in 0.3

func Open added in v0.2.0

func Open(r io.ReaderAt, opts ...OpenOpt) (fs.FS, error)

Open returns a FileSystem reading from the given ReaderAt. The ReaderAt must be a valid EROFS block file. No additional memory mapping is done and must be handled by the caller.

Example
package main

import (
	"fmt"
	"io/fs"
	"log"
	"os"

	erofs "github.com/erofs/go-erofs"
)

func main() {
	f, err := os.Open("testdata/basic-default.erofs")
	if err != nil {
		log.Fatal(err)
	}

	img, err := erofs.Open(f)
	if err != nil {
		_ = f.Close()
		log.Fatal(err)
	}
	defer func() { _ = f.Close() }()

	_ = fs.WalkDir(img, ".", func(path string, d fs.DirEntry, err error) error {
		if err != nil {
			return err
		}
		fmt.Println(path)
		return nil
	})
}

Types

type CopyOpt added in v0.3.0

type CopyOpt func(*Writer)

CopyOpt configures a CopyFrom operation.

func Merge added in v0.3.0

func Merge() CopyOpt

Merge enables overlay merge semantics for the current CopyFrom. AUFS-style whiteout files (.wh.<name>) delete the named entry from prior layers, and opaque markers (.wh..wh..opq) delete all children of their parent directory. The whiteout entries themselves are not added to the image.

When using Merge with a source containing AUFS whiteout files, do not pre-convert them; the Writer processes raw whiteout entries directly.

func MetadataOnly added in v0.3.0

func MetadataOnly() CopyOpt

MetadataOnly configures the current CopyFrom to emit only metadata. Regular files with pre-existing chunk mappings use chunk-based layout referencing an external device; file data is not copied.

type CreateOpt added in v0.3.0

type CreateOpt func(*createOptions)

CreateOpt configures EROFS image creation.

func WithBuildTime added in v0.3.0

func WithBuildTime(sec uint64, nsec uint32) CreateOpt

WithBuildTime sets the filesystem build timestamp.

func WithDataFile added in v0.3.0

func WithDataFile(f *os.File) CreateOpt

WithDataFile sets an external data file for metadata-only mode. File.Write appends to this file at block-aligned offsets; chunk indexes reference those blocks with DeviceID=1.

func WithTempDir added in v0.3.0

func WithTempDir(dir string) CreateOpt

WithTempDir overrides the temp directory for the spool file. Only used when no data file is provided.

type File added in v0.3.0

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

File is a writable regular file returned by Writer.Create. Data is written via Write or ReadFrom, then committed with Close.

func (*File) Chmod added in v0.3.0

func (f *File) Chmod(mode fs.FileMode) error

Chmod sets permission bits on the file, matching os.File.Chmod.

func (*File) Chown added in v0.3.0

func (f *File) Chown(uid, gid int) error

Chown sets the owner UID and GID on the file, matching os.File.Chown.

func (*File) Close added in v0.3.0

func (f *File) Close() error

Close commits the file entry. For data file mode, pads to block boundary and records chunk indexes.

func (*File) ReadFrom added in v0.3.0

func (f *File) ReadFrom(r io.Reader) (int64, error)

ReadFrom implements io.ReaderFrom, allowing io.Copy(f, src) to use a shared buffer instead of allocating a new 32KB buffer per call.

func (*File) Write added in v0.3.0

func (f *File) Write(p []byte) (int, error)

Write appends data to the file.

type OpenOpt added in v0.2.0

type OpenOpt func(*options)

OpenOpt is an option for configuring the EROFS reader

func WithExtraDevices

func WithExtraDevices(devices ...io.ReaderAt) OpenOpt

WithExtraDevices specifies additional devices to read chunk data from

type Opt deprecated

type Opt = OpenOpt

Deprecated: Use OpenOpt instead, will be removed in 0.3

type Stat

type Stat struct {
	Mode        fs.FileMode
	Size        int64
	InodeLayout uint8
	Rdev        uint32
	Ino         int64
	UID         uint32
	GID         uint32
	Mtime       uint64
	MtimeNs     uint32
	Nlink       int
	Xattrs      map[string]string
}

Stat is the raw erofs stat data returned by Sys() on fs.FileInfo values. It is a plain data struct analogous to syscall.Stat_t.

For cross-platform fs.FS compatibility, callers should prefer type-asserting the fs.FileInfo to accessor interfaces rather than inspecting Stat fields directly. The returned fs.FileInfo implements the following single-method interfaces:

Ownership:  UID() uint32, GID() uint32
InodeInfo:  Ino() uint64, Nlink() uint64
DeviceInfo: Rdev() uint64
Xattrs:     GetAllXattr() map[string]string, GetXattr(string) (string, bool)

type Writer added in v0.3.0

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

Writer is a writable filesystem that produces an EROFS image on Close. Files are added via Create, Mkdir, Symlink, and Mknod, then finalized by calling Close which serializes the complete EROFS image.

func Create added in v0.3.0

func Create(out io.WriteSeeker, opts ...CreateOpt) *Writer

Create returns a Writer that produces an EROFS image on Close. Options configure build time, data file, and temp directory.

Example
var buf testBuffer
w := erofs.Create(&buf)

f, err := w.Create("/hello.txt")
if err != nil {
	log.Fatal(err)
}
if _, err := f.Write([]byte("hello world\n")); err != nil {
	log.Fatal(err)
}
if err := f.Close(); err != nil {
	log.Fatal(err)
}

if err := w.Mkdir("/dir", 0o755); err != nil {
	log.Fatal(err)
}

if err := w.Close(); err != nil {
	log.Fatal(err)
}

// Read back
img, err := erofs.Open(bytes.NewReader(buf.Bytes()))
if err != nil {
	log.Fatal(err)
}

data, err := fs.ReadFile(img, "hello.txt")
if err != nil {
	log.Fatal(err)
}
fmt.Print(string(data))
Output:
hello world

func (*Writer) Chmod added in v0.3.0

func (fsys *Writer) Chmod(name string, mode fs.FileMode) error

Chmod sets permission bits on the named path, preserving type bits.

func (*Writer) Chown added in v0.3.0

func (fsys *Writer) Chown(name string, uid, gid int) error

Chown sets the owner UID and GID on the named path.

func (*Writer) Chtimes added in v0.3.0

func (fsys *Writer) Chtimes(name string, atime time.Time, mtime time.Time) error

Chtimes sets the access and modification times on the named path. EROFS only stores mtime; atime is retained for read-back before Close.

func (*Writer) Close added in v0.3.0

func (fsys *Writer) Close() error

Close writes the EROFS image. The FS must not be used after Close.

func (*Writer) CopyFrom added in v0.3.0

func (fsys *Writer) CopyFrom(src fs.FS, opts ...CopyOpt) error

CopyFrom walks an fs.FS and adds all entries. Opens files for data when Entry.Data is nil. Reads symlink targets via readLinker interface when Entry.LinkTarget is empty. If src implements blockSizer, the image block size is set accordingly.

func (*Writer) Create added in v0.3.0

func (fsys *Writer) Create(name string) (*File, error)

Create creates a regular file with default mode 0644. The caller must Close the returned File.

func (*Writer) Mkdir added in v0.3.0

func (fsys *Writer) Mkdir(name string, perm fs.FileMode) error

Mkdir creates a directory. Only permission bits from perm are used; type bits are forced to directory. Mkdir("/", perm) sets root permissions.

func (*Writer) Mknod added in v0.3.0

func (fsys *Writer) Mknod(name string, mode uint16, rdev uint32) error

Mknod creates a device, FIFO, or socket. mode must include type bits (e.g. disk.StatTypeChrdev | 0o666).

func (*Writer) Open added in v0.3.0

func (fsys *Writer) Open(name string) (fs.File, error)

Open opens the named file for reading. For regular files, the file must have been closed (data finalized) before it can be opened for reading. For directories, the returned file implements fs.ReadDirFile.

func (fsys *Writer) SetNlink(name string, nlink uint32) error

SetNlink overrides the computed link count on the named path.

func (*Writer) Setxattr added in v0.3.0

func (fsys *Writer) Setxattr(name, attr, value string) error

Setxattr sets an extended attribute on the named path.

func (*Writer) Stat added in v0.3.0

func (fsys *Writer) Stat(name string) (fs.FileInfo, error)

Stat returns file info for the named path. The name is cleaned the same way as other Writer methods (leading slash, no trailing slash).

func (fsys *Writer) Symlink(oldname, newname string) error

Symlink creates newname as a symbolic link to oldname (mode 0777).

Directories

Path Synopsis
cmd
erofs-cli command
internal
builder
Package builder provides shared types for the mkfs sub-packages.
Package builder provides shared types for the mkfs sub-packages.

Jump to

Keyboard shortcuts

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