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