Whamcloud - gitweb
Wholesale changes to blkid library to simplify the implementation
authorTheodore Ts'o <tytso@mit.edu>
Thu, 13 Feb 2003 04:51:21 +0000 (23:51 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Thu, 13 Feb 2003 04:51:21 +0000 (23:51 -0500)
and shrink its size.  Change library version to be 1.0.

16 files changed:
lib/blkid/ChangeLog
lib/blkid/Makefile.in
lib/blkid/blkid.h
lib/blkid/blkidP.h
lib/blkid/cache.c
lib/blkid/dev.c
lib/blkid/devname.c
lib/blkid/devno.c
lib/blkid/libblkid.3.in
lib/blkid/probe.c
lib/blkid/probe.h
lib/blkid/read.c
lib/blkid/resolve.c
lib/blkid/save.c
lib/blkid/tag.c
misc/blkid.c

index 827a685..b73e5aa 100644 (file)
@@ -1,3 +1,10 @@
+2003-02-12  Theodore Ts'o  <tytso@mit.edu>
+
+       * blkid.h, blkidP.h, cache.c, dev.c, devname.c, devno.c, probe.c,
+               probe.h, read.c, resolve.c, save.c, tag.c: Wholesale
+               changes to library to simplify the implementation and
+               shrink its size.  Change library version to be 1.0.
+
 2003-01-27  Theodore Ts'o  <tytso@mit.edu>
 
        * read.c (parse_tag): Do not return that blkid_tag when parsing
index 6d8a776..4252835 100644 (file)
@@ -31,8 +31,8 @@ HFILES_IN=    blkid_types.h
 LIBRARY= libblkid
 LIBDIR= blkid
 
-ELF_VERSION = 2.0
-ELF_SO_VERSION = 2
+ELF_VERSION = 1.0
+ELF_SO_VERSION = 1
 ELF_IMAGE = libblkid
 ELF_MYDIR = blkid
 ELF_INSTALL_DIR = $(root_libdir)
@@ -97,7 +97,14 @@ tst_resolve: $(srcdir)/resolve.c $(DEPLIBS_BLKID)
 tst_save: $(srcdir)/save.c $(DEPLIBS_BLKID)
        $(CC) -Wall -o tst_save -DTEST_PROGRAM $(srcdir)/save.c $(LIBS_BLKID) $(LIBUUID) $(ALL_CFLAGS)
 
-check:: tst_cache tst_dev tst_devname tst_devno tst_getsize tst_probe \
+../../misc/blkid.o: $(top_srcdir)/misc/blkid.c blkid.h
+       $(CC) -Wall $(ALL_CFLAGS) -c $(top_srcdir)/misc/blkid.c \
+               -o ../../misc/blkid.o
+
+blkid: ../../misc/blkid.o libblkid.a $(LIBBLKID) $(LIBUUID)
+       $(CC) -Wall -o blkid ../../misc/blkid.o libblkid.a $(LIBBLKID) $(LIBUUID)
+
+check:: tst_cache tst_devname tst_devno tst_getsize tst_probe \
  tst_read tst_resolve tst_save
 
 installdirs::
@@ -129,7 +136,7 @@ uninstall::
 clean::
        $(RM) -f \#* *.s *.o *.orig *.a *~ *.bak tst_* core profiled/* \
                checker/* blkid_types.h ../libblkid.a ../libblkid_p.a \
-               $(SMANPAGES)
+               $(SMANPAGES) blkid
 
 mostlyclean:: clean
 distclean:: clean
@@ -140,21 +147,27 @@ distclean:: clean
 # Makefile dependencies follow.  This must be the last section in
 # the Makefile.in file
 #
-cache.o: $(srcdir)/cache.c $(srcdir)/blkid.h $(srcdir)/list.h \
- $(top_builddir)/lib/blkid/blkid_types.h
-dev.o: $(srcdir)/dev.c $(srcdir)/blkid.h $(srcdir)/list.h \
- $(top_builddir)/lib/blkid/blkid_types.h
-devname.o: $(srcdir)/devname.c $(srcdir)/blkid.h $(srcdir)/list.h \
- $(top_builddir)/lib/blkid/blkid_types.h
-devno.o: $(srcdir)/devno.c $(srcdir)/blkid.h $(srcdir)/list.h \
- $(top_builddir)/lib/blkid/blkid_types.h
-getsize.o: $(srcdir)/getsize.c $(srcdir)/blkid.h $(srcdir)/list.h \
- $(top_builddir)/lib/blkid/blkid_types.h
-llseek.o: $(srcdir)/llseek.c $(srcdir)/blkid.h $(srcdir)/list.h \
- $(top_builddir)/lib/blkid/blkid_types.h
-read.o: $(srcdir)/read.c $(srcdir)/blkid.h $(srcdir)/list.h \
- $(top_builddir)/lib/blkid/blkid_types.h $(top_srcdir)/lib/uuid/uuid.h
-save.o: $(srcdir)/save.c $(srcdir)/blkid.h $(srcdir)/list.h \
+cache.o: $(srcdir)/cache.c $(srcdir)/blkidP.h $(srcdir)/blkid.h \
+ $(srcdir)/list.h $(top_builddir)/lib/blkid/blkid_types.h
+dev.o: $(srcdir)/dev.c $(srcdir)/blkidP.h $(srcdir)/blkid.h $(srcdir)/list.h \
  $(top_builddir)/lib/blkid/blkid_types.h
-tag.o: $(srcdir)/tag.c $(srcdir)/blkid.h $(srcdir)/list.h \
+devname.o: $(srcdir)/devname.c $(srcdir)/blkidP.h $(srcdir)/blkid.h \
+ $(srcdir)/list.h $(top_builddir)/lib/blkid/blkid_types.h
+devno.o: $(srcdir)/devno.c $(srcdir)/blkidP.h $(srcdir)/blkid.h \
+ $(srcdir)/list.h $(top_builddir)/lib/blkid/blkid_types.h
+getsize.o: $(srcdir)/getsize.c $(srcdir)/blkidP.h $(srcdir)/blkid.h \
+ $(srcdir)/list.h $(top_builddir)/lib/blkid/blkid_types.h
+llseek.o: $(srcdir)/llseek.c $(srcdir)/blkidP.h $(srcdir)/blkid.h \
+ $(srcdir)/list.h $(top_builddir)/lib/blkid/blkid_types.h
+probe.o: $(srcdir)/probe.c $(srcdir)/blkidP.h $(srcdir)/blkid.h \
+ $(srcdir)/list.h $(top_builddir)/lib/blkid/blkid_types.h \
+ $(top_srcdir)/lib/uuid/uuid.h $(srcdir)/probe.h
+read.o: $(srcdir)/read.c $(srcdir)/blkidP.h $(srcdir)/blkid.h \
+ $(srcdir)/list.h $(top_builddir)/lib/blkid/blkid_types.h \
+ $(top_srcdir)/lib/uuid/uuid.h
+resolve.o: $(srcdir)/resolve.c $(srcdir)/blkidP.h $(srcdir)/blkid.h \
+ $(srcdir)/list.h $(top_builddir)/lib/blkid/blkid_types.h $(srcdir)/probe.h
+save.o: $(srcdir)/save.c $(srcdir)/blkidP.h $(srcdir)/blkid.h \
+ $(srcdir)/list.h $(top_builddir)/lib/blkid/blkid_types.h
+tag.o: $(srcdir)/tag.c $(srcdir)/blkidP.h $(srcdir)/blkid.h $(srcdir)/list.h \
  $(top_builddir)/lib/blkid/blkid_types.h
index f8faa0d..c0ec660 100644 (file)
 #ifndef _BLKID_BLKID_H
 #define _BLKID_BLKID_H
 
+#include <blkid/blkid_types.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-#define BLKID_VERSION  "1.2.0"
-#define BLKID_DATE     "22-Nov-2001"
+#define BLKID_VERSION  "1.0.0"
+#define BLKID_DATE     "12-Feb-2003"
 
 typedef struct blkid_struct_dev *blkid_dev;
-typedef struct blkid_struct_tag *blkid_tag;
 typedef struct blkid_struct_cache *blkid_cache;
+typedef __s64 blkid_loff_t;
+
+typedef struct blkid_struct_tag_iterate *blkid_tag_iterate;
+typedef struct blkid_struct_dev_iterate *blkid_dev_iterate;
+
+/*
+ * Flags for blkid_get_devname
+ *
+ * BLKID_DEV_CREATE    Create an empty device structure if not found
+ *                     in the cache.
+ * BLKID_DEV_VERIFY    Make sure the device structure corresponds
+ *                     with reality.
+ * BLKID_DEV_FIND      Just look up a device entry, and return NULL
+ *                     if it is not found.
+ * BLKID_DEV_NORMAL    Get a valid device structure, either from the
+ *                     cache or by probing the device.
+ */
+#define BLKID_DEV_FIND         0x0000
+#define BLKID_DEV_CREATE       0x0001
+#define BLKID_DEV_VERIFY       0x0002
+#define BLKID_DEV_NORMAL       (BLKID_DEV_CREATE | BLKID_DEV_VERIFY)
 
 /* cache.c */
-extern void blkid_free_cache(blkid_cache cache);
+extern void blkid_put_cache(blkid_cache cache);
 
 /* dev.c */
 extern const char *blkid_devname_name(blkid_dev dev);
 
-typedef struct blkid_struct_dev_iterate *blkid_dev_iterate;
 extern blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache);
 extern int blkid_dev_next(blkid_dev_iterate iterate, blkid_dev *dev);
 extern void blkid_dev_iterate_end(blkid_dev_iterate iterate);
 
+/* devno.c */
+extern char *blkid_devno_to_devname(dev_t devno);
+
 /* devname.c */
-extern int blkid_probe_all(blkid_cache *cache);
-extern blkid_dev blkid_get_devname(blkid_cache cache, const char *devname);
+extern int blkid_probe_all(blkid_cache cache);
+extern blkid_dev blkid_get_devname(blkid_cache cache, const char *devname,
+                                  int flags);
+
+/* getsize.c */
+extern blkid_loff_t blkid_get_dev_size(int fd);
 
 /* read.c */
-int blkid_read_cache(blkid_cache *cache, const char *filename);
+int blkid_get_cache(blkid_cache *cache, const char *filename);
 
 /* resolve.c */
 extern char *blkid_get_tagname_devname(blkid_cache cache, const char *tagname,
@@ -48,15 +76,12 @@ extern char *blkid_get_tagname_devname(blkid_cache cache, const char *tagname,
 extern char *blkid_get_token(blkid_cache cache, const char *token,
                             const char *value);
 
-/* save.c */
-extern int blkid_save_cache(blkid_cache cache, const char *filename);
-
 /* tag.c */
-typedef struct blkid_struct_tag_iterate *blkid_tag_iterate;
 extern blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev);
 extern int blkid_tag_next(blkid_tag_iterate iterate,
                              const char **type, const char **value);
 extern void blkid_tag_iterate_end(blkid_tag_iterate iterate);
+
 extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache,
                                         const char *type,
                                         const char *value);
index 6b30061..5a99802 100644 (file)
@@ -19,9 +19,6 @@
 #include <blkid/blkid.h>
 
 #include <blkid/list.h>
-#include <blkid/blkid_types.h>
-
-typedef __s64 blkid_loff_t;
 
 /*
  * This describes the attributes of a specific device.
@@ -33,6 +30,7 @@ struct blkid_struct_dev
 {
        struct list_head        bid_devs;       /* All devices in the cache */
        struct list_head        bid_tags;       /* All tags for this device */
+       blkid_cache             bid_cache;      /* Dev belongs to this cache */
        char                    *bid_name;      /* Device inode pathname */
        char                    *bid_type;      /* Preferred device TYPE */
        blkid_loff_t            bid_size;       /* Filesystem size in bytes */
@@ -47,6 +45,7 @@ struct blkid_struct_dev
 
 #define BLKID_BID_FL_VERIFIED  0x0001  /* Device data validated from disk */
 #define BLKID_BID_FL_MTYPE     0x0002  /* Device has multiple type matches */
+#define BLKID_BID_FL_INVALID   0x0004  /* Device is invalid */
 
 /*
  * Each tag defines a NAME=value pair for a particular device.  The tags
@@ -63,6 +62,7 @@ struct blkid_struct_tag
        char                    *bit_val;       /* value of tag */
        blkid_dev               bit_dev;        /* pointer to device */
 };
+typedef struct blkid_struct_tag *blkid_tag;
 
 /*
  * Minimum number of seconds between device probes, even when reading
@@ -91,19 +91,18 @@ struct blkid_struct_cache
        time_t                  bic_time;       /* Last probe time */
        unsigned int            bic_idmax;      /* Highest ID assigned */
        unsigned int            bic_flags;      /* Status flags of the cache */
+       char                    *bic_filename;  /* filename of cache */
 };
 
-#define BLKID_BIC_FL_PARSED    0x0001  /* We parsed a cache file */
 #define BLKID_BIC_FL_PROBED    0x0002  /* We probed /proc/partition devices */
 #define BLKID_BIC_FL_CHANGED   0x0004  /* Cache has changed from disk */
 
-extern char *string_copy(const char *s);
-extern char *stringn_copy(const char *s, const int length);
-extern void string_free(char *s);
+extern char *blkid_strdup(const char *s);
+extern char *blkid_strndup(const char *s, const int length);
 extern blkid_cache blkid_new_cache(void);
 
 #define BLKID_CACHE_FILE "/etc/blkid.tab"
-extern const char *devdirs[];
+extern const char *blkid_devdirs[];
 
 #define BLKID_ERR_IO    5
 #define BLKID_ERR_PROC  9
@@ -193,60 +192,28 @@ static inline void DEB_DUMP_CACHE(blkid_cache cache)
 #define DEB_DUMP_CACHE(cache) do {} while (0)
 #endif
 
-/*
- * Primitive disk functions: llseek.c, getsize.c
- */
+/* lseek.c */
 extern blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int whence);
-extern blkid_loff_t blkid_get_dev_size(int fd);
-
-/*
- * Getting data from the cache file: read.c
- */
-int blkid_read_cache_line(blkid_cache cache, blkid_dev *dev_p, char *cp);
-int blkid_read_cache_file(blkid_cache *cache, FILE *file);
-
-/*
- * Save data to the cache file: save.c
- */
-int blkid_save_cache_file(blkid_cache cache, FILE *file);
-
-/*
- * Identify a device by inode name: probe.c
- */
-extern blkid_dev blkid_devname_to_dev(const char *devname,
-                                      blkid_loff_t size);
 
-/*
- * Locate a device by inode name: devname.c
- */
-extern blkid_dev blkid_find_devname(blkid_cache cache, const char *devname);
+/* probe.c */
 extern blkid_dev blkid_verify_devname(blkid_cache cache, blkid_dev dev);
-extern blkid_dev blkid_get_devname(blkid_cache cache, const char *devname);
 
-/*
- * Locate a device by device major/minor number: devno.c
- */
-extern char *blkid_devno_to_devname(dev_t devno);
-extern blkid_dev blkid_find_devno(blkid_cache cache, dev_t devno);
-extern blkid_dev blkid_get_devno(blkid_cache cache, dev_t devno);
+/* save.c */
+extern int blkid_flush_cache(blkid_cache cache);
 
 /*
  * Functions to create and find a specific tag type: tag.c
  */
