/******************************************************************************/ /* */ /* X r d C o m m a n d L i n e . c c */ /* */ /* Author: Fabrizio Furano (INFN Padova, 2005) */ /* Rewritten by Elvin Sindrilaru */ /* with mods from Lukasz Janyst (CERN, 2010) */ /* */ /* This file is part of the XRootD software suite. */ /* */ /* XRootD is free software: you can redistribute it and/or modify it under */ /* the terms of the GNU Lesser General Public License as published by the */ /* Free Software Foundation, either version 3 of the License, or (at your */ /* option) any later version. */ /* */ /* XRootD is distributed in the hope that it will be useful, but WITHOUT */ /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */ /* License for more details. */ /* */ /* You should have received a copy of the GNU Lesser General Public License */ /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */ /* COPYING (GPL license). If not, see . */ /* */ /* The copyright holder's institutional names and contributor's names may not */ /* be used to endorse or promote products derived from this software without */ /* specific prior written permission of the institution or contributor. */ /******************************************************************************/ //------------------------------------------------------------------------------ // A command line tool for xrootd environments. The executable normally // is named xrd. //------------------------------------------------------------------------------ #include "XrdClient/XrdClientUrlInfo.hh" #include "XrdClient/XrdClient.hh" #include "XrdClient/XrdClientAdmin.hh" #include "XrdClient/XrdClientDebug.hh" #include "XrdClient/XrdClientEnv.hh" #include "XrdOuc/XrdOucTokenizer.hh" #include "XrdSys/XrdSysHeaders.hh" #include #include #include #include #include #include #include #ifdef HAVE_READLINE #include #include #endif #define XRDCLI_VERSION "(C) 2004-2010 by the Xrootd group. Xrootd version: " XrdVSTRING //------------------------------------------------------------------------------ // Some globals //------------------------------------------------------------------------------ char *opaqueinfo = 0; // opaque info to be added to urls kXR_unt16 xrd_wr_flags = kXR_async | kXR_mkpath | kXR_open_updt | kXR_new; char *initialhost = 0; XrdClient *genclient = 0; XrdClientAdmin *genadmin = 0; XrdOucString currentpath = "/"; XrdOucString cmdline_cmd; //------------------------------------------------------------------------------ // Interrupt signal handler //------------------------------------------------------------------------------ void CtrlCHandler(int sig) { std::cerr << std::endl; std::cerr << "Please use 'exit' to terminate this program." << std::endl; } //------------------------------------------------------------------------------ // Commandline help message //------------------------------------------------------------------------------ void PrintUsage() { std::cerr << "usage: xrd [host]"; std::cerr << "[-DSparmname stringvalue] ... [-DIparmname intvalue] "; std::cerr << "[-O] [command]" << std::endl; std::cerr << " -DSparmname stringvalue : "; std::cerr << "override the default value of an internal XrdClient setting "; std::cerr << "(of string type)" << std::endl; std::cerr << " -DIparmname intvalue : "; std::cerr << "override the default value of an internal XrdClient setting "; std::cerr << "(of int type)" << std::endl; std::cerr << " -O : adds some opaque information to any used "; std::cerr << "xrootd url" << std::endl; std::cerr << " -h : this help screen" << std::endl; std::cerr <GetCurrentUrl().Host; s << ":" << genadmin->GetCurrentUrl().Port; s << "/" << currentpath; } s << "> "; } //------------------------------------------------------------------------------ // Out own primitive implementation of GNU readline //------------------------------------------------------------------------------ #ifndef HAVE_READLINE char *readline(const char *prompt) { std::cout << prompt << std::flush; std::string input; std::getline( std::cin, input ); if( !cin.good() ) return 0; char *linebuf = (char *)malloc( input.size()+1 ); strncpy( linebuf, input.c_str(), input.size()+1 ); return linebuf; } #endif //------------------------------------------------------------------------------ // Print help //------------------------------------------------------------------------------ void PrintHelp() { std::cout << std::endl << XRDCLI_VERSION << std::endl << std::endl; std::cout << "Usage: xrd [-O] [-DS stringvalue] "; std::cout << "[-DI integervalue] [host[:port]] [batchcommand]"; std::cout << std::endl << std::endl; std::cout << "List of available commands:" << std::endl << std::endl; std::cout << std::left; std::cout << std::setw(55) << "cat [xrdcp parameters]"; std::cout << "Output a file on standard output using xrdcp. "; std::cout << "can be a root:// URL." << std::endl; std::cout << std::setw(55) << "cd "; std::cout << "Change the current directory. Note: no existence check is "; std::cout << "performed." << std::endl; std::cout << std::setw(55) << "chmod "; std::cout << "Modify file permissions." << std::endl; std::cout << std::setw(55) << "connect [hostname[:port]]"; std::cout << "Connect to the specified host." << std::endl; std::cout << std::setw(55) << "cp [xrdcp parameters]"; std::cout << "Copies a file using xrdcp. are always "; std::cout << "relative to the" << std::endl; std::cout << std::setw(55) << " " << "current remote path. Also, they "; std::cout << "can be root:// URLs specifying any other host." << std::endl; std::cout << std::setw(55) << "dirlist [dirname]"; std::cout << "Get the requested directory listing." << std::endl; std::cout << std::setw(55) << "dirlistrec [dirname]"; std::cout << "Get the requested recursive directory listing."; std::cout << std::endl; std::cout << std::setw(55) << "envputint "; std::cout << "Put an integer in the internal environment." << std::endl; std::cout << std::setw(55) << "envputstring "; std::cout << "Put a string in the internal environment." << std::endl; std::cout << std::setw(55) << "exit"; std::cout << "Exits from the program." << std::endl; std::cout << std::setw(55) << "help"; std::cout << "This help screen." << std::endl; std::cout << std::setw(55) << "stat [fileordirname]"; std::cout << "Get info about the given file or directory path."; std::cout << std::endl; std::cout << std::setw(55) << "statvfs [vfilesystempath]"; std::cout << "Get info about a virtual file system." << std::endl; std::cout << std::setw(55) << "existfile "; std::cout << "Test if the specified file exists." << std::endl; std::cout << std::setw(55) << "existdir "; std::cout << "Test if the specified directory exists." << std::endl; std::cout << std::setw(55) << "getchecksum "; std::cout << "Get the checksum for the specified file." << std::endl; std::cout << std::setw(55) << "isfileonline "; std::cout << "Test if the specified file is online." << std::endl; std::cout << std::setw(55) << "locatesingle "; std::cout << "Give a location of the given file in the currently "; std::cout << "connected cluster." << std::endl; std::cout << std::setw(55) << " " << "if writable is true only a "; std::cout << "writable location is searched" << std::endl; std::cout << std::setw(55) << " " << "but, if no writable locations "; std::cout << "are found, the result is negative but may" << std::endl; std::cout << std::setw(55) << " " << "propose a non writable one."; std::cout << std::endl; std::cout << std::setw(55) << "locateall "; std::cout << "Give all the locations of the given file in the currently"; std::cout << "connected cluster." << std::endl; std::cout << std::setw(55) << "mv "; std::cout << "Move filename1 to filename2 locally to the same server."; std::cout << std::endl; std::cout << std::setw(55) << "mkdir [user] [group] [other]"; std::cout << "Creates a directory." << std::endl; std::cout << std::setw(55) << "rm "; std::cout << "Remove a file." << std::endl; std::cout << std::setw(55) << "rmdir "; std::cout << "Removes a directory." << std::endl; std::cout << std::setw(55) << "prepare "; std::cout << "Stage a file in." << std::endl; std::cout << std::setw(55) << "query "; std::cout << "Obtain server information." << std::endl; std::cout << std::setw(55) << "queryspace "; std::cout << "Obtain space information." << std::endl; std::cout << std::setw(55) << "truncate "; std::cout << "Truncate a file." << std::endl; std::cout << std::endl << "For further information, please read the "; std::cout << "xrootd protocol documentation." << std::endl; std::cout << std::endl; } //------------------------------------------------------------------------------ // Check the answer of the server //------------------------------------------------------------------------------ bool CheckAnswer(XrdClientAbs *gencli) { if (!gencli->LastServerResp()) return false; switch (gencli->LastServerResp()->status) { case kXR_ok: return true; case kXR_error: std::cout << "Error " << gencli->LastServerError()->errnum; std::cout << ": " << gencli->LastServerError()->errmsg << std::endl; std::cout << std::endl; return false; default: std::cout << "Server response: " << gencli->LastServerResp()->status; std::cout << std::endl; return true; } } //------------------------------------------------------------------------------ // Print the output from locate //------------------------------------------------------------------------------ void PrintLocateInfo(XrdClientLocate_Info &loc) { std::cout << "InfoType: "; switch (loc.Infotype) { case XrdClientLocate_Info::kXrdcLocNone: std::cout << "none" << std::endl; break; case XrdClientLocate_Info::kXrdcLocDataServer: std::cout << "kXrdcLocDataServer" << std::endl; break; case XrdClientLocate_Info::kXrdcLocDataServerPending: std::cout << "kXrdcLocDataServerPending" << std::endl; break; case XrdClientLocate_Info::kXrdcLocManager: std::cout << "kXrdcLocManager" << std::endl; break; case XrdClientLocate_Info::kXrdcLocManagerPending: std::cout << "kXrdcLocManagerPending" << std::endl; break; default: std::cout << "Invalid Infotype" << std::endl; } std::cout << "CanWrite: "; if (loc.CanWrite) std::cout << "true" << std::endl; else std::cout << "false" << std::endl; std::cout << "Location: '" << loc.Location << "'" << std::endl; } //------------------------------------------------------------------------------ // process the "EXISTDIR" command //------------------------------------------------------------------------------ void executeExistDir(XrdOucTokenizer &tkzer) { int retval = 0; if (!genadmin) { std::cout << "Not connected to any server." << std::endl << std::endl; retval = 1; } if (!retval) { char *fname = tkzer.GetToken(0, 0); XrdOucString pathname; if (fname) { if (fname[0] == '/') pathname = fname; else pathname = currentpath + "/" + fname; } else pathname = currentpath; // Try to issue the request vecBool vb; vecString vs; vs.Push_back(pathname); genadmin->ExistDirs(vs, vb); // Check the answer if (vb[0] && (vb.GetSize() >= 1)) std::cout << "The directory exists." << std::endl; else std::cout << "Directory not found." << std::endl; std::cout << std::endl; return; } } //------------------------------------------------------------------------------ // process the "CD" command //------------------------------------------------------------------------------ void executeCd(XrdOucTokenizer &tkzer) { char *parmname = tkzer.GetToken(0, 0); XrdOucString pathname; if (!genadmin) { std::cout << "Not connected to any server." << std::endl << std::endl; return; } if (!parmname || !strlen(parmname)) { std::cout << "A directory name is needed." << std::endl << std::endl; } else { // Quite trivial directory processing if (!strcmp(parmname, "..")) { if (currentpath == "/") return; int pos = currentpath.rfind('/'); if (pos != STR_NPOS) currentpath.erase(pos); if (!currentpath.length()) currentpath = "/"; return; } else if (!strcmp(parmname, ".")) { return; } if (!currentpath.length() || (currentpath[currentpath.length()-1] != '/')) currentpath += "/"; XrdOucString tmpPath; if (parmname[0] == '/') tmpPath = parmname; else tmpPath = currentpath + parmname; // Verify if tmpPath really exists vecBool vb; vecString vs; vs.Push_back(tmpPath); genadmin->ExistDirs(vs, vb); // Now check the answer if (CheckAnswer(genadmin)) currentpath = tmpPath; else std::cout << "The directory does not exist." << std::endl << std::endl; return; } } //------------------------------------------------------------------------------ // process the "ENVPUTINT" command //------------------------------------------------------------------------------ void executeEnvPutInt(XrdOucTokenizer &tkzer) { char *parmname = tkzer.GetToken(0, 0), *val = tkzer.GetToken(0, 1); if (!parmname || !val) { std::cout << "Please provide command parameters:envputint "; std::cout << "" << std::endl << std::endl; } else { EnvPutInt(parmname, atoi(val)); DebugSetLevel(EnvGetLong(NAME_DEBUG)); } return; } //------------------------------------------------------------------------------ // process the "ENVPUTSTRING" command //------------------------------------------------------------------------------ void executeEnvPutString(XrdOucTokenizer &tkzer) { char *parmname = tkzer.GetToken(0, 0), *val = tkzer.GetToken(0, 1); if (!parmname || !val) { std::cout << "Please provide command parameters:envputstring "; std::cout << "" << std::endl << std::endl; } else EnvPutString(parmname, val); return; } //------------------------------------------------------------------------------ // process the "HELP" command //------------------------------------------------------------------------------ void executeHelp(XrdOucTokenizer &) { PrintHelp(); } //------------------------------------------------------------------------------ // process the "CONNECT" command //------------------------------------------------------------------------------ void executeConnect(XrdOucTokenizer &tkzer) { int retval = 0; char *host = initialhost; // If no host was given, then pretend one if (!host) { host = tkzer.GetToken(0, 1); if (!host || !strlen(host)) { std::cout << "A hostname is needed to connect somewhere."; std::cout << std::endl << std::endl; retval = 1; } } if (!retval) { // Init the instance if (genadmin) delete genadmin; XrdOucString h(host); h = "root://" + h; h += "//dummy"; genadmin = new XrdClientAdmin(h.c_str()); // Then connect if (!genadmin->Connect()) { delete genadmin; genadmin = 0; } } } //------------------------------------------------------------------------------ // process the "DIRLISTREC" command //------------------------------------------------------------------------------ void executeDirListRec(XrdOucTokenizer &tkzer) { XrdClientVector pathq; int retval = 0; if (!genadmin) { std::cout << "Not connected to any server." << std::endl << std::endl; retval = 1; } if (!retval) { char *dirname = tkzer.GetToken(0, 0); XrdOucString path; if (dirname) { if (dirname[0] == '/') path = dirname; else { if ((currentpath.length() > 0) && (currentpath[currentpath.length()-1] != '/')) path = currentpath + "/" + dirname; else path = currentpath + dirname; } } else path = currentpath; if (!path.length()) { std::cout << "The current path is an empty string. Assuming '/'."; std::cout << std::endl << std::endl; path = '/'; } // Initialize the queue with this path pathq.Push_back(path); while (pathq.GetSize() > 0) { XrdOucString pathtodo = pathq.Pop_back(); // Now try to issue the request XrdClientVector nfo; genadmin->DirList(pathtodo.c_str(), nfo, true); // Now check the answer if (!CheckAnswer(genadmin)) { retval = 1; std::cout << "In server "; std::cout << genadmin->GetCurrentUrl().HostWPort; std::cout << " or in some of its child nodes." << std::endl; break; } for (int i = 0; i < nfo.GetSize(); i++) { if ((nfo[i].flags & kXR_isDir) && (nfo[i].flags & kXR_readable) && (nfo[i].flags & kXR_xset)) { // The path has not to be pushed if it's already present // This may happen if several servers have the same path bool foundpath = false; for (int ii = 0; ii < pathq.GetSize(); ii++) { if (nfo[i].fullpath == pathq[ii]) { foundpath = true; break; } } if (!foundpath) pathq.Push_back(nfo[i].fullpath); else // If the path is already present in the queue // then it was already printed as well. continue; } char ts[256]; strcpy(ts, "n/a"); struct tm *t = gmtime(&nfo[i].modtime); strftime(ts, 255, "%F %T", t); char cflgs[16]; memset(cflgs, 0, 16); if (nfo[i].flags & kXR_isDir) strcat(cflgs, "d"); else strcat(cflgs, "-"); if (nfo[i].flags & kXR_readable) strcat(cflgs, "r"); else strcat(cflgs, "-"); if (nfo[i].flags & kXR_writable) strcat(cflgs, "w"); else strcat(cflgs, "-"); if (nfo[i].flags & kXR_xset) strcat(cflgs, "x"); else strcat(cflgs, "-"); printf( "%s(%03ld) %12lld %s %s\n", cflgs, nfo[i].flags, nfo[i].size, ts, nfo[i].fullpath.c_str()); } } } std::cout << std::endl; return; } //------------------------------------------------------------------------------ // process the "DIRLIST" command //------------------------------------------------------------------------------ void executeDirList(XrdOucTokenizer &tkzer) { int retval = 0; if (!genadmin) { std::cout << "Not connected to any server." << std::endl << std::endl; retval = 1; } if (!retval) { char *dirname = tkzer.GetToken(0, 0); XrdOucString path; if (dirname) { if (dirname[0] == '/') path = dirname; else { if ((currentpath.length() > 0) && (currentpath[currentpath.length()-1] != '/')) path = currentpath + "/" + dirname; else path = currentpath + dirname; } } else path = currentpath; if (!path.length()) { std::cout << "The current path is an empty string. Assuming '/'."; std::cout << std::endl << std::endl; path = '/'; } // Now try to issue the request XrdClientVector nfo; genadmin->DirList(path.c_str(), nfo, true); // Now check the answer if (!CheckAnswer(genadmin)) { retval = 1; std::cout << "In server " << genadmin->GetCurrentUrl().HostWPort; std::cout << " or in some of its child nodes." << std::endl; //nfo.Clear(); } for (int i = 0; i < nfo.GetSize(); i++) { char ts[256]; strcpy(ts, "n/a"); struct tm *t = gmtime(&nfo[i].modtime); strftime(ts, 255, "%F %T", t); char cflgs[16]; memset(cflgs, 0, 16); if (nfo[i].flags & kXR_isDir) strcat(cflgs, "d"); else strcat(cflgs, "-"); if (nfo[i].flags & kXR_readable) strcat(cflgs, "r"); else strcat(cflgs, "-"); if (nfo[i].flags & kXR_writable) strcat(cflgs, "w"); else strcat(cflgs, "-"); if (nfo[i].flags & kXR_xset) strcat(cflgs, "x"); else strcat(cflgs, "-"); printf( "%s(%03ld) %12lld %s %s\n", cflgs, nfo[i].flags, nfo[i].size, ts, nfo[i].fullpath.c_str()); } std::cout << std::endl; } return; } //------------------------------------------------------------------------------ // process the "LOCATESINGLE" command //------------------------------------------------------------------------------ void executeLocateSingle(XrdOucTokenizer &tkzer) { int retval = 0; if (!genadmin) { std::cout << "Not connected to any server." <Locate((kXR_char *)pathname.c_str(), loc, wrt); if (!r) std::cout << "No matching files were found." < loc; bool r; r = genadmin->Locate((kXR_char *)pathname.c_str(), loc); if (!r) std::cout << "No matching files were found." <Stat(pathname.c_str(), id, size, flags, modtime); // Now check the answer if (!CheckAnswer(genadmin)) { std::cout << "The command returned an error."; std::cout << std::endl << std::endl; } else { std::cout << "Id: " << id << " Size: " << size << " Flags: "; std::cout << flags << " Modtime: " << modtime << std::endl; std::cout <Stat_vfs(pathname.c_str(), rwservers, rwfree, rwutil, stagingservers, stagingfree, stagingutil); // Now check the answer if (!CheckAnswer(genadmin)) { std::cout << "The command returned an error."; std::cout << std::endl <ExistFiles(vs, vb); // Now check the answer if (!CheckAnswer(genadmin)) retval = 1; if (vb[0] && (vb.GetSize() >= 1)) std::cout << "The file exists." << std::endl; else std::cout << "File not found." << std::endl; std::cout <GetChecksum((kXR_char *)pathname.c_str(), &ans); // Now check the answer if (!CheckAnswer(genadmin)) { std::cout << "The command returned an error."; std::cout << std::endl << std::endl; } else { std::cout << "Checksum: " << ans << std::endl; free(ans); std::cout << std::endl; } } else { std::cout << "Please provide command parameter: getchecksum "; std::cout << "" << std::endl << std::endl; } } } //------------------------------------------------------------------------------ // process the "ISFILEONLINE" command //------------------------------------------------------------------------------ void executeIsFileOnline(XrdOucTokenizer &tkzer) { int retval = 0; if (!genadmin) { std::cout << "Not connected to any server." << std::endl << std::endl; retval = 1; } if (!retval) { char *fname = tkzer.GetToken(0, 0); XrdOucString pathname; if (fname) { if (fname[0] == '/') pathname = fname; else pathname = currentpath + "/" + fname; // Now try to issue the request vecBool vb; vecString vs; vs.Push_back(pathname); genadmin->IsFileOnline(vs, vb); // Now check the answer if (!CheckAnswer(genadmin)) { std::cout << "The command returned an error."; std::cout << std::endl << std::endl; } else { if (vb[0] && (vb.GetSize() >= 1)) std::cout << "The file is online." << std::endl; else std::cout << "The file is not online." << std::endl; std::cout <" << std::endl << std::endl; } } } //------------------------------------------------------------------------------ // process the "MV" command //------------------------------------------------------------------------------ void executeMv(XrdOucTokenizer &tkzer) { int retval = 0; if (!genadmin) { std::cout << "Not connected to any server." << std::endl << std::endl; retval = 1; } if (!retval) { char *fname1 = tkzer.GetToken(0, 0); char *fname2 = tkzer.GetToken(0, 0); XrdOucString pathname1, pathname2; if (!fname1 || !fname2) { std::cout << "Please provide command parameteres: mv "; std::cout << "" <Mv(pathname1.c_str(), pathname2.c_str()); // Now check the answer if (!CheckAnswer(genadmin)) std::cout << "The command returned an error." < "; std::cout << "[ ]" << std::endl << std::endl; } else { int user = 0, group = 0, other = 0; if (userc) user = atoi(userc); if (groupc) group = atoi(groupc); if (otherc) other = atoi(otherc); XrdOucString pathname1; if (fname1[0] == '/') pathname1 = fname1; else pathname1 = currentpath + "/" + fname1; // Now try to issue the request genadmin->Mkdir(pathname1.c_str(), user, group, other); // Now check the answer if (!CheckAnswer(genadmin)) { std::cout << "The command returned an error."; std::cout << std::endl << std::endl; } } } } //------------------------------------------------------------------------------ // process the "CHMOD" command //------------------------------------------------------------------------------ void executeChmod(XrdOucTokenizer &tkzer) { int retval = 0; if (!genadmin) { std::cout << "Not connected to any server." < "; std::cout << " " << std::endl << std::endl; } else { int user = 0, group = 0, other = 0; if (userc) user = atoi(userc); if (groupc) group = atoi(groupc); if (otherc) other = atoi(otherc); XrdOucString pathname1; if (fname1[0] == '/') pathname1 = fname1; else pathname1 = currentpath + "/" + fname1; // Now try to issue the request genadmin->Chmod(pathname1.c_str(), user, group, other); // Now check the answer if (!CheckAnswer(genadmin)) std::cout << "The command returned an error." <Truncate(pathname1.c_str(), len); // Now check the answer if (!CheckAnswer(genadmin)) std::cout << "The command returned an error." < "; std::cout << "" << std::endl << std::endl; return; } } } //------------------------------------------------------------------------------ // process the "RM" command //------------------------------------------------------------------------------ void executeRm(XrdOucTokenizer &tkzer) { int retval = 0; if (!genadmin) { std::cout << "Not connected to any server." <Rm(pathname.c_str()); // Now check the answer if (!CheckAnswer(genadmin)) { std::cout << "The command returned an error."; std::cout << std::endl << std::endl; } } else { std::cout << "Please provide command parameter: rm "; std::cout << std::endl << std::endl; } } } //------------------------------------------------------------------------------ // process the "RMDIR" command //------------------------------------------------------------------------------ void executeRmDir(XrdOucTokenizer &tkzer) { int retval = 0; if (!genadmin) { std::cout << "Not connected to any server." <Rmdir(pathname.c_str()); // Now check the answer if (!CheckAnswer(genadmin)) { std::cout << "The command returned an error."; std::cout << std::endl << std::endl; } } else { std::cout << "Please provide command parameter: rmdir "; std::cout << std::endl << std::endl; } } } //------------------------------------------------------------------------------ // process the "PREPARE" command //------------------------------------------------------------------------------ void executePrepare(XrdOucTokenizer &tkzer) { int retval = 0; if (!genadmin) { std::cout << "Not connected to any server." << std::endl << std::endl; retval = 1; } if (!retval) { char *fname1 = tkzer.GetToken(0, 0); char *optsc = tkzer.GetToken(0, 0); char *prioc = tkzer.GetToken(0, 0); if (!fname1) { std::cout << "Please provide command parameters: prepare "; std::cout << " "; std::cout << std::endl << std::endl; } else { int opts = 0, prio = 0; if (optsc) opts = atoi(optsc); if (prioc) prio = atoi(prioc); XrdOucString pathname1; if (fname1[0] == '/') pathname1 = fname1; else pathname1 = currentpath + "/" + fname1; // Now try to issue the request vecString vs; vs.Push_back(pathname1); genadmin->Prepare(vs, (kXR_char)opts, (kXR_char)prio); // Now check the answer if (!CheckAnswer(genadmin)) { std::cout << "The command returned an error."; std::cout << std::endl << std::endl; } } } } //------------------------------------------------------------------------------ // process the "CAT" command //------------------------------------------------------------------------------ void executeCat(XrdOucTokenizer &tkzer) { int retval = 0; if (!genadmin) { std::cout << "Not connected to any server." << std::endl << std::endl; retval = 1; } if (!retval) { char *fname1 = tkzer.GetToken(0, 0); char *tk; XrdOucString pars; while ((tk = tkzer.GetToken(0, 0))) { pars += " "; pars += tk; } XrdOucString pathname1; if (fname1) { if ( (strstr(fname1, "root://") == fname1) || (strstr(fname1, "xroot://") == fname1) ) pathname1 = fname1; else if (fname1[0] == '/') { pathname1 = "root://" + genadmin->GetCurrentUrl().HostWPort; pathname1 += "/"; pathname1 += fname1; } else { pathname1 = "root://" + genadmin->GetCurrentUrl().HostWPort; pathname1 += "/"; pathname1 += currentpath; pathname1 += "/"; pathname1 += fname1; } } else std::cout << "Missing parameter." <GetCurrentUrl().HostWPort; pathname1 += "/"; pathname1 += fname1; } else { pathname1 = "root://" + genadmin->GetCurrentUrl().HostWPort; pathname1 += "/"; pathname1 += currentpath; pathname1 += "/"; pathname1 += fname1; } if (fname2) { if ( (strstr(fname2, "root://") == fname2) || (strstr(fname2, "xroot://") == fname2) ) pathname2 = fname2; else if (fname2[0] == '/') { pathname2 = "root://" + genadmin->GetCurrentUrl().HostWPort; pathname2 += "/"; pathname2 += fname2; } else { pathname2 = "root://" + genadmin->GetCurrentUrl().HostWPort; pathname2 += "/"; pathname2 += currentpath; pathname2 += "/"; pathname2 += fname2; } } else { std::cout << "Please provide command parameters: cp "; std::cout << " []" < "; std::cout << " []" < " << std::endl << std::endl; } else { const kXR_char *args = (const kXR_char *)tkzer.GetToken(0, 0); kXR_char *Resp = 0; genadmin->Query(atoi(reqcode), args, &Resp, 0); // Now check the answer if (!CheckAnswer(genadmin)) retval = 1; std::cout << Resp << std::endl << std::endl; free( Resp ); } } } //------------------------------------------------------------------------------ // process the "QUERYSPACE" command //------------------------------------------------------------------------------ void executeQuerySpace(XrdOucTokenizer &tkzer) { int retval = 0; if (!genadmin) { std::cout << "Not connected to any server." <" << std::endl << std::endl; } else { long long totspace; long long totfree; long long totused; long long largestchunk; genadmin->GetSpaceInfo(ns, totspace, totfree, totused, largestchunk); // Now check the answer if (!CheckAnswer(genadmin)) retval = 1; std::cout << "Disk space approximations (MB):" << std::endl; std::cout << "Total : " << totspace/(1024*1024) << std::endl; std::cout << "Free : " << totfree/(1024*1024) << std::endl; std::cout << "Used : " << totused/(1024*1024) << std::endl; std::cout << "Largest chunk : " << largestchunk/(1024*1024); std::cout << std::endl << std::endl; } } } //------------------------------------------------------------------------------ // process the "DEGBUG" command //------------------------------------------------------------------------------ void executeDebug(XrdOucTokenizer &tkzer) { int level = -2, retval = 0; string delim = "="; if (!genadmin) { std::cout << "Not connected to any server." <" << std::endl << std::endl; } //------------------------------------------------------------------------------ // Function lookup //------------------------------------------------------------------------------ typedef void (*CommandCallback)(XrdOucTokenizer &); struct LookupItem { const char *name; CommandCallback callback; }; LookupItem lookupTable[] = { {"cd", executeCd }, {"envputint", executeEnvPutInt }, {"envputstring", executeEnvPutString}, {"help", executeHelp }, {"connect", executeConnect }, {"dirlistrec", executeDirListRec }, {"dirlist", executeDirList }, {"ls", executeDirList }, {"locatesingle", executeLocateSingle}, {"locateall", executeLocateAll }, {"stat", executeStat }, {"statvfs", executeStatvfs }, {"existfile", executeExistFile }, {"existdir", executeExistDir }, {"getchecksum", executeGetCheckSum }, {"isfileonline", executeIsFileOnline}, {"mv", executeMv }, {"mkdir", executeMkDir }, {"chmod", executeChmod }, {"truncate", executeTruncate }, {"rm", executeRm }, {"rmdir", executeRmDir }, {"prepare", executePrepare }, {"cat", executeCat }, {"cp", executeCp }, {"query", executeQuery }, {"queryspace", executeQuerySpace }, {"debug", executeDebug }, {0, 0 } }; CommandCallback lookup( char *command ) { LookupItem *it = lookupTable; while( it->name != 0 ) { if( strcmp( command, it->name ) == 0 ) return it->callback; ++it; } return 0; } //------------------------------------------------------------------------------ // Main program //------------------------------------------------------------------------------ int main(int argc, char**argv) { int retval = 0; DebugSetLevel(0); std::cerr << "Note: this tool is DEPRECATED, use xrdfs instead." << std::endl; Info(XrdClientDebug::kUSERDEBUG, "Main", "Note: this tool is DEPRECATED, use xrdfs instead."); // We want this tool to be able to connect everywhere // Note that the side effect of these calls here is to initialize the // XrdClient environment. // This is crucial if we want to later override its default values EnvPutString( NAME_REDIRDOMAINALLOW_RE, "*" ); EnvPutString( NAME_CONNECTDOMAINALLOW_RE, "*" ); EnvPutString( NAME_REDIRDOMAINDENY_RE, "" ); EnvPutString( NAME_CONNECTDOMAINDENY_RE, "" ); EnvPutInt( NAME_DEBUG, -1); //-------------------------------------------------------------------------- // Parse the commandline //-------------------------------------------------------------------------- for (int i=1; i < argc; i++) { if ( (strstr(argv[i], "-O") == argv[i])) { opaqueinfo=argv[i]+2; continue; } if ( (strstr(argv[i], "-h") == argv[i]) || (strstr(argv[i], "--help") == argv[i]) ) { PrintUsage(); exit(0); continue; } if ( (strstr(argv[i], "-DS") == argv[i]) && (argc >= i+2) ) { std::cerr << "Overriding " << argv[i]+3 << " with value "; std::cerr << argv[i+1] << ". "; EnvPutString( argv[i]+3, argv[i+1] ); std::cerr << " Final value: " << EnvGetString(argv[i]+3); std::cerr << std::endl; i++; continue; } if ( (strstr(argv[i], "-DI") == argv[i]) && (argc >= i+2) ) { std::cerr << "Overriding '" << argv[i]+3 << "' with value "; std::cerr << argv[i+1] << ". "; EnvPutInt( argv[i]+3, atoi(argv[i+1]) ); std::cerr << " Final value: " << EnvGetLong(argv[i]+3); std::cerr << std::endl; i++; continue; } // Any other par is ignored if ( (strstr(argv[i], "-") == argv[i]) && (strlen(argv[i]) > 1) ) { std::cerr << "Unknown parameter " << argv[i] << std::endl; continue; } if (!initialhost) initialhost = argv[i]; else { cmdline_cmd += argv[i]; cmdline_cmd += " "; } } //-------------------------------------------------------------------------- // Initialize the client //-------------------------------------------------------------------------- DebugSetLevel(EnvGetLong(NAME_DEBUG)); // if there's no command to execute from the cmdline... if (cmdline_cmd.length() == 0) { std::cout << XRDCLI_VERSION << std::endl; std::cout << "Welcome to the xrootd command line interface."; std::cout << std::endl; std::cout << "Type 'help' for a list of available commands."; std::cout << std::endl; } if (initialhost) { XrdOucString s = "root://"; s += initialhost; s += "//dummy"; genadmin = new XrdClientAdmin(s.c_str()); // Then connect if (!genadmin->Connect()) { delete genadmin; genadmin = 0; } } //-------------------------------------------------------------------------- // Get the command from the std input //-------------------------------------------------------------------------- while( true ) { //---------------------------------------------------------------------- // Parse the string //---------------------------------------------------------------------- stringstream prompt; char *linebuf=0; if (cmdline_cmd.length() == 0) { BuildPrompt(prompt); linebuf = readline(prompt.str().c_str()); if( !linebuf ) { std::cout << "Goodbye." << std::endl << std::endl; break; } if( ! *linebuf) { free(linebuf); continue; } #ifdef HAVE_READLINE add_history(linebuf); #endif } else linebuf = strdup(cmdline_cmd.c_str()); XrdOucTokenizer tkzer(linebuf); if (!tkzer.GetLine()) continue; char *cmd = tkzer.GetToken(0, 1); if (!cmd) continue; //---------------------------------------------------------------------- // Execute the command //---------------------------------------------------------------------- CommandCallback callback = lookup( cmd ); if( !callback ) { if( strcmp( cmd, "exit" ) == 0 ) { std::cout << "Goodbye." << std::endl << std::endl; free( linebuf ); break; } std::cout << "Command not recognized." << std::endl; std::cout << "Type \"help\" for a list of commands."; std::cout < 0) break; } if (genadmin) delete genadmin; return retval; }