XRootD
Loading...
Searching...
No Matches
XrdFrmAdminAudit.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d F r m A d m i n A u d i t . c c */
4/* */
5/* (c) 2009 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 <cstdio>
32#include <cstring>
33#include <sys/param.h>
34
35#include "XrdFrc/XrdFrcTrace.hh"
36#include "XrdFrc/XrdFrcUtils.hh"
37#include "XrdFrm/XrdFrmAdmin.hh"
39#include "XrdFrm/XrdFrmFiles.hh"
40#include "XrdOss/XrdOssPath.hh"
41#include "XrdOss/XrdOssSpace.hh"
43#include "XrdOuc/XrdOucTList.hh"
44
45using namespace XrdFrc;
46using namespace XrdFrm;
47
48/******************************************************************************/
49/* A u d i t N a m e N B */
50/******************************************************************************/
51
52int XrdFrmAdmin::AuditNameNB(XrdFrmFileset *sP)
53{
54 char Resp, buff[80];
55 int num = 0, rem;
56
57// Report what is orphaned
58//
59 if (sP->lockFile())
60 {num++; Msg("Orphaned lock file: ", sP->lockPath());}
61 if (sP->pfnFile() )
62 {num++; Msg("Orphaned pfn file: ", sP->pfnPath());
63 Msg("PFN file refers to: ", sP->pfnFile()->Link);
64 }
65 if (sP->pinFile() )
66 {num++; Msg("Orphaned pin file: ", sP->pinPath());}
67
68// Return if no fix is needed, otherwise check if we should ask before removal
69//
70 numProb += num;
71 if (!Opt.Fix || !num) return 1;
72 if (!Opt.Force)
73 {Resp = XrdFrcUtils::Ask('n', "Remove orphaned files?");
74 if (Resp != 'y') return Resp != 'a';
75 }
76
77// Remove the orphaned files
78//
79 rem = AuditRemove(sP);
80 numFix += rem;
81
82// Indicate final resolution
83//
84 sprintf(buff, "%d of %d orphaned files removed.", rem, num);
85 Msg(buff);
86 return 1;
87}
88
89/******************************************************************************/
90/* A u d i t N a m e N F */
91/******************************************************************************/
92
93int XrdFrmAdmin::AuditNameNF(XrdFrmFileset *sP)
94{
95 char Resp;
96
97// Indicate what is wrong
98//
99 Msg("Dangling link: ", sP->basePath());
100 Msg("Missing target: ", sP->baseFile()->Link);
101 numProb++;
102
103// Return if no fix is needed, otherwise check if we should ask before removal
104//
105 if (!Opt.Fix) return 1;
106 if (!Opt.Force)
107 {Resp = XrdFrcUtils::Ask('n', "Remove symlink?");
108 if (Resp != 'y') return Resp != 'a';
109 }
110
111// Remove the symlink and associated files
112//
113 if (unlink(sP->basePath()))
114 Emsg(errno,"remove symlink", sP->basePath());
115 else if (AuditRemove(sP))
116 {Msg("Symlink removed.");
117 numFix++;
118 return 1;
119 }
120 return 1;
121}
122
123/******************************************************************************/
124/* A u d i t N a m e N L */
125/******************************************************************************/
126
127int XrdFrmAdmin::AuditNameNL(XrdFrmFileset *sP)
128{
129 static const char *noCPT = "No copy time for: ";
130 static const char *mkCPT = "Set copy time?";
131 char Resp;
132
133// Indicate what is wrong
134//
135 Msg(noCPT, sP->basePath());
136 numProb++;
137
138// Return if no fix is needed, otherwise check if we should ask before removal
139//
140 if (!Opt.Fix) return -1;
141 if (!Opt.Force)
142 {Resp = XrdFrcUtils::Ask('y', mkCPT);
143 if (Resp != 'y') return Resp != 'a';
144 }
145
146// Set copy time
147//
148 if (XrdFrcUtils::updtCpy(sP->basePath(),(Opt.MPType == 'p' ? 0 : -113)))
149 {numFix++;
150 Msg("Copy time set.");
151 }
152 return 1;
153}
154
155/******************************************************************************/
156/* A u d i t N a m e s */
157/******************************************************************************/
158
159int XrdFrmAdmin::AuditNames()
160{
161 static const int fsetOpts = XrdFrmFiles::GetCpyTim | XrdFrmFiles::NoAutoDel;
162 XrdFrmFileset *sP;
163 XrdFrmFiles *fP;
164 char pDir[MAXPATHLEN], *lDir = Opt.Args[1];
165 int opts = (Opt.Recurse ? XrdFrmFiles::Recursive : 0) | fsetOpts;
166 int ec = 0, Act = 1;
167
168// Initialization
169//
170 numProb = 0; numFix = 0;
171 if (VerifyMP("audit", lDir) != 'y') return 0;
172
173// Process the directory
174//
175 if (!Config.LocalPath(lDir, pDir, sizeof(pDir))) {finalRC = 4; return 1;}
176 fP = new XrdFrmFiles(pDir, opts);
177 while(Act && (sP = fP->Get(ec,1)))
178 {if (!(sP->baseFile())) Act = AuditNameNB(sP);
179 else {if (sP->baseFile()->Type == XrdOucNSWalk::NSEnt::isLink)
180 Act = AuditNameNF(sP);
181 if (Act && Opt.MPType && !(sP->cpyInfo.Attr.cpyTime))
182 Act = AuditNameNL(sP);
183 if (Act && sP->baseFile()->Link && isXA(sP->baseFile()))
184 Act = AuditNameXA(sP);
185 }
186 delete sP;
187 }
188 if (ec) finalRC = 4;
189 delete fP;
190
191// All done
192//
193 if (!Act) Msg("Audit names aborted!");
194 sprintf(pDir,"%d problem%s found; %d fixed.", numProb,
195 (numProb == 1 ? "" : "s"), numFix);
196 Msg(pDir);
197 return !Act;
198}
199
200/******************************************************************************/
201/* A u d i t N a m e X A */
202/******************************************************************************/
203
204int XrdFrmAdmin::AuditNameXA(XrdFrmFileset *sP)
205{
207 const char *doWhat = "Recreate pfn xref?";
208 char Resp, dfltAns = 'n';
209 int rc;
210
211// Make sure there is a PFN attribute is here and references the file
212//
213 if ((rc = pfnInfo.Get(sP->baseFile()->Link)) > 0)
214 {if (!strcmp(pfnInfo.Attr.Pfn,sP->basePath())) return 1;
215 Msg("Incorrect pfn xref to ", sP->basePath());
216 Msg("Data file refers to ", pfnInfo.Attr.Pfn);
217 } else {
218 if (rc) Emsg(-rc, "get pfn xattr for ",sP->basePath());
219 else {Msg("Missing pfn xref to ", sP->basePath());
220 doWhat = "Create pfn xref?"; dfltAns = 'y';
221 }
222 }
223
224// Check if we can fix this problem
225//
226 if (!Opt.Fix || rc < 0) return 1;
227 if (!Opt.Force)
228 {Resp = XrdFrcUtils::Ask(dfltAns, doWhat);
229 if (Resp != 'y') return Resp != 'a';
230 }
231
232// Reset the pfn xattr
233//
234 strcpy(pfnInfo.Attr.Pfn, sP->basePath());
235 if (!(rc = pfnInfo.Set(sP->baseFile()->Link)))
236 {Msg("pfn xref set."); numFix++;}
237 else Emsg(-rc, "set pfn xref to ", sP->basePath());
238
239
240// All done.
241//
242 return 1;
243}
244
245/******************************************************************************/
246/* A u d i t R e m o v e */
247/******************************************************************************/
248
249int XrdFrmAdmin::AuditRemove(XrdFrmFileset *sP)
250{
251 int rem = 0;
252
253// Remove the orphaned files
254//
255 if (sP->lockFile())
256 {if (unlink(sP->lockPath())) Emsg(errno,"remove lock file.");
257 else rem++;
258 }
259 if (sP-> pinFile())
260 {if (unlink(sP-> pinPath())) Emsg(errno,"remove pin file.");
261 else rem++;
262 }
263 if (sP-> pfnFile())
264 {if (unlink(sP-> pfnPath())) Emsg(errno,"remove pfn file.");
265 else rem++;
266 }
267
268 return rem;
269}
270
271/******************************************************************************/
272/* A u d i t S p a c e */
273/******************************************************************************/
274
275int XrdFrmAdmin::AuditSpace()
276{
277 XrdOucTList *pP;
278 char buff[256], *Path = 0, *Space = Opt.Args[1];
279 int Act;
280
281// Parse the space specification
282//
283 if (!(pP = ParseSpace(Space, &Path))) return 4;
284
285// Initialize
286//
287 numBytes = 0; numFiles = 0; numProb = 0; numFix = 0;
288
289// Index the space via filesets
290//
291 do {Act = (pP->val ? AuditSpaceXA(Space, pP->text) : AuditSpaceAX(pP->text));
292 pP = pP->next;
293 } while(pP && !Path && Act);
294
295// All done
296//
297 sprintf(buff,"%d problem%s found; %d fixed.", numProb,
298 (numProb == 1 ? "" : "s"), numFix);
299 Msg(buff);
300 if (!Act) Msg("Audit space aborted!");
301 else {if (Path) *(--Path) = ':';
302 sprintf(buff, "Space %s has %d file%s with %lld byte%s in use "
303 "(%lld unreachable).",
304 Space,
305 numFiles, (numFiles == 1 ? "" : "s"),
306 numBytes, (numBytes == 1 ? "" : "s"),
307 numBLost);
308 Msg(buff);
309 }
310 return (Act ? 0 : 4);
311}
312
313/******************************************************************************/
314/* A u d i t S p a c e A X */
315/******************************************************************************/
316
317int XrdFrmAdmin::AuditSpaceAX(const char *Path)
318{
322 XrdOucNSWalk::NSEnt *nP, *pP;
323 char buff[1032];
324 int ec, Act = 1;
325
326// Get the files in this directory
327//
328 if (!(nP = nsWalk.Index(ec))) {if (ec) finalRC = 4; return 1;}
329 pP = nP;
330
331// Now traverse through all of the files
332//
333 while(nP && Act)
334 {Act = (XrdOssPath::genPFN(buff, sizeof(buff), nP->Path)
335 ? AuditSpaceAXDC(buff, nP) : AuditSpaceAXDB(nP->Path));
336 nP = nP->Next;
337 }
338
339// Delete the entries and return
340//
341 while(pP) {nP = pP; pP = pP->Next; delete nP;}
342 return Act;
343}
344
345/******************************************************************************/
346/* A u d i t S p a c e A X D B */
347/******************************************************************************/
348
349int XrdFrmAdmin::AuditSpaceAXDB(const char *Path)
350{
351 char Resp;
352
353// Indicate the problem
354//
355 Msg("Invalid name for data file ", Path);
356 numProb++;
357
358// Return if no fix is needed, otherwise check if we should ask before doing it
359//
360 if (Opt.Fix)
361 {if (!Opt.Force)
362 {Resp = XrdFrcUtils::Ask('n', "Delete file?");
363 if (Resp != 'y') return Resp != 'a';
364 }
365 if (unlink(Path)) Emsg(errno, "remove ", Path);
366 else numFix++;
367 }
368 return 1;
369}
370
371/******************************************************************************/
372/* A u d i t S p a c e A X D C */
373/******************************************************************************/
374
375int XrdFrmAdmin::AuditSpaceAXDC(const char *Path, XrdOucNSWalk::NSEnt *nP)
376{
377 struct stat buf;
378 char lkbuff[1032], *Dest = nP->Path;
379 int n;
380
381// Assume we have a problem
382//
383 numProb++;
384
385// Verify that the link to the file exists
386//
387 if (lstat(Path,&buf))
388 {if (errno != ENOENT) {Emsg(errno, "stat ", Path); return -1;}
389 Msg("Missing pfn data link ", Path);
390 return AuditSpaceAXDL(0, Path, Dest);
391 }
392
393// Make sure the PFN file is a link
394//
395 if ((buf.st_mode & S_IFMT) != S_IFLNK)
396 {Msg("Invalid pfn data link ", Path);
397 return AuditSpaceAXDL(1, Path, Dest);
398 }
399
400// Make sure tyhe link points to the right file
401//
402 if ((n = readlink(Path, lkbuff, sizeof(lkbuff)-1)) < 0)
403 {Emsg(errno, "read link from ", Path); return -1;}
404 lkbuff[n] = '\0';
405 if (strcmp(Dest, lkbuff))
406 {Msg("Incorrect pfn data link ", Path);
407 return AuditSpaceAXDL(1, Path, Dest);
408 }
409
410// All went well
411//
412 numProb--; numFiles++; numBytes += nP->Stat.st_size;
413 return 1;
414}
415
416/******************************************************************************/
417/* A u d i t S p a c e A X D L */
418/******************************************************************************/
419
420int XrdFrmAdmin::AuditSpaceAXDL(int dorm, const char *Path, const char *Dest)
421{
422 char Resp;
423
424// Return if no fix is needed, otherwise check if we should ask before doing it
425//
426 if (!Opt.Fix) return -1;
427 if (!Opt.Force)
428 {if (dorm)
429 Resp = XrdFrcUtils::Ask('n', "Recreate pfn symlink?");
430 else
431 Resp = XrdFrcUtils::Ask('y', "Create pfn symlink?");
432 if (Resp != 'y') return Resp != 'a';
433 }
434
435// Create the pfn symlink
436//
437 if (dorm) unlink(Path);
438 if (symlink(Dest, Path))
439 {Emsg(errno, "create symlink ", Path); return -1;}
440 Msg("pfn symlink created.");
441 numFix++;
442 return 1;
443}
444
445/******************************************************************************/
446/* A u d i t S p a c e X A */
447/******************************************************************************/
448
449int XrdFrmAdmin::AuditSpaceXA(const char *Space, const char *Path)
450{
451 XrdFrmFileset *sP;
452 XrdFrmFiles *fP;
453 char tmpv[8], *buff;
454 int ec = 0, Act = 1;
455
456// Construct the right space path and get a files object
457//
458 buff = XrdOssPath::genPath(Path, Space, tmpv);
460
461// Go and check out the files
462//
463 while(Act && (sP = fP->Get(ec,1)))
464 {if (!sP->baseFile()) Act = AuditNameNB(sP);
465 else {numFiles++;
466 if ((Act = AuditSpaceXA(sP)))
467 {if (Act < 0) numFiles--;
468 else numBytes += sP->baseFile()->Stat.st_size;
469 }
470 }
471 delete sP;
472 }
473
474// All done
475//
476 if (ec) finalRC = 4;
477 free(buff);
478 delete fP;
479 return Act;
480}
481
482/******************************************************************************/
483
484int XrdFrmAdmin::AuditSpaceXA(XrdFrmFileset *sP)
485{
487 struct stat buf;
488 const char *Plug;
489 char Resp = 0, tempPath[1032], lkbuff[1032], *Pfn = pfnInfo.Attr.Pfn;
490 int n;
491
492// First step is to get the pfn extended attribute
493//
494 if (pfnInfo.Get(sP->basePath()) <= 0)
495 {Msg("Missing pfn xref for data file ", sP->basePath());
496 numProb++;
497 return 1;
498 }
499
500// If there is no PFN file then recreate symlink if possible
501//
502 if (lstat(Pfn,&buf))
503 {numProb++;
504 if (errno != ENOENT) {Emsg(errno, "stat ", Pfn); return 1;}
505 Msg("Data file xrefs missing pfn ", Pfn);
506 if (Opt.Fix)
507 {if (Opt.Force) Resp = 'y';
508 else Resp = XrdFrcUtils::Ask('y',"Create pfn symlink?");
509 if (Resp == 'y')
510 {if (!symlink(sP->basePath(), Pfn))
511 {Msg("pfn symlink created."); numFix++; return 1;}
512 Emsg(errno, "create symlink ", Pfn);
513 }
514 }
515 numBLost += sP->baseFile()->Stat.st_size;
516 return Resp != 'a';
517 }
518
519// If the PFN file is not a link, the see if we should remove the data file
520//
521 if ((buf.st_mode & S_IFMT) != S_IFLNK)
522 {numProb++;
523 Msg("Data file xrefs non-symlink pfn ", Pfn);
524 if (Opt.Fix)
525 {if (Opt.Force) Resp = 'n';
526 else Resp = XrdFrcUtils::Ask('n',"Remove data file?");
527 if (Resp == 'y')
528 {if (unlink(sP->basePath())) Emsg(errno,"remove ",sP->basePath());
529 else {Msg("Data file removed."); numFix++; return -1;}
530 }
531 }
532 numBLost += sP->baseFile()->Stat.st_size;
533 return Resp != 'a';
534 }
535
536// Check if xrefs are consistent.
537//
538 if ((n = readlink(Pfn, lkbuff, sizeof(lkbuff)-1)) < 0)
539 {Emsg(errno, "read link from ", Pfn); numProb++; return 1;}
540 lkbuff[n] = '\0';
541 if (!strcmp(sP->basePath(), lkbuff)) return 1;
542
543// Issue first message (there is value in seeing the data file path)
544//
545 Msg("Inconsistent data file: ", sP->basePath());
546 numProb++;
547
548// Diagnose the problem and check if fix is possible
549//
550 if (!stat(lkbuff, &buf)) Plug = "exists.";
551 else if (errno == ENOENT) Plug = "is missing.";
552 else {Emsg(errno, "stat ", lkbuff); return 1;}
553 Msg("Data file xrefs pfn ", Pfn);
554 Msg("Pfn points to a different data file that ", Plug);
555 if (!Opt.Fix) return 1;
556
557// If the data file is orphaned then check if we can remove it otherwise
558// see if we can simply change the symlink to point to this file
559//
560 if (*Plug == 'e')
561 {if (Opt.Force) Resp = 'n';
562 else Resp = XrdFrcUtils::Ask('n',"Remove unreferenced data file?");
563 if (Resp == 'y')
564 {if (unlink(sP->basePath())) Emsg(errno,"remove ",sP->basePath());
565 else {Msg("Data file removed."); numFix++; return -1;}
566 }
567 } else {
568 if (Opt.Force) Resp = 'n';
569 else Resp = XrdFrcUtils::Ask('n',"Change pfn symlink?");
570 if (Resp == 'y')
571 {*tempPath = ' '; strcpy(tempPath+1, Pfn); unlink(tempPath);
572 if (symlink(sP->basePath(), tempPath) || rename(tempPath, Pfn))
573 {Emsg(errno, "create symlink ", Pfn); unlink(tempPath);}
574 else {Msg("pfn symlink changed."); numFix++; return 1;}
575 }
576 }
577
578// Space for this file is definitely lost
579//
580 numBLost += sP->baseFile()->Stat.st_size;
581 return Resp != 'a';
582}
583
584/******************************************************************************/
585/* A u d i t U s a g e */
586/******************************************************************************/
587
588int XrdFrmAdmin::AuditUsage()
589{
591 char Sbuff[1024];
592 int retval, rc;
593
594// Check if we have a space or we should do all spaces
595//
596 if (Opt.Args[1]) return AuditUsage(Opt.Args[1]);
597
598// If no cache configured say so
599//
600 if (!vP) {Emsg("No outplace space has been configured."); return -1;}
601
602// Audit usage for each space
603//
604 retval = 1;
605 while(vP)
606 {strcpy(Sbuff, vP->Name);
607 if (!(rc = AuditUsage(Sbuff))) return 0;
608 if (rc < 0) retval = rc;
609 vP = vP->Next;
610 }
611 return retval;
612}
613
614/******************************************************************************/
615
616int XrdFrmAdmin::AuditUsage(char *Space)
617{
618 XrdOucTList *pP;
619 const char *Sfx;
620 char Resp, buff[256], *Path = 0;
621 long long theClaim, theDiff;
622 int haveUsage, Probs = 0;
623
624// Parse the space specification
625//
626 if (!(pP = ParseSpace(Space, &Path))) return -1;
627 if (Path) {Emsg("Path not allowed for audit usage."); return -1;}
628
629// Initialize
630//
631 numBytes = 0; numFiles = 0; numProb = 0;
632 haveUsage = XrdOssSpace::Init();
633
634// Index the space via filesets
635//
636 do {Probs |= (pP->val ? AuditUsageXA(pP->text, Space)
637 : AuditUsageAX(pP->text));
638 pP = pP->next;
639 } while(pP);
640
641// Print ending condition
642//
643 sprintf(buff, "Audit of %d file%s in %s space completed with %serrors.",
644 numFiles, (numFiles == 1 ? "" : "s"), Space,
645 (Probs ? "" : "no "));
646 Msg(buff);
647
648// Print what is in the usage file
649//
650 if (haveUsage)
651 {XrdOssSpace::uEnt myEnt;
652 XrdOssSpace::Usage(Space, myEnt);
653 theClaim = myEnt.Bytes[XrdOssSpace::Serv]
654 + myEnt.Bytes[XrdOssSpace::Pstg]
655 - myEnt.Bytes[XrdOssSpace::Purg]
656 + myEnt.Bytes[XrdOssSpace::Admin];
657 sprintf(buff, "%12lld", theClaim);
658 Msg("Claimed: ", buff);
659 } else theClaim = numBytes;
660
661// Print what we came up with
662//
663 sprintf(buff, "%12lld", numBytes);
664 Msg("Actual: ", buff);
665
666// Check if fix is required and wanted
667//
668 if (numBytes == theClaim || !Opt.Fix) return 1;
669 if (!haveUsage)
670 {Emsg(0, "No usage file present to fix!"); return -1;}
671
672// Compute difference
673//
674 if (theClaim < numBytes) theDiff = numBytes - theClaim;
675 else theDiff = theClaim - numBytes;
676
677// See if we should fix this
678//
679 if (!Opt.Force)
680 {if (theDiff < 500000) Sfx = "byte";
681 {theDiff = (theDiff+512)/1024; Sfx = "KB";}
682 sprintf(buff, "Fix %lld %s difference?", theDiff, Sfx);
683 Resp = XrdFrcUtils::Ask('n', "Fix usage information?");
684 if (Resp != 'y') return Resp != 'a';
685 }
686
687// Fix the problem
688//
689 XrdOssSpace::Adjust(Space, numBytes-theClaim, XrdOssSpace::Admin);
690 return 1;
691}
692
693/******************************************************************************/
694/* A u d i t U s a g e A X */
695/******************************************************************************/
696
697int XrdFrmAdmin::AuditUsageAX(const char *Path)
698{
702 XrdOucNSWalk::NSEnt *nP, *pP;
703 int ec;
704
705// Get the files in this directory
706//
707 if (!(nP = nsWalk.Index(ec))) {if (ec) finalRC = 4; return 1;}
708
709// Now traverse through all of the files
710//
711 while(nP)
712 {numBytes += nP->Stat.st_size;
713 numFiles++;
714 pP = nP;
715 nP = nP->Next;
716 delete pP;
717 }
718
719// All done
720//
721 return 0;
722}
723
724/******************************************************************************/
725/* A u d i t U s a g e X A */
726/******************************************************************************/
727
728int XrdFrmAdmin::AuditUsageXA(const char *Path, const char *Space)
729{
730 XrdFrmFileset *sP;
731 XrdFrmFiles *fP;
732 char tmpv[8], *buff;
733 int ec = 0;
734
735// Construct the right space path and get a files object
736//
737 buff = XrdOssPath::genPath(Path, Space, tmpv);
739
740// Go and check out the files
741//
742 while((sP = fP->Get(ec)))
743 {if ((sP->baseFile()))
744 {numFiles++; numBytes += sP->baseFile()->Stat.st_size;}
745 delete sP;
746 }
747
748// All done
749//
750 free(buff);
751 delete fP;
752 return ec;
753}
754
755/******************************************************************************/
756/* i s X A */
757/******************************************************************************/
758
759int XrdFrmAdmin::isXA(XrdOucNSWalk::NSEnt *nP)
760{
761 char *lP;
762
763 if (!(nP->Link)) return 0;
764 lP = nP->Link + nP->Lksz -1;
765 return (*lP == XrdOssPath::xChar);
766}
XrdOucPup XrdCmsParser::Pup & Say
int lstat(const char *path, struct stat *buf)
#define unlink(a)
Definition XrdPosix.hh:113
#define stat(a, b)
Definition XrdPosix.hh:101
#define rename(a, b)
Definition XrdPosix.hh:92
XrdOucString Path
struct myOpts opts
static char Ask(char dflt, const char *Msg1, const char *Msg2="", const char *Msg3="")
static int updtCpy(const char *Pfn, int Adj)
long long cpyTime
struct XrdFrmConfig::VPInfo * VPList
int LocalPath(const char *oldp, char *newp, int newpsz)
static const int NoAutoDel
static const int GetCpyTim
XrdFrmFileset * Get(int &rc, int noBase=0)
static const int Recursive
const char * pinPath()
const char * basePath()
const char * pfnPath()
XrdOucNSWalk::NSEnt * baseFile()
const char * lockPath()
XrdOucXAttr< XrdFrcXAttrCpy > cpyInfo
XrdOucNSWalk::NSEnt * lockFile()
XrdOucNSWalk::NSEnt * pinFile()
XrdOucNSWalk::NSEnt * pfnFile()
static char * genPFN(fnInfo &Info, char *buff, int blen, const char *Path=0)
static const char xChar
Definition XrdOssPath.hh:47
static char * genPath(const char *inPath, const char *cgrp, char *sfx)
static long long Usage(int gent)
static int Init()
long long Bytes[Totn]
static void Adjust(int Gent, off_t Space, sType=Serv)
static const int retFile
static const int skpErrs
static const int retStat
XrdOucTList * next
int Get(const char *Path, int fd=-1)
int Set(const char *Path, int fd=-1)
XrdFrmConfig Config
struct NSEnt * Next