Lumiera  0.pre.03
»edit your freedom«
temp-dir.hpp
Go to the documentation of this file.
1 /*
2  TEMP-DIR.hpp - automatic allocation of a temporary working directory
3 
4  Copyright (C)
5  2024, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 */
13 
14 
21 #ifndef LIB_TEST_TEMP_DIR_H
22 #define LIB_TEST_TEMP_DIR_H
23 
24 
25 #include "lib/error.hpp"
26 #include "lib/nocopy.hpp"
27 #include "lib/random.hpp"
28 #include "lib/stat/file.hpp"
29 #include "include/limits.hpp"
30 #include "lib/format-string.hpp"
31 #include "lib/util.hpp"
32 
33 #include <fstream>
34 #include <string>
35 
36 
37 namespace lib {
38 namespace test{
39 
40  namespace error = lumiera::error;
41 
42  using util::_Fmt;
43  using util::isnil;
44  using std::string;
45 
46  namespace {
47  Literal TEMPFILE_PREFIX = "Lux";
48  }
49 
50 
54  class TempDir
56  {
57  fs::path loc_;
58 
59  public:
60  TempDir()
61  : loc_{establishNewDirectory()}
62  { }
63 
64  ~TempDir()
65  {
66  if (fs::exists (loc_))
67  destroyTempDirectory();
68  }
69 
70 
71  operator fs::path const& () const
72  {
73  return loc_;
74  }
75 
76  fs::path
77  makeFile (string name ="")
78  {
79  if (isnil (name))
80  return establishNewFile (string{TEMPFILE_PREFIX});
81 
82  auto newFile = loc_ / name;
83  if (fs::exists (newFile))
84  return establishNewFile (name);
85 
86  std::ofstream{newFile};
87  if (fs::exists (newFile) and fs::is_empty(newFile))
88  return newFile;
89  //
90  throw error::Fatal{_Fmt{"Failed to create unique new file %s in TempDir."} % newFile};
91  }
92 
93 
94  private:
95  static fs::path
96  establishNewDirectory()
97  {
98  auto tmpDir = fs::temp_directory_path();
99  for (uint attempt=0; attempt<LUMIERA_MAX_COMPETITION; ++attempt)
100  {
101  auto randName = TEMPFILE_PREFIX + util::showHash (entropyGen.u64());
102  auto newPath = tmpDir / randName;
103  // attempt to create it....
104  if (fs::create_directory (newPath)
105  and has_perm (newPath, fs::perms::owner_all)
106  and fs::is_empty (newPath)
107  ) // success!
108  return newPath;
109  }
110  throw error::Fatal{_Fmt{"Failed to create unique new TempDir after %d attempts."}
111  % LUMIERA_MAX_COMPETITION
112  ,error::LUMIERA_ERROR_SAFETY_LIMIT };
113  }
114 
115  fs::path
116  establishNewFile (string prefix)
117  {
118  for (uint attempt=0; attempt<LUMIERA_MAX_COMPETITION; ++attempt)
119  {
120  auto randName = prefix + "." + util::showHash (entropyGen.u64());
121  auto newPath = loc_ / randName;
122  // attempt to create it....
123  if (fs::exists(newPath))
124  continue;
125  std::ofstream{newPath};
126  if (fs::exists(newPath) and fs::is_empty (newPath))
127  return newPath; // success!
128  }
129  throw error::Fatal{_Fmt{"Failed to create unique new file at %s after %d attempts."}
130  % loc_ % LUMIERA_MAX_COMPETITION
131  ,error::LUMIERA_ERROR_SAFETY_LIMIT };
132  }
133 
134  void
135  destroyTempDirectory()
136  try {
137  fs::remove_all (loc_);
138  ENSURE (not fs::exists(loc_));
139  }
140  ERROR_LOG_AND_IGNORE (filesys, "TempDir clean-up")
141  };
142 
143 
144 }} // namespace lib::test
145 #endif /*LIB_TEST_TEMP_DIR_H*/
#define ERROR_LOG_AND_IGNORE(_FLAG_, _OP_DESCR_)
convenience shortcut for a sequence of catch blocks just logging and consuming an error...
Definition: error.hpp:266
Definition: run.hpp:40
Includes the C++ Filesystem library and provides some convenience helpers.
inline string literal This is a marker type to indicate that
Definition: symbol.hpp:76
Types marked with this mix-in may be moved but not copied.
Definition: nocopy.hpp:49
Front-end for printf-style string template interpolation.
hard wired safety limits.
Random entropyGen
a global RandomSequencer seeded with real entropy
Definition: random.cpp:71
A front-end for using printf-style formatting.
Implementation namespace for support and library code.
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:190
Mix-Ins to allow or prohibit various degrees of copying and cloning.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
uint64_t u64()
random 64bit number from full range.
Definition: random.hpp:224
A RAII style temporary directory.
Definition: temp-dir.hpp:54
Lumiera error handling (C++ interface).
Generating (pseudo) random numbers with controlled seed.
ElementBoxWidget::Config::Qualifier name(string id)
define the name-ID displayed in the caption