12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829 |
- // Copyright 2020 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- //go:build zos && s390x
- // +build zos,s390x
- package unix
- import (
- "bytes"
- "runtime"
- "sort"
- "sync"
- "syscall"
- "unsafe"
- )
- const (
- O_CLOEXEC = 0 // Dummy value (not supported).
- AF_LOCAL = AF_UNIX // AF_LOCAL is an alias for AF_UNIX
- )
- func syscall_syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
- func syscall_rawsyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
- func syscall_syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
- func syscall_rawsyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
- func syscall_syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno)
- func syscall_rawsyscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno)
- func copyStat(stat *Stat_t, statLE *Stat_LE_t) {
- stat.Dev = uint64(statLE.Dev)
- stat.Ino = uint64(statLE.Ino)
- stat.Nlink = uint64(statLE.Nlink)
- stat.Mode = uint32(statLE.Mode)
- stat.Uid = uint32(statLE.Uid)
- stat.Gid = uint32(statLE.Gid)
- stat.Rdev = uint64(statLE.Rdev)
- stat.Size = statLE.Size
- stat.Atim.Sec = int64(statLE.Atim)
- stat.Atim.Nsec = 0 //zos doesn't return nanoseconds
- stat.Mtim.Sec = int64(statLE.Mtim)
- stat.Mtim.Nsec = 0 //zos doesn't return nanoseconds
- stat.Ctim.Sec = int64(statLE.Ctim)
- stat.Ctim.Nsec = 0 //zos doesn't return nanoseconds
- stat.Blksize = int64(statLE.Blksize)
- stat.Blocks = statLE.Blocks
- }
- func svcCall(fnptr unsafe.Pointer, argv *unsafe.Pointer, dsa *uint64)
- func svcLoad(name *byte) unsafe.Pointer
- func svcUnload(name *byte, fnptr unsafe.Pointer) int64
- func (d *Dirent) NameString() string {
- if d == nil {
- return ""
- }
- return string(d.Name[:d.Namlen])
- }
- func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
- if sa.Port < 0 || sa.Port > 0xFFFF {
- return nil, 0, EINVAL
- }
- sa.raw.Len = SizeofSockaddrInet4
- sa.raw.Family = AF_INET
- p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
- p[0] = byte(sa.Port >> 8)
- p[1] = byte(sa.Port)
- for i := 0; i < len(sa.Addr); i++ {
- sa.raw.Addr[i] = sa.Addr[i]
- }
- return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
- }
- func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
- if sa.Port < 0 || sa.Port > 0xFFFF {
- return nil, 0, EINVAL
- }
- sa.raw.Len = SizeofSockaddrInet6
- sa.raw.Family = AF_INET6
- p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
- p[0] = byte(sa.Port >> 8)
- p[1] = byte(sa.Port)
- sa.raw.Scope_id = sa.ZoneId
- for i := 0; i < len(sa.Addr); i++ {
- sa.raw.Addr[i] = sa.Addr[i]
- }
- return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
- }
- func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) {
- name := sa.Name
- n := len(name)
- if n >= len(sa.raw.Path) || n == 0 {
- return nil, 0, EINVAL
- }
- sa.raw.Len = byte(3 + n) // 2 for Family, Len; 1 for NUL
- sa.raw.Family = AF_UNIX
- for i := 0; i < n; i++ {
- sa.raw.Path[i] = int8(name[i])
- }
- return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
- }
- func anyToSockaddr(_ int, rsa *RawSockaddrAny) (Sockaddr, error) {
- // TODO(neeilan): Implement use of first param (fd)
- switch rsa.Addr.Family {
- case AF_UNIX:
- pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
- sa := new(SockaddrUnix)
- // For z/OS, only replace NUL with @ when the
- // length is not zero.
- if pp.Len != 0 && pp.Path[0] == 0 {
- // "Abstract" Unix domain socket.
- // Rewrite leading NUL as @ for textual display.
- // (This is the standard convention.)
- // Not friendly to overwrite in place,
- // but the callers below don't care.
- pp.Path[0] = '@'
- }
- // Assume path ends at NUL.
- //
- // For z/OS, the length of the name is a field
- // in the structure. To be on the safe side, we
- // will still scan the name for a NUL but only
- // to the length provided in the structure.
- //
- // This is not technically the Linux semantics for
- // abstract Unix domain sockets--they are supposed
- // to be uninterpreted fixed-size binary blobs--but
- // everyone uses this convention.
- n := 0
- for n < int(pp.Len) && pp.Path[n] != 0 {
- n++
- }
- bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))[0:n]
- sa.Name = string(bytes)
- return sa, nil
- case AF_INET:
- pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
- sa := new(SockaddrInet4)
- p := (*[2]byte)(unsafe.Pointer(&pp.Port))
- sa.Port = int(p[0])<<8 + int(p[1])
- for i := 0; i < len(sa.Addr); i++ {
- sa.Addr[i] = pp.Addr[i]
- }
- return sa, nil
- case AF_INET6:
- pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
- sa := new(SockaddrInet6)
- p := (*[2]byte)(unsafe.Pointer(&pp.Port))
- sa.Port = int(p[0])<<8 + int(p[1])
- sa.ZoneId = pp.Scope_id
- for i := 0; i < len(sa.Addr); i++ {
- sa.Addr[i] = pp.Addr[i]
- }
- return sa, nil
- }
- return nil, EAFNOSUPPORT
- }
- func Accept(fd int) (nfd int, sa Sockaddr, err error) {
- var rsa RawSockaddrAny
- var len _Socklen = SizeofSockaddrAny
- nfd, err = accept(fd, &rsa, &len)
- if err != nil {
- return
- }
- // TODO(neeilan): Remove 0 in call
- sa, err = anyToSockaddr(0, &rsa)
- if err != nil {
- Close(nfd)
- nfd = 0
- }
- return
- }
- func (iov *Iovec) SetLen(length int) {
- iov.Len = uint64(length)
- }
- func (msghdr *Msghdr) SetControllen(length int) {
- msghdr.Controllen = int32(length)
- }
- func (cmsg *Cmsghdr) SetLen(length int) {
- cmsg.Len = int32(length)
- }
- //sys fcntl(fd int, cmd int, arg int) (val int, err error)
- //sys read(fd int, p []byte) (n int, err error)
- //sys readlen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_READ
- //sys write(fd int, p []byte) (n int, err error)
- //sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) = SYS___ACCEPT_A
- //sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = SYS___BIND_A
- //sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = SYS___CONNECT_A
- //sysnb getgroups(n int, list *_Gid_t) (nn int, err error)
- //sysnb setgroups(n int, list *_Gid_t) (err error)
- //sys getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error)
- //sys setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error)
- //sysnb socket(domain int, typ int, proto int) (fd int, err error)
- //sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error)
- //sysnb getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = SYS___GETPEERNAME_A
- //sysnb getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = SYS___GETSOCKNAME_A
- //sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) = SYS___RECVFROM_A
- //sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) = SYS___SENDTO_A
- //sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = SYS___RECVMSG_A
- //sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = SYS___SENDMSG_A
- //sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) = SYS_MMAP
- //sys munmap(addr uintptr, length uintptr) (err error) = SYS_MUNMAP
- //sys ioctl(fd int, req uint, arg uintptr) (err error) = SYS_IOCTL
- //sys Access(path string, mode uint32) (err error) = SYS___ACCESS_A
- //sys Chdir(path string) (err error) = SYS___CHDIR_A
- //sys Chown(path string, uid int, gid int) (err error) = SYS___CHOWN_A
- //sys Chmod(path string, mode uint32) (err error) = SYS___CHMOD_A
- //sys Creat(path string, mode uint32) (fd int, err error) = SYS___CREAT_A
- //sys Dup(oldfd int) (fd int, err error)
- //sys Dup2(oldfd int, newfd int) (err error)
- //sys Errno2() (er2 int) = SYS___ERRNO2
- //sys Err2ad() (eadd *int) = SYS___ERR2AD
- //sys Exit(code int)
- //sys Fchdir(fd int) (err error)
- //sys Fchmod(fd int, mode uint32) (err error)
- //sys Fchown(fd int, uid int, gid int) (err error)
- //sys FcntlInt(fd uintptr, cmd int, arg int) (retval int, err error) = SYS_FCNTL
- //sys fstat(fd int, stat *Stat_LE_t) (err error)
- func Fstat(fd int, stat *Stat_t) (err error) {
- var statLE Stat_LE_t
- err = fstat(fd, &statLE)
- copyStat(stat, &statLE)
- return
- }
- //sys Fstatvfs(fd int, stat *Statvfs_t) (err error) = SYS_FSTATVFS
- //sys Fsync(fd int) (err error)
- //sys Ftruncate(fd int, length int64) (err error)
- //sys Getpagesize() (pgsize int) = SYS_GETPAGESIZE
- //sys Mprotect(b []byte, prot int) (err error) = SYS_MPROTECT
- //sys Msync(b []byte, flags int) (err error) = SYS_MSYNC
- //sys Poll(fds []PollFd, timeout int) (n int, err error) = SYS_POLL
- //sys Times(tms *Tms) (ticks uintptr, err error) = SYS_TIMES
- //sys W_Getmntent(buff *byte, size int) (lastsys int, err error) = SYS_W_GETMNTENT
- //sys W_Getmntent_A(buff *byte, size int) (lastsys int, err error) = SYS___W_GETMNTENT_A
- //sys mount_LE(path string, filesystem string, fstype string, mtm uint32, parmlen int32, parm string) (err error) = SYS___MOUNT_A
- //sys unmount(filesystem string, mtm int) (err error) = SYS___UMOUNT_A
- //sys Chroot(path string) (err error) = SYS___CHROOT_A
- //sys Select(nmsgsfds int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (ret int, err error) = SYS_SELECT
- //sysnb Uname(buf *Utsname) (err error) = SYS___UNAME_A
- func Ptsname(fd int) (name string, err error) {
- r0, _, e1 := syscall_syscall(SYS___PTSNAME_A, uintptr(fd), 0, 0)
- name = u2s(unsafe.Pointer(r0))
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
- }
- func u2s(cstr unsafe.Pointer) string {
- str := (*[1024]uint8)(cstr)
- i := 0
- for str[i] != 0 {
- i++
- }
- return string(str[:i])
- }
- func Close(fd int) (err error) {
- _, _, e1 := syscall_syscall(SYS_CLOSE, uintptr(fd), 0, 0)
- for i := 0; e1 == EAGAIN && i < 10; i++ {
- _, _, _ = syscall_syscall(SYS_USLEEP, uintptr(10), 0, 0)
- _, _, e1 = syscall_syscall(SYS_CLOSE, uintptr(fd), 0, 0)
- }
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
- }
- var mapper = &mmapper{
- active: make(map[*byte][]byte),
- mmap: mmap,
- munmap: munmap,
- }
- // Dummy function: there are no semantics for Madvise on z/OS
- func Madvise(b []byte, advice int) (err error) {
- return
- }
- func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
- return mapper.Mmap(fd, offset, length, prot, flags)
- }
- func Munmap(b []byte) (err error) {
- return mapper.Munmap(b)
- }
- //sys Gethostname(buf []byte) (err error) = SYS___GETHOSTNAME_A
- //sysnb Getegid() (egid int)
- //sysnb Geteuid() (uid int)
- //sysnb Getgid() (gid int)
- //sysnb Getpid() (pid int)
- //sysnb Getpgid(pid int) (pgid int, err error) = SYS_GETPGID
- func Getpgrp() (pid int) {
- pid, _ = Getpgid(0)
- return
- }
- //sysnb Getppid() (pid int)
- //sys Getpriority(which int, who int) (prio int, err error)
- //sysnb Getrlimit(resource int, rlim *Rlimit) (err error) = SYS_GETRLIMIT
- //sysnb getrusage(who int, rusage *rusage_zos) (err error) = SYS_GETRUSAGE
- func Getrusage(who int, rusage *Rusage) (err error) {
- var ruz rusage_zos
- err = getrusage(who, &ruz)
- //Only the first two fields of Rusage are set
- rusage.Utime.Sec = ruz.Utime.Sec
- rusage.Utime.Usec = int64(ruz.Utime.Usec)
- rusage.Stime.Sec = ruz.Stime.Sec
- rusage.Stime.Usec = int64(ruz.Stime.Usec)
- return
- }
- //sysnb Getsid(pid int) (sid int, err error) = SYS_GETSID
- //sysnb Getuid() (uid int)
- //sysnb Kill(pid int, sig Signal) (err error)
- //sys Lchown(path string, uid int, gid int) (err error) = SYS___LCHOWN_A
- //sys Link(path string, link string) (err error) = SYS___LINK_A
- //sys Listen(s int, n int) (err error)
- //sys lstat(path string, stat *Stat_LE_t) (err error) = SYS___LSTAT_A
- func Lstat(path string, stat *Stat_t) (err error) {
- var statLE Stat_LE_t
- err = lstat(path, &statLE)
- copyStat(stat, &statLE)
- return
- }
- //sys Mkdir(path string, mode uint32) (err error) = SYS___MKDIR_A
- //sys Mkfifo(path string, mode uint32) (err error) = SYS___MKFIFO_A
- //sys Mknod(path string, mode uint32, dev int) (err error) = SYS___MKNOD_A
- //sys Pread(fd int, p []byte, offset int64) (n int, err error)
- //sys Pwrite(fd int, p []byte, offset int64) (n int, err error)
- //sys Readlink(path string, buf []byte) (n int, err error) = SYS___READLINK_A
- //sys Rename(from string, to string) (err error) = SYS___RENAME_A
- //sys Rmdir(path string) (err error) = SYS___RMDIR_A
- //sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
- //sys Setpriority(which int, who int, prio int) (err error)
- //sysnb Setpgid(pid int, pgid int) (err error) = SYS_SETPGID
- //sysnb Setrlimit(resource int, lim *Rlimit) (err error)
- //sysnb Setregid(rgid int, egid int) (err error) = SYS_SETREGID
- //sysnb Setreuid(ruid int, euid int) (err error) = SYS_SETREUID
- //sysnb Setsid() (pid int, err error) = SYS_SETSID
- //sys Setuid(uid int) (err error) = SYS_SETUID
- //sys Setgid(uid int) (err error) = SYS_SETGID
- //sys Shutdown(fd int, how int) (err error)
- //sys stat(path string, statLE *Stat_LE_t) (err error) = SYS___STAT_A
- func Stat(path string, sta *Stat_t) (err error) {
- var statLE Stat_LE_t
- err = stat(path, &statLE)
- copyStat(sta, &statLE)
- return
- }
- //sys Symlink(path string, link string) (err error) = SYS___SYMLINK_A
- //sys Sync() = SYS_SYNC
- //sys Truncate(path string, length int64) (err error) = SYS___TRUNCATE_A
- //sys Tcgetattr(fildes int, termptr *Termios) (err error) = SYS_TCGETATTR
- //sys Tcsetattr(fildes int, when int, termptr *Termios) (err error) = SYS_TCSETATTR
- //sys Umask(mask int) (oldmask int)
- //sys Unlink(path string) (err error) = SYS___UNLINK_A
- //sys Utime(path string, utim *Utimbuf) (err error) = SYS___UTIME_A
- //sys open(path string, mode int, perm uint32) (fd int, err error) = SYS___OPEN_A
- func Open(path string, mode int, perm uint32) (fd int, err error) {
- return open(path, mode, perm)
- }
- func Mkfifoat(dirfd int, path string, mode uint32) (err error) {
- wd, err := Getwd()
- if err != nil {
- return err
- }
- if err := Fchdir(dirfd); err != nil {
- return err
- }
- defer Chdir(wd)
- return Mkfifo(path, mode)
- }
- //sys remove(path string) (err error)
- func Remove(path string) error {
- return remove(path)
- }
- const ImplementsGetwd = true
- func Getcwd(buf []byte) (n int, err error) {
- var p unsafe.Pointer
- if len(buf) > 0 {
- p = unsafe.Pointer(&buf[0])
- } else {
- p = unsafe.Pointer(&_zero)
- }
- _, _, e := syscall_syscall(SYS___GETCWD_A, uintptr(p), uintptr(len(buf)), 0)
- n = clen(buf) + 1
- if e != 0 {
- err = errnoErr(e)
- }
- return
- }
- func Getwd() (wd string, err error) {
- var buf [PathMax]byte
- n, err := Getcwd(buf[0:])
- if err != nil {
- return "", err
- }
- // Getcwd returns the number of bytes written to buf, including the NUL.
- if n < 1 || n > len(buf) || buf[n-1] != 0 {
- return "", EINVAL
- }
- return string(buf[0 : n-1]), nil
- }
- func Getgroups() (gids []int, err error) {
- n, err := getgroups(0, nil)
- if err != nil {
- return nil, err
- }
- if n == 0 {
- return nil, nil
- }
- // Sanity check group count. Max is 1<<16 on Linux.
- if n < 0 || n > 1<<20 {
- return nil, EINVAL
- }
- a := make([]_Gid_t, n)
- n, err = getgroups(n, &a[0])
- if err != nil {
- return nil, err
- }
- gids = make([]int, n)
- for i, v := range a[0:n] {
- gids[i] = int(v)
- }
- return
- }
- func Setgroups(gids []int) (err error) {
- if len(gids) == 0 {
- return setgroups(0, nil)
- }
- a := make([]_Gid_t, len(gids))
- for i, v := range gids {
- a[i] = _Gid_t(v)
- }
- return setgroups(len(a), &a[0])
- }
- func gettid() uint64
- func Gettid() (tid int) {
- return int(gettid())
- }
- type WaitStatus uint32
- // Wait status is 7 bits at bottom, either 0 (exited),
- // 0x7F (stopped), or a signal number that caused an exit.
- // The 0x80 bit is whether there was a core dump.
- // An extra number (exit code, signal causing a stop)
- // is in the high bits. At least that's the idea.
- // There are various irregularities. For example, the
- // "continued" status is 0xFFFF, distinguishing itself
- // from stopped via the core dump bit.
- const (
- mask = 0x7F
- core = 0x80
- exited = 0x00
- stopped = 0x7F
- shift = 8
- )
- func (w WaitStatus) Exited() bool { return w&mask == exited }
- func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != exited }
- func (w WaitStatus) Stopped() bool { return w&0xFF == stopped }
- func (w WaitStatus) Continued() bool { return w == 0xFFFF }
- func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 }
- func (w WaitStatus) ExitStatus() int {
- if !w.Exited() {
- return -1
- }
- return int(w>>shift) & 0xFF
- }
- func (w WaitStatus) Signal() Signal {
- if !w.Signaled() {
- return -1
- }
- return Signal(w & mask)
- }
- func (w WaitStatus) StopSignal() Signal {
- if !w.Stopped() {
- return -1
- }
- return Signal(w>>shift) & 0xFF
- }
- func (w WaitStatus) TrapCause() int { return -1 }
- //sys waitpid(pid int, wstatus *_C_int, options int) (wpid int, err error)
- func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
- // TODO(mundaym): z/OS doesn't have wait4. I don't think getrusage does what we want.
- // At the moment rusage will not be touched.
- var status _C_int
- wpid, err = waitpid(pid, &status, options)
- if wstatus != nil {
- *wstatus = WaitStatus(status)
- }
- return
- }
- //sysnb gettimeofday(tv *timeval_zos) (err error)
- func Gettimeofday(tv *Timeval) (err error) {
- var tvz timeval_zos
- err = gettimeofday(&tvz)
- tv.Sec = tvz.Sec
- tv.Usec = int64(tvz.Usec)
- return
- }
- func Time(t *Time_t) (tt Time_t, err error) {
- var tv Timeval
- err = Gettimeofday(&tv)
- if err != nil {
- return 0, err
- }
- if t != nil {
- *t = Time_t(tv.Sec)
- }
- return Time_t(tv.Sec), nil
- }
- func setTimespec(sec, nsec int64) Timespec {
- return Timespec{Sec: sec, Nsec: nsec}
- }
- func setTimeval(sec, usec int64) Timeval { //fix
- return Timeval{Sec: sec, Usec: usec}
- }
- //sysnb pipe(p *[2]_C_int) (err error)
- func Pipe(p []int) (err error) {
- if len(p) != 2 {
- return EINVAL
- }
- var pp [2]_C_int
- err = pipe(&pp)
- p[0] = int(pp[0])
- p[1] = int(pp[1])
- return
- }
- //sys utimes(path string, timeval *[2]Timeval) (err error) = SYS___UTIMES_A
- func Utimes(path string, tv []Timeval) (err error) {
- if len(tv) != 2 {
- return EINVAL
- }
- return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
- }
- func UtimesNano(path string, ts []Timespec) error {
- if len(ts) != 2 {
- return EINVAL
- }
- // Not as efficient as it could be because Timespec and
- // Timeval have different types in the different OSes
- tv := [2]Timeval{
- NsecToTimeval(TimespecToNsec(ts[0])),
- NsecToTimeval(TimespecToNsec(ts[1])),
- }
- return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
- }
- func Getsockname(fd int) (sa Sockaddr, err error) {
- var rsa RawSockaddrAny
- var len _Socklen = SizeofSockaddrAny
- if err = getsockname(fd, &rsa, &len); err != nil {
- return
- }
- // TODO(neeilan) : Remove this 0 ( added to get sys/unix compiling on z/OS )
- return anyToSockaddr(0, &rsa)
- }
- const (
- // identifier constants
- nwmHeaderIdentifier = 0xd5e6d4c8
- nwmFilterIdentifier = 0xd5e6d4c6
- nwmTCPConnIdentifier = 0xd5e6d4c3
- nwmRecHeaderIdentifier = 0xd5e6d4d9
- nwmIPStatsIdentifier = 0xd5e6d4c9d7e2e340
- nwmIPGStatsIdentifier = 0xd5e6d4c9d7c7e2e3
- nwmTCPStatsIdentifier = 0xd5e6d4e3c3d7e2e3
- nwmUDPStatsIdentifier = 0xd5e6d4e4c4d7e2e3
- nwmICMPGStatsEntry = 0xd5e6d4c9c3d4d7c7
- nwmICMPTStatsEntry = 0xd5e6d4c9c3d4d7e3
- // nwmHeader constants
- nwmVersion1 = 1
- nwmVersion2 = 2
- nwmCurrentVer = 2
- nwmTCPConnType = 1
- nwmGlobalStatsType = 14
- // nwmFilter constants
- nwmFilterLclAddrMask = 0x20000000 // Local address
- nwmFilterSrcAddrMask = 0x20000000 // Source address
- nwmFilterLclPortMask = 0x10000000 // Local port
- nwmFilterSrcPortMask = 0x10000000 // Source port
- // nwmConnEntry constants
- nwmTCPStateClosed = 1
- nwmTCPStateListen = 2
- nwmTCPStateSynSent = 3
- nwmTCPStateSynRcvd = 4
- nwmTCPStateEstab = 5
- nwmTCPStateFinWait1 = 6
- nwmTCPStateFinWait2 = 7
- nwmTCPStateClosWait = 8
- nwmTCPStateLastAck = 9
- nwmTCPStateClosing = 10
- nwmTCPStateTimeWait = 11
- nwmTCPStateDeletTCB = 12
- // Existing constants on linux
- BPF_TCP_CLOSE = 1
- BPF_TCP_LISTEN = 2
- BPF_TCP_SYN_SENT = 3
- BPF_TCP_SYN_RECV = 4
- BPF_TCP_ESTABLISHED = 5
- BPF_TCP_FIN_WAIT1 = 6
- BPF_TCP_FIN_WAIT2 = 7
- BPF_TCP_CLOSE_WAIT = 8
- BPF_TCP_LAST_ACK = 9
- BPF_TCP_CLOSING = 10
- BPF_TCP_TIME_WAIT = 11
- BPF_TCP_NEW_SYN_RECV = -1
- BPF_TCP_MAX_STATES = -2
- )
- type nwmTriplet struct {
- offset uint32
- length uint32
- number uint32
- }
- type nwmQuadruplet struct {
- offset uint32
- length uint32
- number uint32
- match uint32
- }
- type nwmHeader struct {
- ident uint32
- length uint32
- version uint16
- nwmType uint16
- bytesNeeded uint32
- options uint32
- _ [16]byte
- inputDesc nwmTriplet
- outputDesc nwmQuadruplet
- }
- type nwmFilter struct {
- ident uint32
- flags uint32
- resourceName [8]byte
- resourceId uint32
- listenerId uint32
- local [28]byte // union of sockaddr4 and sockaddr6
- remote [28]byte // union of sockaddr4 and sockaddr6
- _ uint16
- _ uint16
- asid uint16
- _ [2]byte
- tnLuName [8]byte
- tnMonGrp uint32
- tnAppl [8]byte
- applData [40]byte
- nInterface [16]byte
- dVipa [16]byte
- dVipaPfx uint16
- dVipaPort uint16
- dVipaFamily byte
- _ [3]byte
- destXCF [16]byte
- destXCFPfx uint16
- destXCFFamily byte
- _ [1]byte
- targIP [16]byte
- targIPPfx uint16
- targIPFamily byte
- _ [1]byte
- _ [20]byte
- }
- type nwmRecHeader struct {
- ident uint32
- length uint32
- number byte
- _ [3]byte
- }
- type nwmTCPStatsEntry struct {
- ident uint64
- currEstab uint32
- activeOpened uint32
- passiveOpened uint32
- connClosed uint32
- estabResets uint32
- attemptFails uint32
- passiveDrops uint32
- timeWaitReused uint32
- inSegs uint64
- predictAck uint32
- predictData uint32
- inDupAck uint32
- inBadSum uint32
- inBadLen uint32
- inShort uint32
- inDiscOldTime uint32
- inAllBeforeWin uint32
- inSomeBeforeWin uint32
- inAllAfterWin uint32
- inSomeAfterWin uint32
- inOutOfOrder uint32
- inAfterClose uint32
- inWinProbes uint32
- inWinUpdates uint32
- outWinUpdates uint32
- outSegs uint64
- outDelayAcks uint32
- outRsts uint32
- retransSegs uint32
- retransTimeouts uint32
- retransDrops uint32
- pmtuRetrans uint32
- pmtuErrors uint32
- outWinProbes uint32
- probeDrops uint32
- keepAliveProbes uint32
- keepAliveDrops uint32
- finwait2Drops uint32
- acceptCount uint64
- inBulkQSegs uint64
- inDiscards uint64
- connFloods uint32
- connStalls uint32
- cfgEphemDef uint16
- ephemInUse uint16
- ephemHiWater uint16
- flags byte
- _ [1]byte
- ephemExhaust uint32
- smcRCurrEstabLnks uint32
- smcRLnkActTimeOut uint32
- smcRActLnkOpened uint32
- smcRPasLnkOpened uint32
- smcRLnksClosed uint32
- smcRCurrEstab uint32
- smcRActiveOpened uint32
- smcRPassiveOpened uint32
- smcRConnClosed uint32
- smcRInSegs uint64
- smcROutSegs uint64
- smcRInRsts uint32
- smcROutRsts uint32
- smcDCurrEstabLnks uint32
- smcDActLnkOpened uint32
- smcDPasLnkOpened uint32
- smcDLnksClosed uint32
- smcDCurrEstab uint32
- smcDActiveOpened uint32
- smcDPassiveOpened uint32
- smcDConnClosed uint32
- smcDInSegs uint64
- smcDOutSegs uint64
- smcDInRsts uint32
- smcDOutRsts uint32
- }
- type nwmConnEntry struct {
- ident uint32
- local [28]byte // union of sockaddr4 and sockaddr6
- remote [28]byte // union of sockaddr4 and sockaddr6
- startTime [8]byte // uint64, changed to prevent padding from being inserted
- lastActivity [8]byte // uint64
- bytesIn [8]byte // uint64
- bytesOut [8]byte // uint64
- inSegs [8]byte // uint64
- outSegs [8]byte // uint64
- state uint16
- activeOpen byte
- flag01 byte
- outBuffered uint32
- inBuffered uint32
- maxSndWnd uint32
- reXmtCount uint32
- congestionWnd uint32
- ssThresh uint32
- roundTripTime uint32
- roundTripVar uint32
- sendMSS uint32
- sndWnd uint32
- rcvBufSize uint32
- sndBufSize uint32
- outOfOrderCount uint32
- lcl0WindowCount uint32
- rmt0WindowCount uint32
- dupacks uint32
- flag02 byte
- sockOpt6Cont byte
- asid uint16
- resourceName [8]byte
- resourceId uint32
- subtask uint32
- sockOpt byte
- sockOpt6 byte
- clusterConnFlag byte
- proto byte
- targetAppl [8]byte
- luName [8]byte
- clientUserId [8]byte
- logMode [8]byte
- timeStamp uint32
- timeStampAge uint32
- serverResourceId uint32
- intfName [16]byte
- ttlsStatPol byte
- ttlsStatConn byte
- ttlsSSLProt uint16
- ttlsNegCiph [2]byte
- ttlsSecType byte
- ttlsFIPS140Mode byte
- ttlsUserID [8]byte
- applData [40]byte
- inOldestTime [8]byte // uint64
- outOldestTime [8]byte // uint64
- tcpTrustedPartner byte
- _ [3]byte
- bulkDataIntfName [16]byte
- ttlsNegCiph4 [4]byte
- smcReason uint32
- lclSMCLinkId uint32
- rmtSMCLinkId uint32
- smcStatus byte
- smcFlags byte
- _ [2]byte
- rcvWnd uint32
- lclSMCBufSz uint32
- rmtSMCBufSz uint32
- ttlsSessID [32]byte
- ttlsSessIDLen int16
- _ [1]byte
- smcDStatus byte
- smcDReason uint32
- }
- var svcNameTable [][]byte = [][]byte{
- []byte("\xc5\xe9\xc2\xd5\xd4\xc9\xc6\xf4"), // svc_EZBNMIF4
- }
- const (
- svc_EZBNMIF4 = 0
- )
- func GetsockoptTCPInfo(fd, level, opt int) (*TCPInfo, error) {
- jobname := []byte("\x5c\x40\x40\x40\x40\x40\x40\x40") // "*"
- responseBuffer := [4096]byte{0}
- var bufferAlet, reasonCode uint32 = 0, 0
- var bufferLen, returnValue, returnCode int32 = 4096, 0, 0
- dsa := [18]uint64{0}
- var argv [7]unsafe.Pointer
- argv[0] = unsafe.Pointer(&jobname[0])
- argv[1] = unsafe.Pointer(&responseBuffer[0])
- argv[2] = unsafe.Pointer(&bufferAlet)
- argv[3] = unsafe.Pointer(&bufferLen)
- argv[4] = unsafe.Pointer(&returnValue)
- argv[5] = unsafe.Pointer(&returnCode)
- argv[6] = unsafe.Pointer(&reasonCode)
- request := (*struct {
- header nwmHeader
- filter nwmFilter
- })(unsafe.Pointer(&responseBuffer[0]))
- EZBNMIF4 := svcLoad(&svcNameTable[svc_EZBNMIF4][0])
- if EZBNMIF4 == nil {
- return nil, errnoErr(EINVAL)
- }
- // GetGlobalStats EZBNMIF4 call
- request.header.ident = nwmHeaderIdentifier
- request.header.length = uint32(unsafe.Sizeof(request.header))
- request.header.version = nwmCurrentVer
- request.header.nwmType = nwmGlobalStatsType
- request.header.options = 0x80000000
- svcCall(EZBNMIF4, &argv[0], &dsa[0])
- // outputDesc field is filled by EZBNMIF4 on success
- if returnCode != 0 || request.header.outputDesc.offset == 0 {
- return nil, errnoErr(EINVAL)
- }
- // Check that EZBNMIF4 returned a nwmRecHeader
- recHeader := (*nwmRecHeader)(unsafe.Pointer(&responseBuffer[request.header.outputDesc.offset]))
- if recHeader.ident != nwmRecHeaderIdentifier {
- return nil, errnoErr(EINVAL)
- }
- // Parse nwmTriplets to get offsets of returned entries
- var sections []*uint64
- var sectionDesc *nwmTriplet = (*nwmTriplet)(unsafe.Pointer(&responseBuffer[0]))
- for i := uint32(0); i < uint32(recHeader.number); i++ {
- offset := request.header.outputDesc.offset + uint32(unsafe.Sizeof(*recHeader)) + i*uint32(unsafe.Sizeof(*sectionDesc))
- sectionDesc = (*nwmTriplet)(unsafe.Pointer(&responseBuffer[offset]))
- for j := uint32(0); j < sectionDesc.number; j++ {
- offset = request.header.outputDesc.offset + sectionDesc.offset + j*sectionDesc.length
- sections = append(sections, (*uint64)(unsafe.Pointer(&responseBuffer[offset])))
- }
- }
- // Find nwmTCPStatsEntry in returned entries
- var tcpStats *nwmTCPStatsEntry = nil
- for _, ptr := range sections {
- switch *ptr {
- case nwmTCPStatsIdentifier:
- if tcpStats != nil {
- return nil, errnoErr(EINVAL)
- }
- tcpStats = (*nwmTCPStatsEntry)(unsafe.Pointer(ptr))
- case nwmIPStatsIdentifier:
- case nwmIPGStatsIdentifier:
- case nwmUDPStatsIdentifier:
- case nwmICMPGStatsEntry:
- case nwmICMPTStatsEntry:
- default:
- return nil, errnoErr(EINVAL)
- }
- }
- if tcpStats == nil {
- return nil, errnoErr(EINVAL)
- }
- // GetConnectionDetail EZBNMIF4 call
- responseBuffer = [4096]byte{0}
- dsa = [18]uint64{0}
- bufferAlet, reasonCode = 0, 0
- bufferLen, returnValue, returnCode = 4096, 0, 0
- nameptr := (*uint32)(unsafe.Pointer(uintptr(0x21c))) // Get jobname of current process
- nameptr = (*uint32)(unsafe.Pointer(uintptr(*nameptr + 12)))
- argv[0] = unsafe.Pointer(uintptr(*nameptr))
- request.header.ident = nwmHeaderIdentifier
- request.header.length = uint32(unsafe.Sizeof(request.header))
- request.header.version = nwmCurrentVer
- request.header.nwmType = nwmTCPConnType
- request.header.options = 0x80000000
- request.filter.ident = nwmFilterIdentifier
- var localSockaddr RawSockaddrAny
- socklen := _Socklen(SizeofSockaddrAny)
- err := getsockname(fd, &localSockaddr, &socklen)
- if err != nil {
- return nil, errnoErr(EINVAL)
- }
- if localSockaddr.Addr.Family == AF_INET {
- localSockaddr := (*RawSockaddrInet4)(unsafe.Pointer(&localSockaddr.Addr))
- localSockFilter := (*RawSockaddrInet4)(unsafe.Pointer(&request.filter.local[0]))
- localSockFilter.Family = AF_INET
- var i int
- for i = 0; i < 4; i++ {
- if localSockaddr.Addr[i] != 0 {
- break
- }
- }
- if i != 4 {
- request.filter.flags |= nwmFilterLclAddrMask
- for i = 0; i < 4; i++ {
- localSockFilter.Addr[i] = localSockaddr.Addr[i]
- }
- }
- if localSockaddr.Port != 0 {
- request.filter.flags |= nwmFilterLclPortMask
- localSockFilter.Port = localSockaddr.Port
- }
- } else if localSockaddr.Addr.Family == AF_INET6 {
- localSockaddr := (*RawSockaddrInet6)(unsafe.Pointer(&localSockaddr.Addr))
- localSockFilter := (*RawSockaddrInet6)(unsafe.Pointer(&request.filter.local[0]))
- localSockFilter.Family = AF_INET6
- var i int
- for i = 0; i < 16; i++ {
- if localSockaddr.Addr[i] != 0 {
- break
- }
- }
- if i != 16 {
- request.filter.flags |= nwmFilterLclAddrMask
- for i = 0; i < 16; i++ {
- localSockFilter.Addr[i] = localSockaddr.Addr[i]
- }
- }
- if localSockaddr.Port != 0 {
- request.filter.flags |= nwmFilterLclPortMask
- localSockFilter.Port = localSockaddr.Port
- }
- }
- svcCall(EZBNMIF4, &argv[0], &dsa[0])
- // outputDesc field is filled by EZBNMIF4 on success
- if returnCode != 0 || request.header.outputDesc.offset == 0 {
- return nil, errnoErr(EINVAL)
- }
- // Check that EZBNMIF4 returned a nwmConnEntry
- conn := (*nwmConnEntry)(unsafe.Pointer(&responseBuffer[request.header.outputDesc.offset]))
- if conn.ident != nwmTCPConnIdentifier {
- return nil, errnoErr(EINVAL)
- }
- // Copy data from the returned data structures into tcpInfo
- // Stats from nwmConnEntry are specific to that connection.
- // Stats from nwmTCPStatsEntry are global (to the interface?)
- // Fields may not be an exact match. Some fields have no equivalent.
- var tcpinfo TCPInfo
- tcpinfo.State = uint8(conn.state)
- tcpinfo.Ca_state = 0 // dummy
- tcpinfo.Retransmits = uint8(tcpStats.retransSegs)
- tcpinfo.Probes = uint8(tcpStats.outWinProbes)
- tcpinfo.Backoff = 0 // dummy
- tcpinfo.Options = 0 // dummy
- tcpinfo.Rto = tcpStats.retransTimeouts
- tcpinfo.Ato = tcpStats.outDelayAcks
- tcpinfo.Snd_mss = conn.sendMSS
- tcpinfo.Rcv_mss = conn.sendMSS // dummy
- tcpinfo.Unacked = 0 // dummy
- tcpinfo.Sacked = 0 // dummy
- tcpinfo.Lost = 0 // dummy
- tcpinfo.Retrans = conn.reXmtCount
- tcpinfo.Fackets = 0 // dummy
- tcpinfo.Last_data_sent = uint32(*(*uint64)(unsafe.Pointer(&conn.lastActivity[0])))
- tcpinfo.Last_ack_sent = uint32(*(*uint64)(unsafe.Pointer(&conn.outOldestTime[0])))
- tcpinfo.Last_data_recv = uint32(*(*uint64)(unsafe.Pointer(&conn.inOldestTime[0])))
- tcpinfo.Last_ack_recv = uint32(*(*uint64)(unsafe.Pointer(&conn.inOldestTime[0])))
- tcpinfo.Pmtu = conn.sendMSS // dummy, NWMIfRouteMtu is a candidate
- tcpinfo.Rcv_ssthresh = conn.ssThresh
- tcpinfo.Rtt = conn.roundTripTime
- tcpinfo.Rttvar = conn.roundTripVar
- tcpinfo.Snd_ssthresh = conn.ssThresh // dummy
- tcpinfo.Snd_cwnd = conn.congestionWnd
- tcpinfo.Advmss = conn.sendMSS // dummy
- tcpinfo.Reordering = 0 // dummy
- tcpinfo.Rcv_rtt = conn.roundTripTime // dummy
- tcpinfo.Rcv_space = conn.sendMSS // dummy
- tcpinfo.Total_retrans = conn.reXmtCount
- svcUnload(&svcNameTable[svc_EZBNMIF4][0], EZBNMIF4)
- return &tcpinfo, nil
- }
- // GetsockoptString returns the string value of the socket option opt for the
- // socket associated with fd at the given socket level.
- func GetsockoptString(fd, level, opt int) (string, error) {
- buf := make([]byte, 256)
- vallen := _Socklen(len(buf))
- err := getsockopt(fd, level, opt, unsafe.Pointer(&buf[0]), &vallen)
- if err != nil {
- return "", err
- }
- return string(buf[:vallen-1]), nil
- }
- func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) {
- var msg Msghdr
- var rsa RawSockaddrAny
- msg.Name = (*byte)(unsafe.Pointer(&rsa))
- msg.Namelen = SizeofSockaddrAny
- var iov Iovec
- if len(p) > 0 {
- iov.Base = (*byte)(unsafe.Pointer(&p[0]))
- iov.SetLen(len(p))
- }
- var dummy byte
- if len(oob) > 0 {
- // receive at least one normal byte
- if len(p) == 0 {
- iov.Base = &dummy
- iov.SetLen(1)
- }
- msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
- msg.SetControllen(len(oob))
- }
- msg.Iov = &iov
- msg.Iovlen = 1
- if n, err = recvmsg(fd, &msg, flags); err != nil {
- return
- }
- oobn = int(msg.Controllen)
- recvflags = int(msg.Flags)
- // source address is only specified if the socket is unconnected
- if rsa.Addr.Family != AF_UNSPEC {
- // TODO(neeilan): Remove 0 arg added to get this compiling on z/OS
- from, err = anyToSockaddr(0, &rsa)
- }
- return
- }
- func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) {
- _, err = SendmsgN(fd, p, oob, to, flags)
- return
- }
- func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) {
- var ptr unsafe.Pointer
- var salen _Socklen
- if to != nil {
- var err error
- ptr, salen, err = to.sockaddr()
- if err != nil {
- return 0, err
- }
- }
- var msg Msghdr
- msg.Name = (*byte)(unsafe.Pointer(ptr))
- msg.Namelen = int32(salen)
- var iov Iovec
- if len(p) > 0 {
- iov.Base = (*byte)(unsafe.Pointer(&p[0]))
- iov.SetLen(len(p))
- }
- var dummy byte
- if len(oob) > 0 {
- // send at least one normal byte
- if len(p) == 0 {
- iov.Base = &dummy
- iov.SetLen(1)
- }
- msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
- msg.SetControllen(len(oob))
- }
- msg.Iov = &iov
- msg.Iovlen = 1
- if n, err = sendmsg(fd, &msg, flags); err != nil {
- return 0, err
- }
- if len(oob) > 0 && len(p) == 0 {
- n = 0
- }
- return n, nil
- }
- func Opendir(name string) (uintptr, error) {
- p, err := BytePtrFromString(name)
- if err != nil {
- return 0, err
- }
- dir, _, e := syscall_syscall(SYS___OPENDIR_A, uintptr(unsafe.Pointer(p)), 0, 0)
- runtime.KeepAlive(unsafe.Pointer(p))
- if e != 0 {
- err = errnoErr(e)
- }
- return dir, err
- }
- // clearsyscall.Errno resets the errno value to 0.
- func clearErrno()
- func Readdir(dir uintptr) (*Dirent, error) {
- var ent Dirent
- var res uintptr
- // __readdir_r_a returns errno at the end of the directory stream, rather than 0.
- // Therefore to avoid false positives we clear errno before calling it.
- // TODO(neeilan): Commented this out to get sys/unix compiling on z/OS. Uncomment and fix. Error: "undefined: clearsyscall"
- //clearsyscall.Errno() // TODO(mundaym): check pre-emption rules.
- e, _, _ := syscall_syscall(SYS___READDIR_R_A, dir, uintptr(unsafe.Pointer(&ent)), uintptr(unsafe.Pointer(&res)))
- var err error
- if e != 0 {
- err = errnoErr(Errno(e))
- }
- if res == 0 {
- return nil, err
- }
- return &ent, err
- }
- func Closedir(dir uintptr) error {
- _, _, e := syscall_syscall(SYS_CLOSEDIR, dir, 0, 0)
- if e != 0 {
- return errnoErr(e)
- }
- return nil
- }
- func Seekdir(dir uintptr, pos int) {
- _, _, _ = syscall_syscall(SYS_SEEKDIR, dir, uintptr(pos), 0)
- }
- func Telldir(dir uintptr) (int, error) {
- p, _, e := syscall_syscall(SYS_TELLDIR, dir, 0, 0)
- pos := int(p)
- if pos == -1 {
- return pos, errnoErr(e)
- }
- return pos, nil
- }
- // FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command.
- func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error {
- // struct flock is packed on z/OS. We can't emulate that in Go so
- // instead we pack it here.
- var flock [24]byte
- *(*int16)(unsafe.Pointer(&flock[0])) = lk.Type
- *(*int16)(unsafe.Pointer(&flock[2])) = lk.Whence
- *(*int64)(unsafe.Pointer(&flock[4])) = lk.Start
- *(*int64)(unsafe.Pointer(&flock[12])) = lk.Len
- *(*int32)(unsafe.Pointer(&flock[20])) = lk.Pid
- _, _, errno := syscall_syscall(SYS_FCNTL, fd, uintptr(cmd), uintptr(unsafe.Pointer(&flock)))
- lk.Type = *(*int16)(unsafe.Pointer(&flock[0]))
- lk.Whence = *(*int16)(unsafe.Pointer(&flock[2]))
- lk.Start = *(*int64)(unsafe.Pointer(&flock[4]))
- lk.Len = *(*int64)(unsafe.Pointer(&flock[12]))
- lk.Pid = *(*int32)(unsafe.Pointer(&flock[20]))
- if errno == 0 {
- return nil
- }
- return errno
- }
- func Flock(fd int, how int) error {
- var flock_type int16
- var fcntl_cmd int
- switch how {
- case LOCK_SH | LOCK_NB:
- flock_type = F_RDLCK
- fcntl_cmd = F_SETLK
- case LOCK_EX | LOCK_NB:
- flock_type = F_WRLCK
- fcntl_cmd = F_SETLK
- case LOCK_EX:
- flock_type = F_WRLCK
- fcntl_cmd = F_SETLKW
- case LOCK_UN:
- flock_type = F_UNLCK
- fcntl_cmd = F_SETLKW
- default:
- }
- flock := Flock_t{
- Type: int16(flock_type),
- Whence: int16(0),
- Start: int64(0),
- Len: int64(0),
- Pid: int32(Getppid()),
- }
- err := FcntlFlock(uintptr(fd), fcntl_cmd, &flock)
- return err
- }
- func Mlock(b []byte) (err error) {
- _, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_NONSWAP, 0, 0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
- }
- func Mlock2(b []byte, flags int) (err error) {
- _, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_NONSWAP, 0, 0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
- }
- func Mlockall(flags int) (err error) {
- _, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_NONSWAP, 0, 0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
- }
- func Munlock(b []byte) (err error) {
- _, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_SWAP, 0, 0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
- }
- func Munlockall() (err error) {
- _, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_SWAP, 0, 0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
- }
- func ClockGettime(clockid int32, ts *Timespec) error {
- var ticks_per_sec uint32 = 100 //TODO(kenan): value is currently hardcoded; need sysconf() call otherwise
- var nsec_per_sec int64 = 1000000000
- if ts == nil {
- return EFAULT
- }
- if clockid == CLOCK_REALTIME || clockid == CLOCK_MONOTONIC {
- var nanotime int64 = runtime.Nanotime1()
- ts.Sec = nanotime / nsec_per_sec
- ts.Nsec = nanotime % nsec_per_sec
- } else if clockid == CLOCK_PROCESS_CPUTIME_ID || clockid == CLOCK_THREAD_CPUTIME_ID {
- var tm Tms
- _, err := Times(&tm)
- if err != nil {
- return EFAULT
- }
- ts.Sec = int64(tm.Utime / ticks_per_sec)
- ts.Nsec = int64(tm.Utime) * nsec_per_sec / int64(ticks_per_sec)
- } else {
- return EINVAL
- }
- return nil
- }
- func Statfs(path string, stat *Statfs_t) (err error) {
- fd, err := open(path, O_RDONLY, 0)
- defer Close(fd)
- if err != nil {
- return err
- }
- return Fstatfs(fd, stat)
- }
- var (
- Stdin = 0
- Stdout = 1
- Stderr = 2
- )
- // Do the interface allocations only once for common
- // Errno values.
- var (
- errEAGAIN error = syscall.EAGAIN
- errEINVAL error = syscall.EINVAL
- errENOENT error = syscall.ENOENT
- )
- var (
- signalNameMapOnce sync.Once
- signalNameMap map[string]syscall.Signal
- )
- // errnoErr returns common boxed Errno values, to prevent
- // allocations at runtime.
- func errnoErr(e Errno) error {
- switch e {
- case 0:
- return nil
- case EAGAIN:
- return errEAGAIN
- case EINVAL:
- return errEINVAL
- case ENOENT:
- return errENOENT
- }
- return e
- }
- // ErrnoName returns the error name for error number e.
- func ErrnoName(e Errno) string {
- i := sort.Search(len(errorList), func(i int) bool {
- return errorList[i].num >= e
- })
- if i < len(errorList) && errorList[i].num == e {
- return errorList[i].name
- }
- return ""
- }
- // SignalName returns the signal name for signal number s.
- func SignalName(s syscall.Signal) string {
- i := sort.Search(len(signalList), func(i int) bool {
- return signalList[i].num >= s
- })
- if i < len(signalList) && signalList[i].num == s {
- return signalList[i].name
- }
- return ""
- }
- // SignalNum returns the syscall.Signal for signal named s,
- // or 0 if a signal with such name is not found.
- // The signal name should start with "SIG".
- func SignalNum(s string) syscall.Signal {
- signalNameMapOnce.Do(func() {
- signalNameMap = make(map[string]syscall.Signal, len(signalList))
- for _, signal := range signalList {
- signalNameMap[signal.name] = signal.num
- }
- })
- return signalNameMap[s]
- }
- // clen returns the index of the first NULL byte in n or len(n) if n contains no NULL byte.
- func clen(n []byte) int {
- i := bytes.IndexByte(n, 0)
- if i == -1 {
- i = len(n)
- }
- return i
- }
- // Mmap manager, for use by operating system-specific implementations.
- type mmapper struct {
- sync.Mutex
- active map[*byte][]byte // active mappings; key is last byte in mapping
- mmap func(addr, length uintptr, prot, flags, fd int, offset int64) (uintptr, error)
- munmap func(addr uintptr, length uintptr) error
- }
- func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
- if length <= 0 {
- return nil, EINVAL
- }
- // Map the requested memory.
- addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset)
- if errno != nil {
- return nil, errno
- }
- // Slice memory layout
- var sl = struct {
- addr uintptr
- len int
- cap int
- }{addr, length, length}
- // Use unsafe to turn sl into a []byte.
- b := *(*[]byte)(unsafe.Pointer(&sl))
- // Register mapping in m and return it.
- p := &b[cap(b)-1]
- m.Lock()
- defer m.Unlock()
- m.active[p] = b
- return b, nil
- }
- func (m *mmapper) Munmap(data []byte) (err error) {
- if len(data) == 0 || len(data) != cap(data) {
- return EINVAL
- }
- // Find the base of the mapping.
- p := &data[cap(data)-1]
- m.Lock()
- defer m.Unlock()
- b := m.active[p]
- if b == nil || &b[0] != &data[0] {
- return EINVAL
- }
- // Unmap the memory and update m.
- if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != nil {
- return errno
- }
- delete(m.active, p)
- return nil
- }
- func Read(fd int, p []byte) (n int, err error) {
- n, err = read(fd, p)
- if raceenabled {
- if n > 0 {
- raceWriteRange(unsafe.Pointer(&p[0]), n)
- }
- if err == nil {
- raceAcquire(unsafe.Pointer(&ioSync))
- }
- }
- return
- }
- func Write(fd int, p []byte) (n int, err error) {
- if raceenabled {
- raceReleaseMerge(unsafe.Pointer(&ioSync))
- }
- n, err = write(fd, p)
- if raceenabled && n > 0 {
- raceReadRange(unsafe.Pointer(&p[0]), n)
- }
- return
- }
- // For testing: clients can set this flag to force
- // creation of IPv6 sockets to return EAFNOSUPPORT.
- var SocketDisableIPv6 bool
- // Sockaddr represents a socket address.
- type Sockaddr interface {
- sockaddr() (ptr unsafe.Pointer, len _Socklen, err error) // lowercase; only we can define Sockaddrs
- }
- // SockaddrInet4 implements the Sockaddr interface for AF_INET type sockets.
- type SockaddrInet4 struct {
- Port int
- Addr [4]byte
- raw RawSockaddrInet4
- }
- // SockaddrInet6 implements the Sockaddr interface for AF_INET6 type sockets.
- type SockaddrInet6 struct {
- Port int
- ZoneId uint32
- Addr [16]byte
- raw RawSockaddrInet6
- }
- // SockaddrUnix implements the Sockaddr interface for AF_UNIX type sockets.
- type SockaddrUnix struct {
- Name string
- raw RawSockaddrUnix
- }
- func Bind(fd int, sa Sockaddr) (err error) {
- ptr, n, err := sa.sockaddr()
- if err != nil {
- return err
- }
- return bind(fd, ptr, n)
- }
- func Connect(fd int, sa Sockaddr) (err error) {
- ptr, n, err := sa.sockaddr()
- if err != nil {
- return err
- }
- return connect(fd, ptr, n)
- }
- func Getpeername(fd int) (sa Sockaddr, err error) {
- var rsa RawSockaddrAny
- var len _Socklen = SizeofSockaddrAny
- if err = getpeername(fd, &rsa, &len); err != nil {
- return
- }
- return anyToSockaddr(fd, &rsa)
- }
- func GetsockoptByte(fd, level, opt int) (value byte, err error) {
- var n byte
- vallen := _Socklen(1)
- err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)
- return n, err
- }
- func GetsockoptInt(fd, level, opt int) (value int, err error) {
- var n int32
- vallen := _Socklen(4)
- err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)
- return int(n), err
- }
- func GetsockoptInet4Addr(fd, level, opt int) (value [4]byte, err error) {
- vallen := _Socklen(4)
- err = getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen)
- return value, err
- }
- func GetsockoptIPMreq(fd, level, opt int) (*IPMreq, error) {
- var value IPMreq
- vallen := _Socklen(SizeofIPMreq)
- err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
- return &value, err
- }
- func GetsockoptIPv6Mreq(fd, level, opt int) (*IPv6Mreq, error) {
- var value IPv6Mreq
- vallen := _Socklen(SizeofIPv6Mreq)
- err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
- return &value, err
- }
- func GetsockoptIPv6MTUInfo(fd, level, opt int) (*IPv6MTUInfo, error) {
- var value IPv6MTUInfo
- vallen := _Socklen(SizeofIPv6MTUInfo)
- err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
- return &value, err
- }
- func GetsockoptICMPv6Filter(fd, level, opt int) (*ICMPv6Filter, error) {
- var value ICMPv6Filter
- vallen := _Socklen(SizeofICMPv6Filter)
- err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
- return &value, err
- }
- func GetsockoptLinger(fd, level, opt int) (*Linger, error) {
- var linger Linger
- vallen := _Socklen(SizeofLinger)
- err := getsockopt(fd, level, opt, unsafe.Pointer(&linger), &vallen)
- return &linger, err
- }
- func GetsockoptTimeval(fd, level, opt int) (*Timeval, error) {
- var tv Timeval
- vallen := _Socklen(unsafe.Sizeof(tv))
- err := getsockopt(fd, level, opt, unsafe.Pointer(&tv), &vallen)
- return &tv, err
- }
- func GetsockoptUint64(fd, level, opt int) (value uint64, err error) {
- var n uint64
- vallen := _Socklen(8)
- err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen)
- return n, err
- }
- func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) {
- var rsa RawSockaddrAny
- var len _Socklen = SizeofSockaddrAny
- if n, err = recvfrom(fd, p, flags, &rsa, &len); err != nil {
- return
- }
- if rsa.Addr.Family != AF_UNSPEC {
- from, err = anyToSockaddr(fd, &rsa)
- }
- return
- }
- func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) {
- ptr, n, err := to.sockaddr()
- if err != nil {
- return err
- }
- return sendto(fd, p, flags, ptr, n)
- }
- func SetsockoptByte(fd, level, opt int, value byte) (err error) {
- return setsockopt(fd, level, opt, unsafe.Pointer(&value), 1)
- }
- func SetsockoptInt(fd, level, opt int, value int) (err error) {
- var n = int32(value)
- return setsockopt(fd, level, opt, unsafe.Pointer(&n), 4)
- }
- func SetsockoptInet4Addr(fd, level, opt int, value [4]byte) (err error) {
- return setsockopt(fd, level, opt, unsafe.Pointer(&value[0]), 4)
- }
- func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (err error) {
- return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPMreq)
- }
- func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (err error) {
- return setsockopt(fd, level, opt, unsafe.Pointer(mreq), SizeofIPv6Mreq)
- }
- func SetsockoptICMPv6Filter(fd, level, opt int, filter *ICMPv6Filter) error {
- return setsockopt(fd, level, opt, unsafe.Pointer(filter), SizeofICMPv6Filter)
- }
- func SetsockoptLinger(fd, level, opt int, l *Linger) (err error) {
- return setsockopt(fd, level, opt, unsafe.Pointer(l), SizeofLinger)
- }
- func SetsockoptString(fd, level, opt int, s string) (err error) {
- var p unsafe.Pointer
- if len(s) > 0 {
- p = unsafe.Pointer(&[]byte(s)[0])
- }
- return setsockopt(fd, level, opt, p, uintptr(len(s)))
- }
- func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (err error) {
- return setsockopt(fd, level, opt, unsafe.Pointer(tv), unsafe.Sizeof(*tv))
- }
- func SetsockoptUint64(fd, level, opt int, value uint64) (err error) {
- return setsockopt(fd, level, opt, unsafe.Pointer(&value), 8)
- }
- func Socket(domain, typ, proto int) (fd int, err error) {
- if domain == AF_INET6 && SocketDisableIPv6 {
- return -1, EAFNOSUPPORT
- }
- fd, err = socket(domain, typ, proto)
- return
- }
- func Socketpair(domain, typ, proto int) (fd [2]int, err error) {
- var fdx [2]int32
- err = socketpair(domain, typ, proto, &fdx)
- if err == nil {
- fd[0] = int(fdx[0])
- fd[1] = int(fdx[1])
- }
- return
- }
- var ioSync int64
- func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) }
- func SetNonblock(fd int, nonblocking bool) (err error) {
- flag, err := fcntl(fd, F_GETFL, 0)
- if err != nil {
- return err
- }
- if nonblocking {
- flag |= O_NONBLOCK
- } else {
- flag &= ^O_NONBLOCK
- }
- _, err = fcntl(fd, F_SETFL, flag)
- return err
- }
- // Exec calls execve(2), which replaces the calling executable in the process
- // tree. argv0 should be the full path to an executable ("/bin/ls") and the
- // executable name should also be the first argument in argv (["ls", "-l"]).
- // envv are the environment variables that should be passed to the new
- // process (["USER=go", "PWD=/tmp"]).
- func Exec(argv0 string, argv []string, envv []string) error {
- return syscall.Exec(argv0, argv, envv)
- }
- func Mount(source string, target string, fstype string, flags uintptr, data string) (err error) {
- if needspace := 8 - len(fstype); needspace <= 0 {
- fstype = fstype[:8]
- } else {
- fstype += " "[:needspace]
- }
- return mount_LE(target, source, fstype, uint32(flags), int32(len(data)), data)
- }
- func Unmount(name string, mtm int) (err error) {
- // mountpoint is always a full path and starts with a '/'
- // check if input string is not a mountpoint but a filesystem name
- if name[0] != '/' {
- return unmount(name, mtm)
- }
- // treat name as mountpoint
- b2s := func(arr []byte) string {
- nulli := bytes.IndexByte(arr, 0)
- if nulli == -1 {
- return string(arr)
- } else {
- return string(arr[:nulli])
- }
- }
- var buffer struct {
- header W_Mnth
- fsinfo [64]W_Mntent
- }
- fsCount, err := W_Getmntent_A((*byte)(unsafe.Pointer(&buffer)), int(unsafe.Sizeof(buffer)))
- if err != nil {
- return err
- }
- if fsCount == 0 {
- return EINVAL
- }
- for i := 0; i < fsCount; i++ {
- if b2s(buffer.fsinfo[i].Mountpoint[:]) == name {
- err = unmount(b2s(buffer.fsinfo[i].Fsname[:]), mtm)
- break
- }
- }
- return err
- }
|