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