예제 #1
0
// Read a buffer (dir) into the pointer to the DirentBuf, `db`
// Returns remaining buffer size and number of entries created
// It's a modified version of syscall.ParseDirent in Go's standard library
func ParseDir(buf []byte, max int64, db *[]syscall.Dirent) (int, int) {
	orig := len(buf)

	i := int64(0)
	for max != 0 && len(buf) > 0 {
		dirent := *(*syscall.Dirent)(unsafe.Pointer(&buf[0]))

		buf = buf[dirent.Reclen:]
		if dirent.Ino == 0 {
			continue
		}

		b := (*[257]byte)(unsafe.Pointer(&dirent.Name[0]))
		bn := string(b[0:general.Clen(b[:])])
		if bn == "." || bn == ".." {
			continue
		}

		if len(*db) <= int(i) {
			*db = append(*db, dirent)
		} else {
			(*db)[i] = dirent
		}

		max--
		i++
	}
	return orig - len(buf), int(i)
}
예제 #2
0
// recursively walk through the named directory `dir` until the correct device
// is found.
// Directories in []searchDevs are automatically skipped
func checkDirs(dir string) (string, error) {
	var (
		rs      string
		nameBuf = make([]byte, 256)
		dirBuf  = make([]syscall.Dirent, 256)
	)

	fi, err := os.Open(dir)
	if err != nil {
		return "", err
	}
	defer fi.Close()

	err = dirent.ReadDir(int(fi.Fd()), -1, &dirBuf)
	if err != nil && err != io.EOF {
		return "", err
	}

	for _, v := range dirBuf {
		// quickly skip most entries
		if v.Ino != Stat.Ino {
			continue
		}

		_ = copy(nameBuf, general.Int8ToByte(v.Name[:]))
		name := path.Join(dir, string(nameBuf[:general.Clen(nameBuf)]))

		// Directories to skip
		if name == "/dev/stderr" ||
			name == "/dev/stdin" ||
			name == "/dev/stdout" ||
			(len(name) >= 8 &&
				name[0:8] == "/dev/fd/") {
			continue
		}

		// We have to stat the file to determine its Rdev
		fstat := new(syscall.Stat_t)
		err = syscall.Stat(name, fstat)
		if err != nil {
			continue
		}

		// file mode sans permission bits
		fmode := os.FileMode(fstat.Mode)
		if fmode.IsDir() {
			rs, err = checkDirs(name)
			if err != nil {
				continue
			}

			return rs, nil
		}

		if fmode&os.ModeCharDevice == 0 &&
			fstat.Ino == Stat.Ino &&
			fstat.Rdev == Stat.Rdev {
			return name, nil
		}

	}

	return "", ErrNotFound
}
예제 #3
0
// Return stringified version of a username.
// Trims after first null byte
func (u *Utmp) ExtractTrimmedName() string {
	return string(u.User[:general.Clen(u.User[:])])
}