github.com/aayushi-bansal/sys@v0.0.0-20180118120756-90d962a959d8/unix/syscall_unix.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 netbsd openbsd solaris 6 7 package unix 8 9 import ( 10 "runtime" 11 "sync" 12 "syscall" 13 "unsafe" 14 ) 15 16 var ( 17 Stdin = 0 18 Stdout = 1 19 Stderr = 2 20 ) 21 22 const ( 23 darwin64Bit = runtime.GOOS == "darwin" && sizeofPtr == 8 24 dragonfly64Bit = runtime.GOOS == "dragonfly" && sizeofPtr == 8 25 netbsd32Bit = runtime.GOOS == "netbsd" && sizeofPtr == 4 26 solaris64Bit = runtime.GOOS == "solaris" && sizeofPtr == 8 27 ) 28 29 // Do the interface allocations only once for common 30 // Errno values. 31 var ( 32 errEAGAIN error = syscall.EAGAIN 33 errEINVAL error = syscall.EINVAL 34 errENOENT error = syscall.ENOENT 35 ) 36 37 // errnoErr returns common boxed Errno values, to prevent 38 // allocations at runtime. 39 func errnoErr(e syscall.Errno) error { 40 switch e { 41 case 0: 42 return nil 43 case EAGAIN: 44 return errEAGAIN 45 case EINVAL: 46 return errEINVAL 47 case ENOENT: 48 return errENOENT 49 } 50 return e 51 } 52 53 // clen returns the index of the first NULL byte in n or len(n) if n contains no 54 // NULL byte or len(n) if n contains no NULL byte 55 func clen(n []byte) int { 56 for i := 0; i < len(n); i++ { 57 if n[i] == 0 { 58 return i 59 } 60 } 61 return len(n) 62 } 63 64 // Mmap manager, for use by operating system-specific implementations. 65 66 type mmapper struct { 67 sync.Mutex 68 active map[*byte][]byte // active mappings; key is last byte in mapping 69 mmap func(addr, length uintptr, prot, flags, fd int, offset int64) (uintptr, error) 70 munmap func(addr uintptr, length uintptr) error 71 } 72 73 func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) { 74 if length <= 0 { 75 return nil, EINVAL 76 } 77 78 // Map the requested memory. 79 addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset) 80 if errno != nil { 81 return nil, errno 82 } 83 84 // Slice memory layout 85 var sl = struct { 86 addr uintptr 87 len int 88 cap int 89 }{addr, length, length} 90 91 // Use unsafe to turn sl into a []byte. 92 b := *(*[]byte)(unsafe.Pointer(&sl)) 93 94 // Register mapping in m and return it. 95 p := &b[cap(b)-1] 96 m.Lock() 97 defer m.Unlock() 98 m.active[p] = b 99 return b, nil 100 } 101 102 func (m *mmapper) Munmap(data []byte) (err error) { 103 if len(data) == 0 || len(data) != cap(data) { 104 return EINVAL 105 } 106 107 // Find the base of the mapping. 108 p := &data[cap(data)-1] 109 m.Lock() 110 defer m.Unlock() 111 b := m.active[p] 112 if b == nil || &b[0] != &data[0] { 113 return EINVAL 114 } 115 116 // Unmap the memory and update m. 117 if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != nil { 118 return errno 119 } 120 delete(m.active, p) 121 return nil 122 } 123 124 func Read(fd int, p []byte) (n int, err error) { 125 n, err = read(fd, p) 126 if raceenabled { 127 if n > 0 { 128 raceWriteRange(unsafe.Pointer(&p[0]), n) 129 } 130 if err == nil { 131 raceAcquire(unsafe.Pointer(&ioSync)) 132 } 133 } 134 return 135 } 136 137 func Write(fd int, p []byte) (n int, err error) { 138 if raceenabled { 139 raceReleaseMerge(unsafe.Pointer(&ioSync)) 140 } 141 n, err = write(fd, p) 142 if raceenabled && n > 0 { 143 raceReadRange(unsafe.Pointer(&p[0]), n) 144 } 145 return 146 } 147 148 // For testing: clients can set this flag to force 149 // creation of IPv6 sockets to return EAFNOSUPPORT. 150 var SocketDisableIPv6 bool 151 152 type Sockaddr interface { 153 sockaddr() (ptr unsafe.Pointer, len _Socklen, err error) // lowercase; only we can define Sockaddrs 154 } 155 156 type SockaddrInet4 struct { 157 Port int 158 Addr [4]byte 159 raw RawSockaddrInet4 160 } 161 162 type SockaddrInet6 struct { 163 Port int 164 ZoneId uint32 165 Addr [16]byte 166 raw RawSockaddrInet6 167 } 168 169 type SockaddrUnix struct { 170 Name string 171 raw RawSockaddrUnix 172 } 173 174 func Bind(fd int, sa Sockaddr) (err error) { 175 ptr, n, err := sa.sockaddr() 176 if err != nil { 177 return err 178 } 179 return bind(fd, ptr, n) 180 } 181 182 func Connect(fd int, sa Sockaddr) (err error) { 183 ptr, n, err := sa.sockaddr() 184 if err != nil { 185 return err 186 } 187 return connect(fd, ptr, n) 188 } 189 190 func Getpeername(fd int) (sa Sockaddr, err error) { 191 var rsa RawSockaddrAny 192 var len _Socklen = SizeofSockaddrAny 193 if err = getpeername(fd, &rsa, &len); err != nil { 194 return 195 } 196 return anyToSockaddr(&rsa) 197 } 198 199 func GetsockoptInt(fd, level, opt int) (value int, err error) { 200 var n int32 201 vallen := _Socklen(4) 202 err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen) 203 return int(n), err 204 } 205 206 func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) { 207 var rsa RawSockaddrAny 208 var len _Socklen = SizeofSockaddrAny 209 if n, err = recvfrom(fd, p, flags, &rsa, &len); err != nil { 210 return 211 } 212 if rsa.Addr.Family != AF_UNSPEC { 213 from, err = anyToSockaddr(&rsa) 214 } 215 return 216 } 217 218 func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) { 219 ptr, n, err := to.sockaddr() 220 if err != nil { 221 return err 222 } 223 return sendto(fd, p, flags, ptr, n) 224 } 225 226 func SetsockoptByte(fd, level, opt int, value byte) (err error) { 227 return setsockopt(fd, level, opt, unsafe.Pointer(&value), 1) 228 } 229 230 func SetsockoptInt(fd, level, opt int, value int) (err error) { 231 var n = int32(value) 232 return setsockopt(fd, level, opt, unsafe.Pointer(&n), 4) 233 } 234 235 func SetsockoptInet4Addr(fd, level, opt int, value [4]byte) (err error) { 236 return setsockopt(fd, level, opt, unsafe.Pointer(&value[0]), 4) 237 } 238 239 func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (err error) { 240 return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPMreq) 241 } 242 243 func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (err error) { 244 return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPv6Mreq) 245 } 246 247 func SetsockoptICMPv6Filter(fd, level, opt int, filter *ICMPv6Filter) error { 248 return setsockopt(fd, level, opt, unsafe.Pointer(filter), SizeofICMPv6Filter) 249 } 250 251 func SetsockoptLinger(fd, level, opt int, l *Linger) (err error) { 252 return setsockopt(fd, level, opt, unsafe.Pointer(l), SizeofLinger) 253 } 254 255 func SetsockoptString(fd, level, opt int, s string) (err error) { 256 return setsockopt(fd, level, opt, unsafe.Pointer(&[]byte(s)[0]), uintptr(len(s))) 257 } 258 259 func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (err error) { 260 return setsockopt(fd, level, opt, unsafe.Pointer(tv), unsafe.Sizeof(*tv)) 261 } 262 263 func Socket(domain, typ, proto int) (fd int, err error) { 264 if domain == AF_INET6 && SocketDisableIPv6 { 265 return -1, EAFNOSUPPORT 266 } 267 fd, err = socket(domain, typ, proto) 268 return 269 } 270 271 func Socketpair(domain, typ, proto int) (fd [2]int, err error) { 272 var fdx [2]int32 273 err = socketpair(domain, typ, proto, &fdx) 274 if err == nil { 275 fd[0] = int(fdx[0]) 276 fd[1] = int(fdx[1]) 277 } 278 return 279 } 280 281 func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { 282 if raceenabled { 283 raceReleaseMerge(unsafe.Pointer(&ioSync)) 284 } 285 return sendfile(outfd, infd, offset, count) 286 } 287 288 var ioSync int64 289 290 func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) } 291 292 func SetNonblock(fd int, nonblocking bool) (err error) { 293 flag, err := fcntl(fd, F_GETFL, 0) 294 if err != nil { 295 return err 296 } 297 if nonblocking { 298 flag |= O_NONBLOCK 299 } else { 300 flag &= ^O_NONBLOCK 301 } 302 _, err = fcntl(fd, F_SETFL, flag) 303 return err 304 }