| // Copyright 2009 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. |
| |
| //go:build unix || (js && wasm) || wasip1 |
| |
| package syscall |
| |
| import ( |
| "internal/byteorder" |
| "internal/goarch" |
| "runtime" |
| "unsafe" |
| ) |
| |
| // readInt returns the size-bytes unsigned integer in native byte order at offset off. |
| func readInt(b []byte, off, size uintptr) (u uint64, ok bool) { |
| if len(b) < int(off+size) { |
| return 0, false |
| } |
| if goarch.BigEndian { |
| return readIntBE(b[off:], size), true |
| } |
| return readIntLE(b[off:], size), true |
| } |
| |
| func readIntBE(b []byte, size uintptr) uint64 { |
| switch size { |
| case 1: |
| return uint64(b[0]) |
| case 2: |
| return uint64(byteorder.BEUint16(b)) |
| case 4: |
| return uint64(byteorder.BEUint32(b)) |
| case 8: |
| return uint64(byteorder.BEUint64(b)) |
| default: |
| panic("syscall: readInt with unsupported size") |
| } |
| } |
| |
| func readIntLE(b []byte, size uintptr) uint64 { |
| switch size { |
| case 1: |
| return uint64(b[0]) |
| case 2: |
| return uint64(byteorder.LEUint16(b)) |
| case 4: |
| return uint64(byteorder.LEUint32(b)) |
| case 8: |
| return uint64(byteorder.LEUint64(b)) |
| default: |
| panic("syscall: readInt with unsupported size") |
| } |
| } |
| |
| // ParseDirent parses up to max directory entries in buf, |
| // appending the names to names. It returns the number of |
| // bytes consumed from buf, the number of entries added |
| // to names, and the new names slice. |
| func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) { |
| origlen := len(buf) |
| count = 0 |
| for max != 0 && len(buf) > 0 { |
| reclen, ok := direntReclen(buf) |
| if !ok || reclen > uint64(len(buf)) { |
| return origlen, count, names |
| } |
| rec := buf[:reclen] |
| buf = buf[reclen:] |
| ino, ok := direntIno(rec) |
| if !ok { |
| break |
| } |
| // See src/os/dir_unix.go for the reason why this condition is |
| // excluded on wasip1. |
| if ino == 0 && runtime.GOOS != "wasip1" { // File absent in directory. |
| continue |
| } |
| const namoff = uint64(unsafe.Offsetof(Dirent{}.Name)) |
| namlen, ok := direntNamlen(rec) |
| if !ok || namoff+namlen > uint64(len(rec)) { |
| break |
| } |
| name := rec[namoff : namoff+namlen] |
| for i, c := range name { |
| if c == 0 { |
| name = name[:i] |
| break |
| } |
| } |
| // Check for useless names before allocating a string. |
| if string(name) == "." || string(name) == ".." { |
| continue |
| } |
| max-- |
| count++ |
| names = append(names, string(name)) |
| } |
| return origlen - len(buf), count, names |
| } |