Source file src/pkg/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 // +build darwin freebsd linux netbsd openbsd windows 6 7 package os 8 9 import ( 10 "syscall" 11 "time" 12 ) 13 14 func sigpipe() // implemented in package runtime 15 16 func epipecheck(file *File, e error) { 17 if e == syscall.EPIPE { 18 file.nepipe++ 19 if file.nepipe >= 10 { 20 sigpipe() 21 } 22 } else { 23 file.nepipe = 0 24 } 25 } 26 27 // Link creates newname as a hard link to the oldname file. 28 // If there is an error, it will be of type *LinkError. 29 func Link(oldname, newname string) error { 30 e := syscall.Link(oldname, newname) 31 if e != nil { 32 return &LinkError{"link", oldname, newname, e} 33 } 34 return nil 35 } 36 37 // Symlink creates newname as a symbolic link to oldname. 38 // If there is an error, it will be of type *LinkError. 39 func Symlink(oldname, newname string) error { 40 e := syscall.Symlink(oldname, newname) 41 if e != nil { 42 return &LinkError{"symlink", oldname, newname, e} 43 } 44 return nil 45 } 46 47 // Readlink returns the destination of the named symbolic link. 48 // If there is an error, it will be of type *PathError. 49 func Readlink(name string) (string, error) { 50 for len := 128; ; len *= 2 { 51 b := make([]byte, len) 52 n, e := syscall.Readlink(name, b) 53 if e != nil { 54 return "", &PathError{"readlink", name, e} 55 } 56 if n < len { 57 return string(b[0:n]), nil 58 } 59 } 60 // Silence 6g. 61 return "", nil 62 } 63 64 // Rename renames a file. 65 func Rename(oldname, newname string) error { 66 e := syscall.Rename(oldname, newname) 67 if e != nil { 68 return &LinkError{"rename", oldname, newname, e} 69 } 70 return nil 71 } 72 73 // syscallMode returns the syscall-specific mode bits from Go's portable mode bits. 74 func syscallMode(i FileMode) (o uint32) { 75 o |= uint32(i.Perm()) 76 if i&ModeSetuid != 0 { 77 o |= syscall.S_ISUID 78 } 79 if i&ModeSetgid != 0 { 80 o |= syscall.S_ISGID 81 } 82 if i&ModeSticky != 0 { 83 o |= syscall.S_ISVTX 84 } 85 // No mapping for Go's ModeTemporary (plan9 only). 86 return 87 } 88 89 // Chmod changes the mode of the named file to mode. 90 // If the file is a symbolic link, it changes the mode of the link's target. 91 // If there is an error, it will be of type *PathError. 92 func Chmod(name string, mode FileMode) error { 93 if e := syscall.Chmod(name, syscallMode(mode)); e != nil { 94 return &PathError{"chmod", name, e} 95 } 96 return nil 97 } 98 99 // Chmod changes the mode of the file to mode. 100 // If there is an error, it will be of type *PathError. 101 func (f *File) Chmod(mode FileMode) error { 102 if e := syscall.Fchmod(f.fd, syscallMode(mode)); e != nil { 103 return &PathError{"chmod", f.name, e} 104 } 105 return nil 106 } 107 108 // Chown changes the numeric uid and gid of the named file. 109 // If the file is a symbolic link, it changes the uid and gid of the link's target. 110 // If there is an error, it will be of type *PathError. 111 func Chown(name string, uid, gid int) error { 112 if e := syscall.Chown(name, uid, gid); e != nil { 113 return &PathError{"chown", name, 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 func Lchown(name string, uid, gid int) error { 122 if e := syscall.Lchown(name, uid, gid); e != nil { 123 return &PathError{"lchown", name, e} 124 } 125 return nil 126 } 127 128 // Chown changes the numeric uid and gid of the named file. 129 // If there is an error, it will be of type *PathError. 130 func (f *File) Chown(uid, gid int) error { 131 if e := syscall.Fchown(f.fd, uid, gid); e != nil { 132 return &PathError{"chown", f.name, e} 133 } 134 return nil 135 } 136 137 // Truncate changes the size of the file. 138 // It does not change the I/O offset. 139 // If there is an error, it will be of type *PathError. 140 func (f *File) Truncate(size int64) error { 141 if e := syscall.Ftruncate(f.fd, size); e != nil { 142 return &PathError{"truncate", f.name, e} 143 } 144 return nil 145 } 146 147 // Sync commits the current contents of the file to stable storage. 148 // Typically, this means flushing the file system's in-memory copy 149 // of recently written data to disk. 150 func (f *File) Sync() (err error) { 151 if f == nil { 152 return syscall.EINVAL 153 } 154 if e := syscall.Fsync(f.fd); e != nil { 155 return NewSyscallError("fsync", e) 156 } 157 return nil 158 } 159 160 // Chtimes changes the access and modification times of the named 161 // file, similar to the Unix utime() or utimes() functions. 162 // 163 // The underlying filesystem may truncate or round the values to a 164 // less precise time unit. 165 // If there is an error, it will be of type *PathError. 166 func Chtimes(name string, atime time.Time, mtime time.Time) error { 167 var utimes [2]syscall.Timeval 168 atime_ns := atime.Unix()*1e9 + int64(atime.Nanosecond()) 169 mtime_ns := mtime.Unix()*1e9 + int64(mtime.Nanosecond()) 170 utimes[0] = syscall.NsecToTimeval(atime_ns) 171 utimes[1] = syscall.NsecToTimeval(mtime_ns) 172 if e := syscall.Utimes(name, utimes[0:]); e != nil { 173 return &PathError{"chtimes", name, e} 174 } 175 return nil 176 }