diff options
| author | levlam <levlam@telegram.org> | 2023-01-04 17:25:30 +0300 |
|---|---|---|
| committer | levlam <levlam@telegram.org> | 2023-01-04 17:25:30 +0300 |
| commit | 3573990d524123b861730827366f898183c998f1 (patch) | |
| tree | bd710a4920fa0d05408ad4dc650f2df5d127d2c4 | |
| parent | 8df67f0c3a77fd9bb07ef05c68042cd5870986a0 (diff) | |
Support symbolic links in walk_path.
| -rw-r--r-- | benchmark/bench_misc.cpp | 24 | ||||
| -rw-r--r-- | benchmark/rmdir.cpp | 17 | ||||
| -rw-r--r-- | td/telegram/files/FileStatsWorker.cpp | 2 | ||||
| -rw-r--r-- | tdnet/td/net/SslCtx.cpp | 2 | ||||
| -rw-r--r-- | tdutils/td/utils/port/path.cpp | 47 | ||||
| -rw-r--r-- | tdutils/td/utils/port/path.h | 2 | ||||
| -rw-r--r-- | tdutils/test/port.cpp | 2 |
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++; |
