XRootD
Loading...
Searching...
No Matches
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
46#include "XrdCl/XrdClFile.hh"
47#include "XrdCl/XrdClURL.hh"
49
52
53#include "XrdOuc/XrdOucCache.hh"
54#include "XrdOuc/XrdOucECMsg.hh"
55#include "XrdOuc/XrdOucEnv.hh"
57#include "XrdOuc/XrdOucPsx.hh"
58
72
73#include "XrdSys/XrdSysTrace.hh"
74
75/******************************************************************************/
76/* S t a t i c M e m b e r s */
77/******************************************************************************/
78
79class XrdSysError;
80
81namespace XrdPosixGlobals
82{
83thread_local XrdOucECMsg ecMsg("[posix]");
84
91XrdSysTrace Trace("Posix", 0,
92 (getenv("XRDPOSIX_DEBUG") ? TRACE_Debug : 0));
93int ddInterval= 30;
94int ddMaxTries= 180/30;
96bool oidsOK = false;
97bool p2lSRC = false;
98bool p2lSGI = false;
99bool autoPGRD = false;
100bool usingEC = false;
101};
102
103int XrdPosixXrootd::baseFD = 0;
104int XrdPosixXrootd::initDone = 0;
105
106XrdVERSIONINFO(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
115namespace
116{
117class LfnPath
118{
119public:
120const 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
127private:
128char *relURL;
129};
130}
131
132/******************************************************************************/
133/* L o c a l F u n c t i o n s */
134/******************************************************************************/
135
136namespace
137{
138
139/******************************************************************************/
140/* O p e n D e f e r */
141/******************************************************************************/
142
143int OpenDefer(XrdPosixFile *fp,
144 XrdPosixCallBack *cbP,
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
179XrdPosixXrootd::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
241int 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
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//
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
330int 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
368int 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
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
439int 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
463long long XrdPosixXrootd::Getxattr (const char *path, const char *name,
464 void *value, unsigned long long size)
465{
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
496off_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
527int 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//
544 flags,
547 );
548}
549
550/******************************************************************************/
551/* O p e n */
552/******************************************************************************/
553
554int XrdPosixXrootd::Open(const char *path, int oflags, mode_t mode,
555 XrdPosixCallBack *cbP)
556{
557 return Open(path, oflags, mode, cbP, 0);
558}
559
560int 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;
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))
574 {Opts = XrdPosixFile::isUpdt;
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
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,
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();
656}
657
658/******************************************************************************/
659/* Private: O p e n C a c h e */
660/******************************************************************************/
661
662bool XrdPosixXrootd::OpenCache(XrdPosixFile &file,XrdPosixInfo &Info)
663{
664 EPNAME("OpenCache");
665 int rc;
666
667// Check if the full file is in the cache
668//
669 rc = XrdPosixGlobals::theCache->LocalFilePath(file.Path(), Info.cachePath,
670 (int)sizeof(Info.cachePath),
672 Info.ffReady);
673 if (rc == 0)
674 {Info.ffReady = true;
675 DEBUG("File in cache url=" <<Info.cacheURL);
676 return true;
677 }
678
679// File is not fully in the cache
680//
681 Info.ffReady = false;
682 return false;
683}
684
685/******************************************************************************/
686/* O p e n d i r */
687/******************************************************************************/
688
689DIR* XrdPosixXrootd::Opendir(const char *path)
690{
691 XrdPosixDir *dP;
692 DIR *dirP;
693 int rc;
694
695// Get a new directory object
696//
697 if (!(dP = new XrdPosixDir(path)))
699 return (DIR*)0;
700 }
701
702// Assign a file descriptor to this file
703//
704 if (!(dP->AssignFD()))
705 {delete dP;
707 return (DIR*)0;
708 }
709
710// Open the directory
711//
712 if ((dirP = dP->Open())) return dirP;
713
714// We failed
715//
716 rc = errno;
717 delete dP;
718 errno = rc; // Restore saved errno
719 return (DIR *)0;
720}
721
722/******************************************************************************/
723/* P r e a d */
724/******************************************************************************/
725
726ssize_t XrdPosixXrootd::Pread(int fildes, void *buf, size_t nbyte, off_t offset)
727{
728 XrdPosixFile *fp;
729 long long offs, bytes;
730 int iosz;
731
732// Find the file object
733//
734 if (!(fp = XrdPosixObject::File(fildes)))
735 return XrdPosixGlobals::ecMsg.SetErrno(EBADF);
736
737// Make sure the size is not too large
738//
739 if (nbyte > (size_t)0x7fffffff)
740 return Fault(fp, EOVERFLOW, "read size too large");
741 else iosz = static_cast<int>(nbyte);
742
743// Issue the read
744//
745 offs = static_cast<long long>(offset);
746 bytes = fp->XCio->Read((char *)buf, offs, (int)iosz);
747 if (bytes < 0) return Fault(fp,-bytes,"*");
748
749// All went well
750//
751 fp->UnLock();
752 return (ssize_t)bytes;
753}
754
755/******************************************************************************/
756
757void XrdPosixXrootd::Pread(int fildes, void *buf, size_t nbyte, off_t offset,
759{
760 XrdPosixFile *fp;
761 long long offs;
762 int iosz;
763
764// Find the file object
765//
766 if (!(fp = XrdPosixObject::File(fildes))) {cbp->Complete(-1); return;}
767
768// Make sure the size is not too large
769//
770 if (nbyte > (size_t)0x7fffffff)
771 {fp->UnLock();
772 fp->ecMsg.SetErrno(EOVERFLOW,0,"read size too large");
773 cbp->Complete(-1);
774 return;
775 }
776
777// Prepare for the read
778//
779 cbp->theFile = fp;
780 fp->Ref(); fp->UnLock();
781 iosz = static_cast<int>(nbyte);
782 offs = static_cast<long long>(offset);
783
784// Issue the read
785//
786 fp->XCio->Read(*cbp, (char *)buf, offs, (int)iosz);
787}
788
789/******************************************************************************/
790/* P w r i t e */
791/******************************************************************************/
792
793ssize_t XrdPosixXrootd::Pwrite(int fildes, const void *buf, size_t nbyte, off_t offset)
794{
795 XrdPosixFile *fp;
796 long long offs;
797 int iosz, bytes;
798
799// Find the file object
800//
801 if (!(fp = XrdPosixObject::File(fildes))) return -1;
802
803// Make sure the size is not too large
804//
805 if (nbyte > (size_t)0x7fffffff)
806 return Fault(fp,EOVERFLOW,"write size too large");
807 else iosz = static_cast<int>(nbyte);
808
809// Issue the write
810//
811 offs = static_cast<long long>(offset);
812 bytes = fp->XCio->Write((char *)buf, offs, (int)iosz);
813 if (bytes < 0) return Fault(fp,-bytes,"*");
814
815// All went well
816//
817 fp->UpdtSize(offs + iosz);
818 fp->UnLock();
819 return (ssize_t)iosz;
820}
821
822/******************************************************************************/
823
824void XrdPosixXrootd::Pwrite(int fildes, const void *buf, size_t nbyte,
825 off_t offset, XrdPosixCallBackIO *cbp)
826{
827 XrdPosixFile *fp;
828 long long offs;
829 int iosz;
830
831// Find the file object
832//
833 if (!(fp = XrdPosixObject::File(fildes))) {cbp->Complete(-1); return;}
834
835// Make sure the size is not too large
836//
837 if (nbyte > (size_t)0x7fffffff)
838 {fp->UnLock();
839 fp->ecMsg.SetErrno(EOVERFLOW,0,"read size too large");
840 cbp->Complete(-1);
841 return;
842 }
843
844// Prepare for the writing
845//
846 cbp->theFile = fp;
847 fp->Ref(); fp->UnLock();
848 iosz = static_cast<int>(nbyte);
849 offs = static_cast<long long>(offset);
850
851// Issue the read
852//
853 fp->XCio->Write(*cbp, (char *)buf, offs, (int)iosz);
854}
855
856/******************************************************************************/
857/* R e a d */
858/******************************************************************************/
859
860ssize_t XrdPosixXrootd::Read(int fildes, void *buf, size_t nbyte)
861{
862 XrdPosixFile *fp;
863 long long bytes;
864 int iosz;
865
866// Find the file object
867//
868 if (!(fp = XrdPosixObject::File(fildes))) return -1;
869
870// Make sure the size is not too large
871//
872 if (nbyte > (size_t)0x7fffffff) return Fault(fp,EOVERFLOW);
873 else iosz = static_cast<int>(nbyte);
874
875// Issue the read
876//
877 bytes = fp->XCio->Read((char *)buf,fp->Offset(),(int)iosz);
878 if (bytes < 0) return Fault(fp,-bytes);
879
880// All went well
881//
882 fp->addOffset(bytes);
883 fp->UnLock();
884 return (ssize_t)bytes;
885}
886
887/******************************************************************************/
888/* R e a d v */
889/******************************************************************************/
890
891ssize_t XrdPosixXrootd::Readv(int fildes, const struct iovec *iov, int iovcnt)
892{
893 ssize_t bytes, totbytes = 0;
894 int i;
895
896// Return the results of the read for each iov segment
897//
898 for (i = 0; i < iovcnt; i++)
899 {bytes = Read(fildes,(void *)iov[i].iov_base,(size_t)iov[i].iov_len);
900 if (bytes > 0) totbytes += bytes;
901 else if (bytes < 0) return -1;
902 else break;
903 }
904
905// All done
906//
907 return totbytes;
908}
909
910/******************************************************************************/
911/* V R e a d */
912/******************************************************************************/
913
914ssize_t XrdPosixXrootd::VRead(int fildes, const XrdOucIOVec *readV, int n)
915{
916 XrdPosixFile *fp;
917 ssize_t bytes;
918
919// Find the file object
920//
921 if (!(fp = XrdPosixObject::File(fildes))) return -1;
922
923// Issue the read
924//
925 if ((bytes = fp->XCio->ReadV(readV, n)) < 0) return Fault(fp,-bytes);
926
927// Return bytes read
928//
929 fp->UnLock();
930 return bytes;
931}
932
933/******************************************************************************/
934
935void XrdPosixXrootd::VRead(int fildes, const XrdOucIOVec *readV, int n,
937{
938 XrdPosixFile *fp;
939
940// Find the file object and issue read
941//
942 if ((fp = XrdPosixObject::File(fildes)))
943 {cbp->theFile = fp;
944 fp->Ref(); fp->UnLock();
945 fp->XCio->ReadV(*cbp, readV, n);
946 } else cbp->Complete(-1);
947}
948
949/******************************************************************************/
950/* R e a d d i r */
951/******************************************************************************/
952
953struct dirent* XrdPosixXrootd::Readdir(DIR *dirp)
954{
955 dirent64 *dp64;
956 dirent *dp32; // Could be the same as dp64
957
958 if (!(dp64 = Readdir64(dirp))) return 0;
959
960 dp32 = (struct dirent *)dp64;
961 if ((char*)dp32->d_name != (char*)dp64->d_name)
962 {dp32->d_ino = dp64->d_ino;
963#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__GNU__) && !(defined(__FreeBSD_kernel__) && defined(__GLIBC__))
964 dp32->d_off = dp64->d_off;
965#endif
966#ifndef __solaris__
967 dp32->d_type = dp64->d_type;
968#endif
969 dp32->d_reclen = dp64->d_reclen;
970 strcpy(dp32->d_name, dp64->d_name);
971 }
972 return dp32;
973}
974
975struct dirent64* XrdPosixXrootd::Readdir64(DIR *dirp)
976{
977 XrdPosixDir *dP;
978 dirent64 *dentP;
979 int rc, fildes = XrdPosixDir::dirNo(dirp);
980
981// Find the object
982//
983 if (!(dP = XrdPosixObject::Dir(fildes)))
985 return (dirent64*)0;
986 }
987
988// Get the next directory entry
989//
990 if (!(dentP = dP->nextEntry())) rc = dP->Status();
991 else rc = 0;
992
993// Return the appropriate result
994//
995 dP->UnLock();
996 if (rc) errno = rc;
997 return dentP;
998}
999
1000/******************************************************************************/
1001/* R e a d d i r _ r */
1002/******************************************************************************/
1003
1004int XrdPosixXrootd::Readdir_r(DIR *dirp, struct dirent *entry,
1005 struct dirent **result)
1006{
1007 dirent64 *dp64 = 0, d64ent;
1008 int rc;
1009
1010 if ((rc = Readdir64_r(dirp, &d64ent, &dp64)) || !dp64)
1011 {*result = 0; return rc;}
1012
1013 entry->d_ino = dp64->d_ino;
1014#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__GNU__) && !(defined(__FreeBSD_kernel__) && defined(__GLIBC__))
1015 entry->d_off = dp64->d_off;
1016#endif
1017#ifndef __solaris__
1018 entry->d_type = dp64->d_type;
1019#endif
1020 entry->d_reclen = dp64->d_reclen;
1021 strcpy(entry->d_name, dp64->d_name);
1022 *result = entry;
1023 return rc;
1024}
1025
1026int XrdPosixXrootd::Readdir64_r(DIR *dirp, struct dirent64 *entry,
1027 struct dirent64 **result)
1028{
1029 XrdPosixDir *dP;
1030 int rc, fildes = XrdPosixDir::dirNo(dirp);
1031
1032// Find the object
1033//
1034 if (!(dP = XrdPosixObject::Dir(fildes))) return EBADF;
1035
1036// Get the next entry
1037//
1038 if (!(*result = dP->nextEntry(entry))) {rc = dP->Status(); *result = 0;}
1039 else {rc = 0; *result = entry;}
1040
1041// Return the appropriate result
1042//
1043 dP->UnLock();
1044 return rc;
1045}
1046
1047/******************************************************************************/
1048/* R e n a m e */
1049/******************************************************************************/
1050
1051int XrdPosixXrootd::Rename(const char *oldpath, const char *newpath)
1052{
1054 XrdCl::URL newUrl((std::string)newpath);
1055
1056// Make sure the admin is OK and the new url is valid
1057//
1058 if (!admin.isOK() || !newUrl.IsValid())
1059 return XrdPosixGlobals::ecMsg.SetErrno(EINVAL);
1060
1061// Issue rename to he cache (it really should just deep-six both files)
1062//
1064 {LfnPath oldF("rename", oldpath);
1065 LfnPath newF("rename", newpath);
1066 if (!oldF.path || !newF.path) return -1;
1067 XrdPosixGlobals::theCache->Rename(oldF.path, newF.path);
1068 }
1069
1070// Issue the rename
1071//
1073 return EcRename(oldpath, newpath, admin);
1074
1075 return XrdPosixMap::Result(admin.Xrd.Mv(admin.Url.GetPathWithParams(),
1076 newUrl.GetPathWithParams()),
1078}
1079
1080/******************************************************************************/
1081/* R e w i n d d i r */
1082/******************************************************************************/
1083
1085{
1086 XrdPosixDir *dP;
1087 int fildes = XrdPosixDir::dirNo(dirp);
1088
1089// Find the object and rewind it
1090//
1091 if ((dP = XrdPosixObject::Dir(fildes)))
1092 {dP->rewind();
1093 dP->UnLock();
1094 }
1095}
1096
1097/******************************************************************************/
1098/* R m d i r */
1099/******************************************************************************/
1100
1101int XrdPosixXrootd::Rmdir(const char *path)
1102{
1104
1105// Make sure the admin is OK
1106//
1107 if (!admin.isOK()) return -1;
1108
1109// Remove directory from the cache first
1110//
1112 {LfnPath rmd("rmdir", path);
1113 if (!rmd.path) return -1;
1115 }
1116
1117// Issue the rmdir
1118//
1119 return XrdPosixMap::Result(admin.Xrd.RmDir(admin.Url.GetPathWithParams()),
1121}
1122
1123/******************************************************************************/
1124/* S e e k d i r */
1125/******************************************************************************/
1126
1127void XrdPosixXrootd::Seekdir(DIR *dirp, long loc)
1128{
1129 XrdPosixDir *dP;
1130 int fildes = XrdPosixDir::dirNo(dirp);
1131
1132// Find the object
1133//
1134 if (!(dP = XrdPosixObject::Dir(fildes))) return;
1135
1136// Sets the current directory position
1137//
1138 if (dP->Unread() && !(dP->Open()))
1139 {if (loc >= dP->getEntries()) loc = dP->getEntries();
1140 else if (loc < 0) loc = 0;
1141 dP->setOffset(loc);
1142 }
1143 dP->UnLock();
1144}
1145
1146/******************************************************************************/
1147/* S t a t */
1148/******************************************************************************/
1149
1150int XrdPosixXrootd::Stat(const char *path, struct stat *buf)
1151{
1153
1154// Make sure the admin is OK
1155//
1156 if (!admin.isOK()) return -1;
1157
1158// Initialize the stat buffer
1159//
1161
1162// Check if we can get the stat informatation from the cache
1163//
1165 {LfnPath statX("stat", path, false);
1166 if (!statX.path) return -1;
1167 int rc = XrdPosixGlobals::theCache->Stat(statX.path, *buf);
1168 if (!rc) return 0;
1169 if (rc < 0) {errno = -rc; return -1;} // does the cache set this???
1170 }
1171
1172// Issue the stat and verify that all went well
1173//
1175 return EcStat(path, buf, admin);
1176
1177 if (!admin.Stat(*buf)) return -1;
1178 return 0;
1179}
1180
1181/******************************************************************************/
1182/* S t a t f s */
1183/******************************************************************************/
1184
1185int XrdPosixXrootd::Statfs(const char *path, struct statfs *buf)
1186{
1187 struct statvfs myVfs;
1188 int rc;
1189
1190// Issue a statvfs() call and transcribe the results
1191//
1192 if ((rc = Statvfs(path, &myVfs))) return rc;
1193
1194// The vfs structure and fs structures should be size compatible (not really)
1195//
1196 memset(buf, 0, sizeof(struct statfs));
1197 buf->f_bsize = myVfs.f_bsize;
1198 buf->f_blocks = myVfs.f_blocks;
1199 buf->f_bfree = myVfs.f_bfree;
1200 buf->f_files = myVfs.f_files;
1201 buf->f_ffree = myVfs.f_ffree;
1202#if defined(__APPLE__) || defined(__FreeBSD__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__))
1203 buf->f_iosize = myVfs.f_frsize;
1204#else
1205 buf->f_frsize = myVfs.f_frsize;
1206#endif
1207#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__GNU__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__))
1208 buf->f_bavail = myVfs.f_bavail;
1209#endif
1210#if defined(__linux__) || defined(__GNU__)
1211 buf->f_namelen = myVfs.f_namemax;
1212#elif defined(__FreeBSD__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__))
1213 buf->f_namemax = myVfs.f_namemax;
1214#endif
1215 return 0;
1216}
1217
1218/******************************************************************************/
1219/* S t a t v f s */
1220/******************************************************************************/
1221
1222int XrdPosixXrootd::Statvfs(const char *path, struct statvfs *buf)
1223{
1224 static const int szVFS = sizeof(buf->f_bfree);
1225 static const long long max32 = 0x7fffffffLL;
1226
1228 XrdCl::StatInfoVFS *vfsStat;
1229
1230 long long rwFree, ssFree, rwBlks;
1231 int rwNum, ssNum, rwUtil, ssUtil;
1232
1233// Make sure we connected
1234//
1235 if (!admin.isOK()) return -1;
1236
1237// Issue the statfvs call
1238//
1240 vfsStat),
1241 XrdPosixGlobals::ecMsg) < 0) return -1;
1242
1243// Extract out the information
1244//
1245 rwNum = static_cast<int>(vfsStat->GetNodesRW());
1246 rwFree = (long long)vfsStat->GetFreeRW();
1247 rwUtil = static_cast<int>(vfsStat->GetUtilizationRW());
1248 ssNum = static_cast<int>(vfsStat->GetNodesStaging());
1249 ssFree = (long long)vfsStat->GetFreeStaging();
1250 ssUtil = static_cast<int>(vfsStat->GetUtilizationStaging());
1251 delete vfsStat;
1252
1253// Calculate number of blocks
1254//
1255 if (rwUtil == 0) rwBlks = rwFree;
1256 else if (rwUtil >= 100) rwBlks = 0;
1257 else rwBlks = rwFree * (100 / (100 - rwUtil));
1258 if (ssUtil == 0) rwBlks += ssFree;
1259 else if (ssUtil < 100) rwBlks += ssFree * (100 / (100 - ssUtil));
1260
1261// Scale units to what will fit here (we can have a 32-bit or 64-bit struct)
1262//
1263 if (szVFS < 8)
1264 {if (rwBlks > max32) rwBlks = max32;
1265 if (rwFree > max32) rwFree = max32;
1266 if (ssFree > max32) ssFree = max32;
1267 }
1268
1269// Return what little we can
1270//
1271 memset(buf, 0, sizeof(struct statvfs));
1272 buf->f_bsize = 1024*1024;
1273 buf->f_frsize = 1024*1024;
1274 buf->f_blocks = static_cast<fsblkcnt_t>(rwBlks);
1275 buf->f_bfree = static_cast<fsblkcnt_t>(rwFree + ssFree);
1276 buf->f_bavail = static_cast<fsblkcnt_t>(rwFree);
1277 buf->f_ffree = rwNum + ssNum;
1278 buf->f_favail = rwNum;
1279 buf->f_namemax = 255; // The best we are going to do here
1280 buf->f_flag = (rwNum == 0 ? ST_RDONLY|ST_NOSUID : ST_NOSUID);
1281 return 0;
1282}
1283
1284/******************************************************************************/
1285/* T e l l d i r */
1286/******************************************************************************/
1287
1289{
1290 XrdPosixDir *dP;
1291 long pos;
1292 int fildes = XrdPosixDir::dirNo(dirp);
1293
1294// Find the object
1295//
1296 if (!(dP = XrdPosixObject::Dir(fildes)))
1297 return XrdPosixGlobals::ecMsg.SetErrno(EBADF,0);
1298
1299// Tell the current directory location
1300//
1301 pos = dP->getOffset();
1302 dP->UnLock();
1303 return pos;
1304}
1305
1306/******************************************************************************/
1307/* T r u n c a t e */
1308/******************************************************************************/
1309
1310int XrdPosixXrootd::Truncate(const char *path, off_t Size)
1311{
1313 uint64_t tSize = static_cast<uint64_t>(Size);
1314
1315// Make sure the admin is OK
1316//
1317 if (!admin.isOK()) return -1;
1318
1319// Truncate in the cache first
1320//
1322 {LfnPath trunc("truncate", path);
1323 if (!trunc.path) return -1;
1324 XrdPosixGlobals::theCache->Truncate(trunc.path, tSize);
1325 }
1326
1327// Issue the truncate to the origin
1328//
1329 std::string urlp = admin.Url.GetPathWithParams();
1330 return XrdPosixMap::Result(admin.Xrd.Truncate(urlp,tSize),
1332}
1333
1334/******************************************************************************/
1335/* U n l i n k */
1336/******************************************************************************/
1337
1338int XrdPosixXrootd::Unlink(const char *path)
1339{
1341
1342// Make sure the admin is OK
1343//
1344 if (!admin.isOK()) return -1;
1345
1346// Unlink the cache first
1347//
1349 {LfnPath remf("unlink", path);
1350 if (!remf.path) return -1;
1352 }
1353
1354// Issue the UnLink
1355//
1357 return EcUnlink(path, admin);
1358
1359 return XrdPosixMap::Result(admin.Xrd.Rm(admin.Url.GetPathWithParams()),
1361}
1362
1363/******************************************************************************/
1364/* W r i t e */
1365/******************************************************************************/
1366
1367ssize_t XrdPosixXrootd::Write(int fildes, const void *buf, size_t nbyte)
1368{
1369 XrdPosixFile *fp;
1370 int iosz, bytes;
1371
1372// Find the file object
1373//
1374 if (!(fp = XrdPosixObject::File(fildes))) return -1;
1375
1376// Make sure the size is not too large
1377//
1378 if (nbyte > (size_t)0x7fffffff) return Fault(fp,EOVERFLOW);
1379 else iosz = static_cast<int>(nbyte);
1380
1381// Issue the write
1382//
1383 bytes = fp->XCio->Write((char *)buf,fp->Offset(),(int)iosz);
1384 if (bytes < 0) return Fault(fp,-bytes);
1385
1386// All went well
1387//
1388 fp->addOffset(iosz, 1);
1389 fp->UnLock();
1390 return (ssize_t)iosz;
1391}
1392
1393/******************************************************************************/
1394/* W r i t e v */
1395/******************************************************************************/
1396
1397ssize_t XrdPosixXrootd::Writev(int fildes, const struct iovec *iov, int iovcnt)
1398{
1399 ssize_t totbytes = 0;
1400 int i;
1401
1402// Return the results of the write for each iov segment
1403//
1404 for (i = 0; i < iovcnt; i++)
1405 {if (!Write(fildes,(void *)iov[i].iov_base,(size_t)iov[i].iov_len))
1406 return -1;
1407 totbytes += iov[i].iov_len;
1408 }
1409
1410// All done
1411//
1412 return totbytes;
1413}
1414
1415/******************************************************************************/
1416/* i s X r o o t d D i r */
1417/******************************************************************************/
1418
1420{
1421 XrdPosixDir *dP;
1422 int fildes;
1423
1424 if (!dirp) return false;
1425 fildes = XrdPosixDir::dirNo(dirp);
1426
1427 if (!myFD(fildes) || !(dP = XrdPosixObject::Dir(fildes))) return false;
1428
1429 dP->UnLock();
1430 return true;
1431}
1432
1433/******************************************************************************/
1434/* m y F D */
1435/******************************************************************************/
1436
1438{
1439 return XrdPosixObject::Valid(fd);
1440}
1441
1442/******************************************************************************/
1443/* Q u e r y C h k s u m */
1444/******************************************************************************/
1445
1446int XrdPosixXrootd::QueryChksum(const char *path, time_t &Mtime,
1447 char *value, int vsize)
1448{
1450
1451// Stat the file first to allow vectoring of the request to the right server
1452//
1453 if (!admin.Stat(0, &Mtime)) return -1;
1454
1455// Now we can get the checksum as we have landed on the right server
1456//
1457 return admin.Query(XrdCl::QueryCode::Checksum, value, vsize);
1458}
1459
1460/******************************************************************************/
1461/* Q u e r y E r r o r */
1462/******************************************************************************/
1463
1464int XrdPosixXrootd::QueryError(std::string& emsg, int fd, bool reset)
1465{
1466 XrdOucECMsg* ecmP;
1467
1468// If global wanted then use that one otherwise find the object specific one
1469//
1470 if (fd < 0) ecmP = &XrdPosixGlobals::ecMsg;
1471 else {XrdPosixFile *fp;
1472 if (!(fp = XrdPosixObject::File(fd))) return -1;
1473 ecmP = fp->getECMsg();
1474 }
1475
1476// Return the message information
1477//
1478 return ecmP->Get(emsg, reset);
1479}
1480
1481/******************************************************************************/
1482
1483int XrdPosixXrootd::QueryError(std::string& emsg, DIR* dirP, bool reset)
1484{
1485 XrdPosixDir *dP;
1486 int fildes = XrdPosixDir::dirNo(dirP);
1487
1488// Find the object
1489//
1490 if (!(dP = XrdPosixObject::Dir(fildes)))
1491 return XrdPosixGlobals::ecMsg.SetErrno(EBADF);
1492
1493// Return result
1494//
1495 return dP->getECMsg()->Get(emsg, reset);
1496}
1497
1498/******************************************************************************/
1499/* Q u e r y O p a q u e */
1500/******************************************************************************/
1501
1502long long XrdPosixXrootd::QueryOpaque(const char *path, char *value, int size)
1503{
1505
1506// Stat the file first to allow vectoring of the request to the right server
1507//
1508 if (!admin.Stat()) return -1;
1509
1510// Now we can get the checksum as we have landed on the right server
1511//
1512 return admin.Query(XrdCl::QueryCode::OpaqueFile, value, size);
1513}
1514
1515/******************************************************************************/
1516/* P r i v a t e M e t h o d s */
1517/******************************************************************************/
1518/******************************************************************************/
1519/* F a u l t */
1520/******************************************************************************/
1521
1522int XrdPosixXrootd::Fault(XrdPosixFile *fp, int ecode, const char *msg)
1523{
1524 fp->UnLock();
1525 return XrdPosixGlobals::ecMsg.SetErrno(ecode, -1, msg);
1526}
1527
1528/******************************************************************************/
1529/* E c R e n a m e */
1530/******************************************************************************/
1531
1532int XrdPosixXrootd::EcRename(const char *oldpath, const char *newpath,
1533 XrdPosixAdmin &admin)
1534{
1535 XrdCl::URL url(oldpath);
1536 XrdCl::URL newUrl(newpath);
1537
1538 std::string file = url.GetPath();
1539 XrdCl::LocationInfo *info = nullptr;
1540 XrdCl::FileSystem fs(oldpath);
1541
1542 XrdCl::Buffer queryArgs(5), *queryResp = nullptr;
1543 queryArgs.FromString("role");
1544 XrdCl::XRootDStatus st = fs.Query(XrdCl::QueryCode::Config, queryArgs, queryResp);
1545 // xrootdfs call this function with individual servers. but we can only do
1546 // fs.DeepLocate("*"...) agaist a redirector
1547 // xrootdfs already did a stat and know that this is a file, not a dir
1548 if (!st.IsOK() || queryResp->ToString() == "server"
1549 || queryResp->ToString() == "server\n")
1550 {
1551 if (queryResp) delete queryResp;
1552 return XrdPosixMap::Result(admin.Xrd.Mv(admin.Url.GetPathWithParams(),
1553 newUrl.GetPathWithParams()),
1555 }
1556 else
1557 if (queryResp) delete queryResp;
1558
1559 st = fs.DeepLocate("*", XrdCl::OpenFlags::None, info );
1560 std::unique_ptr<XrdCl::LocationInfo> ptr( info );
1561 if( !st.IsOK() )
1563
1564 // check if this is a file or a dir, do not support dir renaming in EC
1565 struct stat buf;
1566 if (XrdPosixXrootd::Stat(oldpath, &buf) != 0)
1567 return XrdPosixGlobals::ecMsg.SetErrno(ENOENT);
1568
1569 if ( ! S_ISREG(buf.st_mode))
1570 return XrdPosixGlobals::ecMsg.SetErrno(ENOTSUP);
1571
1572 if (XrdPosixXrootd::Stat(newpath, &buf) == 0)
1573 return XrdPosixGlobals::ecMsg.SetErrno(EEXIST);
1574
1575 int rc = -ENOENT;
1576 for( size_t i = 0; i < info->GetSize(); ++i )
1577 {
1578 std::string url_i = "root://" + info->At(i).GetAddress() + "/" + file;
1579 XrdPosixAdmin *admin_i = new XrdPosixAdmin(url_i.c_str(),admin.ecMsg);
1580 int x = XrdPosixMap::Result(admin_i->Xrd.Mv(admin_i->Url.GetPathWithParams(),
1581 newUrl.GetPathWithParams()),
1582 admin.ecMsg);
1583 if (x != -ENOENT && rc != 0)
1584 rc = x;
1585 if (admin_i) delete admin_i;
1586 }
1587 return rc;
1588}
1589
1590/******************************************************************************/
1591/* E c S t a t */
1592/******************************************************************************/
1593
1594int XrdPosixXrootd::EcStat(const char *path, struct stat *buf,
1595 XrdPosixAdmin &admin)
1596{
1597 XrdCl::URL url(path);
1598 std::string file = url.GetPath();
1599 XrdCl::LocationInfo *info = nullptr;
1600 XrdCl::FileSystem fs(path);
1601
1602 std::vector<std::string> xattrkeys;
1603 std::vector<XrdCl::XAttr> xattrvals;
1604 xattrkeys.push_back("xrdec.strpver");
1605 xattrkeys.push_back("xrdec.filesize");
1606
1607 XrdCl::Buffer queryArgs(5), *queryResp = nullptr;
1608 queryArgs.FromString("role");
1609 XrdCl::XRootDStatus st = fs.Query(XrdCl::QueryCode::Config, queryArgs, queryResp);
1610 // xrootdfs call this function with individual servers. but we can only do
1611 // // fs.DeepLocate("*"...) agaist a redirector
1612 if (!st.IsOK() || queryResp->ToString() == "server"
1613 || queryResp->ToString() == "server\n")
1614 {
1615 if (queryResp) delete queryResp;
1616 if (!admin.Stat(*buf))
1617 return -1;
1618 else
1619 {
1620 st = fs.GetXAttr(file, xattrkeys, xattrvals, 0);
1621 if (! xattrvals[0].value.empty())
1622 {
1623 std::stringstream sstream0(xattrvals[0].value);
1624 sstream0 >> buf->st_mtime;
1625 std::stringstream sstream1(xattrvals[1].value);
1626 sstream1 >> buf->st_size;
1627 buf->st_blocks = (buf->st_size + 512)/512;
1628 }
1629 return 0;
1630 }
1631 }
1632 else
1633 if (queryResp) delete queryResp;
1634
1635 st = fs.DeepLocate("*", XrdCl::OpenFlags::None, info );
1636 std::unique_ptr<XrdCl::LocationInfo> ptr( info );
1637 if( !st.IsOK() )
1638 {
1639 errno = ENOENT;
1640 return -1;
1641 }
1642
1643 int found = 0;
1644 uint64_t verNumMax = 0;
1645 struct stat buf_i;
1647 for( size_t i = 0; i < info->GetSize(); ++i )
1648 {
1649 std::string url_i = "root://" + info->At(i).GetAddress() + "/" + file;
1650 XrdPosixAdmin *admin_i = new XrdPosixAdmin(url_i.c_str(),admin.ecMsg);
1651
1652 if (admin_i->Stat(buf_i))
1653 {
1654 if (! S_ISREG(buf_i.st_mode))
1655 {
1656 memcpy(buf, &buf_i, sizeof(struct stat));
1657 if (admin_i) delete admin_i;
1658 return 0;
1659 }
1660 else
1661 {
1662 if (verNumMax == 0) memcpy(buf, &buf_i, sizeof(struct stat));
1663 found = 1;
1664 }
1665 XrdCl::FileSystem *fs_i = new XrdCl::FileSystem(info->At( i ).GetAddress());
1666
1667 xattrvals.clear();
1668 st = fs_i->GetXAttr(file, xattrkeys, xattrvals, 0);
1669 if (! xattrvals[0].value.empty())
1670 {
1671 std::stringstream sstream(xattrvals[0].value);
1672 uint64_t verNum;
1673 sstream >> verNum;
1674 if ( verNum > verNumMax )
1675 {
1676 verNumMax = verNum;
1677 memcpy(buf, &buf_i, sizeof(struct stat));
1678 buf->st_mtime = verNumMax; // assume verNum is mtime
1679 std::stringstream sstream(xattrvals[1].value);
1680 sstream >> buf->st_size;
1681 buf->st_blocks = (buf->st_size + 512)/512;
1682 }
1683 }
1684 if (fs_i) delete fs_i;
1685 }
1686 if (admin_i) delete admin_i;
1687 }
1688 if (! found)
1689 {
1690 errno = ENOENT;
1691 return -1;
1692 }
1693 return 0;
1694}
1695
1696/******************************************************************************/
1697/* E c U n l i n k */
1698/******************************************************************************/
1699
1700int XrdPosixXrootd::EcUnlink(const char *path, XrdPosixAdmin &admin)
1701{
1702 XrdCl::URL url(path);
1703 std::string file = url.GetPath();
1704 XrdCl::LocationInfo *info = nullptr;
1705 XrdCl::FileSystem fs(path);
1706
1707 XrdCl::Buffer queryArgs(5), *queryResp = nullptr;
1708 queryArgs.FromString("role");
1709 XrdCl::XRootDStatus st = fs.Query(XrdCl::QueryCode::Config, queryArgs, queryResp);
1710 // xrootdfs call this function with individual servers. but we can only do
1711 // fs.DeepLocate("*"...) agaist a redirector
1712 if (!st.IsOK() || queryResp->ToString() == "server"
1713 || queryResp->ToString() == "server\n")
1714 {
1715 if (queryResp) delete queryResp;
1716 return XrdPosixMap::Result(admin.Xrd.Rm(admin.Url.GetPathWithParams()),
1717 admin.ecMsg, true);
1718 }
1719 else
1720 if (queryResp) delete queryResp;
1721
1722 st = fs.DeepLocate("*", XrdCl::OpenFlags::None, info );
1723 std::unique_ptr<XrdCl::LocationInfo> ptr( info );
1724 if( !st.IsOK() )
1725 return XrdPosixMap::Result(st, admin.ecMsg, true);
1726
1727 int rc = -ENOENT;
1728 for( size_t i = 0; i < info->GetSize(); ++i )
1729 {
1730 std::string url_i = "root://" + info->At(i).GetAddress() + "/" + file;
1731 XrdPosixAdmin *admin_i = new XrdPosixAdmin(url_i.c_str(),admin.ecMsg);
1732 int x = XrdPosixMap::Result(admin_i->
1733 Xrd.Rm(admin_i->Url.GetPathWithParams()),
1734 admin.ecMsg);
1735 if (x != -ENOENT && rc != 0)
1736 rc = x;
1737 if (admin_i) delete admin_i;
1738 }
1739 return rc;
1740}
#define ENOATTR
#define DEBUG(x)
#define EPNAME(x)
#define TRACE_Debug
#define DEBUGON
XrdVERSIONINFO(XrdPosix, XrdPosix)
#define statvfs(a, b)
Definition XrdPosix.hh:100
#define stat(a, b)
Definition XrdPosix.hh:96
#define statfs(a, b)
Definition XrdPosix.hh:98
int emsg(int rc, char *msg)
Binary blob representation.
void FromString(const std::string str)
Fill the buffer from a string.
std::string ToString() const
Convert the buffer to a string.
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:304
bool IsValid() const
Is the url valid.
Definition XrdClURL.cc:438
int GetPort() const
Get the target port.
Definition XrdClURL.hh:183
virtual int Read(char *buff, long long offs, int rlen)=0
virtual int Fstat(struct stat &sbuff)
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)
virtual int Rename(const char *oldp, const char *newp)
virtual int Stat(const char *url, struct stat &sbuff)
virtual int Truncate(const char *path, off_t size)
virtual int Unlink(const char *path)
virtual int LocalFilePath(const char *url, char *buff=0, int blen=0, LFP_Reason why=ForAccess, bool forall=false)
virtual int Prepare(const char *url, int oflags, mode_t mode)
virtual int Rmdir(const char *dirp)
int Get(std::string &ecm, bool rst=true)
int SetErrno(int ecc, int retval=-1, const char *alt=0)
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)
void rewind()
long getOffset()
DIR * Open()
bool Unread()
dirent64 * nextEntry(dirent64 *dp=0)
void setOffset(long offset)
long getEntries()
const char * Origin()
static const int isUpdt
static const int isStrm
XrdPosixPrepIO * PrepIO
void UpdtSize(size_t newsz)
long long addOffset(long long offs, int updtSz=0)
int Fstat(struct stat &buf) override
bool Close(XrdCl::XRootDStatus &Status)
XrdCl::File clFile
XrdOucCacheIO * XCio
const char * Path() override
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)
static XrdCl::Access::Mode Mode2Access(mode_t mode)
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
XrdOucECMsg * getECMsg()
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()
XrdScheduler * schedP
XrdSysLogger * theLogger
XrdPosixStats Stats
thread_local XrdOucECMsg ecMsg
XrdSysError * eDest
XrdOucCache * theCache
XrdOucName2Name * theN2N
XrdSysTrace Trace
XrdCl::DirListFlags::Flags dlFlag
@ 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.
std::string ToString() const
Create a string representation.