Reconsider how to handle deleted directories in readdir
It's possible that readdir is passed a descriptor to a directory which does not exist anymore (child of DeletedRoot
).
Testcase:
QVERIFY(QDir(localDir.path()).mkdir(QStringLiteral("adir")));
int dirfd = open(qPrintable(mirrorDir.filePath(QStringLiteral("adir"))), O_RDONLY);
QVERIFY(dirfd >= 0);
// Replace the directory locally with a file
QVERIFY(QDir(localDir.path()).rmdir(QStringLiteral("adir")));
QVERIFY(forceNodeTimeout());
// The opened directory can still be iterated (though it's empty)
DIR *dir = fdopendir(dirfd);
QVERIFY(dir);
QStringList entries;
while(auto dirent = readdir(dir))
entries.push_back(QString::fromUtf8(dirent->d_name));
closedir(dir);
entries.sort();
QCOMPARE(entries, (QStringList{QStringLiteral("."), QStringLiteral("..")}));
This passes currently, but changing to test the behaviour on a local FS with open(qPrintable(localDir.filePath(QStringLiteral("adir"))), O_RDONLY);
results in
openat(AT_FDCWD, "/tmp/fileopstest-cache-CgerHl/adir", O_RDONLY) = 6
rmdir("/tmp/fileopstest-cache-CgerHl/adir") = 0
[...]
fstat(6, {st_mode=S_IFDIR|0755, st_size=40, ...}) = 0
fcntl(6, F_GETFL) = 0x8000 (flags O_RDONLY|O_LARGEFILE)
fcntl(6, F_SETFD, FD_CLOEXEC) = 0
getdents64(6, 0x73d7e0, 32768) = -1 ENOENT (Datei oder Verzeichnis nicht gefunden)
close(6) = 0
write(1, "FAIL! : FileOpsTest::testTypeRe"..., 288FAIL! : FileOpsTest::testTypeRefresh() Compared lists have different sizes.
Actual (entries) size: 0
Expected ((QStringList{QStringLiteral("."), QStringLiteral("..")})) size: 2
Loc: [/home/fabian/Arbeitsfläche/Meine Projekte/kde/kio-fuse/kio-fuse/tests/fileopstest.cpp(822)]
) = 288
So fstat
returns that it's a directory but getdents64
fails with ENOENT
?