fs

package module
v0.0.0-...-4ce0219 Latest Latest
Warning

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

Go to latest
Published: Jun 8, 2026 License: MIT Imports: 38 Imported by: 31

README

go-fs: A unified file system for Go

Go Reference Go Report Card Go Version GitHub release

The package is built around a File type that is a string underneath and interprets its value as a local file system path or as a URI.

TODO

  • Return ErrFileSystemClosed from all closable FS
  • Test dropboxfs
  • Consider secsy/goftp for ftpfs

Introduction

FileSystem implementations can be registered with their URI qualifiers like file:// or http://.

The methods of File parse their string value for a qualifier and look up a FileSystem in the Registry. The only special rule is, that if no qualifier is present, then the string value is interpreted as a local file path.

The LocalFileSystem is registered by default.

Work with Local directly:

fs.Local.Separator() // Either `/` or `\`

fs.Local.IsSymbolicLink("~/file") // Tilde expands to user home dir

For example, create a FileSystem from a multi-part HTTP form request that contains an uploaded file:

import "github.com/ungerik/go-fs/multipartfs"

multipartFS, err := multipartfs.FromRequestForm(request, MaxUploadSize)

defer multipartFS.Close()

// Access form values as string
multipartFS.Form.Value["email"] 

// Access form files as fs.File
file, err := multipartFS.FormFile("file")

// Use like any other fs.File
bytes, err := file.ReadAll(ctx)

fs.File

type File string

As a string-type it's easy to assign string literals and it can be const which would be impossible if File was an interface or struct:

const fileConst fs.File = "~/file.a"

var fileVar fs.File = "~/file.b"

fileVar = fileConst
fileVar = "~/file.c"

Handy to pass string literals of local paths or URIs to functions:

func readFile(f fs.File) { /* ... */ }

readFile("../my-local-file.txt")

// HTTP reading works when httpfs is imported
import _ "github.com/ungerik/go-fs/httpfs"

readFile("https://example.com/file-via-uri.txt")

As a string type File naturally marshals/unmarshals as string path/URI without having to implement marshaling interfaces.

But it implements fmt.Stringer to add the name of the path/URI filesystem as debug information and gob.GobEncoder, gob.GobDecoder to encode filename and content instead of the path/URI value.

Path related methods:

file := fs.TempDir().Join("file.txt")

dir := file.Dir()   // "/tmp" == fs.TempDir()
name := file.Name() // "file.txt"
path := file.Path() // "/tmp/file.txt"
url := file.URL()   // "file:///tmp/file.txt"
ext := file.Ext()   // ".txt"
lower := file.ExtLower() // ".txt"
trimmed := file.TrimExt() // "/tmp/file"

slashed := file.PathWithSlashes() // forward slashes regardless of OS
local := file.LocalPath()         // "" if not on Local
mustLocal := file.MustLocalPath() // panics if not on Local

file2 := file.Dir().Join("a", "b", "c").Joinf("file%d.txt", 2)
path2 := file2.Path() // "/tmp/a/b/c/file2.txt"

abs := fs.File("~/some-dir/../file").AbsPath() // "/home/erik/file"
isAbs := abs.HasAbsPath()                      // true
absFile := fs.File("relative/path").ToAbsPath() // File with an absolute path

// Relative path between two files on the same FileSystem
base := fs.File("/tmp/project")
rel, err := base.RelPathOf(base.Join("a", "b", "c")) // "a/b/c"

Access and existence checks:

file.IsReadable() // file exists and is readable
file.IsWritable() // file (or its parent dir) is writable
file.IsEmptyDir() // directory exists and contains no entries

Ownership (where the file system supports it, e.g. LocalFileSystem):

user, err := file.User()
err = file.SetUser("alice")

group, err := file.Group()
err = file.SetGroup("staff")

Resizing existing files (where supported):

err := file.Truncate(1024) // resize to exactly 1024 bytes

Meta information:

size := file.Size() // int64, 0 for non existing or dirs
isDir := dir.IsDir()      // true
exists := file.Exists()   // true
fileIsDir := file.IsDir() // false
modTime := file.Modified()
hash, err := file.ContentHash()  // Dropbox hash algo
regular := file.Info().IsRegular // true
info := file.Info().FSFileInfo() // io/fs.FileInfo

Reading and writing files

Reading:

bytes, err := file.ReadAll(ctx)

str, err := file.ReadAllString(ctx)

var w io.Writer
n, err := file.WriteTo(w)

f, err := file.OpenReader()     // io/fs.File 
r, err := file.OpenReadSeeker() // fs.ReadSeekCloser

Writing:

err := file.WriteAll(ctx, []byte("Hello"))

err := file.WriteAllString(ctx, "Hello")

err := file.Append(ctx, []byte("Hello"))

err := file.AppendString(ctx, "Hello")

var r io.Reader
n, err := file.ReadFrom(r)

w, err := file.OpenWriter()       // io.WriteCloser
w, err := file.OpenAppendWriter() // io.WriteCloser

rw, err := file.OpenReadWriter() // fs.ReadWriteSeekCloser

fs.FileReader

For cases where a file should be passed only for reading, it's recommended to use the interface type FileReader. It has all the read-related methods of File, so a File can be assigned or passed as FileReader:

type FileReader interface { /* ... */ }
func readFile(f fs.FileReader) { /* ... */ }

// An untyped string literal does not work as interface,
// needs a concrete type like fs.File
readFile(fs.File("../my-local-file.txt"))

fs.MemFile

MemFile combines the buffered in-memory data of a file with a filename to implement fs.FileReader. It exposes FileName and FileData as exported struct fields to emphasize its simple nature as just a wrapper of a name and some bytes.

type MemFile struct {
	FileName string
	FileData []byte
}

Pass by value: MemFile should be passed by value (not by pointer) because it's a small, simple struct containing only a string and a slice (both reference types internally). Passing by value is more efficient and idiomatic for such lightweight types. This is why NewMemFile returns a MemFile value, not a pointer.

The type exists because it's very common to build up a file in memory and/or pass around some buffered file bytes together with a filename:

func readFile(f fs.FileReader) { /* ... */ }

readFile(fs.NewMemFile("hello-world.txt", []byte("Hello World!")))

// Read another fs.FileReader into a fs.MemFile
// to have it buffered in memory
memFile, err := fs.ReadMemFile(ctx, fs.File("../my-local-file.txt"))

// Read all data similar to io.ReadAll from an io.Reader
var r io.Reader
memFile, err := fs.ReadAllMemFile(ctx, r, "in-mem-file.txt")

Note that MemFile is not a File because it has no backing file system: its FileName is just a name, not a registered path or URI.

The FileName can mirror the complete path of a file or directory on a file system, but the most common simple case is just a name without any slashes and path semantics. When the FileName contains slashes, the path methods interpret it as a /-separated path (a backslash is an ordinary character, not a separator). A FileName ending with a slash marks the MemFile as a directory: IsDir returns true, FileData is ignored, and the read methods return an ErrIsDirectory error.

mf := fs.NewMemFile("some/path/file.txt", data)

mf.Name()                    // "file.txt"
mf.Ext()                     // ".txt"
mf.Dir()                     // MemFile{FileName: "some/path/"}, a directory
dir, name := mf.DirAndName() // MemFile{FileName: "some/path/"}, "file.txt"

mf.IsDir()                                   // false
fs.MemFile{FileName: "some/path/"}.IsDir()   // true
fs.MemFile{FileName: "a/b/../c"}.CleanPath() // "a/c"

Derive new MemFile values without copying the underlying data:

renamed := memFile.WithName("renamed.txt")  // same FileData, different name
patched := memFile.WithData(newBytes)       // same FileName, different data

WithName replaces the whole FileName (like WithData replaces the whole FileData) including any path, so it is not symmetric with Name which only returns the last path element.

fs.MemDir

MemDir is the directory counterpart of MemFile: an in-memory directory represented by nothing but its path string. Like MemFile it implements fs.FileReader and is passed by value.

type MemDir string

Because a directory has no contents, every read method returns an ErrIsDirectory error, while IsDir returns true and ContentHash returns an empty string (matching File for a directory). All path methods use / as separator and ignore trailing slashes:

dir := fs.MemDir("some/path/sub/")

dir.Name()                  // "sub"        (trailing slash ignored)
dir.Dir()                   // "some/path"  (parent directory)
dir.Ext()                   // ""
sub := dir.Join("a", "b")   // "some/path/sub/a/b"
clean := fs.MemDir("a/b/../c/").CleanPath() // "a/c"

reader, err := dir.OpenReader() // err is an ErrIsDirectory error

Like MemFile, MemDir implements fmt.Stringer and round-trips its path through gob without touching any file system.

Listing directories

Callback-based listing (cancel by returning an error from the callback or canceling the context):

// Print names of all entries in dir
dir.ListDir(func(f fs.File) error {
	_, err := fmt.Println(f.Name())
	return err
})

// Print names of all JPEGs in dir and all recursive sub-dirs
// with cancelable context
dir.ListDirRecursiveContext(ctx, func(f fs.File) error {
	_, err := fmt.Println(f.Name())
	return err
}, "*.jpg", "*.jpeg")

// Get all files in dir without limit
files, err := dir.ListDirMax(-1)

// Get the first 100 JPEGs in dir
files, err := dir.ListDirMaxContext(ctx, 100, "*.jpg", "*.jpeg")

// Recursive variant with a hard cap
files, err := dir.ListDirRecursiveMax(1000, "*.go")

Go 1.23+ iterator methods (iter.Seq2[fs.File, error]):

// Range directly over directory entries
for file, err := range dir.ListDirIter("*.jpg", "*.jpeg") {
	if err != nil {
		return err
	}
	fmt.Println(file.Name())
}

// Recursive iteration with a cancelable context
for file, err := range dir.ListDirRecursiveIterContext(ctx, "*.go") {
	if err != nil {
		return err
	}
	fmt.Println(file.Path())
}

Channel-based listing for fan-out pipelines (the cancel channel stops the goroutine if any value is sent into it):

cancel := make(chan error)
files, errs := dir.ListDirChan(cancel, "*.log")

for f := range files {
	process(f)
}
if err := <-errs; err != nil {
	return err
}

// Recursive variant
files, errs = dir.ListDirRecursiveChan(cancel, "*.log")

Glob with wildcard substitution (Go 1.23+ iterator, the second yielded value is the list of substituted wildcard segments):

// All Go files under any "cmd/*" sub-directory
for file, segments := range fs.MustGlob("cmd/*/*.go") {
	fmt.Println(segments, file.Path()) // segments == ["mytool", "main.go"]
}

// Relative to a specific base directory
iter, err := dir.Glob("**/*.png")
if err != nil {
	return err
}
for file := range iter {
	fmt.Println(file.Path())
}

A pattern ending with a slash (/) only matches directories. Glob ignores I/O errors and only fails on a malformed pattern.

Standard library compatibility (io/fs)

A File can be exposed as an io/fs.FS so it works with any code that expects the standard library file system abstraction (fs.WalkDir, html/template.ParseFS, http.FS, ...):

stdFS := fs.File("/srv/static").StdFS()

// Use with io/fs
entries, err := iofs.ReadDir(stdFS, ".")

// Or with http.FS (note: http.FS expects io/fs.FS)
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.FS(stdFS))))

StdFS implements io/fs.FS, io/fs.SubFS, io/fs.StatFS, io/fs.ReadDirFS, and io/fs.ReadFileFS.

A File can also be returned as a directory entry:

entry := fs.File("./file.txt").StdDirEntry() // io/fs.DirEntry

JSON and XML helpers

type Config struct { Name string `json:"name"` }

var cfg Config
err := fs.File("config.json").ReadJSON(ctx, &cfg)
err = fs.File("config.json").WriteJSON(ctx, &cfg, "  ") // indented

err = fs.File("config.xml").ReadXML(ctx, &cfg)
err = fs.File("config.xml").WriteXML(ctx, &cfg, "  ")

The same helpers are also available as MemFile constructors:

m, err := fs.NewMemFileWriteJSON("config.json", &cfg, "  ")
m, err  = fs.NewMemFileWriteXML("config.xml", &cfg, "  ")

Encoding files with encoding/gob

File implements gob.GobEncoder / gob.GobDecoder. Unlike the default string marshaling (which only encodes the path/URI), gob encoding includes the file's content so the receiver can rematerialize the bytes:

var buf bytes.Buffer
err := gob.NewEncoder(&buf).Encode(fs.File("/tmp/data.bin"))

// On the receiver, decoding into a File writes the bytes to that file.
var dst fs.File = fs.TempDir().Join("decoded.bin")
err = gob.NewDecoder(&buf).Decode(&dst)

MemFile implements the same interfaces and round-trips its name and data through gob without touching any file system.

File systems opt into symbolic link support by implementing the SymbolicLinkFileSystem interface. LocalFileSystem and MemFileSystem opt in; the cloud and archive backends (s3fs, httpfs, ftpfs, sftpfs, zipfs, dropboxfs, multipartfs) do not, so calling these methods on files from those backends returns an ErrUnsupported error.

target := fs.File("/etc/hosts")
link := fs.File("/tmp/hosts-link")

// Create link as a symbolic link pointing to target
err := link.CreateSymbolicLink(target)

// Check whether a file is a symbolic link
if link.IsSymbolicLink() {
    // Read the link target as stored on disk (may be relative)
    resolved, err := link.ReadSymbolicLink()
    _ = resolved
}

Both files must live on the same FileSystem; passing a target from a different file system returns an error. The target path is stored verbatim, so pass an absolute path if you want the link to resolve the same way regardless of where it is read from.

Watching the local file system

The local file system supports watching files and directories for changes using the fsnotify package. This functionality is available through the WatchFileSystem interface and the File.Watch method.

// Watch a directory for changes
dir := fs.File("/path/to/watch")

cancel, err := dir.Watch(func(file fs.File, event fs.Event) {
    if event.HasCreate() {
        fmt.Printf("File created: %s\n", file.Name())
    }
    if event.HasWrite() {
        fmt.Printf("File written: %s\n", file.Name())
    }
    if event.HasRemove() {
        fmt.Printf("File removed: %s\n", file.Name())
    }
    if event.HasRename() {
        fmt.Printf("File renamed: %s\n", file.Name())
    }
    if event.HasChmod() {
        fmt.Printf("File permissions changed: %s\n", file.Name())
    }
})

if err != nil {
    log.Fatal(err)
}

// Later, cancel the watch
defer cancel()

Event Types:

  • HasCreate() - File or directory was created
  • HasWrite() - File was written to
  • HasRemove() - File or directory was removed
  • HasRename() - File or directory was renamed
  • HasChmod() - File permissions were changed

Important Notes:

  • Watching a directory only reports changes directly within it, not in recursive sub-directories
  • Multiple watches can be set on the same file/directory
  • The returned cancel function stops a specific watch
  • Events are delivered asynchronously via goroutines
  • The local filesystem supports watching; other filesystems may not

Logging: You can enable logging for watch events and errors:

fs.Local.WatchEventLogger = fs.LoggerFunc(func(format string, args ...any) {
    log.Printf("WATCH: "+format, args...)
})

fs.Local.WatchErrorLogger = fs.LoggerFunc(func(format string, args ...any) {
    log.Printf("WATCH ERROR: "+format, args...)
})

File system implementations

go-fs ships with the local file system and several remote / virtual backends. Each backend is an independent Go module under its own sub-directory. Importing the package registers a FileSystem for its URI prefix, after which File values with that prefix transparently route to the right backend.

Package URI prefix Constructor Read Write
(built-in) file:// fs.Local (registered by default) yes yes
httpfs http://, https:// side-effect import: import _ ".../httpfs" yes no
s3fs s3://<bucket> s3fs.NewAndRegister / s3fs.NewLoadDefaultConfig yes yes/ro
sftpfs sftp:// sftpfs.Dial / sftpfs.DialAndRegister yes yes
ftpfs ftp:// ftpfs.Dial / ftpfs.DialAndRegister yes yes
dropboxfs dropbox:// dropboxfs.NewAndRegister yes yes
zipfs zip:// zipfs.NewReaderFileSystem / NewWriterFileSystem yes/ro yes/ro
multipartfs (per-request) multipartfs.FromRequestForm yes no
(built-in) mem:// fs.NewMemFileSystem yes yes
httpfs
import _ "github.com/ungerik/go-fs/httpfs"

data, err := fs.File("https://example.com/file.txt").ReadAll(ctx)

Read-only. Useful for treating remote files uniformly with local ones.

s3fs
import "github.com/ungerik/go-fs/s3fs"

// Using the default AWS credential chain
bucket, err := s3fs.NewLoadDefaultConfig(ctx, "my-bucket", false)

// Or with an existing aws-sdk-go-v2 client
bucket = s3fs.NewAndRegister(client, "my-bucket", false)

err = fs.File("s3://my-bucket/path/file.txt").WriteAllString(ctx, "Hello")

Multipart upload/download is used automatically for files larger than 5/10 MB.

sftpfs
import "github.com/ungerik/go-fs/sftpfs"

sftpFS, err := sftpfs.DialAndRegister(
    ctx,
    "sftp://user@host:22/",
    sftpfs.Password("secret"),
    ssh.InsecureIgnoreHostKey(), // use a real callback in production
    nil,
)

data, err := fs.File("sftp://user@host:22/etc/hostname").ReadAll(ctx)
ftpfs
import "github.com/ungerik/go-fs/ftpfs"

ftpFS, err := ftpfs.DialAndRegister(
    ctx,
    "ftp://example.com:21/",
    ftpfs.AnonymousCredentials,
    nil, // debug output
)

Supports plain FTP and FTPS.

dropboxfs
import "github.com/ungerik/go-fs/dropboxfs"

dbxFS := dropboxfs.NewAndRegister(accessToken, 5*time.Minute, false)

err := fs.File("dropbox://Apps/MyApp/notes.md").WriteAllString(ctx, "...")
zipfs
import "github.com/ungerik/go-fs/zipfs"

// Read a ZIP archive as a file system
zipFS, err := zipfs.NewReaderFileSystem(fs.File("archive.zip"))
defer zipFS.Close()

err = zipFS.RootDir().ListDir(func(f fs.File) error {
    fmt.Println(f.Path())
    return nil
})

// Write a new ZIP archive
out, err := zipfs.NewWriterFileSystem(fs.File("out.zip"))
defer out.Close()

A ZipFileSystem is either reader- or writer-mode depending on the constructor used.

multipartfs

See the introduction for multipartfs.FromRequestForm — it wraps an uploaded HTML form so files can be consumed using the regular fs.File API.

MemFileSystem

A fully-featured, thread-safe, in-memory file system useful for tests or as a cache for slower backends:

memFS, err := fs.NewMemFileSystem("/", fs.NewMemFile("hello.txt", []byte("hi")))
defer memFS.Close()

// Access through the global Registry using the URI prefix
data, err := fs.File(memFS.Prefix() + "/hello.txt").ReadAll(ctx)

// Or create a one-shot single-file FS that gives you a ready-to-use File
ms, file, err := fs.NewSingleMemFileSystem(fs.NewMemFile("a.txt", []byte("a")))
defer ms.Close()

MemFileSystem implements every optional FileSystem interface the local backend does — including RenameFileSystem, MoveFileSystem, WatchFileSystem, PermissionsFileSystem, UserFileSystem, GroupFileSystem, ListDirMaxFileSystem, ListDirRecursiveFileSystem, XAttrFileSystem, and SymbolicLinkFileSystem — so it can stand in for any other backend in tests. Watch events are synthesized from every mutation that goes through the FS API; direct mutation of a MemFile.FileData byte slice obtained outside the API is not observable.

Documentation

Index

Constants

View Source
const (
	// LocalPrefix is the prefix of the LocalFileSystem
	LocalPrefix = "file://"

	// Separator used in LocalFileSystem paths
	Separator = string(filepath.Separator)
)
View Source
const InvalidFile = File("")

InvalidFile is a file with an empty path and thus invalid.

View Source
const PrefixSeparator = "://"

Variables

ErrEmptyPath indications an empty file path

Functions

func AllExist

func AllExist[F interface{ Exists() bool }](files []F) bool

AllExist returns true if the Exists method of all files returned true

func ContainsLocalPath

func ContainsLocalPath[F interface{ LocalPath() string }](files []F, localPath string) bool

