From 6689aa5210856471fe521373999d9466612eeabd Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Wed, 20 Sep 2023 13:00:15 +0200 Subject: [PATCH] stream: add file::exists and file::readonly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We are targeting C++14, while C++17 already has std::filesystem::exists. 😢 Signed-off-by: Simon Rozman --- UnitTests/main.cpp | 3 ++- UnitTests/stream.cpp | 7 +++++ include/stdex/stream.hpp | 55 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/UnitTests/main.cpp b/UnitTests/main.cpp index 266de47ed..a3fcb4bb4 100644 --- a/UnitTests/main.cpp +++ b/UnitTests/main.cpp @@ -1,4 +1,4 @@ -/* +/* SPDX-License-Identifier: MIT Copyright © 2023 Amebis */ @@ -26,6 +26,7 @@ int main(int argc, const char * argv[]) UnitTests::stream::async(); UnitTests::stream::replicator(); UnitTests::stream::open_close(); + UnitTests::stream::file_stat(); UnitTests::unicode::str2wstr(); UnitTests::unicode::wstr2str(); UnitTests::unicode::charset_encoder(); diff --git a/UnitTests/stream.cpp b/UnitTests/stream.cpp index 0a2373b43..b50c0bae3 100644 --- a/UnitTests/stream.cpp +++ b/UnitTests/stream.cpp @@ -139,6 +139,13 @@ namespace UnitTests std::filesystem::remove(filename[i]); } + TEST_METHOD(file_stat) + { + sstring path(temp_path()); + Assert::IsTrue(stdex::stream::file::exists(path)); + Assert::IsFalse(stdex::stream::file::readonly(path)); + } + protected: static sstring temp_path() { diff --git a/include/stdex/stream.hpp b/include/stdex/stream.hpp index 4b0e246d0..63d84a4b2 100644 --- a/include/stdex/stream.hpp +++ b/include/stdex/stream.hpp @@ -2777,6 +2777,61 @@ namespace stdex #endif throw std::runtime_error("failed to set file mtime"); } + + /// + /// Checks if file/folder/symlink likely exists + /// + /// \param[in] filename Filename + /// + static bool exists(_In_z_ const stdex::schar_t* filename) + { +#ifdef _WIN32 + return GetFileAttributes(filename) != INVALID_FILE_ATTRIBUTES; +#else + struct stat s; + return stat(filename, &s) == 0; +#endif + } + + /// + /// Checks if file/folder/symlink likely exists + /// + /// \param[in] filename Filename + /// + static inline bool exists(_In_ const stdex::sstring& filename) + { + return exists(filename.c_str()); + } + + /// + /// Checks if file/folder/symlink is read-only + /// + /// For inexisting or inaccessible paths, writeability is assumed. + /// + /// \param[in] filename Filename + /// + static bool readonly(_In_z_ const stdex::schar_t* filename) + { +#ifdef _WIN32 + DWORD dwAttr = GetFileAttributes(filename); + return dwAttr != INVALID_FILE_ATTRIBUTES && (dwAttr & FILE_ATTRIBUTE_READONLY) != 0; +#else + struct stat s; + return stat(filename, &s) == 0 && (s.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)) == 0; +#endif + } + + /// + /// Checks if file/folder/symlink is read-only + /// + /// For inexisting or inaccessible paths, writeability is assumed. + /// + /// \param[in] filename Filename + /// + static inline bool readonly(_In_ const stdex::sstring& filename) + { + return readonly(filename.c_str()); + } }; #pragma warning(pop)