github.com/philippgille/go@v0.0.0-20180418191957-236c567ba9b7/src/os/file_posix.go (about)

     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 windows
     6  
     7  package os
     8  
     9  import (
    10  	"syscall"
    11  	"time"
    12  )
    13  
    14  func sigpipe() // implemented in package runtime
    15  
    16  // Readlink returns the destination of the named symbolic link.
    17  // If there is an error, it will be of type *PathError.
    18  func Readlink(name string) (string, error) {
    19  	for len := 128; ; len *= 2 {
    20  		b := make([]byte, len)
    21  		n, e := fixCount(syscall.Readlink(fixLongPath(name), b))
    22  		if e != nil {
    23  			return "", &PathError{"readlink", name, e}
    24  		}
    25  		if n < len {
    26  			return string(b[0:n]), nil
    27  		}
    28  	}
    29  }
    30  
    31  // syscallMode returns the syscall-specific mode bits from Go's portable mode bits.
    32  func syscallMode(i FileMode) (o uint32) {
    33  	o |= uint32(i.Perm())
    34  	if i&ModeSetuid != 0 {
    35  		o |= syscall.S_ISUID
    36  	}
    37  	if i&ModeSetgid != 0 {
    38  		o |= syscall.S_ISGID
    39  	}
    40  	if i&ModeSticky != 0 {
    41  		o |= syscall.S_ISVTX
    42  	}
    43  	// No mapping for Go's ModeTemporary (plan9 only).
    44  	return
    45  }
    46  
    47  // See docs in file.go:Chmod.
    48  func chmod(name string, mode FileMode) error {
    49  	if e := syscall.Chmod(fixLongPath(name), syscallMode(mode)); e != nil {
    50  		return &PathError{"chmod", name, e}
    51  	}
    52  	return nil
    53  }
    54  
    55  // See docs in file.go:(*File).Chmod.
    56  func (f *File) chmod(mode FileMode) error {
    57  	if err := f.checkValid("chmod"); err != nil {
    58  		return err
    59  	}
    60  	if e := f.pfd.Fchmod(syscallMode(mode)); e != nil {
    61  		return f.wrapErr("chmod", e)
    62  	}
    63  	return nil
    64  }
    65  
    66  // Chown changes the numeric uid and gid of the named file.
    67  // If the file is a symbolic link, it changes the uid and gid of the link's target.
    68  // A uid or gid of -1 means to not change that value.
    69  // If there is an error, it will be of type *PathError.
    70  //
    71  // On Windows or Plan 9, Chown always returns the syscall.EWINDOWS or
    72  // EPLAN9 error, wrapped in *PathError.
    73  func Chown(name string, uid, gid int) error {
    74  	if e := syscall.Chown(name, uid, gid); e != nil {
    75  		return &PathError{"chown", name, e}
    76  	}
    77  	return nil
    78  }
    79  
    80  // Lchown changes the numeric uid and gid of the named file.
    81  // If the file is a symbolic link, it changes the uid and gid of the link itself.
    82  // If there is an error, it will be of type *PathError.
    83  //
    84  // On Windows, it always returns the syscall.EWINDOWS error, wrapped
    85  // in *PathError.
    86  func Lchown(name string, uid, gid int) error {
    87  	if e := syscall.Lchown(name, uid, gid); e != nil {
    88  		return &PathError{"lchown", name, e}
    89  	}
    90  	return nil
    91  }
    92  
    93  // Chown changes the numeric uid and gid of the named file.
    94  // If there is an error, it will be of type *PathError.
    95  //
    96  // On Windows, it always returns the syscall.EWINDOWS error, wrapped
    97  // in *PathError.
    98  func (f *File) Chown(uid, gid int) error {
    99  	if err := f.checkValid("chown"); err != nil {
   100  		return err
   101  	}
   102  	if e := f.pfd.Fchown(uid, gid); e != nil {
   103  		return f.wrapErr("chown", e)
   104  	}
   105  	return nil
   106  }
   107  
   108  // Truncate changes the size of the file.
   109  // It does not change the I/O offset.
   110  // If there is an error, it will be of type *PathError.
   111  func (f *File) Truncate(size int64) error {
   112  	if err := f.checkValid("truncate"); err != nil {
   113  		return err
   114  	}
   115  	if e := f.pfd.Ftruncate(size); e != nil {
   116  		return f.wrapErr("truncate", e)
   117  	}
   118  	return nil
   119  }
   120  
   121  // Sync commits the current contents of the file to stable storage.
   122  // Typically, this means flushing the file system's in-memory copy
   123  // of recently written data to disk.
   124  func (f *File) Sync() error {
   125  	if err := f.checkValid("sync"); err != nil {
   126  		return err
   127  	}
   128  	if e := f.pfd.Fsync(); e != nil {
   129  		return f.wrapErr("sync", e)
   130  	}
   131  	return nil
   132  }
   133  
   134  // Chtimes changes the access and modification times of the named
   135  // file, similar to the Unix utime() or utimes() functions.
   136  //
   137  // The underlying filesystem may truncate or round the values to a
   138  // less precise time unit.
   139  // If there is an error, it will be of type *PathError.
   140  func Chtimes(name string, atime time.Time, mtime time.Time) error {
   141  	var utimes [2]syscall.Timespec
   142  	utimes[0] = syscall.NsecToTimespec(atime.UnixNano())
   143  	utimes[1] = syscall.NsecToTimespec(mtime.UnixNano())
   144  	if e := syscall.UtimesNano(fixLongPath(name), utimes[0:]); e != nil {
   145  		return &PathError{"chtimes", name, e}
   146  	}
   147  	return nil
   148  }
   149  
   150  // Chdir changes the current working directory to the file,
   151  // which must be a directory.
   152  // If there is an error, it will be of type *PathError.
   153  func (f *File) Chdir() error {
   154  	if err := f.checkValid("chdir"); err != nil {
   155  		return err
   156  	}
   157  	if e := f.pfd.Fchdir(); e != nil {
   158  		return f.wrapErr("chdir", e)
   159  	}
   160  	return nil
   161  }
   162  
   163  // setDeadline sets the read and write deadline.
   164  func (f *File) setDeadline(t time.Time) error {
   165  	if err := f.checkValid("SetDeadline"); err != nil {
   166  		return err
   167  	}
   168  	return f.pfd.SetDeadline(t)
   169  }
   170  
   171  // setReadDeadline sets the read deadline.
   172  func (f *File) setReadDeadline(t time.Time) error {
   173  	if err := f.checkValid("SetReadDeadline"); err != nil {
   174  		return err
   175  	}
   176  	return f.pfd.SetReadDeadline(t)
   177  }
   178  
   179  // setWriteDeadline sets the write deadline.
   180  func (f *File) setWriteDeadline(t time.Time) error {
   181  	if err := f.checkValid("SetWriteDeadline"); err != nil {
   182  		return err
   183  	}
   184  	return f.pfd.SetWriteDeadline(t)
   185  }
   186  
   187  // checkValid checks whether f is valid for use.
   188  // If not, it returns an appropriate error, perhaps incorporating the operation name op.
   189  func (f *File) checkValid(op string) error {
   190  	if f == nil {
   191  		return ErrInvalid
   192  	}
   193  	return nil
   194  }