ContainsLocalPath returns true if the passed localPath matches the result from the LocalPath method of any of the files.

func ContainsName

func ContainsName[F interface{ Name() string }](files []F, filename string) bool

ContainsName returns true if the passed filename matches the result from the Name method of any of the files.

func ContentHashIndex

func ContentHashIndex[F interface {
	ContentHashContext(ctx context.Context) (string, error)
}](ctx context.Context, files []F, hash string) (int, error)

ContentHashIndex returns the slice index of the first file where the passed hash equals the result from the ContentHashContext method or -1 in case of no match.

func CopyFile

func CopyFile(ctx context.Context, src FileReader, dest File, perm ...Permissions) error

CopyFile copies a single file between different file systems. If dest has a path that does not exist, then all directories up to that path will be created. If dest is an existing directory, then a file with the base name of src will be created there.

func CopyFileBuf

func CopyFileBuf(ctx context.Context, src FileReader, dest File, buf *[]byte, perm ...Permissions) error

CopyFileBuf copies a single file between different file systems. If dest has a path that does not exist, then all directories up to that path will be created. If dest is an existing directory, then a file with the base name of src will be created there. An pointer to a []byte variable must be passed for buf. If that variable holds a non zero length byte slice then this slice will be used as buffer, else a byte slice will be allocated and assigned to the variable. Use this function to re-use buffers between CopyFileBuf calls.

func CopyRecursive

func CopyRecursive(ctx context.Context, src, dest File, patterns ...string) error

CopyRecursive can copy between files of different file systems. The filter patterns are applied on filename level, not the whole path.

func FileContentHash

func FileContentHash(ctx context.Context, fileReader FileReader, hashFunc ContentHashFunc) (string, error)

FileContentHash returns the hashFunc result for fileReader

func FileInfoToFileCallback

func FileInfoToFileCallback(fileCallback func(File) error) func(*FileInfo) error

FileInfoToFileCallback converts a File callback function into a FileInfo callback function that is calling the passed fileCallback with the FileInfo.File.

func FileNames

func FileNames[T interface{ Name() string }](files []T) []string

FileNames returns the names of the passed files

func FilePaths

func FilePaths[F interface{ Path() string }](files []F) []string

FilePaths returns the FileSystem specific paths the passed files

func FileURLs

func FileURLs[F interface{ URL() string }](files []F) []string

FileURLs returns the URLs of the passed files

func Glob

func Glob(pattern string) (iter.Seq2[File, []string], error)

Glob yields files and wildcard substituting path segments matching a path pattern.

The pattern is appended to the current working directory if it is not an absolute path.

The yielded path segments are the strings necessary to substitute all wildcard containing path segments in the pattern to form a valid path for a yielded file. This includes the name of the yielded file itself if the pattern contains wildcards for the last segment. Non wildcard segments are not included.

The syntax of patterns is the same as in path.Match. It always uses slash '/' as path segment separator independently of the file's file system.

A pattern ending with a slash '/' will match only directories.

Glob ignores file system errors such as I/O errors reading directories. The only possible returned error is path.ErrBadPattern, reporting that the pattern is malformed.

func IdenticalDirContents

func IdenticalDirContents(ctx context.Context, dirA, dirB File, recursive bool) (identical bool, err error)

IdenticalDirContents returns true if the files in dirA and dirB are identical in size and content. If recursive is true, then directories will be considered too.

func IdenticalFileContents

func IdenticalFileContents(ctx context.Context, files ...FileReader) (identical bool, err error)

IdenticalFileContents returns if the passed files have identical content. An error is returned if one of the files does not exist (ErrDoesNotExist) or if less than 2 files are passed. Compares files larger than 16MB via content hash to not allocate too much memory.

func IsRegistered

func IsRegistered(fs FileSystem) bool

IsRegistered returns true if the file system is registered with its prefix.

func LocalPathIndex

func LocalPathIndex[F interface{ LocalPath() string }](files []F, localPath string) int

LocalPathIndex returns the slice index of the first file where the passed localPath equals the result from the LocalPath method or -1 in case of no match.

func Move

func Move(ctx context.Context, source, destination File) error

Move moves and/or renames source to destination. source and destination can be files or directories. If source is a directory, it will be moved with all its contents. If source and destination are using the same FileSystem, then FileSystem.Move will be used, else source will be copied recursively first to destination and then deleted.

When source and destination resolve to the same location on the same FileSystem, Move returns nil without touching the file. This matches the os.Rename no-op behavior required by the MoveFileSystem contract and protects against the copy-then-delete fallback path destroying the file when caller passes identical source and destination.

func MustGlob

func MustGlob(pattern string) iter.Seq2[File, []string]

MustGlob yields files and wildcard substituting path segments matching a path pattern.

The pattern is appended to the current working directory if it is not an absolute path.

The yielded path segments are the strings necessary to substitute all wildcard containing path segments in the pattern to form a valid path for a yielded file. This includes the name of the yielded file itself if the pattern contains wildcards for the last segment. Non wildcard segments are not included.

The syntax of patterns is the same as in path.Match. It always uses slash '/' as path segment separator independently of the file's file system.

MustGlob ignores file system errors such as I/O errors reading directories. The only possible panic is in case of a malformed pattern.

func NameIndex

func NameIndex[F interface{ Name() string }](files []F, filename string) int

NameIndex returns the slice index of the first file where the passed filename equals the result from the Name method or -1 in case of no match.

func NewSingleMemFileSystem

func NewSingleMemFileSystem(file MemFile) (*MemFileSystem, File, error)

NewSingleMemFileSystem creates and registers a new MemFileSystem containing a single MemFile that is returned as a File that can be used to access the file without knowing the file system. Closing the file system will make the File invalid.

func NotExistsIndex

func NotExistsIndex[F interface{ Exists() bool }](files []F) int

NotExistsIndex returns the slice index of the first FileReader where the Exists method returned false or -1 in case of no match.

func ParseRequestMultipartFormMemFiles

func ParseRequestMultipartFormMemFiles(request *http.Request, maxMemory int64) (map[string][]MemFile, error)

ParseRequestMultipartFormMemFiles parses the multipart form from the request and returns a map of form field name to MemFiles.

func ReadAllContext

func ReadAllContext(ctx context.Context, r io.Reader) ([]byte, error)

ReadAllContext reads all data from r until EOF is reached, another error is returned, or the context got canceled. It is identical to io.ReadAll except that it can be canceled via a context.

func ReadHeader

func ReadHeader(fr FileReader, maxNumBytes int) ([]byte, error)

ReadHeader reads up to maxNumBytes from the beginning of the passed FileReader. If fr is a MemFile then a slice of its FileData is returned without copying it.

func ReadHeaderString

func ReadHeaderString(fr FileReader, maxNumBytes int) (string, error)

ReadHeaderString reads up to maxNumBytes as string from the beginning of the passed FileReader. If fr is a MemFile then a slice of its FileData will be used as fast path.

func ReadMultipartFormMemFiles

func ReadMultipartFormMemFiles(ctx context.Context, form *multipart.Form) (map[string][]MemFile, error)

ReadMultipartFormMemFiles reads the multipart form and returns a map of form field name to MemFiles.

func Register

func Register(fs FileSystem) int

Register adds a file system or increments its reference count if it is already registered. The function returns the reference file system's reference count.

func Remove

func Remove(fileURIs ...string) error

Remove removes all files with fileURIs. If a file does not exist, then it is skipped and not reported as error.

func RemoveErrDoesNotExist

func RemoveErrDoesNotExist(err error) error

RemoveErrDoesNotExist returns nil if err wraps os.ErrNotExist, else err will be returned unchanged.

func RemoveFile

func RemoveFile(file File) error

RemoveFile removes a single file. It's just a wrapper for calling file.Remove(), useful mostly as callback for methods that list files to delete all files of a certain pattern. Or as a more elegant way to remove a file passed as string literal path:

fs.RemoveFile("/my/hardcoded.path")

func RemoveFiles

func RemoveFiles(files ...File) error

RemoveFiles removes all files. If a file does not exist, then it is skipped and not reported as error.

func RunFileSystemTests

func RunFileSystemTests(ctx context.Context, t *testing.T, fs FileSystem, name, prefix, testDir string)

RunFileSystemTests is a comprehensive test helper that tests all methods of a FileSystem interface implementation.

name is the expected name of the filesystem that will be verified against fs.Name(). prefix is the expected prefix of the filesystem that will be verified against fs.Prefix(). testDir is the directory path within the filesystem where test files will be created. It should be empty and will be cleaned up after tests.

func SameFile

func SameFile(a, b File) bool

SameFile returns if a and b describe the same file or directory

func ServeFileHTTP

func ServeFileHTTP(response http.ResponseWriter, request *http.Request, file FileReader, contentType ...string)

ServeFileHTTP serves the passed file with a Content-Type header via HTTP. If no contentType is passed then it will be deduced from the filename and if that fails from the content. A status code 404 error is returned if the file does not exist and a status code 500 error if there was any other error while reading it.

Uses http.ServeContent under the hood.

func ServeFileHTTPHandler

func ServeFileHTTPHandler(file FileReader, contentType ...string) http.Handler

ServeFileHTTPHandler returns a http.Handler that serves the passed file with a Content-Type header via HTTP. If no contentType is passed then it will be deduced from the filename and if that fails from the content. A status code 404 error is returned if the file does not exist and a status code 500 error if there was any other error while reading it.

Uses http.ServeContent under the hood.

func SortByLocalPath

func SortByLocalPath[F interface{ LocalPath() string }](files []F)

func SortByModified

func SortByModified[F interface{ Modified() time.Time }](files []File)

func SortByModifiedDirsFirst

func SortByModifiedDirsFirst(files []File)

func SortByName

func SortByName[F interface{ Name() string }](files []F)

func SortByNameDirsFirst

func SortByNameDirsFirst[F FileReader](files []F)

func SortByPath

func SortByPath[F interface{ Path() string }](files []F)

func SortBySize

func SortBySize[F interface{ Size() int64 }](files []F)

func Unregister

func Unregister(fs FileSystem) int

Unregister a file system decrements its reference count and removes it when the reference count reaches 0. If the file system is not registered, -1 is returned.

func WriteAllContext

func WriteAllContext(ctx context.Context, w io.Writer, data []byte) error

WriteAllContext writes all data wo the to w with a cancelable context.

func Zip

func Zip(ctx context.Context, files ...FileReader) ([]byte, error)

Zip the passed files using flate.BestCompression.

func ZipMemFiles

func ZipMemFiles(files ...MemFile) ([]byte, error)

ZipMemFiles zips the passed MemFiles using flate.BestCompression.

Types

type AppendFileSystem

type AppendFileSystem interface {
	FileSystem

	// Append appends data to the file at filePath, creating it if it does not exist.
	Append(ctx context.Context, filePath string, data []byte, perm []Permissions) error
}

AppendFileSystem can be implemented by file systems that can append to files more efficiently than using OpenAppendWriter.

type AppendWriterFileSystem

type AppendWriterFileSystem interface {
	FileSystem

	// OpenAppendWriter opens the file at filePath for appending,
	// creating it if it does not exist.
	OpenAppendWriter(filePath string, perm []Permissions) (WriteCloser, error)
}

AppendWriterFileSystem can be implemented by file systems that have native append writer functionality.

type ContentHashFunc

type ContentHashFunc func(ctx context.Context, reader io.Reader) (string, error)

ContentHashFunc is used tot return the string representation of a content hash by reading from an io.Reader until io.EOF or the context is cancelled.

var DefaultContentHash ContentHashFunc = fsimpl.DropboxContentHash

DefaultContentHash configures the default content hash function used by methods like File.ContentHash and FileReader.ContentHash.

func ContentHashFuncFrom

func ContentHashFuncFrom(h hash.Hash) ContentHashFunc

ContentHashFuncFrom returns a ContentHashFunc that uses a standard hash.Hash implementation to return the hash sum as hex encoded string.

type CopyFileSystem

type CopyFileSystem interface {
	FileSystem

	// CopyFile copies a single file.
	// buf must point to a []byte variable.
	// If that variable is initialized with a byte slice, then this slice will be used as buffer,
	// else a byte slice will be allocated for the variable.
	CopyFile(ctx context.Context, srcFile string, destFile string, buf *[]byte) error
}

CopyFileSystem can be implemented by file systems that have native file copying functionality.

If a file system does not implement this interface then it's functionality will be emulated with other methods.

type ErrAlreadyExists

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

ErrAlreadyExists is returned when a file already exists. It wraps os.ErrExist, check for this error type with:

errors.Is(err, os.ErrExist)

func NewErrAlreadyExists

func NewErrAlreadyExists(file File) ErrAlreadyExists

NewErrAlreadyExists returns a new ErrAlreadyExists

func (ErrAlreadyExists) Error

func (err ErrAlreadyExists) Error() string

func (ErrAlreadyExists) File

func (err ErrAlreadyExists) File() File

File returns the file that already exists

func (ErrAlreadyExists) Unwrap

func (ErrAlreadyExists) Unwrap() error

Unwrap returns os.ErrExist

type ErrDoesNotExist

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

ErrDoesNotExist is returned when a file does not exist and wraps os.ErrNotExist. Check for this error type with:

errors.Is(err, os.ErrNotExist)

Implements http.Handler by responding with http.NotFound.

func NewErrDoesNotExist

func NewErrDoesNotExist(file File) ErrDoesNotExist

NewErrDoesNotExist returns a new ErrDoesNotExist

func NewErrDoesNotExistFileReader

func NewErrDoesNotExistFileReader(fileReader FileReader) ErrDoesNotExist

NewErrDoesNotExistFileReader returns an ErrDoesNotExist error for a FileReader.

func NewErrPathDoesNotExist

func NewErrPathDoesNotExist(path string) ErrDoesNotExist

NewErrPathDoesNotExist returns an ErrDoesNotExist error for a file path.

func (ErrDoesNotExist) Error

func (err ErrDoesNotExist) Error() string

Error implements the error interface

func (ErrDoesNotExist) File

func (err ErrDoesNotExist) File() (file File, ok bool)

File returns the File that error concerns or false for ok if the error is not about a File but another type.

func (ErrDoesNotExist) FileReader

func (err ErrDoesNotExist) FileReader() (file FileReader, ok bool)

FileReader returns the FileReader that error concerns or false for ok if the error is not about a FileReader but another type.

func (ErrDoesNotExist) ServeHTTP

func (err ErrDoesNotExist) ServeHTTP(w http.ResponseWriter, r *http.Request)

func (ErrDoesNotExist) Unwrap

func (ErrDoesNotExist) Unwrap() error

Unwrap returns os.ErrNotExist

type ErrIsDirectory

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

ErrIsDirectory is returned when an operation is not possible because a file is a directory.

func NewErrIsDirectory

func NewErrIsDirectory(file any) ErrIsDirectory

NewErrIsDirectory returns a new ErrIsDirectory

func (ErrIsDirectory) Error

func (err ErrIsDirectory) Error() string

func (ErrIsDirectory) File

func (err ErrIsDirectory) File() (file File, ok bool)

File returns the File that error concerns or false for ok if the error is not about a File but another type.

func (ErrIsDirectory) FileReader

func (err ErrIsDirectory) FileReader() (file FileReader, ok bool)

FileReader returns the FileReader that error concerns or false for ok if the error is not about a FileReader but another type.

type ErrIsNotDirectory

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

ErrIsNotDirectory is returned when an operation is not possible because a file is not a directory.

func NewErrIsNotDirectory

func NewErrIsNotDirectory(file any) ErrIsNotDirectory

NewErrIsNotDirectory returns a new ErrIsNotDirectory

func (ErrIsNotDirectory) Error

func (err ErrIsNotDirectory) Error() string

func (ErrIsNotDirectory) File

func (err ErrIsNotDirectory) File() (file File, ok bool)

File returns the File that error concerns or false for ok if the error is not about a File but another type.

func (ErrIsNotDirectory) FileReader

func (err ErrIsNotDirectory) FileReader() (file FileReader, ok bool)

FileReader returns the FileReader that error concerns or false for ok if the error is not about a FileReader but another type.

type ErrPermission

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

ErrPermission is returned when an operation lacks permissions on a file. It wraps os.ErrPermission. Check for this error type with:

errors.Is(err, os.ErrPermission)

Implements http.Handler by responding with 403 Forbidden.

func NewErrPermission

func NewErrPermission(file File) ErrPermission

NewErrPermission returns a new ErrPermission

func (ErrPermission) Error

func (err ErrPermission) Error() string

func (ErrPermission) File

func (err ErrPermission) File() File

File returns the file that error concerns

func (ErrPermission) ServeHTTP

func (err ErrPermission) ServeHTTP(w http.ResponseWriter, r *http.Request)

func (ErrPermission) Unwrap

func (ErrPermission) Unwrap() error

Unwrap returns os.ErrPermission

type ErrUnsupported

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

func NewErrUnsupported

func NewErrUnsupported(fileSystem FileSystem, operation string) ErrUnsupported

NewErrUnsupported returns a new ErrUnsupported

func (ErrUnsupported) Error

func (err ErrUnsupported) Error() string

func (ErrUnsupported) Unwrap

func (ErrUnsupported) Unwrap() error

type Event

type Event uint32

Event reported for watched files.

This is a bitmask and some systems may send multiple operations at once. Use the Has... methods to check if an event has a certain operation.

func (Event) HasChmod

func (e Event) HasChmod() bool

func (Event) HasCreate

func (e Event) HasCreate() bool

func (Event) HasRemove

func (e Event) HasRemove() bool

func (Event) HasRename

func (e Event) HasRename() bool

func (Event) HasWrite

func (e Event) HasWrite() bool

func (Event) String

func (e Event) String() string

type ExistsFileSystem

type ExistsFileSystem interface {
	FileSystem

	// Exists returns if a file exists and is accessible.
	// Depending on the FileSystem implementation,
	// this could be faster than using Stat.
	// Note that a file could exist but might not be accessible.
	Exists(filePath string) bool
}

ExistsFileSystem can be implemented by file systems that can check file existence more efficiently than using Stat.

type File

type File string

File is a local file system path or a complete URI. It is a string underneath, so string literals can be passed everywhere a File is expected. Marshalling functions that use reflection will also work out of the box when they detect that File is of kind reflect.String. File implements FileReader.

func CleanFilePath

func CleanFilePath(uri string) File

CleanFilePath returns a File from uri with cleaned path and a file system prefix

func CurrentWorkingDir

func CurrentWorkingDir() File

CurrentWorkingDir returns the current working directory of the process. In case of an erorr, Exists() of the result File will return false.

func ExecutableFile

func ExecutableFile() File

ExecutableFile returns a File for the executable that started the current process. It wraps os.ExecutableFile, see https://golang.org/pkg/os/#ExecutableFile

func Filef

func Filef(format string, args ...any) File

Filef is a shortcut for File(fmt.Sprintf(format, args...))

func FilesFromStrings

func FilesFromStrings(fileURIs []string) []File

FilesFromStrings returns Files for the given fileURIs.

func HomeDir

func HomeDir() File

HomeDir returns the home directory of the current user.

It first calls os.UserHomeDir, which honors the $HOME environment variable on Unix and macOS, %USERPROFILE% on Windows, and $home on Plan 9. This lets tests, containers, and HOME=/other invocations override the resolved directory.

If os.UserHomeDir returns an error (for example when the relevant environment variable is unset) HomeDir falls back to looking up the current user's home via user.Current.

func JoinCleanFilePath

func JoinCleanFilePath(uriParts ...string) File

JoinCleanFilePath returns a File from joined and cleaned uriParts with a file system prefix

func MakeTempDir

func MakeTempDir() (File, error)

MakeTempDir makes and returns a new randomly named sub directory in TempDir(). Example:

tempDir, err := fs.MakeTempDir()
if err != nil {
    return err
}
defer tempDir.RemoveRecursive()
doThingsWith(tempDir)

func MustMakeTempDir

func MustMakeTempDir() File

MustMakeTempDir makes and returns a new randomly named sub directory in TempDir(). It panics on errors. Example:

tempDir := fs.MustMakeTempDir()
defer tempDir.RemoveRecursive()
doThingsWith(tempDir)

func SourceFile

func SourceFile() File

SourceFile returns the file of the caller of the current function.

func TempDir

func TempDir() File

TempDir returns the temp directory of the operating system

