00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 const char *XrdCpWorkLstCVSID = "$Id: XrdCpWorkLst.cc 30949 2009-11-02 16:37:58Z ganis $";
00014
00015 #include "XrdClient/XrdCpWorkLst.hh"
00016 #include "XrdOuc/XrdOucErrInfo.hh"
00017 #include "XrdSys/XrdSysDir.hh"
00018 #include "XrdSys/XrdSysHeaders.hh"
00019 #include <sys/stat.h>
00020 #include <errno.h>
00021 #ifndef WIN32
00022 #include <unistd.h>
00023 #else
00024 #include "XrdSys/XrdWin32.hh"
00025 #endif
00026
00027 using namespace std;
00028
00029
00030
00031 void PrintLastServerError(XrdClient *cli) {
00032 struct ServerResponseBody_Error *e;
00033
00034 if ( cli && (e = cli->LastServerError()) )
00035 cerr << "Last server error " << e->errnum << " ('" << e->errmsg << "')" <<
00036 endl;
00037
00038 }
00039
00040
00041
00042 bool PedanticOpen4Write(XrdClient *cli, kXR_unt16 mode, kXR_unt16 options) {
00043
00044 bool paropen = !(options & kXR_delete);
00045
00046 if (!cli) return false;
00047
00048 if ( !cli->Open(mode, options, paropen) ) {
00049
00050 if ( (cli->LastServerError()->errnum == kXR_NotFound)
00051 && (options & kXR_delete) ) {
00052
00053 XrdClientAdmin adm(cli->GetCurrentUrl().GetUrl().c_str());
00054 if (adm.Connect()) {
00055 adm.Rm( cli->GetCurrentUrl().File.c_str() );
00056 }
00057
00058
00059 if ( !cli->Open(mode, options, paropen) )
00060 return false;
00061
00062 }
00063 else return false;
00064 }
00065
00066 return true;
00067 }
00068
00069
00070
00071
00072 XrdCpWorkLst::XrdCpWorkLst() {
00073 fWorkList.Clear();
00074 xrda_src = 0;
00075 xrda_dst = 0;
00076 }
00077
00078 XrdCpWorkLst::~XrdCpWorkLst() {
00079 fWorkList.Clear();
00080 }
00081
00082
00083
00084 int XrdCpWorkLst::SetSrc(XrdClient **srccli, XrdOucString url,
00085 XrdOucString urlopaquedata, bool do_recurse) {
00086
00087 XrdOucString fullurl(url);
00088
00089 if (urlopaquedata.length())
00090 fullurl = url + "?" + urlopaquedata;
00091
00092 fSrcIsDir = FALSE;
00093
00094 if (fullurl.beginswith("root://") || fullurl.beginswith("xroot://") ) {
00095
00096
00097 fSrc = url;
00098
00099
00100 if (!*srccli)
00101 (*srccli) = new XrdClient(fullurl.c_str());
00102
00103 if ((*srccli)->Open(0, kXR_async) &&
00104 ((*srccli)->LastServerResp()->status == kXR_ok)) {
00105
00106 fWorkList.Push_back(fSrc);
00107 }
00108 else
00109 if ( do_recurse &&
00110 ((*srccli)->LastServerError()->errnum == kXR_isDirectory) ){
00111
00112
00113 delete (*srccli);
00114 *srccli = 0;
00115
00116
00117
00118
00119 fSrcIsDir = TRUE;
00120
00121 xrda_src = new XrdClientAdmin(fullurl.c_str());
00122
00123 if (xrda_src->Connect()) {
00124
00125 BuildWorkList_xrd(fSrc, urlopaquedata);
00126 }
00127
00128 delete xrda_src;
00129 xrda_src = 0;
00130
00131 }
00132 else {
00133
00134 PrintLastServerError(*srccli);
00135 return 1;
00136
00137 }
00138
00139
00140
00141
00142 }
00143 else {
00144
00145 fSrc = url;
00146 fSrcIsDir = FALSE;
00147
00148
00149 XrdSysDir d(url.c_str());
00150 if (!d.isValid()) {
00151 if (d.lastError() == ENOTDIR)
00152 fWorkList.Push_back(fSrc);
00153 else
00154 return d.lastError();
00155 } else {
00156 fSrcIsDir = TRUE;
00157 BuildWorkList_loc(&d, url);
00158 }
00159 }
00160
00161 fWorkIt = 0;
00162 return 0;
00163 }
00164
00165
00166
00167
00168 int XrdCpWorkLst::SetDest(XrdClient **xrddest, const char *url,
00169 const char *urlopaquedata,
00170 kXR_unt16 xrdopenflags) {
00171 int retval = 0;
00172
00173
00174 if (url[strlen(url)-1] == '/') {
00175 fDest = url;
00176 fDestIsDir = TRUE;
00177 return 0;
00178 }
00179
00180 if ( (strstr(url, "root://") == url) ||
00181 (strstr(url, "xroot://") == url) ) {
00182
00183
00184 fDest = url;
00185
00186 if (fSrcIsDir) {
00187 fDestIsDir = TRUE;
00188
00189
00190 if (!fDest.endswith('/'))
00191 fDest += '/';
00192 return 0;
00193 }
00194 else {
00195
00196
00197 fDestIsDir = FALSE;
00198 XrdOucString fullurl(url);
00199
00200 if (urlopaquedata) {
00201 fullurl += "?";
00202 fullurl += urlopaquedata;
00203 }
00204
00205
00206 *xrddest = new XrdClient(fullurl.c_str());
00207
00208 if ( PedanticOpen4Write(*xrddest, kXR_ur | kXR_uw | kXR_gw | kXR_gr | kXR_or,
00209 xrdopenflags) &&
00210 ((*xrddest)->LastServerResp()->status == kXR_ok) ) {
00211
00212 return 0;
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229 } else {
00230
00231
00232
00233 if ((*xrddest)->LastServerError()->errnum == kXR_isDirectory) {
00234
00235
00236 fDestIsDir = TRUE;
00237
00238
00239
00240 if (!fDest.endswith('/'))
00241 fDest += '/';
00242
00243
00244 retval = 0;
00245 }
00246 else {
00247 PrintLastServerError(*xrddest);
00248 retval = 1;
00249 }
00250
00251
00252
00253 delete *xrddest;
00254 *xrddest = 0;
00255
00256 return retval;
00257 }
00258
00259 }
00260
00261 }
00262 else {
00263
00264
00265 if (strcmp(url, "-")) {
00266
00267 fDestIsDir = TRUE;
00268
00269 struct stat st;
00270 if (lstat(url, &st) == 0) {
00271 if (!S_ISDIR(st.st_mode))
00272 fDestIsDir = FALSE;
00273 } else {
00274 if (errno == ENOENT)
00275 fDestIsDir = FALSE;
00276 else
00277 return errno;
00278 }
00279 fDest = url;
00280
00281
00282 if (fDestIsDir && !fDest.endswith('/'))
00283 fDest += '/';
00284 return 0;
00285 }
00286 else {
00287
00288 fDest = url;
00289 fDestIsDir = FALSE;
00290 }
00291
00292 }
00293
00294 fWorkIt = 0;
00295 return 0;
00296 }
00297
00298
00299 int XrdCpWorkLst::BuildWorkList_xrd(XrdOucString url, XrdOucString opaquedata) {
00300 vecString entries;
00301 int it;
00302 long id, flags, modtime;
00303 long long size;
00304 XrdOucString fullpath;
00305 XrdClientUrlInfo u(url);
00306
00307
00308 if (!xrda_src->DirList(u.File.c_str(), entries)) return -1;
00309
00310
00311 for (it = 0; it < entries.GetSize(); it++) {
00312 fullpath = url + "/" + entries[it];
00313
00314 XrdClientUrlInfo u(fullpath);
00315
00316
00317
00318 if ( xrda_src->Stat((char *)u.File.c_str(), id, size, flags, modtime) &&
00319 (flags & kXR_isDir) ) {
00320
00321 BuildWorkList_xrd(fullpath, opaquedata);
00322 }
00323 else
00324 fWorkList.Push_back(fullpath);
00325
00326
00327 }
00328
00329 return 0;
00330 }
00331
00332
00333 int XrdCpWorkLst::BuildWorkList_loc(XrdSysDir *dir, XrdOucString path)
00334 {
00335
00336 char *ent = 0;
00337 XrdOucString fullpath;
00338
00339
00340
00341 while (dir && (ent = dir->nextEntry())) {
00342
00343 if (!strcmp(ent, ".") || !strcmp(ent, ".."))
00344 continue;
00345
00346
00347 fullpath = path + "/" + ent;
00348
00349
00350 struct stat ftype;
00351 if ( lstat(fullpath.c_str(), &ftype) < 0 )
00352 continue;
00353
00354
00355 if (S_ISDIR(ftype.st_mode)) {
00356 XrdSysDir d(fullpath.c_str());
00357
00358 if (d.isValid())
00359 BuildWorkList_loc(&d, fullpath);
00360 } else
00361
00362 if (S_ISREG(ftype.st_mode))
00363 fWorkList.Push_back(fullpath);
00364 }
00365
00366 return 0;
00367 }
00368
00369
00370
00371 bool XrdCpWorkLst::GetCpJob(XrdOucString &src, XrdOucString &dest) {
00372
00373 if (fWorkIt >= fWorkList.GetSize()) return FALSE;
00374
00375 src = fWorkList[fWorkIt];
00376 dest = fDest;
00377
00378 if (fDestIsDir) {
00379
00380
00381
00382 int slpos = src.rfind('/');
00383
00384 if (slpos != STR_NPOS)
00385 dest += XrdOucString(src, slpos);
00386 }
00387
00388 fWorkIt++;
00389
00390 return TRUE;
00391 }
00392