]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - libblkid/src/tag.c
40cac016670b9d0d4921be4941de5db227d4151c
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.
20 static blkid_tag
blkid_new_tag(void)
24 if (!(tag
= calloc(1, sizeof(struct blkid_struct_tag
))))
27 DBG(TAG
, ul_debugobj(tag
, "alloc"));
28 INIT_LIST_HEAD(&tag
->bit_tags
);
29 INIT_LIST_HEAD(&tag
->bit_names
);
34 void blkid_free_tag(blkid_tag tag
)
39 DBG(TAG
, ul_debugobj(tag
, "freeing tag %s (%s)", tag
->bit_name
, tag
->bit_val
));
41 list_del(&tag
->bit_tags
); /* list of tags for this device */
42 list_del(&tag
->bit_names
); /* list of tags with this type */
51 * Find the desired tag on a device. If value is NULL, then the
52 * first such tag is returned, otherwise return only exact tag if found.
54 blkid_tag
blkid_find_tag_dev(blkid_dev dev
, const char *type
)
61 list_for_each(p
, &dev
->bid_tags
) {
62 blkid_tag tmp
= list_entry(p
, struct blkid_struct_tag
,
65 if (!strcmp(tmp
->bit_name
, type
))
71 int blkid_dev_has_tag(blkid_dev dev
, const char *type
,
76 tag
= blkid_find_tag_dev(dev
, type
);
79 if (!tag
|| strcmp(tag
->bit_val
, value
))
85 * Find the desired tag type in the cache.
86 * We return the head tag for this tag type.
88 static blkid_tag
blkid_find_head_cache(blkid_cache cache
, const char *type
)
90 blkid_tag head
= NULL
, tmp
;
96 list_for_each(p
, &cache
->bic_tags
) {
97 tmp
= list_entry(p
, struct blkid_struct_tag
, bit_tags
);
98 if (!strcmp(tmp
->bit_name
, type
)) {
99 DBG(TAG
, ul_debug("found cache tag head %s", type
));
108 * Set a tag on an existing device.
110 * If value is NULL, then delete the tagsfrom the device.
112 int blkid_set_tag(blkid_dev dev
, const char *name
,
113 const char *value
, const int vlength
)
115 blkid_tag t
= 0, head
= 0;
120 return -BLKID_ERR_PARAM
;
122 if (value
&& !(val
= strndup(value
, vlength
)))
123 return -BLKID_ERR_MEM
;
126 * Certain common tags are linked directly to the device struct
127 * We need to know what they are before we do anything else because
128 * the function name parameter might get freed later on.
130 if (!strcmp(name
, "TYPE"))
131 dev_var
= &dev
->bid_type
;
132 else if (!strcmp(name
, "LABEL"))
133 dev_var
= &dev
->bid_label
;
134 else if (!strcmp(name
, "UUID"))
135 dev_var
= &dev
->bid_uuid
;
137 t
= blkid_find_tag_dev(dev
, name
);
142 if (!strcmp(t
->bit_val
, val
)) {
143 /* Same thing, exit */
147 DBG(TAG
, ul_debugobj(t
, "update (%s) '%s' -> '%s'", t
->bit_name
, t
->bit_val
, val
));
151 /* Existing tag not present, add to device */
152 if (!(t
= blkid_new_tag()))
154 t
->bit_name
= strdup(name
);
158 DBG(TAG
, ul_debugobj(t
, "setting (%s) '%s'", t
->bit_name
, t
->bit_val
));
159 list_add_tail(&t
->bit_tags
, &dev
->bid_tags
);
161 if (dev
->bid_cache
) {
162 head
= blkid_find_head_cache(dev
->bid_cache
,
165 head
= blkid_new_tag();
169 DBG(TAG
, ul_debugobj(head
, "creating new cache tag head %s", name
));
170 head
->bit_name
= strdup(name
);
173 list_add_tail(&head
->bit_tags
,
174 &dev
->bid_cache
->bic_tags
);
176 list_add_tail(&t
->bit_names
, &head
->bit_names
);
180 /* Link common tags directly to the device struct */
185 dev
->bid_cache
->bic_flags
|= BLKID_BIC_FL_CHANGED
;
194 blkid_free_tag(head
);
195 return -BLKID_ERR_MEM
;
200 * Parse a "NAME=value" string. This is slightly different than
201 * parse_token, because that will end an unquoted value at a space, while
202 * this will assume that an unquoted value is the rest of the token (e.g.
203 * if we are passed an already quoted string from the command-line we don't
204 * have to both quote and escape quote so that the quotes make it to
207 * Returns 0 on success, and -1 on failure.
209 int blkid_parse_tag_string(const char *token
, char **ret_type
, char **ret_val
)
211 char *name
, *value
, *cp
;
213 DBG(TAG
, ul_debug("trying to parse '%s' as a tag", token
));
215 if (!token
|| !(cp
= strchr(token
, '=')))
218 name
= strdup(token
);
221 value
= name
+ (cp
- token
);
223 if (*value
== '"' || *value
== '\'') {
225 if (!(cp
= strrchr(value
, c
)))
226 goto errout
; /* missing closing quote */
231 value
= *value
? strdup(value
) : NULL
;
245 DBG(TAG
, ul_debug("parse error: '%s'", token
));
251 * Tag iteration routines for the public libblkid interface.
253 * These routines do not expose the list.h implementation, which are a
254 * contamination of the namespace, and which force us to reveal far, far
255 * too much of our internal implemenation. I'm not convinced I want
256 * to keep list.h in the long term, anyway. It's fine for kernel
257 * programming, but performance is not the #1 priority for this
258 * library, and I really don't like the tradeoff of type-safety for
259 * performance for this application. [tytso:20030125.2007EST]
263 * This series of functions iterate over all tags in a device
265 #define TAG_ITERATE_MAGIC 0x01a5284c
267 struct blkid_struct_tag_iterate
{
273 blkid_tag_iterate
blkid_tag_iterate_begin(blkid_dev dev
)
275 blkid_tag_iterate iter
;
282 iter
= malloc(sizeof(struct blkid_struct_tag_iterate
));
284 iter
->magic
= TAG_ITERATE_MAGIC
;
286 iter
->p
= dev
->bid_tags
.next
;
292 * Return 0 on success, -1 on error
294 int blkid_tag_next(blkid_tag_iterate iter
,
295 const char **type
, const char **value
)
299 if (!type
|| !value
||
300 !iter
|| iter
->magic
!= TAG_ITERATE_MAGIC
||
301 iter
->p
== &iter
->dev
->bid_tags
)
306 tag
= list_entry(iter
->p
, struct blkid_struct_tag
, bit_tags
);
307 *type
= tag
->bit_name
;
308 *value
= tag
->bit_val
;
309 iter
->p
= iter
->p
->next
;
313 void blkid_tag_iterate_end(blkid_tag_iterate iter
)
315 if (!iter
|| iter
->magic
!= TAG_ITERATE_MAGIC
)
322 * This function returns a device which matches a particular
323 * type/value pair. If there is more than one device that matches the
324 * search specification, it returns the one with the highest priority
325 * value. This allows us to give preference to EVMS or LVM devices.
327 blkid_dev
blkid_find_dev_with_tag(blkid_cache cache
,
337 if (!cache
|| !type
|| !value
)
340 blkid_read_cache(cache
);
342 DBG(TAG
, ul_debug("looking for %s=%s in cache", type
, value
));
347 head
= blkid_find_head_cache(cache
, type
);
350 list_for_each(p
, &head
->bit_names
) {
351 blkid_tag tmp
= list_entry(p
, struct blkid_struct_tag
,
354 if (!strcmp(tmp
->bit_val
, value
) &&
355 (tmp
->bit_dev
->bid_pri
> pri
) &&
356 !access(tmp
->bit_dev
->bid_name
, F_OK
)) {
362 if (dev
&& !(dev
->bid_flags
& BLKID_BID_FL_VERIFIED
)) {
363 dev
= blkid_verify(cache
, dev
);
364 if (!dev
|| dev
->bid_flags
& BLKID_BID_FL_VERIFIED
)
368 if (!dev
&& !probe_new
) {
369 if (blkid_probe_all_new(cache
) < 0)
375 if (!dev
&& !(cache
->bic_flags
& BLKID_BIC_FL_PROBED
)) {
376 if (blkid_probe_all(cache
) < 0)
391 static void __attribute__((__noreturn__
)) usage(char *prog
)
393 fprintf(stderr
, "Usage: %s [-f blkid_file] [-m debug_mask] device "
396 fprintf(stderr
, "\tList all tags for a device and exit\n");
400 int main(int argc
, char **argv
)
402 blkid_tag_iterate iter
;
403 blkid_cache cache
= NULL
;
406 int flags
= BLKID_DEV_FIND
;
409 char *devname
= NULL
;
410 char *search_type
= NULL
;
411 char *search_value
= NULL
;
412 const char *type
, *value
;
414 while ((c
= getopt (argc
, argv
, "m:f:")) != EOF
)
421 int mask
= strtoul (optarg
, &tmp
, 0);
423 fprintf(stderr
, "Invalid debug mask: %s\n",
427 blkid_init_debug(mask
);
434 devname
= argv
[optind
++];
436 search_type
= argv
[optind
++];
438 search_value
= argv
[optind
++];
439 if (!devname
|| (argc
!= optind
))
442 if ((ret
= blkid_get_cache(&cache
, file
)) != 0) {
443 fprintf(stderr
, "%s: error creating cache (%d)\n",
448 dev
= blkid_get_dev(cache
, devname
, flags
);
450 fprintf(stderr
, "%s: Can not find device in blkid cache\n",
455 found
= blkid_dev_has_tag(dev
, search_type
, search_value
);
456 printf("Device %s: (%s, %s) %s\n", blkid_dev_devname(dev
),
457 search_type
, search_value
? search_value
: "NULL",
458 found
? "FOUND" : "NOT FOUND");
461 printf("Device %s...\n", blkid_dev_devname(dev
));
463 iter
= blkid_tag_iterate_begin(dev
);
464 while (blkid_tag_next(iter
, &type
, &value
) == 0) {
465 printf("\tTag %s has value %s\n", type
, value
);
467 blkid_tag_iterate_end(iter
);
469 blkid_put_cache(cache
);