Whamcloud - gitweb
AOSP: Android: consolidate addition of include/mingw/
[tools/e2fsprogs.git] / lib / blkid / dev.c
index 2075d45..1d62dd8 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
  * %End-Header%
  */
 
+#include "config.h"
 #include <stdlib.h>
 #include <string.h>
+#include <stdint.h>
 
 #include "blkidP.h"
 
-#ifdef DEBUG_DEV
-#include <stdio.h>
-#define DBG(x) x
-#else
-#define DBG(x)
-#endif
-
 blkid_dev blkid_new_dev(void)
 {
        blkid_dev dev;
@@ -39,8 +35,10 @@ void blkid_free_dev(blkid_dev dev)
        if (!dev)
                return;
 
-       DBG(printf("  freeing dev %s (%s)\n", dev->bid_name, dev->bid_type));
-       DEB_DUMP_DEV(dev);
+       DBG(DEBUG_DEV,
+           printf("  freeing dev %s (%s)\n", dev->bid_name, dev->bid_type ?
+                  dev->bid_type : "(null)"));
+       DBG(DEBUG_DEV, blkid_debug_dump_dev(dev));
 
        list_del(&dev->bid_devs);
        while (!list_empty(&dev->bid_tags)) {
@@ -49,92 +47,52 @@ void blkid_free_dev(blkid_dev dev)
                                           bit_tags);
                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
+ * Given a blkid device, return its name
  */
-#define SC_DIFF        0x0001
-#define SC_NONE        0x0003
-#define SC_SAME        0x0002
-
-static int string_compare(char *s1, char *s2)
+extern const char *blkid_dev_devname(blkid_dev dev)
 {
-       if (!s1 && !s2)
-               return SC_NONE;
-
-       if (!s1 || !s2)
-               return SC_DIFF;
-
-       if (strcmp(s1, s2))
-               return SC_DIFF;
-
-       return SC_SAME;
+       return dev->bid_name;
 }
 
-/*
- * Add a tag to the global cache tag list.
- */
-static int add_tag_to_cache(blkid_cache cache, blkid_tag tag)
+#ifdef CONFIG_BLKID_DEBUG
+void blkid_debug_dump_dev(blkid_dev dev)
 {
-       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;
-               }
+       struct list_head *p;
 
-               list_add_tail(&head->bit_tags, &cache->bic_tags);
+       if (!dev) {
+               printf("  dev: NULL\n");
+               return;
        }
 
-       /* Add this tag to global list */
-       list_add_tail(&tag->bit_names, &head->bit_names);
+       printf("  dev: name = %s\n", dev->bid_name);
+       printf("  dev: DEVNO=\"0x%0llx\"\n", (long long)dev->bid_devno);
+       printf("  dev: TIME=\"%ld\"\n", (long)dev->bid_time);
+       printf("  dev: PRI=\"%d\"\n", dev->bid_pri);
+       printf("  dev: flags = 0x%08X\n", dev->bid_flags);
 
-       return 0;
-}
-
-/*
- * Given a blkid device, return its name
- */
-extern const char *blkid_devname_name(blkid_dev dev)
-{
-       return dev->bid_name;
+       list_for_each(p, &dev->bid_tags) {
+               blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags);
+               if (tag)
+                       printf("    tag: %s=\"%s\"\n", tag->bit_name,
+                              tag->bit_val);
+               else
+                       printf("    tag: NULL\n");
+       }
+       printf("\n");
 }
+#endif
 
 /*
  * dev iteration routines for the public libblkid interface.
  *
  * These routines do not expose the list.h implementation, which are a
  * contamination of the namespace, and which force us to reveal far, far
- * too much of our internal implemenation.  I'm not convinced I want
+ * too much of our internal implementation.  I'm not convinced I want
  * to keep list.h in the long term, anyway.  It's fine for kernel
  * programming, but performance is not the #1 priority for this
  * library, and I really don't like the tradeoff of type-safety for
@@ -145,10 +103,12 @@ extern const char *blkid_devname_name(blkid_dev dev)
  * This series of functions iterate over all devices in a blkid cache
  */
 #define DEV_ITERATE_MAGIC      0x01a5284c
-       
+
 struct blkid_struct_dev_iterate {
        int                     magic;
        blkid_cache             cache;
+       char                    *search_type;
+       char                    *search_value;
        struct list_head        *p;
 };
 
@@ -161,23 +121,58 @@ extern blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache)
                iter->magic = DEV_ITERATE_MAGIC;
                iter->cache = cache;
                iter->p = cache->bic_devs.next;
