1 /* Copyright (c) 2008, 2009
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 * https://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
26 ****************************************************************
33 #include <sys/types.h> /* dev_t, ino_t, off_t, ... */
34 #include <sys/stat.h> /* struct stat */
35 #include <fcntl.h> /* O_WRONLY for logfile_reopen */
43 static void changed_logfile(Log
*);
44 static Log
*lookup_logfile(char *);
45 static int stolen_logfile(Log
*);
47 static Log
*logroot
= NULL
;
49 static void changed_logfile(Log
*l
)
51 struct stat o
, *s
= l
->st
;
53 if (fstat(fileno(l
->fp
), &o
) < 0) /* get trouble later */
55 if (o
.st_size
> s
->st_size
) { /* aha, appended text */
56 s
->st_size
= o
.st_size
; /* this should have changed */
57 s
->st_mtime
= o
.st_mtime
; /* only size and mtime */
62 * Requires fd to be open and need_fd to be closed.
63 * If possible, need_fd will be open afterwards and refer to
64 * the object originally reffered by fd. fd will be closed then.
65 * Works just like ``fcntl(fd, DUPFD, need_fd); close(fd);''
67 * need_fd is returned on success, else -1 is returned.
69 int lf_move_fd(int fd
, int need_fd
)
75 if (fd
>= 0 && fd
< need_fd
)
76 r
= lf_move_fd(dup(fd
), need_fd
);
81 static int logfile_reopen(char *name
, int wantfd
, Log
*l
)
86 if (((got_fd
= open(name
, O_WRONLY
| O_CREAT
| O_APPEND
, 0666)) < 0) || lf_move_fd(got_fd
, wantfd
) < 0) {
91 l
->st
->st_ino
= l
->st
->st_dev
= 0;
96 * If the logfile has been removed, truncated, unlinked or the like,
98 * The l->st structure initialised by logfopen is updated
101 static int stolen_logfile(Log
*l
)
103 struct stat o
, *s
= l
->st
;
106 if (fstat(fileno(l
->fp
), s
) < 0) /* remember that stat failed */
107 s
->st_ino
= s
->st_dev
= 0;
108 if (!o
.st_dev
&& !o
.st_ino
) /* nothing to compare with */
111 if ((!s
->st_dev
&& !s
->st_ino
) || /* stat failed, that's new! */
112 !s
->st_nlink
|| /* red alert: file unlinked */
113 (s
->st_size
< o
.st_size
) || /* file truncated */
114 (s
->st_mtime
!= o
.st_mtime
) || /* file modified */
115 ((s
->st_ctime
!= o
.st_ctime
) && /* file changed (moved) */
116 !(s
->st_mtime
== s
->st_ctime
&& /* and it was not a change */
117 o
.st_ctime
< s
->st_ctime
))) { /* due to delayed nfs write */
124 static Log
*lookup_logfile(char *name
)
128 for (l
= logroot
; l
; l
= l
->next
)
129 if (!strcmp(name
, l
->name
))
134 Log
*logfopen(char *name
, FILE * fp
)
139 if (!(l
= lookup_logfile(name
)))
145 if (!(l
= calloc(1, sizeof(Log
))))
147 if (!(l
->st
= calloc(1, sizeof(struct stat
)))) {
152 if (!(l
->name
= SaveStr(name
))) {
168 int islogfile(char *name
)
171 return logroot
? 1 : 0;
172 return lookup_logfile(name
) ? 1 : 0;
175 int logfclose(Log
*l
)
179 for (lp
= &logroot
; *lp
; lp
= &(*lp
)->next
)
186 if ((--l
->opencount
) > 0)
188 if (l
->opencount
< 0)
200 * write and flush both *should* check the file's stat, if it disappeared
201 * or changed, re-open it.
203 int logfwrite(Log
*l
, char *buf
, size_t n
)
207 if (stolen_logfile(l
) && logfile_reopen(l
->name
, fileno(l
->fp
), l
))
209 r
= fwrite(buf
, n
, 1, l
->fp
);
210 l
->writecount
+= l
->flushcount
+ 1;
216 int logfflush(Log
*l
)
221 for (l
= logroot
; l
; l
= l
->next
) {
222 if (stolen_logfile(l
) && logfile_reopen(l
->name
, fileno(l
->fp
), l
))
228 if (stolen_logfile(l
) && logfile_reopen(l
->name
, fileno(l
->fp
), l
))