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