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