]> err.no Git - util-linux/commitdiff
blkid: add support for /etc/blkid.conf file
authorKarel Zak <kzak@redhat.com>
Tue, 3 Feb 2009 14:23:18 +0000 (15:23 +0100)
committerKarel Zak <kzak@redhat.com>
Wed, 11 Feb 2009 22:35:25 +0000 (23:35 +0100)
We need a config file for the library. Now the library supports
config options:

EVALUATION=<method>[,<method>]

SEND_UEVENT=<yes|not>

CACHE_FILE=<path>

Signed-off-by: Karel Zak <kzak@redhat.com>
libs/blkid/TODO
libs/blkid/src/Makefile.am
libs/blkid/src/blkidP.h
libs/blkid/src/cache.c
libs/blkid/src/config.c [new file with mode: 0644]

index 6986d0edb68a4aef4a11a55dc3f28aa6790c6d44..4e00683ef678177886743c1532a32d73de0c3556 100644 (file)
@@ -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 -<BE|LE> suffix to test images for native-endian filesystems (e.g. swap)
    and add support for such functionality to tests/ts/blkid/low-probe
 
index e21fbc20627a4cb463b5da7e7e1adc97ae56b878..7821d804c83ad6dc54bf695653581b570044825a 100644 (file)
@@ -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
index f10c7474970d6cb94e167ccfc67e29dcc9c885ad..92b4296684fceeb875007665e5d0ad1b5ea68806 100644 (file)
@@ -20,7 +20,6 @@
 #include <stdio.h>
 
 #include "bitops.h"    /* $(top_srcdir)/include/ */
-
 #include "blkid.h"
 #include "list.h"
 
 #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=<udev,cache> options */
+       int nevals;                     /* number of elems in eval array */
+       int uevent;                     /* SEND_UEVENT=<yes|not> option */
+       char *cachefile;                /* CACHE_FILE=<path> 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
  */
index 228b3155e99fd6ff8bf1ddc49f56a5f86bbbca66..9897729e400fe5389bc8994376c18851a9fe0f45 100644 (file)
@@ -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 (file)
index 0000000..f75b292
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * config.c - blkid.conf routines
+ *
+ * Copyright (C) 2009 Karel Zak <kzak@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_MKDEV_H
+#include <sys/mkdev.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <stdint.h>
+#ifdef HAVE_LIBUUID
+#include <uuid/uuid.h>
+#endif
+#include <stdarg.h>
+
+#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 [<filename>]
+ */
+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