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 // Chmod changes the mode of the named file to mode. 48 // If the file is a symbolic link, it changes the mode of the link's target. 49 // If there is an error, it will be of type *PathError. 50 func Chmod(name string, mode FileMode) error { 51 if e := syscall.Chmod(name, syscallMode(mode)); e != nil { 52 return &PathError{"chmod", name, e} 53 } 54 return nil 55 } 56 57 // Chmod changes the mode of the file to mode. 58 // If there is an error, it will be of type *PathError. 59 func (f *File) Chmod(mode FileMode) error { 60 if err := f.checkValid("chmod"); err != nil { 61 return err 62 } 63 if e := syscall.Fchmod(f.fd, syscallMode(mode)); e != nil { 64 return &PathError{"chmod", f.name, e} 65 } 66 return nil 67 } 68 69 // Chown changes the numeric uid and gid of the named file. 70 // If the file is a symbolic link, it changes the uid and gid of the link's target. 71 // If there is an error, it will be of type *PathError. 72 func Chown(name string, uid, gid int) error { 73 if e := syscall.Chown(name, uid, gid); e != nil { 74 return &PathError{"chown", name, e} 75 } 76 return nil 77 } 78 79 // Lchown changes the numeric uid and gid of the named file. 80 // If the file is a symbolic link, it changes the uid and gid of the link itself. 81 // If there is an error, it will be of type *PathError. 82 func Lchown(name string, uid, gid int) error { 83 if e := syscall.Lchown(name, uid, gid); e != nil { 84 return &PathError{"lchown", name, e} 85 } 86 return nil 87 } 88 89 // Chown changes the numeric uid and gid of the named file. 90 // If there is an error, it will be of type *PathError. 91 func (f *File) Chown(uid, gid int) error { 92 if err := f.checkValid("chown"); err != nil { 93 return err 94 } 95 if e := syscall.Fchown(f.fd, uid, gid); e != nil { 96 return &PathError{"chown", f.name, e} 97 } 98 return nil 99 } 100 101 // Truncate changes the size of the file. 102 // It does not change the I/O offset. 103 // If there is an error, it will be of type *PathError. 104 func (f *File) Truncate(size int64) error { 105 if err := f.checkValid("truncate"); err != nil { 106 return err 107 } 108 if e := syscall.Ftruncate(f.fd, size); e != nil { 109 return &PathError{"truncate", f.name, e} 110 } 111 return nil 112 } 113 114 // Sync commits the current contents of the file to stable storage. 115 // Typically, this means flushing the file system's in-memory copy 116 // of recently written data to disk. 117 func (f *File) Sync() error { 118 if err := f.checkValid("sync"); err != nil { 119 return err 120 } 121 if e := syscall.Fsync(f.fd); e != nil { 122 return &PathError{"sync", f.name, e} 123 } 124 return nil 125 } 126 127 // Chtimes changes the access and modification times of the named 128 // file, similar to the Unix utime() or utimes() functions. 129 // 130 // The underlying filesystem may truncate or round the values to a 131 // less precise time unit. 132 // If there is an error, it will be of type *PathError. 133 func Chtimes(name string, atime time.Time, mtime time.Time) error { 134 var utimes [2]syscall.Timespec 135 utimes[0] = syscall.NsecToTimespec(atime.UnixNano()) 136 utimes[1] = syscall.NsecToTimespec(mtime.UnixNano()) 137 if e := syscall.UtimesNano(fixLongPath(name), utimes[0:]); e != nil { 138 return &PathError{"chtimes", name, e} 139 } 140 return nil 141 } 142