package sysfs

import "github.com/tetratelabs/wazero/internal/sysfs"

Package sysfs includes a low-level filesystem interface and utilities needed for WebAssembly host functions (ABI) such as WASI and runtime.GOOS=js.

The name sysfs was chosen because wazero's public API has a "sys" package, which was named after https://github.com/golang/sys.

Index

Functions

func FileDatasync

func FileDatasync(f fs.File) (err error)

FileDatasync is like syscall.Fdatasync except that's only defined in linux.

func ReaderAtOffset

func ReaderAtOffset(f fs.File, offset int64) io.Reader

ReaderAtOffset gets an io.Reader from a fs.File that reads from an offset, yet doesn't affect the underlying position. This is used to implement syscall.Pread.

Note: The file accessed shouldn't be used concurrently, but wasm isn't safe to use concurrently anyway. Hence, we don't do any locking against parallel reads.

func StatFile

func StatFile(f fs.File) (s fs.FileInfo, err error)

StatFile is like the same method on fs.File, except the returned error is nil or syscall.Errno.

func StatPath

func StatPath(fs FS, path string) (s fs.FileInfo, err error)

StatPath is a convenience that calls FS.OpenFile, then StatFile, until there is a stat method.

func StripPrefixesAndTrailingSlash

func StripPrefixesAndTrailingSlash(path string) string

func UnwrapOSError

func UnwrapOSError(err error) error

UnwrapOSError returns a syscall.Errno or nil if the input is nil.

func WriterAtOffset

func WriterAtOffset(f fs.File, offset int64) io.Writer

WriterAtOffset gets an io.Writer from a fs.File that writes to an offset, yet doesn't affect the underlying position. This is used to implement syscall.Pwrite.

Types

type CompositeFS

type CompositeFS struct {
	UnimplementedFS
	// contains filtered or unexported fields
}

func (*CompositeFS) FS

func (c *CompositeFS) FS() (fs []FS)

FS returns the underlying filesystems in original order.

func (*CompositeFS) GuestPaths

func (c *CompositeFS) GuestPaths() (guestPaths []string)

GuestPaths returns the underlying pre-open paths in original order.

func (*CompositeFS) Mkdir

func (c *CompositeFS) Mkdir(path string, perm fs.FileMode) error

Mkdir implements FS.Mkdir

func (*CompositeFS) Open

func (c *CompositeFS) Open(name string) (fs.File, error)

Open implements the same method as documented on fs.FS

func (*CompositeFS) OpenFile

func (c *CompositeFS) OpenFile(path string, flag int, perm fs.FileMode) (f fs.File, err error)

OpenFile implements FS.OpenFile

func (*CompositeFS) Rename

func (c *CompositeFS) Rename(from, to string) error

Rename implements FS.Rename

func (*CompositeFS) Rmdir

func (c *CompositeFS) Rmdir(path string) error

Rmdir implements FS.Rmdir

func (*CompositeFS) String

func (c *CompositeFS) String() string

String implements fmt.Stringer

func (c *CompositeFS) Unlink(path string) error

Unlink implements FS.Unlink

func (*CompositeFS) Utimes

func (c *CompositeFS) Utimes(path string, atimeNsec, mtimeNsec int64) error

Utimes implements FS.Utimes

type FS

