11 // syscall_bsd.go or syscall_unix.go. |
11 // syscall_bsd.go or syscall_unix.go. |
12 |
12 |
13 package unix |
13 package unix |
14 |
14 |
15 import ( |
15 import ( |
16 "errors" |
16 "fmt" |
|
17 "runtime" |
17 "syscall" |
18 "syscall" |
18 "unsafe" |
19 "unsafe" |
19 ) |
20 ) |
20 |
|
21 const ImplementsGetwd = true |
|
22 |
|
23 func Getwd() (string, error) { |
|
24 buf := make([]byte, 2048) |
|
25 attrs, err := getAttrList(".", attrList{CommonAttr: attrCmnFullpath}, buf, 0) |
|
26 if err == nil && len(attrs) == 1 && len(attrs[0]) >= 2 { |
|
27 wd := string(attrs[0]) |
|
28 // Sanity check that it's an absolute path and ends |
|
29 // in a null byte, which we then strip. |
|
30 if wd[0] == '/' && wd[len(wd)-1] == 0 { |
|
31 return wd[:len(wd)-1], nil |
|
32 } |
|
33 } |
|
34 // If pkg/os/getwd.go gets ENOTSUP, it will fall back to the |
|
35 // slow algorithm. |
|
36 return "", ENOTSUP |
|
37 } |
|
38 |
21 |
39 // SockaddrDatalink implements the Sockaddr interface for AF_LINK type sockets. |
22 // SockaddrDatalink implements the Sockaddr interface for AF_LINK type sockets. |
40 type SockaddrDatalink struct { |
23 type SockaddrDatalink struct { |
41 Len uint8 |
24 Len uint8 |
42 Family uint8 |
25 Family uint8 |
47 Slen uint8 |
30 Slen uint8 |
48 Data [12]int8 |
31 Data [12]int8 |
49 raw RawSockaddrDatalink |
32 raw RawSockaddrDatalink |
50 } |
33 } |
51 |
34 |
|
35 // SockaddrCtl implements the Sockaddr interface for AF_SYSTEM type sockets. |
|
36 type SockaddrCtl struct { |
|
37 ID uint32 |
|
38 Unit uint32 |
|
39 raw RawSockaddrCtl |
|
40 } |
|
41 |
|
42 func (sa *SockaddrCtl) sockaddr() (unsafe.Pointer, _Socklen, error) { |
|
43 sa.raw.Sc_len = SizeofSockaddrCtl |
|
44 sa.raw.Sc_family = AF_SYSTEM |
|
45 sa.raw.Ss_sysaddr = AF_SYS_CONTROL |
|
46 sa.raw.Sc_id = sa.ID |
|
47 sa.raw.Sc_unit = sa.Unit |
|
48 return unsafe.Pointer(&sa.raw), SizeofSockaddrCtl, nil |
|
49 } |
|
50 |
|
51 func anyToSockaddrGOOS(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { |
|
52 switch rsa.Addr.Family { |
|
53 case AF_SYSTEM: |
|
54 pp := (*RawSockaddrCtl)(unsafe.Pointer(rsa)) |
|
55 if pp.Ss_sysaddr == AF_SYS_CONTROL { |
|
56 sa := new(SockaddrCtl) |
|
57 sa.ID = pp.Sc_id |
|
58 sa.Unit = pp.Sc_unit |
|
59 return sa, nil |
|
60 } |
|
61 } |
|
62 return nil, EAFNOSUPPORT |
|
63 } |
|
64 |
|
65 // Some external packages rely on SYS___SYSCTL being defined to implement their |
|
66 // own sysctl wrappers. Provide it here, even though direct syscalls are no |
|
67 // longer supported on darwin. |
|
68 const SYS___SYSCTL = SYS_SYSCTL |
|
69 |
52 // Translate "kern.hostname" to []_C_int{0,1,2,3}. |
70 // Translate "kern.hostname" to []_C_int{0,1,2,3}. |
53 func nametomib(name string) (mib []_C_int, err error) { |
71 func nametomib(name string) (mib []_C_int, err error) { |
54 const siz = unsafe.Sizeof(mib[0]) |
72 const siz = unsafe.Sizeof(mib[0]) |
55 |
73 |
56 // NOTE(rsc): It seems strange to set the buffer to have |
74 // NOTE(rsc): It seems strange to set the buffer to have |
90 } |
108 } |
91 |
109 |
92 func PtraceAttach(pid int) (err error) { return ptrace(PT_ATTACH, pid, 0, 0) } |
110 func PtraceAttach(pid int) (err error) { return ptrace(PT_ATTACH, pid, 0, 0) } |
93 func PtraceDetach(pid int) (err error) { return ptrace(PT_DETACH, pid, 0, 0) } |
111 func PtraceDetach(pid int) (err error) { return ptrace(PT_DETACH, pid, 0, 0) } |
94 |
112 |
95 const ( |
|
96 attrBitMapCount = 5 |
|
97 attrCmnFullpath = 0x08000000 |
|
98 ) |
|
99 |
|
100 type attrList struct { |
113 type attrList struct { |
101 bitmapCount uint16 |
114 bitmapCount uint16 |
102 _ uint16 |
115 _ uint16 |
103 CommonAttr uint32 |
116 CommonAttr uint32 |
104 VolAttr uint32 |
117 VolAttr uint32 |
105 DirAttr uint32 |
118 DirAttr uint32 |
106 FileAttr uint32 |
119 FileAttr uint32 |
107 Forkattr uint32 |
120 Forkattr uint32 |
108 } |
121 } |
109 |
122 |
110 func getAttrList(path string, attrList attrList, attrBuf []byte, options uint) (attrs [][]byte, err error) { |
123 //sysnb pipe(p *[2]int32) (err error) |
111 if len(attrBuf) < 4 { |
|
112 return nil, errors.New("attrBuf too small") |
|
113 } |
|
114 attrList.bitmapCount = attrBitMapCount |
|
115 |
|
116 var _p0 *byte |
|
117 _p0, err = BytePtrFromString(path) |
|
118 if err != nil { |
|
119 return nil, err |
|
120 } |
|
121 |
|
122 if err := getattrlist(_p0, unsafe.Pointer(&attrList), unsafe.Pointer(&attrBuf[0]), uintptr(len(attrBuf)), int(options)); err != nil { |
|
123 return nil, err |
|
124 } |
|
125 size := *(*uint32)(unsafe.Pointer(&attrBuf[0])) |
|
126 |
|
127 // dat is the section of attrBuf that contains valid data, |
|
128 // without the 4 byte length header. All attribute offsets |
|
129 // are relative to dat. |
|
130 dat := attrBuf |
|
131 if int(size) < len(attrBuf) { |
|
132 dat = dat[:size] |
|
133 } |
|
134 dat = dat[4:] // remove length prefix |
|
135 |
|
136 for i := uint32(0); int(i) < len(dat); { |
|
137 header := dat[i:] |
|
138 if len(header) < 8 { |
|
139 return attrs, errors.New("truncated attribute header") |
|
140 } |
|
141 datOff := *(*int32)(unsafe.Pointer(&header[0])) |
|
142 attrLen := *(*uint32)(unsafe.Pointer(&header[4])) |
|
143 if datOff < 0 || uint32(datOff)+attrLen > uint32(len(dat)) { |
|
144 return attrs, errors.New("truncated results; attrBuf too small") |
|
145 } |
|
146 end := uint32(datOff) + attrLen |
|
147 attrs = append(attrs, dat[datOff:end]) |
|
148 i = end |
|
149 if r := i % 4; r != 0 { |
|
150 i += (4 - r) |
|
151 } |
|
152 } |
|
153 return |
|
154 } |
|
155 |
|
156 //sys getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) |
|
157 |
|
158 //sysnb pipe() (r int, w int, err error) |
|
159 |
124 |
160 func Pipe(p []int) (err error) { |
125 func Pipe(p []int) (err error) { |
161 if len(p) != 2 { |
126 if len(p) != 2 { |
162 return EINVAL |
127 return EINVAL |
163 } |
128 } |
164 p[0], p[1], err = pipe() |
129 var x [2]int32 |
|
130 err = pipe(&x) |
|
131 p[0] = int(x[0]) |
|
132 p[1] = int(x[1]) |
165 return |
133 return |
166 } |
134 } |
167 |
135 |
168 func Getfsstat(buf []Statfs_t, flags int) (n int, err error) { |
136 func Getfsstat(buf []Statfs_t, flags int) (n int, err error) { |
169 var _p0 unsafe.Pointer |
137 var _p0 unsafe.Pointer |
303 unsafe.Pointer(&attributes), |
271 unsafe.Pointer(&attributes), |
304 unsafe.Sizeof(attributes), |
272 unsafe.Sizeof(attributes), |
305 options) |
273 options) |
306 } |
274 } |
307 |
275 |
308 //sys setattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) |
276 //sys setattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) |
309 |
277 |
310 func utimensat(dirfd int, path string, times *[2]Timespec, flags int) error { |
278 func utimensat(dirfd int, path string, times *[2]Timespec, flags int) error { |
311 // Darwin doesn't support SYS_UTIMENSAT |
279 // Darwin doesn't support SYS_UTIMENSAT |
312 return ENOSYS |
280 return ENOSYS |
313 } |
281 } |
322 |
290 |
323 func Kill(pid int, signum syscall.Signal) (err error) { return kill(pid, int(signum), 1) } |
291 func Kill(pid int, signum syscall.Signal) (err error) { return kill(pid, int(signum), 1) } |
324 |
292 |
325 //sys ioctl(fd int, req uint, arg uintptr) (err error) |
293 //sys ioctl(fd int, req uint, arg uintptr) (err error) |
326 |
294 |
327 //sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS_SYSCTL |
295 func IoctlCtlInfo(fd int, ctlInfo *CtlInfo) error { |
|
296 err := ioctl(fd, CTLIOCGINFO, uintptr(unsafe.Pointer(ctlInfo))) |
|
297 runtime.KeepAlive(ctlInfo) |
|
298 return err |
|
299 } |
|
300 |
|
301 // IfreqMTU is struct ifreq used to get or set a network device's MTU. |
|
302 type IfreqMTU struct { |
|
303 Name [IFNAMSIZ]byte |
|
304 MTU int32 |
|
305 } |
|
306 |
|
307 // IoctlGetIfreqMTU performs the SIOCGIFMTU ioctl operation on fd to get the MTU |
|
308 // of the network device specified by ifname. |
|
309 func IoctlGetIfreqMTU(fd int, ifname string) (*IfreqMTU, error) { |
|
310 var ifreq IfreqMTU |
|
311 copy(ifreq.Name[:], ifname) |
|
312 err := ioctl(fd, SIOCGIFMTU, uintptr(unsafe.Pointer(&ifreq))) |
|
313 return &ifreq, err |
|
314 } |
|
315 |
|
316 // IoctlSetIfreqMTU performs the SIOCSIFMTU ioctl operation on fd to set the MTU |
|
317 // of the network device specified by ifreq.Name. |
|
318 func IoctlSetIfreqMTU(fd int, ifreq *IfreqMTU) error { |
|
319 err := ioctl(fd, SIOCSIFMTU, uintptr(unsafe.Pointer(ifreq))) |
|
320 runtime.KeepAlive(ifreq) |
|
321 return err |
|
322 } |
|
323 |
|
324 //sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS_SYSCTL |
328 |
325 |
329 func Uname(uname *Utsname) error { |
326 func Uname(uname *Utsname) error { |
330 mib := []_C_int{CTL_KERN, KERN_OSTYPE} |
327 mib := []_C_int{CTL_KERN, KERN_OSTYPE} |
331 n := unsafe.Sizeof(uname.Sysname) |
328 n := unsafe.Sizeof(uname.Sysname) |
332 if err := sysctl(mib, &uname.Sysname[0], &n, nil, 0); err != nil { |
329 if err := sysctl(mib, &uname.Sysname[0], &n, nil, 0); err != nil { |
378 } |
375 } |
379 var length = int64(count) |
376 var length = int64(count) |
380 err = sendfile(infd, outfd, *offset, &length, nil, 0) |
377 err = sendfile(infd, outfd, *offset, &length, nil, 0) |
381 written = int(length) |
378 written = int(length) |
382 return |
379 return |
|
380 } |
|
381 |
|
382 func GetsockoptIPMreqn(fd, level, opt int) (*IPMreqn, error) { |
|
383 var value IPMreqn |
|
384 vallen := _Socklen(SizeofIPMreqn) |
|
385 errno := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) |
|
386 return &value, errno |
|
387 } |
|
388 |
|
389 func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) { |
|
390 return setsockopt(fd, level, opt, unsafe.Pointer(mreq), unsafe.Sizeof(*mreq)) |
|
391 } |
|
392 |
|
393 // GetsockoptXucred is a getsockopt wrapper that returns an Xucred struct. |
|
394 // The usual level and opt are SOL_LOCAL and LOCAL_PEERCRED, respectively. |
|
395 func GetsockoptXucred(fd, level, opt int) (*Xucred, error) { |
|
396 x := new(Xucred) |
|
397 vallen := _Socklen(SizeofXucred) |
|
398 err := getsockopt(fd, level, opt, unsafe.Pointer(x), &vallen) |
|
399 return x, err |
|
400 } |
|
401 |
|
402 func SysctlKinfoProcSlice(name string) ([]KinfoProc, error) { |
|
403 mib, err := sysctlmib(name) |
|
404 if err != nil { |
|
405 return nil, err |
|
406 } |
|
407 |
|
408 // Find size. |
|
409 n := uintptr(0) |
|
410 if err := sysctl(mib, nil, &n, nil, 0); err != nil { |
|
411 return nil, err |
|
412 } |
|
413 if n == 0 { |
|
414 return nil, nil |
|
415 } |
|
416 if n%SizeofKinfoProc != 0 { |
|
417 return nil, fmt.Errorf("sysctl() returned a size of %d, which is not a multiple of %d", n, SizeofKinfoProc) |
|
418 } |
|
419 |
|
420 // Read into buffer of that size. |
|
421 buf := make([]KinfoProc, n/SizeofKinfoProc) |
|
422 if err := sysctl(mib, (*byte)(unsafe.Pointer(&buf[0])), &n, nil, 0); err != nil { |
|
423 return nil, err |
|
424 } |
|
425 if n%SizeofKinfoProc != 0 { |
|
426 return nil, fmt.Errorf("sysctl() returned a size of %d, which is not a multiple of %d", n, SizeofKinfoProc) |
|
427 } |
|
428 |
|
429 // The actual call may return less than the original reported required |
|
430 // size so ensure we deal with that. |
|
431 return buf[:n/SizeofKinfoProc], nil |
383 } |
432 } |
384 |
433 |
385 //sys sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) |
434 //sys sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) |
386 |
435 |
387 /* |
436 /* |
394 //sys Chmod(path string, mode uint32) (err error) |
443 //sys Chmod(path string, mode uint32) (err error) |
395 //sys Chown(path string, uid int, gid int) (err error) |
444 //sys Chown(path string, uid int, gid int) (err error) |
396 //sys Chroot(path string) (err error) |
445 //sys Chroot(path string) (err error) |
397 //sys ClockGettime(clockid int32, time *Timespec) (err error) |
446 //sys ClockGettime(clockid int32, time *Timespec) (err error) |
398 //sys Close(fd int) (err error) |
447 //sys Close(fd int) (err error) |
|
448 //sys Clonefile(src string, dst string, flags int) (err error) |
|
449 //sys Clonefileat(srcDirfd int, src string, dstDirfd int, dst string, flags int) (err error) |
399 //sys Dup(fd int) (nfd int, err error) |
450 //sys Dup(fd int) (nfd int, err error) |
400 //sys Dup2(from int, to int) (err error) |
451 //sys Dup2(from int, to int) (err error) |
401 //sys Exchangedata(path1 string, path2 string, options int) (err error) |
452 //sys Exchangedata(path1 string, path2 string, options int) (err error) |
402 //sys Exit(code int) |
453 //sys Exit(code int) |
403 //sys Faccessat(dirfd int, path string, mode uint32, flags int) (err error) |
454 //sys Faccessat(dirfd int, path string, mode uint32, flags int) (err error) |
405 //sys Fchflags(fd int, flags int) (err error) |
456 //sys Fchflags(fd int, flags int) (err error) |
406 //sys Fchmod(fd int, mode uint32) (err error) |
457 //sys Fchmod(fd int, mode uint32) (err error) |
407 //sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) |
458 //sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) |
408 //sys Fchown(fd int, uid int, gid int) (err error) |
459 //sys Fchown(fd int, uid int, gid int) (err error) |
409 //sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) |
460 //sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) |
|
461 //sys Fclonefileat(srcDirfd int, dstDirfd int, dst string, flags int) (err error) |
410 //sys Flock(fd int, how int) (err error) |
462 //sys Flock(fd int, how int) (err error) |
411 //sys Fpathconf(fd int, name int) (val int, err error) |
463 //sys Fpathconf(fd int, name int) (val int, err error) |
412 //sys Fsync(fd int) (err error) |
464 //sys Fsync(fd int) (err error) |
413 //sys Ftruncate(fd int, length int64) (err error) |
465 //sys Ftruncate(fd int, length int64) (err error) |
|
466 //sys Getcwd(buf []byte) (n int, err error) |
414 //sys Getdtablesize() (size int) |
467 //sys Getdtablesize() (size int) |
415 //sysnb Getegid() (egid int) |
468 //sysnb Getegid() (egid int) |
416 //sysnb Geteuid() (uid int) |
469 //sysnb Geteuid() (uid int) |
417 //sysnb Getgid() (gid int) |
470 //sysnb Getgid() (gid int) |
418 //sysnb Getpgid(pid int) (pgid int, err error) |
471 //sysnb Getpgid(pid int) (pgid int, err error) |
421 //sysnb Getppid() (ppid int) |
474 //sysnb Getppid() (ppid int) |
422 //sys Getpriority(which int, who int) (prio int, err error) |
475 //sys Getpriority(which int, who int) (prio int, err error) |
423 //sysnb Getrlimit(which int, lim *Rlimit) (err error) |
476 //sysnb Getrlimit(which int, lim *Rlimit) (err error) |
424 //sysnb Getrusage(who int, rusage *Rusage) (err error) |
477 //sysnb Getrusage(who int, rusage *Rusage) (err error) |
425 //sysnb Getsid(pid int) (sid int, err error) |
478 //sysnb Getsid(pid int) (sid int, err error) |
|
479 //sysnb Gettimeofday(tp *Timeval) (err error) |
426 //sysnb Getuid() (uid int) |
480 //sysnb Getuid() (uid int) |
427 //sysnb Issetugid() (tainted bool) |
481 //sysnb Issetugid() (tainted bool) |
428 //sys Kqueue() (fd int, err error) |
482 //sys Kqueue() (fd int, err error) |
429 //sys Lchown(path string, uid int, gid int) (err error) |
483 //sys Lchown(path string, uid int, gid int) (err error) |
430 //sys Link(path string, link string) (err error) |
484 //sys Link(path string, link string) (err error) |
469 //sys Undelete(path string) (err error) |
523 //sys Undelete(path string) (err error) |
470 //sys Unlink(path string) (err error) |
524 //sys Unlink(path string) (err error) |
471 //sys Unlinkat(dirfd int, path string, flags int) (err error) |
525 //sys Unlinkat(dirfd int, path string, flags int) (err error) |
472 //sys Unmount(path string, flags int) (err error) |
526 //sys Unmount(path string, flags int) (err error) |
473 //sys write(fd int, p []byte) (n int, err error) |
527 //sys write(fd int, p []byte) (n int, err error) |
474 //sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) |
528 //sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) |
475 //sys munmap(addr uintptr, length uintptr) (err error) |
529 //sys munmap(addr uintptr, length uintptr) (err error) |
476 //sys readlen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_READ |
530 //sys readlen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_READ |
477 //sys writelen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_WRITE |
531 //sys writelen(fd int, buf *byte, nbuf int) (n int, err error) = SYS_WRITE |
478 |
532 |
479 /* |
533 /* |
480 * Unimplemented |
534 * Unimplemented |