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