SST  15.1.0
StructuralSimulationToolkit
filesystem.h
1 // Copyright 2009-2025 NTESS. Under the terms
2 // of Contract DE-NA0003525 with NTESS, the U.S.
3 // Government retains certain rights in this software.
4 //
5 // Copyright (c) 2009-2025, NTESS
6 // All rights reserved.
7 //
8 // This file is part of the SST software package. For license
9 // information, see the LICENSE file in the top level directory of the
10 // distribution.
11 
12 #ifndef SST_CORE_FILESYSTEM_H
13 #define SST_CORE_FILESYSTEM_H
14 
15 #include <cstdio>
16 #include <fstream>
17 #include <iostream>
18 #include <mutex>
19 #include <stdexcept>
20 #include <string>
21 
22 // REMOVE ME
23 #include <filesystem>
24 
25 namespace SST {
26 namespace Util {
27 
28 
29 /**
30  Class used to manage files and directories. One of the features is
31  that you can set the base directory to be used for all files and
32  directories specified with a relative path.
33  */
35 {
36 public:
37  Filesystem() = default;
38 
39  /**
40  Set the base path to be use when relative paths are used. If a
41  relative path is passed into this function, then the current
42  working directory will be used as the base path. When the
43  base_path is set, the class will check to see if the path
44  already exists, and if not, whether or not the user has
45  permissions to create the directory. If the directory doesn't
46  exist and the user doesn't have permission to create it, the
47  function will return false and thee base_path will remain
48  unchanged. If the directory doesn't exist and the user has
49  permissions to create it, the directory will be created on
50  demand.
51 
52  @param base_path Path to set as the base path. The path can be
53  absolute or relative, and a path starting with ~/ with the ~
54  expanded to the user's home directory.
55 
56  @return True if path is valid and either exists and is writable
57  by the user or can be created, false otherwise.
58  */
59  bool setBasePath(const std::string& base_path);
60 
61  /**
62  This function will ensure a directory exists, and if it doesn't
63  already exist, it will create it. If the directory starts with
64  / or ~/ (where ~ represents your home directory) then the path
65  will be considered absolute. Otherwise, the path will be
66  relative to base path set using setBasePath(), or the current
67  working directory if a base path has not been set, or the
68  filename begins with ./ or ../. All intermediate directories
69  that don't exist will be created.
70 
71  @param path Path to verify or create
72 
73  @param strip_filename Set to true if input is a file and you
74  need to strip the filename to get the directory name. Default
75  is false.
76 
77  @return false if directory exists but is not writable, true
78  otherwise
79 
80  @throws std::filesystem::filesystem_error Thrown when the
81  directory does not exist and the function tries to create it
82  but sees an underlying OS API error (see
83  std::filesystem::create_directories()); the most likely cause
84  is a permissions error, or an identically named file.
85 
86  @throws std::invalid_argument Thrown when the passed in path
87  starts with ~/ and the home directory cannot be determined.
88  */
89  bool ensureDirectoryExists(std::filesystem::path p, bool strip_filename = false);
90 
91 
92  /**
93  Creates a unique directory. If the specified directory already
94  exists, the function will append _1 to the directory name. If
95  that is also taken, it will increment the ID until it finds the
96  lowest index that is not used. The function will also create
97  any directory in the path that does not already exist, but only
98  the final directory will be made unique.
99 
100  @param dir_name Name of directory to create. Directory can be
101  relative or absolute and all intermediate paths that don't
102  exist will be created. The unique name only applies to the last
103  level directory.
104 
105  @return Absolute path of the created directory
106 
107  @throws std::filesystem::filesystem_error Thrown when the call
108  sees an underlying OS API error (see
109  std::filesystem::create_directories()); the most likely cause
110  is a permissions error, or an file named identically to one of
111  the directory names that needs to be created.
112 
113  @throws std::invalid_argument Thrown when the passed in path
114  starts with ~/ and the home directory cannot be determined.
115 
116  */
117  std::string createUniqueDirectory(std::filesystem::path dir_name);
118 
119 
120  /**
121  Open a file using std::fopen(). If the passed-in path is
122  relative, it will be relative to the path set using
123  setBasePath(). If setBasePath() was not called, then it will
124  be relative to the current working directory. The FILE*
125  returned from this function can be closed by using
126  std::fclose().
127 
128  @param filename Name of file to open.
129 
130  @param mode read/write mode as defined by std::fopen()
131 
132  @return FILE* to opened file
133  */
134  FILE* fopen(const std::string& filename, const char* mode);
135 
136 
137  /**
138  Get the absolute path for a directory or name. If the directory
139  starts with / or ~/ (where ~ represents your home directory)
140  then the path will be considered absolute. Otherwise, the path
141  will be relative to the base_path, or the current working
142  directory if no base_path was set or the path starts with ./ or
143  ../
144 
145  @param path Path to turn into an absolute path, based on the
146  base_path of the filesystem object
147 
148  @return returns the absolute path
149 
150  @throws std::invalid_argument Thrown when base_path is not
151  absolute (in format, there is no check to see if the directory
152  actually exists) and the passed in path is relative. Also
153  thrown when the passed in path starts with ~/ and the home
154  directory cannot be determined.
155  */
156  std::string getAbsolutePath(const std::string& path);
157 
158  /**
159  Open a file using ofstream. If the passed-in path is relative,
160  it will be relative to the path set using setBasePath(). If
161  setBasePath() was not called, then it will be relative to the
162  current working directory.
163 
164  @param filename Name of file to open
165 
166  @param mode read/write mode as defined by std::ofstream
167 
168  @return ofstream object representing the new opened file
169  */
170  std::ofstream ofstream(const std::string& filename, std::ios_base::openmode mode = std::ios_base::out);
171 
172 
173  /**
174  Get the base_path set by setBasePath
175 
176  @return base_path set by setBasePath. This will be an absolute
177  path
178  */
179  std::string getBasePath() const { return base_path_.string(); }
180 
181 
182  /**
183  Get the absolute path for a directory or name. If the directory
184  starts with / or ~/ (where ~ represents your home directory)
185  then the path will be considered absolute. Otherwise, the path
186  will be relative to the set base_path, or the current working
187  directory if no base_path was set, or the path starts with ./
188  or ../
189 
190  @param path Path to turn into an absolute path
191 
192  @param base_path Path to use as the base path for relative
193  paths passed into the path parameter. If an empty string is
194  passed in, then the current working directory will be used as
195  the base_path (default behavior if you don't pass in a
196  base_path). base_path must be an absolute path and cannot
197  include a ~
198 
199  @throws std::invalid_argument Thrown when base_path is not
200  absolute (in format, there is no check to see if the directory
201  actually exists) and the passed in path is relative. Also
202  thrown when the passed in path starts with ~/ and the home
203  directory cannot be determined.
204  */
205  static std::string getAbsolutePath(const std::string& path, std::string base_path);
206 
207  /**
208  Gets a random file name for use as a temporary file or
209  directory
210  */
211  static std::string getRandomName(size_t length = 8);
212 
213 private:
214  std::filesystem::path base_path_;
215  static std::mutex create_mutex_;
216 };
217 
218 void test_filesystem();
219 
220 } // end namespace Util
221 } // end namespace SST
222 
223 #endif // SST_CORE_FILESYSTEM_H
bool ensureDirectoryExists(std::filesystem::path p, bool strip_filename=false)
This function will ensure a directory exists, and if it doesn&#39;t already exist, it will create it...
Definition: filesystem.cc:145
static std::string getRandomName(size_t length=8)
Gets a random file name for use as a temporary file or directory.
Definition: filesystem.cc:266
std::string getAbsolutePath(const std::string &path)
Get the absolute path for a directory or name.
Definition: filesystem.cc:200
Definition: action.cc:18
FILE * fopen(const std::string &filename, const char *mode)
Open a file using std::fopen().
Definition: filesystem.cc:210
std::string getBasePath() const
Get the base_path set by setBasePath.
Definition: filesystem.h:179
bool setBasePath(const std::string &base_path)
Set the base path to be use when relative paths are used.
Definition: filesystem.cc:103
std::ofstream ofstream(const std::string &filename, std::ios_base::openmode mode=std::ios_base::out)
Open a file using ofstream.
Definition: filesystem.cc:218
std::string createUniqueDirectory(std::filesystem::path dir_name)
Creates a unique directory.
Definition: filesystem.cc:169
Class used to manage files and directories.
Definition: filesystem.h:34