From cd84d863c2b15845479528ce9cfb31418449021f Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Wed, 21 Feb 2024 14:54:53 +1000 Subject: [PATCH] fs/tmp: make temp queries and path generator more robust --- CMakeLists.txt | 3 +- fs/tmp_posix.cpp | 9 +++++- fs/tmp_win32.cpp | 74 ++++++++++++++++++++++++++++++++++++++++++++++++ paths_win32.cpp | 16 +++++++++++ 4 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 fs/tmp_win32.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 50c9b3fb..e77ddfee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -127,6 +127,7 @@ if (NOT WIN32) debug/crash_posix.cpp debug/fpe_posix.cpp debug/system_posix.cpp + fs/tmp_posix.cpp io_posix.cpp io_posix.hpp library_posix.hpp @@ -153,6 +154,7 @@ if (WIN32) debug/fpe_win32.cpp debug/system_win32.cpp exe_win32.cpp + fs/tmp_win32.cpp io_win32.cpp io_win32.hpp library_win32.cpp @@ -357,7 +359,6 @@ list ( fourcc.hpp fs/scoped.cpp fs/scoped.hpp - fs/tmp_posix.cpp fs/tmp.hpp functor.hpp geom/fwd.hpp diff --git a/fs/tmp_posix.cpp b/fs/tmp_posix.cpp index fa862d46..8287feed 100644 --- a/fs/tmp_posix.cpp +++ b/fs/tmp_posix.cpp @@ -11,6 +11,8 @@ #include "./paths.hpp" #include "./posix/except.hpp" +#include + /////////////////////////////////////////////////////////////////////////////// std::filesystem::path @@ -25,8 +27,13 @@ std::filesystem::path cruft::fs::mktempfile (std::filesystem::path const &dir) { auto pattern = (dir / PACKAGE_NAME "-XXXXXX").native (); - if (!mkstemp (pattern.data ())) + + auto const fd = mkstemp (pattern.data ()); + if (fd < 0) cruft::posix::error::throw_code (); + + cruft::posix::error::try_call(::close, fd); + return pattern; } diff --git a/fs/tmp_win32.cpp b/fs/tmp_win32.cpp new file mode 100644 index 00000000..9f54e687 --- /dev/null +++ b/fs/tmp_win32.cpp @@ -0,0 +1,74 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Copyright 2023, Danny Robson + */ + +#include "./tmp.hpp" + +#include "../paths.hpp" +#include "../posix/except.hpp" + +#include +#include + + +/////////////////////////////////////////////////////////////////////////////// +static std::filesystem::path +_temp_path_at (std::filesystem::path const &root) +{ + // The pattern suffix we'll append to the temp directory. + // + // * We might as well append the package name for clarity + // * The libc call REQUIRES the string end with "XXXXXX" + char const SUFFIX[] = "/" PACKAGE_NAME "-XXXXXX"; + + std::string path; + path.reserve (root.string ().size () + sizeof (SUFFIX)); + path = root.string (); + path += SUFFIX; + + if (auto const err = _mktemp_s (path.data (), path.size ()); err) + throw cruft::posix::error (err); + + return path; +} + + +/////////////////////////////////////////////////////////////////////////////// +std::filesystem::path +cruft::fs::mktempfile (std::filesystem::path const &dir) +{ + auto pattern = (dir / PACKAGE_NAME "-XXXXXX").string (); + + auto const fd = mkstemp (pattern.data ()); + if (fd < 0) + cruft::posix::error::throw_code (); + + cruft::posix::error::try_call(::close, fd); + + return pattern; +} + + +/////////////////////////////////////////////////////////////////////////////// +std::filesystem::path +cruft::fs::mktmpdir (void) +{ + static constexpr int RETRIES = 10; + + auto const root = cruft::paths::temp (); + + for (int i = 0; i < RETRIES; ++i) { + auto const path = _temp_path_at (root); + + if (_mkdir (path.string ().c_str ())) + continue; + + return path; + } + + throw std::runtime_error ("Unable to create tmpdir"); +} diff --git a/paths_win32.cpp b/paths_win32.cpp index 85c5a8b9..243b5ea1 100644 --- a/paths_win32.cpp +++ b/paths_win32.cpp @@ -35,4 +35,20 @@ cruft::paths::expand (std::filesystem::path const &val) store.resize (actual_size); return store; +} + + +/////////////////////////////////////////////////////////////////////////////// +std::filesystem::path +cruft::paths::temp (void) +{ + std::string value; + value.resize (MAX_PATH + 1); + + auto const size = GetTempPathA (value.size (), value.data ()); + if (!size) + throw std::runtime_error ("Unable to locate temp"); + value.resize (size); + + return value; } \ No newline at end of file