(root)/
util-linux-2.39/
libblkid/
src/
config.c
       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  
      26  #include "blkidP.h"
      27  #include "env.h"
      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:
      53  	DBG(CONFIG, ul_debug(
      54  		"config file: unknown evaluation method '%s'.", s));
      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;
      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 {
      74  				DBG(CONFIG, ul_debug(
      75  					"config file: missing newline at line '%s'.",
      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)) {
      91  		s += 12;
      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  		free(conf->cachefile);
      99  		if (*s)
     100  			conf->cachefile = strdup(s);
     101  		else
     102  			conf->cachefile = NULL;
     103  	} else if (!strncmp(s, "EVALUATE=", 9)) {
     104  		s += 9;
     105  		if (*s && parse_evaluate(conf, s) == -1)
     106  			return -1;
     107  	} else {
     108  		DBG(CONFIG, ul_debug(
     109  			"config file: unknown option '%s'.", s));
     110  		return -1;
     111  	}
     112  	return 0;
     113  }
     114  
     115  /* return real config data or built-in default */
     116  struct blkid_config *blkid_read_config(const char *filename)
     117  {
     118  	struct blkid_config *conf;
     119  	FILE *f;
     120  
     121  	if (!filename)
     122  		filename = safe_getenv("BLKID_CONF");
     123  	if (!filename)
     124  		filename = BLKID_CONFIG_FILE;
     125  
     126  	conf = calloc(1, sizeof(*conf));
     127  	if (!conf)
     128  		return NULL;
     129  	conf->uevent = -1;
     130  
     131  	DBG(CONFIG, ul_debug("reading config file: %s.", filename));
     132  
     133  	f = fopen(filename, "r" UL_CLOEXECSTR);
     134  	if (!f) {
     135  		DBG(CONFIG, ul_debug("%s: does not exist, using built-in default", filename));
     136  		goto dflt;
     137  	}
     138  	while (!feof(f)) {
     139  		if (parse_next(f, conf)) {
     140  			DBG(CONFIG, ul_debug("%s: parse error", filename));
     141  			goto err;
     142  		}
     143  	}
     144  dflt:
     145  	if (!conf->nevals) {
     146  		conf->eval[0] = BLKID_EVAL_UDEV;
     147  		conf->eval[1] = BLKID_EVAL_SCAN;
     148  		conf->nevals = 2;
     149  	}
     150  	if (!conf->cachefile)
     151  		conf->cachefile = strdup(BLKID_CACHE_FILE);
     152  	if (conf->uevent == -1)
     153  		conf->uevent = TRUE;
     154  	if (f)
     155  		fclose(f);
     156  	return conf;
     157  err:
     158  	free(conf);
     159  	fclose(f);
     160  	return NULL;
     161  }
     162  
     163  void blkid_free_config(struct blkid_config *conf)
     164  {
     165  	if (!conf)
     166  		return;
     167  	free(conf->cachefile);
     168  	free(conf);
     169  }
     170  
     171  #ifdef TEST_PROGRAM
     172  /*
     173   * usage: tst_config [<filename>]
     174   */
     175  int main(int argc, char *argv[])
     176  {
     177  	int i;
     178  	struct blkid_config *conf;
     179  	char *filename = NULL;
     180  
     181  	blkid_init_debug(BLKID_DEBUG_ALL);
     182  
     183  	if (argc == 2)
     184  		filename = argv[1];
     185  
     186  	conf = blkid_read_config(filename);
     187  	if (!conf)
     188  		return EXIT_FAILURE;
     189  
     190  	printf("EVALUATE:    ");
     191  	for (i = 0; i < conf->nevals; i++)
     192  		printf("%s ", conf->eval[i] == BLKID_EVAL_UDEV ? "udev" : "scan");
     193  	printf("\n");
     194  
     195  	printf("SEND UEVENT: %s\n", conf->uevent ? "TRUE" : "FALSE");
     196  	printf("CACHE_FILE:  %s\n", conf->cachefile);
     197  
     198  	blkid_free_config(conf);
     199  	return EXIT_SUCCESS;
     200  }
     201  #endif