Help us shape the future of Go! Take the 2026 Go Developer Survey

vfs

package module
v1.4.6 Latest Latest
Warning

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

Go to latest
Published: Oct 22, 2026 License: MPL-2.0 Imports: 19 Imported by: 1

README

vfs-kit

Go Reference License Go Test Coverage Go Report Card

中文文档

Virtual file systems with read-write support in Go. Zero external dependencies.

Extracted from rainycape/vfs and maintained as github.com/soulteary/vfs-kit for use across soulteary projects (for example apt-proxy and httpcache-kit).

Features

  • One interface: Memory, on-disk, archive, mounted and rewritten file systems all satisfy VFS
  • Read-write: not only a read-only overlay — OpenFile, Mkdir, Remove and friends
  • Contained: an on-disk or chrooted VFS rejects paths that would escape its root
  • Archives: read and write tar, tar.gz, tar.bz2 and zip
  • Composable: mount file systems at arbitrary points, rewrite paths, wrap read-only
  • io/fs bridge: AsReadOnlyFS adapts any VFS to fs.FS
  • Zero dependencies: standard library only

Requirements

  • Go 1.27.2+ (go.mod declares go 1.27.2)

Install

go get github.com/soulteary/vfs-kit

Quick Start

package main

import (
    "fmt"
    "log"

    vfs "github.com/soulteary/vfs-kit"
)

func main() {
    fs := vfs.Memory()

    if err := vfs.WriteFile(fs, "hello.txt", []byte("hello"), 0644); err != nil {
        log.Fatal(err)
    }

    data, err := vfs.ReadFile(fs, "hello.txt")
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(string(data))
}

Creating a File System

fs := vfs.Memory()                      // in-memory, read-write

fs, err := vfs.FS("/var/lib/myapp")     // on-disk, rooted at that directory
fs, err = vfs.Chroot("sub/dir", fs)     // a sub-tree of another VFS
tmp, err := vfs.TmpFS("myapp-")         // temporary on-disk; tmp.Close() removes it
fs = vfs.ReadOnly(fs)                   // reject every write

fs, err = vfs.Map(map[string]*vfs.File{ // in-memory from a literal map
    "a/b.txt": {Data: []byte("content"), Mode: 0644},
})

TmpFS returns a TemporaryVFS, which adds Root() and Close():

tmp, err := vfs.TmpFS("myapp-")
if err != nil {
    log.Fatal(err)
}
defer tmp.Close() // removes the directory
log.Println("working in", tmp.Root())

Path Containment

An on-disk VFS (FS) and a chrooted one (Chroot) reject a path that would escape the root, at every entry point — Open, OpenFile, Stat, Lstat, Mkdir and Remove all go through the same check, so a path cannot be accepted by one and rejected by another.

v, _ := vfs.FS("/var/lib/myapp")

_, err := v.Open("../../etc/passwd")
errors.Is(err, vfs.ErrInvalidPath) // true

A .. is matched as a whole path segment, so ordinary names work:

vfs.ReadFile(v, "v1..2.json")        // fine
vfs.ReadFile(v, "..hidden")          // fine
vfs.ReadFile(v, "sub/../inside.txt") // fine — resolves inside the root

Errors returned from an on-disk VFS name the VFS path, not the deployment's real root, so an error string does not disclose where the VFS lives. The wrapped errno is preserved, so classification keeps working:

import iofs "io/fs"

_, err := vfs.ReadFile(v, "missing.txt")
errors.Is(err, iofs.ErrNotExist) // true
vfs.IsNotExist(err)              // true

Containment is lexical. A symlink stored inside the VFS that points outside it is still followed, exactly as in a real chroot. Do not rely on a VFS root as a security boundary against content you did not put there yourself.

Reading and Writing

data, err := vfs.ReadFile(fs, "path/to/file")
err = vfs.WriteFile(fs, "path/to/file", data, 0644)

err = vfs.MkdirAll(fs, "a/b/c", 0755)
err = vfs.RemoveAll(fs, "a")

