XRootD
XrdXrootdPrepare.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d X r o o t d P r e p a r e . c c */
4 /* */
5 /* (c) 2004 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 <dirent.h>
32 #include <fcntl.h>
33 #include <unistd.h>
34 #include <cstdio>
35 #include <cstdlib>
36 #include <strings.h>
37 #include <sys/param.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <sys/uio.h>
41 
42 #ifdef __linux__
43 #include <syscall.h>
44 #define getdents(fd, dirp, cnt) syscall(SYS_getdents, fd, dirp, cnt)
45 #endif
46 
47 #include "XrdSys/XrdSysError.hh"
48 #include "XrdSys/XrdSysPlatform.hh"
49 #include "XrdOuc/XrdOucTList.hh"
52 
53 /******************************************************************************/
54 /* G l o b a l O b j e c t s */
55 /******************************************************************************/
56 
57 /******************************************************************************/
58 /* G l o b a l s */
59 /******************************************************************************/
60 
61 #ifndef NODEBUG
63 #endif
64 
65  XrdScheduler *XrdXrootdPrepare::SchedP;
66 
67  XrdSysError *XrdXrootdPrepare::eDest; // Error message handler
68 
69  int XrdXrootdPrepare::scrubtime = 60*60;
70  int XrdXrootdPrepare::scrubkeep = 60*60*24;
71  char *XrdXrootdPrepare::LogDir = 0;
72  int XrdXrootdPrepare::LogDirLen = 0;
73 const char *XrdXrootdPrepare::TraceID = "Prepare";
74 
75 /******************************************************************************/
76 /* C o n s t r u c t o r */
77 /******************************************************************************/
78 
80  bool nomsg) : XrdJob("Prep log scrubber")
81 {eDest = errp;
82  SchedP = sp;
83  if (LogDir) SchedP->Schedule((XrdJob *)this, scrubtime+time(0));
84 // else if (!nomsg) eDest->Say("Config warning: 'xrootd.prepare logdir' "
85 // "not specified; prepare tracking disabled.");
86 }
87 
88 /******************************************************************************/
89 /* L i s t */
90 /******************************************************************************/
91 
92 int XrdXrootdPrepare::List(XrdXrootdPrepArgs &pargs, char *resp, int resplen)
93 {
94  char *up, path[2048];
95  struct dirent *dp;
96  struct stat buf;
97  int rc;
98 
99 // If logging is not supported, return eof
100 //
101  if (!LogDir) return -1;
102 
103 // Check if this is the first call
104 //
105  if (!pargs.dirP)
106  {if (!(pargs.dirP = opendir((const char *)LogDir)))
107  {eDest->Emsg("List", errno, "open prep log directory", LogDir);
108  return -1;
109  }
110  if (pargs.reqid) pargs.reqlen = strlen(pargs.reqid);
111  if (pargs.user) pargs.usrlen = strlen(pargs.user);
112  }
113 
114 // Find the next entry that satisfies the search criteria
115 //
116  errno = 0;
117  while((dp = readdir(pargs.dirP)))
118  {if (!(up = (char *) index((const char *)dp->d_name, '_'))) continue;
119  if (pargs.reqlen && pargs.reqid
120  && strncmp(dp->d_name, pargs.reqid, pargs.reqlen))
121  continue;
122  if (pargs.usrlen && pargs.user)
123  if (!up || strcmp((const char *)up+1,(const char *)pargs.user))
124  continue;
125  strcpy(path, (const char *)LogDir);
126  strcpy(path+LogDirLen, (const char *)dp->d_name);
127  if (stat((const char *)path, &buf)) continue;
128  *up = ' ';
129  if ((up = (char *) index((const char *)(up+1), (int)'_'))) *up = ' ';
130  else continue;
131  if ((up = (char *) index((const char *)(up+1), (int)'_'))) *up = ' ';
132  else continue;
133  return snprintf(resp, resplen-1, "%s %lld",
134  dp->d_name, (long long) buf.st_mtime);
135  }
136 
137 // Completed
138 //
139  if ((rc = errno))
140  eDest->Emsg("List", errno, "read prep log directory", LogDir);
141  closedir(pargs.dirP);
142  pargs.dirP = 0;
143  return (rc ? -1 : 0);
144 }
145 
146 /******************************************************************************/
147 /* L o g */
148 /******************************************************************************/
149 
151 {
152  int rc, pnum = 0, xfd;
153  XrdOucTList *tp = pargs.paths;
154  char buff[2048], blink[2048];
155  struct iovec iovec[2];
156 
157 // If logging not enabled, return
158 //
159  if (!LogDir) return;
160 
161 // Count number of paths in the list
162 //
163  while(tp) {pnum++; tp = tp->next;}
164 
165 // Construct the file name: <reqid>_<user>_<prty>_<numpaths>
166 //
167  snprintf(buff, sizeof(buff)-1, "%s%s_%s_%d_%d", LogDir,
168  pargs.reqid, pargs.user, pargs.prty, pnum);
169 
170 // Create the file
171 //
172  if ((xfd = open(buff, O_WRONLY|O_CREAT|O_TRUNC,0644)) < 0)
173  {eDest->Emsg("Log", errno, "open prep log file", buff);
174  return;
175  }
176 
177 // Write all the paths into the file, separating each by a space
178 //
179  iovec[1].iov_base = (char *)" ";
180  iovec[1].iov_len = 1;
181  tp = pargs.paths;
182  while(tp)
183  {if (tp->next == 0) iovec[1].iov_base = (char *)"\n";
184  iovec[0].iov_base = tp->text;
185  iovec[0].iov_len = strlen(tp->text);
186  do {rc = writev(xfd, (const struct iovec *)iovec, 2);}
187  while(rc < 0 && errno == EINTR);
188  if (rc < 0)
189  {eDest->Emsg("Log", errno, "write prep log file", buff);
190  close(xfd);
191  return;
192  }
193  tp = tp->next;
194  }
195 
196 // Create a symlink to the file
197 //
198  close(xfd);
199  strcpy(blink, LogDir);
200  strlcpy(blink+LogDirLen, pargs.reqid, sizeof(blink)-1);
201  if (symlink((const char *)buff, (const char *)blink))
202  {eDest->Emsg("Log", errno, "create symlink to prep log file", buff);
203  return;
204  }
205 }
206 
207 /******************************************************************************/
208 /* L o g d e l */
209 /******************************************************************************/
210 
211 void XrdXrootdPrepare::Logdel(char *reqid)
212 {
213  int rc;
214  char path[MAXPATHLEN+256], buff[MAXPATHLEN+1];
215 
216 // If logging not enabled, return
217 //
218  if (!LogDir || strlen(reqid) > 255) return;
219 
220 // Construct the file name of the symlink
221 //
222  strcpy(path, (const char *)LogDir);
223  strcpy(&path[LogDirLen], (const char *)reqid);
224 
225 // Read the symlink contents for this request
226 //
227  if ((rc = readlink((const char *)path, buff, sizeof(buff)-1)) < 0)
228  {if (errno != ENOENT) eDest->Emsg("Logdel",errno,"read symlink",path);
229  return;
230  }
231 
232 // Delete the file, then the symlink
233 //
234  buff[rc] = '\0';
235  if (unlink((const char *)buff)
236  && errno != ENOENT) eDest->Emsg("Logdel",errno,"remove",buff);
237  else TRACE(DEBUG, "Logdel removed " <<buff);
238  if (unlink((const char *)path)
239  && errno != ENOENT) eDest->Emsg("Logdel", errno, "remove", path);
240  else TRACE(DEBUG, "Logdel removed " <<path);
241 }
242 
243 /******************************************************************************/
244 /* O p e n */
245 /******************************************************************************/
246 
247 int XrdXrootdPrepare::Open(const char *reqid, int &fsz)
248 {
249  int fd;
250  char path[MAXPATHLEN+264];
251  struct stat buf;
252 
253 // If logging is not supported, indicate so
254 //
255  if (!LogDir) return -ENOTSUP;
256 
257 // Construct the file name
258 //
259  strcpy(path, (const char *)LogDir);
260  strcpy(path+LogDirLen, reqid);
261 
262 // Open the file and return the file descriptor
263 //
264  if ((fd = open((const char *)path, O_RDONLY)) < 0) return -errno;
265 
266 // Get the file size
267 //
268  if (fstat(fd, &buf) != 0) {
269  close(fd);
270  return -errno;
271  }
272 
273  fsz = buf.st_size;
274 
275  return fd;
276 }
277 
278 /******************************************************************************/
279 /* S c r u b */
280 /******************************************************************************/
281 
283 {
284  DIR *prepD;
285  time_t stale = time(0) - scrubkeep;
286  char *up, path[2048], *fn = path+LogDirLen;
287  struct dirent *dp;
288  struct stat buf;
289 
290 // If logging is not supported, return eof
291 //
292  if (!LogDir) return;
293 
294 // Open the log directory
295 //
296  if (!(prepD = opendir((const char *)LogDir)))
297  {eDest->Emsg("Scrub", errno, "open prep log directory", LogDir);
298  return;
299  }
300  strcpy(path, (const char *)LogDir);
301 
302 // Delete all stale entries
303 //
304  errno = 0;
305  while((dp = readdir(prepD)))
306  {if (!(up = (char *) index((const char *)dp->d_name, '_'))) continue;
307  strcpy(fn, (const char *)dp->d_name);
308  if (stat((const char *)path, &buf)) continue;
309  if (buf.st_mtime <= stale)
310  {TRACE(DEBUG, "Scrub removed stale prep log " <<path);
311  unlink((const char *)path);
312  *(fn+(up-dp->d_name)) = '\0';
313  unlink((const char *)path);
314  errno = 0;
315  }
316  }
317 
318 // All done
319 //
320  if (errno)
321  eDest->Emsg("List", errno, "read prep log directory", LogDir);
322  closedir(prepD);
323 }
324 
325 /******************************************************************************/
326 /* s e t P a r m s */
327 /******************************************************************************/
328 
329 int XrdXrootdPrepare::setParms(int stime, int keep)
330 {if (stime > 0) scrubtime = stime;
331  if (keep > 0) scrubkeep = keep;
332  return 0;
333 }
334 
336 {
337  char path[2048];
338  struct stat buf;
339  int plen;
340 
341 // If parm not supplied, ignore call
342 //
343  if (!ldir) return 0;
344 
345 // Make sure we have appropriate permissions for this directory
346 //
347  if (access((const char *)ldir, X_OK | W_OK | R_OK) || stat(ldir, &buf))
348  return -errno;
349  if ((buf.st_mode & S_IFMT) != S_IFDIR) return -ENOTDIR;
350 
351 // Create the path name
352 //
353  if (LogDir) free(LogDir);
354  LogDir = 0;
355  plen = strlen(ldir);
356  strcpy(path, ldir);
357  if (path[plen-1] != '/') path[plen++] = '/';
358  path[plen] = '\0';
359 
360 // Save the path and return
361 //
362  LogDir = strdup(path);
363  LogDirLen = strlen(LogDir);
364  return 0;
365 }
#define DEBUG(x)
Definition: XrdBwmTrace.hh:54
static XrdSysError eDest(0,"crypto_")
int unlink(const char *path)
int access(const char *path, int amode)
int closedir(DIR *dirp)
ssize_t writev(int fildes, const struct iovec *iov, int iovcnt)
DIR * opendir(const char *path)
#define close(a)
Definition: XrdPosix.hh:48
#define fstat(a, b)
Definition: XrdPosix.hh:62
#define open
Definition: XrdPosix.hh:76
#define stat(a, b)
Definition: XrdPosix.hh:101
#define readdir(a)
Definition: XrdPosix.hh:86
size_t strlcpy(char *dst, const char *src, size_t sz)
#define TRACE(act, x)
Definition: XrdTrace.hh:63
XrdSysTrace XrdXrootdTrace
Definition: XrdJob.hh:43
XrdOucTList * next
Definition: XrdOucTList.hh:45
char * text
Definition: XrdOucTList.hh:46
void Schedule(XrdJob *jp)
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95
XrdOucTList * paths
static int List(XrdXrootdPrepArgs &pargs, char *resp, int resplen)
static void Log(XrdXrootdPrepArgs &pargs)
static void Logdel(char *reqid)
static void Scrub()
static int setParms(int stime, int skeep)
XrdXrootdPrepare(XrdSysError *lp, XrdScheduler *sp, bool nomsg)
static int Open(const char *reqid, int &fsz)