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