79 TNetFile::TNetFile(
const char *url, Option_t *option,
const char *ftitle,
80 Int_t compress, Int_t netopt)
81 : TFile(url,
"NET", ftitle, compress), fEndpointUrl(url)
84 Create(url, option, netopt);
92 TNetFile::TNetFile(
const char *url,
const char *ftitle, Int_t compress, Bool_t)
93 : TFile(url,
"NET", ftitle, compress), fEndpointUrl(url)
104 TNetFile::~TNetFile()
112 Int_t TNetFile::SysOpen(
const char * , Int_t , UInt_t )
116 Create(fUrl.GetUrl(), fOption, fNetopt);
117 if (!fSocket)
return -1;
121 if (fProtocol > 15) {
122 fSocket->Send(Form(
"%s %s", fUrl.GetFile(), ToLower(fOption).Data()),
126 fSocket->Send(Form(
"/%s %s", fUrl.GetFile(), ToLower(fOption).Data()),
134 if (kind == kROOTD_ERR) {
135 PrintError(
"SysOpen", stat);
147 Int_t TNetFile::SysClose(Int_t )
150 fSocket->Send(kROOTD_CLOSE);
159 Int_t TNetFile::SysStat(Int_t, Long_t *
id, Long64_t *size, Long_t *flags, Long_t *modtime)
161 if (fProtocol < 3)
return 1;
163 if (!fSocket)
return 1;
165 fSocket->Send(kROOTD_FSTAT);
169 fSocket->Recv(msg,
sizeof(msg), kind);
171 Int_t mode, uid, gid, islink;
174 if (fProtocol > 12) {
176 sscanf(msg,
"%ld %ld %d %d %d %I64d %ld %d", &dev, &ino, &mode,
177 &uid, &gid, size, modtime, &islink);
179 sscanf(msg,
"%ld %ld %d %d %d %lld %ld %d", &dev, &ino, &mode,
180 &uid, &gid, size, modtime, &islink);
185 *
id = (dev << 24) + ino;
188 if (mode & (kS_IXUSR|kS_IXGRP|kS_IXOTH))
192 if (!R_ISREG(mode) && !R_ISDIR(mode))
197 sscanf(msg,
"%ld %I64d %ld %ld",
id, size, flags, modtime);
199 sscanf(msg,
"%ld %lld %ld %ld",
id, size, flags, modtime);
211 void TNetFile::Close(Option_t *opt)
213 if (!fSocket)
return;
218 fSocket->Send(kROOTD_BYE);
228 void TNetFile::Flush()
232 if (fSocket && fWritable)
233 fSocket->Send(kROOTD_FLUSH);
239 void TNetFile::Init(Bool_t create)
250 Bool_t TNetFile::IsOpen()
const
252 return fSocket == 0 ? kFALSE : kTRUE;
258 void TNetFile::Print(Option_t *)
const
260 const char *fname = fUrl.GetFile();
261 Printf(
"URL: %s", ((TUrl*)&fUrl)->GetUrl());
262 Printf(
"Remote file: %s", &fname[1]);
263 Printf(
"Remote user: %s", fUser.Data());
264 Printf(
"Title: %s", fTitle.Data());
265 Printf(
"Option: %s", fOption.Data());
266 Printf(
"Bytes written: %lld", fBytesWrite);
267 Printf(
"Bytes read: %lld", fBytesRead);
273 void TNetFile::PrintError(
const char *where, Int_t err)
276 Error(where,
"%s", gRootdErrStr[err]);
288 Int_t TNetFile::ReOpen(Option_t *mode)
291 Error(
"ReOpen",
"operation not supported by remote rootd (protocol = %d)",
296 return TFile::ReOpen(mode);
303 Bool_t TNetFile::ReadBuffer(
char *buf, Int_t len)
305 if (!fSocket)
return kTRUE;
309 Bool_t result = kFALSE;
312 if ((st = ReadBufferViaCache(buf, len))) {
318 if (gApplication && gApplication->GetSignalHandler())
319 gApplication->GetSignalHandler()->Delay();
322 if (gPerfStats) start = TTimeStamp();
324 if (fSocket->Send(Form(
"%lld %d", fOffset, len), kROOTD_GET) < 0) {
325 Error(
"ReadBuffer",
"error sending kROOTD_GET command");
334 if (Recv(stat, kind) < 0 || kind == kROOTD_ERR) {
335 PrintError(
"ReadBuffer", stat);
340 while ((n = fSocket->RecvRaw(buf, len)) < 0 && TSystem::GetErrno() == EINTR)
341 TSystem::ResetErrno();
344 Error(
"ReadBuffer",
"error receiving buffer of length %d, got %d", len, n);
354 SetFileBytesRead(GetFileBytesRead() + len);
355 SetFileReadCalls(GetFileReadCalls() + 1);
364 gPerfStats->FileReadEvent(
this, len, start);
366 if (gApplication && gApplication->GetSignalHandler())
367 gApplication->GetSignalHandler()->HandleDelayedSignal();
376 Bool_t TNetFile::ReadBuffer(
char *buf, Long64_t pos, Int_t len)
379 return ReadBuffer(buf, len);
387 Bool_t TNetFile::ReadBuffers(
char *buf, Long64_t *pos, Int_t *len, Int_t nbuf)
389 if (!fSocket)
return kTRUE;
393 return TFile::ReadBuffers(buf, pos, len, nbuf);
396 Int_t blockSize = 262144;
397 Bool_t result = kFALSE;
401 if (gApplication && gApplication->GetSignalHandler())
402 gApplication->GetSignalHandler()->Delay();
405 if (gPerfStats) start = TTimeStamp();
408 Long64_t total_len = 0;
410 for(Int_t i = 0; i < nbuf; i++) {
411 data_buf += pos[i] + fArchiveOffset;
419 if (fSocket->Send(Form(
"%d %d %d", nbuf, data_buf.Length(), blockSize),
421 Error(
"ReadBuffers",
"error sending kROOTD_GETS command");
426 if (fSocket->SendRaw(data_buf, data_buf.Length()) < 0) {
427 Error(
"ReadBuffers",
"error sending buffer");
433 if (Recv(stat, kind) < 0 || kind == kROOTD_ERR) {
434 PrintError(
"ReadBuffers", stat);
440 while (actual_pos < total_len) {
441 Long64_t left = total_len - actual_pos;
442 if (left > blockSize)
446 while ((n = fSocket->RecvRaw(buf + actual_pos, Int_t(left))) < 0 &&
447 TSystem::GetErrno() == EINTR)
448 TSystem::ResetErrno();
450 if (n != Int_t(left)) {
451 Error(
"GetBuffers",
"error receiving buffer of length %d, got %d",
459 fBytesRead += total_len;
462 SetFileBytesRead(GetFileBytesRead() + total_len);
463 SetFileReadCalls(GetFileReadCalls() + 1);
465 fgBytesRead += total_len;
472 gPerfStats->FileReadEvent(
this, total_len, start);
474 if (gApplication && gApplication->GetSignalHandler())
475 gApplication->GetSignalHandler()->HandleDelayedSignal();
480 Info(
"ReadBuffers",
"Couldnt use the specific implementation, calling TFile::ReadBuffers");
481 return TFile::ReadBuffers(buf, pos, len, nbuf);
491 Bool_t TNetFile::WriteBuffer(
const char *buf, Int_t len)
493 if (!fSocket || !fWritable)
return kTRUE;
495 Bool_t result = kFALSE;
498 if ((st = WriteBufferViaCache(buf, len))) {
504 gSystem->IgnoreInterrupt();
506 if (fSocket->Send(Form(
"%lld %d", fOffset, len), kROOTD_PUT) < 0) {
508 Error(
"WriteBuffer",
"error sending kROOTD_PUT command");
512 if (fSocket->SendRaw(buf, len) < 0) {
514 Error(
"WriteBuffer",
"error sending buffer");
523 if (Recv(stat, kind) < 0 || kind == kROOTD_ERR) {
525 PrintError(
"WriteBuffer", stat);
534 SetFileBytesWritten(GetFileBytesWritten() + len);
540 gSystem->IgnoreInterrupt(kFALSE);
549 Int_t TNetFile::Recv(Int_t &status, EMessageTypes &kind)
554 if (!fSocket)
return -1;
557 Int_t n = fSocket->Recv(status, what);
558 kind = (EMessageTypes) what;
565 void TNetFile::Seek(Long64_t offset, ERelativeTo pos)
567 SetOffset(offset, pos);
573 void TNetFile::ConnectServer(Int_t *stat, EMessageTypes *kind, Int_t netopt,
574 Int_t tcpwindowsize, Bool_t forceOpen,
577 TString fn = fUrl.GetFile();
580 Int_t sSize = netopt < -1 ? -netopt : 1;
581 TString url(fUrl.GetProtocol());
582 if (url.Contains(
"root")) {
587 url += TString(Form(
"://%s@%s:%d",
588 fUrl.GetUser(), fUrl.GetHost(), fUrl.GetPort()));
589 fSocket = TSocket::CreateAuthSocket(url, sSize, tcpwindowsize, fSocket, stat);
590 if (!fSocket || (fSocket && !fSocket->IsAuthenticated())) {
592 Error(
"TNetFile",
"can't open %d-stream connection to rootd on "
593 "host %s at port %d", sSize, fUrl.GetHost(), fUrl.GetPort());
595 Error(
"TNetFile",
"can't open connection to rootd on "
596 "host %s at port %d", fUrl.GetHost(), fUrl.GetPort());
602 fProtocol = fSocket->GetRemoteProtocol();
603 if (forceRead && fProtocol < 5) {
604 Warning(
"ConnectServer",
"rootd does not support \"+read\" option");
613 fSocket->Send(Form(
"%s %s", fn.Data(),
614 ToLower(
"f"+fOption).Data()), kROOTD_OPEN);
616 fSocket->Send(Form(
"%s %s", fn.Data(),
"+read"), kROOTD_OPEN);
618 fSocket->Send(Form(
"%s %s", fn.Data(),
619 ToLower(fOption).Data()), kROOTD_OPEN);
621 EMessageTypes tmpkind;
623 Recv(tmpstat, tmpkind);
662 void TNetFile::Create(
const char * , Option_t *option, Int_t netopt)
664 Int_t tcpwindowsize = 65535;
670 Bool_t forceOpen = kFALSE;
671 if (option[0] ==
'-') {
672 fOption = &option[1];
676 if (option[0] ==
'F' || option[0] ==
'f') {
677 fOption = &option[1];
681 Bool_t forceRead = kFALSE;
682 if (!strcasecmp(option,
"+read")) {
683 fOption = &option[1];
689 if (fOption ==
"NEW")
692 Bool_t create = (fOption ==
"CREATE") ? kTRUE : kFALSE;
693 Bool_t recreate = (fOption ==
"RECREATE") ? kTRUE : kFALSE;
694 Bool_t update = (fOption ==
"UPDATE") ? kTRUE : kFALSE;
695 Bool_t read = (fOption ==
"READ") ? kTRUE : kFALSE;
696 if (!create && !recreate && !update && !read) {
701 if (!fUrl.IsValid()) {
702 Error(
"Create",
"invalid URL specified: %s", fUrl.GetUrl());
706 if (netopt > tcpwindowsize)
707 tcpwindowsize = netopt;
712 ConnectServer(&stat, &kind, netopt, tcpwindowsize, forceOpen, forceRead);
713 if (gDebug > 2) Info(
"Create",
"got from host %d %d", stat, kind);
715 if (kind == kROOTD_ERR) {
716 PrintError(
"Create", stat);
717 Error(
"Create",
"failing on file %s", fUrl.GetUrl());
727 if (update && stat > 1) {
755 void TNetFile::Create(TSocket *s, Option_t *option, Int_t netopt)
761 Create(s->GetUrl(), option, netopt);
768 Bool_t TNetFile::Matches(
const char *url)
771 Bool_t rc = TFile::Matches(url);
778 if (!strcmp(u.GetFile(),fEndpointUrl.GetFile())) {
780 TString fqdn = u.GetHostFQDN();
783 if (u.GetPort() == fEndpointUrl.GetPort()) {
784 TString fqdnref = fEndpointUrl.GetHostFQDN();
805 TNetSystem::TNetSystem(Bool_t ftpowner)
806 : TSystem(
"-root",
"Net file Helper System")
814 fFTPOwner = ftpowner;
827 TNetSystem::TNetSystem(
const char *url, Bool_t ftpowner)
828 : TSystem(
"-root",
"Net file Helper System")
833 fFTPOwner = ftpowner;
841 void TNetSystem::InitRemoteEntity(
const char *url)
846 fUser = turl.GetUser();
847 if (!fUser.Length()) {
848 UserGroup_t *u = gSystem->GetUserInfo();
855 fHost = turl.GetHostFQDN();
859 fPort = turl.GetPort();
865 void TNetSystem::Create(
const char *url, TSocket *sock)
870 if (!surl.Contains(
"://")) {
871 surl.Insert(surl.Index(
":")+1,
"//");
883 Bool_t forceRemote = gEnv->GetValue(
"Path.ForceRemote", 0);
884 TString opts = TUrl(url).GetOptions();
885 if (opts.Contains(
"remote=1"))
887 else if (opts.Contains(
"remote=0"))
888 forceRemote = kFALSE;
890 if ((fIsLocal = TSystem::IsPathLocal(url))) {
891 fLocalPrefix = gEnv->GetValue(
"Path.Localroot",
"");
898 InitRemoteEntity(surl);
901 if (fHost.Length()) {
904 if (strlen(turl.GetProtocol())) {
905 eurl = turl.GetProtocol();
910 if (strlen(turl.GetUser())) {
911 eurl += turl.GetUser();
918 eurl += turl.GetPort();
920 fFTP =
new TFTP(eurl, 1, TFTP::kDfltWindowSize, sock);
921 if (fFTP && fFTP->IsOpen()) {
922 if (fFTP->GetSocket()->GetRemoteProtocol() < 12) {
924 "remote daemon does not support 'system' functionality");
928 fUser = fFTP->GetSocket()->GetSecContext()->GetUser();
929 fHost = fFTP->GetSocket()->GetSecContext()->GetHost();
934 gROOT->GetListOfSockets()->Remove(fFTP);
943 TNetSystem::~TNetSystem()
948 if (fFTP->IsOpen()) {
952 fFTP->FreeDirectory(kFALSE);
967 Int_t TNetSystem::MakeDirectory(
const char *dir)
971 TString edir = TUrl(dir).GetFile();
972 if (!fLocalPrefix.IsNull())
973 edir.Insert(0, fLocalPrefix);
974 return gSystem->MakeDirectory(edir);
977 if (fFTP && fFTP->IsOpen()) {
979 TString edir = TUrl(dir).GetFile();
980 return fFTP->MakeDirectory(edir,kFALSE);
989 void *TNetSystem::OpenDirectory(
const char *dir)
993 TString edir = TUrl(dir).GetFile();
994 if (!fLocalPrefix.IsNull())
995 edir.Insert(0, fLocalPrefix);
996 return gSystem->OpenDirectory(edir);
999 if (!fFTP || !fFTP->IsOpen())
1004 Info(
"OpenDirectory",
"a directory is already open: close it first");
1005 fFTP->FreeDirectory(kFALSE);
1010 TString edir = TUrl(dir).GetFile();
1012 if (fFTP->OpenDirectory(edir,kFALSE)) {
1014 fDirp = (
void *)&fDir;
1023 void TNetSystem::FreeDirectory(
void *dirp)
1027 gSystem->FreeDirectory(dirp);
1031 if (dirp != fDirp) {
1032 Error(
"FreeDirectory",
"invalid directory pointer (should never happen)");
1036 if (fFTP && fFTP->IsOpen()) {
1038 fFTP->FreeDirectory(kFALSE);
1048 const char *TNetSystem::GetDirEntry(
void *dirp)
1052 return gSystem->GetDirEntry(dirp);
1055 if (dirp != fDirp) {
1056 Error(
"GetDirEntry",
"invalid directory pointer (should never happen)");
1060 if (fFTP && fFTP->IsOpen() && fDir) {
1061 return fFTP->GetDirEntry(kFALSE);
1072 Int_t TNetSystem::GetPathInfo(
const char *path, FileStat_t &buf)
1076 TString epath = TUrl(path).GetFile();
1077 if (!fLocalPrefix.IsNull())
1078 epath.Insert(0, fLocalPrefix);
1079 return gSystem->GetPathInfo(epath, buf);
1082 if (fFTP && fFTP->IsOpen()) {
1084 TString epath = TUrl(path).GetFile();
1085 fFTP->GetPathInfo(epath, buf, kFALSE);
1096 Bool_t TNetSystem::AccessPathName(
const char *path, EAccessMode mode)
1100 TString epath = TUrl(path).GetFile();
1101 if (!fLocalPrefix.IsNull())
1102 epath.Insert(0, fLocalPrefix);
1103 return gSystem->AccessPathName(epath, mode);
1106 if (fFTP && fFTP->IsOpen()) {
1108 TString epath = TUrl(path).GetFile();
1109 return fFTP->AccessPathName(epath, mode, kFALSE);
1118 Bool_t TNetSystem::ConsistentWith(
const char *path,
void *dirptr)
1121 Bool_t checkstd = TSystem::ConsistentWith(path, dirptr);
1122 if (!checkstd)
return kFALSE;
1125 Bool_t checknet = path ? kFALSE : kTRUE;
1126 if (path && strlen(path)) {
1130 TString user = url.GetUser();
1131 if (user.IsNull() && !fUser.IsNull()) {
1132 UserGroup_t *u = gSystem->GetUserInfo();
1139 TString host = url.GetHostFQDN();
1142 Int_t port = url.GetPort();
1144 Info(
"ConsistentWith",
"fUser:'%s' (%s), fHost:'%s' (%s), fPort:%d (%d)",
1145 fUser.Data(), user.Data(), fHost.Data(), host.Data(),
1148 if (user == fUser && host == fHost && port == fPort)
1152 return (checkstd && checknet);
1158 Int_t TNetSystem::Unlink(
const char *path)
1162 TString epath = TUrl(path).GetFile();
1163 if (!fLocalPrefix.IsNull())
1164 epath.Insert(0, fLocalPrefix);
1165 return gSystem->Unlink(epath);
1169 Warning(
"Unlink",
"functionality not implemented - ignored (path: %s)", path);