info_file.c revision 174294
1/* 2 * Copyright (c) 1997-2006 Erez Zadok 3 * Copyright (c) 1990 Jan-Simon Pendry 4 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine 5 * Copyright (c) 1990 The Regents of the University of California. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Jan-Simon Pendry at Imperial College, London. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgment: 21 * This product includes software developed by the University of 22 * California, Berkeley and its contributors. 23 * 4. Neither the name of the University nor the names of its contributors 24 * may be used to endorse or promote products derived from this software 25 * without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 * 39 * 40 * File: am-utils/amd/info_file.c 41 * 42 */ 43 44/* 45 * Get info from file 46 */ 47 48#ifdef HAVE_CONFIG_H 49# include <config.h> 50#endif /* HAVE_CONFIG_H */ 51#include <am_defs.h> 52#include <amd.h> 53 54#define MAX_LINE_LEN 1500 55 56/* forward declarations */ 57int file_init_or_mtime(mnt_map *m, char *map, time_t *tp); 58int file_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *)); 59int file_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp); 60 61 62static int 63read_line(char *buf, int size, FILE *fp) 64{ 65 int done = 0; 66 67 do { 68 while (fgets(buf, size, fp)) { 69 int len = strlen(buf); 70 done += len; 71 if (len > 1 && buf[len - 2] == '\\' && 72 buf[len - 1] == '\n') { 73 int ch; 74 buf += len - 2; 75 size -= len - 2; 76 *buf = '\n'; 77 buf[1] = '\0'; 78 /* 79 * Skip leading white space on next line 80 */ 81 while ((ch = getc(fp)) != EOF && 82 isascii(ch) && isspace(ch)) ; 83 (void) ungetc(ch, fp); 84 } else { 85 return done; 86 } 87 } 88 } while (size > 0 && !feof(fp) && !ferror(fp)); 89 90 return done; 91} 92 93 94/* 95 * Try to locate a key in a file 96 */ 97static int 98file_search_or_reload(FILE *fp, 99 char *map, 100 char *key, 101 char **val, 102 mnt_map *m, 103 void (*fn) (mnt_map *m, char *, char *)) 104{ 105 char key_val[MAX_LINE_LEN]; 106 int chuck = 0; 107 int line_no = 0; 108 109 while (read_line(key_val, sizeof(key_val), fp)) { 110 char *kp; 111 char *cp; 112 char *hash; 113 int len = strlen(key_val); 114 line_no++; 115 116 /* 117 * Make sure we got the whole line 118 */ 119 if (key_val[len - 1] != '\n') { 120 plog(XLOG_WARNING, "line %d in \"%s\" is too long", line_no, map); 121 chuck = 1; 122 } else { 123 key_val[len - 1] = '\0'; 124 } 125 126 /* 127 * Strip comments 128 */ 129 hash = strchr(key_val, '#'); 130 if (hash) 131 *hash = '\0'; 132 133 /* 134 * Find start of key 135 */ 136 for (kp = key_val; *kp && isascii(*kp) && isspace((int)*kp); kp++) ; 137 138 /* 139 * Ignore blank lines 140 */ 141 if (!*kp) 142 goto again; 143 144 /* 145 * Find end of key 146 */ 147 for (cp = kp; *cp && (!isascii(*cp) || !isspace((int)*cp)); cp++) ; 148 149 /* 150 * Check whether key matches 151 */ 152 if (*cp) 153 *cp++ = '\0'; 154 155 if (fn || (*key == *kp && STREQ(key, kp))) { 156 while (*cp && isascii(*cp) && isspace((int)*cp)) 157 cp++; 158 if (*cp) { 159 /* 160 * Return a copy of the data 161 */ 162 char *dc = strdup(cp); 163 if (fn) { 164 (*fn) (m, strdup(kp), dc); 165 } else { 166 *val = dc; 167 dlog("%s returns %s", key, dc); 168 } 169 if (!fn) 170 return 0; 171 } else { 172 plog(XLOG_USER, "%s: line %d has no value field", map, line_no); 173 } 174 } 175 176 again: 177 /* 178 * If the last read didn't get a whole line then 179 * throw away the remainder before continuing... 180 */ 181 if (chuck) { 182 while (fgets(key_val, sizeof(key_val), fp) && 183 !strchr(key_val, '\n')) ; 184 chuck = 0; 185 } 186 } 187 188 return fn ? 0 : ENOENT; 189} 190 191 192static FILE * 193file_open(char *map, time_t *tp) 194{ 195 FILE *mapf = fopen(map, "r"); 196 197 if (mapf && tp) { 198 struct stat stb; 199 if (fstat(fileno(mapf), &stb) < 0) 200 *tp = clocktime(NULL); 201 else 202 *tp = stb.st_mtime; 203 } 204 return mapf; 205} 206 207 208int 209file_init_or_mtime(mnt_map *m, char *map, time_t *tp) 210{ 211 FILE *mapf = file_open(map, tp); 212 213 if (mapf) { 214 fclose(mapf); 215 return 0; 216 } 217 return errno; 218} 219 220 221int 222file_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *)) 223{ 224 FILE *mapf = file_open(map, (time_t *) 0); 225 226 if (mapf) { 227 int error = file_search_or_reload(mapf, map, 0, 0, m, fn); 228 (void) fclose(mapf); 229 return error; 230 } 231 return errno; 232} 233 234 235int 236file_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp) 237{ 238 time_t t; 239 FILE *mapf = file_open(map, &t); 240 241 if (mapf) { 242 int error; 243 if (*tp < t) { 244 *tp = t; 245 error = -1; 246 } else { 247 error = file_search_or_reload(mapf, map, key, pval, 0, 0); 248 } 249 (void) fclose(mapf); 250 return error; 251 } 252 return errno; 253} 254