1// Package os implements a subset of the Go "os" package. See
2// https://godoc.org/os for details.
3//
4// Note that the current implementation is blocking. This limitation should be
5// removed in a future version.
6package os
7
8import (
9	"syscall"
10)
11
12// Mkdir creates a directory. If the operation fails, it will return an error of
13// type *PathError.
14func Mkdir(path string, perm FileMode) error {
15	fs, suffix := findMount(path)
16	if fs == nil {
17		return &PathError{"mkdir", path, ErrNotExist}
18	}
19	err := fs.Mkdir(suffix, perm)
20	if err != nil {
21		return &PathError{"mkdir", path, err}
22	}
23	return nil
24}
25
26// Remove removes a file or (empty) directory. If the operation fails, it will
27// return an error of type *PathError.
28func Remove(path string) error {
29	fs, suffix := findMount(path)
30	if fs == nil {
31		return &PathError{"remove", path, ErrNotExist}
32	}
33	err := fs.Remove(suffix)
34	if err != nil {
35		return &PathError{"remove", path, err}
36	}
37	return nil
38}
39
40// File represents an open file descriptor.
41type File struct {
42	handle FileHandle
43	name   string
44}
45
46// Name returns the name of the file with which it was opened.
47func (f *File) Name() string {
48	return f.name
49}
50
51// OpenFile opens the named file. If the operation fails, the returned error
52// will be of type *PathError.
53func OpenFile(name string, flag int, perm FileMode) (*File, error) {
54	fs, suffix := findMount(name)
55	if fs == nil {
56		return nil, &PathError{"open", name, ErrNotExist}
57	}
58	handle, err := fs.OpenFile(suffix, flag, perm)
59	if err != nil {
60		return nil, &PathError{"open", name, err}
61	}
62	return &File{name: name, handle: handle}, nil
63}
64
65// Open opens the file named for reading.
66func Open(name string) (*File, error) {
67	return OpenFile(name, O_RDONLY, 0)
68}
69
70// Create creates the named file, overwriting it if it already exists.
71func Create(name string) (*File, error) {
72	return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
73}
74
75// Read reads up to len(b) bytes from the File. It returns the number of bytes
76// read and any error encountered. At end of file, Read returns 0, io.EOF.
77func (f *File) Read(b []byte) (n int, err error) {
78	n, err = f.handle.Read(b)
79	if err != nil {
80		err = &PathError{"read", f.name, err}
81	}
82	return
83}
84
85func (f *File) ReadAt(b []byte, off int64) (n int, err error) {
86	return 0, ErrNotImplemented
87}
88
89// Write writes len(b) bytes to the File. It returns the number of bytes written
90// and an error, if any. Write returns a non-nil error when n != len(b).
91func (f *File) Write(b []byte) (n int, err error) {
92	n, err = f.handle.Write(b)
93	if err != nil {
94		err = &PathError{"write", f.name, err}
95	}
96	return
97}
98
99// Close closes the File, rendering it unusable for I/O.
100func (f *File) Close() (err error) {
101	err = f.handle.Close()
102	if err != nil {
103		err = &PathError{"close", f.name, err}
104	}
105	return
106}
107
108// Readdir is a stub, not yet implemented
109func (f *File) Readdir(n int) ([]FileInfo, error) {
110	return nil, &PathError{"readdir", f.name, ErrNotImplemented}
111}
112
113// Readdirnames is a stub, not yet implemented
114func (f *File) Readdirnames(n int) (names []string, err error) {
115	return nil, &PathError{"readdirnames", f.name, ErrNotImplemented}
116}
117
118// Stat is a stub, not yet implemented
119func (f *File) Stat() (FileInfo, error) {
120	return nil, &PathError{"stat", f.name, ErrNotImplemented}
121}
122
123// Sync is a stub, not yet implemented
124func (f *File) Sync() error {
125	return ErrNotImplemented
126}
127
128func (f *File) SyscallConn() (syscall.RawConn, error) {
129	return nil, ErrNotImplemented
130}
131
132// Fd returns the file handle referencing the open file.
133func (f *File) Fd() uintptr {
134	panic("unimplemented: os.file.Fd()")
135}
136
137const (
138	PathSeparator     = '/' // OS-specific path separator
139	PathListSeparator = ':' // OS-specific path list separator
140)
141
142// IsPathSeparator reports whether c is a directory separator character.
143func IsPathSeparator(c uint8) bool {
144	return PathSeparator == c
145}
146
147// PathError records an error and the operation and file path that caused it.
148type PathError struct {
149	Op   string
150	Path string
151	Err  error
152}
153
154func (e *PathError) Error() string {
155	return e.Op + " " + e.Path + ": " + e.Err.Error()
156}
157
158type FileMode uint32
159
160// Mode constants, copied from the mainline Go source
161// https://github.com/golang/go/blob/4ce6a8e89668b87dce67e2f55802903d6eb9110a/src/os/types.go#L35-L63
162const (
163	// The single letters are the abbreviations used by the String method's formatting.
164	ModeDir        FileMode = 1 << (32 - 1 - iota) // d: is a directory
165	ModeAppend                                     // a: append-only
166	ModeExclusive                                  // l: exclusive use
167	ModeTemporary                                  // T: temporary file; Plan 9 only
168	ModeSymlink                                    // L: symbolic link
169	ModeDevice                                     // D: device file
170	ModeNamedPipe                                  // p: named pipe (FIFO)
171	ModeSocket                                     // S: Unix domain socket
172	ModeSetuid                                     // u: setuid
173	ModeSetgid                                     // g: setgid
174	ModeCharDevice                                 // c: Unix character device, when ModeDevice is set
175	ModeSticky                                     // t: sticky
176	ModeIrregular                                  // ?: non-regular file; nothing else is known about this file
177
178	// Mask for the type bits. For regular files, none will be set.
179	ModeType = ModeDir | ModeSymlink | ModeNamedPipe | ModeSocket | ModeDevice | ModeCharDevice | ModeIrregular
180
181	ModePerm FileMode = 0777 // Unix permission bits
182)
183
184// IsDir is a stub, always returning false
185func (m FileMode) IsDir() bool {
186	return false
187}
188
189// Stub constants
190const (
191	O_RDONLY int = 1
192	O_WRONLY int = 2
193	O_RDWR   int = 4
194	O_APPEND int = 8
195	O_CREATE int = 16
196	O_EXCL   int = 32
197	O_SYNC   int = 64
198	O_TRUNC  int = 128
199)
200
201// A FileInfo describes a file and is returned by Stat and Lstat.
202type FileInfo interface {
203	Name() string   // base name of the file
204	Size() int64    // length in bytes for regular files; system-dependent for others
205	Mode() FileMode // file mode bits
206	// TODO ModTime() time.Time // modification time
207	IsDir() bool      // abbreviation for Mode().IsDir()
208	Sys() interface{} // underlying data source (can return nil)
209}
210
211// Stat is a stub, not yet implemented
212func Stat(name string) (FileInfo, error) {
213	return nil, &PathError{"stat", name, ErrNotImplemented}
214}
215
216// Lstat is a stub, not yet implemented
217func Lstat(name string) (FileInfo, error) {
218	return nil, &PathError{"lstat", name, ErrNotImplemented}
219}
220
221// Getwd is a stub (for now), always returning an empty string
222func Getwd() (string, error) {
223	return "", nil
224}
225
226// Readlink is a stub (for now), always returning the string it was given
227func Readlink(name string) (string, error) {
228	return name, nil
229}
230
231// TempDir is a stub (for now), always returning the string "/tmp"
232func TempDir() string {
233	return "/tmp"
234}
235
236// IsExist is a stub (for now), always returning false
237func IsExist(err error) bool {
238	return false
239}
240
241// IsNotExist is a stub (for now), always returning false
242func IsNotExist(err error) bool {
243	return false
244}
245
246// Getpid is a stub (for now), always returning 1
247func Getpid() int {
248	return 1
249}
250