38 #include <sys/param.h>
39 #include <sys/types.h>
65 const char *XrdFrmAdmin::AuditHelp =
67 "audit [opts] {names ldir | space name[:pdir] | usage [name]}\n\n"
69 "opts: -fix -f[orce] -m[igratable] -p[urgeable] -r[ecursive]";
81 static const char *Reqs[] = {
"type", 0};
85 if (!Parse(
"audit ", Spec, Reqs))
return 1;
86 Opt.Args[1] = Spec.
getarg();
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]);
105 const char *XrdFrmAdmin::ChksumHelp =
107 "chksum [opts] {calc | ls | set <csval> | unset | ver[ify] <csval>} fn\n\n"
109 "opts: -f[orce] -pfn -t[ype] <cstype> -v[erbose]";
117 "verbose", 1,
"v", (
const char *)0);
119 static const char *Reqs[] = {
"function",
"target", 0};
121 char pfnbuf[MAXPATHLEN], *Pfn, *Lfn, *csFunc;
127 if (!
Config.CksMan || !(CksData.Length =
Config.CksMan->Size()))
128 {Emsg(
"Checksum support has not been configured!");
return 8;}
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());}
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]);
145 if (!(Opt.Args[1] = Spec.
getarg()))
146 {Emsg(
"chksum target not specified.");
return 4;}
151 Pfn = Lfn = Opt.Args[1];
152 if (Opt.MPType !=
'p')
153 {
if (!
Config.LocalPath(Opt.Args[1], pfnbuf,
sizeof(pfnbuf)))
return 4;
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;}
165 else if (!strcmp(
"ls", csFunc))
166 {
if (!(rc = ChksumList(Lfn, Pfn)))
return 0;}
168 else if (!strcmp(csFunc,
"set"))
169 {
if (!(rc =
Config.CksMan->Set(Pfn, CksData)))
return 0;}
171 else if (!strcmp(csFunc,
"unset"))
172 {
if (!(rc =
Config.CksMan->Del(Pfn, CksData)))
return 0;}
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;}
178 {
Say.
Say(CksData.Name,
" checksums differ for ",Lfn);
return 1;}
181 else {Emsg(
"Unknown chksum function - ", csFunc);
return 4;}
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");
200 int XrdFrmAdmin::ChksumList(
const char *Lfn,
const char *Pfn)
202 char Buff[256], *csBP;
209 {
if (!(csBP =
Config.CksMan->List(Pfn, Buff,
sizeof(Buff))))
210 {
Say.
Say(
"No checksums exist for ", Lfn);
return 0;}
217 {
if ((csBP = csList.GetToken())) CksData.Set(csBP);
220 if ((rc =
Config.CksMan->Get(Pfn, CksData)) <= 0
221 && rc != -ESTALE && rc != -ENOTSUP)
return rc;
222 ChksumPrint(Lfn, rc);
234 void XrdFrmAdmin::ChksumPrint(
const char *Lfn,
int rc)
242 strcpy(Buff+1, CksData.Name);
247 {time_t csTime = CksData.fmTime + CksData.csTime;
248 strftime(Buff+strlen(Buff), bSize,
" %D %T ", localtime(&csTime));
253 if (rc == -ENOTSUP) strcpy(csBuff,
"Unsupported!");
254 else if (rc < 0 ) strcpy(csBuff,
"Invalid!");
255 else CksData.Get(csBuff,
sizeof(csBuff));
259 Say.
Say(csBuff, Buff, (Opt.Verbose ? Lfn : 0));
266 const char *XrdFrmAdmin::FindHelp =
"find [-r[ecursive]] what ldir [ldir [...]]\n\n"
268 "what: fail[files] | mmap[ped] | nochksum <type> | nolk[files] | pin[ned] | unmig[rated]";
273 "recursive", 1,
"r", (
const char *)0);
275 static const char *Reqs[] = {
"type",
"target", 0};
279 if (!Parse(
"find ", Spec, Reqs))
return 1;
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);
292 Emsg(
"Unknown find type - ", Opt.Args[0]);
300 const char *XrdFrmAdmin::HelpHelp =
301 "[help] {audit | chksum | exit | f[ind] | makelf | mark | mmap | mv | pin "
302 "| q[uery] | quit | reloc | rm} ...";
306 static struct CmdInfo {
const char *Name;
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}
323 static int CmdNum =
sizeof(CmdTab)/
sizeof(
struct CmdInfo);
324 const char *theHelp = HelpHelp;
330 if (!ArgS) Cmd = ArgV[0];
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;}
344 Emsg(0,
"Usage: ", theHelp);
352 const char *XrdFrmAdmin::MakeLFHelp =
"makelf [opts] lspec [lspec [...]]\n\n"
354 "opts: -m[igratable] -o[wner] [usr][:[grp]] -p[urgeable] "
357 "lspec: lfn | ldir[*]";
362 "migratable", 1,
"m",
368 static const char *Reqs[] = {
"lfn", 0};
370 char *lfn, buff[80], Resp;
375 if (!Parse(
"makelf ", Spec, Reqs))
return 1;
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()));
388 if (Resp ==
'a' || !ok) Msg(
"makelf aborted!");
389 sprintf(buff,
"%d lock file%s made.", numFiles, (numFiles == 1 ?
"" :
"s"));
398 const char *XrdFrmAdmin::MarkHelp =
"mark [opts] lspec [lspec [...]]\n\n"
400 "opts: -f[orce] -m[igratable] -p[urgeable] -r[ecursive]\n\n"
402 "lspec: lfn | ldir[/*]";
408 "migratable", 1,
"m",
413 static const char *Reqs[] = {
"lfn", 0};
415 char *lfn, buff[80], Resp;
420 if (!Parse(
"mark ", Spec, Reqs))
return 1;
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()));
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"));
444 const char *XrdFrmAdmin::MmapHelp =
"mmap [opts] lspec [lspec [...]]\n\n"
446 "opts: -k[eep] -l[ock] -o[ff] -r[ecursive]\n\n"
448 "lspec: lfn | ldir[/*]";
459 static const char *Reqs[] = {
"lfn", 0};
461 char *lfn, itbuff[80], Resp;
466 if (!Parse(
"pin ", Spec, Reqs))
return 1;
473 do {Opt.All = VerifyAll(lfn);
474 if ((Resp = VerifyMP(
"mmap", lfn)) ==
'y') ok = mkMmap(lfn);
475 }
while(Resp !=
'a' && ok && (lfn = Spec.
getarg()));
479 if (Resp ==
'a' || !ok) Msg(
"mmap aborted!");
480 sprintf(itbuff,
"%d mmap%s processed.",numFiles,(numFiles==1?
"":
"s"));
489 const char *XrdFrmAdmin::MvHelp =
"mv oldlfn newlfn";
493 static XrdOucArgs Spec(&
Say,
"frm_admin: ",
"", (
const char *)0);
495 static const char *Reqs[] = {
"oldlfn",
"newlfn", 0};
501 if (!Parse(
"mv ", Spec, Reqs))
return 1;
506 Emsg(-rc,
"rename ", Opt.Args[0]);
507 else Msg(Opt.Args[0],
" renamed to ", Opt.Args[1]);
515 const char *XrdFrmAdmin::PinHelp =
"pin [opts] lspec [lspec [...]]\n\n"
517 "opts: -k[eep] <time> -r[ecursive]\n\n"
519 "time: [+]<n>[d|h|m|s] | mm/dd/[yy]yy | forever\n\n"
521 "lspec: lfn | ldir[/*]";
530 static const char *Reqs[] = {
"lfn", 0};
533 char *lfn, itbuff[80], Resp;
538 if (!Parse(
"pin ", Spec, Reqs))
return 1;
545 do {Opt.All = VerifyAll(lfn);
546 if ((Resp = VerifyMP(
"pin", lfn)) ==
'y') ok = mkPin(lfn);
547 }
while(Resp !=
'a' && ok && (lfn = Spec.
getarg()));
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"));
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"
569 "lspec: lfn | ldir[*]";
573 static XrdOucArgs Spec(&
Say,
"frm_admin: ",
"", (
const char *)0);
575 static const char *Reqs[] = {
"type", 0};
576 static struct CmdInfo {
const char *Name;
579 CmdTab[] = {{
"pfn", &XrdFrmAdmin::QueryPfn},
580 {
"rfn", &XrdFrmAdmin::QueryRfn},
581 {
"space", &XrdFrmAdmin::QuerySpace},
582 {
"usage", &XrdFrmAdmin::QueryUsage},
583 {
"xfrq", &XrdFrmAdmin::QueryXfrQ}
585 static int CmdNum =
sizeof(CmdTab)/
sizeof(
struct CmdInfo);
591 if (!Parse(
"query ", Spec, Reqs))
return 1;
595 for (i = 0; i < CmdNum; i++)
596 if (!strcmp(CmdTab[i].Name, Opt.Args[0]))
break;
601 {Emsg(
"Invalid query type - ", Opt.Args[0]);
607 return (*this.*CmdTab[i].Method)(Spec);
614 const char *XrdFrmAdmin::RelocHelp =
"reloc lfn {cgroup[:path]}";
618 static XrdOucArgs Spec(&
Say,
"frm_admin: ",
"", (
const char *)0);
620 static const char *Reqs[] = {
"lfn",
"target", 0};
626 if (!Parse(
"reloc ", Spec, Reqs))
return 1;
631 Emsg(-rc,
"reloc ", Opt.Args[0]);
632 else Msg(Opt.Args[0],
" relocated to space ", Opt.Args[1]);
640 const char *XrdFrmAdmin::RemoveHelp =
"rm [opts] lspec [lspec [...]]\n\n"
642 "opts: -e[cho] -f[orce] -n[otify] -r[ecursive]\n\n"
644 "lspec: lfn | ldir[*]";
654 static const char *Reqs[] = {
"lfn", 0};
656 const char *Txt =
"";
662 if (!Parse(
"rm ", Spec, Reqs))
return 1;
666 numDirs = numFiles = numProb = 0;
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()));
674 if (!rc) {Txt =
"rm aborted; only "; finalRC = 4;}
675 else if (numProb || !aOK) {Txt =
"rm incomplete; only "; finalRC = 4;}
679 sprintf(buff,
"%s%d %s and %d %s deleted.", Txt,
680 numFiles, (numFiles != 1 ?
"files" :
"file"),
681 numDirs, (numDirs != 1 ?
"directories" :
"directory"));
692 ArgC = argc; ArgV = argv; ArgS = 0;
698 ArgC = 0; ArgV = 0; ArgS = args;
707 static struct CmdInfo {
const char *Name;
727 static int CmdNum =
sizeof(CmdTab)/
sizeof(
struct CmdInfo);
729 int i, n = strlen(Cmd);
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;
740 {Emsg(
"Invalid command - ", Cmd);
746 return (*this.*CmdTab[i].Method)();
756 int XrdFrmAdmin::Abbrev(
const char *Spec,
const char *Word,
int minLen)
758 int n = strlen(Spec);
759 if (n >
int(strlen(Word)) || n < minLen)
return 0;
760 return !strncmp(Spec, Word, n);
767 void XrdFrmAdmin::ConfigProxy()
769 static struct {
const char *qFN;
int qID;} qVec[] =
776 char qBuff[1032], *qBase;
781 if (frmProxy || frmProxz)
return;
785 strcpy(qBuff,
Config.QPath);
787 strcpy(qBuff, qBase); free(qBase); qBase = qBuff+strlen(qBuff);
792 for (i = 0; qVec[i].qFN; i++)
793 {strcpy(qBase, qVec[i].qFN);
794 if (!
stat(qBuff, &
Stat)) qTypes |= qVec[i].qID;
801 frmProxz = frmProxy->Init(qTypes, 0, -1,
Config.QPath);
803 *qBase = 0; frmProxz = 1;
804 Emsg(
"No transfer queues found in ", qBuff);
812 void XrdFrmAdmin::Emsg(
const char *tx1,
const char *tx2,
const char *tx3,
813 const char *tx4,
const char *tx5)
815 Say.
Say(
"frm_admin: ", tx1, tx2, tx3, tx4, tx5);
819 void XrdFrmAdmin::Emsg(
int ec,
const char *tx2,
const char *tx3,
820 const char *tx4,
const char *tx5)
824 if (!
ec)
Say.
Say(tx2, tx3, tx4, tx5);
826 buff[0] =
';'; buff[1] =
' ';
827 Say.
Say(
"frm_admin: Unable to ", tx2, tx3, tx4, tx5, buff);
836 void XrdFrmAdmin::Msg(
const char *tx1,
const char *tx2,
const char *tx3,
837 const char *tx4,
const char *tx5)
839 Say.
Say(tx1, tx2, tx3, tx4, tx5);
846 int XrdFrmAdmin::Parse(
const char *What,
XrdOucArgs &Spec,
const char **Reqs)
848 static const int MaxArgs =
sizeof(Opt.Args)/
sizeof(
char *);
854 memset(&Opt, 0,
sizeof(Opt));
855 Opt.Uid =
static_cast<uid_t
>(-1); Opt.Gid =
static_cast<gid_t
>(-1);
859 if (ArgS) Spec.
Set(ArgS);
860 else Spec.
Set(ArgC, ArgV);
864 while((theOpt = Spec.
getopt()) != (
char)-1)
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;
874 case 'K': Opt.Keep = 1;
break;
875 case 'l': Opt.Local = 1;
break;
876 case 'm': Opt.MPType =
'm';
break;
877 case 'o':
if (!ParseOwner(What, Spec.
argval))
return 0;
879 case 'p': Opt.MPType =
'p';
break;
880 case 'r': Opt.Recurse = 1;
break;
881 case 't':
if (!ParseType(What, Spec.
argval))
return 0;
883 case 'v': Opt.Verbose = 1;
break;
885 default: Emsg(
"Internal error mapping options!");
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;}
905 int XrdFrmAdmin::ParseKeep(
const char *What,
const char *kTime)
919 if (!strcmp(kTime,
"forever")) {Opt.ktAlways = 1;
return 1;}
923 if (!index(kTime,
'/'))
924 {
if (*kTime ==
'+') {Opt.ktIdle = 1; kTime++;}
926 if (Opt.ktIdle || !theSec) {Opt.KeepTime = theSec; Opt.ktIdle = 1;}
927 else Opt.KeepTime =
static_cast<time_t
>(theSec)+time(0);
933 eP = strptime(kTime,
"%D", &myTM);
934 if (*eP) {Emsg(
"Invalid ", What,
"keep date - ", kTime);
return 0;}
935 Opt.KeepTime = mktime(&myTM);
943 int XrdFrmAdmin::ParseOwner(
const char *What,
char *Uname)
957 if (*Uname ==
':') {Gname = Uname+1; Uname = 0;}
958 else if ((Gname = index(Uname,
':'))) *Gname++ =
'\0';
959 if (Gname && *Gname ==
'\0') Gname = 0;
964 {
if (*Uname >=
'0' && *Uname <=
'9')
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;
977 {
if (*Gname >=
'0' && *Gname <=
'9')
981 else {
if (!(grP = getgrnam(Gname)))
982 {Emsg(
"Invalid group name - ", Gname);
return 0;}
983 Opt.Gid = grP->gr_gid;
1002 if ((*
Path = index(Space,
':'))) {**
Path =
'\0'; (*Path)++;}
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;}
1016 int XrdFrmAdmin::ParseType(
const char *What,
char *Type)
1021 if (!CksData.Set(Type)) {Emsg(
"Invalid type - ", Type);
return 0;}
1029 int XrdFrmAdmin::VerifyAll(
char *path)
1031 char *Slash = rindex(path,
'/');
1033 if (!Slash || strcmp(Slash,
"/*"))
return 0;
1042 char XrdFrmAdmin::VerifyMP(
const char *func,
const char *path)
1044 unsigned long long Popts = 0;
1045 const char *msg = 0;
1051 {Emsg(rc, func,
" ", path);
return 0;}
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';
1062 if (msg && !Opt.Force)
int stat(const char *path, struct stat *buf)
const char * XrdSysE2T(int errcode)
static const int ValuSize
static const int NameSize
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)
virtual int StatXP(const char *path, unsigned long long &attr, XrdOucEnv *envP=0)
virtual int Reloc(const char *tident, const char *path, const char *cgName, const char *anchor=0)
virtual int Rename(const char *oPath, const char *nPath, XrdOucEnv *oEnvP=0, XrdOucEnv *nEnvP=0)=0
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)
static int a2tm(XrdSysError &, const char *emsg, const char *item, int *val, int minv=-1, int maxv=-1)
void Say(const char *text1, const char *text2=0, const char *txt3=0, const char *text4=0, const char *text5=0, const char *txt6=0)
XrdSysLogger * logger(XrdSysLogger *lp=0)
XRootDStatus Unlink(Davix::DavPosix &davix_client, const std::string &url, uint16_t timeout)