XRootD
Loading...
Searching...
No Matches
XrdPosixXrootdPath.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d P o s i x X r o o t d P a t h . c c */
4/* */
5/* (c) 2011 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 <cstdlib>
33#include <cstring>
34#include <strings.h>
35#include <sys/param.h>
36
43
44/******************************************************************************/
45/* S t a t i c s */
46/******************************************************************************/
47
48namespace
49{
50struct ProtoTable
51 {const char *name;
52 int nlen;
53 };
54
55static const int ptEnts = 8; // Number of protocol entries we support
56}
57
58namespace XrdPosixGlobals
59{
60extern XrdOucName2Name *theN2N;
61extern bool oidsOK;
62extern bool p2lSRC;
63extern bool p2lSGI;
64
65 ProtoTable protoTab[ptEnts] = {{"root://", 7}, {"xroot://", 8},
66 {"roots://", 8}, {"xroots://", 9}};
67}
68
69/******************************************************************************/
70/* X r d P o s i x X r o o t P a t h C o n s t r u c t o r */
71/******************************************************************************/
72
74 : xplist(0),
75 pBase(0)
76{
77 XrdOucTokenizer thePaths(0);
78 char *plist = 0, *colon = 0, *subs = 0, *lp = 0, *tp = 0;
79 int aOK = 0;
80
81 cwdPath = 0; cwdPlen = 0;
82
83 if (!(plist = getenv("XROOTD_VMP")) || !*plist) return;
84 pBase = strdup(plist);
85
86 thePaths.Attach(pBase);
87
88 if ((lp = thePaths.GetLine())) while((tp = thePaths.GetToken()))
89 {aOK = 1;
90 if ((colon = rindex(tp, (int)':')) && *(colon+1) == '/')
91 {if (!(subs = index(colon, (int)'='))) subs = 0;
92 else if (*(subs+1) == '/') {*subs = '\0'; subs++;}
93 else if (*(subs+1)) aOK = 0;
94 else {*subs = '\0'; subs = (char*)"";}
95 } else aOK = 0;
96
97 if (aOK)
98 {*colon++ = '\0';
99 while(*(colon+1) == '/') colon++;
100 xplist = new xpath(xplist, tp, colon, subs);
101 } else DMSG("Path", "Invalid XROOTD_VMP token '" <<tp <<'"');
102 }
103}
104
105/******************************************************************************/
106/* X r d P o s i x X r o o t P a t h D e s t r u c t o r */
107/******************************************************************************/
108
110{
111 struct xpath *xpnow;
112
113 while((xpnow = xplist))
114 {xplist = xplist->next; delete xpnow;}
115}
116
117/******************************************************************************/
118/* X r d P o s i x P a t h : : A d d P r o t o */
119/******************************************************************************/
120
121bool XrdPosixXrootPath::AddProto(const char *proto)
122{
123 int i;
124
125// Check if we already have this protocol entry. The proto argument must be
126// in the form "pname://", where pname is the protocol name.
127//
128 for (i = 0; i < ptEnts && XrdPosixGlobals::protoTab[i].name; i++)
129 if (!strcmp(proto, XrdPosixGlobals::protoTab[i].name)) return true;
130
131// Add the entry if we have room
132//
133 if (i >= ptEnts) return false;
134 XrdPosixGlobals::protoTab[i].name = strdup(proto);
135 XrdPosixGlobals::protoTab[i].nlen = strlen(proto);
136 return true;
137}
138
139/******************************************************************************/
140/* X r d P o s i x P a t h : : C W D */
141/******************************************************************************/
142
143void XrdPosixXrootPath::CWD(const char *path)
144{
145 if (cwdPath) free(cwdPath);
146 cwdPlen = strlen(path);
147 if (*(path+cwdPlen-1) == '/') cwdPath = strdup(path);
148 else if (cwdPlen <= MAXPATHLEN)
149 {char buff[MAXPATHLEN+8];
150 strcpy(buff, path);
151 *(buff+cwdPlen ) = '/';
152 *(buff+cwdPlen+1) = '\0';
153 cwdPath = strdup(buff); cwdPlen++;
154 }
155}
156
157/******************************************************************************/
158/* X r d P o s i x P a t h : : P 2 L */
159/******************************************************************************/
160
161const char *XrdPosixXrootPath::P2L(const char *who,
162 const char *inP,
163 char *&relP,
164 bool ponly)
165{
166 EPNAME("P2L");
167 const char *urlP, *slash, *quest;
168 char *outP, *lfnP, lfnBuff[1032];
169 int cgiLen, lfnLen, pfnLen, pfxLen, n;
170 bool notOurs = true;
171
172// Preset repP to zero to indicate no translation required, nothing to free
173//
174 relP = 0;
175
176// Check if we need to do any translation at all
177//
178 if (!XrdPosixGlobals::theN2N && !ponly) return inP;
179
180// If this is a protocol we support, then we can convert the path
181//
182 for (int i = 0; i < ptEnts && XrdPosixGlobals::protoTab[i].name; i++)
183 if (!strncmp(inP, XrdPosixGlobals::protoTab[i].name,
185 {urlP = inP + XrdPosixGlobals::protoTab[i].nlen;
186 notOurs = false;
187 break;
188 }
189 if (notOurs) return inP;
190
191// Search for the next slash which must be followed by another slash unless we
192// are allowing object ids.
193//
194 if (!(slash = index(urlP, '/'))) return inP;
195 if (*(slash+1) != '/' && !XrdPosixGlobals::oidsOK) return inP;
196 pfxLen = slash - inP;
197 slash++;
198
199// Search for start of the cgi
200//
201 if ((quest = index(slash, '?')))
202 {cgiLen = strlen(quest);
203 pfnLen = quest - slash;
204 } else {
205 cgiLen = 0;
206 pfnLen = strlen(slash);
207 }
208
209// Allocate sufficient space for the pfn with possible extensions (e.g. "?src="
210// and the whole url prefix and possible cgi).
211//
212 n = (XrdPosixGlobals::p2lSGI ? cgiLen : 0);
213 char *pfnBP = (char *)alloca(pfnLen + 5 + pfxLen + n + 1);
214
215// Copy out the pfn. We know it will definitely fit.
216//
217 strncpy(pfnBP, slash, pfnLen);
218
219// Check if the N2N wants to know the source and add it if so.
220//
221 if (!XrdPosixGlobals::p2lSRC) *(pfnBP+pfnLen) = 0;
222 else {char *bP = pfnBP+pfnLen;
223 memcpy(bP, "?src=", 5); bP += 5;
224 strncpy(bP, inP, pfxLen);
225 bP += pfxLen;
226 if (XrdPosixGlobals::p2lSGI && cgiLen)
227 {if (*(quest+1) != '&') *bP++ = '&';
228 strcpy(bP, quest+1);
229 } else *bP = 0;
230 }
231
232// Invoke the name2name translator if we have one
233//
235 {if ((n = XrdPosixGlobals::theN2N->pfn2lfn(pfnBP,lfnBuff,sizeof(lfnBuff))))
236 {errno = n;
237 return 0;
238 }
239 lfnP = lfnBuff;
240 } else lfnP = pfnBP;
241
242// If only the path is wanted, then adjust lengths
243//
244 if (ponly) pfxLen = cgiLen = 0;
245
246// Allocate storage to assemble the new url
247//
248 lfnLen = strlen(lfnP);
249 if (!(relP = (char *)malloc(pfxLen + lfnLen + cgiLen + 1)))
250 {errno = ENOMEM;
251 return 0;
252 }
253 outP = relP;
254
255// Assemble the new url, we know we have room to do this
256//
257 if (pfxLen) {strncpy(outP, inP, pfxLen); outP += pfxLen;}
258 strcpy( outP, lfnP);
259 if (cgiLen) strcpy(outP+lfnLen, quest);
260
261// Do some debugging
262//
263 DEBUG(who <<' ' <<pfnBP <<" pfn2lfn " <<lfnBuff);
264
265// All done, return result
266//
267 return relP;
268}
269
270/******************************************************************************/
271/* X r d P o s i x P a t h : : U R L */
272/******************************************************************************/
273
274char *XrdPosixXrootPath::URL(const char *path, char *buff, int blen)
275{
276 struct xpath *xpnow = xplist;
277 char tmpbuff[2048];
278 int plen, pathlen = 0;
279
280// Check if this is a protocol we support
281//
282 for (int i = 0; i < ptEnts && XrdPosixGlobals::protoTab[i].name; i++)
283 {if (!strncmp(path, XrdPosixGlobals::protoTab[i].name,
285 return (char *)path;
286 }
287
288// If a relative path was specified, convert it to an absolute path
289//
290 if (path[0] == '.' && path[1] == '/' && cwdPath)
291 {pathlen = (strlen(path) + cwdPlen - 2);
292 if (pathlen < (int)sizeof(tmpbuff))
293 {strcpy(tmpbuff, cwdPath);
294 strcpy(tmpbuff+cwdPlen, path+2);
295 path = (const char *)tmpbuff;
296 } else return 0;
297 }
298
299// Check if this path starts with one or our known paths
300//
301 while(*(path+1) == '/') path++;
302 while(xpnow)
303 if (!strncmp(path, xpnow->path, xpnow->plen)) break;
304 else xpnow = xpnow->next;
305
306// If we did not match a path, this is not our path.
307//
308 if (!xpnow) return 0;
309 if (!buff) return (char *)1;
310
311// Verify that we won't overflow the buffer
312//
313 if (!pathlen) pathlen = strlen(path);
314 plen = pathlen + xpnow->servln + 2;
315 if (xpnow->nath) plen = plen - xpnow->plen + xpnow->nlen;
316 if (plen >= blen) return 0;
317
318// Build the url
319//
320 strcpy(buff, XrdPosixGlobals::protoTab[0].name);
321 strcat(buff, xpnow->server);
322 strcat(buff, "/");
323 if (xpnow->nath) {strcat(buff, xpnow->nath); path += xpnow->plen;}
324 if (*path != '/') strcat(buff, "/");
325 strcat(buff, path);
326 return buff;
327}
#define DEBUG(x)
#define EPNAME(x)
#define DMSG(x, y)
char * GetToken(char **rest=0, int lowcase=0)
void Attach(char *bp)
static bool AddProto(const char *proto)
char * URL(const char *path, char *buff, int blen)
static const char * P2L(const char *who, const char *inP, char *&relP, bool ponly=false)
void CWD(const char *path)
ProtoTable protoTab[ptEnts]
XrdOucName2Name * theN2N