exists := !vfs.IsNotExist(err)

Lower level, through the VFS interface:

f, err := fs.Open("file")                                  // vfs.RFile
w, err := fs.OpenFile("file", os.O_CREATE|os.O_WRONLY, 0644) // vfs.WFile
info, err := fs.Stat("file")
info, err = fs.Lstat("link")
entries, err := fs.ReadDir("dir")
err = fs.Mkdir("dir", 0755)
err = fs.Remove("file")
name := fs.String()
Walking
err := vfs.Walk(fs, "/", func(fs vfs.VFS, path string, info os.FileInfo, err error) error {
    if err != nil {
        return err
    }
    if info.IsDir() && filepath.Base(path) == "vendor" {
        return vfs.ErrSkipDir // skip this directory
    }
    fmt.Println(path)
    return nil
})
Copying
err := vfs.Clone(dst, src)

Files or directories whose permissions are all zero become 0755 for directories and 0644 for files. Use Walk directly when you need finer control.

Archives

// Read — by extension: .zip, .tar, .tar.gz, .tar.bz2
fs, err := vfs.Open("assets.tar.gz")

// Or explicitly, from a reader
fs, err = vfs.Tar(r)
fs, err = vfs.TarGzip(r)
fs, err = vfs.TarBzip2(r)
fs, err = vfs.Zip(r, size) // zip needs the total size

// Write
err = vfs.WriteTar(w, fs)
err = vfs.WriteTarGzip(w, fs)
err = vfs.WriteZip(w, fs)

An archive is loaded into an in-memory VFS, so it is read-write once open — the changes simply do not reach the original file unless you write it back out.

Composing

Mounting

Mounter implements VFS and mounts other file systems at arbitrary points, much like a UNIX filesystem. The first mount must be at "/".

m := &vfs.Mounter{}
if err := m.Mount(vfs.Memory(), "/"); err != nil {
    log.Fatal(err)
}

assets, _ := vfs.Open("assets.zip")
if err := m.Mount(vfs.ReadOnly(assets), "/static"); err != nil {
    log.Fatal(err)
}

data, err := vfs.ReadFile(m, "/static/logo.png")
err = m.Umount("/static")
Rewriting paths
// Serve "/v2/..." from "/..."
fs = vfs.Rewriter(fs, func(oldPath string) string {
    return strings.TrimPrefix(oldPath, "/v2")
})
Read-only
ro := vfs.ReadOnly(fs)
err := vfs.WriteFile(ro, "x", nil, 0644)
errors.Is(err, vfs.ErrReadOnly) // true
Using a VFS as an io/fs.FS
import iofs "io/fs"

var fsys iofs.FS = vfs.AsReadOnlyFS(v)

data, err := iofs.ReadFile(fsys, "path/to/file") // io/fs paths: no leading slash

vfs.VFSPathFromFSName(name) converts an io/fs name back to a VFS path.

Compression

Some file systems support transparent per-file compression through the Compressor interface:

if err := vfs.Compress(fs); err != nil {
    log.Fatal(err) // not every file system supports it
}

if c, ok := entry.(vfs.Compressor); ok {
    c.SetCompressed(true)
    _ = c.IsCompressed()
}

vfs.ModeCompress is the mode bit used to mark a compressed entry. Changing compression requires a writable file handle. SetCompressed on a read-only handle leaves the file unchanged. Compress opens writable handles on file systems that support compression and returns an error if writes are not allowed; file systems without compression support remain unchanged.

Concurrency

File contents are safe to use from several goroutines. Each *File carries its own sync.RWMutex, and everything that reads or writes an entry's contents or mode takes it — including opening a file while another goroutine closes a handle for the same path.

Directory structure is synchronized as well. Mkdir, Remove and creating an entry take the parent directory's lock, and Remove holds the directory it is unlinking under that directory's own write lock across both the emptiness check and the unlink. Removing a directory while another goroutine creates an entry inside it resolves one way or the other, never both: either the creation lands first and the removal reports directory ... not empty, or the removal lands first and the creation reports os.ErrNotExist. A creation is never silently dropped into a detached directory. Handle os.ErrNotExist from OpenFile and Mkdir if you remove directories while other goroutines write.

