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 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