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