Index: src/pkg/syscall/syscall_darwin.go |
=================================================================== |
--- a/src/pkg/syscall/syscall_darwin.go |
+++ b/src/pkg/syscall/syscall_darwin.go |
@@ -12,7 +12,28 @@ |
package syscall |
-import "unsafe" |
+import ( |
+ errorspkg "errors" |
+ "unsafe" |
+) |
+ |
+const ImplementsGetwd = true |
+ |
+func Getwd() (string, error) { |
+ buf := make([]byte, 2048) |
+ attrs, err := getAttrList(".", attrList{CommonAttr: attrCmnFullpath}, buf, 0) |
+ if err == nil && len(attrs) == 1 && len(attrs[0]) >= 2 { |
+ wd := string(attrs[0]) |
+ // Sanity check that it's an absolute path and ends |
+ // in a null byte, which we then strip. |
+ if wd[0] == '/' && wd[len(wd)-1] == 0 { |
+ return wd[:len(wd)-1], nil |
+ } |
+ } |
+ // If pkg/os/getwd.go gets ENOTSUP, it will fall back to the |
+ // slow algorithm. |
+ return "", ENOTSUP |
+} |
type SockaddrDatalink struct { |
Len uint8 |
@@ -86,6 +107,76 @@ |
func PtraceAttach(pid int) (err error) { return ptrace(PT_ATTACH, pid, 0, 0) } |
func PtraceDetach(pid int) (err error) { return ptrace(PT_DETACH, pid, 0, 0) } |
+const ( |
+ attrBitMapCount = 5 |
+ attrCmnFullpath = 0x08000000 |
+) |
+ |
+type attrList struct { |
+ bitmapCount uint16 |
+ _ uint16 |
+ CommonAttr uint32 |
+ VolAttr uint32 |
+ DirAttr uint32 |
+ FileAttr uint32 |
+ Forkattr uint32 |
+} |
+ |
+func getAttrList(path string, attrList attrList, attrBuf []byte, options uint) (attrs [][]byte, err error) { |
+ if len(attrBuf) < 4 { |
+ return nil, errorspkg.New("attrBuf too small") |
+ } |
+ attrList.bitmapCount = attrBitMapCount |
+ |
+ var _p0 *byte |
+ _p0, err = BytePtrFromString(path) |
+ if err != nil { |
+ return nil, err |
+ } |
+ |
+ _, _, e1 := Syscall6( |
+ SYS_GETATTRLIST, |
+ uintptr(unsafe.Pointer(_p0)), |
+ uintptr(unsafe.Pointer(&attrList)), |
+ uintptr(unsafe.Pointer(&attrBuf[0])), |
+ uintptr(len(attrBuf)), |
+ uintptr(options), |
+ 0, |
+ ) |
+ if e1 != 0 { |
+ return nil, e1 |
+ } |
+ size := *(*uint32)(unsafe.Pointer(&attrBuf[0])) |
+ |
+ // dat is the section of attrBuf that contains valid data, |
+ // without the 4 byte length header. All attribute offsets |
+ // are relative to dat. |
+ dat := attrBuf |
+ if int(size) < len(attrBuf) { |
+ dat = dat[:size] |
+ } |
+ dat = dat[4:] // remove length prefix |
+ |
+ for i := uint32(0); int(i) < len(dat); { |
+ header := dat[i:] |
+ if len(header) < 8 { |
+ return attrs, errorspkg.New("truncated attribute header") |
+ } |
+ datOff := *(*int32)(unsafe.Pointer(&header[0])) |
+ attrLen := *(*uint32)(unsafe.Pointer(&header[4])) |
+ if datOff < 0 || uint32(datOff)+attrLen > uint32(len(dat)) { |
+ return attrs, errorspkg.New("truncated results; attrBuf too small") |
+ } |
+ end := uint32(datOff) + attrLen |
+ attrs = append(attrs, dat[datOff:end]) |
+ i = end |
+ if r := i % 4; r != 0 { |
+ i += (4 - r) |
+ } |
+ } |
+ return |
+} |
+ |
//sysnb pipe() (r int, w int, err error) |
func Pipe(p []int) (err error) { |