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