XrdOssPath.cc

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /*                                                                            */
00003 /*                         X r d O s s P a t h . c c                          */
00004 /*                                                                            */
00005 /* (c) 2008 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: XrdOssPath.cc 35287 2010-09-14 21:19:35Z ganis $
00012  
00013 const char *XrdOssPathCVSID = "$Id: XrdOssPath.cc 35287 2010-09-14 21:19:35Z ganis $";
00014 
00015 #include <errno.h>
00016 #include <fcntl.h>
00017 #include <limits.h>
00018 #include <time.h>
00019 #include <unistd.h>
00020 #include <sys/stat.h>
00021 #include <sys/types.h>
00022 #include <sys/param.h>
00023 
00024 #include "XrdOss/XrdOssPath.hh"
00025 #include "XrdOss/XrdOssSpace.hh"
00026 #include "XrdSys/XrdSysPthread.hh"
00027 
00028 /******************************************************************************/
00029 /*                          L o c a l   M a c r o s                           */
00030 /******************************************************************************/
00031 
00032 #define XrdOssTAMP(dst, src) \
00033    while(*src) {*dst = (*src == '/' ? xChar : *src); src++; dst++;}; *dst='\0'
00034   
00035 /******************************************************************************/
00036 /*                        S t a t i c   O b j e c t s                         */
00037 /******************************************************************************/
00038   
00039 char   XrdOssPath::h2c[16] = {'0','1','2','3','4','5','6','7',
00040                               '8','9','A','B','C','D','E','F'};
00041 
00042 const char XrdOssPath::xChar;
00043 
00044 // The initialization must be in 1-to-1 order with theSfx enum!
00045 //
00046 const char *XrdOssPath::Sfx[XrdOssPath::sfxNum] =
00047                       {".anew", ".fail",  ".lock", ".pin", ".stage",
00048                        ".mmap", ".mkeep", ".mlock",".pfn", 0};
00049 
00050 /******************************************************************************/
00051 /*                               C o n v e r t                                */
00052 /******************************************************************************/
00053   
00054 int XrdOssPath::Convert(char *dst, int dln, const char *oldP, const char *newP)
00055 {
00056    int i;
00057 
00058 // Copy all the char up to the first % into the new link buffer
00059 //
00060    for (i = 0; oldP[i] && oldP[i] != xChar; i++) *dst++ = oldP[i];
00061 
00062 // Now make sure the resulting name will fit
00063 //
00064    if ((i + static_cast<int>(strlen(newP))) >= dln) return -ENAMETOOLONG;
00065 
00066 // Complete the name
00067 //
00068    XrdOssTAMP(dst, newP);
00069    return 0;
00070 }
00071   
00072 /******************************************************************************/
00073 /*                               E x t r a c t                                */
00074 /******************************************************************************/
00075   
00076 const char *XrdOssPath::Extract(char *path, char *lbuf, int &lbsz)
00077 {
00078    struct stat Stat;
00079    char *pP;
00080    int j, lnklen = 0;
00081 
00082 // If path is 0, the caller already has read the link; else read it.
00083 //
00084         if (!path) lnklen = lbsz;
00085    else if (!lstat(path, &Stat) && S_ISLNK(Stat.st_mode))
00086            {if ((lnklen = readlink(path, lbuf, lbsz-1)) < 0) *lbuf = 0;
00087                else *(lbuf+lnklen) = 0;
00088            }
00089    else {lnklen = strlen(path);
00090          if (lnklen >= lbsz) lnklen = lbsz-1;
00091          strncpy(lbuf, path, lnklen); *(lbuf+lnklen) = '\0';
00092         }
00093 
00094 // Extract out the cache group name from "<path>/cgroup/nn/fn" if possible
00095 //
00096    if (lnklen >= 4 && lbuf[lnklen-1] == xChar && (pP=posCname(lbuf,lnklen,j)))
00097       {*(pP+j) = '\0';
00098        if (pP != lbuf) *(pP-1) = '\0';
00099        return pP;
00100       }
00101 
00102 // This is not a normal cache, so do something reasonable
00103 //
00104    if ((pP = index(lbuf, xChar))) *pP = '\0';
00105       else *(lbuf+1) = '\0';
00106    return "public";
00107 }
00108 
00109 /******************************************************************************/
00110 /*                               g e n P a t h                                */
00111 /******************************************************************************/
00112   
00113 char *XrdOssPath::genPath(const char *inPath, const char *cgrp, char *sfx)
00114 {
00115    char *dirP, cgbuff[XrdOssSpace::minSNbsz], pbuff[MAXPATHLEN+64], *pP = pbuff;
00116    int n;
00117 
00118 // Check if the group name is already in the path
00119 //
00120    strcpy(pbuff, inPath); strcpy(cgbuff, cgrp); strcat(cgbuff, "/");
00121    do {if ((dirP = index(pP, '/')) && !strcmp(dirP+1, cgbuff)) break;
00122        pP = dirP+1;
00123       } while(dirP);
00124 
00125 // If the group name is not in the path, add the group name to it.
00126 //
00127    if (!dirP)
00128       {dirP = pbuff + strlen(inPath) - 1;
00129        strcpy(dirP+1, cgbuff);
00130       }
00131 
00132 // Construct a suffix that will allow us to quickly find the group name
00133 // We rely on the fact that group names are typically less than 16 characters 
00134 // and cache group paths are less than 240 characters
00135 //
00136    if ((n = strlen(cgrp)) > 15) sfx[2] = 'f';
00137       else sfx[2] = h2c[n];
00138    n = (dirP - pbuff + 1) & 0xff;
00139    sfx[1] = h2c[(n & 0x0f)]; n = n >> 4; sfx[0] = h2c[(n & 0x0f)];
00140    sfx[3] = xChar;
00141 
00142 // Return the path
00143 //
00144    return strdup(pbuff);
00145 }
00146 
00147 /******************************************************************************/
00148 /*                                g e n P F N                                 */
00149 /******************************************************************************/
00150   
00151 char *XrdOssPath::genPFN(fnInfo &Info, char *buff, int blen, const char *Path)
00152 {
00153     static XrdSysMutex myMutex;
00154     static char pfnPfx[8];
00155     static int mySeq = Init(pfnPfx);
00156     union {int  bin;
00157            char chr[4];} Seq;
00158     char   *bP = buff;
00159 
00160 // Construct old style path if we have a path present (i.e., non-xa path)
00161 //
00162    if (Path)
00163       {const char *pap = Path;
00164        if ((Info.Plen + static_cast<int>(strlen(Path))) >= blen) 
00165            {*buff = '\0'; return 0;}
00166        memcpy(bP, Info.Path,  Info.Plen);
00167        bP += Info.Plen;
00168        XrdOssTAMP(bP, pap);
00169        Info.Slash = buff;
00170        return 0;
00171       }
00172 
00173 // Increment the sequence number
00174 //
00175    myMutex.Lock();
00176    Seq.bin = mySeq++;
00177    myMutex.UnLock();
00178 
00179 // Construct the path (buffer will be big enough)
00180 //
00181    memcpy(bP, Info.Path, Info.Plen);
00182    bP += Info.Plen;
00183    *bP++ = h2c[((Seq.bin>4) & 0x0f)];
00184    *bP++ = h2c[( Seq.bin    & 0x0f)];
00185    Info.Slash= bP;
00186    *bP++ = '/';
00187    memcpy(bP, pfnPfx, sizeof(pfnPfx));
00188    bP = bin2hex(Seq.chr, sizeof(Seq.chr), bP+sizeof(pfnPfx));
00189    memcpy(bP, Info.Sfx, sfxLen);
00190    bP += sfxLen;
00191    *bP = '\0';
00192 
00193 // All done
00194 //
00195    return bP;
00196 }
00197 
00198 /******************************************************************************/
00199 
00200 char *XrdOssPath::genPFN(char *dst, int dln, const char *src)
00201 {
00202    char *pP;
00203 
00204    if (!(pP = (char *) index(src, xChar))|| dln <= (int)strlen(pP)) return 0;
00205 
00206    while(*pP) {*dst++ = (*pP == xChar ? '/' : *pP); pP++;}
00207 
00208    *dst = '\0';
00209    return dst;
00210 }
00211 
00212 /******************************************************************************/
00213 /*                              g e t C n a m e                               */
00214 /******************************************************************************/
00215   
00216 int  XrdOssPath::getCname(const char *path, char *Cache,
00217                                 char *lbuf, int   lbsz)
00218 {
00219    struct stat lbuff;
00220    char *xP, lnkbuff[MAXPATHLEN+64];
00221    int j, lnklen = 0;
00222 
00223 // Set up local buffer or remote buffer
00224 //
00225    if (!lbuf) {lbuf = lnkbuff; lbsz = MAXPATHLEN;}
00226 
00227 // If path is 0, the caller already has read the link; else read it.
00228 //
00229    if (!path) lnklen = lbsz;
00230       else if (!lstat(path, &lbuff) && S_ISLNK(lbuff.st_mode))
00231               lnklen = readlink(path, lbuf, lbsz);
00232 
00233 // Check if the symlink references a new cache. If not then the cache group is
00234 // always deemed to be public.
00235 //
00236    if (lnklen < 4 || lbuf[lnklen-1] != xChar)
00237       {strcpy(Cache, "public"); return (lnklen < 0 ? 0 : lnklen);}
00238 
00239 // Extract out the cache group name from "<path>/cgroup/nn/fn"
00240 //
00241    if (!(xP = posCname(lbuf, lnklen, j))) strcpy(Cache, "public");
00242       else {strncpy(Cache, xP, j); *(Cache+j)='\0';}
00243 
00244 // All done
00245 //
00246    return lnklen;
00247 }
00248 
00249 /******************************************************************************/
00250 /*                              p a t h T y p e                               */
00251 /******************************************************************************/
00252 
00253 XrdOssPath::theSfx XrdOssPath::pathType(const char *Path, int chkWhat)
00254 {
00255    static const int chkMM = chkMem | chkMig;
00256 
00257    char  *Dot;
00258    int    i, iBeg, iEnd;
00259 
00260 // Compute ending test
00261 //
00262         if ( chkWhat & chkAll)           {iBeg = 0; iEnd = int(sfxLast);}
00263    else if ((chkWhat & chkMM ) == chkMM) {iBeg = 1; iEnd = int(sfxMemL);}
00264    else if ( chkWhat & chkMig)           {iBeg = 1; iEnd = int(sfxMigL);}
00265    else if ( chkWhat & chkMem) {iBeg = int(sfxMemF);iEnd = int(sfxMigL);}
00266    else                                  {iBeg = 0; iEnd = 0;}
00267 
00268 // Convert path to suffix number
00269 //
00270         if ((Dot = (char *) rindex(Path, '.')))
00271       for (i = iBeg; i < iEnd; i++) if (!strcmp(Dot,Sfx[i])) return theSfx(i+1);
00272    return isBase;
00273 }
00274   
00275 /******************************************************************************/
00276 /*                             T r i m 2 B a s e                              */
00277 /******************************************************************************/
00278   
00279 void XrdOssPath::Trim2Base(char *eP)
00280 {
00281    int oneMore = (*eP == xChar);
00282 
00283 // Trim to the cache group name in "<path>/cgroup/nn/fn" or "<path>/fn"
00284 //
00285    do {eP--;} while(*eP != '/');
00286    if (oneMore) do {eP--;} while(*eP != '/');
00287    *(eP+1) = '\0';
00288 }
00289 
00290 /******************************************************************************/
00291 /*                       P r i v a t e   M e t h o d s                        */
00292 /******************************************************************************/
00293 /******************************************************************************/
00294 /*                               b i n 2 h e x                                */
00295 /******************************************************************************/
00296   
00297 char *XrdOssPath::bin2hex(char *inbuff, int dlen, char *buff)
00298 {
00299     int i;
00300 
00301     for (i = 0; i < dlen; i++) {
00302         *buff++ = h2c[(inbuff[i] >> 4) & 0x0f];
00303         *buff++ = h2c[ inbuff[i]       & 0x0f];
00304         }
00305      return buff;
00306 }
00307 
00308 /******************************************************************************/
00309 /*                                  I n i t                                   */
00310 /******************************************************************************/
00311   
00312 int XrdOssPath::Init(char *pfnPfx)
00313 {
00314    time_t theTime = time(0);
00315    union {int  binT;
00316           char chrT[4];} xTime;
00317 
00318 // Generate the pfn prefix
00319 //
00320    xTime.binT = static_cast<int>(theTime);
00321    bin2hex(xTime.chrT, sizeof(xTime.binT), pfnPfx);
00322    return 0;
00323 }
00324 
00325 /******************************************************************************/
00326 /*                              p o s C n a m e                               */
00327 /******************************************************************************/
00328 
00329 char *XrdOssPath::posCname(char *lbuf, int lbsz, int &cnsz)
00330 {
00331    char *eP, *xP = lbuf + lbsz - 4;
00332    long xCode;
00333    int k;
00334 
00335 // Extract out the cache group name from "<path>/cgroup/nn/fn"
00336 //
00337    if ((xCode = strtol(xP, &eP, 16)) && *eP == xChar
00338    &&  (cnsz = xCode & 0x0f) && (k = xCode>>4) && k < (lbsz-cnsz))
00339       {xP = lbuf + k;
00340        if (cnsz == 15 && *(xP+cnsz) != '/' && (eP = index(xP+cnsz,'/'))
00341        &&  eP-xP <= XrdOssSpace::maxSNlen) cnsz = eP - xP;
00342        return xP;
00343       }
00344    return 0;
00345 }

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