Measured clean under -race: reading a file while another writes it, two goroutines creating different files in one directory, removing a file while it is open, Mkdir against Remove, Stat against a write, and removing a directory while an entry is created inside it.

Two more things the file lock does not cover:

  • A single open handle is not shared state. Read, Seek and Write move one offset. Give each goroutine its own handle rather than passing one around.
  • Containment is lexical, not a lock. Two goroutines writing the same path race for the final contents, the same as two processes writing one file.

The on-disk VFS inherits the operating system's semantics; it holds no locks of its own.

Errors

Sentinel Meaning
ErrInvalidPath The path is malformed, or would escape the VFS root
ErrReadOnly A write was attempted on a read-only VFS
ErrReadOnlyFileSystem The underlying file system itself is read-only
ErrWriteOnly A read was attempted on a write-only file
ErrSkipDir Returned from a WalkFunc to skip a directory
ErrRemoveRoot Remove was called on the file system root, which has no parent

Match them with errors.Is. vfs.IsExist and vfs.IsNotExist classify existence errors from any backend.

Diagnostics

Closing a file can fail in a place with nowhere to return the error — a finalizer, for instance. LogCloseError is called when that happens, and is a no-op by default:

vfs.LogCloseError = func(err error) { log.Printf("vfs close error: %v", err) }

API Overview

Function / Type Description
Memory() In-memory read-write VFS
FS(root) On-disk VFS rooted at root
TmpFS(prefix) Temporary on-disk VFS (TemporaryVFS: Root, Close)
Chroot(root, fs) A sub-tree of another VFS as its own root
Map(files) In-memory VFS from a map[string]*File
ReadOnly(fs) Read-only wrapper
Rewriter(fs, fn) Rewrite paths on the way through
Mounter Mount several VFSs at different points
AsReadOnlyFS(v) / VFSPathFromFSName(n) io/fs bridge
Open(filename) Load a .zip/.tar/.tar.gz/.tar.bz2 into memory
Tar, TarGzip, TarBzip2, Zip Load an archive from a reader
WriteTar, WriteTarGzip, WriteZip Write a VFS out as an archive
ReadFile, WriteFile, MkdirAll, RemoveAll Path-level helpers
Walk, WalkFunc, ErrSkipDir Tree traversal
Clone(dst, src) Copy every file between two VFSs
Compress(fs), Compressor, ModeCompress Transparent compression
IsExist, IsNotExist Error classification
File, Dir, Entry, EntryInfo In-memory entry types
RFile, WFile, Opener, Container File and capability interfaces
LogCloseError Hook for close failures with nowhere to return

See the package documentation for full signatures.

Upgrade Notes (v1.4.1)

