1 package os
2 3 import (
4 "bytes"
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 directory 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 bytes.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 }
98