XRootD
XrdOucPup.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d O u c P u p . c c */
4 /* */
5 /* (c) 2007 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 <sys/uio.h>
33 #include <netinet/in.h>
34 #include <cinttypes>
35 #include <cstdio>
36 #include <cstring>
37 
38 #ifdef WIN32
39 #include <direct.h>
40 #include "XrdSys/XrdWin32.hh"
41 #endif
42 
43 #include "XrdOuc/XrdOucPup.hh"
44 #include "XrdSys/XrdSysError.hh"
45 #include "XrdSys/XrdSysHeaders.hh"
46 #include "XrdSys/XrdSysPlatform.hh"
47 
48 /******************************************************************************/
49 /* P a c k */
50 /******************************************************************************/
51 
52 int XrdOucPup::Pack(struct iovec **iovP,
53  const char *data,
54  unsigned short &buff)
55 {
56  unsigned short dlen;
57  struct iovec *vP = *iovP;
58 
59 // Pack the data as "<short len><char>" if data is present or "<short 0>" o/w.
60 // When data is present, the null byte is always included.
61 //
62  vP->iov_base = (char *)&buff; vP->iov_len = sizeof(buff); vP++;
63 
64  if (data)
65  {dlen = static_cast<unsigned short>(strlen(data)+1);
66  buff = htons(dlen);
67  vP->iov_base = (char *)data; vP->iov_len = dlen; vP++;
68  } else {buff = 0; dlen = 0;}
69 
70  *iovP = vP;
71  return dlen+sizeof(buff);
72 }
73 
74 /******************************************************************************/
75 
76 int XrdOucPup::Pack(struct iovec **iovP,
77  const char *data,
78  unsigned short &buff,
79  int dlen)
80 {
81  struct iovec *vP = *iovP;
82 
83  vP->iov_base = (char *)&buff; vP->iov_len = sizeof(buff); vP++;
84 
85  if (data)
86  {buff = htons(static_cast<unsigned short>(dlen));
87  vP->iov_base = (char *)data; vP->iov_len = dlen; vP++;
88  } else {buff = 0; dlen = 0;}
89 
90  *iovP = vP;
91  return dlen+sizeof(buff);
92 }
93 
94 /******************************************************************************/
95 
96 int XrdOucPup::Pack(char **buff,
97  const char *data,
98  int dlen)
99 {
100  char *bp = *buff;
101  unsigned short xlen;
102 
103  if (data)
104  {if (dlen < 0) dlen = strlen(data)+1;
105  xlen = htons(static_cast<unsigned short>(dlen));
106  memcpy(bp, &xlen, sizeof(xlen)); bp += sizeof(xlen);
107  memcpy(bp, data, dlen);
108  bp += dlen;
109  } else {*bp++ = '\0'; *bp++ = '\0'; dlen = 0;}
110 
111  *buff = bp;
112  return dlen+sizeof(xlen);
113 }
114 
115 /******************************************************************************/
116 
117 int XrdOucPup::Pack(char **buff,
118  unsigned int data)
119 {
120  unsigned int netData = htonl(data);
121  char *bp = *buff;
122 
123  if (netData & PT_Mask)
124  {*bp = static_cast<char>(PT_int);
125  memcpy(bp+1, &netData, sizeof(netData));
126  *buff = bp + sizeof(netData)+1;
127  return sizeof(netData)+1;
128  }
129  (*(char *)&netData) |= PT_int | PT_Inline;
130  memcpy(bp, &netData, sizeof(netData));
131  *buff = bp + sizeof(netData);
132  return sizeof(netData);
133 }
134 
135 /******************************************************************************/
136 
137 int XrdOucPup::Pack(struct iovec *iovP, struct iovec *iovE, XrdOucPupArgs *pup,
138  char *base, char *Work)
139 {
140  static char Nil[] = {PT_char, '\0'};
141  static const int Sz16 = sizeof(short) + 1;
142  static const int Sz32 = sizeof(int) + 1;
143  static const int Sz64 = sizeof(long long) + 1;
144  struct iovec *vP = iovP;
145  XrdOucPupArgs *pP = pup;
146  char *wP = Work;
147  int Dtype, dlen = 0, TotLen = 0;
148 
149  unsigned long long n64;
150  unsigned int n32;
151  unsigned short n16;
152 
153  union {unsigned long long *B64;
154  unsigned int *B32;
155  unsigned short *B16;
156  char **B08;} Base;
157 
158  Dtype = pP->Dtype;
159  do {Base.B08 = (char **)(base + pP->Doffs);
160  //std::cerr <<"arg " <<pP-pup <<" type " <<Dtype <<' '
161  // <<(Names->NList[pP->Name] ? Names->NList[pP->Name] : "?") <<std::endl;
162  switch(Dtype)
163  {case PT_char:
164 /* Null Pointer */ if (!*Base.B08) {vP->iov_base = Nil; vP->iov_len = 2;
165  vP++; TotLen += 2; break;
166  }
167  dlen = (pP->Dlen < 0 ? strlen(*Base.B08)+1 : pP->Dlen);
168 /* Full String */ if (dlen > MaxLen)
169  return eMsg("string too long packing", int(pP-pup), pP);
170  if (vP >= iovE)
171  return eMsg("too many args packing", int(pP-pup), pP);
172  n16 = htons(static_cast<unsigned short>(dlen));
173  vP->iov_base = wP; vP->iov_len = sizeof(n16); vP++;
174  memcpy(wP, &n16, sizeof(n16)); wP += sizeof(n16);
175  vP->iov_base = *Base.B08; vP->iov_len = dlen; vP++;
176  TotLen += dlen + sizeof(n16);
177  break;
178 
179  case PT_short:
180  n16 = htons(*Base.B16);
181  *wP = static_cast<char>(PT_short);
182  memcpy(wP+1, &n16, sizeof(n16));
183  vP->iov_base = wP; vP->iov_len = Sz16; vP++;
184  wP += Sz16; TotLen += Sz16; dlen = sizeof(n16);
185  break;
186 
187  case PT_int:
188  n32 = htonl(*Base.B32);
189  *wP = static_cast<char>(PT_int);
190  memcpy(wP+1, &n32, sizeof(n32));
191  vP->iov_base = wP; vP->iov_len = Sz32; vP++;
192  wP += Sz32; TotLen += Sz32; dlen = sizeof(n32);
193  break;
194 
195  case PT_longlong:
196  h2nll(*Base.B64, n64);
197  *wP = static_cast<char>(PT_longlong);
198  memcpy(wP+1, &n64, sizeof(n64));
199  vP->iov_base = wP; vP->iov_len = Sz64; vP++;
200  wP += Sz64; TotLen += Sz64; dlen = sizeof(n64);
201  break;
202 
203  case PT_special: break;
204 
205  case PT_Fence: break;
206  case PT_Ignore: break;
207 
208  case PT_MandS:
209  case PT_Mark:
210  *Base.B08 = (char *)vP;
211  if (pP->Dtype == PT_Mark) break;
212  vP++;
213  break;
214 
215  case PT_Skip:
216  vP++;
217  break;
218 
219  case PT_Datlen:
220  *Base.B32 = dlen;
221  break;
222 
223  case PT_Totlen:
224  *Base.B32 = TotLen;
225  break;
226 
227  case PT_EndFill:
228  *Base.B16 = htons(static_cast<unsigned short>(TotLen));
229  return static_cast<int>(vP-iovP);
230 
231  case PT_End:
232  return static_cast<int>(vP-iovP);
233 
234  default: {}
235  }
236  pP++;
237  Dtype = pP->Dtype;
238  } while(vP < iovE || (vP==iovE && Dtype != PT_Skip && (Dtype & PT_MaskD)));
239 
240 // We over-ran the iovec array
241 //
242  return eMsg("arg list too long packing", int(pP-pup), pup);
243 }
244 
245 /******************************************************************************/
246 /* U n p a c k */
247 /******************************************************************************/
248 
249 
250 int XrdOucPup::Unpack( char **buff,
251  const char *bend,
252  char **data,
253  int &dlen)
254 {
255  unsigned short temp;
256  char *bnxt = *buff;
257 
258 // Grab the length but make sure it's within bounds
259 //
260  if ((bnxt = bnxt+sizeof(temp)) > bend) return 0;
261  memcpy(&temp, *buff, sizeof(temp));
262  dlen = static_cast<int>(ntohs(temp));
263 
264 // Now grab the data
265 //
266  if (dlen) {*data = (char *)bnxt; bnxt += dlen;}
267  else *data = 0;
268  *buff = bnxt;
269  return (bnxt <= bend);
270 }
271 
272 /******************************************************************************/
273 
274 int XrdOucPup::Unpack(const char *buff, const char *bend,
275  XrdOucPupArgs *pup, char *base)
276 {
277  const char *bp = buff, *dp;
278  XrdOucPupArgs *uP = pup;
279  int dlen = 0, Dtype, Aok = 0, Done = 0;
280  union {unsigned long long b64;
281  unsigned int b32;
282  unsigned short b16;
283  unsigned char b08;} Temp;
284 
285  union {unsigned long long *B64;
286  unsigned int *B32;
287  unsigned short *B16;
288  char **B08;} Base;
289 
290 
291  while(!Done)
292  {Base.B08 = (char **)(base+uP->Doffs);
293  if (uP->Dtype & PT_MaskD)
294  {switch(uP->Dtype)
295  {case PT_Fence: Aok = 1; break;
296  case PT_Datlen: *Base.B32 = dlen; break;
297  case PT_End:
298  case PT_EndFill: Done = 1; uP--; break;
299  default: {}
300  }
301  uP++; continue;
302  }
303  if (bp+2 > bend)
304  {if (bp == bend && Aok) {Done = 1; uP--; break;}
305  return eMsg("buffer overrun unpacking", int(uP-pup), uP);
306  }
307  if (uP->Dtype == PT_char && !(*bp & PT_short))
308  {memcpy(&Temp.b16, bp, sizeof(unsigned short));
309  dlen = static_cast<int>(ntohs(Temp.b16));
310  bp += sizeof(unsigned short);
311  if (dlen)
312  if (bp+dlen > bend)
313  return eMsg("buffer overrun unpacking", int(uP-pup), uP);
314  else *Base.B08 = (char *)bp;
315  else if (!Aok) break;
316  else *Base.B08 = 0;
317  } else {
318  Dtype = static_cast<int>(*bp & PT_MaskT);
319  if ((unsigned char)Dtype != uP->Dtype)
320  return eMsg("arg/data mismatch unpacking", int(uP-pup), uP);
321  if (!(dlen = (*bp & PT_MaskB)>>3)) dlen = sizeof(unsigned short);
322  dp = (*bp & PT_Inline ? bp : bp+1);
323  if (dp+dlen > bend)
324  return eMsg("buffer overrun unpacking", int(uP-pup), uP);
325  memcpy(&Temp.b64, dp, dlen);
326  if (bp == dp) Temp.b08 &= PT_MaskD;
327  else bp++;
328  switch(Dtype)
329  {case PT_short: *Base.B16 = ntohs(Temp.b16); break;
330 
331  case PT_int: *Base.B32 = ntohl(Temp.b32); break;
332 
333  case PT_longlong: *Base.B64 = ntohll(Temp.b64); break;
334 
335  default: {}
336  }
337  }
338  uP++; bp += dlen;
339  };
340 
341 // Make sure we are not missing any items
342 //
343  if (Aok || uP->Dtype == PT_End || uP->Dtype == PT_EndFill)
344  return static_cast<int>(uP-pup);
345  return eMsg("missing arg unpacking", int(uP-pup), uP);
346 }
347 
348 /******************************************************************************/
349 /* e M s g */
350 /******************************************************************************/
351 
352 int XrdOucPup::eMsg(const char *etxt, int ino, XrdOucPupArgs *pup)
353 {
354  const char *dtn;
355  char buff[1024];
356 
357 // Check if we can print an error message
358 //
359  if (!eDest) return 0;
360 
361 // Get type name
362 //
363  switch(pup->Dtype)
364  {case PT_char: dtn = "char"; break;
365  case PT_short: dtn = "short"; break;
366  case PT_int: dtn = "int"; break;
367  case PT_longlong: dtn = "long long"; break;
368  case PT_special: dtn = "special"; break;
369  default: dtn = ""; break;
370  };
371 
372 // Format the message
373 //
374  sprintf(buff, "%s arg %d: %s.", dtn, ino,
375  (!Names||pup->Name >= Names->NLnum ? "?" : Names->NList[pup->Name]));
376 
377  eDest->Emsg("Pup", etxt, buff);
378  return 0;
379 }
unsigned char Name
Definition: XrdOucPup.hh:73
@ PT_Totlen
Definition: XrdOucPup.hh:52
@ PT_MandS
Definition: XrdOucPup.hh:49
@ PT_special
Definition: XrdOucPup.hh:61
@ PT_short
Definition: XrdOucPup.hh:58
@ PT_MaskD
Definition: XrdOucPup.hh:67
@ PT_Datlen
Definition: XrdOucPup.hh:51
@ PT_Fence
Definition: XrdOucPup.hh:50
@ PT_int
Definition: XrdOucPup.hh:59
@ PT_Mask
Definition: XrdOucPup.hh:66
@ PT_EndFill
Definition: XrdOucPup.hh:54
@ PT_MaskT
Definition: XrdOucPup.hh:65
@ PT_Skip
Definition: XrdOucPup.hh:48
@ PT_MaskB
Definition: XrdOucPup.hh:64
@ PT_Inline
Definition: XrdOucPup.hh:63
@ PT_char
Definition: XrdOucPup.hh:57
@ PT_longlong
Definition: XrdOucPup.hh:60
@ PT_Mark
Definition: XrdOucPup.hh:47
@ PT_Ignore
Definition: XrdOucPup.hh:46
@ PT_End
Definition: XrdOucPup.hh:53
unsigned char Dtype
Definition: XrdOucPup.hh:74
static const int MaxLen
Definition: XrdOucPup.hh:102
static int Unpack(char **buff, const char *bend, char **data, int &dlen)
Definition: XrdOucPup.cc:250
static int Pack(struct iovec **, const char *, unsigned short &buff)
Definition: XrdOucPup.cc:52
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95
const char ** NList
Definition: XrdOucPup.hh:78