-extern blkid_tag blkid_new_tag(void);
 extern void blkid_free_tag(blkid_tag tag);
-extern int blkid_create_tag(blkid_dev dev, const char *name,
-                           const char *value, const int vlength);
-extern blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type,
-                                   const char *value);
-extern blkid_tag blkid_find_head_cache(blkid_cache cache, const char *type);
+extern blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type);
+extern int blkid_set_tag(blkid_dev dev, const char *name,
+                        const char *value, const int vlength, int replace);
 
 /*
  * Functions to create and find a specific tag type: dev.c
  */
 extern blkid_dev blkid_new_dev(void);
 extern void blkid_free_dev(blkid_dev dev);
-extern blkid_dev blkid_add_dev_to_cache(blkid_cache cache, blkid_dev dev);
 
 #ifdef __cplusplus
 }
index 188dc82..0e1fc8e 100644 (file)
@@ -2,6 +2,7 @@
  * cache.c - allocation/initialization/free routines for cache
  *
  * Copyright (C) 2001 Andreas Dilger
+ * Copyright (C) 2003 Theodore Ts'o
  *
  * %Begin-Header%
  * This file may be redistributed under the terms of the
@@ -32,12 +33,15 @@ blkid_cache blkid_new_cache(void)
        return cache;
 }
 
-void blkid_free_cache(blkid_cache cache)
+void blkid_put_cache(blkid_cache cache)
 {
        if (!cache)
                return;
 
+       (void) blkid_flush_cache(cache);
+
        DBG(printf("freeing cache struct\n"));
+       
        /* DEB_DUMP_CACHE(cache); */
 
        while (!list_empty(&cache->bic_devs)) {
@@ -63,6 +67,9 @@ void blkid_free_cache(blkid_cache cache)
                }
                blkid_free_tag(tag);
        }
+       if (cache->bic_filename)
+               free(cache->bic_filename);
+       
        free(cache);
 }
 
@@ -77,16 +84,19 @@ int main(int argc, char** argv)
                exit(1);
        }
 
-       if ((ret = blkid_read_cache(&cache, argv[1])) < 0)
+       if ((ret = blkid_get_cache(&cache, argv[1])) < 0) {
                fprintf(stderr, "error %d parsing cache file %s\n", ret,
                        argv[1] ? argv[1] : BLKID_CACHE_FILE);
-       else if ((ret = blkid_probe_all(&cache) < 0))
+               exit(1);
+       }
+       if ((cache = blkid_new_cache()) == NULL) {
+               fprintf(stderr, "%s: error creating cache\n", argv[0]);
+               exit(1);
+       }
+       if ((ret = blkid_probe_all(cache) < 0))
                fprintf(stderr, "error probing devices\n");
-       else if ((ret = blkid_save_cache(cache, argv[1])) < 0)
-               fprintf(stderr, "error %d saving cache to %s\n", ret,
-                       argv[1] ? argv[1] : BLKID_CACHE_FILE);
 
-       blkid_free_cache(cache);
+       blkid_put_cache(cache);
 
        return ret;
 }
index 2075d45..b6e675a 100644 (file)
@@ -2,6 +2,7 @@
  * dev.c - allocation/initialization/free routines for dev
  *
  * Copyright (C) 2001 Andreas Dilger
+ * Copyright (C) 2003 Theodore Ts'o
  *
  * %Begin-Header%
  * This file may be redistributed under the terms of the
@@ -50,78 +51,11 @@ void blkid_free_dev(blkid_dev dev)
                blkid_free_tag(tag);
        }
        if (dev->bid_name)
-               string_free(dev->bid_name);
+               free(dev->bid_name);
        free(dev);
 }
 
 /*
- * This is kind of ugly, but I want to be able to compare two strings in
- * several different ways.  For example, in some cases, if both strings
- * are NULL, those would be considered different, but in other cases
- * they would be considered the same.  Hence the ugliness.
- *
- * Use as:     "ret == SC_SAME" if both strings exist and are equal
- *                             this is equivalent to "!(ret & SC_DIFF)"
- *             "ret & SC_SAME" if both strings being NULL is also equal
- *                             this is equivalent to "!(ret == SC_DIFF)"
- *             "ret == SC_DIFF" if both strings exist and are different
- *                             this is equivalent to "!(ret & SC_SAME)"
- *             "ret & SC_DIFF" if both strings being NULL is also different
- *                             this is equivalent to "!(ret == SC_SAME)"
- *             "ret == SC_NONE" to see if both strings do not exist
- */
-#define SC_DIFF        0x0001
-#define SC_NONE        0x0003
-#define SC_SAME        0x0002
-
-static int string_compare(char *s1, char *s2)
-{
-       if (!s1 && !s2)
-               return SC_NONE;
-
-       if (!s1 || !s2)
-               return SC_DIFF;
-
-       if (strcmp(s1, s2))
-               return SC_DIFF;
-
-       return SC_SAME;
-}
-
-/*
- * Add a tag to the global cache tag list.
- */
-static int add_tag_to_cache(blkid_cache cache, blkid_tag tag)
-{
-       blkid_tag head = NULL;
-
-       if (!cache || !tag)
-               return 0;
-
-       DBG(printf("    adding tag %s=%s to cache\n", tag->bit_name, tag->bit_val));
-
-       if (!(head = blkid_find_head_cache(cache, tag->bit_name))) {
-               head = blkid_new_tag();
-               if (!head)
-                       return -BLKID_ERR_MEM;
-
-               DBG(printf("    creating new cache tag head %s\n",tag->bit_name));
-               head->bit_name = string_copy(tag->bit_name);
-               if (!head->bit_name) {
-                       blkid_free_tag(head);
-                       return -BLKID_ERR_MEM;
-               }
-
-               list_add_tail(&head->bit_tags, &cache->bic_tags);
-       }
-
-       /* Add this tag to global list */
-       list_add_tail(&tag->bit_names, &head->bit_names);
-
-       return 0;
-}
-
-/*
  * Given a blkid device, return its name
  */
 extern const char *blkid_devname_name(blkid_dev dev)
@@ -188,146 +122,3 @@ extern void blkid_dev_iterate_end(blkid_dev_iterate iter)
        free(iter);
 }
 
-/*
- * Add a device to the global cache list, along with all its tags.
- */
-blkid_dev blkid_add_dev_to_cache(blkid_cache cache, blkid_dev dev)
-{
-       struct list_head *p;
-
-       if (!cache || !dev)
-               return dev;
-
-       if (!dev->bid_id)
-               dev->bid_id = ++(cache->bic_idmax);
-
-       list_for_each(p, &cache->bic_devs) {
-               blkid_dev odev = list_entry(p, struct blkid_struct_dev, bid_devs);
-               int dup_uuid, dup_label, dup_name, dup_type;
-
-               dup_name = string_compare(odev->bid_name, dev->bid_name);
-               dup_label = string_compare(odev->bid_label, dev->bid_label);
-               dup_uuid = string_compare(odev->bid_uuid, dev->bid_uuid);
-
-               if (odev->bid_id == dev->bid_id)
-                       dev->bid_id = ++(cache->bic_idmax);
-
-               /* Fields different, do nothing (check more fields?) */
-               if ((dup_name & SC_DIFF) && (dup_uuid & SC_DIFF) &&
-                   (dup_label & SC_DIFF))
-                       continue;
-
-               /* We can't simply allow duplicate fields if the bid_type is
-                * different, given that a filesystem may change from ext2
-                * to ext3 but it will have the same UUID and LABEL fields.
-                * We need to discard the old cache entry in this case.
-                */
-
-               /* If the UUIDs are the same but one is unverified discard it */
-               if (dup_uuid == SC_SAME) {
-                       DBG(printf("  duplicate uuid %s\n", dev->bid_uuid));
-                       if (!(odev->bid_flags & BLKID_BID_FL_VERIFIED)) {
-                               dev->bid_id = odev->bid_id; /* keep old id */
-                               blkid_free_dev(odev);
-                               goto exit_new;
-                       } else if (!(dev->bid_flags & BLKID_BID_FL_VERIFIED)) {
-                               blkid_free_dev(dev);
-                               dev = odev;
-                               goto exit_old;
-                       }
-
-                       /* This shouldn't happen */
-                       fprintf(stderr, "blkid: same UUID for %s and %s\n",
-                               dev->bid_name, odev->bid_name);
-               }
-
-               /* If the device name is the same, discard one of them
-                * (prefer one that has been validated, or the first one).
-                */
-               if (dup_name == SC_SAME) {
-                       DBG(printf("  duplicate devname %s\n", dev->bid_name));
-                       if (odev->bid_flags & BLKID_BID_FL_VERIFIED ||
-                           !(dev->bid_flags & BLKID_BID_FL_VERIFIED)) {
-                               if ((dup_uuid & SC_SAME) &&
-                                   (dup_label & SC_SAME))      /* use old id */
-                                       dev->bid_id = odev->bid_id;
-                               blkid_free_dev(dev);
-                               dev = odev;
-                               goto exit_old;
-                       } else {
-                               blkid_free_dev(odev);
-                               goto exit_new;
-                       }
-               }
-
-               dup_type = string_compare(odev->bid_type, dev->bid_type);
-
-               if (dup_label == SC_SAME && dup_type == SC_SAME) {
-                       DBG(printf("  duplicate label %s\n", dev->bid_label));
-                       if (!(odev->bid_flags & BLKID_BID_FL_VERIFIED)) {
-                               blkid_free_dev(odev);
-                               goto exit_new;
-                       } else if (!(dev->bid_flags & BLKID_BID_FL_VERIFIED)) {
-                               blkid_free_dev(dev);
-                               dev = odev;
-                               goto exit_old;
-                       }
-                       fprintf(stderr, "blkid: same LABEL for %s and %s\n",
-                               dev->bid_name, odev->bid_name);
-               }
-       }
-
-exit_new:
-       DBG(printf("  adding new devname %s to cache\n", dev->bid_name));
-
-       cache->bic_flags |= BLKID_BIC_FL_CHANGED;
-
-       list_add_tail(&dev->bid_devs, &cache->bic_devs);
-       list_for_each(p, &dev->bid_tags) {
-               blkid_tag tag = list_entry(p, struct blkid_struct_tag, 
-                                          bit_tags);
-               add_tag_to_cache(cache, tag);
-       }
-       return dev;
-
-exit_old:
-       DBG(printf("  using old devname %s from cache\n", dev->bid_name));
-       return dev;
-}
-
-#ifdef TEST_PROGRAM
-int main(int argc, char** argv)
-{
-       blkid_cache cache;
-       blkid_dev dev, newdev;
-
-       if ((argc != 3)) {
-               fprintf(stderr, "Usage:\t%s dev1 dev2\n"
-                       "Test that adding the same device to the cache fails\n",
-                       argv[0]);
-               exit(1);
-       }
-
-       cache = blkid_new_cache();
-       if (!cache) {
-               perror(argv[0]);
-               return 1;
-       }
-       dev = blkid_devname_to_dev(argv[1], 0);
-       newdev = blkid_add_dev_to_cache(cache, dev);
-       if (newdev != dev)
-               printf("devices changed for %s (unexpected)\n", argv[1]);
-       dev = blkid_devname_to_dev(argv[2], 0);
-       newdev = blkid_add_dev_to_cache(cache, dev);
-       if (newdev != dev)
-               printf("devices changed for %s (unexpected)\n", argv[2]);
-       dev = blkid_devname_to_dev(argv[2], 0);
-       newdev = blkid_add_dev_to_cache(cache, dev);
-       if (newdev != dev)
-               printf("devices changed for %s (expected)\n", argv[2]);
-
-       blkid_free_cache(cache);
-
-       return 0;
-}
-#endif
index 2c8681d..6cb3a8e 100644 (file)
 
 /*
  * Find a dev struct in the cache by device name, if available.
+ *
+ * If there is no entry with the specified device name, and the create
+ * flag is set, then create an empty device entry.
  */
