XRootD
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 
41 #include "XrdSys/XrdSysHeaders.hh"
42 #include "XrdSys/XrdSysPlatform.hh"
43 
44 /******************************************************************************/
45 /* S t a t i c s */
46 /******************************************************************************/
47 
48 namespace
49 {
50 struct ProtoTable
51  {const char *name;
52  int nlen;
53  };
54 
55 static const int ptEnts = 8; // Number of protocol entries we support
56 }
57 
58 namespace XrdPosixGlobals
59 {
60 extern XrdOucName2Name *theN2N;
61 extern bool oidsOK;
62 extern bool p2lSRC;
63 extern 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 
121 bool 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 
143 void 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 
161 const 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,
184  XrdPosixGlobals::protoTab[i].nlen))
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 
274 char *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,
284  XrdPosixGlobals::protoTab[i].nlen))
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)
Definition: XrdBwmTrace.hh:54
#define EPNAME(x)
Definition: XrdBwmTrace.hh:56
#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
Definition: XrdPosixFile.cc:62