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

View as plain text