+               iter->search_type = 0;
+               iter->search_value = 0;
        }
        return (iter);
 }
 
+extern int blkid_dev_set_search(blkid_dev_iterate iter,
+                                char *search_type, char *search_value)
+{
+       char *new_type, *new_value;
+
+       if (!iter || iter->magic != DEV_ITERATE_MAGIC || !search_type ||
+           !search_value)
+               return -1;
+       new_type = malloc(strlen(search_type)+1);
+       new_value = malloc(strlen(search_value)+1);
+       if (!new_type || !new_value) {
+               free(new_type);
+               free(new_value);
+               return -1;
+       }
+       strcpy(new_type, search_type);
+       strcpy(new_value, search_value);
+       free(iter->search_type);
+       free(iter->search_value);
+       iter->search_type = new_type;
+       iter->search_value = new_value;
+       return 0;
+}
+
 /*
  * Return 0 on success, -1 on error
  */
 extern int blkid_dev_next(blkid_dev_iterate iter,
-                         blkid_dev *dev)
+                         blkid_dev *ret_dev)
 {
-       *dev = 0;
-       if (!iter || iter->magic != DEV_ITERATE_MAGIC ||
-           iter->p == &iter->cache->bic_devs)
+       blkid_dev               dev;
+
+       *ret_dev = 0;
+       if (!iter || iter->magic != DEV_ITERATE_MAGIC)
                return -1;
-       *dev = list_entry(iter->p, struct blkid_struct_dev, bid_devs);
-       iter->p = iter->p->next;
-       return 0;
+       while (iter->p != &iter->cache->bic_devs) {
+               dev = list_entry(iter->p, struct blkid_struct_dev, bid_devs);
+               iter->p = iter->p->next;
+               if (iter->search_type &&
+                   !blkid_dev_has_tag(dev, iter->search_type,
+                                      iter->search_value))
+                       continue;
+               *ret_dev = dev;
+               return 0;
+       }
+       return -1;
 }
 
 extern void blkid_dev_iterate_end(blkid_dev_iterate iter)
@@ -188,146 +183,72 @@ 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);
-               }
+#ifdef TEST_PROGRAM
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else
+extern char *optarg;
+extern int optind;
+#endif
 
-               /* 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;
-                       }
-               }
+void usage(char *prog)
+{
+       fprintf(stderr, "Usage: %s [-f blkid_file] [-m debug_mask]\n", prog);
+       fprintf(stderr, "\tList all devices and exit\n");
+       exit(1);
+}
 
-               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;
+int main(int argc, char **argv)
+{
+       blkid_dev_iterate       iter;
+       blkid_cache             cache = NULL;
+       blkid_dev               dev;
+       int                     c, ret;
+       char                    *tmp;
+       char                    *file = NULL;
+       char                    *search_type = NULL;
+       char                    *search_value = NULL;
+
+       while ((c = getopt (argc, argv, "m:f:")) != EOF)
+               switch (c) {
+               case 'f':
+                       file = optarg;
+                       break;
+               case 'm':
+                       blkid_debug_mask = strtoul (optarg, &tmp, 0);
+                       if (*tmp) {
+                               fprintf(stderr, "Invalid debug mask: %s\n",
+                                       optarg);
+                               exit(1);
                        }
-                       fprintf(stderr, "blkid: same LABEL for %s and %s\n",
-                               dev->bid_name, odev->bid_name);
+                       break;
+               case '?':
+                       usage(argv[0]);
                }
+       if (argc >= optind+2) {
+               search_type = argv[optind];
+               search_value = argv[optind+1];
+               optind += 2;
        }
+       if (argc != optind)
+               usage(argv[0]);
 
-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]);
+       if ((ret = blkid_get_cache(&cache, file)) != 0) {
+               fprintf(stderr, "%s: error creating cache (%d)\n",
+                       argv[0], ret);
                exit(1);
        }
 
-       cache = blkid_new_cache();
-       if (!cache) {
-               perror(argv[0]);
-               return 1;
+       iter = blkid_dev_iterate_begin(cache);
+       if (search_type)
+               blkid_dev_set_search(iter, search_type, search_value);
+       while (blkid_dev_next(iter, &dev) == 0) {
+               printf("Device: %s\n", blkid_dev_devname(dev));
        }
-       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);
+       blkid_dev_iterate_end(iter);
 
-       return 0;
+
+       blkid_put_cache(cache);
+       return (0);
 }
 #endif