mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			110 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			110 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// +build darwin freebsd linux netbsd openbsd
 | 
						|
 | 
						|
package godirwalk
 | 
						|
 | 
						|
import (
 | 
						|
	"os"
 | 
						|
	"path/filepath"
 | 
						|
	"syscall"
 | 
						|
	"unsafe"
 | 
						|
 | 
						|
	"github.com/pkg/errors"
 | 
						|
)
 | 
						|
 | 
						|
func readdirents(osDirname string, scratchBuffer []byte) (Dirents, error) {
 | 
						|
	dh, err := os.Open(osDirname)
 | 
						|
	if err != nil {
 | 
						|
		return nil, errors.Wrap(err, "cannot Open")
 | 
						|
	}
 | 
						|
 | 
						|
	var entries Dirents
 | 
						|
 | 
						|
	fd := int(dh.Fd())
 | 
						|
 | 
						|
	if len(scratchBuffer) < MinimumScratchBufferSize {
 | 
						|
		scratchBuffer = make([]byte, DefaultScratchBufferSize)
 | 
						|
	}
 | 
						|
 | 
						|
	var de *syscall.Dirent
 | 
						|
 | 
						|
	for {
 | 
						|
		n, err := syscall.ReadDirent(fd, scratchBuffer)
 | 
						|
		if err != nil {
 | 
						|
			_ = dh.Close() // ignore potential error returned by Close
 | 
						|
			return nil, errors.Wrap(err, "cannot ReadDirent")
 | 
						|
		}
 | 
						|
		if n <= 0 {
 | 
						|
			break // end of directory reached
 | 
						|
		}
 | 
						|
		// Loop over the bytes returned by reading the directory entries.
 | 
						|
		buf := scratchBuffer[:n]
 | 
						|
		for len(buf) > 0 {
 | 
						|
			de = (*syscall.Dirent)(unsafe.Pointer(&buf[0])) // point entry to first syscall.Dirent in buffer
 | 
						|
			buf = buf[de.Reclen:]                           // advance buffer
 | 
						|
 | 
						|
			if inoFromDirent(de) == 0 {
 | 
						|
				continue // this item has been deleted, but not yet removed from directory
 | 
						|
			}
 | 
						|
 | 
						|
			nameSlice := nameFromDirent(de)
 | 
						|
			namlen := len(nameSlice)
 | 
						|
			if (namlen == 0) || (namlen == 1 && nameSlice[0] == '.') || (namlen == 2 && nameSlice[0] == '.' && nameSlice[1] == '.') {
 | 
						|
				continue // skip unimportant entries
 | 
						|
			}
 | 
						|
			osChildname := string(nameSlice)
 | 
						|
 | 
						|
			// Convert syscall constant, which is in purview of OS, to a
 | 
						|
			// constant defined by Go, assumed by this project to be stable.
 | 
						|
			var mode os.FileMode
 | 
						|
			switch de.Type {
 | 
						|
			case syscall.DT_REG:
 | 
						|
				// regular file
 | 
						|
			case syscall.DT_DIR:
 | 
						|
				mode = os.ModeDir
 | 
						|
			case syscall.DT_LNK:
 | 
						|
				mode = os.ModeSymlink
 | 
						|
			case syscall.DT_CHR:
 | 
						|
				mode = os.ModeDevice | os.ModeCharDevice
 | 
						|
			case syscall.DT_BLK:
 | 
						|
				mode = os.ModeDevice
 | 
						|
			case syscall.DT_FIFO:
 | 
						|
				mode = os.ModeNamedPipe
 | 
						|
			case syscall.DT_SOCK:
 | 
						|
				mode = os.ModeSocket
 | 
						|
			default:
 | 
						|
				// If syscall returned unknown type (e.g., DT_UNKNOWN, DT_WHT),
 | 
						|
				// then resolve actual mode by getting stat.
 | 
						|
				fi, err := os.Lstat(filepath.Join(osDirname, osChildname))
 | 
						|
				if err != nil {
 | 
						|
					_ = dh.Close() // ignore potential error returned by Close
 | 
						|
					return nil, errors.Wrap(err, "cannot Stat")
 | 
						|
				}
 | 
						|
				// We only care about the bits that identify the type of a file
 | 
						|
				// system node, and can ignore append, exclusive, temporary,
 | 
						|
				// setuid, setgid, permission bits, and sticky bits, which are
 | 
						|
				// coincident to the bits that declare type of the file system
 | 
						|
				// node.
 | 
						|
				mode = fi.Mode() & os.ModeType
 | 
						|
			}
 | 
						|
 | 
						|
			entries = append(entries, &Dirent{name: osChildname, modeType: mode})
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if err = dh.Close(); err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	return entries, nil
 | 
						|
}
 | 
						|
 | 
						|
func readdirnames(osDirname string, scratchBuffer []byte) ([]string, error) {
 | 
						|
	des, err := readdirents(osDirname, scratchBuffer)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	names := make([]string, len(des))
 | 
						|
	for i, v := range des {
 | 
						|
		names[i] = v.name
 | 
						|
	}
 | 
						|
	return names, nil
 | 
						|
}
 |