/* SPDX-License-Identifier: LGPL-2.1 OR MIT */ /* * Directory access for NOLIBC * Copyright (C) 2025 Thomas Weißschuh */ #ifndef _NOLIBC_DIRENT_H #define _NOLIBC_DIRENT_H #include "stdint.h" #include "types.h" #include struct dirent { ino_t d_ino; char d_name[NAME_MAX + 1]; }; /* See comment of FILE in stdio.h */ typedef struct { char dummy[1]; } DIR; static __attribute__((unused)) DIR *fdopendir(int fd) { if (fd < 0) { SET_ERRNO(EBADF); return NULL; } return (DIR *)(intptr_t)~fd; } static __attribute__((unused)) DIR *opendir(const char *name) { int fd; fd = open(name, O_RDONLY); if (fd == -1) return NULL; return fdopendir(fd); } static __attribute__((unused)) int closedir(DIR *dirp) { intptr_t i = (intptr_t)dirp; if (i >= 0) { SET_ERRNO(EBADF); return -1; } return close(~i); } static __attribute__((unused)) int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) { char buf[sizeof(struct linux_dirent64) + NAME_MAX + 1]; struct linux_dirent64 *ldir = (void *)buf; intptr_t i = (intptr_t)dirp; int fd, ret; if (i >= 0) return EBADF; fd = ~i; ret = sys_getdents64(fd, ldir, sizeof(buf)); if (ret < 0) return -ret; if (ret == 0) { *result = NULL; return 0; } /* * getdents64() returns as many entries as fit the buffer. * readdir() can only return one entry at a time. * Make sure the non-returned ones are not skipped. */ ret = lseek(fd, ldir->d_off, SEEK_SET); if (ret == -1) return errno; entry->d_ino = ldir->d_ino; /* the destination should always be big enough */ strlcpy(entry->d_name, ldir->d_name, sizeof(entry->d_name)); *result = entry; return 0; } /* make sure to include all global symbols */ #include "nolibc.h" #endif /* _NOLIBC_DIRENT_H */