From: Karel Zak Date: Tue, 3 Feb 2009 14:23:18 +0000 (+0100) Subject: blkid: add support for /etc/blkid.conf file X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=568871ae4dad99bbd48cad6f23ef659cd7904d6e;p=util-linux blkid: add support for /etc/blkid.conf file We need a config file for the library. Now the library supports config options: EVALUATION=[,] SEND_UEVENT= CACHE_FILE= Signed-off-by: Karel Zak --- diff --git a/libs/blkid/TODO b/libs/blkid/TODO index 6986d0ed..4e00683e 100644 --- a/libs/blkid/TODO +++ b/libs/blkid/TODO @@ -2,6 +2,9 @@ TODO ---- + - (?) we need to ignore cache and config files when the files are writable + for non-root users and the library is linked with suid programs + - add - suffix to test images for native-endian filesystems (e.g. swap) and add support for such functionality to tests/ts/blkid/low-probe diff --git a/libs/blkid/src/Makefile.am b/libs/blkid/src/Makefile.am index e21fbc20..7821d804 100644 --- a/libs/blkid/src/Makefile.am +++ b/libs/blkid/src/Makefile.am @@ -9,6 +9,7 @@ lib_LIBRARIES = libblkid.a libblkid_a_SOURCES = cache.c dev.c devname.c devno.c getsize.c llseek.c \ probe.c read.c resolve.c save.c tag.c version.c verify.c \ encode.c blkid.h blkidP.h list.h probers/probers.h \ + config.c \ $(top_srcdir)/lib/blkdev.c \ $(top_srcdir)/lib/linux_version.c \ $(top_srcdir)/lib/md5.c diff --git a/libs/blkid/src/blkidP.h b/libs/blkid/src/blkidP.h index f10c7474..92b42966 100644 --- a/libs/blkid/src/blkidP.h +++ b/libs/blkid/src/blkidP.h @@ -20,7 +20,6 @@ #include #include "bitops.h" /* $(top_srcdir)/include/ */ - #include "blkid.h" #include "list.h" @@ -30,6 +29,11 @@ #define __BLKID_ATTR(x) #endif +#ifndef TRUE +#define TRUE 1 +#define FALSE 1 +#endif + /* TODO: move to some top-level util-linux include file */ #ifndef ARRAY_SIZE #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) @@ -153,6 +157,29 @@ struct blkid_idinfo */ #define BLKID_IDINFO_TOLERANT (1 << 1) +/* + * Evaluation methods (for blkid_eval_* API) + */ +enum { + BLKID_EVAL_UDEV = 0, + BLKID_EVAL_SCAN, + + __BLKID_EVAL_LAST +}; + +/* + * Library config options + */ +struct blkid_config { + int eval[__BLKID_EVAL_LAST]; /* array with EVALUATION= options */ + int nevals; /* number of elems in eval array */ + int uevent; /* SEND_UEVENT= option */ + char *cachefile; /* CACHE_FILE= option */ +}; + +extern struct blkid_config *blkid_read_config(const char *filename); +extern void blkid_free_config(struct blkid_config *conf); + /* * Minimum number of seconds between device probes, even when reading * from the cache. This is to avoid re-probing all devices which were @@ -190,7 +217,8 @@ struct blkid_struct_cache extern char *blkid_strdup(const char *s); extern char *blkid_strndup(const char *s, const int length); -#define BLKID_CACHE_FILE "/etc/blkid.tab" +#define BLKID_CACHE_FILE "/etc/blkid.tab" +#define BLKID_CONFIG_FILE "/etc/blkid.conf" #define BLKID_ERR_IO 5 #define BLKID_ERR_PROC 9 @@ -223,6 +251,7 @@ extern char *blkid_strndup(const char *s, const int length); #define DEBUG_SAVE 0x0100 #define DEBUG_TAG 0x0200 #define DEBUG_LOWPROBE 0x0400 +#define DEBUG_CONFIG 0x0800 #define DEBUG_INIT 0x8000 #define DEBUG_ALL 0xFFFF @@ -256,6 +285,9 @@ extern void blkid_read_cache(blkid_cache cache); /* save.c */ extern int blkid_flush_cache(blkid_cache cache); +/* cache */ +extern char *blkid_safe_getenv(const char *arg); + /* * Functions to create and find a specific tag type: tag.c */ diff --git a/libs/blkid/src/cache.c b/libs/blkid/src/cache.c index 228b3155..9897729e 100644 --- a/libs/blkid/src/cache.c +++ b/libs/blkid/src/cache.c @@ -34,7 +34,7 @@ int blkid_debug_mask = 0; -static char *safe_getenv(const char *arg) +char *blkid_safe_getenv(const char *arg) { if ((getuid() != geteuid()) || (getgid() != getegid())) return NULL; @@ -112,13 +112,20 @@ int blkid_get_cache(blkid_cache *ret_cache, const char *filename) INIT_LIST_HEAD(&cache->bic_devs); INIT_LIST_HEAD(&cache->bic_tags); - if (filename && !strlen(filename)) - filename = 0; + if (filename && !*filename) + filename = NULL; if (!filename) - filename = safe_getenv("BLKID_FILE"); - if (!filename) - filename = BLKID_CACHE_FILE; - cache->bic_filename = blkid_strdup(filename); + filename = blkid_safe_getenv("BLKID_FILE"); + if (filename) + cache->bic_filename = blkid_strdup(filename); + else { + struct blkid_config *conf = blkid_read_config(NULL); + if (!conf) + return -BLKID_ERR_PARAM; + cache->bic_filename = conf->cachefile; + conf->cachefile = NULL; + blkid_free_config(conf); + } blkid_read_cache(cache); @@ -190,7 +197,6 @@ void blkid_gc_cache(blkid_cache cache) } } - #ifdef TEST_PROGRAM int main(int argc, char** argv) { diff --git a/libs/blkid/src/config.c b/libs/blkid/src/config.c new file mode 100644 index 00000000..f75b2928 --- /dev/null +++ b/libs/blkid/src/config.c @@ -0,0 +1,208 @@ +/* + * config.c - blkid.conf routines + * + * Copyright (C) 2009 Karel Zak + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_SYS_MKDEV_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#include +#ifdef HAVE_LIBUUID +#include +#endif +#include + +#include "blkdev.h" +#include "blkidP.h" + + +static int parse_evaluate(struct blkid_config *conf, char *s) +{ + while(s && *s) { + char *sep; + + if (conf->nevals >= __BLKID_EVAL_LAST) + goto err; + sep = strchr(s, ','); + if (sep) + *sep = '\0'; + if (strcmp(s, "udev") == 0) + conf->eval[conf->nevals] = BLKID_EVAL_UDEV; + else if (strcmp(s, "scan") == 0) + conf->eval[conf->nevals] = BLKID_EVAL_SCAN; + else + goto err; + conf->nevals++; + if (sep) + s = sep + 1; + else + break; + } + return 0; +err: + DBG(DEBUG_CONFIG, printf( + "config file: unknown evaluation method '%s'.\n", s)); + return -1; +} + +static int parse_next(FILE *fd, struct blkid_config *conf) +{ + char buf[BUFSIZ]; + char *s; + + /* read the next non-blank non-comment line */ + do { + if (fgets (buf, sizeof(buf), fd) == NULL) + return feof(fd) ? 0 : -1; + s = index (buf, '\n'); + if (!s) { + /* Missing final newline? Otherwise extremely */ + /* long line - assume file was corrupted */ + if (feof(fd)) + s = index (buf, '\0'); + else { + DBG(DEBUG_CONFIG, fprintf(stderr, + "libblkid: config file: missing newline at line '%s'.\n", + buf)); + return -1; + } + } + *s = '\0'; + if (--s >= buf && *s == '\r') + *s = '\0'; + + s = buf; + while (*s == ' ' || *s == '\t') /* skip space */ + s++; + + } while (*s == '\0' || *s == '#'); + + if (!strncmp(s, "SEND_UEVENT=", 12)) { + s += 13; + if (*s && !strcasecmp(s, "yes")) + conf->uevent = TRUE; + else if (*s) + conf->uevent = FALSE; + } else if (!strncmp(s, "CACHE_FILE=", 11)) { + s += 11; + if (*s) + conf->cachefile = blkid_strdup(s); + } else if (!strncmp(s, "EVALUATE=", 9)) { + s += 9; + if (*s && parse_evaluate(conf, s) == -1) + return -1; + } else { + DBG(DEBUG_CONFIG, printf( + "config file: unknown option '%s'.\n", s)); + return -1; + } + return 0; +} + +/* return real config data or built-in default */ +struct blkid_config *blkid_read_config(const char *filename) +{ + struct blkid_config *conf; + FILE *f; + + if (!filename) + filename = blkid_safe_getenv("BLKID_CONF"); + if (!filename) + filename = BLKID_CONFIG_FILE; + + conf = (struct blkid_config *) calloc(1, sizeof(*conf)); + if (!conf) + return NULL; + conf->uevent = -1; + + DBG(DEBUG_CONFIG, fprintf(stderr, + "reading config file: %s.\n", filename)); + + f = fopen(filename, "r"); + if (!f) { + DBG(DEBUG_CONFIG, fprintf(stderr, + "%s: does not exist, using built-in default\n", filename)); + goto dflt; + } + while (!feof(f)) { + if (parse_next(f, conf)) { + DBG(DEBUG_CONFIG, fprintf(stderr, + "%s: parse error\n", filename)); + goto err; + } + } +dflt: + if (!conf->nevals) { + conf->eval[0] = BLKID_EVAL_UDEV; + conf->eval[1] = BLKID_EVAL_SCAN; + conf->nevals = 2; + } + if (!conf->cachefile) + conf->cachefile = blkid_strdup(BLKID_CACHE_FILE); + if (conf->uevent == -1) + conf->uevent = TRUE; + if (f) + fclose(f); + return conf; +err: + free(conf); + fclose(f); + return NULL; +} + +void blkid_free_config(struct blkid_config *conf) +{ + if (!conf) + return; + free(conf->cachefile); + free(conf); +} + +#ifdef TEST_PROGRAM +/* + * usage: tst_config [] + */ +int main(int argc, char *argv[]) +{ + int i; + struct blkid_config *conf; + char *filename = NULL; + + blkid_debug_init(DEBUG_ALL); + + if (argc == 2) + filename = argv[1]; + + conf = blkid_read_config(filename); + if (!conf) + return EXIT_FAILURE; + + printf("EVALUATE: "); + for (i = 0; i < conf->nevals; i++) + printf("%s ", conf->eval[i] == BLKID_EVAL_UDEV ? "udev" : "scan"); + printf("\n"); + + printf("SEND UEVENT: %s\n", conf->uevent ? "TRUE" : "FALSE"); + printf("CACHE_FILE: %s\n", conf->cachefile); + + blkid_free_config(conf); + return EXIT_SUCCESS; +} +#endif