XRootD
XrdCksManager.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d O s s C k s M a n a g e r . c c */
4 /* */
5 /* (c) 2011 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 Department 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 <cerrno>
32 #include <fcntl.h>
33 #include <cstring>
34 #include <ctime>
35 #include <cstdio>
36 #include <unistd.h>
37 #include <sys/mman.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 
41 #include "XrdCks/XrdCksCalc.hh"
45 #include "XrdCks/XrdCksCalcmd5.hh"
46 #include "XrdCks/XrdCksLoader.hh"
47 #include "XrdCks/XrdCksManager.hh"
48 #include "XrdCks/XrdCksXAttr.hh"
51 #include "XrdOuc/XrdOucUtils.hh"
52 #include "XrdOuc/XrdOucXAttr.hh"
53 #include "XrdSys/XrdSysError.hh"
54 #include "XrdSys/XrdSysFAttr.hh"
55 #include "XrdSys/XrdSysPlugin.hh"
56 #include "XrdSys/XrdSysPthread.hh"
57 
58 #ifndef ENOATTR
59 #define ENOATTR ENODATA
60 #endif
61 
62 /******************************************************************************/
63 /* L o c a l S t a t i c s */
64 /******************************************************************************/
65 
66 namespace
67 {
68 int CksOpts = 0;
69 }
70 
71 /******************************************************************************/
72 /* C o n s t r u c t o r */
73 /******************************************************************************/
74 
75 XrdCksManager::XrdCksManager(XrdSysError *erP, int rdsz, XrdVersionInfo &vInfo,
76  bool autoload)
77  : XrdCks(erP), myVersion(vInfo)
78 {
79 
80 // Get a dynamic loader if so wanted
81 //
82  if (autoload) cksLoader = new XrdCksLoader(vInfo);
83  else cksLoader = 0;
84 
85 // Prefill the native digests we support
86 //
87  strcpy(csTab[0].Name, "adler32");
88  strcpy(csTab[1].Name, "crc32");
89  strcpy(csTab[2].Name, "crc32c");
90  strcpy(csTab[3].Name, "md5");
91  csLast = 3;
92 
93 // Compute the i/o size
94 //
95  if (rdsz <= 65536) segSize = 67108864;
96  else segSize = ((rdsz/65536) + (rdsz%65536 != 0)) * 65536;
97 }
98 
99 /******************************************************************************/
100 /* D e s t r u c t o r */
101 /******************************************************************************/
102 
104 {
105  int i;
106  for (i = 0; i <= csLast; i++)
107  {if (csTab[i].Obj && csTab[i].doDel) csTab[i].Obj->Recycle();
108  if (csTab[i].Path) free( csTab[i].Path);
109  if (csTab[i].Parms) free( csTab[i].Parms);
110  if (csTab[i].Plugin) delete csTab[i].Plugin;
111  }
112  if (cksLoader) delete cksLoader;
113 }
114 
115 /******************************************************************************/
116 /* C a l c */
117 /******************************************************************************/
118 
119 int XrdCksManager::Calc(const char *Pfn, XrdCksData &Cks, int doSet)
120 {
121  XrdCksCalc *csP;
122  csInfo *csIP = &csTab[0];
123  time_t MTime;
124  int rc;
125 
126 // Determine which checksum to get
127 //
128  if (csLast < 0) return -ENOTSUP;
129  if (!(*Cks.Name)) Cks.Set(csIP->Name);
130  else if (!(csIP = Find(Cks.Name))) return -ENOTSUP;
131 
132 // If we need not set the checksum then see if we can get it from the
133 // extended attributes.
134 
135 // Obtain a new checksum object
136 //
137  if (!(csP = csIP->Obj->New())) return -ENOMEM;
138 
139 // Use the calculator to get and possibly set the checksum
140 //
141  if (!(rc = Calc(Pfn, MTime, csP)))
142  {memcpy(Cks.Value, csP->Final(), csIP->Len);
143  Cks.fmTime = static_cast<long long>(MTime);
144  Cks.csTime = static_cast<int>(time(0) - MTime);
145  Cks.Length = csIP->Len;
146  csP->Recycle();
147  if (doSet)
149  memcpy(&xCS.Attr.Cks, &Cks, sizeof(xCS.Attr.Cks));
150  if ((rc = xCS.Set(Pfn))) return -rc;
151  }
152  }
153 
154 // All done
155 //
156  return rc;
157 }
158 
159 /******************************************************************************/
160 
161 int XrdCksManager::Calc(const char *Pfn, time_t &MTime, XrdCksCalc *csP)
162 {
163  class ioFD
164  {public:
165  int FD;
166  ioFD() : FD(-1) {}
167  ~ioFD() {if (FD >= 0) close(FD);}
168  } In;
169  struct stat Stat;
170  char *inBuff;
171  off_t Offset=0, fileSize;
172  size_t ioSize, calcSize;
173  int rc;
174 
175 // Open the input file
176 //
177  if ((In.FD = open(Pfn, O_RDONLY)) < 0) return -errno;
178 
179 // Get the file characteristics
180 //
181  if (fstat(In.FD, &Stat)) return -errno;
182  if (!(Stat.st_mode & S_IFREG)) return -EPERM;
183  calcSize = fileSize = Stat.st_size;
184  MTime = Stat.st_mtime;
185 
186 // We now compute checksum 64MB at a time using mmap I/O
187 //
188  ioSize = (fileSize < (off_t)segSize ? fileSize : segSize); rc = 0;
189  while(calcSize)
190  {if ((inBuff = (char *)mmap(0, ioSize, PROT_READ,
191 #if defined(__FreeBSD__)
192  MAP_RESERVED0040|MAP_PRIVATE, In.FD, Offset)) == MAP_FAILED)
193 #elif defined(__GNU__)
194  MAP_PRIVATE, In.FD, Offset)) == MAP_FAILED)
195 #else
196  MAP_NORESERVE|MAP_PRIVATE, In.FD, Offset)) == MAP_FAILED)
197 #endif
198  {rc = errno; eDest->Emsg("Cks", rc, "memory map", Pfn); break;}
199  madvise(inBuff, ioSize, MADV_SEQUENTIAL);
200  csP->Update(inBuff, ioSize);
201  calcSize -= ioSize; Offset += ioSize;
202  if (munmap(inBuff, ioSize) < 0)
203  {rc = errno; eDest->Emsg("Cks",rc,"unmap memory for",Pfn); break;}
204  if (calcSize < (size_t)segSize) ioSize = calcSize;
205  }
206 
207 // Return if we failed
208 //
209  if (calcSize) return (rc ? -rc : -EIO);
210  return 0;
211 }
212 
213 /******************************************************************************/
214 /* C o n f i g */
215 /******************************************************************************/
216 /*
217  Purpose: To parse the directive: ckslib <digest> <path> [<parms>]
218 
219  <digest> the name of the checksum.
220  <path> the path of the checksum library to be used.
221  <parms> optional parms to be passed
222 
223  Output: 0 upon success or !0 upon failure.
224 */
225 int XrdCksManager::Config(const char *Token, char *Line)
226 {
227  XrdOucTokenizer Cfg(Line);
228  char *val, *path = 0, name[XrdCksData::NameSize], *parms;
229  int i;
230 
231 // Get the the checksum name
232 //
233  Cfg.GetLine();
234  if (!(val = Cfg.GetToken()) || !val[0])
235  {eDest->Emsg("Config", "checksum name not specified"); return 1;}
236  if (int(strlen(val)) >= XrdCksData::NameSize)
237  {eDest->Emsg("Config", "checksum name too long"); return 1;}
238  strcpy(name, val); XrdOucUtils::toLower(name);
239 
240 // Get the path and optional parameters
241 //
242  val = Cfg.GetToken(&parms);
243  if (val && val[0]) path = strdup(val);
244  else {eDest->Emsg("Config","library path missing for ckslib digest",name);
245  return 1;
246  }
247 
248 // Check if this replaces an existing checksum
249 //
250  for (i = 0; i < csMax; i++)
251  if (!(*csTab[i].Name) || !strcmp(csTab[i].Name, name)) break;
252 
253 // See if we can insert a new checksum (or replace one)
254 //
255  if (i >= csMax)
256  {eDest->Emsg("Config", "too many checksums specified");
257  if (path) free(path);
258  return 1;
259  } else if (!(*csTab[i].Name)) csLast = i;
260 
261 // Insert the new checksum
262 //
263  strcpy(csTab[i].Name, name);
264  if (csTab[i].Path) free(csTab[i].Path);
265  csTab[i].Path = path;
266  if (csTab[i].Parms) free(csTab[i].Parms);
267  csTab[i].Parms = (parms && *parms ? strdup(parms) : 0);
268 
269 // All done
270 //
271  return 0;
272 }
273 
274 /******************************************************************************/
275 /* I n i t */
276 /******************************************************************************/
277 
278 int XrdCksManager::Init(const char *ConfigFN, const char *DfltCalc)
279 {
280  int i;
281 
282 // See if we need to set the default calculation
283 //
284  if (DfltCalc)
285  {for (i = 0; i < csLast; i++) if (!strcmp(csTab[i].Name, DfltCalc)) break;
286  if (i >= csMax)
287  {eDest->Emsg("Config", DfltCalc, "cannot be made the default; "
288  "not supported.");
289  return 0;
290  }
291  if (i) {csInfo Temp = csTab[i]; csTab[i] = csTab[0]; csTab[0] = Temp;}
292  }
293 
294 // See if there are any checksums to configure
295 //
296  if (csLast < 0)
297  {eDest->Emsg("Config", "No checksums defined; cannot configure!");
298  return 0;
299  }
300 
301 // Complete the checksum table
302 //
303  for (i = 0; i <= csLast; i++)
304  {if (csTab[i].Path) {if (!(Config(ConfigFN, csTab[i]))) return 0;}
305  else { if (!strcmp("adler32", csTab[i].Name))
306  csTab[i].Obj = new XrdCksCalcadler32;
307  else if (!strcmp("crc32", csTab[i].Name))
308  csTab[i].Obj = new XrdCksCalccrc32;
309  else if (!strcmp("crc32c", csTab[i].Name))
310  csTab[i].Obj = new XrdCksCalccrc32C;
311  else if (!strcmp("md5", csTab[i].Name))
312  csTab[i].Obj = new XrdCksCalcmd5;
313  else {eDest->Emsg("Config", "Invalid native checksum -",
314  csTab[i].Name);
315  return 0;
316  }
317  csTab[i].Obj->Type(csTab[i].Len);
318  }
319  }
320 
321 // All done
322 //
323  return 1;
324 }
325 
326 /******************************************************************************/
327 
328 #define XRDOSSCKSLIBARGS XrdSysError *, const char *, const char *, const char *
329 
330 int XrdCksManager::Config(const char *cFN, csInfo &Info)
331 {
332  XrdOucPinLoader myPin(eDest, &myVersion, "ckslib", Info.Path);
334  int n;
335 
336 // Find the entry point
337 //
338  Info.Plugin = 0;
339  if (!(ep = (XrdCksCalc *(*)(XRDOSSCKSLIBARGS))
340  (myPin.Resolve("XrdCksCalcInit"))))
341  {eDest->Emsg("Config", "Unable to configure cksum", Info.Name);
342  myPin.Unload();
343  return 0;
344  }
345 
346 // Get the initial object
347 //
348  if (!(Info.Obj = ep(eDest,cFN,Info.Name,(Info.Parms ? Info.Parms : ""))))
349  {eDest->Emsg("Config", Info.Name, "checksum initialization failed");
350  myPin.Unload();
351  return 0;
352  }
353 
354 // Verify the object
355 //
356  if (strcmp(Info.Name, Info.Obj->Type(n)))
357  {eDest->Emsg("Config",Info.Name,"cksum plugin returned wrong name -",
358  Info.Obj->Type(n));
359  myPin.Unload();
360  return 0;
361  }
362  if (n > XrdCksData::ValuSize || n <= 0)
363  {eDest->Emsg("Config",Info.Name,"cksum plugin has an unsupported "
364  "checksum length");
365  myPin.Unload();
366  return 0;
367  }
368 
369 // All is well
370 //
371  Info.Plugin = myPin.Export();
372  Info.Len = n;
373  return 1;
374 }
375 
376 /******************************************************************************/
377 /* F i n d */
378 /******************************************************************************/
379 
380 XrdCksManager::csInfo *XrdCksManager::Find(const char *Name)
381 {
382  static XrdSysMutex myMutex;
383  XrdCksCalc *myCalc;
384  int i;
385 
386 // Find the pre-loaded checksum
387 //
388  for (i = 0; i <= csLast; i++)
389  if (!strcmp(Name, csTab[i].Name)) return &csTab[i];
390 
391 // If we have loader see if we can auto-load this object
392 //
393  if (!cksLoader) return 0;
394  myMutex.Lock();
395 
396 // An entry could have been added as we were running unlocked
397 //
398  for (i = 0; i <= csLast; i++)
399  if (!strcmp(Name, csTab[i].Name))
400  {myMutex.UnLock();
401  return &csTab[i];
402  }
403 
404 // Check if we have room in the table
405 //
406  if (csLast >= csMax)
407  {myMutex.UnLock();
408  eDest->Emsg("CksMan","Unable to load",Name,"; checksum limit reached.");
409  return 0;
410  }
411 
412 // Attempt to dynamically load this object
413 //
414 { char buff[2048];
415  *buff = 0;
416  if (!(myCalc = cksLoader->Load(Name, 0, buff, sizeof(buff), true)))
417  {myMutex.UnLock();
418  eDest->Emsg("CksMan", "Unable to load", Name);
419  if (*buff) eDest->Emsg("CksMan", buff);
420  return 0;
421  }
422 }
423 
424 // Fill out the table
425 //
426  i = csLast + 1;
427  strncpy(csTab[i].Name, Name, XrdCksData::NameSize);
428  csTab[i].Obj = myCalc;
429  csTab[i].Path = 0;
430  csTab[i].Parms = 0;
431  csTab[i].Plugin = 0;
432  csTab[i].doDel = false;
433  myCalc->Type(csTab[i].Len);
434 
435 // Return the result
436 //
437  csLast = i;
438  myMutex.UnLock();
439  return &csTab[i];
440 }
441 
442 /******************************************************************************/
443 /* D e l */
444 /******************************************************************************/
445 
446 int XrdCksManager::Del(const char *Pfn, XrdCksData &Cks)
447 {
449 
450 // Set the checksum name
451 //
452  xCS.Attr.Cks.Set(Cks.Name);
453 
454 // Delete the attribute and return the result
455 //
456  return xCS.Del(Pfn);
457 }
458 
459 /******************************************************************************/
460 /* G e t */
461 /******************************************************************************/
462 
463 int XrdCksManager::Get(const char *Pfn, XrdCksData &Cks)
464 {
466  time_t MTime;
467  int rc, nFault;
468 
469 // Determine which checksum to get (we will accept unsupported ones as well)
470 //
471  if (csLast < 0) return -ENOTSUP;
472  if (!*Cks.Name) Cks.Set(csTab[0].Name);
473  if (!xCS.Attr.Cks.Set(Cks.Name)) return -ENOTSUP;
474 
475 // Retreive the attribute
476 //
477  if ((rc = xCS.Get(Pfn)) <= 0) return (rc && rc != -ENOATTR ? rc : -ESRCH);
478 
479 // Mark state of the name and copy the attribute over
480 //
481  nFault = strcmp(xCS.Attr.Cks.Name, Cks.Name);
482  Cks = xCS.Attr.Cks;
483 
484 // Verify the file. We do this with modification time unless that check
485 // has been turned off.
486 //
487  if (CksOpts & Cks_nomtchk) MTime = Cks.fmTime;
488  else if ((rc = ModTime(Pfn, MTime))) return rc;
489 
490 // Return result
491 //
492  return (Cks.fmTime != MTime || nFault
493  || Cks.Length > XrdCksData::ValuSize || Cks.Length <= 0
494  ? -ESTALE : int(Cks.Length));
495 }
496 
497 /******************************************************************************/
498 /* L i s t */
499 /******************************************************************************/
500 
501 char *XrdCksManager::List(const char *Pfn, char *Buff, int Blen, char Sep)
502 {
503  static const char *vPfx = "XrdCks.";
504  static const int vPln = strlen(vPfx);
505  XrdSysFAttr::AList *vP, *axP = 0;
506  char *bP = Buff;
507  int i, n;
508 
509 // Verify that the buffer is large enough
510 //
511  if (Blen < 2) return 0;
512 
513 // Check if the default list is wanted
514 //
515  if (!Pfn)
516  {if (csLast < 0) return 0;
517  i = 0;
518  while(i <= csLast && Blen > 1)
519  {n = strlen(csTab[i].Name);
520  if (n >= Blen) break;
521  if (bP != Buff) *bP++ = Sep;
522  strcpy(bP, csTab[i].Name); bP += n; *bP = 0;
523  }
524  return (bP == Buff ? 0 : Buff);
525  }
526 
527 // Get a list of attributes for this file
528 //
529  if (XrdSysFAttr::Xat->List(&axP, Pfn) < 0 || !axP) return 0;
530 
531 // Go through the list extracting what we are looking for
532 //
533  vP = axP;
534  while(vP)
535  {if (vP->Nlen > vPln && !strncmp(vP->Name, vPfx, vPln))
536  {n = vP->Nlen - vPln;
537  if (n >= Blen) break;
538  if (bP != Buff) *bP++ = Sep;
539  strcpy(bP, vP->Name + vPln); bP += n; *bP = 0;
540  }
541  vP = vP->Next;
542  }
543 
544 // All done
545 //
546  XrdSysFAttr::Xat->Free(axP);
547  return (bP == Buff ? 0 : Buff);
548 }
549 
550 /******************************************************************************/
551 /* M o d T i m e */
552 /******************************************************************************/
553 
554 int XrdCksManager::ModTime(const char *Pfn, time_t &MTime)
555 {
556  struct stat Stat;
557 
558  if (stat(Pfn, &Stat)) return -errno;
559 
560  MTime = Stat.st_mtime;
561  return 0;
562 }
563 
564 /******************************************************************************/
565 /* N a m e */
566 /******************************************************************************/
567 
568 const char *XrdCksManager::Name(int seqNum)
569 {
570 
571  return (seqNum < 0 || seqNum > csLast ? 0 : csTab[seqNum].Name);
572 }
573 
574 /******************************************************************************/
575 /* O b j e c t */
576 /******************************************************************************/
577 
579 {
580  csInfo *csIP = &csTab[0];
581 
582 // Return an object it at all possible
583 //
584  if (name && !(csIP = Find(name))) return 0;
585  return csIP->Obj->New();
586 }
587 
588 /******************************************************************************/
589 /* S i z e */
590 /******************************************************************************/
591 
592 int XrdCksManager::Size(const char *Name)
593 {
594  csInfo *iP = (Name != 0 ? Find(Name) : &csTab[0]);
595  return (iP != 0 ? iP->Len : 0);
596 }
597 
598 /******************************************************************************/
599 /* S e t */
600 /******************************************************************************/
601 
602 int XrdCksManager::Set(const char *Pfn, XrdCksData &Cks, int myTime)
603 {
605  csInfo *csIP = &csTab[0];
606 
607 // Verify the incoming checksum for correctness
608 //
609  if (csLast < 0 || (*Cks.Name && !(csIP = Find(Cks.Name)))) return -ENOTSUP;
610  if (Cks.Length != csIP->Len) return -EDOM;
611  memcpy(&xCS.Attr.Cks, &Cks, sizeof(xCS.Attr.Cks));
612 
613 // Set correct times if need be
614 //
615  if (!myTime)
616  {time_t MTime;
617  int rc = ModTime(Pfn, MTime);
618  if (rc) return rc;
619  xCS.Attr.Cks.fmTime = static_cast<long long>(MTime);
620  xCS.Attr.Cks.csTime = static_cast<int>(time(0) - MTime);
621  }
622 
623 // Now set the checksum information in the extended attribute object
624 //
625  return xCS.Set(Pfn);
626 }
627 
628 /******************************************************************************/
629 /* S e t O p t s */
630 /******************************************************************************/
631 
632 void XrdCksManager::SetOpts(int opt) {CksOpts = opt;}
633 
634 /******************************************************************************/
635 /* V e r */
636 /******************************************************************************/
637 
638 int XrdCksManager::Ver(const char *Pfn, XrdCksData &Cks)
639 {
641  time_t MTime;
642  csInfo *csIP = &csTab[0];
643  int rc;
644 
645 // Determine which checksum to get
646 //
647  if (csLast < 0 || (*Cks.Name && !(csIP = Find(Cks.Name)))) return -ENOTSUP;
648  xCS.Attr.Cks.Set(csIP->Name);
649 
650 // Verify the file
651 //
652  if ((rc = ModTime(Pfn, MTime))) return rc;
653 
654 // Retreive the attribute. Return upon fatal error.
655 //
656  if ((rc = xCS.Get(Pfn)) < 0) return rc;
657 
658 // Verify the checksum and see if we need to recalculate it
659 //
660  if (!rc || xCS.Attr.Cks.fmTime != MTime
661  || strcmp(xCS.Attr.Cks.Name, csIP->Name)
662  || xCS.Attr.Cks.Length != csIP->Len)
663  {strcpy(xCS.Attr.Cks.Name, Cks.Name);
664  if ((rc = Calc(Pfn, xCS.Attr.Cks, 1)) < 0) return rc;
665  }
666 
667 // Compare the checksums
668 //
669  return (xCS.Attr.Cks.Length == Cks.Length
670  && !memcmp(xCS.Attr.Cks.Value, Cks.Value, csIP->Len));
671 }
#define ENOATTR
#define XRDOSSCKSLIBARGS
struct stat Stat
Definition: XrdCks.cc:49
XrdOucXAttr< XrdCksXAttr > xCS
Definition: XrdCks.cc:48
int stat(const char *path, struct stat *buf)
int open(const char *path, int oflag,...)
int fstat(int fildes, struct stat *buf)
#define close(a)
Definition: XrdPosix.hh:48
XrdOucString Path
virtual char * Final()=0
virtual void Update(const char *Buff, int BLen)=0
virtual const char * Type(int &csSize)=0
virtual void Recycle()
Recycle the checksum object as it is no longer needed. A default is given.
Definition: XrdCksCalc.hh:95
virtual XrdCksCalc * New()=0
char Value[ValuSize]
Definition: XrdCksData.hh:53
static const int ValuSize
Definition: XrdCksData.hh:42
int Set(const char *csName)
Definition: XrdCksData.hh:81
char Length
Definition: XrdCksData.hh:52
static const int NameSize
Definition: XrdCksData.hh:41
char Name[NameSize]
Definition: XrdCksData.hh:44
XrdCksCalc * Load(const char *csName, const char *csParms=0, char *eBuff=0, int eBlen=0, bool orig=false)
virtual int Config(const char *Token, char *Line)
virtual int Get(const char *Pfn, XrdCksData &Cks)
virtual int Del(const char *Pfn, XrdCksData &Cks)
virtual int Size(const char *Name=0)
virtual const char * Name(int seqNum=0)
virtual ~XrdCksManager()
XrdCksManager(XrdSysError *erP, int iosz, XrdVersionInfo &vInfo, bool autoload=false)
virtual int Calc(const char *Pfn, XrdCksData &Cks, int doSet=1)
virtual int ModTime(const char *Pfn, time_t &MTime)
virtual char * List(const char *Pfn, char *Buff, int Blen, char Sep=' ')
virtual XrdCksCalc * Object(const char *name)
virtual int Ver(const char *Pfn, XrdCksData &Cks)
virtual int Set(const char *Pfn, XrdCksData &Cks, int myTime=0)
void SetOpts(int opt)
virtual int Init(const char *ConfigFN, const char *AddCalc=0)
Definition: XrdCks.hh:92
XrdSysError * eDest
Definition: XrdCks.hh:289
XrdSysPlugin * Export()
void * Resolve(const char *symbl, int mcnt=1)
void Unload(bool dodel=false)
static void toLower(char *str)
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95
static XrdSysXAttr * Xat
Definition: XrdSysFAttr.hh:51
char Name[1]
Start of the name (size of struct is dynamic)
Definition: XrdSysXAttr.hh:56
int Nlen
The length of the attribute name that follows.
Definition: XrdSysXAttr.hh:55
virtual void Free(AList *aPL)=0
AList * Next
-> next element.
Definition: XrdSysXAttr.hh:53
XrdVersionInfo myVersion