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 c n t l */
367/******************************************************************************/
368
370 const std::string& args,
371 std::string& resp)
372{
373 XrdPosixFile *fp;
374
375// Find the file object
376//
377 if (!(fp = XrdPosixObject::File(fildes))) return -1;
378
379// At the moment we support nothing
380//
381 resp = "Function not supported.";
382 errno = ENOTSUP;
383 return -1;
384}
385
386/******************************************************************************/
387/* F s t a t */
388/******************************************************************************/
389
390int XrdPosixXrootd::Fstat(int fildes, struct stat *buf)
391{
392 XrdPosixFile *fp;
393 int rc;
394
395// Find the file object
396//
397 if (!(fp = XrdPosixObject::File(fildes))) return -1;
398
399// First initialize the stat buffer
400//
402
403// Check if we can get the stat information from the cache.
404//
405 rc = fp->XCio->Fstat(*buf);
406 if (rc <= 0)
407 {fp->UnLock();
408 if (!rc) return 0;
409 errno = -rc; //???
410 return -1;
411 }
412
413// At this point we can call the file's Fstat() and if the file is not open
414// it will be opened.
415//
416 rc = fp->Fstat(*buf);
417 fp->UnLock();
418 if (rc < 0) {errno = -rc; rc = -1;}
419 return rc;
420}
421
422/******************************************************************************/
423/* F s y n c */
424/******************************************************************************/
425
427{
428 XrdPosixFile *fp;
429 int rc;
430
431// Find the file object
432//
433 if (!(fp = XrdPosixObject::File(fildes))) return -1;
434
435// Do the sync
436//
437 if ((rc = fp->XCio->Sync()) < 0) return Fault(fp, -rc);
438 fp->UnLock();
439 return 0;
440}
441
442/******************************************************************************/
443
445{
446 XrdPosixFile *fp;
447
448// Find the file object and do the sync
449//
450 if ((fp = XrdPosixObject::File(fildes)))
451 {cbp->theFile = fp;
452 fp->Ref(); fp->UnLock();
453 fp->XCio->Sync(*cbp);
454 } else cbp->Complete(-1);
455}
456
457/******************************************************************************/
458/* F t r u n c a t e */
459/******************************************************************************/
460
461int XrdPosixXrootd::Ftruncate(int fildes, off_t offset)
462{
463 XrdPosixFile *fp;
464 int rc;
465
466// Find the file object
467//
468 if (!(fp = XrdPosixObject::File(fildes))) return -1;
469
470// Do the trunc
471//
472 if ((rc = fp->XCio->Trunc(offset)) < 0) return Fault(fp, -rc);
473 fp->UnLock();
474 return 0;
475}
476
477/******************************************************************************/
478/* G e t x a t t r */
479/******************************************************************************/
480
481#ifndef ENOATTR
482#define ENOATTR ENOTSUP
483#endif
484
485long long XrdPosixXrootd::Getxattr (const char *path, const char *name,
486 void *value, unsigned long long size)
487{
490 int vsize = static_cast<int>(size);
491
492// Check if user just wants the maximum length needed
493//
494 if (size == 0) return 1024;
495
496// Check if we support the query
497//
498 if (name)
499 { if (!strcmp(name,"xroot.cksum")) reqCode=XrdCl::QueryCode::Checksum;
500 else if (!strcmp(name,"xroot.space")) reqCode=XrdCl::QueryCode::Space;
501 else if (!strcmp(name,"xroot.xattr")) reqCode=XrdCl::QueryCode::XAttr;
502 else {errno = ENOATTR; return -1;} //???
503 }else {errno = EINVAL; return -1;}
504
505// Stat the file first to allow vectoring of the request to the right server
506//
507 if (!admin.Stat()) return -1;
508
509// Return the result
510//
511 return admin.Query(reqCode, value, vsize);
512}
513
514/******************************************************************************/
515/* L s e e k */
516/******************************************************************************/
517
518off_t XrdPosixXrootd::Lseek(int fildes, off_t offset, int whence)
519{
520 XrdPosixFile *fp;
521 long long curroffset;
522
523// Find the file object
524//
525 if (!(fp = XrdPosixObject::File(fildes))) return -1;
526
527// Set the new offset. Note that SEEK_END requires that the file be opened.
528// An open may occur by calling the FSize() method via the cache pointer.
529//
530 if (whence == SEEK_SET) curroffset = fp->setOffset(offset);
531 else if (whence == SEEK_CUR) curroffset = fp->addOffset(offset);
532 else if (whence == SEEK_END)
533 {curroffset = fp->XCio->FSize();
534 if (curroffset < 0) return Fault(fp,static_cast<int>(-curroffset));
535 curroffset = fp->setOffset(curroffset+offset);
536 }
537 else return Fault(fp, EINVAL);
538
539// All done
540//
541 fp->UnLock();
542 return curroffset;
543}
544
545/******************************************************************************/
546/* M k d i r */
547/******************************************************************************/
548
549int XrdPosixXrootd::Mkdir(const char *path, mode_t mode)
550{
553
554// Preferentially make the whole path unless told otherwise
555//
556 flags = (mode & S_ISUID ? XrdCl::MkDirFlags::None
558
559// Make sure the admin is OK
560//
561 if (!admin.isOK()) return -1;
562
563// Issue the mkdir
564//
566 flags,
569 );
570}
571
572/******************************************************************************/
573/* O p e n */
574/******************************************************************************/
575
576int XrdPosixXrootd::Open(const char *path, int oflags, mode_t mode,
577 XrdPosixCallBack *cbP)
578{
579 return Open(path, oflags, mode, cbP, 0);
580}
581
582int XrdPosixXrootd::Open(const char *path, int oflags, mode_t mode,
583 XrdPosixCallBack *cbP, XrdPosixInfo *infoP)
584{
585 EPNAME("Open");
586 XrdCl::XRootDStatus Status;
587 XrdPosixFile *fp;
590 int Opts;
591 bool aOK, isRO = false;
592
593// Translate R/W and R/O flags
594//
595 if ((oflags & O_ACCMODE) != O_RDONLY)
596 {Opts = XrdPosixFile::isUpdt;
597 XOflags = XrdCl::OpenFlags::Update;
598 } else {
599 Opts = 0;
600 XOflags = XrdCl::OpenFlags::Read;
601 isRO = true;
602 }
603
604// Pass along the stream flag
605//
606 if (oflags & isStream)
608 return XrdPosixGlobals::ecMsg.SetErrno(EMFILE);
609 }
610
611// Translate create vs simple open. Always make dirpath on create!
612//
613 if (oflags & O_CREAT)
614 {XOflags |= (oflags & O_EXCL ? XrdCl::OpenFlags::New
617 XOmode = XrdPosixMap::Mode2Access(mode);
618 }
619 else if (oflags & O_TRUNC && Opts & XrdPosixFile::isUpdt)
620 XOflags |= XrdCl::OpenFlags::Delete;
621
622// Allocate the new file object
623//
624 if (!(fp = new XrdPosixFile(aOK, path, cbP, Opts)))
625 return XrdPosixGlobals::ecMsg.SetErrno(EMFILE);
626
627// Check if all went well during allocation
628//
629 if (!aOK) {delete fp; return -1;}
630
631// If we have a cache, then issue a prepare as the cache may want to defer the
632// open request ans we have a lot more work to do.
633//
635 {int rc;
636 if (infoP && isRO && OpenCache(*fp, *infoP))
637 {delete fp;
638 errno = 0;
639 return -3;
640 }
641 rc = XrdPosixGlobals::theCache->Prepare(fp->Path(), oflags, mode);
642 if (rc > 0) return OpenDefer(fp, cbP, XOflags, XOmode, oflags&isStream);
643 if (rc < 0) {delete fp; return XrdPosixGlobals::ecMsg.SetErrno(-rc);}
644 }
645
646// Open the file (sync or async)
647//
649 if (!cbP) Status = fp->clFile.Open((std::string)path, XOflags, XOmode);
650 else Status = fp->clFile.Open((std::string)path, XOflags, XOmode,
651 (XrdCl::ResponseHandler *)fp);
652
653// If we failed, return the reason
654//
655 if (!Status.IsOK())
657 int rc = XrdPosixMap::Result(Status,XrdPosixGlobals::ecMsg,false);
658 if (DEBUGON && rc != -ENOENT && rc != -ELOOP)
659 {DEBUG(XrdPosixGlobals::ecMsg.Msg() <<" open " << obfuscateAuth(fp->Origin()));}
660 delete fp;
661 errno = -rc; // Saved errno across the delete
662 return -1;
663 }
664
665// Assign a file descriptor to this file
666//
667 if (!(fp->AssignFD(oflags & isStream)))
668 {delete fp;
669 return XrdPosixGlobals::ecMsg.SetErrno(EMFILE);
670 }
671
672// Finalize the open (this gets the stat info). For async opens, the
673// finalization is deferred until the callback happens.
674//
675 if (cbP) {errno = EINPROGRESS; return -1;}
676 if (fp->Finalize(&Status)) return fp->FDNum();
677
678// At this point the open() has failed as we could neither defer nor finalize.
679// We need to delete the file pointer and come up with a rational errno as a
680// file descriptor should not be returned. We need to return the causal error
681// message and errno. It is considered impossible for no error state to exist.
682//
683 delete fp;
684 if (XrdPosixMap::Result(Status,XrdPosixGlobals::ecMsg,true)) return -1;
685
686// The impossible happened, there is no error state. So, create a suitable one.
687// Note that our error text will be included as contextual information since
688// ENOMSG, while logically correct, provides no useful information.
689//
690 XrdPosixGlobals::ecMsg = "Impossible condition detected!";
691 XrdPosixGlobals::ecMsg = errno = ENOMSG;
692 return -1;
693}
694
695/******************************************************************************/
696/* Private: O p e n C a c h e */
697/******************************************************************************/
698
699bool XrdPosixXrootd::OpenCache(XrdPosixFile &file,XrdPosixInfo &Info)
700{
701 EPNAME("OpenCache");
702 int rc;
703
704// Check if the full file is in the cache
705//
706 rc = XrdPosixGlobals::theCache->LocalFilePath(file.Path(), Info.cachePath,
707 (int)sizeof(Info.cachePath),
709 Info.ffReady);
710 if (rc == 0)
711 {Info.ffReady = true;
712 DEBUG("File in cache url=" <<Info.cacheURL);
713 return true;
714 }
715
716// File is not fully in the cache
717//
718 Info.ffReady = false;
719 return false;
720}
721
722/******************************************************************************/
723/* O p e n d i r */
724/******************************************************************************/
725
726DIR* XrdPosixXrootd::Opendir(const char *path)
727{
728 XrdPosixDir *dP;
729 DIR *dirP;
730 int rc;
731
732// Get a new directory object
733//
734 if (!(dP = new XrdPosixDir(path)))
735 {XrdPosixGlobals::ecMsg.SetErrno(ENOMEM);
736 return (DIR*)0;
737 }
738
739// Assign a file descriptor to this file
740//
741 if (!(dP->AssignFD()))
742 {delete dP;
743 XrdPosixGlobals::ecMsg.SetErrno(EMFILE);
744 return (DIR*)0;
745 }
746
747// Open the directory
748//
749 if ((dirP = dP->Open())) return dirP;
750
751// We failed
752//
753 rc = errno;
754 delete dP;
755 errno = rc; // Restore saved errno
756 return (DIR *)0;
757}
758
759/******************************************************************************/
760/* P r e a d */
761/******************************************************************************/
762
763ssize_t XrdPosixXrootd::Pread(int fildes, void *buf, size_t nbyte, off_t offset)
764{
765 XrdPosixFile *fp;
766 long long offs, bytes;
767 int iosz;
768
769// Find the file object
770//
771 if (!(fp = XrdPosixObject::File(fildes)))
772 return XrdPosixGlobals::ecMsg.SetErrno(EBADF);
773
774// Make sure the size is not too large
775//
776 if (nbyte > (size_t)0x7fffffff)
777 return Fault(fp, EOVERFLOW, "read size too large");
778 else iosz = static_cast<int>(nbyte);
779
780// Issue the read
781//
782 offs = static_cast<long long>(offset);
783 bytes = fp->XCio->Read((char *)buf, offs, (int)iosz);
784 if (bytes < 0) return Fault(fp,-bytes,"*");
785
786// All went well
787//
788 fp->UnLock();
789 return (ssize_t)bytes;
790}
791
792/******************************************************************************/
793
794void XrdPosixXrootd::Pread(int fildes, void *buf, size_t nbyte, off_t offset,
796{
797 XrdPosixFile *fp;
798 long long offs;
799 int iosz;
800
801// Find the file object
802//
803 if (!(fp = XrdPosixObject::File(fildes))) {cbp->Complete(-1); return;}
804
805// Make sure the size is not too large
806//
807 if (nbyte > (size_t)0x7fffffff)
808 {fp->UnLock();
809 fp->ecMsg.SetErrno(EOVERFLOW,0,"read size too large");
810 cbp->Complete(-1);
811 return;
812 }
813
814// Prepare for the read
815//
816 cbp->theFile = fp;
817 fp->Ref(); fp->UnLock();
818 iosz = static_cast<int>(nbyte);
819 offs = static_cast<long long>(offset);
820
821// Issue the read
822//
823 fp->XCio->Read(*cbp, (char *)buf, offs, (int)iosz);
824}
825
826/******************************************************************************/
827/* P w r i t e */
828/******************************************************************************/
829
830ssize_t XrdPosixXrootd::Pwrite(int fildes, const void *buf, size_t nbyte, off_t offset)
831{
832 XrdPosixFile *fp;
833 long long offs;
834 int iosz, bytes;
835
836// Find the file object
837//
838 if (!(fp = XrdPosixObject::File(fildes))) return -1;
839
840// Make sure the size is not too large
841//
842 if (nbyte > (size_t)0x7fffffff)
843 return Fault(fp,EOVERFLOW,"write size too large");
844 else iosz = static_cast<int>(nbyte);
845
846// Issue the write
847//
848 offs = static_cast<long long>(offset);
849 bytes = fp->XCio->Write((char *)buf, offs, (int)iosz);
850 if (bytes < 0) return Fault(fp,-bytes,"*");
851
852// All went well
853//
854 fp->UpdtSize(offs + iosz);
855 fp->UnLock();
856 return (ssize_t)iosz;
857}
858
859/******************************************************************************/
860
861void XrdPosixXrootd::Pwrite(int fildes, const void *buf, size_t nbyte,
862 off_t offset, XrdPosixCallBackIO *cbp)
863{
864 XrdPosixFile *fp;
865 long long offs;
866 int iosz;
867
868// Find the file object
869//
870 if (!(fp = XrdPosixObject::File(fildes))) {cbp->Complete(-1); return;}
871
872// Make sure the size is not too large
873//
874 if (nbyte > (size_t)0x7fffffff)
875 {fp->UnLock();
876 fp->ecMsg.SetErrno(EOVERFLOW,0,"read size too large");
877 cbp->Complete(-1);
878 return;
879 }
880
881// Prepare for the writing
882//
883 cbp->theFile = fp;
884 fp->Ref(); fp->UnLock();
885 iosz = static_cast<int>(nbyte);
886 offs = static_cast<long long>(offset);
887
888// Issue the read
889//
890 fp->XCio->Write(*cbp, (char *)buf, offs, (int)iosz);
891}
892
893/******************************************************************************/
894/* R e a d */
895/******************************************************************************/
896
897ssize_t XrdPosixXrootd::Read(int fildes, void *buf, size_t nbyte)
898{
899 XrdPosixFile *fp;
900 long long bytes;
901 int iosz;
902
903// Find the file object
904//
905 if (!(fp = XrdPosixObject::File(fildes))) return -1;
906
907// Make sure the size is not too large
908//
909 if (nbyte > (size_t)0x7fffffff) return Fault(fp,EOVERFLOW);
910 else iosz = static_cast<int>(nbyte);
911
912// Issue the read
913//
914 bytes = fp->XCio->Read((char *)buf,fp->Offset(),(int)iosz);
915 if (bytes < 0) return Fault(fp,-bytes);
916
917// All went well
918//
919 fp->addOffset(bytes);
920 fp->UnLock();
921 return (ssize_t)bytes;
922}
923
924/******************************************************************************/
925/* R e a d v */
926/******************************************************************************/
927
928ssize_t XrdPosixXrootd::Readv(int fildes, const struct iovec *iov, int iovcnt)
929{
930 ssize_t bytes, totbytes = 0;
931 int i;
932
933// Return the results of the read for each iov segment
934//
935 for (i = 0; i < iovcnt; i++)
936 {bytes = Read(fildes,(void *)iov[i].iov_base,(size_t)iov[i].iov_len);
937 if (bytes > 0) totbytes += bytes;
938 else if (bytes < 0) return -1;
939 else break;
940 }
941
942// All done
943//
944 return totbytes;
945}
946
947/******************************************************************************/
948/* V R e a d */
949/******************************************************************************/
950
951ssize_t XrdPosixXrootd::VRead(int fildes, const XrdOucIOVec *readV, int n)
952{
953 XrdPosixFile *fp;
954 ssize_t bytes;
955
956// Find the file object
957//
958 if (!(fp = XrdPosixObject::File(fildes))) return -1;
959
960// Issue the read
961//
962 if ((bytes = fp->XCio->ReadV(readV, n)) < 0) return Fault(fp,-bytes);
963
964// Return bytes read
965//
966 fp->UnLock();
967 return bytes;
968}
969
970/******************************************************************************/
971
972void XrdPosixXrootd::VRead(int fildes, const XrdOucIOVec *readV, int n,
974{
975 XrdPosixFile *fp;
976
977// Find the file object and issue read
978//
979 if ((fp = XrdPosixObject::File(fildes)))
980 {cbp->theFile = fp;
981 fp->Ref(); fp->UnLock();
982 fp->XCio->ReadV(*cbp, readV, n);
983 } else cbp->Complete(-1);
984}
985
986/******************************************************************************/
987/* R e a d d i r */
988/******************************************************************************/
989
990struct dirent* XrdPosixXrootd::Readdir(DIR *dirp)
991{
992 dirent64 *dp64;
993 dirent *dp32; // Could be the same as dp64
994
995 if (!(dp64 = Readdir64(dirp))) return 0;
996
997 dp32 = (struct dirent *)dp64;
998 if ((char*)dp32->d_name != (char*)dp64->d_name)
999 {dp32->d_ino = dp64->d_ino;
1000#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__GNU__) && !(defined(__FreeBSD_kernel__) && defined(__GLIBC__))
1001 dp32->d_off = dp64->d_off;
1002#endif
1003#ifndef __solaris__
1004 dp32->d_type = dp64->d_type;
1005#endif
1006 dp32->d_reclen = dp64->d_reclen;
1007 strcpy(dp32->d_name, dp64->d_name);
1008 }
1009 return dp32;
1010}
1011
1012struct dirent64* XrdPosixXrootd::Readdir64(DIR *dirp)
1013{
1014 XrdPosixDir *dP;
1015 dirent64 *dentP;
1016 int rc, fildes = XrdPosixDir::dirNo(dirp);
1017
1018// Find the object
1019//
1020 if (!(dP = XrdPosixObject::Dir(fildes)))
1021 {XrdPosixGlobals::ecMsg.SetErrno(EBADF);
1022 return (dirent64*)0;
1023 }
1024
1025// Get the next directory entry
1026//
1027 if (!(dentP = dP->nextEntry())) rc = dP->Status();
1028 else rc = 0;
1029
1030// Return the appropriate result
1031//
1032 dP->UnLock();
1033 if (rc) errno = rc;
1034 return dentP;
1035}
1036
1037/******************************************************************************/
1038/* R e a d d i r _ r */
1039/******************************************************************************/
1040
1041int XrdPosixXrootd::Readdir_r(DIR *dirp, struct dirent *entry,
1042 struct dirent **result)
1043{
1044 dirent64 *dp64 = 0, d64ent;
1045 int rc;
1046
1047 if ((rc = Readdir64_r(dirp, &d64ent, &dp64)) || !dp64)
1048 {*result = 0; return rc;}
1049
1050 entry->d_ino = dp64->d_ino;
1051#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__GNU__) && !(defined(__FreeBSD_kernel__) && defined(__GLIBC__))
1052 entry->d_off = dp64->d_off;
1053#endif
1054#ifndef __solaris__
1055 entry->d_type = dp64->d_type;
1056#endif
1057 entry->d_reclen = dp64->d_reclen;
1058 strcpy(entry->d_name, dp64->d_name);
1059 *result = entry;
1060 return rc;
1061}
1062
1063int XrdPosixXrootd::Readdir64_r(DIR *dirp, struct dirent64 *entry,
1064 struct dirent64 **result)
1065{
1066 XrdPosixDir *dP;
1067 int rc, fildes = XrdPosixDir::dirNo(dirp);
1068
1069// Find the object
1070//
1071 if (!(dP = XrdPosixObject::Dir(fildes))) return EBADF;
1072
1073// Get the next entry
1074//
1075 if (!(*result = dP->nextEntry(entry))) {rc = dP->Status(); *result = 0;}
1076 else {rc = 0; *result = entry;}
1077
1078// Return the appropriate result
1079//
1080 dP->UnLock();
1081 return rc;
1082}
1083
1084/******************************************************************************/
1085/* R e n a m e */
1086/******************************************************************************/
1087
1088int XrdPosixXrootd::Rename(const char *oldpath, const char *newpath)
1089{
1091 XrdCl::URL newUrl((std::string)newpath);
1092
1093// Make sure the admin is OK and the new url is valid
1094//
1095 if (!admin.isOK() || !newUrl.IsValid())
1096 return XrdPosixGlobals::ecMsg.SetErrno(EINVAL);
1097
1098// Issue rename to he cache (it really should just deep-six both files)
1099//
1101 {LfnPath oldF("rename", oldpath);
1102 LfnPath newF("rename", newpath);
1103 if (!oldF.path || !newF.path) return -1;
1104 XrdPosixGlobals::theCache->Rename(oldF.path, newF.path);
1105 }
1106
1107// Issue the rename
1108//
1110 return EcRename(oldpath, newpath, admin);
1111
1112 return XrdPosixMap::Result(admin.Xrd.Mv(admin.Url.GetPathWithParams(),
1113 newUrl.GetPathWithParams()),
1115}
1116
1117/******************************************************************************/
1118/* R e w i n d d i r */
1119/******************************************************************************/
1120
1122{
1123 XrdPosixDir *dP;
1124 int fildes = XrdPosixDir::dirNo(dirp);
1125
1126// Find the object and rewind it
1127//
1128 if ((dP = XrdPosixObject::Dir(fildes)))
1129 {dP->rewind();
1130 dP->UnLock();
1131 }
1132}
1133
1134/******************************************************************************/
1135/* R m d i r */
1136/******************************************************************************/
1137
1138int XrdPosixXrootd::Rmdir(const char *path)
1139{
1141
1142// Make sure the admin is OK
1143//
1144 if (!admin.isOK()) return -1;
1145
1146// Remove directory from the cache first
1147//
1149 {LfnPath rmd("rmdir", path);
1150 if (!rmd.path) return -1;
1151 XrdPosixGlobals::theCache->Rmdir(rmd.path);
1152 }
1153
1154// Issue the rmdir
1155//
1156 return XrdPosixMap::Result(admin.Xrd.RmDir(admin.Url.GetPathWithParams()),
1158}
1159
1160/******************************************************************************/
1161/* S e e k d i r */
1162/******************************************************************************/
1163
1164void XrdPosixXrootd::Seekdir(DIR *dirp, long loc)
1165{
1166 XrdPosixDir *dP;
1167 int fildes = XrdPosixDir::dirNo(dirp);
1168
1169// Find the object
1170//
1171 if (!(dP = XrdPosixObject::Dir(fildes))) return;
1172
1173// Sets the current directory position
1174//
1175 if (dP->Unread() && !(dP->Open()))
1176 {if (loc >= dP->getEntries()) loc = dP->getEntries();
1177 else if (loc < 0) loc = 0;
1178 dP->setOffset(loc);
1179 }
1180 dP->UnLock();
1181}
1182
1183/******************************************************************************/
1184/* S t a t */
1185/******************************************************************************/
1186
1187int XrdPosixXrootd::Stat(const char *path, struct stat *buf)
1188{
1190 bool cacheChk = false;
1191
1192// Make sure the admin is OK
1193//
1194 if (!admin.isOK()) return -1;
1195
1196// Initialize the stat buffer
1197//
1199
1200// Check if we can get the stat informatation from the cache
1201//
1203 {LfnPath statX("stat", path, false);
1204 if (!statX.path) return -1;
1205 int rc = XrdPosixGlobals::theCache->Stat(statX.path, *buf);
1206 if (!rc) return 0;
1207 if (rc < 0) {errno = -rc; return -1;} // does the cache set this???
1208 cacheChk = true;
1209 }
1210
1211// Issue the stat and verify that all went well
1212//
1214 return EcStat(path, buf, admin);
1215
1216 if (!admin.Stat(*buf)) return -1;
1217
1218// If we are here and the cache was checked then the file was not in the cache.
1219// We informally tell the caller this is the case by setting atime to zero.
1220// Normally, atime will never be zero in any other case.
1221//
1222 if (cacheChk) buf->st_atime = 0;
1223 return 0;
1224}
1225
1226/******************************************************************************/
1227/* S t a t f s */
1228/******************************************************************************/
1229
1230int XrdPosixXrootd::Statfs(const char *path, struct statfs *buf)
1231{
1232 struct statvfs myVfs;
1233 int rc;
1234
1235// Issue a statvfs() call and transcribe the results
1236//
1237 if ((rc = Statvfs(path, &myVfs))) return rc;
1238
1239// The vfs structure and fs structures should be size compatible (not really)
1240//
1241 memset(buf, 0, sizeof(struct statfs));
1242 buf->f_bsize = myVfs.f_bsize;
1243 buf->f_blocks = myVfs.f_blocks;
1244 buf->f_bfree = myVfs.f_bfree;
1245 buf->f_files = myVfs.f_files;
1246 buf->f_ffree = myVfs.f_ffree;
1247#if defined(__APPLE__) || defined(__FreeBSD__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__))
1248 buf->f_iosize = myVfs.f_frsize;
1249#else
1250 buf->f_frsize = myVfs.f_frsize;
1251#endif
1252#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__GNU__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__))
1253 buf->f_bavail = myVfs.f_bavail;
1254#endif
1255#if defined(__linux__) || defined(__GNU__)
1256 buf->f_namelen = myVfs.f_namemax;
1257#elif defined(__FreeBSD__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__))
1258 buf->f_namemax = myVfs.f_namemax;
1259#endif
1260 return 0;
1261}
1262
1263/******************************************************************************/
1264/* S t a t R e t */
1265/******************************************************************************/
1266
1267int XrdPosixXrootd::StatRet(DIR *dirp, struct stat *buf)
1268{
1269// Find the object
1270//
1271 auto fildes = XrdPosixDir::dirNo(dirp);
1272 auto dP = XrdPosixObject::Dir(fildes);
1273 if (!dP) return EBADF;
1274
1275// Get the stat info
1276 auto rc = dP->StatRet(buf);
1277
1278 dP->UnLock();
1279 return rc;
1280}
1281
1282/******************************************************************************/
1283/* S t a t v f s */
1284/******************************************************************************/
1285
1286int XrdPosixXrootd::Statvfs(const char *path, struct statvfs *buf)
1287{
1288 static const int szVFS = sizeof(buf->f_bfree);
1289 static const long long max32 = 0x7fffffffLL;
1290
1292 XrdCl::StatInfoVFS *vfsStat;
1293
1294 long long rwFree, ssFree, rwBlks;
1295 int rwNum, ssNum, rwUtil, ssUtil;
1296
1297// Make sure we connected
1298//
1299 if (!admin.isOK()) return -1;
1300
1301// Issue the statfvs call
1302//
1304 vfsStat),
1305 XrdPosixGlobals::ecMsg) < 0) return -1;
1306
1307// Extract out the information
1308//
1309 rwNum = static_cast<int>(vfsStat->GetNodesRW());
1310 rwFree = (long long)vfsStat->GetFreeRW();
1311 rwUtil = static_cast<int>(vfsStat->GetUtilizationRW());
1312 ssNum = static_cast<int>(vfsStat->GetNodesStaging());
1313 ssFree = (long long)vfsStat->GetFreeStaging();
1314 ssUtil = static_cast<int>(vfsStat->GetUtilizationStaging());
1315 delete vfsStat;
1316
1317// Calculate number of blocks
1318//
1319 if (rwUtil == 0) rwBlks = rwFree;
1320 else if (rwUtil >= 100) rwBlks = 0;
1321 else rwBlks = rwFree * (100 / (100 - rwUtil));
1322 if (ssUtil == 0) rwBlks += ssFree;
1323 else if (ssUtil < 100) rwBlks += ssFree * (100 / (100 - ssUtil));
1324
1325// Scale units to what will fit here (we can have a 32-bit or 64-bit struct)
1326//
1327 if (szVFS < 8)
1328 {if (rwBlks > max32) rwBlks = max32;
1329 if (rwFree > max32) rwFree = max32;
1330 if (ssFree > max32) ssFree = max32;
1331 }
1332
1333// Return what little we can
1334//
1335 memset(buf, 0, sizeof(struct statvfs));
1336 buf->f_bsize = 1024*1024;
1337 buf->f_frsize = 1024*1024;
1338 buf->f_blocks = static_cast<fsblkcnt_t>(rwBlks);
1339 buf->f_bfree = static_cast<fsblkcnt_t>(rwFree + ssFree);
1340 buf->f_bavail = static_cast<fsblkcnt_t>(rwFree);
1341 buf->f_ffree = rwNum + ssNum;
1342 buf->f_favail = rwNum;
1343 buf->f_namemax = 255; // The best we are going to do here
1344 buf->f_flag = (rwNum == 0 ? ST_RDONLY|ST_NOSUID : ST_NOSUID);
1345 return 0;
1346}
1347
1348/******************************************************************************/
1349/* T e l l d i r */
1350/******************************************************************************/
1351
1353{
1354 XrdPosixDir *dP;
1355 long pos;
1356 int fildes = XrdPosixDir::dirNo(dirp);
1357
1358// Find the object
1359//
1360 if (!(dP = XrdPosixObject::Dir(fildes)))
1361 return XrdPosixGlobals::ecMsg.SetErrno(EBADF,0);
1362
1363// Tell the current directory location
1364//
1365 pos = dP->getOffset();
1366 dP->UnLock();
1367 return pos;
1368}
1369
1370/******************************************************************************/
1371/* T r u n c a t e */
1372/******************************************************************************/
1373
1374int XrdPosixXrootd::Truncate(const char *path, off_t Size)
1375{
1377 uint64_t tSize = static_cast<uint64_t>(Size);
1378
1379// Make sure the admin is OK
1380//
1381 if (!admin.isOK()) return -1;
1382
1383// Truncate in the cache first
1384//
1386 {LfnPath trunc("truncate", path);
1387 if (!trunc.path) return -1;
1388 XrdPosixGlobals::theCache->Truncate(trunc.path, tSize);
1389 }
1390
1391// Issue the truncate to the origin
1392//
1393 std::string urlp = admin.Url.GetPathWithParams();
1394 return XrdPosixMap::Result(admin.Xrd.Truncate(urlp,tSize),
1396}
1397
1398/******************************************************************************/
1399/* U n l i n k */
1400/******************************************************************************/
1401
1402int XrdPosixXrootd::Unlink(const char *path)
1403{
1405
1406// Make sure the admin is OK
1407//
1408 if (!admin.isOK()) return -1;
1409
1410// Unlink the cache first
1411//
1413 {LfnPath remf("unlink", path);
1414 if (!remf.path) return -1;
1415 XrdPosixGlobals::theCache->Unlink(remf.path);
1416 }
1417
1418// Issue the UnLink
1419//
1421 return EcUnlink(path, admin);
1422
1423 return XrdPosixMap::Result(admin.Xrd.Rm(admin.Url.GetPathWithParams()),
1425}
1426
1427/******************************************************************************/
1428/* W r i t e */
1429/******************************************************************************/
1430
1431ssize_t XrdPosixXrootd::Write(int fildes, const void *buf, size_t nbyte)
1432{
1433 XrdPosixFile *fp;
1434 int iosz, bytes;
1435
1436// Find the file object
1437//
1438 if (!(fp = XrdPosixObject::File(fildes))) return -1;
1439
1440// Make sure the size is not too large
1441//
1442 if (nbyte > (size_t)0x7fffffff) return Fault(fp,EOVERFLOW);
1443 else iosz = static_cast<int>(nbyte);
1444
1445// Issue the write
1446//
1447 bytes = fp->XCio->Write((char *)buf,fp->Offset(),(int)iosz);
1448 if (bytes < 0) return Fault(fp,-bytes);
1449
1450// All went well
1451//
1452 fp->addOffset(iosz, 1);
1453 fp->UnLock();
1454 return (ssize_t)iosz;
1455}
1456
1457/******************************************************************************/
1458/* W r i t e v */
1459/******************************************************************************/
1460
1461ssize_t XrdPosixXrootd::Writev(int fildes, const struct iovec *iov, int iovcnt)
1462{
1463 ssize_t totbytes = 0;
1464 int i;
1465
1466// Return the results of the write for each iov segment
1467//
1468 for (i = 0; i < iovcnt; i++)
1469 {if (!Write(fildes,(void *)iov[i].iov_base,(size_t)iov[i].iov_len))
1470 return -1;
1471 totbytes += iov[i].iov_len;
1472 }
1473
1474// All done
1475//
1476 return totbytes;
1477}
1478
1479/******************************************************************************/
1480/* i s X r o o t d D i r */
1481/******************************************************************************/
1482
1484{
1485 XrdPosixDir *dP;
1486 int fildes;
1487
1488 if (!dirp) return false;
1489 fildes = XrdPosixDir::dirNo(dirp);
1490
1491 if (!myFD(fildes) || !(dP = XrdPosixObject::Dir(fildes))) return false;
1492
1493 dP->UnLock();
1494 return true;
1495}
1496
1497/******************************************************************************/
1498/* m y F D */
1499/******************************************************************************/
1500
1502{
1503 return XrdPosixObject::Valid(fd);
1504}
1505
1506/******************************************************************************/
1507/* Q u e r y C h k s u m */
1508/******************************************************************************/
1509
1510int XrdPosixXrootd::QueryChksum(const char *path, time_t &Mtime,
1511 char *value, int vsize)
1512{
1514
1515// Stat the file first to allow vectoring of the request to the right server
1516//
1517 if (!admin.Stat(0, &Mtime)) return -1;
1518
1519// Now we can get the checksum as we have landed on the right server
1520//
1521 return admin.Query(XrdCl::QueryCode::Checksum, value, vsize);
1522}
1523
1524/******************************************************************************/
1525/* Q u e r y E r r o r */
1526/******************************************************************************/
1527
1528int XrdPosixXrootd::QueryError(std::string& emsg, int fd, bool reset)
1529{
1530 XrdOucECMsg* ecmP;
1531 XrdPosixFile* fp = 0;
1532
1533// If global wanted then use that one otherwise find the object specific one
1534//
1535 if (fd < 0) ecmP = &XrdPosixGlobals::ecMsg;
1536 else {if (!(fp = XrdPosixObject::File(fd))) return -1;
1537 ecmP = fp->getECMsg();
1538 }
1539
1540// Return the message information
1541//
1542 const int rc = ecmP->Get(emsg, reset);
1543 if (fp) fp->UnLock();
1544 return rc;
1545}
1546
1547/******************************************************************************/
1548
1549int XrdPosixXrootd::QueryError(std::string& emsg, DIR* dirP, bool reset)
1550{
1551 XrdPosixDir *dP;
1552 int fildes = XrdPosixDir::dirNo(dirP);
1553
1554// Find the object
1555//
1556 if (!(dP = XrdPosixObject::Dir(fildes)))
1557 return XrdPosixGlobals::ecMsg.SetErrno(EBADF);
1558
1559// Return result
1560//
1561 return dP->getECMsg()->Get(emsg, reset);
1562}
1563
1564/******************************************************************************/
1565/* Q u e r y O p a q u e */
1566/******************************************************************************/
1567
1568long long XrdPosixXrootd::QueryOpaque(const char *path, char *value, int size)
1569{
1571
1572// Stat the file first to allow vectoring of the request to the right server
1573//
1574 if (!admin.Stat()) return -1;
1575
1576// Now we can get the checksum as we have landed on the right server
1577//
1578 return admin.Query(XrdCl::QueryCode::OpaqueFile, value, size);
1579}
1580
1581/******************************************************************************/
1582/* P r i v a t e M e t h o d s */
1583/******************************************************************************/
1584/******************************************************************************/
1585/* F a u l t */
1586/******************************************************************************/
1587
1588int XrdPosixXrootd::Fault(XrdPosixFile *fp, int ecode, const char *msg)
1589{
1590 fp->UnLock();
1591 return XrdPosixGlobals::ecMsg.SetErrno(ecode, -1, msg);
1592}
1593
1594/******************************************************************************/
1595/* E c R e n a m e */
1596/******************************************************************************/
1597
1598int XrdPosixXrootd::EcRename(const char *oldpath, const char *newpath,
1599 XrdPosixAdmin &admin)
1600{
1601 XrdCl::URL url(oldpath);
1602 XrdCl::URL newUrl(newpath);
1603
1604 std::string file = url.GetPath();
1605 XrdCl::LocationInfo *info = nullptr;
1606 XrdCl::FileSystem fs(oldpath);
1607
1608 XrdCl::Buffer queryArgs(5), *queryResp = nullptr;
1609 queryArgs.FromString("role");
1610 XrdCl::XRootDStatus st = fs.Query(XrdCl::QueryCode::Config, queryArgs, queryResp);
1611 // xrootdfs call this function with individual servers. but we can only do
1612 // fs.DeepLocate("*"...) agaist a redirector
1613 // xrootdfs already did a stat and know that this is a file, not a dir
1614 if (!st.IsOK() || queryResp->ToString() == "server"
1615 || queryResp->ToString() == "server\n")
1616 {
1617 if (queryResp) delete queryResp;
1618 return XrdPosixMap::Result(admin.Xrd.Mv(admin.Url.GetPathWithParams(),
1619 newUrl.GetPathWithParams()),
1621 }
1622 else
1623 if (queryResp) delete queryResp;
1624
1625 st = fs.DeepLocate("*", XrdCl::OpenFlags::PrefName, info );
1626 std::unique_ptr<XrdCl::LocationInfo> ptr( info );
1627 if( !st.IsOK() )
1629
1630 // check if this is a file or a dir, do not support dir renaming in EC
1631 struct stat buf;
1632 if (XrdPosixXrootd::Stat(oldpath, &buf) != 0)
1633 return XrdPosixGlobals::ecMsg.SetErrno(ENOENT);
1634
1635 if ( ! S_ISREG(buf.st_mode))
1636 return XrdPosixGlobals::ecMsg.SetErrno(ENOTSUP);
1637
1638 if (XrdPosixXrootd::Stat(newpath, &buf) == 0)
1639 return XrdPosixGlobals::ecMsg.SetErrno(EEXIST);
1640
1641 int rc = -ENOENT;
1642 for( size_t i = 0; i < info->GetSize(); ++i )
1643 {
1644 std::string url_i = "root://" + info->At(i).GetAddress() + "/" + file;
1645 XrdPosixAdmin *admin_i = new XrdPosixAdmin(url_i.c_str(),admin.ecMsg);
1646 int x = XrdPosixMap::Result(admin_i->Xrd.Mv(admin_i->Url.GetPathWithParams(),
1647 newUrl.GetPathWithParams()),
1648 admin.ecMsg);
1649 if (x != -ENOENT && rc != 0)
1650 rc = x;
1651 if (admin_i) delete admin_i;
1652 }
1653 return rc;
1654}
1655
1656/******************************************************************************/
1657/* E c S t a t */
1658/******************************************************************************/
1659
1660int XrdPosixXrootd::EcStat(const char *path, struct stat *buf,
1661 XrdPosixAdmin &admin)
1662{
1663 XrdCl::URL url(path);
1664 std::string file = url.GetPath();
1665 XrdCl::LocationInfo *info = nullptr;
1666 XrdCl::FileSystem fs(path);
1667
1668 std::vector<std::string> xattrkeys;
1669 std::vector<XrdCl::XAttr> xattrvals;
1670 xattrkeys.push_back("xrdec.strpver");
1671 xattrkeys.push_back("xrdec.filesize");
1672
1673 XrdCl::Buffer queryArgs(5), *queryResp = nullptr;
1674 queryArgs.FromString("role");
1675 XrdCl::XRootDStatus st = fs.Query(XrdCl::QueryCode::Config, queryArgs, queryResp);
1676 // xrootdfs call this function with individual servers. but we can only do
1677 // // fs.DeepLocate("*"...) agaist a redirector
1678 if (!st.IsOK() || queryResp->ToString() == "server"
1679 || queryResp->ToString() == "server\n")
1680 {
1681 if (queryResp) delete queryResp;
1682 if (!admin.Stat(*buf))
1683 return -1;
1684 else
1685 {
1686 st = fs.GetXAttr(file, xattrkeys, xattrvals, 0);
1687 if (! xattrvals[0].value.empty())
1688 {
1689 std::stringstream sstream0(xattrvals[0].value);
1690 sstream0 >> buf->st_mtime;
1691 std::stringstream sstream1(xattrvals[1].value);
1692 sstream1 >> buf->st_size;
1693 buf->st_blocks = (buf->st_size + 512)/512;
1694 }
1695 return 0;
1696 }
1697 }
1698 else
1699 if (queryResp) delete queryResp;
1700
1701 st = fs.DeepLocate("*", XrdCl::OpenFlags::PrefName, info );
1702 std::unique_ptr<XrdCl::LocationInfo> ptr( info );
1703 if( !st.IsOK() )
1704 {
1705 errno = ENOENT;
1706 return -1;
1707 }
1708
1709 int found = 0;
1710 uint64_t verNumMax = 0;
1711 struct stat buf_i;
1713 for( size_t i = 0; i < info->GetSize(); ++i )
1714 {
1715 std::string url_i = "root://" + info->At(i).GetAddress() + "/" + file;
1716 XrdPosixAdmin *admin_i = new XrdPosixAdmin(url_i.c_str(),admin.ecMsg);
1717
1718 if (admin_i->Stat(buf_i))
1719 {
1720 if (! S_ISREG(buf_i.st_mode))
1721 {
1722 memcpy(buf, &buf_i, sizeof(struct stat));
1723 if (admin_i) delete admin_i;
1724 return 0;
1725 }
1726 else
1727 {
1728 if (verNumMax == 0) memcpy(buf, &buf_i, sizeof(struct stat));
1729 found = 1;
1730 }
1731 XrdCl::FileSystem *fs_i = new XrdCl::FileSystem(info->At( i ).GetAddress());
1732
1733 xattrvals.clear();
1734 st = fs_i->GetXAttr(file, xattrkeys, xattrvals, 0);
1735 if (! xattrvals[0].value.empty())
1736 {
1737 std::stringstream sstream(xattrvals[0].value);
1738 uint64_t verNum;
1739 sstream >> verNum;
1740 if ( verNum > verNumMax )
1741 {
1742 verNumMax = verNum;
1743 memcpy(buf, &buf_i, sizeof(struct stat));
1744 buf->st_mtime = verNumMax; // assume verNum is mtime
1745 std::stringstream sstream(xattrvals[1].value);
1746 sstream >> buf->st_size;
1747 buf->st_blocks = (buf->st_size + 512)/512;
1748 }
1749 }
1750 if (fs_i) delete fs_i;
1751 }
1752 if (admin_i) delete admin_i;
1753 }
1754 if (! found)
1755 {
1756 errno = ENOENT;
1757 return -1;
1758 }
1759 return 0;
1760}
1761
1762/******************************************************************************/
1763/* E c U n l i n k */
1764/******************************************************************************/
1765
1766int XrdPosixXrootd::EcUnlink(const char *path, XrdPosixAdmin &admin)
1767{
1768 XrdCl::URL url(path);
1769 std::string file = url.GetPath();
1770 XrdCl::LocationInfo *info = nullptr;
1771 XrdCl::FileSystem fs(path);
1772
1773 XrdCl::Buffer queryArgs(5), *queryResp = nullptr;
1774 queryArgs.FromString("role");
1775 XrdCl::XRootDStatus st = fs.Query(XrdCl::QueryCode::Config, queryArgs, queryResp);
1776 // xrootdfs call this function with individual servers. but we can only do
1777 // fs.DeepLocate("*"...) agaist a redirector
1778 if (!st.IsOK() || queryResp->ToString() == "server"
1779 || queryResp->ToString() == "server\n")
1780 {
1781 if (queryResp) delete queryResp;
1782 return XrdPosixMap::Result(admin.Xrd.Rm(admin.Url.GetPathWithParams()),
1783 admin.ecMsg, true);
1784 }
1785 else
1786 if (queryResp) delete queryResp;
1787
1788 st = fs.DeepLocate("*", XrdCl::OpenFlags::PrefName, info );
1789 std::unique_ptr<XrdCl::LocationInfo> ptr( info );
1790 if( !st.IsOK() )
1791 return XrdPosixMap::Result(st, admin.ecMsg, true);
1792
1793 int rc = -ENOENT;
1794 for( size_t i = 0; i < info->GetSize(); ++i )
1795 {
1796 std::string url_i = "root://" + info->At(i).GetAddress() + "/" + file;
1797 XrdPosixAdmin *admin_i = new XrdPosixAdmin(url_i.c_str(),admin.ecMsg);
1798 int x = XrdPosixMap::Result(admin_i->
1799 Xrd.Rm(admin_i->Url.GetPathWithParams()),
1800 admin.ecMsg);
1801 if (x != -ENOENT && rc != 0)
1802 rc = x;
1803 if (admin_i) delete admin_i;
1804 }
1805 return rc;
1806}
#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)
void FromString(const std::string str)
Fill the buffer from a string.
std::string ToString() const
Convert the buffer to a string.
XRootDStatus Mv(const std::string &source, const std::string &dest, ResponseHandler *handler, time_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus Truncate(const std::string &path, uint64_t size, ResponseHandler *handler, time_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus RmDir(const std::string &path, ResponseHandler *handler, time_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus Rm(const std::string &path, ResponseHandler *handler, time_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus StatVFS(const std::string &path, ResponseHandler *handler, time_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus GetXAttr(const std::string &path, const std::vector< std::string > &attrs, ResponseHandler *handler, time_t timeout=0)
XRootDStatus MkDir(const std::string &path, MkDirFlags::Flags flags, Access::Mode mode, ResponseHandler *handler, time_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus Open(const std::string &url, OpenFlags::Flags flags, Access::Mode mode, ResponseHandler *handler, time_t timeout=0) XRD_WARN_UNUSED_RESULT
Definition XrdClFile.cc:125
bool IsOpen() const
Check if the file is open.
Definition XrdClFile.cc:962
bool GetProperty(const std::string &name, std::string &value) const
Definition XrdClFile.cc:994
const std::string & GetAddress() const
Get address.
uint32_t GetSize() const
Get number of locations.
Location & At(uint32_t index)
Get the location at index.
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 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)
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 Fcntl(int fildes, Fcop op, const std::string &args, std::string &resp)
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
XrdOucECMsg ecMsg
XrdSysLogger * theLogger
XrdPosixStats Stats
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.