]>
Commit | Line | Data |
---|---|---|
568871ae KZ |
1 | /* |
2 | * config.c - blkid.conf routines | |
3 | * | |
4 | * Copyright (C) 2009 Karel Zak <kzak@redhat.com> | |
5 | * | |
6 | * This file may be redistributed under the terms of the | |
7 | * GNU Lesser General Public License. | |
8 | */ | |
9 | ||
10 | #include <stdio.h> | |
11 | #include <string.h> | |
12 | #include <stdlib.h> | |
13 | #include <unistd.h> | |
14 | #include <fcntl.h> | |
15 | #include <ctype.h> | |
16 | #include <sys/types.h> | |
17 | #ifdef HAVE_SYS_STAT_H | |
18 | #include <sys/stat.h> | |
19 | #endif | |
568871ae KZ |
20 | #ifdef HAVE_ERRNO_H |
21 | #include <errno.h> | |
22 | #endif | |
23 | #include <stdint.h> | |
568871ae KZ |
24 | #include <stdarg.h> |
25 | ||
568871ae | 26 | #include "blkidP.h" |
035507c8 | 27 | #include "env.h" |
568871ae KZ |
28 | |
29 | static int parse_evaluate(struct blkid_config *conf, char *s) | |
30 | { | |
31 | while(s && *s) { | |
32 | char *sep; | |
33 | ||
34 | if (conf->nevals >= __BLKID_EVAL_LAST) | |
35 | goto err; | |
36 | sep = strchr(s, ','); | |
37 | if (sep) | |
38 | *sep = '\0'; | |
39 | if (strcmp(s, "udev") == 0) | |
40 | conf->eval[conf->nevals] = BLKID_EVAL_UDEV; | |
41 | else if (strcmp(s, "scan") == 0) | |
42 | conf->eval[conf->nevals] = BLKID_EVAL_SCAN; | |
43 | else | |
44 | goto err; | |
45 | conf->nevals++; | |
46 | if (sep) | |
47 | s = sep + 1; | |
48 | else | |
49 | break; | |
50 | } | |
51 | return 0; | |
52 | err: | |
c62a6311 | 53 | DBG(CONFIG, ul_debug( |
0540ea54 | 54 | "config file: unknown evaluation method '%s'.", s)); |
568871ae KZ |
55 | return -1; |
56 | } | |
57 | ||
58 | static int parse_next(FILE *fd, struct blkid_config *conf) | |
59 | { | |
60 | char buf[BUFSIZ]; | |
61 | char *s; | |
62 | ||
63 | /* read the next non-blank non-comment line */ | |
64 | do { | |
65 | if (fgets (buf, sizeof(buf), fd) == NULL) | |
66 | return feof(fd) ? 0 : -1; | |
c0f19ccf | 67 | s = strchr (buf, '\n'); |
568871ae KZ |
68 | if (!s) { |
69 | /* Missing final newline? Otherwise extremely */ | |
70 | /* long line - assume file was corrupted */ | |
71 | if (feof(fd)) | |
c0f19ccf | 72 | s = strchr (buf, '\0'); |
568871ae | 73 | else { |
c62a6311 | 74 | DBG(CONFIG, ul_debug( |
0540ea54 | 75 | "config file: missing newline at line '%s'.", |
568871ae KZ |
76 | buf)); |
77 | return -1; | |
78 | } | |
79 | } | |
80 | *s = '\0'; | |
81 | if (--s >= buf && *s == '\r') | |
82 | *s = '\0'; | |
83 | ||
84 | s = buf; | |
85 | while (*s == ' ' || *s == '\t') /* skip space */ | |
86 | s++; | |
87 | ||
88 | } while (*s == '\0' || *s == '#'); | |
89 | ||
90 | if (!strncmp(s, "SEND_UEVENT=", 12)) { | |
55a5fbbc | 91 | s += 12; |
568871ae KZ |
92 | if (*s && !strcasecmp(s, "yes")) |
93 | conf->uevent = TRUE; | |
94 | else if (*s) | |
95 | conf->uevent = FALSE; | |
96 | } else if (!strncmp(s, "CACHE_FILE=", 11)) { | |
97 | s += 11; | |
98 | if (*s) | |
e0a9b8cf | 99 | conf->cachefile = strdup(s); |
568871ae KZ |
100 | } else if (!strncmp(s, "EVALUATE=", 9)) { |
101 | s += 9; | |
102 | if (*s && parse_evaluate(conf, s) == -1) | |
103 | return -1; | |
104 | } else { | |
c62a6311 | 105 | DBG(CONFIG, ul_debug( |
0540ea54 | 106 | "config file: unknown option '%s'.", s)); |
568871ae KZ |
107 | return -1; |
108 | } | |
109 | return 0; | |
110 | } | |
111 | ||
112 | /* return real config data or built-in default */ | |
113 | struct blkid_config *blkid_read_config(const char *filename) | |
114 | { | |
115 | struct blkid_config *conf; | |
116 | FILE *f; | |
117 | ||
118 | if (!filename) | |
035507c8 | 119 | filename = safe_getenv("BLKID_CONF"); |
568871ae KZ |
120 | if (!filename) |
121 | filename = BLKID_CONFIG_FILE; | |
122 | ||
fea1cbf7 | 123 | conf = calloc(1, sizeof(*conf)); |
568871ae KZ |
124 | if (!conf) |
125 | return NULL; | |
126 | conf->uevent = -1; | |
127 | ||
c62a6311 | 128 | DBG(CONFIG, ul_debug("reading config file: %s.", filename)); |
568871ae | 129 | |
4000fc12 | 130 | f = fopen(filename, "r" UL_CLOEXECSTR); |
568871ae | 131 | if (!f) { |
c62a6311 | 132 | DBG(CONFIG, ul_debug("%s: does not exist, using built-in default", filename)); |
568871ae KZ |
133 | goto dflt; |
134 | } | |
135 | while (!feof(f)) { | |
136 | if (parse_next(f, conf)) { | |
c62a6311 | 137 | DBG(CONFIG, ul_debug("%s: parse error", filename)); |
568871ae KZ |
138 | goto err; |
139 | } | |
140 | } | |
141 | dflt: | |
142 | if (!conf->nevals) { | |
143 | conf->eval[0] = BLKID_EVAL_UDEV; | |
144 | conf->eval[1] = BLKID_EVAL_SCAN; | |
145 | conf->nevals = 2; | |
146 | } | |
147 | if (!conf->cachefile) | |
e0a9b8cf | 148 | conf->cachefile = strdup(BLKID_CACHE_FILE); |
568871ae KZ |
149 | if (conf->uevent == -1) |
150 | conf->uevent = TRUE; | |
151 | if (f) | |
152 | fclose(f); | |
153 | return conf; | |
154 | err: | |
155 | free(conf); | |
156 | fclose(f); | |
157 | return NULL; | |
158 | } | |
159 | ||
160 | void blkid_free_config(struct blkid_config *conf) | |
161 | { | |
162 | if (!conf) | |
163 | return; | |
164 | free(conf->cachefile); | |
165 | free(conf); | |
166 | } | |
167 | ||
168 | #ifdef TEST_PROGRAM | |
169 | /* | |
170 | * usage: tst_config [<filename>] | |
171 | */ | |
172 | int main(int argc, char *argv[]) | |
173 | { | |
174 | int i; | |
175 | struct blkid_config *conf; | |
176 | char *filename = NULL; | |
177 | ||
0540ea54 | 178 | blkid_init_debug(BLKID_DEBUG_ALL); |
568871ae KZ |
179 | |
180 | if (argc == 2) | |
181 | filename = argv[1]; | |
182 | ||
183 | conf = blkid_read_config(filename); | |
184 | if (!conf) | |
185 | return EXIT_FAILURE; | |
186 | ||
187 | printf("EVALUATE: "); | |
188 | for (i = 0; i < conf->nevals; i++) | |
189 | printf("%s ", conf->eval[i] == BLKID_EVAL_UDEV ? "udev" : "scan"); | |
190 | printf("\n"); | |
191 | ||
192 | printf("SEND UEVENT: %s\n", conf->uevent ? "TRUE" : "FALSE"); | |
193 | printf("CACHE_FILE: %s\n", conf->cachefile); | |
194 | ||
195 | blkid_free_config(conf); | |
196 | return EXIT_SUCCESS; | |
197 | } | |
198 | #endif |