Library: also create unique temporary files

...using the same method for sake of uniformity

Also move the permissions helpers to the file.hpp support functions
and setup a separate unit test for these
This commit is contained in:
Fischlurch 2024-03-12 22:54:05 +01:00
parent a1832b1cb9
commit 18b1d37a3d
6 changed files with 206 additions and 52 deletions

View file

@ -78,6 +78,33 @@ namespace std::filesystem {
fs::canonical(rawPath))
: rawPath;
}
/** check if the denoted path \a p has at least the given permissions */
inline bool
has_perm (fs::path const& p, fs::perms permissionMask)
{
return (fs::status(p).permissions() & permissionMask) == permissionMask;
}
/** check if the owner has read permissions on the denoted file or directory */
inline bool
can_read (fs::path const& p)
{
return has_perm (p, fs::perms::owner_read);
}
inline bool
can_write (fs::path const& p)
{
return has_perm (p, fs::perms::owner_write);
}
inline bool
can_exec (fs::path const& p)
{
return has_perm (p, fs::perms::owner_exec);
}
}//(End)namespace fs

View file

@ -37,9 +37,12 @@
#include "lib/stat/file.hpp"
#include "include/limits.hpp"
#include "lib/format-string.hpp"
#include "lib/util.hpp"
//#include <unordered_map>
//#include <iostream>
//#include <vector>
#include <fstream>
#include <string>
//#include <map>
@ -50,30 +53,12 @@ namespace test{
namespace error = lumiera::error;
using util::_Fmt;
using util::isnil;
using std::string;
namespace {
Literal TEMPFILE_PREFIX = "Lux";
}
inline bool
has_perm (fs::path const& p, fs::perms permissionMask)
{
return (fs::status(p).permissions() & permissionMask) == permissionMask;
}
inline bool
can_read (fs::path const& p)
{
return has_perm (p, fs::perms::owner_read);
}
inline bool
can_write (fs::path const& p)
{
return has_perm (p, fs::perms::owner_write);
}
inline bool
can_exec (fs::path const& p)
{
return has_perm (p, fs::perms::owner_exec);
}
/**
@ -101,9 +86,20 @@ namespace test{
}
fs::path
makeFile()
makeFile (string name ="")
{
UNIMPLEMENTED ("make temporary file");
if (isnil (name))
return establishNewFile (string{TEMPFILE_PREFIX});
auto newFile = loc_ / name;
if (fs::exists (newFile))
return establishNewFile (name);
std::ofstream{newFile};
if (fs::exists (newFile) and fs::is_empty(newFile))
return newFile;
//
throw error::Fatal{_Fmt{"Failed to create unique new file %s in TempDir."} % newFile};
}
@ -127,6 +123,26 @@ namespace test{
% LUMIERA_MAX_COMPETITION
,error::LUMIERA_ERROR_SAFETY_LIMIT };
}
fs::path
establishNewFile (string prefix)
{
for (uint attempt=0; attempt<LUMIERA_MAX_COMPETITION; ++attempt)
{
auto randName = prefix + "." + util::showHash (entropyGen.u64());
auto newPath = loc_ / randName;
// attempt to create it....
if (fs::exists(newPath))
continue;
std::ofstream{newPath};
if (fs::exists(newPath) and fs::is_empty (newPath))
return newPath; // success!
}
throw error::Fatal{_Fmt{"Failed to create unique new file at %s after %d attempts."}
% loc_ % LUMIERA_MAX_COMPETITION
,error::LUMIERA_ERROR_SAFETY_LIMIT };
}
void
destroyTempDirectory()
{

View file

@ -180,6 +180,11 @@ return: 0
END
PLANNED "Filesystem manipulations" FileSupport_test <<END
return: 0
END
TEST "formatting/string conversion in output" FormatCOUT_test <<END
out-lit: Type: int ......
out-lit: is_StringLike<int> : No

View file

@ -0,0 +1,124 @@
/*
FileSupport(Test) - verify additional filesystem helpers
Copyright (C) Lumiera.org
2024, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *****************************************************/
/** @file file-support-test.cpp
** unit test \ref FileSupport_test
*/
#include "lib/test/run.hpp"
#include "lib/test/test-helper.hpp"
#include "lib/test/temp-dir.hpp"
#include "lib/stat/file.hpp"
//#include "lib/time/timevalue.hpp"
//#include "lib/error.hpp"
//#include "lib/util-foreach.hpp"
#include "lib/format-cout.hpp"
#include "lib/test/diagnostic-output.hpp"
//#include <boost/algorithm/string.hpp>
#include <fstream>
//#include <functional>
//#include <string>
//using util::for_each;
//using lumiera::Error;
//using lumiera::LUMIERA_ERROR_EXCEPTION;
//using lumiera::error::LUMIERA_ERROR_ASSERTION;
//using lib::time::TimeVar;
//using lib::time::Time;
//using boost::algorithm::is_lower;
//using boost::algorithm::is_digit;
//using std::function;
//using std::string;
namespace lib {
namespace stat{
namespace test{
using lib::test::TempDir;
/***************************************************************//**
* @test verify supplemental helper functions for file-handling support,
* provided to complement the C++ `<filesystem>` library.
* @see file.hpp
* @see TempDir_test
*/
class FileSupport_test : public Test
{
void
run (Arg)
{
simplifiedPermissionAccess();
homedirectoryExpansion();
}
void
simplifiedPermissionAccess()
{
TempDir temp;
SHOW_EXPR(temp)
SHOW_EXPR(fs::path{temp})
fs::path f = temp.makeFile("Lumiera.nix");
SHOW_EXPR(f);
SHOW_EXPR(fs::exists(f));
std::ofstream out{f};
SHOW_EXPR(fs::exists(f));
SHOW_EXPR(fs::status(f).permissions())
SHOW_EXPR(fs::has_perm(temp, fs::perms::owner_read));
SHOW_EXPR(fs::has_perm(temp, fs::perms::owner_write));
SHOW_EXPR(fs::has_perm(temp, fs::perms::owner_exec));
SHOW_EXPR(fs::has_perm(temp, fs::perms::owner_all));
SHOW_EXPR(fs::has_perm(temp, fs::perms::group_read));
SHOW_EXPR(fs::has_perm(temp, fs::perms::group_write));
SHOW_EXPR(fs::has_perm(temp, fs::perms::group_exec));
SHOW_EXPR(fs::has_perm(temp, fs::perms::group_all));
SHOW_EXPR(fs::has_perm(temp, fs::perms::others_read));
SHOW_EXPR(fs::has_perm(temp, fs::perms::others_write));
SHOW_EXPR(fs::has_perm(temp, fs::perms::others_exec));
SHOW_EXPR(fs::has_perm(temp, fs::perms::others_all));
SHOW_EXPR(fs::has_perm(temp, fs::perms::all));
SHOW_EXPR(fs::can_read(temp));
SHOW_EXPR(fs::can_write(temp));
SHOW_EXPR(fs::can_exec(temp));
}
/** @test prints "sizeof()" including some type name. */
void
homedirectoryExpansion ()
{
}
};
LAUNCHER (FileSupport_test, "unit common");
}}} // namespace lib::stat::test

View file

@ -2,7 +2,7 @@
TempDir(Test) - verify automated temporary working directory
Copyright (C) Lumiera.org
2009, Hermann Vosseler <Ichthyostega@web.de>
2024, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@ -79,24 +79,6 @@ namespace test{
simpleUsage()
{
TempDir temp;
SHOW_EXPR(temp)
SHOW_EXPR(fs::path{temp})
SHOW_EXPR(has_perm(temp, fs::perms::owner_read));
SHOW_EXPR(has_perm(temp, fs::perms::owner_write));
SHOW_EXPR(has_perm(temp, fs::perms::owner_exec));
SHOW_EXPR(has_perm(temp, fs::perms::owner_all));
SHOW_EXPR(has_perm(temp, fs::perms::group_read));
SHOW_EXPR(has_perm(temp, fs::perms::group_write));
SHOW_EXPR(has_perm(temp, fs::perms::group_exec));
SHOW_EXPR(has_perm(temp, fs::perms::group_all));
SHOW_EXPR(has_perm(temp, fs::perms::others_read));
SHOW_EXPR(has_perm(temp, fs::perms::others_write));
SHOW_EXPR(has_perm(temp, fs::perms::others_exec));
SHOW_EXPR(has_perm(temp, fs::perms::others_all));
SHOW_EXPR(has_perm(temp, fs::perms::all));
SHOW_EXPR(can_read(temp));
SHOW_EXPR(can_write(temp));
SHOW_EXPR(can_exec(temp));
auto ff = temp.makeFile();
CHECK (fs::exists (ff));
CHECK (fs::is_empty (ff));

View file

@ -57246,14 +57246,15 @@
<node CREATED="1710185838462" ID="ID_1494325621" MODIFIED="1710185847781" TEXT="modelliert als RAII"/>
<node CREATED="1710185850649" ID="ID_507946689" MODIFIED="1710185923149" TEXT="erzeugt einen zuf&#xe4;lligen Namen"/>
</node>
<node CREATED="1710185930891" ID="ID_406086033" MODIFIED="1710185934026" TEXT="Implementierung">
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1710185930891" ID="ID_406086033" MODIFIED="1710280179518" TEXT="Implementierung">
<icon BUILTIN="pencil"/>
<node CREATED="1710185934990" ID="ID_1561994557" LINK="https://stackoverflow.com/a/58454949" MODIFIED="1710186020053" TEXT="Ausgangspunkt: L&#xf6;sung von Stackoverflow"/>
<node COLOR="#338800" CREATED="1710186086663" ID="ID_206197040" MODIFIED="1710269456216" TEXT="Zufallserzeugung extrahiert">
<arrowlink COLOR="#752d90" DESTINATION="ID_588494337" ENDARROW="Default" ENDINCLINATION="33;-54;" ID="Arrow_ID_353980881" STARTARROW="None" STARTINCLINATION="-193;18;"/>
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1710188183049" ID="ID_91824274" MODIFIED="1710188192430" TEXT="Allokation">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1710188183049" ID="ID_91824274" MODIFIED="1710280175554" TEXT="Allokation">
<icon BUILTIN="button_ok"/>
<node COLOR="#435e98" CREATED="1710262702973" ID="ID_18843364" MODIFIED="1710266321814" TEXT="Semantik von fs::create_directory ist nicht klar">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1710262728032" ID="ID_1183825932" LINK="https://en.cppreference.com/w/cpp/filesystem/create_directory" MODIFIED="1710262791786">
@ -57266,8 +57267,7 @@
Verstehe die Doku so: wenn directory existiert &#10233; <b>kein</b>&#160;Fehler
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1710262793847" ID="ID_921510496" LINK="https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkdir.html" MODIFIED="1710262817664" TEXT="Doku verweist auf POSIX mkdir()">
<node CREATED="1710262820691" ID="ID_715729723" MODIFIED="1710262853435" TEXT="dieses erzeugt Fehler EEXIST"/>
@ -57279,8 +57279,7 @@
<body>
if -1 is returned, no directory shall be created.
</body>
</html>
</richcontent>
</html></richcontent>
<node CREATED="1710262914300" ID="ID_1769904987" MODIFIED="1710262918682" TEXT="naja... nicht wirklich"/>
<node CREATED="1710262919166" ID="ID_156263596" MODIFIED="1710262926049" TEXT="es existiert, wurde aber nicht created"/>
</node>
@ -57331,8 +57330,7 @@
&#10233; <font size="5" color="#ca0992">JAGNI</font>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
</node>
<node COLOR="#338800" CREATED="1710269734115" ID="ID_536611603" MODIFIED="1710269883844" TEXT="Zufallszahl als Hex">
@ -57347,8 +57345,7 @@
die gestern implementierte Zufalls-Sequenz <font face="Monospaced" color="#2216ba">entropyGen.u64()</font>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1710269833165" ID="ID_1640785265" MODIFIED="1710269871853" TEXT="das util::showHash() von vor zwei Monaten">
<icon BUILTIN="ksmiletris"/>
@ -57379,6 +57376,9 @@
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1710188193120" ID="ID_988204568" MODIFIED="1710188200824" TEXT="Destruktion">
<icon BUILTIN="flag-yellow"/>
</node>
<node COLOR="#338800" CREATED="1710280159637" ID="ID_1031094481" MODIFIED="1710280171203" TEXT="Eindeutige Dateien dort erzeugen">
<icon BUILTIN="button_ok"/>
</node>
</node>
<node CREATED="1710269985121" ID="ID_1475343702" MODIFIED="1710269987814" TEXT="Test">
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1710269988763" ID="ID_1423252413" LINK="#ID_992572632" MODIFIED="1710270061936" TEXT="Test f&#xfc;r TempDir">