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 }