No exported API was removed or changed, and one sentinel error was added. Two data races and one panic are gone.

  • Reading an entry's contents or mode now takes the file's lock. *File already carried an RWMutex and the writers took it — (*file).Close sets Data, and clears ModeCompress from Mode, under the write lock — but the readers did not, so the lock protected nothing. Opening a file while another goroutine closed a handle for the same path was a race, reported by -race between fileData and Close. fileData, (*File).FileMode and (*file).IsCompressed now take the read side. If you run the in-memory VFS under -race in your own tests, this is the report that goes away.
  • fileData decompresses outside the lock. It snapshots Data and Mode under the read lock and releases before inflating, so a large compressed entry does not hold other openers off the file.
  • (*file).Close is safe to call from several goroutines. It pre-checked the handle's closed flag outside the lock, while writing it under the lock, so concurrent closes of one handle raced on it. The check now happens under the lock; Close stays idempotent.
  • Removing a directory is now atomic against entry creation. Remove read the target directory's entry count before taking that directory's lock, while Dir.Add mutates the same slice under it, which -race reports as a write/read pair between Dir.Add and Remove. The same gap let a directory be unlinked just after another goroutine created an entry in it: both calls returned success and the entry was unreachable, about 3 losses per 2000 attempts in a two-goroutine loop. Remove now holds the directory's write lock across the emptiness check and the unlink, and marks the directory detached. A creation that resolved the directory before it was removed now fails with os.ErrNotExist instead of succeeding into nothing.
  • Remove no longer unlinks an entry it never checked. It looked the name up again after locking the parent, so a name rebound in between was unlinked regardless of what it now held: the emptiness check had applied to the previous occupant, and rebinding can change the type, so a Remove that resolved a file could drop a whole directory without ever checking it was empty. Remove now confirms it is unlinking the entry it resolved, and returns os.ErrNotExist otherwise.
  • Remove on the filesystem root returns an error instead of panicking. The root has no parent to unlink it from, and that nil parent was dereferenced. RemoveAll(fs, "/") reached it through the package's own helper. It now empties the tree and returns the new ErrRemoveRoot sentinel. If you called RemoveAll(fs, "/") to clear an in-memory VFS, it stops panicking and starts returning that error; ignore it with errors.Is.
  • Dir gained an unexported field to track whether it has been unlinked. Keyed struct literals are unaffected; an unkeyed vfs.Dir{...} literal in your own code would stop compiling, which go vet already flags for structs from another package.

Upgrade Notes (v1.4.0)

No API was added or removed. Some paths that used to resolve are now rejected, and some that used to be rejected now work.

  • Open on an on-disk VFS no longer escapes the root. It joined the root with an uncleaned relative path — filepath.Clean("../x") is still "../x", and Join then resolved the .. away — so Open("../secret.txt") read files outside the VFS root. Every other entry point was already anchored, which made the gap easy to miss: the one unguarded method was the main read entry point.
  • Chroot contains .. too. Its path handling was plain string concatenation with no .. handling, so "../.." climbed straight back out into the parent VFS.
  • Every entry point shares one containment check. Open, OpenFile, Lstat, Stat, Mkdir and Remove all route through it, so a path can no longer be accepted by one and rejected by another.
  • .. is matched as a whole path segment. It was a substring match, so legal names like v1..2.json and ..hidden were rejected. If you worked around that by renaming files, you can stop.
  • Error strings name the VFS path, not the host path. *fs.PathError values had the deployment's real root in them. The wrapped errno is preserved, so errors.Is(err, fs.ErrNotExist) (from io/fs) and os.IsNotExist keep working.
  • Documented, not changed: containment is lexical. A symlink stored inside the VFS that points outside is still followed, as in a real chroot.

Testing

go test ./...

# With coverage
go test ./... -coverprofile=coverage.out -covermode=atomic
go tool cover -func=coverage.out

License

Mozilla Public License 2.0 — see LICENSE. Derived from rainycape/vfs.

Documentation

Overview

Package vfs implements Virtual File Systems with read-write support.

All implementations use slash ('/') separated paths, with / representing the root directory. This means that to manipulate or construct paths, the functions in path package should be used, like path.Join or path.Dir. There's also no notion of the current directory nor relative paths. The paths /a/b/c and a/b/c are considered to point to the same element.

This package also implements some shorthand functions which might be used with any VFS implementation, providing the same functionality than functions in the io/ioutil, os and path/filepath packages:

io/ioutil.ReadFile => ReadFile
io/ioutil.WriteFile => WriteFile
os.IsExist => IsExist
os.IsNotExist => IsNotExist
os.MkdirAll => MkdirAll
os.RemoveAll => RemoveAll
path/filepath.Walk => Walk

All VFS implementations are thread safe, so multiple readers and writers might operate on them at any time.

For read-only code paths, AsReadOnlyFS returns an io/fs.FS view of any VFS. Use it with fs.ReadFile, fs.WalkDir, fs.Glob, etc., without changing the VFS interface. The on-disk fileSystem's ReadDir uses io/fs.ReadDir internally (Go 1.16+) for the read-only list path.

