-
Notifications
You must be signed in to change notification settings - Fork 203
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
If fd_readdir
returns a zero inode, call fstatat
to get the inode value.
#345
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 |
---|---|---|
|
@@ -3,6 +3,9 @@ | |
// SPDX-License-Identifier: BSD-2-Clause | ||
|
||
#include <sys/stat.h> | ||
#include <sys/types.h> | ||
#include <unistd.h> | ||
#include <fcntl.h> | ||
|
||
#include <assert.h> | ||
#include <wasi/api.h> | ||
|
@@ -77,10 +80,35 @@ struct dirent *readdir(DIR *dirp) { | |
GROW(dirp->dirent, dirp->dirent_size, | ||
offsetof(struct dirent, d_name) + entry.d_namlen + 1); | ||
struct dirent *dirent = dirp->dirent; | ||
dirent->d_ino = entry.d_ino; | ||
dirent->d_type = entry.d_type; | ||
memcpy(dirent->d_name, name, entry.d_namlen); | ||
dirent->d_name[entry.d_namlen] = '\0'; | ||
|
||
// `fd_readdir` implementations may set the inode field to zero if the | ||
// the inode number is unknown. In that case, do an `fstatat` to get the | ||
// inode number. | ||
off_t d_ino = entry.d_ino; | ||
unsigned char d_type = entry.d_type; | ||
if (d_ino == 0) { | ||
struct stat statbuf; | ||
if (fstatat(dirp->fd, dirent->d_name, &statbuf, AT_SYMLINK_NOFOLLOW) != 0) { | ||
if (errno == ENOENT) { | ||
// The file disappeared before we could read it, so skip it. | ||
continue; | ||
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. don't you need to advance buffer_processed? 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. +1 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. Good catch! I've now filed #352 to fix that and one other bug. |
||
} | ||
return NULL; | ||
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. ENOENT etc can happen because of concurrent activities. 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. Good idea about |
||
} | ||
|
||
// Fill in the inode. | ||
d_ino = statbuf.st_ino; | ||
|
||
// In case someone raced with us and replaced the object with this name | ||
// with another of a different type, update the type too. | ||
d_type = __wasilibc_iftodt(statbuf.st_mode & S_IFMT); | ||
} | ||
dirent->d_ino = d_ino; | ||
dirent->d_type = d_type; | ||
|
||
dirp->cookie = entry.d_next; | ||
dirp->buffer_processed += entry_size; | ||
return dirent; | ||
|
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.
is it (ie. d_ino can be 0) going to be a part of the official spec of fd_readdir?
otherwise i'm not sure if it's a good idea to have a workaround here.
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.
Yes, the idea here would be that we'd document that
d_ino
can be zero at the WASI level. I've now filed WebAssembly/wasi-filesystem#71 to track this.