-
Notifications
You must be signed in to change notification settings - Fork 21
posix: implement missing directory functions #433
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,6 +26,7 @@ | |
| #include <sys/stat.h> | ||
| #include <sys/file.h> | ||
| #include <posix/utils.h> | ||
| #include <fcntl.h> | ||
|
|
||
|
|
||
| static struct { | ||
|
|
@@ -347,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; | ||
| } | ||
|
|
||
|
|
||
|
|
@@ -440,8 +452,75 @@ 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 (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) | ||
| { | ||
| assert(dirp != NULL); | ||
|
|
||
| dirp->pos = loc; | ||
oI0ck marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
R4ken marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| long telldir(DIR *dirp) | ||
| { | ||
| if (dirp == NULL) { | ||
| return SET_ERRNO(-EBADF); | ||
| } | ||
|
|
||
| return dirp->pos; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, this behavior exists in Linux, POSIX does not specify it
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As above
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please look carefully at the condition. Also, I agree that POSIX does not specify how to report the error, but: should we deviate from the "common"
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Addressed |
||
| } | ||
|
|
||
|
|
||
| void rewinddir(DIR *dirp) | ||
| { | ||
| assert(dirp != NULL); | ||
|
|
||
| dirp->pos = 0; | ||
| } | ||
|
|
||
|
|
@@ -450,6 +529,10 @@ int closedir(DIR *dirp) | |
| { | ||
| int ret = 0; | ||
|
|
||
| if (dirp == NULL) { | ||
| return SET_ERRNO(-EBADF); | ||
| } | ||
|
|
||
| msg_t msg = { | ||
| .type = mtClose, | ||
| .oid = dirp->oid | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keep two empty lines between function prototypes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed.