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