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.
5 // The os package provides a platform-independent interface to operating
6 // system functionality. The design is Unix-like.
14 // File represents an open file descriptor.
18 dirinfo
*dirInfo
// nil unless directory being read
19 nepipe
int // number of consecutive EPIPE in Write
22 // Fd returns the integer Unix file descriptor referencing the open file.
23 func (file
*File
) Fd() int { return file
.fd
}
25 // Name returns the name of the file as presented to Open.
26 func (file
*File
) Name() string { return file
.name
}
28 // NewFile returns a new File with the given file descriptor and name.
29 func NewFile(fd
int, name
string) *File
{
33 f
:= &File
{fd
, name
, nil, 0}
34 runtime
.SetFinalizer(f
, (*File
).Close
)
38 // Stdin, Stdout, and Stderr are open Files pointing to the standard input,
39 // standard output, and standard error file descriptors.
41 Stdin
= NewFile(syscall
.Stdin
, "/dev/stdin")
42 Stdout
= NewFile(syscall
.Stdout
, "/dev/stdout")
43 Stderr
= NewFile(syscall
.Stderr
, "/dev/stderr")
46 // Flags to Open wrapping those of the underlying system. Not all flags
47 // may be implemented on a given system.
49 O_RDONLY
int = syscall
.O_RDONLY
// open the file read-only.
50 O_WRONLY
int = syscall
.O_WRONLY
// open the file write-only.
51 O_RDWR
int = syscall
.O_RDWR
// open the file read-write.
52 O_APPEND
int = syscall
.O_APPEND
// append data to the file when writing.
53 O_ASYNC
int = syscall
.O_ASYNC
// generate a signal when I/O is available.
54 O_CREAT
int = syscall
.O_CREAT
// create a new file if none exists.
55 O_EXCL
int = syscall
.O_EXCL
// used with O_CREAT, file must not exist
56 O_NOCTTY
int = syscall
.O_NOCTTY
// do not make file the controlling tty.
57 O_NONBLOCK
int = syscall
.O_NONBLOCK
// open in non-blocking mode.
58 O_NDELAY
int = O_NONBLOCK
// synonym for O_NONBLOCK
59 O_SYNC
int = syscall
.O_SYNC
// open for synchronous I/O.
60 O_TRUNC
int = syscall
.O_TRUNC
// if possible, truncate file when opened.
61 O_CREATE
int = O_CREAT
// create a new file if none exists.
66 func (eofError
) String() string { return "EOF" }
68 // EOF is the Error returned by Read when no more input is available.
69 // Functions should return EOF only to signal a graceful end of input.
70 // If the EOF occurs unexpectedly in a structured data stream,
71 // the appropriate error is either io.ErrUnexpectedEOF or some other error
72 // giving more detail.
73 var EOF Error
= eofError(0)
75 // Read reads up to len(b) bytes from the File.
76 // It returns the number of bytes read and an Error, if any.
77 // EOF is signaled by a zero count with err set to EOF.
78 func (file
*File
) Read(b
[]byte) (n
int, err Error
) {
82 n
, e
:= syscall
.Read(file
.fd
, b
)
90 err
= &PathError
{"read", file
.name
, Errno(e
)}
95 // ReadAt reads len(b) bytes from the File starting at byte offset off.
96 // It returns the number of bytes read and the Error, if any.
97 // EOF is signaled by a zero count with err set to EOF.
98 // ReadAt always returns a non-nil Error when n != len(b).
99 func (file
*File
) ReadAt(b
[]byte, off
int64) (n
int, err Error
) {
104 m
, e
:= syscall
.Pread(file
.fd
, b
, off
)
105 if m
== 0 && e
== 0 {
109 err
= &PathError
{"read", file
.name
, Errno(e
)}
119 // Write writes len(b) bytes to the File.
120 // It returns the number of bytes written and an Error, if any.
121 // Write returns a non-nil Error when n != len(b).
122 func (file
*File
) Write(b
[]byte) (n
int, err Error
) {
126 n
, e
:= syscall
.Write(file
.fd
, b
)
130 if e
== syscall
.EPIPE
{
132 if file
.nepipe
>= 10 {
139 err
= &PathError
{"write", file
.name
, Errno(e
)}
144 // WriteAt writes len(b) bytes to the File starting at byte offset off.
145 // It returns the number of bytes written and an Error, if any.
146 // WriteAt returns a non-nil Error when n != len(b).
147 func (file
*File
) WriteAt(b
[]byte, off
int64) (n
int, err Error
) {
152 m
, e
:= syscall
.Pwrite(file
.fd
, b
, off
)
154 err
= &PathError
{"write", file
.name
, Errno(e
)}
164 // Seek sets the offset for the next Read or Write on file to offset, interpreted
165 // according to whence: 0 means relative to the origin of the file, 1 means
166 // relative to the current offset, and 2 means relative to the end.
167 // It returns the new offset and an Error, if any.
168 func (file
*File
) Seek(offset
int64, whence
int) (ret
int64, err Error
) {
169 r
, e
:= syscall
.Seek(file
.fd
, offset
, whence
)
170 if e
== 0 && file
.dirinfo
!= nil && r
!= 0 {
174 return 0, &PathError
{"seek", file
.name
, Errno(e
)}
179 // WriteString is like Write, but writes the contents of string s rather than
180 // an array of bytes.
181 func (file
*File
) WriteString(s
string) (ret
int, err Error
) {
185 b
:= syscall
.StringByteSlice(s
)
190 // Pipe returns a connected pair of Files; reads from r return bytes written to w.
191 // It returns the files and an Error, if any.
192 func Pipe() (r
*File
, w
*File
, err Error
) {
195 // See ../syscall/exec.go for description of lock.
196 syscall
.ForkLock
.RLock()
197 e
:= syscall
.Pipe(p
[0:])
199 syscall
.ForkLock
.RUnlock()
200 return nil, nil, NewSyscallError("pipe", e
)
202 syscall
.CloseOnExec(p
[0])
203 syscall
.CloseOnExec(p
[1])
204 syscall
.ForkLock
.RUnlock()
206 return NewFile(p
[0], "|0"), NewFile(p
[1], "|1"), nil
209 // Mkdir creates a new directory with the specified name and permission bits.
210 // It returns an error, if any.
211 func Mkdir(name
string, perm
uint32) Error
{
212 e
:= syscall
.Mkdir(name
, perm
)
214 return &PathError
{"mkdir", name
, Errno(e
)}
219 // Stat returns a FileInfo structure describing the named file and an error, if any.
220 // If name names a valid symbolic link, the returned FileInfo describes
221 // the file pointed at by the link and has fi.FollowedSymlink set to true.
222 // If name names an invalid symbolic link, the returned FileInfo describes
223 // the link itself and has fi.FollowedSymlink set to false.
224 func Stat(name
string) (fi
*FileInfo
, err Error
) {
225 var lstat
, stat syscall
.Stat_t
226 e
:= syscall
.Lstat(name
, &lstat
)
228 return nil, &PathError
{"stat", name
, Errno(e
)}
231 if lstat
.Mode
&syscall
.S_IFMT
== syscall
.S_IFLNK
{
232 e
:= syscall
.Stat(name
, &stat
)
237 return fileInfoFromStat(name
, new(FileInfo
), &lstat
, statp
), nil
240 // Lstat returns the FileInfo structure describing the named file and an
241 // error, if any. If the file is a symbolic link, the returned FileInfo
242 // describes the symbolic link. Lstat makes no attempt to follow the link.
243 func Lstat(name
string) (fi
*FileInfo
, err Error
) {
244 var stat syscall
.Stat_t
245 e
:= syscall
.Lstat(name
, &stat
)
247 return nil, &PathError
{"lstat", name
, Errno(e
)}
249 return fileInfoFromStat(name
, new(FileInfo
), &stat
, &stat
), nil
252 // Chdir changes the current working directory to the named directory.
253 func Chdir(dir
string) Error
{
254 if e
:= syscall
.Chdir(dir
); e
!= 0 {
255 return &PathError
{"chdir", dir
, Errno(e
)}
260 // Chdir changes the current working directory to the file,
261 // which must be a directory.
262 func (f
*File
) Chdir() Error
{
263 if e
:= syscall
.Fchdir(f
.fd
); e
!= 0 {
264 return &PathError
{"chdir", f
.name
, Errno(e
)}
269 // Remove removes the named file or directory.
270 func Remove(name
string) Error
{
271 // System call interface forces us to know
272 // whether name is a file or directory.
273 // Try both: it is cheaper on average than
274 // doing a Stat plus the right one.
275 e
:= syscall
.Unlink(name
)
279 e1
:= syscall
.Rmdir(name
)
284 // Both failed: figure out which error to return.
285 // OS X and Linux differ on whether unlink(dir)
286 // returns EISDIR, so can't use that. However,
287 // both agree that rmdir(file) returns ENOTDIR,
288 // so we can use that to decide which error is real.
289 // Rmdir might also return ENOTDIR if given a bad
290 // file path, like /etc/passwd/foo, but in that case,
291 // both errors will be ENOTDIR, so it's okay to
292 // use the error from unlink.
293 // For windows syscall.ENOTDIR is set
294 // to syscall.ERROR_DIRECTORY, hopefully it should
296 if e1
!= syscall
.ENOTDIR
{
299 return &PathError
{"remove", name
, Errno(e
)}
302 // LinkError records an error during a link or symlink or rename
303 // system call and the paths that caused it.
304 type LinkError
struct {
311 func (e
*LinkError
) String() string {
312 return e
.Op
+ " " + e
.Old
+ " " + e
.New
+ ": " + e
.Error
.String()
315 // Link creates a hard link.
316 func Link(oldname
, newname
string) Error
{
317 e
:= syscall
.Link(oldname
, newname
)
319 return &LinkError
{"link", oldname
, newname
, Errno(e
)}
324 // Symlink creates a symbolic link.
325 func Symlink(oldname
, newname
string) Error
{
326 e
:= syscall
.Symlink(oldname
, newname
)
328 return &LinkError
{"symlink", oldname
, newname
, Errno(e
)}
333 // Readlink reads the contents of a symbolic link: the destination of
334 // the link. It returns the contents and an Error, if any.
335 func Readlink(name
string) (string, Error
) {
336 for len := 128; ; len *= 2 {
337 b
:= make([]byte, len)
338 n
, e
:= syscall
.Readlink(name
, b
)
340 return "", &PathError
{"readlink", name
, Errno(e
)}
343 return string(b
[0:n
]), nil
350 // Rename renames a file.
351 func Rename(oldname
, newname
string) Error
{
352 e
:= syscall
.Rename(oldname
, newname
)
354 return &LinkError
{"rename", oldname
, newname
, Errno(e
)}
359 // Chmod changes the mode of the named file to mode.
360 // If the file is a symbolic link, it changes the mode of the link's target.
361 func Chmod(name
string, mode
uint32) Error
{
362 if e
:= syscall
.Chmod(name
, mode
); e
!= 0 {
363 return &PathError
{"chmod", name
, Errno(e
)}
368 // Chmod changes the mode of the file to mode.
369 func (f
*File
) Chmod(mode
uint32) Error
{
370 if e
:= syscall
.Fchmod(f
.fd
, mode
); e
!= 0 {
371 return &PathError
{"chmod", f
.name
, Errno(e
)}
376 // Chown changes the numeric uid and gid of the named file.
377 // If the file is a symbolic link, it changes the uid and gid of the link's target.
378 func Chown(name
string, uid
, gid
int) Error
{
379 if e
:= syscall
.Chown(name
, uid
, gid
); e
!= 0 {
380 return &PathError
{"chown", name
, Errno(e
)}
385 // Lchown changes the numeric uid and gid of the named file.
386 // If the file is a symbolic link, it changes the uid and gid of the link itself.
387 func Lchown(name
string, uid
, gid
int) Error
{
388 if e
:= syscall
.Lchown(name
, uid
, gid
); e
!= 0 {
389 return &PathError
{"lchown", name
, Errno(e
)}
394 // Chown changes the numeric uid and gid of the named file.
395 func (f
*File
) Chown(uid
, gid
int) Error
{
396 if e
:= syscall
.Fchown(f
.fd
, uid
, gid
); e
!= 0 {
397 return &PathError
{"chown", f
.name
, Errno(e
)}
402 // Truncate changes the size of the file.
403 // It does not change the I/O offset.
404 func (f
*File
) Truncate(size
int64) Error
{
405 if e
:= syscall
.Ftruncate(f
.fd
, size
); e
!= 0 {
406 return &PathError
{"truncate", f
.name
, Errno(e
)}
411 // Chtimes changes the access and modification times of the named
412 // file, similar to the Unix utime() or utimes() functions.
414 // The argument times are in nanoseconds, although the underlying
415 // filesystem may truncate or round the values to a more
417 func Chtimes(name
string, atime_ns
int64, mtime_ns
int64) Error
{
418 var utimes
[2]syscall
.Timeval
419 utimes
[0] = syscall
.NsecToTimeval(atime_ns
)
420 utimes
[1] = syscall
.NsecToTimeval(mtime_ns
)
421 if e
:= syscall
.Utimes(name
, utimes
[0:]); e
!= 0 {
422 return &PathError
{"chtimes", name
, Errno(e
)}