...
Run Format

Source file src/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 darwin dragonfly freebsd linux nacl netbsd openbsd solaris
     6	
     7	package os
     8	
     9	import (
    10		"runtime"
    11		"sync/atomic"
    12		"syscall"
    13	)
    14	
    15	func rename(oldname, newname string) error {
    16		e := syscall.Rename(oldname, newname)
    17		if e != nil {
    18			return &LinkError{"rename", oldname, newname, e}
    19		}
    20		return nil
    21	}
    22	
    23	// File represents an open file descriptor.
    24	type File struct {
    25		*file
    26	}
    27	
    28	// file is the real representation of *File.
    29	// The extra level of indirection ensures that no clients of os
    30	// can overwrite this data, which could cause the finalizer
    31	// to close the wrong file descriptor.
    32	type file struct {
    33		fd      int
    34		name    string
    35		dirinfo *dirInfo // nil unless directory being read
    36		nepipe  int32    // number of consecutive EPIPE in Write
    37	}
    38	
    39	// Fd returns the integer Unix file descriptor referencing the open file.
    40	// The file descriptor is valid only until f.Close is called or f is garbage collected.
    41	func (f *File) Fd() uintptr {
    42		if f == nil {
    43			return ^(uintptr(0))
    44		}
    45		return uintptr(f.fd)
    46	}
    47	
    48	// NewFile returns a new File with the given file descriptor and name.
    49	func NewFile(fd uintptr, name string) *File {
    50		fdi := int(fd)
    51		if fdi < 0 {
    52			return nil
    53		}
    54		f := &File{&file{fd: fdi, name: name}}
    55		runtime.SetFinalizer(f.file, (*file).close)
    56		return f
    57	}
    58	
    59	// Auxiliary information if the File describes a directory
    60	type dirInfo struct {
    61		buf  []byte // buffer for directory I/O
    62		nbuf int    // length of buf; return value from Getdirentries
    63		bufp int    // location of next record in buf.
    64	}
    65	
    66	func epipecheck(file *File, e error) {
    67		if e == syscall.EPIPE {
    68			if atomic.AddInt32(&file.nepipe, 1) >= 10 {
    69				sigpipe()
    70			}
    71		} else {
    72			atomic.StoreInt32(&file.nepipe, 0)
    73		}
    74	}
    75	
    76	// DevNull is the name of the operating system's ``null device.''
    77	// On Unix-like systems, it is "/dev/null"; on Windows, "NUL".
    78	const DevNull = "/dev/null"
    79	
    80	// OpenFile is the generalized open call; most users will use Open
    81	// or Create instead.  It opens the named file with specified flag
    82	// (O_RDONLY etc.) and perm, (0666 etc.) if applicable.  If successful,
    83	// methods on the returned File can be used for I/O.
    84	// If there is an error, it will be of type *PathError.
    85	func OpenFile(name string, flag int, perm FileMode) (*File, error) {
    86		chmod := false
    87		if !supportsCreateWithStickyBit && flag&O_CREATE != 0 && perm&ModeSticky != 0 {
    88			if _, err := Stat(name); IsNotExist(err) {
    89				chmod = true
    90			}
    91		}
    92	
    93		r, e := syscall.Open(name, flag|syscall.O_CLOEXEC, syscallMode(perm))
    94		if e != nil {
    95			return nil, &PathError{"open", name, e}
    96		}
    97	
    98		// open(2) itself won't handle the sticky bit on *BSD and Solaris
    99		if chmod {
   100			Chmod(name, perm)
   101		}
   102	
   103		// There's a race here with fork/exec, which we are
   104		// content to live with.  See ../syscall/exec_unix.go.
   105		if !supportsCloseOnExec {
   106			syscall.CloseOnExec(r)
   107		}
   108	
   109		return NewFile(uintptr(r), name), nil
   110	}
   111	
   112	// Close closes the File, rendering it unusable for I/O.
   113	// It returns an error, if any.
   114	func (f *File) Close() error {
   115		if f == nil {
   116			return ErrInvalid
   117		}
   118		return f.file.close()
   119	}
   120	
   121	func (file *file) close() error {
   122		if file == nil || file.fd < 0 {
   123			return syscall.EINVAL
   124		}
   125		var err error
   126		if e := syscall.Close(file.fd); e != nil {
   127			err = &PathError{"close", file.name, e}
   128		}
   129		file.fd = -1 // so it can't be closed again
   130	
   131		// no need for a finalizer anymore
   132		runtime.SetFinalizer(file, nil)
   133		return err
   134	}
   135	
   136	// Stat returns the FileInfo structure describing file.
   137	// If there is an error, it will be of type *PathError.
   138	func (f *File) Stat() (FileInfo, error) {
   139		if f == nil {
   140			return nil, ErrInvalid
   141		}
   142		var stat syscall.Stat_t
   143		err := syscall.Fstat(f.fd, &stat)
   144		if err != nil {
   145			return nil, &PathError{"stat", f.name, err}
   146		}
   147		return fileInfoFromStat(&stat, f.name), nil
   148	}
   149	
   150	// Stat returns a FileInfo describing the named file.
   151	// If there is an error, it will be of type *PathError.
   152	func Stat(name string) (FileInfo, error) {
   153		var stat syscall.Stat_t
   154		err := syscall.Stat(name, &stat)
   155		if err != nil {
   156			return nil, &PathError{"stat", name, err}
   157		}
   158		return fileInfoFromStat(&stat, name), nil
   159	}
   160	
   161	// Lstat returns a FileInfo describing the named file.
   162	// If the file is a symbolic link, the returned FileInfo
   163	// describes the symbolic link.  Lstat makes no attempt to follow the link.
   164	// If there is an error, it will be of type *PathError.
   165	func Lstat(name string) (FileInfo, error) {
   166		var stat syscall.Stat_t
   167		err := syscall.Lstat(name, &stat)
   168		if err != nil {
   169			return nil, &PathError{"lstat", name, err}
   170		}
   171		return fileInfoFromStat(&stat, name), nil
   172	}
   173	
   174	func (f *File) readdir(n int) (fi []FileInfo, err error) {
   175		dirname := f.name
   176		if dirname == "" {
   177			dirname = "."
   178		}
   179		names, err := f.Readdirnames(n)
   180		fi = make([]FileInfo, 0, len(names))
   181		for _, filename := range names {
   182			fip, lerr := lstat(dirname + "/" + filename)
   183			if IsNotExist(lerr) {
   184				// File disappeared between readdir + stat.
   185				// Just treat it as if it didn't exist.
   186				continue
   187			}
   188			if lerr != nil {
   189				return fi, lerr
   190			}
   191			fi = append(fi, fip)
   192		}
   193		return fi, err
   194	}
   195	
   196	// Darwin and FreeBSD can't read or write 2GB+ at a time,
   197	// even on 64-bit systems. See golang.org/issue/7812.
   198	// Use 1GB instead of, say, 2GB-1, to keep subsequent
   199	// reads aligned.
   200	const (
   201		needsMaxRW = runtime.GOOS == "darwin" || runtime.GOOS == "freebsd"
   202		maxRW      = 1 << 30
   203	)
   204	
   205	// read reads up to len(b) bytes from the File.
   206	// It returns the number of bytes read and an error, if any.
   207	func (f *File) read(b []byte) (n int, err error) {
   208		if needsMaxRW && len(b) > maxRW {
   209			b = b[:maxRW]
   210		}
   211		return fixCount(syscall.Read(f.fd, b))
   212	}
   213	
   214	// pread reads len(b) bytes from the File starting at byte offset off.
   215	// It returns the number of bytes read and the error, if any.
   216	// EOF is signaled by a zero count with err set to nil.
   217	func (f *File) pread(b []byte, off int64) (n int, err error) {
   218		if needsMaxRW && len(b) > maxRW {
   219			b = b[:maxRW]
   220		}
   221		return fixCount(syscall.Pread(f.fd, b, off))
   222	}
   223	
   224	// write writes len(b) bytes to the File.
   225	// It returns the number of bytes written and an error, if any.
   226	func (f *File) write(b []byte) (n int, err error) {
   227		for {
   228			bcap := b
   229			if needsMaxRW && len(bcap) > maxRW {
   230				bcap = bcap[:maxRW]
   231			}
   232			m, err := fixCount(syscall.Write(f.fd, bcap))
   233			n += m
   234	
   235			// If the syscall wrote some data but not all (short write)
   236			// or it returned EINTR, then assume it stopped early for
   237			// reasons that are uninteresting to the caller, and try again.
   238			if 0 < m && m < len(bcap) || err == syscall.EINTR {
   239				b = b[m:]
   240				continue
   241			}
   242	
   243			if needsMaxRW && len(bcap) != len(b) && err == nil {
   244				b = b[m:]
   245				continue
   246			}
   247	
   248			return n, err
   249		}
   250	}
   251	
   252	// pwrite writes len(b) bytes to the File starting at byte offset off.
   253	// It returns the number of bytes written and an error, if any.
   254	func (f *File) pwrite(b []byte, off int64) (n int, err error) {
   255		if needsMaxRW && len(b) > maxRW {
   256			b = b[:maxRW]
   257		}
   258		return fixCount(syscall.Pwrite(f.fd, b, off))
   259	}
   260	
   261	// seek sets the offset for the next Read or Write on file to offset, interpreted
   262	// according to whence: 0 means relative to the origin of the file, 1 means
   263	// relative to the current offset, and 2 means relative to the end.
   264	// It returns the new offset and an error, if any.
   265	func (f *File) seek(offset int64, whence int) (ret int64, err error) {
   266		return syscall.Seek(f.fd, offset, whence)
   267	}
   268	
   269	// Truncate changes the size of the named file.
   270	// If the file is a symbolic link, it changes the size of the link's target.
   271	// If there is an error, it will be of type *PathError.
   272	func Truncate(name string, size int64) error {
   273		if e := syscall.Truncate(name, size); e != nil {
   274			return &PathError{"truncate", name, e}
   275		}
   276		return nil
   277	}
   278	
   279	// Remove removes the named file or directory.
   280	// If there is an error, it will be of type *PathError.
   281	func Remove(name string) error {
   282		// System call interface forces us to know
   283		// whether name is a file or directory.
   284		// Try both: it is cheaper on average than
   285		// doing a Stat plus the right one.
   286		e := syscall.Unlink(name)
   287		if e == nil {
   288			return nil
   289		}
   290		e1 := syscall.Rmdir(name)
   291		if e1 == nil {
   292			return nil
   293		}
   294	
   295		// Both failed: figure out which error to return.
   296		// OS X and Linux differ on whether unlink(dir)
   297		// returns EISDIR, so can't use that.  However,
   298		// both agree that rmdir(file) returns ENOTDIR,
   299		// so we can use that to decide which error is real.
   300		// Rmdir might also return ENOTDIR if given a bad
   301		// file path, like /etc/passwd/foo, but in that case,
   302		// both errors will be ENOTDIR, so it's okay to
   303		// use the error from unlink.
   304		if e1 != syscall.ENOTDIR {
   305			e = e1
   306		}
   307		return &PathError{"remove", name, e}
   308	}
   309	
   310	// basename removes trailing slashes and the leading directory name from path name
   311	func basename(name string) string {
   312		i := len(name) - 1
   313		// Remove trailing slashes
   314		for ; i > 0 && name[i] == '/'; i-- {
   315			name = name[:i]
   316		}
   317		// Remove leading directory name
   318		for i--; i >= 0; i-- {
   319			if name[i] == '/' {
   320				name = name[i+1:]
   321				break
   322			}
   323		}
   324	
   325		return name
   326	}
   327	
   328	// TempDir returns the default directory to use for temporary files.
   329	func TempDir() string {
   330		dir := Getenv("TMPDIR")
   331		if dir == "" {
   332			if runtime.GOOS == "android" {
   333				dir = "/data/local/tmp"
   334			} else {
   335				dir = "/tmp"
   336			}
   337		}
   338		return dir
   339	}
   340	
   341	// Link creates newname as a hard link to the oldname file.
   342	// If there is an error, it will be of type *LinkError.
   343	func Link(oldname, newname string) error {
   344		e := syscall.Link(oldname, newname)
   345		if e != nil {
   346			return &LinkError{"link", oldname, newname, e}
   347		}
   348		return nil
   349	}
   350	
   351	// Symlink creates newname as a symbolic link to oldname.
   352	// If there is an error, it will be of type *LinkError.
   353	func Symlink(oldname, newname string) error {
   354		e := syscall.Symlink(oldname, newname)
   355		if e != nil {
   356			return &LinkError{"symlink", oldname, newname, e}
   357		}
   358		return nil
   359	}
   360	

View as plain text