XRootD
Loading...
Searching...
No Matches
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
43#include "XrdFrc/XrdFrcProxy.hh"
44#include "XrdFrc/XrdFrcTrace.hh"
45#include "XrdFrc/XrdFrcUtils.hh"
46#include "XrdFrm/XrdFrmAdmin.hh"
48#include "XrdOss/XrdOss.hh"
49#include "XrdOuc/XrdOuca2x.hh"
50#include "XrdOuc/XrdOucArgs.hh"
52#include "XrdOuc/XrdOucTList.hh"
54#include "XrdSys/XrdSysE2T.hh"
56#include "XrdSys/XrdSysTimer.hh"
57
58using namespace XrdFrc;
59using namespace XrdFrm;
60
61/******************************************************************************/
62/* A u d i t */
63/******************************************************************************/
64
65const 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
105const 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
200int 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
234void 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
266const 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
300const 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
352const 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
398const 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
444const 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
489const 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
515const 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
562const 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
614const 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
640const 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
690void XrdFrmAdmin::setArgs(int argc, char **argv)
691{
692 ArgC = argc; ArgV = argv; ArgS = 0;
693}
694
695
696void 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
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
756int 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
767void 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
812void 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
819void 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
836void 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
846int 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
905int 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
943int 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
996XrdOucTList *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
1016int 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
1029int 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
1042char 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
XrdOucPup XrdCmsParser::Pup & Say
#define XRDEXP_STAGE
#define XRDEXP_MIG
#define stat(a, b)
Definition XrdPosix.hh:101
int Help
XrdOucString Path
const char * XrdSysE2T(int errcode)
Definition XrdSysE2T.cc:104
static const int ValuSize
Definition XrdCksData.hh:42
int Set(const char *csName)
Definition XrdCksData.hh:81
void Reset()
int Get(char *Buff, int Blen)
Definition XrdCksData.hh:69
static const int NameSize
Definition XrdCksData.hh:41
char Name[NameSize]
Definition XrdCksData.hh:44
virtual int Ver(const char *Xfn, XrdCksData &Cks)=0
virtual const char * Name(int seqNum=0)=0
virtual int Get(const char *Xfn, XrdCksData &Cks)=0
virtual int Del(const char *Xfn, XrdCksData &Cks)=0
virtual char * List(const char *Xfn, char *Buff, int Blen, char Sep=' ')=0
virtual int Size(const char *Name=0)=0
virtual int Set(const char *Xfn, XrdCksData &Cks, int myTime=0)=0
virtual int Calc(const char *Xfn, XrdCksData &Cks, int doSet=1)=0
static const int opPut
int Init(int opX, const char *aPath, int aMode, const char *qPath=0)
static const int opGet
static const int opMig
static const int opStg
static char Ask(char dflt, const char *Msg1, const char *Msg2="", const char *Msg3="")
static char * makeQDir(const char *Path, int Mode)
void setArgs(int argc, char **argv)
int xeqArgs(char *Cmd)
XrdOucTList * Space(const char *Name, const char *Path=0)
const char * myInst
XrdCks * CksMan
XrdOss * ossFS
int LocalPath(const char *oldp, char *newp, int newpsz)
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()
char * getarg()
void Set(char *arglist)
char * argval
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
XrdOucTrace Trace
XrdFrmConfig Config