xrpld
Loading...
Searching...
No Matches
libxrpl/basics/FileUtilities.cpp
1#include <xrpl/basics/FileUtilities.h>
2
3#include <xrpl/basics/contract.h>
4
5#include <cerrno>
6#include <cstddef>
7#include <filesystem>
8#include <fstream>
9#include <iomanip>
10#include <ios>
11#include <iostream>
12#include <iterator>
13#include <optional>
14#include <random>
15#include <sstream>
16#include <stdexcept>
17#include <string>
18#include <system_error>
19
20namespace xrpl {
21
22std::string
25 std::filesystem::path const& sourcePath,
27{
28 using namespace std::filesystem;
29
30 path const fullPath{canonical(sourcePath, ec)};
31 if (ec)
32 return {};
33
34 if (maxSize && (file_size(fullPath, ec) > *maxSize || ec))
35 {
36 if (!ec)
37 ec = make_error_code(std::errc::file_too_large);
38 return {};
39 }
40
41 std::ifstream fileStream(fullPath, std::ios::in);
42
43 if (!fileStream)
44 {
45 ec.assign(errno, std::generic_category());
46 return {};
47 }
48
49 std::string result{
51
52 if (fileStream.bad())
53 {
54 ec.assign(errno, std::generic_category());
55 return {};
56 }
57
58 return result;
59}
60
61void
64 std::filesystem::path const& destPath,
65 std::string const& contents)
66{
67 std::ofstream fileStream(destPath, std::ios::out | std::ios::trunc);
68
69 if (!fileStream)
70 {
71 ec.assign(errno, std::generic_category());
72 return;
73 }
74
75 fileStream << contents;
76
77 if (fileStream.bad())
78 {
79 ec.assign(errno, std::generic_category());
80 return;
81 }
82}
83
86 std::filesystem::path const& base,
87 std::string const& prefix,
88 std::size_t maxAttempts)
89{
91 for (std::size_t attempt = 0; attempt < maxAttempts; ++attempt)
92 {
94 oss << prefix << std::hex << std::setfill('0') << std::setw(8) << rd() << std::setw(8)
95 << rd();
96 auto candidate = base / oss.str();
98 bool const exists = std::filesystem::exists(candidate, ec);
99 if (ec)
100 {
102 "Unable to check path '" + candidate.string() + "': " + ec.message());
103 }
104 if (!exists)
105 return candidate;
106 }
107 Throw<std::runtime_error>("Unable to generate a unique path under '" + base.string() + "'");
108}
109
114
116{
117 // use non-throwing calls in the destructor
120 if (ec)
121 {
122 std::cerr << "Unable to remove temporary directory '" << path_.string()
123 << "': " << ec.message() << '\n';
124 }
125}
126
129{
130 return path_.string();
131}
132
134TempDir::file(std::string const& name) const
135{
136 return (path_ / name).string();
137}
138
139} // namespace xrpl
T assign(T... args)
T bad(T... args)
T canonical(T... args)
std::filesystem::path path_
TempDir()
Construct a temporary directory.
std::string path() const
Get the native path for the temporary directory.
~TempDir()
Destroy a temporary directory.
std::string file(std::string const &name) const
Get the native path for a file.
T create_directory(T... args)
T exists(T... args)
T file_size(T... args)
T generic_category(T... args)
T hex(T... args)
T message(T... args)
STL namespace.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
std::error_code make_error_code(xrpl::TokenCodecErrc e)
std::filesystem::path uniqueRandomPath(std::filesystem::path const &base, std::string const &prefix="", std::size_t maxAttempts=100)
Generate a unique, non-existing path under base whose filename starts with prefix and ends with a ran...
std::string getFileContents(std::error_code &ec, std::filesystem::path const &sourcePath, std::optional< std::size_t > maxSize=std::nullopt)
void writeFileContents(std::error_code &ec, std::filesystem::path const &destPath, std::string const &contents)
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
Definition contract.h:52
T remove_all(T... args)
T setfill(T... args)
T setw(T... args)
T str(T... args)
T temp_directory_path(T... args)