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) Lumiera.org
5  2024, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 */
22 
23 
30 #ifndef LIB_TEST_TEMP_DIR_H
31 #define LIB_TEST_TEMP_DIR_H
32 
33 
34 #include "lib/error.hpp"
35 #include "lib/nocopy.hpp"
36 #include "lib/random.hpp"
37 #include "lib/stat/file.hpp"
38 #include "include/limits.hpp"
39 #include "lib/format-string.hpp"
40 #include "lib/util.hpp"
41 
42 #include <fstream>
43 #include <string>
44 
45 
46 namespace lib {
47 namespace test{
48 
49  namespace error = lumiera::error;
50 
51  using util::_Fmt;
52  using util::isnil;
53  using std::string;
54 
55  namespace {
56  Literal TEMPFILE_PREFIX = "Lux";
57  }
58 
59 
63  class TempDir
65  {
66  fs::path loc_;
67 
68  public:
69  TempDir()
70  : loc_{establishNewDirectory()}
71  { }
72 
73  ~TempDir()
74  {
75  if (fs::exists (loc_))
76  destroyTempDirectory();
77  }
78 
79 
80  operator fs::path const& () const
81  {
82  return loc_;
83  }
84 
85  fs::path
86  makeFile (string name ="")
87  {
88  if (isnil (name))
89  return establishNewFile (string{TEMPFILE_PREFIX});
90 
91  auto newFile = loc_ / name;
92  if (fs::exists (newFile))
93  return establishNewFile (name);
94 
95  std::ofstream{newFile};
96  if (fs::exists (newFile) and fs::is_empty(newFile))
97  return newFile;
98  //
99  throw error::Fatal{_Fmt{"Failed to create unique new file %s in TempDir."} % newFile};
100  }
101 
102 
103  private:
104  static fs::path
105  establishNewDirectory()
106  {
107  auto tmpDir = fs::temp_directory_path();
108  for (uint attempt=0; attempt<LUMIERA_MAX_COMPETITION; ++attempt)
109  {
110  auto randName = TEMPFILE_PREFIX + util::showHash (entropyGen.u64());
111  auto newPath = tmpDir / randName;
112  // attempt to create it....
113  if (fs::create_directory (newPath)
114  and has_perm (newPath, fs::perms::owner_all)
115  and fs::is_empty (newPath)
116  ) // success!
117  return newPath;
118  }
119  throw error::Fatal{_Fmt{"Failed to create unique new TempDir after %d attempts."}
120  % LUMIERA_MAX_COMPETITION
121  ,error::LUMIERA_ERROR_SAFETY_LIMIT };
122  }
123 
124  fs::path
125  establishNewFile (string prefix)
126  {
127  for (uint attempt=0; attempt<LUMIERA_MAX_COMPETITION; ++attempt)
128  {
129  auto randName = prefix + "." + util::showHash (entropyGen.u64());
130  auto newPath = loc_ / randName;
131  // attempt to create it....
132  if (fs::exists(newPath))
133  continue;
134  std::ofstream{newPath};
135  if (fs::exists(newPath) and fs::is_empty (newPath))
136  return newPath; // success!
137  }
138  throw error::Fatal{_Fmt{"Failed to create unique new file at %s after %d attempts."}
139  % loc_ % LUMIERA_MAX_COMPETITION
140  ,error::LUMIERA_ERROR_SAFETY_LIMIT };
141  }
142 
143  void
144  destroyTempDirectory()
145  try {
146  fs::remove_all (loc_);
147  ENSURE (not fs::exists(loc_));
148  }
149  ERROR_LOG_AND_IGNORE (filesys, "TempDir clean-up")
150  };
151 
152 
153 }} // namespace lib::test
154 #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:275
Definition: run.hpp:49
Includes the C++ Filesystem library and provides some convenience helpers.
inline string literal This is a marker type to indicate that
Definition: symbol.hpp:85
Types marked with this mix-in may be moved but not copied.
Definition: nocopy.hpp:58
Front-end for printf-style string template interpolation.
hard wired safety limits.
Random entropyGen
a global RandomSequencer seeded with real entropy
Definition: random.cpp:81
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:199
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...
A RAII style temporary directory.
Definition: temp-dir.hpp:63
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