blob: 3c7f3124c2789aef202d503b7f81f163d7fd3f15 [file] [log] [blame]
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001/*
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
20#ifdef HAVE_ERRNO_H
21#include <errno.h>
22#endif
23#include <stdint.h>
24#include <stdarg.h>
25
26#include "blkidP.h"
27#include "env.h"
28
29static 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;
52err:
bigbiff7b4c7a62015-01-01 19:44:14 -050053 DBG(CONFIG, ul_debug(
54 "config file: unknown evaluation method '%s'.", s));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -050055 return -1;
56}
57
58static 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;
67 s = strchr (buf, '\n');
68 if (!s) {
69 /* Missing final newline? Otherwise extremely */
70 /* long line - assume file was corrupted */
71 if (feof(fd))
72 s = strchr (buf, '\0');
73 else {
bigbiff7b4c7a62015-01-01 19:44:14 -050074 DBG(CONFIG, ul_debug(
75 "config file: missing newline at line '%s'.",
bigbiff bigbiffe60683a2013-02-22 20:55:50 -050076 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)) {
91 s += 13;
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)
99 conf->cachefile = strdup(s);
100 } else if (!strncmp(s, "EVALUATE=", 9)) {
101 s += 9;
102 if (*s && parse_evaluate(conf, s) == -1)
103 return -1;
104 } else {
bigbiff7b4c7a62015-01-01 19:44:14 -0500105 DBG(CONFIG, ul_debug(
106 "config file: unknown option '%s'.", s));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500107 return -1;
108 }
109 return 0;
110}
111
112/* return real config data or built-in default */
113struct blkid_config *blkid_read_config(const char *filename)
114{
115 struct blkid_config *conf;
116 FILE *f;
117
118 if (!filename)
119 filename = safe_getenv("BLKID_CONF");
120 if (!filename)
121 filename = BLKID_CONFIG_FILE;
122
123 conf = (struct blkid_config *) calloc(1, sizeof(*conf));
124 if (!conf)
125 return NULL;
126 conf->uevent = -1;
127
bigbiff7b4c7a62015-01-01 19:44:14 -0500128 DBG(CONFIG, ul_debug("reading config file: %s.", filename));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500129
bigbiff7b4c7a62015-01-01 19:44:14 -0500130 f = fopen(filename, "r" UL_CLOEXECSTR);
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500131 if (!f) {
bigbiff7b4c7a62015-01-01 19:44:14 -0500132 DBG(CONFIG, ul_debug("%s: does not exist, using built-in default", filename));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500133 goto dflt;
134 }
135 while (!feof(f)) {
136 if (parse_next(f, conf)) {
bigbiff7b4c7a62015-01-01 19:44:14 -0500137 DBG(CONFIG, ul_debug("%s: parse error", filename));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500138 goto err;
139 }
140 }
141dflt:
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)
148 conf->cachefile = strdup(BLKID_CACHE_FILE);
149 if (conf->uevent == -1)
150 conf->uevent = TRUE;
151 if (f)
152 fclose(f);
153 return conf;
154err:
155 free(conf);
156 fclose(f);
157 return NULL;
158}
159
160void 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 */
172int main(int argc, char *argv[])
173{
174 int i;
175 struct blkid_config *conf;
176 char *filename = NULL;
177
bigbiff7b4c7a62015-01-01 19:44:14 -0500178 blkid_init_debug(BLKID_DEBUG_ALL);
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500179
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