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