Whamcloud - gitweb
Update release notes, etc., for the 1.46.4 release
[tools/e2fsprogs.git] / lib / blkid / tag.c
index 63e5e7b..e88ebc4 100644 (file)
@@ -10,6 +10,8 @@
  * %End-Header%
  */
 
+#include "config.h"
+#include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
@@ -29,6 +31,18 @@ static blkid_tag blkid_new_tag(void)
        return tag;
 }
 
+#ifdef CONFIG_BLKID_DEBUG
+void blkid_debug_dump_tag(blkid_tag tag)
+{
+       if (!tag) {
+               printf("    tag: NULL\n");
+               return;
+       }
+
+       printf("    tag: %s=\"%s\"\n", tag->bit_name, tag->bit_val);
+}
+#endif
+
 void blkid_free_tag(blkid_tag tag)
 {
        if (!tag)
@@ -36,15 +50,13 @@ void blkid_free_tag(blkid_tag tag)
 
        DBG(DEBUG_TAG, printf("    freeing tag %s=%s\n", tag->bit_name,
                   tag->bit_val ? tag->bit_val : "(NULL)"));
-       DEB_DUMP_TAG(DEBUG_TAG, tag);
+       DBG(DEBUG_TAG, blkid_debug_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)
-               free(tag->bit_name);
-       if (tag->bit_val)
-               free(tag->bit_val);
+       free(tag->bit_name);
+       free(tag->bit_val);
 
        free(tag);
 }
@@ -70,6 +82,22 @@ blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type)
        return NULL;
 }
 
