mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 06:57:45 +00:00
Userland: Ditch Core::DirIterator for readdir() in find(1)
While Core::DirIterator is nice C++ API, we want more low-level control here. In particular, we want to open the directory using openat(), to also not pay the cost of re-traversing the path components we have already resolved previously. This gives us another nice speedup :^) Also, in the future commits this will allow us to make use of more data from the returned struct dirent, to speed things up even further.
This commit is contained in:
parent
4c126ea908
commit
ad15d0c880
1 changed files with 24 additions and 11 deletions
|
@ -10,13 +10,15 @@
|
||||||
#include <AK/NonnullOwnPtr.h>
|
#include <AK/NonnullOwnPtr.h>
|
||||||
#include <AK/OwnPtr.h>
|
#include <AK/OwnPtr.h>
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
#include <LibCore/DirIterator.h>
|
#include <dirent.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
@ -459,28 +461,39 @@ static void walk_tree(const FileData& root_data, Command& command)
|
||||||
{
|
{
|
||||||
command.evaluate(root_data);
|
command.evaluate(root_data);
|
||||||
|
|
||||||
Core::DirIterator dir_iterator(root_data.full_path.string(), Core::DirIterator::SkipParentAndBaseDir);
|
int dirfd = openat(root_data.dirfd, root_data.basename, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
|
||||||
if (dir_iterator.has_error() && dir_iterator.error() == ENOTDIR)
|
if (dirfd < 0 && errno == ENOTDIR)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while (dir_iterator.has_next()) {
|
DIR* dir = fdopendir(dirfd);
|
||||||
String basename = dir_iterator.next_path();
|
|
||||||
|
while (true) {
|
||||||
|
errno = 0;
|
||||||
|
auto* dirent = readdir(dir);
|
||||||
|
if (!dirent)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name, "..") == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
FileData file_data {
|
FileData file_data {
|
||||||
root_data.full_path.append(basename),
|
root_data.full_path.append(dirent->d_name),
|
||||||
dir_iterator.fd(),
|
dirfd,
|
||||||
basename.characters(),
|
dirent->d_name,
|
||||||
};
|
};
|
||||||
struct stat stat;
|
struct stat stat;
|
||||||
if (g_follow_symlinks || fstatat(dir_iterator.fd(), basename.characters(), &stat, AT_SYMLINK_NOFOLLOW) < 0 || !S_ISLNK(stat.st_mode))
|
if (g_follow_symlinks || fstatat(dirfd, dirent->d_name, &stat, AT_SYMLINK_NOFOLLOW) < 0 || !S_ISLNK(stat.st_mode))
|
||||||
walk_tree(file_data, command);
|
walk_tree(file_data, command);
|
||||||
else
|
else
|
||||||
command.evaluate(file_data);
|
command.evaluate(file_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dir_iterator.has_error()) {
|
if (errno != 0) {
|
||||||
warnln("{}: {}", root_data.full_path, dir_iterator.error_string());
|
perror(root_data.full_path.string().characters());
|
||||||
g_there_was_an_error = true;
|
g_there_was_an_error = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
closedir(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue