XRootD
XrdOssPath.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d O s s P a t h . c c */
4 /* */
5 /* (c) 2008 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 <limits.h>
34 #include <ctime>
35 #include <unistd.h>
36 #include <sys/stat.h>
37 #include <sys/types.h>
38 #include <sys/param.h>
39 
40 #include "XrdOss/XrdOssPath.hh"
41 #include "XrdOss/XrdOssSpace.hh"
42 #include "XrdSys/XrdSysPthread.hh"
43 #include "XrdNet/XrdNetAddr.hh"
44 #include "XrdNet/XrdNetUtils.hh"
45 
46 /******************************************************************************/
47 /* L o c a l M a c r o s */
48 /******************************************************************************/
49 
50 #define XrdOssTAMP(dst, src) \
51  while(*src) {*dst = (*src == '/' ? xChar : *src); src++; dst++;}; *dst='\0'
52 
53 /******************************************************************************/
54 /* S t a t i c O b j e c t s */
55 /******************************************************************************/
56 
57 char XrdOssPath::h2c[16] = {'0','1','2','3','4','5','6','7',
58  '8','9','A','B','C','D','E','F'};
59 
60 char XrdOssPath::pfnPfx[60] = {'\0'};
61 
62 const char XrdOssPath::xChar;
63 
64 // The initialization must be in 1-to-1 order with theSfx enum!
65 //
67  {".anew", ".fail", ".lock", ".pin",
68  ".mmap", ".mkeep", ".mlock",".pfn", 0};
69 
70 
71 /******************************************************************************/
72 /* C o n v e r t */
73 /******************************************************************************/
74 
75 int XrdOssPath::Convert(char *dst, int dln, const char *oldP, const char *newP)
76 {
77  int i;
78 
79 // Copy all the char up to the first % into the new link buffer
80 //
81  for (i = 0; oldP[i] && oldP[i] != xChar; i++) *dst++ = oldP[i];
82 
83 // Now make sure the resulting name will fit
84 //
85  if ((i + static_cast<int>(strlen(newP))) >= dln) return -ENAMETOOLONG;
86 
87 // Complete the name
88 //
89  XrdOssTAMP(dst, newP);
90  return 0;
91 }
92 
93 /******************************************************************************/
94 /* E x t r a c t */
95 /******************************************************************************/
96 
97 const char *XrdOssPath::Extract(char *path, char *lbuf, int &lbsz)
98 {
99  struct stat Stat;
100  char *pP;
101  int j, lnklen = 0;
102 
103 // If path is 0, the caller already has read the link; else read it.
104 //
105  if (!path) lnklen = lbsz;
106  else if (!lstat(path, &Stat) && S_ISLNK(Stat.st_mode))
107  {if ((lnklen = readlink(path, lbuf, lbsz-1)) < 0) *lbuf = 0;
108  else *(lbuf+lnklen) = 0;
109  }
110  else {lnklen = strlen(path);
111  if (lnklen >= lbsz) lnklen = lbsz-1;
112  strncpy(lbuf, path, lnklen); *(lbuf+lnklen) = '\0';
113  }
114 
115 // Extract out the cache group name from "<path>/cgroup/nn/fn" if possible
116 //
117  if (lnklen >= 4 && lbuf[lnklen-1] == xChar && (pP=posCname(lbuf,lnklen,j)))
118  {*(pP+j) = '\0';
119  if (pP != lbuf) *(pP-1) = '\0';
120  return pP;
121  }
122 
123 // This is not a normal cache, so do something reasonable
124 //
125  if ((pP = index(lbuf, xChar))) *pP = '\0';
126  else *(lbuf+1) = '\0';
127  return "public";
128 }
129 
130 /******************************************************************************/
131 /* g e n P a t h */
132 /******************************************************************************/
133 
134 char *XrdOssPath::genPath(const char *inPath, const char *cgrp, char *sfx)
135 {
136  char *dirP, cgbuff[XrdOssSpace::minSNbsz], pbuff[MAXPATHLEN+64], *pP = pbuff;
137  int n;
138 
139 // Check if the group name is already in the path
140 //
141  strcpy(pbuff, inPath); strcpy(cgbuff, cgrp); strcat(cgbuff, "/");
142  do {if ((dirP = index(pP, '/')) && !strcmp(dirP+1, cgbuff)) break;
143  pP = dirP+1;
144  } while(dirP);
145 
146 // If the group name is not in the path, add the group name to it.
147 //
148  if (!dirP)
149  {dirP = pbuff + strlen(inPath) - 1;
150  strcpy(dirP+1, cgbuff);
151  }
152 
153 // Construct a suffix that will allow us to quickly find the group name
154 // We rely on the fact that group names are typically less than 16 characters
155 // and cache group paths are less than 240 characters
156 //
157  if ((n = strlen(cgrp)) > 15) sfx[2] = 'f';
158  else sfx[2] = h2c[n];
159  n = (dirP - pbuff + 1) & 0xff;
160  sfx[1] = h2c[(n & 0x0f)]; n = n >> 4; sfx[0] = h2c[(n & 0x0f)];
161  sfx[3] = xChar;
162 
163 // Return the path
164 //
165  return strdup(pbuff);
166 }
167 
168 /******************************************************************************/
169 /* g e n P F N */
170 /******************************************************************************/
171 
172 char *XrdOssPath::genPFN(fnInfo &Info, char *buff, int blen, const char *Path)
173 {
174  static XrdSysMutex myMutex;
175  static int mySeq = 0;
176  union {int bin;
177  char chr[4];} Seq;
178  char *bP = buff;
179 
180 // Construct old style path if we have a path present (i.e., non-xa path)
181 //
182  if (Path)
183  {const char *pap = Path;
184  if ((Info.Plen + static_cast<int>(strlen(Path))) >= blen)
185  {*buff = '\0'; return 0;}
186  memcpy(bP, Info.Path, Info.Plen);
187  bP += Info.Plen;
188  XrdOssTAMP(bP, pap);
189  Info.Slash = buff;
190  return 0;
191  }
192 
193  if (! *pfnPfx) {
194  *bP = '\0';
195  return bP;
196  }
197 
198 // Increment the sequence number
199 //
200  myMutex.Lock();
201  Seq.bin = mySeq++;
202  myMutex.UnLock();
203 
204 // Construct the path (buffer will be big enough)
205 //
206  memcpy(bP, Info.Path, Info.Plen);
207  bP += Info.Plen;
208  *bP++ = h2c[((Seq.bin>>4) & 0x0f)];
209  *bP++ = h2c[( Seq.bin & 0x0f)];
210  Info.Slash= bP;
211  *bP++ = '/';
212  strcpy(bP, pfnPfx);
213  bP = bin2hex(Seq.chr, sizeof(Seq.chr), bP+strlen(pfnPfx));
214  memcpy(bP, Info.Sfx, sfxLen);
215  bP += sfxLen;
216  *bP = '\0';
217 
218 // All done
219 //
220  return bP;
221 }
222 
223 /******************************************************************************/
224 
225 char *XrdOssPath::genPFN(char *dst, int dln, const char *src)
226 {
227  char *pP;
228 
229  if (!(pP = (char *) index(src, xChar))|| dln <= (int)strlen(pP)) return 0;
230 
231  while(*pP) {*dst++ = (*pP == xChar ? '/' : *pP); pP++;}
232 
233  *dst = '\0';
234  return dst;
235 }
236 
237 /******************************************************************************/
238 /* g e t C n a m e */
239 /******************************************************************************/
240 
241 int XrdOssPath::getCname(const char *path, char *Cache,
242  char *lbuf, int lbsz)
243 {
244  struct stat lbuff;
245  char *xP, lnkbuff[MAXPATHLEN+64];
246  int j, lnklen = 0;
247 
248 // Set up local buffer or remote buffer
249 //
250  if (!lbuf) {lbuf = lnkbuff; lbsz = MAXPATHLEN;}
251 
252 // If path is 0, the caller already has read the link; else read it.
253 //
254  if (!path) lnklen = lbsz;
255  else if (!lstat(path, &lbuff) && S_ISLNK(lbuff.st_mode))
256  lnklen = readlink(path, lbuf, lbsz);
257 
258 // Check if the symlink references a new cache. If not then the cache group is
259 // always deemed to be public.
260 //
261  if (lnklen < 4 || lbuf[lnklen-1] != xChar)
262  {strcpy(Cache, "public"); return (lnklen < 0 ? 0 : lnklen);}
263 
264 // Extract out the cache group name from "<path>/cgroup/nn/fn"
265 //
266  if (!(xP = posCname(lbuf, lnklen, j))) strcpy(Cache, "public");
267  else {strncpy(Cache, xP, j); *(Cache+j)='\0';}
268 
269 // All done
270 //
271  return lnklen;
272 }
273 
274 /******************************************************************************/
275 /* p a t h T y p e */
276 /******************************************************************************/
277 
279 {
280  static const int chkMM = chkMem | chkMig;
281 
282  char *Dot;
283  int i, iBeg, iEnd;
284 
285 // Compute ending test
286 //
287  if ( chkWhat & chkAll) {iBeg = 0; iEnd = int(sfxLast);}
288  else if ((chkWhat & chkMM ) == chkMM) {iBeg = 1; iEnd = int(sfxMemL);}
289  else if ( chkWhat & chkMig) {iBeg = 1; iEnd = int(sfxMigL);}
290  else if ( chkWhat & chkMem) {iBeg = int(sfxMemF);iEnd = int(sfxMigL);}
291  else {iBeg = 0; iEnd = 0;}
292 
293 // Convert path to suffix number
294 //
295  if ((Dot = (char *) rindex(Path, '.')))
296  for (i = iBeg; i < iEnd; i++) if (!strcmp(Dot,Sfx[i])) return theSfx(i+1);
297  return isBase;
298 }
299 
300 /******************************************************************************/
301 /* T r i m 2 B a s e */
302 /******************************************************************************/
303 
304 void XrdOssPath::Trim2Base(char *eP)
305 {
306  int oneMore = (*eP == xChar);
307 
308 // Trim to the cache group name in "<path>/cgroup/nn/fn" or "<path>/fn"
309 //
310  do {eP--;} while(*eP != '/');
311  if (oneMore) do {eP--;} while(*eP != '/');
312  *(eP+1) = '\0';
313 }
314 
315 /******************************************************************************/
316 /* P r i v a t e M e t h o d s */
317 /******************************************************************************/
318 /******************************************************************************/
319 /* b i n 2 h e x */
320 /******************************************************************************/
321 
322 char *XrdOssPath::bin2hex(char *inbuff, int dlen, char *buff)
323 {
324  int i;
325 
326  for (i = 0; i < dlen; i++) {
327  *buff++ = h2c[(inbuff[i] >> 4) & 0x0f];
328  *buff++ = h2c[ inbuff[i] & 0x0f];
329  }
330  return buff;
331 }
332 
333 /******************************************************************************/
334 /* I n i t P r e f i x */
335 /******************************************************************************/
336 
337 // Create a prefix for files in a cache. It is create only once when oss is
338 // configured. It is unique using: <time><pid><encoded-network-address>
339 
341 {
342  union {int binT;
343  char chrT[4];} xT;
344 
345  size_t plen = sizeof(pfnPfx) - 4*sizeof(xT.binT) - 1;
346 
347  if (plen < 1) return 1;
348 
349  char *bp = pfnPfx;
350 
351  time_t theTime = time(0);
352  xT.binT = static_cast<int>(theTime);
353  bp = bin2hex(xT.chrT, sizeof(xT.binT), bp);
354 
355  pid_t pid = getpid();
356  xT.binT = static_cast<int> (pid);
357  bp = bin2hex(xT.chrT, sizeof(xT.binT), bp);
358 
359  XrdNetAddr theAddr(0);
360  int rc = XrdNetUtils::Encode(theAddr.NetAddr(), bp, plen);
361 
362  if ( rc < 0 ) {
363  pfnPfx[0] = '\0';
364  return 1;
365  }
366 
367  return 0;
368 }
369 
370 
371 /******************************************************************************/
372 /* p o s C n a m e */
373 /******************************************************************************/
374 
375 char *XrdOssPath::posCname(char *lbuf, int lbsz, int &cnsz)
376 {
377  char *eP, *xP = lbuf + lbsz - 4;
378  long xCode;
379  int k;
380 
381 // Extract out the cache group name from "<path>/cgroup/nn/fn"
382 //
383  if ((xCode = strtol(xP, &eP, 16)) && *eP == xChar
384  && (cnsz = xCode & 0x0f) && (k = xCode>>4) && k < (lbsz-cnsz))
385  {xP = lbuf + k;
386  if (cnsz == 15 && *(xP+cnsz) != '/' && (eP = index(xP+cnsz,'/'))
387  && eP-xP <= XrdOssSpace::maxSNlen) cnsz = eP - xP;
388  return xP;
389  }
390  return 0;
391 }
struct stat Stat
Definition: XrdCks.cc:49
#define XrdOssTAMP(dst, src)
Definition: XrdOssPath.cc:50
@ Info
int stat(const char *path, struct stat *buf)
int lstat(const char *path, struct stat *buf)
XrdOucString Path
const XrdNetSockAddr * NetAddr()
static int Encode(const XrdNetSockAddr *sadr, char *buff, int blen, int port=-1)
Definition: XrdNetUtils.cc:120
static const int chkAll
Definition: XrdOssPath.hh:80
static int getCname(const char *path, char *Cache, char *lbuf=0, int lbsz=0)
Definition: XrdOssPath.cc:241
static int Convert(char *dst, int dln, const char *oldP, const char *newP)
Definition: XrdOssPath.cc:75
static const char * Extract(char *path, char *lbuf, int &lbsz)
Definition: XrdOssPath.cc:97
static theSfx pathType(const char *Path, int chkWhat=chkAll)
Definition: XrdOssPath.cc:278
static const int sfxLen
Definition: XrdOssPath.hh:49
static const int chkMem
Definition: XrdOssPath.hh:77
static char * genPFN(fnInfo &Info, char *buff, int blen, const char *Path=0)
Definition: XrdOssPath.cc:172
static const char * Sfx[sfxNum]
Definition: XrdOssPath.hh:75
static const int chkMig
Definition: XrdOssPath.hh:78
static void Trim2Base(char *eP)
Definition: XrdOssPath.cc:304
static const char xChar
Definition: XrdOssPath.hh:47
static char * genPath(const char *inPath, const char *cgrp, char *sfx)
Definition: XrdOssPath.cc:134
static int InitPrefix()
Definition: XrdOssPath.cc:340
static const int minSNbsz
Definition: XrdOssSpace.hh:45
static const int maxSNlen
Definition: XrdOssSpace.hh:44
XrdCmsCache Cache
Definition: XrdPfcFile.hh:204