From 9ae23540b418b566bd42b092c77835758bb0970c Mon Sep 17 00:00:00 2001 From: R4ken Date: Wed, 13 Aug 2025 13:04:38 +0200 Subject: [PATCH 1/3] posix: implement missing directory functions Implement missing POSIX functions (fdopendir,seekdir, telldir) working on DIR structs JIRA: RTOS-1088 --- include/dirent.h | 11 ++++++++- unistd/dir.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/include/dirent.h b/include/dirent.h index a305e5b6..90f4156b 100644 --- a/include/dirent.h +++ b/include/dirent.h @@ -48,12 +48,21 @@ struct dirent { }; -extern struct dirent *readdir(DIR *s); +extern struct dirent *readdir(DIR *dirp); extern DIR *opendir(const char *dirname); +extern DIR *fdopendir(int fd); + + +extern void seekdir(DIR *dirp, long loc); + + +extern long telldir(DIR *dirp); + + extern void rewinddir(DIR *dirp); diff --git a/unistd/dir.c b/unistd/dir.c index aef2fbf3..ba511b2d 100644 --- a/unistd/dir.c +++ b/unistd/dir.c @@ -26,6 +26,7 @@ #include #include #include +#include static struct { @@ -440,6 +441,69 @@ DIR *opendir(const char *dirname) } +DIR *fdopendir(int fd) +{ + DIR *s; + struct stat statbuf; + int fd_flags; + + fd_flags = fcntl(fd, F_GETFL); + if (fd_flags < 0) { + return NULL; + } + if ((fd_flags & O_RDONLY) == 0) { + errno = EBADF; + return NULL; /* EBADF */ + } + + if (fstat(fd, &statbuf) < 0) { + return NULL; + } + + msg_t msg = { + .type = mtGetAttr, + .oid = { .port = statbuf.st_dev, .id = statbuf.st_ino }, + .i.attr.type = atType, + }; + + if ((msgSend(statbuf.st_dev, &msg) < 0) || (msg.o.err < 0)) { + errno = EIO; + return NULL; /* EIO */ + } + + if (msg.o.attr.val != otDir) { + errno = ENOTDIR; + return NULL; /* ENOTDIR */ + } + + if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) { + return NULL; + } + + s = calloc(1, sizeof(DIR)); + if (s == NULL) { + errno = ENOMEM; + return NULL; + } + s->oid = msg.oid; + s->dirent = NULL; + + return s; +} + + +void seekdir(DIR *dirp, long loc) +{ + dirp->pos = loc; +} + + +long telldir(DIR *dirp) +{ + return dirp->pos; +} + + void rewinddir(DIR *dirp) { dirp->pos = 0; From d9cee5c716a5ac98d19fce3510729327e4b03142 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Lach?= Date: Wed, 26 Nov 2025 15:04:49 +0100 Subject: [PATCH 2/3] posix: introduce NULL checks in *dir routines JIRA: RTOS-1088 --- unistd/dir.c | 49 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/unistd/dir.c b/unistd/dir.c index ba511b2d..e7595479 100644 --- a/unistd/dir.c +++ b/unistd/dir.c @@ -348,36 +348,47 @@ char *realpath(const char *path, char *resolved_path) } -struct dirent *readdir(DIR *s) +struct dirent *readdir(DIR *dirp) { - if (s->dirent == NULL) { - if ((s->dirent = calloc(1, sizeof(struct dirent) + NAME_MAX + 1)) == NULL) + if (dirp == NULL) { + errno = EBADF; + return NULL; + } + + if (dirp->dirent == NULL) { + if ((dirp->dirent = calloc(1, sizeof(struct dirent) + NAME_MAX + 1)) == NULL) { + errno = -ENOMEM; return NULL; + } } msg_t msg = { .type = mtReaddir, - .oid = s->oid, - .i.readdir.offs = s->pos, - .o.data = s->dirent, + .oid = dirp->oid, + .i.readdir.offs = dirp->pos, + .o.data = dirp->dirent, .o.size = sizeof(struct dirent) + NAME_MAX + 1 }; - if (msgSend(s->oid.port, &msg) < 0) { - free(s->dirent); - s->dirent = NULL; + if (msgSend(dirp->oid.port, &msg) < 0) { + free(dirp->dirent); + dirp->dirent = NULL; + errno = EIO; return NULL; /* EIO */ } if (msg.o.err < 0) { - free(s->dirent); - s->dirent = NULL; + free(dirp->dirent); + dirp->dirent = NULL; + if (msg.o.err != -ENOENT) { + errno = -msg.o.err; + } return NULL; } - s->pos += s->dirent->d_reclen; + dirp->pos += dirp->dirent->d_reclen; - return s->dirent; + return dirp->dirent; } @@ -494,18 +505,26 @@ DIR *fdopendir(int fd) void seekdir(DIR *dirp, long loc) { + assert(dirp != NULL); + dirp->pos = loc; } long telldir(DIR *dirp) { + if (dirp == NULL) { + return SET_ERRNO(-EBADF); + } + return dirp->pos; } void rewinddir(DIR *dirp) { + assert(dirp != NULL); + dirp->pos = 0; } @@ -514,6 +533,10 @@ int closedir(DIR *dirp) { int ret = 0; + if (dirp == NULL) { + return SET_ERRNO(-EBADF); + } + msg_t msg = { .type = mtClose, .oid = dirp->oid From 76474768bdbb6d3a9abf92d0b28af685efdc97a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Lach?= Date: Thu, 26 Mar 2026 16:00:05 +0100 Subject: [PATCH 3/3] posix: make access mode enum fields instead of bitfields JIRA: RTOS-1088 --- stdio/file.c | 4 ++-- unistd/dir.c | 4 ---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/stdio/file.c b/stdio/file.c index c54d207c..716ccac2 100644 --- a/stdio/file.c +++ b/stdio/file.c @@ -234,8 +234,8 @@ FILE *fdopen(int fd, const char *mode) } /* POSIX: check if mode argument is allowed by the file access mode of the FD (not necessarily exactly the same) */ - fdm &= 0x7; - if ((fdm != O_RDWR) && (fdm != (m & 0x7))) { + fdm &= O_ACCMODE; + if ((fdm != O_RDWR) && (fdm != (m & O_ACCMODE))) { errno = EINVAL; return NULL; } diff --git a/unistd/dir.c b/unistd/dir.c index e7595479..96a16f01 100644 --- a/unistd/dir.c +++ b/unistd/dir.c @@ -462,10 +462,6 @@ DIR *fdopendir(int fd) if (fd_flags < 0) { return NULL; } - if ((fd_flags & O_RDONLY) == 0) { - errno = EBADF; - return NULL; /* EBADF */ - } if (fstat(fd, &statbuf) < 0) { return NULL;