Skip to content

Commit aead0b0

Browse files
authored
Ensure the ino we give to readdir matches the ino we give to stat (#23139)
If we stat a file in the nodefs it gives a different value for the inode than if we use readdir. Readdir gives the inode in the host file system, stat gives the inode in the native file system. Ideally they should agree about what the inode is.
1 parent 021e174 commit aead0b0

File tree

4 files changed

+69
-14
lines changed

4 files changed

+69
-14
lines changed

src/library_nodefs.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ addToLibrary({
138138
}
139139
return {
140140
dev: stat.dev,
141-
ino: stat.ino,
141+
ino: node.id,
142142
mode: stat.mode,
143143
nlink: stat.nlink,
144144
uid: stat.uid,

test/common.py

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -742,27 +742,16 @@ def make_executable(name):
742742

743743

744744
def make_dir_writeable(dirname):
745-
# Ensure all files are readable and writable by the current user.
746-
permission_bits = stat.S_IWRITE | stat.S_IREAD
747-
748-
def is_writable(path):
749-
return (os.stat(path).st_mode & permission_bits) != permission_bits
750-
751-
def make_writable(path):
752-
new_mode = os.stat(path).st_mode | permission_bits
753-
os.chmod(path, new_mode)
754-
755745
# Some tests make files and subdirectories read-only, so rmtree/unlink will not delete
756746
# them. Force-make everything writable in the subdirectory to make it
757747
# removable and re-attempt.
758-
if not is_writable(dirname):
759-
make_writable(dirname)
748+
os.chmod(dirname, 0o777)
760749

761750
for directory, subdirs, files in os.walk(dirname):
762751
for item in files + subdirs:
763752
i = os.path.join(directory, item)
764753
if not os.path.islink(i):
765-
make_writable(i)
754+
os.chmod(i, 0o777)
766755

767756

768757
def force_delete_dir(dirname):
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#include <stdio.h>
2+
#include <unistd.h>
3+
#include <assert.h>
4+
#include <fcntl.h>
5+
#include <string.h>
6+
#include <sys/stat.h>
7+
#include <assert.h>
8+
#include <errno.h>
9+
#include <string.h>
10+
#include <dirent.h>
11+
12+
// TODO: Consider merging this with test/dirent/test_readdir.c?
13+
// That test doesn't work on nodefs, which has to be fixed before these two
14+
// tests can be merged .
15+
16+
void setup() {
17+
// If the node working directory does not have execute permissions, then
18+
// `fs.readdir` will fail. For that reason we have to work in a subdirectory
19+
// and remove execute permissions from that.
20+
mkdir("sub", 0775);
21+
assert(chdir("sub") == 0);
22+
int res = open("b", O_CREAT, 0777);
23+
assert(res >= 0);
24+
assert(close(res) == 0);
25+
assert(symlink("b", "a") == 0);
26+
}
27+
28+
int main() {
29+
setup();
30+
int dirfd = open(".", O_RDONLY);
31+
assert(dirfd > 0);
32+
DIR *dirp = fdopendir(dirfd);
33+
assert(dirp != NULL);
34+
struct stat sta, stb;
35+
assert(lstat("a", &sta) == 0);
36+
assert(lstat("b", &stb) == 0);
37+
// Test that removing permissions from the directory does not affect the
38+
// already open directory handle that we have (dirp).
39+
#ifndef NODERAWFS
40+
assert(chmod(".", 0675) == 0);
41+
#endif
42+
int a_ino = -1;
43+
int b_ino = -1;
44+
struct dirent *ep;
45+
while ((ep = readdir(dirp))) {
46+
if (strcmp(ep->d_name, "a") == 0) {
47+
a_ino = ep->d_ino;
48+
}
49+
if (strcmp(ep->d_name, "b") == 0) {
50+
b_ino = ep->d_ino;
51+
}
52+
}
53+
assert(errno == 0);
54+
assert(a_ino >= 0);
55+
assert(b_ino >= 0);
56+
printf("readdir a_ino: %d, b_ino: %d\n", a_ino, b_ino);
57+
printf("stat a_ino: %llu, b_ino: %llu\n", sta.st_ino, stb.st_ino);
58+
assert(a_ino == sta.st_ino);
59+
assert(b_ino == stb.st_ino);
60+
printf("success\n");
61+
return 0;
62+
}

test/test_core.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5859,6 +5859,10 @@ def test_fs_rename_on_existing(self):
58595859
self.set_setting('FORCE_FILESYSTEM')
58605860
self.do_runf('fs/test_fs_rename_on_existing.c', 'success')
58615861

5862+
@also_with_nodefs_both
5863+
def test_fs_readdir_ino_matches_stat_ino(self):
5864+
self.do_runf('fs/test_fs_readdir_ino_matches_stat_ino.c', 'success')
5865+
58625866
@also_with_nodefs_both
58635867
def test_fs_open_no_permissions(self):
58645868
self.do_runf('fs/test_fs_open_no_permissions.c', 'success')

0 commit comments

Comments
 (0)