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 5package syscall 6 7import "unsafe" 8 9const ( 10 _SYS_setgroups = SYS_SETGROUPS32 11 _SYS_clone3 = 435 12 _SYS_faccessat2 = 439 13 _SYS_fchmodat2 = 452 14) 15 16func setTimespec(sec, nsec int64) Timespec { 17 return Timespec{Sec: int32(sec), Nsec: int32(nsec)} 18} 19 20func setTimeval(sec, usec int64) Timeval { 21 return Timeval{Sec: int32(sec), Usec: int32(usec)} 22} 23 24// 64-bit file system and 32-bit uid calls 25// (386 default is 32-bit file system and 16-bit uid). 26//sys Dup2(oldfd int, newfd int) (err error) 27//sys Fchown(fd int, uid int, gid int) (err error) = SYS_FCHOWN32 28//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64 29//sys fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64 30//sys Ftruncate(fd int, length int64) (err error) = SYS_FTRUNCATE64 31//sysnb Getegid() (egid int) = SYS_GETEGID32 32//sysnb Geteuid() (euid int) = SYS_GETEUID32 33//sysnb Getgid() (gid int) = SYS_GETGID32 34//sysnb Getuid() (uid int) = SYS_GETUID32 35//sysnb InotifyInit() (fd int, err error) 36//sys Ioperm(from int, num int, on int) (err error) 37//sys Iopl(level int) (err error) 38//sys Pause() (err error) 39//sys pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64 40//sys pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64 41//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) 42//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64 43//sys Setfsgid(gid int) (err error) = SYS_SETFSGID32 44//sys Setfsuid(uid int) (err error) = SYS_SETFSUID32 45//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, err error) 46//sys SyncFileRange(fd int, off int64, n int64, flags int) (err error) 47//sys Truncate(path string, length int64) (err error) = SYS_TRUNCATE64 48//sys Ustat(dev int, ubuf *Ustat_t) (err error) 49//sysnb getgroups(n int, list *_Gid_t) (nn int, err error) = SYS_GETGROUPS32 50//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS__NEWSELECT 51 52//sys mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error) 53//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) 54 55func Stat(path string, stat *Stat_t) (err error) { 56 return fstatat(_AT_FDCWD, path, stat, 0) 57} 58 59func Lchown(path string, uid int, gid int) (err error) { 60 return Fchownat(_AT_FDCWD, path, uid, gid, _AT_SYMLINK_NOFOLLOW) 61} 62 63func Lstat(path string, stat *Stat_t) (err error) { 64 return fstatat(_AT_FDCWD, path, stat, _AT_SYMLINK_NOFOLLOW) 65} 66 67func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) { 68 page := uintptr(offset / 4096) 69 if offset != int64(page)*4096 { 70 return 0, EINVAL 71 } 72 return mmap2(addr, length, prot, flags, fd, page) 73} 74 75type rlimit32 struct { 76 Cur uint32 77 Max uint32 78} 79 80//sysnb getrlimit(resource int, rlim *rlimit32) (err error) = SYS_GETRLIMIT 81 82const rlimInf32 = ^uint32(0) 83const rlimInf64 = ^uint64(0) 84 85func Getrlimit(resource int, rlim *Rlimit) (err error) { 86 err = prlimit(0, resource, nil, rlim) 87 if err != ENOSYS { 88 return err 89 } 90 91 rl := rlimit32{} 92 err = getrlimit(resource, &rl) 93 if err != nil { 94 return 95 } 96 97 if rl.Cur == rlimInf32 { 98 rlim.Cur = rlimInf64 99 } else { 100 rlim.Cur = uint64(rl.Cur) 101 } 102 103 if rl.Max == rlimInf32 { 104 rlim.Max = rlimInf64 105 } else { 106 rlim.Max = uint64(rl.Max) 107 } 108 return 109} 110 111//sysnb setrlimit1(resource int, rlim *rlimit32) (err error) = SYS_SETRLIMIT 112 113func setrlimit(resource int, rlim *Rlimit) (err error) { 114 err = prlimit(0, resource, rlim, nil) 115 if err != ENOSYS { 116 return err 117 } 118 119 rl := rlimit32{} 120 if rlim.Cur == rlimInf64 { 121 rl.Cur = rlimInf32 122 } else if rlim.Cur < uint64(rlimInf32) { 123 rl.Cur = uint32(rlim.Cur) 124 } else { 125 return EINVAL 126 } 127 if rlim.Max == rlimInf64 { 128 rl.Max = rlimInf32 129 } else if rlim.Max < uint64(rlimInf32) { 130 rl.Max = uint32(rlim.Max) 131 } else { 132 return EINVAL 133 } 134 135 return setrlimit1(resource, &rl) 136} 137 138//go:nosplit 139func rawSetrlimit(resource int, rlim *Rlimit) Errno { 140 _, _, errno := RawSyscall6(SYS_PRLIMIT64, 0, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0, 0, 0) 141 if errno != ENOSYS { 142 return errno 143 } 144 145 rl := rlimit32{} 146 if rlim.Cur == rlimInf64 { 147 rl.Cur = rlimInf32 148 } else if rlim.Cur < uint64(rlimInf32) { 149 rl.Cur = uint32(rlim.Cur) 150 } else { 151 return EINVAL 152 } 153 if rlim.Max == rlimInf64 { 154 rl.Max = rlimInf32 155 } else if rlim.Max < uint64(rlimInf32) { 156 rl.Max = uint32(rlim.Max) 157 } else { 158 return EINVAL 159 } 160 161 _, _, errno = RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0) 162 return errno 163} 164 165// Underlying system call writes to newoffset via pointer. 166// Implemented in assembly to avoid allocation. 167func seek(fd int, offset int64, whence int) (newoffset int64, err Errno) 168 169func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { 170 newoffset, errno := seek(fd, offset, whence) 171 if errno != 0 { 172 return 0, errno 173 } 174 return newoffset, nil 175} 176 177//sys futimesat(dirfd int, path string, times *[2]Timeval) (err error) 178//sysnb Gettimeofday(tv *Timeval) (err error) 179//sysnb Time(t *Time_t) (tt Time_t, err error) 180//sys Utime(path string, buf *Utimbuf) (err error) 181//sys utimes(path string, times *[2]Timeval) (err error) 182 183// On x86 Linux, all the socket calls go through an extra indirection, 184// I think because the 5-register system call interface can't handle 185// the 6-argument calls like sendto and recvfrom. Instead the 186// arguments to the underlying system call are the number below 187// and a pointer to an array of uintptr. We hide the pointer in the 188// socketcall assembly to avoid allocation on every system call. 189 190const ( 191 // see linux/net.h 192 _SOCKET = 1 193 _BIND = 2 194 _CONNECT = 3 195 _LISTEN = 4 196 _ACCEPT = 5 197 _GETSOCKNAME = 6 198 _GETPEERNAME = 7 199 _SOCKETPAIR = 8 200 _SEND = 9 201 _RECV = 10 202 _SENDTO = 11 203 _RECVFROM = 12 204 _SHUTDOWN = 13 205 _SETSOCKOPT = 14 206 _GETSOCKOPT = 15 207 _SENDMSG = 16 208 _RECVMSG = 17 209 _ACCEPT4 = 18 210 _RECVMMSG = 19 211 _SENDMMSG = 20 212) 213 214func socketcall(call int, a0, a1, a2, a3, a4, a5 uintptr) (n int, err Errno) 215func rawsocketcall(call int, a0, a1, a2, a3, a4, a5 uintptr) (n int, err Errno) 216 217func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { 218 fd, e := socketcall(_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) 219 if e != 0 { 220 err = e 221 } 222 return 223} 224 225func getsockname(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { 226 _, e := rawsocketcall(_GETSOCKNAME, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0) 227 if e != 0 { 228 err = e 229 } 230 return 231} 232 233func getpeername(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { 234 _, e := rawsocketcall(_GETPEERNAME, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0) 235 if e != 0 { 236 err = e 237 } 238 return 239} 240 241func socketpair(domain int, typ int, flags int, fd *[2]int32) (err error) { 242 _, e := rawsocketcall(_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(flags), uintptr(unsafe.Pointer(fd)), 0, 0) 243 if e != 0 { 244 err = e 245 } 246 return 247} 248 249func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { 250 _, e := socketcall(_BIND, uintptr(s), uintptr(addr), uintptr(addrlen), 0, 0, 0) 251 if e != 0 { 252 err = e 253 } 254 return 255} 256 257func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { 258 _, e := socketcall(_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen), 0, 0, 0) 259 if e != 0 { 260 err = e 261 } 262 return 263} 264 265func socket(domain int, typ int, proto int) (fd int, err error) { 266 fd, e := rawsocketcall(_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto), 0, 0, 0) 267 if e != 0 { 268 err = e 269 } 270 return 271} 272 273func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) { 274 _, e := socketcall(_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0) 275 if e != 0 { 276 err = e 277 } 278 return 279} 280 281func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) { 282 _, e := socketcall(_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), vallen, 0) 283 if e != 0 { 284 err = e 285 } 286 return 287} 288 289func recvfrom(s int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) { 290 var base uintptr 291 if len(p) > 0 { 292 base = uintptr(unsafe.Pointer(&p[0])) 293 } 294 n, e := socketcall(_RECVFROM, uintptr(s), base, uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) 295 if e != 0 { 296 err = e 297 } 298 return 299} 300 301func sendto(s int, p []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) { 302 var base uintptr 303 if len(p) > 0 { 304 base = uintptr(unsafe.Pointer(&p[0])) 305 } 306 _, e := socketcall(_SENDTO, uintptr(s), base, uintptr(len(p)), uintptr(flags), uintptr(to), uintptr(addrlen)) 307 if e != 0 { 308 err = e 309 } 310 return 311} 312 313func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { 314 n, e := socketcall(_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags), 0, 0, 0) 315 if e != 0 { 316 err = e 317 } 318 return 319} 320 321func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { 322 n, e := socketcall(_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags), 0, 0, 0) 323 if e != 0 { 324 err = e 325 } 326 return 327} 328 329func Listen(s int, n int) (err error) { 330 _, e := socketcall(_LISTEN, uintptr(s), uintptr(n), 0, 0, 0, 0) 331 if e != 0 { 332 err = e 333 } 334 return 335} 336 337func Shutdown(s, how int) (err error) { 338 _, e := socketcall(_SHUTDOWN, uintptr(s), uintptr(how), 0, 0, 0, 0) 339 if e != 0 { 340 err = e 341 } 342 return 343} 344 345func Fstatfs(fd int, buf *Statfs_t) (err error) { 346 _, _, e := Syscall(SYS_FSTATFS64, uintptr(fd), unsafe.Sizeof(*buf), uintptr(unsafe.Pointer(buf))) 347 if e != 0 { 348 err = e 349 } 350 return 351} 352 353func Statfs(path string, buf *Statfs_t) (err error) { 354 pathp, err := BytePtrFromString(path) 355 if err != nil { 356 return err 357 } 358 _, _, e := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(pathp)), unsafe.Sizeof(*buf), uintptr(unsafe.Pointer(buf))) 359 if e != 0 { 360 err = e 361 } 362 return 363} 364 365func (r *PtraceRegs) PC() uint64 { return uint64(uint32(r.Eip)) } 366 367func (r *PtraceRegs) SetPC(pc uint64) { r.Eip = int32(pc) } 368 369func (iov *Iovec) SetLen(length int) { 370 iov.Len = uint32(length) 371} 372 373func (msghdr *Msghdr) SetControllen(length int) { 374 msghdr.Controllen = uint32(length) 375} 376 377func (cmsg *Cmsghdr) SetLen(length int) { 378 cmsg.Len = uint32(length) 379} 380