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.
|
|
|
|
|
|
2018-03-04 12:16:18 +01:00
|
|
|
// +build darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris
|
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 (
|
2017-02-10 15:17:38 -08:00
|
|
|
"internal/poll"
|
2018-03-11 19:11:33 +02:00
|
|
|
"internal/syscall/unix"
|
2010-04-13 16:30:11 -07:00
|
|
|
"runtime"
|
|
|
|
|
"syscall"
|
|
|
|
|
)
|
|
|
|
|
|
2016-10-28 13:01:51 -04:00
|
|
|
// fixLongPath is a noop on non-Windows platforms.
|
|
|
|
|
func fixLongPath(path string) string {
|
|
|
|
|
return path
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-26 12:10:11 -08:00
|
|
|
func rename(oldname, newname string) error {
|
2016-10-18 12:34:19 -04:00
|
|
|
fi, err := Lstat(newname)
|
|
|
|
|
if err == nil && fi.IsDir() {
|
2017-05-18 22:50:35 +00:00
|
|
|
// There are two independent errors this function can return:
|
|
|
|
|
// one for a bad oldname, and one for a bad newname.
|
|
|
|
|
// At this point we've determined the newname is bad.
|
|
|
|
|
// But just in case oldname is also bad, prioritize returning
|
|
|
|
|
// the oldname error because that's what we did historically.
|
|
|
|
|
if _, err := Lstat(oldname); err != nil {
|
|
|
|
|
if pe, ok := err.(*PathError); ok {
|
|
|
|
|
err = pe.Err
|
2017-04-13 11:23:35 -05:00
|
|
|
}
|
|
|
|
|
return &LinkError{"rename", oldname, newname, err}
|
|
|
|
|
}
|
2016-10-18 12:34:19 -04:00
|
|
|
return &LinkError{"rename", oldname, newname, syscall.EEXIST}
|
|
|
|
|
}
|
2017-04-13 11:23:35 -05:00
|
|
|
err = syscall.Rename(oldname, newname)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return &LinkError{"rename", oldname, newname, err}
|
2015-02-26 12:10:11 -08:00
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
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 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 {
|
2017-09-23 22:00:53 -07:00
|
|
|
pfd poll.FD
|
|
|
|
|
name string
|
|
|
|
|
dirinfo *dirInfo // nil unless directory being read
|
|
|
|
|
nonblock bool // whether we set nonblocking mode
|
|
|
|
|
stdoutOrErr bool // whether this is stdout or stderr
|
2011-07-01 10:18:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fd returns the integer Unix file descriptor referencing the open file.
|
2014-11-06 09:36:51 -05:00
|
|
|
// The file descriptor is valid only until f.Close is called or f is garbage collected.
|
os: calling Fd disables the SetDeadline methods
The full truth seems too complicated to write in this method's doc, so
I'm going with a simple half truth.
The full truth is that Fd returns the descriptor in blocking mode,
because that is historically how it worked, and existing programs
would be surprised if the descriptor is suddenly non-blocking. On Unix
systems whether a file is non-blocking or not is a property of the
underlying file description, not of a particular file descriptor, so
changing the returned descriptor to blocking mode also changes the
existing File to blocking mode. Blocking mode works fine, althoug I/O
operations now take up a thread. SetDeadline and friends rely on the
runtime poller, and the runtime poller only works if the descriptor is
non-blocking. So it's correct that calling Fd disables SetDeadline.
The other half of the truth is that if the program is willing to work
with a non-blocking descriptor, it could call
syscall.SetNonblock(descriptor, true) to change the descriptor, and
the original File, to non-blocking mode. At that point SetDeadline
would start working again. I tried to write that in a way that is
short and comprehensible but failed. Since deadlines mostly work on
pipes, and there isn't much reason to call Fd on a pipe, and few
people use SetDeadline, I decided to punt.
Fixes #22934
Change-Id: I2e49e036f0bcf71f5365193831696f9e4120527c
Reviewed-on: https://go-review.googlesource.com/81636
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2017-12-01 16:55:46 -08:00
|
|
|
// On Unix systems this will cause the SetDeadline methods to stop working.
|
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
|
|
|
}
|
2017-02-10 15:17:38 -08:00
|
|
|
|
|
|
|
|
// If we put the file descriptor into nonblocking mode,
|
|
|
|
|
// then set it to blocking mode before we return it,
|
|
|
|
|
// because historically we have always returned a descriptor
|
|
|
|
|
// opened in blocking mode. The File will continue to work,
|
|
|
|
|
// but any blocking operation will tie up a thread.
|
|
|
|
|
if f.nonblock {
|
2017-12-13 06:32:06 -08:00
|
|
|
f.pfd.SetBlocking()
|
2017-02-10 15:17:38 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return uintptr(f.pfd.Sysfd)
|
2011-07-01 10:18:07 -04:00
|
|
|
}
|
|
|
|
|
|
2017-04-20 11:13:55 +02:00
|
|
|
// NewFile returns a new File with the given file descriptor and
|
|
|
|
|
// name. The returned value will be nil if fd is not a valid file
|
2018-03-11 19:11:33 +02:00
|
|
|
// descriptor. On Unix systems, if the file descriptor is in
|
|
|
|
|
// non-blocking mode, NewFile will attempt to return a pollable File
|
|
|
|
|
// (one for which the SetDeadline methods work).
|
2012-02-10 14:16:15 +11:00
|
|
|
func NewFile(fd uintptr, name string) *File {
|
2018-03-11 19:11:33 +02:00
|
|
|
kind := kindNewFile
|
|
|
|
|
if nb, err := unix.IsNonblock(int(fd)); err == nil && nb {
|
|
|
|
|
kind = kindNonBlock
|
|
|
|
|
}
|
|
|
|
|
return newFile(fd, name, kind)
|
2017-02-10 15:17:38 -08:00
|
|
|
}
|
|
|
|
|
|
2017-10-17 13:57:34 -07:00
|
|
|
// newFileKind describes the kind of file to newFile.
|
|
|
|
|
type newFileKind int
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
kindNewFile newFileKind = iota
|
|
|
|
|
kindOpenFile
|
|
|
|
|
kindPipe
|
2018-03-11 19:11:33 +02:00
|
|
|
kindNonBlock
|
2017-10-17 13:57:34 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// newFile is like NewFile, but if called from OpenFile or Pipe
|
|
|
|
|
// (as passed in the kind parameter) it tries to add the file to
|
|
|
|
|
// the runtime poller.
|
|
|
|
|
func newFile(fd uintptr, name string, kind newFileKind) *File {
|
2012-02-10 14:16:15 +11:00
|
|
|
fdi := int(fd)
|
|
|
|
|
if fdi < 0 {
|
2011-07-01 10:18:07 -04:00
|
|
|
return nil
|
|
|
|
|
}
|
2017-02-10 15:17:38 -08:00
|
|
|
f := &File{&file{
|
|
|
|
|
pfd: poll.FD{
|
|
|
|
|
Sysfd: fdi,
|
|
|
|
|
IsStream: true,
|
|
|
|
|
ZeroReadIsEOF: true,
|
|
|
|
|
},
|
2017-09-23 22:00:53 -07:00
|
|
|
name: name,
|
|
|
|
|
stdoutOrErr: fdi == 1 || fdi == 2,
|
2017-02-10 15:17:38 -08:00
|
|
|
}}
|
|
|
|
|
|
|
|
|
|
// Don't try to use kqueue with regular files on FreeBSD.
|
|
|
|
|
// It crashes the system unpredictably while running all.bash.
|
|
|
|
|
// Issue 19093.
|
2018-03-11 19:11:33 +02:00
|
|
|
// If the caller passed a non-blocking filedes (kindNonBlock),
|
|
|
|
|
// we assume they know what they are doing so we allow it to be
|
|
|
|
|
// used with kqueue.
|
2017-10-17 13:57:34 -07:00
|
|
|
if runtime.GOOS == "freebsd" && kind == kindOpenFile {
|
|
|
|
|
kind = kindNewFile
|
2017-02-10 15:17:38 -08:00
|
|
|
}
|
|
|
|
|
|
2018-03-11 19:11:33 +02:00
|
|
|
pollable := kind == kindOpenFile || kind == kindPipe || kind == kindNonBlock
|
2017-04-07 15:53:19 -07:00
|
|
|
if err := f.pfd.Init("file", pollable); err != nil {
|
|
|
|
|
// An error here indicates a failure to register
|
|
|
|
|
// with the netpoll system. That can happen for
|
|
|
|
|
// a file descriptor that is not supported by
|
|
|
|
|
// epoll/kqueue; for example, disk files on
|
|
|
|
|
// GNU/Linux systems. We assume that any real error
|
|
|
|
|
// will show up in later I/O.
|
|
|
|
|
} else if pollable {
|
|
|
|
|
// We successfully registered with netpoll, so put
|
|
|
|
|
// the file into nonblocking mode.
|
|
|
|
|
if err := syscall.SetNonblock(fdi, true); err == nil {
|
|
|
|
|
f.nonblock = true
|
2017-02-10 15:17:38 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
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.
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-28 11:29:22 -08:00
|
|
|
// epipecheck raises SIGPIPE if we get an EPIPE error on standard
|
|
|
|
|
// output or standard error. See the SIGPIPE docs in os/signal, and
|
|
|
|
|
// issue 11845.
|
2012-07-27 22:21:33 +10:00
|
|
|
func epipecheck(file *File, e error) {
|
2017-09-23 22:00:53 -07:00
|
|
|
if e == syscall.EPIPE && file.stdoutOrErr {
|
2015-12-28 11:29:22 -08:00
|
|
|
sigpipe()
|
2012-07-27 22:21:33 +10:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
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"
|
|
|
|
|
|
2017-12-11 16:41:37 -08:00
|
|
|
// openFileNolog is the Unix implementation of OpenFile.
|
|
|
|
|
func openFileNolog(name string, flag int, perm FileMode) (*File, error) {
|
2017-12-16 19:06:10 +02:00
|
|
|
setSticky := false
|
2014-12-16 08:22:17 -08:00
|
|
|
if !supportsCreateWithStickyBit && flag&O_CREATE != 0 && perm&ModeSticky != 0 {
|
|
|
|
|
if _, err := Stat(name); IsNotExist(err) {
|
2017-12-16 19:06:10 +02:00
|
|
|
setSticky = true
|
2014-12-16 08:22:17 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-17 16:28:15 +10:00
|
|
|
var r int
|
|
|
|
|
for {
|
|
|
|
|
var e error
|
|
|
|
|
r, e = syscall.Open(name, flag|syscall.O_CLOEXEC, syscallMode(perm))
|
|
|
|
|
if e == nil {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-17 08:32:09 +10:00
|
|
|
// On OS X, sigaction(2) doesn't guarantee that SA_RESTART will cause
|
|
|
|
|
// open(2) to be restarted for regular files. This is easy to reproduce on
|
2018-06-01 17:29:59 -03:00
|
|
|
// fuse file systems (see https://golang.org/issue/11180).
|
2015-09-17 16:28:15 +10:00
|
|
|
if runtime.GOOS == "darwin" && e == syscall.EINTR {
|
|
|
|
|
continue
|
2015-09-17 08:32:09 +10:00
|
|
|
}
|
|
|
|
|
|
2011-11-13 22:44:52 -05:00
|
|
|
return nil, &PathError{"open", name, e}
|
2010-04-13 16:30:11 -07:00
|
|
|
}
|
|
|
|
|
|
2014-12-16 08:22:17 -08:00
|
|
|
// open(2) itself won't handle the sticky bit on *BSD and Solaris
|
2017-12-16 19:06:10 +02:00
|
|
|
if setSticky {
|
|
|
|
|
setStickyBit(name)
|
2014-12-16 08:22:17 -08:00
|
|
|
}
|
|
|
|
|
|
2010-04-13 16:30:11 -07:00
|
|
|
// There's a race here with fork/exec, which we are
|
2016-03-01 23:21:55 +00:00
|
|
|
// content to live with. See ../syscall/exec_unix.go.
|
2014-03-04 09:27:29 +09:00
|
|
|
if !supportsCloseOnExec {
|
2010-04-13 16:30:11 -07:00
|
|
|
syscall.CloseOnExec(r)
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-17 13:57:34 -07:00
|
|
|
return newFile(uintptr(r), name, kindOpenFile), 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 {
|
2017-04-24 21:49:26 -07:00
|
|
|
if file == nil {
|
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
|
2017-02-10 15:17:38 -08:00
|
|
|
if e := file.pfd.Close(); e != nil {
|
2017-04-25 17:47:34 -07:00
|
|
|
if e == poll.ErrFileClosing {
|
|
|
|
|
e = ErrClosed
|
|
|
|
|
}
|
2011-11-13 22:44:52 -05:00
|
|
|
err = &PathError{"close", file.name, e}
|
2010-04-13 16:30:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// no need for a finalizer anymore
|
|
|
|
|
runtime.SetFinalizer(file, nil)
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
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) {
|
2017-02-10 15:17:38 -08:00
|
|
|
n, err = f.pfd.Read(b)
|
|
|
|
|
runtime.KeepAlive(f)
|
|
|
|
|
return n, err
|
2011-04-26 18:09:46 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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.
|
2014-04-26 10:34:33 -07:00
|
|
|
// EOF is signaled by a zero count with err set to nil.
|
2011-11-13 22:44:52 -05:00
|
|
|
func (f *File) pread(b []byte, off int64) (n int, err error) {
|
2017-02-10 15:17:38 -08:00
|
|
|
n, err = f.pfd.Pread(b, off)
|
|
|
|
|
runtime.KeepAlive(f)
|
|
|
|
|
return n, err
|
2011-04-26 18:09:46 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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) {
|
2017-02-10 15:17:38 -08:00
|
|
|
n, err = f.pfd.Write(b)
|
|
|
|
|
runtime.KeepAlive(f)
|
|
|
|
|
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) {
|
2017-02-10 15:17:38 -08:00
|
|
|
n, err = f.pfd.Pwrite(b, off)
|
|
|
|
|
runtime.KeepAlive(f)
|
|
|
|
|
return n, err
|
2011-04-26 18:09:46 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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) {
|
2017-02-10 15:17:38 -08:00
|
|
|
ret, err = f.pfd.Seek(offset, whence)
|
|
|
|
|
runtime.KeepAlive(f)
|
|
|
|
|
return ret, err
|
2011-04-26 18:09:46 +10:00
|
|
|
}
|
|
|
|
|
|
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)
|
2016-03-01 23:21:55 +00:00
|
|
|
// returns EISDIR, so can't use that. However,
|
2011-12-20 11:52:20 +11:00
|
|
|
// 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}
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-14 18:29:49 +00:00
|
|
|
func tempDir() string {
|
2011-11-14 14:06:50 -05:00
|
|
|
dir := Getenv("TMPDIR")
|
|
|
|
|
if dir == "" {
|
2014-07-09 14:12:30 -04:00
|
|
|
if runtime.GOOS == "android" {
|
|
|
|
|
dir = "/data/local/tmp"
|
|
|
|
|
} else {
|
|
|
|
|
dir = "/tmp"
|
|
|
|
|
}
|
2011-11-14 14:06:50 -05:00
|
|
|
}
|
|
|
|
|
return dir
|
|
|
|
|
}
|
2014-07-17 17:02:46 +10:00
|
|
|
|
|
|
|
|
// Link creates newname as a hard link to the oldname file.
|
|
|
|
|
// If there is an error, it will be of type *LinkError.
|
|
|
|
|
func Link(oldname, newname string) error {
|
|
|
|
|
e := syscall.Link(oldname, newname)
|
|
|
|
|
if e != nil {
|
|
|
|
|
return &LinkError{"link", oldname, newname, e}
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Symlink creates newname as a symbolic link to oldname.
|
|
|
|
|
// If there is an error, it will be of type *LinkError.
|
|
|
|
|
func Symlink(oldname, newname string) error {
|
|
|
|
|
e := syscall.Symlink(oldname, newname)
|
|
|
|
|
if e != nil {
|
|
|
|
|
return &LinkError{"symlink", oldname, newname, e}
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|