1 /* $NetBSD: load_file.c,v 1.1.1.1 2009/06/23 10:09:00 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 52 /* load_file - load file with some prejudice */ 53 54 void load_file(const char *path, LOAD_FILE_FN action, void *context) 55 { 56 VSTREAM *fp; 57 struct stat st; 58 time_t before; 59 time_t after; 60 61 /* 62 * Read the file again if it is hot. This may result in reading a partial 63 * parameter name or missing end marker when a file changes in the middle 64 * of a read. 65 */ 66 for (before = time((time_t *) 0); /* see below */ ; before = after) { 67 if ((fp = vstream_fopen(path, O_RDONLY, 0)) == 0) 68 msg_fatal("open %s: %m", path); 69 action(fp, context); 70 if (fstat(vstream_fileno(fp), &st) < 0) 71 msg_fatal("fstat %s: %m", path); 72 if (vstream_ferror(fp) || vstream_fclose(fp)) 73 msg_fatal("read %s: %m", path); 74 after = time((time_t *) 0); 75 if (st.st_mtime < before - 1 || st.st_mtime > after) 76 break; 77 if (msg_verbose) 78 msg_info("pausing to let %s cool down", path); 79 doze(300000); 80 } 81 } 82