Index

Constants

View Source
const (
	ModeCompress os.FileMode = 1 << 16
)

Variables

View Source
var (
	// ErrSkipDir is used by a WalkFunc to signal Walk that
	// it wants to skip the given directory.
	ErrSkipDir = errors.New("skip this directory")
	// ErrReadOnly is returned from Write() on a read-only file.
	ErrReadOnly = errors.New("can't write to read only file")
	// ErrWriteOnly is returned from Read() on a write-only file.
	ErrWriteOnly = errors.New("can't read from write only file")
)
View Source
var ErrInvalidPath = errors.New("invalid path: attempt to access parent directory")
View Source
var (
	// ErrReadOnlyFileSystem is the error returned by read only file systems
	// from calls which would result in a write operation.
	ErrReadOnlyFileSystem = errors.New("read-only filesystem")
)
View Source
var ErrRemoveRoot = errors.New("can't remove the filesystem root")

ErrRemoveRoot is returned when removing the root of a file system, which has no parent to be unlinked from. RemoveAll reaches it after emptying the tree, so callers clearing a whole in-memory VFS can ignore it with errors.Is.

View Source
var LogCloseError = func(error) {}

LogCloseError is called when closing a file fails (e.g. in finalizer). Default is a no-op; callers may set it to log or report errors.

Functions

func AsReadOnlyFS

func AsReadOnlyFS(v VFS) fs.FS

AsReadOnlyFS returns a read-only fs.FS view of the given VFS. It allows read-only code paths to use fs.ReadFile, fs.WalkDir, fs.Glob, etc. Names use forward slashes; "." represents the root. The VFS root is "/" or ".". The returned value implements fs.ReadFileFS so fs.ReadFile uses Open+ReadAll directly and avoids the default read loop.

func Clone

func Clone(dst VFS, src VFS) error

Clone copies all the files from the src VFS to dst. Note that files or directories with all permissions set to 0 will be set to 0755 for directories and 0644 for files. If you need more granularity, use Walk directly to clone the file systems.

func Compress

func Compress(fs VFS) error

Compress is a shorthand method for compressing all the files in a VFS. Note that not all file systems support transparent compression/decompression.

func IsExist

func IsExist(err error) bool

IsExist returns whether the error indicates that the file or directory already exists.

func IsNotExist

func IsNotExist(err error) bool

IsNotExist returns whether the error indicates that the file or directory does not exist.

func MkdirAll

func MkdirAll(fs VFS, path string, perm os.FileMode) error

MkdirAll makes all directories pointed by the given path, using the same permissions for all of them. Note that MkdirAll skips directories which already exists rather than returning an error.

func ReadFile

func ReadFile(fs VFS, path string) ([]byte, error)

ReadFile reads the file at the given path from the given fs, returning either its contents or an error if the file couldn't be read.

func RemoveAll

func RemoveAll(fs VFS, path string) error

RemoveAll removes all files from the given fs and path, including directories (by removing its contents first).

func VFSPathFromFSName

func VFSPathFromFSName(name string) string

VFSPathFromFSName converts an io/fs name (forward slashes, "." = root) to the path form used by this VFS (e.g. "/" for root). Useful when wrapping an fs.FS that was created with AsReadOnlyFS.

func Walk

func Walk(fs VFS, root string, fn WalkFunc) error

Walk iterates over all the files in the VFS which descend from the given root (including root itself), descending into any subdirectories. In each directory, files are visited in alphabetical order. The given function might chose to skip a directory by returning ErrSkipDir.

func WriteFile

func WriteFile(fs VFS, path string, data []byte, perm os.FileMode) error

WriteFile writes a file at the given path and fs with the given data and permissions. If the file already exists, WriteFile truncates it before writing. If the file can't be created, an error will be returned.

func WriteTar

func WriteTar(w io.Writer, fs VFS) error

