aboutsummaryrefslogtreecommitdiff
path: root/e2fsprogs/blkid/tag.c
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2005-05-09 22:13:22 +0000
committerMike Frysinger <vapier@gentoo.org>2005-05-09 22:13:22 +0000
commit38a33f91c0a46f51d07900731245492a3b244ae4 (patch)
treeb86c6e23c1baa56577715cdeef6551d10a4ead2c /e2fsprogs/blkid/tag.c
parent1fd98e039d146dcff02a5350f509cabca65fd29c (diff)
downloadbusybox-38a33f91c0a46f51d07900731245492a3b244ae4.tar.gz
import more libs to prep for new e2fsprogs
Diffstat (limited to 'e2fsprogs/blkid/tag.c')
-rw-r--r--e2fsprogs/blkid/tag.c340
1 files changed, 340 insertions, 0 deletions
diff --git a/e2fsprogs/blkid/tag.c b/e2fsprogs/blkid/tag.c
new file mode 100644
index 000000000..63e5e7b4d
--- /dev/null
+++ b/e2fsprogs/blkid/tag.c
@@ -0,0 +1,340 @@
+/*
+ * 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
+ * GNU Lesser General Public License.
+ * %End-Header%
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "blkidP.h"
+
+static blkid_tag blkid_new_tag(void)
+{
+ blkid_tag tag;
+
+ if (!(tag = (blkid_tag) calloc(1, sizeof(struct blkid_struct_tag))))
+ return NULL;
+
+ INIT_LIST_HEAD(&tag->bit_tags);
+ INIT_LIST_HEAD(&tag->bit_names);
+
+ return tag;
+}
+
+void blkid_free_tag(blkid_tag tag)
+{
+ if (!tag)
+ return;
+
+ 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);
+
+ 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);
+}
+
+/*
+ * 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)
+{
+ struct list_head *p;
+
+ 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))
+ return tmp;
+ }
+ return NULL;
+}
+
+/*
+ * Find the desired tag type in the cache.
+ * We return the head tag for this tag type.
+ */
+static blkid_tag blkid_find_head_cache(blkid_cache cache, const char *type)
+{
+ blkid_tag head = NULL, tmp;
+ struct list_head *p;
+
+ if (!cache || !type)
+ return NULL;
+
+ list_for_each(p, &cache->bic_tags) {
+ tmp = list_entry(p, struct blkid_struct_tag, bit_tags);
+ if (!strcmp(tmp->bit_name, type)) {
+ DBG(DEBUG_TAG,
+ printf(" found cache tag head %s\n", type));
+ head = tmp;
+ break;
+ }
+ }
+ return head;
+}
+
+/*
+ * 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,
+ const char *value, const int vlength)
+{
+ blkid_tag t = 0, head = 0;
+ char *val = 0;
+
+ if (!dev || !name)
+ return -BLKID_ERR_PARAM;
+
+ if (!(val = blkid_strndup(value, vlength)) && value)
+ return -BLKID_ERR_MEM;
+ t = blkid_find_tag_dev(dev, name);
+ if (!value) {
+ if (t)
+ blkid_free_tag(t);
+ } else if (t) {
+ if (!strcmp(t->bit_val, val)) {
+ /* Same thing, exit */
+ free(val);
+ return 0;
+ }
+ free(t->bit_val);
+ t->bit_val = val;
+ } else {
+ /* Existing tag not present, add to device */
+ if (!(t = blkid_new_tag()))
+ 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(DEBUG_TAG,
+ 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);
+ }
+ }
+
+ /* 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->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 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).
+ *
+ * Returns 0 on success, and -1 on failure.
+ */
+int blkid_parse_tag_string(const char *token, char **ret_type, char **ret_val)
+{
+ char *name, *value, *cp;
+
+ DBG(DEBUG_TAG, printf("trying to parse '%s' as a tag\n", token));
+
+ if (!token || !(cp = strchr(token, '=')))
+ return -1;
+
+ name = blkid_strdup(token);
+ if (!name)
+ return -1;
+ value = name + (cp - token);
+ *value++ = '\0';
+ if (*value == '"' || *value == '\'') {
+ char c = *value++;
+ if (!(cp = strrchr(value, c)))
+ goto errout; /* missing closing quote */
+ *cp = '\0';
+ }
+ value = blkid_strdup(value);
+ if (!value)
+ goto errout;
+
+ *ret_type = name;
+ *ret_val = value;
+
+ return 0;
+
+errout:
+ free(name);
+ return -1;
+}
+
+/*
+ * Tag 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
+ * 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
+ * performance for this application. [tytso:20030125.2007EST]
+ */
+
+/*
+ * 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;
+ struct list_head *p;
+};
+
+extern blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev)
+{
+ blkid_tag_iterate iter;
+
+ iter = malloc(sizeof(struct blkid_struct_tag_iterate));
+ if (iter) {
+ iter->magic = TAG_ITERATE_MAGIC;
+ iter->dev = dev;
+ iter->p = dev->bid_tags.next;
+ }
+ return (iter);
+}
+
+/*
+ * Return 0 on success, -1 on error
+ */
+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 ||
+ iter->p == &iter->dev->bid_tags)
+ return -1;
+ tag = list_entry(iter->p, struct blkid_struct_tag, bit_tags);
+ *type = tag->bit_name;
+ *value = tag->bit_val;
+ iter->p = iter->p->next;
+ return 0;
+}
+
+extern void blkid_tag_iterate_end(blkid_tag_iterate iter)
+{
+ if (!iter || iter->magic != TAG_ITERATE_MAGIC)
+ return;
+ iter->magic = 0;
+ free(iter);
+}
+
+/*
+ * This function returns a device which matches a particular
+ * 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,
+ const char *value)
+{
+ blkid_tag head;
+ blkid_dev dev;
+ int pri;
+ struct list_head *p;
+
+ 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;
+ head = blkid_find_head_cache(cache, type);
+
+ 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) &&
+ tmp->bit_dev->bid_pri > pri) {
+ dev = tmp->bit_dev;
+ pri = dev->bid_pri;
+ }
+ }
+ }
+ if (dev && !(dev->bid_flags & BLKID_BID_FL_VERIFIED)) {
+ dev = blkid_verify(cache, dev);
+ if (dev && (dev->bid_flags & BLKID_BID_FL_VERIFIED))
+ goto try_again;
+ }
+
+ if (!dev && !(cache->bic_flags & BLKID_BIC_FL_PROBED)) {
+ if (blkid_probe_all(cache) < 0)
+ return NULL;
+ goto try_again;
+ }
+ return dev;
+}