ROOT  6.06/09
Reference Guide
XrdProofdAux.cxx
Go to the documentation of this file.
1 // @(#)root/proofd:$Id$
2 // Author: G. Ganis June 2007
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2005, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 //////////////////////////////////////////////////////////////////////////
13 // //
14 // XrdProofdAux //
15 // //
16 // Authors: G. Ganis, CERN, 2007 //
17 // //
18 // Small auxiliary classes used in XrdProof //
19 // //
20 //////////////////////////////////////////////////////////////////////////
21 #include "XrdProofdPlatform.h"
22 
23 #include "XrdOuc/XrdOucStream.hh"
24 #include "XrdSys/XrdSysPriv.hh"
25 
26 #include "XpdSysError.h"
27 #include "XpdSysLogger.h"
28 #include "XrdProofdAux.h"
29 #include "XrdProofdConfig.h"
30 #include "XrdProofdProtocol.h"
31 
32 // Tracing
33 #include "XrdProofdTrace.h"
34 
35 // Local definitions
36 #ifdef XPD_MAXLEN
37 #undefine XPD_MAXLEN
38 #endif
39 #define XPD_MAXLEN 1024
40 
42 
43 ////////////////////////////////////////////////////////////////////////////////
44 /// Translates the admin message type in a human readable string.
45 /// Must be consistent with the values in XProofProtocol.h
46 
48 {
49  static const char *msgtypes[] = { "Undef",
50  "QuerySessions", "SessionTag", "SessionAlias", "GetWorkers", "QueryWorkers",
51  "CleanupSessions", "QueryLogPaths", "ReadBuffer", "QueryROOTVersions",
52  "ROOTVersion", "GroupProperties", "SendMsgToUser", "ReleaseWorker",
53  "Exec", "GetFile", "PutFile", "CpFile", "QueryMssUrl"};
54 
55  if (type < 1000 || type >= kUndef) {
56  return msgtypes[0];
57  } else {
58  int t = type - 999;
59  return msgtypes[t];
60  }
61 }
62 
63 ////////////////////////////////////////////////////////////////////////////////
64 /// Translates the proof request type in a human readable string.
65 /// Must be consistent with the values in XProofProtocol.h.
66 /// The reserved ones are for un
67 
69 {
70  static const char *reqtypes[] = { "Undef",
71  "XP_login", "XP_auth", "XP_create", "XP_destroy", "XP_attach", "XP_detach",
72  "XP_3107", "XP_3108", "XP_3109", "XP_3110",
73  "XP_urgent", "XP_sendmsg", "XP_admin", "XP_interrupt", "XP_ping",
74  "XP_cleanup", "XP_readbuf", "XP_touch", "XP_ctrlc", "XR_direct" };
75 
76  if (type < 3101 || type >= kXP_Undef) {
77  return reqtypes[0];
78  } else {
79  int t = type - 3100;
80  return reqtypes[t];
81  }
82 }
83 
84 ////////////////////////////////////////////////////////////////////////////////
85 /// Expand path 'p' relative to:
86 /// $HOME if begins with ~/
87 /// <user>'s $HOME if begins with ~<user>/
88 /// $PWD if does not begin with '/' or '~'
89 /// getenv(<ENVVAR>) if it begins with $<ENVVAR>)
90 /// The returned array of chars is the result of reallocation
91 /// of the input one.
92 /// If something is inconsistent, for example <ENVVAR> does not
93 /// exists, the original string is untouched
94 
95 char *XrdProofdAux::Expand(char *p)
96 {
97  // Make sure there soething to expand
98  if (!p || strlen(p) <= 0 || p[0] == '/')
99  return p;
100 
101  char *po = p;
102 
103  // Relative to the environment variable
104  if (p[0] == '$') {
105  // Resolve env
106  XrdOucString env(&p[1]);
107  int isl = env.find('/');
108  env.erase(isl);
109  char *p1 = (isl > 0) ? (char *)(p + isl + 2) : 0;
110  if (getenv(env.c_str())) {
111  int lenv = strlen(getenv(env.c_str()));
112  int lp1 = p1 ? strlen(p1) : 0;
113  po = (char *) malloc(lp1 + lenv + 2);
114  if (po) {
115  memcpy(po, getenv(env.c_str()), lenv);
116  if (p1) {
117  memcpy(po+lenv+1, p1, lp1);
118  po[lenv] = '/';
119  }
120  po[lp1 + lenv + 1] = 0;
121  free(p);
122  } else
123  po = p;
124  }
125  return po;
126  }
127 
128  // Relative to the local location
129  if (p[0] != '~') {
130  if (getenv("PWD")) {
131  int lpwd = strlen(getenv("PWD"));
132  int lp = strlen(p);
133  po = (char *) malloc(lp + lpwd + 2);
134  if (po) {
135  memcpy(po, getenv("PWD"), lpwd);
136  memcpy(po+lpwd+1, p, lp);
137  po[lpwd] = '/';
138  po[lpwd+lp+1] = 0;
139  free(p);
140  } else
141  po = p;
142  }
143  return po;
144  }
145 
146  // Relative to $HOME or <user>'s $HOME
147  if (p[0] == '~') {
148  char *pu = p+1;
149  char *pd = strchr(pu,'/');
150  *pd++ = '\0';
151  // Get the correct user structure
152  XrdProofUI ui;
153  int rc = 0;
154  if (strlen(pu) > 0) {
155  rc = XrdProofdAux::GetUserInfo(pu, ui);
156  } else {
157  rc = XrdProofdAux::GetUserInfo(getuid(), ui);
158  }
159  if (rc == 0) {
160  int ldir = ui.fHomeDir.length();
161  int lpd = strlen(pd);
162  po = (char *) malloc(lpd + ldir + 2);
163  if (po) {
164  memcpy(po, ui.fHomeDir.c_str(), ldir);
165  memcpy(po+ldir+1, pd, lpd);
166  po[ldir] = '/';
167  po[lpd + ldir + 1] = 0;
168  free(p);
169  } else
170  po = p;
171  }
172  return po;
173  }
174 
175  // We are done
176  return po;
177 }
178 
179 ////////////////////////////////////////////////////////////////////////////////
180 /// Expand path 'p' relative to:
181 /// $HOME if begins with ~/
182 /// <user>'s $HOME if begins with ~<user>/
183 /// $PWD if does not begin with '/' or '~'
184 /// getenv(<ENVVAR>) if it begins with $<ENVVAR>)
185 /// The input string is updated with the result.
186 /// If something is inconsistent, for example <ENVVAR> does not
187 /// exists, the original string is untouched
188 
189 void XrdProofdAux::Expand(XrdOucString &p)
190 {
191  char *po = strdup((char *)p.c_str());
192  po = Expand(po);
193  p = po;
194  SafeFree(po);
195 }
196 
197 ////////////////////////////////////////////////////////////////////////////////
198 /// Extract first integer from string at 'str', if any
199 
200 long int XrdProofdAux::GetLong(char *str)
201 {
202  // Reposition on first digit
203  char *p = str;
204  while ((*p < 48 || *p > 57) && (*p) != '\0')
205  p++;
206  if (*p == '\0')
207  return LONG_MAX;
208 
209  // Find the last digit
210  int j = 0;
211  while (*(p+j) >= 48 && *(p+j) <= 57)
212  j++;
213  *(p+j) = '\0';
214 
215  // Convert now
216  return strtol(p, 0, 10);
217 }
218 
219 ////////////////////////////////////////////////////////////////////////////////
220 /// Get information about group with 'gid' in a thread safe way.
221 /// Retur 0 on success, -errno on error
222 
223 int XrdProofdAux::GetGroupInfo(const char *grp, XrdProofGI &gi)
224 {
225  // Make sure input is defined
226  if (!grp || strlen(grp) <= 0)
227  return -EINVAL;
228 
229  // Call getgrgid_r ...
230  struct group gr;
231  struct group *pgr = 0;
232  char buf[2048];
233 #if defined(__sun) && !defined(__GNUC__)
234  pgr = getgrnam_r(grp, &gr, buf, sizeof(buf));
235 #else
236  getgrnam_r(grp, &gr, buf, sizeof(buf), &pgr);
237 #endif
238  if (pgr) {
239  // Fill output
240  gi.fGroup = grp;
241  gi.fGid = (int) gr.gr_gid;
242  // Done
243  return 0;
244  }
245 
246  // Failure
247  if (errno != 0)
248  return ((int) -errno);
249  else
250  return -ENOENT;
251 }
252 
253 ////////////////////////////////////////////////////////////////////////////////
254 /// Get information about group with 'gid' in a thread safe way.
255 /// Retur 0 on success, -errno on error
256 
258 {
259  // Make sure input make sense
260  if (gid <= 0)
261  return -EINVAL;
262 
263  // Call getgrgid_r ...
264  struct group gr;
265  struct group *pgr = 0;
266  char buf[2048];
267 #if defined(__sun) && !defined(__GNUC__)
268  pgr = getgrgid_r((gid_t)gid, &gr, buf, sizeof(buf));
269 #else
270  getgrgid_r((gid_t)gid, &gr, buf, sizeof(buf), &pgr);
271 #endif
272  if (pgr) {
273  // Fill output
274  gi.fGroup = gr.gr_name;
275  gi.fGid = gid;
276  // Done
277  return 0;
278  }
279 
280  // Failure
281  if (errno != 0)
282  return ((int) -errno);
283  else
284  return -ENOENT;
285 }
286 
287 ////////////////////////////////////////////////////////////////////////////////
288 /// Get information about user 'usr' in a thread safe way.
289 /// Return 0 on success, -errno on error
290 
291 int XrdProofdAux::GetUserInfo(const char *usr, XrdProofUI &ui)
292 {
293  // Make sure input is defined
294  if (!usr || strlen(usr) <= 0)
295  return -EINVAL;
296 
297  // Call getpwnam_r ...
298  struct passwd pw;
299  struct passwd *ppw = 0;
300  char buf[2048];
301 #if defined(__sun) && !defined(__GNUC__)
302  ppw = getpwnam_r(usr, &pw, buf, sizeof(buf));
303 #else
304  getpwnam_r(usr, &pw, buf, sizeof(buf), &ppw);
305 #endif
306  if (ppw) {
307  // Fill output
308  ui.fUid = (int) pw.pw_uid;
309  ui.fGid = (int) pw.pw_gid;
310  ui.fHomeDir = pw.pw_dir;
311  ui.fUser = usr;
312  // Done
313  return 0;
314  }
315 
316  // Failure
317  if (errno != 0)
318  return ((int) -errno);
319  else
320  return -ENOENT;
321 }
322 
323 ////////////////////////////////////////////////////////////////////////////////
324 /// Get information about user with 'uid' in a thread safe way.
325 /// Retur 0 on success, -errno on error
326 
328 {
329  // Make sure input make sense
330  if (uid < 0)
331  return -EINVAL;
332 
333  // Call getpwuid_r ...
334  struct passwd pw;
335  struct passwd *ppw = 0;
336  char buf[2048];
337 #if defined(__sun) && !defined(__GNUC__)
338  ppw = getpwuid_r((uid_t)uid, &pw, buf, sizeof(buf));
339 #else
340  getpwuid_r((uid_t)uid, &pw, buf, sizeof(buf), &ppw);
341 #endif
342  if (ppw) {
343  // Fill output
344  ui.fUid = uid;
345  ui.fGid = (int) pw.pw_gid;
346  ui.fHomeDir = pw.pw_dir;
347  ui.fUser = pw.pw_name;
348  // Done
349  return 0;
350  }
351 
352  // Failure
353  if (errno != 0)
354  return ((int) -errno);
355  else
356  return -ENOENT;
357 }
358 
359 ////////////////////////////////////////////////////////////////////////////////
360 /// Write nb bytes at buf to descriptor 'fd' ignoring interrupts
361 /// Return the number of bytes written or -1 in case of error
362 
363 int XrdProofdAux::Write(int fd, const void *buf, size_t nb)
364 {
365  if (fd < 0)
366  return -1;
367 
368  const char *pw = (const char *)buf;
369  int lw = nb;
370  int nw = 0, written = 0;
371  while (lw) {
372  if ((nw = write(fd, pw + written, lw)) < 0) {
373  if (errno == EINTR) {
374  errno = 0;
375  continue;
376  } else {
377  break;
378  }
379  }
380  // Count
381  written += nw;
382  lw -= nw;
383  }
384 
385  // Done
386  return written;
387 }
388 
389 ////////////////////////////////////////////////////////////////////////////////
390 /// Logs error message 'emsg' to file 'flog' using standard technology
391 
392 void XrdProofdAux::LogEmsgToFile(const char *flog, const char *emsg, const char *pfx)
393 {
394  XPDLOC(AUX, "Aux::LogEmsgToFile")
395 
396  if (flog && strlen(flog)) {
397  // Open the file in write-only, append mode
398  int logfd = open(flog, O_WRONLY|O_APPEND, 0644);
399  if (logfd >= 0) {
400  fcntl(logfd, F_SETFD, FD_CLOEXEC);
401  // Attach a logger to the file
402  XrdSysLogger logger(logfd, 0);
403  XrdSysError error(&logger, "xpd");
404  // Log the message
405  if (emsg && strlen(emsg) > 0) error.Emsg("-E", pfx, emsg);
406  // Make sure that it is written to file
407  if (fsync(logfd) != 0)
408  TRACE(XERR, "problem syncing file "<<flog<<" - errno: "<<errno);
409  // Free the descriptor
410  if (close(logfd) != 0)
411  TRACE(XERR, "problem closing file "<<flog<<" - errno: "<<errno);
412  } else {
413  TRACE(XERR, "file "<<flog<<" could not be opened - errno: "<<errno);
414  }
415  } else {
416  TRACE(XERR, "file path undefined!");
417  }
418  // Done
419  return;
420 }
421 
422 ////////////////////////////////////////////////////////////////////////////////
423 /// Make sure that 'path' exists and is owned by the entity
424 /// described by 'ui'.
425 /// If changeown is TRUE it tries to acquire the privileges before.
426 /// Return 0 in case of success, -1 in case of error
427 
428 int XrdProofdAux::AssertDir(const char *path, XrdProofUI ui, bool changeown)
429 {
430  XPDLOC(AUX, "Aux::AssertDir")
431 
432  TRACE(DBG, path);
433 
434  if (!path || strlen(path) <= 0)
435  return -1;
436  XrdSysPrivGuard pGuard((uid_t)0, (gid_t)0);
437  if (XpdBadPGuard(pGuard, ui.fUid) && changeown) {
438  TRACE(XERR, "could not get privileges to change ownership");
439  return -1;
440  }
441 
442  if (mkdir(path, 0755) != 0 && (errno != EEXIST)) {
443  TRACE(XERR, "unable to create dir: "<<path<<" (errno: "<<errno<<")");
444  return -1;
445  }
446 
447  if (changeown) {
448  // Set ownership of the path to the client
449  if (chown(path, ui.fUid, ui.fGid) == -1) {
450  TRACE(XERR, "cannot set user ownership on path (errno: "<<errno<<")");
451  return -1;
452  }
453  }
454 
455  // We are done
456  return 0;
457 }
458 
459 ////////////////////////////////////////////////////////////////////////////////
460 /// Make sure that the base dir of 'path' is either owned by 'ui' or
461 /// gives full permissions to 'ui'.
462 /// If 'path' is a directory, go through the paths inside it recursively.
463 /// Return 0 in case of success, -1 in case of error
464 
465 int XrdProofdAux::AssertBaseDir(const char *path, XrdProofUI ui)
466 {
467  XPDLOC(AUX, "Aux::AssertBaseDir")
468 
469  TRACE(DBG, path);
470 
471  if (!path || strlen(path) <= 0)
472  return -1;
473 
474  XrdOucString base(path);
475  if (base.endswith("/")) base.erasefromend(1);
476  int isl = base.rfind('/');
477  if (isl != 0) base.erase(isl);
478  TRACE(DBG, "base: " <<base);
479 
480  struct stat st;
481  if (stat(base.c_str(), &st) != 0) {
482  // Failure: stop
483  TRACE(XERR, "unable to stat base path: "<<base<<" (errno: "<<errno<<")");
484  return -1;
485  }
486 
487  // Check ownership and permissions
488  if (ui.fUid != (int) st.st_uid) {
489  unsigned pa = (st.st_mode & S_IRWXG);
490  if (ui.fGid != (int) st.st_gid)
491  pa |= (st.st_mode & S_IRWXO);
492  else
493  pa |= S_IRWXO;
494  if (pa != 0077) {
495  TRACE(XERR, "effective user has not full permissions on base path: "<<base);
496  return -1;
497  }
498  }
499 
500  // Done
501  return 0;
502 }
503 
504 ////////////////////////////////////////////////////////////////////////////////
505 /// Change the ownership of 'path' to the entity described by 'ui'.
506 /// If 'path' is a directory, go through the paths inside it recursively.
507 /// Return 0 in case of success, -1 in case of error
508 
509 int XrdProofdAux::ChangeOwn(const char *path, XrdProofUI ui)
510 {
511  XPDLOC(AUX, "Aux::ChangeOwn")
512 
513  TRACE(DBG, path);
514 
515  if (!path || strlen(path) <= 0)
516  return -1;
517  DIR *dir = opendir(path);
518  if (dir) {
519  // Loop over the dir
520  XrdOucString proot(path);
521  if (!proot.endswith('/')) proot += "/";
522 
523  struct dirent *ent = 0;
524  while ((ent = readdir(dir))) {
525  if (ent->d_name[0] == '.' || !strcmp(ent->d_name, "..")) continue;
526  XrdOucString fn(proot);
527  fn += ent->d_name;
528 
529  // Apply recursively
530  if (XrdProofdAux::ChangeOwn(fn.c_str(), ui) != 0) {
531  TRACE(XERR, "problems changing recursively ownership of: "<<fn);
532  closedir(dir);
533  return -1;
534  }
535  }
536  // Close the directory
537  closedir(dir);
538 
539  } else {
540  // If it was a directory and opening failed, we fail
541  if (errno != 0 && (errno != ENOTDIR)) {
542  TRACE(XERR,"cannot open "<<path<< "- errno: "<< errno);
543  return -1;
544  }
545  // Get the privileges, if needed
546  XrdSysPrivGuard pGuard((uid_t)0, (gid_t)0);
547  if (XpdBadPGuard(pGuard, ui.fUid)) {
548  TRACE(XERR, "could not get privileges to change ownership");
549  return -1;
550  }
551  // Set ownership of the path to the client
552  if (chown(path, ui.fUid, ui.fGid) == -1) {
553  TRACE(XERR, "cannot set user ownership on path (errno: "<<errno<<")");
554  return -1;
555  }
556  }
557  // We are done
558  return 0;
559 }
560 
561 ////////////////////////////////////////////////////////////////////////////////
562 /// Change the permission mode of 'path' to 'mode'.
563 /// If 'path' is a directory, go through the paths inside it recursively.
564 /// Return 0 in case of success, -1 in case of error
565 
566 int XrdProofdAux::ChangeMod(const char *path, unsigned int mode)
567 {
568  XPDLOC(AUX, "Aux::ChangeMod")
569 
570  TRACE(HDBG, "path: "<<path);
571 
572  if (!path || strlen(path) <= 0)
573  return -1;
574 
575  struct stat st;
576  if (stat(path,&st) != 0) {
577  // Failure: stop
578  TRACE(XERR, "unable to stat path: "<<path<<" (errno: "<<errno<<")");
579  return -1;
580  }
581 
582  // Change the path first; then do it recursively, if needed
583  { // Get the privileges, if needed
584  XrdSysPrivGuard pGuard(st.st_uid, st.st_gid);
585  if (XpdBadPGuard(pGuard, st.st_uid)) {
586  TRACE(XERR, "could not get privileges to change ownership");
587  return -1;
588  }
589  // Set ownership of the path to the client
590  if (chmod(path, mode) == -1) {
591  TRACE(XERR, "cannot change permissions on path (errno: "<<errno<<")");
592  return -1;
593  }
594  }
595 
596  // If is a directory apply this on it
597  if (S_ISDIR(st.st_mode)) {
598  // Loop over the dir
599  DIR *dir = opendir(path);
600  if (!dir) {
601  TRACE(XERR,"cannot open "<<path<< "- errno: "<< errno);
602  return -1;
603  }
604  XrdOucString proot(path);
605  if (!proot.endswith('/')) proot += "/";
606 
607  struct dirent *ent = 0;
608  while ((ent = readdir(dir))) {
609  if (ent->d_name[0] == '.' || !strcmp(ent->d_name, "..")) continue;
610  XrdOucString fn(proot);
611  fn += ent->d_name;
612 
613  struct stat xst;
614  if (stat(fn.c_str(),&xst) == 0) {
615  { // Get the privileges, if needed
616  TRACE(HDBG,"getting {"<<xst.st_uid<<", "<< xst.st_gid<<"} identity");
617  XrdSysPrivGuard pGuard(xst.st_uid, xst.st_gid);
618  if (XpdBadPGuard(pGuard, xst.st_uid)) {
619  TRACE(XERR, "could not get privileges to change ownership");
620  closedir(dir);
621  return -1;
622  }
623  // Set the permission mode of the path
624  if (chmod(fn.c_str(), mode) == -1) {
625  TRACE(XERR, "cannot change permissions on path (errno: "<<errno<<")");
626  closedir(dir);
627  return -1;
628  }
629  }
630  // If is a directory apply this on it
631  if (S_ISDIR(xst.st_mode)) {
632  if (XrdProofdAux::ChangeMod(fn.c_str(), mode) != 0) {
633  TRACE(XERR, "problems changing recursively permissions of: "<<fn);
634  closedir(dir);
635  return -1;
636  }
637  }
638  } else {
639  TRACE(XERR, "unable to stat dir: "<<fn<<" (errno: "<<errno<<")");
640  }
641  }
642  // Close the directory
643  closedir(dir);
644  }
645 
646  // We are done
647  return 0;
648 }
649 
650 ////////////////////////////////////////////////////////////////////////////////
651 /// Change current directory to 'dir'.
652 /// If changeown is TRUE it tries to acquire the privileges before.
653 /// Return 0 in case of success, -1 in case of error
654 
655 int XrdProofdAux::ChangeToDir(const char *dir, XrdProofUI ui, bool changeown)
656 {
657  XPDLOC(AUX, "Aux::ChangeToDir")
658 
659  TRACE(DBG, "changing to " << ((dir) ? dir : "**undef***"));
660 
661  if (!dir || strlen(dir) <= 0)
662  return -1;
663 
664  if (changeown && ((int) geteuid() != ui.fUid || (int) getegid() != ui.fGid)) {
665 
666  XrdSysPrivGuard pGuard((uid_t)0, (gid_t)0);
667  if (XpdBadPGuard(pGuard, ui.fUid)) {
668  TRACE(XERR, changeown << ": could not get privileges; {uid,gid} req: {"<< ui.fUid <<","<<ui.fGid<<
669  "}, {euid,egid}: {" << geteuid() <<","<<getegid()<<"}, {uid,gid}: {"<<getuid()<<","<<getgid() << "}; errno: "<<errno);
670  return -1;
671  }
672  if (chdir(dir) == -1) {
673  TRACE(XERR, changeown << ": can't change directory to '"<< dir<<"'; {ui.fUid,ui.fGid}: {"<< ui.fUid <<","<<ui.fGid<<
674  "}, {euid,egid}: {" << geteuid() <<","<<getegid()<<"}, {uid,gid}: {"<<getuid()<<","<<getgid() << "}; errno: "<<errno);
675  return -1;
676  }
677  } else {
678  if (chdir(dir) == -1) {
679  TRACE(XERR, changeown << ": can't change directory to "<< dir <<
680  ", euid: " << geteuid() <<", uid:"<<getuid()<<"; errno: "<<errno);
681  return -1;
682  }
683  }
684 
685  // We are done
686  return 0;
687 }
688 
689 ////////////////////////////////////////////////////////////////////////////////
690 /// Create a symlink 'link' to 'path'
691 /// Return 0 in case of success, -1 in case of error
692 
693 int XrdProofdAux::SymLink(const char *path, const char *link)
694 {
695  XPDLOC(AUX, "Aux::SymLink")
696 
697  TRACE(DBG, path<<" -> "<<link);
698 
699  if (!path || strlen(path) <= 0 || !link || strlen(link) <= 0)
700  return -1;
701 
702  // Remove existing link, if any
703  if (unlink(link) != 0 && errno != ENOENT) {
704  TRACE(XERR, "problems unlinking existing symlink "<< link<<
705  " (errno: "<<errno<<")");
706  return -1;
707  }
708  if (symlink(path, link) != 0) {
709  TRACE(XERR, "problems creating symlink " << link<<
710  " (errno: "<<errno<<")");
711  return -1;
712  }
713 
714  // We are done
715  return 0;
716 }
717 
718 ////////////////////////////////////////////////////////////////////////////////
719 /// Check existence and match condition of an 'if' directive
720 /// If none (valid) is found, return -1.
721 /// Else, return number of chars matching.
722 
723 int XrdProofdAux::CheckIf(XrdOucStream *s, const char *host)
724 {
725  XPDLOC(AUX, "")
726 
727  // There must be an 'if'
728  char *val = s ? s->GetWord() : 0;
729  if (!val || strncmp(val,"if",2)) {
730  if (val)
731  // allow the analysis of the token
732  s->RetToken();
733  return -1;
734  }
735 
736  // check value if any
737  val = s->GetWord();
738  if (!val)
739  return -1;
740 
741  // Deprecate
742  TRACE(ALL, ">>> Warning: 'if' conditions at the end of the directive are deprecated ");
743  TRACE(ALL, ">>> Please use standard Scalla/Xrootd 'if-else-fi' constructs");
744  TRACE(ALL, ">>> (see http://xrootd.slac.stanford.edu/doc/xrd_config/xrd_config.htm)");
745 
746  // Notify
747  TRACE(DBG, "Aux::CheckIf: <pattern>: " <<val);
748 
749  // Return number of chars matching
750  XrdOucString h(host);
751  return h.matches((const char *)val);
752 }
753 
754 ////////////////////////////////////////////////////////////////////////////////
755 /// Find out and return the number of CPUs in the local machine.
756 /// Return -1 in case of failure.
757 
759 {
760  XPDLOC(AUX, "Aux::GetNumCPUs")
761 
762  static int ncpu = -1;
763 
764  // Use cached value, if any
765  if (ncpu > 0)
766  return ncpu;
767  ncpu = 0;
768 
769  XrdOucString emsg;
770 
771 #if defined(linux)
772  // Look for in the /proc/cpuinfo file
773  XrdOucString fcpu("/proc/cpuinfo");
774  FILE *fc = fopen(fcpu.c_str(), "r");
775  if (!fc) {
776  if (errno == ENOENT) {
777  TRACE(XERR, "/proc/cpuinfo missing!!! Something very bad going on");
778  } else {
779  XPDFORM(emsg, "cannot open %s; errno: %d", fcpu.c_str(), errno);
780  TRACE(XERR, emsg);
781  }
782  return -1;
783  }
784  // Read lines and count those starting with "processor"
785  char line[2048] = { 0 };
786  while (fgets(line, sizeof(line), fc)) {
787  if (!strncmp(line, "processor", strlen("processor")))
788  ncpu++;
789  }
790  // Close the file
791  fclose(fc);
792 
793 #elif defined(__sun)
794 
795  // Run "psrinfo" in popen and count lines
796  FILE *fp = popen("psrinfo", "r");
797  if (fp != 0) {
798  char line[2048] = { 0 };
799  while (fgets(line, sizeof(line), fp))
800  ncpu++;
801  pclose(fp);
802  }
803 
804 #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
805 
806  // Run "sysctl -n hw.ncpu" in popen and decode the output
807  FILE *fp = popen("sysctl -n hw.ncpu", "r");
808  if (fp != 0) {
809  char line[2048] = { 0 };
810  while (fgets(line, sizeof(line), fp))
811  ncpu = XrdProofdAux::GetLong(&line[0]);
812  pclose(fp);
813  }
814 #endif
815 
816  TRACE(DBG, "# of cores found: "<<ncpu);
817 
818  // Done
819  return (ncpu <= 0) ? (int)(-1) : ncpu ;
820 }
821 
822 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
823 ////////////////////////////////////////////////////////////////////////////////
824 /// Returns a list of all processes on the system. This routine
825 /// allocates the list and puts it in *plist and counts the
826 /// number of entries in 'nproc'. Caller is responsible for 'freeing'
827 /// the list.
828 /// On success, the function returns 0.
829 /// On error, the function returns an errno value.
830 ///
831 /// Adapted from: reply to Technical Q&A 1123,
832 /// http://developer.apple.com/qa/qa2001/qa1123.html
833 ///
834 
835 int XrdProofdAux::GetMacProcList(kinfo_proc **plist, int &nproc)
836 {
837  XPDLOC(AUX, "Aux::GetMacProcList")
838 
839  int rc = 0;
840  kinfo_proc *res;
841  bool done = 0;
842  static const int name[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0};
843 
844  TRACE(DBG, "enter");
845 
846  // Declaring name as const requires us to cast it when passing it to
847  // sysctl because the prototype doesn't include the const modifier.
848  size_t len = 0;
849 
850  if (!plist || (*plist))
851  return EINVAL;
852  nproc = 0;
853 
854  // We start by calling sysctl with res == 0 and len == 0.
855  // That will succeed, and set len to the appropriate length.
856  // We then allocate a buffer of that size and call sysctl again
857  // with that buffer. If that succeeds, we're done. If that fails
858  // with ENOMEM, we have to throw away our buffer and loop. Note
859  // that the loop causes use to call sysctl with 0 again; this
860  // is necessary because the ENOMEM failure case sets length to
861  // the amount of data returned, not the amount of data that
862  // could have been returned.
863 
864  res = 0;
865  do {
866  // Call sysctl with a 0 buffer.
867  len = 0;
868  if ((rc = sysctl((int *)name, (sizeof(name)/sizeof(*name)) - 1,
869  0, &len, 0, 0)) == -1) {
870  rc = errno;
871  }
872 
873  // Allocate an appropriately sized buffer based on the results
874  // from the previous call.
875  if (rc == 0) {
876  res = (kinfo_proc *) malloc(len);
877  if (!res)
878  rc = ENOMEM;
879  }
880 
881  // Call sysctl again with the new buffer. If we get an ENOMEM
882  // error, toss away our buffer and start again.
883  if (rc == 0) {
884  if ((rc = sysctl((int *)name, (sizeof(name)/sizeof(*name)) - 1,
885  res, &len, 0, 0)) == -1) {
886  rc = errno;
887  }
888  if (rc == 0) {
889  done = 1;
890  } else if (rc == ENOMEM) {
891  if (res)
892  free(res);
893  res = 0;
894  rc = 0;
895  }
896  }
897  } while (rc == 0 && !done);
898 
899  // Clean up and establish post conditions.
900  if (rc != 0 && !res) {
901  free(res);
902  res = 0;
903  }
904  *plist = res;
905  if (rc == 0)
906  nproc = len / sizeof(kinfo_proc);
907 
908  // Done
909  return rc;
910 }
911 #endif
912 
913 ////////////////////////////////////////////////////////////////////////////////
914 /// Get from the process table list of PIDs for processes named "proofserv'
915 /// For {linux, sun, macosx} it uses the system info; for other systems it
916 /// invokes the command shell 'ps ax' via popen.
917 /// Return the number of processes found, or -1 if some error occured.
918 
919 int XrdProofdAux::GetProcesses(const char *pn, std::map<int,XrdOucString> *pmap)
920 {
921  XPDLOC(AUX, "Aux::GetProcesses")
922 
923  int np = 0;
924 
925  // Check input consistency
926  if (!pn || strlen(pn) <= 0 || !pmap) {
927  TRACE(XERR, "invalid inputs");
928  return -1;
929  }
930  TRACE(DBG, "process name: "<<pn);
931 
932  XrdOucString emsg;
933 
934 #if defined(linux) || defined(__sun)
935  // Loop over the "/proc" dir
936  DIR *dir = opendir("/proc");
937  if (!dir) {
938  emsg = "cannot open /proc - errno: ";
939  emsg += errno;
940  TRACE(DBG, emsg.c_str());
941  return -1;
942  }
943 
944  struct dirent *ent = 0;
945  while ((ent = readdir(dir))) {
946  if (DIGIT(ent->d_name[0])) {
947  XrdOucString fn("/proc/", 256);
948  fn += ent->d_name;
949 #if defined(linux)
950  fn += "/status";
951  // Open file
952  FILE *ffn = fopen(fn.c_str(), "r");
953  if (!ffn) {
954  emsg = "cannot open file ";
955  emsg += fn; emsg += " - errno: "; emsg += errno;
956  TRACE(HDBG, emsg);
957  continue;
958  }
959  // Read info
960  bool ok = 0;
961  int pid = -1;
962  char line[2048] = { 0 };
963  while (fgets(line, sizeof(line), ffn)) {
964  // Check name
965  if (strstr(line, "Name:")) {
966  if (strstr(line, pn)) {
967  // Good one
968  ok = 1;
969  }
970  // We are done with this proc file
971  break;
972  }
973  }
974  if (ok) {
975  fclose(ffn);
976  fn.replace("/status", "/cmdline");
977  // Open file
978  if (!(ffn = fopen(fn.c_str(), "r"))) {
979  emsg = "cannot open file ";
980  emsg += fn; emsg += " - errno: "; emsg += errno;
981  TRACE(HDBG, emsg);
982  continue;
983  }
984  // Read the command line
985  XrdOucString cmd;
986  char buf[256];
987  char *p = &buf[0];
988  int pos = 0, ltot = 0, nr = 1;
989  errno = 0;
990  while (nr > 0) {
991  while ((nr = read(fileno(ffn), p + pos, 1)) == -1 && errno == EINTR) {
992  errno = 0;
993  }
994  ltot += nr;
995  if (ltot == 254) {
996  buf[255] = 0;
997  cmd += buf;
998  pos = 0;
999  ltot = 0;
1000  } else if (nr > 0) {
1001  if (*p == 0) *p = ' ';
1002  p += nr;
1003  }
1004  }
1005  // Null terminate
1006  buf[ltot] = 0;
1007  cmd += buf;
1008  // Good one: take the pid
1009  pid = strtol(ent->d_name, 0, 10);
1010  pmap->insert(std::make_pair(pid, cmd));
1011  np++;
1012  }
1013  // Close the file
1014  fclose(ffn);
1015 #elif defined(__sun)
1016  fn += "/psinfo";
1017  // Open file
1018  int ffd = open(fn.c_str(), O_RDONLY);
1019  if (ffd <= 0) {
1020  emsg = "cannot open file ";
1021  emsg += fn; emsg += " - errno: "; emsg += errno;
1022  TRACE(HDBG, emsg);
1023  continue;
1024  }
1025  // Get the information
1026  psinfo_t psi;
1027  if (read(ffd, &psi, sizeof(psinfo_t)) != sizeof(psinfo_t)) {
1028  emsg = "cannot read ";
1029  emsg += fn; emsg += ": errno: "; emsg += errno;
1030  TRACE(XERR, emsg);
1031  close(ffd);
1032  continue;
1033  }
1034  // Check name
1035  if (strstr(psi.pr_fname, pn)) {
1036  // Build command line
1037  XrdOucString cmd(psi.pr_fname);
1038  if (cmd.length() > 0) cmd += " ";
1039  cmd += psi.pr_psargs;
1040  // Good one: take the pid
1041  int pid = strtol(ent->d_name, 0, 10);
1042  pmap->insert(std::make_pair(pid, cmd));
1043  np++;
1044  }
1045  // Close the file
1046  close(ffd);
1047 #endif
1048  }
1049  }
1050  // Close the directory
1051  closedir(dir);
1052 
1053 #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
1054 
1055  // Get the proclist
1056  kinfo_proc *pl = 0;
1057  int ern = 0;
1058  if ((ern = XrdProofdAux::GetMacProcList(&pl, np)) != 0) {
1059  emsg = "cannot get the process list: errno: ";
1060  emsg += ern;
1061  TRACE(XERR, emsg);
1062  return -1;
1063  }
1064 
1065  // Loop over the list
1066  int ii = np;
1067  while (ii--) {
1068  if (strstr(pl[ii].kp_proc.p_comm, pn)) {
1069  // Good one: take the pid
1070  pmap->insert(std::make_pair(pl[ii].kp_proc.p_pid, XrdOucString(pl[ii].kp_proc.p_comm)));
1071  np++;
1072  }
1073  }
1074  // Cleanup
1075  free(pl);
1076 #else
1077 
1078  // For the remaining cases we use 'ps' via popen to localize the processes
1079 
1080  // Build command
1081  XrdOucString cmd = "ps ax -ww | grep proofserv 2>/dev/null";
1082 
1083  // Run it ...
1084  XrdOucString pids = ":";
1085  FILE *fp = popen(cmd.c_str(), "r");
1086  if (fp != 0) {
1087  char line[2048] = { 0 };
1088  while (fgets(line, sizeof(line), fp)) {
1089  int pid = (int) XrdProofdAux::GetLong(&line[from]);
1090  pmap->insert(std::make_pair(pid, XrdOucString(line)));
1091  np++;
1092  }
1093  pclose(fp);
1094  } else {
1095  // Error executing the command
1096  return -1;
1097  }
1098 
1099 #endif
1100 
1101  // Done
1102  return np;
1103 }
1104 
1105 ////////////////////////////////////////////////////////////////////////////////
1106 /// Extract an integer from a file
1107 
1108 int XrdProofdAux::GetIDFromPath(const char *path, XrdOucString &emsg)
1109 {
1110  emsg = "";
1111  // Get the ID
1112  int id = -1;
1113  FILE *fid = fopen(path, "r");
1114  if (fid) {
1115  char line[64];
1116  if (fgets(line, sizeof(line), fid)) {
1117  if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = 0;
1118  id = atoi(line);
1119  }
1120  fclose(fid);
1121  } else if (errno != ENOENT) {
1122  XPDFORM(emsg, "GetIDFromPath: error reading id from: %s (errno: %d)",
1123  path, errno);
1124  }
1125  // Done
1126  return id;
1127 }
1128 
1129 ////////////////////////////////////////////////////////////////////////////////
1130 /// Returns true is 's' contains at least one of the comma-separated tokens
1131 /// in 'tokens'. Else returns false.
1132 
1133 bool XrdProofdAux::HasToken(const char *s, const char *tokens)
1134 {
1135  if (s && strlen(s) > 0) {
1136  XrdOucString tks(tokens), tok;
1137  int from = 0;
1138  while ((from = tks.tokenize(tok, from, ',')) != -1)
1139  if (strstr(s, tok.c_str())) return 1;
1140  }
1141  return 0;
1142 }
1143 
1144 ////////////////////////////////////////////////////////////////////////////////
1145 /// Check if a process named 'pname' and process 'pid' is still
1146 /// in the process table.
1147 /// For {linux, sun, macosx} it uses the system info; for other systems it
1148 /// invokes the command shell 'ps ax' via popen.
1149 /// Return 1 if running, 0 if not running, -1 if the check could not be run.
1150 
1151 int XrdProofdAux::VerifyProcessByID(int pid, const char *pname)
1152 {
1153  XPDLOC(AUX, "Aux::VerifyProcessByID")
1154 
1155  int rc = 0;
1156 
1157  TRACE(DBG, "pid: "<<pid);
1158 
1159  // Check input consistency
1160  if (pid < 0) {
1161  TRACE(XERR, "invalid pid");
1162  return -1;
1163  }
1164 
1165  XrdOucString emsg;
1166 
1167  // Name
1168  const char *pn = (pname && strlen(pname) > 0) ? pname : "proofserv";
1169 
1170 #if defined(linux)
1171  // Look for the relevant /proc dir
1172  XrdOucString fn("/proc/");
1173  fn += pid;
1174  fn += "/stat";
1175  FILE *ffn = fopen(fn.c_str(), "r");
1176  if (!ffn) {
1177  if (errno == ENOENT) {
1178  TRACE(DBG, "process does not exists anymore");
1179  return 0;
1180  } else {
1181  XPDFORM(emsg, "cannot open %s; errno: %d", fn.c_str(), errno);
1182  TRACE(XERR, emsg);
1183  return -1;
1184  }
1185  }
1186  // Read status line
1187  char line[2048] = { 0 };
1188  if (fgets(line, sizeof(line), ffn)) {
1189  if (XrdProofdAux::HasToken(line, pn))
1190  // Still there
1191  rc = 1;
1192  } else {
1193  XPDFORM(emsg, "cannot read %s; errno: %d", fn.c_str(), errno);
1194  TRACE(XERR, emsg);
1195  fclose(ffn);
1196  return -1;
1197  }
1198  // Close the file
1199  fclose(ffn);
1200 
1201 #elif defined(__sun)
1202 
1203  // Look for the relevant /proc dir
1204  XrdOucString fn("/proc/");
1205  fn += pid;
1206  fn += "/psinfo";
1207  int ffd = open(fn.c_str(), O_RDONLY);
1208  if (ffd <= 0) {
1209  if (errno == ENOENT) {
1210  TRACE(DBG, "VerifyProcessByID: process does not exists anymore");
1211  return 0;
1212  } else {
1213  XPDFORM(emsg, "cannot open %s; errno: %d", fn.c_str(), errno);
1214  TRACE(XERR, emsg);
1215  close(ffd);
1216  return -1;
1217  }
1218  }
1219  // Get the information
1220  psinfo_t psi;
1221  if (read(ffd, &psi, sizeof(psinfo_t)) != sizeof(psinfo_t)) {
1222  XPDFORM(emsg, "cannot read %s; errno: %d", fn.c_str(), errno);
1223  TRACE(XERR, emsg);
1224  close(ffd);
1225  return -1;
1226  }
1227 
1228  // Verify now
1229  if (XrdProofdAux::HasToken(psi.pr_fname, pn))
1230  // The process is still there
1231  rc = 1;
1232 
1233  // Close the file
1234  close(ffd);
1235 
1236 #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
1237 
1238  // Get the proclist
1239  kinfo_proc *pl = 0;
1240  int np;
1241  int ern = 0;
1242  if ((ern = XrdProofdAux::GetMacProcList(&pl, np)) != 0) {
1243  XPDFORM(emsg, "cannot get the process list: errno: %d", ern);
1244  TRACE(XERR, emsg);
1245  return -1;
1246  }
1247 
1248  // Loop over the list
1249  while (np--) {
1250  if (pl[np].kp_proc.p_pid == pid &&
1251  XrdProofdAux::HasToken(pl[np].kp_proc.p_comm, pn)) {
1252  // Process still exists
1253  rc = 1;
1254  break;
1255  }
1256  }
1257  // Cleanup
1258  free(pl);
1259 #else
1260  // Use the output of 'ps ax' as a backup solution
1261  XrdOucString cmd = "ps ax | grep proofserv 2>/dev/null";
1262  if (pname && strlen(pname))
1263  cmd.replace("proofserv", pname);
1264  FILE *fp = popen(cmd.c_str(), "r");
1265  if (fp != 0) {
1266  char line[2048] = { 0 };
1267  while (fgets(line, sizeof(line), fp)) {
1268  if (pid == XrdProofdAux::GetLong(line)) {
1269  // Process still running
1270  rc = 1;
1271  break;
1272  }
1273  }
1274  pclose(fp);
1275  } else {
1276  // Error executing the command
1277  return -1;
1278  }
1279 #endif
1280  // Done
1281  return rc;
1282 }
1283 
1284 ////////////////////////////////////////////////////////////////////////////////
1285 /// Kill the process 'pid'.
1286 /// A SIGTERM is sent, unless 'kill' is TRUE, in which case a SIGKILL is used.
1287 /// If add is TRUE (default) the pid is added to the list of processes
1288 /// requested to terminate.
1289 /// Return 0 on success, -1 if not allowed or other errors occured.
1290 
1291 int XrdProofdAux::KillProcess(int pid, bool forcekill, XrdProofUI ui, bool changeown)
1292 {
1293  XPDLOC(AUX, "Aux::KillProcess")
1294 
1295  TRACE(DBG, "pid: "<<pid<< ", forcekill: "<< forcekill);
1296 
1297  XrdOucString msg;
1298  if (pid > 0) {
1299  // We need the right privileges to do this
1300  XrdSysPrivGuard pGuard((uid_t)0, (gid_t)0);
1301  if (XpdBadPGuard(pGuard, ui.fUid) && changeown) {
1302  TRACE(XERR, "could not get privileges");
1303  return -1;
1304  } else {
1305  bool signalled = 1;
1306  if (forcekill) {
1307  // Hard shutdown via SIGKILL
1308  if (kill(pid, SIGKILL) != 0) {
1309  if (errno != ESRCH) {
1310  XPDFORM(msg, "kill(pid,SIGKILL) failed for process %d; errno: %d", pid, errno);
1311  TRACE(XERR, msg);
1312  return -1;
1313  }
1314  signalled = 0;
1315  }
1316  } else {
1317  // Softer shutdown via SIGTERM
1318  if (kill(pid, SIGTERM) != 0) {
1319  if (errno != ESRCH) {
1320  XPDFORM(msg, "kill(pid,SIGTERM) failed for process %d; errno: %d", pid, errno);
1321  TRACE(XERR, msg);
1322  return -1;
1323  }
1324  signalled = 0;
1325  }
1326  }
1327  // Notify failure
1328  if (!signalled) {
1329  TRACE(DBG, "process ID "<<pid<<" not found in the process table");
1330  }
1331  }
1332  } else {
1333  return -1;
1334  }
1335 
1336  // Done
1337  return 0;
1338 }
1339 
1340 ////////////////////////////////////////////////////////////////////////////////
1341 /// Remove directory at path and its content.
1342 /// Returns 0 on success, -errno of the last error on failure
1343 
1344 int XrdProofdAux::RmDir(const char *path)
1345 {
1346  XPDLOC(AUX, "Aux::RmDir")
1347 
1348  int rc = 0;
1349 
1350  TRACE(DBG, path);
1351 
1352  // Open dir
1353  DIR *dir = opendir(path);
1354  if (!dir) {
1355  TRACE(XERR, "cannot open dir "<<path<<" ; error: "<<errno);
1356  return -errno;
1357  }
1358 
1359  // Scan the directory
1360  XrdOucString entry;
1361  struct stat st;
1362  struct dirent *ent = 0;
1363  while ((ent = (struct dirent *)readdir(dir))) {
1364  // Skip the basic entries
1365  if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) continue;
1366  // Get info about the entry
1367  XPDFORM(entry, "%s/%s", path, ent->d_name);
1368  if (stat(entry.c_str(), &st) != 0) {
1369  TRACE(XERR, "cannot stat entry "<<entry<<" ; error: "<<errno);
1370  rc = -errno;
1371  break;
1372  }
1373  // Remove directories recursively
1374  if (S_ISDIR(st.st_mode)) {
1375  rc = XrdProofdAux::RmDir(entry.c_str());
1376  if (rc != 0) {
1377  TRACE(XERR, "problems removing"<<entry<<" ; error: "<<-rc);
1378  break;
1379  }
1380  } else {
1381  // Remove the entry
1382  if (unlink(entry.c_str()) != 0) {
1383  rc = -errno;
1384  TRACE(XERR, "problems removing"<<entry<<" ; error: "<<-rc);
1385  break;
1386  }
1387  }
1388  }
1389  // Close the directory
1390  closedir(dir);
1391 
1392  // If successful, remove the directory
1393  if (!rc && rmdir(path) != 0) {
1394  rc = -errno;
1395  TRACE(XERR, "problems removing"<<path<<" ; error: "<<-rc);
1396  }
1397 
1398  // Done
1399  return rc;
1400 }
1401 
1402 ////////////////////////////////////////////////////////////////////////////////
1403 /// Move content of directory at oldpath to newpath.
1404 /// The destination path 'newpath' must exist.
1405 /// Returns 0 on success, -errno of the last error on failure
1406 
1407 int XrdProofdAux::MvDir(const char *oldpath, const char *newpath)
1408 {
1409  XPDLOC(AUX, "Aux::MvDir")
1410 
1411  int rc = 0;
1412 
1413  TRACE(DBG, "oldpath "<<oldpath<<", newpath: "<<newpath);
1414 
1415  // Open existing dir
1416  DIR *dir = opendir(oldpath);
1417  if (!dir) {
1418  TRACE(XERR, "cannot open dir "<<oldpath<<" ; error: "<<errno);
1419  return -errno;
1420  }
1421 
1422  // Assert destination dir
1423  struct stat st;
1424  if (stat(newpath, &st) != 0 || !S_ISDIR(st.st_mode)) {
1425  TRACE(XERR, "destination dir "<<newpath<<
1426  " does not exist or is not a directory; errno: "<<errno);
1427  closedir(dir);
1428  return -ENOENT;
1429  }
1430 
1431  // Scan the source directory
1432  XrdOucString srcentry, dstentry;
1433  struct dirent *ent = 0;
1434  while ((ent = (struct dirent *)readdir(dir))) {
1435  // Skip the basic entries
1436  if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) continue;
1437  // Get info about the entry
1438  XPDFORM(srcentry, "%s/%s", oldpath, ent->d_name);
1439  if (stat(srcentry.c_str(), &st) != 0) {
1440  TRACE(XERR, "cannot stat entry "<<srcentry<<" ; error: "<<errno);
1441  rc = -errno;
1442  break;
1443  }
1444  // Destination entry
1445  XPDFORM(dstentry, "%s/%s", newpath, ent->d_name);
1446  // Mv directories recursively
1447  if (S_ISDIR(st.st_mode)) {
1448  mode_t srcmode = st.st_mode;
1449  // Create dest sub-dir
1450  if (mkdir(dstentry.c_str(), srcmode) != 0 && (errno != EEXIST)) {
1451  TRACE(XERR, "cannot create entry "<<dstentry<<" ; error: "<<errno);
1452  rc = -errno;
1453  break;
1454  }
1455  if ((rc = XrdProofdAux::MvDir(srcentry.c_str(), dstentry.c_str())) != 0) {
1456  TRACE(XERR, "problems moving "<<srcentry<<" to "<<dstentry<<"; error: "<<-rc);
1457  break;
1458  }
1459  if ((rc = XrdProofdAux::RmDir(srcentry.c_str())) != 0) {
1460  TRACE(XERR, "problems removing "<<srcentry<<"; error: "<<-rc);
1461  break;
1462  }
1463  } else {
1464  // Move the entry
1465  if (rename(srcentry.c_str(), dstentry.c_str()) != 0) {
1466  rc = -errno;
1467  TRACE(XERR, "problems moving "<<srcentry<<" to "<<dstentry<<"; error: "<<-rc);
1468  break;
1469  }
1470  }
1471  }
1472  // Close the directory
1473  closedir(dir);
1474 
1475  // Done
1476  return rc;
1477 }
1478 
1479 ////////////////////////////////////////////////////////////////////////////////
1480 /// Set access (opt == 1), modify (opt =2 ) or access&modify (opt = 0, default)
1481 /// times of path to current time.
1482 /// Returns 0 on success, -errno on failure
1483 
1484 int XrdProofdAux::Touch(const char *path, int opt)
1485 {
1486  if (opt == 0) {
1487  if (utime(path, 0) != 0)
1488  return -errno;
1489  } else if (opt <= 2) {
1490  struct stat st;
1491  if (stat(path, &st) != 0)
1492  return -errno;
1493  struct utimbuf ut = {0,0};
1494  if (opt == 1) {
1495  ut.actime = time(0);
1496  ut.modtime = st.st_mtime;
1497  } else if (opt == 2) {
1498  ut.modtime = time(0);
1499  ut.actime = st.st_atime;
1500  }
1501  if (utime(path, &ut) != 0)
1502  return -errno;
1503  } else {
1504  // Unknown option
1505  return -1;
1506  }
1507  // Done
1508  return 0;
1509 }
1510 
1511 ////////////////////////////////////////////////////////////////////////////////
1512 /// Receive 'msg' from pipe fd
1513 
1514 int XrdProofdAux::ReadMsg(int fd, XrdOucString &msg)
1515 {
1516  XPDLOC(AUX, "Aux::ReadMsg")
1517 
1518  msg = "";
1519  if (fd > 0) {
1520 
1521  // Read message length
1522  int len = 0;
1523  if (read(fd, &len, sizeof(len)) != sizeof(len))
1524  return -errno;
1525  TRACE(HDBG,fd<<": len: "<<len);
1526 
1527  // Read message
1528  char buf[XPD_MAXLEN];
1529  int nr = -1;
1530  do {
1531  int wanted = (len > XPD_MAXLEN-1) ? XPD_MAXLEN-1 : len;
1532  while ((nr = read(fd, buf, wanted)) < 0 &&
1533  errno == EINTR)
1534  errno = 0;
1535  if (nr < wanted) {
1536  break;
1537  } else {
1538  buf[nr] = '\0';
1539  msg += buf;
1540  }
1541  // Update counters
1542  len = (nr >= len) ? 0 : len - nr;
1543  } while (nr > 0 && len > 0);
1544 
1545  TRACE(HDBG,fd<<": buf: "<<buf);
1546 
1547  // Done
1548  return 0;
1549  }
1550  // Undefined socket
1551  TRACE(XERR, "pipe descriptor undefined: "<<fd);
1552  return -1;
1553 }
1554 
1555 ////////////////////////////////////////////////////////////////////////////////
1556 /// Parse a path in the form of "<before>[.<pid>][.<after>]", filling 'rest'
1557 /// and returning 'pid'.
1558 /// Return 0 if pid is not defined; 'before' is filled with the string preceding
1559 /// <pid>, <after> with the string following <pid>.
1560 
1561 int XrdProofdAux::ParsePidPath(const char *path,
1562  XrdOucString &before, XrdOucString &after)
1563 {
1564  XPDLOC(AUX, "ParsePidPath")
1565 
1566  before = "";
1567  after = "";
1568  long int pid = -1;
1569  if (path && strlen(path)) {
1570  pid = 0;
1571  int from = 0;
1572  XrdOucString spid, s(path);
1573  bool nopid = 1;
1574  while ((from = s.tokenize(spid, from, '.')) != -1) {
1575  if (spid.length() > 0) {
1576  if (spid.isdigit()) {
1577  // Get pid
1578  pid = (int) spid.atoi();
1579  if (!XPD_LONGOK(pid)) {
1580  // Substring is not a PID
1581  pid = 0;
1582  }
1583  }
1584  if (nopid && pid > 0) {
1585  nopid = 0;
1586  } else if (nopid) {
1587  if (before.length() > 0) before += ".";
1588  before += spid;
1589  } else {
1590  if (after.length() > 0) after += ".";
1591  after += spid;
1592  }
1593  }
1594  }
1595  if (pid == 0 && before.length() == 0) {
1596  before = after;
1597  after = "";
1598  }
1599  }
1600 
1601  TRACE(HDBG,"path: "<<(path ? path : "<nul>")<<" --> before: '"<<before
1602  <<"', pid: "<<pid<<", after: '"<<after<<"'");
1603 
1604  // Done
1605  return pid;
1606 }
1607 
1608 ////////////////////////////////////////////////////////////////////////////////
1609 /// Parse a path in the form of "<usr>[.<grp>][.<pid>]", filling 'usr' and 'grp'.
1610 /// Returns -1 on failure, 0 if the pid is not defined or the pid.
1611 
1612 int XrdProofdAux::ParseUsrGrp(const char *path, XrdOucString &usr, XrdOucString &grp)
1613 {
1614  XrdOucString rest, after;
1615  int pid = ParsePidPath(path, rest, after);
1616 
1617  if (pid >= 0 && rest.length() > 0) {
1618  // Fill 'usr' (everything until the last dot)
1619  usr = rest;
1620  int ip = STR_NPOS;
1621  if ((ip = rest.rfind('.')) != STR_NPOS) {
1622  usr.erase(ip);
1623  // Fill 'grp'
1624  grp = rest;
1625  grp.erase(0, ip + 1);
1626  }
1627  }
1628  // Done
1629  return pid;
1630 }
1631 
1632 //
1633 // Functions to process directives for integer and strings
1634 //
1635 
1636 ////////////////////////////////////////////////////////////////////////////////
1637 /// Generic class directive processor
1638 
1639 int DoDirectiveClass(XrdProofdDirective *d, char *val, XrdOucStream *cfg, bool rcf)
1640 {
1641  if (!d || !(d->fVal))
1642  // undefined inputs
1643  return -1;
1644 
1645  return ((XrdProofdConfig *)d->fVal)->DoDirective(d, val, cfg, rcf);
1646 }
1647 
1648 ////////////////////////////////////////////////////////////////////////////////
1649 /// Process directive for an integer
1650 
1651 int DoDirectiveInt(XrdProofdDirective *d, char *val, XrdOucStream *cfg, bool rcf)
1652 {
1653  XPDLOC(AUX, "DoDirectiveInt")
1654 
1655  if (!d || !(d->fVal) || !val)
1656  // undefined inputs
1657  return -1;
1658 
1659  if (rcf && !d->fRcf)
1660  // Not re-configurable: do nothing
1661  return 0;
1662 
1663  // Check deprecated 'if' directive
1664  if (d->fHost && cfg)
1665  if (XrdProofdAux::CheckIf(cfg, d->fHost) == 0)
1666  return 0;
1667 
1668  long int v = strtol(val,0,10);
1669  *((int *)d->fVal) = v;
1670 
1671  TRACE(DBG, "set "<<d->fName<<" to "<<*((int *)d->fVal));
1672 
1673  return 0;
1674 }
1675 
1676 ////////////////////////////////////////////////////////////////////////////////
1677 /// Process directive for a string
1678 
1679 int DoDirectiveString(XrdProofdDirective *d, char *val, XrdOucStream *cfg, bool rcf)
1680 {
1681  XPDLOC(AUX, "DoDirectiveString")
1682 
1683  if (!d || !(d->fVal) || !val)
1684  // undefined inputs
1685  return -1;
1686 
1687  if (rcf && !d->fRcf)
1688  // Not re-configurable: do nothing
1689  return 0;
1690 
1691  // Check deprecated 'if' directive
1692  if (d->fHost && cfg)
1693  if (XrdProofdAux::CheckIf(cfg, d->fHost) == 0)
1694  return 0;
1695 
1696  *((XrdOucString *)d->fVal) = val;
1697 
1698  TRACE(DBG, "set "<<d->fName<<" to "<<*((XrdOucString *)d->fVal));
1699  return 0;
1700 }
1701 
1702 ////////////////////////////////////////////////////////////////////////////////
1703 /// Set host field for directive 'd' to (const char *h)
1704 
1705 int SetHostInDirectives(const char *, XrdProofdDirective *d, void *h)
1706 {
1707  const char *host = (const char *)h;
1708 
1709  if (!d || !host || strlen(host) <= 0)
1710  // Dataset root dir undefined: we cannot continue
1711  return 1;
1712 
1713  d->fHost = host;
1714 
1715  // Process next
1716  return 0;
1717 }
1718 
1719 //
1720 // XrdProofdPipe: class implementing pipe functionality
1721 //
1722 ////////////////////////////////////////////////////////////////////////////////
1723 /// Constructor: create the pipe
1724 
1726 {
1727  // Init pipe for the poller
1728  if (pipe(fPipe) != 0) {
1729  fPipe[0] = -1;
1730  fPipe[1] = -1;
1731  }
1732 }
1733 
1734 ////////////////////////////////////////////////////////////////////////////////
1735 /// Destructor
1736 
1738 {
1739  // Close the pipe
1740  Close();
1741 }
1742 
1743 ////////////////////////////////////////////////////////////////////////////////
1744 /// If open, close and invalidated the pipe descriptors
1745 
1747 {
1748  if (IsValid()) {
1749  close(fPipe[0]);
1750  close(fPipe[1]);
1751  fPipe[0] = -1;
1752  fPipe[1] = -1;
1753  }
1754 }
1755 
1756 ////////////////////////////////////////////////////////////////////////////////
1757 /// Post message on the pipe
1758 
1759 int XrdProofdPipe::Post(int type, const char *msg)
1760 {
1761  XPDLOC(AUX, "Pipe::Post")
1762 
1763 
1764  if (IsValid()) {
1765  XrdOucString buf;
1766  if (msg && strlen(msg) > 0) {
1767  XPDFORM(buf, "%d %s", type, msg);
1768  } else {
1769  buf += type;
1770  }
1771  TRACE(HDBG, fPipe[1] << ": posting: type: "<<type<<", buf: "<<buf);
1772  int len = buf.length() + 1;
1774  if (write(fPipe[1], &len, sizeof(len)) != sizeof(len))
1775  return -errno;
1776  if (write(fPipe[1], buf.c_str(), len) != len)
1777  return -errno;
1778  // Done
1779  return 0;
1780  }
1781  // Invalid pipe
1782  TRACE(XERR, "pipe is invalid");
1783  return -1;
1784 }
1785 
1786 ////////////////////////////////////////////////////////////////////////////////
1787 /// Recv message from the pipe
1788 
1790 {
1791  XPDLOC(AUX, "Pipe::Recv")
1792 
1793  if (IsValid()) {
1794  XrdOucString buf;
1795  { XrdSysMutexHelper mh(fRdMtx);
1796  if (XrdProofdAux::ReadMsg(fPipe[0], buf) != 0)
1797  return -1;
1798  }
1799  TRACE(HDBG, fPipe[0] << ": receiving: msg: "<< buf);
1800  msg.Init(buf.c_str());
1801  // Done
1802  return 0;
1803  }
1804  // Invalid pipe
1805  TRACE(XERR, "pipe is invalid");
1806  return -1;
1807 }
1808 
1809 ////////////////////////////////////////////////////////////////////////////////
1810 /// Poll over the read pipe for to secs; return whatever poll returns
1811 
1813 {
1814  XPDLOC(AUX, "Pipe::Poll")
1815 
1816  if (IsValid()) {
1817 
1818  // Read descriptor
1819  struct pollfd fds_r;
1820  fds_r.fd = fPipe[0];
1821  fds_r.events = POLLIN;
1822 
1823  // We wait for processes to communicate a session status change
1824  int pollrc = 0;
1825  int xto = (to > 0) ? to * 1000 : -1;
1826  while ((pollrc = poll(&fds_r, 1, xto)) < 0 && (errno == EINTR)) {
1827  errno = 0;
1828  }
1829  // Done
1830  return (pollrc >= 0) ? pollrc : -errno;
1831  }
1832  // Invalid pipe
1833  TRACE(XERR, "pipe is invalid");
1834  return -1;
1835 }
1836 
1837 //
1838 // XpdMsg: class to handle messages received over the pipe
1839 //
1840 ////////////////////////////////////////////////////////////////////////////////
1841 /// Init from buffer
1842 
1843 int XpdMsg::Init(const char *buf)
1844 {
1845  XPDLOC(AUX, "Msg::Init")
1846 
1847  fType = -1;
1848  fBuf = "";
1849  fFrom = -1;
1850 
1851  TRACE(HDBG, "buf: "<< (const char *)(buf ? buf : "+++ empty +++"));
1852 
1853  if (buf && strlen(buf) > 0) {
1854  fBuf = buf;
1855  fFrom = 0;
1856  // Extract the type
1857  XrdOucString ctyp;
1858  if ((fFrom = fBuf.tokenize(ctyp, fFrom, ' ')) == -1 || ctyp.length() <= 0) {
1859  TRACE(XERR, "ctyp: "<<ctyp<<" fFrom: "<<fFrom);
1860  fBuf = "";
1861  fFrom = -1;
1862  return -1;
1863  }
1864  fType = ctyp.atoi();
1865  if (!XPD_LONGOK(fType)) {
1866  TRACE(XERR, "ctyp: "<<ctyp<<" fType: "<<fType);
1867  fBuf = "";
1868  fFrom = -1;
1869  return -1;
1870  }
1871  fBuf.erase(0,fFrom);
1872  while (fBuf.beginswith(' '))
1873  fBuf.erase(0, 1);
1874  fFrom = 0;
1875  TRACE(HDBG, fType<<", "<<fBuf);
1876  }
1877  // Done
1878  return 0;
1879 }
1880 
1881 ////////////////////////////////////////////////////////////////////////////////
1882 /// Get next token and interpret it as an int
1883 
1884 int XpdMsg::Get(int &i)
1885 {
1886  XPDLOC(AUX, "Msg::Get")
1887 
1888  TRACE(HDBG,"int &i: "<<fFrom<<" "<<fBuf);
1889 
1890  int iold = i;
1891  XrdOucString tkn;
1892  if ((fFrom = fBuf.tokenize(tkn, fFrom, ' ')) == -1 || tkn.length() <= 0)
1893  return -1;
1894  i = tkn.atoi();
1895  if (!XPD_LONGOK(i)) {
1896  TRACE(XERR, "tkn: "<<tkn<<" i: "<<i);
1897  i = iold;
1898  return -1;
1899  }
1900  // Done
1901  return 0;
1902 }
1903 
1904 ////////////////////////////////////////////////////////////////////////////////
1905 /// Get next token
1906 
1907 int XpdMsg::Get(XrdOucString &s)
1908 {
1909  XPDLOC(AUX, "Msg::Get")
1910 
1911  TRACE(HDBG,"XrdOucString &s: "<<fFrom<<" "<<fBuf);
1912 
1913  if ((fFrom = fBuf.tokenize(s, fFrom, ' ')) == -1 || s.length() <= 0) {
1914  TRACE(XERR, "s: "<<s<<" fFrom: "<<fFrom);
1915  return -1;
1916  }
1917 
1918  // Done
1919  return 0;
1920 }
1921 
1922 ////////////////////////////////////////////////////////////////////////////////
1923 /// Get next token and interpret it as a pointer
1924 
1925 int XpdMsg::Get(void **p)
1926 {
1927  XPDLOC(AUX, "Msg::Get")
1928 
1929  TRACE(HDBG,"void **p: "<<fFrom<<" "<<fBuf);
1930 
1931  XrdOucString tkn;
1932  if ((fFrom = fBuf.tokenize(tkn, fFrom, ' ')) == -1 || tkn.length() <= 0) {
1933  TRACE(XERR, "tkn: "<<tkn<<" fFrom: "<<fFrom);
1934  return -1;
1935  }
1936  sscanf(tkn.c_str(), "%p", p);
1937 
1938  // Done
1939  return 0;
1940 }
1941 
1942 
1943 //
1944 // Class to handle condensed multi-string specification, e.g <head>[01-25]<tail>
1945 //
1946 
1947 ////////////////////////////////////////////////////////////////////////////////
1948 /// Init the multi-string handler.
1949 /// Supported formats:
1950 /// <head>[1-4]<tail> for <head>1<tail>, ..., <head>4<tail> (4 items)
1951 /// <head>[a,b]<tail> for <head>a<tail>, <head>b<tail> (2 items)
1952 /// <head>[a,1-3]<tail> for <head>a<tail>, <head>1<tail>, <head>2<tail>,
1953 /// <head>3<tail> (4 items)
1954 /// <head>[01-15]<tail> for <head>01<tail>, ..., <head>15<tail> (15 items)
1955 ///
1956 /// A dashed is possible only between numerically treatable values, i.e.
1957 /// single letters ([a-Z] will take all tokens between 'a' and 'Z') or n-field
1958 /// numbers ([001-999] will take all numbers 1 to 999 always using 3 spaces).
1959 /// Mixed values (e.g. [a-034]) are not allowed.
1960 
1961 void XrdProofdMultiStr::Init(const char *s)
1962 {
1963  fN = 0;
1964  if (s && strlen(s)) {
1965  XrdOucString kernel(s);
1966  // Find begin of kernel
1967  int ib = kernel.find('[');
1968  if (ib == STR_NPOS) return;
1969  // Find end of kernel
1970  int ie = kernel.find(']', ib + 1);
1971  if (ie == STR_NPOS) return;
1972  // Check kernel length (it must not be empty)
1973  if (ie == ib + 1) return;
1974  // Fill head and tail
1975  fHead.assign(kernel, 0, ib -1);
1976  fTail.assign(kernel, ie + 1);
1977  // The rest is the kernel
1978  XrdOucString tkns(kernel, ib + 1, ie - 1);
1979  // Tokenize the kernel filling the list
1980  int from = 0;
1981  XrdOucString tkn;
1982  while ((from = tkns.tokenize(tkn, from, ',')) != -1) {
1983  if (tkn.length() > 0) {
1984  XrdProofdMultiStrToken t(tkn.c_str());
1985  if (t.IsValid()) {
1986  fN += t.N();
1987  fTokens.push_back(t);
1988  }
1989  }
1990  }
1991  // Reset everything if nothing found
1992  if (!IsValid()) {
1993  fHead = "";
1994  fTail = "";
1995  }
1996  }
1997 }
1998 
1999 ////////////////////////////////////////////////////////////////////////////////
2000 /// Return true if 's' is compatible with this multi-string
2001 
2002 bool XrdProofdMultiStr::Matches(const char *s)
2003 {
2004  if (s && strlen(s)) {
2005  XrdOucString str(s);
2006  if (fHead.length() <= 0 || str.beginswith(fHead)) {
2007  if (fTail.length() <= 0 || str.endswith(fTail)) {
2008  str.replace(fHead,"");
2009  str.replace(fTail,"");
2010  std::list<XrdProofdMultiStrToken>::iterator it = fTokens.begin();
2011  for (; it != fTokens.end(); it++) {
2012  if ((*it).Matches(str.c_str()))
2013  return 1;
2014  }
2015  }
2016  }
2017  }
2018  // Done
2019  return 0;
2020 }
2021 
2022 ////////////////////////////////////////////////////////////////////////////////
2023 /// Return a string with comma-separated elements
2024 
2026 {
2027  XrdOucString str(fN * (fHead.length() + fTail.length() + 4)) ;
2028  str = "";
2029  if (fN > 0) {
2030  std::list<XrdProofdMultiStrToken>::iterator it = fTokens.begin();
2031  for (; it != fTokens.end(); it++) {
2032  int n = (*it).N(), j = -1;
2033  while (n--) {
2034  str += fHead;
2035  str += (*it).Export(j);
2036  str += fTail;
2037  str += ",";
2038  }
2039  }
2040  }
2041  // Remove last ','
2042  if (str.endswith(','))
2043  str.erase(str.rfind(','));
2044  // Done
2045  return str;
2046 }
2047 
2048 ////////////////////////////////////////////////////////////////////////////////
2049 /// Return i-th combination (i : 0 -> fN-1)
2050 
2051 XrdOucString XrdProofdMultiStr::Get(int i)
2052 {
2053  XrdOucString str;
2054 
2055  if (i >= 0) {
2056  std::list<XrdProofdMultiStrToken>::iterator it = fTokens.begin();
2057  for (; it != fTokens.end(); it++) {
2058  int n = (*it).N(), j = -1;
2059  if ((i + 1) > n) {
2060  i -= n;
2061  } else {
2062  j = i;
2063  str = fHead;
2064  str += (*it).Export(j);
2065  str += fTail;
2066  break;
2067  }
2068  }
2069  }
2070 
2071  // Done
2072  return str;
2073 }
2074 
2075 ////////////////////////////////////////////////////////////////////////////////
2076 /// Init the multi-string token.
2077 /// Supported formats:
2078 /// [1-4] for 1, ..., 4 (4 items)
2079 /// [a,b] for a, b<tail> (2 items)
2080 /// [a,1-3] for a, 1, 2, 3 (4 items)
2081 /// [01-15] for 01, ..., 15 (15 items)
2082 ///
2083 /// A dashed is possible only between numerically treatable values, i.e.
2084 /// single letters ([a-Z] will take all tokens between 'a' and 'Z') or n-field
2085 /// numbers ([001-999] will take all numbers 1 to 999 always using 3 spaces).
2086 /// Mixed values (e.g. [a-034]) are not allowed.
2087 
2088 void XrdProofdMultiStrToken::Init(const char *s)
2089 {
2090  XPDLOC(AUX, "MultiStrToken::Init")
2091 
2092  fIa = LONG_MAX;
2093  fIb = LONG_MAX;
2094  fType = kUndef;
2095  fN = 0;
2096  bool bad = 0;
2097  XrdOucString emsg;
2098  if (s && strlen(s)) {
2099  fA = s;
2100  // Find the dash, if any
2101  int id = fA.find('-');
2102  if (id == STR_NPOS) {
2103  // Simple token, nothing much to do
2104  fN = 1;
2105  fType = kSimple;
2106  return;
2107  }
2108  // Define the extremes
2109  fB.assign(fA, id + 1);
2110  fA.erase(id);
2111  if (fB.length() <= 0) {
2112  if (fA.length() > 0) {
2113  // Simple token, nothing much to do
2114  fN = 1;
2115  fType = kSimple;
2116  }
2117  // Invalid
2118  return;
2119  }
2120  // Check validity
2121  char *a = (char *)fA.c_str();
2122  char *b = (char *)fB.c_str();
2123  if (fA.length() == 1 && fB.length() == 1) {
2124  LETTOIDX(*a, fIa);
2125  if (fIa != LONG_MAX) {
2126  LETTOIDX(*b, fIb);
2127  if (fIb != LONG_MAX && fIa <= fIb) {
2128  // Ordered single-letter extremes: OK
2129  fType = kLetter;
2130  fN = fIb - fIa + 1;
2131  return;
2132  }
2133  } else if (DIGIT(*a) && DIGIT(*b) &&
2134  (fIa = *a) <= (fIb = *b)) {
2135  // Ordered single-digit extremes: OK
2136  fType = kDigit;
2137  fN = fIb - fIa + 1;
2138  return;
2139  }
2140  // Not-supported single-field extremes
2141  emsg = "not-supported single-field extremes";
2142  bad = 1;
2143  }
2144  if (!bad) {
2145  fIa = fA.atoi();
2146  if (fIa != LONG_MAX && fIa != LONG_MIN) {
2147  fIb = fB.atoi();
2148  if (fIb != LONG_MAX && fIb != LONG_MIN && fIb >= fIa) {
2149  fType = kDigits;
2150  fN = fIb - fIa + 1;
2151  return;
2152  }
2153  // Not-supported single-field extremes
2154  emsg = "non-digit or wrong-ordered extremes";
2155  bad = 1;
2156  } else {
2157  // Not-supported single-field extremes
2158  emsg = "non-digit extremes";
2159  bad = 1;
2160  }
2161  }
2162  }
2163  // Print error message, if any
2164  if (bad) {
2165  TRACE(XERR, emsg);
2166  fA = "";
2167  fB = "";
2168  fIa = LONG_MAX;
2169  fIb = LONG_MAX;
2170  }
2171  // Done
2172  return;
2173 }
2174 
2175 ////////////////////////////////////////////////////////////////////////////////
2176 /// Return true if 's' is compatible with this token
2177 
2179 {
2180  if (s && strlen(s)) {
2181  if (fType == kSimple)
2182  return ((fA == s) ? 1 : 0);
2183  // Multiple one: parse it
2184  XrdOucString str(s);
2185  long ls = LONG_MIN;
2186  if (fType != kDigits) {
2187  if (str.length() > 1)
2188  return 0;
2189  char *ps = (char *)s;
2190  if (fType == kDigit) {
2191  if (!DIGIT(*ps) || *ps < fIa || *ps > fIb)
2192  return 0;
2193  } else if (fType == kLetter) {
2194  LETTOIDX(*ps, ls);
2195  if (ls == LONG_MAX || ls < fIa || ls > fIb)
2196  return 0;
2197  }
2198  } else {
2199  ls = str.atoi();
2200  if (ls == LONG_MAX || ls < fIa || ls > fIb)
2201  return 0;
2202  }
2203  // OK
2204  return 1;
2205  }
2206  // Undefined
2207  return 0;
2208 }
2209 
2210 ////////////////////////////////////////////////////////////////////////////////
2211 /// Export 'next' token; use next < 0 start from the first
2212 
2214 {
2215  XrdOucString tkn(fA.length());
2216 
2217  // If simple, return the one we have
2218  if (fType == kSimple)
2219  return (tkn = fA);
2220 
2221  // Check if we still have something
2222  if (next > fIb - fIa)
2223  return tkn;
2224 
2225  // Check where we are
2226  if (next == -1)
2227  next = 0;
2228 
2229  // If letters we need to found the right letter
2230  if (fType == kLetter) {
2231  char c = 0;
2232  IDXTOLET(fIa + next, c);
2233  next++;
2234  return (tkn = c);
2235  }
2236 
2237  // If single digit, add the offset
2238  if (fType == kDigit) {
2239  tkn = (char)(fIa + next);
2240  next++;
2241  return tkn;
2242  }
2243 
2244  // If digits, check if we need to pad 0's
2245  XrdOucString tmp(fA.length());
2246  tmp.form("%ld", fIa + next);
2247  next++;
2248  int dl = fA.length() - tmp.length();
2249  if (dl <= 0) return tmp;
2250  // Add padding 0's
2251  tkn = "";
2252  while (dl--) tkn += "0";
2253  tkn += tmp;
2254  return tkn;
2255 }
2256 
2257 ////////////////////////////////////////////////////////////////////////////////
2258 /// Recreate the string according to 'fmt', the up to 5 'const char *',
2259 /// up to 6 'int' arguments, up to 5 'void *' and up to 1 unsigned integer.
2260 
2261 void XrdProofdAux::Form(XrdOucString &s, const char *fmt,
2262  int ns, const char *ss[5],
2263  int ni, int ii[6],
2264  int np, void *pp[5],
2265  int nu, unsigned int ui)
2266 {
2267  int len = 0;
2268  if (!fmt || (len = strlen(fmt)) <= 0) return;
2269 
2270  char si[32], sp[32];
2271 
2272  // Estimate length
2273  int i = ns;
2274  while (i-- > 0) { if (ss[i]) { len += strlen(ss[i]); } }
2275  i = ni + np;
2276  while (i-- > 0) { len += 32; }
2277 
2278  s.resize(len+1);
2279 
2280  int from = 0;
2281  s.assign(fmt, from);
2282  int nii = 0, nss = 0, npp = 0, nui = 0;
2283  int k = STR_NPOS;
2284  while ((k = s.find('%', from)) != STR_NPOS) {
2285  bool replaced = 0;
2286  if (s[k+1] == 's') {
2287  if (nss < ns) {
2288  s.replace("%s", ss[nss++], k, k + 1);
2289  replaced = 1;
2290  }
2291  } else if (s[k+1] == 'd') {
2292  if (nii < ni) {
2293  snprintf(si, 32, "%d", ii[nii++]);
2294  s.replace("%d", si, k, k + 1);
2295  replaced = 1;
2296  }
2297  } else if (s[k+1] == 'u') {
2298  if (nui < nu) {
2299  snprintf(si, 32, "%u", ui);
2300  s.replace("%u", si, k, k + 1);
2301  replaced = 1;
2302  }
2303  } else if (s[k+1] == 'p') {
2304  if (npp < np) {
2305  snprintf(sp, 32, "%p", pp[npp++]);
2306  s.replace("%p", sp, k, k + 1);
2307  replaced = 1;
2308  }
2309  }
2310  if (!replaced) from = k + 1;
2311  }
2312 }
2313 
2314 ////////////////////////////////////////////////////////////////////////////////
2315 /// Recreate the string according to 'fmt' and the 5 'const char *' arguments
2316 
2317 void XrdProofdAux::Form(XrdOucString &s, const char *fmt,
2318  const char *s0, const char *s1,
2319  const char *s2, const char *s3, const char *s4)
2320 {
2321  const char *ss[5] = {s0, s1, s2, s3, s4};
2322  int ii[6] = {0,0,0,0,0,0};
2323  void *pp[5] = {0,0,0,0,0};
2324 
2325  XrdProofdAux::Form(s,fmt,5,ss,0,ii,0,pp);
2326 }
2327 
2328 ////////////////////////////////////////////////////////////////////////////////
2329 /// Recreate the string according to 'fmt' and the 5 'int' arguments
2330 
2331 void XrdProofdAux::Form(XrdOucString &s, const char *fmt, int i0,
2332  int i1, int i2, int i3, int i4, int i5)
2333 {
2334  const char *ss[5] = {0, 0, 0, 0, 0};
2335  int ii[6] = {i0,i1,i2,i3,i4,i5};
2336  void *pp[5] = {0,0,0,0,0};
2337 
2338  XrdProofdAux::Form(s,fmt,0,ss,6,ii,5,pp);
2339 }
2340 
2341 ////////////////////////////////////////////////////////////////////////////////
2342 /// Recreate the string according to 'fmt' and the 5 'void *' arguments
2343 
2344 void XrdProofdAux::Form(XrdOucString &s, const char *fmt,
2345  void *p0, void *p1, void *p2, void *p3, void *p4)
2346 {
2347  const char *ss[5] = {0, 0, 0, 0, 0};
2348  int ii[6] = {0,0,0,0,0,0};
2349  void *pp[5] = {p0,p1,p2,p3,p4};
2350 
2351  XrdProofdAux::Form(s,fmt,0,ss,0,ii,5,pp);
2352 }
2353 
2354 
2355 ////////////////////////////////////////////////////////////////////////////////
2356 /// Recreate the string according to 'fmt' and the 5 'void *' arguments
2357 
2358 void XrdProofdAux::Form(XrdOucString &s, const char *fmt, int i0, const char *s0,
2359  const char *s1, const char *s2, const char *s3)
2360 {
2361  const char *ss[5] = {s0, s1, s2, s3, 0};
2362  int ii[6] = {i0,0,0,0,0,0};
2363  void *pp[5] = {0,0,0,0,0};
2364 
2365  XrdProofdAux::Form(s,fmt,4,ss,1,ii,0,pp);
2366 }
2367 
2368 ////////////////////////////////////////////////////////////////////////////////
2369 /// Recreate the string according to 'fmt' and the 5 'void *' arguments
2370 
2371 void XrdProofdAux::Form(XrdOucString &s, const char *fmt, const char *s0,
2372  int i0, int i1, int i2, int i3)
2373 {
2374  const char *ss[5] = {s0,0,0,0,0};
2375  int ii[6] = {i0,i1,i2,i3,0,0};
2376  void *pp[5] = {0,0,0,0,0};
2377 
2378  XrdProofdAux::Form(s,fmt,1,ss,4,ii,0,pp);
2379 }
2380 
2381 ////////////////////////////////////////////////////////////////////////////////
2382 /// Recreate the string according to 'fmt' and the 5 'void *' arguments
2383 
2384 void XrdProofdAux::Form(XrdOucString &s, const char *fmt, const char *s0,
2385  int i0, int i1, unsigned int ui)
2386 {
2387  const char *ss[5] = {s0,0,0,0,0};
2388  int ii[6] = {i0,i1,0,0,0,0};
2389  void *pp[5] = {0,0,0,0,0};
2390 
2391  XrdProofdAux::Form(s,fmt,1,ss,2,ii,0,pp, 1, ui);
2392 }
2393 
2394 ////////////////////////////////////////////////////////////////////////////////
2395 /// Recreate the string according to 'fmt' and the 5 'void *' arguments
2396 
2397 void XrdProofdAux::Form(XrdOucString &s, const char *fmt, const char *s0, const char *s1,
2398  int i0, int i1, int i2)
2399 {
2400  const char *ss[5] = {s0,s1,0,0,0};
2401  int ii[6] = {i0,i1,i2,0,0,0};
2402  void *pp[5] = {0,0,0,0,0};
2403 
2404  XrdProofdAux::Form(s,fmt,2,ss,3,ii,0,pp);
2405 }
2406 
2407 ////////////////////////////////////////////////////////////////////////////////
2408 /// Recreate the string according to 'fmt' and the 5 'void *' arguments
2409 
2410 void XrdProofdAux::Form(XrdOucString &s, const char *fmt, int i0, int i1,
2411  const char *s0, const char *s1, const char *s2)
2412 {
2413  const char *ss[5] = {s0,s1,s2,0,0};
2414  int ii[6] = {i0,i1,0,0,0,0};
2415  void *pp[5] = {0,0,0,0,0};
2416 
2417  XrdProofdAux::Form(s,fmt,3,ss,2,ii,0,pp);
2418 }
2419 
2420 
2421 ////////////////////////////////////////////////////////////////////////////////
2422 /// Recreate the string according to 'fmt' and the 5 'void *' arguments
2423 
2424 void XrdProofdAux::Form(XrdOucString &s, const char *fmt, const char *s0,
2425  const char *s1, const char *s2,
2426  int i0, int i1,
2427  const char *s3, const char *s4)
2428 {
2429  const char *ss[5] = {s0,s1,s2,s3,s4};
2430  int ii[6] = {i0,i1,0,0,0,0};
2431  void *pp[5] = {0,0,0,0,0};
2432 
2433  XrdProofdAux::Form(s,fmt,5,ss,2,ii,0,pp);
2434 }
2435 
2436 ////////////////////////////////////////////////////////////////////////////////
2437 /// Recreate the string according to 'fmt' and the 5 'void *' arguments
2438 
2439 void XrdProofdAux::Form(XrdOucString &s, const char *fmt, const char *s0,
2440  int i0, int i1, const char *s1,
2441  const char *s2, const char *s3)
2442 {
2443  const char *ss[5] = {s0,s1,s2,s3,0};
2444  int ii[6] = {i0,i1,0,0,0,0};
2445  void *pp[5] = {0,0,0,0,0};
2446 
2447  XrdProofdAux::Form(s,fmt,4,ss,2,ii,0,pp);
2448 }
2449 
2450 ////////////////////////////////////////////////////////////////////////////////
2451 /// Recreate the string according to 'fmt' and the 5 'void *' arguments
2452 
2453 void XrdProofdAux::Form(XrdOucString &s, const char *fmt, const char *s0,
2454  const char *s1, const char *s2,
2455  int i0, unsigned int ui)
2456 {
2457  const char *ss[5] = {s0,s1,s2,0,0};
2458  int ii[6] = {i0,0,0,0,0,0};
2459  void *pp[5] = {0,0,0,0,0};
2460 
2461  XrdProofdAux::Form(s,fmt,3,ss,1,ii,0,pp, 1, ui);
2462 }
2463 
2464 ////////////////////////////////////////////////////////////////////////////////
2465 /// Recreate the string according to 'fmt' and the 5 'void *' arguments
2466 
2467 void XrdProofdAux::Form(XrdOucString &s, const char *fmt, int i0, int i1, int i2,
2468  const char *s0, const char *s1)
2469 {
2470  const char *ss[5] = {s0,s1,0,0,0};
2471  int ii[6] = {i0,i1,i2,0,0,0};
2472  void *pp[5] = {0,0,0,0,0};
2473 
2474  XrdProofdAux::Form(s,fmt,2,ss,3,ii,0,pp);
2475 }
2476 
2477 
2478 ////////////////////////////////////////////////////////////////////////////////
2479 /// Recreate the string according to 'fmt' and the 5 'void *' arguments
2480 
2481 void XrdProofdAux::Form(XrdOucString &s, const char *fmt, const char *s0,
2482  const char *s1, const char *s2, const char *s3, int i0)
2483 {
2484  const char *ss[5] = {s0,s1,s2,s3,0};
2485  int ii[6] = {i0,0,0,0,0,0};
2486  void *pp[5] = {0,0,0,0,0};
2487 
2488  XrdProofdAux::Form(s,fmt,4,ss,1,ii,0,pp);
2489 }
2490 
2491 ////////////////////////////////////////////////////////////////////////////////
2492 /// Recreate the string according to 'fmt' and the 5 'void *' arguments
2493 
2494 void XrdProofdAux::Form(XrdOucString &s, const char *fmt, int i0, int i1, int i2,
2495  int i3, const char *s0)
2496 {
2497  const char *ss[5] = {s0,0,0,0,0};
2498  int ii[6] = {i0,i1,i2,i3,0,0};
2499  void *pp[5] = {0,0,0,0,0};
2500 
2501  XrdProofdAux::Form(s,fmt,1,ss,4,ii,0,pp);
2502 }
2503 
2504 ////////////////////////////////////////////////////////////////////////////////
2505 /// Recreate the string according to 'fmt' and the 5 'void *' arguments
2506 
2507 void XrdProofdAux::Form(XrdOucString &s, const char *fmt, int i0, int i1, void *p0)
2508 {
2509  const char *ss[5] = {0,0,0,0,0};
2510  int ii[6] = {i0,i1,0,0,0,0};
2511  void *pp[5] = {p0,0,0,0,0};
2512 
2513  XrdProofdAux::Form(s,fmt,0,ss,2,ii,1,pp);
2514 }
2515 
2516 ////////////////////////////////////////////////////////////////////////////////
2517 /// Recreate the string according to 'fmt' and the 5 'void *' arguments
2518 
2519 void XrdProofdAux::Form(XrdOucString &s, const char *fmt,
2520  int i0, int i1, int i2, void *p0)
2521 {
2522  const char *ss[5] = {0,0,0,0,0};
2523  int ii[6] = {i0,i1,i2,0,0,0};
2524  void *pp[5] = {p0,0,0,0,0};
2525 
2526  XrdProofdAux::Form(s,fmt,0,ss,3,ii,1,pp);
2527 }
2528 
2529 ////////////////////////////////////////////////////////////////////////////////
2530 /// Recreate the string according to 'fmt' and the 5 'void *' arguments
2531 
2532 void XrdProofdAux::Form(XrdOucString &s, const char *fmt,
2533  int i0, int i1, int i2, int i3, void *p0)
2534 {
2535  const char *ss[5] = {0,0,0,0,0};
2536  int ii[6] = {i0,i1,i2,i3,0,0};
2537  void *pp[5] = {p0,0,0,0,0};
2538 
2539  XrdProofdAux::Form(s,fmt,0,ss,4,ii,1,pp);
2540 }
2541 
2542 ////////////////////////////////////////////////////////////////////////////////
2543 /// Recreate the string according to 'fmt' and the 5 'void *' arguments
2544 
2545 void XrdProofdAux::Form(XrdOucString &s, const char *fmt, int i0, int i1,
2546  void *p0, int i2, int i3)
2547 {
2548  const char *ss[5] = {0,0,0,0,0};
2549  int ii[6] = {i0,i1,i2,i3,0,0};
2550  void *pp[5] = {p0,0,0,0,0};
2551 
2552  XrdProofdAux::Form(s,fmt,0,ss,4,ii,1,pp);
2553 }
2554 
2555 ////////////////////////////////////////////////////////////////////////////////
2556 /// Recreate the string according to 'fmt' and the 5 'void *' arguments
2557 
2558 void XrdProofdAux::Form(XrdOucString &s, const char *fmt, void *p0, int i0, int i1)
2559 {
2560  const char *ss[5] = {0,0,0,0,0};
2561  int ii[6] = {i0,i1,0,0,0,0};
2562  void *pp[5] = {p0,0,0,0,0};
2563 
2564  XrdProofdAux::Form(s,fmt,0,ss,2,ii,1,pp);
2565 }
2566 
2567 ////////////////////////////////////////////////////////////////////////////////
2568 /// Recreate the string according to 'fmt' and the 5 'void *' arguments
2569 
2570 void XrdProofdAux::Form(XrdOucString &s, const char *fmt,
2571  const char *s0, void *p0, int i0, int i1)
2572 {
2573  const char *ss[5] = {s0,0,0,0,0};
2574  int ii[6] = {i0,i1,0,0,0,0};
2575  void *pp[5] = {p0,0,0,0,0};
2576 
2577  XrdProofdAux::Form(s,fmt,1,ss,2,ii,1,pp);
2578 }
2579 
2580 ////////////////////////////////////////////////////////////////////////////////
2581 /// Recreate the string according to 'fmt' and the 5 'void *' arguments
2582 
2583 void XrdProofdAux::Form(XrdOucString &s, const char *fmt,
2584  void *p0, const char *s0, int i0)
2585 {
2586  const char *ss[5] = {s0,0,0,0,0};
2587  int ii[6] = {i0,0,0,0,0,};
2588  void *pp[5] = {p0,0,0,0,0};
2589 
2590  XrdProofdAux::Form(s,fmt,1,ss,1,ii,1,pp);
2591 }
2592 
2593 ////////////////////////////////////////////////////////////////////////////////
2594 /// Recreate the string according to 'fmt' and the 5 'void *' arguments
2595 
2596 void XrdProofdAux::Form(XrdOucString &s, const char *fmt,
2597  const char *s0, const char *s1, void *p0)
2598 {
2599  const char *ss[5] = {s0,s1,0,0,0};
2600  int ii[6] = {0,0,0,0,0,0};
2601  void *pp[5] = {p0,0,0,0,0};
2602 
2603  XrdProofdAux::Form(s,fmt,2,ss,0,ii,1,pp);
2604 }
2605 
2606 ////////////////////////////////////////////////////////////////////////////////
2607 /// Recreate the string according to 'fmt' and the 5 'void *' arguments
2608 
2609 void XrdProofdAux::Form(XrdOucString &s, const char *fmt, int i0,
2610  const char *s0, const char *s1, int i1, int i2)
2611 {
2612  const char *ss[5] = {s0,s1,0,0,0};
2613  int ii[6] = {i0,i1,i2,0,0,0};
2614  void *pp[5] = {0,0,0,0,0};
2615 
2616  XrdProofdAux::Form(s,fmt,2,ss,3,ii,0,pp);
2617 }
2618 
2619 ////////////////////////////////////////////////////////////////////////////////
2620 /// Recreate the string according to 'fmt' and the 5 'void *' arguments
2621 
2622 void XrdProofdAux::Form(XrdOucString &s, const char *fmt, int i0,
2623  const char *s0, int i1, int i2)
2624 {
2625  const char *ss[5] = {s0,0,0,0,0};
2626  int ii[6] = {i0,i1,i2,0,0,0};
2627  void *pp[5] = {0,0,0,0,0};
2628 
2629  XrdProofdAux::Form(s,fmt,1,ss,3,ii,0,pp);
2630 }
2631 
double read(const std::string &file_name)
reading
static int GetNumCPUs()
Find out and return the number of CPUs in the local machine.
#define XPD_MAXLEN
#define XrdSysLogger
Definition: XpdSysLogger.h:8
static int Write(int fd, const void *buf, size_t nb)
Write nb bytes at buf to descriptor 'fd' ignoring interrupts Return the number of bytes written or -1...
int pw_uid
Definition: TWinNTSystem.h:52
int DoDirectiveInt(XrdProofdDirective *d, char *val, XrdOucStream *cfg, bool rcf)
Process directive for an integer.
int Poll(int to=-1)
Poll over the read pipe for to secs; return whatever poll returns.
int fType
Definition: XrdProofdAux.h:178
static int AssertBaseDir(const char *path, XrdProofUI ui)
Make sure that the base dir of 'path' is either owned by 'ui' or gives full permissions to 'ui'...
static double p3(double t, double a, double b, double c, double d)
double write(int n, const std::string &file_name, const std::string &vector_type, int compress=0)
writing
ClassImp(TSeqCollection) Int_t TSeqCollection TIter next(this)
Return index of object in collection.
TLine * line
static int GetUserInfo(const char *usr, XrdProofUI &ui)
Get information about user 'usr' in a thread safe way.
int gr_gid
Definition: TWinNTSystem.h:64
static const char * AdminMsgType(int type)
Translates the admin message type in a human readable string.
XrdSysRecMutex fWrMtx
Definition: XrdProofdAux.h:202
TH1 * h
Definition: legend2.C:5
static int RmDir(const char *path)
Remove directory at path and its content.
XrdOucString fBuf
Definition: XrdProofdAux.h:179
char * gr_name
Definition: TWinNTSystem.h:62
#define XrdSysRecMutex
Definition: XrdSysToOuc.h:18
int DoDirectiveClass(XrdProofdDirective *d, char *val, XrdOucStream *cfg, bool rcf)
Generic class directive processor.
#define TRACE(Flag, Args)
Definition: TGHtml.h:124
int Init(const char *buf)
Init from buffer.
TArc * a
Definition: textangle.C:12
#define XPD_LONGOK(x)
static bool HasToken(const char *s, const char *tokens)
Returns true is 's' contains at least one of the comma-separated tokens in 'tokens'.
static struct mg_connection * fc(struct mg_context *ctx)
Definition: civetweb.c:839
int Recv(XpdMsg &msg)
Recv message from the pipe.
ClassImp(RooList) TObjOptLink *RooList TObjLink * link
Find the link corresponding to the named object in this list.
Definition: RooList.cxx:48
Vc_ALWAYS_INLINE void free(T *p)
Frees memory that was allocated with Vc::malloc.
Definition: memory.h:94
static int ParsePidPath(const char *path, XrdOucString &before, XrdOucString &after)
Parse a path in the form of "[.][.]", filling 'rest' and returning 'pid'...
static int SymLink(const char *path, const char *link)
Create a symlink 'link' to 'path' Return 0 in case of success, -1 in case of error.
#define LETTOIDX(x, ilet)
Definition: XrdProofdAux.h:353
XrdOucString fTail
Definition: XrdProofdAux.h:157
static double p2(double t, double a, double b, double c)
XrdOucString fHead
Definition: XrdProofdAux.h:156
void Close()
If open, close and invalidated the pipe descriptors.
char * pw_name
Definition: TWinNTSystem.h:50
bool Matches(const char *s)
Return true if 's' is compatible with this multi-string.
XFontStruct * id
Definition: TGX11.cxx:108
TString flog
Definition: pq2main.cxx:37
static void Form(XrdOucString &s, const char *fmt, int ns, const char *ss[5], int ni, int ii[6], int np, void *pp[5], int nu=0, unsigned int ui=0)
Recreate the string according to 'fmt', the up to 5 'const char *', up to 6 'int' arguments...
XrdOucString fUser
Definition: XrdProofdAux.h:40
#define XPDLOC(d, x)
static const char * ProofRequestTypes(int type)
Translates the proof request type in a human readable string.
SVector< double, 2 > v
Definition: Dict.h:5
static int GetIDFromPath(const char *path, XrdOucString &emsg)
Extract an integer from a file.
int DoDirectiveString(XrdProofdDirective *d, char *val, XrdOucStream *cfg, bool rcf)
Process directive for a string.
int fFrom
Definition: XrdProofdAux.h:180
int changeown(const std::string &path, uid_t u, gid_t g)
Change the ownership of 'path' to the entity described by {u,g}.
Definition: proofexecv.cxx:802
#define XrdSysMutexHelper
Definition: XrdSysToOuc.h:17
#define XrdSysError
Definition: XpdSysError.h:8
static int Touch(const char *path, int opt=0)
Set access (opt == 1), modify (opt =2 ) or access&modify (opt = 0, default) times of path to current ...
#define XpdBadPGuard(g, u)
Definition: XrdProofdAux.h:368
XrdOucString fGroup
Definition: XrdProofdAux.h:61
static double p1(double t, double a, double b)
Long64_t entry
static long int GetLong(char *str)
Extract first integer from string at 'str', if any.
static int GetGroupInfo(const char *grp, XrdProofGI &gi)
Get information about group with 'gid' in a thread safe way.
bool IsValid() const
Definition: XrdProofdAux.h:167
static int AssertDir(const char *path, XrdProofUI ui, bool changeown)
Make sure that 'path' exists and is owned by the entity described by 'ui'.
static int ReadMsg(int fd, XrdOucString &msg)
Receive 'msg' from pipe fd.
#define XPDFORM
Definition: XrdProofdAux.h:381
static int CheckIf(XrdOucStream *s, const char *h)
Check existence and match condition of an 'if' directive If none (valid) is found, return -1.
#define DIGIT(x)
Definition: XrdProofdAux.h:349
static char * Expand(char *p)
Expand path 'p' relative to: $HOME if begins with ~/ 's $HOME if begins with ~/ $PWD if d...
int type
Definition: TGX11.cxx:120
#define SafeFree(x)
Definition: XrdProofdAux.h:341
static int ParseUsrGrp(const char *path, XrdOucString &usr, XrdOucString &grp)
Parse a path in the form of "[.][.]", filling 'usr' and 'grp'.
bool Matches(const char *s)
Return true if 's' is compatible with this token.
static int ChangeMod(const char *path, unsigned int mode)
Change the permission mode of 'path' to 'mode'.
bool IsValid() const
Definition: XrdProofdAux.h:209
const char * fHost
Definition: XrdProofdAux.h:114
XrdOucString Export()
Return a string with comma-separated elements.
#define name(a, b)
Definition: linkTestLib0.cpp:5
int pw_gid
Definition: TWinNTSystem.h:53
virtual ~XrdProofdPipe()
Destructor.
XrdOucString fName
Definition: XrdProofdAux.h:111
std::list< XrdProofdMultiStrToken > fTokens
Definition: XrdProofdAux.h:158
int Get(int &i)
Get next token and interpret it as an int.
XrdOucString Get(int i)
Return i-th combination (i : 0 -> fN-1)
XrdOucString fHomeDir
Definition: XrdProofdAux.h:42
static int ChangeToDir(const char *dir, XrdProofUI ui, bool changeown)
Change current directory to 'dir'.
char * pw_dir
Definition: TWinNTSystem.h:56
ClassImp(TSlaveInfo) Int_t TSlaveInfo const TSlaveInfo * si
Used to sort slaveinfos by ordinal.
Definition: TProof.cxx:167
XrdSysRecMutex fRdMtx
Definition: XrdProofdAux.h:201
static int ChangeOwn(const char *path, XrdProofUI ui)
Change the ownership of 'path' to the entity described by 'ui'.
int Post(int type, const char *msg)
Post message on the pipe.
void Init(const char *s)
Init the multi-string token.
static int VerifyProcessByID(int pid, const char *pname="proofserv")
Check if a process named 'pname' and process 'pid' is still in the process table. ...
void Init(const char *s)
Init the multi-string handler.
XrdProofdPipe()
Constructor: create the pipe.
static int GetProcesses(const char *pn, std::map< int, XrdOucString > *plist)
Get from the process table list of PIDs for processes named "proofserv' For {linux, sun, macosx} it uses the system info; for other systems it invokes the command shell 'ps ax' via popen.
static void LogEmsgToFile(const char *flog, const char *emsg, const char *pfx=0)
Logs error message 'emsg' to file 'flog' using standard technology.
XrdOucString Export(int &next)
Export 'next' token; use next < 0 start from the first.
Vc_ALWAYS_INLINE_L T *Vc_ALWAYS_INLINE_R malloc(size_t n)
Allocates memory on the Heap with alignment and padding suitable for vectorized access.
Definition: memory.h:67
int SetHostInDirectives(const char *, XrdProofdDirective *d, void *h)
Set host field for directive 'd' to (const char *h)
const Int_t n
Definition: legend1.C:16
static int MvDir(const char *oldpath, const char *newpath)
Move content of directory at oldpath to newpath.
static int KillProcess(int pid, bool forcekill, XrdProofUI ui, bool changeown)
Kill the process 'pid'.
#define IDXTOLET(ilet, x)
Definition: XrdProofdAux.h:358
static XrdSysRecMutex fgFormMutex
Definition: XrdProofdAux.h:248