syscall_aix.go raw
1 // Copyright 2018 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 //go:build aix
6
7 // Aix system calls.
8 // This file is compiled as ordinary Go code,
9 // but it is also input to mksyscall,
10 // which parses the //sys lines and generates system call stubs.
11 // Note that sometimes we use a lowercase //sys name and
12 // wrap it in our own nicer implementation.
13
14 package unix
15
16 import "unsafe"
17
18 /*
19 * Wrapped
20 */
21
22 func Access(path string, mode uint32) (err error) {
23 return Faccessat(AT_FDCWD, path, mode, 0)
24 }
25
26 func Chmod(path string, mode uint32) (err error) {
27 return Fchmodat(AT_FDCWD, path, mode, 0)
28 }
29
30 func Chown(path string, uid int, gid int) (err error) {
31 return Fchownat(AT_FDCWD, path, uid, gid, 0)
32 }
33
34 func Creat(path string, mode uint32) (fd int, err error) {
35 return Open(path, O_CREAT|O_WRONLY|O_TRUNC, mode)
36 }
37
38 //sys utimes(path string, times *[2]Timeval) (err error)
39
40 func Utimes(path string, tv []Timeval) error {
41 if len(tv) != 2 {
42 return EINVAL
43 }
44 return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
45 }
46
47 //sys utimensat(dirfd int, path string, times *[2]Timespec, flag int) (err error)
48
49 func UtimesNano(path string, ts []Timespec) error {
50 if len(ts) != 2 {
51 return EINVAL
52 }
53 return utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
54 }
55
56 func UtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) error {
57 if ts == nil {
58 return utimensat(dirfd, path, nil, flags)
59 }
60 if len(ts) != 2 {
61 return EINVAL
62 }
63 return utimensat(dirfd, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), flags)
64 }
65
66 func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
67 if sa.Port < 0 || sa.Port > 0xFFFF {
68 return nil, 0, EINVAL
69 }
70 sa.raw.Family = AF_INET
71 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
72 p[0] = byte(sa.Port >> 8)
73 p[1] = byte(sa.Port)
74 sa.raw.Addr = sa.Addr
75 return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil
76 }
77
78 func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
79 if sa.Port < 0 || sa.Port > 0xFFFF {
80 return nil, 0, EINVAL
81 }
82 sa.raw.Family = AF_INET6
83 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
84 p[0] = byte(sa.Port >> 8)
85 p[1] = byte(sa.Port)
86 sa.raw.Scope_id = sa.ZoneId
87 sa.raw.Addr = sa.Addr
88 return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil
89 }
90
91 func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) {
92 name := sa.Name
93 n := len(name)
94 if n > len(sa.raw.Path) {
95 return nil, 0, EINVAL
96 }
97 if n == len(sa.raw.Path) && name[0] != '@' {
98 return nil, 0, EINVAL
99 }
100 sa.raw.Family = AF_UNIX
101 for i := 0; i < n; i++ {
102 sa.raw.Path[i] = uint8(name[i])
103 }
104 // length is family (uint16), name, NUL.
105 sl := _Socklen(2)
106 if n > 0 {
107 sl += _Socklen(n) + 1
108 }
109 if sa.raw.Path[0] == '@' || (sa.raw.Path[0] == 0 && sl > 3) {
110 // Check sl > 3 so we don't change unnamed socket behavior.
111 sa.raw.Path[0] = 0
112 // Don't count trailing NUL for abstract address.
113 sl--
114 }
115
116 return unsafe.Pointer(&sa.raw), sl, nil
117 }
118
119 func Getsockname(fd int) (sa Sockaddr, err error) {
120 var rsa RawSockaddrAny
121 var len _Socklen = SizeofSockaddrAny
122 if err = getsockname(fd, &rsa, &len); err != nil {
123 return
124 }
125 return anyToSockaddr(fd, &rsa)
126 }
127
128 //sys getcwd(buf []byte) (err error)
129
130 const ImplementsGetwd = true
131
132 func Getwd() (ret string, err error) {
133 for len := uint64(4096); ; len *= 2 {
134 b := make([]byte, len)
135 err := getcwd(b)
136 if err == nil {
137 i := 0
138 for b[i] != 0 {
139 i++
140 }
141 return string(b[0:i]), nil
142 }
143 if err != ERANGE {
144 return "", err
145 }
146 }
147 }
148
149 func Getcwd(buf []byte) (n int, err error) {
150 err = getcwd(buf)
151 if err == nil {
152 i := 0
153 for buf[i] != 0 {
154 i++
155 }
156 n = i + 1
157 }
158 return
159 }
160
161 func Getgroups() (gids []int, err error) {
162 n, err := getgroups(0, nil)
163 if err != nil {
164 return nil, err
165 }
166 if n == 0 {
167 return nil, nil
168 }
169
170 // Sanity check group count. Max is 16 on BSD.
171 if n < 0 || n > 1000 {
172 return nil, EINVAL
173 }
174
175 a := make([]_Gid_t, n)
176 n, err = getgroups(n, &a[0])
177 if err != nil {
178 return nil, err
179 }
180 gids = make([]int, n)
181 for i, v := range a[0:n] {
182 gids[i] = int(v)
183 }
184 return
185 }
186
187 func Setgroups(gids []int) (err error) {
188 if len(gids) == 0 {
189 return setgroups(0, nil)
190 }
191
192 a := make([]_Gid_t, len(gids))
193 for i, v := range gids {
194 a[i] = _Gid_t(v)
195 }
196 return setgroups(len(a), &a[0])
197 }
198
199 /*
200 * Socket
201 */
202
203 //sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error)
204
205 func Accept(fd int) (nfd int, sa Sockaddr, err error) {
206 var rsa RawSockaddrAny
207 var len _Socklen = SizeofSockaddrAny
208 nfd, err = accept(fd, &rsa, &len)
209 if nfd == -1 {
210 return
211 }
212 sa, err = anyToSockaddr(fd, &rsa)
213 if err != nil {
214 Close(nfd)
215 nfd = 0
216 }
217 return
218 }
219
220 func recvmsgRaw(fd int, iov []Iovec, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) {
221 var msg Msghdr
222 msg.Name = (*byte)(unsafe.Pointer(rsa))
223 msg.Namelen = uint32(SizeofSockaddrAny)
224 var dummy byte
225 if len(oob) > 0 {
226 // receive at least one normal byte
227 if emptyIovecs(iov) {
228 var iova [1]Iovec
229 iova[0].Base = &dummy
230 iova[0].SetLen(1)
231 iov = iova[:]
232 }
233 msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
234 msg.SetControllen(len(oob))
235 }
236 if len(iov) > 0 {
237 msg.Iov = &iov[0]
238 msg.SetIovlen(len(iov))
239 }
240 if n, err = recvmsg(fd, &msg, flags); n == -1 {
241 return
242 }
243 oobn = int(msg.Controllen)
244 recvflags = int(msg.Flags)
245 return
246 }
247
248 func sendmsgN(fd int, iov []Iovec, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) {
249 var msg Msghdr
250 msg.Name = (*byte)(unsafe.Pointer(ptr))
251 msg.Namelen = uint32(salen)
252 var dummy byte
253 var empty bool
254 if len(oob) > 0 {
255 // send at least one normal byte
256 empty = emptyIovecs(iov)
257 if empty {
258 var iova [1]Iovec
259 iova[0].Base = &dummy
260 iova[0].SetLen(1)
261 iov = iova[:]
262 }
263 msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
264 msg.SetControllen(len(oob))
265 }
266 if len(iov) > 0 {
267 msg.Iov = &iov[0]
268 msg.SetIovlen(len(iov))
269 }
270 if n, err = sendmsg(fd, &msg, flags); err != nil {
271 return 0, err
272 }
273 if len(oob) > 0 && empty {
274 n = 0
275 }
276 return n, nil
277 }
278
279 func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
280 switch rsa.Addr.Family {
281
282 case AF_UNIX:
283 pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
284 sa := new(SockaddrUnix)
285
286 // Some versions of AIX have a bug in getsockname (see IV78655).
287 // We can't rely on sa.Len being set correctly.
288 n := SizeofSockaddrUnix - 3 // subtract leading Family, Len, terminating NUL.
289 for i := 0; i < n; i++ {
290 if pp.Path[i] == 0 {
291 n = i
292 break
293 }
294 }
295 sa.Name = string(unsafe.Slice((*byte)(unsafe.Pointer(&pp.Path[0])), n))
296 return sa, nil
297
298 case AF_INET:
299 pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
300 sa := new(SockaddrInet4)
301 p := (*[2]byte)(unsafe.Pointer(&pp.Port))
302 sa.Port = int(p[0])<<8 + int(p[1])
303 sa.Addr = pp.Addr
304 return sa, nil
305
306 case AF_INET6:
307 pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
308 sa := new(SockaddrInet6)
309 p := (*[2]byte)(unsafe.Pointer(&pp.Port))
310 sa.Port = int(p[0])<<8 + int(p[1])
311 sa.ZoneId = pp.Scope_id
312 sa.Addr = pp.Addr
313 return sa, nil
314 }
315 return nil, EAFNOSUPPORT
316 }
317
318 func Gettimeofday(tv *Timeval) (err error) {
319 err = gettimeofday(tv, nil)
320 return
321 }
322
323 func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
324 if raceenabled {
325 raceReleaseMerge(unsafe.Pointer(&ioSync))
326 }
327 return sendfile(outfd, infd, offset, count)
328 }
329
330 // TODO
331 func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
332 return -1, ENOSYS
333 }
334
335 func direntIno(buf []byte) (uint64, bool) {
336 return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
337 }
338
339 func direntReclen(buf []byte) (uint64, bool) {
340 return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
341 }
342
343 func direntNamlen(buf []byte) (uint64, bool) {
344 reclen, ok := direntReclen(buf)
345 if !ok {
346 return 0, false
347 }
348 return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true
349 }
350
351 //sys getdirent(fd int, buf []byte) (n int, err error)
352
353 func Getdents(fd int, buf []byte) (n int, err error) {
354 return getdirent(fd, buf)
355 }
356
357 //sys wait4(pid Pid_t, status *_C_int, options int, rusage *Rusage) (wpid Pid_t, err error)
358
359 func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
360 var status _C_int
361 var r Pid_t
362 err = ERESTART
363 // AIX wait4 may return with ERESTART errno, while the process is still
364 // active.
365 for err == ERESTART {
366 r, err = wait4(Pid_t(pid), &status, options, rusage)
367 }
368 wpid = int(r)
369 if wstatus != nil {
370 *wstatus = WaitStatus(status)
371 }
372 return
373 }
374
375 /*
376 * Wait
377 */
378
379 type WaitStatus uint32
380
381 func (w WaitStatus) Stopped() bool { return w&0x40 != 0 }
382 func (w WaitStatus) StopSignal() Signal {
383 if !w.Stopped() {
384 return -1
385 }
386 return Signal(w>>8) & 0xFF
387 }
388
389 func (w WaitStatus) Exited() bool { return w&0xFF == 0 }
390 func (w WaitStatus) ExitStatus() int {
391 if !w.Exited() {
392 return -1
393 }
394 return int((w >> 8) & 0xFF)
395 }
396
397 func (w WaitStatus) Signaled() bool { return w&0x40 == 0 && w&0xFF != 0 }
398 func (w WaitStatus) Signal() Signal {
399 if !w.Signaled() {
400 return -1
401 }
402 return Signal(w>>16) & 0xFF
403 }
404
405 func (w WaitStatus) Continued() bool { return w&0x01000000 != 0 }
406
407 func (w WaitStatus) CoreDump() bool { return w&0x80 == 0x80 }
408
409 func (w WaitStatus) TrapCause() int { return -1 }
410
411 //sys ioctl(fd int, req int, arg uintptr) (err error)
412 //sys ioctlPtr(fd int, req int, arg unsafe.Pointer) (err error) = ioctl
413
414 // fcntl must never be called with cmd=F_DUP2FD because it doesn't work on AIX
415 // There is no way to create a custom fcntl and to keep //sys fcntl easily,
416 // Therefore, the programmer must call dup2 instead of fcntl in this case.
417
418 // FcntlInt performs a fcntl syscall on fd with the provided command and argument.
419 //sys FcntlInt(fd uintptr, cmd int, arg int) (r int,err error) = fcntl
420
421 // FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command.
422 //sys FcntlFlock(fd uintptr, cmd int, lk *Flock_t) (err error) = fcntl
423
424 //sys fcntl(fd int, cmd int, arg int) (val int, err error)
425
426 //sys fsyncRange(fd int, how int, start int64, length int64) (err error) = fsync_range
427
428 func Fsync(fd int) error {
429 return fsyncRange(fd, O_SYNC, 0, 0)
430 }
431
432 /*
433 * Direct access
434 */
435
436 //sys Acct(path string) (err error)
437 //sys Chdir(path string) (err error)
438 //sys Chroot(path string) (err error)
439 //sys Close(fd int) (err error)
440 //sys Dup(oldfd int) (fd int, err error)
441 //sys Exit(code int)
442 //sys Faccessat(dirfd int, path string, mode uint32, flags int) (err error)
443 //sys Fchdir(fd int) (err error)
444 //sys Fchmod(fd int, mode uint32) (err error)
445 //sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error)
446 //sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error)
447 //sys Fdatasync(fd int) (err error)
448 // readdir_r
449 //sysnb Getpgid(pid int) (pgid int, err error)
450
451 //sys Getpgrp() (pid int)
452
453 //sysnb Getpid() (pid int)
454 //sysnb Getppid() (ppid int)
455 //sys Getpriority(which int, who int) (prio int, err error)
456 //sysnb Getrusage(who int, rusage *Rusage) (err error)
457 //sysnb Getsid(pid int) (sid int, err error)
458 //sysnb Kill(pid int, sig Signal) (err error)
459 //sys Klogctl(typ int, buf []byte) (n int, err error) = syslog
460 //sys Mkdir(dirfd int, path string, mode uint32) (err error)
461 //sys Mkdirat(dirfd int, path string, mode uint32) (err error)
462 //sys Mkfifo(path string, mode uint32) (err error)
463 //sys Mknod(path string, mode uint32, dev int) (err error)
464 //sys Mknodat(dirfd int, path string, mode uint32, dev int) (err error)
465 //sys Nanosleep(time *Timespec, leftover *Timespec) (err error)
466 //sys Open(path string, mode int, perm uint32) (fd int, err error) = open64
467 //sys Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
468 //sys read(fd int, p []byte) (n int, err error)
469 //sys Readlink(path string, buf []byte) (n int, err error)
470 //sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
471 //sys Setdomainname(p []byte) (err error)
472 //sys Sethostname(p []byte) (err error)
473 //sysnb Setpgid(pid int, pgid int) (err error)
474 //sysnb Setsid() (pid int, err error)
475 //sysnb Settimeofday(tv *Timeval) (err error)
476
477 //sys Setuid(uid int) (err error)
478 //sys Setgid(uid int) (err error)
479
480 //sys Setpriority(which int, who int, prio int) (err error)
481 //sys Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error)
482 //sys Sync()
483 //sysnb Times(tms *Tms) (ticks uintptr, err error)
484 //sysnb Umask(mask int) (oldmask int)
485 //sysnb Uname(buf *Utsname) (err error)
486 //sys Unlink(path string) (err error)
487 //sys Unlinkat(dirfd int, path string, flags int) (err error)
488 //sys Ustat(dev int, ubuf *Ustat_t) (err error)
489 //sys write(fd int, p []byte) (n int, err error)
490
491 //sys Dup2(oldfd int, newfd int) (err error)
492 //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = posix_fadvise64
493 //sys Fchown(fd int, uid int, gid int) (err error)
494 //sys fstat(fd int, stat *Stat_t) (err error)
495 //sys fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = fstatat
496 //sys Fstatfs(fd int, buf *Statfs_t) (err error)
497 //sys Ftruncate(fd int, length int64) (err error)
498 //sysnb Getegid() (egid int)
499 //sysnb Geteuid() (euid int)
500 //sysnb Getgid() (gid int)
501 //sysnb Getuid() (uid int)
502 //sys Lchown(path string, uid int, gid int) (err error)
503 //sys Listen(s int, n int) (err error)
504 //sys lstat(path string, stat *Stat_t) (err error)
505 //sys Pause() (err error)
506 //sys pread(fd int, p []byte, offset int64) (n int, err error) = pread64
507 //sys pwrite(fd int, p []byte, offset int64) (n int, err error) = pwrite64
508 //sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
509 //sys Pselect(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *Sigset_t) (n int, err error)
510 //sysnb Setregid(rgid int, egid int) (err error)
511 //sysnb Setreuid(ruid int, euid int) (err error)
512 //sys Shutdown(fd int, how int) (err error)
513 //sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
514 //sys stat(path string, statptr *Stat_t) (err error)
515 //sys Statfs(path string, buf *Statfs_t) (err error)
516 //sys Truncate(path string, length int64) (err error)
517
518 //sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
519 //sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
520 //sysnb getgroups(n int, list *_Gid_t) (nn int, err error)
521 //sysnb setgroups(n int, list *_Gid_t) (err error)
522 //sys getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error)
523 //sys setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error)
524 //sysnb socket(domain int, typ int, proto int) (fd int, err error)
525 //sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error)
526 //sysnb getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
527 //sysnb getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
528 //sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error)
529 //sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error)
530
531 // In order to use msghdr structure with Control, Controllen, nrecvmsg and nsendmsg must be used.
532 //sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = nrecvmsg
533 //sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = nsendmsg
534
535 //sys munmap(addr uintptr, length uintptr) (err error)
536 //sys Madvise(b []byte, advice int) (err error)
537 //sys Mprotect(b []byte, prot int) (err error)
538 //sys Mlock(b []byte) (err error)
539 //sys Mlockall(flags int) (err error)
540 //sys Msync(b []byte, flags int) (err error)
541 //sys Munlock(b []byte) (err error)
542 //sys Munlockall() (err error)
543
544 //sysnb pipe(p *[2]_C_int) (err error)
545
546 func Pipe(p []int) (err error) {
547 if len(p) != 2 {
548 return EINVAL
549 }
550 var pp [2]_C_int
551 err = pipe(&pp)
552 if err == nil {
553 p[0] = int(pp[0])
554 p[1] = int(pp[1])
555 }
556 return
557 }
558
559 //sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
560
561 func Poll(fds []PollFd, timeout int) (n int, err error) {
562 if len(fds) == 0 {
563 return poll(nil, 0, timeout)
564 }
565 return poll(&fds[0], len(fds), timeout)
566 }
567
568 //sys gettimeofday(tv *Timeval, tzp *Timezone) (err error)
569 //sysnb Time(t *Time_t) (tt Time_t, err error)
570 //sys Utime(path string, buf *Utimbuf) (err error)
571
572 //sys Getsystemcfg(label int) (n uint64)
573
574 //sys umount(target string) (err error)
575
576 func Unmount(target string, flags int) (err error) {
577 if flags != 0 {
578 // AIX doesn't have any flags for umount.
579 return ENOSYS
580 }
581 return umount(target)
582 }
583