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 c n t l */
367 /******************************************************************************/
368 
370  const std::string& args,
371  std::string& resp)
372 {
373  XrdPosixFile *fp;
374 
375 // Find the file object
376 //
377  if (!(fp = XrdPosixObject::File(fildes))) return -1;
378 
379 // At the moment we support nothing
380 //
381  resp = "Function not supported.";
382  errno = ENOTSUP;
383  return -1;
384 }
385 
386 /******************************************************************************/
387 /* F s t a t */
388 /******************************************************************************/
389 
390 int XrdPosixXrootd::Fstat(int fildes, struct stat *buf)
391 {
392  XrdPosixFile *fp;
393  int rc;
394 
395 // Find the file object
396 //
397  if (!(fp = XrdPosixObject::File(fildes))) return -1;
398 
399 // First initialize the stat buffer
400 //
402 
403 // Check if we can get the stat information from the cache.
404 //
405  rc = fp->XCio->Fstat(*buf);
406  if (rc <= 0)
407  {fp->UnLock();
408  if (!rc) return 0;
409  errno = -rc; //???
410  return -1;
411  }
412 
413 // At this point we can call the file's Fstat() and if the file is not open
414 // it will be opened.
415 //
416  rc = fp->Fstat(*buf);
417  fp->UnLock();
418  if (rc < 0) {errno = -rc; rc = -1;}
419  return rc;
420 }
421 
422 /******************************************************************************/
423 /* F s y n c */
424 /******************************************************************************/
425 
426 int XrdPosixXrootd::Fsync(int fildes)
427 {
428  XrdPosixFile *fp;
429  int rc;
430 
431 // Find the file object
432 //
433  if (!(fp = XrdPosixObject::File(fildes))) return -1;
434 
435 // Do the sync
436 //
437  if ((rc = fp->XCio->Sync()) < 0) return Fault(fp, -rc);
438  fp->UnLock();
439  return 0;
440 }
441 
442 /******************************************************************************/
443 
445 {
446  XrdPosixFile *fp;
447 
448 // Find the file object and do the sync
449 //
450  if ((fp = XrdPosixObject::File(fildes)))
451  {cbp->theFile = fp;
452  fp->Ref(); fp->UnLock();
453  fp->XCio->Sync(*cbp);
454  } else cbp->Complete(-1);
455 }
456 
457 /******************************************************************************/
458 /* F t r u n c a t e */
459 /******************************************************************************/
460 
461 int XrdPosixXrootd::Ftruncate(int fildes, off_t offset)
462 {
463  XrdPosixFile *fp;
464  int rc;
465 
466 // Find the file object
467 //
468  if (!(fp = XrdPosixObject::File(fildes))) return -1;
469 
470 // Do the trunc
471 //
472  if ((rc = fp->XCio->Trunc(offset)) < 0) return Fault(fp, -rc);
473  fp->UnLock();
474  return 0;
475 }
476 
477 /******************************************************************************/
478 /* G e t x a t t r */
479 /******************************************************************************/
480 
481 #ifndef ENOATTR
482 #define ENOATTR ENOTSUP
483 #endif
484 
485 long long XrdPosixXrootd::Getxattr (const char *path, const char *name,
486  void *value, unsigned long long size)
487 {
489  XrdCl::QueryCode::Code reqCode;
490  int vsize = static_cast<int>(size);
491 
492 // Check if user just wants the maximum length needed
493 //
494  if (size == 0) return 1024;
495 
496 // Check if we support the query
497 //
498  if (name)
499  { if (!strcmp(name,"xroot.cksum")) reqCode=XrdCl::QueryCode::Checksum;
500  else if (!strcmp(name,"xroot.space")) reqCode=XrdCl::QueryCode::Space;
501  else if (!strcmp(name,"xroot.xattr")) reqCode=XrdCl::QueryCode::XAttr;
502  else {errno = ENOATTR; return -1;} //???
503  }else {errno = EINVAL; return -1;}
504 
505 // Stat the file first to allow vectoring of the request to the right server
506 //
507  if (!admin.Stat()) return -1;
508 
509 // Return the result
510 //
511  return admin.Query(reqCode, value, vsize);
512 }
513 
514 /******************************************************************************/
515 /* L s e e k */
516 /******************************************************************************/
517 
518 off_t XrdPosixXrootd::Lseek(int fildes, off_t offset, int whence)
519 {
520  XrdPosixFile *fp;
521  long long curroffset;
522 
523 // Find the file object
524 //
525  if (!(fp = XrdPosixObject::File(fildes))) return -1;
526 
527 // Set the new offset. Note that SEEK_END requires that the file be opened.
528 // An open may occur by calling the FSize() method via the cache pointer.
529 //
530  if (whence == SEEK_SET) curroffset = fp->setOffset(offset);
531  else if (whence == SEEK_CUR) curroffset = fp->addOffset(offset);
532  else if (whence == SEEK_END)
533  {curroffset = fp->XCio->FSize();
534  if (curroffset < 0) return Fault(fp,static_cast<int>(-curroffset));
535  curroffset = fp->setOffset(curroffset+offset);
536  }
537  else return Fault(fp, EINVAL);
538 
539 // All done
540 //
541  fp->UnLock();
542  return curroffset;
543 }
544 
545 /******************************************************************************/
546 /* M k d i r */
547 /******************************************************************************/
548 
549 int XrdPosixXrootd::Mkdir(const char *path, mode_t mode)
550 {
553 
554 // Preferentially make the whole path unless told otherwise
555 //
556  flags = (mode & S_ISUID ? XrdCl::MkDirFlags::None
558 
559 // Make sure the admin is OK
560 //
561  if (!admin.isOK()) return -1;
562 
563 // Issue the mkdir
564 //
565  return XrdPosixMap::Result(admin.Xrd.MkDir(admin.Url.GetPathWithParams(),
566  flags,
569  );
570 }
571 
572 /******************************************************************************/
573 /* O p e n */
574 /******************************************************************************/
575 
576 int XrdPosixXrootd::Open(const char *path, int oflags, mode_t mode,
577  XrdPosixCallBack *cbP)
578 {
579  return Open(path, oflags, mode, cbP, 0);
580 }
581 
582 int XrdPosixXrootd::Open(const char *path, int oflags, mode_t mode,
583  XrdPosixCallBack *cbP, XrdPosixInfo *infoP)
584 {
585  EPNAME("Open");
586  XrdCl::XRootDStatus Status;
587  XrdPosixFile *fp;
589  XrdCl::OpenFlags::Flags XOflags;
590  int Opts;
591  bool aOK, isRO = false;
592 
593 // Translate R/W and R/O flags
594 //
595  if ((oflags & O_ACCMODE) != O_RDONLY)
597  XOflags = XrdCl::OpenFlags::Update;
598  } else {
599  Opts = 0;
600  XOflags = XrdCl::OpenFlags::Read;
601  isRO = true;
602  }
603 
604 // Pass along the stream flag
605 //
606  if (oflags & isStream)
608  return XrdPosixGlobals::ecMsg.SetErrno(EMFILE);
609  }
610 
611 // Translate create vs simple open. Always make dirpath on create!
612 //
613  if (oflags & O_CREAT)
614  {XOflags |= (oflags & O_EXCL ? XrdCl::OpenFlags::New
616  XOflags |= XrdCl::OpenFlags::MakePath;
617  XOmode = XrdPosixMap::Mode2Access(mode);
618  }
619  else if (oflags & O_TRUNC && Opts & XrdPosixFile::isUpdt)
620  XOflags |= XrdCl::OpenFlags::Delete;
621 
622 // Allocate the new file object
623 //
624  if (!(fp = new XrdPosixFile(aOK, path, cbP, Opts)))
625  return XrdPosixGlobals::ecMsg.SetErrno(EMFILE);
626 
627 // Check if all went well during allocation
628 //
629  if (!aOK) {delete fp; return -1;}
630 
631 // If we have a cache, then issue a prepare as the cache may want to defer the
632 // open request ans we have a lot more work to do.
633 //
635  {int rc;
636  if (infoP && isRO && OpenCache(*fp, *infoP))
637  {delete fp;
638  errno = 0;
639  return -3;
640  }
641  rc = XrdPosixGlobals::theCache->Prepare(fp->Path(), oflags, mode);
642  if (rc > 0) return OpenDefer(fp, cbP, XOflags, XOmode, oflags&isStream);
643  if (rc < 0) {delete fp; return XrdPosixGlobals::ecMsg.SetErrno(-rc);}
644  }
645 
646 // Open the file (sync or async)
647 //
649  if (!cbP) Status = fp->clFile.Open((std::string)path, XOflags, XOmode);
650  else Status = fp->clFile.Open((std::string)path, XOflags, XOmode,
651  (XrdCl::ResponseHandler *)fp);
652 
653 // If we failed, return the reason
654 //
655  if (!Status.IsOK())
657  int rc = XrdPosixMap::Result(Status,XrdPosixGlobals::ecMsg,false);
658  if (DEBUGON && rc != -ENOENT && rc != -ELOOP)
659  {DEBUG(XrdPosixGlobals::ecMsg.Msg() <<" open " << obfuscateAuth(fp->Origin()));}
660  delete fp;
661  errno = -rc; // Saved errno across the delete
662  return -1;
663  }
664 
665 // Assign a file descriptor to this file
666 //
667  if (!(fp->AssignFD(oflags & isStream)))
668  {delete fp;
669  return XrdPosixGlobals::ecMsg.SetErrno(EMFILE);
670  }
671 
672 // Finalize the open (this gets the stat info). For async opens, the
673 // finalization is deferred until the callback happens.
674 //
675  if (cbP) {errno = EINPROGRESS; return -1;}
676  if (fp->Finalize(&Status)) return fp->FDNum();
677 
678 // At this point the open() has failed as we could neither defer nor finalize.
679 // We need to delete the file pointer and come up with a rational errno as a
680 // file descriptor should not be returned. We need to return the causal error
681 // message and errno. It is considered impossible for no error state to exist.
682 //
683  delete fp;
684  if (XrdPosixMap::Result(Status,XrdPosixGlobals::ecMsg,true)) return -1;
685 
686 // The impossible happened, there is no error state. So, create a suitable one.
687 // Note that our error text will be included as contextual information since
688 // ENOMSG, while logically correct, provides no useful information.
689 //
690  XrdPosixGlobals::ecMsg = "Impossible condition detected!";
691  XrdPosixGlobals::ecMsg = errno = ENOMSG;
692  return -1;
693 }
694 
695 /******************************************************************************/
696 /* Private: O p e n C a c h e */
697 /******************************************************************************/
698 
699 bool XrdPosixXrootd::OpenCache(XrdPosixFile &file,XrdPosixInfo &Info)
700 {
701  EPNAME("OpenCache");
702  int rc;
703 
704 // Check if the full file is in the cache
705 //
706  rc = XrdPosixGlobals::theCache->LocalFilePath(file.Path(), Info.cachePath,
707  (int)sizeof(Info.cachePath),
709  Info.ffReady);
710  if (rc == 0)
711  {Info.ffReady = true;
712  DEBUG("File in cache url=" <<Info.cacheURL);
713  return true;
714  }
715 
716 // File is not fully in the cache
717 //
718  Info.ffReady = false;
719  return false;
720 }
721 
722 /******************************************************************************/
723 /* O p e n d i r */
724 /******************************************************************************/
725 
726 DIR* XrdPosixXrootd::Opendir(const char *path)
727 {
728  XrdPosixDir *dP;
729  DIR *dirP;
730  int rc;
731 
732 // Get a new directory object
733 //
734  if (!(dP = new XrdPosixDir(path)))
736  return (DIR*)0;
737  }
738 
739 // Assign a file descriptor to this file
740 //
741  if (!(dP->AssignFD()))
742  {delete dP;
744  return (DIR*)0;
745  }
746 
747 // Open the directory
748 //
749  if ((dirP = dP->Open())) return dirP;
750 
751 // We failed
752 //
753  rc = errno;
754  delete dP;
755  errno = rc; // Restore saved errno
756  return (DIR *)0;
757 }
758 
759 /******************************************************************************/
760 /* P r e a d */
761 /******************************************************************************/
762 
763 ssize_t XrdPosixXrootd::Pread(int fildes, void *buf, size_t nbyte, off_t offset)
764 {
765  XrdPosixFile *fp;
766  long long offs, bytes;
767  int iosz;
768 
769 // Find the file object
770 //
771  if (!(fp = XrdPosixObject::File(fildes)))
772  return XrdPosixGlobals::ecMsg.SetErrno(EBADF);
773 
774 // Make sure the size is not too large
775 //
776  if (nbyte > (size_t)0x7fffffff)
777  return Fault(fp, EOVERFLOW, "read size too large");
778  else iosz = static_cast<int>(nbyte);
779 
780 // Issue the read
781 //
782  offs = static_cast<long long>(offset);
783  bytes = fp->XCio->Read((char *)buf, offs, (int)iosz);
784  if (bytes < 0) return Fault(fp,-bytes,"*");
785 
786 // All went well
787 //
788  fp->UnLock();
789  return (ssize_t)bytes;
790 }
791 
792 /******************************************************************************/
793 
794 void XrdPosixXrootd::Pread(int fildes, void *buf, size_t nbyte, off_t offset,
795  XrdPosixCallBackIO *cbp)
796 {
797  XrdPosixFile *fp;
798  long long offs;
799  int iosz;
800 
801 // Find the file object
802 //
803  if (!(fp = XrdPosixObject::File(fildes))) {cbp->Complete(-1); return;}
804 
805 // Make sure the size is not too large
806 //
807  if (nbyte > (size_t)0x7fffffff)
808  {fp->UnLock();
809  fp->ecMsg.SetErrno(EOVERFLOW,0,"read size too large");
810  cbp->Complete(-1);
811  return;
812  }
813 
814 // Prepare for the read
815 //
816  cbp->theFile = fp;
817  fp->Ref(); fp->UnLock();
818  iosz = static_cast<int>(nbyte);
819  offs = static_cast<long long>(offset);
820 
821 // Issue the read
822 //
823  fp->XCio->Read(*cbp, (char *)buf, offs, (int)iosz);
824 }
825 
826 /******************************************************************************/
827 /* P w r i t e */
828 /******************************************************************************/
829 
830 ssize_t XrdPosixXrootd::Pwrite(int fildes, const void *buf, size_t nbyte, off_t offset)
831 {
832  XrdPosixFile *fp;
833  long long offs;
834  int iosz, bytes;
835 
836 // Find the file object
837 //
838  if (!(fp = XrdPosixObject::File(fildes))) return -1;
839 
840 // Make sure the size is not too large
841 //
842  if (nbyte > (size_t)0x7fffffff)
843  return Fault(fp,EOVERFLOW,"write size too large");
844  else iosz = static_cast<int>(nbyte);
845 
846 // Issue the write
847 //
848  offs = static_cast<long long>(offset);
849  bytes = fp->XCio->Write((char *)buf, offs, (int)iosz);
850  if (bytes < 0) return Fault(fp,-bytes,"*");
851 
852 // All went well
853 //
854  fp->UpdtSize(offs + iosz);
855  fp->UnLock();
856  return (ssize_t)iosz;
857 }
858 
859 /******************************************************************************/
860 
861 void XrdPosixXrootd::Pwrite(int fildes, const void *buf, size_t nbyte,
862  off_t offset, XrdPosixCallBackIO *cbp)
863 {
864  XrdPosixFile *fp;
865  long long offs;
866  int iosz;
867 
868 // Find the file object
869 //
870  if (!(fp = XrdPosixObject::File(fildes))) {cbp->Complete(-1); return;}
871 
872 // Make sure the size is not too large
873 //
874  if (nbyte > (size_t)0x7fffffff)
875  {fp->UnLock();
876  fp->ecMsg.SetErrno(EOVERFLOW,0,"read size too large");
877  cbp->Complete(-1);
878  return;
879  }
880 
881 // Prepare for the writing
882 //
883  cbp->theFile = fp;
884  fp->Ref(); fp->UnLock();
885  iosz = static_cast<int>(nbyte);
886  offs = static_cast<long long>(offset);
887 
888 // Issue the read
889 //
890  fp->XCio->Write(*cbp, (char *)buf, offs, (int)iosz);
891 }
892 
893 /******************************************************************************/
894 /* R e a d */
895 /******************************************************************************/
896 
897 ssize_t XrdPosixXrootd::Read(int fildes, void *buf, size_t nbyte)
898 {
899  XrdPosixFile *fp;
900  long long bytes;
901  int iosz;
902 
903 // Find the file object
904 //
905  if (!(fp = XrdPosixObject::File(fildes))) return -1;
906 
907 // Make sure the size is not too large
908 //
909  if (nbyte > (size_t)0x7fffffff) return Fault(fp,EOVERFLOW);
910  else iosz = static_cast<int>(nbyte);
911 
912 // Issue the read
913 //
914  bytes = fp->XCio->Read((char *)buf,fp->Offset(),(int)iosz);
915  if (bytes < 0) return Fault(fp,-bytes);
916 
917 // All went well
918 //
919  fp->addOffset(bytes);
920  fp->UnLock();
921  return (ssize_t)bytes;
922 }
923 
924 /******************************************************************************/
925 /* R e a d v */
926 /******************************************************************************/
927 
928 ssize_t XrdPosixXrootd::Readv(int fildes, const struct iovec *iov, int iovcnt)
929 {
930  ssize_t bytes, totbytes = 0;
931  int i;
932 
933 // Return the results of the read for each iov segment
934 //
935  for (i = 0; i < iovcnt; i++)
936  {bytes = Read(fildes,(void *)iov[i].iov_base,(size_t)iov[i].iov_len);
937  if (bytes > 0) totbytes += bytes;
938  else if (bytes < 0) return -1;
939  else break;
940  }
941 
942 // All done
943 //
944  return totbytes;
945 }
946 
947 /******************************************************************************/
948 /* V R e a d */
949 /******************************************************************************/
950 
951 ssize_t XrdPosixXrootd::VRead(int fildes, const XrdOucIOVec *readV, int n)
952 {
953  XrdPosixFile *fp;
954  ssize_t bytes;
955 
956 // Find the file object
957 //
958  if (!(fp = XrdPosixObject::File(fildes))) return -1;
959 
960 // Issue the read
961 //
962  if ((bytes = fp->XCio->ReadV(readV, n)) < 0) return Fault(fp,-bytes);
963 
964 // Return bytes read
965 //
966  fp->UnLock();
967  return bytes;
968 }
969 
970 /******************************************************************************/
971 
972 void XrdPosixXrootd::VRead(int fildes, const XrdOucIOVec *readV, int n,
973  XrdPosixCallBackIO *cbp)
974 {
975  XrdPosixFile *fp;
976 
977 // Find the file object and issue read
978 //
979  if ((fp = XrdPosixObject::File(fildes)))
980  {cbp->theFile = fp;
981  fp->Ref(); fp->UnLock();
982  fp->XCio->ReadV(*cbp, readV, n);
983  } else cbp->Complete(-1);
984 }
985 
986 /******************************************************************************/
987 /* R e a d d i r */
988 /******************************************************************************/
989 
990 struct dirent* XrdPosixXrootd::Readdir(DIR *dirp)
991 {
992  dirent64 *dp64;
993  dirent *dp32; // Could be the same as dp64
994 
995  if (!(dp64 = Readdir64(dirp))) return 0;
996 
997  dp32 = (struct dirent *)dp64;
998  if ((char*)dp32->d_name != (char*)dp64->d_name)
999  {dp32->d_ino = dp64->d_ino;
1000 #if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__GNU__) && !(defined(__FreeBSD_kernel__) && defined(__GLIBC__))
1001  dp32->d_off = dp64->d_off;
1002 #endif
1003 #ifndef __solaris__
1004  dp32->d_type = dp64->d_type;
1005 #endif
1006  dp32->d_reclen = dp64->d_reclen;
1007  strcpy(dp32->d_name, dp64->d_name);
1008  }
1009  return dp32;
1010 }
1011 
1012 struct dirent64* XrdPosixXrootd::Readdir64(DIR *dirp)
1013 {
1014  XrdPosixDir *dP;
1015  dirent64 *dentP;
1016  int rc, fildes = XrdPosixDir::dirNo(dirp);
1017 
1018 // Find the object
1019 //
1020  if (!(dP = XrdPosixObject::Dir(fildes)))
1022  return (dirent64*)0;
1023  }
1024 
1025 // Get the next directory entry
1026 //
1027  if (!(dentP = dP->nextEntry())) rc = dP->Status();
1028  else rc = 0;
1029 
1030 // Return the appropriate result
1031 //
1032  dP->UnLock();
1033  if (rc) errno = rc;
1034  return dentP;
1035 }
1036 
1037 /******************************************************************************/
1038 /* R e a d d i r _ r */
1039 /******************************************************************************/
1040 
1041 int XrdPosixXrootd::Readdir_r(DIR *dirp, struct dirent *entry,
1042  struct dirent **result)
1043 {
1044  dirent64 *dp64 = 0, d64ent;
1045  int rc;
1046 
1047  if ((rc = Readdir64_r(dirp, &d64ent, &dp64)) || !dp64)
1048  {*result = 0; return rc;}
1049 
1050  entry->d_ino = dp64->d_ino;
1051 #if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__GNU__) && !(defined(__FreeBSD_kernel__) && defined(__GLIBC__))
1052  entry->d_off = dp64->d_off;
1053 #endif
1054 #ifndef __solaris__
1055  entry->d_type = dp64->d_type;
1056 #endif
1057  entry->d_reclen = dp64->d_reclen;
1058  strcpy(entry->d_name, dp64->d_name);
1059  *result = entry;
1060  return rc;
1061 }
1062 
1063 int XrdPosixXrootd::Readdir64_r(DIR *dirp, struct dirent64 *entry,
1064  struct dirent64 **result)
1065 {
1066  XrdPosixDir *dP;
1067  int rc, fildes = XrdPosixDir::dirNo(dirp);
1068 
1069 // Find the object
1070 //
1071  if (!(dP = XrdPosixObject::Dir(fildes))) return EBADF;
1072 
1073 // Get the next entry
1074 //
1075  if (!(*result = dP->nextEntry(entry))) {rc = dP->Status(); *result = 0;}
1076  else {rc = 0; *result = entry;}
1077 
1078 // Return the appropriate result
1079 //
1080  dP->UnLock();
1081  return rc;
1082 }
1083 
1084 /******************************************************************************/
1085 /* R e n a m e */
1086 /******************************************************************************/
1087 
1088 int XrdPosixXrootd::Rename(const char *oldpath, const char *newpath)
1089 {
1090  XrdPosixAdmin admin(oldpath,XrdPosixGlobals::ecMsg);
1091  XrdCl::URL newUrl((std::string)newpath);
1092 
1093 // Make sure the admin is OK and the new url is valid
1094 //
1095  if (!admin.isOK() || !newUrl.IsValid())
1096  return XrdPosixGlobals::ecMsg.SetErrno(EINVAL);
1097 
1098 // Issue rename to he cache (it really should just deep-six both files)
1099 //
1101  {LfnPath oldF("rename", oldpath);
1102  LfnPath newF("rename", newpath);
1103  if (!oldF.path || !newF.path) return -1;
1104  XrdPosixGlobals::theCache->Rename(oldF.path, newF.path);
1105  }
1106 
1107 // Issue the rename
1108 //
1110  return EcRename(oldpath, newpath, admin);
1111 
1112  return XrdPosixMap::Result(admin.Xrd.Mv(admin.Url.GetPathWithParams(),
1113  newUrl.GetPathWithParams()),
1114  XrdPosixGlobals::ecMsg, true);
1115 }
1116 
1117 /******************************************************************************/
1118 /* R e w i n d d i r */
1119 /******************************************************************************/
1120 
1122 {
1123  XrdPosixDir *dP;
1124  int fildes = XrdPosixDir::dirNo(dirp);
1125 
1126 // Find the object and rewind it
1127 //
1128  if ((dP = XrdPosixObject::Dir(fildes)))
1129  {dP->rewind();
1130  dP->UnLock();
1131  }
1132 }
1133 
1134 /******************************************************************************/
1135 /* R m d i r */
1136 /******************************************************************************/
1137 
1138 int XrdPosixXrootd::Rmdir(const char *path)
1139 {
1141 
1142 // Make sure the admin is OK
1143 //
1144  if (!admin.isOK()) return -1;
1145 
1146 // Remove directory from the cache first
1147 //
1149  {LfnPath rmd("rmdir", path);
1150  if (!rmd.path) return -1;
1151  XrdPosixGlobals::theCache->Rmdir(rmd.path);
1152  }
1153 
1154 // Issue the rmdir
1155 //
1156  return XrdPosixMap::Result(admin.Xrd.RmDir(admin.Url.GetPathWithParams()),
1157  XrdPosixGlobals::ecMsg, true);
1158 }
1159 
1160 /******************************************************************************/
1161 /* S e e k d i r */
1162 /******************************************************************************/
1163 
1164 void XrdPosixXrootd::Seekdir(DIR *dirp, long loc)
1165 {
1166  XrdPosixDir *dP;
1167  int fildes = XrdPosixDir::dirNo(dirp);
1168 
1169 // Find the object
1170 //
1171  if (!(dP = XrdPosixObject::Dir(fildes))) return;
1172 
1173 // Sets the current directory position
1174 //
1175  if (dP->Unread() && !(dP->Open()))
1176  {if (loc >= dP->getEntries()) loc = dP->getEntries();
1177  else if (loc < 0) loc = 0;
1178  dP->setOffset(loc);
1179  }
1180  dP->UnLock();
1181 }
1182 
1183 /******************************************************************************/
1184 /* S t a t */
1185 /******************************************************************************/
1186 
1187 int XrdPosixXrootd::Stat(const char *path, struct stat *buf)
1188 {
1190  bool cacheChk = false;
1191 
1192 // Make sure the admin is OK
1193 //
1194  if (!admin.isOK()) return -1;
1195 
1196 // Initialize the stat buffer
1197 //
1199 
1200 // Check if we can get the stat informatation from the cache
1201 //
1203  {LfnPath statX("stat", path, false);
1204  if (!statX.path) return -1;
1205  int rc = XrdPosixGlobals::theCache->Stat(statX.path, *buf);
1206  if (!rc) return 0;
1207  if (rc < 0) {errno = -rc; return -1;} // does the cache set this???
1208  cacheChk = true;
1209  }
1210 
1211 // Issue the stat and verify that all went well
1212 //
1214  return EcStat(path, buf, admin);
1215 
1216  if (!admin.Stat(*buf)) return -1;
1217 
1218 // If we are here and the cache was checked then the file was not in the cache.
1219 // We informally tell the caller this is the case by setting atime to zero.
1220 // Normally, atime will never be zero in any other case.
1221 //
1222  if (cacheChk) buf->st_atime = 0;
1223  return 0;
1224 }
1225 
1226 /******************************************************************************/
1227 /* S t a t f s */
1228 /******************************************************************************/
1229 
1230 int XrdPosixXrootd::Statfs(const char *path, struct statfs *buf)
1231 {
1232  struct statvfs myVfs;
1233  int rc;
1234 
1235 // Issue a statvfs() call and transcribe the results
1236 //
1237  if ((rc = Statvfs(path, &myVfs))) return rc;
1238 
1239 // The vfs structure and fs structures should be size compatible (not really)
1240 //
1241  memset(buf, 0, sizeof(struct statfs));
1242  buf->f_bsize = myVfs.f_bsize;
1243  buf->f_blocks = myVfs.f_blocks;
1244  buf->f_bfree = myVfs.f_bfree;
1245  buf->f_files = myVfs.f_files;
1246  buf->f_ffree = myVfs.f_ffree;
1247 #if defined(__APPLE__) || defined(__FreeBSD__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__))
1248  buf->f_iosize = myVfs.f_frsize;
1249 #else
1250  buf->f_frsize = myVfs.f_frsize;
1251 #endif
1252 #if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__GNU__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__))
1253  buf->f_bavail = myVfs.f_bavail;
1254 #endif
1255 #if defined(__linux__) || defined(__GNU__)
1256  buf->f_namelen = myVfs.f_namemax;
1257 #elif defined(__FreeBSD__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__))
1258  buf->f_namemax = myVfs.f_namemax;
1259 #endif
1260  return 0;
1261 }
1262 
1263 /******************************************************************************/
1264 /* S t a t R e t */
1265 /******************************************************************************/
1266 
1267 int XrdPosixXrootd::StatRet(DIR *dirp, struct stat *buf)
1268 {
1269 // Find the object
1270 //
1271  auto fildes = XrdPosixDir::dirNo(dirp);
1272  auto dP = XrdPosixObject::Dir(fildes);
1273  if (!dP) return EBADF;
1274 
1275 // Get the stat info
1276  auto rc = dP->StatRet(buf);
1277 
1278  dP->UnLock();
1279  return rc;
1280 }
1281 
1282 /******************************************************************************/
1283 /* S t a t v f s */
1284 /******************************************************************************/
1285 
1286 int XrdPosixXrootd::Statvfs(const char *path, struct statvfs *buf)
1287 {
1288  static const int szVFS = sizeof(buf->f_bfree);
1289  static const long long max32 = 0x7fffffffLL;
1290 
1292  XrdCl::StatInfoVFS *vfsStat;
1293 
1294  long long rwFree, ssFree, rwBlks;
1295  int rwNum, ssNum, rwUtil, ssUtil;
1296 
1297 // Make sure we connected
1298 //
1299  if (!admin.isOK()) return -1;
1300 
1301 // Issue the statfvs call
1302 //
1304  vfsStat),
1305  XrdPosixGlobals::ecMsg) < 0) return -1;
1306 
1307 // Extract out the information
1308 //
1309  rwNum = static_cast<int>(vfsStat->GetNodesRW());
1310  rwFree = (long long)vfsStat->GetFreeRW();
1311  rwUtil = static_cast<int>(vfsStat->GetUtilizationRW());
1312  ssNum = static_cast<int>(vfsStat->GetNodesStaging());
1313  ssFree = (long long)vfsStat->GetFreeStaging();
1314  ssUtil = static_cast<int>(vfsStat->GetUtilizationStaging());
1315  delete vfsStat;
1316 
1317 // Calculate number of blocks
1318 //
1319  if (rwUtil == 0) rwBlks = rwFree;
1320  else if (rwUtil >= 100) rwBlks = 0;
1321  else rwBlks = rwFree * (100 / (100 - rwUtil));
1322  if (ssUtil == 0) rwBlks += ssFree;
1323  else if (ssUtil < 100) rwBlks += ssFree * (100 / (100 - ssUtil));
1324 
1325 // Scale units to what will fit here (we can have a 32-bit or 64-bit struct)
1326 //
1327  if (szVFS < 8)
1328  {if (rwBlks > max32) rwBlks = max32;
1329  if (rwFree > max32) rwFree = max32;
1330  if (ssFree > max32) ssFree = max32;
1331  }
1332 
1333 // Return what little we can
1334 //
1335  memset(buf, 0, sizeof(struct statvfs));
1336  buf->f_bsize = 1024*1024;
1337  buf->f_frsize = 1024*1024;
1338  buf->f_blocks = static_cast<fsblkcnt_t>(rwBlks);
1339  buf->f_bfree = static_cast<fsblkcnt_t>(rwFree + ssFree);
1340  buf->f_bavail = static_cast<fsblkcnt_t>(rwFree);
1341  buf->f_ffree = rwNum + ssNum;
1342  buf->f_favail = rwNum;
1343  buf->f_namemax = 255; // The best we are going to do here
1344  buf->f_flag = (rwNum == 0 ? ST_RDONLY|ST_NOSUID : ST_NOSUID);
1345  return 0;
1346 }
1347 
1348 /******************************************************************************/
1349 /* T e l l d i r */
1350 /******************************************************************************/
1351 
1353 {
1354  XrdPosixDir *dP;
1355  long pos;
1356  int fildes = XrdPosixDir::dirNo(dirp);
1357 
1358 // Find the object
1359 //
1360  if (!(dP = XrdPosixObject::Dir(fildes)))
1361  return XrdPosixGlobals::ecMsg.SetErrno(EBADF,0);
1362 
1363 // Tell the current directory location
1364 //
1365  pos = dP->getOffset();
1366  dP->UnLock();
1367  return pos;
1368 }
1369 
1370 /******************************************************************************/
1371 /* T r u n c a t e */
1372 /******************************************************************************/
1373 
1374 int XrdPosixXrootd::Truncate(const char *path, off_t Size)
1375 {
1377  uint64_t tSize = static_cast<uint64_t>(Size);
1378 
1379 // Make sure the admin is OK
1380 //
1381  if (!admin.isOK()) return -1;
1382 
1383 // Truncate in the cache first
1384 //
1386  {LfnPath trunc("truncate", path);
1387  if (!trunc.path) return -1;
1388  XrdPosixGlobals::theCache->Truncate(trunc.path, tSize);
1389  }
1390 
1391 // Issue the truncate to the origin
1392 //
1393  std::string urlp = admin.Url.GetPathWithParams();
1394  return XrdPosixMap::Result(admin.Xrd.Truncate(urlp,tSize),
1395  XrdPosixGlobals::ecMsg,true);
1396 }
1397 
1398 /******************************************************************************/
1399 /* U n l i n k */
1400 /******************************************************************************/
1401 
1402 int XrdPosixXrootd::Unlink(const char *path)
1403 {
1405 
1406 // Make sure the admin is OK
1407 //
1408  if (!admin.isOK()) return -1;
1409 
1410 // Unlink the cache first
1411 //
1413  {LfnPath remf("unlink", path);
1414  if (!remf.path) return -1;
1415  XrdPosixGlobals::theCache->Unlink(remf.path);
1416  }
1417 
1418 // Issue the UnLink
1419 //
1421  return EcUnlink(path, admin);
1422 
1423  return XrdPosixMap::Result(admin.Xrd.Rm(admin.Url.GetPathWithParams()),
1424  XrdPosixGlobals::ecMsg, true);
1425 }
1426 
1427 /******************************************************************************/
1428 /* W r i t e */
1429 /******************************************************************************/
1430 
1431 ssize_t XrdPosixXrootd::Write(int fildes, const void *buf, size_t nbyte)
1432 {
1433  XrdPosixFile *fp;
1434  int iosz, bytes;
1435 
1436 // Find the file object
1437 //
1438  if (!(fp = XrdPosixObject::File(fildes))) return -1;
1439 
1440 // Make sure the size is not too large
1441 //
1442  if (nbyte > (size_t)0x7fffffff) return Fault(fp,EOVERFLOW);
1443  else iosz = static_cast<int>(nbyte);
1444 
1445 // Issue the write
1446 //
1447  bytes = fp->XCio->Write((char *)buf,fp->Offset(),(int)iosz);
1448  if (bytes < 0) return Fault(fp,-bytes);
1449 
1450 // All went well
1451 //
1452  fp->addOffset(iosz, 1);
1453  fp->UnLock();
1454  return (ssize_t)iosz;
1455 }
1456 
1457 /******************************************************************************/
1458 /* W r i t e v */
1459 /******************************************************************************/
1460 
1461 ssize_t XrdPosixXrootd::Writev(int fildes, const struct iovec *iov, int iovcnt)
1462 {
1463  ssize_t totbytes = 0;
1464  int i;
1465 
1466 // Return the results of the write for each iov segment
1467 //
1468  for (i = 0; i < iovcnt; i++)
1469  {if (!Write(fildes,(void *)iov[i].iov_base,(size_t)iov[i].iov_len))
1470  return -1;
1471  totbytes += iov[i].iov_len;
1472  }
1473 
1474 // All done
1475 //
1476  return totbytes;
1477 }
1478 
1479 /******************************************************************************/
1480 /* i s X r o o t d D i r */
1481 /******************************************************************************/
1482 
1484 {
1485  XrdPosixDir *dP;
1486  int fildes;
1487 
1488  if (!dirp) return false;
1489  fildes = XrdPosixDir::dirNo(dirp);
1490 
1491  if (!myFD(fildes) || !(dP = XrdPosixObject::Dir(fildes))) return false;
1492 
1493  dP->UnLock();
1494  return true;
1495 }
1496 
1497 /******************************************************************************/
1498 /* m y F D */
1499 /******************************************************************************/
1500 
1502 {
1503  return XrdPosixObject::Valid(fd);
1504 }
1505 
1506 /******************************************************************************/
1507 /* Q u e r y C h k s u m */
1508 /******************************************************************************/
1509 
1510 int XrdPosixXrootd::QueryChksum(const char *path, time_t &Mtime,
1511  char *value, int vsize)
1512 {
1514 
1515 // Stat the file first to allow vectoring of the request to the right server
1516 //
1517  if (!admin.Stat(0, &Mtime)) return -1;
1518 
1519 // Now we can get the checksum as we have landed on the right server
1520 //
1521  return admin.Query(XrdCl::QueryCode::Checksum, value, vsize);
1522 }
1523 
1524 /******************************************************************************/
1525 /* Q u e r y E r r o r */
1526 /******************************************************************************/
1527 
1528 int XrdPosixXrootd::QueryError(std::string& emsg, int fd, bool reset)
1529 {
1530  XrdOucECMsg* ecmP;
1531  XrdPosixFile* fp = 0;
1532 
1533 // If global wanted then use that one otherwise find the object specific one
1534 //
1535  if (fd < 0) ecmP = &XrdPosixGlobals::ecMsg;
1536  else {if (!(fp = XrdPosixObject::File(fd))) return -1;
1537  ecmP = fp->getECMsg();
1538  }
1539 
1540 // Return the message information
1541 //
1542  const int rc = ecmP->Get(emsg, reset);
1543  if (fp) fp->UnLock();
1544  return rc;
1545 }
1546 
1547 /******************************************************************************/
1548 
1549 int XrdPosixXrootd::QueryError(std::string& emsg, DIR* dirP, bool reset)
1550 {
1551  XrdPosixDir *dP;
1552  int fildes = XrdPosixDir::dirNo(dirP);
1553 
1554 // Find the object
1555 //
1556  if (!(dP = XrdPosixObject::Dir(fildes)))
1557  return XrdPosixGlobals::ecMsg.SetErrno(EBADF);
1558 
1559 // Return result
1560 //
1561  return dP->getECMsg()->Get(emsg, reset);
1562 }
1563 
1564 /******************************************************************************/
1565 /* Q u e r y O p a q u e */
1566 /******************************************************************************/
1567 
1568 long long XrdPosixXrootd::QueryOpaque(const char *path, char *value, int size)
1569 {
1571 
1572 // Stat the file first to allow vectoring of the request to the right server
1573 //
1574  if (!admin.Stat()) return -1;
1575 
1576 // Now we can get the checksum as we have landed on the right server
1577 //
1578  return admin.Query(XrdCl::QueryCode::OpaqueFile, value, size);
1579 }
1580 
1581 /******************************************************************************/
1582 /* P r i v a t e M e t h o d s */
1583 /******************************************************************************/
1584 /******************************************************************************/
1585 /* F a u l t */
1586 /******************************************************************************/
1587 
1588 int XrdPosixXrootd::Fault(XrdPosixFile *fp, int ecode, const char *msg)
1589 {
1590  fp->UnLock();
1591  return XrdPosixGlobals::ecMsg.SetErrno(ecode, -1, msg);
1592 }
1593 
1594 /******************************************************************************/
1595 /* E c R e n a m e */
1596 /******************************************************************************/
1597 
1598 int XrdPosixXrootd::EcRename(const char *oldpath, const char *newpath,
1599  XrdPosixAdmin &admin)
1600 {
1601  XrdCl::URL url(oldpath);
1602  XrdCl::URL newUrl(newpath);
1603 
1604  std::string file = url.GetPath();
1605  XrdCl::LocationInfo *info = nullptr;
1606  XrdCl::FileSystem fs(oldpath);
1607 
1608  XrdCl::Buffer queryArgs(5), *queryResp = nullptr;
1609  queryArgs.FromString("role");
1610  XrdCl::XRootDStatus st = fs.Query(XrdCl::QueryCode::Config, queryArgs, queryResp);
1611  // xrootdfs call this function with individual servers. but we can only do
1612  // fs.DeepLocate("*"...) agaist a redirector
1613  // xrootdfs already did a stat and know that this is a file, not a dir
1614  if (!st.IsOK() || queryResp->ToString() == "server"
1615  || queryResp->ToString() == "server\n")
1616  {
1617  if (queryResp) delete queryResp;
1618  return XrdPosixMap::Result(admin.Xrd.Mv(admin.Url.GetPathWithParams(),
1619  newUrl.GetPathWithParams()),
1620  XrdPosixGlobals::ecMsg, true);
1621  }
1622  else
1623  if (queryResp) delete queryResp;
1624 
1625  st = fs.DeepLocate("*", XrdCl::OpenFlags::PrefName, info );
1626  std::unique_ptr<XrdCl::LocationInfo> ptr( info );
1627  if( !st.IsOK() )
1628  return XrdPosixMap::Result(st, XrdPosixGlobals::ecMsg, true);
1629 
1630  // check if this is a file or a dir, do not support dir renaming in EC
1631  struct stat buf;
1632  if (XrdPosixXrootd::Stat(oldpath, &buf) != 0)
1633  return XrdPosixGlobals::ecMsg.SetErrno(ENOENT);
1634 
1635  if ( ! S_ISREG(buf.st_mode))
1636  return XrdPosixGlobals::ecMsg.SetErrno(ENOTSUP);
1637 
1638  if (XrdPosixXrootd::Stat(newpath, &buf) == 0)
1639  return XrdPosixGlobals::ecMsg.SetErrno(EEXIST);
1640 
1641  int rc = -ENOENT;
1642  for( size_t i = 0; i < info->GetSize(); ++i )
1643  {
1644  std::string url_i = "root://" + info->At(i).GetAddress() + "/" + file;
1645  XrdPosixAdmin *admin_i = new XrdPosixAdmin(url_i.c_str(),admin.ecMsg);
1646  int x = XrdPosixMap::Result(admin_i->Xrd.Mv(admin_i->Url.GetPathWithParams(),
1647  newUrl.GetPathWithParams()),
1648  admin.ecMsg);
1649  if (x != -ENOENT && rc != 0)
1650  rc = x;
1651  if (admin_i) delete admin_i;
1652  }
1653  return rc;
1654 }
1655 
1656 /******************************************************************************/
1657 /* E c S t a t */
1658 /******************************************************************************/
1659 
1660 int XrdPosixXrootd::EcStat(const char *path, struct stat *buf,
1661  XrdPosixAdmin &admin)
1662 {
1663  XrdCl::URL url(path);
1664  std::string file = url.GetPath();
1665  XrdCl::LocationInfo *info = nullptr;
1666  XrdCl::FileSystem fs(path);
1667 
1668  std::vector<std::string> xattrkeys;
1669  std::vector<XrdCl::XAttr> xattrvals;
1670  xattrkeys.push_back("xrdec.strpver");
1671  xattrkeys.push_back("xrdec.filesize");
1672 
1673  XrdCl::Buffer queryArgs(5), *queryResp = nullptr;
1674  queryArgs.FromString("role");
1675  XrdCl::XRootDStatus st = fs.Query(XrdCl::QueryCode::Config, queryArgs, queryResp);
1676  // xrootdfs call this function with individual servers. but we can only do
1677  // // fs.DeepLocate("*"...) agaist a redirector
1678  if (!st.IsOK() || queryResp->ToString() == "server"
1679  || queryResp->ToString() == "server\n")
1680  {
1681  if (queryResp) delete queryResp;
1682  if (!admin.Stat(*buf))
1683  return -1;
1684  else
1685  {
1686  st = fs.GetXAttr(file, xattrkeys, xattrvals, 0);
1687  if (! xattrvals[0].value.empty())
1688  {
1689  std::stringstream sstream0(xattrvals[0].value);
1690  sstream0 >> buf->st_mtime;
1691  std::stringstream sstream1(xattrvals[1].value);
1692  sstream1 >> buf->st_size;
1693  buf->st_blocks = (buf->st_size + 512)/512;
1694  }
1695  return 0;
1696  }
1697  }
1698  else
1699  if (queryResp) delete queryResp;
1700 
1701  st = fs.DeepLocate("*", XrdCl::OpenFlags::PrefName, info );
1702  std::unique_ptr<XrdCl::LocationInfo> ptr( info );
1703  if( !st.IsOK() )
1704  {
1705  errno = ENOENT;
1706  return -1;
1707  }
1708 
1709  int found = 0;
1710  uint64_t verNumMax = 0;
1711  struct stat buf_i;
1712  XrdPosixConfig::initStat(&buf_i);
1713  for( size_t i = 0; i < info->GetSize(); ++i )
1714  {
1715  std::string url_i = "root://" + info->At(i).GetAddress() + "/" + file;
1716  XrdPosixAdmin *admin_i = new XrdPosixAdmin(url_i.c_str(),admin.ecMsg);
1717 
1718  if (admin_i->Stat(buf_i))
1719  {
1720  if (! S_ISREG(buf_i.st_mode))
1721  {
1722  memcpy(buf, &buf_i, sizeof(struct stat));
1723  if (admin_i) delete admin_i;
1724  return 0;
1725  }
1726  else
1727  {
1728  if (verNumMax == 0) memcpy(buf, &buf_i, sizeof(struct stat));
1729  found = 1;
1730  }
1731  XrdCl::FileSystem *fs_i = new XrdCl::FileSystem(info->At( i ).GetAddress());
1732 
1733  xattrvals.clear();
1734  st = fs_i->GetXAttr(file, xattrkeys, xattrvals, 0);
1735  if (! xattrvals[0].value.empty())
1736  {
1737  std::stringstream sstream(xattrvals[0].value);
1738  uint64_t verNum;
1739  sstream >> verNum;
1740  if ( verNum > verNumMax )
1741  {
1742  verNumMax = verNum;
1743  memcpy(buf, &buf_i, sizeof(struct stat));
1744  buf->st_mtime = verNumMax; // assume verNum is mtime
1745  std::stringstream sstream(xattrvals[1].value);
1746  sstream >> buf->st_size;
1747  buf->st_blocks = (buf->st_size + 512)/512;
1748  }
1749  }
1750  if (fs_i) delete fs_i;
1751  }
1752  if (admin_i) delete admin_i;
1753  }
1754  if (! found)
1755  {
1756  errno = ENOENT;
1757  return -1;
1758  }
1759  return 0;
1760 }
1761 
1762 /******************************************************************************/
1763 /* E c U n l i n k */
1764 /******************************************************************************/
1765 
1766 int XrdPosixXrootd::EcUnlink(const char *path, XrdPosixAdmin &admin)
1767 {
1768  XrdCl::URL url(path);
1769  std::string file = url.GetPath();
1770  XrdCl::LocationInfo *info = nullptr;
1771  XrdCl::FileSystem fs(path);
1772 
1773  XrdCl::Buffer queryArgs(5), *queryResp = nullptr;
1774  queryArgs.FromString("role");
1775  XrdCl::XRootDStatus st = fs.Query(XrdCl::QueryCode::Config, queryArgs, queryResp);
1776  // xrootdfs call this function with individual servers. but we can only do
1777  // fs.DeepLocate("*"...) agaist a redirector
1778  if (!st.IsOK() || queryResp->ToString() == "server"
1779  || queryResp->ToString() == "server\n")
1780  {
1781  if (queryResp) delete queryResp;
1782  return XrdPosixMap::Result(admin.Xrd.Rm(admin.Url.GetPathWithParams()),
1783  admin.ecMsg, true);
1784  }
1785  else
1786  if (queryResp) delete queryResp;
1787 
1788  st = fs.DeepLocate("*", XrdCl::OpenFlags::PrefName, info );
1789  std::unique_ptr<XrdCl::LocationInfo> ptr( info );
1790  if( !st.IsOK() )
1791  return XrdPosixMap::Result(st, admin.ecMsg, true);
1792 
1793  int rc = -ENOENT;
1794  for( size_t i = 0; i < info->GetSize(); ++i )
1795  {
1796  std::string url_i = "root://" + info->At(i).GetAddress() + "/" + file;
1797  XrdPosixAdmin *admin_i = new XrdPosixAdmin(url_i.c_str(),admin.ecMsg);
1798  int x = XrdPosixMap::Result(admin_i->
1799  Xrd.Rm(admin_i->Url.GetPathWithParams()),
1800  admin.ecMsg);
1801  if (x != -ENOENT && rc != 0)
1802  rc = x;
1803  if (admin_i) delete admin_i;
1804  }
1805  return rc;
1806 }
#define ENOATTR
Definition: XProtocol.hh:1385
#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)
#define DEBUGON
XrdVERSIONINFO(XrdPosix, XrdPosix)
#define statvfs(a, b)
Definition: XrdPosix.hh:135
#define stat(a, b)
Definition: XrdPosix.hh:105
#define statfs(a, b)
Definition: XrdPosix.hh:111
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 Mv(const std::string &source, const std::string &dest, ResponseHandler *handler, time_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus Truncate(const std::string &path, uint64_t size, ResponseHandler *handler, time_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus RmDir(const std::string &path, ResponseHandler *handler, time_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus Rm(const std::string &path, ResponseHandler *handler, time_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus StatVFS(const std::string &path, ResponseHandler *handler, time_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus GetXAttr(const std::string &path, const std::vector< std::string > &attrs, ResponseHandler *handler, time_t timeout=0)
XRootDStatus MkDir(const std::string &path, MkDirFlags::Flags flags, Access::Mode mode, ResponseHandler *handler, time_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus Open(const std::string &url, OpenFlags::Flags flags, Access::Mode mode, ResponseHandler *handler, time_t timeout=0) XRD_WARN_UNUSED_RESULT
Definition: XrdClFile.cc:125
bool IsOpen() const
Check if the file is open.
Definition: XrdClFile.cc:962
bool GetProperty(const std::string &name, std::string &value) const
Definition: XrdClFile.cc:994
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:175
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:664
virtual int Stat(const char *url, struct stat &sbuff)
Definition: XrdOucCache.hh:692
virtual int Truncate(const char *path, off_t size)
Definition: XrdOucCache.hh:705
virtual int Unlink(const char *path)
Definition: XrdOucCache.hh:717
virtual int LocalFilePath(const char *url, char *buff=0, int blen=0, LFP_Reason why=ForAccess, bool forall=false)
Definition: XrdOucCache.hh:626
virtual int Prepare(const char *url, int oflags, mode_t mode)
Definition: XrdOucCache.hh:651
virtual int Rmdir(const char *dirp)
Definition: XrdOucCache.hh:676
int SetErrno(int ecc, int ret=-1, const char *alt=0)
Definition: XrdOucECMsg.cc:152
int Get(std::string &ecm, bool rst=true)
Definition: XrdOucECMsg.cc:41
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:63
void rewind()
Definition: XrdPosixDir.hh:80
long getOffset()
Definition: XrdPosixDir.hh:67
DIR * Open()
Definition: XrdPosixDir.cc:110
bool Unread()
Definition: XrdPosixDir.hh:86
dirent64 * nextEntry(dirent64 *dp=0)
Definition: XrdPosixDir.cc:48
void setOffset(long offset)
Definition: XrdPosixDir.hh:69
int Status()
Definition: XrdPosixDir.hh:84
long getEntries()
Definition: XrdPosixDir.hh:65
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:195
static XrdCl::Access::Mode Mode2Access(mode_t mode)
Definition: XrdPosixMap.cc:175
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 Fcntl(int fildes, Fcop op, const std::string &args, std::string &resp)
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.
@ Stat
Stat each entry.
@ 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