Black Lives Matter. Support the Equal Justice Initiative.

Source file src/os/file_posix.go

Documentation: os

     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 netbsd openbsd solaris windows
     6  
     7  package os
     8  
     9  import (
    10  	"runtime"
    11  	"syscall"
    12  	"time"
    13  )
    14  
    15  func sigpipe() // implemented in package runtime
    16  
    17  // Close closes the File, rendering it unusable for I/O.
    18  // On files that support SetDeadline, any pending I/O operations will
    19  // be canceled and return immediately with an error.
    20  // Close will return an error if it has already been called.
    21  func (f *File) Close() error {
    22  	if f == nil {
    23  		return ErrInvalid
    24  	}
    25  	return f.file.close()
    26  }
    27  
    28  // read reads up to len(b) bytes from the File.
    29  // It returns the number of bytes read and an error, if any.
    30  func (f *File) read(b []byte) (n int, err error) {
    31  	n, err = f.pfd.Read(b)
    32  	runtime.KeepAlive(f)
    33  	return n, err
    34  }
    35  
    36  // pread reads len(b) bytes from the File starting at byte offset off.
    37  // It returns the number of bytes read and the error, if any.
    38  // EOF is signaled by a zero count with err set to nil.
    39  func (f *File) pread(b []byte, off int64) (n int, err error) {
    40  	n, err = f.pfd.Pread(b, off)
    41  	runtime.KeepAlive(f)
    42  	return n, err
    43  }
    44  
    45  // write writes len(b) bytes to the File.
    46  // It returns the number of bytes written and an error, if any.
    47  func (f *File) write(b []byte) (n int, err error) {
    48  	n, err = f.pfd.Write(b)
    49  	runtime.KeepAlive(f)
    50  	return n, err
    51  }
    52  
    53  // pwrite writes len(b) bytes to the File starting at byte offset off.
    54  // It returns the number of bytes written and an error, if any.
    55  func (f *File) pwrite(b []byte, off int64) (n int, err error) {
    56  	n, err = f.pfd.Pwrite(b, off)
    57  	runtime.KeepAlive(f)
    58  	return n, err
    59  }
    60  
    61  // syscallMode returns the syscall-specific mode bits from Go's portable mode bits.
    62  func syscallMode(i FileMode) (o uint32) {
    63  	o |= uint32(i.Perm())
    64  	if i&ModeSetuid != 0 {
    65  		o |= syscall.S_ISUID
    66  	}
    67  	if i&ModeSetgid != 0 {
    68  		o |= syscall.S_ISGID
    69  	}
    70  	if i&ModeSticky != 0 {
    71  		o |= syscall.S_ISVTX
    72  	}
    73  	// No mapping for Go's ModeTemporary (plan9 only).
    74  	return
    75  }
    76  
    77  // See docs in file.go:Chmod.
    78  func chmod(name string, mode FileMode) error {
    79  	longName := fixLongPath(name)
    80  	e := ignoringEINTR(func() error {
    81  		return syscall.Chmod(longName, syscallMode(mode))
    82  	})
    83  	if e != nil {
    84  		return &PathError{Op: "chmod", Path: name, Err: e}
    85  	}
    86  	return nil
    87  }
    88  
    89  // See docs in file.go:(*File).Chmod.
    90  func (f *File) chmod(mode FileMode) error {
    91  	if err := f.checkValid("chmod"); err != nil {
    92  		return err
    93  	}
    94  	if e := f.pfd.Fchmod(syscallMode(mode)); e != nil {
    95  		return f.wrapErr("chmod", e)
    96  	}
    97  	return nil
    98  }
    99  
   100  // Chown changes the numeric uid and gid of the named file.
   101  // If the file is a symbolic link, it changes the uid and gid of the link's target.
   102  // A uid or gid of -1 means to not change that value.
   103  // If there is an error, it will be of type *PathError.
   104  //
   105  // On Windows or Plan 9, Chown always returns the syscall.EWINDOWS or
   106  // EPLAN9 error, wrapped in *PathError.
   107  func Chown(name string, uid, gid int) error {
   108  	e := ignoringEINTR(func() error {
   109  		return syscall.Chown(name, uid, gid)
   110  	})
   111  	if e != nil {
   112  		return &PathError{Op: "chown", Path: name, Err: e}
   113  	}
   114  	return nil
   115  }
   116  
   117  // Lchown changes the numeric uid and gid of the named file.
   118  // If the file is a symbolic link, it changes the uid and gid of the link itself.
   119  // If there is an error, it will be of type *PathError.
   120  //
   121  // On Windows, it always returns the syscall.EWINDOWS error, wrapped
   122  // in *PathError.
   123  func Lchown(name string, uid, gid int) error {
   124  	e := ignoringEINTR(func() error {
   125  		return syscall.Lchown(name, uid, gid)
   126  	})
   127  	if e != nil {
   128  		return &PathError{Op: "lchown", Path: name, Err: e}
   129  	}
   130  	return nil
   131  }
   132  
   133  // Chown changes the numeric uid and gid of the named file.
   134  // If there is an error, it will be of type *PathError.
   135  //
   136  // On Windows, it always returns the syscall.EWINDOWS error, wrapped
   137  // in *PathError.
   138  func (f *File) Chown(uid, gid int) error {
   139  	if err := f.checkValid("chown"); err != nil {
   140  		return err
   141  	}
   142  	if e := f.pfd.Fchown(uid, gid); e != nil {
   143  		return f.wrapErr("chown", e)
   144  	}
   145  	return nil
   146  }
   147  
   148  // Truncate changes the size of the file.
   149  // It does not change the I/O offset.
   150  // If there is an error, it will be of type *PathError.
   151  func (f *File) Truncate(size int64) error {
   152  	if err := f.checkValid("truncate"); err != nil {
   153  		return err
   154  	}
   155  	if e := f.pfd.Ftruncate(size); e != nil {
   156  		return f.wrapErr("truncate", e)
   157  	}
   158  	return nil
   159  }
   160  
   161  // Sync commits the current contents of the file to stable storage.
   162  // Typically, this means flushing the file system's in-memory copy
   163  // of recently written data to disk.
   164  func (f *File) Sync() error {
   165  	if err := f.checkValid("sync"); err != nil {
   166  		return err
   167  	}
   168  	if e := f.pfd.Fsync(); e != nil {
   169  		return f.wrapErr("sync", e)
   170  	}
   171  	return nil
   172  }
   173  
   174  // Chtimes changes the access and modification times of the named
   175  // file, similar to the Unix utime() or utimes() functions.
   176  //
   177  // The underlying filesystem may truncate or round the values to a
   178  // less precise time unit.
   179  // If there is an error, it will be of type *PathError.
   180  func Chtimes(name string, atime time.Time, mtime time.Time) error {
   181  	var utimes [2]syscall.Timespec
   182  	utimes[0] = syscall.NsecToTimespec(atime.UnixNano())
   183  	utimes[1] = syscall.NsecToTimespec(mtime.UnixNano())
   184  	if e := syscall.UtimesNano(fixLongPath(name), utimes[0:]); e != nil {
   185  		return &PathError{Op: "chtimes", Path: name, Err: e}
   186  	}
   187  	return nil
   188  }
   189  
   190  // Chdir changes the current working directory to the file,
   191  // which must be a directory.
   192  // If there is an error, it will be of type *PathError.
   193  func (f *File) Chdir() error {
   194  	if err := f.checkValid("chdir"); err != nil {
   195  		return err
   196  	}
   197  	if e := f.pfd.Fchdir(); e != nil {
   198  		return f.wrapErr("chdir", e)
   199  	}
   200  	return nil
   201  }
   202  
   203  // setDeadline sets the read and write deadline.
   204  func (f *File) setDeadline(t time.Time) error {
   205  	if err := f.checkValid("SetDeadline"); err != nil {
   206  		return err
   207  	}
   208  	return f.pfd.SetDeadline(t)
   209  }
   210  
   211  // setReadDeadline sets the read deadline.
   212  func (f *File) setReadDeadline(t time.Time) error {
   213  	if err := f.checkValid("SetReadDeadline"); err != nil {
   214  		return err
   215  	}
   216  	return f.pfd.SetReadDeadline(t)
   217  }
   218  
   219  // setWriteDeadline sets the write deadline.
   220  func (f *File) setWriteDeadline(t time.Time) error {
   221  	if err := f.checkValid("SetWriteDeadline"); err != nil {
   222  		return err
   223  	}
   224  	return f.pfd.SetWriteDeadline(t)
   225  }
   226  
   227  // checkValid checks whether f is valid for use.
   228  // If not, it returns an appropriate error, perhaps incorporating the operation name op.
   229  func (f *File) checkValid(op string) error {
   230  	if f == nil {
   231  		return ErrInvalid
   232  	}
   233  	return nil
   234  }
   235  
   236  // ignoringEINTR makes a function call and repeats it if it returns an
   237  // EINTR error. This appears to be required even though we install all
   238  // signal handlers with SA_RESTART: see #22838, #38033, #38836, #40846.
   239  // Also #20400 and #36644 are issues in which a signal handler is
   240  // installed without setting SA_RESTART. None of these are the common case,
   241  // but there are enough of them that it seems that we can't avoid
   242  // an EINTR loop.
   243  func ignoringEINTR(fn func() error) error {
   244  	for {
   245  		err := fn()
   246  		if err != syscall.EINTR {
   247  			return err
   248  		}
   249  	}
   250  }
   251  

View as plain text