...

Source file src/pkg/os/file_unix.go

     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	// +build aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris
     6	
     7	package os
     8	
     9	import (
    10		"internal/poll"
    11		"internal/syscall/unix"
    12		"io"
    13		"runtime"
    14		"syscall"
    15	)
    16	
    17	// fixLongPath is a noop on non-Windows platforms.
    18	func fixLongPath(path string) string {
    19		return path
    20	}
    21	
    22	func rename(oldname, newname string) error {
    23		fi, err := Lstat(newname)
    24		if err == nil && fi.IsDir() {
    25			// There are two independent errors this function can return:
    26			// one for a bad oldname, and one for a bad newname.
    27			// At this point we've determined the newname is bad.
    28			// But just in case oldname is also bad, prioritize returning
    29			// the oldname error because that's what we did historically.
    30			if _, err := Lstat(oldname); err != nil {
    31				if pe, ok := err.(*PathError); ok {
    32					err = pe.Err
    33				}
    34				return &LinkError{"rename", oldname, newname, err}
    35			}
    36			return &LinkError{"rename", oldname, newname, syscall.EEXIST}
    37		}
    38		err = syscall.Rename(oldname, newname)
    39		if err != nil {
    40			return &LinkError{"rename", oldname, newname, err}
    41		}
    42		return nil
    43	}
    44	
    45	// file is the real representation of *File.
    46	// The extra level of indirection ensures that no clients of os
    47	// can overwrite this data, which could cause the finalizer
    48	// to close the wrong file descriptor.
    49	type file struct {
    50		pfd         poll.FD
    51		name        string
    52		dirinfo     *dirInfo // nil unless directory being read
    53		nonblock    bool     // whether we set nonblocking mode
    54		stdoutOrErr bool     // whether this is stdout or stderr
    55		appendMode  bool     // whether file is opened for appending
    56	}
    57	
    58	// Fd returns the integer Unix file descriptor referencing the open file.
    59	// The file descriptor is valid only until f.Close is called or f is garbage collected.
    60	// On Unix systems this will cause the SetDeadline methods to stop working.
    61	func (f *File) Fd() uintptr {
    62		if f == nil {
    63			return ^(uintptr(0))
    64		}
    65	
    66		// If we put the file descriptor into nonblocking mode,
    67		// then set it to blocking mode before we return it,
    68		// because historically we have always returned a descriptor
    69		// opened in blocking mode. The File will continue to work,
    70		// but any blocking operation will tie up a thread.
    71		if f.nonblock {
    72			f.pfd.SetBlocking()
    73		}
    74	
    75		return uintptr(f.pfd.Sysfd)
    76	}
    77	
    78	// NewFile returns a new File with the given file descriptor and
    79	// name. The returned value will be nil if fd is not a valid file
    80	// descriptor. On Unix systems, if the file descriptor is in
    81	// non-blocking mode, NewFile will attempt to return a pollable File
    82	// (one for which the SetDeadline methods work).
    83	func NewFile(fd uintptr, name string) *File {
    84		kind := kindNewFile
    85		if nb, err := unix.IsNonblock(int(fd)); err == nil && nb {
    86			kind = kindNonBlock
    87		}
    88		return newFile(fd, name, kind)
    89	}
    90	
    91	// newFileKind describes the kind of file to newFile.
    92	type newFileKind int
    93	
    94	const (
    95		kindNewFile newFileKind = iota
    96		kindOpenFile
    97		kindPipe
    98		kindNonBlock
    99	)
   100	
   101	// newFile is like NewFile, but if called from OpenFile or Pipe
   102	// (as passed in the kind parameter) it tries to add the file to
   103	// the runtime poller.
   104	func newFile(fd uintptr, name string, kind newFileKind) *File {
   105		fdi := int(fd)
   106		if fdi < 0 {
   107			return nil
   108		}
   109		f := &File{&file{
   110			pfd: poll.FD{
   111				Sysfd:         fdi,
   112				IsStream:      true,
   113				ZeroReadIsEOF: true,
   114			},
   115			name:        name,
   116			stdoutOrErr: fdi == 1 || fdi == 2,
   117		}}
   118	
   119		pollable := kind == kindOpenFile || kind == kindPipe || kind == kindNonBlock
   120	
   121		// If the caller passed a non-blocking filedes (kindNonBlock),
   122		// we assume they know what they are doing so we allow it to be
   123		// used with kqueue.
   124		if kind == kindOpenFile {
   125			switch runtime.GOOS {
   126			case "darwin", "dragonfly", "freebsd", "netbsd", "openbsd":
   127				var st syscall.Stat_t
   128				err := syscall.Fstat(fdi, &st)
   129				typ := st.Mode & syscall.S_IFMT
   130				// Don't try to use kqueue with regular files on *BSDs.
   131				// On FreeBSD a regular file is always
   132				// reported as ready for writing.
   133				// On Dragonfly, NetBSD and OpenBSD the fd is signaled
   134				// only once as ready (both read and write).
   135				// Issue 19093.
   136				// Also don't add directories to the netpoller.
   137				if err == nil && (typ == syscall.S_IFREG || typ == syscall.S_IFDIR) {
   138					pollable = false
   139				}
   140	
   141				// In addition to the behavior described above for regular files,
   142				// on Darwin, kqueue does not work properly with fifos:
   143				// closing the last writer does not cause a kqueue event
   144				// for any readers. See issue #24164.
   145				if runtime.GOOS == "darwin" && typ == syscall.S_IFIFO {
   146					pollable = false
   147				}
   148			}
   149		}
   150	
   151		if err := f.pfd.Init("file", pollable); err != nil {
   152			// An error here indicates a failure to register
   153			// with the netpoll system. That can happen for
   154			// a file descriptor that is not supported by
   155			// epoll/kqueue; for example, disk files on
   156			// GNU/Linux systems. We assume that any real error
   157			// will show up in later I/O.
   158		} else if pollable {
   159			// We successfully registered with netpoll, so put
   160			// the file into nonblocking mode.
   161			if err := syscall.SetNonblock(fdi, true); err == nil {
   162				f.nonblock = true
   163			}
   164		}
   165	
   166		runtime.SetFinalizer(f.file, (*file).close)
   167		return f
   168	}
   169	
   170	// epipecheck raises SIGPIPE if we get an EPIPE error on standard
   171	// output or standard error. See the SIGPIPE docs in os/signal, and
   172	// issue 11845.
   173	func epipecheck(file *File, e error) {
   174		if e == syscall.EPIPE && file.stdoutOrErr {
   175			sigpipe()
   176		}
   177	}
   178	
   179	// DevNull is the name of the operating system's ``null device.''
   180	// On Unix-like systems, it is "/dev/null"; on Windows, "NUL".
   181	const DevNull = "/dev/null"
   182	
   183	// openFileNolog is the Unix implementation of OpenFile.
   184	// Changes here should be reflected in openFdAt, if relevant.
   185	func openFileNolog(name string, flag int, perm FileMode) (*File, error) {
   186		setSticky := false
   187		if !supportsCreateWithStickyBit && flag&O_CREATE != 0 && perm&ModeSticky != 0 {
   188			if _, err := Stat(name); IsNotExist(err) {
   189				setSticky = true
   190			}
   191		}
   192	
   193		var r int
   194		for {
   195			var e error
   196			r, e = syscall.Open(name, flag|syscall.O_CLOEXEC, syscallMode(perm))
   197			if e == nil {
   198				break
   199			}
   200	
   201			// On OS X, sigaction(2) doesn't guarantee that SA_RESTART will cause
   202			// open(2) to be restarted for regular files. This is easy to reproduce on
   203			// fuse file systems (see https://golang.org/issue/11180).
   204			if runtime.GOOS == "darwin" && e == syscall.EINTR {
   205				continue
   206			}
   207	
   208			return nil, &PathError{"open", name, e}
   209		}
   210	
   211		// open(2) itself won't handle the sticky bit on *BSD and Solaris
   212		if setSticky {
   213			setStickyBit(name)
   214		}
   215	
   216		// There's a race here with fork/exec, which we are
   217		// content to live with. See ../syscall/exec_unix.go.
   218		if !supportsCloseOnExec {
   219			syscall.CloseOnExec(r)
   220		}
   221	
   222		return newFile(uintptr(r), name, kindOpenFile), nil
   223	}
   224	
   225	// Close closes the File, rendering it unusable for I/O.
   226	// On files that support SetDeadline, any pending I/O operations will
   227	// be canceled and return immediately with an error.
   228	// Close will return an error if it has already been called.
   229	func (f *File) Close() error {
   230		if f == nil {
   231			return ErrInvalid
   232		}
   233		return f.file.close()
   234	}
   235	
   236	func (file *file) close() error {
   237		if file == nil {
   238			return syscall.EINVAL
   239		}
   240		if file.dirinfo != nil {
   241			file.dirinfo.close()
   242		}
   243		var err error
   244		if e := file.pfd.Close(); e != nil {
   245			if e == poll.ErrFileClosing {
   246				e = ErrClosed
   247			}
   248			err = &PathError{"close", file.name, e}
   249		}
   250	
   251		// no need for a finalizer anymore
   252		runtime.SetFinalizer(file, nil)
   253		return err
   254	}
   255	
   256	// read reads up to len(b) bytes from the File.
   257	// It returns the number of bytes read and an error, if any.
   258	func (f *File) read(b []byte) (n int, err error) {
   259		n, err = f.pfd.Read(b)
   260		runtime.KeepAlive(f)
   261		return n, err
   262	}
   263	
   264	// pread reads len(b) bytes from the File starting at byte offset off.
   265	// It returns the number of bytes read and the error, if any.
   266	// EOF is signaled by a zero count with err set to nil.
   267	func (f *File) pread(b []byte, off int64) (n int, err error) {
   268		n, err = f.pfd.Pread(b, off)
   269		runtime.KeepAlive(f)
   270		return n, err
   271	}
   272	
   273	// write writes len(b) bytes to the File.
   274	// It returns the number of bytes written and an error, if any.
   275	func (f *File) write(b []byte) (n int, err error) {
   276		n, err = f.pfd.Write(b)
   277		runtime.KeepAlive(f)
   278		return n, err
   279	}
   280	
   281	// pwrite writes len(b) bytes to the File starting at byte offset off.
   282	// It returns the number of bytes written and an error, if any.
   283	func (f *File) pwrite(b []byte, off int64) (n int, err error) {
   284		n, err = f.pfd.Pwrite(b, off)
   285		runtime.KeepAlive(f)
   286		return n, err
   287	}
   288	
   289	// seek sets the offset for the next Read or Write on file to offset, interpreted
   290	// according to whence: 0 means relative to the origin of the file, 1 means
   291	// relative to the current offset, and 2 means relative to the end.
   292	// It returns the new offset and an error, if any.
   293	func (f *File) seek(offset int64, whence int) (ret int64, err error) {
   294		ret, err = f.pfd.Seek(offset, whence)
   295		runtime.KeepAlive(f)
   296		return ret, err
   297	}
   298	
   299	// Truncate changes the size of the named file.
   300	// If the file is a symbolic link, it changes the size of the link's target.
   301	// If there is an error, it will be of type *PathError.
   302	func Truncate(name string, size int64) error {
   303		if e := syscall.Truncate(name, size); e != nil {
   304			return &PathError{"truncate", name, e}
   305		}
   306		return nil
   307	}
   308	
   309	// Remove removes the named file or (empty) directory.
   310	// If there is an error, it will be of type *PathError.
   311	func Remove(name string) error {
   312		// System call interface forces us to know
   313		// whether name is a file or directory.
   314		// Try both: it is cheaper on average than
   315		// doing a Stat plus the right one.
   316		e := syscall.Unlink(name)
   317		if e == nil {
   318			return nil
   319		}
   320		e1 := syscall.Rmdir(name)
   321		if e1 == nil {
   322			return nil
   323		}
   324	
   325		// Both failed: figure out which error to return.
   326		// OS X and Linux differ on whether unlink(dir)
   327		// returns EISDIR, so can't use that. However,
   328		// both agree that rmdir(file) returns ENOTDIR,
   329		// so we can use that to decide which error is real.
   330		// Rmdir might also return ENOTDIR if given a bad
   331		// file path, like /etc/passwd/foo, but in that case,
   332		// both errors will be ENOTDIR, so it's okay to
   333		// use the error from unlink.
   334		if e1 != syscall.ENOTDIR {
   335			e = e1
   336		}
   337		return &PathError{"remove", name, e}
   338	}
   339	
   340	func tempDir() string {
   341		dir := Getenv("TMPDIR")
   342		if dir == "" {
   343			if runtime.GOOS == "android" {
   344				dir = "/data/local/tmp"
   345			} else {
   346				dir = "/tmp"
   347			}
   348		}
   349		return dir
   350	}
   351	
   352	// Link creates newname as a hard link to the oldname file.
   353	// If there is an error, it will be of type *LinkError.
   354	func Link(oldname, newname string) error {
   355		e := syscall.Link(oldname, newname)
   356		if e != nil {
   357			return &LinkError{"link", oldname, newname, e}
   358		}
   359		return nil
   360	}
   361	
   362	// Symlink creates newname as a symbolic link to oldname.
   363	// If there is an error, it will be of type *LinkError.
   364	func Symlink(oldname, newname string) error {
   365		e := syscall.Symlink(oldname, newname)
   366		if e != nil {
   367			return &LinkError{"symlink", oldname, newname, e}
   368		}
   369		return nil
   370	}
   371	
   372	func (f *File) readdir(n int) (fi []FileInfo, err error) {
   373		dirname := f.name
   374		if dirname == "" {
   375			dirname = "."
   376		}
   377		names, err := f.Readdirnames(n)
   378		fi = make([]FileInfo, 0, len(names))
   379		for _, filename := range names {
   380			fip, lerr := lstat(dirname + "/" + filename)
   381			if IsNotExist(lerr) {
   382				// File disappeared between readdir + stat.
   383				// Just treat it as if it didn't exist.
   384				continue
   385			}
   386			if lerr != nil {
   387				return fi, lerr
   388			}
   389			fi = append(fi, fip)
   390		}
   391		if len(fi) == 0 && err == nil && n > 0 {
   392			// Per File.Readdir, the slice must be non-empty or err
   393			// must be non-nil if n > 0.
   394			err = io.EOF
   395		}
   396		return fi, err
   397	}
   398	
   399	// Readlink returns the destination of the named symbolic link.
   400	// If there is an error, it will be of type *PathError.
   401	func Readlink(name string) (string, error) {
   402		for len := 128; ; len *= 2 {
   403			b := make([]byte, len)
   404			n, e := fixCount(syscall.Readlink(name, b))
   405			// buffer too small
   406			if runtime.GOOS == "aix" && e == syscall.ERANGE {
   407				continue
   408			}
   409			if e != nil {
   410				return "", &PathError{"readlink", name, e}
   411			}
   412			if n < len {
   413				return string(b[0:n]), nil
   414			}
   415		}
   416	}
   417	

View as plain text