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