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