40#include <BESInternalError.h>
41#include <BESInternalFatalError.h>
51#define prolog string("TempFile::").append(__func__).append("() - ")
57std::once_flag TempFile::d_init_once;
58std::unique_ptr< std::map<std::string, int> > TempFile::open_files;
59struct sigaction TempFile::cached_sigpipe_handler;
71 for (
const auto &mpair: *open_files) {
72 if (unlink((mpair.first).c_str()) == -1) {
74 msg <<
"Error unlinking temporary file: '" << mpair.first <<
"'";
75 msg <<
" errno: " << errno <<
" message: " << strerror(errno) << endl;
81 sigaction(SIGPIPE, &cached_sigpipe_handler,
nullptr);
87 cerr <<
"Encountered BESError. Message: " << e.get_verbose_message();
88 cerr <<
" (location: " << __FILE__ <<
" at line: " << __LINE__ <<
")" << endl;
91 cerr <<
"Encountered unknown error in " << __FILE__ <<
" at line: " << __LINE__ << endl;
100void TempFile::mk_temp_dir(
const std::string &dir_name) {
102 mode_t mode = S_IRWXU | S_IRWXG;
104 ss << prolog <<
"mode: " << std::oct << mode << endl;
105 BESDEBUG(MODULE, ss.str());
107 if(mkdir(dir_name.c_str(), mode)){
110 msg << prolog <<
"ERROR - Failed to create temp directory: " << dir_name;
111 msg <<
" errno: " << errno <<
" reason: " << strerror(errno);
115 BESDEBUG(MODULE,prolog <<
"The temp directory: " << dir_name <<
" exists." << endl);
117 uid_t uid = getuid();
118 gid_t gid = getgid();
119 BESDEBUG(MODULE,prolog <<
"Assuming ownership of " << dir_name <<
" (uid: " << uid <<
" gid: "<< gid <<
")" << endl);
120 if(chown(dir_name.c_str(),uid,gid)){
122 msg << prolog <<
"ERROR - Failed to assume ownership (uid: "<< uid;
123 msg <<
" gid: " << gid <<
") of: " << dir_name;
124 msg <<
" errno: " << errno <<
" reason: " << strerror(errno);
127 BESDEBUG(MODULE,prolog <<
"Changing permissions to mode: " << std::oct << mode << endl);
128 if(chmod(dir_name.c_str(),mode)){
130 msg << prolog <<
"ERROR - Failed to change permissions (mode: " << std::oct << mode;
131 msg <<
") for: " << dir_name;
132 msg <<
" errno: " << errno <<
" reason: " << strerror(errno);
139 BESDEBUG(MODULE,prolog <<
"The temp directory: " << dir_name <<
" was created." << endl);
146void TempFile::init() {
147 open_files.reset(
new std::map<string, int>());
155 std::call_once(d_init_once,TempFile::init);
172 std::lock_guard<std::recursive_mutex> lock_me(d_tf_lock_mutex);
174 BESDEBUG(MODULE, prolog <<
"dir_name: " << dir_name << endl);
175 mk_temp_dir(dir_name);
177 BESDEBUG(MODULE, prolog <<
"temp_file_prefix: " << temp_file_prefix << endl);
178 string tmplt(
"XXXXXX");
182 string file_template = temp_file_prefix + tmplt;
183 BESDEBUG(MODULE, prolog <<
"file_template: " << file_template << endl);
186 BESDEBUG(MODULE, prolog <<
"target_file: " << target_file << endl);
188 char tmp_name[target_file.length() + 1];
189 std::string::size_type len = target_file.copy(tmp_name, target_file.length());
190 tmp_name[len] =
'\0';
194 mode_t original_mode = umask(077);
195 d_fd = mkstemp(tmp_name);
196 umask(original_mode);
200 msg <<
"Failed to open the temporary file using mkstemp()";
201 msg <<
" errno: " << errno <<
" message: " << strerror(errno);
202 msg <<
" FileTemplate: " + target_file;
205 d_fname.assign(tmp_name);
210 if (open_files->empty()) {
211 struct sigaction act;
212 sigemptyset(&act.sa_mask);
213 sigaddset(&act.sa_mask, SIGPIPE);
218 if (sigaction(SIGPIPE, &act, &cached_sigpipe_handler)) {
220 msg <<
"Could not register a handler to catch SIGPIPE.";
221 msg <<
" errno: " << errno <<
" message: " << strerror(errno);
225 open_files->insert(std::pair<string, int>(d_fname, d_fd));
238 if(d_fd != -1 && close(d_fd) == -1) {
240 msg <<
"Error closing temporary file: '" << d_fname ;
241 msg <<
" errno: " << errno <<
" message: " << strerror(errno) << endl;
242 ERROR_LOG(msg.str());
244 if(!d_fname.empty()) {
245 std::lock_guard<std::recursive_mutex> lock_me(d_tf_lock_mutex);
247 if (unlink(d_fname.c_str()) == -1) {
249 msg <<
"Error unlinking temporary file: '" << d_fname ;
250 msg <<
" errno: " << errno <<
" message: " << strerror(errno) << endl;
251 ERROR_LOG(msg.str());
254 open_files->erase(d_fname);
255 if (open_files->empty()) {
258 if (sigaction(SIGPIPE, &cached_sigpipe_handler,
nullptr)) {
260 msg <<
"Could not de-register the SIGPIPE handler function cached_sigpipe_handler(). ";
261 msg <<
" errno: " << errno <<
" message: " << strerror(errno);
262 ERROR_LOG(msg.str());
268 cerr <<
"Encountered BESError will closing " << d_fname <<
" Message: " << e.get_verbose_message();
269 cerr <<
" (location: " << __FILE__ <<
" at line: " << __LINE__ <<
")" << endl;
272 cerr <<
"Encountered unknown error while closing " << d_fname;
273 cerr <<
" " << __FILE__ <<
" at line: " << __LINE__ << endl;
Base exception class for the BES with basic string message.
exception thrown if internal error encountered
exception thrown if an internal error is found and is fatal to the BES
static bool endsWith(std::string const &fullString, std::string const &ending)
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.
~TempFile()
Free the temporary file.
TempFile(bool keep_temps=false)
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.