WriteTar writes the given VFS as a tar file to the given io.Writer.

func WriteTarGzip

func WriteTarGzip(w io.Writer, fs VFS) error

WriteTarGzip writes the given VFS as a tar.gz file to the given io.Writer.

func WriteZip

func WriteZip(w io.Writer, fs VFS) error

WriteZip writes the given VFS as a zip file to the given io.Writer.

Types

type Compressor

type Compressor interface {
	IsCompressed() bool
	SetCompressed(c bool)
}

Compressor is the interface implemented by VFS files which can be transparently compressed and decompressed. Currently, this is only supported by the in-memory filesystems. SetCompressed requires a writable handle; calling it on a read-only handle leaves the file unchanged.

type Container

type Container interface {
	// VFS returns the underlying VFS.
	VFS() VFS
}

Container is implemented by some file systems which contain another one.

type Dir

type Dir struct {
	sync.RWMutex
	// Mode is the file or directory mode. Note that some filesystems
	// might ignore the permission bits.
	Mode os.FileMode
	// ModTime represents the last modification time to directory.
	ModTime time.Time
	// Entry names in this directory, in order.
	EntryNames []string
	// Entries in the same order as EntryNames.
	Entries []Entry
	// contains filtered or unexported fields
}

Type Dir represents an in-memory directory. Most in-memory VFS implementations should use this structure to represent their directories, in order to save work.

func (*Dir) Add

func (d *Dir) Add(name string, entry Entry) error

Add ads a new entry to the directory. If there's already an entry ith the same name, an error is returned. Callers must hold the directory's write lock: memoryFileSystem.Remove checks a directory's emptiness and unlinks it under that same lock, and relies on no entry being added in between. Binary search could be used here for large directories (future optimization).

func (*Dir) FileMode

func (d *Dir) FileMode() os.FileMode

func (*Dir) Find

func (d *Dir) Find(name string) (Entry, int, error)

Find returns the entry with the given name and its index, or an error if an entry with that name does not exist in the directory. Callers must hold at least the directory's read lock.

func (*Dir) ModificationTime

func (d *Dir) ModificationTime() time.Time

func (*Dir) Size

func (d *Dir) Size() int64

func (*Dir) Type

func (d *Dir) Type() EntryType

type Entry

type Entry interface {
	// Type returns the entry type, either EntryTypeFile or
	// EntryTypeDir.
	Type() EntryType
	// Size returns the file size. For directories, it's always zero.
	Size() int64
	// FileMode returns the file mode as an os.FileMode.
	FileMode() os.FileMode
	// ModificationTime returns the last time the file or the directory
	// was modified.
	ModificationTime() time.Time
}

Entry is the interface implemented by the in-memory representations of files and directories.

type EntryInfo

type EntryInfo struct {
	// Path is the full path to the entry in its VFS.
	Path string
	// Entry is the instance used by the VFS to represent
	// the in-memory entry.
	Entry Entry
}

EntryInfo implements the os.FileInfo interface wrapping a given File and its Path in its VFS.

func (*EntryInfo) IsDir

func (info *EntryInfo) IsDir() bool

func (*EntryInfo) ModTime

func (info *EntryInfo) ModTime() time.Time

func (*EntryInfo) Mode

func (info *EntryInfo) Mode() os.FileMode

func (*EntryInfo) Name

func (info *EntryInfo) Name() string

func (*EntryInfo) Size

func (info *EntryInfo) Size() int64

func (*EntryInfo) Sys

func (info *EntryInfo) Sys() interface{}

Sys returns the underlying Entry.

type EntryType

type EntryType uint8

EntryType indicates the type of the entry.

const (
	// EntryTypeFile indicates the entry is a file.
	EntryTypeFile EntryType = iota + 1
	// EntryTypeDir indicates the entry is a directory.
	EntryTypeDir
)

type File

type File struct {
	sync.RWMutex
	// Data contains the file data.
	Data []byte
	// Mode is the file or directory mode. Note that some filesystems
	// might ignore the permission bits.
	Mode os.FileMode
	// ModTime represents the last modification time to the file.
	ModTime time.Time
}

