2 * tag.c - allocation/initialization/free routines for tag structs
4 * Copyright (C) 2001 Andreas Dilger
5 * Copyright (C) 2003 Theodore Ts'o
8 * This file may be redistributed under the terms of the
9 * GNU Lesser General Public License.
19 static blkid_tag blkid_new_tag(void)
23 if (!(tag = (blkid_tag) calloc(1, sizeof(struct blkid_struct_tag))))
26 INIT_LIST_HEAD(&tag->bit_tags);
27 INIT_LIST_HEAD(&tag->bit_names);
32 void blkid_free_tag(blkid_tag tag)
37 DBG(DEBUG_TAG, printf(" freeing tag %s=%s\n", tag->bit_name,
38 tag->bit_val ? tag->bit_val : "(NULL)"));
39 DEB_DUMP_TAG(DEBUG_TAG, tag);
41 list_del(&tag->bit_tags); /* list of tags for this device */
42 list_del(&tag->bit_names); /* list of tags with this type */
53 * Find the desired tag on a device. If value is NULL, then the
54 * first such tag is returned, otherwise return only exact tag if found.
56 blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type)
63 list_for_each(p, &dev->bid_tags) {
64 blkid_tag tmp = list_entry(p, struct blkid_struct_tag,
67 if (!strcmp(tmp->bit_name, type))
74 * Find the desired tag type in the cache.
75 * We return the head tag for this tag type.
77 static blkid_tag blkid_find_head_cache(blkid_cache cache, const char *type)
79 blkid_tag head = NULL, tmp;
85 list_for_each(p, &cache->bic_tags) {
86 tmp = list_entry(p, struct blkid_struct_tag, bit_tags);
87 if (!strcmp(tmp->bit_name, type)) {
89 printf(" found cache tag head %s\n", type));
98 * Set a tag on an existing device.
100 * If value is NULL, then delete the tagsfrom the device.
102 int blkid_set_tag(blkid_dev dev, const char *name,
103 const char *value, const int vlength)
105 blkid_tag t = 0, head = 0;
109 return -BLKID_ERR_PARAM;
111 if (!(val = blkid_strndup(value, vlength)) && value)
112 return -BLKID_ERR_MEM;
113 t = blkid_find_tag_dev(dev, name);
118 if (!strcmp(t->bit_val, val)) {
119 /* Same thing, exit */
126 /* Existing tag not present, add to device */
127 if (!(t = blkid_new_tag()))
129 t->bit_name = blkid_strdup(name);
133 list_add_tail(&t->bit_tags, &dev->bid_tags);
135 if (dev->bid_cache) {
136 head = blkid_find_head_cache(dev->bid_cache,
139 head = blkid_new_tag();
144 printf(" creating new cache tag head %s\n", name));
145 head->bit_name = blkid_strdup(name);
148 list_add_tail(&head->bit_tags,
149 &dev->bid_cache->bic_tags);
151 list_add_tail(&t->bit_names, &head->bit_names);
155 /* Link common tags directly to the device struct */
156 if (!strcmp(name, "TYPE"))
158 else if (!strcmp(name, "LABEL"))
159 dev->bid_label = val;
160 else if (!strcmp(name, "UUID"))
164 dev->bid_cache->bic_flags |= BLKID_BIC_FL_CHANGED;
173 blkid_free_tag(head);
174 return -BLKID_ERR_MEM;
179 * Parse a "NAME=value" string. This is slightly different than
180 * parse_token, because that will end an unquoted value at a space, while
181 * this will assume that an unquoted value is the rest of the token (e.g.
182 * if we are passed an already quoted string from the command-line we don't
183 * have to both quote and escape quote so that the quotes make it to
186 * Returns 0 on success, and -1 on failure.
188 int blkid_parse_tag_string(const char *token, char **ret_type, char **ret_val)
190 char *name, *value, *cp;
192 DBG(DEBUG_TAG, printf("trying to parse '%s' as a tag\n", token));
194 if (!token || !(cp = strchr(token, '=')))
197 name = blkid_strdup(token);
200 value = name + (cp - token);
202 if (*value == '"' || *value == '\'') {
204 if (!(cp = strrchr(value, c)))
205 goto errout; /* missing closing quote */
208 value = blkid_strdup(value);
223 * Tag iteration routines for the public libblkid interface.
225 * These routines do not expose the list.h implementation, which are a
226 * contamination of the namespace, and which force us to reveal far, far
227 * too much of our internal implemenation. I'm not convinced I want
228 * to keep list.h in the long term, anyway. It's fine for kernel
229 * programming, but performance is not the #1 priority for this
230 * library, and I really don't like the tradeoff of type-safety for
231 * performance for this application. [tytso:20030125.2007EST]
235 * This series of functions iterate over all tags in a device
237 #define TAG_ITERATE_MAGIC 0x01a5284c
239 struct blkid_struct_tag_iterate {
245 extern blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev)
247 blkid_tag_iterate iter;
249 iter = malloc(sizeof(struct blkid_struct_tag_iterate));
251 iter->magic = TAG_ITERATE_MAGIC;
253 iter->p = dev->bid_tags.next;
259 * Return 0 on success, -1 on error
261 extern int blkid_tag_next(blkid_tag_iterate iter,
262 const char **type, const char **value)
268 if (!iter || iter->magic != TAG_ITERATE_MAGIC ||
269 iter->p == &iter->dev->bid_tags)
271 tag = list_entry(iter->p, struct blkid_struct_tag, bit_tags);
272 *type = tag->bit_name;
273 *value = tag->bit_val;
274 iter->p = iter->p->next;
278 extern void blkid_tag_iterate_end(blkid_tag_iterate iter)
280 if (!iter || iter->magic != TAG_ITERATE_MAGIC)
287 * This function returns a device which matches a particular
288 * type/value pair. If there is more than one device that matches the
289 * search specification, it returns the one with the highest priority
290 * value. This allows us to give preference to EVMS or LVM devices.
292 * XXX there should also be an interface which uses an iterator so we
293 * can get all of the devices which match a type/value search parameter.
295 extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache,
304 if (!cache || !type || !value)
307 blkid_read_cache(cache);
309 DBG(DEBUG_TAG, printf("looking for %s=%s in cache\n", type, value));
314 head = blkid_find_head_cache(cache, type);
317 list_for_each(p, &head->bit_names) {
318 blkid_tag tmp = list_entry(p, struct blkid_struct_tag,
321 if (!strcmp(tmp->bit_val, value) &&
322 tmp->bit_dev->bid_pri > pri) {
328 if (dev && !(dev->bid_flags & BLKID_BID_FL_VERIFIED)) {
329 dev = blkid_verify_devname(cache, dev);
330 if (dev && (dev->bid_flags & BLKID_BID_FL_VERIFIED))
334 if (!dev && !(cache->bic_flags & BLKID_BIC_FL_PROBED)) {
335 blkid_probe_all(cache);