Update dir traversal code
This commit is contained in:
parent
37d38b62b1
commit
ab853e1fcf
@ -50,7 +50,7 @@ if (entry->d_name == "."sv || entry->d_name == ".."sv) \
|
|||||||
continue;\
|
continue;\
|
||||||
}
|
}
|
||||||
|
|
||||||
static void post_order_walk(int dirfd, const function<int(int, dirent *)> &&fn) {
|
static void post_order_walk(int dirfd, const function<void(int, dirent *)> &&fn) {
|
||||||
auto dir = xopen_dir(dirfd);
|
auto dir = xopen_dir(dirfd);
|
||||||
if (!dir) return;
|
if (!dir) return;
|
||||||
|
|
||||||
@ -62,8 +62,21 @@ static void post_order_walk(int dirfd, const function<int(int, dirent *)> &&fn)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int remove_at(int dirfd, struct dirent *entry) {
|
static void pre_order_walk(int dirfd, const function<bool(int, dirent *)> &&fn) {
|
||||||
return unlinkat(dirfd, entry->d_name, entry->d_type == DT_DIR ? AT_REMOVEDIR : 0);
|
auto dir = xopen_dir(dirfd);
|
||||||
|
if (!dir) return;
|
||||||
|
|
||||||
|
for (dirent *entry; (entry = xreaddir(dir.get()));) {
|
||||||
|
SKIP_DOTS
|
||||||
|
if (!fn(dirfd, entry))
|
||||||
|
continue;
|
||||||
|
if (entry->d_type == DT_DIR)
|
||||||
|
pre_order_walk(xopenat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC), std::move(fn));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void remove_at(int dirfd, struct dirent *entry) {
|
||||||
|
unlinkat(dirfd, entry->d_name, entry->d_type == DT_DIR ? AT_REMOVEDIR : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rm_rf(const char *path) {
|
void rm_rf(const char *path) {
|
||||||
@ -361,17 +374,17 @@ void backup_folder(const char *dir, vector<raw_file> &files) {
|
|||||||
char path[4096];
|
char path[4096];
|
||||||
xrealpath(dir, path);
|
xrealpath(dir, path);
|
||||||
int len = strlen(path);
|
int len = strlen(path);
|
||||||
post_order_walk(xopen(dir, O_RDONLY), [&](int dfd, dirent *entry) -> int {
|
pre_order_walk(xopen(dir, O_RDONLY), [&](int dfd, dirent *entry) -> bool {
|
||||||
int fd = xopenat(dfd, entry->d_name, O_RDONLY);
|
int fd = xopenat(dfd, entry->d_name, O_RDONLY);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return -1;
|
return false;
|
||||||
run_finally f([&]{ close(fd); });
|
run_finally f([&]{ close(fd); });
|
||||||
if (fd_path(fd, path, sizeof(path)) < 0)
|
if (fd_path(fd, path, sizeof(path)) < 0)
|
||||||
return -1;
|
return false;
|
||||||
raw_file file;
|
raw_file file;
|
||||||
file.path = path + len + 1;
|
file.path = path + len + 1;
|
||||||
if (fgetattr(fd, &file.attr) < 0)
|
if (fgetattr(fd, &file.attr) < 0)
|
||||||
return -1;
|
return false;
|
||||||
if (entry->d_type == DT_REG) {
|
if (entry->d_type == DT_REG) {
|
||||||
fd_full_read(fd, file.buf, file.sz);
|
fd_full_read(fd, file.buf, file.sz);
|
||||||
} else if (entry->d_type == DT_LNK) {
|
} else if (entry->d_type == DT_LNK) {
|
||||||
@ -381,14 +394,14 @@ void backup_folder(const char *dir, vector<raw_file> &files) {
|
|||||||
memcpy(file.buf, path, file.sz);
|
memcpy(file.buf, path, file.sz);
|
||||||
}
|
}
|
||||||
files.emplace_back(std::move(file));
|
files.emplace_back(std::move(file));
|
||||||
return 0;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void restore_folder(const char *dir, vector<raw_file> &files) {
|
void restore_folder(const char *dir, vector<raw_file> &files) {
|
||||||
string base(dir);
|
string base(dir);
|
||||||
// Reversed post-order means folders will always be first
|
// Pre-order means folders will always be first
|
||||||
for (raw_file &file : reversed(files)) {
|
for (raw_file &file : files) {
|
||||||
string path = base + "/" + file.path;
|
string path = base + "/" + file.path;
|
||||||
if (S_ISDIR(file.attr.st.st_mode)) {
|
if (S_ISDIR(file.attr.st.st_mode)) {
|
||||||
mkdirs(path.data(), 0);
|
mkdirs(path.data(), 0);
|
||||||
|
Loading…
Reference in New Issue
Block a user