XRootD
XrdOfsConfig.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d O f s C o n f i g . c c */
4 /* */
5 /* (C) 2010 by the Board of Trustees of the Leland Stanford, Jr., University */
6 /* All Rights Reserved */
7 /* Produced by Andrew Hanushevsky for Stanford University under contract */
8 /* DE-AC02-76-SFO0515 with the Deprtment of Energy */
9 /* */
10 /* This file is part of the XRootD software suite. */
11 /* */
12 /* XRootD is free software: you can redistribute it and/or modify it under */
13 /* the terms of the GNU Lesser General Public License as published by the */
14 /* Free Software Foundation, either version 3 of the License, or (at your */
15 /* option) any later version. */
16 /* */
17 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
18 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
19 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
20 /* License for more details. */
21 /* */
22 /* You should have received a copy of the GNU Lesser General Public License */
23 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
24 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
25 /* */
26 /* The copyright holder's institutional names and contributor's names may not */
27 /* be used to endorse or promote products derived from this software without */
28 /* specific prior written permission of the institution or contributor. */
29 /******************************************************************************/
30 
31 #include <unistd.h>
32 #include <cctype>
33 #include <cerrno>
34 #include <fcntl.h>
35 #include <netdb.h>
36 #include <cstdlib>
37 #include <strings.h>
38 #include <cstdio>
39 #include <netinet/in.h>
40 #include <sys/param.h>
41 #include <sys/stat.h>
42 
43 #include "XrdVersion.hh"
44 #include "XProtocol/XProtocol.hh"
45 
46 #include "XrdCks/XrdCks.hh"
47 
48 #include "XrdNet/XrdNetUtils.hh"
49 
50 #include "XrdSfs/XrdSfsFlags.hh"
51 
52 #include "XrdOfs/XrdOfs.hh"
53 #include "XrdOfs/XrdOfsConfigCP.hh"
54 #include "XrdOfs/XrdOfsConfigPI.hh"
55 #include "XrdOfs/XrdOfsEvs.hh"
56 #include "XrdOfs/XrdOfsFSctl_PI.hh"
57 #include "XrdOfs/XrdOfsPoscq.hh"
58 #include "XrdOfs/XrdOfsStats.hh"
59 #include "XrdOfs/XrdOfsTPC.hh"
61 #include "XrdOfs/XrdOfsTrace.hh"
62 
63 #include "XrdOss/XrdOss.hh"
64 
65 #include "XrdOuc/XrdOuca2x.hh"
66 #include "XrdOuc/XrdOucEnv.hh"
67 #include "XrdOuc/XrdOucNSWalk.hh"
68 #include "XrdOuc/XrdOucStream.hh"
69 #include "XrdOuc/XrdOucUtils.hh"
70 
71 #include "XrdSys/XrdSysError.hh"
72 #include "XrdSys/XrdSysHeaders.hh"
73 
74 #include "XrdNet/XrdNetAddr.hh"
75 
76 #include "XrdCms/XrdCmsClient.hh"
77 #include "XrdCms/XrdCmsFinder.hh"
78 #include "XrdCms/XrdCmsRole.hh"
79 
81 
82 /******************************************************************************/
83 /* G l o b a l O b j e c t s */
84 /******************************************************************************/
85 
86 extern XrdOfsStats OfsStats;
87 
88 extern XrdSysTrace OfsTrace;
89 
90 extern XrdOfs* XrdOfsFS;
91 
92 class XrdOss;
93 extern XrdOss *XrdOfsOss;
94 
95 class XrdScheduler;
97 
99 
100 namespace XrdOfsTPCParms
101 {
102 extern XrdOfsTPCConfig Cfg;
103 }
104 
105 namespace
106 {
107 int SetMode(const char *path, mode_t mode) {return chmod(path, mode);}
108 }
109 
110 /******************************************************************************/
111 /* d e f i n e s */
112 /******************************************************************************/
113 
114 #define TS_Xeq(x,m) if (!strcmp(x,var)) return m(Config,Eroute);
115 
116 #define TS_XPI(x,m) if (!strcmp(x,var))\
117  return !ofsConfig->Parse(XrdOfsConfigPI:: m);
118 
119 #define TS_Str(x,m) if (!strcmp(x,var)) {free(m); m = strdup(val); return 0;}
120 
121 #define TS_PList(x,m) if (!strcmp(x,var)) \
122  {m.Insert(new XrdOucPList(val,1)); return 0;}
123 
124 #define TS_Chr(x,m) if (!strcmp(x,var)) {m = val[0]; return 0;}
125 
126 #define TS_Bit(x,m,v) if (!strcmp(x,var)) {m |= v; Config.Echo(); return 0;}
127 
128 #define Max(x,y) (x > y ? x : y)
129 
130 /******************************************************************************/
131 /* g e t V e r s i o n */
132 /******************************************************************************/
133 
134 const char *XrdOfs::getVersion() {return XrdVERSION;}
135 
136 /******************************************************************************/
137 /* C o n f i g u r e */
138 /******************************************************************************/
139 
140 int XrdOfs::Configure(XrdSysError &Eroute) {return Configure(Eroute, 0);}
141 
142 int XrdOfs::Configure(XrdSysError &Eroute, XrdOucEnv *EnvInfo) {
143 /*
144  Function: Establish default values using a configuration file.
145 
146  Input: None.
147 
148  Output: 0 upon success or !0 otherwise.
149 */
150  char *var;
151  const char *tmp;
152  int cfgFD, retc, NoGo = 0;
153  XrdOucEnv myEnv;
154  XrdOucStream Config(&Eroute, getenv("XRDINSTANCE"), &myEnv, "=====> ");
155 
156 // Print warm-up message
157 //
158  Eroute.Say("++++++ File system initialization started.");
159 
160 // Start off with no POSC log. Note that XrdSfsGetDefaultFileSystem nakes sure
161 // that we are configured only once.
162 //
163  poscLog = NULL;
164 
165 // Establish the network interface that the caller must provide
166 //
167  if (!EnvInfo || !(myIF = (XrdNetIF *)EnvInfo->GetPtr("XrdNetIF*")))
168  {Eroute.Emsg("Finder", "Network i/f undefined; unable to self-locate.");
169  NoGo = 1;
170  }
171  ofsSchedP = (XrdScheduler *)EnvInfo->GetPtr("XrdScheduler*");
172 
173 // Preset all variables with common defaults
174 //
175  Options = 0;
176  if (getenv("XRDDEBUG")) OfsTrace.What = TRACE_MOST | TRACE_debug;
177 
178 // Allocate a our plugin configurator
179 //
180  ofsConfig = XrdOfsConfigPI::New(ConfigFN, &Config, &Eroute, 0, this);
181 
182 // If there is no config file, return with the defaults sets.
183 //
184  if( !ConfigFN || !*ConfigFN)
185  Eroute.Emsg("Config", "Configuration file not specified.");
186  else {
187  // Try to open the configuration file.
188  //
189  if ( (cfgFD = open(ConfigFN, O_RDONLY, 0)) < 0)
190  return Eroute.Emsg("Config", errno, "open config file",
191  ConfigFN);
192  Config.Attach(cfgFD);
193  static const char *cvec[] = {"*** ofs plugin config:",0};
194  Config.Capture(cvec);
195 
196  // Now start reading records until eof.
197  //
198  while((var = Config.GetMyFirstWord()))
199  {if (!strncmp(var, "ofs.", 4)
200  || !strcmp(var, "all.role")
201  || !strcmp(var, "all.subcluster"))
202  {if (ConfigXeq(var+4,Config,Eroute)) {Config.Echo();NoGo=1;}}
203  else if (!strcmp(var, "oss.defaults")
204  || !strcmp(var, "all.export"))
205  {xexp(Config, Eroute, *var == 'a');
206  Config.noEcho();
207  }
208  }
209 
210  // Now check if any errors occurred during file i/o
211  //
212  if ((retc = Config.LastError()))
213  NoGo = Eroute.Emsg("Config", -retc, "read config file",
214  ConfigFN);
215  Config.Close();
216  }
217 
218 // If no exports were specified, the default is that we are writable
219 //
220  if (ossRW == ' ') ossRW = 'w';
221 
222 // Adjust the umask to correspond to the maximum mode allowed
223 //
224  mode_t uMask = 0777 & (~(dMask[1] | fMask[1]));
225  umask(uMask);
226 
227 // Export our role if we actually have one
228 //
229  if (myRole) XrdOucEnv::Export("XRDROLE", myRole);
230 
231 // Set the redirect option for other layers
232 //
233  if (Options & isManager)
234  XrdOucEnv::Export("XRDREDIRECT", (Options & isMeta ? "M" : "R"));
235  else XrdOucEnv::Export("XRDREDIRECT", "0");
236 
237 // If we are a proxy, then figure out where the prosy storge system resides
238 //
239  if ((Options & isProxy) && !(Options & isManager))
240  {char buff[2048], *bp, *libofs = getenv("XRDOFSLIB");
241  if (!libofs) bp = buff;
242  else {strcpy(buff, libofs); bp = buff+strlen(buff)-1;
243  while(bp != buff && *(bp-1) != '/') bp--;
244  }
245  strcpy(bp, "libXrdPss.so");
246  ofsConfig->Default(XrdOfsConfigPI::theOssLib, buff, 0);
247  ofsConfig->Default(XrdOfsConfigPI::theCksLib, buff, 0);
248  }
249 
250 // Configure third party copy but only if we are not a manager. Phase 1 needs
251 // to be done before we load the plugins as they may need this info.
252 //
253  if ((Options & ThirdPC) && !(Options & isManager))
254  NoGo |= ConfigTPC(Eroute, EnvInfo);
255 
256 // We need to do pre-initialization for event recording as the oss needs some
257 // environmental information from that initialization to initialize the frm,
258 // should it need to be used. We will do full evr initialization after the oss
259 // and the finder are initialized. A bit messy in the current plug-in world.
260 //
261  if (!(Options & isManager) && !evrObject.Init(&Eroute)) NoGo = 1;
262 
263 // Determine whether we should load authorization
264 //
265  int piOpts = XrdOfsConfigPI::allXXXLib;
266  if (!(Options & Authorize)) piOpts &= ~XrdOfsConfigPI::theAutLib;
267 
268 // We need to export plugins to other protocols which means we need to
269 // record them in the outmost environment. So get it.
270 //
271  XrdOucEnv *xrdEnv = 0;
272  if (EnvInfo) xrdEnv = (XrdOucEnv*)EnvInfo->GetPtr("xrdEnv*");
273 
274 // Now load all of the required plugins
275 //
276  if (!ofsConfig->Load(piOpts, EnvInfo)) NoGo = 1;
277  else {ofsConfig->Plugin(XrdOfsOss);
278  ossFeatures = XrdOfsOss->Features();
279  if (ossFeatures & XRDOSS_HASNOSF) FeatureSet |= XrdSfs::hasNOSF;
280  if (ossFeatures & XRDOSS_HASCACH)
282  if (xrdEnv) xrdEnv->Put("XrdCache", "T"); // Existence check
283  }
284  if (ossFeatures & XRDOSS_HASNAIO) FeatureSet |= XrdSfs::hasNAIO;
285  if (xrdEnv) xrdEnv->PutPtr("XrdOss*", XrdOfsOss);
286  ofsConfig->Plugin(Cks);
287  CksPfn = !ofsConfig->OssCks();
288  CksRdr = !ofsConfig->LclCks();
289  if (ofsConfig->Plugin(prepHandler))
290  {prepAuth = ofsConfig->PrepAuth();
292  }
293  if (Options & Authorize)
294  {ofsConfig->Plugin(Authorization);
295  XrdOfsTPC::Init(Authorization);
296  if (xrdEnv) xrdEnv->PutPtr("XrdAccAuthorize*",Authorization);
298  }
299  }
300 
301 // If a cache has been configured then that cache may want to interact with
302 // the cache-specific FSctl() operation. We check if a plugin was provided.
303 //
304  if (ossFeatures & XRDOSS_HASCACH)
305  FSctl_PC = (XrdOfsFSctl_PI*)EnvInfo->GetPtr("XrdFSCtl_PC*");
306 
307 // Configure third party copy phase 2, but only if we are not a manager.
308 //
309  if ((Options & ThirdPC) && !(Options & isManager)) NoGo |= ConfigTPC(Eroute);
310 
311 // Extract out the export list should it have been supplied by the oss plugin
312 //
313  ossRPList = (XrdOucPListAnchor *)EnvInfo->GetPtr("XrdOssRPList*");
314 
315 // Initialize redirection. We type te herald here to minimize confusion
316 //
317  if (Options & haveRole)
318  {Eroute.Say("++++++ Configuring ", myRole, " role. . .");
319  if (ConfigRedir(Eroute, EnvInfo))
320  {Eroute.Emsg("Config", "Unable to create cluster management client.");
321  NoGo = 1;
322  }
323  }
324 
325 // Initialize the FSctl plugin if we have one. Note that we needed to defer
326 // until now because we needed to configure the cms plugin first (see above).
327 //
328  if (ofsConfig->Plugin(FSctl_PI) && !ofsConfig->ConfigCtl(Finder, EnvInfo))
329  {Eroute.Emsg("Config", "Unable to configure FSctl plugin.");
330  NoGo = 1;
331  }
332 
333 // Initialize the cache FSctl handler if we have one. The same deferal applies.
334 //
335  if (FSctl_PC)
336  {struct XrdOfsFSctl_PI::Plugins thePI = {Authorization, Finder,
338  XrdOucEnv pcEnv;
339  pcEnv.PutPtr("XrdOfsHandle*", dummyHandle);
340  if (!FSctl_PC->Configure(ConfigFN, 0, &pcEnv, thePI))
341  {Eroute.Emsg("Config", "Unable to configure cache FSctl handler.");
342  NoGo = 1;
343  }
344  }
345 
346 // Initialize th Evr object if we are an actual server
347 //
348  if (!(Options & isManager) && !evrObject.Init(Balancer)) NoGo = 1;
349 
350 // Turn off forwarding if we are not a pure remote redirector or a peer
351 //
352  if (Options & Forwarding)
353  {const char *why = 0;
354  if (!(Options & Authorize)) why = "authorization not enabled";
355  else if (!(Options & isPeer) && (Options & (isServer | isProxy)))
356  why = "not a pure manager";
357  if (why)
358  {Eroute.Say("Config warning: forwarding turned off; ", why);
359  Options &= ~(Forwarding);
362  fwdTRUNC.Reset();
363  }
364  }
365 
366 // If we need to send notifications, initialize the interface
367 //
368  if (!NoGo && evsObject) NoGo = evsObject->Start(&Eroute);
369 
370 // If the OSS plugin is really a proxy. If it is, it will export its origin.
371 // We also suppress translating lfn to pfn (usually done via osslib +cksio).
372 // Note: consulting the ENVAR below is historic and remains for compatibility
373 // Otherwise we can configure checkpointing if we are a data server.
374 //
375  if (ossFeatures & XRDOSS_HASPRXY || getenv("XRDXROOTD_PROXY"))
376  {OssIsProxy = 1;
377  CksPfn = false;
379  } else if (!(Options & isManager) && !XrdOfsConfigCP::Init()) NoGo = 1;
380 
381 // Indicate wheter oss implements pgrw or it has to be simulated
382 //
383  OssHasPGrw = (ossFeatures & XRDOSS_HASPGRW) != 0;
384 
385 // If POSC processing is enabled (as by default) do it. Warning! This must be
386 // the last item in the configuration list as we need a working filesystem.
387 // Note that in proxy mode we always disable posc!
388 //
389  if (OssIsProxy || getenv("XRDXROOTD_NOPOSC"))
390  {if (poscAuto != -1 && !NoGo)
391  Eroute.Say("Config POSC has been disabled by the osslib plugin.");
392  } else if (poscAuto != -1 && !NoGo) NoGo |= ConfigPosc(Eroute);
393 
394 // Setup statistical monitoring
395 //
396  OfsStats.setRole(myRole);
397 
398 // Display final configuration
399 //
400  if (!NoGo) Config_Display(Eroute);
401  delete ofsConfig; ofsConfig = 0;
402 
403 // All done
404 //
405  tmp = (NoGo ? " initialization failed." : " initialization completed.");
406  Eroute.Say("------ File system ", myRole, tmp);
407  return NoGo;
408 }
409 
410 /******************************************************************************/
411 /* C o n f i g _ D i s p l a y */
412 /******************************************************************************/
413 
414 #define setBuff(x,y) {strcpy(bp, x); bp += y;}
415 
417 {
418  const char *cloc, *pval;
419  char buff[8192], fwbuff[512], *bp;
420  int i;
421 
422  if (!ConfigFN || !ConfigFN[0]) cloc = "default";
423  else cloc = ConfigFN;
424  if (!poscQ) pval = "off";
425  else pval = (poscAuto ? "auto" : "manual");
426 
427  snprintf(buff, sizeof(buff), "Config effective %s ofs configuration:\n"
428  " all.role %s\n"
429  "%s"
430  " ofs.maxdelay %d\n"
431  " ofs.persist %s hold %d%s%s\n"
432  " ofs.trace %x",
433  cloc, myRole,
434  (Options & Authorize ? " ofs.authorize\n" : ""),
435  MaxDelay,
436  pval, poscHold, (poscLog ? " logdir " : ""),
437  (poscLog ? poscLog : ""), OfsTrace.What);
438 
439  Eroute.Say(buff);
440  ofsConfig->Display();
441 
442  if (Options & Forwarding)
443  {*fwbuff = 0;
444  if (ConfigDispFwd(buff, fwdCHMOD))
445  {Eroute.Say(buff); strcat(fwbuff, " ch");}
446  if (ConfigDispFwd(buff, fwdMKDIR))
447  {Eroute.Say(buff); strcat(fwbuff, " mk");}
448  if (ConfigDispFwd(buff, fwdMV))
449  {Eroute.Say(buff); strcat(fwbuff, " mv");}
450  if (ConfigDispFwd(buff, fwdRM))
451  {Eroute.Say(buff); strcat(fwbuff, " rm");}
452  if (ConfigDispFwd(buff, fwdRMDIR))
453  {Eroute.Say(buff); strcat(fwbuff, " rd");}
454  if (ConfigDispFwd(buff, fwdTRUNC))
455  {Eroute.Say(buff); strcat(fwbuff, " tr");}
456  if (*fwbuff) XrdOucEnv::Export("XRDOFS_FWD", fwbuff);
457  }
458 
459  if (evsObject)
460  {bp = buff;
461  setBuff(" ofs.notify ", 18); // 1234567890
462  if (evsObject->Enabled(XrdOfsEvs::Chmod)) setBuff("chmod ", 6);
463  if (evsObject->Enabled(XrdOfsEvs::Closer)) setBuff("closer ", 7);
464  if (evsObject->Enabled(XrdOfsEvs::Closew)) setBuff("closew ", 7);
465  if (evsObject->Enabled(XrdOfsEvs::Create)) setBuff("create ", 7);
466  if (evsObject->Enabled(XrdOfsEvs::Mkdir)) setBuff("mkdir ", 6);
467  if (evsObject->Enabled(XrdOfsEvs::Mv)) setBuff("mv ", 3);
468  if (evsObject->Enabled(XrdOfsEvs::Openr)) setBuff("openr ", 6);
469  if (evsObject->Enabled(XrdOfsEvs::Openw)) setBuff("openw ", 6);
470  if (evsObject->Enabled(XrdOfsEvs::Rm)) setBuff("rm ", 3);
471  if (evsObject->Enabled(XrdOfsEvs::Rmdir)) setBuff("rmdir ", 6);
472  if (evsObject->Enabled(XrdOfsEvs::Trunc)) setBuff("trunc ", 6);
473  if (evsObject->Enabled(XrdOfsEvs::Fwrite)) setBuff("fwrite ", 7);
474  setBuff("msgs ", 5);
475  i=sprintf(fwbuff,"%d %d ",evsObject->maxSmsg(),evsObject->maxLmsg());
476  setBuff(fwbuff, i);
477  cloc = evsObject->Prog();
478  if (*cloc != '>') setBuff("|",1);
479  setBuff(cloc, strlen(cloc));
480  setBuff("\0", 1);
481  Eroute.Say(buff);
482  }
483 }
484 
485 /******************************************************************************/
486 /* p r i v a t e f u n c t i o n s */
487 /******************************************************************************/
488 /******************************************************************************/
489 /* C o n f i g D i s p F w d */
490 /******************************************************************************/
491 
492 int XrdOfs::ConfigDispFwd(char *buff, struct fwdOpt &Fwd)
493 {
494  const char *cP;
495  char pbuff[16], *bp;
496 
497 // Return if this is not being forwarded
498 //
499  if (!(cP = Fwd.Cmd)) return 0;
500  bp = buff;
501  setBuff(" ofs.forward ", 19);
502 
503 // Chck which way this is being forwarded
504 //
505  if (*Fwd.Cmd == '+'){setBuff("2way ",5); cP++;}
506  else if (!Fwd.Port) {setBuff("1way ",5);}
507  else { setBuff("3way ",5);
508  if (Fwd.Port < 0) {setBuff("local ",6);}
509  else {int n = sprintf(pbuff, ":%d ", Fwd.Port);
510  setBuff(Fwd.Host, strlen(Fwd.Host));
511  setBuff(pbuff, n);
512  }
513  }
514  setBuff(cP, strlen(cP));
515  return 1;
516 }
517 
518 /******************************************************************************/
519 /* C o n f i g P o s c */
520 /******************************************************************************/
521 
522 int XrdOfs::ConfigPosc(XrdSysError &Eroute)
523 {
524  extern XrdOfs* XrdOfsFS;
525  const int AMode = S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH; // 775
526  class CloseFH : public XrdOfsHanCB
527  {public: void Retired(XrdOfsHandle *hP) {XrdOfsFS->Unpersist(hP);}};
528  static XrdOfsHanCB *hCB = static_cast<XrdOfsHanCB *>(new CloseFH);
529 
530  XrdOfsPoscq::recEnt *rP, *rPP;
532  XrdOfsHandle *hP;
533  const char *iName;
534  char pBuff[MAXPATHLEN], *aPath;
535  int NoGo, rc;
536 
537 // Construct the proper path to the recovery file
538 //
539  iName = XrdOucUtils::InstName(-1);
540  if (poscLog) aPath = XrdOucUtils::genPath(poscLog, iName, ".ofs/posc.log");
541  else {if (!(aPath = getenv("XRDADMINPATH")))
542  {XrdOucUtils::genPath(pBuff, MAXPATHLEN, "/tmp", iName);
543  aPath = pBuff;
544  }
545  aPath = XrdOucUtils::genPath(aPath, (char *)0, ".ofs/posc.log");
546  }
547  rc = strlen(aPath)-1;
548  if (aPath[rc] == '/') aPath[rc] = '\0';
549  free(poscLog); poscLog = aPath;
550 
551 // Make sure directory path exists
552 //
553  if ((rc = XrdOucUtils::makePath(poscLog, AMode)))
554  {Eroute.Emsg("Config", rc, "create path for", poscLog);
555  return 1;
556  }
557 
558 // Create object then initialize it
559 //
560  poscQ = new XrdOfsPoscq(&Eroute, XrdOfsOss, poscLog, int(poscSync));
561  rP = poscQ->Init(rc);
562  if (!rc) return 1;
563 
564 // Get file handles and put then in pending delete for all recovered records
565 //
566  NoGo = 0;
567  while(rP)
568  {qP = &(rP->reqData);
569  if (qP->addT && poscHold)
571  {Eroute.Emsg("Config", "Unable to persist", qP->User, qP->LFN);
572  qP->addT = 0;
573  } else {
574  hP->PoscSet(qP->User, rP->Offset, rP->Mode);
575  hP->Retire(hCB, poscHold);
576  }
577  }
578  if (!(qP->addT) || !poscHold)
579  {if ((rc = XrdOfsOss->Unlink(qP->LFN)) && rc != -ENOENT)
580  {Eroute.Emsg("Config", rc, "unpersist", qP->LFN); NoGo = 1;}
581  else {Eroute.Emsg("Config", "Unpersisted", qP->User, qP->LFN);
582  poscQ->Del(qP->LFN, rP->Offset);
583  }
584  }
585  rPP = rP; rP = rP->Next; delete rPP;
586  }
587 
588 // All done
589 //
590  if (!NoGo) FeatureSet |= XrdSfs::hasPOSC;
591  return NoGo;
592 }
593 
594 /******************************************************************************/
595 /* C o n f i g R e d i r */
596 /******************************************************************************/
597 
598 int XrdOfs::ConfigRedir(XrdSysError &Eroute, XrdOucEnv *EnvInfo)
599 {
600  XrdCmsClient_t CmsPI;
601  XrdSysLogger *myLogger = Eroute.logger();
602  int isRedir = Options & isManager;
603  int RMTopts = (Options & isServer ? XrdCms::IsTarget : 0)
604  | (Options & isProxy ? XrdCms::IsProxy : 0)
605  | (Options & isMeta ? XrdCms::IsMeta : 0);
606  int TRGopts = (Options & isProxy ? XrdCms::IsProxy : 0)
607  | (isRedir ? XrdCms::IsRedir : 0) | XrdCms::IsTarget;
608 
609 // Get the cms object creator plugin
610 //
611  ofsConfig->Plugin(CmsPI);
612 
613 // For manager roles, we simply do a standard config
614 //
615  if (isRedir)
616  { if (CmsPI) Finder = CmsPI(myLogger, RMTopts, myPort, XrdOfsOss);
617  else if (XrdCmsFinderRMT::VCheck(XrdVERSIONINFOVAR(XrdOfs)))
619  RMTopts,myPort);
620  else return 1;
621  if (!Finder) return 1;
622  if (!ofsConfig->Configure(Finder, EnvInfo))
623  {delete Finder; Finder = 0; return 1;}
624  if (EnvInfo) EnvInfo->PutPtr("XRDCMSMANLIST", Finder->Managers());
625  }
626 
627 // If we are a subcluster for another cluster then we can only be so if we
628 // are a pure manager. If a subcluster directive was encountered and this is
629 // not true we need to turn that off here. Subclusters need a target finder
630 // just like supervisors eventhough we are not a supervisor.
631 //
632  if ((Options & haveRole) != isManager) Options &= ~SubCluster;
633 
634 // For server roles find the port number and create the object. We used to pass
635 // the storage system object to the finder to allow it to process cms storage
636 // requests. The cms no longer sends such requests so there is no need to do
637 // so. And, in fact, we need to defer creating a storage system until after the
638 // finder is created. So, it's just as well we pass a numm pointer. At some
639 // point the finder should remove all storage system related code.
640 //
641  if (Options & (isServer | SubCluster | (isPeer & ~isManager)))
642  {if (!myPort)
643  {Eroute.Emsg("Config", "Unable to determine server's port number.");
644  return 1;
645  }
646  if (CmsPI) Balancer = CmsPI(myLogger, TRGopts, myPort, XrdOfsOss);
647  else if (XrdCmsFinderTRG::VCheck(XrdVERSIONINFOVAR(XrdOfs)))
648  Balancer = (XrdCmsClient *)new XrdCmsFinderTRG(myLogger,
649  TRGopts,myPort);
650  else return 1;
651  if (!Balancer) return 1;
652  if (!ofsConfig->Configure(Balancer, EnvInfo))
653  {delete Balancer; Balancer = 0; return 1;}
654  if (Options & (isProxy | SubCluster))
655  Balancer = 0; // No chatting for proxies or subclusters
656  }
657 
658 // All done
659 //
660  return 0;
661 }
662 
663 /******************************************************************************/
664 /* C o n f i g T P C */
665 /******************************************************************************/
666 
667 
668 int XrdOfs::ConfigTPC(XrdSysError &Eroute, XrdOucEnv *envP)
669 {
671 
672 // Check if we need to configure rge credentials directory
673 //
674  if (Cfg.fCreds)
675  {char *cpath = Cfg.cPath;
676  if (!(Cfg.cPath = ConfigTPCDir(Eroute, ".ofs/.tpccreds/", cpath)))
677  return 1;
678  free(cpath);
679  }
680 
681 // Construct the reproxy path. We always do this as need to solve the cart-horse
682 // problem of plugin loading. If we don't need it it will be ignored later.
683 //
684  if (!(Cfg.rPath = ConfigTPCDir(Eroute, ".ofs/.tpcproxy"))) return 1;
685  if (envP) envP->Put("tpc.rpdir", Cfg.rPath);
686 
687 // Check if TPC monitoring is wanted and set it up
688 //
689  Cfg.tpcMon = (XrdXrootdTpcMon*)envP->GetPtr("TpcMonitor*");
690 
691 // All done
692 //
693  return 0;
694 }
695 
696 /******************************************************************************/
697 
698 int XrdOfs::ConfigTPC(XrdSysError &Eroute)
699 {
701 
702 // If the oss plugin does not use a reproxy then remove it from the TPC config.
703 // Otherwise, complete it.
704 //
705  if (ossFeatures & XRDOSS_HASRPXY && Cfg.rPath)
706  {char rPBuff[1024];
707  reProxy = true;
708  snprintf(rPBuff,sizeof(rPBuff),"%s/%x-%%d.rpx",Cfg.rPath,int(time(0)));
709  free(Cfg.rPath);
710  Cfg.rPath = strdup(rPBuff);
711  } else {
712  if (Cfg.rPath) free(Cfg.rPath);
713  Cfg.rPath = 0;
714  }
715 
716 // Initialize the TPC object
717 //
718  XrdOfsTPC::Init();
719 
720 // Start TPC operations
721 //
722  return (XrdOfsTPC::Start() ? 0 : 1);
723 }
724 /******************************************************************************/
725 /* C o n f i g T P C D i r */
726 /******************************************************************************/
727 
728 char *XrdOfs::ConfigTPCDir(XrdSysError &Eroute, const char *sfx,
729  const char *xPath)
730 {
731 
732  const int AMode = S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH; // 775
733  const int BMode = S_IRWXU| S_IRGRP|S_IXGRP; // 750
734  const int nswOpt= XrdOucNSWalk::retFile | XrdOucNSWalk::retLink;
735  const char *iName;
736  char pBuff[MAXPATHLEN], *aPath;
737  int rc;
738 
739 // Construct the proper path to stored credentials
740 //
741  iName = XrdOucUtils::InstName(-1);
742  if (xPath) aPath = XrdOucUtils::genPath(xPath, iName, sfx);
743  else {if (!(aPath = getenv("XRDADMINPATH")))
744  {XrdOucUtils::genPath(pBuff, MAXPATHLEN, "/tmp", iName);
745  aPath = pBuff;
746  }
747  aPath = XrdOucUtils::genPath(aPath, (char *)0, sfx);
748  }
749 
750 // Make sure directory path exists
751 //
752  if ((rc = XrdOucUtils::makePath(aPath, AMode)))
753  {Eroute.Emsg("Config", rc, "create TPC path", aPath);
754  free(aPath);
755  return 0;
756  }
757 
758 // Protect the last component
759 //
760  if (SetMode(aPath, BMode))
761  {Eroute.Emsg("Config", errno, "protect TPC path", aPath);
762  free(aPath);
763  return 0;
764  }
765 
766 // list the contents of the directory
767 //
768  XrdOucNSWalk nsWalk(&Eroute, aPath, 0, nswOpt);
769  XrdOucNSWalk::NSEnt *nsX, *nsP = nsWalk.Index(rc);
770  if (rc)
771  {Eroute.Emsg("Config", rc, "list TPC path", aPath);
772  free(aPath);
773  return 0;
774  }
775 
776 // Remove directory contents of all files
777 //
778  bool isBad = false;
779  while((nsX = nsP))
780  {nsP = nsP->Next;
781  if (unlink(nsX->Path))
782  {Eroute.Emsg("Config", errno, "remove TPC creds", nsX->Path);
783  isBad = true;
784  }
785  delete nsX;
786  }
787 
788 // Check if all went well
789 //
790  if (isBad) {free(aPath); return 0;}
791 
792 // All done
793 //
794  return aPath;
795 }
796 
797 /******************************************************************************/
798 /* C o n f i g X e q */
799 /******************************************************************************/
800 
802  XrdSysError &Eroute)
803 {
804  char *val, vBuff[64];
805 
806  // Now assign the appropriate global variable
807  //
808  TS_Bit("authorize", Options, Authorize);
809  TS_XPI("authlib", theAutLib);
810  TS_XPI("ckslib", theCksLib);
811  TS_Xeq("cksrdsz", xcrds);
812  TS_XPI("cmslib", theCmsLib);
813  TS_Xeq("crmode", xcrm);
814  TS_XPI("ctllib", theCtlLib);
815  TS_Xeq("dirlist", xdirl);
816  TS_Xeq("forward", xforward);
817  TS_Xeq("maxdelay", xmaxd);
818  TS_Xeq("notify", xnot);
819  TS_Xeq("notifymsg", xnmsg);
820  TS_XPI("osslib", theOssLib);
821  TS_Xeq("persist", xpers);
822  TS_XPI("preplib", thePrpLib);
823  TS_Xeq("role", xrole);
824  TS_Xeq("tpc", xtpc);
825  TS_Xeq("trace", xtrace);
826  TS_Xeq("xattr", xatr);
827  TS_XPI("xattrlib", theAtrLib);
828 
829  // Process miscellaneous directives handled elsemwhere
830  //
831  if (!strcmp("chkpnt", var)) return (XrdOfsConfigCP::Parse(Config) ? 0 : 1);
832 
833  // Screen out the subcluster directive (we need to track that)
834  //
835  TS_Bit("subcluster",Options,SubCluster);
836 
837  // Get the actual value for simple directives
838  //
839  strlcpy(vBuff, var, sizeof(vBuff)); var = vBuff;
840  if (!(val = Config.GetWord()))
841  {Eroute.Emsg("Config", "value not specified for", var); return 1;}
842 
843  // No match found, complain.
844  //
845  Eroute.Say("Config warning: ignoring unknown directive '",var,"'.");
846  Config.Echo();
847  return 0;
848 }
849 
850 /******************************************************************************/
851 /* x c r d s */
852 /******************************************************************************/
853 
854 /* Function: xcrds
855 
856  Purpose: To parse the directive: cksrdsz <size>
857 
858  <size> number of bytes to segment reads when calclulating a
859  checksum. Can be suffixed by k,m,g. Maximum is 1g and
860  is automatically set to be atleast 64k and to be a
861  multiple of 64k.
862 
863  Output: 0 upon success or !0 upon failure.
864 */
865 
866 int XrdOfs::xcrds(XrdOucStream &Config, XrdSysError &Eroute)
867 {
868  static const long long maxRds = 1024*1024*1024;
869  char *val;
870  long long rdsz;
871 
872 // Get the size
873 //
874  if (!(val = Config.GetWord()) || !val[0])
875  {Eroute.Emsg("Config", "cksrdsz size not specified"); return 1;}
876 
877 // Now convert it
878 //
879  if (XrdOuca2x::a2sz(Eroute, "cksrdsz size", val, &rdsz, 1, maxRds)) return 1;
880  ofsConfig->SetCksRdSz(static_cast<int>(rdsz));
881  return 0;
882 }
883 
884 /******************************************************************************/
885 /* x c r m */
886 /******************************************************************************/
887 
888 /* Function: xcrm
889 
890  Purpose: To parse the directive: crmode [dirs <mspec>] [files <mspec>]
891 
892  <mspec>: common | legacy | [raw] <modes>
893 
894  common uses dirs 0700:0755 and files 0600:0644
895 
896  legacy uses dirs 0000:0775 and files 0000:0775
897 
898  raw Allows actual specification of mode bits without enforcing
899  default requirements. The resulting modes may not be 0.
900  Otherwise, the specified values are made consistent with
901  the default mode settings.
902 
903  <modes>: <minv> | :<maxv> | <minv>:<maxv>
904 
905  <minv>: The minimum mode value required (always set), see <mval>.
906  <maxv>: The maximum mode value to be enforced, see <mval>.
907 
908  <mval> is either an octal mode specifiation or a standard ls type
909  mode specification (i.e. 'rwx'). The specification is in
910  groups of 3 letters. The first group designates user mode,
911  the scond group mode, and the last other mode. To disallow
912  a mode specify a dash. Note that for files, the 'x'
913  character must be a dash unless raw mode is enabled. It is
914  impossible to disllow any mode for user except for raw mode.
915 
916  Output: 0 upon success or !0 upon failure.
917 */
918 
919 int XrdOfs::xcrm(XrdOucStream &Config, XrdSysError &Eroute)
920 {
921  static const mode_t dMin = 0700, dMax = 0775, fMin = 0600, fMax = 0664;
922  static const mode_t xBit = 0111, wBit = 0002;
923  const char *mtype;
924  char *colon, *val, *minM, *maxM;
925  mode_t mMask[2];
926  bool isDirs, isRaw;
927 
928 // Get the size
929 //
930  if (!(val = Config.GetWord()) || !val[0])
931  {Eroute.Emsg("Config", "crmode argument not specified"); return 1;}
932 
933 // Process all of the specs
934 //
935 do{if (!strcmp("dirs", val)) {isDirs = true; mtype = "dirs mode";}
936  else if (!strcmp("files", val)) {isDirs = false; mtype = "files mode";}
937  else {Eroute.Emsg("Config", "invalid mode type - ", val);
938  return 1;
939  }
940 
941  if (!(val = Config.GetWord()) || !val[0])
942  {Eroute.Emsg("Config", mtype, "value not specified"); return 1;}
943 
944  if (!strcmp(val, "common"))
945  {if (isDirs) {dMask[0] = dMin; dMask[1] = dMax;}
946  else {fMask[0] = fMin; fMask[1] = fMax;}
947  continue;
948  }
949 
950  if (!strcmp(val, "legacy"))
951  {if (isDirs) {dMask[0] = 0; dMask[1] = 0775;}
952  else {fMask[0] = 0; fMask[1] = 0775;}
953  continue;
954  }
955 
956  if ((isRaw = !strcmp(val, "raw")))
957  {if (!(val = Config.GetWord()) || !val[0])
958  {Eroute.Emsg("Config", mtype, "value not specified"); return 1;}
959  }
960 
961  colon = index(val, ':');
962  if (!colon || colon == val || *(colon+1) == 0)
963  {Eroute.Emsg("Config",mtype,"mode spec requires min and max values");
964  return 1;
965  }
966  minM = val; *colon = 0; maxM = colon + 1;
967 
968  if (!XrdOucUtils::mode2mask(minM, mMask[0]))
969  {Eroute.Emsg("Config", mtype, "value is invalid -", minM);
970  return 1;
971  }
972 
973  if (!XrdOucUtils::mode2mask(maxM, mMask[1]))
974  {Eroute.Emsg("Config", mtype, "value is invalid -", maxM);
975  return 1;
976  }
977 
978  if (isDirs)
979  {if (isRaw) {dMask[0] = mMask[0]; dMask[1] = mMask[1];}
980  else {if ((mMask[0] | mMask[1]) & wBit)
981  {Eroute.Say("Config warning: 'other' w-mode removed from dirs mode!");
982  mMask[0] &= ~wBit; mMask[1] &= ~wBit;
983  }
984  dMask[0] = (mMask[0] | dMin) & dMax;
985  dMask[1] = (mMask[1] | dMin) & dMax;
986  }
987  if ((dMask[0] & dMask[1]) != dMask[0])
988  {Eroute.Emsg("Config","dirs mode min and max values are inconsistent!");
989  return 1;
990  }
991  } else { // Files
992  if (isRaw) {fMask[0] = mMask[0]; fMask[1] = mMask[1];}
993  else {if ((mMask[0] | mMask[1]) & wBit)
994  {Eroute.Say("Config warning: 'other' w-mode removed from files mode!");
995  mMask[0] &= ~wBit; mMask[1] &= ~wBit;
996  }
997  if ((mMask[0] | mMask[1]) & xBit)
998  {Eroute.Say("Config warning: x-mode removed from files mode!");
999  mMask[0] &= ~xBit; mMask[1] &= ~xBit;
1000  }
1001  fMask[0] = (mMask[0] | fMin) & fMax;
1002  fMask[1] = (mMask[1] | fMin) & fMax;
1003  }
1004  if ((fMask[0] & fMask[1]) != fMask[0])
1005  {Eroute.Emsg("Config","files mode min and max values are inconsistent!");
1006  return 1;
1007  }
1008  }
1009  } while((val = Config.GetWord()) && val[0]);
1010 
1011 // All done, return success
1012 //
1013  return 0;
1014 }
1015 
1016 /******************************************************************************/
1017 /* x d i r l */
1018 /******************************************************************************/
1019 
1020 /* Function: xdirl
1021 
1022  Purpose: To parse the directive: dirlist {local | remote}
1023 
1024  local processes directory listings locally. The oss plugin
1025  must be capable of doing this. This is the default.
1026  remote if clustering is enabled, directory listings are
1027  processed as directed by the cmsd.
1028 
1029  Output: 0 upon success or !0 upon failure.
1030 */
1031 
1032 int XrdOfs::xdirl(XrdOucStream &Config, XrdSysError &Eroute)
1033 {
1034  char *val;
1035 
1036 // Get the parameter
1037 //
1038  if (!(val = Config.GetWord()) || !val[0])
1039  {Eroute.Emsg("Config", "dirlist parameter not specified"); return 1;}
1040 
1041 // Set appropriate option
1042 //
1043  if (!strcmp(val, "local")) DirRdr = false;
1044  else if (!strcmp(val, "remote")) DirRdr = true;
1045  else {Eroute.Emsg("Config", "Invalid dirlist parameter -", val); return 1;}
1046 
1047  return 0;
1048 }
1049 
1050 /******************************************************************************/
1051 /* x e x p */
1052 /******************************************************************************/
1053 
1054 /* Function: xexp
1055 
1056  Purpose: To prescan the all.export and oss.defaults directives to determine
1057  if we have any writable paths.
1058 
1059  Output: 0 upon success or !0 upon failure.
1060 */
1061 
1062 int XrdOfs::xexp(XrdOucStream &Config, XrdSysError &Eroute, bool isExport)
1063 {
1064  static struct rwOpts {const char *opname; int isRW;} rwtab[] =
1065  {{"r/o", 0}, {"readonly", 0},
1066  {"forcero", 0}, {"notwritable", 0},
1067  {"writable", 1}, {"r/w", 1}
1068  };
1069  static bool defRW = true;
1070  int isrw = -1, numopts = sizeof(rwtab)/sizeof(struct rwOpts);
1071  char *val;
1072 
1073 // If this is an export and we already know that we have a writable path, return
1074 // Otherwise, scan over the path argument.
1075 //
1076  if (isExport && (ossRW == 'w' || !(val = Config.GetWord()))) return 0;
1077 
1078 // Throw away path and scan all the options looking for something of interest
1079 //
1080  while((val = Config.GetWord()))
1081  {for (int i = 0; i < numopts; i++)
1082  if (!strcmp(val, rwtab[i].opname)) isrw = rwtab[i].isRW;
1083  else if (!strcmp(val, "cache")) {isrw = 0; break;}
1084  }
1085 
1086 // Handle result depending if this is an export or a defaults
1087 //
1088  if (isrw < 0) isrw = defRW;
1089  if (isExport) ossRW = (isrw ? 'w' : 'r');
1090  else {defRW = (isrw ? true : false);
1091  if (ossRW == ' ' && !isrw) ossRW = 'r';
1092  }
1093  return 0;
1094 }
1095 
1096 /******************************************************************************/
1097 /* x f o r w a r d */
1098 /******************************************************************************/
1099 
1100 /* Function: xforward
1101 
1102  Purpose: To parse the directive: forward [<handling>] <metaops>
1103 
1104  handling: 1way | 2way | 3way {local | <host>:<port>}
1105 
1106  1way forward does not respond (the default)
1107  2way forward responds; relay response back.
1108  3way forward 1way and execute locally or redirect to <host>
1109  <metaops> list of meta-file operations to forward to manager
1110 
1111  Output: 0 upon success or !0 upon failure.
1112 */
1113 
1114 int XrdOfs::xforward(XrdOucStream &Config, XrdSysError &Eroute)
1115 {
1116  enum fwdType {OfsFWDALL = 0x3f, OfsFWDCHMOD = 0x01, OfsFWDMKDIR = 0x02,
1117  OfsFWDMV = 0x04, OfsFWDRM = 0x08, OfsFWDRMDIR = 0x10,
1118  OfsFWDREM = 0x18, OfsFWDTRUNC = 0x20, OfsFWDNONE = 0};
1119 
1120  static struct fwdopts {const char *opname; fwdType opval;} fwopts[] =
1121  {
1122  {"all", OfsFWDALL},
1123  {"chmod", OfsFWDCHMOD},
1124  {"mkdir", OfsFWDMKDIR},
1125  {"mv", OfsFWDMV},
1126  {"rm", OfsFWDRM},
1127  {"rmdir", OfsFWDRMDIR},
1128  {"remove", OfsFWDREM},
1129  {"trunc", OfsFWDTRUNC}
1130  };
1131  int fwval = OfsFWDNONE, fwspec = OfsFWDNONE;
1132  int numopts = sizeof(fwopts)/sizeof(struct fwdopts);
1133  int i, neg, rPort = 0, is2way = 0, is3way = 0;
1134  char *val, *pp, rHost[512];
1135 
1136  *rHost = '\0';
1137  if (!(val = Config.GetWord()))
1138  {Eroute.Emsg("Config", "forward option not specified"); return 1;}
1139  if ((is2way = !strcmp("2way", val)) || !strcmp("1way", val)
1140  || (is3way = !strcmp("3way", val)))
1141  if (!(val = Config.GetWord()))
1142  {Eroute.Emsg("Config", "forward operation not specified"); return 1;}
1143 
1144  if (is3way)
1145  {if (!strcmp("local", val)) rPort = -1;
1146  else
1147  {if (*val == ':')
1148  {Eroute.Emsg("Config", "redirect host not specified"); return 1;}
1149  if (!(pp = index(val, ':')))
1150  {Eroute.Emsg("Config", "redirect port not specified"); return 1;}
1151  if ((rPort = atoi(pp+1)) <= 0)
1152  {Eroute.Emsg("Config", "redirect port is invalid"); return 1;}
1153  *pp = '\0';
1154  strlcpy(rHost, val, sizeof(rHost));
1155  }
1156  if (!(val = Config.GetWord()))
1157  {Eroute.Emsg("Config", "forward operation not specified"); return 1;}
1158  }
1159 
1160  while (val)
1161  {if (!strcmp(val, "off")) {fwval = OfsFWDNONE; fwspec = OfsFWDALL;}
1162  else {if ((neg = (val[0] == '-' && val[1]))) val++;
1163  for (i = 0; i < numopts; i++)
1164  {if (!strcmp(val, fwopts[i].opname))
1165  {if (neg) fwval &= ~fwopts[i].opval;
1166  else fwval |= fwopts[i].opval;
1167  fwspec |= fwopts[i].opval;
1168  break;
1169  }
1170  }
1171  if (i >= numopts)
1172  Eroute.Say("Config warning: ignoring invalid forward option '",val,"'.");
1173  }
1174  val = Config.GetWord();
1175  }
1176 
1177  if (fwspec & OfsFWDCHMOD)
1178  {fwdCHMOD.Cmd = (fwval&OfsFWDCHMOD ? (is2way ? "+chmod" :"chmod") : 0);
1179  if (fwdCHMOD.Host) free(fwdCHMOD.Host);
1180  fwdCHMOD.Host = strdup(rHost); fwdCHMOD.Port = rPort;
1181  }
1182  if (fwspec&OfsFWDMKDIR)
1183  {fwdMKDIR.Cmd = (fwval&OfsFWDMKDIR ? (is2way ? "+mkdir" :"mkdir") : 0);
1184  if (fwdMKDIR.Host) free(fwdMKDIR.Host);
1185  fwdMKDIR.Host = strdup(rHost); fwdMKDIR.Port = rPort;
1186  fwdMKPATH.Cmd= (fwval&OfsFWDMKDIR ? (is2way ? "+mkpath":"mkpath") : 0);
1187  if (fwdMKPATH.Host) free(fwdMKPATH.Host);
1188  fwdMKPATH.Host = strdup(rHost); fwdMKPATH.Port = rPort;
1189  }
1190  if (fwspec&OfsFWDMV)
1191  {fwdMV .Cmd = (fwval&OfsFWDMV ? (is2way ? "+mv" :"mv") : 0);
1192  if (fwdMV.Host) free(fwdMV.Host);
1193  fwdMV.Host = strdup(rHost); fwdMV.Port = rPort;
1194  }
1195  if (fwspec&OfsFWDRM)
1196  {fwdRM .Cmd = (fwval&OfsFWDRM ? (is2way ? "+rm" :"rm") : 0);
1197  if (fwdRM.Host) free(fwdRM.Host);
1198  fwdRM.Host = strdup(rHost); fwdRM.Port = rPort;
1199  }
1200  if (fwspec&OfsFWDRMDIR)
1201  {fwdRMDIR.Cmd = (fwval&OfsFWDRMDIR ? (is2way ? "+rmdir" :"rmdir") : 0);
1202  if (fwdRMDIR.Host) free(fwdRMDIR.Host);
1203  fwdRMDIR.Host = strdup(rHost); fwdRMDIR.Port = rPort;
1204  }
1205  if (fwspec&OfsFWDTRUNC)
1206  {fwdTRUNC.Cmd = (fwval&OfsFWDTRUNC ? (is2way ? "+trunc" :"trunc") : 0);
1207  if (fwdTRUNC.Host) free(fwdTRUNC.Host);
1208  fwdTRUNC.Host = strdup(rHost); fwdTRUNC.Port = rPort;
1209  }
1210 
1211 // All done
1212 //
1213  Options |= Forwarding;
1214  return 0;
1215 }
1216 
1217 /******************************************************************************/
1218 /* x m a x d */
1219 /******************************************************************************/
1220 
1221 /* Function: xmaxd
1222 
1223  Purpose: To parse the directive: maxdelay <secs>
1224 
1225  <secs> maximum delay imposed for staging
1226 
1227  Output: 0 upon success or !0 upon failure.
1228 */
1229 
1230 int XrdOfs::xmaxd(XrdOucStream &Config, XrdSysError &Eroute)
1231 {
1232  char *val;
1233  int maxd;
1234 
1235  if (!(val = Config.GetWord()))
1236  {Eroute.Emsg("Config","maxdelay value not specified");return 1;}
1237  if (XrdOuca2x::a2i(Eroute, "maxdelay", val, &maxd, 30)) return 1;
1238 
1239  MaxDelay = maxd;
1240  return 0;
1241 }
1242 
1243 /******************************************************************************/
1244 /* x n m s g */
1245 /******************************************************************************/
1246 
1247 /* Function: xnmsg
1248 
1249  Purpose: To parse the directive: notifymsg <event> <msg>
1250 
1251  Args: <events> - one or more of: all chmod closer closew close mkdir mv
1252  openr openw open rm rmdir fwrite
1253  <msg> the notification message to be sent (see notify).
1254 
1255  Type: Manager only, non-dynamic.
1256 
1257  Output: 0 upon success or !0 upon failure.
1258 */
1259 
1260 int XrdOfs::xnmsg(XrdOucStream &Config, XrdSysError &Eroute)
1261 {
1262  static struct notopts {const char *opname; XrdOfsEvs::Event opval;}
1263  noopts[] = {
1264  {"chmod", XrdOfsEvs::Chmod},
1265  {"closer", XrdOfsEvs::Closer},
1266  {"closew", XrdOfsEvs::Closew},
1267  {"create", XrdOfsEvs::Create},
1268  {"mkdir", XrdOfsEvs::Mkdir},
1269  {"mv", XrdOfsEvs::Mv},
1270  {"openr", XrdOfsEvs::Openr},
1271  {"openw", XrdOfsEvs::Openw},
1272  {"rm", XrdOfsEvs::Rm},
1273  {"rmdir", XrdOfsEvs::Rmdir},
1274  {"trunc", XrdOfsEvs::Trunc},
1275  {"fwrite", XrdOfsEvs::Fwrite}
1276  };
1277  XrdOfsEvs::Event noval;
1278  int numopts = sizeof(noopts)/sizeof(struct notopts);
1279  char *val, buff[1024];
1280  XrdOucEnv *myEnv;
1281  int i;
1282 
1283  // At this point, make sure we have a value
1284  //
1285  if (!(val = Config.GetWord()))
1286  {Eroute.Emsg("Config", "notifymsg event not specified");
1287  return 1;
1288  }
1289 
1290  // Get the evant number
1291  //
1292  for (i = 0; i < numopts; i++) if (!strcmp(val, noopts[i].opname)) break;
1293  if (i >= numopts)
1294  {Eroute.Say("Config warning: ignoring invalid notify event '",val,"'.");
1295  return 1;
1296  }
1297  noval = noopts[i].opval;
1298 
1299  // We need to suck all the tokens to the end of the line for remaining
1300  // options. Do so, until we run out of space in the buffer.
1301  //
1302  myEnv = Config.SetEnv(0);
1303  if (!Config.GetRest(buff, sizeof(buff)))
1304  {Eroute.Emsg("Config", "notifymsg arguments too long");
1305  Config.SetEnv(myEnv);
1306  return 1;
1307  }
1308 
1309  // Restore substitutions and parse the message
1310  //
1311  Config.SetEnv(myEnv);
1312  return XrdOfsEvs::Parse(Eroute, noval, buff);
1313 }
1314 
1315 /******************************************************************************/
1316 /* x n o t */
1317 /* Based on code developed by Derek Feichtinger, CERN. */
1318 /******************************************************************************/
1319 
1320 /* Function: xnot
1321 
1322  Purpose: Parse directive: notify <events> [msgs <min> [<max>]]
1323  {|<prog> | ><path>}
1324 
1325  Args: <events> - one or more of: all chmod closer closew close mkdir mv
1326  openr openw open rm rmdir fwrite
1327  opaque and other possible information to be sent.
1328  msgs - Maximum number of messages to keep and queue. The
1329  <min> if for small messages (default 90) and <max> is
1330  for big messages (default 10).
1331  <prog> - is the program to execute and dynamically feed messages
1332  about the indicated events. Messages are piped to prog.
1333  <path> - is the udp named socket to receive the message. The
1334  server creates the path if it's not present.
1335 
1336  Output: 0 upon success or !0 upon failure.
1337 */
1338 int XrdOfs::xnot(XrdOucStream &Config, XrdSysError &Eroute)
1339 {
1340  static struct notopts {const char *opname; XrdOfsEvs::Event opval;}
1341  noopts[] = {
1342  {"all", XrdOfsEvs::All},
1343  {"chmod", XrdOfsEvs::Chmod},
1344  {"close", XrdOfsEvs::Close},
1345  {"closer", XrdOfsEvs::Closer},
1346  {"closew", XrdOfsEvs::Closew},
1347  {"create", XrdOfsEvs::Create},
1348  {"mkdir", XrdOfsEvs::Mkdir},
1349  {"mv", XrdOfsEvs::Mv},
1350  {"open", XrdOfsEvs::Open},
1351  {"openr", XrdOfsEvs::Openr},
1352  {"openw", XrdOfsEvs::Openw},
1353  {"rm", XrdOfsEvs::Rm},
1354  {"rmdir", XrdOfsEvs::Rmdir},
1355  {"trunc", XrdOfsEvs::Trunc},
1356  {"fwrite", XrdOfsEvs::Fwrite}
1357  };
1359  int numopts = sizeof(noopts)/sizeof(struct notopts);
1360  int i, neg, msgL = 90, msgB = 10;
1361  char *val, parms[1024];
1362 
1363  if (!(val = Config.GetWord()))
1364  {Eroute.Emsg("Config", "notify parameters not specified"); return 1;}
1365  while (val && *val != '|' && *val != '>')
1366  {if (!strcmp(val, "msgs"))
1367  {if (!(val = Config.GetWord()))
1368  {Eroute.Emsg("Config", "notify msgs value not specified");
1369  return 1;
1370  }
1371  if (XrdOuca2x::a2i(Eroute, "msg count", val, &msgL, 0)) return 1;
1372  if (!(val = Config.GetWord())) break;
1373  if (isdigit(*val)
1374  && XrdOuca2x::a2i(Eroute, "msg count", val, &msgB, 0)) return 1;
1375  if (!(val = Config.GetWord())) break;
1376  continue;
1377  }
1378  if ((neg = (val[0] == '-' && val[1]))) val++;
1379  i = strlen(val);
1380  for (i = 0; i < numopts; i++)
1381  {if (!strcmp(val, noopts[i].opname))
1382  {if (neg) noval = static_cast<XrdOfsEvs::Event>(~noopts[i].opval&noval);
1383  else noval = static_cast<XrdOfsEvs::Event>( noopts[i].opval|noval);
1384  break;
1385  }
1386  }
1387  if (i >= numopts)
1388  Eroute.Say("Config warning: ignoring invalid notify event '",val,"'.");
1389  val = Config.GetWord();
1390  }
1391 
1392 // Check if we have a program here and some events
1393 //
1394  if (!val) {Eroute.Emsg("Config","notify program not specified");return 1;}
1395  if (!noval) {Eroute.Emsg("Config","notify events not specified"); return 1;}
1396 
1397 // Get the remaining parameters
1398 //
1399  Config.RetToken();
1400  if (!Config.GetRest(parms, sizeof(parms)))
1401  {Eroute.Emsg("Config", "notify parameters too long"); return 1;}
1402  val = (*parms == '|' ? parms+1 : parms);
1403 
1404 // Create an notification object
1405 //
1406  if (evsObject) delete evsObject;
1407  evsObject = new XrdOfsEvs(noval, val, msgL, msgB);
1408 
1409 // All done
1410 //
1411  return 0;
1412 }
1413 
1414 /******************************************************************************/
1415 /* x p e r s */
1416 /******************************************************************************/
1417 
1418 /* Function: xpers
1419 
1420  Purpose: To parse the directive: persist [auto | manual | off]
1421  [hold <sec>] [logdir <dirp>]
1422  [sync <snum>]
1423 
1424  auto POSC processing always on for creation requests
1425  manual POSC processing must be requested (default)
1426  off POSC processing is disabled
1427  <sec> Seconds inclomplete files held (default 10m)
1428  <dirp> Directory to hold POSC recovery log (default adminpath)
1429  <snum> Number of outstanding equests before syncing to disk.
1430 
1431  Output: 0 upon success or !0 upon failure.
1432 */
1433 
1434 int XrdOfs::xpers(XrdOucStream &Config, XrdSysError &Eroute)
1435 {
1436  char *val;
1437  int snum = -1, htime = -1, popt = -2;
1438 
1439  if (!(val = Config.GetWord()))
1440  {Eroute.Emsg("Config","persist option not specified");return 1;}
1441 
1442 // Check for valid option
1443 //
1444  if (!strcmp(val, "auto" )) popt = 1;
1445  else if (!strcmp(val, "off" )) popt = -1;
1446  else if (!strcmp(val, "manual" )) popt = 0;
1447 
1448 // Check if we should get the next token
1449 //
1450  if (popt > -2) val = Config.GetWord();
1451 
1452 // Check for hold or log
1453 //
1454  while(val)
1455  { if (!strcmp(val, "hold"))
1456  {if (!(val = Config.GetWord()))
1457  {Eroute.Emsg("Config","persist hold value not specified");
1458  return 1;
1459  }
1460  if (XrdOuca2x::a2tm(Eroute,"persist hold",val,&htime,0))
1461  return 1;
1462  }
1463  else if (!strcmp(val, "logdir"))
1464  {if (!(val = Config.GetWord()))
1465  {Eroute.Emsg("Config","persist logdir path not specified");
1466  return 1;
1467  }
1468  if (poscLog) free(poscLog);
1469  poscLog = strdup(val);
1470  }
1471  else if (!strcmp(val, "sync"))
1472  {if (!(val = Config.GetWord()))
1473  {Eroute.Emsg("Config","sync value not specified");
1474  return 1;
1475  }
1476  if (XrdOuca2x::a2i(Eroute,"sync value",val,&snum,0,32767))
1477  return 1;
1478  }
1479  else Eroute.Say("Config warning: ignoring invalid persist option '",val,"'.");
1480  val = Config.GetWord();
1481  }
1482 
1483 // Set values as needed
1484 //
1485  if (htime >= 0) poscHold = htime;
1486  if (popt > -2) poscAuto = popt;
1487  if (snum > -1) poscSync = snum;
1488  return 0;
1489 }
1490 
1491 /******************************************************************************/
1492 /* x r o l e */
1493 /******************************************************************************/
1494 
1495 /* Function: xrole
1496 
1497  Purpose: Parse: role { {[meta] | [proxy]} manager
1498  | [proxy] server
1499  | [proxy] supervisor
1500  } [if ...]
1501 
1502  manager xrootd: act as a manager (redirecting server). Prefixes:
1503  meta - connect only to manager meta's
1504  proxy - ignored
1505  cmsd: accept server subscribes and redirectors. Prefix
1506  modifiers do the following:
1507  meta - No other managers apply
1508  proxy - manage a cluster of proxy servers
1509 
1510  server xrootd: act as a server (supply local data). Prefix
1511  modifications do the following:
1512  proxy - server is part of a cluster. A local
1513  cmsd is required.
1514  cmsd: subscribe to a manager, possibly as a proxy.
1515 
1516  supervisor xrootd: equivalent to manager. The prefix modification
1517  is ignored.
1518  cmsd: equivalent to manager but also subscribe to a
1519  manager. When proxy is specified, then subscribe
1520  as a proxy and only accept proxies.
1521 
1522  if Apply the manager directive if "if" is true. See
1523  XrdOucUtils:doIf() for "if" syntax.
1524 
1525  Notes 1. The peer designation only affects how the olbd communicates.
1526 
1527  Type: Server only, non-dynamic.
1528 
1529  Output: 0 upon success or !0 upon failure.
1530 */
1531 
1532 int XrdOfs::xrole(XrdOucStream &Config, XrdSysError &Eroute)
1533 {
1534  const int resetit = ~haveRole;
1535  XrdCmsRole::RoleID roleID;
1536  char *val, *Tok1, *Tok2;
1537  int rc, ropt = 0;
1538 
1539 // Get the first token
1540 //
1541  if (!(val = Config.GetWord()) || !strcmp(val, "if"))
1542  {Eroute.Emsg("Config", "role not specified"); return 1;}
1543  Tok1 = strdup(val);
1544 
1545 // Get second token which might be an "if"
1546 //
1547  if ((val = Config.GetWord()) && strcmp(val, "if"))
1548  {Tok2 = strdup(val);
1549  val = Config.GetWord();
1550  } else Tok2 = 0;
1551 
1552 // Process the if at this point
1553 //
1554  if (val && !strcmp("if", val))
1555  {if ((rc = XrdOucUtils::doIf(&Eroute,Config,"role directive",
1556  getenv("XRDHOST"), XrdOucUtils::InstName(1),
1557  getenv("XRDPROG"))) <= 0)
1558  {free(Tok1); if (Tok2) free(Tok2);
1559  if (!rc) Config.noEcho();
1560  return (rc < 0);
1561  }
1562  }
1563 
1564 // Convert the role names to a role ID, if possible
1565 //
1566  roleID = XrdCmsRole::Convert(Tok1, Tok2);
1567 
1568 // Set markers based on the role we have
1569 //
1570  rc = 0;
1571  switch(roleID)
1572  {case XrdCmsRole::MetaManager: ropt = isManager | isMeta ; break;
1573  case XrdCmsRole::Manager: ropt = isManager ; break;
1574  case XrdCmsRole::Supervisor: ropt = isSuper ; break;
1575  case XrdCmsRole::Server: ropt = isServer ; break;
1576  case XrdCmsRole::ProxyManager: ropt = isManager | isProxy; break;
1577  case XrdCmsRole::ProxySuper: ropt = isSuper | isProxy; break;
1578  case XrdCmsRole::ProxyServer: ropt = isServer | isProxy; break;
1579  default: Eroute.Emsg("Config", "invalid role -", Tok1, Tok2); rc = 1;
1580  }
1581 
1582 // Release storage and return if an error occurred
1583 //
1584  free(Tok1);
1585  if (Tok2) free(Tok2);
1586  if (rc) return rc;
1587 
1588 // Set values
1589 //
1590  free(myRole);
1591  myRole = strdup(XrdCmsRole::Name(roleID));
1592  strcpy(myRType, XrdCmsRole::Type(roleID));
1593  Options &= resetit;
1594  Options |= ropt;
1595  return 0;
1596 }
1597 
1598 /******************************************************************************/
1599 /* x t p c */
1600 /******************************************************************************/
1601 
1602 /* Function: xtpc
1603 
1604  Purpose: To parse the directive: tpc [cksum <type>] [ttl <dflt> [<max>]]
1605  [logok] [xfr <n>] [allow <parms>]
1606  [require {all|client|dest} <auth>[+]]
1607  [restrict <path>]
1608  [streams <num>[,<max>]]
1609  [echo] [scan {stderr | stdout}]
1610  [autorm] [pgm <path> [parms]]
1611  [fcreds [?]<auth> =<evar>]
1612  [fcpath <path>] [oids]
1613 
1614  tpc redirect [xdlg] <host>:<port> [<cgi>]
1615 
1616  xdlg: delegated | undelegated
1617 
1618  parms: [dn <name>] [group <grp>] [host <hn>] [vo <vo>]
1619 
1620  <dflt> the default seconds a tpc authorization may be valid.
1621  <max> the maximum seconds a tpc authorization may be valid.
1622  cksum checksum incoming files using <type> checksum.
1623  logok log successful authorizations.
1624  allow only allow destinations that match the specified
1625  authentication specification.
1626  <n> maximum number of simultaneous transfers.
1627  <num> the default number of TCP streams to use for the copy.
1628  <max> The maximum number of TCP streams to use for the copy/
1629  <auth> require that the client, destination, or both (i.e. all)
1630  use the specified authentication protocol. Additional
1631  require statements may be specified to add additional
1632  valid authentication mechanisms. If the <auth> is suffixed
1633  by a plus, then the request must also be encrypted using
1634  the authentication's session key.
1635  echo echo the pgm's output to the log.
1636  autorm Remove file when copy fails.
1637  scan scan fr error messages either in stderr or stdout. The
1638  default is to scan both.
1639  pgm specifies the transfer command with optional paramaters.
1640  It must be the last parameter on the line.
1641  fcreds Forward destination credentials for protocol <auth>. The
1642  request fails if thee are no credentials for <auth>. If a
1643  question mark preceeds <auth> then if the client has not
1644  forwarded its credentials, the server's credentials are
1645  used. Otherwise, the copy fails.
1646  =<evar> the name of the envar to be set with the path to the
1647  credentials to be forwarded.
1648  fcpath where creds are stored (default <adminpath>/.ofs/.tpccreds).
1649  oids Object ID's are acceptable for the source lfn.
1650  <host> The redirection target host which may be localhost.
1651  <port> The redirection target port.
1652  <cgi> Optional cgi information.
1653 
1654  Output: 0 upon success or !0 upon failure.
1655 */
1656 
1657 int XrdOfs::xtpc(XrdOucStream &Config, XrdSysError &Eroute)
1658 {
1659  char *val, pgm[1024];
1661  *pgm = 0;
1662  int reqType;
1663  bool rdrok = true;
1664 
1665  while((val = Config.GetWord()))
1666  {if (!strcmp(val, "redirect"))
1667  {if (rdrok) return xtpcr(Config, Eroute);
1668  Eroute.Emsg("Config", "tpc redirect must be seprately specified.");
1669  return 1;
1670  }
1671  rdrok = false;
1672  if (!strcmp(val, "allow"))
1673  {if (!xtpcal(Config, Eroute)) return 1;
1674  continue;
1675  }
1676  if (!strcmp(val, "cksum"))
1677  {if (!(val = Config.GetWord()))
1678  {Eroute.Emsg("Config","cksum type not specified"); return 1;}
1679  if (Parms.cksType) free(Parms.cksType);
1680  Parms.cksType = strdup(val);
1681  continue;
1682  }
1683  if (!strcmp(val, "scan"))
1684  {if (!(val = Config.GetWord()))
1685  {Eroute.Emsg("Config","scan type not specified"); return 1;}
1686  if (strcmp(val, "stderr")) Parms.errMon = -2;
1687  else if (strcmp(val, "stdout")) Parms.errMon = -1;
1688  else if (strcmp(val, "all" )) Parms.errMon = 0;
1689  else {Eroute.Emsg("Config","invalid scan type -",val); return 1;}
1690  continue;
1691  }
1692  if (!strcmp(val, "echo")) {Parms.doEcho = true; continue;}
1693  if (!strcmp(val, "logok")) {Parms.LogOK = true; continue;}
1694  if (!strcmp(val, "autorm")){Parms.autoRM = true; continue;}
1695  if (!strcmp(val, "oids")) {Parms.noids = false;continue;}
1696  if (!strcmp(val, "pgm"))
1697  {if (!Config.GetRest(pgm, sizeof(pgm)))
1698  {Eroute.Emsg("Config", "tpc command line too long"); return 1;}
1699  if (!*pgm)
1700  {Eroute.Emsg("Config", "tpc program not specified"); return 1;}
1701  if (Parms.XfrProg) free(Parms.XfrProg);
1702  Parms.XfrProg = strdup( pgm );
1703  break;
1704  }
1705  if (!strcmp(val, "require"))
1706  {if (!(val = Config.GetWord()))
1707  {Eroute.Emsg("Config","tpc require parameter not specified"); return 1;}
1708  if (!strcmp(val, "all")) reqType = XrdOfsTPC::reqALL;
1709  else if (!strcmp(val, "client")) reqType = XrdOfsTPC::reqORG;
1710  else if (!strcmp(val, "dest")) reqType = XrdOfsTPC::reqDST;
1711  else {Eroute.Emsg("Config", "invalid tpc require type -", val); return 1;}
1712  break;
1713  if (!(val = Config.GetWord()))
1714  {Eroute.Emsg("Config","tpc require auth not specified"); return 1;}
1715  XrdOfsTPC::Require(val, reqType);
1716  continue;
1717  }
1718  if (!strcmp(val, "restrict"))
1719  {if (!(val = Config.GetWord()))
1720  {Eroute.Emsg("Config","tpc restrict path not specified"); return 1;}
1721  if (*val != '/')
1722  {Eroute.Emsg("Config","tpc restrict path not absolute"); return 1;}
1723  if (!XrdOfsTPC::Restrict(val)) return 1;
1724  continue;
1725  }
1726  if (!strcmp(val, "ttl"))
1727  {if (!(val = Config.GetWord()))
1728  {Eroute.Emsg("Config","tpc ttl value not specified"); return 1;}
1729  if (XrdOuca2x::a2tm(Eroute,"tpc ttl default",val,&Parms.dflTTL,1))
1730  return 1;
1731  if (!(val = Config.GetWord())) break;
1732  if (!(isdigit(*val))) {Config.RetToken(); continue;}
1733  if (XrdOuca2x::a2tm(Eroute,"tpc ttl maximum",val,&Parms.maxTTL,1))
1734  return 1;
1735  continue;
1736  }
1737  if (!strcmp(val, "xfr"))
1738  {if (!(val = Config.GetWord()))
1739  {Eroute.Emsg("Config","tpc xfr value not specified"); return 1;}
1740  if (XrdOuca2x::a2i(Eroute,"tpc xfr",val,&Parms.xfrMax,1)) return 1;
1741  continue;
1742  }
1743  if (!strcmp(val, "streams"))
1744  {if (!(val = Config.GetWord()))
1745  {Eroute.Emsg("Config","tpc streams value not specified"); return 1;}
1746  char *comma = index(val,',');
1747  if (comma)
1748  {*comma++ = 0;
1749  if (!(*comma))
1750  {Eroute.Emsg("Config","tpc streams max value missing"); return 1;}
1751  if (XrdOuca2x::a2i(Eroute,"tpc max streams",comma,&Parms.tcpSMax,0,15))
1752  return 1;
1753  }
1754  if (XrdOuca2x::a2i(Eroute,"tpc streams",val,&Parms.tcpSTRM,0,15)) return 1;
1755  continue;
1756  }
1757  if (!strcmp(val, "fcreds"))
1758  {char aBuff[64];
1759  Parms.fCreds = true;
1760  if (!(val = Config.GetWord()) || (*val == '?' && *(val+1) == '\0'))
1761  {Eroute.Emsg("Config","tpc fcreds auth not specified"); return 1;}
1762  if (strlen(val) >= sizeof(aBuff))
1763  {Eroute.Emsg("Config","invalid fcreds auth -", val); return 1;}
1764  strcpy(aBuff, val);
1765  if (!(val = Config.GetWord()) || *val != '=' || *(val+1) == 0)
1766  {Eroute.Emsg("Config","tpc fcreds envar not specified"); return 1;}
1767  const char *emsg = XrdOfsTPC::AddAuth(aBuff,val+1);
1768  if (emsg) {Eroute.Emsg("Config",emsg,"-", val); return 1;}
1769  continue;
1770  }
1771  if (!strcmp(val, "fcpath"))
1772  {if (!(val = Config.GetWord()))
1773  {Eroute.Emsg("Config","tpc fcpath arg not specified"); return 1;}
1774  if (Parms.cPath) free(Parms.cPath);
1775  Parms.cPath = strdup(val);
1776  continue;
1777  }
1778  Eroute.Say("Config warning: ignoring invalid tpc option '",val,"'.");
1779  }
1780 
1781  Options |= ThirdPC;
1782  return 0;
1783 }
1784 
1785 /******************************************************************************/
1786 /* x t p c a l */
1787 /******************************************************************************/
1788 
1789 int XrdOfs::xtpcal(XrdOucStream &Config, XrdSysError &Eroute)
1790 {
1791  struct tpcalopts {const char *opname; char *opval;} tpopts[] =
1792  {{"dn", 0}, {"group", 0}, {"host", 0}, {"vo", 0}};
1793  int i, spec = 0, numopts = sizeof(tpopts)/sizeof(struct tpcalopts);
1794  char *val;
1795 
1796  while((val = Config.GetWord()))
1797  {for (i = 0; i < numopts && strcmp(tpopts[i].opname, val); i++) {}
1798  if (i > numopts) {Config.RetToken(); break;}
1799  {Eroute.Emsg("Config", "invalid tpc allow parameter -", val);
1800  return 0;
1801  }
1802  if (!(val = Config.GetWord()))
1803  {Eroute.Emsg("Config","tpc allow",tpopts[i].opname,"value not specified");
1804  return 0;
1805  }
1806  if (tpopts[i].opval) free(tpopts[i].opval);
1807  tpopts[i].opval = strdup(val);
1808  spec = 1;
1809  }
1810 
1811  if (!spec) {Eroute.Emsg("Config","tpc allow parms not specified"); return 1;}
1812 
1813  XrdOfsTPC::Allow(tpopts[0].opval, tpopts[1].opval,
1814  tpopts[2].opval, tpopts[3].opval);
1815  return 1;
1816 }
1817 
1818 /******************************************************************************/
1819 /* x t p c r */
1820 /******************************************************************************/
1821 
1822 int XrdOfs::xtpcr(XrdOucStream &Config, XrdSysError &Eroute)
1823 {
1824  char hname[256];
1825  const char *cgi, *cgisep, *hBeg, *hEnd, *pBeg, *pEnd, *eText;
1826  char *val;
1827  int n, port, dlgI;
1828 
1829 // Get the next token
1830 //
1831  if (!(val = Config.GetWord()))
1832  {Eroute.Emsg("Config", "tpc redirect host not specified"); return 1;}
1833 
1834 // See if this is for delegated or undelegated (all is the default)
1835 //
1836  if (!strcmp(val, "delegated")) dlgI = 0;
1837  else if (!strcmp(val, "undelegated")) dlgI = 1;
1838  else dlgI = -1;
1839 
1840 // Get host and port
1841 //
1842  if (dlgI >= 0 && !(val = Config.GetWord()))
1843  {Eroute.Emsg("Config", "tpc redirect host not specified"); return 1;}
1844 
1845 // Parse this as it may be complicated.
1846 //
1847  if (!XrdNetUtils::Parse(val, &hBeg, &hEnd, &pBeg, &pEnd))
1848  {Eroute.Emsg("Config", "Invalid tpc redirect target -", val); return 1;}
1849 
1850 // Copy out the host target (make sure it's not too long)
1851 //
1852  n = hEnd - hBeg;
1853  if (*val == '[') n += 2;
1854  if (n >= (int)sizeof(hname))
1855  {Eroute.Emsg("Config", "Invalid tpc redirect target -", val); return 1;}
1856  strncpy(hname, val, n);
1857  hname[n] = 0;
1858 
1859 // Substitute our hostname for localhost if present
1860 //
1861  if (!strcmp(hname, "localhost"))
1862  {char *myHost = XrdNetUtils::MyHostName(0, &eText);
1863  if (!myHost)
1864  {Eroute.Emsg("Config", "Unable to determine tpc localhost;",eText);
1865  return 1;
1866  }
1867  n = snprintf(hname, sizeof(hname), "%s", myHost);
1868  free(myHost);
1869  if (n >= (int)sizeof(hname))
1870  {Eroute.Emsg("Config", "Invalid tpc localhost resolution -", hname);
1871  return 1;
1872  }
1873  }
1874 
1875 // Make sure a port was specified
1876 //
1877  if (pBeg == hEnd)
1878  {Eroute.Emsg("Config", "tpc redirect port not specified"); return 1;}
1879 
1880 // Get the numeric version of the port number
1881 //
1882  if (!(port = XrdNetUtils::ServPort(pBeg, false, &eText)))
1883  {Eroute.Emsg("Config", "Invalid tpc redirect port;",eText); return 1;}
1884 
1885 // Check if there is cgi that must be included
1886 //
1887  if (!(cgi = Config.GetWord())) cgisep = cgi = (char *)"";
1888  else cgisep = (*cgi != '?' ? "?" : "");
1889 
1890 // Copy out the hostname to be used
1891 //
1892  int k = (dlgI < 0 ? 0 : dlgI);
1893 do{if (tpcRdrHost[k]) {free(tpcRdrHost[k]); tpcRdrHost[k] = 0;}
1894 
1895  n = strlen(hname) + strlen(cgisep) + strlen(cgi) + 1;
1896  tpcRdrHost[k] = (char *)malloc(n);
1897  snprintf(tpcRdrHost[k], n, "%s%s%s", hname, cgisep, cgi);
1898  tpcRdrPort[k] = port;
1899  k++;
1900  } while(dlgI < 0 && k < 2);
1901 
1902 // All done
1903 //
1904  Options |= RdrTPC;
1905  return 0;
1906 }
1907 
1908 /******************************************************************************/
1909 /* x t r a c e */
1910 /******************************************************************************/
1911 
1912 /* Function: xtrace
1913 
1914  Purpose: To parse the directive: trace <events>
1915 
1916  <events> the blank separated list of events to trace. Trace
1917  directives are cummalative.
1918 
1919  Output: 0 upon success or !0 upon failure.
1920 */
1921 
1922 int XrdOfs::xtrace(XrdOucStream &Config, XrdSysError &Eroute)
1923 {
1924  static struct traceopts {const char *opname; int opval;} tropts[] =
1925  {{"aio", TRACE_aio},
1926  {"all", TRACE_ALL},
1927  {"chkpnt", TRACE_chkpnt},
1928  {"chmod", TRACE_chmod},
1929  {"close", TRACE_close},
1930  {"closedir", TRACE_closedir},
1931  {"debug", TRACE_debug},
1932  {"delay", TRACE_delay},
1933  {"dir", TRACE_dir},
1934  {"exists", TRACE_exists},
1935  {"getstats", TRACE_getstats},
1936  {"fsctl", TRACE_fsctl},
1937  {"io", TRACE_IO},
1938  {"mkdir", TRACE_mkdir},
1939  {"most", TRACE_MOST},
1940  {"open", TRACE_open},
1941  {"opendir", TRACE_opendir},
1942  {"qscan", TRACE_qscan},
1943  {"read", TRACE_read},
1944  {"readdir", TRACE_readdir},
1945  {"redirect", TRACE_redirect},
1946  {"remove", TRACE_remove},
1947  {"rename", TRACE_rename},
1948  {"sync", TRACE_sync},
1949  {"truncate", TRACE_truncate},
1950  {"write", TRACE_write}
1951  };
1952  int i, neg, trval = 0, numopts = sizeof(tropts)/sizeof(struct traceopts);
1953  char *val;
1954 
1955  if (!(val = Config.GetWord()))
1956  {Eroute.Emsg("Config", "trace option not specified"); return 1;}
1957  while (val)
1958  {if (!strcmp(val, "off")) trval = 0;
1959  else {if ((neg = (val[0] == '-' && val[1]))) val++;
1960  for (i = 0; i < numopts; i++)
1961  {if (!strcmp(val, tropts[i].opname))
1962  {if (neg) trval &= ~tropts[i].opval;
1963  else trval |= tropts[i].opval;
1964  break;
1965  }
1966  }
1967  if (i >= numopts)
1968  Eroute.Say("Config warning: ignoring invalid trace option '",val,"'.");
1969  }
1970  val = Config.GetWord();
1971  }
1972  OfsTrace.What = trval;
1973 
1974 // All done
1975 //
1976  return 0;
1977 }
1978 
1979 /******************************************************************************/
1980 /* x a t r */
1981 /******************************************************************************/
1982 
1983 /* Function: xatr
1984 
1985  Purpose: To parse the directive: xattr [maxnsz <nsz>] [maxvsz <vsz>]
1986 
1987  [uset {on|off}]
1988 
1989  on enables user settable extended attributes.
1990 
1991  off disaables user settable extended attributes.
1992 
1993  <nsz> maximum length of an attribute name. The user
1994  specifiable limit will be 8 less.
1995 
1996  <vsz> maximum length of an attribute value.
1997 
1998  Notes: 1. This directive is not cummalative.
1999 
2000  Output: 0 upon success or !0 upon failure.
2001 */
2002 
2003 int XrdOfs::xatr(XrdOucStream &Config, XrdSysError &Eroute)
2004 {
2005  char *val;
2006  static const int xanRsv = 7;
2007  long long vtmp;
2008  int maxN = kXR_faMaxNlen, maxV = kXR_faMaxVlen;
2009  bool isOn = true;
2010 
2011  while((val = Config.GetWord()))
2012  { if (!strcmp("maxnsz", val))
2013  {if (!(val = Config.GetWord()))
2014  {Eroute.Emsg("Config","xattr maxnsz value not specified");
2015  return 1;
2016  }
2017  if (XrdOuca2x::a2sz(Eroute,"maxnsz",val,&vtmp,
2018  xanRsv+1,kXR_faMaxNlen+xanRsv)) return 1;
2019  maxN = static_cast<int>(vtmp);
2020  }
2021  else if (!strcmp("maxvsz", val))
2022  {if (!(val = Config.GetWord()))
2023  {Eroute.Emsg("Config","xattr maxvsz value not specified");
2024  return 1;
2025  }
2026  if (XrdOuca2x::a2sz(Eroute,"maxvsz",val,&vtmp,0,kXR_faMaxVlen))
2027  return 1;
2028  maxV = static_cast<int>(vtmp);
2029  }
2030  else if (!strcmp("uset", val))
2031  {if (!(val = Config.GetWord()))
2032  {Eroute.Emsg("Config","xattr uset value not specified");
2033  return 1;
2034  }
2035  if (!strcmp("on", val)) isOn = true;
2036  else if (!strcmp("off", val)) isOn = false;
2037  else {Eroute.Emsg("Config", "invalid xattr uset value -", val);
2038  return 1;
2039  }
2040  }
2041  else {Eroute.Emsg("Config", "invalid xattr option -", val);
2042  return 1;
2043  }
2044  }
2045 
2046  usxMaxNsz = (isOn ? maxN-xanRsv : 0);
2047  usxMaxVsz = maxV;
2048  return 0;
2049 }
2050 
2051 /******************************************************************************/
2052 /* t h e R o l e */
2053 /******************************************************************************/
2054 
2055 const char *XrdOfs::theRole(int opts)
2056 {
2057  if (opts & isPeer) return "peer";
2058  else if (opts & isManager
2059  && opts & isServer) return "supervisor";
2060  else if (opts & isManager) return "manager";
2061  else if (opts & isProxy) {return "proxy";}
2062  return "server";
2063 }
@ kXR_faMaxVlen
Definition: XProtocol.hh:282
@ kXR_faMaxNlen
Definition: XProtocol.hh:281
XrdSysLogger myLogger
Definition: XrdAccTest.cc:65
#define TRACE_delay
Definition: XrdBwmTrace.hh:75
#define TRACE_debug
Definition: XrdBwmTrace.hh:78
XrdCmsClient *(* XrdCmsClient_t)(XrdSysLogger *, int, int, XrdOss *)
#define setBuff(x, y)
#define TS_Bit(x, m, v)
XrdScheduler * ofsSchedP
Definition: XrdOfsConfig.cc:95
XrdOss * XrdOfsOss
Definition: XrdOfs.cc:163
XrdVERSIONINFO(XrdOfs, XrdOfs)
#define TS_XPI(x, m)
XrdSysTrace OfsTrace
#define TS_Xeq(x, m)
XrdOfsStats OfsStats
Definition: XrdOfs.cc:113
XrdOfs * XrdOfsFS
Definition: XrdOfsFS.cc:47
#define TRACE_dir
Definition: XrdOfsTrace.hh:77
#define TRACE_rename
Definition: XrdOfsTrace.hh:90
#define TRACE_read
Definition: XrdOfsTrace.hh:81
#define TRACE_qscan
Definition: XrdOfsTrace.hh:79
#define TRACE_getstats
Definition: XrdOfsTrace.hh:94
#define TRACE_chkpnt
Definition: XrdOfsTrace.hh:99
#define TRACE_exists
Definition: XrdOfsTrace.hh:85
#define TRACE_close
Definition: XrdOfsTrace.hh:80
#define TRACE_open
Definition: XrdOfsTrace.hh:78
#define TRACE_sync
Definition: XrdOfsTrace.hh:91
#define TRACE_truncate
Definition: XrdOfsTrace.hh:92
#define TRACE_remove
Definition: XrdOfsTrace.hh:89
#define TRACE_redirect
Definition: XrdOfsTrace.hh:82
#define TRACE_opendir
Definition: XrdOfsTrace.hh:73
#define TRACE_chmod
Definition: XrdOfsTrace.hh:86
#define TRACE_closedir
Definition: XrdOfsTrace.hh:75
#define TRACE_IO
Definition: XrdOfsTrace.hh:84
#define TRACE_readdir
Definition: XrdOfsTrace.hh:74
#define TRACE_mkdir
Definition: XrdOfsTrace.hh:95
#define TRACE_MOST
Definition: XrdOfsTrace.hh:71
#define TRACE_fsctl
Definition: XrdOfsTrace.hh:93
#define TRACE_aio
Definition: XrdOfsTrace.hh:97
#define TRACE_write
Definition: XrdOfsTrace.hh:83
#define XRDOSS_HASRPXY
Definition: XrdOss.hh:481
#define XRDOSS_HASCACH
Definition: XrdOss.hh:479
#define XRDOSS_HASPRXY
Definition: XrdOss.hh:477
#define XRDOSS_HASNOSF
Definition: XrdOss.hh:478
#define XRDOSS_HASPGRW
Definition: XrdOss.hh:475
#define XRDOSS_HASNAIO
Definition: XrdOss.hh:480
int open(const char *path, int oflag,...)
int unlink(const char *path)
struct myOpts opts
int emsg(int rc, char *msg)
size_t strlcpy(char *dst, const char *src, size_t sz)
#define TRACE_ALL
Definition: XrdTrace.hh:35
virtual XrdOucTList * Managers()
static bool VCheck(XrdVersionInfo &urVersion)
static bool VCheck(XrdVersionInfo &urVersion)
static const char * Name(RoleID rid)
Definition: XrdCmsRole.hh:63
static RoleID Convert(const char *Tok1, const char *Tok2)
Definition: XrdCmsRole.hh:47
static const char * Type(RoleID rid)
Definition: XrdCmsRole.hh:78
static char * MyHostName(const char *eName="*unknown*", const char **eText=0)
Definition: XrdNetUtils.cc:667
static int ServPort(const char *sName, bool isUDP=false, const char **eText=0)
Definition: XrdNetUtils.cc:839
static bool Parse(const char *hSpec, const char **hName, const char **hNend, const char **hPort, const char **hPend)
Definition: XrdNetUtils.cc:745
static bool Init()
static bool Parse(XrdOucStream &Config)
bool ConfigCtl(XrdCmsClient *cmscP, XrdOucEnv *envP=0)
void Default(TheLib what, const char *lpath, const char *lparm=0)
void SetCksRdSz(int rdsz)
bool Plugin(XrdAccAuthorize *&piP)
Get Authorization plugin.
static XrdOfsConfigPI * New(const char *cfn, XrdOucStream *cfgP, XrdSysError *errP, XrdVersionInfo *verP=0, XrdSfsFileSystem *sfsP=0)
bool Load(int what, XrdOucEnv *envP=0)
bool Configure(XrdCmsClient *cmscP, XrdOucEnv *envP)
@ theOssLib
Oss plugin.
@ allXXXLib
All plugins (Load() only)
@ theCksLib
Checksum manager plugin.
void Display()
Display configuration settings.
int Init(XrdSysError *eObj)
Definition: XrdOfsEvr.cc:132
static int Parse(XrdSysError &Eroute, Event eNum, char *mText)
Definition: XrdOfsEvs.cc:287
int maxSmsg()
Definition: XrdOfsEvs.hh:141
int maxLmsg()
Definition: XrdOfsEvs.hh:142
int Start(XrdSysError *eobj)
Definition: XrdOfsEvs.cc:394
const char * Prog()
Definition: XrdOfsEvs.hh:148
int Enabled(Event theEvents)
Definition: XrdOfsEvs.hh:139
virtual bool Configure(const char *CfgFN, const char *Parms, XrdOucEnv *envP, const Plugins &plugs)
The Plugins struct is used to pass plugin pointers to configure.
int Retire(int &retc, long long *retsz=0, char *buff=0, int blen=0)
int PoscSet(const char *User, int Unum, short Mode)
static const int opPC
static int Alloc(const char *thePath, int Opts, XrdOfsHandle **Handle)
int Del(const char *Lfn, int Offset, int Unlink=0)
Definition: XrdOfsPoscq.cc:159
recEnt * Init(int &Ok)
Definition: XrdOfsPoscq.cc:207
void setRole(const char *theRole)
Definition: XrdOfsStats.hh:68
static int Restrict(const char *Path)
Definition: XrdOfsTPC.cc:465
static const int reqDST
Definition: XrdOfsTPC.hh:86
static const char * AddAuth(const char *auth, const char *avar)
Definition: XrdOfsTPC.cc:164
static void Init()
Definition: XrdOfsTPC.cc:414
static int Start()
Definition: XrdOfsTPC.cc:520
static const int reqORG
Definition: XrdOfsTPC.hh:87
static void Require(const char *Auth, int RType)
Definition: XrdOfsTPC.cc:445
static void Allow(char *vDN, char *vGN, char *vHN, char *vVO)
Definition: XrdOfsTPC.cc:209
static const int reqALL
Definition: XrdOfsTPC.hh:85
struct fwdOpt fwdTRUNC
Definition: XrdOfs.hh:415
mode_t dMask[2]
Definition: XrdOfs.hh:384
int myPort
Definition: XrdOfs.hh:380
XrdCmsClient * Finder
Definition: XrdOfs.hh:429
mode_t fMask[2]
Definition: XrdOfs.hh:385
struct fwdOpt fwdRMDIR
Definition: XrdOfs.hh:414
XrdOfsEvr evrObject
Definition: XrdOfs.hh:428
char * ConfigFN
Definition: XrdOfs.hh:420
int tpcRdrPort[2]
Definition: XrdOfs.hh:390
virtual int Configure(XrdSysError &)
struct fwdOpt fwdMKPATH
Definition: XrdOfs.hh:411
void Config_Display(XrdSysError &)
char * tpcRdrHost[2]
Definition: XrdOfs.hh:389
int Options
Definition: XrdOfs.hh:379
struct fwdOpt fwdMKDIR
Definition: XrdOfs.hh:410
static int MaxDelay
Definition: XrdOfs.hh:417
struct fwdOpt fwdMV
Definition: XrdOfs.hh:412
XrdNetIF * myIF
Definition: XrdOfs.hh:394
const char * getVersion()
struct fwdOpt fwdRM
Definition: XrdOfs.hh:413
@ isProxy
Definition: XrdOfs.hh:367
@ haveRole
Definition: XrdOfs.hh:372
@ RdrTPC
Definition: XrdOfs.hh:376
@ ThirdPC
Definition: XrdOfs.hh:374
@ isMeta
Definition: XrdOfs.hh:371
@ SubCluster
Definition: XrdOfs.hh:375
@ isManager
Definition: XrdOfs.hh:368
@ isPeer
Definition: XrdOfs.hh:366
@ isSuper
Definition: XrdOfs.hh:370
@ isServer
Definition: XrdOfs.hh:369
@ Authorize
Definition: XrdOfs.hh:364
@ Forwarding
Definition: XrdOfs.hh:373
virtual int ConfigXeq(char *var, XrdOucStream &, XrdSysError &)
struct fwdOpt fwdCHMOD
Definition: XrdOfs.hh:409
void Unpersist(XrdOfsHandle *hP, int xcev=1)
Definition: XrdOfs.cc:2738
virtual uint64_t Features()
Definition: XrdOss.cc:60
virtual int Unlink(const char *path, int Opts=0, XrdOucEnv *envP=0)=0
static int Export(const char *Var, const char *Val)
Definition: XrdOucEnv.cc:188
void * GetPtr(const char *varname)
Definition: XrdOucEnv.cc:281
void PutPtr(const char *varname, void *value)
Definition: XrdOucEnv.cc:316
void Put(const char *varname, const char *value)
Definition: XrdOucEnv.hh:85
static const int retFile
static const int retLink
static char * genPath(const char *path, const char *inst, const char *psfx=0)
Definition: XrdOucUtils.cc:418
static const char * InstName(int TranOpt=0)
Definition: XrdOucUtils.cc:764
static bool mode2mask(const char *mode, mode_t &mask)
Definition: XrdOucUtils.cc:980
static int doIf(XrdSysError *eDest, XrdOucStream &Config, const char *what, const char *hname, const char *nname, const char *pname)
Definition: XrdOucUtils.cc:232
static int makePath(char *path, mode_t mode, bool reset=false)
Definition: XrdOucUtils.cc:949
static int a2i(XrdSysError &, const char *emsg, const char *item, int *val, int minv=-1, int maxv=-1)
Definition: XrdOuca2x.cc:45
static int a2sz(XrdSysError &, const char *emsg, const char *item, long long *val, long long minv=-1, long long maxv=-1)
Definition: XrdOuca2x.cc:257
static int a2tm(XrdSysError &, const char *emsg, const char *item, int *val, int minv=-1, int maxv=-1)
Definition: XrdOuca2x.cc:288
virtual void EnvInfo(XrdOucEnv *envP)
uint64_t FeatureSet
Adjust features at initialization.
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95
void Say(const char *text1, const char *text2=0, const char *txt3=0, const char *text4=0, const char *text5=0, const char *txt6=0)
Definition: XrdSysError.cc:141
XrdSysLogger * logger(XrdSysLogger *lp=0)
Definition: XrdSysError.hh:141
@ IsTarget
The role is server and will be a redirection target.
@ IsProxy
The role is proxy {plus one or more of the below}.
@ IsRedir
The role is manager and will redirect users.
@ IsMeta
The role is meta {plus one or more of the above}.
XrdCmsConfig Config
XrdOfsTPCConfig Cfg
Definition: XrdOfsTPC.cc:85
XrdOucEnv * envP
Definition: XrdPss.cc:109
static const uint64_t hasAUTZ
Feature: Authorization.
Definition: XrdSfsFlags.hh:44
static const uint64_t hasPRP2
Feature: Prepare Handler Version 2 (different calling conventions)
Definition: XrdSfsFlags.hh:62
static const uint64_t hasCACH
Feature: Implements a data cache.
Definition: XrdSfsFlags.hh:74
static const uint64_t hasNOSF
Feature: Supports no sendfile.
Definition: XrdSfsFlags.hh:71
static const uint64_t hasPOSC
Feature: Persist On Successful Close.
Definition: XrdSfsFlags.hh:59
static const uint64_t hasNAIO
Feature: Supports no async I/O.
Definition: XrdSfsFlags.hh:77
static const uint64_t hasPRXY
Feature: Proxy Server.
Definition: XrdSfsFlags.hh:65
struct Request reqData
Definition: XrdOfsPoscq.hh:61
XrdXrootdTpcMon * tpcMon
const char * Cmd
Definition: XrdOfs.hh:399
char * Host
Definition: XrdOfs.hh:400
void Reset()
Definition: XrdOfs.hh:402
struct NSEnt * Next
Definition: XrdOucNSWalk.hh:48