func TempFile

func TempFile(ext ...string) File

TempFile returns a randomly named File with an optional extension in the temp directory of the operating system. The returned File does not exist yet, it's just a path.

func TempFileCopy

func TempFileCopy(source FileReader) (File, error)

TempFileCopy copies the provided source file to the temp directory of the operating system using a random filename with the extension of the source file.

func (File) AbsPath

func (file File) AbsPath() string

AbsPath returns the absolute path of the file depending on the file system.

func (File) Append

func (file File) Append(ctx context.Context, data []byte, perm ...Permissions) error

Append appends data to the file.

func (File) AppendString

func (file File) AppendString(ctx context.Context, str string, perm ...Permissions) error

AppendString appends a string to the file.

func (File) CheckExists

func (file File) CheckExists() error

CheckExists returns an ErrDoesNotExist error if the file does not exist or ErrEmptyPath if the file path is empty.

func (File) CheckIsDir

func (file File) CheckIsDir() error

CheckIsDir returns an ErrDoesNotExist error if the file does not exist, ErrEmptyPath if the file path is empty, or ErrIsNotDirectory if a file exists, but is not a directory, or nil if the file is a directory.

func (File) ContentHash

func (file File) ContentHash() (string, error)

ContentHash returns the DefaultContentHash for the file. If the FileSystem implementation does not have this hash pre-computed, then the whole file is read to compute it. If the file is a directory, then an empty string will be returned.

func (File) ContentHashContext

func (file File) ContentHashContext(ctx context.Context) (string, error)

ContentHashContext returns the DefaultContentHash for the file. If the FileSystem implementation does not have this hash pre-computed, then the whole file is read to compute it. If the file is a directory, then an empty string will be returned.

func (file File) CreateSymbolicLink(target File) error

CreateSymbolicLink creates file as a symbolic link pointing to target. file is the link to be created; target is what the link points to.

Both files must belong to the same FileSystem, otherwise an error is returned. An error is also returned if the file system does not implement SymbolicLinkFileSystem.

The target path is stored as given. If you want a stable link regardless of where it is resolved from, pass an absolute target.

func (File) Dir

func (file File) Dir() File

Dir returns the parent directory of the File.

func (File) DirAndName

func (file File) DirAndName() (dir File, name string)

DirAndName returns the parent directory of filePath and the name with that directory of the last filePath element. If filePath is the root of the file system, then an empty string will be returned for name.

func (File) Exists

func (file File) Exists() bool

Exists returns if a file or directory with the path of File exists.

func (File) Ext

func (file File) Ext() string

Ext returns the extension of file name including the point, or an empty string.

Example:

File("image.png").Ext() == ".png"
File("dir.with.ext/file").Ext() == ""
File("dir.with.ext/file.ext").Ext() == ".ext"

func (File) ExtLower

func (file File) ExtLower() string

ExtLower returns the lower case extension of file name including the point, or an empty string. Example: File("Image.PNG").ExtLower() == ".png"

func (File) FileSystem

func (file File) FileSystem() FileSystem

FileSystem returns the FileSystem of the File. Defaults to Local if not a complete URI, or Invalid for an empty path.

func (File) GetXAttr

func (file File) GetXAttr(name string) ([]byte, error)

GetXAttr returns the value of the named extended attribute. Symbolic links are resolved to their target. Returns ErrUnsupported if the file system does not support extended attributes.

func (File) Glob

func (file File) Glob(pattern string) (iter.Seq2[File, []string], error)

Glob yields files and wildcard substituting path segments matching a path pattern.

The yielded path segments are the strings necessary to substitute all wildcard containing path segments in the pattern to form a valid path for a yielded file. This includes the name of the yielded file itself if the pattern contains wildcards for the last segment. Non wildcard segments are not included.

The syntax of patterns is the same as in path.Match. It always uses slash '/' as path segment separator independently of the file's file system.

A pattern ending with a slash '/' will match only directories.

Glob ignores file system errors such as I/O errors reading directories. The only possible returned error is path.ErrBadPattern, reporting that the pattern is malformed.

func (File) GobDecode

func (file File) GobDecode(gobBytes []byte) error

GobDecode decodes a file name and content from gobBytes and writes the content to this file ignoring the decoded name. Implements encoding/gob.GobDecoder.

func (File) GobEncode

func (file File) GobEncode() ([]byte, error)

GobEncode reads and gob encodes the file name and content, implementing encoding/gob.GobEncoder.

func (File) Group

func (file File) Group() (string, error)

Group returns the group owner of the file.

func (File) HasAbsPath

func (file File) HasAbsPath() bool

HasAbsPath returns whether the file has an absolute path depending on the file system.

func (File) Info

func (file File) Info() *FileInfo

Info returns FileInfo.

Use File.Stat to get a standard library io/fs.FileInfo.

func (File) IsDir

func (file File) IsDir() bool

IsDir returns if a directory with the path of File exists.

func (File) IsEmptyDir

func (file File) IsEmptyDir() bool

IsEmptyDir returns if file is an empty directory.

func (File) IsHidden

func (file File) IsHidden() bool

IsHidden returns true if the filename begins with a dot, or if on Windows the hidden file attribute is set.

func (File) IsReadable

func (file File) IsReadable() bool

IsReadable returns if the file exists and is readable.

func (File) IsRegular

func (file File) IsRegular() bool

IsRegular reports if this is a regular file.

func (file File) IsSymbolicLink() bool

IsSymbolicLink returns if the file is a symbolic link. Use File.CreateSymbolicLink and File.ReadSymbolicLink to create and resolve symbolic links.

func (File) IsWritable

func (file File) IsWritable() bool

IsWritable returns if the file exists and is writable, or in case it doesn't exist, if the parent directory exists and is writable.

func (File) Join

func (file File) Join(pathParts ...string) File

Join returns a new File with pathParts cleaned and joined to the current File's URI. Every element of pathParts is a subsequent directory or file that will be appended to the File URI with a path separator. The resulting URI path will be cleaned, removing relative directory names like "..".

func (File) Joinf

func (file File) Joinf(format string, args ...any) File

Joinf returns a new File with fmt.Sprintf(format, args...) cleaned and joined to the current File's URI. The resulting URI path will be cleaned, removing relative directory names like "..".

func (File) LGetXAttr

func (file File) LGetXAttr(name string) ([]byte, error)

LGetXAttr returns the value of the named extended attribute. Symbolic links are not resolved. Returns ErrUnsupported if the file system does not support extended attributes.

func (File) LListXAttr

func (file File) LListXAttr() ([]string, error)

LListXAttr returns the names of all extended attributes for the file. Symbolic links are not resolved. Returns ErrUnsupported if the file system does not support extended attributes.

func (File) LRemoveXAttr

func (file File) LRemoveXAttr(name string) error

LRemoveXAttr removes the named extended attribute from the file. Symbolic links are not resolved. Returns ErrUnsupported if the file system does not support extended attributes.

func (File) LSetXAttr

func (file File) LSetXAttr(name string, data []byte, flags ...int) error

LSetXAttr sets the value of the named extended attribute. Symbolic links are not resolved. The optional flags parameter controls the behavior (e.g., xattr.XATTR_CREATE, xattr.XATTR_REPLACE). Returns ErrUnsupported if the file system does not support extended attributes.

func (File) ListDir

func (file File) ListDir(callback func(File) error, patterns ...string) error

ListDir calls the passed callback function for every file and directory. If any patterns are passed, then only files with a name that matches at least one of the patterns are returned.

func (File) ListDirChan

func (file File) ListDirChan(cancel <-chan error, patterns ...string) (<-chan File, <-chan error)

ListDirChan returns listed files over a channel. An error or nil will returned from the error channel. The file channel will be closed after sending all files. If cancel is not nil and an error is sent to this channel, then the listing will be canceled and the error returned in the error channel returned by the method. See pipeline pattern: http://blog.golang.org/pipelines

func (File) ListDirContext

func (file File) ListDirContext(ctx context.Context, callback func(File) error, patterns ...string) error

ListDirContext calls the passed callback function for every file and directory in the directory. If any patterns are passed, then only files with a name that matches at least one of the patterns are returned. Canceling the context or returning an error from the callback will stop the listing and return the context or callback error.

func (File) ListDirInfo

func (file File) ListDirInfo(callback func(*FileInfo) error, patterns ...string) error

ListDirInfo calls the passed callback function for every file and directory in dirPath. If any patterns are passed, then only files with a name that matches at least one of the patterns are returned.

func (File) ListDirInfoContext

func (file File) ListDirInfoContext(ctx context.Context, callback func(*FileInfo) error, patterns ...string) error

ListDirInfoContext calls the passed callback function for every file and directory in dirPath. If any patterns are passed, then only files with a name that matches at least one of the patterns are returned.

func (File) ListDirInfoRecursive

func (file File) ListDirInfoRecursive(callback func(*FileInfo) error, patterns ...string) error

ListDirInfoRecursive calls the passed callback function for every file (not directory) in dirPath recursing into all sub-directories. If any patterns are passed, then only files (not directories) with a name that matches at least one of the patterns are returned.

func (File) ListDirInfoRecursiveContext

func (file File) ListDirInfoRecursiveContext(ctx context.Context, callback func(*FileInfo) error, patterns ...string) error

ListDirInfoRecursiveContext calls the passed callback function for every file (not directory) in dirPath recursing into all sub-directories. If any patterns are passed, then only files (not directories) with a name that matches at least one of the patterns are returned.

func (File) ListDirIter

func (file File) ListDirIter(patterns ...string) iter.Seq2[File, error]

ListDirIter returns an iterator that yields every file and directory in the directory. If any patterns are passed, then only files with a name that matches at least one of the patterns are returned. In case of an error, the iterator will yield InvalidFile and the error as last key and value and then stop the iteration.

func (File) ListDirIterContext

func (file File) ListDirIterContext(ctx context.Context, patterns ...string) iter.Seq2[File, error]

ListDirIterContext returns an iterator that yields every file and directory in the directory. If any patterns are passed, then only files with a name that matches at least one of the patterns are returned. In case of an error, the iterator will yield InvalidFile and the error as last key and value and then stop the iteration. Canceling the context will stop the iteration and yield the context error.

func (File) ListDirMax

func (file File) ListDirMax(max int, patterns ...string) (files []File, err error)

ListDirMax returns at most max files and directories in dirPath. A max value of -1 returns all files. If any patterns are passed, then only files or directories with a name that matches at least one of the patterns are returned.

func (File) ListDirMaxContext

func (file File) ListDirMaxContext(ctx context.Context, max int, patterns ...string) (files []File, err error)

ListDirMaxContext returns at most max files and directories in dirPath. A max value of -1 returns all files. If any patterns are passed, then only files or directories with a name that matches at least one of the patterns are returned.

func (File) ListDirRecursive

func (file File) ListDirRecursive(callback func(File) error, patterns ...string) error

ListDirRecursive returns only files. patterns are only applied to files, not to directories

func (File) ListDirRecursiveChan

func (file File) ListDirRecursiveChan(cancel <-chan error, patterns ...string) (<-chan File, <-chan error)

ListDirRecursiveChan returns listed files over a channel. An error or nil will returned from the error channel. The file channel will be closed after sending all files. If cancel is not nil and an error is sent to this channel, then the listing will be canceled and the error returned in the error channel returned by the method. See pipeline pattern: http://blog.golang.org/pipelines

func (File) ListDirRecursiveContext

func (file File) ListDirRecursiveContext(ctx context.Context, callback func(File) error, patterns ...string) error

ListDirRecursiveContext returns only files. patterns are only applied to files, not to directories

func (File) ListDirRecursiveIter

func (file File) ListDirRecursiveIter(patterns ...string) iter.Seq2[File, error]

ListDirRecursiveIter returns an iterator that yields every file and directory recursively in the directory and sub-directories. If any patterns are passed, then only files with a name that matches at least one of the patterns are returned. In case of an error, the iterator will yield InvalidFile and the error as last key and value and then stop the iteration.

func (File) ListDirRecursiveIterContext

func (file File) ListDirRecursiveIterContext(ctx context.Context, patterns ...string) iter.Seq2[File, error]

ListDirRecursiveIterContext returns an iterator that yields every file and directory recursively in the directory and sub-directories. If any patterns are passed, then only files with a name that matches at least one of the patterns are returned. In case of an error, the iterator will yield InvalidFile and the error as last key and value and then stop the iteration. Canceling the context will stop the iteration and yield the context error.

func (File) ListDirRecursiveMax

func (file File) ListDirRecursiveMax(max int, patterns ...string) (files []File, err error)

ListDirRecursiveMax returns at most max files from the directory and its sub-directories. A max value of -1 returns all files. If any patterns are passed, then only files with a name that matches at least one of the patterns are returned.

func (File) ListDirRecursiveMaxContext

func (file File) ListDirRecursiveMaxContext(ctx context.Context, max int, patterns ...string) (files []File, err error)

ListDirRecursiveMaxContext returns at most max files from the directory and its sub-directories. A max value of -1 returns all files. If any patterns are passed, then only files with a name that matches at least one of the patterns are returned.

func (File) ListXAttr

func (file File) ListXAttr() ([]string, error)

ListXAttr returns the names of all extended attributes for the file. Symbolic links are resolved to their target. Returns ErrUnsupported if the file system does not support extended attributes.

func (File) LocalPath

func (file File) LocalPath() string

LocalPath returns the cleaned local file-system path of the file, or an empty string if it is not on the local file system.

func (File) MakeAllDirs

func (file File) MakeAllDirs(perm ...Permissions) error

MakeAllDirs creates all directories up to this one. It does not return an error if the directories already exist.

func (File) MakeDir

func (file File) MakeDir(perm ...Permissions) error

MakeDir creates a directory if it does not exist yet. No error is returned if the directory already exists.

Compatible with os.MkdirAll: if the underlying filesystem reports the path already exists (a race with another goroutine or process creating the directory between the File.IsDir check and the FileSystem.MakeDir call), MakeDir re-stats the path. If the path is now a directory, returns nil (race winner created it; treat as success). If the path exists but is not a directory, returns a descriptive ErrIsNotDirectory.

func (File) Modified

func (file File) Modified() time.Time

Modified returns the modification time of the file, or a zero time.Time if the file does not exist.

func (File) MoveTo

func (file File) MoveTo(destination File) error

MoveTo moves and/or renames the file to destination. destination can be a directory or file-path and can be on another FileSystem. If the file and distination are using the LocalFileSystem but are on different volumes, then the file will be copied to the destination and then deleted.

When file and destination resolve to the same location, MoveTo returns nil without touching the file, matching the no-op behavior of os.Rename. See Move for the full contract.

func (File) MustGlob

func (file File) MustGlob(pattern string) iter.Seq2[File, []string]

MustGlob yields files and wildcard substituting path segments matching a path pattern.

The yielded path segments are the strings necessary to substitute all wildcard containing path segments in the pattern to form a valid path for a yielded file. This includes the name of the yielded file itself if the pattern contains wildcards for the last segment. Non wildcard segments are not included.

The syntax of patterns is the same as in path.Match. It always uses slash '/' as path segment separator independently of the file's file system.

A pattern ending with a slash '/' will match only directories.

MustGlob ignores file system errors such as I/O errors reading directories. The only possible panic is in case of a malformed pattern.

func (File) MustLocalPath

func (file File) MustLocalPath() string

MustLocalPath returns the cleaned local file-system path of the file, or panics if it is not on the local file system or an empty path.

func (File) Name

func (file File) Name() string

Name returns the name part of the file path, which is usually the string after the last path Separator.

func (File) OpenAppendWriter

func (file File) OpenAppendWriter(perm ...Permissions) (WriteCloser, error)

OpenAppendWriter opens the file for appending and returns a WriteCloser that has to be closed after writing.

func (File) OpenReadSeeker

func (file File) OpenReadSeeker() (ReadSeekCloser, error)

OpenReadSeeker opens the file and returns a ReadSeekCloser. If the FileSystem implementation doesn't support ReadSeekCloser, then the complete file is read into memory and wrapped with a ReadSeekCloser. Warning: this can use up a lot of memory for big files.

func (File) OpenReadWriter

func (file File) OpenReadWriter(perm ...Permissions) (ReadWriteSeekCloser, error)

OpenReadWriter opens the file for reading and writing and returns a ReadWriteSeekCloser that has to be closed.

func (File) OpenReader

func (file File) OpenReader() (ReadCloser, error)

OpenReader opens the file and returns a io/fs.File that has to be closed after reading.

func (File) OpenWriter

func (file File) OpenWriter(perm ...Permissions) (WriteCloser, error)

OpenWriter opens the file for writing and returns a WriteCloser that has to be closed after writing.

func (File) ParseRawURI

func (file File) ParseRawURI() (fs FileSystem, fsPath string)

ParseRawURI returns a FileSystem for the passed URI and the path component within that file system. Returns the local file system if no other file system could be identified.

func (File) Path

func (file File) Path() string

Path returns the cleaned path of the file. It may differ from the string value of File because it will be cleaned depending on the FileSystem.

func (File) PathWithSlashes

func (file File) PathWithSlashes() string

PathWithSlashes returns the cleaned path of the file always using the slash '/' as separator. It may differ from the string value of File because it will be cleaned depending on the FileSystem.

func (File) Permissions

func (file File) Permissions() Permissions

Permissions returns the file permissions, or NoPermissions if the file does not exist.

func (File) RawURI

func (file File) RawURI() string

RawURI returns the string value of File.

func (File) ReadAll

func (file File) ReadAll() (data []byte, err error)

ReadAll reads and returns all bytes of the file.

func (File) ReadAllContentHash

func (file File) ReadAllContentHash(ctx context.Context) (data []byte, hash string, err error)

ReadAllContentHash reads and returns all bytes of the file together with the DefaultContentHash.

func (File) ReadAllContext

func (file File) ReadAllContext(ctx context.Context) (data []byte, err error)

ReadAllContext reads and returns all bytes of the file.

func (File) ReadAllString

func (file File) ReadAllString() (string, error)

ReadAllString reads the complete file and returns the content as string.

func (File) ReadAllStringContext

func (file File) ReadAllStringContext(ctx context.Context) (string, error)

ReadAllStringContext reads the complete file and returns the content as string.

func (File) ReadFrom

func (file File) ReadFrom(reader io.Reader) (n int64, err error)

ReadFrom implements the io.ReaderFrom interface. The file is written with the existing permissions if it exists, or with the default write permissions if it does not exist yet.

func (File) ReadJSON

func (file File) ReadJSON(ctx context.Context, output any) error

ReadJSON reads and unmarshalles the JSON content of the file to output.

Returns a wrapped ErrUnmarshalJSON when the unmarshalling failed.

func (file File) ReadSymbolicLink() (File, error)

ReadSymbolicLink returns the target of the symbolic link at file. The returned File is the raw link target as stored on disk and may be relative to file's directory.

Returns an ErrUnsupported error if file's FileSystem does not implement SymbolicLinkFileSystem.

func (File) ReadXML

func (file File) ReadXML(ctx context.Context, output any) error

ReadXML reads and unmarshalles the XML content of the file to output.

Returns a wrapped ErrUnmarshalXML when the unmarshalling failed.

func (File) RelPathOf

func (file File) RelPathOf(target File) (string, error)

RelPathOf returns the path of target relative to file, like filepath.Rel but interpreted by file's FileSystem.

file is treated as the base; the result is the path that, when joined with file, refers to the same location as target. The result is cleaned and may contain ".." segments.

Both files must belong to the same FileSystem, otherwise an error is returned. An error is also returned if the file system does not implement RelPathFileSystem, or if target can't be made relative to file (for example when one path is absolute and the other is not, or when computing the relation would require knowing the current working directory).

func (File) Remove

func (file File) Remove() error

Remove deletes the file.

func (File) RemoveDirContents

func (file File) RemoveDirContents(patterns ...string) error

RemoveDirContents deletes all files in this directory, or if given all files with patterns from the this directory.

func (File) RemoveDirContentsContext

func (file File) RemoveDirContentsContext(ctx context.Context, patterns ...string) error

RemoveDirContentsContext deletes all files in this directory, or if given all files with patterns from the this directory.

func (File) RemoveDirContentsRecursive

func (file File) RemoveDirContentsRecursive() error

RemoveDirContentsRecursive deletes all files and directories in this directory recursively.

