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

View as plain text