XRootD
Loading...
Searching...
No Matches
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"
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
57char XrdOssPath::h2c[16] = {'0','1','2','3','4','5','6','7',
58 '8','9','A','B','C','D','E','F'};
59
60char XrdOssPath::pfnPfx[60] = {'\0'};
61
62const 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
75int 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
97const 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
134char *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
172char *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
225char *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
241int 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
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
322char *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
375char *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
#define stat(a, b)
Definition XrdPosix.hh:101
XrdOucString Path
const XrdNetSockAddr * NetAddr()
static int Encode(const XrdNetSockAddr *sadr, char *buff, int blen, int port=-1)
static const int chkAll
Definition XrdOssPath.hh:80
static int getCname(const char *path, char *Cache, char *lbuf=0, int lbsz=0)
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)
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)
static const char * Sfx[sfxNum]
Definition XrdOssPath.hh:66
static const int chkMig
Definition XrdOssPath.hh:78
static void Trim2Base(char *eP)
static const char xChar
Definition XrdOssPath.hh:47
static char * genPath(const char *inPath, const char *cgrp, char *sfx)
static int InitPrefix()
static const int minSNbsz
static const int maxSNlen