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 aix darwin dragonfly freebsd linux netbsd openbsd solaris 6 7package unix 8 9import ( 10 "bytes" 11 "sort" 12 "sync" 13 "syscall" 14 "unsafe" 15 16 "golang.org/x/sys/internal/unsafeheader" 17) 18 19var ( 20 Stdin = 0 21 Stdout = 1 22 Stderr = 2 23) 24 25// Do the interface allocations only once for common 26// Errno values. 27var ( 28 errEAGAIN error = syscall.EAGAIN 29 errEINVAL error = syscall.EINVAL 30 errENOENT error = syscall.ENOENT 31) 32 33var ( 34 signalNameMapOnce sync.Once 35 signalNameMap map[string]syscall.Signal 36) 37 38// errnoErr returns common boxed Errno values, to prevent 39// allocations at runtime. 40func errnoErr(e syscall.Errno) error { 41 switch e { 42 case 0: 43 return nil 44 case EAGAIN: 45 return errEAGAIN 46 case EINVAL: 47 return errEINVAL 48 case ENOENT: 49 return errENOENT 50 } 51 return e 52} 53 54// ErrnoName returns the error name for error number e. 55func ErrnoName(e syscall.Errno) string { 56 i := sort.Search(len(errorList), func(i int) bool { 57 return errorList[i].num >= e 58 }) 59 if i < len(errorList) && errorList[i].num == e { 60 return errorList[i].name 61 } 62 return "" 63} 64 65// SignalName returns the signal name for signal number s. 66func SignalName(s syscall.Signal) string { 67 i := sort.Search(len(signalList), func(i int) bool { 68 return signalList[i].num >= s 69 }) 70 if i < len(signalList) && signalList[i].num == s { 71 return signalList[i].name 72 } 73 return "" 74} 75 76// SignalNum returns the syscall.Signal for signal named s, 77// or 0 if a signal with such name is not found. 78// The signal name should start with "SIG". 79func SignalNum(s string) syscall.Signal { 80 signalNameMapOnce.Do(func() { 81 signalNameMap = make(map[string]syscall.Signal, len(signalList)) 82 for _, signal := range signalList { 83 signalNameMap[signal.name] = signal.num 84 } 85 }) 86 return signalNameMap[s] 87} 88 89// clen returns the index of the first NULL byte in n or len(n) if n contains no NULL byte. 90func clen(n []byte) int { 91 i := bytes.IndexByte(n, 0) 92 if i == -1 { 93 i = len(n) 94 } 95 return i 96} 97 98// Mmap manager, for use by operating system-specific implementations. 99 100type mmapper struct { 101 sync.Mutex 102 active map[*byte][]byte // active mappings; key is last byte in mapping 103 mmap func(addr, length uintptr, prot, flags, fd int, offset int64) (uintptr, error) 104 munmap func(addr uintptr, length uintptr) error 105} 106 107func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) { 108 if length <= 0 { 109 return nil, EINVAL 110 } 111 112 // Map the requested memory. 113 addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset) 114 if errno != nil { 115 return nil, errno 116 } 117 118 // Use unsafe to convert addr into a []byte. 119 var b []byte 120 hdr := (*unsafeheader.Slice)(unsafe.Pointer(&b)) 121 hdr.Data = unsafe.Pointer(addr) 122 hdr.Cap = length 123 hdr.Len = length 124 125 // Register mapping in m and return it. 126 p := &b[cap(b)-1] 127 m.Lock() 128 defer m.Unlock() 129 m.active[p] = b 130 return b, nil 131} 132 133func (m *mmapper) Munmap(data []byte) (err error) { 134 if len(data) == 0 || len(data) != cap(data) { 135 return EINVAL 136 } 137 138 // Find the base of the mapping. 139 p := &data[cap(data)-1] 140 m.Lock() 141 defer m.Unlock() 142 b := m.active[p] 143 if b == nil || &b[0] != &data[0] { 144 return EINVAL 145 } 146 147 // Unmap the memory and update m. 148 if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != nil { 149 return errno 150 } 151 delete(m.active, p) 152 return nil 153} 154 155func Read(fd int, p []byte) (n int, err error) { 156 n, err = read(fd, p) 157 if raceenabled { 158 if n > 0 { 159 raceWriteRange(unsafe.Pointer(&p[0]), n) 160 } 161 if err == nil { 162 raceAcquire(unsafe.Pointer(&ioSync)) 163 } 164 } 165 return 166} 167 168func Write(fd int, p []byte) (n int, err error) { 169 if raceenabled { 170 raceReleaseMerge(unsafe.Pointer(&ioSync)) 171 } 172 n, err = write(fd, p) 173 if raceenabled && n > 0 { 174 raceReadRange(unsafe.Pointer(&p[0]), n) 175 } 176 return 177} 178 179// For testing: clients can set this flag to force 180// creation of IPv6 sockets to return EAFNOSUPPORT. 181var SocketDisableIPv6 bool 182 183// Sockaddr represents a socket address. 184type Sockaddr interface { 185 sockaddr() (ptr unsafe.Pointer, len _Socklen, err error) // lowercase; only we can define Sockaddrs 186} 187 188// SockaddrInet4 implements the Sockaddr interface for AF_INET type sockets. 189type SockaddrInet4 struct { 190 Port int 191 Addr [4]byte 192 raw RawSockaddrInet4 193} 194 195// SockaddrInet6 implements the Sockaddr interface for AF_INET6 type sockets. 196type SockaddrInet6 struct { 197 Port int 198 ZoneId uint32 199 Addr [16]byte 200 raw RawSockaddrInet6 201} 202 203// SockaddrUnix implements the Sockaddr interface for AF_UNIX type sockets. 204type SockaddrUnix struct { 205 Name string 206 raw RawSockaddrUnix 207} 208 209func Bind(fd int, sa Sockaddr) (err error) { 210 ptr, n, err := sa.sockaddr() 211 if err != nil { 212 return err 213 } 214 return bind(fd, ptr, n) 215} 216 217func Connect(fd int, sa Sockaddr) (err error) { 218 ptr, n, err := sa.sockaddr() 219 if err != nil { 220 return err 221 } 222 return connect(fd, ptr, n) 223} 224 225func Getpeername(fd int) (sa Sockaddr, err error) { 226 var rsa RawSockaddrAny 227 var len _Socklen = SizeofSockaddrAny 228 if err = getpeername(fd, &rsa, &len); err != nil { 229 return 230 } 231 return anyToSockaddr(fd, &rsa) 232} 233 234func GetsockoptByte(fd, level, opt int) (value byte, err error) { 235 var n byte 236 vallen := _Socklen(1) 237 err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen) 238 return n, err 239} 240 241func GetsockoptInt(fd, level, opt int) (value int, err error) { 242 var n int32 243 vallen := _Socklen(4) 244 err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen) 245 return int(n), err 246} 247 248func GetsockoptInet4Addr(fd, level, opt int) (value [4]byte, err error) { 249 vallen := _Socklen(4) 250 err = getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen) 251 return value, err 252} 253 254func GetsockoptIPMreq(fd, level, opt int) (*IPMreq, error) { 255 var value IPMreq 256 vallen := _Socklen(SizeofIPMreq) 257 err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) 258 return &value, err 259} 260 261func GetsockoptIPv6Mreq(fd, level, opt int) (*IPv6Mreq, error) { 262 var value IPv6Mreq 263 vallen := _Socklen(SizeofIPv6Mreq) 264 err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) 265 return &value, err 266} 267 268func GetsockoptIPv6MTUInfo(fd, level, opt int) (*IPv6MTUInfo, error) { 269 var value IPv6MTUInfo 270 vallen := _Socklen(SizeofIPv6MTUInfo) 271 err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) 272 return &value, err 273} 274 275func GetsockoptICMPv6Filter(fd, level, opt int) (*ICMPv6Filter, error) { 276 var value ICMPv6Filter 277 vallen := _Socklen(SizeofICMPv6Filter) 278 err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) 279 return &value, err 280} 281 282func GetsockoptLinger(fd, level, opt int) (*Linger, error) { 283 var linger Linger 284 vallen := _Socklen(SizeofLinger) 285 err := getsockopt(fd, level, opt, unsafe.Pointer(&linger), &vallen) 286 return &linger, err 287} 288 289func GetsockoptTimeval(fd, level, opt int) (*Timeval, error) { 290 var tv Timeval 291 vallen := _Socklen(unsafe.Sizeof(tv)) 292 err := getsockopt(fd, level, opt, unsafe.Pointer(&tv), &vallen) 293 return &tv, err 294} 295 296func GetsockoptUint64(fd, level, opt int) (value uint64, err error) { 297 var n uint64 298 vallen := _Socklen(8) 299 err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen) 300 return n, err 301} 302 303func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) { 304 var rsa RawSockaddrAny 305 var len _Socklen = SizeofSockaddrAny 306 if n, err = recvfrom(fd, p, flags, &rsa, &len); err != nil { 307 return 308 } 309 if rsa.Addr.Family != AF_UNSPEC { 310 from, err = anyToSockaddr(fd, &rsa) 311 } 312 return 313} 314 315func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) { 316 ptr, n, err := to.sockaddr() 317 if err != nil { 318 return err 319 } 320 return sendto(fd, p, flags, ptr, n) 321} 322 323func SetsockoptByte(fd, level, opt int, value byte) (err error) { 324 return setsockopt(fd, level, opt, unsafe.Pointer(&value), 1) 325} 326 327func SetsockoptInt(fd, level, opt int, value int) (err error) { 328 var n = int32(value) 329 return setsockopt(fd, level, opt, unsafe.Pointer(&n), 4) 330} 331 332func SetsockoptInet4Addr(fd, level, opt int, value [4]byte) (err error) { 333 return setsockopt(fd, level, opt, unsafe.Pointer(&value[0]), 4) 334} 335 336func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (err error) { 337 return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPMreq) 338} 339 340func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (err error) { 341 return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPv6Mreq) 342} 343 344func SetsockoptICMPv6Filter(fd, level, opt int, filter *ICMPv6Filter) error { 345 return setsockopt(fd, level, opt, unsafe.Pointer(filter), SizeofICMPv6Filter) 346} 347 348func SetsockoptLinger(fd, level, opt int, l *Linger) (err error) { 349 return setsockopt(fd, level, opt, unsafe.Pointer(l), SizeofLinger) 350} 351 352func SetsockoptString(fd, level, opt int, s string) (err error) { 353 var p unsafe.Pointer 354 if len(s) > 0 { 355 p = unsafe.Pointer(&[]byte(s)[0]) 356 } 357 return setsockopt(fd, level, opt, p, uintptr(len(s))) 358} 359 360func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (err error) { 361 return setsockopt(fd, level, opt, unsafe.Pointer(tv), unsafe.Sizeof(*tv)) 362} 363 364func SetsockoptUint64(fd, level, opt int, value uint64) (err error) { 365 return setsockopt(fd, level, opt, unsafe.Pointer(&value), 8) 366} 367 368func Socket(domain, typ, proto int) (fd int, err error) { 369 if domain == AF_INET6 && SocketDisableIPv6 { 370 return -1, EAFNOSUPPORT 371 } 372 fd, err = socket(domain, typ, proto) 373 return 374} 375 376func Socketpair(domain, typ, proto int) (fd [2]int, err error) { 377 var fdx [2]int32 378 err = socketpair(domain, typ, proto, &fdx) 379 if err == nil { 380 fd[0] = int(fdx[0]) 381 fd[1] = int(fdx[1]) 382 } 383 return 384} 385 386var ioSync int64 387 388func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) } 389 390func SetNonblock(fd int, nonblocking bool) (err error) { 391 flag, err := fcntl(fd, F_GETFL, 0) 392 if err != nil { 393 return err 394 } 395 if nonblocking { 396 flag |= O_NONBLOCK 397 } else { 398 flag &= ^O_NONBLOCK 399 } 400 _, err = fcntl(fd, F_SETFL, flag) 401 return err 402} 403 404// Exec calls execve(2), which replaces the calling executable in the process 405// tree. argv0 should be the full path to an executable ("/bin/ls") and the 406// executable name should also be the first argument in argv (["ls", "-l"]). 407// envv are the environment variables that should be passed to the new 408// process (["USER=go", "PWD=/tmp"]). 409func Exec(argv0 string, argv []string, envv []string) error { 410 return syscall.Exec(argv0, argv, envv) 411} 412 413// Lutimes sets the access and modification times tv on path. If path refers to 414// a symlink, it is not dereferenced and the timestamps are set on the symlink. 415// If tv is nil, the access and modification times are set to the current time. 416// Otherwise tv must contain exactly 2 elements, with access time as the first 417// element and modification time as the second element. 418func Lutimes(path string, tv []Timeval) error { 419 if tv == nil { 420 return UtimesNanoAt(AT_FDCWD, path, nil, AT_SYMLINK_NOFOLLOW) 421 } 422 if len(tv) != 2 { 423 return EINVAL 424 } 425 ts := []Timespec{ 426 NsecToTimespec(TimevalToNsec(tv[0])), 427 NsecToTimespec(TimevalToNsec(tv[1])), 428 } 429 return UtimesNanoAt(AT_FDCWD, path, ts, AT_SYMLINK_NOFOLLOW) 430} 431