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:
Rian Hunter 2019-05-06 17:21:36 -07:00 коммит произвёл Sam Clegg
Родитель 07de93c796
Коммит b5586dcb8c
5 изменённых файлов: 41 добавлений и 31 удалений

Просмотреть файл

@ -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

32
tests/test_other.py поставляемый
Просмотреть файл

@ -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']))