-blkid_dev blkid_find_devname(blkid_cache cache, const char *devname)
+blkid_dev blkid_get_devname(blkid_cache cache, const char *devname,
+                            int flags)
 {
-       blkid_dev dev = NULL;
+       blkid_dev dev = NULL, tmp;
        struct list_head *p;
 
        if (!cache || !devname)
                return NULL;
 
        list_for_each(p, &cache->bic_devs) {
-               blkid_dev tmp = list_entry(p, struct blkid_struct_dev, bid_devs);
-
+               tmp = list_entry(p, struct blkid_struct_dev, bid_devs);
                if (strcmp(tmp->bid_name, devname))
                        continue;
 
                DBG(printf("found devname %s in cache\n", tmp->bid_name));
-               dev = blkid_verify_devname(cache, tmp);
+               dev = tmp;
                break;
        }
 
-       return dev;
-}
-
-/*
- * Return a pointer to an dev struct, either from cache or by probing.
- */
-blkid_dev blkid_get_devname(blkid_cache cache, const char *devname)
-{
-       blkid_dev dev;
-
-       if ((dev = blkid_find_devname(cache, devname)))
-               return dev;
+       if (!dev && (flags & BLKID_DEV_CREATE)) {
+               dev = blkid_new_dev();
+               if (!dev)
+                       return NULL;
+               dev->bid_name = blkid_strdup(devname);
+               dev->bid_cache = cache;
+               dev->bid_id = ++(cache->bic_idmax);
+               list_add_tail(&dev->bid_devs, &cache->bic_devs);
+               cache->bic_flags |= BLKID_BIC_FL_CHANGED;
+       }
 
-       dev = blkid_devname_to_dev(devname, 0);
-       return blkid_add_dev_to_cache(cache, dev);
+       if (flags & BLKID_DEV_VERIFY)
+               dev = blkid_verify_devname(cache, dev);
+       return dev;
 }
 
 /*
  * Probe a single block device to add to the device cache.
- * If the size is not specified, it will be found in blkid_devname_to_dev().
  */
 static blkid_dev probe_one(blkid_cache cache, const char *ptname,
-                           int major, int minor, unsigned long long size)
+                           dev_t devno)
 {
-       dev_t devno = makedev(major, minor);
-       blkid_dev dev;
+       blkid_dev dev = NULL;
+       struct list_head *p;
        const char **dir;
        char *devname = NULL;
 
        /* See if we already have this device number in the cache. */
-       if ((dev = blkid_find_devno(cache, devno)))
+       list_for_each(p, &cache->bic_devs) {
+               blkid_dev tmp = list_entry(p, struct blkid_struct_dev,
+                                          bid_devs);
+               if (tmp->bid_devno == devno) {
+                       dev = blkid_verify_devname(cache, tmp);
+                       break;
+               }
+       }
+       if (dev && dev->bid_devno == devno)
                return dev;
 
        /*
@@ -103,17 +112,17 @@ static blkid_dev probe_one(blkid_cache cache, const char *ptname,
         * the stat information doesn't check out, use blkid_devno_to_devname()
         * to find it via an exhaustive search for the device major/minor.
         */
-       for (dir = devdirs; *dir; dir++) {
+       for (dir = blkid_devdirs; *dir; dir++) {
                struct stat st;
                char device[256];
 
                sprintf(device, "%s/%s", *dir, ptname);
-               if ((dev = blkid_find_devname(cache, device)) &&
+               if ((dev = blkid_get_devname(cache, device, BLKID_DEV_FIND)) &&
                    dev->bid_devno == devno)
                        return dev;
 
                if (stat(device, &st) == 0 && st.st_rdev == devno) {
-                       devname = string_copy(device);
+                       devname = blkid_strdup(device);
                        break;
                }
        }
@@ -122,10 +131,10 @@ static blkid_dev probe_one(blkid_cache cache, const char *ptname,
                if (!devname)
                        return NULL;
        }
-       dev = blkid_devname_to_dev(devname, size);
-       string_free(devname);
+       dev = blkid_get_devname(cache, devname, BLKID_DEV_NORMAL);
+       free(devname);
 
-       return blkid_add_dev_to_cache(cache, dev);
+       return dev;
 }
 
 #define PROC_PARTITIONS "/proc/partitions"
@@ -139,29 +148,23 @@ static blkid_dev probe_one(blkid_cache cache, const char *ptname,
  */
 #ifdef VG_DIR
 #include <dirent.h>
-static int lvm_get_devno(const char *lvm_device, int *major, int *minor,
-                        blkid_loff_t *size)
+static dev_t lvm_get_devno(const char *lvm_device)
 {
        FILE *lvf;
        char buf[1024];
-       int ret = 1;
-
-       *major = *minor = 0;
-       *size = 0;
+       int ma, mi;
+       dev_t ret = 0;
 
        DBG(printf("opening %s\n", lvm_device));
        if ((lvf = fopen(lvm_device, "r")) == NULL) {
-               ret = errno;
-               DBG(printf("%s: (%d) %s\n", lvm_device, ret, strerror(ret)));
-               return -ret;
+               DBG(printf("%s: (%d) %s\n", lvm_device, errno,
+                          strerror(errno)));
+               return 0;
        }
 
        while (fgets(buf, sizeof(buf), lvf)) {
-               if (sscanf(buf, "size: %llu", size) == 1) { /* sectors */
-                       *size <<= 9;
-               }
-               if (sscanf(buf, "device: %d:%d", major, minor) == 2) {
-                       ret = 0;
+               if (sscanf(buf, "device: %d:%d", &ma, &mi) == 2) {
+                       ret = makedev(ma, mi);
                        break;
                }
        }
@@ -170,11 +173,12 @@ static int lvm_get_devno(const char *lvm_device, int *major, int *minor,
        return ret;
 }
 
-static void lvm_probe_all(blkid_cache *cache)
+static void lvm_probe_all(blkid_cache cache)
 {
        DIR             *vg_list;
        struct dirent   *vg_iter;
        int             vg_len = strlen(VG_DIR);
+       dev_t           dev;
 
        if ((vg_list = opendir(VG_DIR)) == NULL)
                return;
@@ -202,8 +206,6 @@ static void lvm_probe_all(blkid_cache *cache)
 
                while ((lv_iter = readdir(lv_list)) != NULL) {
                        char            *lv_name, *lvm_device;
-                       int             major, minor;
-                       blkid_loff_t    size;
 
                        lv_name = lv_iter->d_name;
                        if (!strcmp(lv_name, ".") || !strcmp(lv_name, ".."))
@@ -217,14 +219,11 @@ static void lvm_probe_all(blkid_cache *cache)
                        }
                        sprintf(lvm_device, "%s/%s/LVs/%s", VG_DIR, vg_name,
                                lv_name);
-                       if (lvm_get_devno(lvm_device, &major, &minor, &size)) {
-                               free(lvm_device);
-                               continue;
-                       }
+                       dev = lvm_get_devno(lvm_device);
                        sprintf(lvm_device, "%s/%s", vg_name, lv_name);
-                       DBG(printf("LVM dev %s: devno 0x%02X%02X, size %Ld\n",
-                                  lvm_device, major, minor, size));
-                       probe_one(*cache, lvm_device, major, minor, size);
+                       DBG(printf("LVM dev %s: devno 0x%04X\n",
+                                  lvm_device, dev));
+                       probe_one(cache, lvm_device, dev);
                        free(lvm_device);
                }
                closedir(lv_list);
@@ -237,7 +236,7 @@ exit:
 #define PROC_EVMS_VOLUMES "/proc/evms/volumes"
 
 static int
-evms_probe_all(blkid_cache *cache)
+evms_probe_all(blkid_cache cache)
 {
        char line[100];
        int ma, mi, sz, num = 0;
@@ -255,7 +254,7 @@ evms_probe_all(blkid_cache *cache)
                DBG(printf("Checking partition %s (%d, %d)\n",
                           device, ma, mi));
 
-               probe_one(*cache, device, ma, mi, sz << 10);
+               probe_one(cache, device, makedev(ma, mi));
                num++;
        }
        fclose(procpt);
@@ -265,7 +264,7 @@ evms_probe_all(blkid_cache *cache)
 /*
  * Read the device data for all available block devices in the system.
  */
-int blkid_probe_all(blkid_cache *cache)
+int blkid_probe_all(blkid_cache cache)
 {
        FILE *proc;
        int firstPass;
@@ -273,14 +272,8 @@ int blkid_probe_all(blkid_cache *cache)
        if (!cache)
                return -BLKID_ERR_PARAM;
 
-       if (!*cache)
-               *cache = blkid_new_cache();
-
-       if (!*cache)
-               return -BLKID_ERR_MEM;
-
-       if ((*cache)->bic_flags & BLKID_BIC_FL_PROBED &&
-           time(0) - (*cache)->bic_time < BLKID_PROBE_INTERVAL)
+       if (cache->bic_flags & BLKID_BIC_FL_PROBED &&
+           time(0) - cache->bic_time < BLKID_PROBE_INTERVAL)
                return 0;
 
        if (evms_probe_all(cache))
@@ -296,10 +289,11 @@ int blkid_probe_all(blkid_cache *cache)
 
        for (firstPass = 1; firstPass >= 0; firstPass--) {
                char line[1024];
-               char ptname0[128], ptname1[128];
+               char ptname0[128], ptname1[128], *ptname = 0;
                char *ptnames[2] = { ptname0, ptname1 };
-               int majors[2], minors[2];
-               unsigned long long sizes[2];
+               dev_t devs[2];
+               int ma, mi;
+               unsigned long long sz;
                int lens[2] = { 0, 0 };
                int handleOnFirst;
                int which = 0, last = 0;
@@ -309,16 +303,17 @@ int blkid_probe_all(blkid_cache *cache)
                while (fgets(line, sizeof(line), proc)) {
                        last = which;
                        which ^= 1;
+                       ptname = ptnames[which];
 
                        if (sscanf(line, " %d %d %lld %128[^\n ]",
-                                  &majors[which], &minors[which],
-                                  &sizes[which], ptnames[which]) != 4)
+                                  &ma, &mi, &sz, ptname) != 4)
                                continue;
+                       devs[which] = makedev(ma, mi);
 
-                       DBG(printf("read partition name %s\n", ptnames[which]));
+                       DBG(printf("read partition name %s\n", ptname));
 
                        /* look only at md devices on first pass */
-                       handleOnFirst = !strncmp(ptnames[which], "md", 2);
+                       handleOnFirst = !strncmp(ptname, "md", 2);
                        if (firstPass != handleOnFirst)
                                continue;
 
@@ -333,40 +328,34 @@ int blkid_probe_all(blkid_cache *cache)
                         * FIXME: skip /dev/{ida,cciss,rd} whole-disk devs
                         */
 
-                       lens[which] = strlen(ptnames[which]);
-                       if (isdigit(ptnames[which][lens[which] - 1])) {
-                               DBG(printf("partition dev %s, devno 0x%02X%02X\n",
-                                          ptnames[which], majors[which],
-                                          minors[which]));
+                       lens[which] = strlen(ptname);
+                       if (isdigit(ptname[lens[which] - 1])) {
+                               DBG(printf("partition dev %s, devno 0x%04X\n",
+                                          ptname, devs[which]));
 
-                               if (sizes[which] > 1)
-                                       probe_one(*cache, ptnames[which],
-                                                 majors[which], minors[which],
-                                                 sizes[which] << 10);
+                               if (sz > 1)
+                                       probe_one(cache, ptname, devs[which]);
                                lens[which] = 0;
                                lens[last] = 0;
                        } else if (lens[last] &&
-                                  strncmp(ptnames[last], ptnames[which],
+                                  strncmp(ptnames[last], ptname,
                                           lens[last])) {
-                               DBG(printf("whole dev %s, devno 0x%02X%02X\n",
-                                          ptnames[last], majors[last],
-                                          minors[last]));
-                               probe_one(*cache, ptnames[last], majors[last],
-                                         minors[last], sizes[last] << 10);
+                               DBG(printf("whole dev %s, devno 0x%04X\n",
+                                          ptname, devs[last]));
+                               probe_one(cache, ptname, devs[last]);
                                lens[last] = 0;
                        }
                }
 
                /* Handle the last device if it wasn't partitioned */
                if (lens[which])
-                       probe_one(*cache, ptnames[which], majors[which],
-                                 minors[which], sizes[which] << 10);
+                       probe_one(cache, ptname, devs[which]);
        }
        fclose(proc);
 
 finish:
-       (*cache)->bic_time = time(0);
-       (*cache)->bic_flags |= BLKID_BIC_FL_PROBED;
+       cache->bic_time = time(0);
+       cache->bic_flags |= BLKID_BIC_FL_PROBED;
 
        return 0;
 }
@@ -381,10 +370,14 @@ int main(int argc, char **argv)
                        "Probe all devices and exit\n", argv[0]);
                exit(1);
        }
-       if (blkid_probe_all(&cache) < 0)
+       if ((cache = blkid_new_cache()) == NULL) {
+               fprintf(stderr, "%s: error creating cache\n", argv[0]);
+               exit(1);
+       }
+       if (blkid_probe_all(cache) < 0)
                printf("%s: error probing devices\n", argv[0]);
 
-       blkid_free_cache(cache);
+       blkid_put_cache(cache);
        return (0);
 }
 #endif
index 1fe7309..41fdc3d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * devno.c - find a particular device by its device number (major/minor)
  *
- * Copyright (C) 2000, 2001 Theodore Ts'o
+ * Copyright (C) 2000, 2001, 2003 Theodore Ts'o
  * Copyright (C) 2001 Andreas Dilger
  *
  * %Begin-Header%
@@ -44,13 +44,16 @@ struct dir_list {
        struct dir_list *next;
 };
 
-char *stringn_copy(const char *s, const int length)
+char *blkid_strndup(const char *s, int length)
 {
        char *ret;
 
        if (!s)
                return NULL;
 
+       if (!length)
+               length = strlen(s);
+
        ret = malloc(length + 1);
        if (ret) {
                strncpy(ret, s, length);
@@ -59,18 +62,9 @@ char *stringn_copy(const char *s, const int length)
        return ret;
 }
 
-char *string_copy(const char *s)
+char *blkid_strdup(const char *s)
 {
-       if (!s)
-               return NULL;
-
-       return stringn_copy(s, strlen(s));
-}
-
-void string_free(char *s)
-{
-       if (s)
-               free(s);
+       return blkid_strndup(s, 0);
 }
 
 /*
@@ -83,7 +77,7 @@ static void add_to_dirlist(const char *name, struct dir_list **list)
        dp = malloc(sizeof(struct dir_list));
        if (!dp)
                return;
-       dp->name = string_copy(name);
+       dp->name = blkid_strdup(name);
        if (!dp->name) {
                free(dp);
                return;
@@ -101,58 +95,52 @@ static void free_dirlist(struct dir_list **list)
 
        for (dp = *list; dp; dp = next) {
                next = dp->next;
-               string_free(dp->name);
+               free(dp->name);
                free(dp);
        }
        *list = NULL;
 }
 
-static int scan_dir(char *dirname, dev_t devno, struct dir_list **list,
-                   char **devname)
+static void scan_dir(char *dirname, dev_t devno, struct dir_list **list,
+                           char **devname)
 {
        DIR     *dir;
        struct dirent *dp;
        char    path[1024];
        int     dirlen;
        struct stat st;
-       int     ret = 0;
 
-       dirlen = strlen(dirname);
        if ((dir = opendir(dirname)) == NULL)
-               return errno;
-       dp = readdir(dir);
-       while (dp) {
-               if (dirlen + strlen(dp->d_name) + 2 >= sizeof(path))
-                       goto skip_to_next;
+               return;
+       dirlen = strlen(dirname) + 2;
+       while ((dp = readdir(dir)) != 0) {
+               if (dirlen + strlen(dp->d_name) >= sizeof(path))
+                       continue;
 
                if (dp->d_name[0] == '.' &&
                    ((dp->d_name[1] == 0) ||
                     ((dp->d_name[1] == '.') && (dp->d_name[2] == 0))))
-                       goto skip_to_next;
+                       continue;
 
                sprintf(path, "%s/%s", dirname, dp->d_name);
                if (stat(path, &st) < 0)
-                       goto skip_to_next;
+                       continue;
 
                if (S_ISDIR(st.st_mode))
                        add_to_dirlist(path, list);
                else if (S_ISBLK(st.st_mode) && st.st_rdev == devno) {
-                       *devname = string_copy(path);
+                       *devname = blkid_strdup(path);
                        DBG(printf("found 0x%Lx at %s (%p)\n", devno,
-                                  *devname, *devname));
-                       if (!*devname)
-                               ret = -BLKID_ERR_MEM;
+                                  path, *devname));
                        break;
                }
-       skip_to_next:
-               dp = readdir(dir);
        }
        closedir(dir);
-       return ret;
+       return;
 }
 
 /* Directories where we will try to search for device numbers */
-const char *devdirs[] = { "/dev", "/devfs", "/devices", NULL };
+const char *blkid_devdirs[] = { "/devices", "/devfs", "/dev", NULL };
 
 /*
  * This function finds the pathname to a block device with a given
@@ -169,13 +157,8 @@ char *blkid_devno_to_devname(dev_t devno)
         * Add the starting directories to search in reverse order of
         * importance, since we are using a stack...
         */
-       for (dir = devdirs; *dir; dir++)
-               /* go to end of list */;
-
-       do {
-               --dir;
+       for (dir = blkid_devdirs; *dir; dir++)
                add_to_dirlist(*dir, &list);
-       } while (dir != devdirs);
 
        while (list) {
                struct dir_list *current = list;
@@ -183,7 +166,7 @@ char *blkid_devno_to_devname(dev_t devno)
                list = list->next;
                DBG(printf("directory %s\n", current->name));
                scan_dir(current->name, devno, &new_list, &devname);
-               string_free(current->name);
+               free(current->name);
                free(current);
                if (devname)
                        break;
@@ -200,61 +183,14 @@ char *blkid_devno_to_devname(dev_t devno)
        free_dirlist(&new_list);
 
        if (!devname)
-               fprintf(stderr, "blkid: couldn't find devno 0x%04lx\n", 
-                       (unsigned long) devno);
+               DBG(printf("blkid: couldn't find devno 0x%04lx\n", 
+                          (unsigned long) devno));
        else
                DBG(printf("found devno 0x%04Lx as %s\n", devno, devname));
 
        return devname;
 }
 
-blkid_dev blkid_find_devno(blkid_cache cache, dev_t devno)
-{
-       blkid_dev dev = NULL;
-       struct list_head *p, *n;
-
-       if (!cache)
-               return NULL;
-
-       /* This cannot be a standard list_for_each() because we may be
-        * deleting the referenced struct in blkid_verify_devname() and
-        * pointing to another one that was probed from disk, and "p"
-        * would point to freed memory.
-        */
-       list_for_each_safe(p, n, &cache->bic_devs) {
-               blkid_dev tmp = list_entry(p, struct blkid_struct_dev, bid_devs);
-               if (tmp->bid_devno != devno)
-                       continue;
-
-               tmp = blkid_verify_devname(cache, tmp);
-               if (!tmp || tmp->bid_devno != devno)
-                       continue;
-
-               dev = tmp;
-               break;
-       }
-
-       if (dev)
-               DBG(printf("found devno 0x%04LX in cache as %s\n",
-                          devno, dev->bid_name));
-
-       return dev;
-}
-
-blkid_dev blkid_get_devno(blkid_cache cache, dev_t devno)
-{
-       char *devname;
-       blkid_dev dev;
-
-       if (!(dev = blkid_find_devno(cache, devno)) &&
-           (devname = blkid_devno_to_devname(devno))) {
-               dev = blkid_get_devname(cache, devname);
-               string_free(devname);
-       }
-
-       return dev;
-}
-
 #ifdef TEST_PROGRAM
 int main(int argc, char** argv)
 {
@@ -291,7 +227,7 @@ int main(int argc, char** argv)
        printf("Looking for device 0x%04Lx\n", devno);
        devname = blkid_devno_to_devname(devno);
        if (devname)
-               string_free(devname);
+               free(devname);
        return 0;
 }
 #endif
index 98f487f..78d1762 100644 (file)
@@ -80,11 +80,9 @@ or visit
 http://www.gnu.org/licenses/licenses.html#LGPL
 .UE
 .SH "SEE ALSO"
-.BR blkid_read_cache (3),
-.BR blkid_save_cache (3),
-.BR blkid_free_cache (3),
+.BR blkid_get_cache (3),
+.BR blkid_put_cache (3),
 .BR blkid_get_devname (3),
-.BR blkid_get_devno (3),
 .BR blkid_probe_all (3),
 .BR blkid_free_dev (3),
 .BR blkid_find_tag_dev (3),
index 9969a97..eeb544c 100644 (file)
@@ -3,7 +3,7 @@
  *           struct with the details
  *
  * Copyright (C) 1999 by Andries Brouwer
- * Copyright (C) 1999, 2000 by Theodore Ts'o
+ * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
  * Copyright (C) 2001 by Andreas Dilger
  *
  * %Begin-Header%
 #endif
 
 /*
- * Do the required things for instantiating a new device.  This is called if
- * there is nor a probe handler for a filesystem type, and is also called by
- * the filesystem-specific types to do common initialization tasks.
- *
- * The devname, dev_p, and id fields are required.  The buf is
- * a buffer to return superblock data in.
+ * This is a special case code to check for an MDRAID device.  We do
+ * this special since it requires checking for a superblock at the end
+ * of the device.
  */
-static int probe_default(int fd, blkid_dev *dev_p, const char *devname,
-                        struct blkid_magic *id, unsigned char *buf,
-                        blkid_loff_t size)
+static int check_mdraid(int fd, unsigned char *ret_uuid)
 {
-       blkid_loff_t offset;
-       blkid_dev dev;
-       struct stat st;
-       int ret;
-
-       if (!devname || !dev_p || !id || !buf || fd < 0)
+       struct mdp_superblock_s *md;
+       blkid_loff_t            offset;
+       char                    buf[4096];
+       
+       if (fd < 0)
                return -BLKID_ERR_PARAM;
 
-       if (fstat(fd, &st) < 0 || !S_ISBLK(st.st_mode))
-               return -BLKID_ERR_DEV;
-
-       offset = (blkid_loff_t)id->bim_kboff << 10;
-       if (id->bim_kboff < 0)
-               offset += (size & ~((blkid_loff_t)(id->bim_align - 1)));
+       offset = (blkid_get_dev_size(fd) & ~((blkid_loff_t)65535)) - 65536;
 
        if (blkid_llseek(fd, offset, 0) < 0 ||
-           read(fd, buf, id->bim_kbsize << 10) != id->bim_kbsize << 10)
+           read(fd, buf, 4096) != 4096)
                return -BLKID_ERR_IO;
 
-       /* Revalidate magic for blkid_validate_devname */
-       if (memcmp(id->bim_magic, buf + id->bim_sboff, id->bim_len))
+       /* Check for magic number */
+       if (memcmp("\251+N\374", buf, 4))
                return -BLKID_ERR_PARAM;
 
-       dev = blkid_new_dev();
-       if (!dev)
-               return -BLKID_ERR_MEM;
+       if (!ret_uuid)
+               return 0;
+       *ret_uuid = 0;
 
-       dev->bid_name = string_copy(devname);
-       if (!dev->bid_name) {
-               ret = -BLKID_ERR_MEM;
-               goto exit_dev;
+       /* The MD UUID is not contiguous in the superblock, make it so */
+       md = (struct mdp_superblock_s *)buf;
+       if (md->set_uuid0 || md->set_uuid1 || md->set_uuid2 || md->set_uuid3) {
+               memcpy(ret_uuid, &md->set_uuid0, 4);
+               memcpy(ret_uuid, &md->set_uuid1, 12);
        }
+       return 0;
+}
 
-       /* Don't set this until there is no chance of error */
-       *dev_p = dev;
-       dev->bid_devno = st.st_rdev;
-       dev->bid_devsize = size;
-       dev->bid_time = time(0);
-       dev->bid_flags |= BLKID_BID_FL_VERIFIED;
-
-       if (id->bim_type)
-               blkid_create_tag(dev, "TYPE", id->bim_type,
-                                strlen(id->bim_type));
-
-       DBG(printf("%s: devno 0x%04Lx, type %s\n", devname,
-                  st.st_rdev, id->bim_type));
+static void set_uuid(blkid_dev dev, uuid_t uuid)
+{
+       char    str[37];
 
-       return 0;
-exit_dev:
-       blkid_free_dev(dev);
-       return ret;
+       if (!uuid_is_null(uuid)) {
+               uuid_unparse(uuid, str);
+               blkid_set_tag(dev, "UUID", str, sizeof(str), 1);
+       }
 }
 
-static int probe_ext2(int fd, blkid_dev *dev_p, const char *devname,
+static int probe_ext2(int fd, blkid_cache cache, blkid_dev dev,
                      struct blkid_magic *id, unsigned char *buf,
-                     blkid_loff_t size)
+                     const char **ret_sectype)
 {
-       blkid_dev dev;
        struct ext2_super_block *es;
-       int ret;
-
-       if ((ret = probe_default(fd, &dev, devname, id, buf, size)) < 0)
-               return ret;
 
        es = (struct ext2_super_block *)buf;
 
-       DBG(printf("size = %Ld, ext2_sb.compat = %08X:%08X:%08X\n", size,
+       DBG(printf("ext2_sb.compat = %08X:%08X:%08X\n", 
                   blkid_le32(es->s_feature_compat),
                   blkid_le32(es->s_feature_incompat),
                   blkid_le32(es->s_feature_ro_compat)));
 
        /* Make sure we don't keep re-probing as ext2 for a journaled fs */
        if (!strcmp(id->bim_type, "ext2") &&
-           (blkid_le32(es->s_feature_compat) &
-            EXT3_FEATURE_COMPAT_HAS_JOURNAL ||
-            blkid_le32(es->s_feature_incompat) &
-            EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
-               blkid_free_dev(dev);
+           ((blkid_le32(es->s_feature_compat) &
+             EXT3_FEATURE_COMPAT_HAS_JOURNAL) ||
+            (blkid_le32(es->s_feature_incompat) &
+             EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)))
                return -BLKID_ERR_PARAM;
-       }
-
-       /* Don't set this until there is no chance of error */
-       *dev_p = dev;
 
-       dev->bid_size = (blkid_loff_t)blkid_le32(es->s_blocks_count) <<
-               (blkid_le32(es->s_log_block_size) + 10);
+       if (strlen(es->s_volume_name))
+               blkid_set_tag(dev, "LABEL", es->s_volume_name,
+                             sizeof(es->s_volume_name), 1);
 
-       if (strlen(es->s_volume_name)) {
-               blkid_create_tag(dev, "LABEL", es->s_volume_name,
-                                sizeof(es->s_volume_name));
-       }
-
-       if (!uuid_is_null(es->s_uuid)) {
-               char uuid[37];
-               uuid_unparse(es->s_uuid, uuid);
-               blkid_create_tag(dev, "UUID", uuid, sizeof(uuid));
-       }
+       set_uuid(dev, es->s_uuid);
 
        return 0;
 }
 
-static int probe_jbd(int fd, blkid_dev *dev_p, const char *devname,
+static int probe_jbd(int fd, blkid_cache cache, blkid_dev dev, 
                     struct blkid_magic *id, unsigned char *buf,
-                    blkid_loff_t size)
+                    const char **ret_sectype)
 {
-       blkid_dev dev;
-       struct ext2_super_block *es;
-       int ret;
-
-       if ((ret = probe_ext2(fd, &dev, devname, id, buf, size)) < 0)
-               return ret;
-
-       es = (struct ext2_super_block *)buf;
+       struct ext2_super_block *es = (struct ext2_super_block *) buf;
 
        if (!(blkid_le32(es->s_feature_incompat) &
-             EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
-               blkid_free_dev(dev);
+             EXT3_FEATURE_INCOMPAT_JOURNAL_DEV))
                return -BLKID_ERR_PARAM;
-       }
 
-       /* Don't set this until there is no chance of error */
-       *dev_p = dev;
-       return 0;
+       return (probe_ext2(fd, cache, dev, id, buf, ret_sectype));
 }
 
-static int probe_ext3(int fd, blkid_dev *dev_p, const char *devname,
-                    struct blkid_magic *id, unsigned char *buf,
-                    blkid_loff_t size)
+static int probe_ext3(int fd, blkid_cache cache, blkid_dev dev,
+                     struct blkid_magic *id, unsigned char *buf,
+                     const char **ret_sectype)
 {
-       blkid_dev dev;
-       struct ext2_super_block *es;
+       struct ext2_super_block *es = (struct ext2_super_block *) buf;
        int ret;
 
-       if ((ret = probe_ext2(fd, &dev, devname, id, buf, size)) < 0)
-               return ret;
-
-       es = (struct ext2_super_block *)buf;
-
        if (!(blkid_le32(es->s_feature_compat) &
-             EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
-               blkid_free_dev(dev);
-               *dev_p = NULL;
+             EXT3_FEATURE_COMPAT_HAS_JOURNAL))
                return -BLKID_ERR_PARAM;
-       }
-       /* Don't set this until there is no chance of error */
-       *dev_p = dev;
+
+       if ((ret = probe_ext2(fd, cache, dev, id, buf, ret_sectype)) < 0)
+               return ret;
 
        if (!(blkid_le32(es->s_feature_incompat) &
-             EXT3_FEATURE_INCOMPAT_RECOVER)) {
-               blkid_create_tag(dev, "TYPE", "ext2", 4);
-               dev->bid_flags |= BLKID_BID_FL_MTYPE;
-       }
+             EXT3_FEATURE_INCOMPAT_RECOVER))
+               *ret_sectype = "ext2";
 
        return 0;
 }
 
-static int probe_vfat(int fd, blkid_dev *dev_p, const char *devname,
+static int probe_vfat(int fd, blkid_cache cache, blkid_dev dev,
                      struct blkid_magic *id, unsigned char *buf,
-                     blkid_loff_t size)
+                     const char **ret_sectype)
 {
-       blkid_dev dev;
        struct vfat_super_block *vs;
        char serno[10];
-       blkid_loff_t sectors;
-       int cluster_size;
-       int ret;
-
-       if ((ret = probe_default(fd, &dev, devname, id, buf, size)) < 0)
-               return ret;
 
        vs = (struct vfat_super_block *)buf;
 
-       /* Don't set this until there is no chance of error */
-       *dev_p = dev;
-
-       sectors = ((vs->vs_sectors[1] << 8) | vs->vs_sectors[0]);
-       if (sectors == 0)
-               sectors = vs->vs_total_sect;
-       cluster_size = ((vs->vs_sector_size[1] << 8) | vs->vs_sector_size[0]);
-       dev->bid_size = sectors * cluster_size;
-       DBG(printf("%lld %d byte sectors\n", sectors, cluster_size));
-
        if (strncmp(vs->vs_label, "NO NAME", 7)) {
                char *end = vs->vs_label + sizeof(vs->vs_label) - 1;
 
                while (*end == ' ' && end >= vs->vs_label)
                        --end;
                if (end >= vs->vs_label)
-                       blkid_create_tag(dev, "LABEL", vs->vs_label,
-                                        end - vs->vs_label + 1);
+                       blkid_set_tag(dev, "LABEL", vs->vs_label,
+                                     end - vs->vs_label + 1, 1);
        }
 
        /* We can't just print them as %04X, because they are unaligned */
        sprintf(serno, "%02X%02X-%02X%02X", vs->vs_serno[3], vs->vs_serno[2],
                vs->vs_serno[1], vs->vs_serno[0]);
-       blkid_create_tag(dev, "UUID", serno, sizeof(serno));
+       blkid_set_tag(dev, "UUID", serno, sizeof(serno), 1);
 
        return 0;
 }
 
-static int probe_msdos(int fd, blkid_dev *dev_p, const char *devname,
+static int probe_msdos(int fd, blkid_cache cache, blkid_dev dev,
                       struct blkid_magic *id, unsigned char *buf,
-                      blkid_loff_t size)
+                      const char **ret_sectype)
 {
-       blkid_dev dev;
-       struct msdos_super_block *ms;
+       struct msdos_super_block *ms = (struct msdos_super_block *) buf;
        char serno[10];
-       int cluster_size;
-       blkid_loff_t sectors;
-       int ret;
-
-       if ((ret = probe_default(fd, &dev, devname, id, buf, size)) < 0)
-               return ret;
-
-       ms = (struct msdos_super_block *)buf;
-
-       /* Don't set this until there is no chance of error */
-       *dev_p = dev;
-
-       sectors = ((ms->ms_sectors[1] << 8) | ms->ms_sectors[0]);
-       if (sectors == 0)
-               sectors = ms->ms_total_sect;
-       cluster_size = ((ms->ms_sector_size[1] << 8) | ms->ms_sector_size[0]);
-       dev->bid_size = sectors * cluster_size;
-       DBG(printf("%Ld %d byte sectors\n", sectors, cluster_size));
 
        if (strncmp(ms->ms_label, "NO NAME", 7)) {
                char *end = ms->ms_label + sizeof(ms->ms_label) - 1;
@@ -282,445 +189,133 @@ static int probe_msdos(int fd, blkid_dev *dev_p, const char *devname,
                while (*end == ' ' && end >= ms->ms_label)
                        --end;
                if (end >= ms->ms_label)
-                       blkid_create_tag(dev, "LABEL", ms->ms_label,
-                                        end - ms->ms_label + 1);
+                       blkid_set_tag(dev, "LABEL", ms->ms_label,
+                                     end - ms->ms_label + 1, 1);
        }
 
        /* We can't just print them as %04X, because they are unaligned */
        sprintf(serno, "%02X%02X-%02X%02X", ms->ms_serno[3], ms->ms_serno[2],
                ms->ms_serno[1], ms->ms_serno[0]);
-       blkid_create_tag(dev, "UUID", serno, sizeof(serno));
+       blkid_set_tag(dev, "UUID", serno, 0, 1);
 
        return 0;
 }
 
-static int probe_xfs(int fd, blkid_dev *dev_p, const char *devname,
+static int probe_xfs(int fd, blkid_cache cache, blkid_dev dev,
                     struct blkid_magic *id, unsigned char *buf,
-                    blkid_loff_t size)
+                    const char **ret_sectype)
 {
-       blkid_dev dev;
        struct xfs_super_block *xs;
-       int ret;
-
-       if ((ret = probe_default(fd, &dev, devname, id, buf, size)) < 0)
-               return ret;
 
        xs = (struct xfs_super_block *)buf;
 
-       /* Don't set this until there is no chance of error */
-       *dev_p = dev;
-       /* If the filesystem size is larger than the device, this is bad */
-       dev->bid_size = blkid_be64(xs->xs_dblocks) *
-               blkid_be32(xs->xs_blocksize);
-
        if (strlen(xs->xs_fname))
-               blkid_create_tag(dev, "LABEL", xs->xs_fname,
-                                sizeof(xs->xs_fname));
-
-       if (!uuid_is_null(xs->xs_uuid)) {
-               char uuid[37];
-               uuid_unparse(xs->xs_uuid, uuid);
-               blkid_create_tag(dev, "UUID", uuid, sizeof(uuid));
-       }
+               blkid_set_tag(dev, "LABEL", xs->xs_fname,
+                             sizeof(xs->xs_fname), 1);
+       set_uuid(dev, xs->xs_uuid);
        return 0;
 }
 
-static int probe_reiserfs(int fd, blkid_dev *dev_p, const char *devname,
+static int probe_reiserfs(int fd, blkid_cache cache, blkid_dev dev,
                          struct blkid_magic *id, unsigned char *buf,
-                         blkid_loff_t size)
+                         const char **ret_sectype)
 {
-       blkid_dev dev;
-       struct reiserfs_super_block *rs;
+       struct reiserfs_super_block *rs = (struct reiserfs_super_block *) buf;
        unsigned int blocksize;
-       int ret;
-
-       if ((ret = probe_default(fd, &dev, devname, id, buf, size)) < 0)
-               return ret;
-
-       rs = (struct reiserfs_super_block *)buf;
 
        blocksize = blkid_le16(rs->rs_blocksize);
 
        /* If the superblock is inside the journal, we have the wrong one */
-       if (id->bim_kboff/(blocksize>>10) > blkid_le32(rs->rs_journal_block)) {
-               blkid_free_dev(dev);
+       if (id->bim_kboff/(blocksize>>10) > blkid_le32(rs->rs_journal_block))
                return -BLKID_ERR_BIG;
-       }
-
-       /* Don't set this until there is no chance of error */
-       *dev_p = dev;
-
-       /* If the filesystem size is larger than the device, this is bad */
-       dev->bid_size = blkid_le32(rs->rs_blocks_count) * blocksize;
 
        /* LABEL/UUID are only valid for later versions of Reiserfs v3.6. */
        if (!strcmp(id->bim_magic, "ReIsEr2Fs") ||
            !strcmp(id->bim_magic, "ReIsEr3Fs")) {
                if (strlen(rs->rs_label)) {
-                       blkid_create_tag(dev, "LABEL", rs->rs_label,
-                                        sizeof(rs->rs_label));
-               }
-
-               if (!uuid_is_null(rs->rs_uuid)) {
-                       char uuid[37];
-                       uuid_unparse(rs->rs_uuid, uuid);
-                       blkid_create_tag(dev, "UUID", uuid, sizeof(uuid));
+                       blkid_set_tag(dev, "LABEL", rs->rs_label,
+                                     sizeof(rs->rs_label), 1);
                }
-       }
-
-       return 0;
-}
 
-static int probe_minix(int fd, blkid_dev *dev_p, const char *devname,
-                      struct blkid_magic *id, unsigned char *buf,
-                      blkid_loff_t size)
-{
-       blkid_dev dev;
-       struct minix_super_block *ms;
-       int ret;
-
-       if ((ret = probe_default(fd, &dev, devname, id, buf, size)) < 0)
-               return ret;
-
-       ms = (struct minix_super_block *)buf;
-
-       /* Don't set this until there is no chance of error */
-       *dev_p = dev;
-       dev->bid_size = ms->ms_nzones << ms->ms_log_zone_size;
-       return 0;
-}
-
-static int probe_swap(int fd, blkid_dev *dev_p, const char *devname,
-                     struct blkid_magic *id, unsigned char *buf,
-                     blkid_loff_t size)
-{
-       blkid_dev dev;
-       struct swap_header *sh;
-       int psize;
-       int ret;
-
-       if ((ret = probe_default(fd, &dev, devname, id, buf, size)) < 0)
-               return ret;
-
-       /* PAGE_SIZE can be found by where the magic is located */
-       psize = (id->bim_kboff << 10) + (id->bim_sboff + 10);
-
-       /* Don't set this until there is no chance of error */
-       *dev_p = dev;
-
-       sh = (struct swap_header *)buf;
-       /* Is swap data in local endian format? */
-       dev->bid_size = (blkid_loff_t)(sh->sh_last_page + 1) * psize;
-
-       /* A label can not exist on the old (128MB max) swap format */
-       if (!strcmp(id->bim_magic, "SWAPSPACE2") && sh->sh_label[0]) {
-               blkid_create_tag(dev, "LABEL", sh->sh_label,
-                                sizeof(sh->sh_label));
+               set_uuid(dev, rs->rs_uuid);
        }
 
        return 0;
 }
 
-static int probe_mdraid(int fd, blkid_dev *dev_p, const char *devname,
-                       struct blkid_magic *id, unsigned char *buf,
-                       blkid_loff_t size)
-{
-       blkid_dev dev;
-       struct mdp_superblock_s *md;
-       int ret;
-
-       if ((ret = probe_default(fd, &dev, devname, id, buf, size)) < 0)
-               return ret;
-
-       /* Don't set this until there is no chance of error */
-       *dev_p = dev;
-
-       md = (struct mdp_superblock_s *)buf;
-       /* What units is md->size in?  Assume 512-byte sectors? */
-       dev->bid_size = md->size * 512;
-
-       /* The MD UUID is not contiguous in the superblock, make it so */
-       if (md->set_uuid0 || md->set_uuid1 || md->set_uuid2 || md->set_uuid3) {
-               unsigned char md_uuid[16];
-               char uuid[37];
-
-               memcpy(md_uuid, &md->set_uuid0, 4);
-               memcpy(md_uuid + 4, &md->set_uuid1, 12);
-
-               uuid_unparse(md_uuid, uuid);
-               blkid_create_tag(dev, "UUID", uuid, sizeof(uuid));
-       }
-       return 0;
-}
-
-static int probe_hfs(int fd, blkid_dev *dev_p, const char *devname,
-                    struct blkid_magic *id, unsigned char *buf,
-                    blkid_loff_t size)
-{
-       blkid_dev dev;
-       struct hfs_super_block *hfs;
-       int ret;
-
-       if ((ret = probe_default(fd, &dev, devname, id, buf, size)) < 0)
-               return ret;
-
-       hfs = (struct hfs_super_block *)buf;
-
-       if (blkid_be32(hfs->h_blksize) != 512)
-               return -BLKID_ERR_PARAM;
-
-       /* Don't set this until there is no chance of error */
-       *dev_p = dev;
-
-       return 0;
-}
-
-
 /*
  * BLKID_BLK_OFFS is at least as large as the highest bim_kboff defined
- * in the type_array table below + bim_kbalign.  If we ever start looking for magics
- * relative to the end of a device, we can start using negative offsets
- * in type_array.
+ * in the type_array table below + bim_kbalign.
+ *
+ * When probing for a lot of magics, we handle everything in 1kB buffers so
+ * that we don't have to worry about reading each combination of block sizes.
  */
-#define BLKID_BLK_BITS (10)
-#define BLKID_BLK_KBITS        (BLKID_BLK_BITS - 10)
-#define BLKID_BLK_SIZE (1024 << BLKID_BLK_KBITS)
-#define BLKID_BLK_MASK  (BLKID_BLK_SIZE - 1)
-#define BLKID_BLK_OFFS 128     /* currently MDRAID kboff + align */
+#define BLKID_BLK_OFFS 64      /* currently reiserfs */
 
 /*
  * Various filesystem magics that we can check for.  Note that kboff and
  * sboff are in kilobytes and bytes respectively.  All magics are in
  * byte strings so we don't worry about endian issues.
  */
-struct blkid_magic type_array[] = {
-/*  type     kboff   sboff len  magic           align kbsize probe */
-  { "MDRAID",  -64,      0,  4, "\251+N\374",   65536,  4, probe_mdraid },
-/*{ "LVM",       0,      0,  4, "HM\001\000",       1,  4, probe_lvm },*/
-  { "jbd",       1,   0x38,  2, "\123\357",         1,  1, probe_jbd },
-  { "ext3",      1,   0x38,  2, "\123\357",         1,  1, probe_ext3 },
-  { "ext2",      1,   0x38,  2, "\123\357",         1,  1, probe_ext2 },
-  { "reiserfs",  8,   0x34,  8, "ReIsErFs",         1,  1, probe_reiserfs },
-  { "reiserfs", 64,   0x34,  9, "ReIsEr2Fs",        1,  1, probe_reiserfs },
-  { "reiserfs", 64,   0x34,  9, "ReIsEr3Fs",        1,  1, probe_reiserfs },
-  { "reiserfs", 64,   0x34,  8, "ReIsErFs",         1,  1, probe_reiserfs },
-  { "reiserfs",  8,     20,  8, "ReIsErFs",         1,  1, probe_reiserfs },
-  { "ntfs",      0,      3,  8, "NTFS    ",         1,  1, probe_default },
-  { "vfat",      0,   0x52,  5, "MSWIN",            1,  1, probe_vfat },
-  { "vfat",      0,   0x52,  8, "FAT32   ",         1,  1, probe_vfat },
-  { "msdos",     0,   0x36,  5, "MSDOS",            1,  1, probe_msdos },
-  { "msdos",     0,   0x36,  8, "FAT16   ",         1,  1, probe_msdos },
-  { "msdos",     0,   0x36,  8, "FAT12   ",         1,  1, probe_msdos },
-  { "minix",     1,   0x10,  2, "\177\023",         1,  1, probe_minix },
-  { "minix",     1,   0x10,  2, "\217\023",         1,  1, probe_minix },
-  { "minix",     1,   0x10,  2, "\150\044",         1,  1, probe_minix },
-  { "minix",     1,   0x10,  2, "\170\044",         1,  1, probe_minix },
-  { "vxfs",      1,      0,  4, "\365\374\001\245", 1,  1, probe_default },
-  { "xfs",       0,      0,  4, "XFSB",             1,  1, probe_xfs },
-  { "romfs",     0,      0,  8, "-rom1fs-",         1,  1, probe_default },
-  { "bfs",       0,      0,  4, "\316\372\173\033", 1,  1, probe_default },
-  { "cramfs",    0,      0,  4, "E=\315\034",       1,  1, probe_default },
-  { "qnx4",      0,      4,  6, "QNX4FS",           1,  1, probe_default },
-  { "iso9660",  32,      1,  5, "CD001",            1,  1, probe_default },
-  { "iso9660",  32,      9,  5, "CDROM",            1,  1, probe_default },
-  { "udf",      32,      1,  5, "BEA01",            1,  1, probe_default },
-  { "udf",      32,      1,  5, "BOOT2",            1,  1, probe_default },
-  { "udf",      32,      1,  5, "CD001",            1,  1, probe_default },
-  { "udf",      32,      1,  5, "CDW02",            1,  1, probe_default },
-  { "udf",      32,      1,  5, "NSR02",            1,  1, probe_default },
-  { "udf",      32,      1,  5, "NSR03",            1,  1, probe_default },
-  { "udf",      32,      1,  5, "TEA01",            1,  1, probe_default },
-  { "jfs",      32,      0,  4, "JFS1",             1,  1, probe_default },
-  { "hfs",       1,      0,  2, "BD",               1,  1, probe_hfs },
-  { "ufs",       8,  0x55c,  4, "T\031\001\000",    1,  1, probe_default },
-  { "hpfs",      8,      0,  4, "I\350\225\371",    1,  1, probe_default },
-  { "sysv",      0,  0x3f8,  4, "\020~\030\375",    1,  1, probe_default },
-  { "swap",      0,  0xff6, 10, "SWAP-SPACE",       1,  4, probe_swap },
-  { "swap",      0,  0xff6, 10, "SWAPSPACE2",       1,  4, probe_swap },
-  { "swap",      0, 0x1ff6, 10, "SWAP-SPACE",       1,  8, probe_swap },
-  { "swap",      0, 0x1ff6, 10, "SWAPSPACE2",       1,  8, probe_swap },
-  { "swap",      0, 0x3ff6, 10, "SWAP-SPACE",       1, 16, probe_swap },
-  { "swap",      0, 0x3ff6, 10, "SWAPSPACE2",       1, 16, probe_swap },
-  {   NULL,      0,      0,  0, NULL,               1,  0, NULL }
+static struct blkid_magic type_array[] = {
+/*  type     kboff   sboff len  magic                  probe */
+  { "jbd",      1,   0x38,  2, "\123\357",             probe_jbd },
+  { "ext3",     1,   0x38,  2, "\123\357",             probe_ext3 },
+  { "ext2",     1,   0x38,  2, "\123\357",             probe_ext2 },
+  { "reiserfs",         8,   0x34,  8, "ReIsErFs",             probe_reiserfs },
+  { "reiserfs", 64,   0x34,  9, "ReIsEr2Fs",           probe_reiserfs },
+  { "reiserfs", 64,   0x34,  9, "ReIsEr3Fs",           probe_reiserfs },
+  { "reiserfs", 64,   0x34,  8, "ReIsErFs",            probe_reiserfs },
+  { "reiserfs",         8,     20,  8, "ReIsErFs",             probe_reiserfs },
+  { "ntfs",      0,      3,  8, "NTFS    ",             0 },
+  { "vfat",      0,   0x52,  5, "MSWIN",                probe_vfat },
+  { "vfat",      0,   0x52,  8, "FAT32   ",             probe_vfat },
+  { "msdos",     0,   0x36,  5, "MSDOS",                probe_msdos },
+  { "msdos",     0,   0x36,  8, "FAT16   ",             probe_msdos },
+  { "msdos",     0,   0x36,  8, "FAT12   ",             probe_msdos },
+  { "minix",     1,   0x10,  2, "\177\023",             0 },
+  { "minix",     1,   0x10,  2, "\217\023",             0 },
+  { "minix",    1,   0x10,  2, "\150\044",             0 },
+  { "minix",    1,   0x10,  2, "\170\044",             0 },
+  { "vxfs",     1,      0,  4, "\365\374\001\245",     0 },
+  { "xfs",      0,      0,  4, "XFSB",                 probe_xfs },
+  { "romfs",    0,      0,  8, "-rom1fs-",             0 },
+  { "bfs",      0,      0,  4, "\316\372\173\033",     0 },
+  { "cramfs",   0,      0,  4, "E=\315\034",           0 },
+  { "qnx4",     0,      4,  6, "QNX4FS",               0 },
+  { "iso9660", 32,      1,  5, "CD001",                0 },
+  { "iso9660", 32,      9,  5, "CDROM",                0 },
+  { "udf",     32,      1,  5, "BEA01",                0 },
+  { "udf",     32,      1,  5, "BOOT2",                0 },
+  { "udf",     32,      1,  5, "CD001",                0 },
+  { "udf",     32,      1,  5, "CDW02",                0 },
+  { "udf",     32,      1,  5, "NSR02",                0 },
+  { "udf",     32,      1,  5, "NSR03",                0 },
+  { "udf",     32,      1,  5, "TEA01",                0 },
+  { "jfs",     32,      0,  4, "JFS1",                 0 },
+  { "hfs",      1,      0,  2, "BD",                   0 },
+  { "ufs",      8,  0x55c,  4, "T\031\001\000",        0 },
+  { "hpfs",     8,      0,  4, "I\350\225\371",        0 },
+  { "sysv",     0,  0x3f8,  4, "\020~\030\375",        0 },
+  { "swap",     0,  0xff6, 10, "SWAP-SPACE",           0 },
+  { "swap",     0,  0xff6, 10, "SWAPSPACE2",           0 },
+  { "swap",     0, 0x1ff6, 10, "SWAP-SPACE",           0 },
+  { "swap",     0, 0x1ff6, 10, "SWAPSPACE2",           0 },
+  { "swap",     0, 0x3ff6, 10, "SWAP-SPACE",           0 },
+  { "swap",     0, 0x3ff6, 10, "SWAPSPACE2",           0 },
+  {   NULL,     0,      0,  0, NULL,                   NULL }
 };
 
-
-/*
- * When probing for a lot of magics, we handle everything in 1kB buffers so
- * that we don't have to worry about reading each combination of block sizes.
- */
-static unsigned char *read_one_buf(int fd, blkid_loff_t offset)
-{
-       unsigned char *buf;
-
-       if (lseek(fd, offset, SEEK_SET) < 0)
-               return NULL;
-
-       if (!(buf = (unsigned char *)malloc(BLKID_BLK_SIZE)))
-               return NULL;
-
-       if (read(fd, buf, BLKID_BLK_SIZE) != BLKID_BLK_SIZE) {
-               free(buf);
-               return NULL;
-       }
-
-       return buf;
-}
-
-static unsigned char *read_sb_buf(int fd, unsigned char **bufs, int kboff,
-                                 blkid_loff_t start)
-{
-       int idx = kboff >> BLKID_BLK_KBITS;
-       unsigned char **buf;
-
-       if (idx > BLKID_BLK_OFFS || idx < -BLKID_BLK_OFFS) {
-               fprintf(stderr, "reading from invalid offset %d (%d)!\n",
-                       kboff, idx);
-               return NULL;
-       }
-
-       buf = bufs + idx;
-       if (!*buf)
-               *buf = read_one_buf(fd, start);
-
-       return *buf;
-}
-
-static struct blkid_magic *devname_to_magic(const char *devname, int fd,
-                                           unsigned char **bufs,
-                                           struct blkid_magic *id,
-                                           blkid_loff_t size)
-{
-       struct blkid_magic *ret = NULL;
-
-       if (!bufs || fd < 0)
-               return NULL;
-
-       if (id >= type_array + sizeof(type_array) / sizeof(*id))
-               return NULL;
-
-       for (id = id < type_array ? type_array : id + 1; id->bim_type; ++id) {
-               unsigned char *buf;
-               blkid_loff_t start = 0LL;
-               blkid_loff_t offset = 0LL;
-               int kboff;
-
-               offset = ((blkid_loff_t)id->bim_kboff << 10) +
-                       (id->bim_sboff & ~0x3ffULL);
-               /*
-                * We index negative buffers by their actual offset (including
-                * superblock offsets > 1kB, not the aligned offset, so that
-                * we correctly access negative buffers with different
-                * alignment requirements.
-                */
-               if (id->bim_kboff < 0) {
-                       start = (size & ~((blkid_loff_t)(id->bim_align - 1))) +
-                               offset;
-                       if (start < 0) /* Device too small for alignment */
-                               continue;
-                       kboff = (start - size) >> 10;
-               } else {
-                       start = offset;
-                       kboff = offset >> 10;
-               }
-
-               if ((buf =
-                    read_sb_buf(fd, bufs, kboff, start)) &&
-                   !memcmp(id->bim_magic, buf + (id->bim_sboff&0x3ffULL),
-                           id->bim_len)) {
-                       ret = id;
-                       break;
-               }
-       }
-
-       return ret;
-}
-
 /*
- * Get data from a single block special device.
- *
- * Return a blkid_dev with at least the device type and size set.
- * If the passed-in size is zero, then we get the device size here.
+ * If a device's filesystem no longer checks out, we need to nuke
+ * information about it from the entry.
  */
-blkid_dev blkid_devname_to_dev(const char *devname, blkid_loff_t size)
+static void blkid_invalidate_fs(blkid_dev dev)
 {
-       unsigned char *buf_array[BLKID_BLK_OFFS * 2 + 1];
-       unsigned char **bufs = buf_array + BLKID_BLK_OFFS;
-       blkid_dev dev = NULL, last = NULL;
-       unsigned char *sb_buf = NULL;
-       int sb_size = 0;
-       struct blkid_magic *id = NULL;
-       blkid_loff_t diff_last = 0xf000000000000000ULL;
-       int fd;
-
-       if (!devname)
-               return NULL;
-
-       fd = open(devname, O_RDONLY);
-       if (fd < 0)
-               return NULL;
-
-       if (!size)
-               size = blkid_get_dev_size(fd);
-       if (size < 1024)
-               goto exit_fd;
-
-       memset(buf_array, 0, sizeof(buf_array));
-
-       while ((id = devname_to_magic(devname, fd, bufs, id, size)) &&
-              diff_last) {
-               int new_sb;
-               blkid_loff_t diff_dev;
-
-               DBG(printf("found type %s (#%d) on %s, probing\n",
-                          id->bim_type, id - type_array, devname));
-
-               new_sb = id->bim_kbsize << 10;
-               if (sb_size < new_sb) {
-                       unsigned char *sav = sb_buf;
-                       if (!(sb_buf = realloc(sb_buf, new_sb))) {
-                               sb_buf = sav;
-                               continue;
-                       }
-                       sb_size = new_sb;
-               }
-
-               if (id->bim_probe(fd, &dev, devname, id, sb_buf, size) < 0)
-                       continue;
-
-               diff_dev = size - dev->bid_size;
-               DBG(printf("size = %Lu, fs size = %Lu\n", size, dev->bid_size));
-               DBG(printf("checking best match: old %Ld, new %Ld\n",
-                          diff_last, diff_dev));
-               /* See which type is a better match by checking size */
-               if ((diff_last < 0 && diff_dev > diff_last) ||
-                   (diff_last > 0 && diff_dev >= 0 && diff_dev < diff_last)) {
-                       if (last)
-                               blkid_free_dev(last);
-                       last = dev;
-                       diff_last = diff_dev;
-               } else
-                       blkid_free_dev(dev);
-       }
-
-       if (!last)
-               DBG(printf("unknown device type on %s\n", devname));
-       else
-               DBG(printf(last));
-
-       /* Free up any buffers we allocated */
-       for (bufs = buf_array; bufs - buf_array < sizeof(buf_array) /
-                                               sizeof(buf_array[0]); bufs++) {
-               if (*bufs)
-                       free(*bufs);
-       }
-
-       if (sb_buf)
-               free(sb_buf);
-exit_fd:
-       close(fd);
-       return last;
-}
+       blkid_set_tag(dev, "TYPE", 0, 0, 0);
+       blkid_set_tag(dev, "LABEL", 0, 0, 0);
+       blkid_set_tag(dev, "UUID", 0, 0, 0);
+}      
 
 /*
  * Verify that the data in dev is consistent with what is on the actual
@@ -733,13 +328,12 @@ exit_fd:
  */
 blkid_dev blkid_verify_devname(blkid_cache cache, blkid_dev dev)
 {
-       blkid_loff_t size;
        struct blkid_magic *id;
-       blkid_dev new = NULL;
-       unsigned char *sb_buf = NULL;
-       int sb_size = 0;
+       unsigned char *bufs[BLKID_BLK_OFFS + 1], *buf;
+       const char *sec_type, *type;
+       struct stat st;
        time_t diff;
-       int fd;
+       int fd, idx;
 
        if (!dev)
                return NULL;
@@ -752,10 +346,9 @@ blkid_dev blkid_verify_devname(blkid_cache cache, blkid_dev dev)
 
        DBG(printf("need to revalidate %s\n", dev->bid_name));
 
-       if ((fd = open(dev->bid_name, O_RDONLY)) < 0) {
+       if (((fd = open(dev->bid_name, O_RDONLY)) < 0) ||
+           (fstat(fd, &st) < 0) || !S_ISBLK(st.st_mode)) {
                if (errno == ENXIO || errno == ENODEV) {
-                       fprintf(stderr, "unable to open %s for revalidation\n",
-                               dev->bid_name);
                        blkid_free_dev(dev);
                        return NULL;
                }
@@ -764,68 +357,117 @@ blkid_dev blkid_verify_devname(blkid_cache cache, blkid_dev dev)
                return dev;
        }
 
-       size = blkid_get_dev_size(fd);
-
-       /* See if we can probe this device by its existing type directly */
+       memset(bufs, 0, sizeof(bufs));
+       
+       /*
+        * Iterate over the type array.  If we already know the type,
+        * then try that first.  If it doesn't work, then blow away
+        * the type information, and try again.
+        * 
+        */
+try_again:
+       type = 0;
+       sec_type = 0;
+       if (!dev->bid_type || !strcmp(dev->bid_type, "mdraid")) {
+               uuid_t  uuid;
+
+               if (check_mdraid(fd, uuid) == 0) {
+                       set_uuid(dev, uuid);
+                       type = "mdraid";
+                       goto found_type;
+               }
+       }
        for (id = type_array; id->bim_type; id++) {
-               if (!strcmp(id->bim_type, dev->bid_type)) {
-                       int new_sb = id->bim_kbsize << 10;
-                       /* See if we need to allocate a larger sb buffer */
-                       if (sb_size < new_sb) {
-                               unsigned char *sav = sb_buf;
-
-                               /* We can't revalidate, return old dev */
-                               if (!(sb_buf = realloc(sb_buf, new_sb))) {
-                                       fprintf(stderr, "not enough memory for "
-                                               "%s revalidation\n",
-                                               dev->bid_name);
-                                       free(sav);
-                                       goto exit_fd;
-                               }
-                               sb_size = new_sb;
+               if (dev->bid_type &&
+                   strcmp(id->bim_type, dev->bid_type))
+                       continue;
+
+               idx = id->bim_kboff + (id->bim_sboff >> 10);
+               if (idx > BLKID_BLK_OFFS || idx < 0)
+                       continue;
+               buf = bufs[idx];
+               if (!buf) {
+                       if (lseek(fd, idx << 10, SEEK_SET) < 0)
+                               continue;
+
+                       if (!(buf = (unsigned char *)malloc(1024)))
+                               continue;
+                       
+                       if (read(fd, buf, 1024) != 1024) {
+                               free(buf);
+                               continue;
                        }
+                       bufs[idx] = buf;
+               }
 
-                       if (id->bim_probe(fd, &new, dev->bid_name, id, sb_buf,
-                                         size) == 0)
-                               break;
+               if (memcmp(id->bim_magic, buf + (id->bim_sboff&0x3ff),
+                          id->bim_len))
+                       continue;
+
+               if ((id->bim_probe == NULL) ||
+                   (id->bim_probe(fd, cache, dev, id, buf, &sec_type) == 0)) {
+                       type = id->bim_type;
+                       goto found_type;
                }
        }
 
-       if (sb_buf)
-               free(sb_buf);
+       if (!id->bim_type && dev->bid_type) {
+               /*
+                * Zap the device filesystem type and try again
+                */
+               blkid_invalidate_fs(dev);
+               goto try_again;
+       }
 
-       /* Otherwise we need to determine the device type first */
-       if (new || (new = blkid_devname_to_dev(dev->bid_name, size))) {
-               new->bid_id = dev->bid_id; /* save old id for cache */
+       if (!dev->bid_type) {
                blkid_free_dev(dev);
-               dev = blkid_add_dev_to_cache(cache, new);
+               return NULL;
+       }
+               
+found_type:
+       if (dev && type) {
+               dev->bid_devno = st.st_rdev;
+               dev->bid_time = time(0);
+               dev->bid_flags |= BLKID_BID_FL_VERIFIED;
+
+               blkid_set_tag(dev, "TYPE", type, 0, 1);
+               if (sec_type)
+                       blkid_set_tag(dev, "TYPE", sec_type, 0, 0);
+                               
+               DBG(printf("%s: devno 0x%04Lx, type %s\n",
+                          dev->bid_name, st.st_rdev, type));
        }
 
-exit_fd:
        close(fd);
 
-       /* In case the cache is missing the device size */
-       if (dev->bid_devsize == 0)
-               dev->bid_devsize = size;
        return dev;
-
 }
 
 #ifdef TEST_PROGRAM
 int main(int argc, char **argv)
 {
        blkid_dev dev;
+       blkid_cache cache;
 
        if (argc != 2) {
                fprintf(stderr, "Usage: %s device\n"
                        "Probe a single device to determine type\n", argv[0]);
                exit(1);
        }
-       dev = blkid_devname_to_dev(argv[1], 0);
-       if (dev)
-               blkid_free_dev(dev);
-       else
+       cache = blkid_new_cache();
+       dev = blkid_get_devname(cache, argv[1], BLKID_DEV_NORMAL);
+       if (!dev) {
                printf("%s: %s has an unsupported type\n", argv[0], argv[1]);
+               return (1);
+       }
+       printf("%s is type %s\n", argv[1], dev->bid_type ?
+               dev->bid_type : "(null)");
+       if (dev->bid_label)
+               printf("\tlabel is '%s'\n", dev->bid_label);
+       if (dev->bid_uuid)
+               printf("\tuuid is %s\n", dev->bid_uuid);
+       
+       blkid_free_dev(dev);
        return (0);
 }
 #endif
index 23dd07f..3e02604 100644 (file)
@@ -2,7 +2,7 @@
  * probe.h - constants and on-disk structures for extracting device data
  *
  * Copyright (C) 1999 by Andries Brouwer
- * Copyright (C) 1999, 2000 by Theodore Ts'o
+ * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
  * Copyright (C) 2001 by Andreas Dilger
  *
  * %Begin-Header%
@@ -18,9 +18,9 @@
 
 struct blkid_magic;
 
-typedef int (*blkid_probe_t)(int fd, blkid_dev *dev_p, const char *devname,
+typedef int (*blkid_probe_t)(int fd, blkid_cache cache, blkid_dev dev, 
                             struct blkid_magic *id, unsigned char *buf,
-                            blkid_loff_t size);
+                            const char **ret_sectype);
 
 struct blkid_magic {
        const char      *bim_type;      /* type name for this magic */
@@ -28,8 +28,6 @@ struct blkid_magic {
        unsigned        bim_sboff;      /* byte offset within superblock */
        unsigned        bim_len;        /* length of magic */
        const char      *bim_magic;     /* magic string */
-       unsigned        bim_align;      /* byte alignment of superblock */
-       unsigned        bim_kbsize;     /* size of superblock in kilobytes */
        blkid_probe_t   bim_probe;      /* probe function */
 };
 
@@ -202,6 +200,10 @@ struct hfs_super_block {
 #define _INLINE_ extern inline
 #endif
 
+extern __u16 blkid_swab16(__u16 val);
+extern __u32 blkid_swab32(__u32 val);
+extern __u64 blkid_swab64(__u64 val);
+
 #if ((defined __GNUC__) && \
      (defined(__i386__) || defined(__i486__) || defined(__i586__)))
 
index 89a7bfd..7c9c4d4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * read.c - read the blkid cache from disk, to avoid scanning all devices
  *
- * Copyright (C) 2001 Theodore Y. Ts'o
+ * Copyright (C) 2001, 2003 Theodore Y. Ts'o
  * Copyright (C) 2001 Andreas Dilger
  *
  * %Begin-Header%
@@ -179,10 +179,9 @@ static int parse_end(char **cp)
  * <device foo=bar>devname</device>
  * <device>devname<foo>bar</foo></device>
  */
-static int parse_dev(blkid_dev *dev, char **cp)
+static int parse_dev(blkid_cache cache, blkid_dev *dev, char **cp)
 {
-       char **name;
-       char *start, *tmp, *end;
+       char *start, *tmp, *end, *name;
        int ret;
 
        if ((ret = parse_start(cp)) <= 0)
@@ -190,7 +189,7 @@ static int parse_dev(blkid_dev *dev, char **cp)
 
        start = tmp = strchr(*cp, '>');
        if (!start) {
-               fprintf(stderr, "blkid: short line parsing dev: %s\n", *cp);
+               DBG(printf("blkid: short line parsing dev: %s\n", *cp));
                return -BLKID_ERR_CACHE;
        }
        start = skip_over_blank(start + 1);
@@ -206,30 +205,25 @@ static int parse_dev(blkid_dev *dev, char **cp)
        *tmp = '\0';
 
        if (!(tmp = strrchr(end, '<')) || parse_end(&tmp) < 0)
-               fprintf(stderr, "blkid: missing </device> ending: %s\n", end);
+               DBG(printf("blkid: missing </device> ending: %s\n", end));
        else if (tmp)
                *tmp = '\0';
 
        if (end - start <= 1) {
-               fprintf(stderr, "blkid: empty device name: %s\n", *cp);
+               DBG(printf("blkid: empty device name: %s\n", *cp));
                return -BLKID_ERR_CACHE;
        }
 
-       if (!(*dev = blkid_new_dev()))
+       name = blkid_strndup(start, end-start);
+       if (name == NULL)
                return -BLKID_ERR_MEM;
 
-       name = &(*dev)->bid_name;
-       *name = (char *)malloc(end - start + 1);
-       if (*name == NULL) {
-               blkid_free_dev(*dev);
-               return -BLKID_ERR_MEM;
-       }
-
-       memcpy(*name, start, end - start);
-       (*name)[end - start] = '\0';
+       DBG(printf("found dev %s\n", name));
 
-       DBG(printf("found dev %s\n", *name));
+       if (!(*dev = blkid_get_devname(cache, name, BLKID_DEV_CREATE)))
+               return -BLKID_ERR_MEM;
 
+       free(name);
        return 1;
 }
 
@@ -253,7 +247,7 @@ static int parse_token(char **name, char **value, char **cp)
        if (**value == '"') {
                end = strchr(*value + 1, '"');
                if (!end) {
-                       fprintf(stderr, "unbalanced quotes at: %s\n", *value);
+                       DBG(printf("unbalanced quotes at: %s\n", *value));
                        *cp = *value;
                        return -BLKID_ERR_CACHE;
                }
@@ -319,13 +313,11 @@ static int parse_tag(blkid_cache cache, blkid_dev dev, char **cp)
                        cache->bic_idmax = dev->bid_id;
        } else if (!strcmp(name, "DEVNO"))
                dev->bid_devno = STRTOULL(value, 0, 0);
-       else if (!strcmp(name, "DEVSIZE"))
-               dev->bid_devno = STRTOULL(value, 0, 0);
        else if (!strcmp(name, "TIME"))
                /* FIXME: need to parse a long long eventually */
                dev->bid_time = strtol(value, 0, 0);
        else
-               ret = blkid_create_tag(dev, name, value, strlen(value));
+               ret = blkid_set_tag(dev, name, value, strlen(value), 0);
 
        DBG(printf("    tag: %s=\"%s\"\n", name, value));
 
@@ -355,7 +347,7 @@ static int blkid_parse_line(blkid_cache cache, blkid_dev *dev_p, char *cp)
 
        DBG(printf("line: %s\n", cp));
 
-       if ((ret = parse_dev(dev_p, &cp)) <= 0)
+       if ((ret = parse_dev(cache, dev_p, &cp)) <= 0)
                return ret;
 
        dev = *dev_p;
@@ -365,37 +357,54 @@ static int blkid_parse_line(blkid_cache cache, blkid_dev *dev_p, char *cp)
        }
 
        if (dev->bid_type == NULL) {
-               fprintf(stderr, "blkid: device %s has no TYPE\n",dev->bid_name);
+               DBG(printf("blkid: device %s has no TYPE\n",dev->bid_name));
                blkid_free_dev(dev);
        }
 
        DEB_DUMP_DEV(dev);
 
-       *dev_p = blkid_add_dev_to_cache(cache, dev);
-
        return ret;
 }
 
 /*
- * Read the given file stream for cached device data, and return it
- * in a newly allocated cache struct.
- *
- * Returns 0 on success, or -ve error value.
+ * Parse the specified filename, and return the data in the supplied or
+ * a newly allocated cache struct.  If the file doesn't exist, return a
+ * new empty cache struct.
  */
-int blkid_read_cache_file(blkid_cache *cache, FILE *file)
+int blkid_get_cache(blkid_cache *cache, const char *filename)
 {
+       FILE *file;
        char buf[4096];
        int lineno = 0;
 
-       if (!file || !cache)
+       if (!cache)
                return -BLKID_ERR_PARAM;
 
-       if (!*cache)
-               *cache = blkid_new_cache();
-
-       if (!*cache)
+       if ((*cache = blkid_new_cache()) == NULL)
                return -BLKID_ERR_MEM;
 
+       if (!filename || !strlen(filename))
+               filename = BLKID_CACHE_FILE;
+       else
+               (*cache)->bic_filename = blkid_strdup(filename);
+
+       DBG(printf("cache file %s\n", filename));
+
+       if (!strcmp(filename, "-"))
+               file = stdin;
+       else {
+               /*
+                * If the file doesn't exist, then we just return an empty
+                * struct so that the cache can be populated.
+                */
+               if (access(filename, R_OK) < 0)
+                       return 0;
+
+               file = fopen(filename, "r");
+               if (!file)
+                       return errno; /* Should never happen */
+       }
+
        while (fgets(buf, sizeof(buf), file)) {
                blkid_dev dev;
 
@@ -410,77 +419,19 @@ int blkid_read_cache_file(blkid_cache *cache, FILE *file)
                }
 
                if (blkid_parse_line(*cache, &dev, buf) < 0) {
-                       fprintf(stderr, "blkid: bad format on line %d\n",
-                               lineno);
+                       DBG(printf("blkid: bad format on line %d\n", lineno));
                        continue;
                }
        }
-
        /*
-        * Initially assume that we do not need to write out the cache file.
-        * This would be incorrect if we probed first, and parsed the cache
-        * afterwards, or parsed two caches and wanted to write it out, but
-        * the alternative is to force manually marking the cache dirty when
-        * any device is added, and that is also prone to error.
+        * Initially we do not need to write out the cache file.
         */
        (*cache)->bic_flags &= ~BLKID_BIC_FL_CHANGED;
 
-       return 0;
-}
-
-/*
- * Parse the specified filename, and return the data in the supplied or
- * a newly allocated cache struct.  If the file doesn't exist, return a
- * new empty cache struct.
- */
-int blkid_read_cache(blkid_cache *cache, const char *filename)
-{
-       FILE *file;
-       int ret;
-
-       if (!cache)
-               return -BLKID_ERR_PARAM;
-
-       if (!filename || !strlen(filename))
-               filename = BLKID_CACHE_FILE;
-
-       DBG(printf("cache file %s\n", filename));
-
-       /* If we read the standard cache file, do not do so again */
-       if (!strcmp(filename, BLKID_CACHE_FILE) && (*cache) &&
-           ((*cache)->bic_flags & BLKID_BIC_FL_PARSED))
-               return 0;
-
-       if (!strcmp(filename, "-") || !strcmp(filename, "stdin"))
-               file = stdin;
-       else {
-               /*
-                * If the file doesn't exist, then we just return an empty
-                * struct so that the cache can be populated.
-                */
-               if (access(filename, R_OK) < 0) {
-                       *cache = blkid_new_cache();
-
-                       return *cache ? 0 : -BLKID_ERR_MEM;
-               }
-
-               file = fopen(filename, "r");
-               if (!file) {
-                       perror(filename);
-                       return errno;
-               }
-       }
-
-       ret = blkid_read_cache_file(cache, file);
-
        if (file != stdin)
                fclose(file);
 
-       /* Mark us as having read the standard cache file */
-       if (!strcmp(filename, BLKID_CACHE_FILE))
-               (*cache)->bic_flags |= BLKID_BIC_FL_PARSED;
-
-       return ret;
+       return 0;
 }
 
 #ifdef TEST_PROGRAM
@@ -494,11 +445,11 @@ int main(int argc, char**argv)
                        "Test parsing of the cache (filename)\n", argv[0]);
                exit(1);
        }
-       if ((ret = blkid_read_cache(&cache, argv[1])) < 0)
+       if ((ret = blkid_get_cache(&cache, argv[1])) < 0)
                fprintf(stderr, "error %d reading cache file %s\n", ret,
                        argv[1] ? argv[1] : BLKID_CACHE_FILE);
 
-       blkid_free_cache(cache);
+       blkid_put_cache(cache);
 
        return ret;
 }
index 04ce149..19478ed 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * resolve.c - resolve names and tags into specific devices
  *
- * Copyright (C) 2001 Theodore Ts'o.
+ * Copyright (C) 2001, 2003 Theodore Ts'o.
  * Copyright (C) 2001 Andreas Dilger
  *
  * %Begin-Header%
@@ -47,9 +47,9 @@ char *blkid_get_tagname_devname(blkid_cache cache, const char *tagname,
        if (!cache)
                DBG(printf("no cache given, direct device probe\n"));
 
-       if ((dev = blkid_get_devname(cache, devname)) &&
-           (found = blkid_find_tag_dev(dev, tagname, NULL)))
-               ret = string_copy(found->bit_val);
+       if ((dev = blkid_get_devname(cache, devname, BLKID_DEV_NORMAL)) &&
+           (found = blkid_find_tag_dev(dev, tagname)))
+               ret = blkid_strdup(found->bit_val);
 
        if (!cache)
                blkid_free_dev(dev);
@@ -62,8 +62,6 @@ char *blkid_get_tagname_devname(blkid_cache cache, const char *tagname,
  * pair.  In the case of a token, value is ignored.  If the "token" is not
  * of the form "NAME=value" and there is no value given, then it is assumed
  * to be the actual devname and a copy is returned.
- *
- * The string returned must be freed with string_free().
  */
 char *blkid_get_token(blkid_cache cache, const char *token,
                      const char *value)
@@ -80,7 +78,7 @@ char *blkid_get_token(blkid_cache cache, const char *token,
                   value ? value : "", cache ? "in cache" : "from disk"));
 
        if (!cache) {
-               if (blkid_read_cache(&c, NULL) < 0)
+               if (blkid_get_cache(&c, NULL) < 0)
                        c = blkid_new_cache();
                if (!c)
                        return NULL;
@@ -98,7 +96,7 @@ char *blkid_get_token(blkid_cache cache, const char *token,
        if (!dev)
                goto errout;
 
-       ret = string_copy(blkid_devname_name(dev));
+       ret = blkid_strdup(blkid_devname_name(dev));
 
 errout:
        if (t)
@@ -106,8 +104,7 @@ errout:
        if (v)
                free(v);
        if (!cache) {
-               blkid_save_cache(c, NULL);
-               blkid_free_cache(c);
+               blkid_put_cache(c);
        }
        return (ret);
 }
index e888d0c..5a8771e 100644 (file)
@@ -2,6 +2,7 @@
  * save.c - write the cache struct to disk
  *
  * Copyright (C) 2001 by Andreas Dilger
+ * Copyright (C) 2003 Theodore Ts'o
  *
  * %Begin-Header%
  * This file may be redistributed under the terms of the
@@ -54,41 +55,17 @@ static int save_dev(blkid_dev dev, FILE *file)
        return 0;
 }
 
-int blkid_save_cache_file(blkid_cache cache, FILE *file)
-{
-       struct list_head *p;
-       int ret = 0;
-
-       if (!cache || !file)
-               return -BLKID_ERR_PARAM;
-
-       if (list_empty(&cache->bic_devs) ||
-           !cache->bic_flags & BLKID_BIC_FL_CHANGED)
-               return 0;
-
-       list_for_each(p, &cache->bic_devs) {
-               blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs);
-               if ((ret = save_dev(dev, file)) < 0)
-                       break;
-       }
-
-       if (ret >= 0) {
-               cache->bic_flags &= ~BLKID_BIC_FL_CHANGED;
-               ret = 1;
-       }
-
-       return ret;
-}
-
 /*
  * Write out the cache struct to the cache file on disk.
  */
-int blkid_save_cache(blkid_cache cache, const char *filename)
+int blkid_flush_cache(blkid_cache cache)
 {
+       struct list_head *p;
        char *tmp = NULL;
        const char *opened = NULL;
+       const char *filename;
        FILE *file = NULL;
-       int fd, ret;
+       int fd, ret = 0;
 
        if (!cache)
                return -BLKID_ERR_PARAM;
@@ -99,10 +76,9 @@ int blkid_save_cache(blkid_cache cache, const char *filename)
                return 0;
        }
 
-       if (!filename || !strlen(filename))
-               filename = BLKID_CACHE_FILE;
+       filename = cache->bic_filename ? cache->bic_filename: BLKID_CACHE_FILE;
 
-       if (!strcmp(filename, "-") || !strcmp(filename, "stdout"))
+       if (!strcmp(filename, "-"))
                file = stdout;
        else {
                struct stat st;
@@ -142,14 +118,23 @@ int blkid_save_cache(blkid_cache cache, const char *filename)
                DBG(printf("cache file %s (really %s)\n", filename, opened));
 
                if (!file) {
-                       perror(opened);
-                       if (tmp)
-                               free(tmp);
-                       return errno;
+                       ret = errno;
+                       goto errout;
                }
        }
 
-       ret = blkid_save_cache_file(cache, file);
+       list_for_each(p, &cache->bic_devs) {
+               blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs);
+               if (!dev->bid_type)
+                       continue;
+               if ((ret = save_dev(dev, file)) < 0)
+                       break;
+       }
+
+       if (ret >= 0) {
+               cache->bic_flags &= ~BLKID_BIC_FL_CHANGED;
+               ret = 1;
+       }
 
        if (file != stdout) {
                fclose(file);
@@ -173,6 +158,7 @@ int blkid_save_cache(blkid_cache cache, const char *filename)
                }
        }
 