Type File represents an in-memory file. Most in-memory VFS implementations should use this structure to represent their files, in order to save work.

func (*File) FileMode

func (f *File) FileMode() os.FileMode

func (*File) ModificationTime

func (f *File) ModificationTime() time.Time

func (*File) Size

func (f *File) Size() int64

func (*File) Type

func (f *File) Type() EntryType

type FileInfos

type FileInfos []os.FileInfo

FileInfos represents an slice of os.FileInfo which implements the sort.Interface. This type is only exported for users who want to implement their own filesystems, since VFS.ReadDir requires the returned []os.FileInfo to be sorted by name.

func (FileInfos) Len

func (f FileInfos) Len() int

func (FileInfos) Less

func (f FileInfos) Less(i, j int) bool

func (FileInfos) Swap

func (f FileInfos) Swap(i, j int)

type Mounter

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

Mounter implements the VFS interface and allows mounting different virtual file systems at arbitraty points, working much like a UNIX filesystem. Note that the first mounted filesystem must be always at "/".

func (*Mounter) Lstat

func (m *Mounter) Lstat(path string) (os.FileInfo, error)

func (*Mounter) Mkdir

func (m *Mounter) Mkdir(path string, perm os.FileMode) error

func (*Mounter) Mount

func (m *Mounter) Mount(fs VFS, point string) error

Mount mounts the given filesystem at the given mount point. Unless the mount point is /, it must be an already existing directory.

func (*Mounter) Open

func (m *Mounter) Open(path string) (RFile, error)

func (*Mounter) OpenFile

func (m *Mounter) OpenFile(path string, flag int, perm os.FileMode) (WFile, error)

func (*Mounter) ReadDir

func (m *Mounter) ReadDir(path string) ([]os.FileInfo, error)

func (*Mounter) Remove

func (m *Mounter) Remove(path string) error

Remove removes the path. Note: currently empty directories may be removed even if a mount point exists below; this behavior may be restricted in a future version.

func (*Mounter) Stat

func (m *Mounter) Stat(path string) (os.FileInfo, error)

func (*Mounter) String

func (m *Mounter) String() string

func (*Mounter) Umount

func (m *Mounter) Umount(point string) error

Umount umounts the filesystem from the given mount point. If there are other filesystems mounted below it or there's no filesystem mounted at that point, an error is returned.

type Opener

type Opener interface {
	// Open returns a readable file at the given path. See also
	// the shorthand function ReadFile.
	Open(path string) (RFile, error)
	// OpenFile returns a readable and writable file at the given
	// path. Note that, depending on the flags, the file might be
	// only readable or only writable. See also the shorthand
	// function WriteFile.
	OpenFile(path string, flag int, perm os.FileMode) (WFile, error)
}

Opener is the interface which specifies the methods for opening a file. All the VFS implementations implement this interface.

type RFile

type RFile interface {
	io.Reader
	io.Seeker
	io.Closer
}

RFile is the interface implemented by the returned value from a VFS Open method. It allows reading and seeking, and must be closed after use.

func NewRFile

func NewRFile(f *File) (RFile, error)

NewRFile returns a RFile from a *File.

type TemporaryVFS

type TemporaryVFS interface {
	VFS
	// Root returns the root directory for the temporary VFS.
	Root() string
	// Close removes all the files in temporary VFS.
	Close() error
}

TemporaryVFS represents a temporary on-disk file system which can be removed by calling its Close method.

func TmpFS

func TmpFS(prefix string) (TemporaryVFS, error)

TmpFS returns a temporary file system with the given prefix and its root directory name, which might be empty. The temporary file system is created in the default temporary directory for the operating system. Once you're done with the temporary filesystem, you might can all its files by calling its Close method.

type VFS

