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
))