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