Fix getdents syscall to handle seekdir/telldir (#8540)
Directory seeking was broken, this change makes syscall220() respect the current directory offset.
This commit is contained in:
Родитель
07de93c796
Коммит
b5586dcb8c
|
@ -1081,11 +1081,17 @@ var SyscallsLibrary = {
|
|||
if (!stream.getdents) {
|
||||
stream.getdents = FS.readdir(stream.path);
|
||||
}
|
||||
|
||||
var struct_size = {{{ C_STRUCTS.dirent.__size__ }}};
|
||||
var pos = 0;
|
||||
while (stream.getdents.length > 0 && pos + {{{ C_STRUCTS.dirent.__size__ }}} <= count) {
|
||||
var off = FS.llseek(stream, 0, {{{ cDefine('SEEK_CUR') }}});
|
||||
|
||||
var idx = Math.floor(off / struct_size);
|
||||
|
||||
while (idx < stream.getdents.length && pos + struct_size <= count) {
|
||||
var id;
|
||||
var type;
|
||||
var name = stream.getdents.pop();
|
||||
var name = stream.getdents[idx];
|
||||
if (name[0] === '.') {
|
||||
id = 1;
|
||||
type = 4; // DT_DIR
|
||||
|
@ -1098,12 +1104,14 @@ var SyscallsLibrary = {
|
|||
8; // DT_REG, regular file.
|
||||
}
|
||||
{{{ makeSetValue('dirp + pos', C_STRUCTS.dirent.d_ino, 'id', 'i64') }}};
|
||||
{{{ makeSetValue('dirp + pos', C_STRUCTS.dirent.d_off, 'stream.position', 'i64') }}};
|
||||
{{{ makeSetValue('dirp + pos', C_STRUCTS.dirent.d_off, '(idx + 1) * struct_size', 'i64') }}};
|
||||
{{{ makeSetValue('dirp + pos', C_STRUCTS.dirent.d_reclen, C_STRUCTS.dirent.__size__, 'i16') }}};
|
||||
{{{ makeSetValue('dirp + pos', C_STRUCTS.dirent.d_type, 'type', 'i8') }}};
|
||||
stringToUTF8(name, dirp + pos + {{{ C_STRUCTS.dirent.d_name }}}, 256);
|
||||
pos += {{{ C_STRUCTS.dirent.__size__ }}};
|
||||
pos += struct_size;
|
||||
idx += 1;
|
||||
}
|
||||
FS.llseek(stream, idx * struct_size, {{{ cDefine('SEEK_SET') }}});
|
||||
return pos;
|
||||
},
|
||||
__syscall221__deps: ['__setErrNo'],
|
||||
|
|
|
@ -868,6 +868,7 @@
|
|||
"defines": [
|
||||
"EOF",
|
||||
"SEEK_END",
|
||||
"SEEK_CUR",
|
||||
"SEEK_SET"
|
||||
],
|
||||
"structs": {}
|
||||
|
|
|
@ -1910,7 +1910,7 @@ long __syscall220(int which, ...) // getdents64 (get directory entries 64-bit)
|
|||
if (desc->file_pos <= file_pos)
|
||||
{
|
||||
de->d_ino = (ino_t)node; // TODO: Create inode numbers instead of using pointers
|
||||
de->d_off = file_pos;
|
||||
de->d_off = file_pos + sizeof(dirent);
|
||||
de->d_reclen = sizeof(dirent);
|
||||
de->d_type = DT_DIR;
|
||||
strcpy(de->d_name, ".");
|
||||
|
@ -1923,7 +1923,7 @@ long __syscall220(int which, ...) // getdents64 (get directory entries 64-bit)
|
|||
if (desc->file_pos <= file_pos)
|
||||
{
|
||||
de->d_ino = (ino_t)dotdot; // TODO: Create inode numbers instead of using pointers
|
||||
de->d_off = file_pos;
|
||||
de->d_off = file_pos + sizeof(dirent);
|
||||
de->d_reclen = sizeof(dirent);
|
||||
de->d_type = DT_DIR;
|
||||
strcpy(de->d_name, "..");
|
||||
|
@ -1938,7 +1938,7 @@ long __syscall220(int which, ...) // getdents64 (get directory entries 64-bit)
|
|||
if (desc->file_pos <= file_pos)
|
||||
{
|
||||
de->d_ino = (ino_t)node; // TODO: Create inode numbers instead of using pointers
|
||||
de->d_off = file_pos;
|
||||
de->d_off = file_pos + sizeof(dirent);
|
||||
de->d_reclen = sizeof(dirent);
|
||||
de->d_type = (node->type == INODE_DIR) ? DT_DIR : DT_REG /*Regular file*/;
|
||||
de->d_name[255] = 0;
|
||||
|
|
|
@ -43,7 +43,7 @@ void cleanup() {
|
|||
|
||||
void test() {
|
||||
int err;
|
||||
long loc;
|
||||
long loc, loc2;
|
||||
DIR *dir;
|
||||
struct dirent *ent;
|
||||
struct dirent ent_r;
|
||||
|
@ -118,11 +118,9 @@ void test() {
|
|||
ent = readdir(dir);
|
||||
assert(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..") || !strcmp(ent->d_name, "file.txt"));
|
||||
loc = telldir(dir);
|
||||
#ifndef __EMSCRIPTEN__
|
||||
// TODO(https://github.com/emscripten-core/emscripten/issues/8526): Implement telldir/seekdir
|
||||
assert(loc > 0);
|
||||
assert(loc >= 0);
|
||||
//printf("loc=%d\n", loc);
|
||||
#endif
|
||||
loc2 = ent->d_off;
|
||||
ent = readdir(dir);
|
||||
char name_at_loc[1024];
|
||||
strcpy(name_at_loc, ent->d_name);
|
||||
|
@ -133,11 +131,14 @@ void test() {
|
|||
seekdir(dir, loc);
|
||||
ent = readdir(dir);
|
||||
assert(ent);
|
||||
#ifndef __EMSCRIPTEN__
|
||||
// TODO(https://github.com/emscripten-core/emscripten/issues/8526: Implement telldir/seekdir
|
||||
//printf("check: %s / %s\n", ent->d_name, name_at_loc);
|
||||
assert(!strcmp(ent->d_name, name_at_loc));
|
||||
#endif
|
||||
|
||||
seekdir(dir, loc2);
|
||||
ent = readdir(dir);
|
||||
assert(ent);
|
||||
//printf("check: %s / %s\n", ent->d_name, name_at_loc);
|
||||
assert(!strcmp(ent->d_name, name_at_loc));
|
||||
|
||||
//
|
||||
// do a normal read with readdir_r
|
||||
|
|
|
@ -4276,12 +4276,12 @@ int main(int argc, char **argv) {
|
|||
1:
|
||||
make /: -1
|
||||
open /: 1
|
||||
proc, 4
|
||||
dev, 4
|
||||
home, 4
|
||||
tmp, 4
|
||||
.., 4
|
||||
., 4
|
||||
.., 4
|
||||
tmp, 4
|
||||
home, 4
|
||||
dev, 4
|
||||
proc, 4
|
||||
''', run_js('a.out.js', args=['/']))
|
||||
# cannot create empty name, cannot open
|
||||
self.assertContained(r'''
|
||||
|
@ -4294,21 +4294,21 @@ int main(int argc, char **argv) {
|
|||
1:
|
||||
make /a//: 0
|
||||
open /a//: 1
|
||||
.., 4
|
||||
., 4
|
||||
.., 4
|
||||
''', run_js('a.out.js', args=['/a//']))
|
||||
# can create child unnormalized
|
||||
self.assertContained(r'''
|
||||
1:
|
||||
make /a: 0
|
||||
open /a: 1
|
||||
.., 4
|
||||
., 4
|
||||
.., 4
|
||||
2:
|
||||
make /a//b//: 0
|
||||
open /a//b//: 1
|
||||
.., 4
|
||||
., 4
|
||||
.., 4
|
||||
''', run_js('a.out.js', args=['/a', '/a//b//']))
|
||||
|
||||
def test_stat_silly(self):
|
||||
|
@ -4500,17 +4500,17 @@ int main()
|
|||
# cannot symlink nonexistents
|
||||
self.assertContained(r'''Before:
|
||||
dir
|
||||
e
|
||||
d
|
||||
c
|
||||
b
|
||||
a
|
||||
b
|
||||
c
|
||||
d
|
||||
e
|
||||
|
||||
Unlinking e
|
||||
Unlinking d
|
||||
Unlinking c
|
||||
Unlinking b
|
||||
Unlinking a
|
||||
Unlinking b
|
||||
Unlinking c
|
||||
Unlinking d
|
||||
Unlinking e
|
||||
After:
|
||||
dir
|
||||
''', run_js('a.out.js', args=['', 'abc']))
|
||||
|
|
Загрузка…
Ссылка в новой задаче