XRootD
XrdFrmAdmin.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d F r m A d m i n . 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 <fcntl.h>
32 #include <grp.h>
33 #include <cstring>
34 #include <ctime>
35 #include <pwd.h>
36 #include <cstdio>
37 #include <unistd.h>
38 #include <sys/param.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 
42 #include "XrdCks/XrdCksManager.hh"
43 #include "XrdFrc/XrdFrcProxy.hh"
44 #include "XrdFrc/XrdFrcTrace.hh"
45 #include "XrdFrc/XrdFrcUtils.hh"
46 #include "XrdFrm/XrdFrmAdmin.hh"
47 #include "XrdFrm/XrdFrmConfig.hh"
48 #include "XrdOss/XrdOss.hh"
49 #include "XrdOuc/XrdOuca2x.hh"
50 #include "XrdOuc/XrdOucArgs.hh"
51 #include "XrdOuc/XrdOucExport.hh"
52 #include "XrdOuc/XrdOucTList.hh"
54 #include "XrdSys/XrdSysE2T.hh"
55 #include "XrdSys/XrdSysPlatform.hh"
56 #include "XrdSys/XrdSysTimer.hh"
57 
58 using namespace XrdFrc;
59 using namespace XrdFrm;
60 
61 /******************************************************************************/
62 /* A u d i t */
63 /******************************************************************************/
64 
65 const char *XrdFrmAdmin::AuditHelp =
66 
67 "audit [opts] {names ldir | space name[:pdir] | usage [name]}\n\n"
68 
69 "opts: -fix -f[orce] -m[igratable] -p[urgeable] -r[ecursive]";
70 
72 {
73  static XrdOucArgs Spec(&Say, "frm_admin: ", "",
74  "fix", 3, "f",
75  "force", 1, "F",
76  "migratable", 1, "m",
77  "purgeable", 1, "p",
78  "recursive", 1, "r",
79  (const char *)0);
80 
81  static const char *Reqs[] = {"type", 0};
82 
83 // Parse the request
84 //
85  if (!Parse("audit ", Spec, Reqs)) return 1;
86  Opt.Args[1] = Spec.getarg();
87 
88 // Fan out based on the function
89 //
90  if (!strcmp(Opt.Args[0], "usage")) return AuditUsage();
91  if (!Opt.Args[1]) Emsg("audit target not specified.");
92  else if (!strcmp(Opt.Args[0], "names")) return AuditNames();
93  else if (!strcmp(Opt.Args[0], "space")) return AuditSpace();
94  else Emsg("Unknown audit type - ", Opt.Args[0]);
95 
96 // Nothing we understand
97 //
98  return 4;
99 }
100 
101 /******************************************************************************/
102 /* C h k s u m */
103 /******************************************************************************/
104 
105 const char *XrdFrmAdmin::ChksumHelp =
106 
107 "chksum [opts] {calc | ls | set <csval> | unset | ver[ify] <csval>} fn\n\n"
108 
109 "opts: -f[orce] -pfn -t[ype] <cstype> -v[erbose]";
110 
112 {
113  static XrdOucArgs Spec(&Say, "frm_admin: ", "",
114  "force", 1, "f",
115  "pfn", 3, "p",
116  "type", 1, "t:",
117  "verbose", 1, "v", (const char *)0);
118 
119  static const char *Reqs[] = {"function", "target", 0};
120  const char *csName;
121  char pfnbuf[MAXPATHLEN], *Pfn, *Lfn, *csFunc;
122  int rc = 0;
123 
124 // Check if this is even supported
125 //
126  CksData.Reset();
127  if (!Config.CksMan || !(CksData.Length = Config.CksMan->Size()))
128  {Emsg("Checksum support has not been configured!"); return 8;}
129 
130 // Parse the request
131 //
132  if (!Parse("chksum ", Spec, Reqs)) return 1;
133  csFunc = Opt.Args[0];
134  csName = CksData.Name;
135  if (!*CksData.Name) {Opt.All = 1; CksData.Set(Config.CksMan->Name());}
136 
137 // Check first for set or verify
138 //
139  if (!strcmp (csFunc, "set") || Abbrev(csFunc, "verify", 3))
140  {int n = strlen(Opt.Args[1]);
141  if (n != CksData.Length*2 || !CksData.Set(Opt.Args[1], n))
142  {Emsg("Invalid ", csName, " checksum value - ", Opt.Args[1]);
143  return 4;
144  }
145  if (!(Opt.Args[1] = Spec.getarg()))
146  {Emsg("chksum target not specified."); return 4;}
147  }
148 
149 // Convert the lfn to a pfn if it has not been converted already
150 //
151  Pfn = Lfn = Opt.Args[1];
152  if (Opt.MPType != 'p')
153  {if (!Config.LocalPath(Opt.Args[1], pfnbuf, sizeof(pfnbuf))) return 4;
154  Pfn = pfnbuf;
155  }
156 
157 // Process the request
158 //
159  if (!strcmp(csFunc, "calc"))
160  {if (Opt.Force || Config.CksMan->Get(Pfn, CksData) <= 0)
161  rc = Config.CksMan->Calc(Pfn, CksData, 1);
162  if (rc >= 0) {ChksumPrint(Lfn, rc); return 0;}
163  }
164 
165  else if (!strcmp("ls", csFunc))
166  {if (!(rc = ChksumList(Lfn, Pfn))) return 0;}
167 
168  else if (!strcmp(csFunc, "set"))
169  {if (!(rc = Config.CksMan->Set(Pfn, CksData))) return 0;}
170 
171  else if (!strcmp(csFunc, "unset"))
172  {if (!(rc = Config.CksMan->Del(Pfn, CksData))) return 0;}
173 
174  else if (Abbrev(csFunc, "verify", 3))
175  {if ((rc = Config.CksMan->Ver(Pfn, CksData)) > 0)
176  {Say.Say(CksData.Name, " checksums match for ", Lfn); return 0;}
177  if (!rc)
178  {Say.Say(CksData.Name, " checksums differ for ",Lfn); return 1;}
179  }
180 
181  else {Emsg("Unknown chksum function - ", csFunc); return 4;}
182 
183 // Determine name of the problem
184 //
185  if (rc == -EDOM) Emsg("Invalid ", csName, " checksum length.");
186  else if (rc == -ENOTSUP) Emsg(csName, " checksums are not supported.");
187  else if (rc == -ESRCH) Emsg(csName, " checksum not set for ", Lfn);
188  else if (rc == -ESTALE) Emsg(csName, " checksum no longer valid for ", Lfn);
189  else Emsg(-rc, csFunc, " ", csName, " checksum");
190 
191 // Return failure
192 //
193  return 4;
194 }
195 
196 /******************************************************************************/
197 /* C h k s u m L i s t */
198 /******************************************************************************/
199 
200 int XrdFrmAdmin::ChksumList(const char *Lfn, const char *Pfn)
201 {
202  char Buff[256], *csBP;
203  XrdOucTokenizer csList(Buff);
204  int rc = 0;
205 
206 // If all checksums wanted, then check if we have any
207 //
208  if (Opt.All)
209  {if (!(csBP = Config.CksMan->List(Pfn, Buff, sizeof(Buff))))
210  {Say.Say("No checksums exist for ", Lfn); return 0;}
211  csList.GetLine();
212  }
213 
214 // Print one or all checksums, as needed
215 //
216  do {if (Opt.All)
217  {if ((csBP = csList.GetToken())) CksData.Set(csBP);
218  else break;
219  }
220  if ((rc = Config.CksMan->Get(Pfn, CksData)) <= 0
221  && rc != -ESTALE && rc != -ENOTSUP) return rc;
222  ChksumPrint(Lfn, rc);
223  } while(Opt.All);
224 
225 // All done
226 //
227  return 0;
228 }
229 
230 /******************************************************************************/
231 /* C h k s u m P r i n t */
232 /******************************************************************************/
233 
234 void XrdFrmAdmin::ChksumPrint(const char *Lfn, int rc)
235 {
236  char csBuff[XrdCksData::ValuSize*2+8], Buff[64];
237  static const int bSize = sizeof(Buff)-XrdCksData::NameSize;
238 
239 // Insert the checksum and name in the buffer
240 //
241  *Buff = ' ';
242  strcpy(Buff+1, CksData.Name);
243 
244 // Format long display, if so wanted
245 //
246  if (Opt.Verbose)
247  {time_t csTime = CksData.fmTime + CksData.csTime;
248  strftime(Buff+strlen(Buff), bSize, " %D %T ", localtime(&csTime));
249  }
250 
251 // Grab the checksum value
252 //
253  if (rc == -ENOTSUP) strcpy(csBuff, "Unsupported!");
254  else if (rc < 0 ) strcpy(csBuff, "Invalid!");
255  else CksData.Get(csBuff, sizeof(csBuff));
256 
257 // Print result
258 //
259  Say.Say(csBuff, Buff, (Opt.Verbose ? Lfn : 0));
260 }
261 
262 /******************************************************************************/
263 /* F i n d */
264 /******************************************************************************/
265 
266 const char *XrdFrmAdmin::FindHelp = "find [-r[ecursive]] what ldir [ldir [...]]\n\n"
267 
268 "what: fail[files] | mmap[ped] | nochksum <type> | nolk[files] | pin[ned] | unmig[rated]";
269 
271 {
272  static XrdOucArgs Spec(&Say, "frm_admin: ", "",
273  "recursive", 1, "r", (const char *)0);
274 
275  static const char *Reqs[] = {"type", "target", 0};
276 
277 // Parse the request
278 //
279  if (!Parse("find ", Spec, Reqs)) return 1;
280 
281 // Process the correct find
282 //
283  if (Abbrev(Opt.Args[0], "failfiles", 4)) return FindFail(Spec);
284  else if (Abbrev(Opt.Args[0], "mmapped", 4)) return FindMmap(Spec);
285  else if (Abbrev(Opt.Args[0], "nocs", 4)) return FindNocs(Spec);
286  else if (Abbrev(Opt.Args[0], "nochksum", 8)) return FindNocs(Spec);
287  else if (Abbrev(Opt.Args[0], "pinned", 3)) return FindPins(Spec);
288  else if (Abbrev(Opt.Args[0], "unmigrated",4)) return FindUnmi(Spec);
289 
290 // Nothing we understand
291 //
292  Emsg("Unknown find type - ", Opt.Args[0]);
293  return 4;
294 }
295 
296 /******************************************************************************/
297 /* H e l p */
298 /******************************************************************************/
299 
300 const char *XrdFrmAdmin::HelpHelp =
301 "[help] {audit | chksum | exit | f[ind] | makelf | mark | mmap | mv | pin "
302  "| q[uery] | quit | reloc | rm} ...";
303 
305 {
306  static struct CmdInfo {const char *Name;
307  int minL;
308  int maxL;
309  const char *Help;
310  }
311  CmdTab[] = {{"audit", 5, 5, AuditHelp },
312  {"chksum", 6, 6, ChksumHelp },
313  {"find", 1, 4, FindHelp },
314  {"makelf", 6, 6, MakeLFHelp},
315  {"mark", 4, 4, MarkHelp },
316  {"mmap", 4, 4, MmapHelp },
317  {"mv", 2, 2, MvHelp },
318  {"pin", 3, 3, PinHelp },
319  {"query", 1, 5, QueryHelp },
320  {"reloc", 5, 5, RelocHelp },
321  {"rm", 2, 2, RemoveHelp}
322  };
323  static int CmdNum = sizeof(CmdTab)/sizeof(struct CmdInfo);
324  const char *theHelp = HelpHelp;
325  char *Cmd;
326  int i, n;
327 
328 // Get the next argument (array or string)
329 //
330  if (!ArgS) Cmd = ArgV[0];
331  else {XrdOucTokenizer Tokens(ArgS);
332  if ((Cmd = Tokens.GetLine())) Cmd = Tokens.GetToken();
333  }
334 
335 // Try to give the correct help
336 //
337  if (Cmd)
338  {n = strlen(Cmd);
339  for (i = 0; i < CmdNum; i++)
340  if (n <= CmdTab[i].maxL && n >= CmdTab[i].minL
341  && !strncmp(CmdTab[i].Name, Cmd, n)) break;
342  if (i < CmdNum) {Msg("Usage: ", CmdTab[i].Help); return 0;}
343  }
344  Emsg(0, "Usage: ", theHelp);
345  return 0;
346 }
347 
348 /******************************************************************************/
349 /* M a k e L F */
350 /******************************************************************************/
351 
352 const char *XrdFrmAdmin::MakeLFHelp = "makelf [opts] lspec [lspec [...]]\n\n"
353 
354 "opts: -m[igratable] -o[wner] [usr][:[grp]] -p[urgeable] "
355  "-r[ecursive]\n\n"
356 
357 "lspec: lfn | ldir[*]";
358 
360 {
361  static XrdOucArgs Spec(&Say, "frm_admin: ", "",
362  "migratable", 1, "m",
363  "owner", 1, "o:",
364  "purgeable", 1, "p",
365  "recursive", 1, "r",
366  (const char *)0);
367 
368  static const char *Reqs[] = {"lfn", 0};
369 
370  char *lfn, buff[80], Resp;
371  int ok = 1;
372 
373 // Parse the request
374 //
375  if (!Parse("makelf ", Spec, Reqs)) return 1;
376 
377 // Process all of the files
378 //
379  numFiles = 0;
380  lfn = Opt.Args[0];
381  if (!Opt.MPType) Opt.MPType = 'm';
382  do {Opt.All = VerifyAll(lfn);
383  if ((Resp = VerifyMP("makelf", lfn)) == 'y') ok = mkLock(lfn);
384  } while(Resp != 'a' && ok && (lfn = Spec.getarg()));
385 
386 // All done
387 //
388  if (Resp == 'a' || !ok) Msg("makelf aborted!");
389  sprintf(buff, "%d lock file%s made.", numFiles, (numFiles == 1 ? "" : "s"));
390  Msg(buff);
391  return 0;
392 }
393 
394 /******************************************************************************/
395 /* M a r k */
396 /******************************************************************************/
397 
398 const char *XrdFrmAdmin::MarkHelp = "mark [opts] lspec [lspec [...]]\n\n"
399 
400 "opts: -f[orce] -m[igratable] -p[urgeable] -r[ecursive]\n\n"
401 
402 "lspec: lfn | ldir[/*]";
403 
405 {
406  static XrdOucArgs Spec(&Say, "frm_admin: ", "",
407  "force", 1, "F",
408  "migratable", 1, "m",
409  "purgeable", 1, "p",
410  "recursive", 1, "r",
411  (const char *)0);
412 
413  static const char *Reqs[] = {"lfn", 0};
414 
415  char *lfn, buff[80], Resp;
416  int ok = 1;
417 
418 // Parse the request
419 //
420  if (!Parse("mark ", Spec, Reqs)) return 1;
421 
422 // Process all of the files
423 //
424  numFiles = 0;
425  lfn = Opt.Args[0];
426  if (!Opt.MPType) Opt.MPType = 'm';
427  do {Opt.All = VerifyAll(lfn);
428  if ((Resp = VerifyMP("mark", lfn)) == 'y') ok = mkMark(lfn);
429  } while(Resp != 'a' && ok && (lfn = Spec.getarg()));
430 
431 // All done
432 //
433  if (Resp == 'a' || !ok) Msg("mark aborted!");
434  sprintf(buff, "%d file%s marked %s.", numFiles, (numFiles == 1 ? "" : "s"),
435  (Opt.MPType == 'm' ? "migratable" : "purgeable"));
436  Msg(buff);
437  return 0;
438 }
439 
440 /******************************************************************************/
441 /* M m a p */
442 /******************************************************************************/
443 
444 const char *XrdFrmAdmin::MmapHelp = "mmap [opts] lspec [lspec [...]]\n\n"
445 
446 "opts: -k[eep] -l[ock] -o[ff] -r[ecursive]\n\n"
447 
448 "lspec: lfn | ldir[/*]";
449 
451 {
452  static XrdOucArgs Spec(&Say, "frm_admin: ", "",
453  "keep", 1, "K",
454  "lock", 1, "f",
455  "off", 1, "l",
456  "recursive", 1, "r",
457  (const char *)0);
458 
459  static const char *Reqs[] = {"lfn", 0};
460 
461  char *lfn, itbuff[80], Resp;
462  int ok = 1;
463 
464 // Parse the request
465 //
466  if (!Parse("pin ", Spec, Reqs)) return 1;
467 
468 // Process all of the files
469 //
470  numFiles = 0;
471  lfn = Opt.Args[0];
472  Opt.MPType = 'p';
473  do {Opt.All = VerifyAll(lfn);
474  if ((Resp = VerifyMP("mmap", lfn)) == 'y') ok = mkMmap(lfn);
475  } while(Resp != 'a' && ok && (lfn = Spec.getarg()));
476 
477 // All done
478 //
479  if (Resp == 'a' || !ok) Msg("mmap aborted!");
480  sprintf(itbuff,"%d mmap%s processed.",numFiles,(numFiles==1?"":"s"));
481  Msg(itbuff);
482  return 0;
483 }
484 
485 /******************************************************************************/
486 /* M v */
487 /******************************************************************************/
488 
489 const char *XrdFrmAdmin::MvHelp = "mv oldlfn newlfn";
490 
492 {
493  static XrdOucArgs Spec(&Say, "frm_admin: ", "", (const char *)0);
494 
495  static const char *Reqs[] = {"oldlfn", "newlfn", 0};
496 
497  int rc;
498 
499 // Parse the request and do it
500 //
501  if (!Parse("mv ", Spec, Reqs)) return 1;
502 
503 // Simply invoke the reloc function in the underlying FS
504 //
505  if ((rc = Config.ossFS->Rename(Opt.Args[0], Opt.Args[1])))
506  Emsg(-rc, "rename ", Opt.Args[0]);
507  else Msg(Opt.Args[0], " renamed to ", Opt.Args[1]);
508  return rc != 0;
509 }
510 
511 /******************************************************************************/
512 /* P i n */
513 /******************************************************************************/
514 
515 const char *XrdFrmAdmin::PinHelp = "pin [opts] lspec [lspec [...]]\n\n"
516 
517 "opts: -k[eep] <time> -r[ecursive]\n\n"
518 
519 "time: [+]<n>[d|h|m|s] | mm/dd/[yy]yy | forever\n\n"
520 
521 "lspec: lfn | ldir[/*]";
522 
524 {
525  static XrdOucArgs Spec(&Say, "frm_admin: ", "",
526  "keep", 1, "k:",
527  "recursive", 1, "r",
528  (const char *)0);
529 
530  static const char *Reqs[] = {"lfn", 0};
531 
532  const char *Act;
533  char *lfn, itbuff[80], Resp;
534  int ok = 1;
535 
536 // Parse the request
537 //
538  if (!Parse("pin ", Spec, Reqs)) return 1;
539 
540 // Process all of the files
541 //
542  numFiles = 0;
543  lfn = Opt.Args[0];
544  Opt.MPType = 'p';
545  do {Opt.All = VerifyAll(lfn);
546  if ((Resp = VerifyMP("pin", lfn)) == 'y') ok = mkPin(lfn);
547  } while(Resp != 'a' && ok && (lfn = Spec.getarg()));
548 
549 // All done
550 //
551  Act = (Opt.KeepTime || Opt.ktAlways ? "" : "un");
552  if (Resp == 'a' || !ok) Msg("pin aborted!");
553  sprintf(itbuff,"%d %spin%s processed.",numFiles,Act,(numFiles==1?"":"s"));
554  Msg(itbuff);
555  return 0;
556 }
557 
558 /******************************************************************************/
559 /* Q u e r y */
560 /******************************************************************************/
561 
562 const char *XrdFrmAdmin::QueryHelp = "\n"
563  "query pfn lspec [lspec [...]]\n"
564  "query rfn lspec [lspec [...]]\n"
565  "query space [[-r[ecursive]] lspec [...]]\n"
566  "query usage [name]\n"
567  "query xfrq [name] [vars]\n\n"
568 
569  "lspec: lfn | ldir[*]";
570 
572 {
573  static XrdOucArgs Spec(&Say, "frm_admin: ", "", (const char *)0);
574 
575  static const char *Reqs[] = {"type", 0};
576  static struct CmdInfo {const char *Name;
577  int (XrdFrmAdmin::*Method)(XrdOucArgs &Spec);
578  }
579  CmdTab[] = {{"pfn", &XrdFrmAdmin::QueryPfn},
580  {"rfn", &XrdFrmAdmin::QueryRfn},
581  {"space", &XrdFrmAdmin::QuerySpace},
582  {"usage", &XrdFrmAdmin::QueryUsage},
583  {"xfrq", &XrdFrmAdmin::QueryXfrQ}
584  };
585  static int CmdNum = sizeof(CmdTab)/sizeof(struct CmdInfo);
586 
587  int i;
588 
589 // Parse the request
590 //
591  if (!Parse("query ", Spec, Reqs)) return 1;
592 
593 // Find the command
594 //
595  for (i = 0; i < CmdNum; i++)
596  if (!strcmp(CmdTab[i].Name, Opt.Args[0])) break;
597 
598 // See if we found the command
599 //
600  if (i >= CmdNum)
601  {Emsg("Invalid query type - ", Opt.Args[0]);
602  return 1;
603  }
604 
605 // Perform required function
606 //
607  return (*this.*CmdTab[i].Method)(Spec);
608 }
609 
610 /******************************************************************************/
611 /* R e l o c */
612 /******************************************************************************/
613 
614 const char *XrdFrmAdmin::RelocHelp = "reloc lfn {cgroup[:path]}";
615 
617 {
618  static XrdOucArgs Spec(&Say, "frm_admin: ", "", (const char *)0);
619 
620  static const char *Reqs[] = {"lfn", "target", 0};
621 
622  int rc;
623 
624 // Parse the request and do it
625 //
626  if (!Parse("reloc ", Spec, Reqs)) return 1;
627 
628 // Simply invoke the reloc function in the underlying FS
629 //
630  if ((rc = Config.ossFS->Reloc("admin", Opt.Args[0], Opt.Args[1])))
631  Emsg(-rc, "reloc ", Opt.Args[0]);
632  else Msg(Opt.Args[0], " relocated to space ", Opt.Args[1]);
633  return rc != 0;
634 }
635 
636 /******************************************************************************/
637 /* R e m o v e */
638 /******************************************************************************/
639 
640 const char *XrdFrmAdmin::RemoveHelp = "rm [opts] lspec [lspec [...]]\n\n"
641 
642 "opts: -e[cho] -f[orce] -n[otify] -r[ecursive]\n\n"
643 
644 "lspec: lfn | ldir[*]";
645 
647 {
648  static XrdOucArgs Spec(&Say, "frm_admin: ", "",
649  "echo", 1, "E",
650  "force", 1, "F",
651  "recursive", 1, "r",
652  (const char *)0);
653 
654  static const char *Reqs[] = {"lfn", 0};
655 
656  const char *Txt = "";
657  char buff[80];
658  int rc = 0, aOK = 1;
659 
660 // Parse the request
661 //
662  if (!Parse("rm ", Spec, Reqs)) return 1;
663 
664 // Do some initialization
665 //
666  numDirs = numFiles = numProb = 0;
667 
668 // Preform action
669 //
670  do {Opt.All = VerifyAll(Opt.Args[0]);
671  if ((rc = Unlink(Opt.Args[0])) < 0) aOK = 0;
672  } while(rc && (Opt.Args[0] = Spec.getarg()));
673 
674  if (!rc) {Txt = "rm aborted; only "; finalRC = 4;}
675  else if (numProb || !aOK) {Txt = "rm incomplete; only "; finalRC = 4;}
676 
677 // Compose message
678 //
679  sprintf(buff, "%s%d %s and %d %s deleted.", Txt,
680  numFiles, (numFiles != 1 ? "files" : "file"),
681  numDirs, (numDirs != 1 ? "directories" : "directory"));
682  Msg(buff);
683  return 0;
684 }
685 
686 /******************************************************************************/
687 /* s e t A r g s */
688 /******************************************************************************/
689 
690 void XrdFrmAdmin::setArgs(int argc, char **argv)
691 {
692  ArgC = argc; ArgV = argv; ArgS = 0;
693 }
694 
695 
696 void XrdFrmAdmin::setArgs(char *args)
697 {
698  ArgC = 0; ArgV = 0; ArgS = args;
699 }
700 
701 /******************************************************************************/
702 /* x e q A r g s */
703 /******************************************************************************/
704 
705 int XrdFrmAdmin::xeqArgs(char *Cmd)
706 {
707  static struct CmdInfo {const char *Name;
708  int minLen;
709  int maxLen;
710  int (XrdFrmAdmin::*Method)();
711  }
712  CmdTab[] = {{"audit", 5, 5, &XrdFrmAdmin::Audit},
713  {"chksum", 6, 6, &XrdFrmAdmin::Chksum},
714  {"exit", 4, 4, &XrdFrmAdmin::Quit},
715  {"find", 1, 4, &XrdFrmAdmin::Find},
716  {"help", 1, 4, &XrdFrmAdmin::Help},
717  {"makelf", 6, 6, &XrdFrmAdmin::MakeLF},
718  {"mark", 1, 4, &XrdFrmAdmin::Mark},
719  {"mmap", 1, 4, &XrdFrmAdmin::Mmap},
720  {"mv", 2, 2, &XrdFrmAdmin::Mv},
721  {"pin", 3, 3, &XrdFrmAdmin::Pin},
722  {"query", 1, 5, &XrdFrmAdmin::Query},
723  {"quit", 4, 4, &XrdFrmAdmin::Quit},
724  {"reloc", 5, 5, &XrdFrmAdmin::Reloc},
725  {"rm", 2, 2, &XrdFrmAdmin::Remove}
726  };
727  static int CmdNum = sizeof(CmdTab)/sizeof(struct CmdInfo);
728 
729  int i, n = strlen(Cmd);
730 
731 // Find the command
732 //
733  for (i = 0; i < CmdNum; i++)
734  if (n >= CmdTab[i].minLen && n <= CmdTab[i].maxLen
735  && !strncmp(CmdTab[i].Name, Cmd, n)) break;
736 
737 // See if we found the command
738 //
739  if (i >= CmdNum)
740  {Emsg("Invalid command - ", Cmd);
741  return 1;
742  }
743 
744 // Perform required function
745 //
746  return (*this.*CmdTab[i].Method)();
747 }
748 
749 /******************************************************************************/
750 /* P r i v a t e M e t h o d s */
751 /******************************************************************************/
752 /******************************************************************************/
753 /* A b b r e v */
754 /******************************************************************************/
755 
756 int XrdFrmAdmin::Abbrev(const char *Spec, const char *Word, int minLen)
757 {
758  int n = strlen(Spec);
759  if (n > int(strlen(Word)) || n < minLen) return 0;
760  return !strncmp(Spec, Word, n);
761 }
762 
763 /******************************************************************************/
764 /* C o n f i g P r o x y */
765 /******************************************************************************/
766 
767 void XrdFrmAdmin::ConfigProxy()
768 {
769  static struct {const char *qFN; int qID;} qVec[] =
770  {{"getfQ.0", XrdFrcProxy::opGet},
771  {"migrQ.0", XrdFrcProxy::opMig},
772  {"pstgQ.0", XrdFrcProxy::opStg},
773  {"putfQ.0", XrdFrcProxy::opPut},
774  {0, 0}};
775  struct stat Stat;
776  char qBuff[1032], *qBase;
777  int i, qTypes = 0;
778 
779 // If we've been here before, return
780 //
781  if (frmProxy || frmProxz) return;
782 
783 // Construct the directory where the queue files reside
784 //
785  strcpy(qBuff, Config.QPath);
786  qBase = XrdFrcUtils::makeQDir(qBuff, -1);
787  strcpy(qBuff, qBase); free(qBase); qBase = qBuff+strlen(qBuff);
788 
789 // Since routines will create queue files we want to only look at queue files
790 // that actually exist. While may be none.
791 //
792  for (i = 0; qVec[i].qFN; i++)
793  {strcpy(qBase, qVec[i].qFN);
794  if (!stat(qBuff, &Stat)) qTypes |= qVec[i].qID;
795  }
796 
797 // Check if we actually found any queues create them, otherwise complain.
798 //
799  if (qTypes)
800  {frmProxy = new XrdFrcProxy(Say.logger(),Config.myInst,Trace.What != 0);
801  frmProxz = frmProxy->Init(qTypes, 0, -1, Config.QPath);
802  } else {
803  *qBase = 0; frmProxz = 1;
804  Emsg("No transfer queues found in ", qBuff);
805  }
806 }
807 
808 /******************************************************************************/
809 /* E m s g */
810 /******************************************************************************/
811 
812 void XrdFrmAdmin::Emsg(const char *tx1, const char *tx2, const char *tx3,
813  const char *tx4, const char *tx5)
814 {
815  Say.Say("frm_admin: ", tx1, tx2, tx3, tx4, tx5);
816  finalRC = 4;
817 }
818 
819 void XrdFrmAdmin::Emsg(int ec, const char *tx2, const char *tx3,
820  const char *tx4, const char *tx5)
821 {
822  char buff[128];
823 
824  if (!ec) Say.Say(tx2, tx3, tx4, tx5);
825  else {strcpy(buff+2, XrdSysE2T(ec));
826  buff[0] = ';'; buff[1] = ' ';
827  Say.Say("frm_admin: Unable to ", tx2, tx3, tx4, tx5, buff);
828  }
829  finalRC = 4;
830 }
831 
832 /******************************************************************************/
833 /* M s g */
834 /******************************************************************************/
835 
836 void XrdFrmAdmin::Msg(const char *tx1, const char *tx2, const char *tx3,
837  const char *tx4, const char *tx5)
838 {
839  Say.Say(tx1, tx2, tx3, tx4, tx5);
840 }
841 
842 /******************************************************************************/
843 /* P a r s e */
844 /******************************************************************************/
845 
846 int XrdFrmAdmin::Parse(const char *What, XrdOucArgs &Spec, const char **Reqs)
847 {
848  static const int MaxArgs = sizeof(Opt.Args)/sizeof(char *);
849  char theOpt;
850  int i;
851 
852 // Clear the option area
853 //
854  memset(&Opt, 0, sizeof(Opt));
855  Opt.Uid = static_cast<uid_t>(-1); Opt.Gid = static_cast<gid_t>(-1);
856 
857 // Set the Arguments
858 //
859  if (ArgS) Spec.Set(ArgS);
860  else Spec.Set(ArgC, ArgV);
861 
862 // Now process all the options
863 //
864  while((theOpt = Spec.getopt()) != (char)-1)
865  {switch(theOpt)
866  {case 'A': Opt.All = 1; break;
867  case 'e': Opt.Erase = 1; break;
868  case 'E': Opt.Echo = 1; break;
869  case 'f': Opt.Fix = 1; break;
870  case 'F': Opt.Force = 1; break;
871  case 'k': Opt.Keep = 1;
872  if (!ParseKeep(What, Spec.argval)) return 0;
873  break;
874  case 'K': Opt.Keep = 1; break; // No argument
875  case 'l': Opt.Local = 1; break;
876  case 'm': Opt.MPType ='m';break;
877  case 'o': if (!ParseOwner(What, Spec.argval)) return 0;
878  break;
879  case 'p': Opt.MPType ='p';break;
880  case 'r': Opt.Recurse = 1; break;
881  case 't': if (!ParseType(What, Spec.argval)) return 0;
882  break;
883  case 'v': Opt.Verbose = 1; break;
884  case '?': return 0;
885  default: Emsg("Internal error mapping options!");
886  return 0;
887  }
888  }
889 
890 // Check if we need additional arguments (up to three)
891 //
892  for (i = 0; i < MaxArgs && Reqs[i]; i++)
893  if (!(Opt.Args[i] = Spec.getarg()))
894  {Emsg(What, Reqs[i], " not specified."); return 0;}
895 
896 // All done
897 //
898  return 1;
899 }
900 
901 /******************************************************************************/
902 /* P a r s e K e e p */
903 /******************************************************************************/
904 
905 int XrdFrmAdmin::ParseKeep(const char *What, const char *kTime)
906 {
907  struct tm myTM;
908  char *eP;
909  int theSec;
910 
911 // Initialize the values
912 //
913  Opt.ktAlways = 0;
914  Opt.KeepTime = 0;
915  Opt.ktIdle = 0;
916 
917 // Check for forever and unused
918 //
919  if (!strcmp(kTime, "forever")) {Opt.ktAlways = 1; return 1;}
920 
921 // if no slashes then this is number of days
922 //
923  if (!index(kTime, '/'))
924  {if (*kTime == '+') {Opt.ktIdle = 1; kTime++;}
925  if (XrdOuca2x::a2tm(Say,"keep time", kTime, &theSec)) return 0;
926  if (Opt.ktIdle || !theSec) {Opt.KeepTime = theSec; Opt.ktIdle = 1;}
927  else Opt.KeepTime = static_cast<time_t>(theSec)+time(0);
928  return 1;
929  }
930 
931 // Do a date conversion
932 //
933  eP = strptime(kTime, "%D", &myTM);
934  if (*eP) {Emsg("Invalid ", What, "keep date - ", kTime); return 0;}
935  Opt.KeepTime = mktime(&myTM);
936  return 1;
937 }
938 
939 /******************************************************************************/
940 /* P a r s e O w n e r */
941 /******************************************************************************/
942 
943 int XrdFrmAdmin::ParseOwner(const char *What, char *Uname)
944 {
945  struct group *grP;
946  struct passwd *pwP;
947  char *Gname = 0;
948  int Gnum, Unum;
949 
950 // Set defaults
951 //
952  Opt.Uid = Config.myUid;
953  Opt.Gid = Config.myGid;
954 
955 // Separate the uid from the gid
956 //
957  if (*Uname == ':') {Gname = Uname+1; Uname = 0;}
958  else if ((Gname = index(Uname, ':'))) *Gname++ = '\0';
959  if (Gname && *Gname == '\0') Gname = 0;
960 
961 // Process username
962 //
963  if (Uname)
964  {if (*Uname >= '0' && *Uname <= '9')
965  {if (XrdOuca2x::a2i(Say,"uid",Uname, &Unum)) return 0;
966  Opt.Uid = Unum;
967  }
968  else {if (!(pwP = getpwnam(Uname)))
969  {Emsg("Invalid user name - ", Uname); return 0;}
970  Opt.Uid = pwP->pw_uid; Opt.Gid = pwP->pw_gid;
971  }
972  }
973 
974 // Process groupname
975 //
976  if (Gname)
977  {if (*Gname >= '0' && *Gname <= '9')
978  {if (XrdOuca2x::a2i(Say, "gid", Gname, &Gnum)) return 0;
979  Opt.Gid = Gnum;
980  }
981  else {if (!(grP = getgrnam(Gname)))
982  {Emsg("Invalid group name - ", Gname); return 0;}
983  Opt.Gid = grP->gr_gid;
984  }
985  }
986 
987 // All done
988 //
989  return 1;
990 }
991 
992 /******************************************************************************/
993 /* P a r s e S p a c e */
994 /******************************************************************************/
995 
996 XrdOucTList *XrdFrmAdmin::ParseSpace(char *Space, char **Path)
997 {
998  XrdOucTList *pP;
999 
1000 // Check if we should process all paths in the space or just one
1001 //
1002  if ((*Path = index(Space, ':'))) {**Path = '\0'; (*Path)++;}
1003 
1004 // Find the proper space entry
1005 //
1006  if (!(pP = Config.Space(Space, *Path))) Emsg(Space, " space not found.");
1007  else if (!(pP->text))
1008  {Emsg(Space, " space does not contain ", *Path); pP = 0;}
1009  return pP;
1010 }
1011 
1012 /******************************************************************************/
1013 /* P a r s e T y p e */
1014 /******************************************************************************/
1015 
1016 int XrdFrmAdmin::ParseType(const char *What, char *Type)
1017 {
1018 
1019 // Set checksum type and check for all
1020 //
1021  if (!CksData.Set(Type)) {Emsg("Invalid type - ", Type); return 0;}
1022  return 1;
1023 }
1024 
1025 /******************************************************************************/
1026 /* V e r i f y A l l */
1027 /******************************************************************************/
1028 
1029 int XrdFrmAdmin::VerifyAll(char *path)
1030 {
1031  char *Slash = rindex(path, '/');
1032 
1033  if (!Slash || strcmp(Slash, "/*")) return 0;
1034  *Slash = '\0';
1035  return 1;
1036 }
1037 
1038 /******************************************************************************/
1039 /* V e r i f y M P */
1040 /******************************************************************************/
1041 
1042 char XrdFrmAdmin::VerifyMP(const char *func, const char *path)
1043 {
1044  unsigned long long Popts = 0;
1045  const char *msg = 0;
1046  int rc;
1047 
1048 // Get the export attributes for this path
1049 //
1050  if ((rc = Config.ossFS->StatXP(path, Popts)))
1051  {Emsg(rc, func, " ", path); return 0;}
1052 
1053 // Resolve attributes to the options in effect
1054 //
1055  if (Opt.MPType == 'm')
1056  {if (!(Popts & XRDEXP_MIG)) msg = " is not migratable";}
1057  else if (Opt.MPType == 'p')
1058  {if (!(Popts & XRDEXP_STAGE)) msg = " is not stageable"; }
1059  else if (Popts & XRDEXP_MIG) Opt.MPType = 'm';
1060  else if (Popts & XRDEXP_STAGE) Opt.MPType = 'p';
1061 
1062  if (msg && !Opt.Force)
1063  return XrdFrcUtils::Ask('n', path, msg, "; continue?");
1064  return 'y';
1065 }
struct stat Stat
Definition: XrdCks.cc:49
#define XRDEXP_STAGE
Definition: XrdOucExport.hh:52
#define XRDEXP_MIG
Definition: XrdOucExport.hh:54
int stat(const char *path, struct stat *buf)
int Help
XrdOucString Path
const char * XrdSysE2T(int errcode)
Definition: XrdSysE2T.cc:104
static const int ValuSize
Definition: XrdCksData.hh:42
static const int NameSize
Definition: XrdCksData.hh:41
XrdOss * ossFS
static const int opPut
Definition: XrdFrcProxy.hh:50
static const int opGet
Definition: XrdFrcProxy.hh:49
static const int opMig
Definition: XrdFrcProxy.hh:51
static const int opStg
Definition: XrdFrcProxy.hh:52
static char Ask(char dflt, const char *Msg1, const char *Msg2="", const char *Msg3="")
Definition: XrdFrcUtils.cc:56
static char * makeQDir(const char *Path, int Mode)
Definition: XrdFrcUtils.cc:127
void setArgs(int argc, char **argv)
Definition: XrdFrmAdmin.cc:690
int xeqArgs(char *Cmd)
Definition: XrdFrmAdmin.cc:705
virtual int StatXP(const char *path, unsigned long long &attr, XrdOucEnv *envP=0)
Definition: XrdOss.cc:137
virtual int Reloc(const char *tident, const char *path, const char *cgName, const char *anchor=0)
Definition: XrdOss.cc:76
virtual int Rename(const char *oPath, const char *nPath, XrdOucEnv *oEnvP=0, XrdOucEnv *nEnvP=0)=0
char getopt()
Definition: XrdOucArgs.cc:151
char * getarg()
Definition: XrdOucArgs.cc:136
void Set(char *arglist)
Definition: XrdOucArgs.cc:236
char * argval
Definition: XrdOucArgs.hh:102
char * text
Definition: XrdOucTList.hh:46
char * GetToken(char **rest=0, int lowcase=0)
static int a2i(XrdSysError &, const char *emsg, const char *item, int *val, int minv=-1, int maxv=-1)
Definition: XrdOuca2x.cc:45
static int a2tm(XrdSysError &, const char *emsg, const char *item, int *val, int minv=-1, int maxv=-1)
Definition: XrdOuca2x.cc:288
void Say(const char *text1, const char *text2=0, const char *txt3=0, const char *text4=0, const char *text5=0, const char *txt6=0)
Definition: XrdSysError.cc:141
XrdSysLogger * logger(XrdSysLogger *lp=0)
Definition: XrdSysError.hh:141
XRootDStatus Unlink(Davix::DavPosix &davix_client, const std::string &url, uint16_t timeout)
XrdCmsConfig Config
XrdOucTrace Trace
XrdSysError Say