1
/* Copyright (c) 1993-2002
2
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
3
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
4
* Copyright (c) 1987 Oliver Laumann
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2, or (at your option)
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program (see the file COPYING); if not, write to the
18
* Free Software Foundation, Inc.,
19
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21
****************************************************************
24
#include <sys/types.h> /* dev_t, ino_t, off_t, ... */
25
#include <sys/stat.h> /* struct stat */
26
#include <fcntl.h> /* O_WRONLY for logfile_reopen */
34
static void changed_logfile __P((struct logfile *));
35
static struct logfile *lookup_logfile __P((char *));
36
static int stolen_logfile __P((struct logfile *));
38
static struct logfile *logroot = NULL;
44
struct stat o, *s = l->st;
46
if (fstat(fileno(l->fp), &o) < 0) /* get trouble later */
48
if (o.st_size > s->st_size) /* aha, appended text */
50
s->st_size = o.st_size; /* this should have changed */
51
s->st_mtime = o.st_mtime; /* only size and mtime */
56
* Requires fd to be open and need_fd to be closed.
57
* If possible, need_fd will be open afterwards and refer to
58
* the object originally reffered by fd. fd will be closed then.
59
* Works just like ``fcntl(fd, DUPFD, need_fd); close(fd);''
61
* need_fd is returned on success, else -1 is returned.
64
lf_move_fd(fd, need_fd)
71
if (fd >=0 && fd < need_fd)
72
r = lf_move_fd(dup(fd), need_fd);
78
logfile_reopen(name, wantfd, l)
86
if (((got_fd = open(name, O_WRONLY | O_CREAT | O_APPEND, 0666)) < 0) ||
87
lf_move_fd(got_fd, wantfd) < 0)
90
debug1("logfile_reopen: failed for %s\n", name);
94
debug2("logfile_reopen: %d = %s\n", wantfd, name);
98
static int (* lf_reopen_fn)() = logfile_reopen;
101
* Whenever logfwrite discoveres that it is required to close and
102
* reopen the logfile, the function registered here is called.
103
* If you do not register anything here, the above logfile_reopen()
104
* will be used instead.
105
* Your function should perform the same steps as logfile_reopen():
106
* a) close the original filedescriptor without flushing any output
107
* b) open a new logfile for future output on the same filedescriptor number.
108
* c) zero out st_dev, st_ino to tell the stolen_logfile() indcator to
109
* reinitialise itself.
110
* d) return 0 on success.
113
logreopen_register(fn)
114
int (*fn) __P((char *, int, struct logfile *));
116
lf_reopen_fn = fn ? fn : logfile_reopen;
120
* If the logfile has been removed, truncated, unlinked or the like,
122
* The l->st structure initialised by logfopen is updated
129
struct stat o, *s = l->st;
132
if (fstat(fileno(l->fp), s) < 0) /* remember that stat failed */
133
s->st_ino = s->st_dev = 0;
135
if (!o.st_dev && !o.st_ino) /* nothing to compare with */
138
if ((!s->st_dev && !s->st_ino) || /* stat failed, that's new! */
139
!s->st_nlink || /* red alert: file unlinked */
140
(s->st_size < o.st_size) || /* file truncated */
141
(s->st_mtime != o.st_mtime) || /* file modified */
142
((s->st_ctime != o.st_ctime) && /* file changed (moved) */
143
!(s->st_mtime == s->st_ctime && /* and it was not a change */
144
o.st_ctime < s->st_ctime))) /* due to delayed nfs write */
146
debug1("stolen_logfile: %s stolen!\n", l->name);
147
debug3("st_dev %d, st_ino %d, st_nlink %d\n",
148
(int)s->st_dev, (int)s->st_ino, (int)s->st_nlink);
149
debug2("s->st_size %d, o.st_size %d\n", (int)s->st_size, (int)o.st_size);
150
debug2("s->st_mtime %d, o.st_mtime %d\n",
151
(int)s->st_mtime, (int)o.st_mtime);
152
debug2("s->st_ctime %d, o.st_ctime %d\n",
153
(int)s->st_ctime, (int)o.st_ctime);
157
debug1("stolen_logfile: %s o.k.\n", l->name);
161
static struct logfile *
167
for (l = logroot; l; l = l->next)
168
if (!strcmp(name, l->name))
182
if (!(l = lookup_logfile(name)))
188
if (!(l = (struct logfile *)malloc(sizeof(struct logfile))))
190
if (!(l->st = (struct stat *)malloc(sizeof(struct stat))))
196
if (!(l->name = SaveStr(name)))
218
return logroot ? 1 : 0;
219
return lookup_logfile(name) ? 1 : 0;
228
for (lp = &logroot; *lp; lp = &(*lp)->next)
235
if ((--l->opencount) > 0)
237
if (l->opencount < 0)
249
* write and flush both *should* check the file's stat, if it disappeared
250
* or changed, re-open it.
260
if (stolen_logfile(l) && lf_reopen_fn(l->name, fileno(l->fp), l))
262
r = fwrite(buf, n, 1, l->fp);
263
l->writecount += l->flushcount + 1;
276
for (l = logroot; l; l = l->next)
278
if (stolen_logfile(l) && lf_reopen_fn(l->name, fileno(l->fp), l))
286
if (stolen_logfile(l) && lf_reopen_fn(l->name, fileno(l->fp), l))