diff --git a/projects/rocprofiler-systems/source/bin/common/preset_registry.cpp b/projects/rocprofiler-systems/source/bin/common/preset_registry.cpp index 13c525139381..d11261160e6a 100644 --- a/projects/rocprofiler-systems/source/bin/common/preset_registry.cpp +++ b/projects/rocprofiler-systems/source/bin/common/preset_registry.cpp @@ -4,6 +4,7 @@ #include "common/preset_registry.hpp" #include "common/env_vars.hpp" +#include "common/path.hpp" #include "embedded_presets.hpp" #include @@ -28,21 +29,21 @@ find_preset_directory() if(preset_dir_env && std::strlen(preset_dir_env) > 0) { auto dir = std::string{ preset_dir_env }; - if(common::path::exists(dir)) return dir; + if(path::is_directory(dir)) return dir; } auto root = common::path::get_rocprofsys_root(); if(!root.empty()) { auto candidate = fmt::format("{}/share/rocprofiler-systems/presets", root); - if(common::path::exists(candidate)) return candidate; + if(path::is_directory(candidate)) return candidate; } const auto* rocm_path = std::getenv("ROCM_PATH"); if(rocm_path && std::strlen(rocm_path) > 0) { auto candidate = fmt::format("{}/share/rocprofiler-systems/presets", rocm_path); - if(common::path::exists(candidate)) return candidate; + if(path::is_directory(candidate)) return candidate; } return {}; diff --git a/projects/rocprofiler-systems/source/bin/rocprof-sys-avail/common.cpp b/projects/rocprofiler-systems/source/bin/rocprof-sys-avail/common.cpp index 27f3bf087673..339b397a1c18 100644 --- a/projects/rocprofiler-systems/source/bin/rocprof-sys-avail/common.cpp +++ b/projects/rocprofiler-systems/source/bin/rocprof-sys-avail/common.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include using settings = ::tim::settings; @@ -407,17 +406,6 @@ remove(std::string inp, const std::set& entries) //--------------------------------------------------------------------------------------// -bool -file_exists(const std::string& _fname) -{ - struct stat _buffer; - if(stat(_fname.c_str(), &_buffer) == 0) - return (S_ISREG(_buffer.st_mode) != 0 || S_ISLNK(_buffer.st_mode) != 0); - return false; -} - -//--------------------------------------------------------------------------------------// - namespace { constexpr std::string_view _rocm_op_prefix = "ROCPROFSYS_ROCM_"; diff --git a/projects/rocprofiler-systems/source/bin/rocprof-sys-avail/common.hpp b/projects/rocprofiler-systems/source/bin/rocprof-sys-avail/common.hpp index 951b2a1215a1..067a8f35084b 100644 --- a/projects/rocprofiler-systems/source/bin/rocprof-sys-avail/common.hpp +++ b/projects/rocprofiler-systems/source/bin/rocprof-sys-avail/common.hpp @@ -129,9 +129,6 @@ dump_log_abort(int _v); std::string remove(std::string inp, const std::set& entries); -bool -file_exists(const std::string&); - // ROCm operation-list settings follow the env-var shape // ROCPROFSYS_ROCM__OPERATIONS. These helpers are the single source of // truth for that mapping; do not reconstruct the prefix/suffix elsewhere. diff --git a/projects/rocprofiler-systems/source/bin/rocprof-sys-avail/generate_config.cpp b/projects/rocprofiler-systems/source/bin/rocprof-sys-avail/generate_config.cpp index f30502494659..fe3b2b5874fc 100644 --- a/projects/rocprofiler-systems/source/bin/rocprof-sys-avail/generate_config.cpp +++ b/projects/rocprofiler-systems/source/bin/rocprof-sys-avail/generate_config.cpp @@ -10,6 +10,7 @@ #include "common/env_vars.hpp" #include "common/environment.hpp" #include "common/json_config.hpp" +#include "common/path.hpp" #include #include @@ -251,7 +252,7 @@ generate_config(std::string _config_file, const std::set& _config_f auto _open = [&_nout, &fmt_opts](std::ofstream& _ofs, const std::string& _fname, const std::string& _type) -> std::ofstream& { ++_nout; - if(file_exists(_fname)) + if(rocprofsys::path::is_regular_file(_fname)) { if(fmt_opts.force_config) { diff --git a/projects/rocprofiler-systems/source/bin/rocprof-sys-causal/impl.cpp b/projects/rocprofiler-systems/source/bin/rocprof-sys-causal/impl.cpp index 2d3e4cfcf8a4..1c7ab431eeb9 100644 --- a/projects/rocprofiler-systems/source/bin/rocprof-sys-causal/impl.cpp +++ b/projects/rocprofiler-systems/source/bin/rocprof-sys-causal/impl.cpp @@ -395,7 +395,7 @@ parse_args(int argc, char** argv, std::vector& _env, _generate_configs = true; auto _dir = p.get("generate-configs"); if(!_dir.empty()) _config_folder = std::move(_dir); - if(!filepath::exists(_config_folder)) filepath::makedir(_config_folder); + if(!path::is_directory(_config_folder)) filepath::makedir(_config_folder); }); parser .add_argument({ "--no-defaults" }, diff --git a/projects/rocprofiler-systems/source/bin/rocprof-sys-instrument/internal_libs.cpp b/projects/rocprofiler-systems/source/bin/rocprof-sys-instrument/internal_libs.cpp index 493ff8a82ecb..1e8890e4a2a8 100644 --- a/projects/rocprofiler-systems/source/bin/rocprof-sys-instrument/internal_libs.cpp +++ b/projects/rocprofiler-systems/source/bin/rocprof-sys-instrument/internal_libs.cpp @@ -22,7 +22,6 @@ #include #include #include -#include #include #include @@ -34,7 +33,6 @@ namespace { -namespace filepath = ::tim::filepath; using rocprofsys::get_env; using strview_init_t = std::initializer_list; using strview_set_t = std::set; @@ -415,15 +413,16 @@ get_internal_libs_data_impl() { "librocprof-sys-dl.so", "librocprof-sys-user.so", "librocprof-sys-rt.so" }) { auto libpath = fmt::format("{}/{}/{}", rocprofsys_root, lib_dir, lib_fname); - if(filepath::exists(libpath)) + if(rocprofsys::path::is_regular_file(libpath)) { _libs.emplace_back(rocprofsys::path::realpath(libpath)); } } } - rocprofsys::utility::filter_sort_unique( - _libs, [](const auto& itr) { return itr.empty() || !filepath::exists(itr); }); + rocprofsys::utility::filter_sort_unique(_libs, [](const auto& itr) { + return itr.empty() || !rocprofsys::path::is_regular_file(itr); + }); auto _data = library_module_map_t{}; for(const auto& itr : _libs) @@ -527,7 +526,10 @@ find_library(std::string_view _lib_v) for(const auto& itr : get_library_search_paths()) { auto _path = fmt::format("{}/{}", itr, _lib_v); - if(filepath::exists(_path)) return std::optional{ _path }; + if(rocprofsys::path::is_regular_file(_path)) + { + return std::optional{ _path }; + } } return std::optional{}; @@ -544,7 +546,10 @@ find_libraries(std::string_view _lib_v) for(const auto& itr : get_library_search_paths()) { auto _path = fmt::format("{}/{}", itr, _lib_v); - if(filepath::exists(_path)) _libs.emplace_back(_path); + if(rocprofsys::path::is_regular_file(_path)) + { + _libs.emplace_back(_path); + } } return _libs; diff --git a/projects/rocprofiler-systems/source/bin/rocprof-sys-instrument/rocprof-sys-instrument.cpp b/projects/rocprofiler-systems/source/bin/rocprof-sys-instrument/rocprof-sys-instrument.cpp index 2af18d15e8d0..37f63a7e3eb6 100644 --- a/projects/rocprofiler-systems/source/bin/rocprof-sys-instrument/rocprof-sys-instrument.cpp +++ b/projects/rocprofiler-systems/source/bin/rocprof-sys-instrument/rocprof-sys-instrument.cpp @@ -212,11 +212,8 @@ get_absolute_exe_filepath(std::string exe_name); std::string get_absolute_lib_filepath(std::string lib_name); -bool -exists(const std::string& name); - -bool -is_file(std::string _name); +std::string +absolute(std::string _path); std::string get_cwd(); @@ -292,7 +289,8 @@ main(int argc, char** argv) auto rocprofsys_root_from_env = rocprofsys::get_env( "rocprofiler_systems_ROOT", rocprofsys::get_env(rocprofsys::env_vars::ROOT, "")); - if(!rocprofsys_root_from_env.empty() && exists(rocprofsys_root_from_env)) + if(!rocprofsys_root_from_env.empty() && + path::is_directory(absolute(rocprofsys_root_from_env))) { bin_search_paths.emplace_back(rocprofsys_root_from_env + "/bin"); bin_search_paths.emplace_back(rocprofsys_root_from_env + @@ -312,7 +310,7 @@ main(int argc, char** argv) } auto _rocprofsys_exe_filepath = path::realpath(get_absolute_exe_filepath(argv[0])); - if(!exists(_rocprofsys_exe_filepath)) + if(!path::is_regular_file(absolute(_rocprofsys_exe_filepath))) _rocprofsys_exe_filepath = path::realpath(get_absolute_exe_filepath(rocprofsys_get_exe_realpath())); bin_search_paths.emplace_back(path::parent_path(_rocprofsys_exe_filepath)); @@ -2765,12 +2763,15 @@ absolute(std::string _path) std::string get_absolute_filepath(std::string _name, const strvec_t& _search_paths) { - if(!_name.empty() && (!exists(_name) || !is_file(_name))) + if(!_name.empty() && !path::is_regular_file(absolute(_name))) { auto _orig = _name; for(auto itr : _search_paths) { - if(!path::is_directory(itr) || is_file(itr)) itr = path::parent_path(itr); + if(!path::is_directory(itr)) + { + itr = path::parent_path(itr); + } auto _exists = false; ROCPROFSYS_ADD_LOG_ENTRY("searching", itr, "for", _name); @@ -2778,7 +2779,7 @@ get_absolute_filepath(std::string _name, const strvec_t& _search_paths) { absolute(fmt::format("{}/{}", itr, _name)), absolute(fmt::format("{}/{}", itr, path::filename(_name))) }) { - _exists = exists(pitr) && is_file(pitr); + _exists = path::is_regular_file(pitr); if(_exists) { _name = pitr; @@ -2790,7 +2791,7 @@ get_absolute_filepath(std::string _name, const strvec_t& _search_paths) if(_exists) break; } - if(!exists(_name)) + if(!path::is_regular_file(absolute(_name))) { auto _search_paths_v = fmt::format("{}", fmt::join(bin_search_paths, ", ")); verbprintf( @@ -2843,7 +2844,7 @@ get_absolute_lib_filepath(std::string lib_name) { auto _orig_name = lib_name; lib_name = get_absolute_filepath(std::move(lib_name), lib_search_paths); - if(_orig_name == lib_name && !exists(lib_name) && + if(_orig_name == lib_name && !path::is_regular_file(absolute(lib_name)) && lib_name.find(".so") == std::string::npos && lib_name.find(".a") == std::string::npos) { @@ -2852,20 +2853,6 @@ get_absolute_lib_filepath(std::string lib_name) return lib_name; } -bool -exists(const std::string& name) -{ - return filepath::exists(absolute(name)); -} - -bool -is_file(std::string _name) -{ - _name = path::realpath(_name); - struct stat buffer; - return (stat(_name.c_str(), &buffer) == 0 && S_ISREG(buffer.st_mode) != 0); -} - std::string get_cwd() { @@ -2895,10 +2882,10 @@ find_dyn_api_rt() rocprofsys::get_env("DYNINSTAPI_RT_LIB", _dyn_api_rt_base + ".so"); auto _dyn_api_rt_abs = get_absolute_lib_filepath(_dyn_api_rt_env); - if(!exists(_dyn_api_rt_abs)) + if(!path::is_regular_file(absolute(_dyn_api_rt_abs))) _dyn_api_rt_abs = get_absolute_lib_filepath(_dyn_api_rt_base + ".a"); - if(exists(_dyn_api_rt_abs)) + if(path::is_regular_file(absolute(_dyn_api_rt_abs))) { rocprofsys::set_env("DYNINSTAPI_RT_LIB", _dyn_api_rt_abs, 1); rocprofsys::set_env("DYNINST_REWRITER_PATHS", diff --git a/projects/rocprofiler-systems/source/bin/rocprof-sys-instrument/rocprof-sys-instrument.hpp b/projects/rocprofiler-systems/source/bin/rocprof-sys-instrument/rocprof-sys-instrument.hpp index 56c309045967..e950ac76a370 100644 --- a/projects/rocprofiler-systems/source/bin/rocprof-sys-instrument/rocprof-sys-instrument.hpp +++ b/projects/rocprofiler-systems/source/bin/rocprof-sys-instrument/rocprof-sys-instrument.hpp @@ -3,6 +3,7 @@ #pragma once +#include "common/path.hpp" #include "core/common_types.hpp" #include "core/demangler.hpp" #include "function_signature.hpp" @@ -12,7 +13,6 @@ #include "module_function.hpp" #include -#include #include #include @@ -130,13 +130,13 @@ struct rocprofsys_snippet_vec //======================================================================================// // static inline bool -rocprofsys_get_is_executable(std::string_view _cmd, bool _default_v) +rocprofsys_get_is_executable(const std::string& _cmd, bool _default_v) { bool _is_executable = _default_v; - if(_cmd.empty()) + if(!_cmd.empty()) { - if(!tim::filepath::exists(std::string{ _cmd })) + if(!rocprofsys::path::is_regular_file(_cmd)) { verbprintf( 0, diff --git a/projects/rocprofiler-systems/source/lib/binary/analysis.cpp b/projects/rocprofiler-systems/source/lib/binary/analysis.cpp index e54e782b93fd..ea27ca1d8c1f 100644 --- a/projects/rocprofiler-systems/source/lib/binary/analysis.cpp +++ b/projects/rocprofiler-systems/source/lib/binary/analysis.cpp @@ -30,7 +30,6 @@ #include #include #include -#include #include #include "logger/debug.hpp" @@ -138,7 +137,7 @@ get_binary_info(const std::vector& _files, auto _filter = [&_satisfies_binary_filter](const procfs::maps& _v) { if(_v.pathname.empty()) return false; auto _path = path::realpath(_v.pathname); - return (filepath::exists(_path) && _satisfies_binary_filter(_path)); + return (path::is_regular_file(_path) && _satisfies_binary_filter(_path)); }; auto _data = std::vector{}; @@ -148,7 +147,7 @@ get_binary_info(const std::vector& _files, for(const auto& itr : _files) { auto _filename = path::realpath(itr); - if(filepath::exists(_filename) && _satisfies_binary_filter(_filename) && + if(path::is_regular_file(_filename) && _satisfies_binary_filter(_filename) && _exists.find(_filename) == _exists.end()) { _data.emplace_back(parse_line_info(_filename, _process_dwarf, diff --git a/projects/rocprofiler-systems/source/lib/common/environment.hpp b/projects/rocprofiler-systems/source/lib/common/environment.hpp index 817caf9697a7..02aa28bdae03 100644 --- a/projects/rocprofiler-systems/source/lib/common/environment.hpp +++ b/projects/rocprofiler-systems/source/lib/common/environment.hpp @@ -9,14 +9,13 @@ #include "logger/debug.hpp" #include -#include - #include #include #include #include #include #include +#include #include #include #include @@ -484,7 +483,7 @@ discover_llvm_libdir_for_ompt() auto has_libomptarget = [](const std::string& dir) { const std::string so = dir + "/libomptarget.so"; - return ::tim::filepath::exists(so); + return path::is_regular_file(so); }; // Pick the first candidate that contains libomptarget.so diff --git a/projects/rocprofiler-systems/source/lib/common/path.hpp b/projects/rocprofiler-systems/source/lib/common/path.hpp index 00350264eb36..adc6e39c99f6 100644 --- a/projects/rocprofiler-systems/source/lib/common/path.hpp +++ b/projects/rocprofiler-systems/source/lib/common/path.hpp @@ -79,12 +79,9 @@ inline std::string get_origin(const std::string&, std::vector&& = { (RTLD_LAZY | RTLD_NOLOAD) }) ROCPROFSYS_INTERNAL_API; -inline bool -exists(const std::string& _fname) ROCPROFSYS_INTERNAL_API; - inline std::string -find_path(const std::string& _path, int _verbose, - const std::string& _search_paths) ROCPROFSYS_INTERNAL_API; +find_library(const std::string& _path, int _verbose, + const std::string& _search_paths) ROCPROFSYS_INTERNAL_API; [[nodiscard]] inline std::string parent_path(std::string_view fpath, std::uint16_t levels = 1) ROCPROFSYS_INTERNAL_API; @@ -104,6 +101,9 @@ read_symlink(const std::string& path) ROCPROFSYS_INTERNAL_API; [[nodiscard]] inline bool is_directory(std::string_view path) ROCPROFSYS_INTERNAL_API; +[[nodiscard]] inline bool +is_regular_file(std::string_view path) ROCPROFSYS_INTERNAL_API; + inline std::string get_rocprofsys_root() ROCPROFSYS_INTERNAL_API; @@ -160,20 +160,13 @@ path_type::path_type(const std::string& _fname) } } -bool -exists(const std::string& _fname) -{ - struct stat _buffer; - if(lstat(_fname.c_str(), &_buffer) == 0) - return (S_ISDIR(_buffer.st_mode) != 0 || S_ISREG(_buffer.st_mode) != 0 || - S_ISLNK(_buffer.st_mode) != 0); - return false; -} - std::string -find_path(const std::string& _path, int _verbose, const std::string& _search_paths) +find_library(const std::string& _path, int _verbose, const std::string& _search_paths) { - if(exists(_path) && !_path.empty() && _path.at(0) == '/') return _path; + if(!_path.empty() && _path.at(0) == '/' && is_regular_file(_path)) + { + return _path; + } auto _paths = delimit(_search_paths, ":"); @@ -184,7 +177,7 @@ find_path(const std::string& _path, int _verbose, const std::string& _search_pat ROCPROFSYS_PATH_LOG(_verbose >= _verbose_lvl + 1, "searching for '%s' in '%s' ...\n", _path.c_str(), itr.c_str()); - if(exists(_f)) + if(is_regular_file(_f)) { ROCPROFSYS_PATH_LOG(_verbose >= _verbose_lvl, "found '%s' in '%s' ...\n", _path.c_str(), itr.c_str()); @@ -203,7 +196,7 @@ find_path(const std::string& _path, int _verbose, const std::string& _search_pat ROCPROFSYS_PATH_LOG(_verbose >= _verbose_lvl + 1, "searching for '%s' in '%s' ...\n", _path.c_str(), fmt::format("{}/{}", itr, sitr).c_str()); - if(exists(_f)) + if(is_regular_file(_f)) { ROCPROFSYS_PATH_LOG(_verbose >= _verbose_lvl, "found '%s' in '%s' ...\n", _path.c_str(), @@ -284,6 +277,24 @@ is_directory(std::string_view path) return std::filesystem::is_directory(path, unused_error_code); } +/** + * @brief Check whether a path exists and is a regular file. + * + * Follows symbolic links: a link that resolves to a regular file returns true, + * a broken link returns false. Directories, device nodes, FIFOs and sockets are + * not regular files and yield false. Never throws; any filesystem error + * (missing path, permission failure) yields false. + * + * @param path Filesystem path to test. + * @return true if @p path resolves to a regular file, false otherwise. + */ +[[nodiscard]] bool +is_regular_file(std::string_view path) +{ + std::error_code unused_error_code; + return std::filesystem::is_regular_file(path, unused_error_code); +} + /** * Resolve @p path to its canonical absolute form. * Filesystem operation: follows symlinks and collapses '.'/'..'; the path @@ -391,7 +402,7 @@ get_origin(const std::string& _filename, std::vector&& _open_modes) if(dlinfo(_handle, RTLD_DI_ORIGIN, &_buffer) == 0) { auto _origin = std::string{ _buffer }; - if(exists(_origin)) return _origin; + if(is_directory(_origin)) return _origin; } if(_noload == false) dlclose(_handle); @@ -414,7 +425,7 @@ get_internal_libpath(const std::string& _lib) for(const auto* libdir : { "lib", "lib64" }) { auto _candidate = fmt::format("{}/{}/{}", _root, libdir, _lib); - if(exists(_candidate)) return _candidate; + if(is_regular_file(_candidate)) return _candidate; } return fmt::format("{}/lib/{}", _root, _lib); } diff --git a/projects/rocprofiler-systems/source/lib/common/setup.hpp b/projects/rocprofiler-systems/source/lib/common/setup.hpp index 7fc7784601b1..9a1f183eff5e 100644 --- a/projects/rocprofiler-systems/source/lib/common/setup.hpp +++ b/projects/rocprofiler-systems/source/lib/common/setup.hpp @@ -85,8 +85,8 @@ get_environ(int _verbose, std::string _search_paths = {}, _search_paths = get_default_lib_search_paths(); } - _omnilib = common::path::find_path(_omnilib, _verbose, _search_paths); - _omnilib_dl = common::path::find_path(_omnilib_dl, _verbose, _search_paths); + _omnilib = common::path::find_library(_omnilib, _verbose, _search_paths); + _omnilib_dl = common::path::find_library(_omnilib_dl, _verbose, _search_paths); return _data; } diff --git a/projects/rocprofiler-systems/source/lib/common/tests/test_path.cpp b/projects/rocprofiler-systems/source/lib/common/tests/test_path.cpp index 4180f13836cf..6e9f4e44ceee 100644 --- a/projects/rocprofiler-systems/source/lib/common/tests/test_path.cpp +++ b/projects/rocprofiler-systems/source/lib/common/tests/test_path.cpp @@ -85,39 +85,6 @@ TEST_F(PathTest, ParentPath_MultipleSlashes) EXPECT_EQ(parent_path("/a/b/c/d/e"), "/a/b/c/d"); } -TEST_F(PathTest, Exists_ExistingFile) -{ - std::string file_path = create_file("existing_file.txt"); - EXPECT_TRUE(exists(file_path)); -} - -TEST_F(PathTest, Exists_NonexistentFile) -{ - EXPECT_FALSE(exists(m_test_dir + "/nonexistent_file.txt")); -} - -TEST_F(PathTest, Exists_ExistingDirectory) { EXPECT_TRUE(exists(m_test_dir)); } - -TEST_F(PathTest, Exists_NonexistentDirectory) -{ - EXPECT_FALSE(exists("/nonexistent/path/to/dir")); -} - -TEST_F(PathTest, Exists_SymbolicLink) -{ - std::string target = create_file("target.txt"); - std::string link_path = create_symlink(target, "link_to_target"); - EXPECT_TRUE(exists(link_path)); -} - -TEST_F(PathTest, Exists_BrokenSymlink) -{ - std::string link_path = create_symlink("/nonexistent/target", "broken_link"); - EXPECT_TRUE(exists(link_path)); -} - -TEST_F(PathTest, Exists_EmptyPath) { EXPECT_FALSE(exists("")); } - TEST_F(PathTest, ReadSymlink_SymbolicLink) { std::string target = create_file("read_symlink_target.txt"); @@ -287,6 +254,74 @@ TEST_F(PathTest, IsDirectory_RelativePath) ASSERT_EQ(chdir(saved_cwd), 0); } +TEST_F(PathTest, IsRegularFile_ExistingFile) +{ + std::string file_path = create_file("isregular_file.txt"); + EXPECT_TRUE(is_regular_file(file_path)); +} + +TEST_F(PathTest, IsRegularFile_NonexistentFile) +{ + EXPECT_FALSE(is_regular_file(m_test_dir + "/nonexistent_file.txt")); +} + +TEST_F(PathTest, IsRegularFile_Directory) { EXPECT_FALSE(is_regular_file(m_test_dir)); } + +TEST_F(PathTest, IsRegularFile_NonexistentPath) +{ + EXPECT_FALSE(is_regular_file("/nonexistent/path")); +} + +TEST_F(PathTest, IsRegularFile_SymlinkToFile) +{ + std::string target = create_file("isregular_target.txt"); + std::string link_path = create_symlink(target, "isregular_link_to_file"); + EXPECT_TRUE(is_regular_file(link_path)); +} + +TEST_F(PathTest, IsRegularFile_SymlinkToDirectory) +{ + std::string subdir = create_subdir("isregular_target_dir"); + std::string link_path = create_symlink(subdir, "isregular_link_to_dir"); + EXPECT_FALSE(is_regular_file(link_path)); +} + +TEST_F(PathTest, IsRegularFile_BrokenSymlink) +{ + std::string link_path = + create_symlink("/nonexistent/target", "isregular_broken_link"); + EXPECT_FALSE(is_regular_file(link_path)); +} + +TEST_F(PathTest, IsRegularFile_EmptyPath) { EXPECT_FALSE(is_regular_file("")); } + +TEST_F(PathTest, IsRegularFile_SpecialCharactersInPath) +{ + std::string file_path = create_file("isregular file with spaces.txt"); + EXPECT_TRUE(is_regular_file(file_path)); +} + +TEST_F(PathTest, IsRegularFile_Fifo) +{ + std::string fifo_path = m_test_dir + "/isregular_fifo"; + ASSERT_EQ(mkfifo(fifo_path.c_str(), 0644), 0); + EXPECT_FALSE(is_regular_file(fifo_path)); +} + +TEST_F(PathTest, IsRegularFile_RelativePath) +{ + const std::string file_name = "isregular_relative_file.txt"; + create_file(file_name); + + char saved_cwd[PATH_MAX]; + ASSERT_NE(getcwd(saved_cwd, sizeof(saved_cwd)), nullptr); + ASSERT_EQ(chdir(m_test_dir.c_str()), 0); + + EXPECT_TRUE(is_regular_file(file_name)); + + ASSERT_EQ(chdir(saved_cwd), 0); +} + TEST_F(PathTest, GetRocprofsysRoot_ReturnsNonEmptyAbsolute) { std::string root = get_rocprofsys_root(); @@ -319,24 +354,24 @@ TEST_F(PathTest, GetInternalLibpath_ContainsLib) EXPECT_NE(libpath.find("lib"), std::string::npos); } -TEST_F(PathTest, FindPath_AbsoluteExisting) +TEST_F(PathTest, FindLibrary_AbsoluteExisting) { std::string file_path = create_file("findpath_test.txt"); - std::string result = find_path(file_path, 0, ""); + std::string result = find_library(file_path, 0, ""); EXPECT_EQ(result, file_path); } -TEST_F(PathTest, FindPath_NonexistentReturnsOriginal) +TEST_F(PathTest, FindLibrary_NonexistentReturnsOriginal) { std::string nonexistent = "nonexistent_file_xyz.txt"; - std::string result = find_path(nonexistent, 0, m_test_dir); + std::string result = find_library(nonexistent, 0, m_test_dir); EXPECT_EQ(result, nonexistent); } -TEST_F(PathTest, FindPath_InSearchPath) +TEST_F(PathTest, FindLibrary_InSearchPath) { std::string file_path = create_file("searchable.txt"); - std::string result = find_path("searchable.txt", 0, m_test_dir); + std::string result = find_library("searchable.txt", 0, m_test_dir); EXPECT_EQ(result, file_path); } @@ -362,12 +397,6 @@ TEST_F(PathTest, ChainedSymlinks) EXPECT_EQ(resolved, target); } -TEST_F(PathTest, Exists_SpecialCharactersInPath) -{ - std::string file_path = create_file("file with spaces.txt"); - EXPECT_TRUE(exists(file_path)); -} - TEST_F(PathTest, ParentPath_RocprofsysTypicalPath) { std::string path = "/opt/rocm-6.0.0/lib/rocprofiler-systems/librocprof-sys-dl.so"; @@ -383,9 +412,9 @@ TEST_F(PathTest, NestedDirectories) std::string subdir3 = subdir2 + "/level3"; mkdir(subdir3.c_str(), 0755); - EXPECT_TRUE(exists(subdir1)); - EXPECT_TRUE(exists(subdir2)); - EXPECT_TRUE(exists(subdir3)); + EXPECT_TRUE(is_directory(subdir1)); + EXPECT_TRUE(is_directory(subdir2)); + EXPECT_TRUE(is_directory(subdir3)); EXPECT_EQ(parent_path(subdir3), subdir2); EXPECT_EQ(parent_path(subdir2), subdir1); diff --git a/projects/rocprofiler-systems/source/lib/core/argparse.cpp b/projects/rocprofiler-systems/source/lib/core/argparse.cpp index b7d7c1b56e5d..92817fa835c2 100644 --- a/projects/rocprofiler-systems/source/lib/core/argparse.cpp +++ b/projects/rocprofiler-systems/source/lib/core/argparse.cpp @@ -11,7 +11,6 @@ #include #include -#include #include "logger/debug.hpp" @@ -25,10 +24,6 @@ namespace argparse { namespace { -namespace filepath = ::tim::filepath; -namespace path = rocprofsys::common::path; -using rocprofsys::common::remove_env; - auto get_clock_id_choices() { @@ -133,8 +128,10 @@ parser_data& add_ld_library_path(parser_data& _data) { auto libdir = path::parent_path(_data.env.dl_libpath); - if(filepath::exists(libdir)) + if(path::is_directory(libdir)) + { update_env(_data, "LD_LIBRARY_PATH", libdir, update_mode::APPEND); + } return _data; } diff --git a/projects/rocprofiler-systems/source/lib/core/config.cpp b/projects/rocprofiler-systems/source/lib/core/config.cpp index f76d0fbab75a..f4848e295fef 100644 --- a/projects/rocprofiler-systems/source/lib/core/config.cpp +++ b/projects/rocprofiler-systems/source/lib/core/config.cpp @@ -1407,7 +1407,8 @@ configure_settings(bool _init) // Prevent Timemory's read() silently dropping JSON config files without proper // root. Non-existing JSONs should not throw: default ROCPROFSYS_CONFIG_FILE // includes '~/.rocprofiler-systems.json' that can be missing - if(expanded_filename.ends_with(".json") && filepath::exists(expanded_filename) && + if(expanded_filename.ends_with(".json") && + path::is_regular_file(expanded_filename) && !json_has_project_name_root(expanded_filename)) { throw std::runtime_error( @@ -3337,7 +3338,7 @@ tmp_file::~tmp_file() void tmp_file::touch() const { - if(!filepath::exists(filename)) + if(!path::is_regular_file(filename)) { // if the filepath does not exist, open in out mode to create it auto _ofs = std::ofstream{}; @@ -3462,7 +3463,7 @@ tmp_file::remove() if(m_pid != getpid()) return false; close(); - if(filepath::exists(filename)) + if(path::is_regular_file(filename)) { LOG_DEBUG("Removing temporary file '{}'...", filename); auto _ret = ::remove(filename.c_str()); diff --git a/projects/rocprofiler-systems/source/lib/core/dynamic_library.cpp b/projects/rocprofiler-systems/source/lib/core/dynamic_library.cpp index 5f23d2a8b609..00d6db097580 100644 --- a/projects/rocprofiler-systems/source/lib/core/dynamic_library.cpp +++ b/projects/rocprofiler-systems/source/lib/core/dynamic_library.cpp @@ -6,7 +6,7 @@ #include "common/delimit.hpp" #include "common/environment.hpp" -#include +#include "common/path.hpp" #include #include "logger/debug.hpp" @@ -28,8 +28,10 @@ find_library_path(const std::string& _name, const std::vector& _env for(const auto& itr : procfs::get_maps(process::get_id(), true)) { auto&& _path = itr.pathname; - if(_path.find(_name) != std::string::npos && filepath::exists(_path)) + if(_path.find(_name) != std::string::npos && path::is_regular_file(_path)) + { return _path; + } } auto _paths = std::vector{}; @@ -48,11 +50,11 @@ find_library_path(const std::string& _name, const std::vector& _env for(auto& itr : _paths) { auto _v = fmt::format("{}/{}", itr, _name); - if(filepath::exists(_v)) return _v; + if(path::is_regular_file(_v)) return _v; for(const auto& litr : _path_suffixes) { _v = fmt::format("{}/{}/{}", itr, litr, _name); - if(filepath::exists(_v)) return _v; + if(path::is_regular_file(_v)) return _v; } } @@ -75,17 +77,17 @@ dynamic_library::dynamic_library(std::string _env, std::string _fname, int _flag // override with value if(!_env_val.empty()) { - if(_env_val.find('/') == 0 && filepath::exists(_env_val)) + if(_env_val.starts_with('/') && path::is_regular_file(_env_val)) { filename = _env_val; } - else if(_env_val.find('/') == 0) + else if(_env_val.starts_with('/')) { LOG_WARNING("Ignoring environment variable {}=\"{}\" because the " "filepath does not exist. Using \"{}\" instead...", envname, _env_val, filename); } - else if(_env_val.find('/') != 0 && filename.find('/') == 0) + else if(!_env_val.starts_with('/') && filename.starts_with('/')) { LOG_WARNING("Ignoring environment variable {}=\"{}\" because the " "filepath is relative. Using absolute path \"{}\" instead...", diff --git a/projects/rocprofiler-systems/source/lib/core/perfetto.cpp b/projects/rocprofiler-systems/source/lib/core/perfetto.cpp index 99351d852f3f..8c2cf176c2a5 100644 --- a/projects/rocprofiler-systems/source/lib/core/perfetto.cpp +++ b/projects/rocprofiler-systems/source/lib/core/perfetto.cpp @@ -288,7 +288,7 @@ post_process(tim::manager* _timemory_manager, bool& _perfetto_output_error, } // Test that the script exists - if(!filepath::exists(_script_path)) + if(!path::is_regular_file(_script_path)) { LOG_WARNING("Script not found: {}", _script_path); } diff --git a/projects/rocprofiler-systems/source/lib/core/trace_cache/discovery.cpp b/projects/rocprofiler-systems/source/lib/core/trace_cache/discovery.cpp index 3a273b5ea6af..e2a9186bcfb0 100644 --- a/projects/rocprofiler-systems/source/lib/core/trace_cache/discovery.cpp +++ b/projects/rocprofiler-systems/source/lib/core/trace_cache/discovery.cpp @@ -150,7 +150,7 @@ merge_perfetto_files() if(!_script_dir.empty()) _script_path = fmt::format("{}/{}", _script_dir, _script_path); - if(!tim::filepath::exists(_script_path)) + if(!path::is_regular_file(_script_path)) { LOG_WARNING("Merge script not found: {}", _script_path); return; diff --git a/projects/rocprofiler-systems/source/lib/rocprof-sys-dl/dl.cpp b/projects/rocprofiler-systems/source/lib/rocprof-sys-dl/dl.cpp index a1732082457a..3f0a6589d035 100644 --- a/projects/rocprofiler-systems/source/lib/rocprof-sys-dl/dl.cpp +++ b/projects/rocprofiler-systems/source/lib/rocprof-sys-dl/dl.cpp @@ -217,9 +217,9 @@ struct ROCPROFSYS_INTERNAL_API indirect */ ROCPROFSYS_INLINE indirect(const std::string& _omnilib, const std::string& _userlib, const std::string& _dllib, const std::string& _lib_paths) - : m_omnilib{ common::path::find_path(_omnilib, _rocprofsys_dl_verbose, _lib_paths) } - , m_dllib{ common::path::find_path(_dllib, _rocprofsys_dl_verbose, _lib_paths) } - , m_userlib{ common::path::find_path(_userlib, _rocprofsys_dl_verbose, _lib_paths) } + : m_omnilib{ path::find_library(_omnilib, _rocprofsys_dl_verbose, _lib_paths) } + , m_dllib{ path::find_library(_dllib, _rocprofsys_dl_verbose, _lib_paths) } + , m_userlib{ path::find_library(_userlib, _rocprofsys_dl_verbose, _lib_paths) } { if(_rocprofsys_dl_verbose >= 1) { diff --git a/projects/rocprofiler-systems/source/lib/rocprof-sys/library.cpp b/projects/rocprofiler-systems/source/lib/rocprof-sys/library.cpp index 0cb953a52525..a30cf95b169a 100644 --- a/projects/rocprofiler-systems/source/lib/rocprof-sys/library.cpp +++ b/projects/rocprofiler-systems/source/lib/rocprof-sys/library.cpp @@ -10,6 +10,7 @@ #include "common/defines.h" #include "common/delimit.hpp" #include "common/env_vars.hpp" +#include "common/path.hpp" #include "common/setup.hpp" #include "common/static_object.hpp" #include "core/agent.hpp" @@ -1214,7 +1215,7 @@ rocprofsys_finalize_hidden(void) for(auto& itr : _maps) { auto&& _path = itr.pathname; - if(!_path.empty() && _path.at(0) != '[' && filepath::exists(_path)) + if(!_path.empty() && _path.at(0) != '[' && path::is_regular_file(_path)) _libs.emplace(_path); } ar(tim::cereal::make_nvp("memory_maps_files", _libs), diff --git a/projects/rocprofiler-systems/source/lib/rocprof-sys/library/kokkosp.cpp b/projects/rocprofiler-systems/source/lib/rocprof-sys/library/kokkosp.cpp index 2d2ce9ed543e..75d853d5e316 100644 --- a/projects/rocprofiler-systems/source/lib/rocprof-sys/library/kokkosp.cpp +++ b/projects/rocprofiler-systems/source/lib/rocprof-sys/library/kokkosp.cpp @@ -9,6 +9,7 @@ #include "api.hpp" #include "common/defines.h" #include "common/env_vars.hpp" +#include "common/path.hpp" #include "core/agent_manager.hpp" #include "core/components/fwd.hpp" #include "core/config.hpp" @@ -296,7 +297,7 @@ extern "C" { auto&& _path = itr.pathname; if(!_path.empty() && _path.at(0) != '[' && - rocprofsys::filepath::exists(_path)) + rocprofsys::path::is_regular_file(_path)) _libs.emplace(_path); } for(const auto& itr : _libs)