2 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
3 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
4 * Micah Cowan (micah@cowan.name)
5 * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
6 * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
7 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
8 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
9 * Copyright (c) 1987 Oliver Laumann
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3, or (at your option)
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program (see the file COPYING); if not, see
23 * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
26 ****************************************************************
29 #include <sys/types.h> /* dev_t, ino_t, off_t, ... */
30 #include <sys/stat.h> /* struct stat */
31 #include <fcntl.h> /* O_WRONLY for logfile_reopen */
39 static void changed_logfile
__P((struct logfile
*));
40 static struct logfile
*lookup_logfile
__P((char *));
41 static int stolen_logfile
__P((struct logfile
*));
43 static struct logfile
*logroot
= NULL
;
49 struct stat o
, *s
= l
->st
;
51 if (fstat(fileno(l
->fp
), &o
) < 0) /* get trouble later */
53 if (o
.st_size
> s
->st_size
) /* aha, appended text */
55 s
->st_size
= o
.st_size
; /* this should have changed */
56 s
->st_mtime
= o
.st_mtime
; /* only size and mtime */
61 * Requires fd to be open and need_fd to be closed.
62 * If possible, need_fd will be open afterwards and refer to
63 * the object originally reffered by fd. fd will be closed then.
64 * Works just like ``fcntl(fd, DUPFD, need_fd); close(fd);''
66 * need_fd is returned on success, else -1 is returned.
69 lf_move_fd(fd
, need_fd
)
76 if (fd
>=0 && fd
< need_fd
)
77 r
= lf_move_fd(dup(fd
), need_fd
);
83 logfile_reopen(name
, wantfd
, l
)
91 if (((got_fd
= open(name
, O_WRONLY
| O_CREAT
| O_APPEND
, 0666)) < 0) ||
92 lf_move_fd(got_fd
, wantfd
) < 0)
95 debug1("logfile_reopen: failed for %s\n", name
);
99 debug2("logfile_reopen: %d = %s\n", wantfd
, name
);
103 static int (* lf_reopen_fn
)() = logfile_reopen
;
106 * Whenever logfwrite discoveres that it is required to close and
107 * reopen the logfile, the function registered here is called.
108 * If you do not register anything here, the above logfile_reopen()
109 * will be used instead.
110 * Your function should perform the same steps as logfile_reopen():
111 * a) close the original filedescriptor without flushing any output
112 * b) open a new logfile for future output on the same filedescriptor number.
113 * c) zero out st_dev, st_ino to tell the stolen_logfile() indcator to
114 * reinitialise itself.
115 * d) return 0 on success.
118 logreopen_register(fn
)
119 int (*fn
) __P((char *, int, struct logfile
*));
121 lf_reopen_fn
= fn
? fn
: logfile_reopen
;
125 * If the logfile has been removed, truncated, unlinked or the like,
127 * The l->st structure initialised by logfopen is updated
134 struct stat o
, *s
= l
->st
;
137 if (fstat(fileno(l
->fp
), s
) < 0) /* remember that stat failed */
138 s
->st_ino
= s
->st_dev
= 0;
140 if (!o
.st_dev
&& !o
.st_ino
) /* nothing to compare with */
143 if ((!s
->st_dev
&& !s
->st_ino
) || /* stat failed, that's new! */
144 !s
->st_nlink
|| /* red alert: file unlinked */
145 (s
->st_size
< o
.st_size
) || /* file truncated */
146 (s
->st_mtime
!= o
.st_mtime
) || /* file modified */
147 ((s
->st_ctime
!= o
.st_ctime
) && /* file changed (moved) */
148 !(s
->st_mtime
== s
->st_ctime
&& /* and it was not a change */
149 o
.st_ctime
< s
->st_ctime
))) /* due to delayed nfs write */
151 debug1("stolen_logfile: %s stolen!\n", l
->name
);
152 debug3("st_dev %d, st_ino %d, st_nlink %d\n",
153 (int)s
->st_dev
, (int)s
->st_ino
, (int)s
->st_nlink
);
154 debug2("s->st_size %d, o.st_size %d\n", (int)s
->st_size
, (int)o
.st_size
);
155 debug2("s->st_mtime %d, o.st_mtime %d\n",
156 (int)s
->st_mtime
, (int)o
.st_mtime
);
157 debug2("s->st_ctime %d, o.st_ctime %d\n",
158 (int)s
->st_ctime
, (int)o
.st_ctime
);
162 debug1("stolen_logfile: %s o.k.\n", l
->name
);
166 static struct logfile
*
172 for (l
= logroot
; l
; l
= l
->next
)
173 if (!strcmp(name
, l
->name
))
187 if (!(l
= lookup_logfile(name
)))
193 if (!(l
= (struct logfile
*)malloc(sizeof(struct logfile
))))
195 if (!(l
->st
= (struct stat
*)malloc(sizeof(struct stat
))))
201 if (!(l
->name
= SaveStr(name
)))
223 return logroot
? 1 : 0;
224 return lookup_logfile(name
) ? 1 : 0;
233 for (lp
= &logroot
; *lp
; lp
= &(*lp
)->next
)
240 if ((--l
->opencount
) > 0)
242 if (l
->opencount
< 0)
254 * write and flush both *should* check the file's stat, if it disappeared
255 * or changed, re-open it.
265 if (stolen_logfile(l
) && lf_reopen_fn(l
->name
, fileno(l
->fp
), l
))
267 r
= fwrite(buf
, n
, 1, l
->fp
);
268 l
->writecount
+= l
->flushcount
+ 1;
281 for (l
= logroot
; l
; l
= l
->next
)
283 if (stolen_logfile(l
) && lf_reopen_fn(l
->name
, fileno(l
->fp
), l
))
291 if (stolen_logfile(l
) && lf_reopen_fn(l
->name
, fileno(l
->fp
), l
))