00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "RConfig.h"
00023
00024 #include <fcntl.h>
00025 #include <errno.h>
00026 #include <sys/stat.h>
00027 #ifndef R__WIN32
00028 # include <unistd.h>
00029 #else
00030 # define ssize_t int
00031 # include <io.h>
00032 # include <sys/types.h>
00033 #endif
00034
00035 #include "TFTP.h"
00036 #include "TPSocket.h"
00037 #include "TUrl.h"
00038 #include "TStopwatch.h"
00039 #include "TSystem.h"
00040 #include "TEnv.h"
00041 #include "TROOT.h"
00042 #include "TError.h"
00043 #include "NetErrors.h"
00044 #include "TRegexp.h"
00045 #include "TVirtualMutex.h"
00046
00047 #if defined(R__UNIX) || defined(R__MACOSX)
00048 #define HAVE_MMAP
00049 #endif
00050
00051 #ifdef HAVE_MMAP
00052 # include <sys/mman.h>
00053 #ifndef MAP_FILE
00054 #define MAP_FILE 0
00055 #endif
00056 #endif
00057
00058
00059 Long64_t TFTP::fgBytesWrite = 0;
00060 Long64_t TFTP::fgBytesRead = 0;
00061
00062
00063 ClassImp(TFTP)
00064
00065
00066 TFTP::TFTP(const char *url, Int_t par, Int_t wsize, TSocket *sock)
00067 {
00068
00069
00070
00071
00072
00073
00074
00075
00076 fSocket = sock;
00077
00078 TString s = url;
00079 if (s.Contains("://")) {
00080 if (!s.BeginsWith("root")) {
00081 Error("TFTP",
00082 "url must be of the form \"[root[up,s,k,g,h,ug]://]host[:port]\"");
00083 MakeZombie();
00084 return;
00085 }
00086 } else
00087 s = "root://" + s;
00088
00089 Init(s, par, wsize);
00090 }
00091
00092
00093 void TFTP::Init(const char *surl, Int_t par, Int_t wsize)
00094 {
00095
00096
00097 TUrl url(surl);
00098 TString hurl(url.GetProtocol());
00099 if (hurl.Contains("root")) {
00100 hurl.Insert(4,"dp");
00101 } else {
00102 hurl = "rootdp";
00103 }
00104 hurl += TString(Form("://%s@%s:%d",
00105 url.GetUser(), url.GetHost(), url.GetPort()));
00106 fSocket = TSocket::CreateAuthSocket(hurl, par, wsize, fSocket);
00107 if (!fSocket || !fSocket->IsAuthenticated()) {
00108 if (par > 1)
00109 Error("TFTP", "can't open %d-stream connection to rootd on "
00110 "host %s at port %d", par, url.GetHost(), url.GetPort());
00111 else
00112 Error("TFTP", "can't open connection to rootd on "
00113 "host %s at port %d", url.GetHost(), url.GetPort());
00114 goto zombie;
00115 }
00116
00117 fProtocol = fSocket->GetRemoteProtocol();
00118 fUser = fSocket->GetSecContext()->GetUser();
00119
00120 fHost = url.GetHost();
00121 fPort = url.GetPort();
00122 fParallel = par;
00123 fWindowSize = wsize;
00124 fLastBlock = 0;
00125 fRestartAt = 0;
00126 fBlockSize = kDfltBlockSize;
00127 fMode = kBinary;
00128 fBytesWrite = 0;
00129 fBytesRead = 0;
00130
00131
00132
00133
00134 {
00135 R__LOCKGUARD2(gROOTMutex);
00136 gROOT->GetListOfSockets()->Remove(fSocket);
00137 gROOT->GetListOfSockets()->Add(this);
00138 }
00139 return;
00140
00141 zombie:
00142 MakeZombie();
00143 SafeDelete(fSocket);
00144 }
00145
00146
00147 TFTP::~TFTP()
00148 {
00149
00150
00151 Close();
00152 }
00153
00154
00155 void TFTP::Print(Option_t *) const
00156 {
00157
00158
00159 TString secCont;
00160
00161 Printf("Local host: %s", gSystem->HostName());
00162 Printf("Remote host: %s [%d]", fHost.Data(), fPort);
00163 Printf("Remote user: %s", fUser.Data());
00164 if (fSocket->IsAuthenticated())
00165 Printf("Security context: %s",
00166 fSocket->GetSecContext()->AsString(secCont));
00167 Printf("Rootd protocol vers.: %d", fSocket->GetRemoteProtocol());
00168 if (fParallel > 1) {
00169 Printf("Parallel sockets: %d", fParallel);
00170 }
00171 Printf("TCP window size: %d", fWindowSize);
00172 Printf("Rootd protocol: %d", fProtocol);
00173 Printf("Transfer block size: %d", fBlockSize);
00174 Printf("Transfer mode: %s", fMode ? "ascii" : "binary");
00175 Printf("Bytes sent: %lld", fBytesWrite);
00176 Printf("Bytes received: %lld", fBytesRead);
00177 }
00178
00179
00180 void TFTP::PrintError(const char *where, Int_t err) const
00181 {
00182
00183
00184 Error(where, "%s", gRootdErrStr[err]);
00185 }
00186
00187
00188 Int_t TFTP::Recv(Int_t &status, EMessageTypes &kind) const
00189 {
00190
00191
00192
00193 kind = kROOTD_ERR;
00194 status = 0;
00195
00196 if (!fSocket) return -1;
00197
00198 Int_t what;
00199 Int_t n = fSocket->Recv(status, what);
00200 kind = (EMessageTypes) what;
00201 return n;
00202 }
00203
00204
00205 void TFTP::SetBlockSize(Int_t blockSize)
00206 {
00207
00208
00209 if (blockSize < 32768) {
00210 fBlockSize = 32768;
00211 return;
00212 }
00213
00214 int i;
00215 for (i = 0; i < int(sizeof(blockSize)*8); i++)
00216 if ((blockSize >> i) == 1)
00217 break;
00218
00219 fBlockSize = 1 << i;
00220 }
00221
00222
00223 Long64_t TFTP::PutFile(const char *file, const char *remoteName)
00224 {
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235 if (!IsOpen() || !file || !*file) return -1;
00236
00237 #if defined(R__WIN32) || defined(R__WINGCC)
00238 Int_t fd = open(file, O_RDONLY | O_BINARY);
00239 #elif defined(R__SEEK64)
00240 Int_t fd = open64(file, O_RDONLY);
00241 #else
00242 Int_t fd = open(file, O_RDONLY);
00243 #endif
00244 if (fd < 0) {
00245 Error("PutFile", "cannot open %s in read mode", file);
00246 return -1;
00247 }
00248
00249 Long64_t size;
00250 Long_t id, flags, modtime;
00251 if (gSystem->GetPathInfo(file, &id, &size, &flags, &modtime) == 0) {
00252 if (flags > 1) {
00253 Error("PutFile", "%s not a regular file (%ld)", file, flags);
00254 close(fd);
00255 return -1;
00256 }
00257 } else {
00258 Warning("PutFile", "could not stat %s", file);
00259 close(fd);
00260 return -1;
00261 }
00262
00263 if (!remoteName)
00264 remoteName = file;
00265
00266 Long64_t restartat = fRestartAt;
00267
00268
00269 if (restartat && (restartat >= size))
00270 restartat = 0;
00271
00272 if (fSocket->Send(Form("%s %d %d %lld %lld", remoteName, fBlockSize, fMode,
00273 size, restartat), kROOTD_PUTFILE) < 0) {
00274 Error("PutFile", "error sending kROOTD_PUTFILE command");
00275 close(fd);
00276 return -2;
00277 }
00278
00279 Int_t stat;
00280 EMessageTypes kind;
00281
00282 if (Recv(stat, kind) < 0 || kind == kROOTD_ERR) {
00283 PrintError("PutFile", stat);
00284 close(fd);
00285 return -1;
00286 }
00287
00288 Info("PutFile", "sending file %s (%lld bytes, starting at %lld)",
00289 file, size, restartat);
00290
00291 TStopwatch timer;
00292 timer.Start();
00293
00294 Long64_t pos = restartat & ~(fBlockSize-1);
00295 Int_t skip = restartat - pos;
00296
00297 #ifndef HAVE_MMAP
00298 char *buf = new char[fBlockSize];
00299 #if defined(R__SEEK64)
00300 lseek64(fd, pos, SEEK_SET);
00301 #elif defined(R__WIN32)
00302 _lseeki64(fd, pos, SEEK_SET);
00303 #else
00304 lseek(fd, pos, SEEK_SET);
00305 #endif
00306 #endif
00307
00308 while (pos < size) {
00309 Long64_t left = Long64_t(size - pos);
00310 if (left > fBlockSize)
00311 left = fBlockSize;
00312 #ifdef HAVE_MMAP
00313 #if defined(R__SEEK64)
00314 char *buf = (char*) mmap64(0, left, PROT_READ, MAP_FILE | MAP_SHARED, fd, pos);
00315 #else
00316 char *buf = (char*) mmap(0, left, PROT_READ, MAP_FILE | MAP_SHARED, fd, pos);
00317 #endif
00318 if (buf == (char *) -1) {
00319 Error("PutFile", "mmap of file %s failed", file);
00320 close(fd);
00321 return -1;
00322 }
00323 #else
00324 Int_t siz;
00325 while ((siz = read(fd, buf, left)) < 0 && TSystem::GetErrno() == EINTR)
00326 TSystem::ResetErrno();
00327 if (siz < 0 || siz != left) {
00328 Error("PutFile", "error reading from file %s", file);
00329
00330 delete [] buf;
00331 close(fd);
00332 return -1;
00333 }
00334 #endif
00335
00336 if (fSocket->SendRaw(buf+skip, left-skip) < 0) {
00337 Error("PutFile", "error sending buffer");
00338
00339 #ifdef HAVE_MMAP
00340 munmap(buf, left);
00341 #else
00342 delete [] buf;
00343 #endif
00344 close(fd);
00345 return -2;
00346 }
00347
00348 fBytesWrite += left-skip;
00349 fgBytesWrite += left-skip;
00350
00351 fRestartAt = pos;
00352
00353 pos += left;
00354 skip = 0;
00355
00356 #ifdef HAVE_MMAP
00357 munmap(buf, left);
00358 #endif
00359 }
00360
00361 #ifndef HAVE_MMAP
00362 delete [] buf;
00363 #endif
00364
00365 close(fd);
00366
00367 fRestartAt = 0;
00368
00369
00370 if (Recv(stat, kind) < 0 || kind == kROOTD_ERR) {
00371 PrintError("PutFile", stat);
00372 close(fd);
00373 return -1;
00374 }
00375
00376
00377 Double_t speed, t = timer.RealTime();
00378 if (t > 0)
00379 speed = Double_t(size - restartat) / t;
00380 else
00381 speed = 0.0;
00382 if (speed > 524288)
00383 Info("PutFile", "%.3f seconds, %.2f Mbytes per second",
00384 t, speed / 1048576);
00385 else if (speed > 512)
00386 Info("PutFile", "%.3f seconds, %.2f Kbytes per second",
00387 t, speed / 1024);
00388 else
00389 Info("PutFile", "%.3f seconds, %.2f bytes per second",
00390 t, speed);
00391
00392 return Long64_t(size - restartat);
00393 }
00394
00395
00396 Long64_t TFTP::GetFile(const char *file, const char *localName)
00397 {
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408 if (!IsOpen() || !file || !*file) return -1;
00409
00410 if (!localName) {
00411 if (file[0] == '-')
00412 localName = file+1;
00413 else
00414 localName = file;
00415 }
00416
00417 Long64_t restartat = fRestartAt;
00418
00419 if (fSocket->Send(Form("%s %d %d %lld", file, fBlockSize, fMode,
00420 restartat), kROOTD_GETFILE) < 0) {
00421 Error("GetFile", "error sending kROOTD_GETFILE command");
00422 return -2;
00423 }
00424
00425 Int_t stat;
00426 EMessageTypes kind;
00427
00428 if (Recv(stat, kind) < 0 || kind == kROOTD_ERR) {
00429 PrintError("GetFile", stat);
00430 return -1;
00431 }
00432
00433
00434 Long64_t size;
00435 Int_t what;
00436 char mess[128];
00437
00438 if (fSocket->Recv(mess, sizeof(mess), what) < 0) {
00439 Error("GetFile", "error receiving remote file size");
00440 return -2;
00441 }
00442 #ifdef R__WIN32
00443 sscanf(mess, "%I64d", &size);
00444 #else
00445 sscanf(mess, "%lld", &size);
00446 #endif
00447
00448
00449 if (restartat && (restartat >= size))
00450 restartat = 0;
00451
00452
00453 Int_t fd;
00454 if (!restartat) {
00455 #if defined(R__WIN32) || defined(R__WINGCC)
00456 if (fMode == kBinary)
00457 fd = open(localName, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY,
00458 S_IREAD | S_IWRITE);
00459 else
00460 fd = open(localName, O_CREAT | O_TRUNC | O_WRONLY,
00461 S_IREAD | S_IWRITE);
00462 #elif defined(R__SEEK64)
00463 fd = open64(localName, O_CREAT | O_TRUNC | O_WRONLY, 0600);
00464 #else
00465 fd = open(localName, O_CREAT | O_TRUNC | O_WRONLY, 0600);
00466 #endif
00467 } else {
00468 #if defined(R__WIN32) || defined(R__WINGCC)
00469 if (fMode == kBinary)
00470 fd = open(localName, O_WRONLY | O_BINARY, S_IREAD | S_IWRITE);
00471 else
00472 fd = open(localName, O_WRONLY, S_IREAD | S_IWRITE);
00473 #elif defined(R__SEEK64)
00474 fd = open64(localName, O_WRONLY, 0600);
00475 #else
00476 fd = open(localName, O_WRONLY, 0600);
00477 #endif
00478 }
00479
00480 if (fd < 0) {
00481 Error("GetFile", "cannot open %s", localName);
00482
00483 return -1;
00484 }
00485
00486
00487 if (strcmp(localName, "/dev/null")) {
00488 Long_t id, bsize, blocks, bfree;
00489 if (gSystem->GetFsInfo(localName, &id, &bsize, &blocks, &bfree) == 0) {
00490 Long64_t space = (Long64_t)bsize * (Long64_t)bfree;
00491 if (space < size - restartat) {
00492 Error("GetFile", "not enough space to store file %s", localName);
00493
00494 close(fd);
00495 return -1;
00496 }
00497 } else
00498 Warning("GetFile", "could not determine if there is enough free space to store file");
00499 }
00500
00501
00502 if (restartat) {
00503 #if defined(R__SEEK64)
00504 if (lseek64(fd, restartat, SEEK_SET) < 0) {
00505 #elif defined(R__WIN32)
00506 if (_lseeki64(fd, restartat, SEEK_SET) < 0) {
00507 #else
00508 if (lseek(fd, restartat, SEEK_SET) < 0) {
00509 #endif
00510 Error("GetFile", "cannot seek to position %lld in file %s",
00511 restartat, localName);
00512
00513 close(fd);
00514 return -1;
00515 }
00516 }
00517
00518 Info("GetFile", "getting file %s (%lld bytes, starting at %lld)",
00519 localName, size, restartat);
00520
00521 TStopwatch timer;
00522 timer.Start();
00523
00524 char *buf = new char[fBlockSize];
00525 char *buf2 = 0;
00526 if (fMode == kAscii)
00527 buf2 = new char[fBlockSize];
00528
00529 Long64_t pos = restartat & ~(fBlockSize-1);
00530 Int_t skip = restartat - pos;
00531
00532 while (pos < size) {
00533 Long64_t left = size - pos;
00534 if (left > fBlockSize)
00535 left = fBlockSize;
00536
00537 Int_t n;
00538 while ((n = fSocket->RecvRaw(buf, Int_t(left-skip))) < 0 &&
00539 TSystem::GetErrno() == EINTR)
00540 TSystem::ResetErrno();
00541
00542 if (n != Int_t(left-skip)) {
00543 Error("GetFile", "error receiving buffer of length %d, got %d",
00544 Int_t(left-skip), n);
00545 close(fd);
00546 delete [] buf; delete [] buf2;
00547 return -2;
00548 }
00549
00550
00551 ssize_t siz;
00552 if (fMode == kAscii) {
00553 Int_t i = 0, j = 0;
00554 while (i < n) {
00555 if (buf[i] == '\r')
00556 i++;
00557 else
00558 buf2[j++] = buf[i++];
00559 }
00560 n = j;
00561 while ((siz = write(fd, buf2, n)) < 0 && TSystem::GetErrno() == EINTR)
00562 TSystem::ResetErrno();
00563 } else {
00564 while ((siz = write(fd, buf, n)) < 0 && TSystem::GetErrno() == EINTR)
00565 TSystem::ResetErrno();
00566 }
00567
00568 if (siz < 0) {
00569 SysError("GetFile", "error writing file %s", localName);
00570
00571 close(fd);
00572 delete [] buf; delete [] buf2;
00573 return -1;
00574 }
00575
00576 if (siz != n) {
00577 Error("GetFile", "error writing all requested bytes to file %s, wrote %ld of %d",
00578 localName, (Long_t)siz, n);
00579
00580 close(fd);
00581 delete [] buf; delete [] buf2;
00582 return -1;
00583 }
00584
00585 fBytesRead += left-skip;
00586 fgBytesRead += left-skip;
00587
00588 fRestartAt = pos;
00589
00590 pos += left;
00591 skip = 0;
00592 }
00593
00594 delete [] buf; delete [] buf2;
00595
00596 #ifndef R__WIN32
00597 fchmod(fd, 0644);
00598 #endif
00599
00600 close(fd);
00601
00602 fRestartAt = 0;
00603
00604
00605 Double_t speed, t = timer.RealTime();
00606 if (t > 0)
00607 speed = Double_t(size - restartat) / t;
00608 else
00609 speed = 0.0;
00610 if (speed > 524288)
00611 Info("GetFile", "%.3f seconds, %.2f Mbytes per second",
00612 t, speed / 1048576);
00613 else if (speed > 512)
00614 Info("GetFile", "%.3f seconds, %.2f Kbytes per second",
00615 t, speed / 1024);
00616 else
00617 Info("GetFile", "%.3f seconds, %.2f bytes per second",
00618 t, speed);
00619
00620 return Long64_t(size - restartat);
00621 }
00622
00623
00624 Int_t TFTP::ChangeDirectory(const char *dir) const
00625 {
00626
00627
00628
00629
00630 if (!IsOpen()) return -1;
00631
00632 if (!dir || !*dir) {
00633 Error("ChangeDirectory", "illegal directory name specified");
00634 return -1;
00635 }
00636
00637 if (fSocket->Send(Form("%s", dir), kROOTD_CHDIR) < 0) {
00638 Error("ChangeDirectory", "error sending kROOTD_CHDIR command");
00639 return -1;
00640 }
00641
00642 Int_t what;
00643 char mess[1024];
00644
00645 if (fSocket->Recv(mess, sizeof(mess), what) < 0) {
00646 Error("ChangeDirectory", "error receiving chdir confirmation");
00647 return -1;
00648 }
00649 if (what == kMESS_STRING) {
00650 Printf("%s\n", mess);
00651
00652 if (fSocket->Recv(mess, sizeof(mess), what) < 0) {
00653 Error("ChangeDirectory", "error receiving chdir confirmation");
00654 return -1;
00655 }
00656 }
00657
00658 Info("ChangeDirectory", "%s", mess);
00659
00660 return 0;
00661 }
00662
00663
00664 Int_t TFTP::MakeDirectory(const char *dir, Bool_t print) const
00665 {
00666
00667
00668
00669 if (!IsOpen()) return -1;
00670
00671 if (!dir || !*dir) {
00672 Error("MakeDirectory", "illegal directory name specified");
00673 return -1;
00674 }
00675
00676 if (fSocket->Send(Form("%s", dir), kROOTD_MKDIR) < 0) {
00677 Error("MakeDirectory", "error sending kROOTD_MKDIR command");
00678 return -1;
00679 }
00680
00681 Int_t what;
00682 char mess[1024];
00683
00684 if (fSocket->Recv(mess, sizeof(mess), what) < 0) {
00685 Error("MakeDirectory", "error receiving mkdir confirmation");
00686 return -1;
00687 }
00688
00689 if (print)
00690 Info("MakeDirectory", "%s", mess);
00691
00692 if (!strncmp(mess,"OK:",3))
00693 return 1;
00694
00695 return 0;
00696 }
00697
00698
00699 Int_t TFTP::DeleteDirectory(const char *dir) const
00700 {
00701
00702
00703
00704 if (!IsOpen()) return -1;
00705
00706 if (!dir || !*dir) {
00707 Error("DeleteDirectory", "illegal directory name specified");
00708 return -1;
00709 }
00710
00711 if (fSocket->Send(Form("%s", dir), kROOTD_RMDIR) < 0) {
00712 Error("DeleteDirectory", "error sending kROOTD_RMDIR command");
00713 return -1;
00714 }
00715
00716 Int_t what;
00717 char mess[1024];
00718
00719 if (fSocket->Recv(mess, sizeof(mess), what) < 0) {
00720 Error("DeleteDirectory", "error receiving rmdir confirmation");
00721 return -1;
00722 }
00723
00724 Info("DeleteDirectory", "%s", mess);
00725
00726 return 0;
00727 }
00728
00729
00730 Int_t TFTP::ListDirectory(Option_t *cmd) const
00731 {
00732
00733
00734
00735
00736 if (!IsOpen()) return -1;
00737
00738 if (!cmd || !*cmd)
00739 cmd = "ls .";
00740
00741 if (fSocket->Send(Form("%s", cmd), kROOTD_LSDIR) < 0) {
00742 Error("ListDirectory", "error sending kROOTD_LSDIR command");
00743 return -1;
00744 }
00745
00746 Int_t what;
00747 char mess[1024];
00748
00749 do {
00750 if (fSocket->Recv(mess, sizeof(mess), what) < 0) {
00751 Error("ListDirectory", "error receiving lsdir confirmation");
00752 return -1;
00753 }
00754 printf("%s", mess);
00755 } while (what == kMESS_STRING);
00756
00757 return 0;
00758 }
00759
00760
00761 Int_t TFTP::PrintDirectory() const
00762 {
00763
00764
00765
00766 if (!IsOpen()) return -1;
00767
00768 if (fSocket->Send("", kROOTD_PWD) < 0) {
00769 Error("DeleteDirectory", "error sending kROOTD_PWD command");
00770 return -1;
00771 }
00772
00773 Int_t what;
00774 char mess[1024];
00775
00776 if (fSocket->Recv(mess, sizeof(mess), what) < 0) {
00777 Error("PrintDirectory", "error receiving pwd confirmation");
00778 return -1;
00779 }
00780
00781 Info("PrintDirectory", "%s", mess);
00782
00783 return 0;
00784 }
00785
00786
00787 Int_t TFTP::RenameFile(const char *file1, const char *file2) const
00788 {
00789
00790
00791
00792 if (!IsOpen()) return -1;
00793
00794 if (!file1 || !file2 || !*file1 || !*file2) {
00795 Error("RenameFile", "illegal file names specified");
00796 return -1;
00797 }
00798
00799 if (fSocket->Send(Form("%s %s", file1, file2), kROOTD_MV) < 0) {
00800 Error("RenameFile", "error sending kROOTD_MV command");
00801 return -1;
00802 }
00803
00804 Int_t what;
00805 char mess[1024];
00806
00807 if (fSocket->Recv(mess, sizeof(mess), what) < 0) {
00808 Error("RenameFile", "error receiving mv confirmation");
00809 return -1;
00810 }
00811
00812 Info("RenameFile", "%s", mess);
00813
00814 return 0;
00815 }
00816
00817
00818 Int_t TFTP::DeleteFile(const char *file) const
00819 {
00820
00821
00822
00823 if (!IsOpen()) return -1;
00824
00825 if (!file || !*file) {
00826 Error("DeleteFile", "illegal file name specified");
00827 return -1;
00828 }
00829
00830 if (fSocket->Send(Form("%s", file), kROOTD_RM) < 0) {
00831 Error("DeleteFile", "error sending kROOTD_RM command");
00832 return -1;
00833 }
00834
00835 Int_t what;
00836 char mess[1024];
00837
00838 if (fSocket->Recv(mess, sizeof(mess), what) < 0) {
00839 Error("DeleteFile", "error receiving rm confirmation");
00840 return -1;
00841 }
00842
00843 Info("DeleteFile", "%s", mess);
00844
00845 return 0;
00846 }
00847
00848
00849 Int_t TFTP::ChangePermission(const char *file, Int_t mode) const
00850 {
00851
00852
00853
00854
00855 if (!IsOpen()) return -1;
00856
00857 if (!file || !*file) {
00858 Error("ChangePermission", "illegal file name specified");
00859 return -1;
00860 }
00861
00862 if (fSocket->Send(Form("%s %d", file, mode), kROOTD_CHMOD) < 0) {
00863 Error("ChangePermission", "error sending kROOTD_CHMOD command");
00864 return -1;
00865 }
00866
00867 Int_t what;
00868 char mess[1024];
00869
00870 if (fSocket->Recv(mess, sizeof(mess), what) < 0) {
00871 Error("ChangePermission", "error receiving chmod confirmation");
00872 return -1;
00873 }
00874
00875 Info("ChangePermission", "%s", mess);
00876
00877 return 0;
00878 }
00879
00880
00881 Int_t TFTP::Close()
00882 {
00883
00884
00885
00886 if (!IsOpen()) return -1;
00887
00888 if (fSocket->Send(kROOTD_CLOSE) < 0) {
00889 Error("Close", "error sending kROOTD_CLOSE command");
00890 return -1;
00891 }
00892
00893
00894 if (fProtocol > 6)
00895 fSocket->Send(kROOTD_BYE);
00896
00897
00898 {
00899 R__LOCKGUARD2(gROOTMutex);
00900 gROOT->GetListOfSockets()->Remove(this);
00901 }
00902
00903
00904 SafeDelete(fSocket);
00905
00906 return 0;
00907 }
00908
00909
00910 Bool_t TFTP::OpenDirectory(const char *dir, Bool_t print)
00911 {
00912
00913
00914
00915
00916 fDir = kFALSE;
00917
00918 if (!IsOpen()) return fDir;
00919
00920 if (fProtocol < 12) {
00921 Error("OpenDirectory", "call not supported by remote rootd");
00922 return fDir;
00923 }
00924
00925 if (!dir || !*dir) {
00926 Error("OpenDirectory", "illegal directory name specified");
00927 return fDir;
00928 }
00929
00930 if (fSocket->Send(Form("%s", dir), kROOTD_OPENDIR) < 0) {
00931 Error("OpenDirectory", "error sending kROOTD_OPENDIR command");
00932 return fDir;
00933 }
00934
00935 Int_t what;
00936 char mess[1024];;
00937
00938 if (fSocket->Recv(mess, sizeof(mess), what) < 0) {
00939 Error("OpenDirectory", "error receiving opendir confirmation");
00940 return fDir;
00941 }
00942
00943 if (print)
00944 Info("OpenDirectory", "%s", mess);
00945
00946 if (!strncmp(mess,"OK:",3)) {
00947 fDir = kTRUE;
00948 return fDir;
00949 }
00950 return fDir;
00951 }
00952
00953
00954 void TFTP::FreeDirectory(Bool_t print)
00955 {
00956
00957
00958 if (!IsOpen() || !fDir) return;
00959
00960 if (fProtocol < 12) {
00961 Error("FreeDirectory", "call not supported by remote rootd");
00962 return;
00963 }
00964
00965 if (fSocket->Send(kROOTD_FREEDIR) < 0) {
00966 Error("FreeDirectory", "error sending kROOTD_FREEDIR command");
00967 return;
00968 }
00969
00970 Int_t what;
00971 char mess[1024];;
00972
00973 if (fSocket->Recv(mess, sizeof(mess), what) < 0) {
00974 Error("FreeDirectory", "error receiving freedir confirmation");
00975 return;
00976 }
00977
00978 if (print)
00979 Info("FreeDirectory", "%s", mess);
00980
00981 return;
00982 }
00983
00984
00985 const char *TFTP::GetDirEntry(Bool_t print)
00986 {
00987
00988
00989
00990 static char dirent[1024] = {0};
00991
00992 if (!IsOpen() || !fDir) return 0;
00993
00994 if (fProtocol < 12) {
00995 Error("GetDirEntry", "call not supported by remote rootd");
00996 return 0;
00997 }
00998
00999 if (fSocket->Send(kROOTD_DIRENTRY) < 0) {
01000 Error("GetDirEntry", "error sending kROOTD_DIRENTRY command");
01001 return 0;
01002 }
01003
01004 Int_t what;
01005 char mess[1024];;
01006
01007 if (fSocket->Recv(mess, sizeof(mess), what) < 0) {
01008 Error("GetDirEntry", "error receiving dir entry confirmation");
01009 return 0;
01010 }
01011
01012 if (print)
01013 Info("GetDirEntry", "%s", mess);
01014
01015 if (!strncmp(mess,"OK:",3)) {
01016 strlcpy(dirent,mess+3, sizeof(dirent));
01017 return (const char *)dirent;
01018 }
01019
01020 return 0;
01021 }
01022
01023
01024 Int_t TFTP::GetPathInfo(const char *path, FileStat_t &buf, Bool_t print)
01025 {
01026
01027
01028
01029
01030
01031 TUrl url(path);
01032
01033 if (!IsOpen()) return 1;
01034
01035 if (fProtocol < 12) {
01036 Error("GetPathInfo", "call not supported by remote rootd");
01037 return 1;
01038 }
01039
01040 if (!path || !*path) {
01041 Error("GetPathInfo", "illegal path name specified");
01042 return 1;
01043 }
01044
01045 if (fSocket->Send(Form("%s", path), kROOTD_FSTAT) < 0) {
01046 Error("GetPathInfo", "error sending kROOTD_FSTAT command");
01047 return 1;
01048 }
01049
01050 Int_t what;
01051 char mess[1024];;
01052
01053 if (fSocket->Recv(mess, sizeof(mess), what) < 0) {
01054 Error("GetPathInfo", "error receiving fstat confirmation");
01055 return 1;
01056 }
01057 if (print)
01058 Info("GetPathInfo", "%s", mess);
01059
01060 Int_t mode, uid, gid, islink;
01061 Long_t id, flags, dev, ino, mtime;
01062 Long64_t size;
01063 if (fProtocol > 12) {
01064 #ifdef R__WIN32
01065 sscanf(mess, "%ld %ld %d %d %d %I64d %ld %d", &dev, &ino, &mode,
01066 &uid, &gid, &size, &mtime, &islink);
01067 #else
01068 sscanf(mess, "%ld %ld %d %d %d %lld %ld %d", &dev, &ino, &mode,
01069 &uid, &gid, &size, &mtime, &islink);
01070 #endif
01071 if (dev == -1)
01072 return 1;
01073 buf.fDev = dev;
01074 buf.fIno = ino;
01075 buf.fMode = mode;
01076 buf.fUid = uid;
01077 buf.fGid = gid;
01078 buf.fSize = size;
01079 buf.fMtime = mtime;
01080 buf.fIsLink = (islink == 1);
01081 } else {
01082 #ifdef R__WIN32
01083 sscanf(mess, "%ld %I64d %ld %ld", &id, &size, &flags, &mtime);
01084 #else
01085 sscanf(mess, "%ld %lld %ld %ld", &id, &size, &flags, &mtime);
01086 #endif
01087 if (id == -1)
01088 return 1;
01089 buf.fDev = (id >> 24);
01090 buf.fIno = (id & 0x00FFFFFF);
01091 if (flags == 0)
01092 buf.fMode = kS_IFREG;
01093 if (flags & 1)
01094 buf.fMode = (kS_IFREG|kS_IXUSR|kS_IXGRP|kS_IXOTH);
01095 if (flags & 2)
01096 buf.fMode = kS_IFDIR;
01097 if (flags & 4)
01098 buf.fMode = kS_IFSOCK;
01099 buf.fSize = size;
01100 buf.fMtime = mtime;
01101 }
01102
01103 return 0;
01104 }
01105
01106
01107 Bool_t TFTP::AccessPathName(const char *path, EAccessMode mode, Bool_t print)
01108 {
01109
01110
01111
01112
01113 if (!IsOpen()) return kTRUE;
01114
01115 if (fProtocol < 12) {
01116 Error("AccessPathName", "call not supported by remote rootd");
01117 return kTRUE;
01118 }
01119
01120 if (!path || !*path) {
01121 Error("AccessPathName", "illegal path name specified");
01122 return kTRUE;
01123 }
01124
01125 if (fSocket->Send(Form("%s %d", path, mode), kROOTD_ACCESS) < 0) {
01126 Error("AccessPathName", "error sending kROOTD_ACCESS command");
01127 return kTRUE;
01128 }
01129
01130 Int_t what;
01131 char mess[1024];;
01132
01133 if (fSocket->Recv(mess, sizeof(mess), what) < 0) {
01134 Error("AccessPathName", "error receiving access confirmation");
01135 return kTRUE;
01136 }
01137 if (print)
01138 Info("AccessPathName", "%s", mess);
01139
01140 if (!strncmp(mess,"OK",2))
01141 return kFALSE;
01142 else
01143 return kTRUE;
01144 }