XRootD
Loading...
Searching...
No Matches
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"
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;
73const 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
92int 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 && strncmp(dp->d_name, pargs.reqid, pargs.reqlen))
120 continue;
121 if (pargs.usrlen)
122 if (!up || strcmp((const char *)up+1,(const char *)pargs.user))
123 continue;
124 strcpy(path, (const char *)LogDir);
125 strcpy(path+LogDirLen, (const char *)dp->d_name);
126 if (stat((const char *)path, &buf)) continue;
127 *up = ' ';
128 if ((up = (char *) index((const char *)(up+1), (int)'_'))) *up = ' ';
129 else continue;
130 if ((up = (char *) index((const char *)(up+1), (int)'_'))) *up = ' ';
131 else continue;
132 return snprintf(resp, resplen-1, "%s %lld",
133 dp->d_name, (long long) buf.st_mtime);
134 }
135
136// Completed
137//
138 if ((rc = errno))
139 eDest->Emsg("List", errno, "read prep log directory", LogDir);
140 closedir(pargs.dirP);
141 pargs.dirP = 0;
142 return (rc ? -1 : 0);
143}
144
145/******************************************************************************/
146/* L o g */
147/******************************************************************************/
148
150{
151 int rc, pnum = 0, xfd;
152 XrdOucTList *tp = pargs.paths;
153 char buff[2048], blink[2048];
154 struct iovec iovec[2];
155
156// If logging not enabled, return
157//
158 if (!LogDir) return;
159
160// Count number of paths in the list
161//
162 while(tp) {pnum++; tp = tp->next;}
163
164// Construct the file name: <reqid>_<user>_<prty>_<numpaths>
165//
166 snprintf(buff, sizeof(buff)-1, "%s%s_%s_%d_%d", LogDir,
167 pargs.reqid, pargs.user, pargs.prty, pnum);
168
169// Create the file
170//
171 if ((xfd = open(buff, O_WRONLY|O_CREAT|O_TRUNC,0644)) < 0)
172 {eDest->Emsg("Log", errno, "open prep log file", buff);
173 return;
174 }
175
176// Write all the paths into the file, separating each by a space
177//
178 iovec[1].iov_base = (char *)" ";
179 iovec[1].iov_len = 1;
180 tp = pargs.paths;
181 while(tp)
182 {if (tp->next == 0) iovec[1].iov_base = (char *)"\n";
183 iovec[0].iov_base = tp->text;
184 iovec[0].iov_len = strlen(tp->text);
185 do {rc = writev(xfd, (const struct iovec *)iovec, 2);}
186 while(rc < 0 && errno == EINTR);
187 if (rc < 0)
188 {eDest->Emsg("Log", errno, "write prep log file", buff);
189 close(xfd);
190 return;
191 }
192 tp = tp->next;
193 }
194
195// Create a symlink to the file
196//
197 close(xfd);
198 strcpy(blink, LogDir);
199 strlcpy(blink+LogDirLen, pargs.reqid, sizeof(blink)-1);
200 if (symlink((const char *)buff, (const char *)blink))
201 {eDest->Emsg("Log", errno, "create symlink to prep log file", buff);
202 return;
203 }
204}
205
206/******************************************************************************/
207/* L o g d e l */
208/******************************************************************************/
209
211{
212 int rc;
213 char path[MAXPATHLEN+256], buff[MAXPATHLEN+1];
214
215// If logging not enabled, return
216//
217 if (!LogDir || strlen(reqid) > 255) return;
218
219// Construct the file name of the symlink
220//
221 strcpy(path, (const char *)LogDir);
222 strcpy(&path[LogDirLen], (const char *)reqid);
223
224// Read the symlink contents for this request
225//
226 if ((rc = readlink((const char *)path, buff, sizeof(buff)-1)) < 0)
227 {if (errno != ENOENT) eDest->Emsg("Logdel",errno,"read symlink",path);
228 return;
229 }
230
231// Delete the file, then the symlink
232//
233 buff[rc] = '\0';
234 if (unlink((const char *)buff)
235 && errno != ENOENT) eDest->Emsg("Logdel",errno,"remove",buff);
236 else TRACE(DEBUG, "Logdel removed " <<buff);
237 if (unlink((const char *)path)
238 && errno != ENOENT) eDest->Emsg("Logdel", errno, "remove", path);
239 else TRACE(DEBUG, "Logdel removed " <<path);
240}
241
242/******************************************************************************/
243/* O p e n */
244/******************************************************************************/
245
246int XrdXrootdPrepare::Open(const char *reqid, int &fsz)
247{
248 int fd;
249 char path[MAXPATHLEN+264];
250 struct stat buf;
251
252// If logging is not supported, indicate so
253//
254 if (!LogDir) return -ENOTSUP;
255
256// Construct the file name
257//
258 strcpy(path, (const char *)LogDir);
259 strcpy(path+LogDirLen, reqid);
260
261// Open the file and return the file descriptor
262//
263 if ((fd = open((const char *)path, O_RDONLY)) < 0) return -errno;
264
265// Get the file size
266//
267 if (fstat(fd, &buf) != 0) {
268 close(fd);
269 return -errno;
270 }
271
272 fsz = buf.st_size;
273
274 return fd;
275}
276
277/******************************************************************************/
278/* S c r u b */
279/******************************************************************************/
280
282{
283 DIR *prepD;
284 time_t stale = time(0) - scrubkeep;
285 char *up, path[2048], *fn = path+LogDirLen;
286 struct dirent *dp;
287 struct stat buf;
288
289// If logging is not supported, return eof
290//
291 if (!LogDir) return;
292
293// Open the log directory
294//
295 if (!(prepD = opendir((const char *)LogDir)))
296 {eDest->Emsg("Scrub", errno, "open prep log directory", LogDir);
297 return;
298 }
299 strcpy(path, (const char *)LogDir);
300
301// Delete all stale entries
302//
303 errno = 0;
304 while((dp = readdir(prepD)))
305 {if (!(up = (char *) index((const char *)dp->d_name, '_'))) continue;
306 strcpy(fn, (const char *)dp->d_name);
307 if (stat((const char *)path, &buf)) continue;
308 if (buf.st_mtime <= stale)
309 {TRACE(DEBUG, "Scrub removed stale prep log " <<path);
310 unlink((const char *)path);
311 *(fn+(up-dp->d_name)) = '\0';
312 unlink((const char *)path);
313 errno = 0;
314 }
315 }
316
317// All done
318//
319 if (errno)
320 eDest->Emsg("List", errno, "read prep log directory", LogDir);
321 closedir(prepD);
322}
323
324/******************************************************************************/
325/* s e t P a r m s */
326/******************************************************************************/
327
328int XrdXrootdPrepare::setParms(int stime, int keep)
329{if (stime > 0) scrubtime = stime;
330 if (keep > 0) scrubkeep = keep;
331 return 0;
332}
333
335{
336 char path[2048];
337 struct stat buf;
338 int plen;
339
340// If parm not supplied, ignore call
341//
342 if (!ldir) return 0;
343
344// Make sure we have appropriate permissions for this directory
345//
346 if (access((const char *)ldir, X_OK | W_OK | R_OK) || stat(ldir, &buf))
347 return -errno;
348 if ((buf.st_mode & S_IFMT) != S_IFDIR) return -ENOTDIR;
349
350// Create the path name
351//
352 if (LogDir) free(LogDir);
353 LogDir = 0;
354 plen = strlen(ldir);
355 strcpy(path, ldir);
356 if (path[plen-1] != '/') path[plen++] = '/';
357 path[plen] = '\0';
358
359// Save the path and return
360//
361 LogDir = strdup(path);
362 LogDirLen = strlen(LogDir);
363 return 0;
364}
#define DEBUG(x)
static XrdSysError eDest(0,"crypto_")
#define access(a, b)
Definition XrdPosix.hh:39
#define close(a)
Definition XrdPosix.hh:43
#define fstat(a, b)
Definition XrdPosix.hh:57
#define opendir(a)
Definition XrdPosix.hh:73
#define open
Definition XrdPosix.hh:71
#define writev(a, b, c)
Definition XrdPosix.hh:112
#define closedir(a)
Definition XrdPosix.hh:45
#define unlink(a)
Definition XrdPosix.hh:108
#define stat(a, b)
Definition XrdPosix.hh:96
#define readdir(a)
Definition XrdPosix.hh:81
size_t strlcpy(char *dst, const char *src, size_t sz)
#define TRACE(act, x)
Definition XrdTrace.hh:63
XrdSysTrace XrdXrootdTrace
XrdOucTList * next
void Schedule(XrdJob *jp)
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
static int List(XrdXrootdPrepArgs &pargs, char *resp, int resplen)
static void Log(XrdXrootdPrepArgs &pargs)
static void Logdel(char *reqid)
static int setParms(int stime, int skeep)
XrdXrootdPrepare(XrdSysError *lp, XrdScheduler *sp, bool nomsg)
static int Open(const char *reqid, int &fsz)