00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
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
00030
00031
00032 #define XrdOssTAMP(dst, src) \
00033 while(*src) {*dst = (*src == '/' ? xChar : *src); src++; dst++;}; *dst='\0'
00034
00035
00036
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
00045
00046 const char *XrdOssPath::Sfx[XrdOssPath::sfxNum] =
00047 {".anew", ".fail", ".lock", ".pin", ".stage",
00048 ".mmap", ".mkeep", ".mlock",".pfn", 0};
00049
00050
00051
00052
00053
00054 int XrdOssPath::Convert(char *dst, int dln, const char *oldP, const char *newP)
00055 {
00056 int i;
00057
00058
00059
00060 for (i = 0; oldP[i] && oldP[i] != xChar; i++) *dst++ = oldP[i];
00061
00062
00063
00064 if ((i + static_cast<int>(strlen(newP))) >= dln) return -ENAMETOOLONG;
00065
00066
00067
00068 XrdOssTAMP(dst, newP);
00069 return 0;
00070 }
00071
00072
00073
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
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
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
00103
00104 if ((pP = index(lbuf, xChar))) *pP = '\0';
00105 else *(lbuf+1) = '\0';
00106 return "public";
00107 }
00108
00109
00110
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
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
00126
00127 if (!dirP)
00128 {dirP = pbuff + strlen(inPath) - 1;
00129 strcpy(dirP+1, cgbuff);
00130 }
00131
00132
00133
00134
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
00143
00144 return strdup(pbuff);
00145 }
00146
00147
00148
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
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
00174
00175 myMutex.Lock();
00176 Seq.bin = mySeq++;
00177 myMutex.UnLock();
00178
00179
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
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
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
00224
00225 if (!lbuf) {lbuf = lnkbuff; lbsz = MAXPATHLEN;}
00226
00227
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
00234
00235
00236 if (lnklen < 4 || lbuf[lnklen-1] != xChar)
00237 {strcpy(Cache, "public"); return (lnklen < 0 ? 0 : lnklen);}
00238
00239
00240
00241 if (!(xP = posCname(lbuf, lnklen, j))) strcpy(Cache, "public");
00242 else {strncpy(Cache, xP, j); *(Cache+j)='\0';}
00243
00244
00245
00246 return lnklen;
00247 }
00248
00249
00250
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
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
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
00277
00278
00279 void XrdOssPath::Trim2Base(char *eP)
00280 {
00281 int oneMore = (*eP == xChar);
00282
00283
00284
00285 do {eP--;} while(*eP != '/');
00286 if (oneMore) do {eP--;} while(*eP != '/');
00287 *(eP+1) = '\0';
00288 }
00289
00290
00291
00292
00293
00294
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
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
00319
00320 xTime.binT = static_cast<int>(theTime);
00321 bin2hex(xTime.chrT, sizeof(xTime.binT), pfnPfx);
00322 return 0;
00323 }
00324
00325
00326
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
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 }