type VFS interface {
	Opener
	// Lstat returns the os.FileInfo for the given path, without
	// following symlinks.
	Lstat(path string) (os.FileInfo, error)
	// Stat returns the os.FileInfo for the given path, following
	// symlinks.
	Stat(path string) (os.FileInfo, error)
	// ReadDir returns the contents of the directory at path as an slice
	// of os.FileInfo, ordered alphabetically by name. If path is not a
	// directory or the permissions don't allow it, an error will be
	// returned.
	ReadDir(path string) ([]os.FileInfo, error)
	// Mkdir creates a directory at the given path. If the directory
	// already exists or its parent directory does not exist or
	// the permissions don't allow it, an error will be returned. See
	// also the shorthand function MkdirAll.
	Mkdir(path string, perm os.FileMode) error
	// Remove removes the item at the given path. If the path does
	// not exists or the permissions don't allow removing it or it's
	// a non-empty directory, an error will be returned. See also
	// the shorthand function RemoveAll.
	Remove(path string) error
	// String returns a human-readable description of the VFS.
	String() string
}

VFS is the interface implemented by all the Virtual File Systems.

func Chroot

func Chroot(root string, fs VFS) (VFS, error)

Chroot returns a new VFS wrapping the given VFS, making the given directory the new root ("/"). Note that root must be an existing directory in the given file system, otherwise an error is returned.

func FS

func FS(root string) (VFS, error)

FS returns a VFS at the given path, which must be provided as native path of the current operating system. The path might be either absolute or relative, but the fileSystem will be anchored at the absolute path represented by root at the time of the function call.

func Map

func Map(files map[string]*File) (VFS, error)

Map returns an in-memory file system using the given files argument to populate it (which might be nil). Note that the files map does not need to contain any directories, they will be created automatically. If the files contain conflicting paths (e.g. files named a and a/b, thus making "a" both a file and a directory), an error will be returned.

func Memory

func Memory() VFS

Memory returns an empty in memory VFS.

func Open

func Open(filename string) (VFS, error)

Open returns an in-memory VFS initialized with the contents of the given filename, which must have one of the following extensions:

  • .zip
  • .tar
  • .tar.gz
  • .tar.bz2

func ReadOnly

func ReadOnly(fs VFS) VFS

ReadOnly returns a read-only filesystem wrapping the given fs.

func Rewriter

func Rewriter(fs VFS, rewriter func(oldPath string) (newPath string)) VFS

Rewriter returns a file system which uses the provided function to rewrite paths.

func Tar

func Tar(r io.Reader) (VFS, error)

Tar returns an in-memory VFS initialized with the contents of the .tar file read from the given io.Reader.

func TarBzip2

func TarBzip2(r io.Reader) (VFS, error)

TarBzip2 returns an in-memory VFS initialized with the contents of then .tar.bz2 file read from the given io.Reader.

func TarGzip

func TarGzip(r io.Reader) (VFS, error)

TarGzip returns an in-memory VFS initialized with the contents of the .tar.gz file read from the given io.Reader.

func Zip

func Zip(r io.Reader, size int64) (VFS, error)

Zip returns an in-memory VFS initialized with the contents of the .zip file read from the given io.Reader. Since archive/zip requires an io.ReaderAt rather than an io.Reader, and a known size, Zip will read the whole file into memory and provide its own buffering if r does not implement io.ReaderAt or size is <= 0.

type WFile

type WFile interface {
	io.Reader
	io.Writer
	io.Seeker
	io.Closer
}

WFile is the interface implemented by the returned value from a VFS OpenFile method. It allows reading, seeking and writing, and must be closed after use. Note that, depending on the flags passed to OpenFile, the Read or Write methods might always return an error (e.g. if the file was opened in read-only or write-only mode).

func NewWFile

func NewWFile(f *File, read bool, write bool) (WFile, error)

NewWFile returns a WFile from a *File.

type WalkFunc

type WalkFunc func(fs VFS, path string, info os.FileInfo, err error) error

WalkFunc is the function type used by Walk to iterate over a VFS.

Jump to

Keyboard shortcuts

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