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