...

Source file src/syscall/syscall_freebsd.go

     1	// Copyright 2009,2010 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	// FreeBSD system calls.
     6	// This file is compiled as ordinary Go code,
     7	// but it is also input to mksyscall,
     8	// which parses the //sys lines and generates system call stubs.
     9	// Note that sometimes we use a lowercase //sys name and wrap
    10	// it in our own nicer implementation, either here or in
    11	// syscall_bsd.go or syscall_unix.go.
    12	
    13	package syscall
    14	
    15	import (
    16		"sync"
    17		"unsafe"
    18	)
    19	
    20	const (
    21		_SYS_FSTAT_FREEBSD12         = 551 // { int fstat(int fd, _Out_ struct stat *sb); }
    22		_SYS_FSTATAT_FREEBSD12       = 552 // { int fstatat(int fd, _In_z_ char *path, _Out_ struct stat *buf, int flag); }
    23		_SYS_GETDIRENTRIES_FREEBSD12 = 554 // { ssize_t getdirentries(int fd, _Out_writes_bytes_(count) char *buf, size_t count, _Out_ off_t *basep); }
    24		_SYS_STATFS_FREEBSD12        = 555 // { int statfs(_In_z_ char *path, _Out_ struct statfs *buf); }
    25		_SYS_FSTATFS_FREEBSD12       = 556 // { int fstatfs(int fd, _Out_ struct statfs *buf); }
    26		_SYS_GETFSSTAT_FREEBSD12     = 557 // { int getfsstat(_Out_writes_bytes_opt_(bufsize) struct statfs *buf, long bufsize, int mode); }
    27		_SYS_MKNODAT_FREEBSD12       = 559 // { int mknodat(int fd, _In_z_ char *path, mode_t mode, dev_t dev); }
    28	)
    29	
    30	// See https://www.freebsd.org/doc/en_US.ISO8859-1/books/porters-handbook/versions.html.
    31	var (
    32		osreldateOnce sync.Once
    33		osreldate     uint32
    34	)
    35	
    36	// INO64_FIRST from /usr/src/lib/libc/sys/compat-ino64.h
    37	const _ino64First = 1200031
    38	
    39	func supportsABI(ver uint32) bool {
    40		osreldateOnce.Do(func() { osreldate, _ = SysctlUint32("kern.osreldate") })
    41		return osreldate >= ver
    42	}
    43	
    44	type SockaddrDatalink struct {
    45		Len    uint8
    46		Family uint8
    47		Index  uint16
    48		Type   uint8
    49		Nlen   uint8
    50		Alen   uint8
    51		Slen   uint8
    52		Data   [46]int8
    53		raw    RawSockaddrDatalink
    54	}
    55	
    56	// Translate "kern.hostname" to []_C_int{0,1,2,3}.
    57	func nametomib(name string) (mib []_C_int, err error) {
    58		const siz = unsafe.Sizeof(mib[0])
    59	
    60		// NOTE(rsc): It seems strange to set the buffer to have
    61		// size CTL_MAXNAME+2 but use only CTL_MAXNAME
    62		// as the size. I don't know why the +2 is here, but the
    63		// kernel uses +2 for its own implementation of this function.
    64		// I am scared that if we don't include the +2 here, the kernel
    65		// will silently write 2 words farther than we specify
    66		// and we'll get memory corruption.
    67		var buf [CTL_MAXNAME + 2]_C_int
    68		n := uintptr(CTL_MAXNAME) * siz
    69	
    70		p := (*byte)(unsafe.Pointer(&buf[0]))
    71		bytes, err := ByteSliceFromString(name)
    72		if err != nil {
    73			return nil, err
    74		}
    75	
    76		// Magic sysctl: "setting" 0.3 to a string name
    77		// lets you read back the array of integers form.
    78		if err = sysctl([]_C_int{0, 3}, p, &n, &bytes[0], uintptr(len(name))); err != nil {
    79			return nil, err
    80		}
    81		return buf[0 : n/siz], nil
    82	}
    83	
    84	func direntIno(buf []byte) (uint64, bool) {
    85		return readInt(buf, unsafe.Offsetof(Dirent{}.Fileno), unsafe.Sizeof(Dirent{}.Fileno))
    86	}
    87	
    88	func direntReclen(buf []byte) (uint64, bool) {
    89		return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
    90	}
    91	
    92	func direntNamlen(buf []byte) (uint64, bool) {
    93		return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
    94	}
    95	
    96	func Pipe(p []int) error {
    97		return Pipe2(p, 0)
    98	}
    99	
   100	//sysnb pipe2(p *[2]_C_int, flags int) (err error)
   101	
   102	func Pipe2(p []int, flags int) error {
   103		if len(p) != 2 {
   104			return EINVAL
   105		}
   106		var pp [2]_C_int
   107		err := pipe2(&pp, flags)
   108		p[0] = int(pp[0])
   109		p[1] = int(pp[1])
   110		return err
   111	}
   112	
   113	func GetsockoptIPMreqn(fd, level, opt int) (*IPMreqn, error) {
   114		var value IPMreqn
   115		vallen := _Socklen(SizeofIPMreqn)
   116		errno := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
   117		return &value, errno
   118	}
   119	
   120	func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) {
   121		return setsockopt(fd, level, opt, unsafe.Pointer(mreq), unsafe.Sizeof(*mreq))
   122	}
   123	
   124	func Accept4(fd, flags int) (nfd int, sa Sockaddr, err error) {
   125		var rsa RawSockaddrAny
   126		var len _Socklen = SizeofSockaddrAny
   127		nfd, err = accept4(fd, &rsa, &len, flags)
   128		if err != nil {
   129			return
   130		}
   131		if len > SizeofSockaddrAny {
   132			panic("RawSockaddrAny too small")
   133		}
   134		sa, err = anyToSockaddr(&rsa)
   135		if err != nil {
   136			Close(nfd)
   137			nfd = 0
   138		}
   139		return
   140	}
   141	
   142	func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
   143		var (
   144			_p0          unsafe.Pointer
   145			bufsize      uintptr
   146			oldBuf       []statfs_freebsd11_t
   147			needsConvert bool
   148		)
   149	
   150		if len(buf) > 0 {
   151			if supportsABI(_ino64First) {
   152				_p0 = unsafe.Pointer(&buf[0])
   153				bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
   154			} else {
   155				n := len(buf)
   156				oldBuf = make([]statfs_freebsd11_t, n)
   157				_p0 = unsafe.Pointer(&oldBuf[0])
   158				bufsize = unsafe.Sizeof(statfs_freebsd11_t{}) * uintptr(n)
   159				needsConvert = true
   160			}
   161		}
   162		var sysno uintptr = SYS_GETFSSTAT
   163		if supportsABI(_ino64First) {
   164			sysno = _SYS_GETFSSTAT_FREEBSD12
   165		}
   166		r0, _, e1 := Syscall(sysno, uintptr(_p0), bufsize, uintptr(flags))
   167		n = int(r0)
   168		if e1 != 0 {
   169			err = e1
   170		}
   171		if e1 == 0 && needsConvert {
   172			for i := range oldBuf {
   173				buf[i].convertFrom(&oldBuf[i])
   174			}
   175		}
   176		return
   177	}
   178	
   179	func setattrlistTimes(path string, times []Timespec) error {
   180		// used on Darwin for UtimesNano
   181		return ENOSYS
   182	}
   183	
   184	func Stat(path string, st *Stat_t) (err error) {
   185		var oldStat stat_freebsd11_t
   186		if supportsABI(_ino64First) {
   187			return fstatat_freebsd12(_AT_FDCWD, path, st, 0)
   188		}
   189		err = stat(path, &oldStat)
   190		if err != nil {
   191			return err
   192		}
   193	
   194		st.convertFrom(&oldStat)
   195		return nil
   196	}
   197	
   198	func Lstat(path string, st *Stat_t) (err error) {
   199		var oldStat stat_freebsd11_t
   200		if supportsABI(_ino64First) {
   201			return fstatat_freebsd12(_AT_FDCWD, path, st, _AT_SYMLINK_NOFOLLOW)
   202		}
   203		err = lstat(path, &oldStat)
   204		if err != nil {
   205			return err
   206		}
   207	
   208		st.convertFrom(&oldStat)
   209		return nil
   210	}
   211	
   212	func Fstat(fd int, st *Stat_t) (err error) {
   213		var oldStat stat_freebsd11_t
   214		if supportsABI(_ino64First) {
   215			return fstat_freebsd12(fd, st)
   216		}
   217		err = fstat(fd, &oldStat)
   218		if err != nil {
   219			return err
   220		}
   221	
   222		st.convertFrom(&oldStat)
   223		return nil
   224	}
   225	
   226	func Fstatat(fd int, path string, st *Stat_t, flags int) (err error) {
   227		var oldStat stat_freebsd11_t
   228		if supportsABI(_ino64First) {
   229			return fstatat_freebsd12(fd, path, st, flags)
   230		}
   231		err = fstatat(fd, path, &oldStat, flags)
   232		if err != nil {
   233			return err
   234		}
   235	
   236		st.convertFrom(&oldStat)
   237		return nil
   238	}
   239	
   240	func Statfs(path string, st *Statfs_t) (err error) {
   241		var oldStatfs statfs_freebsd11_t
   242		if supportsABI(_ino64First) {
   243			return statfs_freebsd12(path, st)
   244		}
   245		err = statfs(path, &oldStatfs)
   246		if err != nil {
   247			return err
   248		}
   249	
   250		st.convertFrom(&oldStatfs)
   251		return nil
   252	}
   253	
   254	func Fstatfs(fd int, st *Statfs_t) (err error) {
   255		var oldStatfs statfs_freebsd11_t
   256		if supportsABI(_ino64First) {
   257			return fstatfs_freebsd12(fd, st)
   258		}
   259		err = fstatfs(fd, &oldStatfs)
   260		if err != nil {
   261			return err
   262		}
   263	
   264		st.convertFrom(&oldStatfs)
   265		return nil
   266	}
   267	
   268	func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
   269		if supportsABI(_ino64First) {
   270			if basep == nil || unsafe.Sizeof(*basep) == 8 {
   271				return getdirentries_freebsd12(fd, buf, (*uint64)(unsafe.Pointer(basep)))
   272			}
   273			// The freebsd12 syscall needs a 64-bit base. On 32-bit machines
   274			// we can't just use the basep passed in. See #32498.
   275			var base uint64 = uint64(*basep)
   276			n, err = getdirentries_freebsd12(fd, buf, &base)
   277			*basep = uintptr(base)
   278			if base>>32 != 0 {
   279				// We can't stuff the base back into a uintptr, so any
   280				// future calls would be suspect. Generate an error.
   281				// EIO is allowed by getdirentries.
   282				err = EIO
   283			}
   284			return
   285		}
   286	
   287		// The old syscall entries are smaller than the new. Use 1/4 of the original
   288		// buffer size rounded up to DIRBLKSIZ (see /usr/src/lib/libc/sys/getdirentries.c).
   289		oldBufLen := roundup(len(buf)/4, _dirblksiz)
   290		oldBuf := make([]byte, oldBufLen)
   291		n, err = getdirentries(fd, oldBuf, basep)
   292		if err == nil && n > 0 {
   293			n = convertFromDirents11(buf, oldBuf[:n])
   294		}
   295		return
   296	}
   297	
   298	func Mknod(path string, mode uint32, dev uint64) (err error) {
   299		var oldDev int
   300		if supportsABI(_ino64First) {
   301			return mknodat_freebsd12(_AT_FDCWD, path, mode, dev)
   302		}
   303		oldDev = int(dev)
   304		return mknod(path, mode, oldDev)
   305	}
   306	
   307	// round x to the nearest multiple of y, larger or equal to x.
   308	//
   309	// from /usr/include/sys/param.h Macros for counting and rounding.
   310	// #define roundup(x, y)   ((((x)+((y)-1))/(y))*(y))
   311	func roundup(x, y int) int {
   312		return ((x + y - 1) / y) * y
   313	}
   314	
   315	func (s *Stat_t) convertFrom(old *stat_freebsd11_t) {
   316		*s = Stat_t{
   317			Dev:           uint64(old.Dev),
   318			Ino:           uint64(old.Ino),
   319			Nlink:         uint64(old.Nlink),
   320			Mode:          old.Mode,
   321			Uid:           old.Uid,
   322			Gid:           old.Gid,
   323			Rdev:          uint64(old.Rdev),
   324			Atimespec:     old.Atimespec,
   325			Mtimespec:     old.Mtimespec,
   326			Ctimespec:     old.Ctimespec,
   327			Birthtimespec: old.Birthtimespec,
   328			Size:          old.Size,
   329			Blocks:        old.Blocks,
   330			Blksize:       old.Blksize,
   331			Flags:         old.Flags,
   332			Gen:           uint64(old.Gen),
   333		}
   334	}
   335	
   336	func (s *Statfs_t) convertFrom(old *statfs_freebsd11_t) {
   337		*s = Statfs_t{
   338			Version:     _statfsVersion,
   339			Type:        old.Type,
   340			Flags:       old.Flags,
   341			Bsize:       old.Bsize,
   342			Iosize:      old.Iosize,
   343			Blocks:      old.Blocks,
   344			Bfree:       old.Bfree,
   345			Bavail:      old.Bavail,
   346			Files:       old.Files,
   347			Ffree:       old.Ffree,
   348			Syncwrites:  old.Syncwrites,
   349			Asyncwrites: old.Asyncwrites,
   350			Syncreads:   old.Syncreads,
   351			Asyncreads:  old.Asyncreads,
   352			// Spare
   353			Namemax: old.Namemax,
   354			Owner:   old.Owner,
   355			Fsid:    old.Fsid,
   356			// Charspare
   357			// Fstypename
   358			// Mntfromname
   359			// Mntonname
   360		}
   361	
   362		sl := old.Fstypename[:]
   363		n := clen(*(*[]byte)(unsafe.Pointer(&sl)))
   364		copy(s.Fstypename[:], old.Fstypename[:n])
   365	
   366		sl = old.Mntfromname[:]
   367		n = clen(*(*[]byte)(unsafe.Pointer(&sl)))
   368		copy(s.Mntfromname[:], old.Mntfromname[:n])
   369	
   370		sl = old.Mntonname[:]
   371		n = clen(*(*[]byte)(unsafe.Pointer(&sl)))
   372		copy(s.Mntonname[:], old.Mntonname[:n])
   373	}
   374	
   375	func convertFromDirents11(buf []byte, old []byte) int {
   376		const (
   377			fixedSize    = int(unsafe.Offsetof(Dirent{}.Name))
   378			oldFixedSize = int(unsafe.Offsetof(dirent_freebsd11{}.Name))
   379		)
   380	
   381		dstPos := 0
   382		srcPos := 0
   383		for dstPos+fixedSize < len(buf) && srcPos+oldFixedSize < len(old) {
   384			dstDirent := (*Dirent)(unsafe.Pointer(&buf[dstPos]))
   385			srcDirent := (*dirent_freebsd11)(unsafe.Pointer(&old[srcPos]))
   386	
   387			reclen := roundup(fixedSize+int(srcDirent.Namlen)+1, 8)
   388			if dstPos+reclen > len(buf) {
   389				break
   390			}
   391	
   392			dstDirent.Fileno = uint64(srcDirent.Fileno)
   393			dstDirent.Off = 0
   394			dstDirent.Reclen = uint16(reclen)
   395			dstDirent.Type = srcDirent.Type
   396			dstDirent.Pad0 = 0
   397			dstDirent.Namlen = uint16(srcDirent.Namlen)
   398			dstDirent.Pad1 = 0
   399	
   400			copy(dstDirent.Name[:], srcDirent.Name[:srcDirent.Namlen])
   401			padding := buf[dstPos+fixedSize+int(dstDirent.Namlen) : dstPos+reclen]
   402			for i := range padding {
   403				padding[i] = 0
   404			}
   405	
   406			dstPos += int(dstDirent.Reclen)
   407			srcPos += int(srcDirent.Reclen)
   408		}
   409	
   410		return dstPos
   411	}
   412	
   413	/*
   414	 * Exposed directly
   415	 */
   416	//sys	Access(path string, mode uint32) (err error)
   417	//sys	Adjtime(delta *Timeval, olddelta *Timeval) (err error)
   418	//sys	Chdir(path string) (err error)
   419	//sys	Chflags(path string, flags int) (err error)
   420	//sys	Chmod(path string, mode uint32) (err error)
   421	//sys	Chown(path string, uid int, gid int) (err error)
   422	//sys	Chroot(path string) (err error)
   423	//sys	Close(fd int) (err error)
   424	//sys	Dup(fd int) (nfd int, err error)
   425	//sys	Dup2(from int, to int) (err error)
   426	//sys	Fchdir(fd int) (err error)
   427	//sys	Fchflags(fd int, flags int) (err error)
   428	//sys	Fchmod(fd int, mode uint32) (err error)
   429	//sys	Fchown(fd int, uid int, gid int) (err error)
   430	//sys	Flock(fd int, how int) (err error)
   431	//sys	Fpathconf(fd int, name int) (val int, err error)
   432	//sys	fstat(fd int, stat *stat_freebsd11_t) (err error)
   433	//sys	fstat_freebsd12(fd int, stat *Stat_t) (err error) = _SYS_FSTAT_FREEBSD12
   434	//sys	fstatat(fd int, path string, stat *stat_freebsd11_t, flags int) (err error)
   435	//sys	fstatat_freebsd12(fd int, path string, stat *Stat_t, flags int) (err error) = _SYS_FSTATAT_FREEBSD12
   436	//sys	fstatfs(fd int, stat *statfs_freebsd11_t) (err error)
   437	//sys	fstatfs_freebsd12(fd int, stat *Statfs_t) (err error) = _SYS_FSTATFS_FREEBSD12
   438	//sys	Fsync(fd int) (err error)
   439	//sys	Ftruncate(fd int, length int64) (err error)
   440	//sys	getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error)
   441	//sys	getdirentries_freebsd12(fd int, buf []byte, basep *uint64) (n int, err error) = _SYS_GETDIRENTRIES_FREEBSD12
   442	//sys	Getdtablesize() (size int)
   443	//sysnb	Getegid() (egid int)
   444	//sysnb	Geteuid() (uid int)
   445	//sysnb	Getgid() (gid int)
   446	//sysnb	Getpgid(pid int) (pgid int, err error)
   447	//sysnb	Getpgrp() (pgrp int)
   448	//sysnb	Getpid() (pid int)
   449	//sysnb	Getppid() (ppid int)
   450	//sys	Getpriority(which int, who int) (prio int, err error)
   451	//sysnb	Getrlimit(which int, lim *Rlimit) (err error)
   452	//sysnb	Getrusage(who int, rusage *Rusage) (err error)
   453	//sysnb	Getsid(pid int) (sid int, err error)
   454	//sysnb	Gettimeofday(tv *Timeval) (err error)
   455	//sysnb	Getuid() (uid int)
   456	//sys	Issetugid() (tainted bool)
   457	//sys	Kill(pid int, signum Signal) (err error)
   458	//sys	Kqueue() (fd int, err error)
   459	//sys	Lchown(path string, uid int, gid int) (err error)
   460	//sys	Link(path string, link string) (err error)
   461	//sys	Listen(s int, backlog int) (err error)
   462	//sys	lstat(path string, stat *stat_freebsd11_t) (err error)
   463	//sys	Mkdir(path string, mode uint32) (err error)
   464	//sys	Mkfifo(path string, mode uint32) (err error)
   465	//sys	mknod(path string, mode uint32, dev int) (err error)
   466	//sys	mknodat_freebsd12(fd int, path string, mode uint32, dev uint64) (err error) = _SYS_MKNODAT_FREEBSD12
   467	//sys	Nanosleep(time *Timespec, leftover *Timespec) (err error)
   468	//sys	Open(path string, mode int, perm uint32) (fd int, err error)
   469	//sys	Pathconf(path string, name int) (val int, err error)
   470	//sys	Pread(fd int, p []byte, offset int64) (n int, err error)
   471	//sys	Pwrite(fd int, p []byte, offset int64) (n int, err error)
   472	//sys	read(fd int, p []byte) (n int, err error)
   473	//sys	Readlink(path string, buf []byte) (n int, err error)
   474	//sys	Rename(from string, to string) (err error)
   475	//sys	Revoke(path string) (err error)
   476	//sys	Rmdir(path string) (err error)
   477	//sys	Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK
   478	//sys	Select(n int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (err error)
   479	//sysnb	Setegid(egid int) (err error)
   480	//sysnb	Seteuid(euid int) (err error)
   481	//sysnb	Setgid(gid int) (err error)
   482	//sys	Setlogin(name string) (err error)
   483	//sysnb	Setpgid(pid int, pgid int) (err error)
   484	//sys	Setpriority(which int, who int, prio int) (err error)
   485	//sysnb	Setregid(rgid int, egid int) (err error)
   486	//sysnb	Setreuid(ruid int, euid int) (err error)
   487	//sysnb	Setrlimit(which int, lim *Rlimit) (err error)
   488	//sysnb	Setsid() (pid int, err error)
   489	//sysnb	Settimeofday(tp *Timeval) (err error)
   490	//sysnb	Setuid(uid int) (err error)
   491	//sys	stat(path string, stat *stat_freebsd11_t) (err error)
   492	//sys	statfs(path string, stat *statfs_freebsd11_t) (err error)
   493	//sys	statfs_freebsd12(path string, stat *Statfs_t) (err error) = _SYS_STATFS_FREEBSD12
   494	//sys	Symlink(path string, link string) (err error)
   495	//sys	Sync() (err error)
   496	//sys	Truncate(path string, length int64) (err error)
   497	//sys	Umask(newmask int) (oldmask int)
   498	//sys	Undelete(path string) (err error)
   499	//sys	Unlink(path string) (err error)
   500	//sys	Unmount(path string, flags int) (err error)
   501	//sys	write(fd int, p []byte) (n int, err error)
   502	//sys   mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
   503	//sys   munmap(addr uintptr, length uintptr) (err error)
   504	//sys	readlen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_READ
   505	//sys	writelen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_WRITE
   506	//sys	accept4(fd int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (nfd int, err error)
   507	//sys	utimensat(dirfd int, path string, times *[2]Timespec, flag int) (err error)
   508	//sys	getcwd(buf []byte) (n int, err error) = SYS___GETCWD
   509	//sys	sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL
   510	

View as plain text