XRootD
XrdOucUtils.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d O u c U t i l s . c c */
4 /* */
5 /* (c) 2005 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 <cctype>
32 #include <grp.h>
33 #include <cstdio>
34 #include <list>
35 #include <vector>
36 #include <unordered_set>
37 #include <algorithm>
38 
39 #ifdef WIN32
40 #include <direct.h>
41 #include "XrdSys/XrdWin32.hh"
42 #else
43 #include <fcntl.h>
44 #include <pwd.h>
45 #include <sys/stat.h>
46 #include <sys/types.h>
47 #endif
48 #include <map>
49 #include "XrdNet/XrdNetUtils.hh"
50 #include "XrdOuc/XrdOucCRC.hh"
51 #include "XrdOuc/XrdOucEnv.hh"
52 #include "XrdOuc/XrdOucSHA3.hh"
53 #include "XrdOuc/XrdOucStream.hh"
54 #include "XrdOuc/XrdOucString.hh"
55 #include "XrdOuc/XrdOucUtils.hh"
57 #include "XrdSys/XrdSysE2T.hh"
58 #include "XrdSys/XrdSysError.hh"
59 #include "XrdSys/XrdSysPlatform.hh"
60 #include "XrdSys/XrdSysPthread.hh"
61 
62 #ifndef ENODATA
63 #define ENODATA ENOATTR
64 #endif
65 
66 /******************************************************************************/
67 /* L o c a l M e t h o d s */
68 /******************************************************************************/
69 
70 namespace
71 {
72 struct idInfo
73 { time_t Expr;
74  char *Name;
75 
76  idInfo(const char *name, time_t keep)
77  : Expr(time(0)+keep), Name(strdup(name)) {}
78  ~idInfo() {free(Name);}
79 };
80 
81 typedef std::map<unsigned int, struct idInfo*> idMap_t;
82 
83 idMap_t gidMap;
84 idMap_t uidMap;
85 XrdSysMutex idMutex;
86 
87 void AddID(idMap_t &idMap, unsigned int id, const char *name, time_t keepT)
88 {
89  std::pair<idMap_t::iterator,bool> ret;
90  idInfo *infoP = new idInfo(name, keepT);
91 
92  idMutex.Lock();
93  ret = idMap.insert(std::pair<unsigned int, struct idInfo*>(id, infoP));
94  if (ret.second == false) delete infoP;
95  idMutex.UnLock();
96 }
97 
98 int LookUp(idMap_t &idMap, unsigned int id, char *buff, int blen)
99 {
100  idMap_t::iterator it;
101  int luRet = 0;
102 
103  idMutex.Lock();
104  it = idMap.find(id);
105  if (it != idMap.end())
106  {if (it->second->Expr <= time(0))
107  {delete it->second;
108  idMap.erase(it);
109  } else {
110  if (blen > 0) luRet = snprintf(buff, blen, "%s", it->second->Name);
111  }
112  }
113  idMutex.UnLock();
114  return luRet;
115 }
116 }
117 
118 static const std::string OBFUSCATION_STR = "REDACTED";
119 
120 // As the compilation of the regexes when the std::regex object is constructed is expensive,
121 // we initialize the auth obfuscation regexes only once in the XRootD process lifetime
122 
123 static const std::vector<std::regex> authObfuscationRegexes = {
124  //authz=xxx&... We deal with cases like "(message: kXR_stat (path: /tmp/xrootd/public/foo?pelican.timeout=3s&authz=foo1234, flags: none)" where we do not want to obfuscate
125  // ", flags: none)" + we deal with cases where the 'authz=Bearer token' when an admin could set 'http.header2cgi Authorization authz' in the server config
126  std::regex(R"((authz=)(Bearer\s)?([^ &\",<>#%{}|\^~\[\]`]*))",std::regex_constants::optimize),
127  // HTTP Authorization, TransferHeaderAuthorization headers that with the key that can be prefixed with spaces and value prefixed by spaces
128  std::regex(R"((\s*\w*Authorization\s*:\s*)[^$]*)", std::regex_constants::icase | std::regex_constants::optimize)
129 };
130 
131 /******************************************************************************/
132 /* a r g L i s t */
133 /******************************************************************************/
134 
135 int XrdOucUtils::argList(char *args, char **argV, int argC)
136 {
137  char *aP = args;
138  int j;
139 
140 // Construct the argv array based on passed command line.
141 //
142 for (j = 0; j < argC; j++)
143  {while(*aP == ' ') aP++;
144  if (!(*aP)) break;
145 
146  if (*aP == '"' || *aP == '\'')
147  {argV[j] = aP+1;
148  aP = index(aP+1, *aP);
149  if (!aP || (*(aP+1) != ' ' && *(aP+1)))
150  {if (!j) argV[0] = 0; return -EINVAL;}
151  *aP++ = '\0';
152  } else {
153  argV[j] = aP;
154  if ((aP = index(aP+1, ' '))) *aP++ = '\0';
155  else {j++; break;}
156  }
157 
158  }
159 
160 // Make sure we did not overflow the vector
161 //
162  if (j > argC-1) return -E2BIG;
163 
164 // End list with a null pointer and return the actual number of arguments
165 //
166  argV[j] = 0;
167  return j;
168 }
169 
170 /******************************************************************************/
171 /* b i n 2 h e x */
172 /******************************************************************************/
173 
174 char *XrdOucUtils::bin2hex(char *inbuff, int dlen, char *buff, int blen,
175  bool sep)
176 {
177  static char hv[] = "0123456789abcdef";
178  char *outbuff = buff;
179  for (int i = 0; i < dlen && blen > 2; i++) {
180  *outbuff++ = hv[(inbuff[i] >> 4) & 0x0f];
181  *outbuff++ = hv[ inbuff[i] & 0x0f];
182  blen -= 2;
183  if (sep && blen > 1 && ((i & 0x03) == 0x03 || i+1 == dlen))
184  {*outbuff++ = ' '; blen--;}
185  }
186  *outbuff = '\0';
187  return buff;
188 }
189 
190 /******************************************************************************/
191 /* e n d s W i t h */
192 /******************************************************************************/
193 
194 bool XrdOucUtils::endsWith(const char *text, const char *ending, int endlen)
195 {
196  int tlen = strlen(text);
197 
198  return (tlen >= endlen && !strcmp(text+(tlen-endlen), ending));
199 }
200 
201 /******************************************************************************/
202 /* e T e x t */
203 /******************************************************************************/
204 
205 // eText() returns the text associated with the error.
206 // The text buffer pointer is returned.
207 
208 char *XrdOucUtils::eText(int rc, char *eBuff, int eBlen)
209 {
210  const char *etP;
211 
212 // Get error text
213 //
214  etP = XrdSysE2T(rc);
215 
216 // Copy the text and lower case the first letter
217 //
218  strlcpy(eBuff, etP, eBlen);
219 
220 // All done
221 //
222  return eBuff;
223 }
224 
225 /******************************************************************************/
226 /* d o I f */
227 /******************************************************************************/
228 
229 // doIf() parses "if [<hostlist>] [<conds>]"
230 // conds: <cond1> | <cond2> | <cond3>
231 // cond1: defined <varlist> [&& <conds>]
232 // cond2: exec <pgmlist> [&& <cond3>]
233 // cond3: named <namelist>
234 
235 // Returning 1 if true (i.e., this machine is one of the named hosts in hostlist
236 // and is running one of the programs pgmlist and named by one of the names in
237 // namelist).
238 // Return -1 (negative truth) if an error occurred.
239 // Otherwise, returns false (0). Some combination of hostlist, pgm, and
240 // namelist, must be specified.
241 
243  const char *what, const char *hname,
244  const char *nname, const char *pname)
245 {
246  static const char *brk[] = {"defined", "exec", "named", 0};
247  XrdOucEnv *theEnv = 0;
248  char *val;
249  int hostok, isDef;
250 
251 // Make sure that at least one thing appears after the if
252 //
253  if (!(val = Config.GetWord()))
254  {if (eDest) eDest->Emsg("Config","Host name missing after 'if' in", what);
255  return -1;
256  }
257 
258 // Check if we are one of the listed hosts
259 //
260  if (!is1of(val, brk))
261  {do {hostok = XrdNetUtils::Match(hname, val);
262  val = Config.GetWord();
263  } while(!hostok && val && !is1of(val, brk));
264  if (hostok)
265  { while(val && !is1of(val, brk)) val = Config.GetWord();
266  // No more directives
267  if (!val) return 1;
268  } else return 0;
269  }
270 
271 // Check if this is a defined test
272 //
273  while(!strcmp(val, "defined"))
274  {if (!(val = Config.GetWord()) || *val != '?')
275  {if (eDest)
276  {eDest->Emsg("Config","'?var' missing after 'defined' in",what);}
277  return -1;
278  }
279  // Get environment if we have none
280  //
281  if (!theEnv && (theEnv = Config.SetEnv(0))) Config.SetEnv(theEnv);
282  if (!theEnv && *(val+1) != '~') return 0;
283 
284  // Check if any listed variable is defined.
285  //
286  isDef = 0;
287  while(val && *val == '?')
288  {if (*(val+1) == '~' ? getenv(val+2) : theEnv->Get(val+1)) isDef=1;
289  val = Config.GetWord();
290  }
291  if (!val || !isDef) return isDef;
292  if (strcmp(val, "&&"))
293  {if (eDest)
294  {eDest->Emsg("Config",val,"is invalid for defined test in",what);}
295  return -1;
296  } else {
297  if (!(val = Config.GetWord()))
298  {if (eDest)
299  {eDest->Emsg("Config","missing keyword after '&&' in",what);}
300  return -1;
301  }
302  }
303  if (!is1of(val, brk))
304  {if (eDest)
305  {eDest->Emsg("Config",val,"is invalid after '&&' in",what);}
306  return -1;
307  }
308  }
309 
310 // Check if we need to compare program names (we are here only if we either
311 // passed the hostlist test or there was no hostlist present)
312 //
313  if (!strcmp(val, "exec"))
314  {if (!(val = Config.GetWord()) || !strcmp(val, "&&"))
315  {if (eDest)
316  {eDest->Emsg("Config","Program name missing after 'if exec' in",what);}
317  return -1;
318  }
319 
320  // Check if we are one of the programs.
321  //
322  if (!pname) return 0;
323  while(val && strcmp(val, pname))
324  if (!strcmp(val, "&&")) return 0;
325  else val = Config.GetWord();
326  if (!val) return 0;
327  while(val && strcmp(val, "&&")) val = Config.GetWord();
328  if (!val) return 1;
329 
330  if (!(val = Config.GetWord()))
331  {if (eDest)
332  {eDest->Emsg("Config","Keyword missing after '&&' in",what);}
333  return -1;
334  }
335  if (strcmp(val, "named"))
336  {if (eDest)
337  {eDest->Emsg("Config",val,"is invalid after '&&' in",what);}
338  return -1;
339  }
340  }
341 
342 // Check if we need to compare net names (we are here only if we either
343 // passed the hostlist test or there was no hostlist present)
344 //
345  if (!(val = Config.GetWord()))
346  {if (eDest)
347  {eDest->Emsg("Config","Instance name missing after 'if named' in", what);}
348  return -1;
349  }
350 
351 // Check if we are one of the names
352 //
353  if (!nname) return 0;
354  while(val && strcmp(val, nname)) val = Config.GetWord();
355 
356 // All done
357 //
358  return (val != 0);
359 }
360 
361 /******************************************************************************/
362 /* f i n d P g m */
363 /******************************************************************************/
364 
365 bool XrdOucUtils::findPgm(const char *pgm, XrdOucString& path)
366 {
367  struct stat Stat;
368 
369 // Check if only executable bit needs to be checked
370 //
371  if (*pgm == '/')
372  {if (stat(pgm, &Stat) || !(Stat.st_mode & S_IXOTH)) return false;
373  path = pgm;
374  return true;
375  }
376 
377 // Make sure we have the paths to check
378 //
379  const char *pEnv = getenv("PATH");
380  if (!pEnv) return false;
381 
382 // Setup to find th executable
383 //
384  XrdOucString prog, pList(pEnv);
385  int from = 0;;
386  prog += '/'; prog += pgm;
387 
388 // Find it!
389 //
390  while((from = pList.tokenize(path, from, ':')) != -1)
391  {path += prog;
392  if (!stat(path.c_str(), &Stat) && Stat.st_mode & S_IXOTH) return true;
393  }
394  return false;
395 }
396 
397 /******************************************************************************/
398 /* f m t B y t e s */
399 /******************************************************************************/
400 
401 int XrdOucUtils::fmtBytes(long long val, char *buff, int bsz)
402 {
403  static const long long Kval = 1024LL;
404  static const long long Mval = 1024LL*1024LL;
405  static const long long Gval = 1024LL*1024LL*1024LL;
406  static const long long Tval = 1024LL*1024LL*1024LL*1024LL;
407  char sName = ' ';
408  int resid;
409 
410 // Get correct scaling
411 //
412  if (val < 1024) return snprintf(buff, bsz, "%lld", val);
413  if (val < Mval) {val = val*10/Kval; sName = 'K';}
414  else if (val < Gval) {val = val*10/Mval; sName = 'M';}
415  else if (val < Tval) {val = val*10/Gval; sName = 'G';}
416  else {val = val*10/Tval; sName = 'T';}
417  resid = val%10LL; val = val/10LL;
418 
419 // Format it
420 //
421  return snprintf(buff, bsz, "%lld.%d%c", val, resid, sName);
422 }
423 
424 /******************************************************************************/
425 /* g e n P a t h */
426 /******************************************************************************/
427 
428 char *XrdOucUtils::genPath(const char *p_path, const char *inst,
429  const char *s_path)
430 {
431  char buff[2048];
432  int i = strlcpy(buff, p_path, sizeof(buff));
433 
434  if (buff[i-1] != '/') {buff[i++] = '/'; buff[i] = '\0';}
435  if (inst) {strcpy(buff+i, inst); strcat(buff, "/");}
436  if (s_path) strcat(buff, s_path);
437 
438  i = strlen(buff);
439  if (buff[i-1] != '/') {buff[i++] = '/'; buff[i] = '\0';}
440 
441  return strdup(buff);
442 }
443 
444 /******************************************************************************/
445 
446 int XrdOucUtils::genPath(char *buff, int blen, const char *path, const char *psfx)
447 {
448  int i, j;
449 
450  i = strlen(path);
451  j = (psfx ? strlen(psfx) : 0);
452  if (i+j+3 > blen) return -ENAMETOOLONG;
453 
454  strcpy(buff, path);
455  if (psfx)
456  {if (buff[i-1] != '/') buff[i++] = '/';
457  strcpy(&buff[i], psfx);
458  if (psfx[j-1] != '/') strcat(buff, "/");
459  }
460  return 0;
461 }
462 
463 /******************************************************************************/
464 /* g e t F i l e */
465 /******************************************************************************/
466 
467 char *XrdOucUtils::getFile(const char *path, int &rc, int maxsz, bool notempty)
468 {
469  struct stat Stat;
470  struct fdHelper
471  {int fd = -1;
472  fdHelper() {}
473  ~fdHelper() {if (fd >= 0) close(fd);}
474  } file;
475  char *buff;
476  int flen;
477 
478 // Preset RC
479 //
480  rc = 0;
481 
482 // Open the file in read mode
483 //
484  if ((file.fd = open(path, O_RDONLY)) < 0) {rc = errno; return 0;}
485 
486 // Get the size of the file
487 //
488  if (fstat(file.fd, &Stat)) {rc = errno; return 0;}
489 
490 // Check if the size exceeds the maximum allowed
491 //
492  if (Stat.st_size > maxsz) {rc = EFBIG; return 0;}
493 
494 // Make sure the file is not empty if empty files are disallowed
495 //
496  if (Stat.st_size == 0 && notempty) {rc = ENODATA; return 0;}
497 
498 // Allocate a buffer
499 //
500  if ((buff = (char *)malloc(Stat.st_size+1)) == 0)
501  {rc = errno; return 0;}
502 
503 // Read the contents of the file into the buffer
504 //
505  if (Stat.st_size)
506  {if ((flen = read(file.fd, buff, Stat.st_size)) < 0)
507  {rc = errno; free(buff); return 0;}
508  } else flen = 0;
509 
510 // Add null byte. recall the buffer is bigger by one byte
511 //
512  buff[flen] = 0;
513 
514 // Return the size aand the buffer
515 //
516  rc = flen;
517  return buff;
518 }
519 
520 /******************************************************************************/
521 /* g e t G I D */
522 /******************************************************************************/
523 
524 bool XrdOucUtils::getGID(const char *gName, gid_t &gID)
525 {
526  struct group Grp, *result;
527  char buff[65536];
528 
529  getgrnam_r(gName, &Grp, buff, sizeof(buff), &result);
530  if (!result) return false;
531 
532  gID = Grp.gr_gid;
533  return true;
534 }
535 
536 /******************************************************************************/
537 /* g e t U I D */
538 /******************************************************************************/
539 
540 bool XrdOucUtils::getUID(const char *uName, uid_t &uID, gid_t *gID)
541 {
542  struct passwd pwd, *result;
543  char buff[16384];
544 
545  getpwnam_r(uName, &pwd, buff, sizeof(buff), &result);
546  if (!result) return false;
547 
548  uID = pwd.pw_uid;
549  if (gID) *gID = pwd.pw_gid;
550 
551  return true;
552 }
553 
554 /******************************************************************************/
555 /* G i d N a m e */
556 /******************************************************************************/
557 
558 int XrdOucUtils::GidName(gid_t gID, char *gName, int gNsz, time_t keepT)
559 {
560  static const int maxgBsz = 256*1024;
561  static const int addGsz = 4096;
562  struct group *gEnt, gStruct;
563  char gBuff[1024], *gBp = gBuff;
564  int glen = 0, gBsz = sizeof(gBuff), aOK = 1;
565  int n, retVal = 0;
566 
567 // Get ID from cache, if allowed
568 //
569  if (keepT)
570  {int n = LookUp(gidMap, static_cast<unsigned int>(gID),gName,gNsz);
571  if (n > 0) return (n < gNsz ? n : 0);
572  }
573 
574 // Get the the group struct. If we don't have a large enough buffer, get a
575 // larger one and try again up to the maximum buffer we will tolerate.
576 //
577  while(( retVal = getgrgid_r(gID, &gStruct, gBp, gBsz, &gEnt) ) == ERANGE)
578  {if (gBsz >= maxgBsz) {aOK = 0; break;}
579  if (gBsz > addGsz) free(gBp);
580  gBsz += addGsz;
581  if (!(gBp = (char *)malloc(gBsz))) {aOK = 0; break;}
582  }
583 
584 // Return a group name if all went well
585 //
586  if (aOK && retVal == 0 && gEnt != NULL)
587  {if (keepT)
588  AddID(gidMap, static_cast<unsigned int>(gID), gEnt->gr_name, keepT);
589  glen = strlen(gEnt->gr_name);
590  if (glen >= gNsz) glen = 0;
591  else strcpy(gName, gEnt->gr_name);
592  } else {
593  n = snprintf(gName, gNsz, "%ud", static_cast<unsigned int>(gID));
594  if (n >= gNsz) glen = 0;
595  }
596 
597 // Free any allocated buffer and return result
598 //
599  if (gBsz > addGsz && gBp) free(gBp);
600  return glen;
601 }
602 
603 /******************************************************************************/
604 /* G r o u p N a m e */
605 /******************************************************************************/
606 
607 int XrdOucUtils::GroupName(gid_t gID, char *gName, int gNsz)
608 {
609  static const int maxgBsz = 256*1024;
610  static const int addGsz = 4096;
611  struct group *gEnt, gStruct;
612  char gBuff[1024], *gBp = gBuff;
613  int glen, gBsz = sizeof(gBuff), aOK = 1;
614  int retVal = 0;
615 
616 // Get the the group struct. If we don't have a large enough buffer, get a
617 // larger one and try again up to the maximum buffer we will tolerate.
618 //
619  while(( retVal = getgrgid_r(gID, &gStruct, gBp, gBsz, &gEnt) ) == ERANGE)
620  {if (gBsz >= maxgBsz) {aOK = 0; break;}
621  if (gBsz > addGsz) free(gBp);
622  gBsz += addGsz;
623  if (!(gBp = (char *)malloc(gBsz))) {aOK = 0; break;}
624  }
625 
626 // Return a group name if all went well
627 //
628  if (aOK && retVal == 0 && gEnt != NULL)
629  {glen = strlen(gEnt->gr_name);
630  if (glen >= gNsz) glen = 0;
631  else strcpy(gName, gEnt->gr_name);
632  } else glen = 0;
633 
634 // Free any allocated buffer and return result
635 //
636  if (gBsz > addGsz && gBp) free(gBp);
637  return glen;
638 }
639 
640 /******************************************************************************/
641 /* i 2 b s t r */
642 /******************************************************************************/
643 
644 const char *XrdOucUtils::i2bstr(char *buff, int blen, int val, bool pad)
645 {
646  char zo[2] = {'0', '1'};
647 
648  if (blen < 2) return "";
649 
650  buff[--blen] = 0;
651  if (!val) buff[blen--] = '0';
652  else while(val && blen >= 0)
653  {buff[blen--] = zo[val & 0x01];
654  val >>= 1;
655  }
656 
657  if (blen >= 0 && pad) while(blen >= 0) buff[blen--] = '0';
658 
659  return &buff[blen+1];
660 }
661 
662 /******************************************************************************/
663 /* I d e n t */
664 /******************************************************************************/
665 
666 namespace
667 {
668 long long genSID(char *&urSID, const char *iHost, int iPort,
669  const char *iName, const char *iProg)
670 {
671  static const XrdOucSHA3::MDLen mdLen = XrdOucSHA3::SHA3_512;
672  static const uint32_t fpOffs = 2, fpSize = 6; // 48 bit finger print
673 
674  const char *iSite = getenv("XRDSITE");
675  unsigned char mDigest[mdLen];
676  XrdOucString myID;
677  union {uint64_t mdLL; unsigned char mdUC[8];}; // Works for fpSize only!
678 
679 // Construct our unique identification
680 //
681  if (iSite) myID = iSite;
682  myID += iHost;
683  myID += iPort;
684  if (iName) myID += iName;
685  myID += iProg;
686 
687 // Generate a SHA3 digest of this string.
688 //
689  memset(mDigest, 0, sizeof(mDigest));
690  XrdOucSHA3::Calc(myID.c_str(), myID.length(), mDigest, mdLen);
691 
692 // Generate a CRC32C of the same string
693 //
694  uint32_t crc32c = XrdOucCRC::Calc32C(myID.c_str(), myID.length());
695 
696 // We need a 48-bit fingerprint that has a very low probability of collision.
697 // We accomplish this by convoluting the CRC32C checksum with the SHA3 checksum.
698 //
699  uint64_t fpPos = crc32c % (((uint32_t)mdLen) - fpSize);
700  mdLL = 0;
701  memcpy(mdUC+fpOffs, mDigest+fpPos, fpSize);
702  long long fpVal = static_cast<long long>(ntohll(mdLL));
703 
704 // Generate the character version of our fingerprint and return the binary one.
705 //
706  char fpBuff[64];
707  snprintf(fpBuff, sizeof(fpBuff), "%lld", fpVal);
708  urSID = strdup(fpBuff);
709  return fpVal;
710 }
711 }
712 
713 char *XrdOucUtils::Ident(long long &mySID, char *iBuff, int iBlen,
714  const char *iHost, const char *iProg,
715  const char *iName, int iPort)
716 {
717  static char *theSIN;
718  static long long theSID = genSID(theSIN, iHost, iPort, iName, iProg);
719  const char *sP = getenv("XRDSITE");
720  char uName[256];
721  int myPid = static_cast<int>(getpid());
722 
723 // Get our username
724 //
725  if (UserName(getuid(), uName, sizeof(uName)))
726  sprintf(uName, "%d", static_cast<int>(getuid()));
727 
728 // Create identification record
729 //
730  snprintf(iBuff,iBlen,"%s.%d:%s@%s\n&site=%s&port=%d&inst=%s&pgm=%s",
731  uName, myPid, theSIN, iHost, (sP ? sP : ""), iPort, iName, iProg);
732 
733 // Return a copy of the sid key
734 //
735  h2nll(theSID, mySID);
736  return strdup(theSIN);
737 }
738 
739 /******************************************************************************/
740 /* I n s t N a m e */
741 /******************************************************************************/
742 
743 const char *XrdOucUtils::InstName(int TranOpt)
744 {
745  const char *iName = getenv("XRDNAME");
746 
747 // If tran is zero, return what we have
748 //
749  if (!TranOpt) return iName;
750 
751 // If trans is positive then make sure iName has a value. Otherwise, make sure
752 // iName has no value if it's actually "anon".
753 //
754  if (TranOpt > 0) {if (!iName || !*iName) iName = "anon";}
755  else if (iName && !strcmp(iName, "anon")) iName = 0;
756  return iName;
757 }
758 /******************************************************************************/
759 
760 const char *XrdOucUtils::InstName(const char *name, int Fillit)
761 { return (Fillit ? name && *name ? name : "anon"
762  : name && strcmp(name,"anon") && *name ? name : 0);
763 }
764 
765 /******************************************************************************/
766 /* i s 1 o f */
767 /******************************************************************************/
768 
769 int XrdOucUtils::is1of(char *val, const char **clist)
770 {
771  int i = 0;
772  while(clist[i]) if (!strcmp(val, clist[i])) return 1;
773  else i++;
774  return 0;
775 }
776 
777 /******************************************************************************/
778 /* i s F W D */
779 /******************************************************************************/
780 
781 int XrdOucUtils::isFWD(const char *path, int *port, char *hBuff, int hBLen,
782  bool pTrim)
783 {
784  const char *hName, *hNend, *hPort, *hPend, *hP = path;
785  char *eP;
786  int n;
787 
788  if (*path == '/') hP++; // Note: It's assumed an objectid if no slash
789  if (*hP == 'x') hP++;
790  if (strncmp("root:/", hP, 6)) return 0;
791  if (hBuff == 0 || hBLen <= 0) return (hP - path) + 6;
792  hP += 6;
793 
794  if (!XrdNetUtils::Parse(hP, &hName, &hNend, &hPort, &hPend)) return 0;
795  if (*hNend == ']') hNend++;
796  else {if (!(*hNend) && !(hNend = index(hName, '/'))) return 0;
797  if (!(*hPend)) hPend = hNend;
798  }
799 
800  if (pTrim || !(*hPort)) n = hNend - hP;
801  else n = hPend - hP;
802  if (n >= hBLen) return 0;
803  strncpy(hBuff, hP, n);
804  hBuff[n] = 0;
805 
806  if (port)
807  {if (*hNend != ':') *port = 0;
808  else {*port = strtol(hPort, &eP, 10);
809  if (*port < 0 || *port > 65535 || eP != hPend) return 0;
810  }
811  }
812 
813  return hPend-path;
814 }
815 
816 /******************************************************************************/
817 /* L o g 2 */
818 /******************************************************************************/
819 
820 // Based on an algorithm produced by Todd Lehman. However, this one returns 0
821 // when passed 0 (which is invalid). The caller must check the validity of
822 // the input prior to calling Log2(). Essentially, the algorithm subtracts
823 // away progressively smaller squares in the sequence
824 // { 0 <= k <= 5: 2^(2^k) } = { 2**32, 2**16, 2**8 2**4 2**2, 2**1 } =
825 // = { 4294967296, 65536, 256, 16, 4, 2 }
826 // and sums the exponents k of the subtracted values. It is generally the
827 // fastest way to compute log2 for a wide range of possible input values.
828 
829 int XrdOucUtils::Log2(unsigned long long n)
830 {
831  int i = 0;
832 
833  #define SHFT(k) if (n >= (1ULL << k)) { i += k; n >>= k; }
834 
835  SHFT(32); SHFT(16); SHFT(8); SHFT(4); SHFT(2); SHFT(1); return i;
836 
837  #undef SHFT
838 }
839 
840 /******************************************************************************/
841 /* L o g 1 0 */
842 /******************************************************************************/
843 
844 int XrdOucUtils::Log10(unsigned long long n)
845 {
846  int i = 0;
847 
848  #define SHFT(k, m) if (n >= m) { i += k; n /= m; }
849 
850  SHFT(16,10000000000000000ULL); SHFT(8,100000000ULL);
851  SHFT(4,10000ULL); SHFT(2,100ULL); SHFT(1,10ULL);
852  return i;
853 
854  #undef SHFT
855 }
856 
857 /******************************************************************************/
858 /* m a k e H o m e */
859 /******************************************************************************/
860 
861 void XrdOucUtils::makeHome(XrdSysError &eDest, const char *inst)
862 {
863  char buff[2048];
864 
865  if (!inst || !getcwd(buff, sizeof(buff))) return;
866 
867  strcat(buff, "/"); strcat(buff, inst);
868  if (MAKEDIR(buff, pathMode) && errno != EEXIST)
869  {eDest.Emsg("Config", errno, "create home directory", buff);
870  return;
871  }
872 
873  if (chdir(buff) < 0)
874  eDest.Emsg("Config", errno, "chdir to home directory", buff);
875 }
876 
877 /******************************************************************************/
878 
879 bool XrdOucUtils::makeHome(XrdSysError &eDest, const char *inst,
880  const char *path, mode_t mode)
881 {
882  char cwDir[2048];
883  const char *slash = "", *slash2 = "";
884  int n, rc;
885 
886 // Provide backward compatibility for instance name qualification
887 //
888 
889  if (!path || !(n = strlen(path)))
890  {if (inst) makeHome(eDest, inst);
891  return true;
892  }
893 
894 // Augment the path with instance name, if need be
895 //
896  if (path[n-1] != '/') slash = "/";
897  if (!inst || !(n = strlen(inst))) inst = "";
898  else slash2 = "/";
899  n = snprintf(cwDir, sizeof(cwDir), "%s%s%s%s", path, slash, inst, slash2);
900  if (n >= (int)sizeof(cwDir))
901  {eDest.Emsg("Config", ENAMETOOLONG, "create home directory", cwDir);
902  return false;
903  }
904 
905 // Create the path if it doesn't exist
906 //
907  if ((rc = makePath(cwDir, mode, true)))
908  {eDest.Emsg("Config", rc, "create home directory", cwDir);
909  return false;
910  }
911 
912 // Switch to this directory
913 //
914  if (chdir(cwDir) < 0)
915  {eDest.Emsg("Config", errno, "chdir to home directory", cwDir);
916  return false;
917  }
918 
919 // All done
920 //
921  return true;
922 }
923 
924 /******************************************************************************/
925 /* m a k e P a t h */
926 /******************************************************************************/
927 
928 int XrdOucUtils::makePath(char *path, mode_t mode, bool reset)
929 {
930  char *next_path = path+1;
931  struct stat buf;
932  bool dochmod = false; // The 1st component stays as is
933 
934 // Typically, the path exists. So, do a quick check before launching into it
935 //
936  if (!reset && !stat(path, &buf)) return 0;
937 
938 // Start creating directories starting with the root
939 //
940  while((next_path = index(next_path, int('/'))))
941  {*next_path = '\0';
942  if (MAKEDIR(path, mode))
943  if (errno != EEXIST) return -errno;
944  if (dochmod) CHMOD(path, mode);
945  dochmod = reset;
946  *next_path = '/';
947  next_path = next_path+1;
948  }
949 
950 // All done
951 //
952  return 0;
953 }
954 
955 /******************************************************************************/
956 /* m o d e 2 m a s k */
957 /******************************************************************************/
958 
959 bool XrdOucUtils::mode2mask(const char *mode, mode_t &mask)
960 {
961  mode_t mval[3] = {0}, mbit[3] = {0x04, 0x02, 0x01};
962  const char *mok = "rwx";
963  char mlet;
964 
965 // Accept octal mode
966 //
967  if (isdigit(*mode))
968  {char *eP;
969  mask = strtol(mode, &eP, 8);
970  return *eP == 0;
971  }
972 
973 // Make sure we have the correct number of characters
974 //
975  int n = strlen(mode);
976  if (!n || n > 9 || n/3*3 != n) return false;
977 
978 // Convert groups of three
979 //
980  int k = 0;
981  do {for (int i = 0; i < 3; i++)
982  {mlet = *mode++;
983  if (mlet != '-')
984  {if (mlet != mok[i]) return false;
985  mval[k] |= mbit[i];
986  }
987  }
988  } while(++k < 3 && *mode);
989 
990 // Combine the modes and return success
991 //
992  mask = mval[0]<<6 | mval[1]<<3 | mval[2];
993  return true;
994 }
995 
996 /******************************************************************************/
997 /* p a r s e L i b */
998 /******************************************************************************/
999 
1001  const char *libName, char *&libPath, char **libParm)
1002 {
1003  char *val, parms[2048];
1004 
1005 // Get the next token
1006 //
1007  val = Config.GetWord();
1008 
1009 // We do not support stacking as the caller does not support stacking
1010 //
1011  if (val && !strcmp("++", val))
1012  {eDest.Say("Config warning: stacked plugins are not supported in "
1013  "this context; directive ignored!");
1014  return true;
1015  }
1016 
1017 // Now skip over any options
1018 //
1019  while(val && *val && *val == '+') val = Config.GetWord();
1020 
1021 // Check if we actually have a path
1022 //
1023  if (!val || !val[0])
1024  {eDest.Emsg("Config", libName, "not specified"); return false;}
1025 
1026 // Record the path
1027 //
1028  if (libPath) free(libPath);
1029  libPath = strdup(val);
1030 
1031 // Handle optional parameter
1032 //
1033  if (!libParm) return true;
1034  if (*libParm) free(*libParm);
1035  *libParm = 0;
1036 
1037 // Record any parms
1038 //
1039  *parms = 0;
1040  if (!Config.GetRest(parms, sizeof(parms)))
1041  {eDest.Emsg("Config", libName, "parameters too long"); return false;}
1042  if (*parms) *libParm = strdup(parms);
1043  return true;
1044 }
1045 
1046 /******************************************************************************/
1047 /* p a r s e H o m e */
1048 /******************************************************************************/
1049 
1051 {
1052  char *pval, *val, *HomePath = 0;
1053 
1054 // Get the path
1055 //
1056  pval = Config.GetWord();
1057  if (!pval || !pval[0])
1058  {eDest.Emsg("Config", "home path not specified"); return 0;}
1059 
1060 // Make sure it's an absolute path
1061 //
1062  if (*pval != '/')
1063  {eDest.Emsg("Config", "home path not absolute"); return 0;}
1064 
1065 // Record the path
1066 //
1067  HomePath = strdup(pval);
1068 
1069 // Get the optional access rights
1070 //
1071  mode = S_IRWXU;
1072  if ((val = Config.GetWord()) && val[0])
1073  {if (!strcmp("group", val)) mode |= (S_IRGRP | S_IXGRP);
1074  else {eDest.Emsg("Config", "invalid home path modifier -", val);
1075  free(HomePath);
1076  return 0;
1077  }
1078  }
1079  return HomePath;
1080 }
1081 
1082 /******************************************************************************/
1083 /* R e L i n k */
1084 /******************************************************************************/
1085 
1086 int XrdOucUtils::ReLink(const char *path, const char *target, mode_t mode)
1087 {
1088  const mode_t AMode = S_IRWXU; // Only us as a default
1089  char pbuff[MAXPATHLEN+64];
1090  int n;
1091 
1092 // Copy the path
1093 //
1094  n = strlen(path);
1095  if (n >= (int)sizeof(pbuff)) return ENAMETOOLONG;
1096  strcpy(pbuff, path);
1097 
1098 // Unlink the target, make the path, and create the symlink
1099 //
1100  unlink(path);
1101  makePath(pbuff, (mode ? mode : AMode));
1102  if (symlink(target, path)) return errno;
1103  return 0;
1104 }
1105 
1106 /******************************************************************************/
1107 /* S a n i t i z e */
1108 /******************************************************************************/
1109 
1110 void XrdOucUtils::Sanitize(char *str, char subc)
1111 {
1112 
1113 // Sanitize string according to POSIX.1-2008 stanadard using only the
1114 // Portable Filename Character Set: a-z A-Z 0-9 ._- with 1st char not being -
1115 //
1116  if (*str)
1117  {if (*str == '-') *str = subc;
1118  else if (*str == ' ') *str = subc;
1119  char *blank = rindex(str, ' ');
1120  if (blank) while(*blank == ' ') *blank-- = 0;
1121  while(*str)
1122  {if (!isalnum(*str) && index("_-.", *str) == 0) *str = subc;
1123  str++;
1124  }
1125  }
1126 }
1127 
1128 /******************************************************************************/
1129 /* s u b L o g f n */
1130 /******************************************************************************/
1131 
1132 char *XrdOucUtils::subLogfn(XrdSysError &eDest, const char *inst, char *logfn)
1133 {
1134  const mode_t lfm = S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH;
1135  char buff[2048], *sp;
1136  int rc;
1137 
1138  if (!inst || !*inst) return logfn;
1139  if (!(sp = rindex(logfn, '/'))) strcpy(buff, "./");
1140  else {*sp = '\0'; strcpy(buff, logfn); strcat(buff, "/");}
1141 
1142  strcat(buff, inst); strcat(buff, "/");
1143 
1144  if ((rc = XrdOucUtils::makePath(buff, lfm)))
1145  {eDest.Emsg("Config", rc, "create log file path", buff);
1146  return 0;
1147  }
1148 
1149  if (sp) {*sp = '/'; strcat(buff, sp+1);}
1150  else strcat(buff, logfn);
1151 
1152  free(logfn);
1153  return strdup(buff);
1154 }
1155 
1156 /******************************************************************************/
1157 /* t o L o w e r */
1158 /******************************************************************************/
1159 
1160 void XrdOucUtils::toLower(char *str)
1161 {
1162  unsigned char* ustr = (unsigned char*)str; // Avoid undefined behaviour
1163 
1164 // Change each character to lower case
1165 //
1166  while(*ustr) {*ustr = tolower(*ustr); ustr++;}
1167 }
1168 
1169 /******************************************************************************/
1170 /* T o k e n */
1171 /******************************************************************************/
1172 
1173 int XrdOucUtils::Token(const char **str, char delim, char *buff, int bsz)
1174 {
1175  const char *eP, *bP = *str;
1176  int aLen, mLen;
1177 
1178 // Trim off the delimeters. Return zero if nothing left.
1179 //
1180  while(*bP && *bP == delim) bP++;
1181  if (*bP == 0) {*buff = 0; return 0;}
1182 
1183 // Find the next delimiter
1184 //
1185  eP = bP;
1186  while(*eP && *eP != delim) eP++;
1187 
1188 // If we ended at a null, make sure next call will return zero
1189 //
1190  if (*eP == 0) *str = eP;
1191  else *str = eP+1;
1192 
1193 // Calculate length and make sure we don't overrun the buffer
1194 //
1195  aLen = eP-bP;
1196  if (aLen >= bsz) mLen = bsz-1;
1197  else mLen = aLen;
1198 
1199 // Copy token into buffer and end with null byte
1200 //
1201  strncpy(buff, bP, mLen);
1202  buff[mLen] = 0;
1203 
1204 // Return actual length
1205 //
1206  return aLen;
1207 }
1208 
1209 /******************************************************************************/
1210 /* U n d e r c o v e r */
1211 /******************************************************************************/
1212 #ifdef WIN32
1213 void XrdOucUtils::Undercover(XrdSysError &, int, int *)
1214 {
1215 }
1216 #else
1217 void XrdOucUtils::Undercover(XrdSysError &eDest, int noLog, int *pipeFD)
1218 {
1219  static const int maxFiles = 256;
1220  pid_t mypid;
1221  int myfd, logFD = eDest.baseFD();
1222 
1223 // Issue warning if there is no logfile attached
1224 //
1225  if (noLog) eDest.Emsg("Config", "Warning! No log file specified; "
1226  "backgrounding disables all logging!");
1227 
1228 // Fork so that we are not tied to a shell
1229 //
1230  if ((mypid = fork()) < 0)
1231  {eDest.Emsg("Config", errno, "fork process 1 for backgrounding");
1232  return;
1233  }
1234  else if (mypid)
1235  {
1236  // we have been given a pair of pipe descriptors to be able to read the
1237  // status of the child process
1238  if( pipeFD )
1239  {
1240  int status = 1;
1241  close( pipeFD[1] );
1242  // read will wait untill the status is communicated by the
1243  // child process, if the child process dies before being able
1244  // to comunicate the status then read will see EOF
1245  if( read( pipeFD[0], &status, sizeof(status) ) != sizeof(status) )
1246  _exit(1);
1247  _exit(status);
1248  }
1249  // no pipes given, return success
1250  else _exit(0);
1251  }
1252 
1253  if( pipeFD )
1254  close( pipeFD[0] );
1255 
1256 // Become the process group leader
1257 //
1258  if (setsid() < 0)
1259  {eDest.Emsg("Config", errno, "doing setsid() for backgrounding");
1260  return;
1261  }
1262 
1263 // Fork to that we are cannot get a controlling terminal
1264 //
1265  if ((mypid = fork()) < 0)
1266  {eDest.Emsg("Config", errno, "fork process 2 for backgrounding");
1267  return;
1268  }
1269  else if (mypid) _exit(0);
1270 
1271 // Switch stdin, stdout, and stderr to /dev/null (we can't use /dev/console
1272 // unless we are root which is unlikely).
1273 //
1274  if ((myfd = open("/dev/null", O_RDWR)) < 0)
1275  {eDest.Emsg("Config", errno, "open /dev/null for backgrounding");
1276  return;
1277  }
1278  dup2(myfd, 0); dup2(myfd, 1); dup2(myfd, 2); dup2(myfd, logFD);
1279 
1280 // Close any open file descriptors left open by the parent process
1281 // but the communication pipe and the logger's shadow file descriptor.
1282 //
1283  for (myfd = 3; myfd < maxFiles; myfd++)
1284  if( (!pipeFD || myfd != pipeFD[1]) && myfd != logFD ) close(myfd);
1285 }
1286 
1287 /******************************************************************************/
1288 /* U i d N a m e */
1289 /******************************************************************************/
1290 
1291 int XrdOucUtils::UidName(uid_t uID, char *uName, int uNsz, time_t keepT)
1292 {
1293  struct passwd *pEnt, pStruct;
1294  char pBuff[1024];
1295  int n, rc;
1296 
1297 // Get ID from cache, if allowed
1298 //
1299  if (keepT)
1300  {int n = LookUp(uidMap, static_cast<unsigned int>(uID),uName,uNsz);
1301  if (n > 0) return (n < uNsz ? n : 0);
1302  }
1303 
1304 // Try to obtain the username. We use this form to make sure we are using
1305 // the standards conforming version (compilation error otherwise).
1306 //
1307  rc = getpwuid_r(uID, &pStruct, pBuff, sizeof(pBuff), &pEnt);
1308  if (rc || !pEnt)
1309  {n = snprintf(uName, uNsz, "%ud", static_cast<unsigned int>(uID));
1310  return (n >= uNsz ? 0 : n);
1311  }
1312 
1313 // Add entry to the cache if need be
1314 //
1315  if (keepT)
1316  AddID(uidMap, static_cast<unsigned int>(uID), pEnt->pw_name, keepT);
1317 
1318 // Return length of username or zero if it is too big
1319 //
1320  n = strlen(pEnt->pw_name);
1321  if (uNsz <= (int)strlen(pEnt->pw_name)) return 0;
1322  strcpy(uName, pEnt->pw_name);
1323  return n;
1324 }
1325 
1326 /******************************************************************************/
1327 /* U s e r N a m e */
1328 /******************************************************************************/
1329 
1330 int XrdOucUtils::UserName(uid_t uID, char *uName, int uNsz)
1331 {
1332  struct passwd *pEnt, pStruct;
1333  char pBuff[1024];
1334  int rc;
1335 
1336 // Try to obtain the username. We use this form to make sure we are using
1337 // the standards conforming version (compilation error otherwise).
1338 //
1339  rc = getpwuid_r(uID, &pStruct, pBuff, sizeof(pBuff), &pEnt);
1340  if (rc) return rc;
1341  if (!pEnt) return ESRCH;
1342 
1343 // Return length of username or zero if it is too big
1344 //
1345  if (uNsz <= (int)strlen(pEnt->pw_name)) return ENAMETOOLONG;
1346  strcpy(uName, pEnt->pw_name);
1347  return 0;
1348 }
1349 
1350 /******************************************************************************/
1351 /* V a l P a t h */
1352 /******************************************************************************/
1353 
1354 const char *XrdOucUtils::ValPath(const char *path, mode_t allow, bool isdir)
1355 {
1356  static const mode_t mMask = S_IRWXU | S_IRWXG | S_IRWXO;
1357  struct stat buf;
1358 
1359 // Check if this really exists
1360 //
1361  if (stat(path, &buf))
1362  {if (errno == ENOENT) return "does not exist.";
1363  return XrdSysE2T(errno);
1364  }
1365 
1366 // Verify that this is the correct type of file
1367 //
1368  if (isdir)
1369  {if (!S_ISDIR(buf.st_mode)) return "is not a directory.";
1370  } else {
1371  if (!S_ISREG(buf.st_mode)) return "is not a file.";
1372  }
1373 
1374 // Verify that the does not have excessive privileges
1375 //
1376  if ((buf.st_mode & mMask) & ~allow) return "has excessive access rights.";
1377 
1378 // All went well
1379 //
1380  return 0;
1381 }
1382 
1383 /******************************************************************************/
1384 /* P i d F i l e */
1385 /******************************************************************************/
1386 
1387 bool XrdOucUtils::PidFile(XrdSysError &eDest, const char *path)
1388 {
1389  char buff[32];
1390  int fd;
1391 
1392  if( (fd = open( path, O_WRONLY|O_CREAT|O_TRUNC, 0644 )) < 0 )
1393  {
1394  eDest.Emsg( "Config", errno, "create pidfile" );
1395  return false;
1396  }
1397 
1398  if( write( fd, buff, snprintf( buff, sizeof(buff), "%d",
1399  static_cast<int>(getpid()) ) ) < 0 )
1400  {
1401  eDest.Emsg( "Config", errno, "write to pidfile" );
1402  close(fd);
1403  return false;
1404  }
1405 
1406  close(fd);
1407  return true;
1408 }
1409 /******************************************************************************/
1410 /* getModificationTime */
1411 /******************************************************************************/
1412 int XrdOucUtils::getModificationTime(const char *path, time_t &modificationTime) {
1413  struct stat buf;
1414  int statRet = ::stat(path,&buf);
1415  if(!statRet) {
1416  modificationTime = buf.st_mtime;
1417  }
1418  return statRet;
1419 }
1420 
1421 void XrdOucUtils::trim(std::string &str) {
1422  // Trim leading non-letters
1423  while( str.size() && !isgraph(str[0]) ) str.erase(str.begin());
1424 
1425  // Trim trailing non-letters
1426 
1427  while( str.size() && !isgraph(str[str.size()-1]) )
1428  str.resize (str.size () - 1);
1429 }
1430 
1439 std::string obfuscate(const std::string &input, const std::vector<std::regex> &regexes) {
1440  std::string result = input;
1441  for(const auto & regex: regexes) {
1442  //Loop over the regexes and replace the values with OBFUSCATION_STR
1443  //$1 matches the first regex subgroup (e.g: "(authz=)")
1444  result = std::regex_replace(result, regex, std::string("$1" + OBFUSCATION_STR));
1445  }
1446  return result;
1447 }
1448 
1449 std::string obfuscateAuth(const std::string & input) {
1450  return obfuscate(input, authObfuscationRegexes);
1451 }
1452 
1453 #endif
1454 
struct stat Stat
Definition: XrdCks.cc:49
static XrdSysError eDest(0,"crypto_")
uint32_t crc32c(uint32_t crc, void const *buf, size_t len)
#define ENODATA
Definition: XrdOucUtils.cc:63
static const std::vector< std::regex > authObfuscationRegexes
Definition: XrdOucUtils.cc:123
#define SHFT(k)
static const std::string OBFUSCATION_STR
Definition: XrdOucUtils.cc:118
std::string obfuscate(const std::string &input, const std::vector< std::regex > &regexes)
std::string obfuscateAuth(const std::string &input)
int stat(const char *path, struct stat *buf)
int open(const char *path, int oflag,...)
int fstat(int fildes, struct stat *buf)
int chdir(const char *path)
int unlink(const char *path)
ssize_t write(int fildes, const void *buf, size_t nbyte)
ssize_t read(int fildes, void *buf, size_t nbyte)
#define close(a)
Definition: XrdPosix.hh:43
const char * XrdSysE2T(int errcode)
Definition: XrdSysE2T.cc:104
size_t strlcpy(char *dst, const char *src, size_t sz)
#define CHMOD(path, mode)
#define MAKEDIR(path, mode)
static bool Match(const char *hName, const char *pattern)
Definition: XrdNetUtils.cc:623
static bool Parse(const char *hSpec, const char **hName, const char **hNend, const char **hPort, const char **hPend)
Definition: XrdNetUtils.cc:745
static uint32_t Calc32C(const void *data, size_t count, uint32_t prevcs=0)
Definition: XrdOucCRC.cc:190
char * Get(const char *varname)
Definition: XrdOucEnv.hh:69
MDLen
SHA3 digest lengths (bits to bytes).
Definition: XrdOucSHA3.hh:56
static void * Calc(const void *in, size_t inlen, void *md, MDLen mdlen)
Definition: XrdOucSHA3.cc:150
const char * c_str() const
int length() const
int tokenize(XrdOucString &tok, int from, char del=':')
static char * parseHome(XrdSysError &eDest, XrdOucStream &Config, int &mode)
static void Sanitize(char *instr, char subc='_')
static bool getGID(const char *gName, gid_t &gID)
Definition: XrdOucUtils.cc:524
static const mode_t pathMode
Definition: XrdOucUtils.hh:48
static int isFWD(const char *path, int *port=0, char *hBuff=0, int hBLen=0, bool pTrim=false)
Definition: XrdOucUtils.cc:781
static int UserName(uid_t uID, char *uName, int uNsz)
static char * Ident(long long &mySID, char *iBuff, int iBlen, const char *iHost, const char *iProg, const char *iName, int Port)
Definition: XrdOucUtils.cc:713
static bool getUID(const char *uName, uid_t &uID, gid_t *gID=0)
Definition: XrdOucUtils.cc:540
static int getModificationTime(const char *path, time_t &modificationTime)
static const char * ValPath(const char *path, mode_t allow, bool isdir)
static char * genPath(const char *path, const char *inst, const char *psfx=0)
Definition: XrdOucUtils.cc:428
static int Token(const char **str, char delim, char *buff, int bsz)
static int ReLink(const char *path, const char *target, mode_t mode=0)
static bool parseLib(XrdSysError &eDest, XrdOucStream &Config, const char *libName, char *&path, char **libparm)
static int is1of(char *val, const char **clist)
Definition: XrdOucUtils.cc:769
static const char * InstName(int TranOpt=0)
Definition: XrdOucUtils.cc:743
static char * eText(int rc, char *eBuff, int eBlen)
Definition: XrdOucUtils.cc:208
static int argList(char *args, char **argV, int argC)
Definition: XrdOucUtils.cc:135
static bool mode2mask(const char *mode, mode_t &mask)
Definition: XrdOucUtils.cc:959
static int GidName(gid_t gID, char *gName, int gNsz, time_t keepT=0)
Definition: XrdOucUtils.cc:558
static int UidName(uid_t uID, char *uName, int uNsz, time_t keepT=0)
static char * bin2hex(char *inbuff, int dlen, char *buff, int blen, bool sep=true)
Definition: XrdOucUtils.cc:174
static int Log10(unsigned long long n)
Definition: XrdOucUtils.cc:844
static int doIf(XrdSysError *eDest, XrdOucStream &Config, const char *what, const char *hname, const char *nname, const char *pname)
Definition: XrdOucUtils.cc:242
static int makePath(char *path, mode_t mode, bool reset=false)
Definition: XrdOucUtils.cc:928
static int GroupName(gid_t gID, char *gName, int gNsz)
Definition: XrdOucUtils.cc:607
static void trim(std::string &str)
static bool findPgm(const char *pgm, XrdOucString &path)
Definition: XrdOucUtils.cc:365
static bool PidFile(XrdSysError &eDest, const char *path)
static const char * i2bstr(char *buff, int blen, int val, bool pad=false)
Definition: XrdOucUtils.cc:644
static void toLower(char *str)
static int fmtBytes(long long val, char *buff, int bsz)
Definition: XrdOucUtils.cc:401
static int Log2(unsigned long long n)
Definition: XrdOucUtils.cc:829
static void makeHome(XrdSysError &eDest, const char *inst)
Definition: XrdOucUtils.cc:861
static bool endsWith(const char *text, const char *ending, int endlen)
Definition: XrdOucUtils.cc:194
static void Undercover(XrdSysError &eDest, int noLog, int *pipeFD=0)
static char * getFile(const char *path, int &rc, int maxsz=10240, bool notempty=true)
Definition: XrdOucUtils.cc:467
static char * subLogfn(XrdSysError &eDest, const char *inst, char *logfn)
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95
void Say(const char *text1, const char *text2=0, const char *txt3=0, const char *text4=0, const char *text5=0, const char *txt6=0)
Definition: XrdSysError.cc:141
int baseFD()
Definition: XrdSysError.cc:73
XrdCmsConfig Config
XrdOucEnv theEnv