type FS interface {
	// String should return a human-readable format of the filesystem
	//
	// For example, if this filesystem is backed by the real directory
	// "/tmp/wasm", the expected value is "/tmp/wasm".
	//
	// When the host filesystem isn't a real filesystem, substitute a symbolic,
	// human-readable name. e.g. "virtual"
	String() string

	// OpenFile is similar to os.OpenFile, except the path is relative to this
	// file system, and syscall.Errno are returned instead of a os.PathError.
	//
	// # Errors
	//
	// The following errors are expected:
	//   - syscall.EINVAL: `path` or `flag` is invalid.
	//   - syscall.ENOENT: `path` doesn't exist and `flag` doesn't contain
	//     os.O_CREATE.
	//
	// # Constraints on the returned file
	//
	// Implementations that can read flags should enforce them regardless of
	// the type returned. For example, while os.File implements io.Writer,
	// attempts to write to a directory or a file opened with os.O_RDONLY fail
	// with a syscall.EBADF.
	//
	// Some implementations choose whether to enforce read-only opens, namely
	// fs.FS. While fs.FS is supported (Adapt), wazero cannot runtime enforce
	// open flags. Instead, we encourage good behavior and test our built-in
	// implementations.
	//
	// # Notes
	//
	//   - flag are the same as OpenFile, for example, os.O_CREATE.
	//   - Implications of permissions when os.O_CREATE are described in Chmod
	//     notes.
	OpenFile(path string, flag int, perm fs.FileMode) (fs.File, error)

	// Mkdir is similar to os.Mkdir, except the path is relative to this file
	// system, and syscall.Errno are returned instead of a os.PathError.
	//
	// # Errors
	//
	// The following errors are expected:
	//   - syscall.EINVAL: `path` is invalid.
	//   - syscall.EEXIST: `path` exists and is a directory.
	//   - syscall.ENOTDIR: `path` exists and is a file.
	//
	// # Notes
	//
	//   - Implications of permissions are described in Chmod notes.
	Mkdir(path string, perm fs.FileMode) error

	// Chmod is similar to os.Chmod, except the path is relative to this file
	// system, and syscall.Errno are returned instead of a os.PathError.
	//
	// # Errors
	//
	// The following errors are expected:
	//   - syscall.EINVAL: `path` is invalid.
	//   - syscall.ENOENT: `path` does not exist.
	//
	// # Notes
	//
	//   - Windows ignores the execute bit, and any permissions come back as
	//     group and world. For example, chmod of 0400 reads back as 0444, and
	//     0700 0666. Also, permissions on directories aren't supported at all.
	Chmod(path string, perm fs.FileMode) error

	// Rename is similar to syscall.Rename, except the path is relative to this
	// file system.
	//
	// # Errors
	//
	// The following errors are expected:
	//   - syscall.EINVAL: `from` or `to` is invalid.
	//   - syscall.ENOENT: `from` or `to` don't exist.
	//   - syscall.ENOTDIR: `from` is a directory and `to` exists as a file.
	//   - syscall.EISDIR: `from` is a file and `to` exists as a directory.
	//   - syscall.ENOTEMPTY: `both from` and `to` are existing directory, but
	//    `to` is not empty.
	//
	// # Notes
	//
	//   -  Windows doesn't let you overwrite an existing directory.
	Rename(from, to string) error

	// Rmdir is similar to syscall.Rmdir, except the path is relative to this
	// file system.
	//
	// # Errors
	//
	// The following errors are expected:
	//   - syscall.EINVAL: `path` is invalid.
	//   - syscall.ENOENT: `path` doesn't exist.
	//   - syscall.ENOTDIR: `path` exists, but isn't a directory.
	//   - syscall.ENOTEMPTY: `path` exists, but isn't empty.
	//
	// # Notes
	//
	//   - As of Go 1.19, Windows maps syscall.ENOTDIR to syscall.ENOENT.
	Rmdir(path string) error

	// Unlink is similar to syscall.Unlink, except the path is relative to this
	// file system.
	//
	// # Errors
	//
	// The following errors are expected:
	//   - syscall.EINVAL: `path` is invalid.
	//   - syscall.ENOENT: `path` doesn't exist.
	//   - syscall.EISDIR: `path` exists, but is a directory.
	Unlink(path string) error

	// Link is similar to syscall.Link, except the path is relative to this
	// file system. This creates "hard" link from oldPath to newPath, in
	// contrast to soft link as in Symlink.
	//
	// # Errors
	//
	// The following errors are expected:
	//   - syscall.EPERM: `oldPath` is invalid.
	//   - syscall.ENOENT: `oldPath` doesn't exist.
	//   - syscall.EISDIR: `newPath` exists, but is a directory.
	Link(oldPath, newPath string) error

	// Symlink is similar to syscall.Symlink, except the `oldPath` is relative
	// to this file system. This creates "soft" link from oldPath to newPath,
	// in contrast to hard link as in Link.
	//
	// # Errors
	//
	// The following errors are expected:
	//   - syscall.EPERM: `oldPath` or `newPath` is invalid.
	//   - syscall.EEXIST: `newPath` exists.
	//
	// # Notes
	//
	//   - Only `newPath` is relative to this file system and `oldPath` is kept
	//     as-is. That is because the link is only resolved relative to the
	//     directory when dereferencing it (e.g. ReadLink).
	//     See https://github.com/bytecodealliance/cap-std/blob/v1.0.4/cap-std/src/fs/dir.rs#L404-L409
	//     for how others implement this.
	//   - Symlinks in Windows requires `SeCreateSymbolicLinkPrivilege`.
	//     Otherwise, syscall.EPERM results.
	//     See https://learn.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/create-symbolic-links
	Symlink(oldPath, linkName string) error

	// Readlink is similar to syscall.Readlink, except the path is relative to
	// this file system.
	//
	// # Errors
	//
	// The following errors are expected:
	//   - syscall.EINVAL: `path` is invalid.
	//
	// # Notes
	//   - On Windows, the path separator is different from other platforms,
	//     but to provide consistent results to Wasm, this normalizes to a "/"
	//     separator.
	Readlink(path string, buf []byte) (n int, err error)

	// Truncate is similar to syscall.Truncate, except the path is relative to
	// this file system.
	//
	// # Errors
	//
	// The following errors are expected:
	//   - syscall.EINVAL: `path` is invalid or size is negative.
	//   - syscall.ENOENT: `path` doesn't exist
	//   - syscall.EACCES: `path` doesn't have write access.
	Truncate(path string, size int64) error

	// Utimes is similar to syscall.UtimesNano, except the path is relative to
	// this file system.
	//
	// # Errors
	//
	// The following errors are expected:
	//   - syscall.EINVAL: `path` is invalid.
	//   - syscall.ENOENT: `path` doesn't exist
	//
	// # Notes
	//
	//   - To set wall clock time, retrieve it first from sys.Walltime.
	//   - syscall.UtimesNano cannot change the ctime. Also, neither WASI nor
	//     runtime.GOOS=js support changing it. Hence, ctime it is absent here.
	Utimes(path string, atimeNsec, mtimeNsec int64) error
}

