github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/os/filesystem.go (about)

     1  package os
     2  
     3  import (
     4  	"strings"
     5  )
     6  
     7  // mounts lists the mount points currently mounted in the filesystem provided by
     8  // the os package. To resolve a path to a mount point, it is scanned from top to
     9  // bottom looking for the first prefix match.
    10  var mounts []mountPoint
    11  
    12  type mountPoint struct {
    13  	// prefix is a filesystem prefix, that always starts and ends with a forward
    14  	// slash. To denote the root filesystem, use a single slash: "/".
    15  	// This allows fast checking whether a path lies within a mount point.
    16  	prefix string
    17  
    18  	// filesystem is the Filesystem implementation that is mounted at this mount
    19  	// point.
    20  	filesystem Filesystem
    21  }
    22  
    23  // Filesystem provides an interface for generic filesystem drivers mounted in
    24  // the os package. The errors returned must be one of the os.Err* errors, or a
    25  // custom error if one doesn't exist. It should not be a *PathError because
    26  // errors will be wrapped with a *PathError by the filesystem abstraction.
    27  //
    28  // WARNING: this interface is not finalized and may change in a future version.
    29  type Filesystem interface {
    30  	// OpenFile opens the named file.
    31  	OpenFile(name string, flag int, perm FileMode) (uintptr, error)
    32  
    33  	// Mkdir creates a new directoy with the specified permission (before
    34  	// umask). Some filesystems may not support directories or permissions.
    35  	Mkdir(name string, perm FileMode) error
    36  
    37  	// Remove removes the named file or (empty) directory.
    38  	Remove(name string) error
    39  }
    40  
    41  // FileHandle is an interface that should be implemented by filesystems
    42  // implementing the Filesystem interface.
    43  //
    44  // WARNING: this interface is not finalized and may change in a future version.
    45  type FileHandle interface {
    46  	// Read reads up to len(b) bytes from the file.
    47  	Read(b []byte) (n int, err error)
    48  
    49  	// ReadAt reads up to len(b) bytes from the file starting at the given absolute offset
    50  	ReadAt(b []byte, offset int64) (n int, err error)
    51  
    52  	// Seek resets the file pointer relative to start, current position, or end
    53  	Seek(offset int64, whence int) (newoffset int64, err error)
    54  
    55  	// Sync blocks until buffered writes have been written to persistent storage
    56  	Sync() (err error)
    57  
    58  	// Write writes up to len(b) bytes to the file.
    59  	Write(b []byte) (n int, err error)
    60  
    61  	// WriteAt writes b to the file at the given absolute offset
    62  	WriteAt(b []byte, offset int64) (n int, err error)
    63  
    64  	// Close closes the file, making it unusable for further writes.
    65  	Close() (err error)
    66  }
    67  
    68  // findMount returns the appropriate (mounted) filesystem to use for a given
    69  // filename plus the path relative to that filesystem.
    70  func findMount(path string) (Filesystem, string) {
    71  	for i := len(mounts) - 1; i >= 0; i-- {
    72  		mount := mounts[i]
    73  		if strings.HasPrefix(path, mount.prefix) {
    74  			return mount.filesystem, path[len(mount.prefix)-1:]
    75  		}
    76  	}
    77  	if isOS {
    78  		// Assume that the first entry in the mounts slice is the OS filesystem
    79  		// at the root of the directory tree. Use it as-is, to support relative
    80  		// paths.
    81  		return mounts[0].filesystem, path
    82  	}
    83  	return nil, path
    84  }
    85  
    86  // Mount mounts the given filesystem in the filesystem abstraction layer of the
    87  // os package. It is not possible to unmount filesystems. Filesystems added
    88  // later will override earlier filesystems.
    89  //
    90  // The provided prefix must start and end with a forward slash. This is true for
    91  // the root directory ("/") for example.
    92  func Mount(prefix string, filesystem Filesystem) {
    93  	if prefix[0] != '/' || prefix[len(prefix)-1] != '/' {
    94  		panic("os.Mount: invalid prefix")
    95  	}
    96  	mounts = append(mounts, mountPoint{prefix, filesystem})
    97  }