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