FS is a writeable fs.FS bridge backed by syscall functions needed for ABI including WASI and runtime.GOOS=js.

Implementations should embed UnimplementedFS for forward compatability. Any unsupported method or parameter should return syscall.ENOSYS.

See https://github.com/golang/go/issues/45757

func Adapt

func Adapt(fs fs.FS) FS

Adapt adapts the input to FS unless it is already one. NewDirFS should be used instead, if the input is os.DirFS.

Note: This performs no flag verification on FS.OpenFile. fs.FS cannot read flags as there is no parameter to pass them through with. Moreover, fs.FS documentation does not require the file to be present. In summary, we can't enforce flag behavior.

func NewDirFS

func NewDirFS(dir string) FS

func NewReadFS

func NewReadFS(fs FS) FS

NewReadFS is used to mask an existing FS for reads. Notably, this allows the CLI to do read-only mounts of directories the host user can write, but doesn't want the guest wasm to. For example, Python libraries shouldn't be written to at runtime by the python wasm file.

func NewRootFS

func NewRootFS(fs []FS, guestPaths []string) (FS, error)

type UnimplementedFS

type UnimplementedFS struct{}

UnimplementedFS is an FS that returns syscall.ENOSYS for all functions, This should be embedded to have forward compatible implementations.

func (UnimplementedFS) Chmod

func (UnimplementedFS) Chmod(path string, perm fs.FileMode) error

Chmod implements FS.Chmod

func (UnimplementedFS) Link(_, _ string) error

Link implements FS.Link

func (UnimplementedFS) Mkdir

func (UnimplementedFS) Mkdir(path string, perm fs.FileMode) error

Mkdir implements FS.Mkdir

func (UnimplementedFS) Open

func (UnimplementedFS) Open(name string) (fs.File, error)

Open implements the same method as documented on fs.FS

func (UnimplementedFS) OpenFile

func (UnimplementedFS) OpenFile(path string, flag int, perm fs.FileMode) (fs.File, error)

OpenFile implements FS.OpenFile

func (UnimplementedFS) Readlink(string, []byte) (int, error)

Readlink implements FS.Readlink

func (UnimplementedFS) Rename

func (UnimplementedFS) Rename(from, to string) error

Rename implements FS.Rename

func (UnimplementedFS) Rmdir

func (UnimplementedFS) Rmdir(path string) error

Rmdir implements FS.Rmdir

func (UnimplementedFS) String

func (UnimplementedFS) String() string

String implements fmt.Stringer

func (UnimplementedFS) Symlink(_, _ string) error

Symlink implements FS.Symlink

func (UnimplementedFS) Truncate

func (UnimplementedFS) Truncate(string, int64) error

Truncate implements FS.Truncate

func (UnimplementedFS) Unlink(path string) error

Unlink implements FS.Unlink

func (UnimplementedFS) Utimes

func (UnimplementedFS) Utimes(path string, atimeNsec, mtimeNsec int64) error

Utimes implements FS.Utimes

Source Files

adapter.go dirfs.go readfs.go rootfs.go syscall.go sysfs.go unsupported.go

Version
v1.0.0-pre.9
Published
Feb 17, 2023
Platform
linux/amd64
Imports
10 packages
Last checked
8 minutes ago

Tools for package owners.