XRootD
XrdPosixXrootd.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d P o s i x X r o o t d . c c */
4 /* */
5 /* (c) 2010 by the Board of Trustees of the Leland Stanford, Jr., University */
6 /* All Rights Reserved */
7 /* Produced by Andrew Hanushevsky for Stanford University under contract */
8 /* DE-AC02-76-SFO0515 with the Department of Energy */
9 /* */
10 /* This file is part of the XRootD software suite. */
11 /* */
12 /* XRootD is free software: you can redistribute it and/or modify it under */
13 /* the terms of the GNU Lesser General Public License as published by the */
14 /* Free Software Foundation, either version 3 of the License, or (at your */
15 /* option) any later version. */
16 /* */
17 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
18 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
19 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
20 /* License for more details. */
21 /* */
22 /* You should have received a copy of the GNU Lesser General Public License */
23 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
24 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
25 /* */
26 /* The copyright holder's institutional names and contributor's names may not */
27 /* be used to endorse or promote products derived from this software without */
28 /* specific prior written permission of the institution or contributor. */
29 /******************************************************************************/
30 
31 #include <cerrno>
32 #include <fcntl.h>
33 #include <iostream>
34 #include <cstdio>
35 #include <sys/time.h>
36 #include <sys/param.h>
37 #include <sys/resource.h>
38 #include <sys/uio.h>
39 
40 #include "XrdVersion.hh"
41 
42 #include "Xrd/XrdScheduler.hh"
43 
44 #include "XrdCl/XrdClDefaultEnv.hh"
45 #include "XrdCl/XrdClFileSystem.hh"
46 #include "XrdCl/XrdClFile.hh"
47 #include "XrdCl/XrdClURL.hh"
49 
50 #include "XrdSys/XrdSysHeaders.hh"
51 #include "XrdSys/XrdSysPlatform.hh"
52 
53 #include "XrdOuc/XrdOucCache.hh"
54 #include "XrdOuc/XrdOucECMsg.hh"
55 #include "XrdOuc/XrdOucEnv.hh"
57 #include "XrdOuc/XrdOucPsx.hh"
59 
63 #include "XrdPosix/XrdPosixDir.hh"
64 #include "XrdPosix/XrdPosixFile.hh"
66 #include "XrdPosix/XrdPosixInfo.hh"
67 #include "XrdPosix/XrdPosixMap.hh"
73 
74 #include "XrdSys/XrdSysTrace.hh"
75 
76 /******************************************************************************/
77 /* S t a t i c M e m b e r s */
78 /******************************************************************************/
79 
80 class XrdSysError;
81 
82 namespace XrdPosixGlobals
83 {
84 thread_local XrdOucECMsg ecMsg("[posix]");
85 
86 XrdScheduler *schedP = 0;
90 XrdSysError *eDest = 0;
92 XrdSysTrace Trace("Posix", 0,
93  (getenv("XRDPOSIX_DEBUG") ? TRACE_Debug : 0));
94 int ddInterval= 30;
95 int ddMaxTries= 180/30;
97 bool oidsOK = false;
98 bool p2lSRC = false;
99 bool p2lSGI = false;
100 bool autoPGRD = false;
101 bool usingEC = false;
102 };
103 
104 int XrdPosixXrootd::baseFD = 0;
105 int XrdPosixXrootd::initDone = 0;
106 
107 XrdVERSIONINFO(XrdPosix,XrdPosix);
108 
109 /******************************************************************************/
110 /* L o c a l C l a s s e s */
111 /******************************************************************************/
112 /******************************************************************************/
113 /* L f n P a t h */
114 /******************************************************************************/
115 
116 namespace
117 {
118 class LfnPath
119 {
120 public:
121 const char *path;
122 
123  LfnPath(const char *who, const char *pURL, bool ponly=true)
124  {path = XrdPosixXrootPath::P2L(who, pURL, relURL, ponly);}
125 
126  ~LfnPath() {if (relURL) free(relURL);}
127 
128 private:
129 char *relURL;
130 };
131 }
132 
133 /******************************************************************************/
134 /* L o c a l F u n c t i o n s */
135 /******************************************************************************/
136 
137 namespace
138 {
139 
140 /******************************************************************************/
141 /* O p e n D e f e r */
142 /******************************************************************************/
143 
144 int OpenDefer(XrdPosixFile *fp,
145  XrdPosixCallBack *cbP,
146  XrdCl::OpenFlags::Flags XOflags,
147  XrdCl::Access::Mode XOmode,
148  bool isStream)
149 {
150 
151 // Assign a file descriptor to this file
152 //
153  if (!(fp->AssignFD(isStream)))
154  {delete fp; return XrdPosixGlobals::ecMsg.SetErrno(EMFILE);}
155 
156 // Allocate a prepare I/O object to defer this open
157 //
158  fp->PrepIO = new XrdPosixPrepIO(fp, XOflags, XOmode);
159 
160 // Finalize this file object. A null argument indicates it is deferred.
161 //
162  fp->Finalize(0);
163 
164 // For sync opens we just need to return the file descriptor
165 //
166  if (!cbP) return fp->FDNum();
167 
168 // For async opens do the callback here and return an inprogress
169 //
170  cbP->Complete(fp->FDNum());
171  errno = EINPROGRESS;
172  return -1;
173 }
174 };
175 
176 /******************************************************************************/
177 /* C o n s t r u c t o r */
178 /******************************************************************************/
179 
180 XrdPosixXrootd::XrdPosixXrootd(int fdnum, int dirnum, int thrnum)
181 {
182  static XrdSysMutex myMutex;
183  char *cfn;
184 
185 // Test if XRDCL_EC is set. That env var. is set at XrdCl::PlugInManager::LoadFactory
186 // in XrdClPlugInManager.cc, which is called (by XrdOssGetSS while loading
187 // libXrdPss.so) before this function.
188 // Note: some standalone programs will call this constructor directly.
189  XrdPosixGlobals::usingEC = getenv("XRDCL_EC")? true : false;
190 
191 // Only static fields are initialized here. We need to do this only once!
192 //
193  myMutex.Lock();
194  if (initDone) {myMutex.UnLock(); return;}
195  initDone = 1;
196  myMutex.UnLock();
197 
198 // Initialize environment as a client or a server (it differs somewhat).
199 // Note that we create a permanent Env since some plugins rely on it. We
200 // leave the logger handling to OucPsx as we do not want to enable messages
201 // because this is likely a client application that doesn't understand noise.
202 //
203  if (!XrdPosixGlobals::theLogger && (cfn=getenv("XRDPOSIX_CONFIG")) && *cfn)
204  {bool hush;
205  if (*cfn == '+') {hush = false; cfn++;}
206  else hush = (getenv("XRDPOSIX_DEBUG") == 0);
207  if (*cfn)
208  {XrdOucEnv *psxEnv = new XrdOucEnv;
209  psxEnv->Put("psx.Client", "1");
210  XrdOucPsx psxConfig(&XrdVERSIONINFOVAR(XrdPosix), cfn, 0, psxEnv);
211  if (!psxConfig.ClientConfig("posix.", hush)
212  || !XrdPosixConfig::SetConfig(psxConfig))
213  {std::cerr <<"Posix: Unable to instantiate specified "
214  "configuration; program exiting!" <<std::endl;
215  exit(16);
216  }
217  }
218  }
219 
220 // Initialize file tracking
221 //
222  baseFD = XrdPosixObject::Init(fdnum);
223 }
224 
225 /******************************************************************************/
226 /* D e s t r u c t o r */
227 /******************************************************************************/
228 
230 {
231 
232 // Shutdown processing
233 //
235  initDone = 0;
236 }
237 
238 /******************************************************************************/
239 /* A c c e s s */
240 /******************************************************************************/
241 
242 int XrdPosixXrootd::Access(const char *path, int amode)
243 {
245  mode_t stMode;
246  bool aOK = true;
247 
248 // Issue the stat and verify that all went well
249 //
250  if (!admin.Stat(&stMode)) return -1;
251 
252 // Translate the mode bits
253 //
254  if (amode & R_OK && !(stMode & S_IRUSR)) aOK = 0;
255  if (amode & W_OK && !(stMode & S_IWUSR)) aOK = 0;
256  if (amode & X_OK && !(stMode & S_IXUSR)) aOK = 0;
257 
258 // All done
259 //
260  if (aOK) return 0;
261  return XrdPosixGlobals::ecMsg.SetErrno(EACCES);
262 }
263 
264 /******************************************************************************/
265 /* C l o s e */
266 /******************************************************************************/
267 
268 int XrdPosixXrootd::Close(int fildes)
269 {
270  EPNAME("Close");
271  XrdCl::XRootDStatus Status;
272  XrdPosixFile *fP;
273  bool ret;
274 
275 // Map the file number to the file object. In the prcess we relese the file
276 // number so no one can reference this file again.
277 //
278  if (!(fP = XrdPosixObject::ReleaseFile(fildes)))
279  return XrdPosixGlobals::ecMsg.SetErrno(EBADF);
280 
281 // Detach the file from a possible cache. We need to up the reference count
282 // to synchrnoize with any possible callback as we may need to place this
283 // object in he delayed destroy queue if it is stil being used. Note that
284 // the caller will get a zero return code should we delay the close.
285 //
286  fP->Ref();
287  if (fP->XCio->Detach((XrdOucCacheIOCD&)*fP) && fP->Refs() < 2)
288  {if ((ret = fP->Close(Status))) {delete fP; fP = 0;}
289  else if (DEBUGON)
290  {std::string eTxt = Status.ToString();
291  DEBUG(eTxt <<" closing " << obfuscateAuth(fP->Origin()));
292  }
293  } else {
294  ret = true;
295  }
296 
297 // If we still have a handle then we need to do a delayed delete on this
298 // object because either the close failed or there is still active I/O
299 //
300  if (fP) XrdPosixFile::DelayedDestroy(fP);
301 
302 // Return final result. Note: close errors are recorded in global thread status
303 //
304  return (ret ? 0 : XrdPosixMap::Result(Status,XrdPosixGlobals::ecMsg,true));
305 }
306 
307 /******************************************************************************/
308 /* C l o s e d i r */
309 /******************************************************************************/
310 
312 {
313  XrdPosixDir *dP;
314  int fildes = XrdPosixDir::dirNo(dirp);
315 
316 // Get the directory object
317 //
318  if (!(dP = XrdPosixObject::ReleaseDir(fildes)))
319  return XrdPosixGlobals::ecMsg.SetErrno(EBADF);
320 
321 // Deallocate the directory
322 //
323  delete dP;
324  return 0;
325 }
326 
327 /******************************************************************************/
328 /* e n d P o i n t */
329 /******************************************************************************/
330 
331 int XrdPosixXrootd::endPoint(int FD, char *Buff, int Blen)
332 {
333  XrdPosixFile *fp;
334  int uPort;
335 
336 // Find the file object
337 //
338  if (!(fp = XrdPosixObject::File(FD))) return 0;
339 
340 // Make sure url is valid
341 //
342  if (!(fp->clFile.IsOpen()))
343  {fp->UnLock(); return -ENOTCONN;}
344 
345 // Make sure we can fit result in the buffer
346 //
347  std::string dataServer;
348  fp->clFile.GetProperty( "DataServer", dataServer );
349  XrdCl::URL dataServerUrl = dataServer;
350 
351  if (dataServer.size() >= (uint32_t)Blen)
352  {fp->UnLock(); return -ENAMETOOLONG;}
353 
354 // Copy the data server location
355 //
356  strcpy(Buff, dataServer.c_str());
357 
358 // Get the port and return it
359 //
360  uPort = dataServerUrl.GetPort();
361  fp->UnLock();
362  return uPort;
363 }
364 
365 /******************************************************************************/
366 /* F s t a t */
367 /******************************************************************************/
368 
369 int XrdPosixXrootd::Fstat(int fildes, struct stat *buf)
370 {
371  XrdPosixFile *fp;
372  int rc;
373 
374 // Find the file object
375 //
376  if (!(fp = XrdPosixObject::File(fildes))) return -1;
377 
378 // First initialize the stat buffer
379 //
381 
382 // Check if we can get the stat information from the cache.
383 //
384  rc = fp->XCio->Fstat(*buf);
385  if (rc <= 0)
386  {fp->UnLock();
387  if (!rc) return 0;
388  errno = -rc; //???
389  return -1;
390  }
391 
392 // At this point we can call the file's Fstat() and if the file is not open
393 // it will be opened.
394 //
395  rc = fp->Fstat(*buf);
396  fp->UnLock();
397  if (rc < 0) {errno = -rc; rc = -1;}
398  return rc;
399 }
400 
401 /******************************************************************************/
402 /* F s y n c */
403 /******************************************************************************/
404 
405 int XrdPosixXrootd::Fsync(int fildes)
406 {
407  XrdPosixFile *fp;
408  int rc;
409 
410 // Find the file object
411 //
412  if (!(fp = XrdPosixObject::File(fildes))) return -1;
413 
414 // Do the sync
415 //
416  if ((rc = fp->XCio->Sync()) < 0) return Fault(fp, -rc);
417  fp->UnLock();
418  return 0;
419 }
420 
421 /******************************************************************************/
422 
424 {
425  XrdPosixFile *fp;
426 
427 // Find the file object and do the sync
428 //
429  if ((fp = XrdPosixObject::File(fildes)))
430  {cbp->theFile = fp;
431  fp->Ref(); fp->UnLock();
432  fp->XCio->Sync(*cbp);
433  } else cbp->Complete(-1);
434 }
435 
436 /******************************************************************************/
437 /* F t r u n c a t e */
438 /******************************************************************************/
439 
440 int XrdPosixXrootd::Ftruncate(int fildes, off_t offset)
441 {
442  XrdPosixFile *fp;
443  int rc;
444 
445 // Find the file object
446 //
447  if (!(fp = XrdPosixObject::File(fildes))) return -1;
448 
449 // Do the trunc
450 //
451  if ((rc = fp->XCio->Trunc(offset)) < 0) return Fault(fp, -rc);
452  fp->UnLock();
453  return 0;
454 }
455 
456 /******************************************************************************/
457 /* G e t x a t t r */
458 /******************************************************************************/
459 
460 #ifndef ENOATTR
461 #define ENOATTR ENOTSUP
462 #endif
463 
464 long long XrdPosixXrootd::Getxattr (const char *path, const char *name,
465  void *value, unsigned long long size)
466 {
468  XrdCl::QueryCode::Code reqCode;
469  int vsize = static_cast<int>(size);
470 
471 // Check if user just wants the maximum length needed
472 //
473  if (size == 0) return 1024;
474 
475 // Check if we support the query
476 //
477  if (name)
478  { if (!strcmp(name,"xroot.cksum")) reqCode=XrdCl::QueryCode::Checksum;
479  else if (!strcmp(name,"xroot.space")) reqCode=XrdCl::QueryCode::Space;
480  else if (!strcmp(name,"xroot.xattr")) reqCode=XrdCl::QueryCode::XAttr;
481  else {errno = ENOATTR; return -1;} //???
482  }else {errno = EINVAL; return -1;}
483 
484 // Stat the file first to allow vectoring of the request to the right server
485 //
486  if (!admin.Stat()) return -1;
487 
488 // Return the result
489 //
490  return admin.Query(reqCode, value, vsize);
491 }
492 
493 /******************************************************************************/
494 /* L s e e k */
495 /******************************************************************************/
496 
497 off_t XrdPosixXrootd::Lseek(int fildes, off_t offset, int whence)
498 {
499  XrdPosixFile *fp;
500  long long curroffset;
501 
502 // Find the file object
503 //
504  if (!(fp = XrdPosixObject::File(fildes))) return -1;
505 
506 // Set the new offset. Note that SEEK_END requires that the file be opened.
507 // An open may occur by calling the FSize() method via the cache pointer.
508 //
509  if (whence == SEEK_SET) curroffset = fp->setOffset(offset);
510  else if (whence == SEEK_CUR) curroffset = fp->addOffset(offset);
511  else if (whence == SEEK_END)
512  {curroffset = fp->XCio->FSize();
513  if (curroffset < 0) return Fault(fp,static_cast<int>(-curroffset));
514  curroffset = fp->setOffset(curroffset+offset);
515  }
516  else return Fault(fp, EINVAL);
517 
518 // All done
519 //
520  fp->UnLock();
521  return curroffset;
522 }
523 
524 /******************************************************************************/
525 /* M k d i r */
526 /******************************************************************************/
527 
528 int XrdPosixXrootd::Mkdir(const char *path, mode_t mode)
529 {
532 
533 // Preferentially make the whole path unless told otherwise
534 //
535  flags = (mode & S_ISUID ? XrdCl::MkDirFlags::None
537 
538 // Make sure the admin is OK
539 //
540  if (!admin.isOK()) return -1;
541 
542 // Issue the mkdir
543 //
544  return XrdPosixMap::Result(admin.Xrd.MkDir(admin.Url.GetPathWithParams(),
545  flags,
548  );
549 }
550 
551 /******************************************************************************/
552 /* O p e n */
553 /******************************************************************************/
554 
555 int XrdPosixXrootd::Open(const char *path, int oflags, mode_t mode,
556  XrdPosixCallBack *cbP)
557 {
558  return Open(path, oflags, mode, cbP, 0);
559 }
560 
561 int XrdPosixXrootd::Open(const char *path, int oflags, mode_t mode,
562  XrdPosixCallBack *cbP, XrdPosixInfo *infoP)
563 {
564  EPNAME("Open");
565  XrdCl::XRootDStatus Status;
566  XrdPosixFile *fp;
568  XrdCl::OpenFlags::Flags XOflags;
569  int Opts;
570  bool aOK, isRO = false;
571 
572 // Translate R/W and R/O flags
573 //
574  if (oflags & (O_WRONLY | O_RDWR))
576  XOflags = XrdCl::OpenFlags::Update;
577  } else {
578  Opts = 0;
579  XOflags = XrdCl::OpenFlags::Read;
580  isRO = true;
581  }
582 
583 // Pass along the stream flag
584 //
585  if (oflags & isStream)
587  return XrdPosixGlobals::ecMsg.SetErrno(EMFILE);
588  }
589 
590 // Translate create vs simple open. Always make dirpath on create!
591 //
592  if (oflags & O_CREAT)
593  {XOflags |= (oflags & O_EXCL ? XrdCl::OpenFlags::New
595  XOflags |= XrdCl::OpenFlags::MakePath;
596  XOmode = XrdPosixMap::Mode2Access(mode);
597  }
598  else if (oflags & O_TRUNC && Opts & XrdPosixFile::isUpdt)
599  XOflags |= XrdCl::OpenFlags::Delete;
600 
601 // Allocate the new file object
602 //
603  if (!(fp = new XrdPosixFile(aOK, path, cbP, Opts)))
604  return XrdPosixGlobals::ecMsg.SetErrno(EMFILE);
605 
606 // Check if all went well during allocation
607 //
608  if (!aOK) {delete fp; return -1;}
609 
610 // If we have a cache, then issue a prepare as the cache may want to defer the
611 // open request ans we have a lot more work to do.
612 //
614  {int rc;
615  if (infoP && isRO && OpenCache(*fp, *infoP))
616  {delete fp;
617  errno = 0;
618  return -3;
619  }
620  rc = XrdPosixGlobals::theCache->Prepare(fp->Path(), oflags, mode);
621  if (rc > 0) return OpenDefer(fp, cbP, XOflags, XOmode, oflags&isStream);
622  if (rc < 0) {delete fp; return XrdPosixGlobals::ecMsg.SetErrno(-rc);}
623  }
624 
625 // Open the file (sync or async)
626 //
628  if (!cbP) Status = fp->clFile.Open((std::string)path, XOflags, XOmode);
629  else Status = fp->clFile.Open((std::string)path, XOflags, XOmode,
630  (XrdCl::ResponseHandler *)fp);
631 
632 // If we failed, return the reason
633 //
634  if (!Status.IsOK())
636  int rc = XrdPosixMap::Result(Status,XrdPosixGlobals::ecMsg,false);
637  if (DEBUGON && rc != -ENOENT && rc != -ELOOP)
638  {DEBUG(XrdPosixGlobals::ecMsg.Msg() <<" open " << obfuscateAuth(fp->Origin()));}
639  delete fp;
640  errno = -rc; // Saved errno across the delete
641  return -1;
642  }
643 
644 // Assign a file descriptor to this file
645 //
646  if (!(fp->AssignFD(oflags & isStream)))
647  {delete fp;
648  return XrdPosixGlobals::ecMsg.SetErrno(EMFILE);
649  }
650 
651 // Finalize the open (this gets the stat info). For async opens, the
652 // finalization is deferred until the callback happens.
653 //
654  if (cbP) {errno = EINPROGRESS; return -1;}
655  if (fp->Finalize(&Status)) return fp->FDNum();
656 
657 // At this point the open() has failed as we could neither defer nor finalize.
658 // We need to delete the file pointer and come up with a rational errno as a
659 // file descriptor should not be returned. We need to return the causal error
660 // message and errno. It is considered impossible for no error state to exist.
661 //
662  delete fp;
663  if (XrdPosixMap::Result(Status,XrdPosixGlobals::ecMsg,true)) return -1;
664 
665 // The impossible happened, there is no error state. So, create a suitable one.
666 // Note that our error text will be included as contextual information since
667 // ENOMSG, while logically correct, provides no useful information.
668 //
669  XrdPosixGlobals::ecMsg = "Impossible condition detected!";
670  XrdPosixGlobals::ecMsg = errno = ENOMSG;
671  return -1;
672 }
673 
674 /******************************************************************************/
675 /* Private: O p e n C a c h e */
676 /******************************************************************************/
677 
678 bool XrdPosixXrootd::OpenCache(XrdPosixFile &file,XrdPosixInfo &Info)
679 {
680  EPNAME("OpenCache");
681  int rc;
682 
683 // Check if the full file is in the cache
684 //
685  rc = XrdPosixGlobals::theCache->LocalFilePath(file.Path(), Info.cachePath,
686  (int)sizeof(Info.cachePath),
688  Info.ffReady);
689  if (rc == 0)
690  {Info.ffReady = true;
691  DEBUG("File in cache url=" <<Info.cacheURL);
692  return true;
693  }
694 
695 // File is not fully in the cache
696 //
697  Info.ffReady = false;
698  return false;
699 }
700 
701 /******************************************************************************/
702 /* O p e n d i r */
703 /******************************************************************************/
704 
705 DIR* XrdPosixXrootd::Opendir(const char *path)
706 {
707  XrdPosixDir *dP;
708  DIR *dirP;
709  int rc;
710 
711 // Get a new directory object
712 //
713  if (!(dP = new XrdPosixDir(path)))
715  return (DIR*)0;
716  }
717 
718 // Assign a file descriptor to this file
719 //
720  if (!(dP->AssignFD()))
721  {delete dP;
723  return (DIR*)0;
724  }
725 
726 // Open the directory
727 //
728  if ((dirP = dP->Open())) return dirP;
729 
730 // We failed
731 //
732  rc = errno;
733  delete dP;
734  errno = rc; // Restore saved errno
735  return (DIR *)0;
736 }
737 
738 /******************************************************************************/
739 /* P r e a d */
740 /******************************************************************************/
741 
742 ssize_t XrdPosixXrootd::Pread(int fildes, void *buf, size_t nbyte, off_t offset)
743 {
744  XrdPosixFile *fp;
745  long long offs, bytes;
746  int iosz;
747 
748 // Find the file object
749 //
750  if (!(fp = XrdPosixObject::File(fildes)))
751  return XrdPosixGlobals::ecMsg.SetErrno(EBADF);
752 
753 // Make sure the size is not too large
754 //
755  if (nbyte > (size_t)0x7fffffff)
756  return Fault(fp, EOVERFLOW, "read size too large");
757  else iosz = static_cast<int>(nbyte);
758 
759 // Issue the read
760 //
761  offs = static_cast<long long>(offset);
762  bytes = fp->XCio->Read((char *)buf, offs, (int)iosz);
763  if (bytes < 0) return Fault(fp,-bytes,"*");
764 
765 // All went well
766 //
767  fp->UnLock();
768  return (ssize_t)bytes;
769 }
770 
771 /******************************************************************************/
772 
773 void XrdPosixXrootd::Pread(int fildes, void *buf, size_t nbyte, off_t offset,
774  XrdPosixCallBackIO *cbp)
775 {
776  XrdPosixFile *fp;
777  long long offs;
778  int iosz;
779 
780 // Find the file object
781 //
782  if (!(fp = XrdPosixObject::File(fildes))) {cbp->Complete(-1); return;}
783 
784 // Make sure the size is not too large
785 //
786  if (nbyte > (size_t)0x7fffffff)
787  {fp->UnLock();
788  fp->ecMsg.SetErrno(EOVERFLOW,0,"read size too large");
789  cbp->Complete(-1);
790  return;
791  }
792 
793 // Prepare for the read
794 //
795  cbp->theFile = fp;
796  fp->Ref(); fp->UnLock();
797  iosz = static_cast<int>(nbyte);
798  offs = static_cast<long long>(offset);
799 
800 // Issue the read
801 //
802  fp->XCio->Read(*cbp, (char *)buf, offs, (int)iosz);
803 }
804 
805 /******************************************************************************/
806 /* P w r i t e */
807 /******************************************************************************/
808 
809 ssize_t XrdPosixXrootd::Pwrite(int fildes, const void *buf, size_t nbyte, off_t offset)
810 {
811  XrdPosixFile *fp;
812  long long offs;
813  int iosz, bytes;
814 
815 // Find the file object
816 //
817  if (!(fp = XrdPosixObject::File(fildes))) return -1;
818 
819 // Make sure the size is not too large
820 //
821  if (nbyte > (size_t)0x7fffffff)
822  return Fault(fp,EOVERFLOW,"write size too large");
823  else iosz = static_cast<int>(nbyte);
824 
825 // Issue the write
826 //
827  offs = static_cast<long long>(offset);
828  bytes = fp->XCio->Write((char *)buf, offs, (int)iosz);
829  if (bytes < 0) return Fault(fp,-bytes,"*");
830 
831 // All went well
832 //
833  fp->UpdtSize(offs + iosz);
834  fp->UnLock();
835  return (ssize_t)iosz;
836 }
837 
838 /******************************************************************************/
839 
840 void XrdPosixXrootd::Pwrite(int fildes, const void *buf, size_t nbyte,
841  off_t offset, XrdPosixCallBackIO *cbp)
842 {
843  XrdPosixFile *fp;
844  long long offs;
845  int iosz;
846 
847 // Find the file object
848 //
849  if (!(fp = XrdPosixObject::File(fildes))) {cbp->Complete(-1); return;}
850 
851 // Make sure the size is not too large
852 //
853  if (nbyte > (size_t)0x7fffffff)
854  {fp->UnLock();
855  fp->ecMsg.SetErrno(EOVERFLOW,0,"read size too large");
856  cbp->Complete(-1);
857  return;
858  }
859 
860 // Prepare for the writing
861 //
862  cbp->theFile = fp;
863  fp->Ref(); fp->UnLock();
864  iosz = static_cast<int>(nbyte);
865  offs = static_cast<long long>(offset);
866 
867 // Issue the read
868 //
869  fp->XCio->Write(*cbp, (char *)buf, offs, (int)iosz);
870 }
871 
872 /******************************************************************************/
873 /* R e a d */
874 /******************************************************************************/
875 
876 ssize_t XrdPosixXrootd::Read(int fildes, void *buf, size_t nbyte)
877 {
878  XrdPosixFile *fp;
879  long long bytes;
880  int iosz;
881 
882 // Find the file object
883 //
884  if (!(fp = XrdPosixObject::File(fildes))) return -1;
885 
886 // Make sure the size is not too large
887 //
888  if (nbyte > (size_t)0x7fffffff) return Fault(fp,EOVERFLOW);
889  else iosz = static_cast<int>(nbyte);
890 
891 // Issue the read
892 //
893  bytes = fp->XCio->Read((char *)buf,fp->Offset(),(int)iosz);
894  if (bytes < 0) return Fault(fp,-bytes);
895 
896 // All went well
897 //
898  fp->addOffset(bytes);
899  fp->UnLock();
900  return (ssize_t)bytes;
901 }
902 
903 /******************************************************************************/
904 /* R e a d v */
905 /******************************************************************************/
906 
907 ssize_t XrdPosixXrootd::Readv(int fildes, const struct iovec *iov, int iovcnt)
908 {
909  ssize_t bytes, totbytes = 0;
910  int i;
911 
912 // Return the results of the read for each iov segment
913 //
914  for (i = 0; i < iovcnt; i++)
915  {bytes = Read(fildes,(void *)iov[i].iov_base,(size_t)iov[i].iov_len);
916  if (bytes > 0) totbytes += bytes;
917  else if (bytes < 0) return -1;
918  else break;
919  }
920 
921 // All done
922 //
923  return totbytes;
924 }
925 
926 /******************************************************************************/
927 /* V R e a d */
928 /******************************************************************************/
929 
930 ssize_t XrdPosixXrootd::VRead(int fildes, const XrdOucIOVec *readV, int n)
931 {
932  XrdPosixFile *fp;
933  ssize_t bytes;
934 
935 // Find the file object
936 //
937  if (!(fp = XrdPosixObject::File(fildes))) return -1;
938 
939 // Issue the read
940 //
941  if ((bytes = fp->XCio->ReadV(readV, n)) < 0) return Fault(fp,-bytes);
942 
943 // Return bytes read
944 //
945  fp->UnLock();
946  return bytes;
947 }
948 
949 /******************************************************************************/
950 
951 void XrdPosixXrootd::VRead(int fildes, const XrdOucIOVec *readV, int n,
952  XrdPosixCallBackIO *cbp)
953 {
954  XrdPosixFile *fp;
955 
956 // Find the file object and issue read
957 //
958  if ((fp = XrdPosixObject::File(fildes)))
959  {cbp->theFile = fp;
960  fp->Ref(); fp->UnLock();
961  fp->XCio->ReadV(*cbp, readV, n);
962  } else cbp->Complete(-1);
963 }
964 
965 /******************************************************************************/
966 /* R e a d d i r */
967 /******************************************************************************/
968 
969 struct dirent* XrdPosixXrootd::Readdir(DIR *dirp)
970 {
971  dirent64 *dp64;
972  dirent *dp32; // Could be the same as dp64
973 
974  if (!(dp64 = Readdir64(dirp))) return 0;
975 
976  dp32 = (struct dirent *)dp64;
977  if ((char*)dp32->d_name != (char*)dp64->d_name)
978  {dp32->d_ino = dp64->d_ino;
979 #if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__GNU__) && !(defined(__FreeBSD_kernel__) && defined(__GLIBC__))
980  dp32->d_off = dp64->d_off;
981 #endif
982 #ifndef __solaris__
983  dp32->d_type = dp64->d_type;
984 #endif
985  dp32->d_reclen = dp64->d_reclen;
986  strcpy(dp32->d_name, dp64->d_name);
987  }
988  return dp32;
989 }
990 
991 struct dirent64* XrdPosixXrootd::Readdir64(DIR *dirp)
992 {
993  XrdPosixDir *dP;
994  dirent64 *dentP;
995  int rc, fildes = XrdPosixDir::dirNo(dirp);
996 
997 // Find the object
998 //
999  if (!(dP = XrdPosixObject::Dir(fildes)))
1001  return (dirent64*)0;
1002  }
1003 
1004 // Get the next directory entry
1005 //
1006  if (!(dentP = dP->nextEntry())) rc = dP->Status();
1007  else rc = 0;
1008 
1009 // Return the appropriate result
1010 //
1011  dP->UnLock();
1012  if (rc) errno = rc;
1013  return dentP;
1014 }
1015 
1016 /******************************************************************************/
1017 /* R e a d d i r _ r */
1018 /******************************************************************************/
1019 
1020 int XrdPosixXrootd::Readdir_r(DIR *dirp, struct dirent *entry,
1021  struct dirent **result)
1022 {
1023  dirent64 *dp64 = 0, d64ent;
1024  int rc;
1025 
1026  if ((rc = Readdir64_r(dirp, &d64ent, &dp64)) || !dp64)
1027  {*result = 0; return rc;}
1028 
1029  entry->d_ino = dp64->d_ino;
1030 #if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__GNU__) && !(defined(__FreeBSD_kernel__) && defined(__GLIBC__))
1031  entry->d_off = dp64->d_off;
1032 #endif
1033 #ifndef __solaris__
1034  entry->d_type = dp64->d_type;
1035 #endif
1036  entry->d_reclen = dp64->d_reclen;
1037  strcpy(entry->d_name, dp64->d_name);
1038  *result = entry;
1039  return rc;
1040 }
1041 
1042 int XrdPosixXrootd::Readdir64_r(DIR *dirp, struct dirent64 *entry,
1043  struct dirent64 **result)
1044 {
1045  XrdPosixDir *dP;
1046  int rc, fildes = XrdPosixDir::dirNo(dirp);
1047 
1048 // Find the object
1049 //
1050  if (!(dP = XrdPosixObject::Dir(fildes))) return EBADF;
1051 
1052 // Get the next entry
1053 //
1054  if (!(*result = dP->nextEntry(entry))) {rc = dP->Status(); *result = 0;}
1055  else {rc = 0; *result = entry;}
1056 
1057 // Return the appropriate result
1058 //
1059  dP->UnLock();
1060  return rc;
1061 }
1062 
1063 int XrdPosixXrootd::StatRet(DIR *dirp, struct stat *buf)
1064 {
1065 
1066 // Find the object
1067 //
1068  auto fildes = XrdPosixDir::dirNo(dirp);
1069  auto dP = XrdPosixObject::Dir(fildes);
1070  if (!dP) return EBADF;
1071 
1072 // Get the stat info
1073  auto rc = dP->StatRet(buf);
1074 
1075  dP->UnLock();
1076  return rc;
1077 }
1078 
1079 /******************************************************************************/
1080 /* R e n a m e */
1081 /******************************************************************************/
1082 
1083 int XrdPosixXrootd::Rename(const char *oldpath, const char *newpath)
1084 {
1085  XrdPosixAdmin admin(oldpath,XrdPosixGlobals::ecMsg);
1086  XrdCl::URL newUrl((std::string)newpath);
1087 
1088 // Make sure the admin is OK and the new url is valid
1089 //
1090  if (!admin.isOK() || !newUrl.IsValid())
1091  return XrdPosixGlobals::ecMsg.SetErrno(EINVAL);
1092 
1093 // Issue rename to he cache (it really should just deep-six both files)
1094 //
1096  {LfnPath oldF("rename", oldpath);
1097  LfnPath newF("rename", newpath);
1098  if (!oldF.path || !newF.path) return -1;
1099  XrdPosixGlobals::theCache->Rename(oldF.path, newF.path);
1100  }
1101 
1102 // Issue the rename
1103 //
1105  return EcRename(oldpath, newpath, admin);
1106 
1107  return XrdPosixMap::Result(admin.Xrd.Mv(admin.Url.GetPathWithParams(),
1108  newUrl.GetPathWithParams()),
1109  XrdPosixGlobals::ecMsg, true);
1110 }
1111 
1112 /******************************************************************************/
1113 /* R e w i n d d i r */
1114 /******************************************************************************/
1115 
1117 {
1118  XrdPosixDir *dP;
1119  int fildes = XrdPosixDir::dirNo(dirp);
1120 
1121 // Find the object and rewind it
1122 //
1123  if ((dP = XrdPosixObject::Dir(fildes)))
1124  {dP->rewind();
1125  dP->UnLock();
1126  }
1127 }
1128 
1129 /******************************************************************************/
1130 /* R m d i r */
1131 /******************************************************************************/
1132 
1133 int XrdPosixXrootd::Rmdir(const char *path)
1134 {
1136 
1137 // Make sure the admin is OK
1138 //
1139  if (!admin.isOK()) return -1;
1140 
1141 // Remove directory from the cache first
1142 //
1144  {LfnPath rmd("rmdir", path);
1145  if (!rmd.path) return -1;
1146  XrdPosixGlobals::theCache->Rmdir(rmd.path);
1147  }
1148 
1149 // Issue the rmdir
1150 //
1151  return XrdPosixMap::Result(admin.Xrd.RmDir(admin.Url.GetPathWithParams()),
1152  XrdPosixGlobals::ecMsg, true);
1153 }
1154 
1155 /******************************************************************************/
1156 /* S e e k d i r */
1157 /******************************************************************************/
1158 
1159 void XrdPosixXrootd::Seekdir(DIR *dirp, long loc)
1160 {
1161  XrdPosixDir *dP;
1162  int fildes = XrdPosixDir::dirNo(dirp);
1163 
1164 // Find the object
1165 //
1166  if (!(dP = XrdPosixObject::Dir(fildes))) return;
1167 
1168 // Sets the current directory position
1169 //
1170  if (dP->Unread() && !(dP->Open()))
1171  {if (loc >= dP->getEntries()) loc = dP->getEntries();
1172  else if (loc < 0) loc = 0;
1173  dP->setOffset(loc);
1174  }
1175  dP->UnLock();
1176 }
1177 
1178 /******************************************************************************/
1179 /* S t a t */
1180 /******************************************************************************/
1181 
1182 int XrdPosixXrootd::Stat(const char *path, struct stat *buf)
1183 {
1185  bool cacheChk = false;
1186 
1187 // Make sure the admin is OK
1188 //
1189  if (!admin.isOK()) return -1;
1190 
1191 // Initialize the stat buffer
1192 //
1194 
1195 // Check if we can get the stat informatation from the cache
1196 //
1198  {LfnPath statX("stat", path, false);
1199  if (!statX.path) return -1;
1200  int rc = XrdPosixGlobals::theCache->Stat(statX.path, *buf);
1201  if (!rc) return 0;
1202  if (rc < 0) {errno = -rc; return -1;} // does the cache set this???
1203  cacheChk = true;
1204  }
1205 
1206 // Issue the stat and verify that all went well
1207 //
1209  return EcStat(path, buf, admin);
1210 
1211  if (!admin.Stat(*buf)) return -1;
1212 
1213 // If we are here and the cache was checked then the file was not in the cache.
1214 // We informally tell the caller this is the case by setting atime to zero.
1215 // Normally, atime will never be zero in any other case.
1216 //
1217  if (cacheChk) buf->st_atime = 0;
1218  return 0;
1219 }
1220 
1221 /******************************************************************************/
1222 /* S t a t f s */
1223 /******************************************************************************/
1224 
1225 int XrdPosixXrootd::Statfs(const char *path, struct statfs *buf)
1226 {
1227  struct statvfs myVfs;
1228  int rc;
1229 
1230 // Issue a statvfs() call and transcribe the results
1231 //
1232  if ((rc = Statvfs(path, &myVfs))) return rc;
1233 
1234 // The vfs structure and fs structures should be size compatible (not really)
1235 //
1236  memset(buf, 0, sizeof(struct statfs));
1237  buf->f_bsize = myVfs.f_bsize;
1238  buf->f_blocks = myVfs.f_blocks;
1239  buf->f_bfree = myVfs.f_bfree;
1240  buf->f_files = myVfs.f_files;
1241  buf->f_ffree = myVfs.f_ffree;
1242 #if defined(__APPLE__) || defined(__FreeBSD__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__))
1243  buf->f_iosize = myVfs.f_frsize;
1244 #else
1245  buf->f_frsize = myVfs.f_frsize;
1246 #endif
1247 #if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__GNU__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__))
1248  buf->f_bavail = myVfs.f_bavail;
1249 #endif
1250 #if defined(__linux__) || defined(__GNU__)
1251  buf->f_namelen = myVfs.f_namemax;
1252 #elif defined(__FreeBSD__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__))
1253  buf->f_namemax = myVfs.f_namemax;
1254 #endif
1255  return 0;
1256 }
1257 
1258 /******************************************************************************/
1259 /* S t a t v f s */
1260 /******************************************************************************/
1261 
1262 int XrdPosixXrootd::Statvfs(const char *path, struct statvfs *buf)
1263 {
1264  static const int szVFS = sizeof(buf->f_bfree);
1265  static const long long max32 = 0x7fffffffLL;
1266 
1268  XrdCl::StatInfoVFS *vfsStat;
1269 
1270  long long rwFree, ssFree, rwBlks;
1271  int rwNum, ssNum, rwUtil, ssUtil;
1272 
1273 // Make sure we connected
1274 //
1275  if (!admin.isOK()) return -1;
1276 
1277 // Issue the statfvs call
1278 //
1280  vfsStat),
1281  XrdPosixGlobals::ecMsg) < 0) return -1;
1282 
1283 // Extract out the information
1284 //
1285  rwNum = static_cast<int>(vfsStat->GetNodesRW());
1286  rwFree = (long long)vfsStat->GetFreeRW();
1287  rwUtil = static_cast<int>(vfsStat->GetUtilizationRW());
1288  ssNum = static_cast<int>(vfsStat->GetNodesStaging());
1289  ssFree = (long long)vfsStat->GetFreeStaging();
1290  ssUtil = static_cast<int>(vfsStat->GetUtilizationStaging());
1291  delete vfsStat;
1292 
1293 // Calculate number of blocks
1294 //
1295  if (rwUtil == 0) rwBlks = rwFree;
1296  else if (rwUtil >= 100) rwBlks = 0;
1297  else rwBlks = rwFree * (100 / (100 - rwUtil));
1298  if (ssUtil == 0) rwBlks += ssFree;
1299  else if (ssUtil < 100) rwBlks += ssFree * (100 / (100 - ssUtil));
1300 
1301 // Scale units to what will fit here (we can have a 32-bit or 64-bit struct)
1302 //
1303  if (szVFS < 8)
1304  {if (rwBlks > max32) rwBlks = max32;
1305  if (rwFree > max32) rwFree = max32;
1306  if (ssFree > max32) ssFree = max32;
1307  }
1308 
1309 // Return what little we can
1310 //
1311  memset(buf, 0, sizeof(struct statvfs));
1312  buf->f_bsize = 1024*1024;
1313  buf->f_frsize = 1024*1024;
1314  buf->f_blocks = static_cast<fsblkcnt_t>(rwBlks);
1315  buf->f_bfree = static_cast<fsblkcnt_t>(rwFree + ssFree);
1316  buf->f_bavail = static_cast<fsblkcnt_t>(rwFree);
1317  buf->f_ffree = rwNum + ssNum;
1318  buf->f_favail = rwNum;
1319  buf->f_namemax = 255; // The best we are going to do here
1320  buf->f_flag = (rwNum == 0 ? ST_RDONLY|ST_NOSUID : ST_NOSUID);
1321  return 0;
1322 }
1323 
1324 /******************************************************************************/
1325 /* T e l l d i r */
1326 /******************************************************************************/
1327 
1329 {
1330  XrdPosixDir *dP;
1331  long pos;
1332  int fildes = XrdPosixDir::dirNo(dirp);
1333 
1334 // Find the object
1335 //
1336  if (!(dP = XrdPosixObject::Dir(fildes)))
1337  return XrdPosixGlobals::ecMsg.SetErrno(EBADF,0);
1338 
1339 // Tell the current directory location
1340 //
1341  pos = dP->getOffset();
1342  dP->UnLock();
1343  return pos;
1344 }
1345 
1346 /******************************************************************************/
1347 /* T r u n c a t e */
1348 /******************************************************************************/
1349 
1350 int XrdPosixXrootd::Truncate(const char *path, off_t Size)
1351 {
1353  uint64_t tSize = static_cast<uint64_t>(Size);
1354 
1355 // Make sure the admin is OK
1356 //
1357  if (!admin.isOK()) return -1;
1358 
1359 // Truncate in the cache first
1360 //
1362  {LfnPath trunc("truncate", path);
1363  if (!trunc.path) return -1;
1364  XrdPosixGlobals::theCache->Truncate(trunc.path, tSize);
1365  }
1366 
1367 // Issue the truncate to the origin
1368 //
1369  std::string urlp = admin.Url.GetPathWithParams();
1370  return XrdPosixMap::Result(admin.Xrd.Truncate(urlp,tSize),
1371  XrdPosixGlobals::ecMsg,true);
1372 }
1373 
1374 /******************************************************************************/
1375 /* U n l i n k */
1376 /******************************************************************************/
1377 
1378 int XrdPosixXrootd::Unlink(const char *path)
1379 {
1381 
1382 // Make sure the admin is OK
1383 //
1384  if (!admin.isOK()) return -1;
1385 
1386 // Unlink the cache first
1387 //
1389  {LfnPath remf("unlink", path);
1390  if (!remf.path) return -1;
1391  XrdPosixGlobals::theCache->Unlink(remf.path);
1392  }
1393 
1394 // Issue the UnLink
1395 //
1397  return EcUnlink(path, admin);
1398 
1399  return XrdPosixMap::Result(admin.Xrd.Rm(admin.Url.GetPathWithParams()),
1400  XrdPosixGlobals::ecMsg, true);
1401 }
1402 
1403 /******************************************************************************/
1404 /* W r i t e */
1405 /******************************************************************************/
1406 
1407 ssize_t XrdPosixXrootd::Write(int fildes, const void *buf, size_t nbyte)
1408 {
1409  XrdPosixFile *fp;
1410  int iosz, bytes;
1411 
1412 // Find the file object
1413 //
1414  if (!(fp = XrdPosixObject::File(fildes))) return -1;
1415 
1416 // Make sure the size is not too large
1417 //
1418  if (nbyte > (size_t)0x7fffffff) return Fault(fp,EOVERFLOW);
1419  else iosz = static_cast<int>(nbyte);
1420 
1421 // Issue the write
1422 //
1423  bytes = fp->XCio->Write((char *)buf,fp->Offset(),(int)iosz);
1424  if (bytes < 0) return Fault(fp,-bytes);
1425 
1426 // All went well
1427 //
1428  fp->addOffset(iosz, 1);
1429  fp->UnLock();
1430  return (ssize_t)iosz;
1431 }
1432 
1433 /******************************************************************************/
1434 /* W r i t e v */
1435 /******************************************************************************/
1436 
1437 ssize_t XrdPosixXrootd::Writev(int fildes, const struct iovec *iov, int iovcnt)
1438 {
1439  ssize_t totbytes = 0;
1440  int i;
1441 
1442 // Return the results of the write for each iov segment
1443 //
1444  for (i = 0; i < iovcnt; i++)
1445  {if (!Write(fildes,(void *)iov[i].iov_base,(size_t)iov[i].iov_len))
1446  return -1;
1447  totbytes += iov[i].iov_len;
1448  }
1449 
1450 // All done
1451 //
1452  return totbytes;
1453 }
1454 
1455 /******************************************************************************/
1456 /* i s X r o o t d D i r */
1457 /******************************************************************************/
1458 
1460 {
1461  XrdPosixDir *dP;
1462  int fildes;
1463 
1464  if (!dirp) return false;
1465  fildes = XrdPosixDir::dirNo(dirp);
1466 
1467  if (!myFD(fildes) || !(dP = XrdPosixObject::Dir(fildes))) return false;
1468 
1469  dP->UnLock();
1470  return true;
1471 }
1472 
1473 /******************************************************************************/
1474 /* m y F D */
1475 /******************************************************************************/
1476 
1478 {
1479  return XrdPosixObject::Valid(fd);
1480 }
1481 
1482 /******************************************************************************/
1483 /* Q u e r y C h k s u m */
1484 /******************************************************************************/
1485 
1486 int XrdPosixXrootd::QueryChksum(const char *path, time_t &Mtime,
1487  char *value, int vsize)
1488 {
1490 
1491 // Stat the file first to allow vectoring of the request to the right server
1492 //
1493  if (!admin.Stat(0, &Mtime)) return -1;
1494 
1495 // Now we can get the checksum as we have landed on the right server
1496 //
1497  return admin.Query(XrdCl::QueryCode::Checksum, value, vsize);
1498 }
1499 
1500 /******************************************************************************/
1501 /* Q u e r y E r r o r */
1502 /******************************************************************************/
1503 
1504 int XrdPosixXrootd::QueryError(std::string& emsg, int fd, bool reset)
1505 {
1506  XrdOucECMsg* ecmP;
1507 
1508 // If global wanted then use that one otherwise find the object specific one
1509 //
1510  if (fd < 0) ecmP = &XrdPosixGlobals::ecMsg;
1511  else {XrdPosixFile *fp;
1512  if (!(fp = XrdPosixObject::File(fd))) return -1;
1513  ecmP = fp->getECMsg();
1514  }
1515 
1516 // Return the message information
1517 //
1518  return ecmP->Get(emsg, reset);
1519 }
1520 
1521 /******************************************************************************/
1522 
1523 int XrdPosixXrootd::QueryError(std::string& emsg, DIR* dirP, bool reset)
1524 {
1525  XrdPosixDir *dP;
1526  int fildes = XrdPosixDir::dirNo(dirP);
1527 
1528 // Find the object
1529 //
1530  if (!(dP = XrdPosixObject::Dir(fildes)))
1531  return XrdPosixGlobals::ecMsg.SetErrno(EBADF);
1532 
1533 // Return result
1534 //
1535  return dP->getECMsg()->Get(emsg, reset);
1536 }
1537 
1538 /******************************************************************************/
1539 /* Q u e r y O p a q u e */
1540 /******************************************************************************/
1541 
1542 long long XrdPosixXrootd::QueryOpaque(const char *path, char *value, int size)
1543 {
1545 
1546 // Stat the file first to allow vectoring of the request to the right server
1547 //
1548  if (!admin.Stat()) return -1;
1549 
1550 // Now we can get the checksum as we have landed on the right server
1551 //
1552  return admin.Query(XrdCl::QueryCode::OpaqueFile, value, size);
1553 }
1554 
1555 /******************************************************************************/
1556 /* P r i v a t e M e t h o d s */
1557 /******************************************************************************/
1558 /******************************************************************************/
1559 /* F a u l t */
1560 /******************************************************************************/
1561 
1562 int XrdPosixXrootd::Fault(XrdPosixFile *fp, int ecode, const char *msg)
1563 {
1564  fp->UnLock();
1565  return XrdPosixGlobals::ecMsg.SetErrno(ecode, -1, msg);
1566 }
1567 
1568 /******************************************************************************/
1569 /* E c R e n a m e */
1570 /******************************************************************************/
1571 
1572 int XrdPosixXrootd::EcRename(const char *oldpath, const char *newpath,
1573  XrdPosixAdmin &admin)
1574 {
1575  XrdCl::URL url(oldpath);
1576  XrdCl::URL newUrl(newpath);
1577 
1578  std::string file = url.GetPath();
1579  XrdCl::LocationInfo *info = nullptr;
1580  XrdCl::FileSystem fs(oldpath);
1581 
1582  XrdCl::Buffer queryArgs(5), *queryResp = nullptr;
1583  queryArgs.FromString("role");
1584  XrdCl::XRootDStatus st = fs.Query(XrdCl::QueryCode::Config, queryArgs, queryResp);
1585  // xrootdfs call this function with individual servers. but we can only do
1586  // fs.DeepLocate("*"...) agaist a redirector
1587  // xrootdfs already did a stat and know that this is a file, not a dir
1588  if (!st.IsOK() || queryResp->ToString() == "server"
1589  || queryResp->ToString() == "server\n")
1590  {
1591  if (queryResp) delete queryResp;
1592  return XrdPosixMap::Result(admin.Xrd.Mv(admin.Url.GetPathWithParams(),
1593  newUrl.GetPathWithParams()),
1594  XrdPosixGlobals::ecMsg, true);
1595  }
1596  else
1597  if (queryResp) delete queryResp;
1598 
1599  st = fs.DeepLocate("*", XrdCl::OpenFlags::None, info );
1600  std::unique_ptr<XrdCl::LocationInfo> ptr( info );
1601  if( !st.IsOK() )
1602  return XrdPosixMap::Result(st, XrdPosixGlobals::ecMsg, true);
1603 
1604  // check if this is a file or a dir, do not support dir renaming in EC
1605  struct stat buf;
1606  if (XrdPosixXrootd::Stat(oldpath, &buf) != 0)
1607  return XrdPosixGlobals::ecMsg.SetErrno(ENOENT);
1608 
1609  if ( ! S_ISREG(buf.st_mode))
1610  return XrdPosixGlobals::ecMsg.SetErrno(ENOTSUP);
1611 
1612  if (XrdPosixXrootd::Stat(newpath, &buf) == 0)
1613  return XrdPosixGlobals::ecMsg.SetErrno(EEXIST);
1614 
1615  int rc = -ENOENT;
1616  for( size_t i = 0; i < info->GetSize(); ++i )
1617  {
1618  std::string url_i = "root://" + info->At(i).GetAddress() + "/" + file;
1619  XrdPosixAdmin *admin_i = new XrdPosixAdmin(url_i.c_str(),admin.ecMsg);
1620  int x = XrdPosixMap::Result(admin_i->Xrd.Mv(admin_i->Url.GetPathWithParams(),
1621  newUrl.GetPathWithParams()),
1622  admin.ecMsg);
1623  if (x != -ENOENT && rc != 0)
1624  rc = x;
1625  if (admin_i) delete admin_i;
1626  }
1627  return rc;
1628 }
1629 
1630 /******************************************************************************/
1631 /* E c S t a t */
1632 /******************************************************************************/
1633 
1634 int XrdPosixXrootd::EcStat(const char *path, struct stat *buf,
1635  XrdPosixAdmin &admin)
1636 {
1637  XrdCl::URL url(path);
1638  std::string file = url.GetPath();
1639  XrdCl::LocationInfo *info = nullptr;
1640  XrdCl::FileSystem fs(path);
1641 
1642  std::vector<std::string> xattrkeys;
1643  std::vector<XrdCl::XAttr> xattrvals;
1644  xattrkeys.push_back("xrdec.strpver");
1645  xattrkeys.push_back("xrdec.filesize");
1646 
1647  XrdCl::Buffer queryArgs(5), *queryResp = nullptr;
1648  queryArgs.FromString("role");
1649  XrdCl::XRootDStatus st = fs.Query(XrdCl::QueryCode::Config, queryArgs, queryResp);
1650  // xrootdfs call this function with individual servers. but we can only do
1651  // // fs.DeepLocate("*"...) agaist a redirector
1652  if (!st.IsOK() || queryResp->ToString() == "server"
1653  || queryResp->ToString() == "server\n")
1654  {
1655  if (queryResp) delete queryResp;
1656  if (!admin.Stat(*buf))
1657  return -1;
1658  else
1659  {
1660  st = fs.GetXAttr(file, xattrkeys, xattrvals, 0);
1661  if (! xattrvals[0].value.empty())
1662  {
1663  std::stringstream sstream0(xattrvals[0].value);
1664  sstream0 >> buf->st_mtime;
1665  std::stringstream sstream1(xattrvals[1].value);
1666  sstream1 >> buf->st_size;
1667  buf->st_blocks = (buf->st_size + 512)/512;
1668  }
1669  return 0;
1670  }
1671  }
1672  else
1673  if (queryResp) delete queryResp;
1674 
1675  st = fs.DeepLocate("*", XrdCl::OpenFlags::None, info );
1676  std::unique_ptr<XrdCl::LocationInfo> ptr( info );
1677  if( !st.IsOK() )
1678  {
1679  errno = ENOENT;
1680  return -1;
1681  }
1682 
1683  int found = 0;
1684  uint64_t verNumMax = 0;
1685  struct stat buf_i;
1686  XrdPosixConfig::initStat(&buf_i);
1687  for( size_t i = 0; i < info->GetSize(); ++i )
1688  {
1689  std::string url_i = "root://" + info->At(i).GetAddress() + "/" + file;
1690  XrdPosixAdmin *admin_i = new XrdPosixAdmin(url_i.c_str(),admin.ecMsg);
1691 
1692  if (admin_i->Stat(buf_i))
1693  {
1694  if (! S_ISREG(buf_i.st_mode))
1695  {
1696  memcpy(buf, &buf_i, sizeof(struct stat));
1697  if (admin_i) delete admin_i;
1698  return 0;
1699  }
1700  else
1701  {
1702  if (verNumMax == 0) memcpy(buf, &buf_i, sizeof(struct stat));
1703  found = 1;
1704  }
1705  XrdCl::FileSystem *fs_i = new XrdCl::FileSystem(info->At( i ).GetAddress());
1706 
1707  xattrvals.clear();
1708  st = fs_i->GetXAttr(file, xattrkeys, xattrvals, 0);
1709  if (! xattrvals[0].value.empty())
1710  {
1711  std::stringstream sstream(xattrvals[0].value);
1712  uint64_t verNum;
1713  sstream >> verNum;
1714  if ( verNum > verNumMax )
1715  {
1716  verNumMax = verNum;
1717  memcpy(buf, &buf_i, sizeof(struct stat));
1718  buf->st_mtime = verNumMax; // assume verNum is mtime
1719  std::stringstream sstream(xattrvals[1].value);
1720  sstream >> buf->st_size;
1721  buf->st_blocks = (buf->st_size + 512)/512;
1722  }
1723  }
1724  if (fs_i) delete fs_i;
1725  }
1726  if (admin_i) delete admin_i;
1727  }
1728  if (! found)
1729  {
1730  errno = ENOENT;
1731  return -1;
1732  }
1733  return 0;
1734 }
1735 
1736 /******************************************************************************/
1737 /* E c U n l i n k */
1738 /******************************************************************************/
1739 
1740 int XrdPosixXrootd::EcUnlink(const char *path, XrdPosixAdmin &admin)
1741 {
1742  XrdCl::URL url(path);
1743  std::string file = url.GetPath();
1744  XrdCl::LocationInfo *info = nullptr;
1745  XrdCl::FileSystem fs(path);
1746 
1747  XrdCl::Buffer queryArgs(5), *queryResp = nullptr;
1748  queryArgs.FromString("role");
1749  XrdCl::XRootDStatus st = fs.Query(XrdCl::QueryCode::Config, queryArgs, queryResp);
1750  // xrootdfs call this function with individual servers. but we can only do
1751  // fs.DeepLocate("*"...) agaist a redirector
1752  if (!st.IsOK() || queryResp->ToString() == "server"
1753  || queryResp->ToString() == "server\n")
1754  {
1755  if (queryResp) delete queryResp;
1756  return XrdPosixMap::Result(admin.Xrd.Rm(admin.Url.GetPathWithParams()),
1757  admin.ecMsg, true);
1758  }
1759  else
1760  if (queryResp) delete queryResp;
1761 
1762  st = fs.DeepLocate("*", XrdCl::OpenFlags::None, info );
1763  std::unique_ptr<XrdCl::LocationInfo> ptr( info );
1764  if( !st.IsOK() )
1765  return XrdPosixMap::Result(st, admin.ecMsg, true);
1766 
1767  int rc = -ENOENT;
1768  for( size_t i = 0; i < info->GetSize(); ++i )
1769  {
1770  std::string url_i = "root://" + info->At(i).GetAddress() + "/" + file;
1771  XrdPosixAdmin *admin_i = new XrdPosixAdmin(url_i.c_str(),admin.ecMsg);
1772  int x = XrdPosixMap::Result(admin_i->
1773  Xrd.Rm(admin_i->Url.GetPathWithParams()),
1774  admin.ecMsg);
1775  if (x != -ENOENT && rc != 0)
1776  rc = x;
1777  if (admin_i) delete admin_i;
1778  }
1779  return rc;
1780 }
#define ENOATTR
Definition: XProtocol.hh:1343
#define DEBUG(x)
Definition: XrdBwmTrace.hh:54
#define EPNAME(x)
Definition: XrdBwmTrace.hh:56
#define TRACE_Debug
Definition: XrdCmsTrace.hh:37
std::string obfuscateAuth(const std::string &input)
int stat(const char *path, struct stat *buf)
int statvfs(const char *path, struct statvfs *buf)
int statfs(const char *path, struct statfs *buf)
#define DEBUGON
XrdVERSIONINFO(XrdPosix, XrdPosix)
int emsg(int rc, char *msg)
Binary blob representation.
Definition: XrdClBuffer.hh:34
void FromString(const std::string str)
Fill the buffer from a string.
Definition: XrdClBuffer.hh:205
std::string ToString() const
Convert the buffer to a string.
Definition: XrdClBuffer.hh:215
Send file/filesystem queries to an XRootD cluster.
XRootDStatus RmDir(const std::string &path, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus Mv(const std::string &source, const std::string &dest, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus Rm(const std::string &path, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus GetXAttr(const std::string &path, const std::vector< std::string > &attrs, ResponseHandler *handler, uint16_t timeout=0)
XRootDStatus Truncate(const std::string &path, uint64_t size, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus MkDir(const std::string &path, MkDirFlags::Flags flags, Access::Mode mode, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus StatVFS(const std::string &path, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
bool IsOpen() const
Check if the file is open.
Definition: XrdClFile.cc:846
XRootDStatus Open(const std::string &url, OpenFlags::Flags flags, Access::Mode mode, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
Definition: XrdClFile.cc:99
bool GetProperty(const std::string &name, std::string &value) const
Definition: XrdClFile.cc:878
const std::string & GetAddress() const
Get address.
Path location info.
uint32_t GetSize() const
Get number of locations.
Location & At(uint32_t index)
Get the location at index.
Handle an async response.
uint64_t GetFreeRW() const
Get size of the largest contiguous area of free r/w space (in MB)
uint64_t GetNodesStaging() const
Get number of nodes that can provide staging space.
uint8_t GetUtilizationStaging() const
Get percentage of the partition utilization represented by FreeStaging.
uint64_t GetFreeStaging() const
Get size of the largest contiguous area of free staging space (in MB)
uint8_t GetUtilizationRW() const
Get percentage of the partition utilization represented by FreeRW.
uint64_t GetNodesRW() const
Get number of nodes that can provide read/write space.
URL representation.
Definition: XrdClURL.hh:31
std::string GetPathWithParams() const
Get the path with params.
Definition: XrdClURL.cc:318
bool IsValid() const
Is the url valid.
Definition: XrdClURL.cc:452
int GetPort() const
Get the target port.
Definition: XrdClURL.hh:188
virtual int Read(char *buff, long long offs, int rlen)=0
virtual int Fstat(struct stat &sbuff)
Definition: XrdOucCache.hh:148
virtual int Write(char *buff, long long offs, int wlen)=0
virtual int Sync()=0
virtual long long FSize()=0
virtual bool Detach(XrdOucCacheIOCD &iocd)=0
virtual int Trunc(long long offs)=0
virtual int ReadV(const XrdOucIOVec *readV, int rnum)
Definition: XrdOucCache.cc:86
virtual int Rename(const char *oldp, const char *newp)
Definition: XrdOucCache.hh:610
virtual int Stat(const char *url, struct stat &sbuff)
Definition: XrdOucCache.hh:638
virtual int Truncate(const char *path, off_t size)
Definition: XrdOucCache.hh:651
virtual int Unlink(const char *path)
Definition: XrdOucCache.hh:663
virtual int LocalFilePath(const char *url, char *buff=0, int blen=0, LFP_Reason why=ForAccess, bool forall=false)
Definition: XrdOucCache.hh:572
virtual int Prepare(const char *url, int oflags, mode_t mode)
Definition: XrdOucCache.hh:597
virtual int Rmdir(const char *dirp)
Definition: XrdOucCache.hh:622
int Get(std::string &ecm, bool rst=true)
Definition: XrdOucECMsg.cc:41
int SetErrno(int ecc, int retval=-1, const char *alt=0)
Definition: XrdOucECMsg.cc:144
void Put(const char *varname, const char *value)
Definition: XrdOucEnv.hh:85
bool ClientConfig(const char *pfx, bool hush=false)
Definition: XrdOucPsx.cc:100
bool Stat(mode_t *flags=0, time_t *mtime=0)
XrdCl::FileSystem Xrd
XrdOucECMsg & ecMsg
int Query(XrdCl::QueryCode::Code reqCode, void *buff, int bsz)
XrdCl::URL Url
virtual void Complete(ssize_t Result)=0
An abstract class to define a callback for Open() call.
virtual void Complete(int Result)=0
static void initStat(struct stat *buf)
static bool SetConfig(XrdOucPsx &parms)
static int dirNo(DIR *dirP)
Definition: XrdPosixDir.hh:61
void rewind()
Definition: XrdPosixDir.hh:78
long getOffset()
Definition: XrdPosixDir.hh:65
DIR * Open()
Definition: XrdPosixDir.cc:111
bool Unread()
Definition: XrdPosixDir.hh:84
dirent64 * nextEntry(dirent64 *dp=0)
Definition: XrdPosixDir.cc:48
void setOffset(long offset)
Definition: XrdPosixDir.hh:67
int Status()
Definition: XrdPosixDir.hh:82
long getEntries()
Definition: XrdPosixDir.hh:63
const char * Path() override
static const int isUpdt
static const int isStrm
XrdPosixPrepIO * PrepIO
Definition: XrdPosixFile.hh:66
void UpdtSize(size_t newsz)
long long addOffset(long long offs, int updtSz=0)
Definition: XrdPosixFile.hh:69
int Fstat(struct stat &buf) override
const char * Origin()
bool Close(XrdCl::XRootDStatus &Status)
XrdCl::File clFile
Definition: XrdPosixFile.hh:67
XrdOucCacheIO * XCio
Definition: XrdPosixFile.hh:65
long long Offset()
bool Finalize(XrdCl::XRootDStatus *Status)
long long setOffset(long long offs)
static void * DelayedDestroy(void *)
static int Result(const XrdCl::XRootDStatus &Status, XrdOucECMsg &ecMsg, bool retneg1=false)
Definition: XrdPosixMap.cc:185
static XrdCl::Access::Mode Mode2Access(mode_t mode)
Definition: XrdPosixMap.cc:165
XrdOucECMsg * getECMsg()
static void Shutdown()
bool AssignFD(bool isStream=false)
static XrdPosixDir * Dir(int fildes, bool glk=false)
static XrdPosixDir * ReleaseDir(int fildes)
static int Init(int numfd)
static XrdPosixFile * ReleaseFile(int fildes)
static bool Valid(int fd)
static bool CanStream()
XrdOucECMsg ecMsg
static XrdPosixFile * File(int fildes, bool glk=false)
void Count(long long &Dest)
static const char * P2L(const char *who, const char *inP, char *&relP, bool ponly=false)
static ssize_t Readv(int fildes, const struct iovec *iov, int iovcnt)
Readv() conforms to POSIX.1-2001 readv()
static ssize_t Pread(int fildes, void *buf, size_t nbyte, off_t offset)
Pread() conforms to POSIX.1-2001 pread()
static int Closedir(DIR *dirp)
Closedir() conforms to POSIX.1-2001 closedir()
static void Seekdir(DIR *dirp, long loc)
Seekdir() conforms to POSIX.1-2001 seekdir()
static const int isStream
static int Stat(const char *path, struct stat *buf)
Stat() conforms to POSIX.1-2001 stat()
static int QueryChksum(const char *path, time_t &mtime, char *buff, int blen)
static int Mkdir(const char *path, mode_t mode)
Mkdir() conforms to POSIX.1-2001 mkdir()
static int Unlink(const char *path)
Unlink() conforms to POSIX.1-2001 unlink()
static int Rmdir(const char *path)
Rmdir() conforms to POSIX.1-2001 rmdir()
static void Rewinddir(DIR *dirp)
Rewinddir() conforms to POSIX.1-2001 rewinddir()
static void VRead(int fildes, const XrdOucIOVec *readV, int n, XrdPosixCallBackIO *cbp)
static int Rename(const char *oldpath, const char *newpath)
Rename() conforms to POSIX.1-2001 rename()
static int Close(int fildes)
Close() conforms to POSIX.1-2001 close()
static int Statvfs(const char *path, struct statvfs *buf)
Statvfs() conforms to POSIX.1-2001 statvfs()
static int endPoint(int FD, char *Buff, int Blen)
static ssize_t Write(int fildes, const void *buf, size_t nbyte)
Write() conforms to POSIX.1-2001 write()
static struct dirent * Readdir(DIR *dirp)
static int Readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
static ssize_t Writev(int fildes, const struct iovec *iov, int iovcnt)
Writev() conforms to POSIX.1-2001 writev()
static int QueryError(std::string &emsg, int fd=-1, bool reset=true)
static struct dirent64 * Readdir64(DIR *dirp)
XrdPosixXrootd(int maxfd=255, int maxdir=0, int maxthr=0)
static bool myFD(int fd)
static int Ftruncate(int fildes, off_t offset)
Ftruncate() conforms to POSIX.1-2001 ftruncate()
static long Telldir(DIR *dirp)
Telldir() conforms to POSIX.1-2001 telldir()
static bool isXrootdDir(DIR *dirp)
static int Access(const char *path, int amode)
Access() conforms to POSIX.1-2001 access()
static DIR * Opendir(const char *path)
Opendir() conforms to POSIX.1-2001 opendir()
static int Fsync(int fildes)
Fsync() conforms to POSIX.1-2001 fsync()
static int StatRet(DIR *dirp, struct stat *buf)
static long long Getxattr(const char *path, const char *name, void *value, unsigned long long size)
static long long QueryOpaque(const char *path, char *buff, int blen)
static int Statfs(const char *path, struct statfs *buf)
static int Readdir64_r(DIR *dirp, struct dirent64 *entry, struct dirent64 **result)
static ssize_t Read(int fildes, void *buf, size_t nbyte)
Read() conforms to POSIX.1-2001 read()
static int Fstat(int fildes, struct stat *buf)
Fstat() conforms to POSIX.1-2001 fstat()
static off_t Lseek(int fildes, off_t offset, int whence)
Lseek() conforms to POSIX.1-2001 lseek()
static int Open(const char *path, int oflag, mode_t mode=0, XrdPosixCallBack *cbP=0)
static ssize_t Pwrite(int fildes, const void *buf, size_t nbyte, off_t offset)
Pwrite() conforms to POSIX.1-2001 pwrite()
static int Truncate(const char *path, off_t offset)
Telldir() conforms to POSIX.1-2001 telldir()
int Opts
Definition: XrdMpxStats.cc:58
XrdScheduler * schedP
XrdSysLogger * theLogger
XrdPosixStats Stats
Definition: XrdPosixFile.cc:64
thread_local XrdOucECMsg ecMsg
XrdSysError * eDest
Definition: XrdPosixFile.cc:63
XrdOucCache * theCache
XrdOucName2Name * theN2N
Definition: XrdPosixFile.cc:62
XrdSysTrace Trace
XrdCl::DirListFlags::Flags dlFlag
Definition: XrdPosixDir.cc:41
Mode
Access mode.
@ None
Nothing special.
@ None
Nothing special.
@ MakePath
create the entire directory tree if it doesn't exist
Flags
Open flags, may be or'd when appropriate.
@ Read
Open only for reading.
@ Update
Open for reading and writing.
Code
XRootD query request codes.
@ OpaqueFile
Implementation dependent.
@ XAttr
Query file extended attributes.
@ Config
Query server configuration.
@ Checksum
Query file checksum.
@ Space
Query logical space stats.
bool IsOK() const
We're fine.
Definition: XrdClStatus.hh:124
std::string ToString() const
Create a string representation.
Definition: XrdClStatus.cc:97