Logo ROOT  
Reference Guide
XrdProofdSandbox.cxx
Go to the documentation of this file.
1// @(#)root/proofd:$Id$
2// Author: G. Ganis Jan 2008
3
4/*************************************************************************
5 * Copyright (C) 1995-2005, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12//////////////////////////////////////////////////////////////////////////
13// //
14// XrdProofdSandbox //
15// //
16// Authors: G. Ganis, CERN, 2008 //
17// //
18// Create and manage a Unix sandbox. //
19// //
20//////////////////////////////////////////////////////////////////////////
21#include "XrdProofdPlatform.h"
22
23#include "XrdProofdSandbox.h"
24#include "XrdSys/XrdSysPriv.hh"
25
26// Tracing utilities
27#include "XrdProofdTrace.h"
28
29// Modified via config directives by the manager
31XrdOucString XrdProofdSandbox::fgWorkdir = "";
33
34////////////////////////////////////////////////////////////////////////////////
35/// Assert existence on the sandbox for the user defined by 'ui'.
36/// The sandbox is created under fgWorkdir or $HOME/proof; the boolean
37/// 'full' controls the set of directories to be asserted: the sub-set
38/// {cache, packages, .creds} is always asserted; if full is true also
39/// the sub-dirs {queries, datasets} are asserted.
40/// If 'changeown' is true the sandbox ownership is set to 'ui'; this
41/// requires su-privileges.
42/// The constructor also builds the list of sessions directories in the
43/// sandbox; directories corresponding to terminated sessions are
44/// removed if the total number of session directories is larger than
45/// fgMaxOldSessions .
46
48 : fChangeOwn(changeown), fUI(ui)
49{
50 XPDLOC(CMGR, "XrdProofdSandbox")
51
52 fValid = 0;
53
54 // The first time fill the info about the owner of this process
55 if (fgUI.fUid < 0)
57
58 // Default working directory location for the effective user
59 XrdOucString defdir = fgUI.fHomeDir;
60 if (!defdir.endswith('/')) defdir += "/";
61 defdir += ".proof/";
62 XrdOucString initus = ui.fUser[0];
63 int iph = STR_NPOS;
64 if (fgWorkdir.length() > 0) {
65 // The user directory path will be <workdir>/<user>
67 if (fDir.find("<user>") == STR_NPOS) {
68 if (!fDir.endswith('/')) fDir += "/";
69 fDir += "<user>";
70 }
71 // Replace supported place-holders
72 fDir.replace("<workdir>", defdir);
73 // Index of first place-holder
74 iph = fDir.find("<effuser>");
75 int iu = fDir.find("<u>");
76 int ius = fDir.find("<user>");
77 if (iu != STR_NPOS)
78 if ((iph != STR_NPOS && iu < iph) || (iph == STR_NPOS)) iph = iu;
79 if (ius != STR_NPOS)
80 if ((iph != STR_NPOS && ius < iph) || (iph == STR_NPOS)) iph = ius;
81 // Replace supported place-holders
82 fDir.replace("<effuser>", fgUI.fUser);
83 fDir.replace("<u>", initus);
84 fDir.replace("<user>", ui.fUser);
85 } else {
86 if (changeown || ui.fUser == fgUI.fUser) {
87 // Default: $HOME/proof
88 fDir = ui.fHomeDir;
89 if (!fDir.endswith('/'))
90 fDir += "/";
91 fDir += ".proof";
92 } else {
93 // ~daemon_owner/.proof/<user>
95 if (!fDir.endswith('/'))
96 fDir += "/";
97 fDir += ".proof/";
98 fDir += ui.fUser;
99 }
100 }
101 TRACE(REQ, "work dir = " << fDir);
102
103 // Make sure the directory exists
104 if (iph > -1) {
105 // Recursively ...
106 XrdOucString path, sb;
107 path.assign(fDir, 0, iph - 1);
108 int from = iph;
109 while ((from = fDir.tokenize(sb, from, '/')) != -1) {
110 path += sb;
111 if (XrdProofdAux::AssertDir(path.c_str(), ui, changeown) == -1) {
112 fErrMsg += "unable to create work dir: ";
113 fErrMsg += path;
114 TRACE(XERR, fErrMsg);
115 return;
116 }
117 path += "/";
118 }
119 } else {
120 if (XrdProofdAux::AssertDir(fDir.c_str(), ui, changeown) == -1) {
121 fErrMsg += "unable to create work dir: ";
122 fErrMsg += fDir;
123 TRACE(XERR, fErrMsg);
124 return;
125 }
126 }
127
128 // Dirs to be asserted
129 const char *basicdirs[4] = { "/cache", "/packages", "/.creds", "/queries" };
130 int i = 0;
131 int n = (full) ? 4 : 3;
132 for (i = 0; i < n; i++) {
133 XrdOucString dir = fDir;
134 dir += basicdirs[i];
135 if (XrdProofdAux::AssertDir(dir.c_str(), ui, changeown) == -1) {
136 fErrMsg += "unable to create dir: ";
137 fErrMsg += dir;
138 TRACE(XERR, fErrMsg);
139 return;
140 }
141 }
142
143 // Set validity
144 fValid = 1;
145
146 // Trim old terminated sessions
148}
149
150////////////////////////////////////////////////////////////////////////////////
151/// Compare times from session tag strings
152
153bool XpdSessionTagComp(XrdOucString *&lhs, XrdOucString *&rhs)
154{
155 if (!lhs || !rhs)
156 return 1;
157
158 // Left hand side
159 XrdOucString ll(*lhs);
160 ll.erase(ll.rfind('-'));
161 ll.erase(0, ll.rfind('-')+1);
162 int tl = strtol(ll.c_str(), 0, 10);
163
164 // Right hand side
165 XrdOucString rr(*rhs);
166 rr.erase(rr.rfind('-'));
167 rr.erase(0, rr.rfind('-')+1);
168 int tr = strtol(rr.c_str(), 0, 10);
169
170 // Done
171 return ((tl < tr) ? 0 : 1);
172}
173
174#if defined(__sun)
175
176////////////////////////////////////////////////////////////////////////////////
177/// Sort ascendingly the list.
178/// Function used on Solaris where std::list::sort() does not support an
179/// alternative comparison algorithm.
180
181static void Sort(std::list<XrdOucString *> *lst)
182{
183 // Check argument
184 if (!lst)
185 return;
186
187 // If empty or just one element, nothing to do
188 if (lst->size() < 2)
189 return;
190
191 // Fill a temp array with the current status
192 XrdOucString **ta = new XrdOucString *[lst->size()];
193 std::list<XrdOucString *>::iterator i;
194 int n = 0;
195 for (i = lst->begin(); i != lst->end(); ++i)
196 ta[n++] = *i;
197
198 // Now start the loops
199 XrdOucString *tmp = 0;
200 bool notyet = 1;
201 int jold = 0;
202 while (notyet) {
203 int j = jold;
204 while (j < n - 1) {
205 if (XpdSessionTagComp(ta[j], ta[j+1]))
206 break;
207 j++;
208 }
209 if (j >= n - 1) {
210 notyet = 0;
211 } else {
212 jold = j + 1;
213 XPDSWAP(ta[j], ta[j+1], tmp);
214 int k = j;
215 while (k > 0) {
216 if (!XpdSessionTagComp(ta[k], ta[k-1])) {
217 XPDSWAP(ta[k], ta[k-1], tmp);
218 } else {
219 break;
220 }
221 k--;
222 }
223 }
224 }
225
226 // Empty the original list
227 lst->clear();
228
229 // Fill it again
230 while (n--)
231 lst->push_back(ta[n]);
232
233 // Clean up
234 delete[] ta;
235}
236#endif
237
238////////////////////////////////////////////////////////////////////////////////
239/// Scan the sandbox for sessions working dirs and return their
240/// sorted (according to creation time, first is the newest) list
241/// in 'sdirs'.
242/// The option 'opt' may have 3 values:
243/// 0 all working dirs are kept
244/// 1 active sessions only
245/// 2 terminated sessions only
246/// 3 search entry containing 'tag' and fill tag with
247/// the full entry name; if defined, sdirs is filled
248/// Returns -1 otherwise in case of failure.
249/// In case of success returns 0 for opt < 3, 1 if found or 0 if not
250/// found for opt == 3.
251
252int XrdProofdSandbox::GetSessionDirs(int opt, std::list<XrdOucString *> *sdirs,
253 XrdOucString *tag)
254{
255 XPDLOC(CMGR, "Sandbox::GetSessionDirs")
256
257 // If unknown take all
258 opt = (opt >= 0 && opt <= 3) ? opt : 0;
259
260 // Check inputs
261 if ((opt < 3 && !sdirs) || (opt == 3 && !tag)) {
262 TRACE(XERR, "invalid inputs");
263 return -1;
264 }
265
266 TRACE(DBG, "opt: "<<opt<<", dir: "<<fDir);
267
268 // Open dir
269 DIR *dir = opendir(fDir.c_str());
270 if (!dir) {
271 TRACE(XERR, "cannot open dir "<<fDir<< " (errno: "<<errno<<")");
272 return -1;
273 }
274
275 // Scan the directory, and save the paths for terminated sessions
276 // into a list
277 bool found = 0;
278 struct dirent *ent = 0;
279 while ((ent = (struct dirent *)readdir(dir))) {
280 if (!strncmp(ent->d_name, "session-", 8)) {
281 bool keep = 1;
282 if (opt == 3 && tag->length() > 0) {
283 if (strstr(ent->d_name, tag->c_str())) {
284 *tag = ent->d_name;
285 found = 1;
286 }
287 } else {
288 if (opt > 0) {
289 XrdOucString fterm(fDir.c_str());
290 fterm += '/';
291 fterm += ent->d_name;
292 fterm += "/.terminated";
293 int rc = access(fterm.c_str(), F_OK);
294 if ((opt == 1 && rc == 0) || (opt == 2 && rc != 0))
295 keep = 0;
296 }
297 }
298 TRACE(HDBG, "found entry "<<ent->d_name<<", keep: "<<keep);
299 if (sdirs && keep)
300 sdirs->push_back(new XrdOucString(ent->d_name));
301 }
302 }
303
304 // Close the directory
305 closedir(dir);
306
307 // Sort the list
308 if (sdirs)
309#if !defined(__sun)
310 sdirs->sort(&XpdSessionTagComp);
311#else
312 Sort(sdirs);
313#endif
314
315 // Done
316 return ((opt == 3 && found) ? 1 : 0);
317}
318
319////////////////////////////////////////////////////////////////////////////////
320/// Record entry for new proofserv session tagged 'tag' in the active
321/// sessions file (<SandBox>/.sessions). The file is created if needed.
322/// Return 0 on success, -1 on error.
323
325{
326 XPDLOC(CMGR, "Sandbox::AddSession")
327
328 // Check inputs
329 if (!tag) {
330 XPDPRT("invalid input");
331 return -1;
332 }
333 TRACE(DBG, "tag:"<<tag);
334
335 XrdSysPrivGuard pGuard((uid_t)0, (gid_t)0);
336 if (XpdBadPGuard(pGuard, fUI.fUid) && fChangeOwn) {
337 TRACE(XERR, "could not get privileges");
338 return -1;
339 }
340
341 // File name
342 XrdOucString fn = fDir;
343 fn += "/.sessions";
344
345 // Open the file for appending
346 FILE *fact = fopen(fn.c_str(), "a+");
347 if (!fact) {
348 TRACE(XERR, "cannot open file "<<fn<<" for appending (errno: "<<errno<<")");
349 return -1;
350 }
351
352 // Lock the file
353 lseek(fileno(fact), 0, SEEK_SET);
354 if (lockf(fileno(fact), F_LOCK, 0) == -1) {
355 TRACE(XERR, "cannot lock file "<<fn<<" (errno: "<<errno<<")");
356 fclose(fact);
357 return -1;
358 }
359
360 bool writeout = 1;
361
362 // Check if already there
363 std::list<XrdOucString *> actln;
364 char ln[1024];
365 while (fgets(ln, sizeof(ln), fact)) {
366 // Get rid of '\n'
367 if (ln[strlen(ln)-1] == '\n')
368 ln[strlen(ln)-1] = '\0';
369 // Skip empty or comment lines
370 if (strlen(ln) <= 0 || ln[0] == '#')
371 continue;
372 // Count if not the one we want to remove
373 if (strstr(ln, tag))
374 writeout = 0;
375 }
376
377 // Append the session unique tag
378 if (writeout) {
379 lseek(fileno(fact), 0, SEEK_END);
380 fprintf(fact, "%s\n", tag);
381 }
382
383 // Unlock the file
384 lseek(fileno(fact), 0, SEEK_SET);
385 if (lockf(fileno(fact), F_ULOCK, 0) == -1)
386 TRACE(XERR, "cannot unlock file "<<fn<<" (errno: "<<errno<<")");
387
388 // Close the file
389 fclose(fact);
390
391 // We are done
392 return 0;
393}
394
395////////////////////////////////////////////////////////////////////////////////
396/// Guess session tag completing 'tag' (typically "-<pid>") by scanning the
397/// active session file or the session dir.
398/// In case of success, tag is filled with the full tag and 0 is returned.
399/// In case of failure, -1 is returned.
400
401int XrdProofdSandbox::GuessTag(XrdOucString &tag, int ridx)
402{
403 XPDLOC(CMGR, "Sandbox::GuessTag")
404
405 TRACE(DBG, "tag: "<<tag);
406
407 bool found = 0;
408 bool last = (tag == "last") ? 1 : 0;
409
410 if (!last && tag.length() > 0) {
411 // Scan the sessions file
412 XrdOucString fn = fDir;
413 fn += "/.sessions";
414
415 // Open the file for reading
416 FILE *fact = fopen(fn.c_str(), "a+");
417 if (fact) {
418 // Lock the file
419 if (lockf(fileno(fact), F_LOCK, 0) == 0) {
420 // Read content, if already existing
421 char ln[1024];
422 while (fgets(ln, sizeof(ln), fact)) {
423 // Get rid of '\n'
424 if (ln[strlen(ln)-1] == '\n')
425 ln[strlen(ln)-1] = '\0';
426 // Skip empty or comment lines
427 if (strlen(ln) <= 0 || ln[0] == '#')
428 continue;
429 // Count if not the one we want to remove
430 if (!strstr(ln, tag.c_str())) {
431 tag = ln;
432 found = 1;
433 break;
434 }
435 }
436 // Unlock the file
437 lseek(fileno(fact), 0, SEEK_SET);
438 if (lockf(fileno(fact), F_ULOCK, 0) == -1)
439 TRACE(DBG, "cannot unlock file "<<fn<<" ; fact: "<<fact<<
440 ", fd: "<< fileno(fact) << " (errno: "<<errno<<")");
441
442 } else {
443 TRACE(DBG, "cannot lock file: "<<fn<<" ; fact: "<<fact<<
444 ", fd: "<< fileno(fact) << " (errno: "<<errno<<")");
445 }
446 // Close the file
447 fclose(fact);
448
449 } else {
450 TRACE(DBG, "cannot open file "<<fn<<
451 " for reading (errno: "<<errno<<")");
452 }
453 }
454
455 if (!found) {
456
457 // Search the tag in the dirs
458 std::list<XrdOucString *> staglst;
459 staglst.clear();
460 int rc = GetSessionDirs(3, &staglst, &tag);
461 if (rc < 0) {
462 TRACE(XERR, "cannot scan dir "<<fDir);
463 return -1;
464 }
465 found = (rc == 1) ? 1 : 0;
466
467 if (!found && !staglst.empty()) {
468 // Take last one, if required
469 if (last) {
470 tag = staglst.front()->c_str();
471 found = 1;
472 } else {
473 if (ridx < 0) {
474 int itag = ridx;
475 // Reiterate back
476 std::list<XrdOucString *>::iterator i;
477 for (i = staglst.begin(); i != staglst.end(); ++i) {
478 if (itag == 0) {
479 tag = (*i)->c_str();
480 found = 1;
481 break;
482 }
483 itag++;
484 }
485 }
486 }
487 }
488 // Cleanup
489 staglst.clear();
490 // Correct the tag
491 if (found) {
492 tag.replace("session-", "");
493 } else {
494 TRACE(DBG, "tag "<<tag<<" not found in dir");
495 }
496 }
497
498 // We are done
499 return ((found) ? 0 : -1);
500}
501
502////////////////////////////////////////////////////////////////////////////////
503/// Move record for tag from the active sessions file to the old
504/// sessions file (<SandBox>/.sessions). The active file is removed if
505/// empty after the operation. The old sessions file is created if needed.
506/// Return 0 on success, -1 on error.
507
509{
510 XPDLOC(CMGR, "Sandbox::RemoveSession")
511
512 char ln[1024];
513
514 // Check inputs
515 if (!tag) {
516 TRACE(XERR, "invalid input");
517 return -1;
518 }
519 TRACE(DBG, "tag:"<<tag);
520
521 XrdSysPrivGuard pGuard((uid_t)0, (gid_t)0);
522 if (XpdBadPGuard(pGuard, fUI.fUid) && fChangeOwn) {
523 TRACE(XERR, "could not get privileges");
524 return -1;
525 }
526
527 // Update of the active file
528 XrdOucString fna = fDir;
529 fna += "/.sessions";
530
531 // Open the file
532 FILE *fact = fopen(fna.c_str(), "a+");
533 if (!fact) {
534 TRACE(XERR, "cannot open file "<<fna<<" (errno: "<<errno<<")");
535 return -1;
536 }
537
538 // Lock the file
539 if (lockf(fileno(fact), F_LOCK, 0) == -1) {
540 TRACE(XERR, "cannot lock file "<<fna<<" (errno: "<<errno<<")");
541 fclose(fact);
542 return -1;
543 }
544
545 // Read content, if already existing
546 std::list<XrdOucString *> actln;
547 while (fgets(ln, sizeof(ln), fact)) {
548 // Get rid of '\n'
549 if (ln[strlen(ln)-1] == '\n')
550 ln[strlen(ln)-1] = '\0';
551 // Skip empty or comment lines
552 if (strlen(ln) <= 0 || ln[0] == '#')
553 continue;
554 // Count if not the one we want to remove
555 if (!strstr(ln, tag))
556 actln.push_back(new XrdOucString(ln));
557 }
558
559 // Truncate the file
560 if (ftruncate(fileno(fact), 0) == -1) {
561 TRACE(XERR, "cannot truncate file "<<fna<<" (errno: "<<errno<<")");
562 lseek(fileno(fact), 0, SEEK_SET);
563 if (lockf(fileno(fact), F_ULOCK, 0) != 0)
564 TRACE(XERR, "cannot lockf file "<<fna<<" (errno: "<<errno<<")");
565 fclose(fact);
566 return -1;
567 }
568
569 // If active sessions still exist, write out new composition
570 bool unlk = 1;
571 if (!actln.empty()) {
572 unlk = 0;
573 std::list<XrdOucString *>::iterator i;
574 for (i = actln.begin(); i != actln.end(); ++i) {
575 fprintf(fact, "%s\n", (*i)->c_str());
576 delete (*i);
577 }
578 }
579
580 // Unlock the file
581 lseek(fileno(fact), 0, SEEK_SET);
582 if (lockf(fileno(fact), F_ULOCK, 0) == -1)
583 TRACE(DBG, "cannot unlock file "<<fna<<" (errno: "<<errno<<")");
584
585 // Close the file
586 fclose(fact);
587
588 // Unlink the file if empty
589 if (unlk)
590 if (unlink(fna.c_str()) == -1)
591 TRACE(DBG, "cannot unlink file "<<fna<<" (errno: "<<errno<<")");
592
593 // Flag the session as closed
594 XrdOucString fterm = fDir;
595 fterm += (strstr(tag,"session-")) ? "/" : "/session-";
596 fterm += tag;
597 fterm += "/.terminated";
598 // Create the file
599 FILE *ft = fopen(fterm.c_str(), "w");
600 if (!ft) {
601 TRACE(XERR, "cannot open file "<<fterm<<" (errno: "<<errno<<")");
602 return -1;
603 }
604 fclose(ft);
605
606 // Done
607 return 0;
608}
609
610////////////////////////////////////////////////////////////////////////////////
611/// If the static fgMaxOldLogs > 0, logs for a fgMaxOldLogs number of sessions
612/// are kept in the sandbox; working dirs for sessions in excess are removed.
613/// By default logs for the last 10 sessions are kept; the limit can be changed
614/// via the static method XrdProofdClient::SetMaxOldLogs.
615/// Return 0 on success, -1 on error.
616
618{
619 XPDLOC(CMGR, "Sandbox::TrimSessionDirs")
620
621 TRACE(DBG, "maxold:"<<fgMaxOldSessions);
622
623 // To avoid dead locks we must close the file and do the mv actions after
624 XrdOucString tobemv, fnact = fDir;
625 fnact += "/.sessions";
626 FILE *f = fopen(fnact.c_str(), "r");
627 if (f) {
628 char ln[1024];
629 while (fgets(ln, sizeof(ln), f)) {
630 if (ln[strlen(ln)-1] == '\n')
631 ln[strlen(ln)-1] = 0;
632 char *p = strrchr(ln, '-');
633 if (p) {
634 int pid = strtol(p+1, 0, 10);
636 tobemv += ln;
637 tobemv += '|';
638 }
639 }
640 }
641 fclose(f);
642 }
643
644 XrdSysPrivGuard pGuard((uid_t)0, (gid_t)0);
645 if (XpdBadPGuard(pGuard, fUI.fUid) && fChangeOwn) {
646 TRACE(XERR, "could not get privileges to trim directories");
647 return -1;
648 }
649
650 // Mv inactive sessions, if needed
651 if (tobemv.length() > 0) {
652 char del = '|';
653 XrdOucString tag;
654 int from = 0;
655 while ((from = tobemv.tokenize(tag, from, del)) != -1) {
656 if (RemoveSession(tag.c_str()) == -1)
657 TRACE(XERR, "problems tagging session as old in sandbox");
658 }
659 }
660
661 // If a limit on the number of sessions dirs is set, apply it
662 if (fgMaxOldSessions > 0) {
663
664 // Get list of terminated session working dirs
665 std::list<XrdOucString *> staglst;
666 staglst.clear();
667 if (GetSessionDirs(2, &staglst) != 0) {
668 TRACE(XERR, "cannot get list of dirs ");
669 return -1;
670 }
671 TRACE(DBG, "number of working dirs: "<<staglst.size());
672
673 if (TRACING(HDBG)) {
674 std::list<XrdOucString *>::iterator i;
675 for (i = staglst.begin(); i != staglst.end(); ++i) {
676 TRACE(HDBG, "found "<<(*i)->c_str());
677 }
678 }
679
680 // Remove the oldest, if needed
681 while ((int)staglst.size() > fgMaxOldSessions) {
682 XrdOucString *s = staglst.back();
683 if (s) {
684 TRACE(HDBG, "removing "<<s->c_str());
685 // Remove associated workdir
686 XrdOucString rmcmd = "/bin/rm -rf ";
687 rmcmd += fDir;
688 rmcmd += '/';
689 rmcmd += s->c_str();
690 if (system(rmcmd.c_str()) == -1)
691 TRACE(XERR, "cannot invoke system("<<rmcmd<<") (errno: "<<errno<<")");
692 // Delete the string
693 delete s;
694 }
695 // Remove the last element
696 staglst.pop_back();
697 }
698
699 // Clear the list
700 staglst.clear();
701 }
702
703 // Done
704 return 0;
705}
706
707
#define f(i)
Definition: RSha256.hxx:104
#define TRACE(Flag, Args)
Definition: TGHtml.h:120
#define XPDSWAP(a, b, t)
Definition: XrdProofdAux.h:361
#define XpdBadPGuard(g, u)
Definition: XrdProofdAux.h:365
bool XpdSessionTagComp(XrdOucString *&lhs, XrdOucString *&rhs)
Compare times from session tag strings.
#define XPDPRT(x)
#define XPDLOC(d, x)
#define TRACING(x)
XrdOucString fUser
Definition: XrdProofdAux.h:40
XrdOucString fHomeDir
Definition: XrdProofdAux.h:42
static int GetUserInfo(const char *usr, XrdProofUI &ui)
Get information about user 'usr' in a thread safe way.
static int AssertDir(const char *path, XrdProofUI ui, bool changeown)
Make sure that 'path' exists and is owned by the entity described by 'ui'.
static int VerifyProcessByID(int pid, const char *pname="proofserv")
Check if a process named 'pname' and process 'pid' is still in the process table.
XrdProofdSandbox(XrdProofUI ui, bool full, bool changeown)
Assert existence on the sandbox for the user defined by 'ui'.
static XrdProofUI fgUI
static XrdOucString fgWorkdir
static int fgMaxOldSessions
int GuessTag(XrdOucString &tag, int ridx=1)
Guess session tag completing 'tag' (typically "-<pid>") by scanning the active session file or the se...
XrdOucString fDir
int AddSession(const char *tag)
Record entry for new proofserv session tagged 'tag' in the active sessions file (<SandBox>/....
int GetSessionDirs(int opt, std::list< XrdOucString * > *sdirs, XrdOucString *tag=0)
Scan the sandbox for sessions working dirs and return their sorted (according to creation time,...
XrdOucString fErrMsg
int TrimSessionDirs()
If the static fgMaxOldLogs > 0, logs for a fgMaxOldLogs number of sessions are kept in the sandbox; w...
int RemoveSession(const char *tag)
Move record for tag from the active sessions file to the old sessions file (<SandBox>/....
const Int_t n
Definition: legend1.C:16
static constexpr double s
void Sort(Index n, const Element *a, Index *index, Bool_t down=kTRUE)
Definition: TMathBase.h:362
int changeown(const std::string &path, uid_t u, gid_t g)
Change the ownership of 'path' to the entity described by {u,g}.
Definition: proofexecv.cxx:738