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