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 {
244  XrdPosixAdmin admin(path,XrdPosixGlobals::ecMsg,nullptr);
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 {
467  XrdPosixAdmin admin(path,XrdPosixGlobals::ecMsg,nullptr);
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 {
530  XrdPosixAdmin admin(path,XrdPosixGlobals::ecMsg,nullptr);
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  {
789  std::unique_lock lock(fp->ecMutex);
790  fp->ecMsg.SetErrno(EOVERFLOW,0,"read size too large");
791  }
792  cbp->Complete(-1);
793  return;
794  }
795 
796 // Prepare for the read
797 //
798  cbp->theFile = fp;
799  fp->Ref(); fp->UnLock();
800  iosz = static_cast<int>(nbyte);
801  offs = static_cast<long long>(offset);
802 
803 // Issue the read
804 //
805  fp->XCio->Read(*cbp, (char *)buf, offs, (int)iosz);
806 }
807 
808 /******************************************************************************/
809 /* P w r i t e */
810 /******************************************************************************/
811 
812 ssize_t XrdPosixXrootd::Pwrite(int fildes, const void *buf, size_t nbyte, off_t offset)
813 {
814  XrdPosixFile *fp;
815  long long offs;
816  int iosz, bytes;
817 
818 // Find the file object
819 //
820  if (!(fp = XrdPosixObject::File(fildes))) return -1;
821 
822 // Make sure the size is not too large
823 //
824  if (nbyte > (size_t)0x7fffffff)
825  return Fault(fp,EOVERFLOW,"write size too large");
826  else iosz = static_cast<int>(nbyte);
827 
828 // Issue the write
829 //
830  offs = static_cast<long long>(offset);
831  bytes = fp->XCio->Write((char *)buf, offs, (int)iosz);
832  if (bytes < 0) return Fault(fp,-bytes,"*");
833 
834 // All went well
835 //
836  fp->UpdtSize(offs + iosz);
837  fp->UnLock();
838  return (ssize_t)iosz;
839 }
840 
841 /******************************************************************************/
842 
843 void XrdPosixXrootd::Pwrite(int fildes, const void *buf, size_t nbyte,
844  off_t offset, XrdPosixCallBackIO *cbp)
845 {
846  XrdPosixFile *fp;
847  long long offs;
848  int iosz;
849 
850 // Find the file object
851 //
852  if (!(fp = XrdPosixObject::File(fildes))) {cbp->Complete(-1); return;}
853 
854 // Make sure the size is not too large
855 //
856  if (nbyte > (size_t)0x7fffffff)
857  {fp->UnLock();
858  {
859  std::unique_lock lock(fp->ecMutex);
860  fp->ecMsg.SetErrno(EOVERFLOW,0,"read size too large");
861  }
862  cbp->Complete(-1);
863  return;
864  }
865 
866 // Prepare for the writing
867 //
868  cbp->theFile = fp;
869  fp->Ref(); fp->UnLock();
870  iosz = static_cast<int>(nbyte);
871  offs = static_cast<long long>(offset);
872 
873 // Issue the read
874 //
875  fp->XCio->Write(*cbp, (char *)buf, offs, (int)iosz);
876 }
877 
878 /******************************************************************************/
879 /* R e a d */
880 /******************************************************************************/
881 
882 ssize_t XrdPosixXrootd::Read(int fildes, void *buf, size_t nbyte)
883 {
884  XrdPosixFile *fp;
885  long long bytes;
886  int iosz;
887 
888 // Find the file object
889 //
890  if (!(fp = XrdPosixObject::File(fildes))) return -1;
891 
892 // Make sure the size is not too large
893 //
894  if (nbyte > (size_t)0x7fffffff) return Fault(fp,EOVERFLOW);
895  else iosz = static_cast<int>(nbyte);
896 
897 // Issue the read
898 //
899  bytes = fp->XCio->Read((char *)buf,fp->Offset(),(int)iosz);
900  if (bytes < 0) return Fault(fp,-bytes);
901 
902 // All went well
903 //
904  fp->addOffset(bytes);
905  fp->UnLock();
906  return (ssize_t)bytes;
907 }
908 
909 /******************************************************************************/
910 /* R e a d v */
911 /******************************************************************************/
912 
913 ssize_t XrdPosixXrootd::Readv(int fildes, const struct iovec *iov, int iovcnt)
914 {
915  ssize_t bytes, totbytes = 0;
916  int i;
917 
918 // Return the results of the read for each iov segment
919 //
920  for (i = 0; i < iovcnt; i++)
921  {bytes = Read(fildes,(void *)iov[i].iov_base,(size_t)iov[i].iov_len);
922  if (bytes > 0) totbytes += bytes;
923  else if (bytes < 0) return -1;
924  else break;
925  }
926 
927 // All done
928 //
929  return totbytes;
930 }
931 
932 /******************************************************************************/
933 /* V R e a d */
934 /******************************************************************************/
935 
936 ssize_t XrdPosixXrootd::VRead(int fildes, const XrdOucIOVec *readV, int n)
937 {
938  XrdPosixFile *fp;
939  ssize_t bytes;
940 
941 // Find the file object
942 //
943  if (!(fp = XrdPosixObject::File(fildes))) return -1;
944 
945 // Issue the read
946 //
947  if ((bytes = fp->XCio->ReadV(readV, n)) < 0) return Fault(fp,-bytes);
948 
949 // Return bytes read
950 //
951  fp->UnLock();
952  return bytes;
953 }
954 
955 /******************************************************************************/
956 
957 void XrdPosixXrootd::VRead(int fildes, const XrdOucIOVec *readV, int n,
958  XrdPosixCallBackIO *cbp)
959 {
960  XrdPosixFile *fp;
961 
962 // Find the file object and issue read
963 //
964  if ((fp = XrdPosixObject::File(fildes)))
965  {cbp->theFile = fp;
966  fp->Ref(); fp->UnLock();
967  fp->XCio->ReadV(*cbp, readV, n);
968  } else cbp->Complete(-1);
969 }
970 
971 /******************************************************************************/
972 /* R e a d d i r */
973 /******************************************************************************/
974 
975 struct dirent* XrdPosixXrootd::Readdir(DIR *dirp)
976 {
977  dirent64 *dp64;
978  dirent *dp32; // Could be the same as dp64
979 
980  if (!(dp64 = Readdir64(dirp))) return 0;
981 
982  dp32 = (struct dirent *)dp64;
983  if ((char*)dp32->d_name != (char*)dp64->d_name)
984  {dp32->d_ino = dp64->d_ino;
985 #if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__GNU__) && !(defined(__FreeBSD_kernel__) && defined(__GLIBC__))
986  dp32->d_off = dp64->d_off;
987 #endif
988 #ifndef __solaris__
989  dp32->d_type = dp64->d_type;
990 #endif
991  dp32->d_reclen = dp64->d_reclen;
992  strcpy(dp32->d_name, dp64->d_name);
993  }
994  return dp32;
995 }
996 
997 struct dirent64* XrdPosixXrootd::Readdir64(DIR *dirp)
998 {
999  XrdPosixDir *dP;
1000  dirent64 *dentP;
1001  int rc, fildes = XrdPosixDir::dirNo(dirp);
1002 
1003 // Find the object
1004 //
1005  if (!(dP = XrdPosixObject::Dir(fildes)))
1007  return (dirent64*)0;
1008  }
1009 
1010 // Get the next directory entry
1011 //
1012  if (!(dentP = dP->nextEntry())) rc = dP->Status();
1013  else rc = 0;
1014 
1015 // Return the appropriate result
1016 //
1017  dP->UnLock();
1018  if (rc) errno = rc;
1019  return dentP;
1020 }
1021 
1022 /******************************************************************************/
1023 /* R e a d d i r _ r */
1024 /******************************************************************************/
1025 
1026 int XrdPosixXrootd::Readdir_r(DIR *dirp, struct dirent *entry,
1027  struct dirent **result)
1028 {
1029  dirent64 *dp64 = 0, d64ent;
1030  int rc;
1031 
1032  if ((rc = Readdir64_r(dirp, &d64ent, &dp64)) || !dp64)
1033  {*result = 0; return rc;}
1034 
1035  entry->d_ino = dp64->d_ino;
1036 #if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__GNU__) && !(defined(__FreeBSD_kernel__) && defined(__GLIBC__))
1037  entry->d_off = dp64->d_off;
1038 #endif
1039 #ifndef __solaris__
1040  entry->d_type = dp64->d_type;
1041 #endif
1042  entry->d_reclen = dp64->d_reclen;
1043  strcpy(entry->d_name, dp64->d_name);
1044  *result = entry;
1045  return rc;
1046 }
1047 
1048 int XrdPosixXrootd::Readdir64_r(DIR *dirp, struct dirent64 *entry,
1049  struct dirent64 **result)
1050 {
1051  XrdPosixDir *dP;
1052  int rc, fildes = XrdPosixDir::dirNo(dirp);
1053 
1054 // Find the object
1055 //
1056  if (!(dP = XrdPosixObject::Dir(fildes))) return EBADF;
1057 
1058 // Get the next entry
1059 //
1060  if (!(*result = dP->nextEntry(entry))) {rc = dP->Status(); *result = 0;}
1061  else {rc = 0; *result = entry;}
1062 
1063 // Return the appropriate result
1064 //
1065  dP->UnLock();
1066  return rc;
1067 }
1068 
1069 /******************************************************************************/
1070 /* R e n a m e */
1071 /******************************************************************************/
1072 
1073 int XrdPosixXrootd::Rename(const char *oldpath, const char *newpath)
1074 {
1075  XrdPosixAdmin admin(oldpath,XrdPosixGlobals::ecMsg,nullptr);
1076  XrdCl::URL newUrl((std::string)newpath);
1077 
1078 // Make sure the admin is OK and the new url is valid
1079 //
1080  if (!admin.isOK() || !newUrl.IsValid())
1081  return XrdPosixGlobals::ecMsg.SetErrno(EINVAL);
1082 
1083 // Issue rename to he cache (it really should just deep-six both files)
1084 //
1086  {LfnPath oldF("rename", oldpath);
1087  LfnPath newF("rename", newpath);
1088  if (!oldF.path || !newF.path) return -1;
1089  XrdPosixGlobals::theCache->Rename(oldF.path, newF.path);
1090  }
1091 
1092 // Issue the rename
1093 //
1095  return EcRename(oldpath, newpath, admin);
1096 
1097  return XrdPosixMap::Result(admin.Xrd.Mv(admin.Url.GetPathWithParams(),
1098  newUrl.GetPathWithParams()),
1099  XrdPosixGlobals::ecMsg, true);
1100 }
1101 
1102 /******************************************************************************/
1103 /* R e w i n d d i r */
1104 /******************************************************************************/
1105 
1107 {
1108  XrdPosixDir *dP;
1109  int fildes = XrdPosixDir::dirNo(dirp);
1110 
1111 // Find the object and rewind it
1112 //
1113  if ((dP = XrdPosixObject::Dir(fildes)))
1114  {dP->rewind();
1115  dP->UnLock();
1116  }
1117 }
1118 
1119 /******************************************************************************/
1120 /* R m d i r */
1121 /******************************************************************************/
1122 
1123 int XrdPosixXrootd::Rmdir(const char *path)
1124 {
1125  XrdPosixAdmin admin(path,XrdPosixGlobals::ecMsg,nullptr);
1126 
1127 // Make sure the admin is OK
1128 //
1129  if (!admin.isOK()) return -1;
1130 
1131 // Remove directory from the cache first
1132 //
1134  {LfnPath rmd("rmdir", path);
1135  if (!rmd.path) return -1;
1136  XrdPosixGlobals::theCache->Rmdir(rmd.path);
1137  }
1138 
1139 // Issue the rmdir
1140 //
1141  return XrdPosixMap::Result(admin.Xrd.RmDir(admin.Url.GetPathWithParams()),
1142  XrdPosixGlobals::ecMsg, true);
1143 }
1144 
1145 /******************************************************************************/
1146 /* S e e k d i r */
1147 /******************************************************************************/
1148 
1149 void XrdPosixXrootd::Seekdir(DIR *dirp, long loc)
1150 {
1151  XrdPosixDir *dP;
1152  int fildes = XrdPosixDir::dirNo(dirp);
1153 
1154 // Find the object
1155 //
1156  if (!(dP = XrdPosixObject::Dir(fildes))) return;
1157 
1158 // Sets the current directory position
1159 //
1160  if (dP->Unread() && !(dP->Open()))
1161  {if (loc >= dP->getEntries()) loc = dP->getEntries();
1162  else if (loc < 0) loc = 0;
1163  dP->setOffset(loc);
1164  }
1165  dP->UnLock();
1166 }
1167 
1168 /******************************************************************************/
1169 /* S t a t */
1170 /******************************************************************************/
1171 
1172 int XrdPosixXrootd::Stat(const char *path, struct stat *buf)
1173 {
1174  XrdPosixAdmin admin(path,XrdPosixGlobals::ecMsg,nullptr);
1175  bool cacheChk = false;
1176 
1177 // Make sure the admin is OK
1178 //
1179  if (!admin.isOK()) return -1;
1180 
1181 // Initialize the stat buffer
1182 //
1184 
1185 // Check if we can get the stat informatation from the cache
1186 //
1188  {LfnPath statX("stat", path, false);
1189  if (!statX.path) return -1;
1190  int rc = XrdPosixGlobals::theCache->Stat(statX.path, *buf);
1191  if (!rc) return 0;
1192  if (rc < 0) {errno = -rc; return -1;} // does the cache set this???
1193  cacheChk = true;
1194  }
1195 
1196 // Issue the stat and verify that all went well
1197 //
1199  return EcStat(path, buf, admin);
1200 
1201  if (!admin.Stat(*buf)) return -1;
1202 
1203 // If we are here and the cache was checked then the file was not in the cache.
1204 // We informally tell the caller this is the case by setting atime to zero.
1205 // Normally, atime will never be zero in any other case.
1206 //
1207  if (cacheChk) buf->st_atime = 0;
1208  return 0;
1209 }
1210 
1211 /******************************************************************************/
1212 /* S t a t f s */
1213 /******************************************************************************/
1214 
1215 int XrdPosixXrootd::Statfs(const char *path, struct statfs *buf)
1216 {
1217  struct statvfs myVfs;
1218  int rc;
1219 
1220 // Issue a statvfs() call and transcribe the results
1221 //
1222  if ((rc = Statvfs(path, &myVfs))) return rc;
1223 
1224 // The vfs structure and fs structures should be size compatible (not really)
1225 //
1226  memset(buf, 0, sizeof(struct statfs));
1227  buf->f_bsize = myVfs.f_bsize;
1228  buf->f_blocks = myVfs.f_blocks;
1229  buf->f_bfree = myVfs.f_bfree;
1230  buf->f_files = myVfs.f_files;
1231  buf->f_ffree = myVfs.f_ffree;
1232 #if defined(__APPLE__) || defined(__FreeBSD__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__))
1233  buf->f_iosize = myVfs.f_frsize;
1234 #else
1235  buf->f_frsize = myVfs.f_frsize;
1236 #endif
1237 #if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__GNU__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__))
1238  buf->f_bavail = myVfs.f_bavail;
1239 #endif
1240 #if defined(__linux__) || defined(__GNU__)
1241  buf->f_namelen = myVfs.f_namemax;
1242 #elif defined(__FreeBSD__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__))
1243  buf->f_namemax = myVfs.f_namemax;
1244 #endif
1245  return 0;
1246 }
1247 
1248 /******************************************************************************/
1249 /* S t a t R e t */
1250 /******************************************************************************/
1251 
1252 int XrdPosixXrootd::StatRet(DIR *dirp, struct stat *buf)
1253 {
1254 // Find the object
1255 //
1256  auto fildes = XrdPosixDir::dirNo(dirp);
1257  auto dP = XrdPosixObject::Dir(fildes);
1258  if (!dP) return EBADF;
1259 
1260 // Get the stat info
1261  auto rc = dP->StatRet(buf);
1262 
1263  dP->UnLock();
1264  return rc;
1265 }
1266 
1267 /******************************************************************************/
1268 /* S t a t v f s */
1269 /******************************************************************************/
1270 
1271 int XrdPosixXrootd::Statvfs(const char *path, struct statvfs *buf)
1272 {
1273  static const int szVFS = sizeof(buf->f_bfree);
1274  static const long long max32 = 0x7fffffffLL;
1275 
1276  XrdPosixAdmin admin(path,XrdPosixGlobals::ecMsg,nullptr);
1277  XrdCl::StatInfoVFS *vfsStat;
1278 
1279  long long rwFree, ssFree, rwBlks;
1280  int rwNum, ssNum, rwUtil, ssUtil;
1281 
1282 // Make sure we connected
1283 //
1284  if (!admin.isOK()) return -1;
1285 
1286 // Issue the statfvs call
1287 //
1289  vfsStat),
1290  XrdPosixGlobals::ecMsg) < 0) return -1;
1291 
1292 // Extract out the information
1293 //
1294  rwNum = static_cast<int>(vfsStat->GetNodesRW());
1295  rwFree = (long long)vfsStat->GetFreeRW();
1296  rwUtil = static_cast<int>(vfsStat->GetUtilizationRW());
1297  ssNum = static_cast<int>(vfsStat->GetNodesStaging());
1298  ssFree = (long long)vfsStat->GetFreeStaging();
1299  ssUtil = static_cast<int>(vfsStat->GetUtilizationStaging());
1300  delete vfsStat;
1301 
1302 // Calculate number of blocks
1303 //
1304  if (rwUtil == 0) rwBlks = rwFree;
1305  else if (rwUtil >= 100) rwBlks = 0;
1306  else rwBlks = rwFree * (100 / (100 - rwUtil));
1307  if (ssUtil == 0) rwBlks += ssFree;
1308  else if (ssUtil < 100) rwBlks += ssFree * (100 / (100 - ssUtil));
1309 
1310 // Scale units to what will fit here (we can have a 32-bit or 64-bit struct)
1311 //
1312  if (szVFS < 8)
1313  {if (rwBlks > max32) rwBlks = max32;
1314  if (rwFree > max32) rwFree = max32;
1315  if (ssFree > max32) ssFree = max32;
1316  }
1317 
1318 // Return what little we can
1319 //
1320  memset(buf, 0, sizeof(struct statvfs));
1321  buf->f_bsize = 1024*1024;
1322  buf->f_frsize = 1024*1024;
1323  buf->f_blocks = static_cast<fsblkcnt_t>(rwBlks);
1324  buf->f_bfree = static_cast<fsblkcnt_t>(rwFree + ssFree);
1325  buf->f_bavail = static_cast<fsblkcnt_t>(rwFree);
1326  buf->f_ffree = rwNum + ssNum;
1327  buf->f_favail = rwNum;
1328  buf->f_namemax = 255; // The best we are going to do here
1329  buf->f_flag = (rwNum == 0 ? ST_RDONLY|ST_NOSUID : ST_NOSUID);
1330  return 0;
1331 }
1332 
1333 /******************************************************************************/
1334 /* T e l l d i r */
1335 /******************************************************************************/
1336 
1338 {
1339  XrdPosixDir *dP;
1340  long pos;
1341  int fildes = XrdPosixDir::dirNo(dirp);
1342 
1343 // Find the object
1344 //
1345  if (!(dP = XrdPosixObject::Dir(fildes)))
1346  return XrdPosixGlobals::ecMsg.SetErrno(EBADF,0);
1347 
1348 // Tell the current directory location
1349 //
1350  pos = dP->getOffset();
1351  dP->UnLock();
1352  return pos;
1353 }
1354 
1355 /******************************************************************************/
1356 /* T r u n c a t e */
1357 /******************************************************************************/
1358 
1359 int XrdPosixXrootd::Truncate(const char *path, off_t Size)
1360 {
1361  XrdPosixAdmin admin(path,XrdPosixGlobals::ecMsg,nullptr);
1362  uint64_t tSize = static_cast<uint64_t>(Size);
1363 
1364 // Make sure the admin is OK
1365 //
1366  if (!admin.isOK()) return -1;
1367 
1368 // Truncate in the cache first
1369 //
1371  {LfnPath trunc("truncate", path);
1372  if (!trunc.path) return -1;
1373  XrdPosixGlobals::theCache->Truncate(trunc.path, tSize);
1374  }
1375 
1376 // Issue the truncate to the origin
1377 //
1378  std::string urlp = admin.Url.GetPathWithParams();
1379  return XrdPosixMap::Result(admin.Xrd.Truncate(urlp,tSize),
1380  XrdPosixGlobals::ecMsg,true);
1381 }
1382 
1383 /******************************************************************************/
1384 /* U n l i n k */
1385 /******************************************************************************/
1386 
1387 int XrdPosixXrootd::Unlink(const char *path)
1388 {
1389  XrdPosixAdmin admin(path,XrdPosixGlobals::ecMsg,nullptr);
1390 
1391 // Make sure the admin is OK
1392 //
1393  if (!admin.isOK()) return -1;
1394 
1395 // Unlink the cache first
1396 //
1398  {LfnPath remf("unlink", path);
1399  if (!remf.path) return -1;
1400  XrdPosixGlobals::theCache->Unlink(remf.path);
1401  }
1402 
1403 // Issue the UnLink
1404 //
1406  return EcUnlink(path, admin);
1407 
1408  return XrdPosixMap::Result(admin.Xrd.Rm(admin.Url.GetPathWithParams()),
1409  XrdPosixGlobals::ecMsg, true);
1410 }
1411 
1412 /******************************************************************************/
1413 /* W r i t e */
1414 /******************************************************************************/
1415 
1416 ssize_t XrdPosixXrootd::Write(int fildes, const void *buf, size_t nbyte)
1417 {
1418  XrdPosixFile *fp;
1419  int iosz, bytes;
1420 
1421 // Find the file object
1422 //
1423  if (!(fp = XrdPosixObject::File(fildes))) return -1;
1424 
1425 // Make sure the size is not too large
1426 //
1427  if (nbyte > (size_t)0x7fffffff) return Fault(fp,EOVERFLOW);
1428  else iosz = static_cast<int>(nbyte);
1429 
1430 // Issue the write
1431 //
1432  bytes = fp->XCio->Write((char *)buf,fp->Offset(),(int)iosz);
1433  if (bytes < 0) return Fault(fp,-bytes);
1434 
1435 // All went well
1436 //
1437  fp->addOffset(iosz, 1);
1438  fp->UnLock();
1439  return (ssize_t)iosz;
1440 }
1441 
1442 /******************************************************************************/
1443 /* W r i t e v */
1444 /******************************************************************************/
1445 
1446 ssize_t XrdPosixXrootd::Writev(int fildes, const struct iovec *iov, int iovcnt)
1447 {
1448  ssize_t totbytes = 0;
1449  int i;
1450 
1451 // Return the results of the write for each iov segment
1452 //
1453  for (i = 0; i < iovcnt; i++)
1454  {if (!Write(fildes,(void *)iov[i].iov_base,(size_t)iov[i].iov_len))
1455  return -1;
1456  totbytes += iov[i].iov_len;
1457  }
1458 
1459 // All done
1460 //
1461  return totbytes;
1462 }
1463 
1464 /******************************************************************************/
1465 /* i s X r o o t d D i r */
1466 /******************************************************************************/
1467 
1469 {
1470  XrdPosixDir *dP;
1471  int fildes;
1472 
1473  if (!dirp) return false;
1474  fildes = XrdPosixDir::dirNo(dirp);
1475 
1476  if (!myFD(fildes) || !(dP = XrdPosixObject::Dir(fildes))) return false;
1477 
1478  dP->UnLock();
1479  return true;
1480 }
1481 
1482 /******************************************************************************/
1483 /* m y F D */
1484 /******************************************************************************/
1485 
1487 {
1488  return XrdPosixObject::Valid(fd);
1489 }
1490 
1491 /******************************************************************************/
1492 /* Q u e r y C h k s u m */
1493 /******************************************************************************/
1494 
1495 int XrdPosixXrootd::QueryChksum(const char *path, time_t &Mtime,
1496  char *value, int vsize)
1497 {
1498  XrdPosixAdmin admin(path,XrdPosixGlobals::ecMsg,nullptr);
1499 
1500 // Stat the file first to allow vectoring of the request to the right server
1501 //
1502  if (!admin.Stat(0, &Mtime)) return -1;
1503 
1504 // Now we can get the checksum as we have landed on the right server
1505 //
1506  return admin.Query(XrdCl::QueryCode::Checksum, value, vsize);
1507 }
1508 
1509 /******************************************************************************/
1510 /* Q u e r y E r r o r */
1511 /******************************************************************************/
1512 
1513 int XrdPosixXrootd::QueryError(std::string& emsg, int fd, bool reset)
1514 {
1515 // If global wanted then use that one otherwise find the object specific one
1516 //
1517  if (fd < 0) return XrdPosixGlobals::ecMsg.Get(emsg, reset);
1518  else {XrdPosixFile *fp;
1519  if (!(fp = XrdPosixObject::File(fd))) return -1;
1520  std::unique_lock lock(fp->ecMutex);
1521  return fp->ecMsg.Get(emsg, reset);
1522  }
1523 }
1524 
1525 /******************************************************************************/
1526 
1527 int XrdPosixXrootd::QueryError(std::string& emsg, DIR* dirP, bool reset)
1528 {
1529  XrdPosixDir *dP;
1530  int fildes = XrdPosixDir::dirNo(dirP);
1531 
1532 // Find the object
1533 //
1534  if (!(dP = XrdPosixObject::Dir(fildes)))
1535  return XrdPosixGlobals::ecMsg.SetErrno(EBADF);
1536 
1537 // Return result
1538 //
1539  return dP->getECMsg().Get(emsg, reset);
1540 }
1541 
1542 /******************************************************************************/
1543 /* Q u e r y O p a q u e */
1544 /******************************************************************************/
1545 
1546 long long XrdPosixXrootd::QueryOpaque(const char *path, char *value, int size)
1547 {
1548  XrdPosixAdmin admin(path,XrdPosixGlobals::ecMsg,nullptr);
1549 
1550 // Stat the file first to allow vectoring of the request to the right server
1551 //
1552  if (!admin.Stat()) return -1;
1553 
1554 // Now we can get the checksum as we have landed on the right server
1555 //
1556  return admin.Query(XrdCl::QueryCode::OpaqueFile, value, size);
1557 }
1558 
1559 /******************************************************************************/
1560 /* P r i v a t e M e t h o d s */
1561 /******************************************************************************/
1562 /******************************************************************************/
1563 /* F a u l t */
1564 /******************************************************************************/
1565 
1566 int XrdPosixXrootd::Fault(XrdPosixFile *fp, int ecode, const char *msg)
1567 {
1568  fp->UnLock();
1569  return XrdPosixGlobals::ecMsg.SetErrno(ecode, -1, msg);
1570 }
1571 
1572 /******************************************************************************/
1573 /* E c R e n a m e */
1574 /******************************************************************************/
1575 
1576 int XrdPosixXrootd::EcRename(const char *oldpath, const char *newpath,
1577  XrdPosixAdmin &admin)
1578 {
1579  XrdCl::URL url(oldpath);
1580  XrdCl::URL newUrl(newpath);
1581 
1582  std::string file = url.GetPath();
1583  XrdCl::LocationInfo *info = nullptr;
1584  XrdCl::FileSystem fs(oldpath);
1585 
1586  XrdCl::Buffer queryArgs(5), *queryResp = nullptr;
1587  queryArgs.FromString("role");
1588  XrdCl::XRootDStatus st = fs.Query(XrdCl::QueryCode::Config, queryArgs, queryResp);
1589  // xrootdfs call this function with individual servers. but we can only do
1590  // fs.DeepLocate("*"...) agaist a redirector
1591  // xrootdfs already did a stat and know that this is a file, not a dir
1592  if (!st.IsOK() || queryResp->ToString() == "server"
1593  || queryResp->ToString() == "server\n")
1594  {
1595  if (queryResp) delete queryResp;
1596  return XrdPosixMap::Result(admin.Xrd.Mv(admin.Url.GetPathWithParams(),
1597  newUrl.GetPathWithParams()),
1598  XrdPosixGlobals::ecMsg, true);
1599  }
1600  else
1601  if (queryResp) delete queryResp;
1602 
1603  st = fs.DeepLocate("*", XrdCl::OpenFlags::None, info );
1604  std::unique_ptr<XrdCl::LocationInfo> ptr( info );
1605  if( !st.IsOK() )
1606  return XrdPosixMap::Result(st, XrdPosixGlobals::ecMsg, true);
1607 
1608  // check if this is a file or a dir, do not support dir renaming in EC
1609  struct stat buf;
1610  if (XrdPosixXrootd::Stat(oldpath, &buf) != 0)
1611  return XrdPosixGlobals::ecMsg.SetErrno(ENOENT);
1612 
1613  if ( ! S_ISREG(buf.st_mode))
1614  return XrdPosixGlobals::ecMsg.SetErrno(ENOTSUP);
1615 
1616  if (XrdPosixXrootd::Stat(newpath, &buf) == 0)
1617  return XrdPosixGlobals::ecMsg.SetErrno(EEXIST);
1618 
1619  int rc = -ENOENT;
1620  for( size_t i = 0; i < info->GetSize(); ++i )
1621  {
1622  std::string url_i = "root://" + info->At(i).GetAddress() + "/" + file;
1623  XrdPosixAdmin *admin_i = new XrdPosixAdmin(url_i.c_str(),admin.ecMsg,admin.ecMutex);
1624  auto st = admin_i->Xrd.Mv(admin_i->Url.GetPathWithParams(),
1625  newUrl.GetPathWithParams());
1626  int x;
1627  {
1628  std::unique_lock lock(*admin.ecMutex);
1629  x = XrdPosixMap::Result(st, admin.ecMsg);
1630  }
1631  if (x != -ENOENT && rc != 0)
1632  rc = x;
1633  if (admin_i) delete admin_i;
1634  }
1635  return rc;
1636 }
1637 
1638 /******************************************************************************/
1639 /* E c S t a t */
1640 /******************************************************************************/
1641 
1642 int XrdPosixXrootd::EcStat(const char *path, struct stat *buf,
1643  XrdPosixAdmin &admin)
1644 {
1645  XrdCl::URL url(path);
1646  std::string file = url.GetPath();
1647  XrdCl::LocationInfo *info = nullptr;
1648  XrdCl::FileSystem fs(path);
1649 
1650  std::vector<std::string> xattrkeys;
1651  std::vector<XrdCl::XAttr> xattrvals;
1652  xattrkeys.push_back("xrdec.strpver");
1653  xattrkeys.push_back("xrdec.filesize");
1654 
1655  XrdCl::Buffer queryArgs(5), *queryResp = nullptr;
1656  queryArgs.FromString("role");
1657  XrdCl::XRootDStatus st = fs.Query(XrdCl::QueryCode::Config, queryArgs, queryResp);
1658  // xrootdfs call this function with individual servers. but we can only do
1659  // // fs.DeepLocate("*"...) agaist a redirector
1660  if (!st.IsOK() || queryResp->ToString() == "server"
1661  || queryResp->ToString() == "server\n")
1662  {
1663  if (queryResp) delete queryResp;
1664  if (!admin.Stat(*buf))
1665  return -1;
1666  else
1667  {
1668  st = fs.GetXAttr(file, xattrkeys, xattrvals, 0);
1669  if (! xattrvals[0].value.empty())
1670  {
1671  std::stringstream sstream0(xattrvals[0].value);
1672  sstream0 >> buf->st_mtime;
1673  std::stringstream sstream1(xattrvals[1].value);
1674  sstream1 >> buf->st_size;
1675  buf->st_blocks = (buf->st_size + 512)/512;
1676  }
1677  return 0;
1678  }
1679  }
1680  else
1681  if (queryResp) delete queryResp;
1682 
1683  st = fs.DeepLocate("*", XrdCl::OpenFlags::None, info );
1684  std::unique_ptr<XrdCl::LocationInfo> ptr( info );
1685  if( !st.IsOK() )
1686  {
1687  errno = ENOENT;
1688  return -1;
1689  }
1690 
1691  int found = 0;
1692  uint64_t verNumMax = 0;
1693  struct stat buf_i;
1694  XrdPosixConfig::initStat(&buf_i);
1695  for( size_t i = 0; i < info->GetSize(); ++i )
1696  {
1697  std::string url_i = "root://" + info->At(i).GetAddress() + "/" + file;
1698  XrdPosixAdmin *admin_i = new XrdPosixAdmin(url_i.c_str(),admin.ecMsg,admin.ecMutex);
1699 
1700  if (admin_i->Stat(buf_i))
1701  {
1702  if (! S_ISREG(buf_i.st_mode))
1703  {
1704  memcpy(buf, &buf_i, sizeof(struct stat));
1705  if (admin_i) delete admin_i;
1706  return 0;
1707  }
1708  else
1709  {
1710  if (verNumMax == 0) memcpy(buf, &buf_i, sizeof(struct stat));
1711  found = 1;
1712  }
1713  XrdCl::FileSystem *fs_i = new XrdCl::FileSystem(info->At( i ).GetAddress());
1714 
1715  xattrvals.clear();
1716  st = fs_i->GetXAttr(file, xattrkeys, xattrvals, 0);
1717  if (! xattrvals[0].value.empty())
1718  {
1719  std::stringstream sstream(xattrvals[0].value);
1720  uint64_t verNum;
1721  sstream >> verNum;
1722  if ( verNum > verNumMax )
1723  {
1724  verNumMax = verNum;
1725  memcpy(buf, &buf_i, sizeof(struct stat));
1726  buf->st_mtime = verNumMax; // assume verNum is mtime
1727  std::stringstream sstream(xattrvals[1].value);
1728  sstream >> buf->st_size;
1729  buf->st_blocks = (buf->st_size + 512)/512;
1730  }
1731  }
1732  if (fs_i) delete fs_i;
1733  }
1734  if (admin_i) delete admin_i;
1735  }
1736  if (! found)
1737  {
1738  errno = ENOENT;
1739  return -1;
1740  }
1741  return 0;
1742 }
1743 
1744 /******************************************************************************/
1745 /* E c U n l i n k */
1746 /******************************************************************************/
1747 
1748 int XrdPosixXrootd::EcUnlink(const char *path, XrdPosixAdmin &admin)
1749 {
1750  XrdCl::URL url(path);
1751  std::string file = url.GetPath();
1752  XrdCl::LocationInfo *info = nullptr;
1753  XrdCl::FileSystem fs(path);
1754 
1755  XrdCl::Buffer queryArgs(5), *queryResp = nullptr;
1756  queryArgs.FromString("role");
1757  XrdCl::XRootDStatus st = fs.Query(XrdCl::QueryCode::Config, queryArgs, queryResp);
1758  // xrootdfs call this function with individual servers. but we can only do
1759  // fs.DeepLocate("*"...) agaist a redirector
1760  if (!st.IsOK() || queryResp->ToString() == "server"
1761  || queryResp->ToString() == "server\n")
1762  {
1763  if (queryResp) delete queryResp;
1764  auto st = admin.Xrd.Rm(admin.Url.GetPathWithParams());
1765  std::unique_lock lock(*admin.ecMutex);
1766  return XrdPosixMap::Result(st, admin.ecMsg, true);
1767  }
1768  else
1769  if (queryResp) delete queryResp;
1770 
1771  st = fs.DeepLocate("*", XrdCl::OpenFlags::None, info );
1772  std::unique_ptr<XrdCl::LocationInfo> ptr( info );
1773  if( !st.IsOK() )
1774  {std::unique_lock lock(*admin.ecMutex);
1775  return XrdPosixMap::Result(st, admin.ecMsg, true);
1776  }
1777 
1778  int rc = -ENOENT;
1779  for( size_t i = 0; i < info->GetSize(); ++i )
1780  {
1781  std::string url_i = "root://" + info->At(i).GetAddress() + "/" + file;
1782  XrdPosixAdmin *admin_i = new XrdPosixAdmin(url_i.c_str(),admin.ecMsg,admin.ecMutex);
1783  auto st = admin_i->Xrd.Rm(admin_i->Url.GetPathWithParams());
1784  int x;
1785  {
1786  std::unique_lock lock(*admin.ecMutex);
1787  x = XrdPosixMap::Result(st, admin.ecMsg);
1788  }
1789  if (x != -ENOENT && rc != 0)
1790  rc = x;
1791  if (admin_i) delete admin_i;
1792  }
1793  return rc;
1794 }
#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
std::mutex * ecMutex
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:116
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:188
static XrdCl::Access::Mode Mode2Access(mode_t mode)
Definition: XrdPosixMap.cc:168
static void Shutdown()
bool AssignFD(bool isStream=false)
static XrdPosixDir * Dir(int fildes, bool glk=false)
std::mutex ecMutex
static XrdPosixDir * ReleaseDir(int fildes)
XrdOucECMsg getECMsg() const
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.
@ 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