func (File) RemoveDirContentsRecursiveContext

func (file File) RemoveDirContentsRecursiveContext(ctx context.Context) error

RemoveDirContentsRecursiveContext deletes all files and directories in this directory recursively.

func (File) RemoveRecursive

func (file File) RemoveRecursive() error

RemoveRecursive deletes the file or if it's a directory the complete recursive directory tree.

func (File) RemoveRecursiveContext

func (file File) RemoveRecursiveContext(ctx context.Context) error

RemoveRecursiveContext deletes the file or if it's a directory the complete recursive directory tree.

func (File) RemoveXAttr

func (file File) RemoveXAttr(name string) error

RemoveXAttr removes the named extended attribute from the file. Symbolic links are resolved to their target. Returns ErrUnsupported if the file system does not support extended attributes.

func (File) Rename

func (file File) Rename(newName string) (renamedFile File, err error)

Rename changes the name of a file where newName is the name part after file.Dir(). Note: this does not move the file like in other rename implementations, it only changes the name of the file within its directory.

func (File) Renamef

func (file File) Renamef(newNameFormat string, args ...any) (renamedFile File, err error)

Renamef changes the name of a file where fmt.Sprintf(newNameFormat, args...) is the name part after file.Dir(). Note: this does not move the file like in other rename implementations, it only changes the name of the file within its directory.

func (File) SetGroup

func (file File) SetGroup(group string) error

SetGroup sets the group owner of the file.

func (File) SetPermissions

func (file File) SetPermissions(perm Permissions) error

SetPermissions sets the file permissions.

func (File) SetUser

func (file File) SetUser(user string) error

SetUser sets the user owner of the file.

func (File) SetXAttr

func (file File) SetXAttr(name string, data []byte, flags ...int) error

SetXAttr sets the value of the named extended attribute. Symbolic links are resolved to their target. The optional flags parameter controls the behavior (e.g., xattr.XATTR_CREATE, xattr.XATTR_REPLACE). Returns ErrUnsupported if the file system does not support extended attributes.

func (File) Size

func (file File) Size() int64

Size returns the size of the file or 0 if it does not exist or is a directory.

func (File) Stat

func (file File) Stat() (iofs.FileInfo, error)

Stat returns a standard library io/fs.FileInfo describing the file.

func (File) StdDirEntry

func (file File) StdDirEntry() StdDirEntry

StdDirEntry wraps the file as a StdDirEntry struct that implements the io/fs.DirEntry interface from the standard library for a File.

func (File) StdFS

func (file File) StdFS() StdFS

StdFS wraps the file as a StdFS struct that implements the io/fs.FS interface of the standard library for a File.

StdFS implements the following interfaces:

  • io/fs.FS
  • io/fs.SubFS
  • io/fs.StatFS
  • io/fs.GlobFS
  • io/fs.ReadDirFS
  • io/fs.ReadFileFS

func (File) String

func (file File) String() string

String implements the fmt.Stringer interface by returning the URL of the file.

func (File) ToAbsPath

func (file File) ToAbsPath() File

ToAbsPath returns the File with an absolute path depending on the file system.

func (File) Touch

func (file File) Touch(perm ...Permissions) error

Touch creates an empty file or updates the modification time of an existing file.

func (File) TrimExt

func (file File) TrimExt() File

TrimExt returns a File with a path where the extension is removed. Note that this does not rename an actual existing file.

func (File) Truncate

func (file File) Truncate(newSize int64) error

Truncate changes the size of the file. If the file is larger than newSize, it is truncated. If the file is smaller, it is extended with zeros.

func (File) URL

func (file File) URL() string

URL returns the URL of the file.

func (File) User

func (file File) User() (string, error)

User returns the user owner of the file.

func (File) VolumeName

func (file File) VolumeName() string

VolumeName returns the name of the volume at the beginning of the file path, or an empty string if the path has no volume. A volume is for example "C:" on Windows.

func (File) Watch

func (file File) Watch(onEvent func(File, Event)) (cancel func() error, err error)

Watch a file or directory for changes. If the file describes a directory, then changes directly within it will be reported. This does not apply to changes in deeper recursive sub-directories.

It is valid to watch a file with multiple callbacks. Calling the returned cancel function will cancel a particular watch.

func (File) WriteAll

func (file File) WriteAll(data []byte, perm ...Permissions) error

WriteAll writes all data to the file.

func (File) WriteAllContext

func (file File) WriteAllContext(ctx context.Context, data []byte, perm ...Permissions) error

WriteAllContext writes all data to the file.

func (File) WriteAllString

func (file File) WriteAllString(str string, perm ...Permissions) error

WriteAllString writes a string to the file.

func (File) WriteAllStringContext

func (file File) WriteAllStringContext(ctx context.Context, str string, perm ...Permissions) error

WriteAllStringContext writes a string to the file.

func (File) WriteJSON

func (file File) WriteJSON(ctx context.Context, input any, indent ...string) (err error)

WriteJSON marshals input to JSON and writes it as the file. Any indent arguments will be concanated and used as JSON line indentation.

Returns a wrapped ErrMarshalJSON when the marshalling failed.

func (File) WriteTo

func (file File) WriteTo(writer io.Writer) (n int64, err error)

WriteTo implements the io.WriterTo interface

func (File) WriteXML

func (file File) WriteXML(ctx context.Context, input any, indent ...string) (err error)

WriteXML marshals input to XML and writes it as the file. Any indent arguments will be concanated and used as XML line indentation.

Returns a wrapped ErrMarshalXML when the marshalling failed.

type FileInfo

type FileInfo struct {
	File        File
	Name        string
	Exists      bool
	IsDir       bool
	IsRegular   bool
	IsHidden    bool
	Size        int64
	Modified    time.Time
	Permissions Permissions
}

FileInfo is a snapshot of a file's stat information. In comparison to io/fs.FileInfo it's not an interface but a struct with public fields.

func NewFileInfo

func NewFileInfo(file File, info iofs.FileInfo, hidden bool) *FileInfo

NewFileInfo returns a FileInfo using the data from an io/fs.FileInfo as snapshot of an existing file. Use NewNonExistingFileInfo to get a FileInfo for non existing file.

func NewNonExistingFileInfo

func NewNonExistingFileInfo(file File) *FileInfo

NewNonExistingFileInfo returns a FileInfo for a potentially non existing file. FileInfo.Exists will be false, but the file may exist at any point of time. IsHidden will be true if the name starts with a dot.

func (*FileInfo) StdFileInfo

func (i *FileInfo) StdFileInfo() iofs.FileInfo

StdFileInfo returns an io/fs.FileInfo wrapper for the data stored in the FileInfo struct.

func (*FileInfo) Validate

func (i *FileInfo) Validate() error

Validate returns an error if the FileInfo is invalid.

type FileInfoCache

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

FileInfoCache is a cache with timeout for FileInfo data.

func NewFileInfoCache

func NewFileInfoCache(timeout time.Duration) *FileInfoCache

NewFileInfoCache returns a new FileInfoCache with timeout, or nil if timeout is zero. It is valid to call the methods of FileInfoCache for a nil pointer.

func (*FileInfoCache) Delete

func (cache *FileInfoCache) Delete(path string)

Delete deletes the FileInfo with path if was cached.

func (*FileInfoCache) Get

func (cache *FileInfoCache) Get(path string) (info *FileInfo, ok bool)

Get returns the FileInfo for a path or nil and false if there is no FileInfo for the path or the FileInfo has timed out.

func (*FileInfoCache) Put

func (cache *FileInfoCache) Put(path string, info *FileInfo)

Put puts or updates a FileInfo for a path.

type FileReader

type FileReader interface {
	// String returns the name and meta information for the FileReader.
	String() string

	// Name returns the name of the file
	Name() string

	// Ext returns the extension of file name including the point, or an empty string.
	Ext() string

	// LocalPath returns the cleaned local file-system path of the file backing the FileReader,
	// or an empty string if the FileReader is not backed by a local file.
	LocalPath() string

	// Size returns the size of the file
	Size() int64

	// Exists returns if file or data for the implementation exists
	Exists() bool

	// CheckExists return an ErrDoesNotExist error
	// if the file does not exist.
	CheckExists() error

	// IsDir returns true if the file is a directory.
	IsDir() bool

	// CheckIsDir return an ErrDoesNotExist error
	// if the file does not exist, ErrEmptyPath
	// if the file path is empty, or ErrIsNotDirectory
	// if a file exists, but is not a directory,
	// or nil if the file is a directory.
	CheckIsDir() error

	// ContentHash returns the DefaultContentHash for the file.
	ContentHash() (string, error)

	// ContentHashContext returns the DefaultContentHash for the file.
	ContentHashContext(ctx context.Context) (string, error)

	// ReadAll reads and returns all bytes of the file
	ReadAll() (data []byte, err error)

	// ReadAllContext reads and returns all bytes of the file
	ReadAllContext(context.Context) (data []byte, err error)

	// ReadAllContentHash reads and returns all bytes of the file
	// together with the DefaultContentHash.
	ReadAllContentHash(context.Context) (data []byte, hash string, err error)

	// ReadAllString reads the complete file and returns the content as string.
	ReadAllString() (string, error)

	// ReadAllStringContext reads the complete file and returns the content as string.
	ReadAllStringContext(context.Context) (string, error)

	// WriteTo implements the io.WriterTo interface
	WriteTo(writer io.Writer) (n int64, err error)

	// OpenReader opens the file and returns a ReadCloser that has to be closed after reading
	OpenReader() (ReadCloser, error)

	// OpenReadSeeker opens the file and returns a ReadSeekCloser.
	// Use OpenReader if seeking is not necessary because implementations
	// may need additional buffering to support seeking or not support it at all.
	OpenReadSeeker() (ReadSeekCloser, error)

	// ReadJSON reads and unmarshalles the JSON content of the file to output.
	ReadJSON(ctx context.Context, output any) error

	// ReadXML reads and unmarshalles the XML content of the file to output.
	ReadXML(ctx context.Context, output any) error

	// GobEncode reads and gob encodes the file name and content,
	// implementing encoding/gob.GobEncoder.
	GobEncode() ([]byte, error)
}

func AsFileReaders

func AsFileReaders[F FileReader](files []F) []FileReader

AsFileReaders converts the passed files to []FileReader. If the passed files are already of type []FileReader then they are returned as is.

func FileReaderWithName

func FileReaderWithName(fileReader FileReader, name string) FileReader

FileReaderWithName returns a new FileReader that wraps the passed fileReader, but the Name() method returns the passed name instead of name of the wrapped fileReader.

func FileReadersFromStrings

func FileReadersFromStrings(fileURIs []string) []FileReader

FileReadersFromStrings returns FileReaders for the given fileURIs.

type FileSystem

type FileSystem interface {
	// ReadableWritable returns whether the file system is readable and/or writable.
	ReadableWritable() (readable, writable bool)

	// RootDir returns the file system root directory.
	RootDir() File

	// ID returns a unique identifier for the FileSystem.
	ID() (string, error)

	// Prefix returns the URI prefix for this file system (e.g., "file://", "sftp://").
	Prefix() string

	// Name returns the name of the FileSystem implementation.
	Name() string

	// String returns a descriptive string for the FileSystem implementation.
	String() string

	// URL returns a full URL which is Prefix() + cleanPath.
	// Note that the passed cleanPath will not be cleaned
	// by the FileSystem implementation.
	URL(cleanPath string) string

	// CleanPathFromURI returns the clean path part of a URI
	// specific to the implementation of the FileSystem.
	// It's the inverse of the URL method.
	CleanPathFromURI(uri string) string

	// JoinCleanFile joins the file system prefix with uriParts
	// into a File with clean path and prefix.
	JoinCleanFile(uriParts ...string) File

	// JoinCleanPath joins the uriParts into a cleaned path
	// of the file system style without the file system prefix.
	JoinCleanPath(uriParts ...string) string

	// SplitPath returns all Separator() delimited components of filePath
	// without the file system prefix.
	SplitPath(filePath string) []string

	// Separator returns the path separator for the file system.
	Separator() string

	// IsAbsPath indicates if the passed filePath is absolute.
	// For local file systems, this checks if the path starts with / or a volume name.
	// For remote file systems, this may check if the path contains the file system prefix.
	IsAbsPath(filePath string) bool

	// AbsPath returns the passed filePath in absolute form.
	// For relative paths, this converts them to absolute paths.
	// If the absolute path cannot be determined, returns the original filePath.
	AbsPath(filePath string) string

	// MatchAnyPattern returns true if name matches any of patterns,
	// or if len(patterns) == 0.
	// The match per pattern works like path.Match or filepath.Match.
	MatchAnyPattern(name string, patterns []string) (bool, error)

	// SplitDirAndName returns the parent directory of filePath and the name within that directory of the last filePath element.
	// If filePath is the root of the file system, then an empty string will be returned for name.
	SplitDirAndName(filePath string) (dir, name string)

	// Stat returns file information for the file or directory at filePath.
	// Returns an error if the file does not exist or is not accessible.
	Stat(filePath string) (iofs.FileInfo, error)

	// IsHidden returns if a file or directory is hidden depending
	// on the definition of hidden files of the file system.
	// Files and directories starting with a dot are typically considered hidden.
	IsHidden(filePath string) bool

	// IsSymbolicLink returns if a file or directory is a symbolic link.
	// Not all file systems support symbolic links.
	IsSymbolicLink(filePath string) bool

	// ListDirInfo calls the passed callback function for every file and directory in dirPath.
	// If any patterns are passed, then only files or directories with a name that matches
	// at least one of the patterns are returned.
	// Canceling the context or returning an error from the callback
	// will stop the listing and return the context or callback error.
	// Does not recurse into subdirectories.
	ListDirInfo(ctx context.Context, dirPath string, callback func(*FileInfo) error, patterns []string) error

	// MakeDir creates a single directory at dirPath.
	// Does not create parent directories if they don't exist.
	// Use MakeAllDirs for recursive directory creation.
	MakeDir(dirPath string, perm []Permissions) error

	// OpenReader opens the file at filePath for reading.
	OpenReader(filePath string) (ReadCloser, error)

	// OpenWriter opens the file at filePath for writing, creating it if it does not exist
	// or truncating it if it does exist.
	OpenWriter(filePath string, perm []Permissions) (WriteCloser, error)

	// OpenReadWriter opens the file at filePath for reading and writing,
	// creating it if it does not exist but not truncating it if it does exist.
	OpenReadWriter(filePath string, perm []Permissions) (ReadWriteSeekCloser, error)

	// Remove deletes the file or empty directory at filePath.
	// For non-empty directories, behavior is implementation-specific.
	// Use RemoveRecursive on File for recursive deletion.
	Remove(filePath string) error

	// Close closes the file system or does nothing if it is not closable.
	Close() error
}

FileSystem is an interface that has to be implemented for a file system to be accessible via this package.

func GetFileSystem

func GetFileSystem(uriParts ...string) FileSystem

GetFileSystem returns a FileSystem for the passed URI. Returns the local file system if no other file system could be identified. The URI can be passed as parts that will be joined according to the file system.

func GetFileSystemByPrefixOrNil

func GetFileSystemByPrefixOrNil(prefix string) FileSystem

GetFileSystemByPrefixOrNil returns the file system registered with the passed prefix, or nil if it can't be found.

func ParseRawURI

func ParseRawURI(uri string) (fs FileSystem, fsPath string)

ParseRawURI returns a FileSystem for the passed URI and the path component within that file system. Returns the local file system if no other file system could be identified.

func RegisteredFileSystems

func RegisteredFileSystems() []FileSystem

RegisteredFileSystems returns the registered file systems sorted by their prefix.

type FullyFeaturedFileSystem

FullyFeaturedFileSystem is an interface that extends the FileSystem interface with additional methods for all optionally optimized file system operations.

type GroupFileSystem

type GroupFileSystem interface {
	FileSystem

	// Group returns the group owner of the file at filePath.
	Group(filePath string) (string, error)

	// SetGroup sets the group owner of the file at filePath.
	SetGroup(filePath string, group string) error
}

GroupFileSystem can be implemented by file systems that support file group operations.

type InvalidFileSystem

type InvalidFileSystem string

InvalidFileSystem is a file system where all operations are invalid. A File with an empty path defaults to this FS.

The underlying string value is the optional name of the file system and will be added to the URI prefix. It can be used to register different dummy file systems for debugging or testing purposes.

var (
	// Local is the local file system
	Local = &LocalFileSystem{
		DefaultCreatePermissions:    UserAndGroupReadWrite,
		DefaultCreateDirPermissions: UserAndGroupReadWrite,
	}

	Invalid InvalidFileSystem
)

func (InvalidFileSystem) AbsPath

func (fs InvalidFileSystem) AbsPath(filePath string) string

func (InvalidFileSystem) Append

func (InvalidFileSystem) Append(ctx context.Context, filePath string, data []byte, perm []Permissions) error

func (InvalidFileSystem) CleanPathFromURI

func (fs InvalidFileSystem) CleanPathFromURI(uri string) string

func (InvalidFileSystem) Close

func (InvalidFileSystem) Close() error

func (InvalidFileSystem) CopyFile

func (InvalidFileSystem) CopyFile(ctx context.Context, srcFile string, destFile string, buf *[]byte) error

func (InvalidFileSystem) Exists

func (InvalidFileSystem) Exists(filePath string) bool

func (InvalidFileSystem) Group

func (InvalidFileSystem) Group(filePath string) (string, error)

func (InvalidFileSystem) ID

func (fs InvalidFileSystem) ID() (string, error)

func (InvalidFileSystem) IsAbsPath

func (InvalidFileSystem) IsAbsPath(filePath string) bool

func (InvalidFileSystem) IsHidden

func (InvalidFileSystem) IsHidden(filePath string) bool
func (InvalidFileSystem) IsSymbolicLink(filePath string) bool

func (InvalidFileSystem) JoinCleanFile

func (fs InvalidFileSystem) JoinCleanFile(uri ...string) File

func (InvalidFileSystem) JoinCleanPath

func (fs InvalidFileSystem) JoinCleanPath(uriParts ...string) string

func (InvalidFileSystem) ListDirInfo

func (InvalidFileSystem) ListDirInfo(ctx context.Context, dirPath string, callback func(*FileInfo) error, patterns []string) error

func (InvalidFileSystem) ListDirInfoRecursive

func (InvalidFileSystem) ListDirInfoRecursive(ctx context.Context, dirPath string, callback func(*FileInfo) error, patterns []string) error

func (InvalidFileSystem) ListDirMax

func (InvalidFileSystem) ListDirMax(ctx context.Context, dirPath string, n int, patterns []string) (files []File, err error)

func (InvalidFileSystem) MakeAllDirs

func (InvalidFileSystem) MakeAllDirs(dirPath string, perm []Permissions) error

func (InvalidFileSystem) MakeDir

func (InvalidFileSystem) MakeDir(dirPath string, perm []Permissions) error

func (InvalidFileSystem) MatchAnyPattern

func (InvalidFileSystem) MatchAnyPattern(name string, patterns []string) (bool, error)

func (InvalidFileSystem) Move

func (InvalidFileSystem) Move(filePath string, destPath string) error

func (InvalidFileSystem) Name

func (fs InvalidFileSystem) Name() string

func (InvalidFileSystem) OpenAppendWriter

func (InvalidFileSystem) OpenAppendWriter(filePath string, perm []Permissions) (WriteCloser, error)

func (InvalidFileSystem) OpenReadWriter

func (InvalidFileSystem) OpenReadWriter(filePath string, perm []Permissions) (ReadWriteSeekCloser, error)

func (InvalidFileSystem) OpenReader

func (InvalidFileSystem) OpenReader(filePath string) (ReadCloser, error)

func (InvalidFileSystem) OpenWriter

func (InvalidFileSystem) OpenWriter(filePath string, perm []Permissions) (WriteCloser, error)

func (InvalidFileSystem) Prefix

func (fs InvalidFileSystem) Prefix() string

func (InvalidFileSystem) ReadAll

func (InvalidFileSystem) ReadAll(ctx context.Context, filePath string) ([]byte, error)

func (InvalidFileSystem) ReadableWritable

func (InvalidFileSystem) ReadableWritable() (readable, writable bool)

func (InvalidFileSystem) Remove

func (InvalidFileSystem) Remove(filePath string) error

