xref: /netbsd-src/external/ibm-public/postfix/dist/src/util/load_file.c (revision a30b880ed60a24c405edba78187a04247f4d9d33)
1 /*	$NetBSD: load_file.c,v 1.1.1.2 2013/01/02 18:59:13 tron Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	load_file 3
6 /* SUMMARY
7 /*	load file with some prejudice
8 /* SYNOPSIS
9 /*	#include <load_file.h>
10 /*
11 /*	void	load_file(path, action, context)
12 /*	const char *path;
13 /*	void	(*action)(VSTREAM, void *);
14 /*	void	*context;
15 /* DESCRIPTION
16 /*	This routine reads a file and reads it again when the
17 /*	file changed recently.
18 /*
19 /*	Arguments:
20 /* .IP path
21 /*	The file to be opened, read-only.
22 /* .IP action
23 /*	The function that presumably reads the file.
24 /* .IP context
25 /*	Application-specific context for the action routine.
26 /* DIAGNOSTICS
27 /*	Fatal errors: out of memory, cannot open file.
28 /* LICENSE
29 /* .ad
30 /* .fi
31 /*	The Secure Mailer license must be distributed with this software.
32 /* AUTHOR(S)
33 /*	Wietse Venema
34 /*	IBM T.J. Watson Research
35 /*	P.O. Box 704
36 /*	Yorktown Heights, NY 10598, USA
37 /*--*/
38 
39 /* System library. */
40 
41 #include <sys_defs.h>
42 #include <sys/stat.h>
43 #include <time.h>
44 
45 /* Utility library. */
46 
47 #include <msg.h>
48 #include <vstream.h>
49 #include <iostuff.h>
50 #include <load_file.h>
51 #include <warn_stat.h>
52 
53 /* load_file - load file with some prejudice */
54 
load_file(const char * path,LOAD_FILE_FN action,void * context)55 void    load_file(const char *path, LOAD_FILE_FN action, void *context)
56 {
57     VSTREAM *fp;
58     struct stat st;
59     time_t  before;
60     time_t  after;
61 
62     /*
63      * Read the file again if it is hot. This may result in reading a partial
64      * parameter name or missing end marker when a file changes in the middle
65      * of a read.
66      */
67     for (before = time((time_t *) 0); /* see below */ ; before = after) {
68 	if ((fp = vstream_fopen(path, O_RDONLY, 0)) == 0)
69 	    msg_fatal("open %s: %m", path);
70 	action(fp, context);
71 	if (fstat(vstream_fileno(fp), &st) < 0)
72 	    msg_fatal("fstat %s: %m", path);
73 	if (vstream_ferror(fp) || vstream_fclose(fp))
74 	    msg_fatal("read %s: %m", path);
75 	after = time((time_t *) 0);
76 	if (st.st_mtime < before - 1 || st.st_mtime > after)
77 	    break;
78 	if (msg_verbose)
79 	    msg_info("pausing to let %s cool down", path);
80 	doze(300000);
81     }
82 }
83