+errout:
        if (tmp)
                free(tmp);
        return ret;
@@ -189,13 +175,23 @@ int main(int argc, char **argv)
                        "Test loading/saving a cache (filename)\n", argv[0]);
                exit(1);
        }
-       if ((ret = blkid_probe_all(&cache) < 0))
-               fprintf(stderr, "error probing devices\n");
-       else if ((ret = blkid_save_cache(cache, argv[1])) < 0)
-               fprintf(stderr, "error %d saving cache to %s\n", ret,
-                       argv[1] ? argv[1] : BLKID_CACHE_FILE);
 
-       blkid_free_cache(cache);
+       if ((cache = blkid_new_cache()) == NULL) {
+               fprintf(stderr, "%s: error creating cache\n", argv[0]);
+               exit(1);
+       }
+       if ((ret = blkid_probe_all(cache)) < 0) {
+               fprintf(stderr, "error (%d) probing devices\n", ret);
+               exit(1);
+       }
+       cache->bic_filename = blkid_strdup(argv[1]);
+       
+       if ((ret = blkid_flush_cache(cache)) < 0) {
+               fprintf(stderr, "error (%d) saving cache\n", ret);
+               exit(1);
+       }
+
+       blkid_put_cache(cache);
 
        return ret;
 }
index d0e1b0a..9bb99e1 100644 (file)
@@ -2,6 +2,7 @@
  * tag.c - allocation/initialization/free routines for tag structs
  *
  * Copyright (C) 2001 Andreas Dilger
