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();
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
677bool 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
704DIR* 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
741ssize_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
772void XrdPosixXrootd::Pread(int fildes, void *buf, size_t nbyte, off_t offset,
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
808ssize_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
839void 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
875ssize_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
906ssize_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
929ssize_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
950void XrdPosixXrootd::VRead(int fildes, const XrdOucIOVec *readV, int n,
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
968struct 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
990struct 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
1019int 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
1041int 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
1066int XrdPosixXrootd::Rename(const char *oldpath, const char *newpath)
1067{
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()),
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
1116int 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;
1130 }
1131
1132// Issue the rmdir
1133//
1134 return XrdPosixMap::Result(admin.Xrd.RmDir(admin.Url.GetPathWithParams()),
1136}
1137
1138/******************************************************************************/
1139/* S e e k d i r */
1140/******************************************************************************/
1141
1142void 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
1165int 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
1200int 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
1237int 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
1325int 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),
1347}
1348
1349/******************************************************************************/
1350/* U n l i n k */
1351/******************************************************************************/
1352
1353int 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;
1367 }
1368
1369// Issue the UnLink
1370//
1372 return EcUnlink(path, admin);
1373
1374 return XrdPosixMap::Result(admin.Xrd.Rm(admin.Url.GetPathWithParams()),
1376}
1377
1378/******************************************************************************/
1379/* W r i t e */
1380/******************************************************************************/
1381
1382ssize_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
1412ssize_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
1461int 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
1479int 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
1498int 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
1517long 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
1537int 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
1547int 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()),
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() )
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
1609int 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;
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
1715int 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
#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: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)
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.