00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "XrdProofdPlatform.h"
00022
00023 #include "XrdProofdSandbox.h"
00024 #include "XrdSys/XrdSysPriv.hh"
00025
00026
00027 #include "XrdProofdTrace.h"
00028
00029
00030 int XrdProofdSandbox::fgMaxOldSessions = 10;
00031 XrdOucString XrdProofdSandbox::fgWorkdir = "";
00032 XrdProofUI XrdProofdSandbox::fgUI;
00033
00034
00035 XrdProofdSandbox::XrdProofdSandbox(XrdProofUI ui, bool full, bool changeown)
00036 : fChangeOwn(changeown), fUI(ui)
00037 {
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 XPDLOC(CMGR, "XrdProofdSandbox")
00050
00051 fValid = 0;
00052
00053
00054 if (fgUI.fUid < 0)
00055 XrdProofdAux::GetUserInfo(getuid(), fgUI);
00056
00057
00058 if (fgWorkdir.length() > 0) {
00059
00060 fDir = fgWorkdir;
00061 if (!fDir.endswith('/'))
00062 fDir += "/";
00063 fDir += ui.fUser;
00064 } else {
00065 if (changeown || ui.fUser == fgUI.fUser) {
00066
00067 fDir = ui.fHomeDir;
00068 if (!fDir.endswith('/'))
00069 fDir += "/";
00070 fDir += ".proof";
00071 } else {
00072
00073 fDir = fgUI.fHomeDir;
00074 if (!fDir.endswith('/'))
00075 fDir += "/";
00076 fDir += ".proof/";
00077 fDir += ui.fUser;
00078 }
00079 }
00080 TRACE(REQ, "work dir = " << fDir);
00081
00082
00083 if (XrdProofdAux::AssertDir(fDir.c_str(), ui, changeown) == -1) {
00084 fErrMsg += "unable to create work dir: ";
00085 fErrMsg += fDir;
00086 TRACE(XERR, fErrMsg);
00087 return;
00088 }
00089
00090
00091 const char *basicdirs[4] = { "/cache", "/packages", "/.creds", "/queries" };
00092 int i = 0;
00093 int n = (full) ? 4 : 3;
00094 for (i = 0; i < n; i++) {
00095 XrdOucString dir = fDir;
00096 dir += basicdirs[i];
00097 if (XrdProofdAux::AssertDir(dir.c_str(), ui, changeown) == -1) {
00098 fErrMsg += "unable to create dir: ";
00099 fErrMsg += dir;
00100 TRACE(XERR, fErrMsg);
00101 return;
00102 }
00103 }
00104
00105
00106 fValid = 1;
00107
00108
00109 TrimSessionDirs();
00110 }
00111
00112
00113 bool XpdSessionTagComp(XrdOucString *&lhs, XrdOucString *&rhs)
00114 {
00115
00116
00117 if (!lhs || !rhs)
00118 return 1;
00119
00120
00121 XrdOucString ll(*lhs);
00122 ll.erase(ll.rfind('-'));
00123 ll.erase(0, ll.rfind('-')+1);
00124 int tl = strtol(ll.c_str(), 0, 10);
00125
00126
00127 XrdOucString rr(*rhs);
00128 rr.erase(rr.rfind('-'));
00129 rr.erase(0, rr.rfind('-')+1);
00130 int tr = strtol(rr.c_str(), 0, 10);
00131
00132
00133 return ((tl < tr) ? 0 : 1);
00134 }
00135
00136 #if defined(__sun)
00137
00138
00139 static void Sort(std::list<XrdOucString *> *lst)
00140 {
00141
00142
00143
00144
00145
00146 if (!lst)
00147 return;
00148
00149
00150 if (lst->size() < 2)
00151 return;
00152
00153
00154 XrdOucString **ta = new XrdOucString *[lst->size()];
00155 std::list<XrdOucString *>::iterator i;
00156 int n = 0;
00157 for (i = lst->begin(); i != lst->end(); ++i)
00158 ta[n++] = *i;
00159
00160
00161 XrdOucString *tmp = 0;
00162 bool notyet = 1;
00163 int jold = 0;
00164 while (notyet) {
00165 int j = jold;
00166 while (j < n - 1) {
00167 if (XpdSessionTagComp(ta[j], ta[j+1]))
00168 break;
00169 j++;
00170 }
00171 if (j >= n - 1) {
00172 notyet = 0;
00173 } else {
00174 jold = j + 1;
00175 XPDSWAP(ta[j], ta[j+1], tmp);
00176 int k = j;
00177 while (k > 0) {
00178 if (!XpdSessionTagComp(ta[k], ta[k-1])) {
00179 XPDSWAP(ta[k], ta[k-1], tmp);
00180 } else {
00181 break;
00182 }
00183 k--;
00184 }
00185 }
00186 }
00187
00188
00189 lst->clear();
00190
00191
00192 while (n--)
00193 lst->push_back(ta[n]);
00194
00195
00196 delete[] ta;
00197 }
00198 #endif
00199
00200
00201 int XrdProofdSandbox::GetSessionDirs(int opt, std::list<XrdOucString *> *sdirs,
00202 XrdOucString *tag)
00203 {
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 XPDLOC(CMGR, "Sandbox::GetSessionDirs")
00217
00218
00219 opt = (opt >= 0 && opt <= 3) ? opt : 0;
00220
00221
00222 if ((opt < 3 && !sdirs) || (opt == 3 && !tag)) {
00223 TRACE(XERR, "invalid inputs");
00224 return -1;
00225 }
00226
00227 TRACE(DBG, "opt: "<<opt<<", dir: "<<fDir);
00228
00229
00230 DIR *dir = opendir(fDir.c_str());
00231 if (!dir) {
00232 TRACE(XERR, "cannot open dir "<<fDir<< " (errno: "<<errno<<")");
00233 return -1;
00234 }
00235
00236
00237
00238 bool found = 0;
00239 struct dirent *ent = 0;
00240 while ((ent = (struct dirent *)readdir(dir))) {
00241 if (!strncmp(ent->d_name, "session-", 8)) {
00242 bool keep = 1;
00243 if (opt == 3 && tag->length() > 0) {
00244 if (strstr(ent->d_name, tag->c_str())) {
00245 *tag = ent->d_name;
00246 found = 1;
00247 }
00248 } else {
00249 if (opt > 0) {
00250 XrdOucString fterm(fDir.c_str());
00251 fterm += '/';
00252 fterm += ent->d_name;
00253 fterm += "/.terminated";
00254 int rc = access(fterm.c_str(), F_OK);
00255 if ((opt == 1 && rc == 0) || (opt == 2 && rc != 0))
00256 keep = 0;
00257 }
00258 }
00259 TRACE(HDBG, "found entry "<<ent->d_name<<", keep: "<<keep);
00260 if (sdirs && keep)
00261 sdirs->push_back(new XrdOucString(ent->d_name));
00262 }
00263 }
00264
00265
00266 closedir(dir);
00267
00268
00269 if (sdirs)
00270 #if !defined(__sun)
00271 sdirs->sort(&XpdSessionTagComp);
00272 #else
00273 Sort(sdirs);
00274 #endif
00275
00276
00277 return ((opt == 3 && found) ? 1 : 0);
00278 }
00279
00280
00281 int XrdProofdSandbox::AddSession(const char *tag)
00282 {
00283
00284
00285
00286 XPDLOC(CMGR, "Sandbox::AddSession")
00287
00288
00289 if (!tag) {
00290 XPDPRT("invalid input");
00291 return -1;
00292 }
00293 TRACE(DBG, "tag:"<<tag);
00294
00295 XrdSysPrivGuard pGuard((uid_t)0, (gid_t)0);
00296 if (XpdBadPGuard(pGuard, fUI.fUid) && fChangeOwn) {
00297 TRACE(XERR, "could not get privileges");
00298 return -1;
00299 }
00300
00301
00302 XrdOucString fn = fDir;
00303 fn += "/.sessions";
00304
00305
00306 FILE *fact = fopen(fn.c_str(), "a+");
00307 if (!fact) {
00308 TRACE(XERR, "cannot open file "<<fn<<" for appending (errno: "<<errno<<")");
00309 return -1;
00310 }
00311
00312
00313 lseek(fileno(fact), 0, SEEK_SET);
00314 if (lockf(fileno(fact), F_LOCK, 0) == -1) {
00315 TRACE(XERR, "cannot lock file "<<fn<<" (errno: "<<errno<<")");
00316 fclose(fact);
00317 return -1;
00318 }
00319
00320 bool writeout = 1;
00321
00322
00323 std::list<XrdOucString *> actln;
00324 char ln[1024];
00325 while (fgets(ln, sizeof(ln), fact)) {
00326
00327 if (ln[strlen(ln)-1] == '\n')
00328 ln[strlen(ln)-1] = '\0';
00329
00330 if (strlen(ln) <= 0 || ln[0] == '#')
00331 continue;
00332
00333 if (strstr(ln, tag))
00334 writeout = 0;
00335 }
00336
00337
00338 if (writeout) {
00339 lseek(fileno(fact), 0, SEEK_END);
00340 fprintf(fact, "%s\n", tag);
00341 }
00342
00343
00344 lseek(fileno(fact), 0, SEEK_SET);
00345 if (lockf(fileno(fact), F_ULOCK, 0) == -1)
00346 TRACE(XERR, "cannot unlock file "<<fn<<" (errno: "<<errno<<")");
00347
00348
00349 fclose(fact);
00350
00351
00352 return 0;
00353 }
00354
00355
00356 int XrdProofdSandbox::GuessTag(XrdOucString &tag, int ridx)
00357 {
00358
00359
00360
00361
00362 XPDLOC(CMGR, "Sandbox::GuessTag")
00363
00364 TRACE(DBG, "tag: "<<tag);
00365
00366 bool found = 0;
00367 bool last = (tag == "last") ? 1 : 0;
00368
00369 if (!last && tag.length() > 0) {
00370
00371 XrdOucString fn = fDir;
00372 fn += "/.sessions";
00373
00374
00375 FILE *fact = fopen(fn.c_str(), "a+");
00376 if (fact) {
00377
00378 if (lockf(fileno(fact), F_LOCK, 0) == 0) {
00379
00380 char ln[1024];
00381 while (fgets(ln, sizeof(ln), fact)) {
00382
00383 if (ln[strlen(ln)-1] == '\n')
00384 ln[strlen(ln)-1] = '\0';
00385
00386 if (strlen(ln) <= 0 || ln[0] == '#')
00387 continue;
00388
00389 if (!strstr(ln, tag.c_str())) {
00390 tag = ln;
00391 found = 1;
00392 break;
00393 }
00394 }
00395
00396 lseek(fileno(fact), 0, SEEK_SET);
00397 if (lockf(fileno(fact), F_ULOCK, 0) == -1)
00398 TRACE(DBG, "cannot unlock file "<<fn<<" ; fact: "<<fact<<
00399 ", fd: "<< fileno(fact) << " (errno: "<<errno<<")");
00400
00401 } else {
00402 TRACE(DBG, "cannot lock file: "<<fn<<" ; fact: "<<fact<<
00403 ", fd: "<< fileno(fact) << " (errno: "<<errno<<")");
00404 }
00405
00406 fclose(fact);
00407
00408 } else {
00409 TRACE(DBG, "cannot open file "<<fn<<
00410 " for reading (errno: "<<errno<<")");
00411 }
00412 }
00413
00414 if (!found) {
00415
00416
00417 std::list<XrdOucString *> staglst;
00418 staglst.clear();
00419 int rc = GetSessionDirs(3, &staglst, &tag);
00420 if (rc < 0) {
00421 TRACE(XERR, "cannot scan dir "<<fDir);
00422 return -1;
00423 }
00424 found = (rc == 1) ? 1 : 0;
00425
00426 if (!found && staglst.size() > 0) {
00427
00428 if (last) {
00429 tag = staglst.front()->c_str();
00430 found = 1;
00431 } else {
00432 if (ridx < 0) {
00433 int itag = ridx;
00434
00435 std::list<XrdOucString *>::iterator i;
00436 for (i = staglst.begin(); i != staglst.end(); i++) {
00437 if (itag == 0) {
00438 tag = (*i)->c_str();
00439 found = 1;
00440 break;
00441 }
00442 itag++;
00443 }
00444 }
00445 }
00446 }
00447
00448 staglst.clear();
00449
00450 if (found) {
00451 tag.replace("session-", "");
00452 } else {
00453 TRACE(DBG, "tag "<<tag<<" not found in dir");
00454 }
00455 }
00456
00457
00458 return ((found) ? 0 : -1);
00459 }
00460
00461
00462 int XrdProofdSandbox::RemoveSession(const char *tag)
00463 {
00464
00465
00466
00467
00468 XPDLOC(CMGR, "Sandbox::RemoveSession")
00469
00470 char ln[1024];
00471
00472
00473 if (!tag) {
00474 TRACE(XERR, "invalid input");
00475 return -1;
00476 }
00477 TRACE(DBG, "tag:"<<tag);
00478
00479 XrdSysPrivGuard pGuard((uid_t)0, (gid_t)0);
00480 if (XpdBadPGuard(pGuard, fUI.fUid) && fChangeOwn) {
00481 TRACE(XERR, "could not get privileges");
00482 return -1;
00483 }
00484
00485
00486 XrdOucString fna = fDir;
00487 fna += "/.sessions";
00488
00489
00490 FILE *fact = fopen(fna.c_str(), "a+");
00491 if (!fact) {
00492 TRACE(XERR, "cannot open file "<<fna<<" (errno: "<<errno<<")");
00493 return -1;
00494 }
00495
00496
00497 if (lockf(fileno(fact), F_LOCK, 0) == -1) {
00498 TRACE(XERR, "cannot lock file "<<fna<<" (errno: "<<errno<<")");
00499 fclose(fact);
00500 return -1;
00501 }
00502
00503
00504 std::list<XrdOucString *> actln;
00505 while (fgets(ln, sizeof(ln), fact)) {
00506
00507 if (ln[strlen(ln)-1] == '\n')
00508 ln[strlen(ln)-1] = '\0';
00509
00510 if (strlen(ln) <= 0 || ln[0] == '#')
00511 continue;
00512
00513 if (!strstr(ln, tag))
00514 actln.push_back(new XrdOucString(ln));
00515 }
00516
00517
00518 if (ftruncate(fileno(fact), 0) == -1) {
00519 TRACE(XERR, "cannot truncate file "<<fna<<" (errno: "<<errno<<")");
00520 lseek(fileno(fact), 0, SEEK_SET);
00521 if (lockf(fileno(fact), F_ULOCK, 0) != 0)
00522 TRACE(XERR, "cannot lockf file "<<fna<<" (errno: "<<errno<<")");
00523 fclose(fact);
00524 return -1;
00525 }
00526
00527
00528 bool unlk = 1;
00529 if (actln.size() > 0) {
00530 unlk = 0;
00531 std::list<XrdOucString *>::iterator i;
00532 for (i = actln.begin(); i != actln.end(); ++i) {
00533 fprintf(fact, "%s\n", (*i)->c_str());
00534 delete (*i);
00535 }
00536 }
00537
00538
00539 lseek(fileno(fact), 0, SEEK_SET);
00540 if (lockf(fileno(fact), F_ULOCK, 0) == -1)
00541 TRACE(DBG, "cannot unlock file "<<fna<<" (errno: "<<errno<<")");
00542
00543
00544 fclose(fact);
00545
00546
00547 if (unlk)
00548 if (unlink(fna.c_str()) == -1)
00549 TRACE(DBG, "cannot unlink file "<<fna<<" (errno: "<<errno<<")");
00550
00551
00552 XrdOucString fterm = fDir;
00553 fterm += (strstr(tag,"session-")) ? "/" : "/session-";
00554 fterm += tag;
00555 fterm += "/.terminated";
00556
00557 FILE *ft = fopen(fterm.c_str(), "w");
00558 if (!ft) {
00559 TRACE(XERR, "cannot open file "<<fterm<<" (errno: "<<errno<<")");
00560 return -1;
00561 }
00562 fclose(ft);
00563
00564
00565 return 0;
00566 }
00567
00568
00569 int XrdProofdSandbox::TrimSessionDirs()
00570 {
00571
00572
00573
00574
00575
00576 XPDLOC(CMGR, "Sandbox::TrimSessionDirs")
00577
00578 TRACE(DBG, "maxold:"<<fgMaxOldSessions);
00579
00580
00581 XrdOucString tobemv, fnact = fDir;
00582 fnact += "/.sessions";
00583 FILE *f = fopen(fnact.c_str(), "r");
00584 if (f) {
00585 char ln[1024];
00586 while (fgets(ln, sizeof(ln), f)) {
00587 if (ln[strlen(ln)-1] == '\n')
00588 ln[strlen(ln)-1] = 0;
00589 char *p = strrchr(ln, '-');
00590 if (p) {
00591 int pid = strtol(p+1, 0, 10);
00592 if (!XrdProofdAux::VerifyProcessByID(pid)) {
00593 tobemv += ln;
00594 tobemv += '|';
00595 }
00596 }
00597 }
00598 fclose(f);
00599 }
00600
00601 XrdSysPrivGuard pGuard((uid_t)0, (gid_t)0);
00602 if (XpdBadPGuard(pGuard, fUI.fUid) && fChangeOwn) {
00603 TRACE(XERR, "could not get privileges to trim directories");
00604 return -1;
00605 }
00606
00607
00608 if (tobemv.length() > 0) {
00609 char del = '|';
00610 XrdOucString tag;
00611 int from = 0;
00612 while ((from = tobemv.tokenize(tag, from, del)) != -1) {
00613 if (RemoveSession(tag.c_str()) == -1)
00614 TRACE(XERR, "problems tagging session as old in sandbox");
00615 }
00616 }
00617
00618
00619 if (fgMaxOldSessions > 0) {
00620
00621
00622 std::list<XrdOucString *> staglst;
00623 staglst.clear();
00624 if (GetSessionDirs(2, &staglst) != 0) {
00625 TRACE(XERR, "cannot get list of dirs ");
00626 return -1;
00627 }
00628 TRACE(DBG, "number of working dirs: "<<staglst.size());
00629
00630 if (TRACING(HDBG)) {
00631 std::list<XrdOucString *>::iterator i;
00632 for (i = staglst.begin(); i != staglst.end(); ++i) {
00633 TRACE(HDBG, "found "<<(*i)->c_str());
00634 }
00635 }
00636
00637
00638 while ((int)staglst.size() > fgMaxOldSessions) {
00639 XrdOucString *s = staglst.back();
00640 if (s) {
00641 TRACE(HDBG, "removing "<<s->c_str());
00642
00643 XrdOucString rmcmd = "/bin/rm -rf ";
00644 rmcmd += fDir;
00645 rmcmd += '/';
00646 rmcmd += s->c_str();
00647 if (system(rmcmd.c_str()) == -1)
00648 TRACE(XERR, "cannot invoke system("<<rmcmd<<") (errno: "<<errno<<")");
00649
00650 delete s;
00651 }
00652
00653 staglst.pop_back();
00654 }
00655
00656
00657 staglst.clear();
00658 }
00659
00660
00661 return 0;
00662 }
00663
00664