github.com/charlievieth/fastwalk@v1.0.3/internal/dirent/dirent.go (about)

     1  //go:build aix || dragonfly || freebsd || (js && wasm) || wasip1 || linux || netbsd || openbsd || solaris
     2  
     3  package dirent
     4  
     5  import (
     6  	"os"
     7  	"runtime"
     8  	"syscall"
     9  	"unsafe"
    10  )
    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  const InvalidMode = os.FileMode(1<<32 - 1)
    62  
    63  func Parse(buf []byte) (consumed int, name string, typ os.FileMode) {
    64  
    65  	reclen, ok := direntReclen(buf)
    66  	if !ok || reclen > uint64(len(buf)) {
    67  		// WARN: this is a hard error because we consumed 0 bytes
    68  		// and not stopping here could lead to an infinite loop.
    69  		return 0, "", InvalidMode
    70  	}
    71  	consumed = int(reclen)
    72  	rec := buf[:reclen]
    73  
    74  	ino, ok := direntIno(rec)
    75  	if !ok {
    76  		return consumed, "", InvalidMode
    77  	}
    78  	// When building to wasip1, the host runtime might be running on Windows
    79  	// or might expose a remote file system which does not have the concept
    80  	// of inodes. Therefore, we cannot make the assumption that it is safe
    81  	// to skip entries with zero inodes.
    82  	if ino == 0 && runtime.GOOS != "wasip1" {
    83  		return consumed, "", InvalidMode
    84  	}
    85  
    86  	typ = direntType(buf)
    87  
    88  	const namoff = uint64(unsafe.Offsetof(syscall.Dirent{}.Name))
    89  	namlen, ok := direntNamlen(rec)
    90  	if !ok || namoff+namlen > uint64(len(rec)) {
    91  		return consumed, "", InvalidMode
    92  	}
    93  	namebuf := rec[namoff : namoff+namlen]
    94  	for i, c := range namebuf {
    95  		if c == 0 {
    96  			namebuf = namebuf[:i]
    97  			break
    98  		}
    99  	}
   100  	// Check for useless names before allocating a string.
   101  	if string(namebuf) == "." {
   102  		name = "."
   103  	} else if string(namebuf) == ".." {
   104  		name = ".."
   105  	} else {
   106  		name = string(namebuf)
   107  	}
   108  	return consumed, name, typ
   109  }