XrdPosixXrootd.cc

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /*                                                                            */
00003 /*                     X r d P o s i x X r o o t d . c c                      */
00004 /*                                                                            */
00005 /* (c) 2010 by the Board of Trustees of the Leland Stanford, Jr., University  */
00006 /*                            All Rights Reserved                             */
00007 /*   Produced by Andrew Hanushevsky for Stanford University under contract    */
00008 /*              DE-AC02-76-SFO0515 with the Department of Energy              */
00009 /******************************************************************************/
00010 
00011 //         $Id: XrdPosixXrootd.cc 38049 2011-02-11 11:42:35Z rdm $
00012   
00013 const char *XrdPosixXrootdCVSID = "$Id: XrdPosixXrootd.cc 38049 2011-02-11 11:42:35Z rdm $";
00014 
00015 #include <errno.h>
00016 #include <fcntl.h>
00017 #include <sys/time.h>
00018 #include <sys/param.h>
00019 #include <sys/resource.h>
00020 #include <sys/uio.h>
00021 
00022 #include "XrdClient/XrdClient.hh"
00023 #include "XrdClient/XrdClientAdmin.hh"
00024 #include "XrdClient/XrdClientCallback.hh"
00025 #include "XrdClient/XrdClientEnv.hh"
00026 #include "XrdClient/XrdClientUrlInfo.hh"
00027 #include "XrdClient/XrdClientVector.hh"
00028 #include "XrdSys/XrdSysHeaders.hh"
00029 #include "XrdSys/XrdSysPlatform.hh"
00030 #include "XrdOuc/XrdOucString.hh"
00031 #include "XrdPosix/XrdPosixCallBack.hh"
00032 #include "XrdPosix/XrdPosixLinkage.hh"
00033 #include "XrdPosix/XrdPosixXrootd.hh"
00034 
00035 /******************************************************************************/
00036 /*                         L o c a l   C l a s s e s                          */
00037 /******************************************************************************/
00038 /******************************************************************************/
00039 /*                X r d P o s i x A d m i n N e w   C l a s s                 */
00040 /******************************************************************************/
00041   
00042 class XrdPosixAdminNew
00043 {
00044 public:
00045 
00046 XrdClientAdmin Admin;
00047 
00048 int            Fault();
00049 
00050 int            isOK() {return eNum == 0;}
00051 
00052 int            lastError()
00053                    {return XrdPosixXrootd::mapError(Admin.LastServerError()->errnum);}
00054 
00055 int            Result() {if (eNum) {errno = eNum; return -1;}
00056                          return 0;
00057                         }
00058 
00059       XrdPosixAdminNew(const char *path);
00060      ~XrdPosixAdminNew() {}
00061 
00062 private:
00063 
00064 int            eNum;
00065 };
00066 
00067 /******************************************************************************/
00068 /*                     X r d P o s i x D i r   C l a s s                      */
00069 /******************************************************************************/
00070 
00071 class XrdPosixDir {
00072 
00073 public:
00074   XrdPosixDir(int dirno, const char *path);
00075  ~XrdPosixDir();
00076 
00077   void             Lock()   { myMutex.Lock(); }
00078   void             UnLock() { myMutex.UnLock(); }
00079   int              dirNo()  { return fdirno; }
00080   long             getEntries() { return fentries.GetSize(); }
00081   long             getOffset() { return fentry; }
00082   void             setOffset(long offset) { fentry = offset; }
00083   dirent64        *nextEntry(dirent64 *dp=0);
00084   void             rewind() { fentry = -1; fentries.Clear();}
00085   int              Status() { return eNum;}
00086 
00087   
00088 private:
00089   XrdSysMutex     myMutex;
00090   XrdClientAdmin  XAdmin;
00091   dirent64       *myDirent;
00092   static int      maxname;
00093   int             fdirno;
00094   char           *fpath;
00095   vecString       fentries;
00096   long            fentry;
00097   int             eNum;
00098 };
00099   
00100 /******************************************************************************/
00101 /*                    X r d P o s i x F i l e   C l a s s                     */
00102 /******************************************************************************/
00103   
00104 class XrdPosixFile : public XrdClientCallback
00105 {
00106 public:
00107 
00108 XrdClient *XClient;
00109 
00110 int        Active() {return doClose;}
00111 
00112 void       isOpen() {doClose = 1;}
00113 
00114 long long  Offset() {return currOffset;}
00115 
00116 long long  addOffset(long long offs, int updtSz=0)
00117                     {currOffset += offs;
00118                      if (updtSz && currOffset > stat.size) stat.size=currOffset;
00119                      return currOffset;
00120                     }
00121 
00122 long long  setOffset(long long offs)
00123                     {currOffset = offs;
00124                      return currOffset;
00125                     }
00126 
00127 void         Lock() {myMutex.Lock();}
00128 void       UnLock() {myMutex.UnLock();}
00129 
00130 void       OpenComplete(XrdClientAbs *clientP, void *cbArg, bool res)
00131                        {if (cbDone) return;
00132                         XrdPosixXrootd::OpenCB(this, cbArg, res);
00133                         cbDone=1;
00134                        }
00135 
00136 XrdClientStatInfo stat;
00137 XrdPosixCallBack *theCB;
00138 XrdPosixFile     *Next;
00139 int               FD;
00140 int               cbResult;
00141 
00142 static const int realFD = 1;
00143 static const int isSync = 2;
00144 
00145            XrdPosixFile(int fd, const char *path,
00146                         XrdPosixCallBack *cbP=0, int Opts=realFD);
00147           ~XrdPosixFile();
00148 
00149 private:
00150 
00151 XrdSysMutex myMutex;
00152 long long   currOffset;
00153 short       doClose;
00154 short       cbDone;
00155 short       fdClose;
00156 };
00157 
00158 
00159 typedef XrdClientVector<XrdOucString> vecString;
00160 typedef XrdClientVector<bool> vecBool;
00161 
00162 /******************************************************************************/
00163 /*                         L o c a l   D e f i n e s                          */
00164 /******************************************************************************/
00165   
00166 #define Scuttle(fp, rc) fp->UnLock(); errno = rc; return -1
00167 
00168 /******************************************************************************/
00169 /*                               G l o b a l s                                */
00170 /******************************************************************************/
00171 
00172 int            XrdPosixDir::maxname = 255;
00173 XrdSysMutex    XrdPosixXrootd::myMutex;
00174 XrdPosixFile **XrdPosixXrootd::myFiles  =  0;
00175 XrdPosixDir  **XrdPosixXrootd::myDirs   =  0;
00176 int            XrdPosixXrootd::highFD   = -1;
00177 int            XrdPosixXrootd::lastFD   = -1;
00178 int            XrdPosixXrootd::baseFD   =  0;
00179 int            XrdPosixXrootd::freeFD   =  0;
00180 int            XrdPosixXrootd::highDir  = -1;
00181 int            XrdPosixXrootd::lastDir  = -1;
00182 int            XrdPosixXrootd::devNull  = -1;
00183 int            XrdPosixXrootd::pllOpen  =  0;
00184 int            XrdPosixXrootd::maxThreads= 0;
00185 int            XrdPosixXrootd::initDone  = 0;
00186 int            XrdPosixXrootd::Debug    = -2;
00187   
00188 /******************************************************************************/
00189 /*                     T h r e a d   I n t e r f a c e s                      */
00190 /******************************************************************************/
00191 
00192 void *XrdPosixXrootdCB(void *carg)
00193      {XrdPosixXrootd::OpenCB(0,0,0); return (void *)0;}
00194   
00195 /******************************************************************************/
00196 /*                X r d P o s i x A d m i n N e w   C l a s s                 */
00197 /******************************************************************************/
00198 /******************************************************************************/
00199 /*                           C o n s t r u c t o r                            */
00200 /******************************************************************************/
00201   
00202 XrdPosixAdminNew::XrdPosixAdminNew(const char *path) : Admin(path)
00203 {
00204 
00205 // Now Connect to the target host
00206 //
00207    if (!Admin.Connect())
00208        eNum = XrdPosixXrootd::mapError(Admin.LastServerError()->errnum);
00209        else eNum = 0;
00210 }
00211 
00212 /******************************************************************************/
00213 /*                                 F a u l t                                  */
00214 /******************************************************************************/
00215 
00216 int XrdPosixAdminNew::Fault()
00217 {
00218    char *etext = Admin.LastServerError()->errmsg;
00219    int RC = XrdPosixXrootd::mapError(Admin.LastServerError()->errnum);
00220 
00221    if (RC != ENOENT && *etext && XrdPosixXrootd::Debug > -2)
00222       cerr <<"XrdPosix: " <<etext <<endl;
00223    errno = RC;
00224    return -1;
00225 }
00226   
00227 /******************************************************************************/
00228 /*                           X r d P o s i x D i r                            */
00229 /******************************************************************************/
00230 /******************************************************************************/
00231 /*                           C o n s t r u c t o r                            */
00232 /******************************************************************************/
00233 
00234 XrdPosixDir::XrdPosixDir(int dirno, const char *path) : XAdmin(path)
00235 {
00236 
00237 // Now connect up
00238 //
00239    if (!XAdmin.Connect())
00240       eNum = XrdPosixXrootd::mapError(XAdmin.LastServerError()->errnum);
00241       else eNum = 0;
00242 
00243    fentry = -1;     // indicates that the directory content is not valid
00244    fentries.Clear();
00245    fdirno = dirno;
00246 
00247 // Get the path of the url 
00248 //
00249    XrdOucString str(path);
00250    XrdClientUrlInfo url(str);
00251    XrdOucString dir = url.File;
00252    fpath = strdup(dir.c_str());
00253 
00254 // Allocate a local dirent. Note that we get additional padding because on
00255 // some system the dirent structure does not include the name buffer
00256 //
00257    if (!(myDirent = (dirent64 *)malloc(sizeof(dirent64) + maxname + 1)))
00258       eNum = ENOMEM;
00259 }
00260 
00261 /******************************************************************************/
00262 /*                            D e s t r u c t o r                             */
00263 /******************************************************************************/
00264 
00265 XrdPosixDir::~XrdPosixDir()
00266 {
00267   if (fpath)    free(fpath);
00268   if (myDirent) free(myDirent);
00269   close(fdirno);
00270 }
00271 
00272 /******************************************************************************/
00273 /*                            n e x t E n t r y                               */
00274 /******************************************************************************/
00275 
00276 dirent64 *XrdPosixDir::nextEntry(dirent64 *dp)
00277 {
00278    const char *cp;
00279    const int dirhdrln = dp->d_name - (char *)dp;
00280    int reclen;
00281 
00282 // Object is already / must be locked at this point
00283 // Read directory if we haven't done that yet
00284 //
00285    if (fentry<0)
00286       {if (XAdmin.DirList(fpath,fentries)) fentry = 0;
00287           else {eNum = XrdPosixXrootd::mapError(XAdmin.LastServerError()->errnum);
00288                 return 0;
00289                }
00290       }
00291 
00292 // Check if dir is empty or all entries have been read
00293 //
00294    if ((fentries.GetSize()==0) || (fentry>=fentries.GetSize())) return 0;
00295 
00296 // Create a directory entry
00297 //
00298    if (!dp) dp = myDirent;
00299    cp = (fentries[fentry]).c_str();
00300    reclen = strlen(cp);
00301    if (reclen > maxname) reclen = maxname;
00302 #if defined(__macos__) || defined(__FreeBSD__)
00303    dp->d_fileno = fentry;
00304    dp->d_type   = DT_UNKNOWN;
00305    dp->d_namlen = reclen;
00306 #else
00307    dp->d_ino    = fentry;
00308    dp->d_off    = fentry*maxname;
00309 #endif
00310    dp->d_reclen = reclen + dirhdrln;
00311    strncpy(dp->d_name, cp, reclen);
00312    dp->d_name[reclen] = '\0';
00313    fentry++;
00314    return dp;
00315 }
00316 
00317 /******************************************************************************/
00318 /*                          X r d P o s i x F i l e                           */
00319 /******************************************************************************/
00320 /******************************************************************************/
00321 /*                           C o n s t r u c t o r                            */
00322 /******************************************************************************/
00323 
00324 XrdPosixFile::XrdPosixFile(int fd, const char *path, XrdPosixCallBack *cbP,
00325                            int Opts)
00326              : theCB(cbP),
00327                Next(0),
00328                FD(fd),
00329                cbResult(0),
00330                currOffset(0),
00331                doClose(0),
00332                cbDone(0),
00333                fdClose(Opts & realFD)
00334 {
00335    static int OneVal = 1;
00336    XrdClientCallback *myCB = (cbP ? (XrdClientCallback *)this : 0);
00337    void *cbArg = (Opts & isSync ? (void *)&OneVal : 0);
00338 
00339 // Allocate a new client object
00340 //
00341    if (!(XClient = new XrdClient(path, myCB, cbArg))) stat.size = 0;
00342 }
00343   
00344 /******************************************************************************/
00345 /*                            D e s t r u c t o r                             */
00346 /******************************************************************************/
00347   
00348 XrdPosixFile::~XrdPosixFile()
00349 {
00350    XrdClient *cP;
00351    if ((cP = XClient))
00352       {XClient = 0;
00353        if (doClose) {doClose = 0; cP->Close();}
00354        delete cP;
00355       }
00356    if (FD >= 0 && fdClose) close(FD);
00357 }
00358 
00359 /******************************************************************************/
00360 /*                         X r d P o s i x X r o o t d                        */
00361 /******************************************************************************/
00362 /******************************************************************************/
00363 /*                           C o n s t r u c t o r                            */
00364 /******************************************************************************/
00365 
00366 XrdPosixXrootd::XrdPosixXrootd(int fdnum, int dirnum, int thrnum)
00367 {
00368    extern XrdPosixLinkage Xunix;
00369    struct rlimit rlim;
00370    long isize;
00371 
00372 // Only static fields are initialized here. We need to do this only once!
00373 //                                                                             c
00374    myMutex.Lock();
00375    if (initDone) {myMutex.UnLock(); return;}
00376    initDone = 1;
00377    myMutex.UnLock();
00378 
00379 // Initialize the linkage table first before any C calls!
00380 //
00381    Xunix.Init();
00382 
00383 // Initialize environment if not done before. To avoid static initialization
00384 // dependencies, we need to do it once but we must be the last ones to do it
00385 // before any XrdClient library routines are called.
00386 //
00387    initEnv();
00388    maxThreads = thrnum;
00389 
00390 // Compute size of table. if the passed fdnum is negative then the caller does
00391 // not want us to shadow fd's (ther caller promises to be honest). Otherwise,
00392 // the actual fdnum limit will be based on the current limit.
00393 //
00394    if (fdnum < 0)
00395       {fdnum = -fdnum;
00396        baseFD = ( getrlimit(RLIMIT_NOFILE, &rlim) ? 32768 : (int)rlim.rlim_cur);
00397       } else {
00398        if (!getrlimit(RLIMIT_NOFILE, &rlim))  fdnum = (int)rlim.rlim_cur;
00399        if (fdnum > 65536) fdnum = 65536;
00400       }
00401    isize = fdnum * sizeof(XrdPosixFile *);
00402 
00403 // Allocate the table for fd-type pointers
00404 //
00405    if (!(myFiles = (XrdPosixFile **)malloc(isize))) lastFD = -1;
00406       else {memset((void *)myFiles, 0, isize); lastFD = fdnum+baseFD;}
00407 
00408 // Allocate table for DIR descriptors
00409 //
00410    if (dirnum > 32768) dirnum = 32768;
00411    isize = dirnum * sizeof(XrdPosixDir *);
00412    if (!(myDirs = (XrdPosixDir **)malloc(isize))) lastDir = -1;
00413       else {memset((void *)myDirs, 0, isize); lastDir = dirnum;}
00414 
00415 // Open /dev/null as we will be allocating file descriptors based on this fd
00416 //
00417    devNull = open("/dev/null", O_RDWR, 0744);
00418 }
00419  
00420 /******************************************************************************/
00421 /*                            D e s t r u c t o r                             */
00422 /******************************************************************************/
00423   
00424 XrdPosixXrootd::~XrdPosixXrootd()
00425 {
00426    XrdPosixDir  *dP;
00427    XrdPosixFile *fP;
00428    int i;
00429 
00430    myMutex.Lock();
00431    if (myFiles)
00432       {for (i = 0; i <= highFD; i++) 
00433            if ((fP = myFiles[i])) {myFiles[i] = 0; delete fP;};
00434        free(myFiles); myFiles = 0;
00435       }
00436 
00437    if (myDirs) {
00438      for (i = 0; i <= highDir; i++)
00439        if ((dP = myDirs[i])) {myDirs[i] = 0; delete dP;}
00440      free(myDirs); myDirs = 0;
00441    }
00442 
00443    initDone = 0;
00444    myMutex.UnLock();
00445 }
00446  
00447 /******************************************************************************/
00448 /*                                A c c e s s                                 */
00449 /******************************************************************************/
00450   
00451 int XrdPosixXrootd::Access(const char *path, int amode)
00452 {
00453    XrdPosixAdminNew admin(path);
00454    long st_flags, st_modtime, st_id;
00455    long long st_size;
00456    int st_mode, aOK = 1;
00457 
00458 // Make sure we connected
00459 //
00460    if (!admin.isOK()) return admin.Result();
00461 
00462 // Extract out path from the url
00463 //
00464    XrdOucString str(path);
00465    XrdClientUrlInfo url(str);
00466 
00467 // Open the file first
00468 //
00469    if (!admin.Admin.Stat(url.File.c_str(),
00470                          st_id, st_size, st_flags, st_modtime))
00471       {errno = admin.lastError();
00472        return -1;
00473       }
00474 
00475 // Translate the mode bits
00476 //
00477    st_mode = mapFlags(st_flags);
00478    if (amode & R_OK && !(st_mode & S_IRUSR)) aOK = 0;
00479    if (amode & W_OK && !(st_mode & S_IWUSR)) aOK = 0;
00480    if (amode & X_OK && !(st_mode & S_IXUSR)) aOK = 0;
00481 
00482 // All done
00483 //
00484    if (aOK) return 0;
00485    errno = EACCES;
00486    return -1;
00487 }
00488 
00489 /******************************************************************************/
00490 /*                                 C l o s e                                  */
00491 /******************************************************************************/
00492 
00493 int     XrdPosixXrootd::Close(int fildes, int Stream)
00494 {
00495    XrdPosixFile *fp;
00496 
00497 // Find the file object. We tell findFP() to leave the global lock on
00498 //
00499    if (!(fp = findFP(fildes, 1))) return -1;
00500    if (baseFD)
00501       {int myFD = fp->FD - baseFD;
00502        if (myFD < freeFD) freeFD = myFD;
00503        myFiles[myFD] = 0;
00504       } else myFiles[fp->FD] = 0;
00505    if (Stream) fp->FD = -1;
00506 
00507 // Deallocate the file. We have the global lock.
00508 //
00509    fp->UnLock();
00510    myMutex.UnLock();
00511    delete fp;
00512    return 0;
00513 }
00514 
00515 /******************************************************************************/
00516 /*                              C l o s e d i r                               */
00517 /******************************************************************************/
00518 
00519 int XrdPosixXrootd::Closedir(DIR *dirp)
00520 {
00521    XrdPosixDir *XrdDirp = findDIR(dirp,1);
00522    if (!XrdDirp) return -1;
00523 
00524 // Deallocate the directory
00525 //
00526    myDirs[XrdDirp->dirNo()] = 0;
00527    XrdDirp->UnLock();
00528    myMutex.UnLock();
00529    if (XrdDirp) delete XrdDirp;
00530    return 0;
00531 }
00532 
00533 /******************************************************************************/
00534 /*                              e n d P o i n t                               */
00535 /******************************************************************************/
00536   
00537 int XrdPosixXrootd::endPoint(int FD, char *Buff, int Blen)
00538 {
00539    XrdPosixFile    *fp;
00540    XrdClientUrlInfo fURL;
00541 
00542 // Find the file object
00543 //
00544    if (!(fp = findFP(FD))) return 0;
00545 
00546 // Obtain the current url from the file
00547 //
00548    fURL = fp->XClient->GetCurrentUrl();
00549    fp->UnLock();
00550 
00551 // Make sure url is valid
00552 //
00553    if (!fURL.IsValid()) return -ENOTCONN;
00554 
00555 // Format host and port number, check if result is too long
00556 //
00557    if (snprintf(Buff, Blen, "%s:%d", fURL.Host.c_str(), fURL.Port) >= Blen)
00558       return -ENAMETOOLONG;
00559 
00560 // All done
00561 //
00562    return fURL.Port;
00563 }
00564 
00565 /******************************************************************************/
00566 /*                                 F s t a t                                  */
00567 /******************************************************************************/
00568 
00569 int     XrdPosixXrootd::Fstat(int fildes, struct stat *buf)
00570 {
00571    XrdPosixFile *fp;
00572 
00573 // Find the file object
00574 //
00575    if (!(fp = findFP(fildes))) return -1;
00576 
00577 // Return what little we can
00578 //
00579    initStat(buf);
00580    buf->st_size   = fp->stat.size;
00581    buf->st_atime  = buf->st_mtime = buf->st_ctime = fp->stat.modtime;
00582    buf->st_blocks = buf->st_size/512+1;
00583    buf->st_ino    = fp->stat.id;
00584    buf->st_mode   = mapFlags(fp->stat.flags);
00585 
00586 // All done
00587 //
00588    fp->UnLock();
00589    return 0;
00590 }
00591   
00592 /******************************************************************************/
00593 /*                                 F s y n c                                  */
00594 /******************************************************************************/
00595   
00596 int     XrdPosixXrootd::Fsync(int fildes)
00597 {
00598    XrdPosixFile *fp;
00599 
00600 // Find the file object
00601 //
00602    if (!(fp = findFP(fildes))) return -1;
00603 
00604 // Do the sync
00605 //
00606    if (!fp->XClient->Sync()) return Fault(fp);
00607    fp->UnLock();
00608    return 0;
00609 }
00610   
00611 /******************************************************************************/
00612 /*                             F t r u n c a t e                              */
00613 /******************************************************************************/
00614   
00615 int     XrdPosixXrootd::Ftruncate(int fildes, off_t offset)
00616 {
00617    XrdPosixFile *fp;
00618 
00619 // Find the file object
00620 //
00621    if (!(fp = findFP(fildes))) return -1;
00622 
00623 // Do the sync
00624 //
00625    if (!fp->XClient->Truncate(offset)) return Fault(fp);
00626    fp->UnLock();
00627    return 0;
00628 }
00629 
00630 /******************************************************************************/
00631 /*                              G e t x a t t r                               */
00632 /******************************************************************************/
00633 
00634 #ifndef ENOATTR
00635 #define ENOATTR ENOTSUP
00636 #endif
00637 
00638 long long XrdPosixXrootd::Getxattr (const char *path, const char *name, 
00639                                     void *value, unsigned long long size)
00640 {
00641   XrdPosixAdminNew admin(path);
00642   kXR_int16 ReqCode = 0;
00643   kXR_int32 vsize;
00644 
00645 // Check if user just wants the maximum length needed
00646 //
00647    if (size == 0) return 1024;
00648    vsize = static_cast<kXR_int32>(size);
00649 
00650 // Check if we support the query
00651 //
00652    if (name)
00653       {     if (!strcmp(name, "xroot.space")) ReqCode = kXR_Qspace;
00654        else if (!strcmp(name, "xroot.xattr")) ReqCode = kXR_Qxattr;
00655        else {errno = ENOATTR; return -1;}
00656       }else {errno = EINVAL;  return -1;}
00657 
00658   if (admin.isOK())
00659      {XrdOucString str(path);
00660       XrdClientUrlInfo url(str);
00661       if (admin.Admin.Query(ReqCode, (kXR_char *)url.File.c_str(),
00662                                      (kXR_char *)value, vsize))
00663          return strlen((char *)value);
00664       return admin.Fault();
00665      }
00666   return admin.Result();
00667 }
00668   
00669 /******************************************************************************/
00670 /*                                 L s e e k                                  */
00671 /******************************************************************************/
00672   
00673 off_t   XrdPosixXrootd::Lseek(int fildes, off_t offset, int whence)
00674 {
00675    XrdPosixFile *fp;
00676    long long curroffset;
00677 
00678 // Find the file object
00679 //
00680    if (!(fp = findFP(fildes))) return -1;
00681 
00682 // Set the new offset
00683 //
00684    if (whence == SEEK_SET) curroffset = fp->setOffset(offset);
00685       else if (whence == SEEK_CUR) curroffset = fp->addOffset(offset);
00686               else if (whence == SEEK_END)
00687                       curroffset = fp->setOffset(fp->stat.size+offset);
00688                       else {Scuttle(fp, EINVAL);}
00689 
00690 // All done
00691 //
00692    fp->UnLock();
00693    return curroffset;
00694 }
00695   
00696 /******************************************************************************/
00697 /*                                 M k d i r                                  */
00698 /******************************************************************************/
00699 
00700 int XrdPosixXrootd::Mkdir(const char *path, mode_t mode)
00701 {
00702   XrdPosixAdminNew admin(path);
00703   int uMode = 0, gMode = 0, oMode = 0;
00704 
00705   if (admin.isOK())
00706      {XrdOucString str(path);
00707       XrdClientUrlInfo url(str);
00708       if (mode & S_IRUSR) uMode |= 4;
00709       if (mode & S_IWUSR) uMode |= 2;
00710       if (mode & S_IXUSR) uMode |= 1;
00711       if (mode & S_IRGRP) gMode |= 4;
00712       if (mode & S_IWGRP) gMode |= 2;
00713       if (mode & S_IXGRP) gMode |= 1;
00714       if (mode & S_IROTH) oMode |= 4;
00715       if (mode & S_IXOTH) oMode |= 1;
00716       if (admin.Admin.Mkdir(url.File.c_str(), uMode, gMode, oMode))
00717          return 0;
00718       return admin.Fault();
00719      }
00720   return admin.Result();
00721 }
00722 
00723 /******************************************************************************/
00724 /*                                  O p e n                                   */
00725 /******************************************************************************/
00726   
00727 int XrdPosixXrootd::Open(const char *path, int oflags, mode_t mode,
00728                          XrdPosixCallBack *cbP)
00729 {
00730    XrdPosixFile *fp;
00731    int Opts  = ((maxThreads==0) || (oflags & O_SYNC) ? XrdPosixFile::isSync : 0)
00732              | (baseFD ? 0 : XrdPosixFile::realFD);
00733    int XMode = (mode && (oflags & O_CREAT) ? mapMode(mode) : 0);
00734    int retc = 0, fd, XOflags;
00735 
00736 // Translate option bits to the appropraite values. Always 
00737 // make directory path for new file.
00738 //
00739    XOflags = (oflags & (O_WRONLY | O_RDWR) ? kXR_open_updt : kXR_open_read);
00740    if (oflags & O_CREAT) {
00741        XOflags |= (oflags & O_EXCL ? kXR_new : kXR_delete);
00742        XOflags |= kXR_mkpath;
00743    }
00744    else if (oflags & O_TRUNC && XOflags & kXR_open_updt)
00745               XOflags |= kXR_delete;
00746 
00747 // Obtain a new filedscriptor from the system. Use the fd to track the file.
00748 //
00749    if (baseFD)
00750       {myMutex.Lock();
00751        for (fd = freeFD; fd < baseFD && myFiles[fd]; fd++);
00752        if (fd >= baseFD || oflags & isStream) fd = lastFD;
00753           else freeFD = fd+1;
00754       } else
00755         do{if ((fd = dup(devNull)) < 0) return -1;
00756            if (oflags & isStream && fd > 255)
00757               {close(fd); errno = EMFILE; return -1;}
00758            myMutex.Lock();
00759            if (fd >= lastFD || !myFiles[fd]) break;
00760            cerr <<"XrdPosix: FD " <<fd <<" closed outside of XrdPosix!" <<endl;
00761            myMutex.UnLock();
00762           } while(1);
00763 
00764 // Allocate the new file object
00765 //
00766    if (fd >= lastFD || !(fp = new XrdPosixFile(fd+baseFD, path, cbP, Opts)))
00767       {myMutex.UnLock(); errno = EMFILE; return -1;}
00768    myFiles[fd] = fp;
00769    if (fd > highFD) highFD = fd;
00770    myMutex.UnLock();
00771 
00772 // Open the file
00773 //
00774    if (!fp->XClient->Open(XMode, XOflags, (cbP ? 1 : pllOpen))
00775    || (!cbP && (fp->XClient->LastServerResp()->status != kXR_ok)))
00776       {retc = Fault(fp, 0);
00777        myMutex.Lock();
00778        myFiles[fd] = 0;
00779        delete fp;
00780        if (baseFD && fd < freeFD) freeFD = fd;
00781        myMutex.UnLock();
00782        errno = retc;
00783        return -1;
00784       }
00785 
00786 // If this is a callback open then just return EINPROGRESS
00787 //
00788    if (cbP)
00789       {errno = EINPROGRESS;
00790        return -1;
00791       }
00792 
00793 // Get the file size
00794 //
00795    fp->isOpen();
00796    fp->XClient->Stat(&fp->stat);
00797 
00798 // Return the fd number
00799 //
00800    return fd + baseFD;
00801 }
00802 
00803 /******************************************************************************/
00804 /*                                O p e n C B                                 */
00805 /******************************************************************************/
00806   
00807 void XrdPosixXrootd::OpenCB(XrdPosixFile *fp, void *cbArg, int res)
00808 {
00809    static XrdSysMutex     cbMutex;
00810    static XrdSysSemaphore cbReady(0);
00811    static XrdPosixFile   *First = 0, *Last = 0;
00812    static int Waiting = 0, numThreads = 0;
00813           XrdPosixFile *cbFP;
00814           int rc = 0;
00815 
00816 // If this is a feeder thread, look for some work
00817 //
00818    if (!fp)
00819    do {cbMutex.Lock();
00820        if (!First && !Waiting)
00821           {numThreads--; cbMutex.UnLock(); return;}
00822        while(!(cbFP = First))
00823             {Waiting = 1;
00824              cbMutex.UnLock(); cbReady.Wait(); cbMutex.Lock();
00825              Waiting = 0;
00826             }
00827        if (!(First = cbFP->Next)) Last = 0;
00828        cbMutex.UnLock();
00829        if ((rc = (cbFP->cbResult < 0))) errno = -(cbFP->cbResult);
00830        cbFP->theCB->Complete(cbFP->cbResult);
00831        if (rc) delete cbFP;
00832       } while(1);
00833 
00834 // Determine final result for this callback
00835 //
00836    if (!res || (fp->XClient->LastServerResp()->status) != kXR_ok)
00837       {fp->cbResult = -Fault(fp, 0);
00838        myMutex.Lock();
00839        myFiles[fp->FD - baseFD] = 0;
00840        myMutex.UnLock();
00841       } else {
00842        fp->isOpen();
00843        fp->XClient->Stat(&fp->stat);
00844        fp->cbResult = fp->FD;
00845       }
00846 
00847 // Lock our data structure and queue this element
00848 //
00849    cbMutex.Lock();
00850    if (Last) Last->Next = fp;
00851       else   First    = fp;
00852    Last = fp; fp->Next = 0;
00853 
00854 // See if we should start a thread
00855 //
00856    if (!Waiting && numThreads < maxThreads)
00857       {pthread_t tid;
00858        if ((rc = XrdSysThread::Run(&tid, XrdPosixXrootdCB, (void *)0,
00859                                   0, "Callback thread")))
00860           cerr <<"XrdPosix: Unable to create callback thread; "
00861                <<strerror(rc) <<endl;
00862           else numThreads++;
00863       }
00864 
00865 // All done
00866 //
00867    cbReady.Post();
00868    cbMutex.UnLock();
00869 }
00870 
00871 /******************************************************************************/
00872 /*                               O p e n d i r                                */
00873 /******************************************************************************/
00874   
00875 DIR* XrdPosixXrootd::Opendir(const char *path)
00876 {
00877    XrdPosixDir *dirp = 0; // Avoid MacOS compiler warning
00878    int rc, fd;
00879 
00880 // Obtain a new filedscriptor from the system. Use the fd to track the dir.
00881 //
00882    if ((fd = dup(devNull)) < 0) return (DIR*)0;
00883 
00884 // Allocate a new directory structure
00885 //
00886    myMutex.Lock();
00887    if (fd > lastDir) rc = EMFILE;
00888       else if (!(dirp = new XrdPosixDir(fd, path))) rc = ENOMEM;
00889               else rc = dirp->Status();
00890 
00891    if (!rc)
00892       {myDirs[fd] = dirp;
00893        if (fd > highDir) highDir = fd;
00894       }
00895    myMutex.UnLock();
00896 
00897    if (rc) {if (dirp) {delete dirp; dirp = 0;} errno = rc;}
00898 
00899    return (DIR*)dirp;
00900 }
00901 
00902 /******************************************************************************/
00903 /*                                 P r e a d                                  */
00904 /******************************************************************************/
00905   
00906 ssize_t XrdPosixXrootd::Pread(int fildes, void *buf, size_t nbyte, off_t offset)
00907 {
00908    XrdPosixFile *fp;
00909    long long     offs, bytes;
00910    int           iosz;
00911 
00912 // Find the file object
00913 //
00914    if (!(fp = findFP(fildes))) return -1;
00915 
00916 // Make sure the size is not too large
00917 //
00918    if (nbyte > (size_t)0x7fffffff) {Scuttle(fp,EOVERFLOW);}
00919       else iosz = static_cast<int>(nbyte);
00920 
00921 // Issue the read
00922 //
00923    offs = static_cast<long long>(offset);
00924    if ((bytes = fp->XClient->Read(buf,offs,(int)iosz))<=0) return Fault(fp,-1);
00925 
00926 // All went well
00927 //
00928    fp->UnLock();
00929    return (ssize_t)bytes;
00930 }
00931 
00932 /******************************************************************************/
00933 /*                                P w r i t e                                 */
00934 /******************************************************************************/
00935   
00936 ssize_t XrdPosixXrootd::Pwrite(int fildes, const void *buf, size_t nbyte, off_t offset)
00937 {
00938    XrdPosixFile *fp;
00939    long long     offs;
00940    int           iosz;
00941 
00942 // Find the file object
00943 //
00944    if (!(fp = findFP(fildes))) return -1;
00945 
00946 // Make sure the size is not too large
00947 //
00948    if (nbyte > (size_t)0x7fffffff) {Scuttle(fp,EOVERFLOW);}
00949       else iosz = static_cast<int>(nbyte);
00950 
00951 // Issue the write
00952 //
00953    offs = static_cast<long long>(offset);
00954    if (!fp->XClient->Write(buf, offs, iosz) && iosz) return Fault(fp);
00955 
00956 // All went well
00957 //
00958    if (offs+iosz > fp->stat.size) fp->stat.size = offs + iosz;
00959    fp->UnLock();
00960    return (ssize_t)iosz;
00961 }
00962 
00963 /******************************************************************************/
00964 /*                                  R e a d                                   */
00965 /******************************************************************************/
00966   
00967 ssize_t XrdPosixXrootd::Read(int fildes, void *buf, size_t nbyte)
00968 {
00969    XrdPosixFile *fp;
00970    long long     bytes;
00971    int           iosz;
00972 
00973 // Find the file object
00974 //
00975    if (!(fp = findFP(fildes))) return -1;
00976 
00977 
00978 // Make sure the size is not too large
00979 //
00980    if (nbyte > (size_t)0x7fffffff) {Scuttle(fp,EOVERFLOW);}
00981       else iosz = static_cast<int>(nbyte);
00982 
00983 // Issue the read
00984 //
00985    if ((bytes = fp->XClient->Read(buf, fp->Offset(), iosz)) <= 0)
00986       return Fault(fp,-1);
00987 
00988 // All went well
00989 //
00990    fp->addOffset(bytes);
00991    fp->UnLock();
00992    return (ssize_t)bytes;
00993 }
00994 
00995 /******************************************************************************/
00996 /*                                 R e a d v                                  */
00997 /******************************************************************************/
00998   
00999 ssize_t XrdPosixXrootd::Readv(int fildes, const struct iovec *iov, int iovcnt)
01000 {
01001    ssize_t bytes, totbytes = 0;
01002    int i;
01003 
01004 // Return the results of the read for each iov segment
01005 //
01006    for (i = 0; i < iovcnt; i++)
01007        {bytes = Read(fildes,(void *)iov[i].iov_base,(size_t)iov[i].iov_len);
01008              if (bytes > 0) totbytes += bytes;
01009         else if (bytes < 0) return -1;
01010         else                break;
01011        }
01012 
01013 // All done
01014 //
01015    return totbytes;
01016 }
01017 
01018 /******************************************************************************/
01019 /*                                R e a d d i r                               */
01020 /******************************************************************************/
01021 
01022 struct dirent* XrdPosixXrootd::Readdir(DIR *dirp)
01023 {
01024    dirent64 *dp64;
01025    dirent   *dp32; // Could be the same as dp64
01026 
01027    if (!(dp64 = Readdir64(dirp))) return 0;
01028 
01029    dp32 = (struct dirent *)dp64;
01030    if (dp32->d_name != dp64->d_name)
01031       {dp32->d_ino    = dp64->d_ino;
01032 #if !defined(__macos__) && !defined(__FreeBSD__)
01033        dp32->d_off    = dp64->d_off;
01034 #endif
01035        dp32->d_reclen = dp64->d_reclen;
01036        strcpy(dp32->d_name, dp64->d_name);
01037       }
01038    return dp32;
01039 }
01040 
01041 struct dirent64* XrdPosixXrootd::Readdir64(DIR *dirp)
01042 {
01043    XrdPosixDir *XrdDirp = findDIR(dirp);
01044    dirent64 *dp;
01045    int rc;
01046 
01047 // Returns the next directory entry
01048 //
01049    if (!XrdDirp) return 0;
01050 
01051    if (!(dp = XrdDirp->nextEntry())) rc = XrdDirp->Status();
01052       else rc = 0;
01053 
01054 
01055    XrdDirp->UnLock();
01056    if (rc) errno = rc;
01057    return dp;
01058 }
01059 
01060 /******************************************************************************/
01061 /*                              R e a d d i r _ r                             */
01062 /******************************************************************************/
01063 
01064 int XrdPosixXrootd::Readdir_r(DIR *dirp,   struct dirent    *entry,
01065                                            struct dirent   **result)
01066 {
01067    dirent64 *dp64;
01068    int       rc;
01069 
01070    if ((rc = Readdir64_r(dirp, 0, &dp64)) <= 0) {*result = 0; return rc;}
01071 
01072    entry->d_ino    = dp64->d_ino;
01073 #if !defined(__macos__) && !defined(__FreeBSD__)
01074    entry->d_off    = dp64->d_off;
01075 #endif
01076    entry->d_reclen = dp64->d_reclen;
01077    strcpy(entry->d_name, dp64->d_name);
01078    *result = entry;
01079    return rc;
01080 }
01081 
01082 int XrdPosixXrootd::Readdir64_r(DIR *dirp, struct dirent64  *entry,
01083                                            struct dirent64 **result)
01084 {
01085    XrdPosixDir *XrdDirp = findDIR(dirp);
01086    int rc;
01087 
01088 // Thread safe verison of readdir
01089 //
01090    if (!XrdDirp) {errno = EBADF; return -1;}
01091 
01092    if (!(*result = XrdDirp->nextEntry(entry))) rc = XrdDirp->Status();
01093       else rc = 0;
01094 
01095    XrdDirp->UnLock();
01096    return rc;
01097 }
01098 
01099 /******************************************************************************/
01100 /*                                R e n a m e                                 */
01101 /******************************************************************************/
01102 
01103 int XrdPosixXrootd::Rename(const char *oldpath, const char *newpath)
01104 {
01105   XrdPosixAdminNew admin(oldpath);
01106 
01107   if (admin.isOK())
01108      {XrdOucString    oldstr(oldpath);
01109       XrdClientUrlInfo oldurl(oldstr);
01110       XrdOucString    newstr(newpath);
01111       XrdClientUrlInfo newurl(newstr);
01112       if (admin.Admin.Mv(oldurl.File.c_str(),
01113                          newurl.File.c_str())) return 0;
01114       return admin.Fault();
01115      }
01116   return admin.Result();
01117 }
01118 
01119 
01120 /******************************************************************************/
01121 /*                            R e w i n d d i r                               */
01122 /******************************************************************************/
01123 
01124 void XrdPosixXrootd::Rewinddir(DIR *dirp)
01125 {
01126 // Updates and rewinds directory
01127 //
01128    XrdPosixDir *XrdDirp = findDIR(dirp);
01129    if (!XrdDirp) return;
01130 
01131    XrdDirp->rewind();
01132    XrdDirp->UnLock();
01133 }
01134 
01135 /******************************************************************************/
01136 /*                                 R m d i r                                  */
01137 /******************************************************************************/
01138 
01139 int XrdPosixXrootd::Rmdir(const char *path)
01140 {
01141   XrdPosixAdminNew admin(path);
01142 
01143   if (admin.isOK())
01144      {XrdOucString str(path);
01145       XrdClientUrlInfo url(str);
01146       if (admin.Admin.Rmdir(url.File.c_str())) return 0;
01147       return admin.Fault();
01148      }
01149   return admin.Result();
01150 }
01151 
01152 /******************************************************************************/
01153 /*                                S e e k d i r                               */
01154 /******************************************************************************/
01155 
01156 void XrdPosixXrootd::Seekdir(DIR *dirp, long loc)
01157 {
01158 // Sets the current directory position
01159 //
01160    XrdPosixDir *XrdDirp = findDIR(dirp);
01161    if (!XrdDirp) return;
01162    
01163    if (XrdDirp->getOffset()<0) XrdDirp->nextEntry();  // read the directory
01164    if (loc >= XrdDirp->getEntries()) loc = XrdDirp->getEntries()-1;
01165    else if (loc<0) loc = 0;
01166 
01167    XrdDirp->setOffset(loc);
01168    XrdDirp->UnLock();
01169 }
01170 
01171 /******************************************************************************/
01172 /*                                  S t a t                                   */
01173 /******************************************************************************/
01174   
01175 int XrdPosixXrootd::Stat(const char *path, struct stat *buf)
01176 {
01177    XrdPosixAdminNew admin(path);
01178    long st_flags, st_modtime, st_id;
01179    long long st_size;
01180 
01181 // Make sure we connected
01182 //
01183    if (!admin.isOK()) return admin.Result();
01184 
01185 // Extract out path from the url
01186 //
01187    XrdOucString str(path);
01188    XrdClientUrlInfo url(str);
01189 
01190 // Open the file first
01191 //
01192    if (!admin.Admin.Stat(url.File.c_str(),
01193                          st_id, st_size, st_flags, st_modtime))
01194       return admin.Fault();
01195 
01196 // Return what little we can
01197 //
01198    initStat(buf);
01199    buf->st_size   = st_size;
01200    buf->st_blocks = buf->st_size/512+1;
01201    buf->st_atime  = buf->st_mtime = buf->st_ctime = st_modtime;
01202    buf->st_ino    = st_id;
01203    buf->st_mode   = mapFlags(st_flags);
01204    return 0;
01205 }
01206 
01207 /******************************************************************************/
01208 /*                                S t a t f s                                 */
01209 /******************************************************************************/
01210   
01211 int XrdPosixXrootd::Statfs(const char *path, struct statfs *buf)
01212 {
01213    struct statvfs myVfs;
01214    int rc;
01215 
01216 // Issue a statvfs() call and transcribe the results
01217 //
01218    if ((rc = Statvfs(path, &myVfs))) return rc;
01219 
01220 // The vfs structure and fs structures should be size compatible (not really)
01221 //
01222    memset(buf, 0, sizeof(buf));
01223    buf->f_bsize   = myVfs.f_bsize;
01224    buf->f_blocks  = myVfs.f_blocks;
01225    buf->f_bfree   = myVfs.f_bfree;
01226    buf->f_files   = myVfs.f_files;
01227    buf->f_ffree   = myVfs.f_ffree;
01228 #if defined(__macos__) || defined(__FreeBSD__)
01229    buf->f_iosize  = myVfs.f_frsize;
01230 #else
01231    buf->f_frsize  = myVfs.f_frsize;
01232 #endif
01233 #if defined(__linux__) || defined(__macos__) || defined(__FreeBSD__)
01234    buf->f_bavail  = myVfs.f_bavail;
01235 #endif
01236 #if defined(__linux__)
01237    buf->f_namelen = myVfs.f_namemax;
01238 #elif defined(__FreeBSD__)
01239    buf->f_namemax = myVfs.f_namemax;
01240 #endif
01241    return 0;
01242 }
01243 
01244 /******************************************************************************/
01245 /*                               S t a t v f s                                */
01246 /******************************************************************************/
01247   
01248 int XrdPosixXrootd::Statvfs(const char *path, struct statvfs *buf)
01249 {
01250    static const int szVFS = sizeof(buf->f_bfree);
01251    static const long long max32 = 0x7fffffffLL;
01252    XrdPosixAdminNew admin(path);
01253    long long rwFree, ssFree, rwBlks;
01254    int       rwNum, ssNum, rwUtil, ssUtil;
01255 
01256 // Make sure we connected
01257 //
01258    if (!admin.isOK()) return admin.Result();
01259 
01260 // Extract out path from the url
01261 //
01262    XrdOucString str(path);
01263    XrdClientUrlInfo url(str);
01264 
01265 // Open the file first
01266 //
01267    if (!admin.Admin.Stat_vfs(url.File.c_str(),
01268        rwNum, rwFree, rwUtil, ssNum, ssFree, ssUtil)) return admin.Fault();
01269    if (rwNum < 0) {errno = ENOENT; return -1;}
01270 
01271 // Calculate number of blocks
01272 //
01273    if (rwUtil == 0) rwBlks = rwFree;
01274       else if (rwUtil >= 100) rwBlks = 0;
01275               else rwBlks = rwFree * (100 / (100 - rwUtil));
01276    if (ssUtil == 0) rwBlks += ssFree;
01277       else if (ssUtil < 100) rwBlks += ssFree * (100 / (100 - ssUtil));
01278 
01279 // Scale units to what will fit here (we can have a 32-bit or 64-bit struct)
01280 //
01281    if (szVFS < 8)
01282       {if (rwBlks > max32) rwBlks = max32;
01283        if (rwFree > max32) rwFree = max32;
01284        if (ssFree > max32) ssFree = max32;
01285       }
01286 
01287 // Return what little we can
01288 //
01289    memset(buf, 0, sizeof(buf));
01290    buf->f_bsize   = 1024*1024;
01291    buf->f_frsize  = 1024*1024;
01292    buf->f_blocks  = static_cast<fsblkcnt_t>(rwBlks);
01293    buf->f_bfree   = static_cast<fsblkcnt_t>(rwFree + ssFree);
01294    buf->f_bavail  = static_cast<fsblkcnt_t>(rwFree);
01295    buf->f_ffree   = rwNum + ssNum;
01296    buf->f_favail  = rwNum;
01297    buf->f_namemax = 255;    // The best we are going to do here
01298    buf->f_flag    = (rwNum == 0 ? ST_RDONLY|ST_NOSUID : ST_NOSUID);
01299    return 0;
01300 }
01301 
01302 /******************************************************************************/
01303 /*                                T e l l d i r                               */
01304 /******************************************************************************/
01305 
01306 long XrdPosixXrootd::Telldir(DIR *dirp)
01307 {
01308 // Tells the current directory location
01309 //
01310    XrdPosixDir *XrdDirp = findDIR(dirp);
01311    if (!XrdDirp) return -1;
01312 
01313    long pos;
01314    if (XrdDirp->getOffset()<0) pos = 0;  // dir is open but not read yet
01315    else pos = XrdDirp->getOffset();
01316    XrdDirp->UnLock();
01317    return pos;
01318 }
01319 
01320 /******************************************************************************/
01321 /*                              T r u n c a t e                               */
01322 /******************************************************************************/
01323   
01324 int XrdPosixXrootd::Truncate(const char *path, off_t Size)
01325 {
01326   XrdPosixAdminNew admin(path);
01327 
01328   if (admin.isOK())
01329      {XrdOucString str(path);
01330       XrdClientUrlInfo url(str);
01331       if (admin.Admin.Truncate(url.File.c_str(), Size)) return 0;
01332       return admin.Fault();
01333      }
01334   return admin.Result();
01335 }
01336 
01337 /******************************************************************************/
01338 /*                                 U n l i n k                                */
01339 /******************************************************************************/
01340 
01341 int XrdPosixXrootd::Unlink(const char *path)
01342 {
01343   XrdPosixAdminNew admin(path);
01344 
01345   if (admin.isOK())
01346      {XrdOucString str(path);
01347       XrdClientUrlInfo url(str);
01348       if (admin.Admin.Rm(url.File.c_str())) return 0;
01349       return admin.Fault();
01350      }
01351   return admin.Result();
01352 }
01353 
01354 /******************************************************************************/
01355 /*                                 W r i t e                                  */
01356 /******************************************************************************/
01357   
01358 ssize_t XrdPosixXrootd::Write(int fildes, const void *buf, size_t nbyte)
01359 {
01360    XrdPosixFile *fp;
01361    int           iosz;
01362 
01363 // Find the file object
01364 //
01365    if (!(fp = findFP(fildes))) return -1;
01366 
01367 // Make sure the size is not too large
01368 //
01369    if (nbyte > (size_t)0x7fffffff) {Scuttle(fp,EOVERFLOW);}
01370       else iosz = static_cast<int>(nbyte);
01371 
01372 // Issue the write
01373 //
01374    if (!fp->XClient->Write(buf, fp->Offset(), iosz) && iosz) return Fault(fp);
01375 
01376 // All went well
01377 //
01378    fp->addOffset(iosz, 1);
01379    fp->UnLock();
01380    return (ssize_t)iosz;
01381 }
01382  
01383 /******************************************************************************/
01384 /*                                W r i t e v                                 */
01385 /******************************************************************************/
01386   
01387 ssize_t XrdPosixXrootd::Writev(int fildes, const struct iovec *iov, int iovcnt)
01388 {
01389    ssize_t totbytes = 0;
01390    int i;
01391 
01392 // Return the results of the write for each iov segment
01393 //
01394    for (i = 0; i < iovcnt; i++)
01395        {if (!Write(fildes,(void *)iov[i].iov_base,(size_t)iov[i].iov_len))
01396            return -1;
01397         totbytes += iov[i].iov_len;
01398        }
01399 
01400 // All done
01401 //
01402    return totbytes;
01403 }
01404   
01405 /******************************************************************************/
01406 /*                               i n i t E n v                                */
01407 /******************************************************************************/
01408   
01409 void XrdPosixXrootd::initEnv()
01410 {
01411    struct XrdPosix_Env {const char *eName; const char *xName; int *vDest;}
01412           Posix_Env[] =
01413           {
01414           {"XRDPOSIX_DEBUG",       NAME_DEBUG,                &Debug},
01415           {"XRDPOSIX_DSTTL",       NAME_DATASERVERCONN_TTL,   0},
01416           {"XRDPOSIX_POPEN",       "",                        &pllOpen},
01417           {"XRDPOSIX_RASZ",        NAME_READAHEADSIZE,        0},
01418           {"XRDPOSIX_RCSZ",        NAME_READCACHESIZE,        0},
01419           {"XRDPOSIX_RCRP",        NAME_READCACHEBLKREMPOLICY,0},
01420           {"XRDPOSIX_RCUP",        NAME_REMUSEDCACHEBLKS,     0},
01421           {"XRDPOSIX_RDTTL",       NAME_LBSERVERCONN_TTL,     0},
01422           {"XRDPOSIX_RTO",         NAME_REQUESTTIMEOUT,       0},
01423           {"XRDPOSIX_TTO",         NAME_TRANSACTIONTIMEOUT,   0},
01424           {"XRDPSOIX_PSPC",        NAME_MULTISTREAMCNT,       0},
01425           {"XRDPSOIX_CTO",         NAME_CONNECTTIMEOUT,       0},
01426           {"XRDPSOIX_CRDELAY",     NAME_RECONNECTWAIT,        0},
01427           {"XRDPSOIX_CRETRY",      NAME_FIRSTCONNECTMAXCNT,   0},
01428           {"XRDPSOIX_TCPWSZ",      NAME_DFLTTCPWINDOWSIZE,    0}
01429           };
01430    int    Posix_Num = sizeof(Posix_Env)/sizeof(XrdPosix_Env);
01431    char *cvar, *evar;
01432    int i, doEcho;
01433    long nval;
01434 
01435 // Establish wether we need to echo any envars
01436 //
01437    if ((cvar = getenv("XRDPOSIX_ECHO"))) doEcho = strcmp(cvar, "0");
01438       else doEcho = 0;
01439 
01440 // Establish the default debugging level (none)
01441 //
01442    setEnv(NAME_DEBUG, Debug);
01443 
01444 // Run through all of the numeric envars that may be set
01445 //
01446    for (i = 0; i < Posix_Num; i++)
01447        if ((cvar = getenv(Posix_Env[i].eName)) && *cvar)
01448           {nval = strtol(cvar, &evar, 10);
01449            if (*evar) cerr <<"XrdPosix: Invalid " <<Posix_Env[i].eName
01450                            <<" value - " <<cvar <<endl;
01451               else {if (Posix_Env[i].xName[0]) setEnv(Posix_Env[i].xName, nval);
01452                     if (Posix_Env[i].vDest)
01453                        *Posix_Env[i].vDest = static_cast<int>(nval);
01454                     if (doEcho) cerr <<"XrdPosix: " <<Posix_Env[i].eName <<" = "
01455                                 <<nval <<'(' <<Posix_Env[i].xName <<')' <<endl;
01456                    }
01457           }
01458 }
01459 
01460 /******************************************************************************/
01461 /*                             i s X r o o t d D i r                          */
01462 /******************************************************************************/
01463 
01464 bool XrdPosixXrootd::isXrootdDir(DIR *dirp)
01465 {
01466    if (!dirp) return false;
01467 
01468    for (int i = 0; i <= highDir; i++) 
01469      if (((XrdPosixDir*)dirp)==myDirs[i]) return true;
01470 
01471    return false;
01472 }
01473  
01474 /******************************************************************************/
01475 /*                              m a p E r r o r                               */
01476 /******************************************************************************/
01477   
01478 int XrdPosixXrootd::mapError(int rc)
01479 {
01480     switch(rc)
01481        {case kXR_NotFound:      return ENOENT;
01482         case kXR_NotAuthorized: return EACCES;
01483         case kXR_IOError:       return EIO;
01484         case kXR_NoMemory:      return ENOMEM;
01485         case kXR_NoSpace:       return ENOSPC;
01486         case kXR_ArgTooLong:    return ENAMETOOLONG;
01487         case kXR_noserver:      return EHOSTUNREACH;
01488         case kXR_NotFile:       return ENOTBLK;
01489         case kXR_isDirectory:   return EISDIR;
01490         case kXR_FSError:       return ENOSYS;
01491         default:                return ECANCELED;
01492        }
01493 }
01494 
01495 /******************************************************************************/
01496 /*                           Q u e r y O p a q u e                            */
01497 /******************************************************************************/
01498   
01499 long long XrdPosixXrootd::QueryOpaque(const char *path, char *value, int size)
01500 {
01501   XrdPosixAdminNew admin(path);
01502   kXR_int32 vsize = static_cast<kXR_int32>(size);
01503 
01504   if (admin.isOK())
01505      {XrdOucString str(path);
01506       XrdClientUrlInfo url(str);
01507       admin.Admin.GoBackToRedirector();
01508       if (admin.Admin.Query(kXR_Qopaquf, (kXR_char *)url.File.c_str(), 
01509                                          (kXR_char *)value, vsize))
01510          return strlen((char *)value);
01511       return admin.Fault();
01512      }
01513   return admin.Result();
01514 }
01515 
01516 /******************************************************************************/
01517 /*                              s e t D e b u g                               */
01518 /******************************************************************************/
01519 
01520 void XrdPosixXrootd::setDebug(int val)
01521 {
01522      Debug = static_cast<long>(val);
01523      setEnv("DebugLevel", val);
01524 }
01525   
01526 /******************************************************************************/
01527 /*                                s e t E n v                                 */
01528 /******************************************************************************/
01529   
01530 void XrdPosixXrootd::setEnv(const char *var, const char *val)
01531 {
01532      EnvPutString(var, val);
01533 }
01534 
01535 void XrdPosixXrootd::setEnv(const char *var, long val)
01536 {
01537      EnvPutInt(var, val);
01538 }
01539 
01540 /******************************************************************************/
01541 /*                       P r i v a t e   M e t h o d s                        */
01542 /******************************************************************************/
01543 /******************************************************************************/
01544 /*                                 F a u l t                                  */
01545 /******************************************************************************/
01546 
01547 int XrdPosixXrootd::Fault(XrdPosixFile *fp, int complete)
01548 {
01549    char *etext = fp->XClient->LastServerError()->errmsg;
01550    int   ecode = fp->XClient->LastServerError()->errnum;
01551    int   rc = -1;
01552 
01553    if (complete < 0)
01554       {if (ecode && ecode != kXR_noErrorYet) ecode = mapError(ecode);
01555           else ecode = rc = 0;
01556       } else {
01557        ecode = mapError(ecode);
01558        if (ecode != ENOENT && *etext && XrdPosixXrootd::Debug > -2)
01559           cerr <<"XrdPosix: " <<etext <<endl;
01560       }
01561 
01562    if (!complete) return ecode;
01563    fp->UnLock();
01564    errno = ecode;
01565    return rc;
01566 }
01567   
01568 /******************************************************************************/
01569 /*                                f i n d F P                                 */
01570 /******************************************************************************/
01571   
01572 XrdPosixFile *XrdPosixXrootd::findFP(int fd, int glk)
01573 {
01574    XrdPosixFile *fp;
01575 
01576 // Validate the fildes
01577 //
01578    if (fd >= lastFD || fd < baseFD)
01579       {errno = EBADF; return (XrdPosixFile *)0;}
01580 
01581 // Obtain the file object, if any
01582 //
01583    myMutex.Lock();
01584    if (!(fp = myFiles[fd - baseFD]) || !(fp->Active()))
01585       {myMutex.UnLock(); errno = EBADF; return (XrdPosixFile *)0;}
01586 
01587 // Lock the object and unlock the global lock unless it is to be held
01588 //
01589    fp->Lock();
01590    if (!glk) myMutex.UnLock();
01591    return fp;
01592 }
01593 
01594 /******************************************************************************/
01595 /*                                f i n d D I R                               */
01596 /******************************************************************************/
01597 
01598 XrdPosixDir *XrdPosixXrootd::findDIR(DIR *dirp, int glk)
01599 {
01600    if (!dirp) { errno = EBADF; return 0; }
01601 
01602 // Check if this is really an open directory
01603 //
01604    XrdPosixDir *XrdDirp = (XrdPosixDir*)dirp;
01605    myMutex.Lock();
01606    if (!(myDirs[XrdDirp->dirNo()]==XrdDirp))
01607       {myMutex.UnLock();
01608        errno = EBADF;
01609        return 0;
01610       }
01611 
01612 // Lock the object and unlock the global lock unless it is to be held
01613 //
01614    XrdDirp->Lock();
01615    if (!glk) myMutex.UnLock();
01616    return XrdDirp;
01617 }
01618  
01619 /******************************************************************************/
01620 /*                              i n i t S t a t                               */
01621 /******************************************************************************/
01622 
01623 void XrdPosixXrootd::initStat(struct stat *buf)
01624 {
01625    static int initStatDone = 0;
01626    static dev_t st_rdev;
01627    static dev_t st_dev;
01628    static uid_t myUID = getuid();
01629    static gid_t myGID = getgid();
01630 
01631 // Initialize the xdev fields. This cannot be done in the constructor because
01632 // we may not yet have resolved the C-library symbols.
01633 //
01634    if (!initStatDone) {initStatDone = 1; initXdev(st_dev, st_rdev);}
01635    memset(buf, 0, sizeof(struct stat));
01636 
01637 // Preset common fields
01638 //
01639    buf->st_blksize= 64*1024;
01640    buf->st_dev    = st_dev;
01641    buf->st_rdev   = st_rdev;
01642    buf->st_nlink  = 1;
01643    buf->st_uid    = myUID;
01644    buf->st_gid    = myGID;
01645 }
01646   
01647 /******************************************************************************/
01648 /*                              i n i t X d e v                               */
01649 /******************************************************************************/
01650   
01651 void XrdPosixXrootd::initXdev(dev_t &st_dev, dev_t &st_rdev)
01652 {
01653    struct stat buf;
01654 
01655 // Get the device id for /tmp used by stat()
01656 //
01657    if (stat("/tmp", &buf)) {st_dev = 0; st_rdev = 0;}
01658       else {st_dev = buf.st_dev; st_rdev = buf.st_rdev;}
01659 }
01660 
01661 /******************************************************************************/
01662 /*                              m a p F l a g s                               */
01663 /******************************************************************************/
01664   
01665 int XrdPosixXrootd::mapFlags(int flags)
01666 {
01667    int newflags = 0;
01668 
01669 // Map the xroot flags to unix flags
01670 //
01671    if (flags & kXR_xset)     newflags |= S_IXUSR;
01672    if (flags & kXR_readable) newflags |= S_IRUSR;
01673    if (flags & kXR_writable) newflags |= S_IWUSR;
01674    if (flags & kXR_other)    newflags |= S_IFBLK;
01675       else if (flags & kXR_isDir) newflags |= S_IFDIR;
01676               else newflags |= S_IFREG;
01677    if (flags & kXR_offline) newflags |= S_ISVTX;
01678    if (flags & kXR_poscpend)newflags |= S_ISUID;
01679 
01680    return newflags;
01681 }
01682 
01683 /******************************************************************************/
01684 /*                               m a p M o d e                                */
01685 /******************************************************************************/
01686   
01687 int XrdPosixXrootd::mapMode(mode_t mode)
01688 {  int XMode = 0;
01689 
01690 // Map the mode
01691 //
01692    if (mode & S_IRUSR) XMode |= kXR_ur;
01693    if (mode & S_IWUSR) XMode |= kXR_uw;
01694    if (mode & S_IXUSR) XMode |= kXR_ux;
01695    if (mode & S_IRGRP) XMode |= kXR_gr;
01696    if (mode & S_IWGRP) XMode |= kXR_gw;
01697    if (mode & S_IXGRP) XMode |= kXR_gx;
01698    if (mode & S_IROTH) XMode |= kXR_or;
01699    if (mode & S_IXOTH) XMode |= kXR_ox;
01700    return XMode;
01701 }

Generated on Tue Jul 5 14:46:57 2011 for ROOT_528-00b_version by  doxygen 1.5.1