func (InvalidFileSystem) Rename

func (InvalidFileSystem) Rename(filePath string, newName string) (string, error)

func (InvalidFileSystem) RootDir

func (InvalidFileSystem) RootDir() File

func (InvalidFileSystem) Separator

func (InvalidFileSystem) Separator() string

func (InvalidFileSystem) SetGroup

func (InvalidFileSystem) SetGroup(filePath string, group string) error

func (InvalidFileSystem) SetPermissions

func (InvalidFileSystem) SetPermissions(filePath string, perm Permissions) error

func (InvalidFileSystem) SetUser

func (InvalidFileSystem) SetUser(filePath string, user string) error

func (InvalidFileSystem) SplitDirAndName

func (fs InvalidFileSystem) SplitDirAndName(filePath string) (dir, name string)

func (InvalidFileSystem) SplitPath

func (fs InvalidFileSystem) SplitPath(filePath string) []string

func (InvalidFileSystem) Stat

func (InvalidFileSystem) Stat(filePath string) (iofs.FileInfo, error)

func (InvalidFileSystem) String

func (fs InvalidFileSystem) String() string

func (InvalidFileSystem) Touch

func (InvalidFileSystem) Touch(filePath string, perm []Permissions) error

func (InvalidFileSystem) Truncate

func (InvalidFileSystem) Truncate(filePath string, size int64) error

func (InvalidFileSystem) URL

func (fs InvalidFileSystem) URL(cleanPath string) string

func (InvalidFileSystem) User

func (InvalidFileSystem) User(filePath string) (string, error)

func (InvalidFileSystem) VolumeName

func (InvalidFileSystem) VolumeName(filePath string) string

func (InvalidFileSystem) Watch

func (InvalidFileSystem) Watch(filePath string, onEvent func(File, Event)) (cancel func() error, err error)

func (InvalidFileSystem) WriteAll

func (InvalidFileSystem) WriteAll(ctx context.Context, filePath string, data []byte, perm []Permissions) error

type ListDirMaxFileSystem

type ListDirMaxFileSystem interface {
	FileSystem

	// ListDirMax returns at most max files and directories in dirPath.
	// A max value of -1 returns all files.
	// If any patterns are passed, then only files or directories with a name that matches
	// at least one of the patterns are returned.
	ListDirMax(ctx context.Context, dirPath string, max int, patterns []string) ([]File, error)
}

ListDirMaxFileSystem can be implemented by file systems that can efficiently list a limited number of directory entries.

type ListDirRecursiveFileSystem

type ListDirRecursiveFileSystem interface {
	FileSystem

	// ListDirInfoRecursive calls the passed callback function for every file (not directory) in dirPath
	// recursing into all sub-directories.
	// If any patterns are passed, then only files (not directories) with a name that matches
	// at least one of the patterns are returned.
	ListDirInfoRecursive(ctx context.Context, dirPath string, callback func(*FileInfo) error, patterns []string) error
}

ListDirRecursiveFileSystem can be implemented by file systems that can efficiently list directory entries recursively.

type LocalFileSystem

type LocalFileSystem struct {
	// DefaultCreatePermissions are the default file permissions used for creating new files
	DefaultCreatePermissions Permissions
	// DefaultCreateDirPermissions are the default file permissions used for creating new directories
	DefaultCreateDirPermissions Permissions

	WatchEventLogger Logger
	WatchErrorLogger Logger
	// contains filtered or unexported fields
}

LocalFileSystem implements FileSystem for the local file system.

func (*LocalFileSystem) AbsPath

func (local *LocalFileSystem) AbsPath(filePath string) string

AbsPath expands a leading "~" to the current user's home directory and then resolves the path via filepath.Abs. If resolution fails the (tilde-expanded) input is returned unchanged.

func (*LocalFileSystem) Append

func (local *LocalFileSystem) Append(ctx context.Context, filePath string, data []byte, perm []Permissions) error

Append opens filePath in append mode via LocalFileSystem.OpenAppendWriter and writes data. A short write is reported as io.ErrShortWrite. ctx is only checked before opening; the write itself is not cancelable.

func (*LocalFileSystem) CleanPathFromURI

func (local *LocalFileSystem) CleanPathFromURI(uri string) string

CleanPathFromURI strips a leading LocalPrefix, ensures a leading separator, runs filepath.Clean, and finally expands a leading "~".

func (*LocalFileSystem) Close

func (*LocalFileSystem) Close() error

Close is a no-op for the local file system; there are no long-lived resources outside the lazily started fsnotify watcher, which is tied to the process lifetime.

func (*LocalFileSystem) CopyFile

func (local *LocalFileSystem) CopyFile(ctx context.Context, srcFilePath string, destFilePath string, buf *[]byte) error

CopyFile copies srcFilePath to destFilePath using io.CopyBuffer. If both paths refer to the same inode (os.SameFile) the call is a no-op. The destination is created with the source file's mode bits and is truncated if it already exists.

buf controls the copy buffer:

  • nil pointer: a one-shot buffer is allocated for this call only (no buffer reuse).
  • pointer to a nil/empty slice: a fresh buffer of copyBufferSize is allocated and stored back through buf for reuse by later calls.
  • pointer to a non-empty slice: that slice is used as-is.

ctx is only checked before the copy starts; the copy itself is not cancelable.

func (local *LocalFileSystem) CreateSymbolicLink(targetPath, linkPath string) error

CreateSymbolicLink implements SymbolicLinkFileSystem by creating a symbolic link at linkPath pointing to targetPath via os.Symlink. A leading "~" in either path is expanded. On Windows this typically requires the "Create symbolic links" privilege or Developer Mode.

func (*LocalFileSystem) GetXAttr

func (local *LocalFileSystem) GetXAttr(filePath string, name string, followSymlinks bool) ([]byte, error)

GetXAttr returns the value of the named extended attribute via the xattr package (xattr.Get when followSymlinks is true, xattr.LGet otherwise).

func (*LocalFileSystem) Group

func (local *LocalFileSystem) Group(filePath string) (string, error)

func (*LocalFileSystem) ID

func (local *LocalFileSystem) ID() (string, error)

ID returns "/" as a placeholder. It does not currently identify the underlying physical file system.

func (*LocalFileSystem) IsAbsPath

func (local *LocalFileSystem) IsAbsPath(filePath string) bool

IsAbsPath reports whether filePath is absolute using filepath.IsAbs, so the rules are platform-specific (e.g. drive-letter prefixes count on Windows).

func (*LocalFileSystem) IsHidden

func (local *LocalFileSystem) IsHidden(filePath string) bool

IsHidden reports whether the file is hidden. A name beginning with "." is considered hidden on every platform; additionally on Windows the FILE_ATTRIBUTE_HIDDEN attribute is checked. On Unix the attribute check is a no-op. Errors from the attribute lookup are logged to stderr and treated as not-hidden.

func (local *LocalFileSystem) IsSymbolicLink(filePath string) bool

IsSymbolicLink reports whether filePath is a symbolic link using os.Lstat. Any stat error (including not-exist) returns false.

func (*LocalFileSystem) JoinCleanFile

func (local *LocalFileSystem) JoinCleanFile(uri ...string) File

JoinCleanFile is a thin wrapper over LocalFileSystem.JoinCleanPath that returns a File.

func (*LocalFileSystem) JoinCleanPath

func (local *LocalFileSystem) JoinCleanPath(uriParts ...string) string

JoinCleanPath strips a leading LocalPrefix from the first element, joins the parts with filepath.Join, URL-unescapes the result on a best-effort basis (a decoding error keeps the escaped form), cleans it, and finally expands a leading "~".

func (*LocalFileSystem) ListDirInfo

func (local *LocalFileSystem) ListDirInfo(ctx context.Context, dirPath string, callback func(*FileInfo) error, patterns []string) (err error)

ListDirInfo reads dirPath in batches of 256 entries using os.File.ReadDir, honoring ctx cancellation between batches. Each entry is filtered through LocalFileSystem.MatchAnyPattern and its hidden flag is computed via the same rules as LocalFileSystem.IsHidden. The function returns ErrEmptyPath for an empty dirPath and ErrIsNotDirectory when dirPath exists but is not a directory.

func (*LocalFileSystem) ListDirMax

func (local *LocalFileSystem) ListDirMax(ctx context.Context, dirPath string, max int, patterns []string) (files []File, err error)

ListDirMax returns up to max entries of dirPath. A negative max means "all entries" and is read in 64-name batches via os.File.Readdirnames; a positive max preallocates the result slice and reads exactly enough names to satisfy the cap. max == 0 returns nil without touching the disk. Entries are filtered by LocalFileSystem.MatchAnyPattern. Cancellation is checked between batches. Symbolic semantics match LocalFileSystem.ListDirInfo (same error types for empty / not-a-directory).

func (*LocalFileSystem) ListXAttr

func (local *LocalFileSystem) ListXAttr(filePath string, followSymlinks bool) ([]string, error)

ListXAttr returns the names of all extended attributes for filePath using the xattr package. If followSymlinks is true the symlink target's attributes are read (xattr.List); otherwise the link's own attributes are read (xattr.LList). Extended-attribute support is platform- and filesystem-dependent (e.g. tmpfs and FAT do not support xattrs).

func (*LocalFileSystem) MakeAllDirs

func (local *LocalFileSystem) MakeAllDirs(dirPath string, perm []Permissions) error

MakeAllDirs implements MakeAllDirsFileSystem by calling os.MkdirAll. The same permission and umask-workaround rules as LocalFileSystem.MakeDir apply; the umask chmod is issued for every path component that the call may have created.

func (*LocalFileSystem) MakeDir

func (local *LocalFileSystem) MakeDir(dirPath string, perm []Permissions) error

MakeDir creates a single directory at dirPath via os.Mkdir. Permissions are joined with LocalFileSystem.DefaultCreateDirPermissions and ORed with the platform-specific extraDirPermissions (the execute bits on Unix, zero on Windows). On Unix, an explicit os.Chmod is issued afterward when OthersWrite is requested because os.Mkdir honors umask and may drop that bit. os.ErrExist is translated to ErrAlreadyExists (and os.ErrNotExist in the parent path to ErrDoesNotExist).

func (*LocalFileSystem) MatchAnyPattern

func (local *LocalFileSystem) MatchAnyPattern(name string, patterns []string) (bool, error)

MatchAnyPattern returns true if name matches any of patterns, or if len(patterns) == 0. The match per pattern works like path.Match or filepath.Match

func (*LocalFileSystem) Move

func (local *LocalFileSystem) Move(filePath string, destPath string) error

Move moves filePath to destPath. If filePath is a directory, it is moved *into* destPath using the base name of filePath as the new child name.

When filePath and destPath resolve to the same location after cleaning, Move returns nil without touching the file, matching the no-op behavior of os.Rename for same-path renames.

Move first tries os.Rename, which is atomic but only works within the same underlying filesystem. If the OS returns a cross-device error (EXDEV on Unix, ERROR_NOT_SAME_DEVICE on Windows) it falls back to CopyRecursive followed by os.RemoveAll. The fallback is not atomic and uses context.Background, so it is not cancelable.

func (*LocalFileSystem) Name

func (local *LocalFileSystem) Name() string

Name returns the human readable name "local file system".

func (*LocalFileSystem) OpenAppendWriter

func (local *LocalFileSystem) OpenAppendWriter(filePath string, perm []Permissions) (WriteCloser, error)

OpenAppendWriter opens filePath with O_WRONLY|O_CREATE|O_APPEND, so writes are positioned at end-of-file. The file is created with permissions joined from perm and LocalFileSystem.DefaultCreatePermissions when it doesn't yet exist.

func (*LocalFileSystem) OpenReadWriter

func (local *LocalFileSystem) OpenReadWriter(filePath string, perm []Permissions) (ReadWriteSeekCloser, error)

OpenReadWriter opens filePath read-write with O_RDWR|O_CREATE. The file is created with permissions joined from perm and LocalFileSystem.DefaultCreatePermissions when it doesn't yet exist. Existing content is preserved (no O_TRUNC).

func (*LocalFileSystem) OpenReader

func (local *LocalFileSystem) OpenReader(filePath string) (ReadCloser, error)

OpenReader opens filePath read-only via os.OpenFile with O_RDONLY. OS errors are mapped through [wrapOSErr]. The returned *os.File must be closed by the caller.

func (*LocalFileSystem) OpenWriter

func (local *LocalFileSystem) OpenWriter(filePath string, perm []Permissions) (WriteCloser, error)

OpenWriter opens filePath write-only with O_WRONLY|O_CREATE|O_TRUNC, truncating any existing content. The file is created with permissions joined from perm and LocalFileSystem.DefaultCreatePermissions when it doesn't yet exist.

func (*LocalFileSystem) Prefix

func (local *LocalFileSystem) Prefix() string

Prefix returns LocalPrefix ("file://").

func (*LocalFileSystem) ReadAll

func (local *LocalFileSystem) ReadAll(ctx context.Context, filePath string) ([]byte, error)

ReadAll reads filePath in one shot using os.ReadFile. ctx is only checked before the read starts; the read itself is not cancelable. OS errors are mapped through [wrapOSErr].

func (local *LocalFileSystem) ReadSymbolicLink(linkPath string) (targetPath string, err error)

ReadSymbolicLink implements SymbolicLinkFileSystem by returning the target of the symbolic link at linkPath via os.Readlink. The returned path is the raw link target as stored on disk, so it may be relative to linkPath's directory. A leading "~" in linkPath is expanded.

func (*LocalFileSystem) ReadableWritable

func (local *LocalFileSystem) ReadableWritable() (readable, writable bool)

ReadableWritable always returns true, true because the local file system is read-write at the file-system level (individual files may still be denied access by their OS permissions).

func (*LocalFileSystem) RelPath

func (local *LocalFileSystem) RelPath(basePath, targPath string) (string, error)

RelPath implements RelPathFileSystem by delegating to filepath.Rel after expanding a leading "~" in both paths.

func (*LocalFileSystem) Remove

func (local *LocalFileSystem) Remove(filePath string) error

Remove deletes filePath via os.Remove. Directories must be empty; for recursive removal use CopyRecursive / os.RemoveAll callers at a higher level. OS errors are mapped through [wrapOSErr].

func (*LocalFileSystem) RemoveXAttr

func (local *LocalFileSystem) RemoveXAttr(filePath string, name string, followSymlinks bool) error

RemoveXAttr removes the named extended attribute via the xattr package (xattr.Remove when followSymlinks is true, xattr.LRemove otherwise).

func (*LocalFileSystem) Rename

func (local *LocalFileSystem) Rename(filePath string, newName string) (newPath string, err error)

Rename renames the file at filePath to newName within the same directory using os.Rename. newName must be a leaf name without any Separator (otherwise an error is returned); the new full path is built from filepath.Dir(filePath) and newName and returned to the caller. A missing source file yields ErrDoesNotExist.

func (*LocalFileSystem) RootDir

func (local *LocalFileSystem) RootDir() File

