00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 const char *XrdFrmConfigCVSID = "$Id: XrdFrmConfig.cc 38011 2011-02-08 18:35:57Z ganis $";
00014
00015 #include <unistd.h>
00016 #include <ctype.h>
00017 #include <dirent.h>
00018 #include <string.h>
00019 #include <stdio.h>
00020 #include <fcntl.h>
00021 #include <sys/param.h>
00022 #include <sys/types.h>
00023 #include <sys/socket.h>
00024 #include <sys/stat.h>
00025
00026 #include "Xrd/XrdInfo.hh"
00027 #include "XrdFrm/XrdFrmConfig.hh"
00028 #include "XrdFrm/XrdFrmMonitor.hh"
00029 #include "XrdFrm/XrdFrmTrace.hh"
00030 #include "XrdFrm/XrdFrmUtils.hh"
00031 #include "XrdNet/XrdNetCmsNotify.hh"
00032 #include "XrdNet/XrdNetDNS.hh"
00033 #include "XrdOss/XrdOss.hh"
00034 #include "XrdOss/XrdOssSpace.hh"
00035 #include "XrdOuc/XrdOuca2x.hh"
00036 #include "XrdOuc/XrdOucEnv.hh"
00037 #include "XrdOuc/XrdOucExport.hh"
00038 #include "XrdOuc/XrdOucMsubs.hh"
00039 #include "XrdOuc/XrdOucName2Name.hh"
00040 #include "XrdOuc/XrdOucProg.hh"
00041 #include "XrdOuc/XrdOucStream.hh"
00042 #include "XrdOuc/XrdOucPList.hh"
00043 #include "XrdOuc/XrdOucTList.hh"
00044 #include "XrdOuc/XrdOucTokenizer.hh"
00045 #include "XrdOuc/XrdOucUtils.hh"
00046 #include "XrdSys/XrdSysError.hh"
00047 #include "XrdSys/XrdSysHeaders.hh"
00048 #include "XrdSys/XrdSysLogger.hh"
00049 #include "XrdSys/XrdSysPlugin.hh"
00050 #include "XrdSys/XrdSysTimer.hh"
00051 #include "XrdSys/XrdSysPlatform.hh"
00052 #include "XrdSys/XrdSysPthread.hh"
00053
00054 using namespace XrdFrm;
00055
00056
00057
00058
00059
00060 class XrdFrmConfigSE
00061 {
00062 public:
00063
00064 XrdSysSemaphore mySem;
00065 int myFD;
00066 int seFD;
00067 int BLen;
00068 char Buff[32000];
00069
00070 XrdFrmConfigSE() : mySem(0), myFD(-1), seFD(-1), BLen(0) {}
00071 ~XrdFrmConfigSE() {}
00072 };
00073
00074
00075
00076
00077
00078 void *XrdFrmConfigMum(void *parg)
00079 {
00080 XrdFrmConfigSE *theSE = (XrdFrmConfigSE *)parg;
00081 char *bp = theSE->Buff;
00082 int n, bleft = sizeof(theSE->Buff)-2;
00083
00084
00085
00086 theSE->mySem.Post();
00087
00088
00089
00090 do {if ((n = read(theSE->myFD, bp, bleft)) <= 0)
00091 {if (!n || (n < 0 && errno != EINTR)) break;}
00092 bp += n;
00093 } while ((bleft -= n));
00094
00095
00096
00097 dup2(theSE->seFD, STDERR_FILENO);
00098 close(theSE->seFD);
00099
00100
00101
00102 if (theSE->Buff[bp-(theSE->Buff)-1L] != '\n') *bp++ = '\n';
00103 theSE->BLen = bp-(theSE->Buff);
00104
00105
00106
00107 theSE->mySem.Post();
00108 return (void *)0;
00109 }
00110
00111 void *XrdLogWorker(void *parg)
00112 {
00113 time_t midnite = XrdSysTimer::Midnight() + 86400;
00114 char *mememe = strdup((char *)parg);
00115
00116 while(1)
00117 {XrdSysTimer::Snooze(midnite-time(0));
00118 Say.Say(0, XrdBANNER);
00119 Say.Say(0, mememe, " running.");
00120 midnite += 86400;
00121 }
00122 return (void *)0;
00123 }
00124
00125
00126
00127
00128
00129 XrdFrmConfig::XrdFrmConfig(SubSys ss, const char *vopts, const char *uinfo)
00130 : dfltPolicy("*", -2, -3, 72000, 0)
00131 {
00132 char *sP, buff[128];
00133
00134
00135
00136 vOpts = vopts;
00137 uInfo = uinfo;
00138 ssID = ss;
00139 AdminPath= 0;
00140 QPath = 0;
00141 AdminMode= 0740;
00142 xfrMax = 2;
00143 FailHold = 3*60*60;
00144 IdleHold = 10*60;
00145 WaitMigr = 60*60;
00146 WaitPurge= 600;
00147 WaitQChk = 300;
00148 MSSCmd = 0;
00149 memset(&xfrCmd, 0, sizeof(xfrCmd));
00150 xfrCmd[0].Desc = "copycmd in"; xfrCmd[1].Desc = "copycmd out";
00151 xfrCmd[2].Desc = "copycmd in url"; xfrCmd[3].Desc = "copycmd out url";
00152 xfrIN = xfrOUT = 0;
00153 isAgent = (getenv("XRDADMINPATH") ? 1 : 0);
00154 ossLib = 0;
00155 cmsPath = 0;
00156 monStage = 0;
00157 haveCMS = 0;
00158 isOTO = 0;
00159 Test = 0;
00160 Verbose = 0;
00161 pathList = 0;
00162 spacList = 0;
00163 lockFN = "DIR_LOCK";
00164 cmdHold = -1;
00165 cmdFree = 0;
00166 pVecNum = 0;
00167 pProg = 0;
00168 Fix = 0;
00169 dirHold = 40*60*60;
00170
00171 myUid = geteuid();
00172 myGid = getegid();
00173
00174 LocalRoot= RemoteRoot = 0;
00175 lcl_N2N = rmt_N2N = the_N2N = 0;
00176 N2N_Lib = N2N_Parms = 0;
00177
00178
00179
00180 myInst = XrdOucUtils::InstName(-1);
00181
00182
00183
00184 if (!(sP = getenv("XRDCONFIGFN")) || !*sP)
00185 ConfigFN = 0;
00186 else {ConfigFN = strdup(sP); isAgent = 1;}
00187
00188
00189
00190 if (ss == ssAdmin) {myFrmid = "admin"; myFrmID = "ADMIN";}
00191 else if (ss == ssPurg) {myFrmid = "purge"; myFrmID = "PURG";}
00192 else if (ss == ssXfr) {myFrmid = "xfr"; myFrmID = "XFR"; }
00193 else {myFrmid = "frm"; myFrmID = "FRM";}
00194
00195
00196
00197 strcpy(buff, myFrmid);
00198 strcat(buff, "_");
00199 Say.SetPrefix(strdup(buff));
00200
00201
00202
00203 strcpy(buff, "frm.");
00204 strcat(buff, myFrmid);
00205 strcat(buff, ".");
00206 pfxDTS = strdup(buff); plnDTS = strlen(buff);
00207 }
00208
00209
00210
00211
00212
00213 int XrdFrmConfig::Configure(int argc, char **argv, int (*ppf)())
00214 {
00215 extern XrdOss *XrdOssGetSS(XrdSysLogger *, const char *, const char *);
00216 XrdFrmConfigSE theSE;
00217 int n, retc, isMum = 0, myXfrMax = -1, NoGo = 0, optBG = 0;
00218 const char *temp;
00219 char c, buff[1024], *logfn = 0;
00220 long long logkeep = 0;
00221 extern char *optarg;
00222 extern int opterr, optopt;
00223
00224
00225
00226 retc = strlen(argv[0]);
00227 while(retc--) if (argv[0][retc] == '/') break;
00228 myProg = &argv[0][retc+1];
00229 vectArg = argv; numcArg = argc;
00230
00231
00232
00233 opterr = 0; nextArg = 1;
00234 if (argc > 1 && '-' == *argv[1])
00235 while ((c = getopt(argc,argv,vOpts)) && ((unsigned char)c != 0xff))
00236 { switch(c)
00237 {
00238 case 'b': optBG = 1;
00239 break;
00240 case 'c': if (ConfigFN) free(ConfigFN);
00241 ConfigFN = strdup(optarg);
00242 break;
00243 case 'd': Trace.What |= TRACE_ALL;
00244 XrdOucEnv::Export("XRDDEBUG","1");
00245 break;
00246 case 'f': Fix = 1;
00247 break;
00248 case 'h': Usage(0);
00249 case 'k': n = strlen(optarg)-1;
00250 retc = (isalpha(optarg[n])
00251 ? XrdOuca2x::a2sz(Say,"keep size", optarg,&logkeep)
00252 : XrdOuca2x::a2ll(Say,"keep count",optarg,&logkeep));
00253 if (retc) Usage(1);
00254 if (!isalpha(optarg[n])) logkeep = -logkeep;
00255 break;
00256 case 'l': if (logfn) free(logfn);
00257 logfn = strdup(optarg);
00258 break;
00259 case 'm': if (XrdOuca2x::a2i(Say,"max number",optarg,&myXfrMax))
00260 Usage(1);
00261 break;
00262 case 'n': myInst = optarg;
00263 break;
00264 case 'O': isOTO = 1;
00265 if (!ConfigOTO(optarg)) Usage(1);
00266 break;
00267 case 'T': Test = 1;
00268 break;
00269 case 'v': Verbose = 1;
00270 break;
00271 case 'w': if (XrdOuca2x::a2tm(Say,"wait time",optarg,&WaitPurge))
00272 Usage(1);
00273 break;
00274 default: sprintf(buff,"'%c'", optopt);
00275 if (c == ':') Say.Emsg("Config", buff, "value not specified.");
00276 else Say.Emsg("Config", buff, "option is invalid");
00277 Usage(1);
00278 }
00279 nextArg = optind;
00280 }
00281
00282
00283
00284
00285 if (ssID != ssAdmin)
00286 {if (!logfn)
00287 {if (isAgent && (logfn = getenv("XRDLOGDIR")))
00288 {sprintf(buff, "%s%s%clog", logfn, myFrmid, (isAgent ? 'a' : 'd'));
00289 logfn = strdup(buff);
00290 }
00291 } else if (!(logfn=XrdOucUtils::subLogfn(Say,myInst,logfn))) _exit(16);
00292
00293
00294
00295 if (optBG && !isAgent) XrdOucUtils::Undercover(Say, !logfn);
00296
00297
00298
00299 if (logfn)
00300 {if (logkeep) Say.logger()->setKeep(logkeep);
00301 Say.logger()->Bind(logfn, 24*60*60);
00302 }
00303 }
00304
00305
00306
00307 if (!(myName = XrdNetDNS::getHostName()))
00308 {Say.Emsg("Config","Unable to determine host name; execution terminated.");
00309 _exit(16);
00310 }
00311
00312
00313
00314
00315 sprintf(buff,"XRDINSTANCE=%s %s@%s",myProg,
00316 XrdOucUtils::InstName(myInst), myName);
00317 putenv(strdup(buff));
00318 myInstance = strdup(index(buff,'=')+1);
00319 XrdOucEnv::Export("XRDHOST", myName);
00320 XrdOucEnv::Export("XRDPROG", myProg);
00321 XrdOucEnv::Export("XRDNAME", XrdOucUtils::InstName(myInst));
00322
00323
00324
00325 if (!logfn && (ssID == ssAdmin || isOTO) && !Trace.What)
00326 isMum = ConfigMum(theSE);
00327
00328
00329
00330 sprintf(buff, "Scalla %s is starting. . .", myProg);
00331 Say.Say(0, buff);
00332 Say.Say(XrdBANNER);
00333
00334
00335
00336 Say.Say("++++++ ", myInstance, " initialization started.");
00337 if (!ConfigFN || !*ConfigFN) ConfigFN = strdup("/opt/xrootd/etc/xrootd.cf");
00338 Say.Say("Config using configuration file ", ConfigFN);
00339 NoGo = ConfigProc();
00340
00341
00342
00343 if (!NoGo) NoGo = ConfigPaths();
00344
00345
00346
00347 if (!isAgent)
00348 {XrdOucEnv::Export("XRDREDIRECT", "Q");
00349 XrdOucEnv::Export("XRDOSSTYPE", myFrmID);
00350 if (ssID == ssPurg) XrdOucEnv::Export("XRDOSSCSCAN", "off");
00351 if (!NoGo && !(ossFS=XrdOssGetSS(Say.logger(),ConfigFN,ossLib))) NoGo=1;
00352 }
00353
00354
00355
00356 if (myInst) XrdOucUtils::makeHome(Say, myInst);
00357
00358
00359
00360 if (!NoGo) switch(ssID)
00361 {case ssAdmin: NoGo = (ConfigN2N() || ConfigMss());
00362 break;
00363 case ssPurg: if (!(NoGo = (ConfigN2N() || ConfigMP("purgeable"))))
00364 ConfigPF("frm_purged");
00365 break;
00366 case ssXfr: if (!isAgent && !(NoGo = ConfigXfr()))
00367 ConfigPF("frm_xfrd");
00368 break;
00369 default: break;
00370 }
00371
00372
00373
00374 if (!NoGo && ppf) NoGo = ppf();
00375
00376
00377
00378 if (!NoGo && logfn)
00379 {pthread_t tid;
00380 if ((retc = XrdSysThread::Run(&tid, XrdLogWorker, (void *)myInstance,
00381 XRDSYSTHREAD_BIND, "midnight runner")))
00382 {Say.Emsg("Config", retc, "create logger thread"); NoGo = 1;}
00383 }
00384
00385
00386
00387 temp = (NoGo ? " initialization failed." : " initialization completed.");
00388 Say.Say("------ ", myInstance, temp);
00389
00390
00391
00392 if (isMum)
00393 {close(STDERR_FILENO);
00394 theSE.mySem.Wait();
00395 if (NoGo && write(STDERR_FILENO, theSE.Buff, theSE.BLen)) {}
00396 }
00397
00398
00399
00400 return !NoGo;
00401 }
00402
00403
00404
00405
00406
00407 int XrdFrmConfig::LocalPath(const char *oldp, char *newp, int newpsz)
00408 {
00409 int rc = 0;
00410
00411 if (lcl_N2N) rc = lcl_N2N->lfn2pfn(oldp, newp, newpsz);
00412 else if (((int)strlen(oldp)) >= newpsz) rc = ENAMETOOLONG;
00413 else strcpy(newp, oldp);
00414 if (rc) {Say.Emsg("Config", rc, "generate local path from", oldp);
00415 return 0;
00416 }
00417 return 1;
00418 }
00419
00420
00421
00422
00423
00424 int XrdFrmConfig::LogicalPath(const char *oldp, char *newp, int newpsz)
00425 {
00426 int rc = 0;
00427
00428 if (lcl_N2N) rc = lcl_N2N->pfn2lfn(oldp, newp, newpsz);
00429 else if (((int)strlen(oldp)) >= newpsz) rc = ENAMETOOLONG;
00430 else strcpy(newp, oldp);
00431 if (rc) {Say.Emsg("Config", rc, "generate logical path from", oldp);
00432 return 0;
00433 }
00434 return 1;
00435 }
00436
00437
00438
00439
00440
00441 unsigned long long XrdFrmConfig::PathOpts(const char *Lfn)
00442 {
00443 extern XrdOucPListAnchor *XrdOssRPList;
00444
00445 return XrdOssRPList->Find(Lfn);
00446 }
00447
00448
00449
00450
00451
00452 int XrdFrmConfig::RemotePath(const char *oldp, char *newp, int newpsz)
00453 {
00454 int rc = 0;
00455
00456 if (rmt_N2N) rc = rmt_N2N->lfn2rfn(oldp, newp, newpsz);
00457 else if (((int)strlen(oldp)) >= newpsz) rc = ENAMETOOLONG;
00458 else strcpy(newp, oldp);
00459 if (rc) {Say.Emsg("Config", rc, "generate rmote path from", oldp);
00460 return 0;
00461 }
00462 return 1;
00463 }
00464
00465
00466
00467
00468
00469 XrdOucTList *XrdFrmConfig::Space(const char *Name, const char *Path)
00470 {
00471 static XrdOucTList nullEnt;
00472 struct VPInfo *vP = VPList;
00473 XrdOucTList *tP;
00474 char buff[1032];
00475 int n;
00476
00477
00478
00479 while(vP && strcmp(vP->Name, Name)) vP = vP->Next;
00480 if (!vP) return 0;
00481
00482
00483
00484 if (!Path) return vP->Dir;
00485
00486
00487
00488 n = strlen(Path)-1;
00489 if (Path[n] != '/')
00490 {if (n >= (int)sizeof(buff)-2) return &nullEnt;
00491 strcpy(buff, Path); buff[n+1] = '/'; buff[n+2] = '\0';
00492 Path = buff;
00493 }
00494
00495
00496
00497 tP = vP->Dir;
00498 while(tP && strcmp(Path, tP->text)) tP = tP->next;
00499 return (tP ? tP : &nullEnt);
00500 }
00501
00502
00503
00504
00505
00506
00507
00508
00509 XrdOucMsubs *XrdFrmConfig::ConfigCmd(const char *cname, char *cdata)
00510 {
00511 XrdOucMsubs *msubs;
00512 char *cP;
00513
00514 if (!cdata) {Say.Emsg("Config", cname, "not specified."); return 0;}
00515
00516 if ((cP = index(cdata, ' '))) *cP = '\0';
00517
00518 if (access(cdata, X_OK))
00519 {Say.Emsg("Config", errno, "set up", cdata);
00520 return 0;
00521 }
00522 if (cP) *cP = ' ';
00523
00524 msubs = new XrdOucMsubs(&Say);
00525 if (msubs->Parse(cname, cdata)) return msubs;
00526
00527 return 0;
00528 }
00529
00530
00531
00532
00533
00534 int XrdFrmConfig::ConfigMP(const char *pType)
00535 {
00536 EPNAME("ConfigMP");
00537 extern XrdOucPListAnchor *XrdOssRPList;
00538 XrdOucTList *nP, *tP, *mypList = 0, *expList = 0;
00539 char pDir[MAXPATHLEN+1];
00540 long long pOpts, xOpt = (*pType == 'm' ? XRDEXP_MIG : XRDEXP_PURGE);
00541 int i, NoGo = 0;
00542
00543
00544
00545 if (!XrdOssRPList)
00546 {Say.Emsg("Config", "Cannot determine", pType, "paths."); return 1;}
00547
00548
00549
00550 for (i = nextArg; i < numcArg; i++)
00551 {char *psVal = vectArg[i];
00552 int psLen = strlen(psVal);
00553 if (*psVal == '/')
00554 {pOpts = XrdOssRPList->Find(psVal);
00555 if (pOpts & xOpt) mypList = InsertPL(mypList, psVal, psLen,
00556 (pOpts & XRDEXP_MAKELF ? 1:0));
00557 else {Say.Say("Config", psVal, "not marked", pType); NoGo = 1;}
00558 } else {
00559 VPInfo *vP = VPList;
00560 while(vP && strcmp(psVal, vP->Name)) vP = vP->Next;
00561 if (vP) spacList = new XrdOucTList(psVal, psLen, spacList);
00562 else {Say.Emsg("Config", "Space", psVal, "not defined.");
00563 NoGo = 1;
00564 }
00565 }
00566 }
00567
00568
00569
00570 if (NoGo) return 1;
00571
00572
00573
00574 if (!mypList)
00575 {XrdOucPList *fP = XrdOssRPList->First();
00576 short sval[2];
00577 while(fP)
00578 {sval[0] = (fP->Flag() & XRDEXP_MAKELF ? 1 : 0);
00579 sval[1] = fP->Plen();
00580 if (fP->Flag() & xOpt)
00581 mypList = new XrdOucTList(fP->Path(), sval, mypList);
00582 else
00583 expList = new XrdOucTList(fP->Path(), sval, expList);
00584 fP = fP->Next();
00585 }
00586
00587
00588 }
00589
00590
00591
00592
00593 while((tP = mypList))
00594 {if (!LocalPath(tP->text, pDir, sizeof(pDir))) NoGo = 1;
00595 else {pathList = new VPInfo(pDir, int(tP->sval[0]), pathList);
00596 DEBUG("Will scan " <<(tP->sval[0]?"r/w: ":"r/o: ") <<pDir);
00597 nP = expList;
00598 while(nP)
00599 {if (!strncmp(tP->text, nP->text, tP->sval[1]))
00600 InsertXD(nP->text);
00601 nP = nP->next;
00602 }
00603 mypList = tP->next; delete tP;
00604 }
00605 }
00606
00607
00608
00609 while((tP = expList)) {expList = tP->next; delete tP;}
00610
00611
00612
00613
00614
00615
00616 if (!NoGo)
00617 {XrdOucPList *fp = XrdOssRPList->First();
00618 while(fp)
00619 {if (fp->Flag() & (XRDEXP_STAGE | XRDEXP_PURGE))
00620 fp->Set(fp->Flag() & ~XRDEXP_NOTRW);
00621 fp = fp->Next();
00622 }
00623 }
00624
00625
00626
00627 return NoGo;
00628 }
00629
00630
00631
00632
00633
00634 int XrdFrmConfig::ConfigMss()
00635 {
00636 if (MSSCmd)
00637 {MSSProg = new XrdOucProg(&Say);
00638 if (MSSProg->Setup(MSSCmd)) return 1;
00639 }
00640 return 0;
00641 }
00642
00643
00644
00645
00646
00647 int XrdFrmConfig::ConfigMum(XrdFrmConfigSE &theSE)
00648 {
00649 class Recover
00650 {public:
00651 int fdvec[2];
00652 int stdErr;
00653 Recover() : stdErr(-1) {fdvec[0] = -1; fdvec[1] = -1;}
00654 ~Recover() {if (fdvec[0] >= 0) close(fdvec[0]);
00655 if (fdvec[1] >= 0) close(fdvec[1]);
00656 if (stdErr >= 0) {dup2(stdErr, STDERR_FILENO);
00657 close(stdErr);
00658 }
00659 }
00660 };
00661 Recover FD;
00662 pthread_t tid;
00663 int rc;
00664
00665
00666
00667 if (pipe(FD.fdvec) < 0) return 0;
00668 fcntl(FD.fdvec[0], F_SETFD, FD_CLOEXEC);
00669
00670
00671
00672 if ((FD.stdErr = dup(STDERR_FILENO)) < 0) return 0;
00673
00674
00675
00676 if (dup2(FD.fdvec[1], STDERR_FILENO) < 0) return 0;
00677 close(FD.fdvec[1]); FD.fdvec[1] = -1;
00678
00679
00680
00681 theSE.myFD = FD.fdvec[0];
00682 theSE.seFD = FD.stdErr;
00683
00684
00685
00686 if ((rc = XrdSysThread::Run(&tid, XrdFrmConfigMum, (void *)&theSE,
00687 XRDSYSTHREAD_BIND, "Mumify"))) return 0;
00688
00689
00690
00691 theSE.mySem.Wait();
00692 FD.fdvec[0] = -1;
00693 FD.stdErr = -1;
00694 return 1;
00695 }
00696
00697
00698
00699
00700
00701 int XrdFrmConfig::ConfigN2N()
00702 {
00703 XrdSysPlugin *myLib;
00704 XrdOucName2Name *(*ep)(XrdOucgetName2NameArgs);
00705
00706
00707
00708
00709 if (!N2N_Lib)
00710 {the_N2N = XrdOucgetName2Name(&Say, ConfigFN, "", LocalRoot, RemoteRoot);
00711 if (LocalRoot) lcl_N2N = the_N2N;
00712 if (RemoteRoot) rmt_N2N = the_N2N;
00713 return 0;
00714 }
00715
00716
00717
00718
00719 if (!(myLib = new XrdSysPlugin(&Say, N2N_Lib))) return 1;
00720
00721
00722
00723 ep = (XrdOucName2Name *(*)(XrdOucgetName2NameArgs))(myLib->getPlugin("XrdOucgetName2Name"));
00724 if (!ep) return 1;
00725
00726
00727
00728
00729 lcl_N2N = rmt_N2N = the_N2N = ep(&Say, ConfigFN,
00730 (N2N_Parms ? N2N_Parms : ""),
00731 LocalRoot, RemoteRoot);
00732 return lcl_N2N == 0;
00733 }
00734
00735
00736
00737
00738
00739 int XrdFrmConfig::ConfigOTO(char *Parms)
00740 {
00741 char *Comma;
00742
00743
00744
00745 if ((Comma = index(Parms, ','))) *Comma = '\0';
00746 if (XrdOuca2x::a2sp(Say, "free value", Parms, &cmdFree, 1)) return 0;
00747
00748
00749
00750 if (!Comma || !(*(Comma+1))) return 1;
00751 if (*(Comma+1) == ',') Comma++;
00752 else {Parms = Comma+1;
00753 if ((Comma = index(Parms, ','))) *Comma = '\0';
00754 if (XrdOuca2x::a2i(Say,"hold value",Parms,&cmdHold,0)) return 0;
00755 }
00756
00757
00758
00759 return 1;
00760 }
00761
00762
00763
00764
00765
00766 int XrdFrmConfig::ConfigPaths()
00767 {
00768 char *xPath, buff[MAXPATHLEN];
00769 const char *insName;
00770
00771
00772
00773
00774
00775
00776
00777 if ((xPath = AdminPath)) insName = myInst;
00778 else if ((xPath = getenv("XRDADMINPATH"))) insName = 0;
00779 else {xPath = (char *)"/tmp/"; insName = myInst;}
00780
00781
00782
00783
00784 if (haveCMS)
00785 cmsPath = new XrdNetCmsNotify(&Say,xPath,insName,XrdNetCmsNotify::isServ);
00786
00787
00788
00789 if (!(xPath = XrdFrmUtils::makePath(insName, xPath, AdminMode))) return 1;
00790 if (AdminPath) free(AdminPath); AdminPath = xPath;
00791 if (!QPath) QPath = AdminPath;
00792
00793
00794
00795 strcpy(buff, Config.AdminPath); strcat(buff, "STOPPURGE");
00796 StopPurge = strdup(buff);
00797
00798
00799
00800 return 0;
00801 }
00802
00803
00804
00805
00806
00807 void XrdFrmConfig::ConfigPF(const char *pFN)
00808 {
00809 static const int Mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH;
00810 const char *ppP = (PidPath ? PidPath : "/tmp");
00811 char buff[1032], data[24];
00812 int pfFD, n;
00813
00814
00815
00816 if (myInst) sprintf(buff, "%s/%s/%s.pid", ppP, myInst, pFN);
00817 else sprintf(buff, "%s/%s.pid", ppP, pFN);
00818
00819
00820
00821 if ((pfFD = open(buff, O_WRONLY|O_CREAT|O_TRUNC, Mode)) < 0)
00822 {Say.Emsg("Config",errno,"open",buff); return;}
00823
00824
00825
00826 n = sprintf(data, "%lld", static_cast<long long>(getpid()));
00827 if (write(pfFD, data, n) < 0) Say.Emsg("Config",errno,"writing",buff);
00828 close(pfFD);
00829 }
00830
00831
00832
00833
00834
00835 int XrdFrmConfig::ConfigProc()
00836 {
00837 char *var;
00838 int cfgFD, retc, mbok, NoGo = 0;
00839 XrdOucEnv myEnv;
00840 XrdOucStream cfgFile(&Say, myInstance, &myEnv, "=====> ");
00841
00842
00843
00844 if ( (cfgFD = open(ConfigFN, O_RDONLY, 0)) < 0)
00845 {Say.Emsg("Config", errno, "open config file", ConfigFN);
00846 return 1;
00847 }
00848 cfgFile.Attach(cfgFD); cFile = &cfgFile;
00849
00850
00851
00852 while((var = cFile->GetMyFirstWord()))
00853 {mbok = 0;
00854 if (!strncmp(var, pfxDTS, plnDTS)) {var += plnDTS; mbok = 1;}
00855 if(ConfigXeq(var, mbok)) {cfgFile.Echo(); NoGo = 1;}
00856 }
00857
00858
00859
00860 if ((retc = cfgFile.LastError()))
00861 NoGo = Say.Emsg("Config", retc, "read config file", ConfigFN);
00862 cfgFile.Close(); cFile = 0;
00863
00864
00865
00866 return NoGo;
00867 }
00868
00869
00870
00871
00872
00873 int XrdFrmConfig::ConfigXeq(char *var, int mbok)
00874 {
00875
00876
00877
00878 if (!strcmp(var, "all.adminpath" )) return xapath();
00879 if (!strcmp(var, "all.pidpath" )) return Grab(var, &PidPath, 0);
00880 if (!strcmp(var, "all.manager" )) {haveCMS = 1; return 0;}
00881
00882
00883
00884 if (ssID == ssAdmin)
00885 {
00886 if (!strcmp(var, "frm.xfr.qcheck")) return xqchk();
00887 if (!strcmp(var, "ofs.osslib" )) return Grab(var, &ossLib, 0);
00888 if (!strcmp(var, "oss.cache" )) return xspace(0,0);
00889 if (!strcmp(var, "oss.localroot" )) return Grab(var, &LocalRoot, 0);
00890 if (!strcmp(var, "oss.namelib" )) return xnml();
00891 if (!strcmp(var, "oss.remoteroot")) return Grab(var, &RemoteRoot, 0);
00892 if (!strcmp(var, "oss.space" )) return xspace();
00893
00894
00895 }
00896
00897 if (ssID == ssXfr)
00898 {
00899 if (!strcmp(var, "qcheck" )) return xqchk();
00900 if (isAgent) return 0;
00901
00902 if (!strcmp(var, "ofs.osslib" )) return Grab(var, &ossLib, 0);
00903 if (!strcmp(var, "oss.cache" )) return xspace(0,0);
00904 if (!strcmp(var, "oss.localroot" )) return Grab(var, &LocalRoot, 0);
00905 if (!strcmp(var, "oss.namelib" )) return xnml();
00906 if (!strcmp(var, "oss.remoteroot")) return Grab(var, &RemoteRoot, 0);
00907 if (!strcmp(var, "oss.xfr" )) return xxfr();
00908 if (!strcmp(var, "xrootd.monitor")) return xmon();
00909
00910 if (!strcmp(var, "copycmd" )) return xcopy();
00911 if (!strcmp(var, "copymax" )) return xcmax();
00912 if (!strcmp(var, "oss.space" )) return xspace();
00913
00914 if (!strncmp(var, "migr.", 5))
00915 {char *vas = var+5;
00916 if (!strcmp(vas, "idlehold" )) return xitm("idle time", IdleHold);
00917 if (!strcmp(vas, "waittime" )) return xitm("migr wait", WaitMigr);
00918 }
00919 }
00920
00921 if (ssID == ssPurg)
00922 {
00923 if (!strcmp(var, "dirhold" )) return xdpol();
00924 if (!strcmp(var, "oss.cache" )) return xspace(1,0);
00925 if (!strcmp(var, "oss.localroot" )) return Grab(var, &LocalRoot, 0);
00926 if (!strcmp(var, "ofs.osslib" )) return Grab(var, &ossLib, 0);
00927 if (!strcmp(var, "policy" )) return xpol();
00928 if (!strcmp(var, "polprog" )) return xpolprog();
00929 if (!strcmp(var, "oss.space" )) return xspace(1);
00930 if (!strcmp(var, "waittime" )) return xitm("purge wait",WaitPurge);
00931 }
00932
00933
00934
00935 if (!mbok) cFile->noEcho();
00936 else {Say.Say("Config warning: ignoring unknown frm directive '",var,"'.");
00937 cFile->Echo();
00938 }
00939 return 0;
00940 }
00941
00942
00943
00944
00945
00946 int XrdFrmConfig::ConfigXfr()
00947 {
00948 int i, isBad, ioOK[2] = {0};
00949
00950
00951
00952 isBad = ConfigN2N() || ConfigMP("migratable") || ConfigMss();
00953
00954
00955
00956
00957
00958 for (i = 0; i < 4; i++)
00959 {if (xfrCmd[i].theCmd)
00960 {if ((xfrCmd[i].theVec=ConfigCmd(xfrCmd[i].Desc, xfrCmd[i].theCmd)))
00961 ioOK[i%2] = 1;
00962 else isBad = 1;
00963 }
00964 }
00965
00966
00967
00968 if (!(ioOK[0] | ioOK[1]))
00969 {Say.Emsg("Config",
00970 "No copy commands specified; execution is meaningless!");
00971 return 1;
00972 }
00973
00974
00975
00976 if (!(xfrIN = ioOK[0]))
00977 Say.Emsg("Config", "Input copy command not specified; "
00978 "incoming transfers prohibited!");
00979
00980
00981
00982 if (!(xfrOUT = ioOK[1]))
00983 Say.Emsg("Config", "Output copy command not specified; "
00984 "outgoing transfers prohibited!");
00985
00986
00987
00988 isBad |= (monStage &&!XrdFrmMonitor::Init());
00989
00990
00991
00992 return isBad;
00993 }
00994
00995
00996
00997
00998
00999 int XrdFrmConfig::getTime(const char *emsg, const char *item, int *val,
01000 int minv, int maxv)
01001 {
01002 if (strcmp(item, "forever"))
01003 return XrdOuca2x::a2tm(Say, emsg, item, val, minv, maxv);
01004 *val = -1;
01005 return 0;
01006 }
01007
01008
01009
01010
01011
01012 int XrdFrmConfig::Grab(const char *var, char **Dest, int nosubs)
01013 {
01014 char myVar[1024], buff[2048], *val;
01015 XrdOucEnv *myEnv = 0;
01016
01017
01018
01019
01020 strlcpy(myVar, var, sizeof(myVar));
01021 var = myVar;
01022
01023
01024
01025
01026 if (!nosubs) val = cFile->GetWord();
01027 else {myEnv = cFile->SetEnv(0);
01028 if (!cFile->GetRest(buff, sizeof(buff)))
01029 {Say.Emsg("Config", "arguments too long for", var);
01030 cFile->SetEnv(myEnv);
01031 return 1;
01032 }
01033 val = buff;
01034 cFile->SetEnv(myEnv);
01035 }
01036
01037
01038
01039 if (!val || !(*val))
01040 {if (nosubs < 0) Say.Emsg("Config", "no arguments for", var);
01041 else Say.Emsg("Config", "no value for directive", var);
01042 return 1;
01043 }
01044
01045
01046
01047 if (*Dest) {free(*Dest); Dest = 0;}
01048 if (nosubs < 0)
01049 {char fBuff[2048];
01050 int n = strlen(myVar);
01051 if (n + strlen(val) > sizeof(fBuff)-1)
01052 {Say.Emsg("Config", "arguments too long for", var); return 1;}
01053 strcpy(fBuff, myVar); *(fBuff+n) = ' '; strcpy(fBuff+n+1, val);
01054 *Dest = strdup(fBuff);
01055 } else *Dest = strdup(val);
01056
01057
01058
01059 return 0;
01060 }
01061
01062
01063
01064
01065
01066 XrdOucTList *XrdFrmConfig::InsertPL(XrdOucTList *pL, const char *Path,
01067 int Plen, int isRW)
01068 {
01069 short sval[4] = {isRW, Plen};
01070 XrdOucTList *pP = 0, *tP = pL;
01071
01072
01073
01074 while(tP && tP->sval[1] < Plen) {pP = tP; tP = tP->next;}
01075
01076
01077
01078 if (pP) pP->next = new XrdOucTList(Path, sval, tP);
01079 else pL = new XrdOucTList(Path, sval, tP);
01080
01081
01082
01083 return pL;
01084 }
01085
01086
01087
01088
01089
01090 void XrdFrmConfig::InsertXD(const char *Path)
01091 {
01092 EPNAME("InsertXD");
01093 char pBuff[MAXPATHLEN], *pP;
01094 int n = strlen(Path);
01095
01096
01097
01098 strcpy(pBuff, Path);
01099 pP = pBuff + n - 1;
01100 while(*pP == '/' && pP != pBuff) {*pP-- = '\0'; n--;}
01101
01102
01103
01104 pathList->Dir = new XrdOucTList(pBuff, n, pathList->Dir);
01105 DEBUG("Excluding '" <<pBuff <<"'");
01106 }
01107
01108
01109
01110
01111
01112 void XrdFrmConfig::Usage(int rc)
01113 {
01114 cerr <<"\nUsage: " <<myProg <<" " <<uInfo <<endl;
01115 _exit(rc);
01116 }
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133 int XrdFrmConfig::xapath()
01134 {
01135 char *pval, *val;
01136 mode_t mode = S_IRWXU;
01137
01138
01139
01140 pval = cFile->GetWord();
01141 if (!pval || !pval[0])
01142 {Say.Emsg("Config", "adminpath not specified"); return 1;}
01143
01144
01145
01146 if (*pval != '/')
01147 {Say.Emsg("Config", "adminpath not absolute"); return 1;}
01148
01149
01150
01151 if (AdminPath) free(AdminPath);
01152 AdminPath = strdup(pval);
01153
01154
01155
01156 if ((val = cFile->GetWord()) && val[0])
01157 {if (!strcmp("group", val)) mode |= S_IRWXG;
01158 else {Say.Emsg("Config", "invalid admin path modifier -", val);
01159 return 1;
01160 }
01161 }
01162 AdminMode = mode;
01163 return 0;
01164 }
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185 int XrdFrmConfig::xcopy()
01186 { int cmdIO[2] = {0,0}, TLim=0, Stats=0, hasMDP=0, cmdUrl=0, noAlo=0;
01187 char *val, *theCmd = 0;
01188 struct copyopts {const char *opname; int *oploc;} cpopts[] =
01189 {
01190 {"in", &cmdIO[0]},
01191 {"out", &cmdIO[1]},
01192 {"noalloc",&noAlo},
01193 {"stats", &Stats},
01194 {"timeout",&TLim},
01195 {"url", &cmdUrl}
01196 };
01197 int i, n, numopts = sizeof(cpopts)/sizeof(struct copyopts);
01198
01199
01200
01201 val = cFile->GetWord();
01202 while(val && *val != '/')
01203 {for (i = 0; i < numopts; i++)
01204 {if (!strcmp(val,cpopts[i].opname))
01205 {if (strcmp("timeout", val)) {*cpopts[i].oploc = 1; break;}
01206 else if (!xcopy(TLim)) return 1;
01207 }
01208 }
01209 if (i >= numopts)
01210 Say.Say("Config warning: ignoring invalid copycmd option '",val,"'.");
01211 val = cFile->GetWord();
01212 }
01213
01214
01215
01216 if (!val || !*val)
01217 {Say.Emsg("Config", "copy command not specified"); return 1;}
01218 if (Grab(val, &theCmd, -1)) return 1;
01219
01220
01221
01222 if (!cmdIO[0] && !cmdIO[1]) cmdIO[0] = cmdIO[1] = 1;
01223 if (cmdIO[1]) hasMDP = (strstr(theCmd, "$MDP") != 0);
01224
01225
01226
01227 n = (cmdUrl ? 3 : 1);
01228 i = 1;
01229 do {if (cmdIO[i])
01230 {if (xfrCmd[n].theCmd) free(xfrCmd[n].theCmd);
01231 xfrCmd[n].theCmd = strdup(theCmd);
01232 if (Stats) xfrCmd[n].Opts |= cmdStats;
01233 if (hasMDP) xfrCmd[n].Opts |= cmdMDP;
01234 if (noAlo) xfrCmd[n].Opts &=~cmdAlloc;
01235 else xfrCmd[n].Opts |= cmdAlloc;
01236 xfrCmd[n].TLimit = TLim;
01237 }
01238 n--;
01239 } while(i--);
01240
01241
01242
01243 free(theCmd);
01244 return 0;
01245 }
01246
01247
01248
01249 int XrdFrmConfig::xcopy(int &TLim)
01250 {
01251 char *val;
01252
01253 if (!(val = cFile->GetWord()) || !*val)
01254 {Say.Emsg("Config", "copy command timeout not specified"); return 0;}
01255 if (XrdOuca2x::a2tm(Say,"copy command timeout", val, &TLim, 0)) return 0;
01256 return 1;
01257 }
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271 int XrdFrmConfig::xcmax()
01272 { int xmax = 1;
01273 char *val;
01274
01275 if (!(val = cFile->GetWord()))
01276 {Say.Emsg("Config", "maxio value not specified"); return 1;}
01277 if (XrdOuca2x::a2i(Say, "maxio", val, &xmax, 1)) return 1;
01278 xfrMax = xmax;
01279 return 0;
01280 }
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297 int XrdFrmConfig::xdpol()
01298 { int htm;
01299 char *val;
01300
01301 if (!(val = cFile->GetWord()))
01302 {Say.Emsg("Config", "dirpolicy hold time not specified"); return 1;}
01303 if (XrdOuca2x::a2tm(Say,"dirpolicy hold time", val, &htm, 0)) return 1;
01304 dirHold = htm;
01305 return 0;
01306 }
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320 int XrdFrmConfig::xitm(const char *What, int &tDest)
01321 { int itime;
01322 char *val;
01323
01324 if (!(val = cFile->GetWord()))
01325 {Say.Emsg("Config", What, "not specified"); return 1;}
01326 if (XrdOuca2x::a2tm(Say, What, val, &itime)) return 1;
01327 tDest = itime;
01328 return 0;
01329 }
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358 int XrdFrmConfig::xmon()
01359 { char *val, *cp, *monDest[2] = {0, 0};
01360 long long tempval;
01361 int i, monFlush=0, monMBval=0, monWWval=0, monMode[2] = {0, 0};
01362
01363 while((val = cFile->GetWord()))
01364
01365 { if (!strcmp("all", val)) {}
01366 else if (!strcmp("flush", val))
01367 {if (!(val = cFile->GetWord()))
01368 {Say.Emsg("Config", "monitor flush value not specified");
01369 return 1;
01370 }
01371 if (XrdOuca2x::a2tm(Say,"monitor flush",val,
01372 &monFlush,1)) return 1;
01373 }
01374 else if (!strcmp("mbuff",val))
01375 {if (!(val = cFile->GetWord()))
01376 {Say.Emsg("Config", "monitor mbuff value not specified");
01377 return 1;
01378 }
01379 if (XrdOuca2x::a2sz(Say,"monitor mbuff", val,
01380 &tempval, 1024, 65536)) return 1;
01381 monMBval = static_cast<int>(tempval);
01382 }
01383 else if (!strcmp("window", val))
01384 {if (!(val = cFile->GetWord()))
01385 {Say.Emsg("Config", "monitor window value not specified");
01386 return 1;
01387 }
01388 if (XrdOuca2x::a2tm(Say,"monitor window",val,
01389 &monWWval,1)) return 1;
01390 }
01391 else break;
01392 }
01393
01394 if (!val) {Say.Emsg("Config", "monitor dest not specified"); return 1;}
01395
01396 for (i = 0; i < 2; i++)
01397 {if (strcmp("dest", val)) break;
01398 while((val = cFile->GetWord()))
01399 if (!strcmp("files",val)
01400 || !strcmp("info", val)
01401 || !strcmp("io", val)
01402 || !strcmp("user", val)) {}
01403 else if (!strcmp("stage",val)) monMode[i] |= XROOTD_MON_STAGE;
01404 else break;
01405 if (!val) {Say.Emsg("Config","monitor dest value not specified");
01406 return 1;
01407 }
01408 if (!(cp = index(val, (int)':')) || !atoi(cp+1))
01409 {Say.Emsg("Config","monitor dest port missing or invalid in",val);
01410 return 1;
01411 }
01412 monDest[i] = strdup(val);
01413 if (!(val = cFile->GetWord())) break;
01414 }
01415
01416 if (val)
01417 {if (!strcmp("dest", val))
01418 Say.Emsg("Config", "Warning, a maximum of two dest values allowed.");
01419 else Say.Emsg("Config", "Warning, invalid monitor option", val);
01420 }
01421
01422
01423
01424 if (monDest[0] && monDest[1] && !strcmp(monDest[0], monDest[1]))
01425 {Say.Emsg("Config", "Warning, monitor dests are identical.");
01426 monMode[0] |= monMode[1]; monMode[1] = 0;
01427 free(monDest[1]); monDest[1] = 0;
01428 }
01429
01430
01431
01432 if (!monMode[0] && !monMode[1]) return 0;
01433 monStage = 1;
01434
01435
01436
01437 XrdFrmMonitor::Defaults(monDest[0],monMode[0],monDest[1],monMode[1]);
01438 return 0;
01439 }
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455 int XrdFrmConfig::xnml()
01456 {
01457 char *val, parms[1024];
01458
01459
01460
01461 if (!(val = cFile->GetWord()) || !val[0])
01462 {Say.Emsg("Config", "namelib not specified"); return 1;}
01463
01464
01465
01466 if (N2N_Lib) free(N2N_Lib);
01467 N2N_Lib = strdup(val);
01468
01469
01470
01471 if (!cFile->GetRest(parms, sizeof(parms)))
01472 {Say.Emsg("Config", "namelib parameters too long"); return 1;}
01473 if (N2N_Parms) free(N2N_Parms);
01474 N2N_Parms = (*parms ? strdup(parms) : 0);
01475 return 0;
01476 }
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513 int XrdFrmConfig::xpol()
01514 {
01515 Policy *pP = &dfltPolicy;
01516 char *val, sname[XrdOssSpace::minSNbsz];
01517 long long minP = dfltPolicy.minFree, maxP = dfltPolicy.maxFree;
01518 int Hold = dfltPolicy.Hold, Ext = 0;
01519 struct purgeopts {const char *opname; int isTime; int *oploc;} pgopts[] =
01520 {
01521 {"polprog", -1, &Ext},
01522 {"hold", 1, &Hold}
01523 };
01524 int i, rc, numopts = sizeof(pgopts)/sizeof(struct purgeopts);
01525
01526
01527
01528 if (!(val = cFile->GetWord()))
01529 {Say.Emsg("Config", "space name not specified"); return 1;}
01530 if (strlen(val) >= sizeof(sname))
01531 {Say.Emsg("Config", "space name '", val, "' too long"); return 1;}
01532
01533
01534
01535 if (!strcmp("=", val)) return xpolprog();
01536 strcpy(sname, val);
01537
01538
01539
01540
01541 if ( (val = cFile->GetWord()) && isdigit(*val))
01542 {if ( XrdOuca2x::a2sp(Say, "min free", val, &minP, 1)) return 1;
01543 if ((val = cFile->GetWord()) && isdigit(*val))
01544 {if (XrdOuca2x::a2sp(Say, "max free", val, &maxP, 1)) return 1;
01545 if ((minP < 0 && maxP >= 0) || (minP >= 0 && maxP < 0))
01546 {Say.Emsg("Config", "purge min/max may not differ in type.");
01547 return 1;
01548 }
01549 if (XRDABS(minP) >= XRDABS(maxP))
01550 {Say.Emsg("Config", "purge min must be < max value."); return 1;}
01551 val = cFile->GetWord();
01552 } else {
01553 if (minP < 0) maxP = (minP < -99 ? -100 : minP - 1);
01554 else maxP = (minP * 120LL)/100LL;
01555 }
01556 } else if (val && !strcmp(val, "nopurge"))
01557 {minP = maxP = 0;
01558 if ((val = cFile->GetWord()))
01559 {Say.Say("Config warning: ignoring extraneous policy option '",val,"'.");
01560 val = 0;
01561 }
01562 }
01563
01564
01565
01566 while(val)
01567 {for (i = 0; i < numopts; i++) if (!strcmp(val,pgopts[i].opname)) break;
01568 if (i >= numopts)
01569 {Say.Say("Config warning: ignoring invalid policy option '",val,"'.");
01570 val = cFile->GetWord();
01571 continue;
01572 }
01573 if (pgopts[i].isTime < 0) *(pgopts[i].oploc) = 1;
01574 else {if (!(val = cFile->GetWord()))
01575 {Say.Emsg("Config", "policy", pgopts[i].opname,
01576 "argument not specified.");
01577 return 1;
01578 }
01579 rc = (pgopts[i].isTime
01580 ? getTime( "purge value",val,pgopts[i].oploc,0)
01581 : XrdOuca2x::a2i (Say,"purge value",val,pgopts[i].oploc,0));
01582 if (rc) return 1;
01583 }
01584 val = cFile->GetWord();
01585 }
01586
01587
01588
01589 if (Ext && !pProg)
01590 {Say.Emsg("Config", "External policy has not been pre-defined.");
01591 return 1;
01592 }
01593
01594
01595
01596 while(pP && strcmp(pP->Sname, sname)) pP = pP->Next;
01597 if (pP) {pP->minFree=minP; pP->maxFree=maxP; pP->Hold=Hold; pP->Ext=Ext;}
01598 else {pP = new Policy(sname, minP, maxP, Hold, Ext);
01599 pP->Next = dfltPolicy.Next; dfltPolicy.Next = pP;
01600 }
01601 return 0;
01602 }
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632 int XrdFrmConfig::xpolprog()
01633 {
01634 char *val, pBuff[4096], *pbP = pBuff;
01635 struct polopts {const char *opname; int opval;} plopts[] =
01636 {
01637 {"atime", PP_atime },
01638 {"ctime", PP_ctime },
01639 {"fname", PP_fname },
01640 {"fsize", PP_fsize },
01641 {"fspace", PP_fspace},
01642 {"mtime", PP_mtime },
01643 {"pfn", PP_pfn },
01644 {"sname", PP_sname },
01645 {"tspace", PP_tspace},
01646 {"usage", PP_usage}
01647 };
01648 int i, n, numopts = sizeof(plopts)/sizeof(struct polopts);
01649
01650
01651
01652 if (!(val = cFile->GetWord()))
01653 {Say.Emsg("Config", "policy program not specified"); return 1;}
01654 pVecNum = 0;
01655
01656
01657
01658 while(val && *val != '|')
01659 {for (i = 0; i < numopts; i++) if (!strcmp(val,plopts[i].opname)) break;
01660 if (i >= numopts)
01661 {Say.Say("Config warning: ignoring invalid policy option '",val,"'.");
01662 val = cFile->GetWord();
01663 continue;
01664 }
01665 if (pVecNum >= pVecMax)
01666 {Say.Emsg("Config", "To many policy program variables specified.");
01667 return 1;
01668 }
01669 pVec[pVecNum++] = static_cast<char>(plopts[i].opval);
01670 val = cFile->GetWord();
01671 }
01672
01673
01674
01675 if (val) val++;
01676 if (val && !(*val)) val = cFile->GetWord();
01677 if (!val)
01678 {Say.Emsg("Config", "policy program not specified."); return 1;}
01679 i = strlen(val);
01680 if (i >= (int)sizeof(pBuff)-8)
01681 {Say.Emsg("Config", "policy program name is too long."); return 1;}
01682 strcpy(pBuff, val); pbP = pBuff+i; *(pbP+1) = '\0';
01683
01684
01685
01686 n = sizeof(pBuff) - i - 1;
01687 if (!cFile->GetRest(pbP+1, n))
01688 {Say.Emsg("Config", "policy program args are too long."); return 1;}
01689 if (*(pbP+1)) *pbP = ' ';
01690
01691
01692
01693 if (pProg) free(pProg);
01694 pProg = strdup(pBuff);
01695 return 0;
01696 }
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712 int XrdFrmConfig::xqchk()
01713 { int itime;
01714 char *val;
01715
01716
01717
01718 if (!(val = cFile->GetWord()))
01719 {Say.Emsg("Config", "qcheck time not specified"); return 1;}
01720
01721
01722
01723 if (*val != '/')
01724 {if (XrdOuca2x::a2tm(Say, "qcheck time", val, &itime)) return 1;
01725 WaitQChk = itime;
01726 if (!(val = cFile->GetWord())) return 0;
01727 }
01728
01729
01730
01731 if (*val != '/')
01732 {Say.Emsg("Config", "qcheck path not absolute"); return 1;}
01733 if (QPath) free(QPath);
01734 QPath = strdup(val);
01735 return 0;
01736 }
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752 int XrdFrmConfig::xspace(int isPrg, int isXA)
01753 {
01754 char *val, *pfxdir, *sfxdir;
01755 char grp[XrdOssSpace::minSNbsz], fn[MAXPATHLEN], dn[MAXNAMLEN];
01756 int i, k, rc, pfxln, cnum = 0;
01757 struct dirent *dp;
01758 struct stat buff;
01759 DIR *DFD;
01760
01761 if (!(val = cFile->GetWord()))
01762 {Say.Emsg("Config", "space name not specified"); return 1;}
01763 if (strlen(val) >= (int)sizeof(grp))
01764 {Say.Emsg("Config","excessively long space name - ",val); return 1;}
01765 strcpy(grp, val);
01766
01767 if (!(val = cFile->GetWord()))
01768 {Say.Emsg("Config", "path to space not specified"); return 1;}
01769
01770 k = strlen(val);
01771 if (k >= (int)(sizeof(fn)-1) || val[0] != '/' || k < 2)
01772 {Say.Emsg("Config", "invalid space path - ", val); return 1;}
01773 strcpy(fn, val);
01774
01775 if (!isXA && (val = cFile->GetWord()))
01776 {if (strcmp("xa", val))
01777 {Say.Emsg("Config","invalid cache option - ",val); return 1;}
01778 else isXA = 1;
01779 }
01780
01781 if (fn[k-1] != '*')
01782 {for (i = k-1; i; i--) if (fn[i] != '/') break;
01783 fn[i+1] = '/'; fn[i+2] = '\0';
01784 xspaceBuild(grp, fn, isXA);
01785 return 0;
01786 }
01787
01788 for (i = k-1; i; i--) if (fn[i] == '/') break;
01789 i++; strcpy(dn, &fn[i]); fn[i] = '\0';
01790 sfxdir = &fn[i]; pfxdir = dn; pfxln = strlen(dn)-1;
01791 if (!(DFD = opendir(fn)))
01792 {Say.Emsg("Config", errno, "open space directory", fn); return 1;}
01793
01794 errno = 0;
01795 while((dp = readdir(DFD)))
01796 {if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")
01797 || (pfxln && strncmp(dp->d_name, pfxdir, pfxln)))
01798 continue;
01799 strcpy(sfxdir, dp->d_name);
01800 if (stat(fn, &buff)) break;
01801 if ((buff.st_mode & S_IFMT) == S_IFDIR)
01802 {val = sfxdir + strlen(sfxdir) - 1;
01803 if (*val++ != '/') {*val++ = '/'; *val = '\0';}
01804 xspaceBuild(grp, fn, isXA);
01805 cnum++;
01806 }
01807 errno = 0;
01808 }
01809
01810 if ((rc = errno))
01811 Say.Emsg("Config", errno, "process space directory", fn);
01812 else if (!cnum) Say.Say("Config warning: no space directories found in ",val);
01813
01814 closedir(DFD);
01815 return rc != 0;
01816 }
01817
01818 void XrdFrmConfig::xspaceBuild(char *grp, char *fn, int isxa)
01819 {
01820 struct VPInfo *nP = VPList;
01821 XrdOucTList *tP;
01822
01823 while(nP && strcmp(nP->Name, grp)) nP = nP->Next;
01824
01825 if (!nP) VPList = nP = new VPInfo(grp, 0, VPList);
01826
01827 tP = nP->Dir;
01828 while(tP && strcmp(tP->text, fn)) tP = tP->next;
01829 if (!tP) nP->Dir = new XrdOucTList(fn, isxa, nP->Dir);
01830 }
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846 int XrdFrmConfig::xxfr()
01847 {
01848 char *val;
01849 int htime = 3*60*60;
01850 int haveparm = 0;
01851
01852 while((val = cFile->GetWord()))
01853 { if (!strcmp("deny", val))
01854 {if ((val = cFile->GetWord()))
01855 {if (XrdOuca2x::a2tm(Say,"xfr deny",val,&htime,0))
01856 return 1;
01857 FailHold = htime, haveparm=1;
01858 }
01859 }
01860 else if (!strcmp("keep", val))
01861 {if ((val = cFile->GetWord()))
01862 {if (XrdOuca2x::a2tm(Say,"xfr keep",val,&htime,0))
01863 return 1;
01864 haveparm=1;
01865 }
01866 }
01867 else break;
01868 };
01869
01870 if (!val)
01871 {if (haveparm)
01872 { return 0;
01873 }
01874 else
01875 {Say.Emsg("Config", "xfr parameter not specified");
01876 return 1;
01877 }
01878 }
01879
01880 return 0;
01881 }