40#include <BESInternalError.h>
41#include <BESInternalFatalError.h>
51#define prolog string("TempFile::").append(__func__).append("() - ")
57std::map<std::string, int, std::less<>> TempFile::open_files;
58struct sigaction
TempFile::cached_sigpipe_handler;
60static string build_error_msg(const string &msg, const string &file = "", int line = -1) {
62 return {msg +
": " + strerror(errno) +
" (errno: " + to_string(errno) +
")"};
64 return {msg +
": " + strerror(errno) +
" (errno: " + to_string(errno) +
"at" + file +
":"
65 + to_string(line) +
")\n"};
76 int saved_errno = errno;
78 for (
const auto &mpair: open_files) {
79 if (unlink((mpair.first).c_str()) == -1) {
80 ERROR_LOG(build_error_msg(
"Error unlinking temporary file: " + mpair.first, __FILE__, __LINE__));
86 sigaction(SIGPIPE, &cached_sigpipe_handler,
nullptr);
93 catch (
const std::exception &e) {
94 ERROR_LOG(build_error_msg(
"std::exception: " +
string(e.what()), __FILE__, __LINE__));
112bool TempFile::mk_temp_dir(
const std::string &dir_name) {
114 mode_t mode = S_IRWXU | S_IRWXG;
115 BESDEBUG(MODULE, prolog <<
"mode: " << std::oct << mode << endl);
117 if (mkdir(dir_name.c_str(), mode)) {
118 if (errno != EEXIST) {
119 throw BESInternalFatalError(build_error_msg(
"Failed to create temp directory: " + dir_name), __FILE__,
123 BESDEBUG(MODULE, prolog <<
"The temp directory: " << dir_name <<
" exists." << endl);
126 uid_t uid = getuid();
127 gid_t gid = getgid();
128 BESDEBUG(MODULE,prolog <<
"Assuming ownership of " << dir_name <<
" (uid: " << uid <<
" gid: "<< gid <<
")" << endl);
129 if(chown(dir_name.c_str(),uid,gid)){
131 msg << prolog <<
"ERROR - Failed to assume ownership (uid: "<< uid;
132 msg <<
" gid: " << gid <<
") of: " << dir_name;
133 msg <<
" errno: " << errno <<
" reason: " << strerror(errno);
136 BESDEBUG(MODULE,prolog <<
"Changing permissions to mode: " << std::oct << mode << endl);
137 if(chmod(dir_name.c_str(),mode)){
139 msg << prolog <<
"ERROR - Failed to change permissions (mode: " << std::oct << mode;
140 msg <<
") for: " << dir_name;
141 msg <<
" errno: " << errno <<
" reason: " << strerror(errno);
142 throw BESInternalFatalError(msg.str(),__FILE__,__LINE__);
148 BESDEBUG(MODULE, prolog <<
"The temp directory: " << dir_name <<
" was created." << endl);
166 std::lock_guard<std::recursive_mutex> lock_me(d_tf_lock_mutex);
168 BESDEBUG(MODULE, prolog <<
"dir_name: " << dir_name << endl);
170 if (access(dir_name.c_str(), F_OK) == -1) {
171 if (errno == ENOENT) {
172 mk_temp_dir(dir_name);
175 throw BESInternalFatalError(build_error_msg(
"Failed to access temp directory: " + dir_name), __FILE__,
184 string target_file =
BESUtil::pathConcat(dir_name, temp_file_prefix +
"_" + to_string(getpid()) +
"_XXXXXX");
186 BESDEBUG(MODULE, prolog <<
"target_file: " << target_file << endl);
190 mode_t original_mode = umask(077);
192 d_fd = mkstemp(&target_file[0]);
193 umask(original_mode);
197 build_error_msg(
"Failed to open the temporary file using mkstemp(), FileTemplate: " + target_file),
201 d_fname.assign(target_file);
207 if (open_files.empty()) {
208 struct sigaction act{};
209 sigemptyset(&act.sa_mask);
210 sigaddset(&act.sa_mask, SIGPIPE);
216 if (sigaction(SIGPIPE, &act, &cached_sigpipe_handler)) {
217 throw BESInternalFatalError(build_error_msg(
"Could not register a handler to catch SIGPIPE"), __FILE__,
222 open_files.insert(std::pair<string, int>(d_fname, d_fd));
234 if (d_fd != -1 && close(d_fd) == -1) {
235 ERROR_LOG(build_error_msg(
"Error closing temporary file: " + d_fname, __FILE__, __LINE__));
237 if (!d_fname.empty()) {
238 std::lock_guard<std::recursive_mutex> lock_me(d_tf_lock_mutex);
240 if (unlink(d_fname.c_str()) == -1) {
241 ERROR_LOG(build_error_msg(
"Error unlinking temporary file: " + d_fname, __FILE__, __LINE__));
245 open_files.erase(d_fname);
247 if (open_files.empty()) {
251 if (sigaction(SIGPIPE, &cached_sigpipe_handler,
nullptr)) {
252 ERROR_LOG(build_error_msg(
"Could not remove SIGPIPE handler" , __FILE__, __LINE__));
258 ERROR_LOG(build_error_msg(
"BESError while closing " + d_fname +
": " + e.get_verbose_message(),
259 __FILE__, __LINE__));
261 catch (std::exception
const &e) {
262 ERROR_LOG(build_error_msg(
"C++ exception while closing " + d_fname +
": " + e.
what(), __FILE__, __LINE__));
Base exception class for the BES with basic string message.
const char * what() const noexcept override
Return a brief message about the exception.
exception thrown if internal error encountered
exception thrown if an internal error is found and is fatal to the BES
static std::string pathConcat(const std::string &firstPart, const std::string &secondPart, char separator='/')
Concatenate path fragments making sure that they are separated by a single '/' character.
Get a new temporary file.
~TempFile()
Free the temporary file.
static void sigpipe_handler(int signal)
std::string create(const std::string &dir_name="/tmp/hyrax_tmp", const std::string &path_template="opendap")
Create a new temporary file.