2010-04-13 16:30:11 -07:00
|
|
|
// Copyright 2009 The Go Authors. All rights reserved.
|
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
2011-12-18 02:29:18 +11:00
|
|
|
// +build darwin freebsd linux netbsd openbsd
|
build: add build comments to core packages
The go/build package already recognizes
system-specific file names like
mycode_darwin.go
mycode_darwin_386.go
mycode_386.s
However, it is also common to write files that
apply to multiple architectures, so a recent CL added
to go/build the ability to process comments
listing a set of conditions for building. For example:
// +build darwin freebsd openbsd/386
says that this file should be compiled only on
OS X, FreeBSD, or 32-bit x86 OpenBSD systems.
These conventions are not yet documented
(hence this long CL description).
This CL adds build comments to the multi-system
files in the core library, a step toward making it
possible to use go/build to build them.
With this change go/build can handle crypto/rand,
exec, net, path/filepath, os/user, and time.
os and syscall need additional adjustments.
R=golang-dev, r, gri, r, gustavo
CC=golang-dev
https://golang.org/cl/5011046
2011-09-15 16:48:57 -04:00
|
|
|
|
2010-04-13 16:30:11 -07:00
|
|
|
package os
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"runtime"
|
2012-07-27 22:21:33 +10:00
|
|
|
"sync/atomic"
|
2010-04-13 16:30:11 -07:00
|
|
|
"syscall"
|
|
|
|
|
)
|
|
|
|
|
|
2011-07-01 10:18:07 -04:00
|
|
|
// File represents an open file descriptor.
|
|
|
|
|
type File struct {
|
allow copy of struct containing unexported fields
An experiment: allow structs to be copied even if they
contain unexported fields. This gives packages the
ability to return opaque values in their APIs, like reflect
does for reflect.Value but without the kludgy hacks reflect
resorts to.
In general, we trust programmers not to do silly things
like *x = *y on a package's struct pointers, just as we trust
programmers not to do unicode.Letter = unicode.Digit,
but packages that want a harder guarantee can introduce
an extra level of indirection, like in the changes to os.File
in this CL or by using an interface type.
All in one CL so that it can be rolled back more easily if
we decide this is a bad idea.
Originally discussed in March 2011.
https://groups.google.com/group/golang-dev/t/3f5d30938c7c45ef
R=golang-dev, adg, dvyukov, r, bradfitz, jan.mercl, gri
CC=golang-dev
https://golang.org/cl/5372095
2011-11-15 12:20:59 -05:00
|
|
|
*file
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// file is the real representation of *File.
|
|
|
|
|
// The extra level of indirection ensures that no clients of os
|
|
|
|
|
// can overwrite this data, which could cause the finalizer
|
|
|
|
|
// to close the wrong file descriptor.
|
|
|
|
|
type file struct {
|
2011-07-01 10:18:07 -04:00
|
|
|
fd int
|
|
|
|
|
name string
|
2011-07-05 16:01:29 +10:00
|
|
|
dirinfo *dirInfo // nil unless directory being read
|
2012-07-27 15:05:13 +04:00
|
|
|
nepipe int32 // number of consecutive EPIPE in Write
|
2011-07-01 10:18:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fd returns the integer Unix file descriptor referencing the open file.
|
2012-02-10 14:16:15 +11:00
|
|
|
func (f *File) Fd() uintptr {
|
2011-12-01 11:23:39 -08:00
|
|
|
if f == nil {
|
2012-02-10 14:16:15 +11:00
|
|
|
return ^(uintptr(0))
|
2011-07-01 10:18:07 -04:00
|
|
|
}
|
2012-02-10 14:16:15 +11:00
|
|
|
return uintptr(f.fd)
|
2011-07-01 10:18:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NewFile returns a new File with the given file descriptor and name.
|
2012-02-10 14:16:15 +11:00
|
|
|
func NewFile(fd uintptr, name string) *File {
|
|
|
|
|
fdi := int(fd)
|
|
|
|
|
if fdi < 0 {
|
2011-07-01 10:18:07 -04:00
|
|
|
return nil
|
|
|
|
|
}
|
2012-02-10 14:16:15 +11:00
|
|
|
f := &File{&file{fd: fdi, name: name}}
|
allow copy of struct containing unexported fields
An experiment: allow structs to be copied even if they
contain unexported fields. This gives packages the
ability to return opaque values in their APIs, like reflect
does for reflect.Value but without the kludgy hacks reflect
resorts to.
In general, we trust programmers not to do silly things
like *x = *y on a package's struct pointers, just as we trust
programmers not to do unicode.Letter = unicode.Digit,
but packages that want a harder guarantee can introduce
an extra level of indirection, like in the changes to os.File
in this CL or by using an interface type.
All in one CL so that it can be rolled back more easily if
we decide this is a bad idea.
Originally discussed in March 2011.
https://groups.google.com/group/golang-dev/t/3f5d30938c7c45ef
R=golang-dev, adg, dvyukov, r, bradfitz, jan.mercl, gri
CC=golang-dev
https://golang.org/cl/5372095
2011-11-15 12:20:59 -05:00
|
|
|
runtime.SetFinalizer(f.file, (*file).close)
|
2011-07-01 10:18:07 -04:00
|
|
|
return f
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-13 16:30:11 -07:00
|
|
|
// Auxiliary information if the File describes a directory
|
|
|
|
|
type dirInfo struct {
|
|
|
|
|
buf []byte // buffer for directory I/O
|
|
|
|
|
nbuf int // length of buf; return value from Getdirentries
|
|
|
|
|
bufp int // location of next record in buf.
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-27 22:21:33 +10:00
|
|
|
func epipecheck(file *File, e error) {
|
|
|
|
|
if e == syscall.EPIPE {
|
|
|
|
|
if atomic.AddInt32(&file.nepipe, 1) >= 10 {
|
|
|
|
|
sigpipe()
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
atomic.StoreInt32(&file.nepipe, 0)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-03 13:03:50 -07:00
|
|
|
// DevNull is the name of the operating system's ``null device.''
|
|
|
|
|
// On Unix-like systems, it is "/dev/null"; on Windows, "NUL".
|
|
|
|
|
const DevNull = "/dev/null"
|
|
|
|
|
|
2011-04-04 23:42:14 -07:00
|
|
|
// OpenFile is the generalized open call; most users will use Open
|
|
|
|
|
// or Create instead. It opens the named file with specified flag
|
|
|
|
|
// (O_RDONLY etc.) and perm, (0666 etc.) if applicable. If successful,
|
|
|
|
|
// methods on the returned File can be used for I/O.
|
2012-02-09 16:55:36 +11:00
|
|
|
// If there is an error, it will be of type *PathError.
|
2012-01-19 15:45:18 -08:00
|
|
|
func OpenFile(name string, flag int, perm FileMode) (file *File, err error) {
|
|
|
|
|
r, e := syscall.Open(name, flag|syscall.O_CLOEXEC, syscallMode(perm))
|
2011-11-13 22:44:52 -05:00
|
|
|
if e != nil {
|
|
|
|
|
return nil, &PathError{"open", name, e}
|
2010-04-13 16:30:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// There's a race here with fork/exec, which we are
|
2011-12-20 15:41:37 -08:00
|
|
|
// content to live with. See ../syscall/exec_unix.go.
|
|
|
|
|
// On OS X 10.6, the O_CLOEXEC flag is not respected.
|
|
|
|
|
// On OS X 10.7, the O_CLOEXEC flag works.
|
|
|
|
|
// Without a cheap & reliable way to detect 10.6 vs 10.7 at
|
|
|
|
|
// runtime, we just always call syscall.CloseOnExec on Darwin.
|
|
|
|
|
// Once >=10.7 is prevalent, this extra call can removed.
|
|
|
|
|
if syscall.O_CLOEXEC == 0 || runtime.GOOS == "darwin" { // O_CLOEXEC not supported
|
2010-04-13 16:30:11 -07:00
|
|
|
syscall.CloseOnExec(r)
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-10 14:16:15 +11:00
|
|
|
return NewFile(uintptr(r), name), nil
|
2010-04-13 16:30:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Close closes the File, rendering it unusable for I/O.
|
2011-11-01 21:49:08 -04:00
|
|
|
// It returns an error, if any.
|
2011-12-01 11:23:39 -08:00
|
|
|
func (f *File) Close() error {
|
2013-08-20 14:33:03 +10:00
|
|
|
if f == nil {
|
|
|
|
|
return ErrInvalid
|
|
|
|
|
}
|
2011-12-01 11:23:39 -08:00
|
|
|
return f.file.close()
|
allow copy of struct containing unexported fields
An experiment: allow structs to be copied even if they
contain unexported fields. This gives packages the
ability to return opaque values in their APIs, like reflect
does for reflect.Value but without the kludgy hacks reflect
resorts to.
In general, we trust programmers not to do silly things
like *x = *y on a package's struct pointers, just as we trust
programmers not to do unicode.Letter = unicode.Digit,
but packages that want a harder guarantee can introduce
an extra level of indirection, like in the changes to os.File
in this CL or by using an interface type.
All in one CL so that it can be rolled back more easily if
we decide this is a bad idea.
Originally discussed in March 2011.
https://groups.google.com/group/golang-dev/t/3f5d30938c7c45ef
R=golang-dev, adg, dvyukov, r, bradfitz, jan.mercl, gri
CC=golang-dev
https://golang.org/cl/5372095
2011-11-15 12:20:59 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (file *file) close() error {
|
2010-04-13 16:30:11 -07:00
|
|
|
if file == nil || file.fd < 0 {
|
2012-02-17 10:04:29 +11:00
|
|
|
return syscall.EINVAL
|
2010-04-13 16:30:11 -07:00
|
|
|
}
|
2011-11-01 21:49:08 -04:00
|
|
|
var err error
|
2011-11-13 22:44:52 -05:00
|
|
|
if e := syscall.Close(file.fd); e != nil {
|
|
|
|
|
err = &PathError{"close", file.name, e}
|
2010-04-13 16:30:11 -07:00
|
|
|
}
|
|
|
|
|
file.fd = -1 // so it can't be closed again
|
|
|
|
|
|
|
|
|
|
// no need for a finalizer anymore
|
|
|
|
|
runtime.SetFinalizer(file, nil)
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-26 23:17:14 -07:00
|
|
|
// Stat returns the FileInfo structure describing file.
|
2012-02-09 16:55:36 +11:00
|
|
|
// If there is an error, it will be of type *PathError.
|
2011-12-01 11:23:39 -08:00
|
|
|
func (f *File) Stat() (fi FileInfo, err error) {
|
2013-08-20 14:33:03 +10:00
|
|
|
if f == nil {
|
|
|
|
|
return nil, ErrInvalid
|
|
|
|
|
}
|
2010-04-26 23:17:14 -07:00
|
|
|
var stat syscall.Stat_t
|
2011-12-01 11:23:39 -08:00
|
|
|
err = syscall.Fstat(f.fd, &stat)
|
2011-11-30 12:04:16 -05:00
|
|
|
if err != nil {
|
2011-12-01 11:23:39 -08:00
|
|
|
return nil, &PathError{"stat", f.name, err}
|
2010-04-26 23:17:14 -07:00
|
|
|
}
|
2011-12-01 11:23:39 -08:00
|
|
|
return fileInfoFromStat(&stat, f.name), nil
|
2010-04-26 23:17:14 -07:00
|
|
|
}
|
|
|
|
|
|
2012-02-09 16:55:36 +11:00
|
|
|
// Stat returns a FileInfo describing the named file.
|
|
|
|
|
// If there is an error, it will be of type *PathError.
|
2011-11-30 12:04:16 -05:00
|
|
|
func Stat(name string) (fi FileInfo, err error) {
|
|
|
|
|
var stat syscall.Stat_t
|
|
|
|
|
err = syscall.Stat(name, &stat)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, &PathError{"stat", name, err}
|
2011-09-06 09:59:08 +10:00
|
|
|
}
|
2011-11-30 12:04:16 -05:00
|
|
|
return fileInfoFromStat(&stat, name), nil
|
2011-09-06 09:59:08 +10:00
|
|
|
}
|
|
|
|
|
|
2012-02-09 16:55:36 +11:00
|
|
|
// Lstat returns a FileInfo describing the named file.
|
|
|
|
|
// If the file is a symbolic link, the returned FileInfo
|
2011-09-06 09:59:08 +10:00
|
|
|
// describes the symbolic link. Lstat makes no attempt to follow the link.
|
2012-02-09 16:55:36 +11:00
|
|
|
// If there is an error, it will be of type *PathError.
|
2011-11-30 12:04:16 -05:00
|
|
|
func Lstat(name string) (fi FileInfo, err error) {
|
2011-09-06 09:59:08 +10:00
|
|
|
var stat syscall.Stat_t
|
2011-11-30 12:04:16 -05:00
|
|
|
err = syscall.Lstat(name, &stat)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, &PathError{"lstat", name, err}
|
2011-09-06 09:59:08 +10:00
|
|
|
}
|
2011-11-30 12:04:16 -05:00
|
|
|
return fileInfoFromStat(&stat, name), nil
|
2011-09-06 09:59:08 +10:00
|
|
|
}
|
|
|
|
|
|
2012-01-17 16:51:54 +11:00
|
|
|
func (f *File) readdir(n int) (fi []FileInfo, err error) {
|
2011-12-01 11:23:39 -08:00
|
|
|
dirname := f.name
|
2010-04-13 16:30:11 -07:00
|
|
|
if dirname == "" {
|
|
|
|
|
dirname = "."
|
|
|
|
|
}
|
|
|
|
|
dirname += "/"
|
2011-12-01 11:23:39 -08:00
|
|
|
names, err := f.Readdirnames(n)
|
2010-04-13 16:30:11 -07:00
|
|
|
fi = make([]FileInfo, len(names))
|
|
|
|
|
for i, filename := range names {
|
2013-08-08 10:44:01 -07:00
|
|
|
fip, lerr := lstat(dirname + filename)
|
|
|
|
|
if lerr == nil {
|
2011-11-30 12:04:16 -05:00
|
|
|
fi[i] = fip
|
2010-04-13 16:30:11 -07:00
|
|
|
} else {
|
2012-02-03 00:16:18 -02:00
|
|
|
fi[i] = &fileStat{name: filename}
|
2013-08-08 10:44:01 -07:00
|
|
|
if err == nil {
|
|
|
|
|
err = lerr
|
|
|
|
|
}
|
2010-04-13 16:30:11 -07:00
|
|
|
}
|
|
|
|
|
}
|
2011-11-30 12:04:16 -05:00
|
|
|
return fi, err
|
2010-04-13 16:30:11 -07:00
|
|
|
}
|
2010-04-26 23:17:14 -07:00
|
|
|
|
2011-04-26 18:09:46 +10:00
|
|
|
// read reads up to len(b) bytes from the File.
|
|
|
|
|
// It returns the number of bytes read and an error, if any.
|
2011-11-13 22:44:52 -05:00
|
|
|
func (f *File) read(b []byte) (n int, err error) {
|
2011-04-26 18:09:46 +10:00
|
|
|
return syscall.Read(f.fd, b)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// pread reads len(b) bytes from the File starting at byte offset off.
|
|
|
|
|
// It returns the number of bytes read and the error, if any.
|
|
|
|
|
// EOF is signaled by a zero count with err set to 0.
|
2011-11-13 22:44:52 -05:00
|
|
|
func (f *File) pread(b []byte, off int64) (n int, err error) {
|
2011-04-26 18:09:46 +10:00
|
|
|
return syscall.Pread(f.fd, b, off)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// write writes len(b) bytes to the File.
|
|
|
|
|
// It returns the number of bytes written and an error, if any.
|
2011-11-13 22:44:52 -05:00
|
|
|
func (f *File) write(b []byte) (n int, err error) {
|
2012-03-15 15:10:19 -04:00
|
|
|
for {
|
|
|
|
|
m, err := syscall.Write(f.fd, b)
|
|
|
|
|
n += m
|
|
|
|
|
|
|
|
|
|
// If the syscall wrote some data but not all (short write)
|
|
|
|
|
// or it returned EINTR, then assume it stopped early for
|
|
|
|
|
// reasons that are uninteresting to the caller, and try again.
|
|
|
|
|
if 0 < m && m < len(b) || err == syscall.EINTR {
|
|
|
|
|
b = b[m:]
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return n, err
|
|
|
|
|
}
|
2011-04-26 18:09:46 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// pwrite writes len(b) bytes to the File starting at byte offset off.
|
|
|
|
|
// It returns the number of bytes written and an error, if any.
|
2011-11-13 22:44:52 -05:00
|
|
|
func (f *File) pwrite(b []byte, off int64) (n int, err error) {
|
2011-04-26 18:09:46 +10:00
|
|
|
return syscall.Pwrite(f.fd, b, off)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// seek sets the offset for the next Read or Write on file to offset, interpreted
|
|
|
|
|
// according to whence: 0 means relative to the origin of the file, 1 means
|
|
|
|
|
// relative to the current offset, and 2 means relative to the end.
|
|
|
|
|
// It returns the new offset and an error, if any.
|
2011-11-13 22:44:52 -05:00
|
|
|
func (f *File) seek(offset int64, whence int) (ret int64, err error) {
|
2011-04-26 18:09:46 +10:00
|
|
|
return syscall.Seek(f.fd, offset, whence)
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-26 23:17:14 -07:00
|
|
|
// Truncate changes the size of the named file.
|
|
|
|
|
// If the file is a symbolic link, it changes the size of the link's target.
|
2012-02-09 16:55:36 +11:00
|
|
|
// If there is an error, it will be of type *PathError.
|
2011-11-01 21:49:08 -04:00
|
|
|
func Truncate(name string, size int64) error {
|
2011-11-13 22:44:52 -05:00
|
|
|
if e := syscall.Truncate(name, size); e != nil {
|
|
|
|
|
return &PathError{"truncate", name, e}
|
2010-04-26 23:17:14 -07:00
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
2011-03-29 14:23:36 -04:00
|
|
|
|
2011-12-20 11:52:20 +11:00
|
|
|
// Remove removes the named file or directory.
|
2012-02-09 16:55:36 +11:00
|
|
|
// If there is an error, it will be of type *PathError.
|
2011-12-20 11:52:20 +11:00
|
|
|
func Remove(name string) error {
|
|
|
|
|
// System call interface forces us to know
|
|
|
|
|
// whether name is a file or directory.
|
|
|
|
|
// Try both: it is cheaper on average than
|
|
|
|
|
// doing a Stat plus the right one.
|
|
|
|
|
e := syscall.Unlink(name)
|
|
|
|
|
if e == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
e1 := syscall.Rmdir(name)
|
|
|
|
|
if e1 == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Both failed: figure out which error to return.
|
|
|
|
|
// OS X and Linux differ on whether unlink(dir)
|
|
|
|
|
// returns EISDIR, so can't use that. However,
|
|
|
|
|
// both agree that rmdir(file) returns ENOTDIR,
|
|
|
|
|
// so we can use that to decide which error is real.
|
|
|
|
|
// Rmdir might also return ENOTDIR if given a bad
|
|
|
|
|
// file path, like /etc/passwd/foo, but in that case,
|
|
|
|
|
// both errors will be ENOTDIR, so it's okay to
|
|
|
|
|
// use the error from unlink.
|
|
|
|
|
if e1 != syscall.ENOTDIR {
|
|
|
|
|
e = e1
|
|
|
|
|
}
|
|
|
|
|
return &PathError{"remove", name, e}
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-29 14:23:36 -04:00
|
|
|
// basename removes trailing slashes and the leading directory name from path name
|
|
|
|
|
func basename(name string) string {
|
|
|
|
|
i := len(name) - 1
|
|
|
|
|
// Remove trailing slashes
|
|
|
|
|
for ; i > 0 && name[i] == '/'; i-- {
|
|
|
|
|
name = name[:i]
|
|
|
|
|
}
|
|
|
|
|
// Remove leading directory name
|
|
|
|
|
for i--; i >= 0; i-- {
|
|
|
|
|
if name[i] == '/' {
|
|
|
|
|
name = name[i+1:]
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return name
|
|
|
|
|
}
|
2011-07-01 10:18:07 -04:00
|
|
|
|
2011-11-14 14:06:50 -05:00
|
|
|
// TempDir returns the default directory to use for temporary files.
|
|
|
|
|
func TempDir() string {
|
|
|
|
|
dir := Getenv("TMPDIR")
|
|
|
|
|
if dir == "" {
|
|
|
|
|
dir = "/tmp"
|
|
|
|
|
}
|
|
|
|
|
return dir
|
|
|
|
|
}
|