1// Copyright 2009 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Package os provides a platform-independent interface to operating system
6// functionality. The design is Unix-like, although the error handling is
7// Go-like; failing calls return values of type error rather than error numbers.
8// Often, more information is available within the error. For example,
9// if a call that takes a file name fails, such as Open or Stat, the error
10// will include the failing file name when printed and will be of type
11// *PathError, which may be unpacked for more information.
12//
13// The os interface is intended to be uniform across all operating systems.
14// Features not generally available appear in the system-specific package syscall.
15//
16// Here is a simple example, opening a file and reading some of it.
17//
18//	file, err := os.Open("file.go") // For read access.
19//	if err != nil {
20//		log.Fatal(err)
21//	}
22//
23// If the open fails, the error string will be self-explanatory, like
24//
25//	open file.go: no such file or directory
26//
27// The file's data can then be read into a slice of bytes. Read and
28// Write take their byte counts from the length of the argument slice.
29//
30//	data := make([]byte, 100)
31//	count, err := file.Read(data)
32//	if err != nil {
33//		log.Fatal(err)
34//	}
35//	fmt.Printf("read %d bytes: %q\n", count, data[:count])
36//
37package os
38
39import (
40	"io"
41	"syscall"
42)
43
44// Name returns the name of the file as presented to Open.
45func (f *File) Name() string { return f.name }
46
47// Stdin, Stdout, and Stderr are open Files pointing to the standard input,
48// standard output, and standard error file descriptors.
49var (
50	Stdin  = NewFile(uintptr(syscall.Stdin), "/dev/stdin")
51	Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")
52	Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr")
53)
54
55// Flags to Open wrapping those of the underlying system. Not all flags
56// may be implemented on a given system.
57const (
58	O_RDONLY int = syscall.O_RDONLY // open the file read-only.
59	O_WRONLY int = syscall.O_WRONLY // open the file write-only.
60	O_RDWR   int = syscall.O_RDWR   // open the file read-write.
61	O_APPEND int = syscall.O_APPEND // append data to the file when writing.
62	O_CREATE int = syscall.O_CREAT  // create a new file if none exists.
63	O_EXCL   int = syscall.O_EXCL   // used with O_CREATE, file must not exist
64	O_SYNC   int = syscall.O_SYNC   // open for synchronous I/O.
65	O_TRUNC  int = syscall.O_TRUNC  // if possible, truncate file when opened.
66)
67
68// Seek whence values.
69const (
70	SEEK_SET int = 0 // seek relative to the origin of the file
71	SEEK_CUR int = 1 // seek relative to the current offset
72	SEEK_END int = 2 // seek relative to the end
73)
74
75// LinkError records an error during a link or symlink or rename
76// system call and the paths that caused it.
77type LinkError struct {
78	Op  string
79	Old string
80	New string
81	Err error
82}
83
84func (e *LinkError) Error() string {
85	return e.Op + " " + e.Old + " " + e.New + ": " + e.Err.Error()
86}
87
88// Read reads up to len(b) bytes from the File.
89// It returns the number of bytes read and an error, if any.
90// EOF is signaled by a zero count with err set to io.EOF.
91func (f *File) Read(b []byte) (n int, err error) {
92	if f == nil {
93		return 0, ErrInvalid
94	}
95	n, e := f.read(b)
96	if n < 0 {
97		n = 0
98	}
99	if n == 0 && len(b) > 0 && e == nil {
100		return 0, io.EOF
101	}
102	if e != nil {
103		err = &PathError{"read", f.name, e}
104	}
105	return n, err
106}
107
108// ReadAt reads len(b) bytes from the File starting at byte offset off.
109// It returns the number of bytes read and the error, if any.
110// ReadAt always returns a non-nil error when n < len(b).
111// At end of file, that error is io.EOF.
112func (f *File) ReadAt(b []byte, off int64) (n int, err error) {
113	if f == nil {
114		return 0, ErrInvalid
115	}
116	for len(b) > 0 {
117		m, e := f.pread(b, off)
118		if m == 0 && e == nil {
119			return n, io.EOF
120		}
121		if e != nil {
122			err = &PathError{"read", f.name, e}
123			break
124		}
125		n += m
126		b = b[m:]
127		off += int64(m)
128	}
129	return
130}
131
132// Write writes len(b) bytes to the File.
133// It returns the number of bytes written and an error, if any.
134// Write returns a non-nil error when n != len(b).
135func (f *File) Write(b []byte) (n int, err error) {
136	if f == nil {
137		return 0, ErrInvalid
138	}
139	n, e := f.write(b)
140	if n < 0 {
141		n = 0
142	}
143	if n != len(b) {
144		err = io.ErrShortWrite
145	}
146
147	epipecheck(f, e)
148
149	if e != nil {
150		err = &PathError{"write", f.name, e}
151	}
152	return n, err
153}
154
155// WriteAt writes len(b) bytes to the File starting at byte offset off.
156// It returns the number of bytes written and an error, if any.
157// WriteAt returns a non-nil error when n != len(b).
158func (f *File) WriteAt(b []byte, off int64) (n int, err error) {
159	if f == nil {
160		return 0, ErrInvalid
161	}
162	for len(b) > 0 {
163		m, e := f.pwrite(b, off)
164		if e != nil {
165			err = &PathError{"write", f.name, e}
166			break
167		}
168		n += m
169		b = b[m:]
170		off += int64(m)
171	}
172	return
173}
174
175// Seek sets the offset for the next Read or Write on file to offset, interpreted
176// according to whence: 0 means relative to the origin of the file, 1 means
177// relative to the current offset, and 2 means relative to the end.
178// It returns the new offset and an error, if any.
179func (f *File) Seek(offset int64, whence int) (ret int64, err error) {
180	if f == nil {
181		return 0, ErrInvalid
182	}
183	r, e := f.seek(offset, whence)
184	if e == nil && f.dirinfo != nil && r != 0 {
185		e = syscall.EISDIR
186	}
187	if e != nil {
188		return 0, &PathError{"seek", f.name, e}
189	}
190	return r, nil
191}
192
193// WriteString is like Write, but writes the contents of string s rather than
194// a slice of bytes.
195func (f *File) WriteString(s string) (n int, err error) {
196	if f == nil {
197		return 0, ErrInvalid
198	}
199	return f.Write([]byte(s))
200}
201
202// Mkdir creates a new directory with the specified name and permission bits.
203// If there is an error, it will be of type *PathError.
204func Mkdir(name string, perm FileMode) error {
205	e := syscall.Mkdir(name, syscallMode(perm))
206
207	if e != nil {
208		return &PathError{"mkdir", name, e}
209	}
210
211	// mkdir(2) itself won't handle the sticky bit on *BSD and Solaris
212	if !supportsCreateWithStickyBit && perm&ModeSticky != 0 {
213		Chmod(name, perm)
214	}
215
216	return nil
217}
218
219// Chdir changes the current working directory to the named directory.
220// If there is an error, it will be of type *PathError.
221func Chdir(dir string) error {
222	if e := syscall.Chdir(dir); e != nil {
223		return &PathError{"chdir", dir, e}
224	}
225	return nil
226}
227
228// Chdir changes the current working directory to the file,
229// which must be a directory.
230// If there is an error, it will be of type *PathError.
231func (f *File) Chdir() error {
232	if f == nil {
233		return ErrInvalid
234	}
235	if e := syscall.Fchdir(f.fd); e != nil {
236		return &PathError{"chdir", f.name, e}
237	}
238	return nil
239}
240
241// Open opens the named file for reading.  If successful, methods on
242// the returned file can be used for reading; the associated file
243// descriptor has mode O_RDONLY.
244// If there is an error, it will be of type *PathError.
245func Open(name string) (*File, error) {
246	return OpenFile(name, O_RDONLY, 0)
247}
248
249// Create creates the named file with mode 0666 (before umask), truncating
250// it if it already exists. If successful, methods on the returned
251// File can be used for I/O; the associated file descriptor has mode
252// O_RDWR.
253// If there is an error, it will be of type *PathError.
254func Create(name string) (*File, error) {
255	return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
256}
257
258// lstat is overridden in tests.
259var lstat = Lstat
260
261// Rename renames (moves) a file. OS-specific restrictions might apply.
262// If there is an error, it will be of type *LinkError.
263func Rename(oldpath, newpath string) error {
264	return rename(oldpath, newpath)
265}
266
267// Many functions in package syscall return a count of -1 instead of 0.
268// Using fixCount(call()) instead of call() corrects the count.
269func fixCount(n int, err error) (int, error) {
270	if n < 0 {
271		n = 0
272	}
273	return n, err
274}
275