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