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 [hold <sec>] [logdir <dirp>]
1597 [sync <snum>]
1598
1599 auto POSC processing always on for creation requests
1600 manual POSC processing must be requested (default)
1601 off POSC processing is disabled
1602 <sec> Seconds inclomplete files held (default 10m)
1603 <dirp> Directory to hold POSC recovery log (default adminpath)
1604 <snum> Number of outstanding equests before syncing to disk.
1605
1606 Output: 0 upon success or !0 upon failure.
1607*/
1608
1609int XrdOfs::xpers(XrdOucStream &Config, XrdSysError &Eroute)
1610{
1611 char *val;
1612 int snum = -1, htime = -1, popt = -2;
1613
1614 if (!(val = Config.GetWord()))
1615 {Eroute.Emsg("Config","persist option not specified");return 1;}
1616
1617// Check for valid option
1618//
1619 if (!strcmp(val, "auto" )) popt = 1;
1620 else if (!strcmp(val, "off" )) popt = -1;
1621 else if (!strcmp(val, "manual" )) popt = 0;
1622
1623// Check if we should get the next token
1624//
1625 if (popt > -2) val = Config.GetWord();
1626
1627// Check for hold or log
1628//
1629 while(val)
1630 { if (!strcmp(val, "hold"))
1631 {if (!(val = Config.GetWord()))
1632 {Eroute.Emsg("Config","persist hold value not specified");
1633 return 1;
1634 }
1635 if (XrdOuca2x::a2tm(Eroute,"persist hold",val,&htime,0))
1636 return 1;
1637 }
1638 else if (!strcmp(val, "logdir"))
1639 {if (!(val = Config.GetWord()))
1640 {Eroute.Emsg("Config","persist logdir path not specified");
1641 return 1;
1642 }
1643 if (poscLog) free(poscLog);
1644 poscLog = strdup(val);
1645 }
1646 else if (!strcmp(val, "sync"))
1647 {if (!(val = Config.GetWord()))
1648 {Eroute.Emsg("Config","sync value not specified");
1649 return 1;
1650 }
1651 if (XrdOuca2x::a2i(Eroute,"sync value",val,&snum,0,32767))
1652 return 1;
1653 }
1654 else Eroute.Say("Config warning: ignoring invalid persist option '",val,"'.");
1655 val = Config.GetWord();
1656 }
1657
1658// Set values as needed
1659//
1660 if (htime >= 0) poscHold = htime;
1661 if (popt > -2) poscAuto = popt;
1662 if (snum > -1) poscSync = snum;
1663 return 0;
1664}
1665
1666/******************************************************************************/
1667/* x r o l e */
1668/******************************************************************************/
1669
1670/* Function: xrole
1671
1672 Purpose: Parse: role { {[meta] | [proxy]} manager
1673 | [proxy] server
1674 | [proxy] supervisor
1675 } [if ...]
1676
1677 manager xrootd: act as a manager (redirecting server). Prefixes:
1678 meta - connect only to manager meta's
1679 proxy - ignored
1680 cmsd: accept server subscribes and redirectors. Prefix
1681 modifiers do the following:
1682 meta - No other managers apply
1683 proxy - manage a cluster of proxy servers
1684
1685 server xrootd: act as a server (supply local data). Prefix
1686 modifications do the following:
1687 proxy - server is part of a cluster. A local
1688 cmsd is required.
1689 cmsd: subscribe to a manager, possibly as a proxy.
1690
1691 supervisor xrootd: equivalent to manager. The prefix modification
1692 is ignored.
1693 cmsd: equivalent to manager but also subscribe to a
1694 manager. When proxy is specified, then subscribe
1695 as a proxy and only accept proxies.
1696
1697 if Apply the manager directive if "if" is true. See
1698 XrdOucUtils:doIf() for "if" syntax.
1699
1700 Notes 1. The peer designation only affects how the olbd communicates.
1701
1702 Type: Server only, non-dynamic.
1703
1704 Output: 0 upon success or !0 upon failure.
1705*/
1706
1707int XrdOfs::xrole(XrdOucStream &Config, XrdSysError &Eroute)
1708{
1709 const int resetit = ~haveRole;
1710 XrdCmsRole::RoleID roleID;
1711 char *val, *Tok1, *Tok2;
1712 int rc, ropt = 0;
1713
1714// Get the first token
1715//
1716 if (!(val = Config.GetWord()) || !strcmp(val, "if"))
1717 {Eroute.Emsg("Config", "role not specified"); return 1;}
1718 Tok1 = strdup(val);
1719
1720// Get second token which might be an "if"
1721//
1722 if ((val = Config.GetWord()) && strcmp(val, "if"))
1723 {Tok2 = strdup(val);
1724 val = Config.GetWord();
1725 } else Tok2 = 0;
1726
1727// Process the if at this point
1728//
1729 if (val && !strcmp("if", val))
1730 {if ((rc = XrdOucUtils::doIf(&Eroute,Config,"role directive",
1731 getenv("XRDHOST"), XrdOucUtils::InstName(1),
1732 getenv("XRDPROG"))) <= 0)
1733 {free(Tok1); if (Tok2) free(Tok2);
1734 if (!rc) Config.noEcho();
1735 return (rc < 0);
1736 }
1737 }
1738
1739// Convert the role names to a role ID, if possible
1740//
1741 roleID = XrdCmsRole::Convert(Tok1, Tok2);
1742
1743// Set markers based on the role we have
1744//
1745 rc = 0;
1746 switch(roleID)
1747 {case XrdCmsRole::MetaManager: ropt = isManager | isMeta ; break;
1748 case XrdCmsRole::Manager: ropt = isManager ; break;
1749 case XrdCmsRole::Supervisor: ropt = isSuper ; break;
1750 case XrdCmsRole::Server: ropt = isServer ; break;
1751 case XrdCmsRole::ProxyManager: ropt = isManager | isProxy; break;
1752 case XrdCmsRole::ProxySuper: ropt = isSuper | isProxy; break;
1753 case XrdCmsRole::ProxyServer: ropt = isServer | isProxy; break;
1754 default: Eroute.Emsg("Config", "invalid role -", Tok1, Tok2); rc = 1;
1755 }
1756
1757// Release storage and return if an error occurred
1758//
1759 free(Tok1);
1760 if (Tok2) free(Tok2);
1761 if (rc) return rc;
1762
1763// Set values
1764//
1765 free(myRole);
1766 myRole = strdup(XrdCmsRole::Name(roleID));
1767 strcpy(myRType, XrdCmsRole::Type(roleID));
1768 Options &= resetit;
1769 Options |= ropt;
1770 return 0;
1771}
1772
1773/******************************************************************************/
1774/* x t p c */
1775/******************************************************************************/
1776
1777/* Function: xtpc
1778
1779 Purpose: To parse the directive: tpc [cksum <type>] [ttl <dflt> [<max>]]
1780 [logok] [xfr <n>] [allow <parms>]
1781 [require {all|client|dest} <auth>[+]]
1782 [restrict <path>]
1783 [streams <num>[,<max>]]
1784 [echo] [scan {stderr | stdout}]
1785 [autorm] [pgm <path> [parms]]
1786 [fcreds [?]<auth> =<evar>]
1787 [fcpath <path>] [oids]
1788
1789 tpc redirect [xdlg] <host>:<port> [<cgi>]
1790
1791 xdlg: delegated | undelegated
1792
1793 parms: [dn <name>] [group <grp>] [host <hn>] [vo <vo>]
1794
1795 <dflt> the default seconds a tpc authorization may be valid.
1796 <max> the maximum seconds a tpc authorization may be valid.
1797 cksum checksum incoming files using <type> checksum.
1798 logok log successful authorizations.
1799 allow only allow destinations that match the specified
1800 authentication specification.
1801 <n> maximum number of simultaneous transfers.
1802 <num> the default number of TCP streams to use for the copy.
1803 <max> The maximum number of TCP streams to use for the copy/
1804 <auth> require that the client, destination, or both (i.e. all)
1805 use the specified authentication protocol. Additional
1806 require statements may be specified to add additional
1807 valid authentication mechanisms. If the <auth> is suffixed
1808 by a plus, then the request must also be encrypted using
1809 the authentication's session key.
1810 echo echo the pgm's output to the log.
1811 autorm Remove file when copy fails.
1812 scan scan fr error messages either in stderr or stdout. The
1813 default is to scan both.
1814 pgm specifies the transfer command with optional paramaters.
1815 It must be the last parameter on the line.
1816 fcreds Forward destination credentials for protocol <auth>. The
1817 request fails if thee are no credentials for <auth>. If a
1818 question mark preceeds <auth> then if the client has not
1819 forwarded its credentials, the server's credentials are
1820 used. Otherwise, the copy fails.
1821 =<evar> the name of the envar to be set with the path to the
1822 credentials to be forwarded.
1823 fcpath where creds are stored (default <adminpath>/.ofs/.tpccreds).
1824 oids Object ID's are acceptable for the source lfn.
1825 <host> The redirection target host which may be localhost.
1826 <port> The redirection target port.
1827 <cgi> Optional cgi information.
1828
1829 Output: 0 upon success or !0 upon failure.
1830*/
1831
1832int XrdOfs::xtpc(XrdOucStream &Config, XrdSysError &Eroute)
1833{
1834 char *val, pgm[1024];
1835 XrdOfsTPCConfig &Parms = XrdOfsTPCParms::Cfg;
1836 *pgm = 0;
1837 int reqType;
1838 bool rdrok = true;
1839
1840 while((val = Config.GetWord()))
1841 {if (!strcmp(val, "redirect"))
1842 {if (rdrok) return xtpcr(Config, Eroute);
1843 Eroute.Emsg("Config", "tpc redirect must be seprately specified.");
1844 return 1;
1845 }
1846 rdrok = false;
1847 if (!strcmp(val, "allow"))
1848 {if (!xtpcal(Config, Eroute)) return 1;
1849 continue;
1850 }
1851 if (!strcmp(val, "cksum"))
1852 {if (!(val = Config.GetWord()))
1853 {Eroute.Emsg("Config","cksum type not specified"); return 1;}
1854 if (Parms.cksType) free(Parms.cksType);
1855 Parms.cksType = strdup(val);
1856 continue;
1857 }
1858 if (!strcmp(val, "scan"))
1859 {if (!(val = Config.GetWord()))
1860 {Eroute.Emsg("Config","scan type not specified"); return 1;}
1861 if (strcmp(val, "stderr")) Parms.errMon = -2;
1862 else if (strcmp(val, "stdout")) Parms.errMon = -1;
1863 else if (strcmp(val, "all" )) Parms.errMon = 0;
1864 else {Eroute.Emsg("Config","invalid scan type -",val); return 1;}
1865 continue;
1866 }
1867 if (!strcmp(val, "echo")) {Parms.doEcho = true; continue;}
1868 if (!strcmp(val, "logok")) {Parms.LogOK = true; continue;}
1869 if (!strcmp(val, "autorm")){Parms.autoRM = true; continue;}
1870 if (!strcmp(val, "oids")) {Parms.noids = false;continue;}
1871 if (!strcmp(val, "pgm"))
1872 {if (!Config.GetRest(pgm, sizeof(pgm)))
1873 {Eroute.Emsg("Config", "tpc command line too long"); return 1;}
1874 if (!*pgm)
1875 {Eroute.Emsg("Config", "tpc program not specified"); return 1;}
1876 if (Parms.XfrProg) free(Parms.XfrProg);
1877 Parms.XfrProg = strdup( pgm );
1878 break;
1879 }
1880 if (!strcmp(val, "require"))
1881 {if (!(val = Config.GetWord()))
1882 {Eroute.Emsg("Config","tpc require parameter not specified"); return 1;}
1883 if (!strcmp(val, "all")) reqType = XrdOfsTPC::reqALL;
1884 else if (!strcmp(val, "client")) reqType = XrdOfsTPC::reqORG;
1885 else if (!strcmp(val, "dest")) reqType = XrdOfsTPC::reqDST;
1886 else {Eroute.Emsg("Config", "invalid tpc require type -", val); return 1;}
1887 break;
1888 if (!(val = Config.GetWord()))
1889 {Eroute.Emsg("Config","tpc require auth not specified"); return 1;}
1890 XrdOfsTPC::Require(val, reqType);
1891 continue;
1892 }
1893 if (!strcmp(val, "restrict"))
1894 {if (!(val = Config.GetWord()))
1895 {Eroute.Emsg("Config","tpc restrict path not specified"); return 1;}
1896 if (*val != '/')
1897 {Eroute.Emsg("Config","tpc restrict path not absolute"); return 1;}
1898 if (!XrdOfsTPC::Restrict(val)) return 1;
1899 continue;
1900 }
1901 if (!strcmp(val, "ttl"))
1902 {if (!(val = Config.GetWord()))
1903 {Eroute.Emsg("Config","tpc ttl value not specified"); return 1;}
1904 if (XrdOuca2x::a2tm(Eroute,"tpc ttl default",val,&Parms.dflTTL,1))
1905 return 1;
1906 if (!(val = Config.GetWord())) break;
1907 if (!(isdigit(*val))) {Config.RetToken(); continue;}
1908 if (XrdOuca2x::a2tm(Eroute,"tpc ttl maximum",val,&Parms.maxTTL,1))
1909 return 1;
1910 continue;
1911 }
1912 if (!strcmp(val, "xfr"))
1913 {if (!(val = Config.GetWord()))
1914 {Eroute.Emsg("Config","tpc xfr value not specified"); return 1;}
1915 if (XrdOuca2x::a2i(Eroute,"tpc xfr",val,&Parms.xfrMax,1)) return 1;
1916 continue;
1917 }
1918 if (!strcmp(val, "streams"))
1919 {if (!(val = Config.GetWord()))
1920 {Eroute.Emsg("Config","tpc streams value not specified"); return 1;}
1921 char *comma = index(val,',');
1922 if (comma)
1923 {*comma++ = 0;
1924 if (!(*comma))
1925 {Eroute.Emsg("Config","tpc streams max value missing"); return 1;}
1926 if (XrdOuca2x::a2i(Eroute,"tpc max streams",comma,&Parms.tcpSMax,0,15))
1927 return 1;
1928 }
1929 if (XrdOuca2x::a2i(Eroute,"tpc streams",val,&Parms.tcpSTRM,0,15)) return 1;
1930 continue;
1931 }
1932 if (!strcmp(val, "fcreds"))
1933 {char aBuff[64];
1934 Parms.fCreds = true;
1935 if (!(val = Config.GetWord()) || (*val == '?' && *(val+1) == '\0'))
1936 {Eroute.Emsg("Config","tpc fcreds auth not specified"); return 1;}
1937 if (strlen(val) >= sizeof(aBuff))
1938 {Eroute.Emsg("Config","invalid fcreds auth -", val); return 1;}
1939 strcpy(aBuff, val);
1940 if (!(val = Config.GetWord()) || *val != '=' || *(val+1) == 0)
1941 {Eroute.Emsg("Config","tpc fcreds envar not specified"); return 1;}
1942 const char *emsg = XrdOfsTPC::AddAuth(aBuff,val+1);
1943 if (emsg) {Eroute.Emsg("Config",emsg,"-", val); return 1;}
1944 continue;
1945 }
1946 if (!strcmp(val, "fcpath"))
1947 {if (!(val = Config.GetWord()))
1948 {Eroute.Emsg("Config","tpc fcpath arg not specified"); return 1;}
1949 if (Parms.cPath) free(Parms.cPath);
1950 Parms.cPath = strdup(val);
1951 continue;
1952 }
1953 Eroute.Say("Config warning: ignoring invalid tpc option '",val,"'.");
1954 }
1955
1956 Options |= ThirdPC;
1957 return 0;
1958}
1959
1960/******************************************************************************/
1961/* x t p c a l */
1962/******************************************************************************/
1963
1964int XrdOfs::xtpcal(XrdOucStream &Config, XrdSysError &Eroute)
1965{
1966 struct tpcalopts {const char *opname; char *opval;} tpopts[] =
1967 {{"dn", 0}, {"group", 0}, {"host", 0}, {"vo", 0}};
1968 int i, spec = 0, numopts = sizeof(tpopts)/sizeof(struct tpcalopts);
1969 char *val;
1970
1971 while((val = Config.GetWord()))
1972 {for (i = 0; i < numopts && strcmp(tpopts[i].opname, val); i++) {}
1973 if (i > numopts) {Config.RetToken(); break;}
1974 {Eroute.Emsg("Config", "invalid tpc allow parameter -", val);
1975 return 0;
1976 }
1977 if (!(val = Config.GetWord()))
1978 {Eroute.Emsg("Config","tpc allow",tpopts[i].opname,"value not specified");
1979 return 0;
1980 }
1981 if (tpopts[i].opval) free(tpopts[i].opval);
1982 tpopts[i].opval = strdup(val);
1983 spec = 1;
1984 }
1985
1986 if (!spec) {Eroute.Emsg("Config","tpc allow parms not specified"); return 1;}
1987
1988 XrdOfsTPC::Allow(tpopts[0].opval, tpopts[1].opval,
1989 tpopts[2].opval, tpopts[3].opval);
1990 return 1;
1991}
1992
1993/******************************************************************************/
1994/* x t p c r */
1995/******************************************************************************/
1996
1997int XrdOfs::xtpcr(XrdOucStream &Config, XrdSysError &Eroute)
1998{
1999 char hname[256];
2000 const char *cgi, *cgisep, *hBeg, *hEnd, *pBeg, *pEnd, *eText;
2001 char *val;
2002 int n, port, dlgI;
2003
2004// Get the next token
2005//
2006 if (!(val = Config.GetWord()))
2007 {Eroute.Emsg("Config", "tpc redirect host not specified"); return 1;}
2008
2009// See if this is for delegated or undelegated (all is the default)
2010//
2011 if (!strcmp(val, "delegated")) dlgI = 0;
2012 else if (!strcmp(val, "undelegated")) dlgI = 1;
2013 else dlgI = -1;
2014
2015// Get host and port
2016//
2017 if (dlgI >= 0 && !(val = Config.GetWord()))
2018 {Eroute.Emsg("Config", "tpc redirect host not specified"); return 1;}
2019
2020// Parse this as it may be complicated.
2021//
2022 if (!XrdNetUtils::Parse(val, &hBeg, &hEnd, &pBeg, &pEnd))
2023 {Eroute.Emsg("Config", "Invalid tpc redirect target -", val); return 1;}
2024
2025// Copy out the host target (make sure it's not too long)
2026//
2027 n = hEnd - hBeg;
2028 if (*val == '[') n += 2;
2029 if (n >= (int)sizeof(hname))
2030 {Eroute.Emsg("Config", "Invalid tpc redirect target -", val); return 1;}
2031 strncpy(hname, val, n);
2032 hname[n] = 0;
2033
2034// Substitute our hostname for localhost if present
2035//
2036 if (!strcmp(hname, "localhost"))
2037 {char *myHost = XrdNetUtils::MyHostName(0, &eText);
2038 if (!myHost)
2039 {Eroute.Emsg("Config", "Unable to determine tpc localhost;",eText);
2040 return 1;
2041 }
2042 n = snprintf(hname, sizeof(hname), "%s", myHost);
2043 free(myHost);
2044 if (n >= (int)sizeof(hname))
2045 {Eroute.Emsg("Config", "Invalid tpc localhost resolution -", hname);
2046 return 1;
2047 }
2048 }
2049
2050// Make sure a port was specified
2051//
2052 if (pBeg == hEnd)
2053 {Eroute.Emsg("Config", "tpc redirect port not specified"); return 1;}
2054
2055// Get the numeric version of the port number
2056//
2057 if (!(port = XrdNetUtils::ServPort(pBeg, false, &eText)))
2058 {Eroute.Emsg("Config", "Invalid tpc redirect port;",eText); return 1;}
2059
2060// Check if there is cgi that must be included
2061//
2062 if (!(cgi = Config.GetWord())) cgisep = cgi = (char *)"";
2063 else cgisep = (*cgi != '?' ? "?" : "");
2064
2065// Copy out the hostname to be used
2066//
2067 int k = (dlgI < 0 ? 0 : dlgI);
2068do{if (tpcRdrHost[k]) {free(tpcRdrHost[k]); tpcRdrHost[k] = 0;}
2069
2070 n = strlen(hname) + strlen(cgisep) + strlen(cgi) + 1;
2071 tpcRdrHost[k] = (char *)malloc(n);
2072 snprintf(tpcRdrHost[k], n, "%s%s%s", hname, cgisep, cgi);
2073 tpcRdrPort[k] = port;
2074 k++;
2075 } while(dlgI < 0 && k < 2);
2076
2077// All done
2078//
2079 Options |= RdrTPC;
2080 return 0;
2081}
2082
2083/******************************************************************************/
2084/* x t r a c e */
2085/******************************************************************************/
2086
2087/* Function: xtrace
2088
2089 Purpose: To parse the directive: trace <events>
2090
2091 <events> the blank separated list of events to trace. Trace
2092 directives are cummalative.
2093
2094 Output: 0 upon success or !0 upon failure.
2095*/
2096
2097int XrdOfs::xtrace(XrdOucStream &Config, XrdSysError &Eroute)
2098{
2099 static struct traceopts {const char *opname; int opval;} tropts[] =
2100 {{"aio", TRACE_aio},
2101 {"all", TRACE_ALL},
2102 {"chkpnt", TRACE_chkpnt},
2103 {"chmod", TRACE_chmod},
2104 {"close", TRACE_close},
2105 {"closedir", TRACE_closedir},
2106 {"debug", TRACE_debug},
2107 {"delay", TRACE_delay},
2108 {"dir", TRACE_dir},
2109 {"exists", TRACE_exists},
2110 {"getstats", TRACE_getstats},
2111 {"fsctl", TRACE_fsctl},
2112 {"io", TRACE_IO},
2113 {"mkdir", TRACE_mkdir},
2114 {"most", TRACE_MOST},
2115 {"open", TRACE_open},
2116 {"opendir", TRACE_opendir},
2117 {"qscan", TRACE_qscan},
2118 {"read", TRACE_read},
2119 {"readdir", TRACE_readdir},
2120 {"redirect", TRACE_redirect},
2121 {"remove", TRACE_remove},
2122 {"rename", TRACE_rename},
2123 {"sync", TRACE_sync},
2124 {"truncate", TRACE_truncate},
2125 {"write", TRACE_write}
2126 };
2127 int i, neg, trval = 0, numopts = sizeof(tropts)/sizeof(struct traceopts);
2128 char *val;
2129
2130 if (!(val = Config.GetWord()))
2131 {Eroute.Emsg("Config", "trace option not specified"); return 1;}
2132 while (val)
2133 {if (!strcmp(val, "off")) trval = 0;
2134 else {if ((neg = (val[0] == '-' && val[1]))) val++;
2135 for (i = 0; i < numopts; i++)
2136 {if (!strcmp(val, tropts[i].opname))
2137 {if (neg) trval &= ~tropts[i].opval;
2138 else trval |= tropts[i].opval;
2139 break;
2140 }
2141 }
2142 if (i >= numopts)
2143 Eroute.Say("Config warning: ignoring invalid trace option '",val,"'.");
2144 }
2145 val = Config.GetWord();
2146 }
2147 OfsTrace.What = trval;
2148
2149// All done
2150//
2151 return 0;
2152}
2153
2154/******************************************************************************/
2155/* x a t r */
2156/******************************************************************************/
2157
2158/* Function: xatr
2159
2160 Purpose: To parse the directive: xattr [maxnsz <nsz>] [maxvsz <vsz>]
2161
2162 [uset {on|off}]
2163
2164 on enables user settable extended attributes.
2165
2166 off disaables user settable extended attributes.
2167
2168 <nsz> maximum length of an attribute name. The user
2169 specifiable limit will be 8 less.
2170
2171 <vsz> maximum length of an attribute value.
2172
2173 Notes: 1. This directive is not cummalative.
2174
2175 Output: 0 upon success or !0 upon failure.
2176*/
2177
2178int XrdOfs::xatr(XrdOucStream &Config, XrdSysError &Eroute)
2179{
2180 char *val;
2181 static const int xanRsv = 7;
2182 long long vtmp;
2183 int maxN = kXR_faMaxNlen, maxV = kXR_faMaxVlen;
2184 bool isOn = true;
2185
2186 while((val = Config.GetWord()))
2187 { if (!strcmp("maxnsz", val))
2188 {if (!(val = Config.GetWord()))
2189 {Eroute.Emsg("Config","xattr maxnsz value not specified");
2190 return 1;
2191 }
2192 if (XrdOuca2x::a2sz(Eroute,"maxnsz",val,&vtmp,
2193 xanRsv+1,kXR_faMaxNlen+xanRsv)) return 1;
2194 maxN = static_cast<int>(vtmp);
2195 }
2196 else if (!strcmp("maxvsz", val))
2197 {if (!(val = Config.GetWord()))
2198 {Eroute.Emsg("Config","xattr maxvsz value not specified");
2199 return 1;
2200 }
2201 if (XrdOuca2x::a2sz(Eroute,"maxvsz",val,&vtmp,0,kXR_faMaxVlen))
2202 return 1;
2203 maxV = static_cast<int>(vtmp);
2204 }
2205 else if (!strcmp("uset", val))
2206 {if (!(val = Config.GetWord()))
2207 {Eroute.Emsg("Config","xattr uset value not specified");
2208 return 1;
2209 }
2210 if (!strcmp("on", val)) isOn = true;
2211 else if (!strcmp("off", val)) isOn = false;
2212 else {Eroute.Emsg("Config", "invalid xattr uset value -", val);
2213 return 1;
2214 }
2215 }
2216 else {Eroute.Emsg("Config", "invalid xattr option -", val);
2217 return 1;
2218 }
2219 }
2220
2221 usxMaxNsz = (isOn ? maxN-xanRsv : 0);
2222 usxMaxVsz = maxV;
2223 return 0;
2224}
2225
2226/******************************************************************************/
2227/* t h e R o l e */
2228/******************************************************************************/
2229
2230const char *XrdOfs::theRole(int opts)
2231{
2232 if (opts & isPeer) return "peer";
2233 else if (opts & isManager
2234 && opts & isServer) return "supervisor";
2235 else if (opts & isManager) return "manager";
2236 else if (opts & isProxy) {return "proxy";}
2237 return "server";
2238}
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.
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:425
mode_t dMask[2]
Definition XrdOfs.hh:394
int myPort
Definition XrdOfs.hh:390
XrdCmsClient * Finder
Definition XrdOfs.hh:439
mode_t fMask[2]
Definition XrdOfs.hh:395
struct fwdOpt fwdRMDIR
Definition XrdOfs.hh:424
XrdOfsEvr evrObject
Definition XrdOfs.hh:438
char * ConfigFN
Definition XrdOfs.hh:430
int tpcRdrPort[2]
Definition XrdOfs.hh:400
virtual int Configure(XrdSysError &)
struct fwdOpt fwdMKPATH
Definition XrdOfs.hh:421
void Config_Display(XrdSysError &)
XrdOfs()
Definition XrdOfs.cc:171
char * tpcRdrHost[2]
Definition XrdOfs.hh:399
int Options
Definition XrdOfs.hh:389
struct fwdOpt fwdMKDIR
Definition XrdOfs.hh:420
static int MaxDelay
Definition XrdOfs.hh:427
struct fwdOpt fwdMV
Definition XrdOfs.hh:422
XrdNetIF * myIF
Definition XrdOfs.hh:404
const char * getVersion()
struct fwdOpt fwdRM
Definition XrdOfs.hh:423
virtual int ConfigXeq(char *var, XrdOucStream &, XrdSysError &)
bool ValidCST(const char *cst)
struct fwdOpt fwdCHMOD
Definition XrdOfs.hh:419
@ isProxy
Definition XrdOfs.hh:377
@ haveRole
Definition XrdOfs.hh:382
@ RdrTPC
Definition XrdOfs.hh:386
@ ThirdPC
Definition XrdOfs.hh:384
@ isMeta
Definition XrdOfs.hh:381
@ SubCluster
Definition XrdOfs.hh:385
@ isManager
Definition XrdOfs.hh:378
@ isPeer
Definition XrdOfs.hh:376
@ isSuper
Definition XrdOfs.hh:380
@ isServer
Definition XrdOfs.hh:379
@ Authorize
Definition XrdOfs.hh:374
@ Forwarding
Definition XrdOfs.hh:383
void Unpersist(XrdOfsHandle *hP, int xcev=1)
Definition XrdOfs.cc:2943
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:409
char * Host
Definition XrdOfs.hh:410
void Reset()
Definition XrdOfs.hh:412
struct NSEnt * Next