Coverage Report

Created: 2026-02-11 06:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/util-linux/libblkid/src/config.c
Line
Count
Source
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
20
#ifdef HAVE_ERRNO_H
21
#include <errno.h>
22
#endif
23
#include <stdint.h>
24
#include <stdarg.h>
25
#if defined (HAVE_LIBECONF)
26
# include <libeconf.h>
27
# include "pathnames.h"
28
#endif
29
30
#include "blkidP.h"
31
#include "env.h"
32
#include "cctype.h"
33
34
static int parse_evaluate(struct blkid_config *conf, char *s)
35
0
{
36
0
  while(s && *s) {
37
0
    char *sep;
38
39
0
    if (conf->nevals >= __BLKID_EVAL_LAST)
40
0
      goto err;
41
0
    sep = strchr(s, ',');
42
0
    if (sep)
43
0
      *sep = '\0';
44
0
    if (strcmp(s, "udev") == 0)
45
0
      conf->eval[conf->nevals] = BLKID_EVAL_UDEV;
46
0
    else if (strcmp(s, "scan") == 0)
47
0
      conf->eval[conf->nevals] = BLKID_EVAL_SCAN;
48
0
    else
49
0
      goto err;
50
0
    conf->nevals++;
51
0
    if (sep)
52
0
      s = sep + 1;
53
0
    else
54
0
      break;
55
0
  }
56
0
  return 0;
57
0
err:
58
0
  DBG(CONFIG, ul_debug(
59
0
    "config file: unknown evaluation method '%s'.", s));
60
0
  return -1;
61
0
}
62
63
#ifndef HAVE_LIBECONF
64
static int parse_next(FILE *fd, struct blkid_config *conf)
65
0
{
66
0
  char buf[BUFSIZ];
67
0
  char *s;
68
69
  /* read the next non-blank non-comment line */
70
0
  do {
71
0
    if (fgets (buf, sizeof(buf), fd) == NULL)
72
0
      return feof(fd) ? 0 : -1;
73
0
    s = strchr (buf, '\n');
74
0
    if (!s) {
75
      /* Missing final newline?  Otherwise extremely */
76
      /* long line - assume file was corrupted */
77
0
      if (feof(fd))
78
0
        s = strchr (buf, '\0');
79
0
      else {
80
0
        DBG(CONFIG, ul_debug(
81
0
          "config file: missing newline at line '%s'.",
82
0
          buf));
83
0
        return -1;
84
0
      }
85
0
    }
86
0
    *s = '\0';
87
0
    if (--s >= buf && *s == '\r')
88
0
      *s = '\0';
89
90
0
    s = buf;
91
0
    while (*s == ' ' || *s == '\t')   /* skip space */
92
0
      s++;
93
94
0
  } while (*s == '\0' || *s == '#');
95
96
0
  if (!strncmp(s, "SEND_UEVENT=", 12)) {
97
0
    s += 12;
98
0
    if (*s && !c_strcasecmp(s, "yes"))
99
0
      conf->uevent = TRUE;
100
0
    else if (*s)
101
0
      conf->uevent = FALSE;
102
0
  } else if (!strncmp(s, "CACHE_FILE=", 11)) {
103
0
    s += 11;
104
0
    free(conf->cachefile);
105
0
    if (*s)
106
0
      conf->cachefile = strdup(s);
107
0
    else
108
0
      conf->cachefile = NULL;
109
0
  } else if (!strncmp(s, "EVALUATE=", 9)) {
110
0
    s += 9;
111
0
    if (*s && parse_evaluate(conf, s) == -1)
112
0
      return -1;
113
0
  } else {
114
0
    DBG(CONFIG, ul_debug(
115
0
      "config file: unknown option '%s'.", s));
116
0
    return -1;
117
0
  }
118
0
  return 0;
119
0
}
120
#endif /* !HAVE_LIBECONF */
121
122
/* return real config data or built-in default */
123
struct blkid_config *blkid_read_config(const char *filename)
124
0
{
125
0
  struct blkid_config *conf;
126
127
0
  conf = calloc(1, sizeof(*conf));
128
0
  if (!conf)
129
0
    return NULL;
130
0
  conf->uevent = -1;
131
132
133
0
  if (!filename)
134
0
    filename = safe_getenv("BLKID_CONF");
135
136
0
#ifndef HAVE_LIBECONF
137
138
0
  FILE *f;
139
0
  if (!filename)
140
0
    filename = BLKID_CONFIG_FILE;
141
142
0
  DBG(CONFIG, ul_debug("reading config file: %s.", filename));
143
0
  f = fopen(filename, "r" UL_CLOEXECSTR);
144
0
  if (!f) {
145
0
    DBG(CONFIG, ul_debug("%s: does not exist, using built-in default", filename));
146
0
    goto dflt;
147
0
  }
148
0
  while (!feof(f)) {
149
0
    if (parse_next(f, conf)) {
150
0
      DBG(CONFIG, ul_debug("%s: parse error", filename));
151
0
      goto err;
152
0
    }
153
0
  }
154
155
#else /* !HAVE_LIBECONF */
156
157
  econf_file *file = NULL;
158
  char *line = NULL;
159
  bool uevent = false;
160
  econf_err error;
161
162
  if (filename) {
163
    DBG(CONFIG, ul_debug("reading config file: %s.", filename));
164
    error = econf_readFile(&file, filename, "= \t", "#");
165
  } else {
166
#ifdef HAVE_ECONF_READCONFIG
167
    error = econf_readConfig(&file, NULL,
168
      UL_VENDORDIR_PATH, "blkid", "conf", "= \t", "#");
169
#else
170
    error = econf_readDirs(&file,
171
      UL_VENDORDIR_PATH, "/etc", "blkid", "conf", "= \t", "#");
172
#endif
173
  }
174
175
  if (error) {
176
    if (error == ECONF_NOFILE) {
177
      if (filename)
178
        DBG(CONFIG,
179
            ul_debug("%s: does not exist, using built-in default", filename));
180
      else
181
        DBG(CONFIG,
182
            ul_debug("No configuration file blkid.conf found, using built-in default "));
183
      goto dflt;
184
    } else {
185
      if (filename)
186
        DBG(CONFIG, ul_debug("%s: parse error:%s", filename, econf_errString(error)));
187
      else
188
        DBG(CONFIG, ul_debug("parse error:%s", econf_errString(error)));
189
190
      goto err;
191
    }
192
  }
193
194
  if ((error = econf_getBoolValue(file, NULL, "SEND_UEVENT", &uevent))) {
195
    if (error != ECONF_NOKEY) {
196
      DBG(CONFIG, ul_debug("couldn't fetch SEND_UEVENT currently: %s", econf_errString(error)));
197
      goto err;
198
    } else {
199
      DBG(CONFIG, ul_debug("key SEND_UEVENT not found, using built-in default "));
200
    }
201
  } else {
202
    conf->uevent = uevent ? TRUE : FALSE;
203
  }
204
205
  if ((error = econf_getStringValue(file, NULL, "CACHE_FILE", &(conf->cachefile)))) {
206
    conf->cachefile = NULL;
207
    if (error != ECONF_NOKEY) {
208
      DBG(CONFIG, ul_debug("couldn't fetch CACHE_FILE correctly: %s", econf_errString(error)));
209
      goto err;
210
    } else {
211
      DBG(CONFIG, ul_debug("key CACHE_FILE not found, using built-in default "));
212
    }
213
  }
214
215
  if ((error = econf_getStringValue(file, NULL, "EVALUATE", &line))) {
216
    conf->nevals = 0;
217
    if (error != ECONF_NOKEY) {
218
      DBG(CONFIG, ul_debug("couldn't fetch EVALUATE correctly: %s", econf_errString(error)));
219
      goto err;
220
    } else {
221
      DBG(CONFIG, ul_debug("key CACHE_FILE not found, using built-in default "));
222
    }
223
  } else {
224
    if (line && *line && parse_evaluate(conf, line) == -1)
225
      goto err;
226
  }
227
228
#endif /* HAVE_LIBECONF */
229
0
dflt:
230
0
  if (!conf->nevals) {
231
0
    conf->eval[0] = BLKID_EVAL_UDEV;
232
0
    conf->eval[1] = BLKID_EVAL_SCAN;
233
0
    conf->nevals = 2;
234
0
  }
235
0
  if (!conf->cachefile)
236
0
    conf->cachefile = strdup(BLKID_CACHE_FILE);
237
0
  if (conf->uevent == -1)
238
0
    conf->uevent = TRUE;
239
0
#ifndef HAVE_LIBECONF
240
0
  if (f)
241
0
    fclose(f);
242
#else
243
  econf_free(file);
244
  free(line);
245
#endif
246
0
  return conf;
247
0
err:
248
0
  free(conf->cachefile);
249
0
  free(conf);
250
0
#ifndef HAVE_LIBECONF
251
0
  fclose(f);
252
#else
253
  econf_free(file);
254
  free(line);
255
#endif
256
0
  return NULL;
257
0
}
258
259
void blkid_free_config(struct blkid_config *conf)
260
0
{
261
0
  if (!conf)
262
0
    return;
263
0
  free(conf->cachefile);
264
0
  free(conf);
265
0
}
266
267
#ifdef TEST_PROGRAM
268
/*
269
 * usage: tst_config [<filename>]
270
 */
271
int main(int argc, char *argv[])
272
{
273
  int i;
274
  struct blkid_config *conf;
275
  char *filename = NULL;
276
277
  blkid_init_debug(BLKID_DEBUG_ALL);
278
279
  if (argc == 2)
280
    filename = argv[1];
281
282
  conf = blkid_read_config(filename);
283
  if (!conf)
284
    return EXIT_FAILURE;
285
286
  printf("EVALUATE:    ");
287
  for (i = 0; i < conf->nevals; i++)
288
    printf("%s ", conf->eval[i] == BLKID_EVAL_UDEV ? "udev" : "scan");
289
  printf("\n");
290
291
  printf("SEND UEVENT: %s\n", conf->uevent ? "TRUE" : "FALSE");
292
  printf("CACHE_FILE:  %s\n", conf->cachefile);
293
294
  blkid_free_config(conf);
295
  return EXIT_SUCCESS;
296
}
297
#endif