RootDir returns the platform-specific root directory: "/" on Unix and `C:\` on Windows.

func (*LocalFileSystem) Separator

func (local *LocalFileSystem) Separator() string

Separator returns Separator, which is the platform-specific filepath.Separator as a string ("/" on Unix, "\\" on Windows).

func (*LocalFileSystem) SetGroup

func (local *LocalFileSystem) SetGroup(filePath string, group string) error

func (*LocalFileSystem) SetPermissions

func (local *LocalFileSystem) SetPermissions(filePath string, perm Permissions) error

SetPermissions overwrites only the 9 os.ModePerm bits of filePath via os.Chmod. Special bits (setuid, setgid, sticky) and the file-type bits already on the file are preserved.

func (*LocalFileSystem) SetUser

func (local *LocalFileSystem) SetUser(filePath string, username string) error

func (*LocalFileSystem) SetXAttr

func (local *LocalFileSystem) SetXAttr(filePath string, name string, data []byte, flags int, followSymlinks bool) error

SetXAttr sets the value of the named extended attribute via the xattr package (xattr.SetWithFlags when followSymlinks is true, otherwise xattr.LSetWithFlags). The flags parameter is passed through unchanged and accepts values like xattr.XATTR_CREATE and xattr.XATTR_REPLACE.

func (*LocalFileSystem) SplitDirAndName

func (*LocalFileSystem) SplitDirAndName(filePath string) (dir, name string)

SplitDirAndName expands a leading "~", honors the platform-specific volume prefix (e.g. `C:` on Windows), and splits filePath into its parent directory and last element.

func (*LocalFileSystem) SplitPath

func (local *LocalFileSystem) SplitPath(filePath string) []string

SplitPath trims an optional LocalPrefix, expands a leading "~", and splits on Separator. Leading and trailing separators are dropped, so the result has no empty elements. An empty or root-only path returns nil.

func (*LocalFileSystem) Stat

func (local *LocalFileSystem) Stat(filePath string) (iofs.FileInfo, error)

Stat expands a leading "~" and calls os.Stat. A non-existent path is returned as ErrDoesNotExist; other errors are passed through unwrapped.

func (*LocalFileSystem) String

func (local *LocalFileSystem) String() string

String implements fmt.Stringer and returns the [Name] followed by " with prefix " and [Prefix].

func (*LocalFileSystem) Touch

func (local *LocalFileSystem) Touch(filePath string, perm []Permissions) error

Touch updates the access and modification times of an existing file to now via os.Chtimes. If filePath does not exist, an empty file is created using the supplied Permissions joined with LocalFileSystem.DefaultCreatePermissions.

func (*LocalFileSystem) Truncate

func (local *LocalFileSystem) Truncate(filePath string, newSize int64) error

Truncate sets filePath to newSize using os.Truncate. Returns ErrDoesNotExist if the file is missing and ErrIsDirectory if filePath is a directory. A no-op is performed when the file already has the requested size.

func (*LocalFileSystem) URL

func (local *LocalFileSystem) URL(cleanPath string) string

URL returns the LocalPrefix followed by the absolute path with platform separators converted to forward slashes, so a Windows path like `C:\dir\file` becomes "file://C:/dir/file".

func (*LocalFileSystem) User

func (local *LocalFileSystem) User(filePath string) (string, error)

func (*LocalFileSystem) VolumeName

func (local *LocalFileSystem) VolumeName(filePath string) string

VolumeName returns the volume prefix of filePath via filepath.VolumeName after expanding a leading "~". On Unix the result is always empty.

func (*LocalFileSystem) Watch

func (local *LocalFileSystem) Watch(filePath string, onEvent func(File, Event)) (cancel func() error, err error)

Watch registers onEvent for changes to filePath using fsnotify. A single fsnotify.Watcher is lazily created and shared by all watches on this LocalFileSystem; the first call starts the dispatch goroutine. Multiple callbacks per path are supported and stored in a per-path map. The returned cancel function deregisters this specific callback and only removes the underlying fsnotify watch when the last callback for filePath is gone. For every event the watcher dispatches callbacks registered at both the event path and its parent directory, so a callback registered on a directory automatically receives events for entries inside it. Errors and (when configured) raw events are forwarded to LocalFileSystem.WatchErrorLogger and LocalFileSystem.WatchEventLogger. Panics from a callback are recovered and logged to WatchErrorLogger.

func (*LocalFileSystem) WriteAll

func (local *LocalFileSystem) WriteAll(ctx context.Context, filePath string, data []byte, perm []Permissions) error

WriteAll writes data to filePath in one shot using os.WriteFile, creating or truncating the file with permissions joined from perm and LocalFileSystem.DefaultCreatePermissions. ctx is only checked before the write starts; the write itself is not cancelable.

type Logger

type Logger interface {
	// Printf formats and logs a message according to a format specifier.
	// It follows the same formatting rules as fmt.Printf.
	Printf(format string, args ...any)
}

Logger is an interface for logging formatted messages. It provides a Printf method similar to fmt.Printf but allows different implementations for various logging backends.

Logger can be used for error logging, debugging output, or any formatted message output within the fs package.

func WriterLogger

func WriterLogger(w io.Writer) Logger

WriterLogger returns a Logger that writes formatted output to the given io.Writer. The logger uses fmt.Fprintf internally to format and write the log messages. Any errors from the write operation are silently ignored.

This is useful for directing log output to files, buffers, network connections, or any other io.Writer implementation. Common use cases include logging to os.Stderr, os.Stdout, or a log file.

Example:

// Log to stderr
logger := WriterLogger(os.Stderr)
logger.Printf("error processing file: %s", err)

// Log to a file
f, _ := os.Create("app.log")
defer f.Close()
logger := WriterLogger(f)
logger.Printf("started at %s", time.Now())

type LoggerFunc

type LoggerFunc func(format string, args ...any)

LoggerFunc is a function type that implements the Logger interface. It allows any function with the signature func(string, ...any) to be used as a Logger. This is useful for creating inline logger implementations or wrapping existing logging functions without defining a new type.

Example:

logger := LoggerFunc(func(format string, args ...any) {
	log.Printf("[FS] " + format, args...)
})
logger.Printf("operation completed: %s", filename)

func (LoggerFunc) Printf

func (f LoggerFunc) Printf(format string, args ...any)

Printf calls the underlying function, satisfying the Logger interface.

type MakeAllDirsFileSystem

type MakeAllDirsFileSystem interface {
	FileSystem

	// MakeAllDirs creates all directories in dirPath recursively,
	// similar to mkdir -p.
	MakeAllDirs(dirPath string, perm []Permissions) error
}

MakeAllDirsFileSystem can be implemented by file systems that have native recursive directory creation functionality.

If a file system does not implement this interface then its functionality will be emulated with other methods.

type MemDir

type MemDir string

MemDir implements FileReader for an in-memory directory that is represented by nothing but its path string.

It is the directory counterpart of MemFile: a small, simple value type that carries no backing file system and no directory contents. Like MemFile it is meant to be passed by value.

All path methods always use '/' as separator. A backslash '\' is treated as an ordinary character, not as a path separator.

Because a MemDir has no contents, every method that would read file data fails with an ErrIsDirectory error. Methods that are valid for a directory, like IsDir, CheckIsDir and ContentHash, behave like their File counterparts for a directory.

Note that MemDir fails reads more eagerly than a File backed by the local file system: there OpenReader succeeds for a directory (because os.Open does) and only the subsequent Read returns an "is a directory" error. MemDir instead returns ErrIsDirectory immediately from OpenReader and OpenReadSeeker, matching the in-memory MemFileSystem which also rejects opening a directory for reading up front.

MemDir implements the following interfaces:

  • FileReader
  • io.WriterTo
  • gob.GobEncoder
  • gob.GobDecoder
  • fmt.Stringer

func (MemDir) CheckExists

func (d MemDir) CheckExists() error

CheckExists returns an ErrDoesNotExist error if the directory does not exist.

func (MemDir) CheckIsDir

func (d MemDir) CheckIsDir() error

CheckIsDir returns an ErrEmptyPath error if the path is empty, or nil because a MemDir is always a directory.

func (MemDir) CleanPath

func (d MemDir) CleanPath() MemDir

CleanPath returns the path with "." and ".." path elements resolved, redundant slashes removed and trailing slashes trimmed, using '/' as separator. An empty path returns an empty MemDir.

func (MemDir) ContentHash

func (d MemDir) ContentHash() (string, error)

ContentHash returns an empty string because a MemDir is a directory, matching the behavior of File.ContentHash for a directory.

func (MemDir) ContentHashContext

func (d MemDir) ContentHashContext(ctx context.Context) (string, error)

ContentHashContext returns an empty string because a MemDir is a directory, matching the behavior of File.ContentHashContext for a directory.

func (MemDir) Dir

func (d MemDir) Dir() MemDir

Dir returns the parent directory path as a MemDir, using '/' as separator and ignoring trailing slashes.

If the path contains no slash then an empty MemDir is returned. If the path starts with a slash and has no further slashes then the root "/" is returned. The Dir of the root "/" is an empty MemDir.

func (MemDir) DirAndName

func (d MemDir) DirAndName() (dir MemDir, name string)

DirAndName returns the parent directory path as a MemDir together with the name of the last path element. It is equivalent to calling Dir and Name, see those methods for details.

func (MemDir) Exists

func (d MemDir) Exists() bool

Exists returns true if the MemDir has a non empty path.

func (MemDir) Ext

func (d MemDir) Ext() string

Ext returns the extension of the directory name including the point, or an empty string. '/' is used as separator and trailing slashes are ignored.

func (MemDir) ExtLower

func (d MemDir) ExtLower() string

ExtLower returns the lower case extension of the directory name including the point, or an empty string.

func (*MemDir) GobDecode

func (d *MemDir) GobDecode(gobBytes []byte) error

GobDecode decodes the directory path from gobBytes, implementing encoding/gob.GobDecoder.

func (MemDir) GobEncode

func (d MemDir) GobEncode() ([]byte, error)

GobEncode gob encodes the directory path, implementing encoding/gob.GobEncoder.

func (MemDir) IsDir

func (MemDir) IsDir() bool

IsDir always returns true for a MemDir.

func (MemDir) Join

func (d MemDir) Join(parts ...string) MemDir

Join returns a new MemDir with the passed parts appended to the current path, using '/' as separator.

A trailing slash on the current path is ignored, empty parts and slashes at the boundary between joined elements are collapsed so the result has no empty path elements, but special elements like "." or ".." are not resolved. Use CleanPath for that.

func (MemDir) LocalPath

func (MemDir) LocalPath() string

LocalPath always returns an empty string for a MemDir.

func (MemDir) Name

func (d MemDir) Name() string

Name returns the name of the directory. If the path contains a slash then only the last path element will be returned. Trailing slashes are ignored.

func (MemDir) OpenReadSeeker

func (d MemDir) OpenReadSeeker() (ReadSeekCloser, error)

OpenReadSeeker returns an ErrIsDirectory error because a MemDir is a directory.

Unlike a local file system File, whose OpenReadSeeker succeeds for a directory and only fails on the subsequent Read, MemDir reports the ErrIsDirectory error here immediately.

func (MemDir) OpenReader

func (d MemDir) OpenReader() (ReadCloser, error)

OpenReader returns an ErrIsDirectory error because a MemDir is a directory.

Unlike a local file system File, whose OpenReader succeeds for a directory and only fails on the subsequent Read, MemDir reports the ErrIsDirectory error here immediately.

func (MemDir) PrettyString

func (d MemDir) PrettyString() string

PrettyString implements the pretty.Stringer interface to provide a compact representation of the MemDir in error messages and pretty-printed output.

func (MemDir) ReadAll

func (d MemDir) ReadAll() (data []byte, err error)

ReadAll returns an ErrIsDirectory error because a MemDir is a directory.

func (MemDir) ReadAllContentHash

func (d MemDir) ReadAllContentHash(ctx context.Context) (data []byte, hash string, err error)

ReadAllContentHash returns an ErrIsDirectory error because a MemDir is a directory.

func (MemDir) ReadAllContext

func (d MemDir) ReadAllContext(ctx context.Context) (data []byte, err error)

ReadAllContext returns an ErrIsDirectory error because a MemDir is a directory.

func (MemDir) ReadAllString

func (d MemDir) ReadAllString() (string, error)

ReadAllString returns an ErrIsDirectory error because a MemDir is a directory.

func (MemDir) ReadAllStringContext

func (d MemDir) ReadAllStringContext(ctx context.Context) (string, error)

ReadAllStringContext returns an ErrIsDirectory error because a MemDir is a directory.

func (MemDir) ReadJSON

func (d MemDir) ReadJSON(ctx context.Context, output any) error

ReadJSON returns an ErrIsDirectory error because a MemDir is a directory.

func (MemDir) ReadXML

func (d MemDir) ReadXML(ctx context.Context, output any) error

ReadXML returns an ErrIsDirectory error because a MemDir is a directory.

func (MemDir) Size

func (MemDir) Size() int64

Size always returns 0 for a MemDir.

func (MemDir) Stat

func (d MemDir) Stat() (iofs.FileInfo, error)

Stat returns a io/fs.FileInfo describing the MemDir.

func (MemDir) String

func (d MemDir) String() string

String returns the metadata of the directory formatted as a string. String implements the fmt.Stringer interface.

func (MemDir) WriteTo

func (d MemDir) WriteTo(writer io.Writer) (n int64, err error)

WriteTo returns an ErrIsDirectory error because a MemDir is a directory. WriteTo implements the io.WriterTo interface.

type MemFile

type MemFile struct {
	FileName string `json:"filename"`
	FileData []byte `json:"data,omitempty"`
}

MemFile implements FileReader with a filename and an in memory byte slice. It exposes FileName and FileData as exported struct fields to emphasize its simple nature as just an wrapper around a name and some bytes.

As a small an simple struct MemFile is usually passed by value. This is why NewMemFile does not return a pointer.

The FileName can mirror the complete path of a file or directory on a file system, but the most common simple case is just a name without any slashes and path semantics. When the FileName contains slashes, the path related methods like Name, Dir, DirAndName, Ext and CleanPath interpret it as a '/' separated path. A FileName ending with a slash marks the MemFile as a directory (see IsDir), in which case FileData is ignored.

Note that the ReadAll and ReadAllContext methods return FileData directly without copying it to optimize performance. So be careful when modifying the FileData bytes of a MemFile. Since MemFile implements FileReader, any function accepting a FileReader parameter may call these methods and receive a reference to the internal data without copying. This includes functions like ReadMemFile and ReadMemFileRename which will share the FileData when the input is a MemFile.

MemFile implements the following interfaces:

  • FileReader
  • io.Writer
  • io.WriterTo
  • io.ReaderAt
  • json.Marshaler
  • json.Unmarshaler
  • gob.GobEncoder
  • gob.GobDecoder
  • fmt.Stringer

func NewMemFile

func NewMemFile(name string, data []byte) MemFile

NewMemFile returns a new MemFile by value (not a pointer). MemFile should be passed by value because it's a small, simple struct containing only a string and a slice (both reference types internally). Passing by value is more efficient and idiomatic for such lightweight types.

The passed data slice is used directly without copying it, so be careful when modifying the data after passing it to this function.

func NewMemFileWriteJSON

func NewMemFileWriteJSON(name string, input any, indent ...string) (MemFile, error)

NewMemFileWriteJSON returns a new MemFile by value with the input mashalled to JSON as FileData. Any indent arguments will be concanated and used as JSON line indentation.

Returns a wrapped ErrMarshalJSON when the marshalling failed.

func NewMemFileWriteXML

func NewMemFileWriteXML(name string, input any, indent ...string) (MemFile, error)

NewMemFileWriteXML returns a new MemFile by value with the input mashalled to XML as FileData. Any indent arguments will be concanated and used as XML line indentation.

Returns a wrapped ErrMarshalXML when the marshalling failed.

func ReadAllMemFile

func ReadAllMemFile(ctx context.Context, r io.Reader, name string) (MemFile, error)

ReadAllMemFile returns a new MemFile by value with the data from ReadAllContext(r) and the passed name. It reads all data from r until EOF is reached, another error is returned, or the context got canceled.

func ReadMemFile

func ReadMemFile(ctx context.Context, fileReader FileReader) (MemFile, error)

ReadMemFile returns a new MemFile by value with name and data from fileReader. If the passed fileReader is a MemFile then its FileData is used directly without copying it.

func ReadMemFileRename

func ReadMemFileRename(ctx context.Context, fileReader FileReader, name string) (MemFile, error)

ReadMemFileRename returns a new MemFile by value with the data from fileReader and the passed name. If the passed fileReader is a MemFile then its FileData is used directly without copying it.

func UnzipToMemFiles

func UnzipToMemFiles(ctx context.Context, zipFile FileReader) ([]MemFile, error)

UnzipToMemFiles unzips the passed zipFile as MemFiles.

func (MemFile) CheckExists

func (f MemFile) CheckExists() error

CheckExists return an ErrDoesNotExist error if the file does not exist.

func (MemFile) CheckIsDir

func (f MemFile) CheckIsDir() error

CheckIsDir returns nil if the MemFile is a directory (its FileName ends with a slash), ErrEmptyPath if the FileName is empty, or an ErrIsNotDirectory error otherwise.

func (MemFile) CleanPath

func (f MemFile) CleanPath() string

CleanPath returns the FileName with "." and ".." path elements resolved, redundant slashes removed and trailing slashes trimmed, using '/' as separator. An empty FileName returns an empty string.

func (MemFile) ContentHash

func (f MemFile) ContentHash() (string, error)

ContentHash returns the DefaultContentHash for the file, or an empty string if the MemFile is a directory.

func (MemFile) ContentHashContext

func (f MemFile) ContentHashContext(ctx context.Context) (string, error)

ContentHashContext returns the DefaultContentHash for the file, or an empty string if the MemFile is a directory.

func (MemFile) Dir

func (f MemFile) Dir() MemFile

Dir returns the parent directory of the FileName as a MemFile with nil FileData and the FileName truncated up to and including the last slash. Because the returned FileName ends with a slash (or is empty) the resulting MemFile is considered a directory.

If FileName contains no slash then an empty MemFile is returned.

func (MemFile) DirAndName

func (f MemFile) DirAndName() (dir MemFile, name string)

DirAndName returns the parent directory of the FileName as a MemFile together with the name of the last path element. It is equivalent to calling Dir and Name, see those methods for details, but computes both results in a single scan.

func (MemFile) Exists

func (f MemFile) Exists() bool

Exists returns true if the MemFile has non empty FileName. It's valid to call this method on a nil pointer, will return false in this case.

func (MemFile) Ext

func (f MemFile) Ext() string

Ext returns the extension of the file or directory name including the point, or an empty string. '/' is used as separator and a trailing slash is ignored.

func (MemFile) ExtLower

func (f MemFile) ExtLower() string

ExtLower returns the lower case extension of the FileName including the point, or an empty string.

func (*MemFile) GobDecode

func (f *MemFile) GobDecode(gobBytes []byte) error

GobDecode decodes gobBytes file name and content, implementing encoding/gob.GobDecoder.

func (MemFile) GobEncode

func (f MemFile) GobEncode() ([]byte, error)

GobEncode gob encodes the file name and content, implementing encoding/gob.GobEncoder.

func (MemFile) IsDir

func (f MemFile) IsDir() bool

IsDir returns true if the FileName ends with a slash. In that case the MemFile is considered a directory and FileData is ignored.

func (MemFile) LocalPath

func (MemFile) LocalPath() string

LocalPath always returns an empty string for a MemFile.

func (MemFile) Name

func (f MemFile) Name() string

Name returns the name of the file or directory, which is the last element of the FileName path. A single trailing slash marks a directory (see IsDir) and is ignored, so the name before it is returned.

func (MemFile) OpenReadSeeker

func (f MemFile) OpenReadSeeker() (ReadSeekCloser, error)

OpenReadSeeker opens the file and returns a ReadSeekCloser, or an ErrIsDirectory error if the MemFile is a directory. Use OpenReader if seeking is not necessary because implementations may need additional buffering to support seeking or not support it at all.

func (MemFile) OpenReader

func (f MemFile) OpenReader() (ReadCloser, error)

OpenReader opens the file and returns a io/fs.File that has to be closed after reading, or an ErrIsDirectory error if the MemFile is a directory.

func (MemFile) PrettyString

func (f MemFile) PrettyString() string

PrettyString implements the pretty.Stringer interface to provide a compact representation of the MemFile in error messages and pretty-printed output.

func (MemFile) ReadAll

func (f MemFile) ReadAll() (data []byte, err error)

ReadAll returns the FileData without copying it, or an ErrIsDirectory error if the MemFile is a directory.

Be careful when modifying the returned data as it shares the same underlying array with the MemFile's FileData.

func (MemFile) ReadAllContentHash

func (f MemFile) ReadAllContentHash(ctx context.Context) (data []byte, hash string, err error)

ReadAllContentHash returns the FileData without copying it together with the DefaultContentHash, or an ErrIsDirectory error if the MemFile is a directory.

Be careful when modifying the returned data as it shares the same underlying array with the MemFile's FileData.

func (MemFile) ReadAllContext

func (f MemFile) ReadAllContext(ctx context.Context) (data []byte, err error)

ReadAllContext returns the FileData without copying it, or an ErrIsDirectory error if the MemFile is a directory.

Be careful when modifying the returned data as it shares the same underlying array with the MemFile's FileData.

func (MemFile) ReadAllString

func (f MemFile) ReadAllString() (string, error)

ReadAllString returns the FileData as string, or an ErrIsDirectory error if the MemFile is a directory.

func (MemFile) ReadAllStringContext

func (f MemFile) ReadAllStringContext(ctx context.Context) (string, error)

ReadAllStringContext returns the FileData as string, or an ErrIsDirectory error if the MemFile is a directory.

func (MemFile) ReadAt

func (f MemFile) ReadAt(p []byte, off int64) (n int, err error)

ReadAt reads len(p) bytes into p starting at offset off in the underlying input source. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered.

When ReadAt returns n < len(p), it returns a non-nil error explaining why more bytes were not returned. In this respect, ReadAt is stricter than Read.

If the n = len(p) bytes returned by ReadAt are at the end of the input source, ReadAt returns err == nil.

Clients of ReadAt can execute parallel ReadAt calls on the same input source.

ReadAt implements the interface io.ReaderAt. It returns an ErrIsDirectory error if the MemFile is a directory.

func (MemFile) ReadJSON

func (f MemFile) ReadJSON(ctx context.Context, output any) error

ReadJSON reads and unmarshalles the JSON content of the file to output.

Returns an ErrIsDirectory error if the MemFile is a directory, or a wrapped ErrUnmarshalJSON when the unmarshalling failed.

func (MemFile) ReadXML

func (f MemFile) ReadXML(ctx context.Context, output any) error

ReadXML reads and unmarshalles the XML content of the file to output.

Returns an ErrIsDirectory error if the MemFile is a directory, or a wrapped ErrUnmarshalXML when the unmarshalling failed.

func (MemFile) Size

func (f MemFile) Size() int64

Size returns the size of the file

func (MemFile) Stat

func (f MemFile) Stat() (iofs.FileInfo, error)

Stat returns a io/fs.FileInfo describing the MemFile.

func (MemFile) String

func (f MemFile) String() string

String returns the metadata of the file formatted as a string. String implements the fmt.Stringer interface.

func (MemFile) WithData

func (f MemFile) WithData(data []byte) MemFile

WithData returns a MemFile with the passed data and the same name as the original MemFile. Use WithName to derive a MemFile with the same data but a different name.

The passed data slice is used directly without copying it, so be careful when modifying the data after passing it to this function.

func (MemFile) WithName

func (f MemFile) WithName(name string) MemFile

WithName returns a MemFile with the passed name as its complete FileName and the same shared data as the original MemFile. Use WithData to derive a MemFile with the same name but different data.

Note that name replaces the whole FileName including any path, so WithName is not symmetric with the Name method which only returns the last path element. To change just the name while keeping the directory, prepend the FileName of the Dir method:

f = f.WithName(f.Dir().FileName + newName)

func (*MemFile) Write

func (f *MemFile) Write(b []byte) (int, error)

Write appends the passed bytes to the FileData, implementing the io.Writer interface.

func (*MemFile) WriteJSON

func (f *MemFile) WriteJSON(ctx context.Context, input any, indent ...string) (err error)

WriteJSON mashalles input to JSON and writes it as the file. Any indent arguments will be concanated and used as JSON line indentation.

Returns a wrapped ErrMarshalJSON when the marshalling failed.

func (MemFile) WriteTo

func (f MemFile) WriteTo(writer io.Writer) (n int64, err error)

WriteTo implements the io.WriterTo interface. It returns an ErrIsDirectory error if the MemFile is a directory.

func (*MemFile) WriteXML

func (f *MemFile) WriteXML(ctx context.Context, input any, indent ...string) (err error)

WriteXML mashalles input to XML and writes it as the file. Any indent arguments will be concanated and used as XML line indentation.

Returns a wrapped ErrMarshalXML when the marshalling failed.

type MemFileSystem

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

MemFileSystem is a fully featured thread-safe file system implementation that stores all files and directories in random access memory.

Inner Workings

The file system is organized as a tree structure where each node (memFileNode) represents either a file or directory. Directory nodes contain a map of child nodes indexed by name. Files store their content as byte slices ([]byte) in the MemFile.FileData field.

All operations are protected by a read-write mutex (sync.RWMutex) to ensure thread-safety. Read operations (Stat, OpenReader, ListDirInfo) acquire read locks, while write operations (OpenWriter, MakeDir, Remove) acquire write locks.

File I/O is implemented using custom reader/writer types that operate directly on the in-memory byte slices:

  • OpenReader returns a fsimpl.ReadonlyFileBuffer wrapping the file's data
  • OpenWriter returns a memFileWriter that appends or overwrites data
  • OpenReadWriter returns a memFileReadWriter with full seek support

The file system supports configurable path separators ("/" or "\") and optional volume names (e.g., "C:") for Windows-style paths. Each instance is registered globally with a unique ID (memory address by default) and can be accessed via URIs like "mem://<id>/path/to/file".

Use Cases

Useful as a mock file system for tests or for caching of slow file systems. All data is lost when the file system is closed or the process terminates.

func NewMemFileSystem

func NewMemFileSystem(separator string, initialFiles ...MemFile) (*MemFileSystem, error)

func (*MemFileSystem) AbsPath

func (fs *MemFileSystem) AbsPath(filePath string) string

func (*MemFileSystem) AddMemFile

func (fs *MemFileSystem) AddMemFile(f MemFile, modified time.Time) (File, error)

AddMemFile adds a MemFile to the file system with the given modified time. The MemFile.FileName can be a path with the path separator of the MemFileSystem, in which case all directories of the path are created.

func (*MemFileSystem) Append

func (fs *MemFileSystem) Append(ctx context.Context, filePath string, data []byte, perm []Permissions) error

func (*MemFileSystem) CleanPathFromURI

func (fs *MemFileSystem) CleanPathFromURI(uri string) string

func (*MemFileSystem) Clear

func (fs *MemFileSystem) Clear()

func (*MemFileSystem) Close

func (fs *MemFileSystem) Close() error

func (*MemFileSystem) CopyFile

func (fs *MemFileSystem) CopyFile(ctx context.Context, srcFile string, destFile string, buf *[]byte) error
func (fs *MemFileSystem) CreateSymbolicLink(targetPath, linkPath string) error

CreateSymbolicLink creates a symbolic link at linkPath pointing to targetPath. targetPath is stored verbatim, so it may be relative to linkPath's directory or absolute.

func (*MemFileSystem) Exists

func (fs *MemFileSystem) Exists(filePath string) bool

func (*MemFileSystem) GetXAttr

func (fs *MemFileSystem) GetXAttr(filePath string, name string, _ bool) ([]byte, error)

GetXAttr returns the bytes stored for the named extended attribute. If the attribute is not set, an error is returned.

func (*MemFileSystem) Group

func (fs *MemFileSystem) Group(filePath string) (string, error)

Group returns the per-node group string previously set via SetGroup, or the empty string if none was set.

func (*MemFileSystem) ID

func (fs *MemFileSystem) ID() (string, error)

func (*MemFileSystem) IsAbsPath

func (fs *MemFileSystem) IsAbsPath(filePath string) bool

func (*MemFileSystem) IsHidden

func (*MemFileSystem) IsHidden(filePath string) bool
func (fs *MemFileSystem) IsSymbolicLink(filePath string) bool

func (*MemFileSystem) JoinCleanFile

func (fs *MemFileSystem) JoinCleanFile(uri ...string) File

func (*MemFileSystem) JoinCleanPath

func (fs *MemFileSystem) JoinCleanPath(uriParts ...string) string

func (*MemFileSystem) ListDirInfo

func (fs *MemFileSystem) ListDirInfo(ctx context.Context, dirPath string, callback func(*FileInfo) error, patterns []string) error

func (*MemFileSystem) ListDirInfoRecursive

func (fs *MemFileSystem) ListDirInfoRecursive(ctx context.Context, dirPath string, callback func(*FileInfo) error, patterns []string) error

ListDirInfoRecursive calls callback for every file (not directory) in dirPath and its sub-directories. Pattern matching applies only to files; sub-directories are always descended into. Entries are visited in sorted name order for determinism.

func (*MemFileSystem) ListDirMax

func (fs *MemFileSystem) ListDirMax(ctx context.Context, dirPath string, max int, patterns []string) ([]File, error)

ListDirMax returns at most max files and directories in dirPath matching any of the patterns. A max value of -1 returns all matches. Results are sorted by name for deterministic iteration.

func (*MemFileSystem) ListXAttr

func (fs *MemFileSystem) ListXAttr(filePath string, _ bool) ([]string, error)

ListXAttr returns the names of all extended attributes set on the node at filePath. MemFileSystem does not support symbolic links to other nodes, so the followSymlinks argument is ignored.

func (*MemFileSystem) MakeAllDirs

func (fs *MemFileSystem) MakeAllDirs(dirPath string, perm []Permissions) error

func (*MemFileSystem) MakeDir

func (fs *MemFileSystem) MakeDir(dirPath string, perm []Permissions) error

func (*MemFileSystem) MatchAnyPattern

func (*MemFileSystem) MatchAnyPattern(name string, patterns []string) (bool, error)

func (*MemFileSystem) Move

func (fs *MemFileSystem) Move(filePath string, destPath string) error

Move moves the node at filePath to destPath. If destPath resolves to an existing directory the source is moved *into* it using its base name; otherwise destPath is treated as the new full path. The destination must not already exist as a file or non-directory node.

When filePath and destPath resolve to the same location after cleaning, Move returns nil without touching the node, matching the no-op behavior of os.Rename required by the MoveFileSystem contract.

func (*MemFileSystem) Name

func (*MemFileSystem) Name() string

func (*MemFileSystem) OpenAppendWriter

func (fs *MemFileSystem) OpenAppendWriter(filePath string, perm []Permissions) (WriteCloser, error)

func (*MemFileSystem) OpenReadWriter

func (fs *MemFileSystem) OpenReadWriter(filePath string, perm []Permissions) (ReadWriteSeekCloser, error)

func (*MemFileSystem) OpenReader

func (fs *MemFileSystem) OpenReader(filePath string) (iofs.File, error)

func (*MemFileSystem) OpenWriter

func (fs *MemFileSystem) OpenWriter(filePath string, perm []Permissions) (WriteCloser, error)

func (*MemFileSystem) Prefix

func (fs *MemFileSystem) Prefix() string

func (*MemFileSystem) ReadAll

func (fs *MemFileSystem) ReadAll(ctx context.Context, filePath string) ([]byte, error)
func (fs *MemFileSystem) ReadSymbolicLink(linkPath string) (string, error)

ReadSymbolicLink returns the target of the symbolic link at linkPath as stored on the node. An error is returned if the path is missing or is not a symbolic link.

func (*MemFileSystem) ReadableWritable

func (fs *MemFileSystem) ReadableWritable() (readable, writable bool)

func (*MemFileSystem) Remove

func (fs *MemFileSystem) Remove(filePath string) error

func (*MemFileSystem) RemoveXAttr

func (fs *MemFileSystem) RemoveXAttr(filePath string, name string, _ bool) error

RemoveXAttr removes the named extended attribute from the node. It returns an error if the attribute is not set.

func (*MemFileSystem) Rename

func (fs *MemFileSystem) Rename(filePath string, newName string) (string, error)

Rename renames the node at filePath to newName within its existing parent directory. newName must be a leaf name without the file system's path separator. The new full path is returned.

func (*MemFileSystem) RootDir

func (fs *MemFileSystem) RootDir() File

func (*MemFileSystem) Separator

func (fs *MemFileSystem) Separator() string

func (*MemFileSystem) SetGroup

func (fs *MemFileSystem) SetGroup(filePath string, group string) error

func (*MemFileSystem) SetPermissions

func (fs *MemFileSystem) SetPermissions(filePath string, perm Permissions) error

func (*MemFileSystem) SetReadOnly

func (fs *MemFileSystem) SetReadOnly(readOnly bool)

func (*MemFileSystem) SetUser

func (fs *MemFileSystem) SetUser(filePath string, user string) error

func (*MemFileSystem) SetXAttr

func (fs *MemFileSystem) SetXAttr(filePath string, name string, data []byte, flags int, _ bool) error

SetXAttr stores data under the named extended attribute. The flags argument honors xattr.XATTR_CREATE (fail if the attribute already exists) and xattr.XATTR_REPLACE (fail if it does not).

func (*MemFileSystem) SplitDirAndName

func (fs *MemFileSystem) SplitDirAndName(filePath string) (dir, name string)

func (*MemFileSystem) SplitPath

func (fs *MemFileSystem) SplitPath(filePath string) []string

func (*MemFileSystem) Stat

func (fs *MemFileSystem) Stat(filePath string) (iofs.FileInfo, error)

func (*MemFileSystem) String

func (fs *MemFileSystem) String() string

func (*MemFileSystem) Touch

func (fs *MemFileSystem) Touch(filePath string, perm []Permissions) error

func (*MemFileSystem) Truncate

func (fs *MemFileSystem) Truncate(filePath string, newSize int64) error

func (*MemFileSystem) URL

func (fs *MemFileSystem) URL(cleanPath string) string

func (*MemFileSystem) User

func (fs *MemFileSystem) User(filePath string) (string, error)

User returns the per-node user string previously set via SetUser, or the empty string if none was set. MemFileSystem does not consult any OS user database.

func (*MemFileSystem) Volume

func (fs *MemFileSystem) Volume() string

func (*MemFileSystem) VolumeName

func (fs *MemFileSystem) VolumeName(filePath string) string

func (*MemFileSystem) Watch

func (fs *MemFileSystem) Watch(filePath string, onEvent func(File, Event)) (cancel func() error, err error)

Watch registers onEvent for changes to filePath. Events are synthesized from every mutation that goes through the MemFileSystem API (Touch, WriteAll, OpenWriter close, Append, Truncate, Rename, Move, Remove, MakeDir, SetPermissions, SetUser, SetGroup, SetXAttr, RemoveXAttr, CreateSymbolicLink). Direct mutation of a MemFile.FileData byte slice obtained outside the API is not observable and emits no event.

When filePath is a directory the callback fires for events on its direct children (not deeper sub-directories), matching the WatchFileSystem contract.

Callbacks are invoked from a new goroutine per event so a slow consumer can never block the mutation that produced it. Panics inside the callback are recovered and silently discarded.

Because each event is dispatched in its own goroutine, the delivery order of events to a given callback is not guaranteed. Tests should assert on the set of events received rather than on a strict sequence.

func (*MemFileSystem) WithID

func (fs *MemFileSystem) WithID(id string) *MemFileSystem

func (*MemFileSystem) WithVolume

func (fs *MemFileSystem) WithVolume(volume string) *MemFileSystem

func (*MemFileSystem) WriteAll

func (fs *MemFileSystem) WriteAll(ctx context.Context, filePath string, data []byte, perm []Permissions) error

type MockFileSystem

type MockFileSystem struct {
	// MockPrefix is the prefix string returned by the Prefix() method.
	// If empty, defaults to "mock://".
	MockPrefix string

	MockReadableWritable func() (readable, writable bool)
	MockRootDir          func() File
	MockID               func() (string, error)
	MockName             func() string
	MockString           func() string
	MockURL              func(cleanPath string) string
	MockCleanPathFromURI func(uri string) string
	MockJoinCleanFile    func(uriParts ...string) File
	MockJoinCleanPath    func(uriParts ...string) string
	MockSplitPath        func(filePath string) []string
	MockSeparator        func() string
	MockIsAbsPath        func(filePath string) bool
	MockAbsPath          func(filePath string) string
	MockMatchAnyPattern  func(name string, patterns []string) (bool, error)
	MockSplitDirAndName  func(filePath string) (dir, name string)
	MockStat             func(filePath string) (iofs.FileInfo, error)
	MockIsHidden         func(filePath string) bool
	MockIsSymbolicLink   func(filePath string) bool
	MockListDirInfo      func(ctx context.Context, dirPath string, callback func(*FileInfo) error, patterns []string) error
	MockMakeDir          func(dirPath string, perm []Permissions) error
	MockOpenReader       func(filePath string) (ReadCloser, error)
	MockOpenWriter       func(filePath string, perm []Permissions) (WriteCloser, error)
	MockOpenReadWriter   func(filePath string, perm []Permissions) (ReadWriteSeekCloser, error)
	MockRemove           func(filePath string) error
	MockClose            func() error
}

MockFileSystem is a FileSystem implementation with function pointers for every method.

All function pointers are prefixed with "Mock" and use the same calling interface as their corresponding FileSystem method.

If a function pointer is nil, then the corresponding method will panic, except for the Name and String methods, which will return "MockFileSystem" if the function pointer is nil.

func (*MockFileSystem) AbsPath

func (m *MockFileSystem) AbsPath(filePath string) string

AbsPath implements FileSystem

func (*MockFileSystem) CleanPathFromURI

func (m *MockFileSystem) CleanPathFromURI(uri string) string

CleanPathFromURI implements FileSystem

func (*MockFileSystem) Close

func (m *MockFileSystem) Close() error

Close implements FileSystem

func (*MockFileSystem) ID

func (m *MockFileSystem) ID() (string, error)

ID implements FileSystem

func (*MockFileSystem) IsAbsPath

func (m *MockFileSystem) IsAbsPath(filePath string) bool

IsAbsPath implements FileSystem

func (*MockFileSystem) IsHidden

func (m *MockFileSystem) IsHidden(filePath string) bool

IsHidden implements FileSystem

func (m *MockFileSystem) IsSymbolicLink(filePath string) bool

IsSymbolicLink implements FileSystem

func (*MockFileSystem) JoinCleanFile

func (m *MockFileSystem) JoinCleanFile(uriParts ...string) File

JoinCleanFile implements FileSystem

func (*MockFileSystem) JoinCleanPath

func (m *MockFileSystem) JoinCleanPath(uriParts ...string) string

JoinCleanPath implements FileSystem

func (*MockFileSystem) ListDirInfo

func (m *MockFileSystem) ListDirInfo(ctx context.Context, dirPath string, callback func(*FileInfo) error, patterns []string) error

ListDirInfo implements FileSystem

func (*MockFileSystem) MakeDir

func (m *MockFileSystem) MakeDir(dirPath string, perm []Permissions) error

MakeDir implements FileSystem

func (*MockFileSystem) MatchAnyPattern

func (m *MockFileSystem) MatchAnyPattern(name string, patterns []string) (bool, error)

MatchAnyPattern implements FileSystem

func (*MockFileSystem) Name

func (m *MockFileSystem) Name() string

Name implements FileSystem. Calls MockName if not nil, otherwise returns "MockFileSystem".

func (*MockFileSystem) OpenReadWriter

func (m *MockFileSystem) OpenReadWriter(filePath string, perm []Permissions) (ReadWriteSeekCloser, error)

OpenReadWriter implements FileSystem

func (*MockFileSystem) OpenReader

func (m *MockFileSystem) OpenReader(filePath string) (ReadCloser, error)

OpenReader implements FileSystem

func (*MockFileSystem) OpenWriter

func (m *MockFileSystem) OpenWriter(filePath string, perm []Permissions) (WriteCloser, error)

OpenWriter implements FileSystem

func (*MockFileSystem) Prefix

func (m *MockFileSystem) Prefix() string

Prefix implements FileSystem. Returns the value of MockPrefix if not empty, otherwise returns "mock://".

func (*MockFileSystem) ReadableWritable

func (m *MockFileSystem) ReadableWritable() (readable, writable bool)

ReadableWritable implements FileSystem

func (*MockFileSystem) Remove

func (m *MockFileSystem) Remove(filePath string) error

Remove implements FileSystem

func (*MockFileSystem) RootDir

func (m *MockFileSystem) RootDir() File

RootDir implements FileSystem

func (*MockFileSystem) Separator

func (m *MockFileSystem) Separator() string

Separator implements FileSystem

func (*MockFileSystem) SplitDirAndName

func (m *MockFileSystem) SplitDirAndName(filePath string) (dir, name string)

SplitDirAndName implements FileSystem

func (*MockFileSystem) SplitPath

func (m *MockFileSystem) SplitPath(filePath string) []string

SplitPath implements FileSystem

func (*MockFileSystem) Stat

func (m *MockFileSystem) Stat(filePath string) (iofs.FileInfo, error)

Stat implements FileSystem

func (*MockFileSystem) String

func (m *MockFileSystem) String() string

String implements FileSystem. Calls MockString if not nil, otherwise returns "MockFileSystem".

func (*MockFileSystem) URL

func (m *MockFileSystem) URL(cleanPath string) string

URL implements FileSystem

type MockFullyFeaturedFileSystem

type MockFullyFeaturedFileSystem struct {
	MockFileSystem

	MockCopyFile             func(ctx context.Context, srcFile string, destFile string, buf *[]byte) error
	MockMove                 func(filePath string, destinationPath string) error
	MockRename               func(filePath string, newName string) (newPath string, err error)
	MockVolumeName           func(filePath string) string
	MockWatch                func(filePath string, onEvent func(File, Event)) (cancel func() error, err error)
	MockTouch                func(filePath string, perm []Permissions) error
	MockMakeAllDirs          func(dirPath string, perm []Permissions) error
	MockReadAll              func(ctx context.Context, filePath string) ([]byte, error)
	MockWriteAll             func(ctx context.Context, filePath string, data []byte, perm []Permissions) error
	MockAppend               func(ctx context.Context, filePath string, data []byte, perm []Permissions) error
	MockOpenAppendWriter     func(filePath string, perm []Permissions) (WriteCloser, error)
	MockTruncate             func(filePath string, size int64) error
	MockExists               func(filePath string) bool
	MockUser                 func(filePath string) (string, error)
	MockSetUser              func(filePath string, user string) error
	MockGroup                func(filePath string) (string, error)
	MockSetGroup             func(filePath string, group string) error
	MockSetPermissions       func(filePath string, perm Permissions) error
	MockListDirMax           func(ctx context.Context, dirPath string, max int, patterns []string) ([]File, error)
	MockListDirInfoRecursive func(ctx context.Context, dirPath string, callback func(*FileInfo) error, patterns []string) error
}

MockFullyFeaturedFileSystem is a FullyFeaturedFileSystem implementation with function pointers for every method.

All function pointers are prefixed with "Mock" and use the same calling interface as their corresponding FullyFeaturedFileSystem method.

If a function pointer is nil, then the corresponding method will panic, except for the Name and String methods, which will return "MockFileSystem" if the function pointer is nil.

func (*MockFullyFeaturedFileSystem) Append

func (m *MockFullyFeaturedFileSystem) Append(ctx context.Context, filePath string, data []byte, perm []Permissions) error

Append implements AppendFileSystem (optional)

func (*MockFullyFeaturedFileSystem) CopyFile

func (m *MockFullyFeaturedFileSystem) CopyFile(ctx context.Context, srcFile string, destFile string, buf *[]byte) error

CopyFile implements CopyFileSystem (optional)

func (*MockFullyFeaturedFileSystem) Exists

func (m *MockFullyFeaturedFileSystem) Exists(filePath string) bool

Exists implements ExistsFileSystem (optional)

func (*MockFullyFeaturedFileSystem) Group

func (m *MockFullyFeaturedFileSystem) Group(filePath string) (string, error)

Group implements GroupFileSystem (optional)

func (*MockFullyFeaturedFileSystem) ListDirInfoRecursive

func (m *MockFullyFeaturedFileSystem) ListDirInfoRecursive(ctx context.Context, dirPath string, callback func(*FileInfo) error, patterns []string) error

ListDirInfoRecursive implements ListDirRecursiveFileSystem (optional)

func (*MockFullyFeaturedFileSystem) ListDirMax

func (m *MockFullyFeaturedFileSystem) ListDirMax(ctx context.Context, dirPath string, max int, patterns []string) ([]File, error)

ListDirMax implements ListDirMaxFileSystem (optional)

func (*MockFullyFeaturedFileSystem) MakeAllDirs

func (m *MockFullyFeaturedFileSystem) MakeAllDirs(dirPath string, perm []Permissions) error

MakeAllDirs implements MakeAllDirsFileSystem (optional)

func (*MockFullyFeaturedFileSystem) Move

func (m *MockFullyFeaturedFileSystem) Move(filePath string, destinationPath string) error

Move implements MoveFileSystem (optional)

func (*MockFullyFeaturedFileSystem) OpenAppendWriter

func (m *MockFullyFeaturedFileSystem) OpenAppendWriter(filePath string, perm []Permissions) (WriteCloser, error)

OpenAppendWriter implements AppendWriterFileSystem (optional)

func (*MockFullyFeaturedFileSystem) ReadAll

func (m *MockFullyFeaturedFileSystem) ReadAll(ctx context.Context, filePath string) ([]byte, error)

ReadAll implements ReadAllFileSystem (optional)

func (*MockFullyFeaturedFileSystem) Rename

func (m *MockFullyFeaturedFileSystem) Rename(filePath string, newName string) (newPath string, err error)

Rename implements RenameFileSystem (optional)

func (*MockFullyFeaturedFileSystem) SetGroup

func (m *MockFullyFeaturedFileSystem) SetGroup(filePath string, group string) error

SetGroup implements GroupFileSystem (optional)

func (*MockFullyFeaturedFileSystem) SetPermissions

func (m *MockFullyFeaturedFileSystem) SetPermissions(filePath string, perm Permissions) error

SetPermissions implements PermissionsFileSystem (optional)

func (*MockFullyFeaturedFileSystem) SetUser

func (m *MockFullyFeaturedFileSystem) SetUser(filePath string, user string) error

SetUser implements UserFileSystem (optional)

func (*MockFullyFeaturedFileSystem) Touch

func (m *MockFullyFeaturedFileSystem) Touch(filePath string, perm []Permissions) error

Touch implements TouchFileSystem (optional)

func (*MockFullyFeaturedFileSystem) Truncate

func (m *MockFullyFeaturedFileSystem) Truncate(filePath string, size int64) error

Truncate implements TruncateFileSystem (optional)

func (*MockFullyFeaturedFileSystem) User

func (m *MockFullyFeaturedFileSystem) User(filePath string) (string, error)

User implements UserFileSystem (optional)

func (*MockFullyFeaturedFileSystem) VolumeName

func (m *MockFullyFeaturedFileSystem) VolumeName(filePath string) string

VolumeName implements VolumeNameFileSystem (optional)

func (*MockFullyFeaturedFileSystem) Watch

func (m *MockFullyFeaturedFileSystem) Watch(filePath string, onEvent func(File, Event)) (cancel func() error, err error)

Watch implements WatchFileSystem (optional)

func (*MockFullyFeaturedFileSystem) WriteAll

func (m *MockFullyFeaturedFileSystem) WriteAll(ctx context.Context, filePath string, data []byte, perm []Permissions) error

WriteAll implements WriteAllFileSystem (optional)

type MoveFileSystem

type MoveFileSystem interface {
	FileSystem

	// Move moves and/or renames the file to destination.
	// destination can be a directory or file-path.
	// If successful, this also changes the path of this File's implementation.
	//
	// When filePath and destinationPath resolve to the same location after
	// path cleaning, Move must be a no-op and return nil — matching the
	// behavior of [os.Rename] for same-path renames. Implementations must
	// not surface ErrAlreadyExists, an "into itself" cycle error, or any
	// other failure for this case.
	Move(filePath string, destinationPath string) error
}

MoveFileSystem can be implemented by file systems that have native file moving functionality.

If a file system does not implement this interface then it's functionality will be emulated with other methods.

type Permissions

type Permissions uint32

Permissions for a file, follows the Unix/os.FileMode bit schema.

var (
	NoPermissions Permissions = 0

	UserExecute          Permissions = 0100
	UserWrite            Permissions = 0200
	UserRead             Permissions = 0400
	UserReadWrite        Permissions = UserRead | UserWrite
	UserReadWriteExecute Permissions = UserRead | UserWrite | UserExecute

	GroupExecute          Permissions = 0010
	GroupWrite            Permissions = 0020
	GroupRead             Permissions = 0040
	GroupReadWrite        Permissions = GroupRead | GroupWrite
	GroupReadWriteExecute Permissions = GroupRead | GroupWrite | GroupExecute

	UserAndGroupRead             Permissions = UserRead | GroupRead
	UserAndGroupReadWrite        Permissions = UserReadWrite | GroupReadWrite
	UserAndGroupReadWriteExecute Permissions = UserReadWriteExecute | GroupReadWriteExecute

	OthersExecute          Permissions = 0001
	OthersWrite            Permissions = 0002
	OthersRead             Permissions = 0004
	OthersReadWrite        Permissions = OthersRead | OthersWrite
	OthersReadWriteExecute Permissions = OthersRead | OthersWrite | OthersExecute

	AllRead      = UserRead | GroupRead | OthersRead
	AllWrite     = UserWrite | GroupWrite | OthersWrite
	AllExecute   = UserExecute | GroupExecute | OthersExecute
	AllReadWrite = UserReadWrite | GroupReadWrite | OthersReadWrite
)

func JoinPermissions

func JoinPermissions(perms []Permissions, defaultPerm Permissions) (result Permissions)

func PermissionsFromStdFileInfo

func PermissionsFromStdFileInfo(info iofs.FileInfo) Permissions

func (Permissions) Can

func (perm Permissions) Can(p Permissions) bool

func (Permissions) CanAllExecute

func (perm Permissions) CanAllExecute() bool

func (Permissions) CanAllRead

func (perm Permissions) CanAllRead() bool

func (Permissions) CanAllReadWrite

func (perm Permissions) CanAllReadWrite() bool

func (Permissions) CanAllWrite

func (perm Permissions) CanAllWrite() bool

func (Permissions) CanGroupExecute

func (perm Permissions) CanGroupExecute() bool

func (Permissions) CanGroupRead

func (perm Permissions) CanGroupRead() bool

func (Permissions) CanGroupReadWrite

func (perm Permissions) CanGroupReadWrite() bool

func (Permissions) CanGroupWrite

func (perm Permissions) CanGroupWrite() bool

func (Permissions) CanOthersExecute

func (perm Permissions) CanOthersExecute() bool

func (Permissions) CanOthersRead

func (perm Permissions) CanOthersRead() bool

func (Permissions) CanOthersReadWrite

func (perm Permissions) CanOthersReadWrite() bool

func (Permissions) CanOthersWrite

func (perm Permissions) CanOthersWrite() bool

func (Permissions) CanUserAndGroupRead

func (perm Permissions) CanUserAndGroupRead() bool

func (Permissions) CanUserAndGroupReadWrite

func (perm Permissions) CanUserAndGroupReadWrite() bool

func (Permissions) CanUserExecute

func (perm Permissions) CanUserExecute() bool

func (Permissions) CanUserRead

func (perm Permissions) CanUserRead() bool

func (Permissions) CanUserReadWrite

func (perm Permissions) CanUserReadWrite() bool

func (Permissions) CanUserWrite

func (perm Permissions) CanUserWrite() bool

func (Permissions) Executable

func (perm Permissions) Executable() (user, group, others bool)

func (Permissions) FileMode

func (perm Permissions) FileMode(isDir bool) os.FileMode

FileMode returns an os.FileMode for the given permissions together with the information if the file is a directory.

func (Permissions) Readable

func (perm Permissions) Readable() (user, group, others bool)

func (Permissions) Writable

func (perm Permissions) Writable() (user, group, others bool)

type PermissionsFileSystem

type PermissionsFileSystem interface {
	FileSystem

	// SetPermissions sets the permissions of the file at filePath.
	SetPermissions(filePath string, perm Permissions) error
}

PermissionsFileSystem can be implemented by file systems that support setting file permissions.

type ReadAllFileSystem

type ReadAllFileSystem interface {
	FileSystem

	// ReadAll reads the entire content of the file at filePath.
	ReadAll(ctx context.Context, filePath string) ([]byte, error)
}

ReadAllFileSystem can be implemented by file systems that can read entire files more efficiently than using OpenReader.

type ReadCloser

type ReadCloser = iofs.File

type ReadOnlyBase

type ReadOnlyBase struct{}

ReadOnlyBase implements the writing methods of the FileSystem interface to do nothing and return ErrReadOnlyFileSystem. Intended to be used as base for read only file systems, so that only the read methods have to be implemented.

func (*ReadOnlyBase) MakeDir

func (*ReadOnlyBase) MakeDir(dirPath string, perm []Permissions) error

func (*ReadOnlyBase) MatchAnyPattern

func (*ReadOnlyBase) MatchAnyPattern(name string, patterns []string) (bool, error)

MatchAnyPattern returns true if name matches any of patterns, or if len(patterns) == 0. The match per pattern works like path.Match or filepath.Match

func (*ReadOnlyBase) OpenReadWriter

func (*ReadOnlyBase) OpenReadWriter(filePath string, perm []Permissions) (ReadWriteSeekCloser, error)

func (*ReadOnlyBase) OpenWriter

func (*ReadOnlyBase) OpenWriter(filePath string, perm []Permissions) (WriteCloser, error)

func (*ReadOnlyBase) ReadableWritable

func (*ReadOnlyBase) ReadableWritable() (readable, writable bool)

func (*ReadOnlyBase) Remove

func (*ReadOnlyBase) Remove(filePath string) error

func (*ReadOnlyBase) SetGroup

func (*ReadOnlyBase) SetGroup(filePath string, group string) error

func (*ReadOnlyBase) SetPermissions

func (*ReadOnlyBase) SetPermissions(filePath string, perm Permissions) error

func (*ReadOnlyBase) SetUser

func (*ReadOnlyBase) SetUser(filePath string, user string) error

type ReadSeekCloser

type ReadSeekCloser interface {
	io.Reader
	io.ReaderAt
	io.Seeker
	io.Closer
}

ReadSeekCloser combines the interfaces io.Reader io.ReaderAt io.Seeker io.Closer

type ReadWriteSeekCloser

type ReadWriteSeekCloser interface {
	io.Reader
	io.ReaderAt
	io.Writer
	io.WriterAt
	io.Seeker
	io.Closer
}

ReadWriteSeekCloser combines the interfaces io.Reader io.ReaderAt io.Writer io.WriterAt io.Seeker io.Closer

func NewFileReadWriteAllSeekCloser

func NewFileReadWriteAllSeekCloser(file File, permissions ...Permissions) ReadWriteSeekCloser

NewFileReadWriteAllSeekCloser creates a ReadWriteSeekCloser for a File using only File.ReadAll and File.WriteAll. The permissions parameter will be used for WriteAll operations.

It uses fsimpl.NewReadWriteAllSeekCloser to implement ReadWriteSeekCloser by lazily reading all data from a file when first needed, buffering modifications in memory, and writing everything back to the file on Close().

This is useful for file systems that don't support true random access writes, such as ZIP archives, where files must be completely rewritten.

The implementation:

  1. Lazily reads all file content into memory on first read/write operation
  2. Performs all read/write/seek operations in memory using a FileBuffer
  3. Writes the complete modified content back to the file on Close()

type RelPathFileSystem

type RelPathFileSystem interface {
	FileSystem

	// RelPath returns the relative path of targPath relative to basePath
	// like [filepath.Rel] but for the file system implementation.
	//
	// The returned path will always be relative to basePath, even if basePath and
	// targPath share no elements: joining basePath with the result yields a path
	// equivalent to targPath after cleaning. The returned path is cleaned
	// and may contain ".." segments. If basePath and targPath are identical,
	// "." is returned.
	//
	// An error is returned if targPath can't be made relative to basePath
	// (for example when one is absolute and the other is not),
	// or if knowing the current working directory would be necessary to compute it.
	RelPath(basePath, targPath string) (string, error)
}

RelPathFileSystem can be implemented by file systems that support computing a relative path between two paths.

If a file system does not implement this interface then File.RelPathOf returns an ErrUnsupported error.

type RenameFileSystem

type RenameFileSystem interface {
	FileSystem

	// Rename only renames the file in its base directory
	// but does not move it into another directory.
	// If successful, this also changes the path of this File's implementation.
	Rename(filePath string, newName string) (newPath string, err error)
}

RenameFileSystem can be implemented by file systems that have native file renaming functionality.

If a file system does not implement this interface then it's functionality will be emulated with other methods.

type SentinelError

type SentinelError string

SentinelError is used for const sentinel errors

const (
	// ErrReadOnlyFileSystem is returned when a file system doesn't support writes
	ErrReadOnlyFileSystem SentinelError = "file system is read-only"

	// ErrWriteOnlyFileSystem is returned when a file system doesn't support reads
	ErrWriteOnlyFileSystem SentinelError = "file system is write-only"

	// ErrInvalidFileSystem indicates an invalid file system
	ErrInvalidFileSystem SentinelError = "invalid file system"

	// ErrFileSystemClosed is returned after a file system Close method was called
	ErrFileSystemClosed SentinelError = "file system is closed"

	ErrUnmarshalJSON SentinelError = "can't unmarshal JSON"
	ErrMarshalJSON   SentinelError = "can't marshal JSON"

	ErrUnmarshalXML SentinelError = "can't unmarshal XML"
	ErrMarshalXML   SentinelError = "can't marshal XML"
)

func (SentinelError) Error

func (e SentinelError) Error() string

type StdDirEntry

type StdDirEntry struct {
	File File
}

StdDirEntry implements the io/fs.DirEntry interface from the standard library for a File.

func (StdDirEntry) Info

func (de StdDirEntry) Info() (iofs.FileInfo, error)

Info returns the FileInfo for the file or subdirectory described by the entry. The returned FileInfo may be from the time of the original directory read or from the time of the call to Info. If the file has been removed or renamed since the directory read, Info may return an error satisfying errors.Is(err, ErrNotExist). If the entry denotes a symbolic link, Info reports the information about the link itself, not the link's target.

func (StdDirEntry) IsDir

func (de StdDirEntry) IsDir() bool

IsDir reports whether the entry describes a directory.

func (StdDirEntry) Name

func (de StdDirEntry) Name() string

Name returns the name of the file (or subdirectory) described by the entry. This name is only the final element of the path (the base name), not the entire path. For example, Name would return "hello.go" not "/home/gopher/hello.go".

func (StdDirEntry) Type

func (de StdDirEntry) Type() iofs.FileMode

Type returns the type bits for the entry. The type bits are a subset of the usual FileMode bits, those returned by the FileMode.Type method.

type StdFS

type StdFS struct {
	File File
}

StdFS implements the io/fs.FS interface of the standard library for a File.

StdFS implements the following interfaces:

  • io/fs.FS
  • io/fs.SubFS
  • io/fs.StatFS
  • io/fs.GlobFS
  • io/fs.ReadDirFS
  • io/fs.ReadFileFS

func (StdFS) Open

func (f StdFS) Open(name string) (iofs.File, error)

Open opens the named file.

This method implements the io/fs.FS interface.

func (StdFS) ReadDir

func (f StdFS) ReadDir(name string) ([]iofs.DirEntry, error)

ReadDir reads the named directory and returns a list of directory entries sorted by filename.

This method implements the io/fs.ReadDirFS interface.

func (StdFS) ReadFile

func (f StdFS) ReadFile(name string) ([]byte, error)

ReadFile reads the named file and returns its contents.

This method implements the io/fs.ReadFileFS interface.

func (StdFS) Stat

func (f StdFS) Stat(name string) (iofs.FileInfo, error)

Stat returns a io/fs.FileInfo describing the file.

This method implements the io/fs.StatFS interface.

func (StdFS) Sub

func (f StdFS) Sub(dir string) (iofs.FS, error)

Sub returns an io/fs.FS corresponding to the subtree rooted at dir.

This method implements the io/fs.SubFS interface.

type SymbolicLinkFileSystem

type SymbolicLinkFileSystem interface {
	FileSystem

	// CreateSymbolicLink creates a symbolic link at linkPath
	// pointing to targetPath. targetPath is stored verbatim,
	// so it may be relative to linkPath's directory or absolute,
	// depending on what the caller wants the resolved link to mean.
	CreateSymbolicLink(targetPath, linkPath string) error

	// ReadSymbolicLink returns the target of the symbolic link at linkPath
	// as stored on disk. The returned path is raw and may be relative
	// to linkPath's directory.
	ReadSymbolicLink(linkPath string) (targetPath string, err error)
}

SymbolicLinkFileSystem can be implemented by file systems that support creating and reading symbolic links.

If a file system does not implement this interface then File.CreateSymbolicLink and File.ReadSymbolicLink return an ErrUnsupported error.

type TouchFileSystem

type TouchFileSystem interface {
	FileSystem

	// Touch creates an empty file at filePath if it does not exist,
	// or updates the modification time if it does exist.
	Touch(filePath string, perm []Permissions) error
}

TouchFileSystem can be implemented by file systems that have native touch functionality.

type TruncateFileSystem

type TruncateFileSystem interface {
	FileSystem

	// Truncate resizes a file by not only
	// truncating to a smaller size but also
	// appending zeros to a bigger size
	// than the current one.
	Truncate(filePath string, size int64) error
}

TruncateFileSystem can be implemented by file systems that have native file truncation/resizing functionality.

type UserFileSystem

type UserFileSystem interface {
	FileSystem

	// User returns the user owner of the file at filePath.
	User(filePath string) (string, error)

	// SetUser sets the user owner of the file at filePath.
	SetUser(filePath string, user string) error
}

UserFileSystem can be implemented by file systems that support file ownership operations.

type VolumeNameFileSystem

type VolumeNameFileSystem interface {
	FileSystem

	// VolumeName returns the name of the volume at the beginning of the filePath,
	// or an empty string if the filePath has no volume.
	// A volume is for example "C:" on Windows
	VolumeName(filePath string) string
}

VolumeNameFileSystem should be implemented by file systems that have volume names.

type WatchFileSystem

type WatchFileSystem interface {
	FileSystem

	// Watch a file or directory for changes.
	// If filePath describes a directory then
	// changes directly within it will be reported.
	// This does not apply changes in deeper
	// recursive sub-directories.
	//
	// It is valid to watch a file with multiple
	// callbacks, calling the returned cancel function
	// will cancel a particular watch.
	Watch(filePath string, onEvent func(File, Event)) (cancel func() error, err error)
}

WatchFileSystem can be implemented by file systems that have file watching functionality.

type WriteAllFileSystem

type WriteAllFileSystem interface {
	FileSystem

	// WriteAll writes data to the file at filePath, creating it if it does not exist
	// or truncating it if it does exist.
	WriteAll(ctx context.Context, filePath string, data []byte, perm []Permissions) error
}

WriteAllFileSystem can be implemented by file systems that can write entire files more efficiently than using OpenWriter.

type WriteCloser

type WriteCloser = io.WriteCloser

type WriteSeekCloser

type WriteSeekCloser interface {
	io.Writer
	io.WriterAt
	io.Seeker
	io.Closer
}

WriteSeekCloser combines the interfaces io.Writer io.WriterAt io.Seeker io.Closer

type XAttrFileSystem

type XAttrFileSystem interface {
	FileSystem

	// ListXAttr returns the names of all extended attributes for the file.
	// If followSymlinks is true, symlinks are resolved to their target.
	ListXAttr(filePath string, followSymlinks bool) ([]string, error)

	// GetXAttr returns the value of the named extended attribute.
	// If followSymlinks is true, symlinks are resolved to their target.
	GetXAttr(filePath string, name string, followSymlinks bool) ([]byte, error)

	// SetXAttr sets the value of the named extended attribute.
	// The flags parameter controls the behavior (e.g., unix.XATTR_CREATE, unix.XATTR_REPLACE).
	// If followSymlinks is true, symlinks are resolved to their target.
	SetXAttr(filePath string, name string, data []byte, flags int, followSymlinks bool) error

	// RemoveXAttr removes the named extended attribute from the file.
	// If followSymlinks is true, symlinks are resolved to their target.
	RemoveXAttr(filePath string, name string, followSymlinks bool) error
}

XAttrFileSystem extends FileSystem with support for extended file attributes (xattrs). Extended attributes are name-value pairs associated with files that provide additional metadata beyond standard file attributes. Not all file systems support xattrs (e.g., FAT32 does not). On Linux, xattr names are typically prefixed with a namespace like "user.".

Directories

Path Synopsis
dropboxfs module
Package fsimpl contains helper functions and types for implementing a fs.FileSystem.
Package fsimpl contains helper functions and types for implementing a fs.FileSystem.
ftpfs module
Package httpfs implements a read only file system for HTTP URLs.
Package httpfs implements a read only file system for HTTP URLs.
s3fs module
sftpfs module
Package uuiddirs provides functions to split up a UUID into a series of sub-directories so that an unlimited number of UUIDs can be used as directories.
Package uuiddirs provides functions to split up a UUID into a series of sub-directories so that an unlimited number of UUIDs can be used as directories.

Jump to

Keyboard shortcuts

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