...

Source file src/syscall/dirent.go

     1	// Copyright 2009 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	// +build aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris
     6	
     7	package syscall
     8	
     9	import "unsafe"
    10	
    11	// readInt returns the size-bytes unsigned integer in native byte order at offset off.
    12	func readInt(b []byte, off, size uintptr) (u uint64, ok bool) {
    13		if len(b) < int(off+size) {
    14			return 0, false
    15		}
    16		if isBigEndian {
    17			return readIntBE(b[off:], size), true
    18		}
    19		return readIntLE(b[off:], size), true
    20	}
    21	
    22	func readIntBE(b []byte, size uintptr) uint64 {
    23		switch size {
    24		case 1:
    25			return uint64(b[0])
    26		case 2:
    27			_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
    28			return uint64(b[1]) | uint64(b[0])<<8
    29		case 4:
    30			_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
    31			return uint64(b[3]) | uint64(b[2])<<8 | uint64(b[1])<<16 | uint64(b[0])<<24
    32		case 8:
    33			_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
    34			return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
    35				uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
    36		default:
    37			panic("syscall: readInt with unsupported size")
    38		}
    39	}
    40	
    41	func readIntLE(b []byte, size uintptr) uint64 {
    42		switch size {
    43		case 1:
    44			return uint64(b[0])
    45		case 2:
    46			_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
    47			return uint64(b[0]) | uint64(b[1])<<8
    48		case 4:
    49			_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
    50			return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24
    51		case 8:
    52			_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
    53			return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
    54				uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
    55		default:
    56			panic("syscall: readInt with unsupported size")
    57		}
    58	}
    59	
    60	// ParseDirent parses up to max directory entries in buf,
    61	// appending the names to names. It returns the number of
    62	// bytes consumed from buf, the number of entries added
    63	// to names, and the new names slice.
    64	func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) {
    65		origlen := len(buf)
    66		count = 0
    67		for max != 0 && len(buf) > 0 {
    68			reclen, ok := direntReclen(buf)
    69			if !ok || reclen > uint64(len(buf)) {
    70				return origlen, count, names
    71			}
    72			rec := buf[:reclen]
    73			buf = buf[reclen:]
    74			ino, ok := direntIno(rec)
    75			if !ok {
    76				break
    77			}
    78			if ino == 0 { // File absent in directory.
    79				continue
    80			}
    81			const namoff = uint64(unsafe.Offsetof(Dirent{}.Name))
    82			namlen, ok := direntNamlen(rec)
    83			if !ok || namoff+namlen > uint64(len(rec)) {
    84				break
    85			}
    86			name := rec[namoff : namoff+namlen]
    87			for i, c := range name {
    88				if c == 0 {
    89					name = name[:i]
    90					break
    91				}
    92			}
    93			// Check for useless names before allocating a string.
    94			if string(name) == "." || string(name) == ".." {
    95				continue
    96			}
    97			max--
    98			count++
    99			names = append(names, string(name))
   100		}
   101		return origlen - len(buf), count, names
   102	}
   103	

View as plain text