+ * Copyright (C) 2003 Theodore Ts'o
  *
  * %Begin-Header%
  * This file may be redistributed under the terms of the
@@ -21,7 +22,7 @@
 #define DBG(x)
 #endif
 
-blkid_tag blkid_new_tag(void)
+static blkid_tag blkid_new_tag(void)
 {
        blkid_tag tag;
 
@@ -39,16 +40,17 @@ void blkid_free_tag(blkid_tag tag)
        if (!tag)
                return;
 
-       DBG(printf("    freeing tag %s=%s\n", tag->bit_name, tag->bit_val));
+       DBG(printf("    freeing tag %s=%s\n", tag->bit_name,
+                  tag->bit_val ? tag->bit_val : "(NULL)"));
        DEB_DUMP_TAG(tag);
 
        list_del(&tag->bit_tags);       /* list of tags for this device */
        list_del(&tag->bit_names);      /* list of tags with this type */
 
        if (tag->bit_name)
-               string_free(tag->bit_name);
+               free(tag->bit_name);
        if (tag->bit_val)
-               string_free(tag->bit_val);
+               free(tag->bit_val);
 
        free(tag);
 }
@@ -57,122 +59,148 @@ void blkid_free_tag(blkid_tag tag)
  * Find the desired tag on a device.  If value is NULL, then the
  * first such tag is returned, otherwise return only exact tag if found.
  */
-blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type,
-                            const char *value)
+blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type)
 {
-       blkid_tag found = NULL;
        struct list_head *p;
 
-       if (!dev || !type || !value)
+       if (!dev || !type)
                return NULL;
 
        list_for_each(p, &dev->bid_tags) {
                blkid_tag tmp = list_entry(p, struct blkid_struct_tag,
                                           bit_tags);
 
-               if (!strcmp(tmp->bit_name, type) &&
-                   (!value || !strcmp(tmp->bit_val, value))){
-                       found = tmp;
-                       break;
-               }
+               if (!strcmp(tmp->bit_name, type))
+                       return tmp;
        }
-
-       return found;
+       return NULL;
 }
 
 /*
  * Find the desired tag type in the cache.
  * We return the head tag for this tag type.
  */
-blkid_tag blkid_find_head_cache(blkid_cache cache, const char *type)
+static blkid_tag blkid_find_head_cache(blkid_cache cache, const char *type)
 {
-       blkid_tag head = NULL;
+       blkid_tag head = NULL, tmp;
        struct list_head *p;
 
        if (!cache || !type)
                return NULL;
 
        list_for_each(p, &cache->bic_tags) {
-               blkid_tag tmp = list_entry(p, struct blkid_struct_tag, 
-                                          bit_tags);
-
+               tmp = list_entry(p, struct blkid_struct_tag, bit_tags);
                if (!strcmp(tmp->bit_name, type)) {
                        DBG(printf("    found cache tag head %s\n", type));
                        head = tmp;
                        break;
                }
        }
-
        return head;
 }
 
 /*
- * Add a single tag to the given device.
- * This function is not currently exported because adding arbitrary tags to
- * a device will just get lost as soon as we verify the device (which
- * uses the dev struct returned from the device probe).  At some point in
- * the future it may be desirable to allow adding arbitrary tags to a device,
- * and ensure that verify keeps all such tags (maybe lower case tag names?)
- */
-static void add_tag_to_dev(blkid_dev dev, blkid_tag tag)
-{
-       if (!dev)
-               return;
-
-       DBG(printf("adding tag %s=%s\n", tag->bit_name, tag->bit_val));
-
-       tag->bit_dev = dev;
-
-       list_add_tail(&tag->bit_tags, &dev->bid_tags);
-
-       /* Link common tags directly to the device struct */
-       if (!strcmp(tag->bit_name, "TYPE") && !dev->bid_type)
-               dev->bid_type = tag->bit_val;
-       else if (!strcmp(tag->bit_name, "LABEL"))
-               dev->bid_label = tag->bit_val;
-       else if (!strcmp(tag->bit_name, "UUID"))
-               dev->bid_uuid = tag->bit_val;
-}
-
-/*
- * Allocate and fill out a tag struct.
- * If dev is valid, the tag will be added to the tags for this device
- * if an identical tag does not already exist.
- * If tag is valid, the tag will be returned in this pointer.
+ * Set a tag on an existing device.
+ * 
+ * If replace is non-zero, blkid_set_tag() will replace the existing
+ * tag with the specified value.  Otherwise, it will add the specified
+ * tag to the device.
+ *
+ * If value is NULL, then delete all tags with that name from the
+ * device.
  */