+extern int blkid_dev_has_tag(blkid_dev dev, const char *type,
+                            const char *value)
+{
+       blkid_tag               tag;
+
+       if (!dev || !type)
+               return -1;
+
+       tag = blkid_find_tag_dev(dev, type);
+       if (!value)
+               return (tag != NULL);
+       if (!tag || strcmp(tag->bit_val, value))
+               return 0;
+       return 1;
+}
+
 /*
  * Find the desired tag type in the cache.
  * We return the head tag for this tag type.
@@ -96,7 +124,7 @@ static blkid_tag blkid_find_head_cache(blkid_cache cache, const char *type)
 
 /*
  * Set a tag on an existing device.
- * 
+ *
  * If value is NULL, then delete the tagsfrom the device.
  */
 int blkid_set_tag(blkid_dev dev, const char *name,
@@ -104,12 +132,26 @@ int blkid_set_tag(blkid_dev dev, const char *name,
 {
        blkid_tag       t = 0, head = 0;
        char            *val = 0;
+       char            **dev_var = 0;
 
        if (!dev || !name)
                return -BLKID_ERR_PARAM;
 
        if (!(val = blkid_strndup(value, vlength)) && value)
                return -BLKID_ERR_MEM;
+
+       /*
+        * Certain common tags are linked directly to the device struct
+        * We need to know what they are before we do anything else because
+        * the function name parameter might get freed later on.
+        */
+       if (!strcmp(name, "TYPE"))
+               dev_var = &dev->bid_type;
+       else if (!strcmp(name, "LABEL"))
+               dev_var = &dev->bid_label;
+       else if (!strcmp(name, "UUID"))
+               dev_var = &dev->bid_uuid;
+
        t = blkid_find_tag_dev(dev, name);
        if (!value) {
                if (t)
@@ -131,7 +173,7 @@ int blkid_set_tag(blkid_dev dev, const char *name,
                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);
@@ -151,15 +193,11 @@ int blkid_set_tag(blkid_dev dev, const char *name,
                        list_add_tail(&t->bit_names, &head->bit_names);
                }
        }
-       
+
        /* Link common tags directly to the device struct */
-       if (!strcmp(name, "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_var)
+               *dev_var = val;
+
        if (dev->bid_cache)
                dev->bid_cache->bic_flags |= BLKID_BIC_FL_CHANGED;
        return 0;
@@ -167,8 +205,7 @@ int blkid_set_tag(blkid_dev dev, const char *name,
 errout:
        if (t)
                blkid_free_tag(t);
-       else if (val)
-               free(val);
+       else free(val);
        if (head)
                blkid_free_tag(head);
        return -BLKID_ERR_MEM;
@@ -224,7 +261,7 @@ errout:
  *
  * 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
@@ -235,7 +272,7 @@ errout:
  * This series of functions iterate over all tags in a device
  */
 #define TAG_ITERATE_MAGIC      0x01a5284c
-       
+
 struct blkid_struct_tag_iterate {
        int                     magic;
        blkid_dev               dev;
@@ -262,7 +299,7 @@ extern int blkid_tag_next(blkid_tag_iterate iter,
                          const char **type, const char **value)
 {
        blkid_tag tag;
-       
+
        *type = 0;
        *value = 0;
        if (!iter || iter->magic != TAG_ITERATE_MAGIC ||
@@ -288,9 +325,6 @@ extern void blkid_tag_iterate_end(blkid_tag_iterate iter)
  * type/value pair.  If there is more than one device that matches the
  * search specification, it returns the one with the highest priority
  * value.  This allows us to give preference to EVMS or LVM devices.
- *
- * XXX there should also be an interface which uses an iterator so we
- * can get all of the devices which match a type/value search parameter.
  */
 extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache,
                                         const char *type,
@@ -300,14 +334,15 @@ extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache,
        blkid_dev       dev;
        int             pri;
        struct list_head *p;
+       int             probe_new = 0;
 
        if (!cache || !type || !value)
                return NULL;
 
        blkid_read_cache(cache);
-       
+
        DBG(DEBUG_TAG, printf("looking for %s=%s in cache\n", type, value));
-       
+
 try_again:
        pri = -1;
        dev = 0;
@@ -315,11 +350,12 @@ try_again:
 
        if (head) {
                list_for_each(p, &head->bit_names) {
-                       blkid_tag tmp = list_entry(p, struct blkid_struct_tag, 
+                       blkid_tag tmp = list_entry(p, struct blkid_struct_tag,
                                                   bit_names);
 
                        if (!strcmp(tmp->bit_val, value) &&
-                           tmp->bit_dev->bid_pri > pri) {
+                           (tmp->bit_dev->bid_pri > pri) &&
+                           !access(tmp->bit_dev->bid_name, F_OK)) {
                                dev = tmp->bit_dev;
                                pri = dev->bid_pri;
                        }
@@ -327,10 +363,17 @@ try_again:
        }
        if (dev && !(dev->bid_flags & BLKID_BID_FL_VERIFIED)) {
                dev = blkid_verify(cache, dev);
-               if (dev && (dev->bid_flags & BLKID_BID_FL_VERIFIED))
+               if (!dev || (dev && (dev->bid_flags & BLKID_BID_FL_VERIFIED)))
                        goto try_again;
        }
 
+       if (!dev && !probe_new) {
+               if (blkid_probe_all_new(cache) < 0)
+                       return NULL;
+               probe_new++;
+               goto try_again;
+       }
+
        if (!dev && !(cache->bic_flags & BLKID_BIC_FL_PROBED)) {
                if (blkid_probe_all(cache) < 0)
                        return NULL;
@@ -338,3 +381,91 @@ try_again:
        }
        return dev;
 }
+
+#ifdef TEST_PROGRAM
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else
+extern char *optarg;
+extern int optind;
+#endif
+
+void usage(char *prog)
+{
+       fprintf(stderr, "Usage: %s [-f blkid_file] [-m debug_mask] device "
+               "[type value]\n",
+               prog);
+       fprintf(stderr, "\tList all tags for a device and exit\n");
+       exit(1);
+}
+
+int main(int argc, char **argv)
+{
+       blkid_tag_iterate       iter;
+       blkid_cache             cache = NULL;
+       blkid_dev               dev;
+       int                     c, ret, found;
+       int                     flags = BLKID_DEV_FIND;
+       char                    *tmp;
+       char                    *file = NULL;
+       char                    *devname = NULL;
+       char                    *search_type = NULL;
+       char                    *search_value = NULL;
+       const char              *type, *value;
+
+       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);
+                       }
+                       break;
+               case '?':
+                       usage(argv[0]);
+               }
+       if (argc > optind)
+               devname = argv[optind++];
+       if (argc > optind)
+               search_type = argv[optind++];
+       if (argc > optind)
+               search_value = argv[optind++];
+       if (!devname || (argc != optind))
+               usage(argv[0]);
+
+       if ((ret = blkid_get_cache(&cache, file)) != 0) {
+               fprintf(stderr, "%s: error creating cache (%d)\n",
+                       argv[0], ret);
+               exit(1);
+       }
+
+       dev = blkid_get_dev(cache, devname, flags);
+       if (!dev) {
+               fprintf(stderr, "%s: Can not find device in blkid cache\n",
+                       devname);
+               exit(1);
+       }
+       if (search_type) {
+               found = blkid_dev_has_tag(dev, search_type, search_value);
+               printf("Device %s: (%s, %s) %s\n", blkid_dev_devname(dev),
+                      search_type, search_value ? search_value : "NULL",
+                      found ? "FOUND" : "NOT FOUND");
+               return(!found);
+       }
+       printf("Device %s...\n", blkid_dev_devname(dev));
+
+       iter = blkid_tag_iterate_begin(dev);
+       while (blkid_tag_next(iter, &type, &value) == 0) {
+               printf("\tTag %s has value %s\n", type, value);
+       }
+       blkid_tag_iterate_end(iter);
+
+       blkid_put_cache(cache);
+       return (0);
+}
+#endif