105 lines · 2.5 KB · C
RawDownload
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) *//* * Lightweight directory reading library. */#ifndef __API_IO_DIR__#define __API_IO_DIR__ #include <dirent.h>#include <fcntl.h>#include <stdlib.h>#include <unistd.h>#include <sys/stat.h>#include <sys/syscall.h>#include <linux/limits.h> #if !defined(SYS_getdents64)#if defined(__x86_64__) || defined(__arm__)  #define SYS_getdents64 217#elif defined(__i386__) || defined(__s390x__) || defined(__sh__)  #define SYS_getdents64 220#elif defined(__alpha__)  #define SYS_getdents64 377#elif defined(__mips__)  #define SYS_getdents64 308#elif defined(__powerpc64__) || defined(__powerpc__)  #define SYS_getdents64 202#elif defined(__sparc64__) || defined(__sparc__)  #define SYS_getdents64 154#elif defined(__xtensa__)  #define SYS_getdents64 60#else  #define SYS_getdents64 61#endif#endif /* !defined(SYS_getdents64) */ static inline ssize_t perf_getdents64(int fd, void *dirp, size_t count){#ifdef MEMORY_SANITIZER	memset(dirp, 0, count);#endif	return syscall(SYS_getdents64, fd, dirp, count);} struct io_dirent64 {	ino64_t        d_ino;    /* 64-bit inode number */	off64_t        d_off;    /* 64-bit offset to next structure */	unsigned short d_reclen; /* Size of this dirent */	unsigned char  d_type;   /* File type */	char           d_name[NAME_MAX + 1]; /* Filename (null-terminated) */}; struct io_dir {	int dirfd;	ssize_t available_bytes;	struct io_dirent64 *next;	struct io_dirent64 buff[4];}; static inline void io_dir__init(struct io_dir *iod, int dirfd){	iod->dirfd = dirfd;	iod->available_bytes = 0;} static inline void io_dir__rewinddir(struct io_dir *iod){	lseek(iod->dirfd, 0, SEEK_SET);	iod->available_bytes = 0;} static inline struct io_dirent64 *io_dir__readdir(struct io_dir *iod){	struct io_dirent64 *entry; 	if (iod->available_bytes <= 0) {		ssize_t rc = perf_getdents64(iod->dirfd, iod->buff, sizeof(iod->buff)); 		if (rc <= 0)			return NULL;		iod->available_bytes = rc;		iod->next = iod->buff;	}	entry = iod->next;	iod->next = (struct io_dirent64 *)((char *)entry + entry->d_reclen);	iod->available_bytes -= entry->d_reclen;	return entry;} static inline bool io_dir__is_dir(const struct io_dir *iod, struct io_dirent64 *dent){	if (dent->d_type == DT_UNKNOWN) {		struct stat st; 		if (fstatat(iod->dirfd, dent->d_name, &st, /*flags=*/0))			return false; 		if (S_ISDIR(st.st_mode)) {			dent->d_type = DT_DIR;			return true;		}	}	return dent->d_type == DT_DIR;} #endif  /* __API_IO_DIR__ */