-int blkid_create_tag(blkid_dev dev, const char *name,
-                    const char *value, const int vlength)
+int blkid_set_tag(blkid_dev dev, const char *name,
+                 const char *value, const int vlength, int replace)
 {
-       blkid_tag t, found;
+       blkid_tag       t = 0, head = 0;
+       char            *val = 0;
 
-       if (!dev)
+       if (!dev || !name)
                return -BLKID_ERR_PARAM;
 
-       if (!name)
-               return -BLKID_ERR_PARAM;
+repeat:
+       t = blkid_find_tag_dev(dev, name);
+       val = blkid_strndup(value, vlength);
+       if (!value) {
+               if (t) {
+                       blkid_free_tag(t);
+                       goto repeat;
+               } else
+                       goto link_tags;
+       }
+       if (!val)
+               goto errout;
+       if (t) {
+               if (!strcmp(t->bit_val, val)) {
+                       /* Same thing, exit */
+                       free(val);
+                       return 0;
+               }
+               if (replace) {
+                       free(t->bit_val);
+                       t->bit_val = val;
+                       goto link_tags;
+               }
+               dev->bid_flags |= BLKID_BID_FL_MTYPE;
+       }
 
+       /* Existing tag not present, add to device */
        t = blkid_new_tag();
        if (!t)
-               return -BLKID_ERR_MEM;
-
-       t->bit_name = string_copy(name);
-       t->bit_val = stringn_copy(value, vlength);
-
-       if ((found = blkid_find_tag_dev(dev, name, t->bit_val))) {
-               blkid_free_tag(t);
-               return 0;
+               goto errout;
+       t->bit_name = blkid_strdup(name);
+       t->bit_val = val;
+       t->bit_dev = dev;
+
+       list_add_tail(&t->bit_tags, &dev->bid_tags);
+               
+       if (dev->bid_cache) {
+               head = blkid_find_head_cache(dev->bid_cache, t->bit_name);
+               if (!head) {
+                       head = blkid_new_tag();
+                       if (!head)
+                               goto errout;
+
+                       DBG(printf("    creating new cache tag head %s\n",
+                                  name));
+                       head->bit_name = blkid_strdup(name);
+                       if (!head->bit_name)
+                               goto errout;
+                       list_add_tail(&head->bit_tags,
+                                     &dev->bid_cache->bic_tags);
+               }
+               list_add_tail(&t->bit_names, &head->bit_names);
        }
-
-       add_tag_to_dev(dev, t);
-
+       
+link_tags:
+       /* Link common tags directly to the device struct */
+       if (!strcmp(name, "TYPE") && (!val || !dev->bid_type))
+               dev->bid_type = val;
+       else if (!strcmp(name, "LABEL"))
+               dev->bid_label = val;
+       else if (!strcmp(name, "UUID"))
+               dev->bid_uuid = val;
+               
+       if (dev->bid_cache)
+               dev->bid_cache->bic_flags |= BLKID_BIC_FL_CHANGED;
        return 0;
+
+errout:
+       if (t)
+               blkid_free_tag(t);
+       else if (val)
+               free(val);
+       if (head)
+               blkid_free_tag(head);
+       return -BLKID_ERR_MEM;
 }
 
+
 /*
  * Parse a "NAME=value" string.  This is slightly different than
  * parse_token, because that will end an unquoted value at a space, while
  * this will assume that an unquoted value is the rest of the token (e.g.
- * if we are passed al alreay quoted string from the command-line we don't
+ * if we are passed an already quoted string from the command-line we don't
  * have to both quote and escape quote so that the quotes make it to
  * us).
  *
@@ -187,7 +215,7 @@ int blkid_parse_tag_string(const char *token, char **ret_type, char **ret_val)
        if (!token || !(cp = strchr(token, '=')))
                return -1;
 
-       name = string_copy(token);
+       name = blkid_strdup(token);
        if (!name)
                return -1;
        value = name + (cp - token);
@@ -198,7 +226,7 @@ int blkid_parse_tag_string(const char *token, char **ret_type, char **ret_val)
                        goto errout; /* missing closing quote */
                *cp = '\0';
        }
