Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
2/*
3 * Directory access for NOLIBC
4 * Copyright (C) 2025 Thomas Weißschuh <linux@weissschuh.net>
5 */
6
7/* make sure to include all global symbols */
8#include "nolibc.h"
9
10#ifndef _NOLIBC_DIRENT_H
11#define _NOLIBC_DIRENT_H
12
13#include "compiler.h"
14#include "stdint.h"
15#include "types.h"
16#include "fcntl.h"
17
18#include <linux/limits.h>
19
20struct dirent {
21 ino_t d_ino;
22 char d_name[NAME_MAX + 1];
23};
24
25/* See comment of FILE in stdio.h */
26typedef struct {
27 char dummy[1];
28} DIR;
29
30static __attribute__((unused))
31DIR *fdopendir(int fd)
32{
33 if (fd < 0) {
34 SET_ERRNO(EBADF);
35 return NULL;
36 }
37 return (DIR *)(intptr_t)~fd;
38}
39
40static __attribute__((unused))
41DIR *opendir(const char *name)
42{
43 int fd;
44
45 fd = open(name, O_RDONLY);
46 if (fd == -1)
47 return NULL;
48 return fdopendir(fd);
49}
50
51static __attribute__((unused))
52int closedir(DIR *dirp)
53{
54 intptr_t i = (intptr_t)dirp;
55
56 if (i >= 0) {
57 SET_ERRNO(EBADF);
58 return -1;
59 }
60 return close(~i);
61}
62
63static __attribute__((unused))
64int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
65{
66 char buf[sizeof(struct linux_dirent64) + NAME_MAX + 1] __nolibc_aligned_as(struct linux_dirent64);
67 struct linux_dirent64 *ldir = (void *)buf;
68 intptr_t i = (intptr_t)dirp;
69 int fd, ret;
70
71 if (i >= 0)
72 return EBADF;
73
74 fd = ~i;
75
76 ret = sys_getdents64(fd, ldir, sizeof(buf));
77 if (ret < 0)
78 return -ret;
79 if (ret == 0) {
80 *result = NULL;
81 return 0;
82 }
83
84 /*
85 * getdents64() returns as many entries as fit the buffer.
86 * readdir() can only return one entry at a time.
87 * Make sure the non-returned ones are not skipped.
88 */
89 ret = sys_lseek(fd, ldir->d_off, SEEK_SET);
90 if (ret < 0)
91 return -ret;
92
93 entry->d_ino = ldir->d_ino;
94 /* the destination should always be big enough */
95 strlcpy(entry->d_name, ldir->d_name, sizeof(entry->d_name));
96 *result = entry;
97 return 0;
98}
99
100#endif /* _NOLIBC_DIRENT_H */