ir) path, err := ZosFdToPath(fd) if err != nil { return 0, err } d, err := Opendir(path) if err != nil { return 0, err } defer Closedir(d) var cnt int64 for { var entryLE direntLE var entrypLE *direntLE e := Readdir_r(d, &entryLE, &entrypLE) if e != nil { return n, e } if entrypLE == nil { break } if skip > 0 { skip-- cnt++ continue } // Dirent on zos has a different structure entry, e := direntLeToDirentUnix(&entryLE, d, path) if e != nil { return n, e } reclen := int(entry.Reclen) if reclen > len(buf) { // Not enough room. Return for now. // The counter will let us know where we should start up again. // Note: this strategy for suspending in the middle and // restarting is O(n^2) in the length of the directory. Oh well. break } // Copy entry into return buffer. s := unsafe.Slice((*byte)(unsafe.Pointer(&entry)), reclen) copy(buf, s) buf = buf[reclen:] n += reclen cnt++ } // Set the seek offset of the input fd to record // how many files we've already returned. _, err = Seek(fd, cnt, 0 /* SEEK_SET */) if err != nil { return n, err } return n, nil } func Err2ad() (eadd *int) { r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS___ERR2AD<<4) eadd = (*int)(unsafe.Pointer(r0)) return } func ZosConsolePrintf(format string, v ...interface{}) (int, error) { type __cmsg struct { _ uint16 _ [2]uint8 __msg_length uint32 __msg uintptr _ [4]uint8 } msg := fmt.Sprintf(format, v...) strptr := unsafe.Pointer((*reflect.StringHeader)(unsafe.Pointer(&msg)).Data) len := (*reflect.StringHeader)(unsafe.Pointer(&msg)).Len cmsg := __cmsg{__msg_length: uint32(len), __msg: uintptr(strptr)} cmd := uint32(0) runtime.EnterSyscall() rc, err2, err1 := CallLeFuncWithErr(GetZosLibVec()+SYS_____CONSOLE_A<<4, uintptr(unsafe.Pointer(&cmsg)), 0, uintptr(unsafe.Pointer(&cmd))) runtime.ExitSyscall() if rc != 0 { return 0, fmt.Errorf("%s (errno2=0x%x)\n", err1.Error(), err2) } return 0, nil } func ZosStringToEbcdicBytes(str string, nullterm bool) (ebcdicBytes []byte) { if nullterm { ebcdicBytes = []byte(str + "\x00") } else { ebcdicBytes = []byte(str) } A2e(ebcdicBytes) return } func ZosEbcdicBytesToString(b []byte, trimRight bool) (str string) { res := make([]byte, len(b)) copy(res, b) E2a(res) if trimRight { str = string(bytes.TrimRight(res, " \x00")) } else { str = string(res) } return } func fdToPath(dirfd int) (path string, err error) { var buffer [1024]byte // w_ctrl() ret := runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS_W_IOCTL<<4, []uintptr{uintptr(dirfd), 17, 1024, uintptr(unsafe.Pointer(&buffer[0]))}) if ret == 0 { zb := bytes.IndexByte(buffer[:], 0) if zb == -1 { zb = len(buffer) } // __e2a_l() runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___E2A_L<<4, []uintptr{uintptr(unsafe.Pointer(&buffer[0])), uintptr(zb)}) return string(buffer[:zb]), nil } // __errno() errno := int(*(*int32)(unsafe.Pointer(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO<<4, []uintptr{})))) // __errno2() errno2 := int(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO2<<4, []uintptr{})) // strerror_r() ret = runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS_STRERROR_R<<4, []uintptr{uintptr(errno), uintptr(unsafe.Pointer(&buffer[0])), 1024}) if ret == 0 { zb := bytes.IndexByte(buffer[:], 0) if zb == -1 { zb = len(buffer) } return "", fmt.Errorf("%s (errno2=0x%x)", buffer[:zb], errno2) } else { return "", fmt.Errorf("fdToPath errno %d (errno2=0x%x)", errno, errno2) } } func impl_Mkfifoat(dirfd int, path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { return } runtime.EnterSyscall() r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MKFIFOAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) runtime.ExitSyscall() if int64(r0) == -1 { err = errnoErr2(e1, e2) } return } //go:nosplit func get_MkfifoatAddr() *(func(dirfd int, path string, mode uint32) (err error)) var Mkfifoat = enter_Mkfifoat func enter_Mkfifoat(dirfd int, path string, mode uint32) (err error) { funcref := get_MkfifoatAddr() if funcptrtest(GetZosLibVec()+SYS___MKFIFOAT_A<<4, "") == 0 { *funcref = impl_Mkfifoat } else { *funcref = legacy_Mkfifoat } return (*funcref)(dirfd, path, mode) } func legacy_Mkfifoat(dirfd int, path string, mode uint32) (err error) { dirname, err := ZosFdToPath(dirfd) if err != nil { return err } return Mkfifo(dirname+"/"+path, mode) } //sys Posix_openpt(oflag int) (fd int, err error) = SYS_POSIX_OPENPT //sys Grantpt(fildes int) (rc int, err error) = SYS_GRANTPT //sys Unlockpt(fildes int) (rc int, err error) = SYS_UNLOCKPT func fcntlAsIs(fd uintptr, cmd int, arg uintptr) (val int, err error) { runtime.EnterSyscall() r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FCNTL<<4, uintptr(fd), uintptr(cmd), arg) runtime.ExitSyscall() val = int(r0) if int64(r0) == -1 { err = errnoErr2(e1, e2) } return } func Fcntl(fd uintptr, cmd int, op interface{}) (ret int, err error) { switch op.(type) { case *Flock_t: err = FcntlFlock(fd, cmd, op.(*Flock_t)) if err != nil { ret = -1 } return case int: return FcntlInt(fd, cmd, op.(int)) case *F_cnvrt: return fcntlAsIs(fd, cmd, uintptr(unsafe.Pointer(op.(*F_cnvrt)))) case unsafe.Pointer: return fcntlAsIs(fd, cmd, uintptr(op.(unsafe.Pointer))) default: return -1, EINVAL } return } func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { if raceenabled { raceReleaseMerge(unsafe.Pointer(&ioSync)) } return sendfile(outfd, infd, offset, count) } func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { // TODO: use LE call instead if the call is implemented originalOffset, err := Seek(infd, 0, SEEK_CUR) if err != nil { return -1, err } //start reading data from in_fd if offset != nil { _, err := Seek(infd, *offset, SEEK_SET) if err != nil { return -1, err } } buf := make([]byte, count) readBuf := make([]byte, 0) var n int = 0 for i := 0; i < count; i += n { n, err := Read(infd, buf) if n == 0 { if err != nil { return -1, err } else { // EOF break } } readBuf = append(readBuf, buf...) buf = buf[0:0] } n2, err := Write(outfd, readBuf) if err != nil { return -1, err } //When sendfile() returns, this variable will be set to the // offset of the byte following the last byte that was read. if offset != nil { *offset = *offset + int64(n) // If offset is not NULL, then sendfile() does not modify the file // offset of in_fd _, err := Seek(infd, originalOffset, SEEK_SET) if err != nil { return -1, err } } return n2, nil }