vendor/golang.org/x/sys/unix/syscall_zos_s390x.go
changeset 265 05c40b36d3b2
parent 260 445e01aede7e
equal deleted inserted replaced
264:8f478162d991 265:05c40b36d3b2
     7 
     7 
     8 package unix
     8 package unix
     9 
     9 
    10 import (
    10 import (
    11 	"bytes"
    11 	"bytes"
       
    12 	"fmt"
    12 	"runtime"
    13 	"runtime"
    13 	"sort"
    14 	"sort"
       
    15 	"strings"
    14 	"sync"
    16 	"sync"
    15 	"syscall"
    17 	"syscall"
    16 	"unsafe"
    18 	"unsafe"
    17 )
    19 )
    18 
    20 
    53 
    55 
    54 func (d *Dirent) NameString() string {
    56 func (d *Dirent) NameString() string {
    55 	if d == nil {
    57 	if d == nil {
    56 		return ""
    58 		return ""
    57 	}
    59 	}
    58 	return string(d.Name[:d.Namlen])
    60 	s := string(d.Name[:])
       
    61 	idx := strings.IndexByte(s, 0)
       
    62 	if idx == -1 {
       
    63 		return s
       
    64 	} else {
       
    65 		return s[:idx]
       
    66 	}
    59 }
    67 }
    60 
    68 
    61 func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
    69 func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
    62 	if sa.Port < 0 || sa.Port > 0xFFFF {
    70 	if sa.Port < 0 || sa.Port > 0xFFFF {
    63 		return nil, 0, EINVAL
    71 		return nil, 0, EINVAL
  1228 		return nil, err
  1236 		return nil, err
  1229 	}
  1237 	}
  1230 	return &ent, err
  1238 	return &ent, err
  1231 }
  1239 }
  1232 
  1240 
       
  1241 func readdir_r(dirp uintptr, entry *direntLE, result **direntLE) (err error) {
       
  1242 	r0, _, e1 := syscall_syscall(SYS___READDIR_R_A, dirp, uintptr(unsafe.Pointer(entry)), uintptr(unsafe.Pointer(result)))
       
  1243 	if int64(r0) == -1 {
       
  1244 		err = errnoErr(Errno(e1))
       
  1245 	}
       
  1246 	return
       
  1247 }
       
  1248 
  1233 func Closedir(dir uintptr) error {
  1249 func Closedir(dir uintptr) error {
  1234 	_, _, e := syscall_syscall(SYS_CLOSEDIR, dir, 0, 0)
  1250 	_, _, e := syscall_syscall(SYS_CLOSEDIR, dir, 0, 0)
  1235 	if e != 0 {
  1251 	if e != 0 {
  1236 		return errnoErr(e)
  1252 		return errnoErr(e)
  1237 	}
  1253 	}
  1819 			break
  1835 			break
  1820 		}
  1836 		}
  1821 	}
  1837 	}
  1822 	return err
  1838 	return err
  1823 }
  1839 }
       
  1840 
       
  1841 func fdToPath(dirfd int) (path string, err error) {
       
  1842 	var buffer [1024]byte
       
  1843 	// w_ctrl()
       
  1844 	ret := runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS_W_IOCTL<<4,
       
  1845 		[]uintptr{uintptr(dirfd), 17, 1024, uintptr(unsafe.Pointer(&buffer[0]))})
       
  1846 	if ret == 0 {
       
  1847 		zb := bytes.IndexByte(buffer[:], 0)
       
  1848 		if zb == -1 {
       
  1849 			zb = len(buffer)
       
  1850 		}
       
  1851 		// __e2a_l()
       
  1852 		runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___E2A_L<<4,
       
  1853 			[]uintptr{uintptr(unsafe.Pointer(&buffer[0])), uintptr(zb)})
       
  1854 		return string(buffer[:zb]), nil
       
  1855 	}
       
  1856 	// __errno()
       
  1857 	errno := int(*(*int32)(unsafe.Pointer(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO<<4,
       
  1858 		[]uintptr{}))))
       
  1859 	// __errno2()
       
  1860 	errno2 := int(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO2<<4,
       
  1861 		[]uintptr{}))
       
  1862 	// strerror_r()
       
  1863 	ret = runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS_STRERROR_R<<4,
       
  1864 		[]uintptr{uintptr(errno), uintptr(unsafe.Pointer(&buffer[0])), 1024})
       
  1865 	if ret == 0 {
       
  1866 		zb := bytes.IndexByte(buffer[:], 0)
       
  1867 		if zb == -1 {
       
  1868 			zb = len(buffer)
       
  1869 		}
       
  1870 		return "", fmt.Errorf("%s (errno2=0x%x)", buffer[:zb], errno2)
       
  1871 	} else {
       
  1872 		return "", fmt.Errorf("fdToPath errno %d (errno2=0x%x)", errno, errno2)
       
  1873 	}
       
  1874 }
       
  1875 
       
  1876 func direntLeToDirentUnix(dirent *direntLE, dir uintptr, path string) (Dirent, error) {
       
  1877 	var d Dirent
       
  1878 
       
  1879 	d.Ino = uint64(dirent.Ino)
       
  1880 	offset, err := Telldir(dir)
       
  1881 	if err != nil {
       
  1882 		return d, err
       
  1883 	}
       
  1884 
       
  1885 	d.Off = int64(offset)
       
  1886 	s := string(bytes.Split(dirent.Name[:], []byte{0})[0])
       
  1887 	copy(d.Name[:], s)
       
  1888 
       
  1889 	d.Reclen = uint16(24 + len(d.NameString()))
       
  1890 	var st Stat_t
       
  1891 	path = path + "/" + s
       
  1892 	err = Lstat(path, &st)
       
  1893 	if err != nil {
       
  1894 		return d, err
       
  1895 	}
       
  1896 
       
  1897 	d.Type = uint8(st.Mode >> 24)
       
  1898 	return d, err
       
  1899 }
       
  1900 
       
  1901 func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
       
  1902 	// Simulation of Getdirentries port from the Darwin implementation.
       
  1903 	// COMMENTS FROM DARWIN:
       
  1904 	// It's not the full required semantics, but should handle the case
       
  1905 	// of calling Getdirentries or ReadDirent repeatedly.
       
  1906 	// It won't handle assigning the results of lseek to *basep, or handle
       
  1907 	// the directory being edited underfoot.
       
  1908 
       
  1909 	skip, err := Seek(fd, 0, 1 /* SEEK_CUR */)
       
  1910 	if err != nil {
       
  1911 		return 0, err
       
  1912 	}
       
  1913 
       
  1914 	// Get path from fd to avoid unavailable call (fdopendir)
       
  1915 	path, err := fdToPath(fd)
       
  1916 	if err != nil {
       
  1917 		return 0, err
       
  1918 	}
       
  1919 	d, err := Opendir(path)
       
  1920 	if err != nil {
       
  1921 		return 0, err
       
  1922 	}
       
  1923 	defer Closedir(d)
       
  1924 
       
  1925 	var cnt int64
       
  1926 	for {
       
  1927 		var entryLE direntLE
       
  1928 		var entrypLE *direntLE
       
  1929 		e := readdir_r(d, &entryLE, &entrypLE)
       
  1930 		if e != nil {
       
  1931 			return n, e
       
  1932 		}
       
  1933 		if entrypLE == nil {
       
  1934 			break
       
  1935 		}
       
  1936 		if skip > 0 {
       
  1937 			skip--
       
  1938 			cnt++
       
  1939 			continue
       
  1940 		}
       
  1941 
       
  1942 		// Dirent on zos has a different structure
       
  1943 		entry, e := direntLeToDirentUnix(&entryLE, d, path)
       
  1944 		if e != nil {
       
  1945 			return n, e
       
  1946 		}
       
  1947 
       
  1948 		reclen := int(entry.Reclen)
       
  1949 		if reclen > len(buf) {
       
  1950 			// Not enough room. Return for now.
       
  1951 			// The counter will let us know where we should start up again.
       
  1952 			// Note: this strategy for suspending in the middle and
       
  1953 			// restarting is O(n^2) in the length of the directory. Oh well.
       
  1954 			break
       
  1955 		}
       
  1956 
       
  1957 		// Copy entry into return buffer.
       
  1958 		s := unsafe.Slice((*byte)(unsafe.Pointer(&entry)), reclen)
       
  1959 		copy(buf, s)
       
  1960 
       
  1961 		buf = buf[reclen:]
       
  1962 		n += reclen
       
  1963 		cnt++
       
  1964 	}
       
  1965 	// Set the seek offset of the input fd to record
       
  1966 	// how many files we've already returned.
       
  1967 	_, err = Seek(fd, cnt, 0 /* SEEK_SET */)
       
  1968 	if err != nil {
       
  1969 		return n, err
       
  1970 	}
       
  1971 
       
  1972 	return n, nil
       
  1973 }
       
  1974 
       
  1975 func ReadDirent(fd int, buf []byte) (n int, err error) {
       
  1976 	var base = (*uintptr)(unsafe.Pointer(new(uint64)))
       
  1977 	return Getdirentries(fd, buf, base)
       
  1978 }
       
  1979 
       
  1980 func direntIno(buf []byte) (uint64, bool) {
       
  1981 	return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
       
  1982 }
       
  1983 
       
  1984 func direntReclen(buf []byte) (uint64, bool) {
       
  1985 	return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
       
  1986 }
       
  1987 
       
  1988 func direntNamlen(buf []byte) (uint64, bool) {
       
  1989 	reclen, ok := direntReclen(buf)
       
  1990 	if !ok {
       
  1991 		return 0, false
       
  1992 	}
       
  1993 	return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true
       
  1994 }