71 {
73 {
75 {
77
78
79 if (
data.submitDir[0] !=
'/')
80 data.submitDir = gSystem->WorkingDirectory () + (
"/" +
data.submitDir);
81
82
83 const std::regex identityEndExpr {"(/$)|(/\\.$)"};
84 while (std::regex_search (
data.submitDir,
match, identityEndExpr))
86 const std::regex relativeEndExpr {"/\\.\\.$"};
87 if (std::regex_search (
data.submitDir,
match, relativeEndExpr))
88 {
90 return ::StatusCode::FAILURE;
91 }
92
93
94
95
96
97
98
99 const std::regex identityExpr {"(/\\./)|(//)|(^/\\.\\./)"};
100 while (std::regex_search (
data.submitDir,
match, identityExpr))
102 const std::regex relativeExpr {"/[^/]+/\\.\\./"};
103 while (std::regex_search (
data.submitDir,
match, relativeExpr))
105
106 if (
data.submitDir.find (
"/pnfs/") == 0)
107 {
109 return ::StatusCode::FAILURE;
110 }
111
113 }
114 break;
115
117 {
120 {
121 if (mode == "no-clobber")
123 else if (mode == "overwrite")
125 else if (mode == "unique")
127 else if (mode == "unique-link")
129 else
130 {
132 ANA_MSG_ERROR (
"known modes: no-clobber, overwrite, unique, unique-link");
133 return ::StatusCode::FAILURE;
134 }
135 }
136
138 {
140 {
141 ANA_MSG_ERROR (
"can't specify both an explicit submit-dir mode and optRemoveSubmitDir");
142 return ::StatusCode::FAILURE;
143 }
145 }
146 }
147 break;
148
150 {
152
153 bool success {false};
154 unsigned tries {0};
156 std::size_t
hash {0};
157 while (success == false && tries < 10)
158 {
159 tries += 1;
160
161 switch (
data.submitDirMode)
162 {
166 break;
167
170 {
171 timeval tv;
172 tm tvSplit;
173 if (gettimeofday (&tv, nullptr) == -1 ||
174 localtime_r (&tv.tv_sec, &tvSplit) == nullptr)
175 {
176 reportErrno ();
178 return ::StatusCode::FAILURE;
179 }
180 const std::string uniqueDateFormat {
182 "-%Y-%m-%d-%H%M-")};
184 if (strftime (timeString, sizeof (timeString),
185 uniqueDateFormat.c_str(), &tvSplit) == 0)
186 {
187 ANA_MSG_ERROR (
"failed to format the unique date, please check optUniqueDateFormat: " << uniqueDateFormat);
188 return ::StatusCode::FAILURE;
189 }
190
191
192 boost::hash_combine (hash, std::hash<pid_t>() (getpid()));
193 boost::hash_combine (hash, std::hash<suseconds_t>() (tv.tv_usec));
194 std::size_t hash16 {
hash};
195 while (hash16 > 0xffff)
196 hash16 = (hash16&0xffff) ^ (hash16 >> 16);
197
198
199
200
201
202
203
204
205
206
208 std::format("{:04x}", hash16);
210 }
211 break;
212 }
213
214 if (::mkdir (
submitDir.c_str(), 0777) == 0)
215 {
216 success = true;
217 } else
218 {
219 const int myerrno {errno};
220 if (myerrno == EEXIST)
221 {
222 switch (
data.submitDirMode)
223 {
225 ANA_MSG_ERROR (
"cowardly refusing to overwrite " << submitDir);
226 ANA_MSG_ERROR (
"change the name or remove file/directory already there");
227 return ::StatusCode::FAILURE;
229 if (tries > 1)
230 {
233 return ::StatusCode::FAILURE;
234 }
238 break;
241
242
243 break;
244 }
245 } else
246 {
247 reportErrno (myerrno);
249 return ::StatusCode::FAILURE;
250 }
251 }
252 }
253
254 if (success)
255 {
256 ANA_MSG_INFO (
"created submission directory " + submitDir);
257 switch (
data.submitDirMode)
258 {
262
263 break;
264
266 {
267 if (unlink (
data.submitDir.c_str()) == -1 && errno != ENOENT)
268 {
269 reportErrno ();
271 return ::StatusCode::FAILURE;
272 }
273
275 if (symlink (
file.c_str(),
data.submitDir.c_str()) == -1)
276 {
277 reportErrno ();
279 return ::StatusCode::FAILURE;
280 }
282 }
283 break;
284 }
286 } else
287 {
288 ANA_MSG_ERROR (
"tried " << tries <<
" times to create directory and failed: " <<
data.submitDir);
290 return ::StatusCode::FAILURE;
291 }
292 }
293 break;
294
295 default:
296
297 break;
298 }
299 return ::StatusCode::SUCCESS;
300 }
static const std::string optSubmitDirMode
the submit-dir mode (allowed values: "no-clobber", "overwrite", "unique", "unique-link")
static const std::string optUniqueDateFormat
the date-format to use when generating unique submission directory names
static const std::string optRemoveSubmitDir
description: the name of the option for overwriting the submission directory.
bool match(std::string s1, std::string s2)
match the individual directories of two strings
@ OVERWRITE
create the directory as is, removing existing directories if needed
@ UNIQUE_LINK
append a unique suffix to the directory name and place a symbolic link in place of the originally req...
@ NO_CLOBBER
create the directory as is, raise an error if it already exists
@ UNIQUE
append a unique suffix to the directory name
@ updateSubmitDir
update the submitDir variable to be an absolute path
@ extractOptions
extract any options into ManagerData for which it is appropriate
@ createSubmitDir
create the submission directory
std::string quote(const std::string &name)
effects: quote the given name to protect it from the shell returns: the quoted name guarantee: strong...