-       value = string_copy(value);
+       value = blkid_strdup(value);
        if (!value)
                goto errout;
 
@@ -208,7 +236,7 @@ int blkid_parse_tag_string(const char *token, char **ret_type, char **ret_val)
        return 0;
 
 errout:
-       string_free(name);
+       free(name);
        return -1;
 }
 
@@ -291,7 +319,7 @@ extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache,
                                         const char *type,
                                         const char *value)
 {
-       blkid_tag head = 0, found;
+       blkid_tag head = 0, found = 0;
        struct list_head *p;
 
        if (!cache || !type || !value)
@@ -303,19 +331,20 @@ try_again:
        if (!head)
                head = blkid_find_head_cache(cache, type);
 
-       found = 0;
-       list_for_each(p, &head->bit_names) {
-               blkid_tag tmp = list_entry(p, struct blkid_struct_tag, 
-                                          bit_names);
+       if (head) {
+               list_for_each(p, &head->bit_names) {
+                       blkid_tag tmp = list_entry(p, struct blkid_struct_tag, 
+                                                  bit_names);
 
-               if (!strcmp(tmp->bit_val, value)) {
-                       found = tmp;
-                       break;
+                       if (!strcmp(tmp->bit_val, value)) {
+                               found = tmp;
+                               break;
+                       }
                }
        }
 
        if ((!head || !found) && !(cache->bic_flags & BLKID_BIC_FL_PROBED)) {
-               blkid_probe_all(&cache);
+               blkid_probe_all(cache);
                goto try_again;
        }
        return (found ? found->bit_dev : NULL);
index 622f652..47a1c57 100644 (file)
@@ -68,11 +68,6 @@ static void print_tags(blkid_dev dev, char *show[], int numtag)
                        printf("%s: ", blkid_devname_name(dev));
                        first = 0;
                }
-               if (!strcmp(type, "TYPE")) {
-                       if (printed_type)
-                               return;
-                       printed_type = 1;
-               }
                printf("%s=\"%s\" ", type, value);
        }
        blkid_tag_iterate_end(iter);
@@ -156,7 +151,7 @@ int main(int argc, char **argv)
                goto exit;
        }
 
-       if (blkid_read_cache(&cache, read) < 0)
+       if (blkid_get_cache(&cache, read) < 0)
                goto exit;
 
        err = 2;
@@ -166,7 +161,7 @@ int main(int argc, char **argv)
 
                /* Load any additional devices not in the cache */
                for (i = 0; i < numdev; i++)
-                       blkid_get_devname(cache, devices[i]);
+                       blkid_get_devname(cache, devices[i], BLKID_DEV_NORMAL);
 
                if ((dev = blkid_find_dev_with_tag(cache, search_type,
                                                   search_value))) {
@@ -178,7 +173,7 @@ int main(int argc, char **argv)
                blkid_dev_iterate       iter;
                blkid_dev               dev;
 
-               blkid_probe_all(&cache);
+               blkid_probe_all(cache);
 
                iter = blkid_dev_iterate_begin(cache);
                while (blkid_dev_next(iter, &dev) == 0) {
@@ -188,7 +183,8 @@ int main(int argc, char **argv)
                blkid_dev_iterate_end(iter);
        /* Add all specified devices to cache (optionally display tags) */
        } else for (i = 0; i < numdev; i++) {
-               blkid_dev dev = blkid_get_devname(cache, devices[i]);
+               blkid_dev dev = blkid_get_devname(cache, devices[i],
+                                                 BLKID_DEV_NORMAL);
 
                if (dev) {
                        print_tags(dev, show, numtag);
@@ -201,7 +197,6 @@ exit:
                free(search_type);
        if (search_value)
                free(search_value);
-       blkid_save_cache(cache, write);
-       blkid_free_cache(cache);
+       blkid_put_cache(cache);
        return err;
 }