aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorlevlam <levlam@telegram.org>2023-01-04 17:25:30 +0300
committerlevlam <levlam@telegram.org>2023-01-04 17:25:30 +0300
commit3573990d524123b861730827366f898183c998f1 (patch)
treebd710a4920fa0d05408ad4dc650f2df5d127d2c4
parent8df67f0c3a77fd9bb07ef05c68042cd5870986a0 (diff)
Support symbolic links in walk_path.
-rw-r--r--benchmark/bench_misc.cpp24
-rw-r--r--benchmark/rmdir.cpp17
-rw-r--r--td/telegram/files/FileStatsWorker.cpp2
-rw-r--r--tdnet/td/net/SslCtx.cpp2
-rw-r--r--tdutils/td/utils/port/path.cpp47
-rw-r--r--tdutils/td/utils/port/path.h2
-rw-r--r--tdutils/test/port.cpp2
7 files changed, 62 insertions, 34 deletions
diff --git a/benchmark/bench_misc.cpp b/benchmark/bench_misc.cpp
index 18b68417f..1cbbbe170 100644
--- a/benchmark/bench_misc.cpp
+++ b/benchmark/bench_misc.cpp
@@ -228,13 +228,7 @@ class CreateFileBench final : public td::Benchmark {
}
}
void tear_down() final {
- td::walk_path("A/", [&](td::CSlice path, auto type) {
- if (type == td::WalkPath::Type::ExitDir) {
- td::rmdir(path).ignore();
- } else if (type == td::WalkPath::Type::NotDir) {
- td::unlink(path).ignore();
- }
- }).ignore();
+ td::rmrf("A/").ignore();
}
};
@@ -250,22 +244,10 @@ class WalkPathBench final : public td::Benchmark {
}
void run(int n) final {
int cnt = 0;
- td::walk_path("A/", [&](td::CSlice path, auto type) {
- if (type == td::WalkPath::Type::EnterDir) {
- return;
- }
- td::stat(path).ok();
- cnt++;
- }).ignore();
+ td::rmrf("A/").ignore();
}
void tear_down() final {
- td::walk_path("A/", [&](td::CSlice path, auto type) {
- if (type == td::WalkPath::Type::ExitDir) {
- td::rmdir(path).ignore();
- } else if (type == td::WalkPath::Type::NotDir) {
- td::unlink(path).ignore();
- }
- }).ignore();
+ td::rmrf("A/").ignore();
}
};
diff --git a/benchmark/rmdir.cpp b/benchmark/rmdir.cpp
index 163f2986b..1a1a7133b 100644
--- a/benchmark/rmdir.cpp
+++ b/benchmark/rmdir.cpp
@@ -17,8 +17,23 @@ int main(int argc, char *argv[]) {
auto status = td::walk_path(dir, [&](td::CSlice path, auto type) {
if (type != td::WalkPath::Type::EnterDir) {
cnt++;
- LOG(INFO) << path << " " << (type == td::WalkPath::Type::ExitDir);
}
+ auto type_name = [&] {
+ switch (type) {
+ case td::WalkPath::Type::EnterDir:
+ return td::CSlice("Open");
+ case td::WalkPath::Type::ExitDir:
+ return td::CSlice("Exit");
+ case td::WalkPath::Type::RegularFile:
+ return td::CSlice("File");
+ case td::WalkPath::Type::Symlink:
+ return td::CSlice("Link");
+ default:
+ UNREACHABLE();
+ return td::CSlice();
+ }
+ }();
+ LOG(INFO) << type_name << ' ' << path;
//if (is_dir) {
// td::rmdir(path);
//} else {
diff --git a/td/telegram/files/FileStatsWorker.cpp b/td/telegram/files/FileStatsWorker.cpp
index 81446eca3..1f5e001da 100644
--- a/td/telegram/files/FileStatsWorker.cpp
+++ b/td/telegram/files/FileStatsWorker.cpp
@@ -112,7 +112,7 @@ void scan_fs(CancellationToken &token, CallbackT &&callback) {
if (token) {
return WalkPath::Action::Abort;
}
- if (type != WalkPath::Type::NotDir) {
+ if (type != WalkPath::Type::RegularFile) {
return WalkPath::Action::Continue;
}
auto r_stat = stat(path);
diff --git a/tdnet/td/net/SslCtx.cpp b/tdnet/td/net/SslCtx.cpp
index 128b888fa..a7737ac02 100644
--- a/tdnet/td/net/SslCtx.cpp
+++ b/tdnet/td/net/SslCtx.cpp
@@ -121,7 +121,7 @@ X509_STORE *load_system_certificate_store() {
string default_cert_dir = X509_get_default_cert_dir();
for (auto cert_dir : full_split(default_cert_dir, ':')) {
walk_path(cert_dir, [&](CSlice path, WalkPath::Type type) {
- if (type != WalkPath::Type::NotDir) {
+ if (type != WalkPath::Type::RegularFile) {
return type == WalkPath::Type::EnterDir && path != cert_dir ? WalkPath::Action::SkipDir
: WalkPath::Action::Continue;
}
diff --git a/tdutils/td/utils/port/path.cpp b/tdutils/td/utils/port/path.cpp
index d7d23aaf7..744d706d0 100644
--- a/tdutils/td/utils/port/path.cpp
+++ b/tdutils/td/utils/port/path.cpp
@@ -91,9 +91,12 @@ Status rmrf(CSlice path) {
case WalkPath::Type::ExitDir:
rmdir(path).ignore();
break;
- case WalkPath::Type::NotDir:
+ case WalkPath::Type::RegularFile:
unlink(path).ignore();
break;
+ case WalkPath::Type::Symlink:
+ // never follow symbolic links
+ break;
}
});
}
@@ -263,6 +266,8 @@ Result<bool> walk_path_dir(string &path, const WalkFunction &func) TD_WARN_UNUSE
Result<bool> walk_path_file(string &path, const WalkFunction &func) TD_WARN_UNUSED_RESULT;
+Result<bool> walk_path_symlink(string &path, const WalkFunction &func) TD_WARN_UNUSED_RESULT;
+
Result<bool> walk_path(string &path, const WalkFunction &func) TD_WARN_UNUSED_RESULT;
Result<bool> walk_path_subdir(string &path, DIR *dir, const WalkFunction &func) {
@@ -296,6 +301,8 @@ Result<bool> walk_path_subdir(string &path, DIR *dir, const WalkFunction &func)
status = walk_path_dir(path, func);
} else if (entry->d_type == DT_REG) {
status = walk_path_file(path, func);
+ } else if (entry->d_type == DT_LNK) {
+ status = walk_path_symlink(path, func);
}
#else
#if !TD_SOLARIS
@@ -354,7 +361,18 @@ Result<bool> walk_path_dir(string &path, const WalkFunction &func) {
}
Result<bool> walk_path_file(string &path, const WalkFunction &func) {
- switch (func(path, WalkPath::Type::NotDir)) {
+ switch (func(path, WalkPath::Type::RegularFile)) {
+ case WalkPath::Action::Abort:
+ return false;
+ case WalkPath::Action::SkipDir:
+ case WalkPath::Action::Continue:
+ break;
+ }
+ return true;
+}
+
+Result<bool> walk_path_symlink(string &path, const WalkFunction &func) {
+ switch (func(path, WalkPath::Type::Symlink)) {
case WalkPath::Action::Abort:
return false;
case WalkPath::Action::SkipDir:
@@ -368,17 +386,20 @@ Result<bool> walk_path(string &path, const WalkFunction &func) {
TRY_RESULT(fd, FileFd::open(path, FileFd::Read));
TRY_RESULT(stat, fd.stat());
- bool is_dir = stat.is_dir_;
- bool is_reg = stat.is_reg_;
- if (is_dir) {
+ if (stat.is_dir_) {
return walk_path_dir(path, std::move(fd), func);
}
fd.close();
- if (is_reg) {
+
+ if (stat.is_reg_) {
return walk_path_file(path, func);
}
+ if (stat.is_symbolic_link_) {
+ return walk_path_symlink(path, func);
+ }
+
return true;
}
} // namespace detail
@@ -589,14 +610,24 @@ static Result<bool> walk_path_dir(const std::wstring &dir_name,
if (!is_ok) {
return false;
}
- } else {
- switch (func(entry_name, WalkPath::Type::NotDir)) {
+ } else if ((file_data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
+ switch (func(entry_name, WalkPath::Type::RegularFile)) {
case WalkPath::Action::Abort:
return false;
case WalkPath::Action::SkipDir:
case WalkPath::Action::Continue:
break;
}
+ } else if (file_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK) {
+ switch (func(entry_name, WalkPath::Type::Symlink)) {
+ case WalkPath::Action::Abort:
+ return false;
+ case WalkPath::Action::SkipDir:
+ case WalkPath::Action::Continue:
+ break;
+ }
+ } else {
+ // skip other reparse points
}
}
auto status = FindNextFileW(handle, &file_data);
diff --git a/tdutils/td/utils/port/path.h b/tdutils/td/utils/port/path.h
index 5c86ac1ae..613a5027f 100644
--- a/tdutils/td/utils/port/path.h
+++ b/tdutils/td/utils/port/path.h
@@ -44,7 +44,7 @@ Result<string> mkdtemp(CSlice dir, Slice prefix) TD_WARN_UNUSED_RESULT;
class WalkPath {
public:
enum class Action { Continue, Abort, SkipDir };
- enum class Type { EnterDir, ExitDir, NotDir };
+ enum class Type { EnterDir, ExitDir, RegularFile, Symlink };
template <class F, class R = decltype(std::declval<F>()("", Type::ExitDir))>
static TD_WARN_UNUSED_RESULT std::enable_if_t<std::is_same<R, Action>::value, Status> run(CSlice path, F &&func) {
diff --git a/tdutils/test/port.cpp b/tdutils/test/port.cpp
index af3dffabe..6701efdbc 100644
--- a/tdutils/test/port.cpp
+++ b/tdutils/test/port.cpp
@@ -54,7 +54,7 @@ TEST(Port, files) {
const int ITER_COUNT = 1000;
for (int i = 0; i < ITER_COUNT; i++) {
td::walk_path(main_dir, [&](td::CSlice name, td::WalkPath::Type type) {
- if (type == td::WalkPath::Type::NotDir) {
+ if (type == td::WalkPath::Type::RegularFile) {
ASSERT_TRUE(name == fd_path || name == fd2_path);
}
cnt++;