| // Copyright 2009,2010 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package syscall |
| |
| import "unsafe" |
| |
| func direntIno(buf []byte) (uint64, bool) { |
| return readInt(buf, unsafe.Offsetof(Dirent{}.Fileno), unsafe.Sizeof(Dirent{}.Fileno)) |
| } |
| |
| func direntReclen(buf []byte) (uint64, bool) { |
| return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen)) |
| } |
| |
| func direntNamlen(buf []byte) (uint64, bool) { |
| return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen)) |
| } |
| |
| //sys Getdents(fd int, buf []byte) (n int, err error) |
| //getdents(fd _C_int, buf *byte, nbytes uintptr) _C_int |
| |
| func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { |
| n, err = Getdents(fd, buf) |
| if err != nil || basep == nil { |
| return |
| } |
| |
| var off int64 |
| off, err = Seek(fd, 0, 1 /* SEEK_CUR */) |
| if err != nil { |
| *basep = ^uintptr(0) |
| return |
| } |
| *basep = uintptr(off) |
| if unsafe.Sizeof(*basep) == 8 { |
| return |
| } |
| if off>>32 != 0 { |
| // We can't stuff the offset back into a uintptr, so any |
| // future calls would be suspect. Generate an error. |
| // EIO is allowed by getdirentries. |
| err = EIO |
| } |
| return |
| } |
| |
| func sysctlNodes(mib []_C_int) (nodes []Sysctlnode, err error) { |
| var olen uintptr |
| |
| // Get a list of all sysctl nodes below the given MIB by performing |
| // a sysctl for the given MIB with CTL_QUERY appended. |
| mib = append(mib, CTL_QUERY) |
| qnode := Sysctlnode{Flags: SYSCTL_VERS_1} |
| qp := (*byte)(unsafe.Pointer(&qnode)) |
| sz := unsafe.Sizeof(qnode) |
| if err = sysctl(mib, nil, &olen, qp, sz); err != nil { |
| return nil, err |
| } |
| |
| // Now that we know the size, get the actual nodes. |
| nodes = make([]Sysctlnode, olen/sz) |
| np := (*byte)(unsafe.Pointer(&nodes[0])) |
| if err = sysctl(mib, np, &olen, qp, sz); err != nil { |
| return nil, err |
| } |
| |
| return nodes, nil |
| } |
| |
| func nametomib(name string) (mib []_C_int, err error) { |
| // Split name into components. |
| var parts []string |
| last := 0 |
| for i := 0; i < len(name); i++ { |
| if name[i] == '.' { |
| parts = append(parts, name[last:i]) |
| last = i + 1 |
| } |
| } |
| parts = append(parts, name[last:]) |
| |
| // Discover the nodes and construct the MIB OID. |
| for partno, part := range parts { |
| nodes, err := sysctlNodes(mib) |
| if err != nil { |
| return nil, err |
| } |
| for _, node := range nodes { |
| n := make([]byte, 0) |
| for i := range node.Name { |
| if node.Name[i] != 0 { |
| n = append(n, byte(node.Name[i])) |
| } |
| } |
| if string(n) == part { |
| mib = append(mib, _C_int(node.Num)) |
| break |
| } |
| } |
| if len(mib) != partno+1 { |
| return nil, EINVAL |
| } |
| } |
| |
| return mib, nil |
| } |