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 }