...

Source file src/syscall/dirent.go

Documentation: syscall

		 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