1 /* vi: set sw=4 ts=4: */
3 * tag.c - allocation/initialization/free routines for tag structs
5 * Copyright (C) 2001 Andreas Dilger
6 * Copyright (C) 2003 Theodore Ts'o
9 * This file may be redistributed under the terms of the
10 * GNU Lesser General Public License.
20 static blkid_tag
blkid_new_tag(void)
24 tag
= xzalloc(sizeof(struct blkid_struct_tag
));
26 INIT_LIST_HEAD(&tag
->bit_tags
);
27 INIT_LIST_HEAD(&tag
->bit_names
);
32 #ifdef CONFIG_BLKID_DEBUG
33 void blkid_debug_dump_tag(blkid_tag tag
)
36 printf(" tag: NULL\n");
40 printf(" tag: %s=\"%s\"\n", tag
->bit_name
, tag
->bit_val
);
44 void blkid_free_tag(blkid_tag tag
)
49 DBG(DEBUG_TAG
, printf(" freeing tag %s=%s\n", tag
->bit_name
,
50 tag
->bit_val
? tag
->bit_val
: "(NULL)"));
51 DBG(DEBUG_TAG
, blkid_debug_dump_tag(tag
));
53 list_del(&tag
->bit_tags
); /* list of tags for this device */
54 list_del(&tag
->bit_names
); /* list of tags with this type */
62 * Find the desired tag on a device. If value is NULL, then the
63 * first such tag is returned, otherwise return only exact tag if found.
65 blkid_tag
blkid_find_tag_dev(blkid_dev dev
, const char *type
)
72 list_for_each(p
, &dev
->bid_tags
) {
73 blkid_tag tmp
= list_entry(p
, struct blkid_struct_tag
,
76 if (!strcmp(tmp
->bit_name
, type
))
83 * Find the desired tag type in the cache.
84 * We return the head tag for this tag type.
86 static blkid_tag
blkid_find_head_cache(blkid_cache cache
, const char *type
)
88 blkid_tag head
= NULL
, tmp
;
94 list_for_each(p
, &cache
->bic_tags
) {
95 tmp
= list_entry(p
, struct blkid_struct_tag
, bit_tags
);
96 if (!strcmp(tmp
->bit_name
, type
)) {
98 printf(" found cache tag head %s\n", type
));
107 * Set a tag on an existing device.
109 * If value is NULL, then delete the tagsfrom the device.
111 int blkid_set_tag(blkid_dev dev
, const char *name
,
112 const char *value
, const int vlength
)
114 blkid_tag t
= 0, head
= 0;
118 return -BLKID_ERR_PARAM
;
120 if (!(val
= blkid_strndup(value
, vlength
)) && value
)
121 return -BLKID_ERR_MEM
;
122 t
= blkid_find_tag_dev(dev
, name
);
126 if (!strcmp(t
->bit_val
, val
)) {
127 /* Same thing, exit */
134 /* Existing tag not present, add to device */
135 if (!(t
= blkid_new_tag()))
137 t
->bit_name
= blkid_strdup(name
);
141 list_add_tail(&t
->bit_tags
, &dev
->bid_tags
);
143 if (dev
->bid_cache
) {
144 head
= blkid_find_head_cache(dev
->bid_cache
,
147 head
= blkid_new_tag();
152 printf(" creating new cache tag head %s\n", name
));
153 head
->bit_name
= blkid_strdup(name
);
156 list_add_tail(&head
->bit_tags
,
157 &dev
->bid_cache
->bic_tags
);
159 list_add_tail(&t
->bit_names
, &head
->bit_names
);
163 /* Link common tags directly to the device struct */
164 if (!strcmp(name
, "TYPE"))
166 else if (!strcmp(name
, "LABEL"))
167 dev
->bid_label
= val
;
168 else if (!strcmp(name
, "UUID"))
172 dev
->bid_cache
->bic_flags
|= BLKID_BIC_FL_CHANGED
;
179 blkid_free_tag(head
);
180 return -BLKID_ERR_MEM
;
185 * Parse a "NAME=value" string. This is slightly different than
186 * parse_token, because that will end an unquoted value at a space, while
187 * this will assume that an unquoted value is the rest of the token (e.g.
188 * if we are passed an already quoted string from the command-line we don't
189 * have to both quote and escape quote so that the quotes make it to
192 * Returns 0 on success, and -1 on failure.
194 int blkid_parse_tag_string(const char *token
, char **ret_type
, char **ret_val
)
196 char *name
, *value
, *cp
;
198 DBG(DEBUG_TAG
, printf("trying to parse '%s' as a tag\n", token
));
200 if (!token
|| !(cp
= strchr(token
, '=')))
203 name
= blkid_strdup(token
);
206 value
= name
+ (cp
- token
);
208 if (*value
== '"' || *value
== '\'') {
210 if (!(cp
= strrchr(value
, c
)))
211 goto errout
; /* missing closing quote */
214 value
= blkid_strdup(value
);
229 * Tag iteration routines for the public libblkid interface.
231 * These routines do not expose the list.h implementation, which are a
232 * contamination of the namespace, and which force us to reveal far, far
233 * too much of our internal implemenation. I'm not convinced I want
234 * to keep list.h in the long term, anyway. It's fine for kernel
235 * programming, but performance is not the #1 priority for this
236 * library, and I really don't like the tradeoff of type-safety for
237 * performance for this application. [tytso:20030125.2007EST]
241 * This series of functions iterate over all tags in a device
243 #define TAG_ITERATE_MAGIC 0x01a5284c
245 struct blkid_struct_tag_iterate
{
251 blkid_tag_iterate
blkid_tag_iterate_begin(blkid_dev dev
)
253 blkid_tag_iterate iter
;
255 iter
= xmalloc(sizeof(struct blkid_struct_tag_iterate
));
256 iter
->magic
= TAG_ITERATE_MAGIC
;
258 iter
->p
= dev
->bid_tags
.next
;
263 * Return 0 on success, -1 on error
265 extern int blkid_tag_next(blkid_tag_iterate iter
,
266 const char **type
, const char **value
)
272 if (!iter
|| iter
->magic
!= TAG_ITERATE_MAGIC
||
273 iter
->p
== &iter
->dev
->bid_tags
)
275 tag
= list_entry(iter
->p
, struct blkid_struct_tag
, bit_tags
);
276 *type
= tag
->bit_name
;
277 *value
= tag
->bit_val
;
278 iter
->p
= iter
->p
->next
;
282 void blkid_tag_iterate_end(blkid_tag_iterate iter
)
284 if (!iter
|| iter
->magic
!= TAG_ITERATE_MAGIC
)
291 * This function returns a device which matches a particular
292 * type/value pair. If there is more than one device that matches the
293 * search specification, it returns the one with the highest priority
294 * value. This allows us to give preference to EVMS or LVM devices.
296 * XXX there should also be an interface which uses an iterator so we
297 * can get all of the devices which match a type/value search parameter.
299 extern blkid_dev
blkid_find_dev_with_tag(blkid_cache cache
,
308 if (!cache
|| !type
|| !value
)
311 blkid_read_cache(cache
);
313 DBG(DEBUG_TAG
, printf("looking for %s=%s in cache\n", type
, value
));
318 head
= blkid_find_head_cache(cache
, type
);
321 list_for_each(p
, &head
->bit_names
) {
322 blkid_tag tmp
= list_entry(p
, struct blkid_struct_tag
,
325 if (!strcmp(tmp
->bit_val
, value
) &&
326 tmp
->bit_dev
->bid_pri
> pri
) {
332 if (dev
&& !(dev
->bid_flags
& BLKID_BID_FL_VERIFIED
)) {
333 dev
= blkid_verify(cache
, dev
);
334 if (dev
&& (dev
->bid_flags
& BLKID_BID_FL_VERIFIED
))
338 if (!dev
&& !(cache
->bic_flags
& BLKID_BIC_FL_PROBED
)) {
339 if (blkid_probe_all(cache
) < 0)
354 void usage(char *prog
)
356 fprintf(stderr
, "Usage: %s [-f blkid_file] [-m debug_mask] device "
359 fprintf(stderr
, "\tList all tags for a device and exit\n", prog
);
363 int main(int argc
, char **argv
)
365 blkid_tag_iterate iter
;
366 blkid_cache cache
= NULL
;
369 int flags
= BLKID_DEV_FIND
;
372 char *devname
= NULL
;
373 char *search_type
= NULL
;
374 char *search_value
= NULL
;
375 const char *type
, *value
;
377 while ((c
= getopt (argc
, argv
, "m:f:")) != EOF
)
383 blkid_debug_mask
= strtoul (optarg
, &tmp
, 0);
385 fprintf(stderr
, "Invalid debug mask: %d\n",
394 devname
= argv
[optind
++];
396 search_type
= argv
[optind
++];
398 search_value
= argv
[optind
++];
399 if (!devname
|| (argc
!= optind
))
402 if ((ret
= blkid_get_cache(&cache
, file
)) != 0) {
403 fprintf(stderr
, "%s: error creating cache (%d)\n",
408 dev
= blkid_get_dev(cache
, devname
, flags
);
410 fprintf(stderr
, "%s: cannot find device in blkid cache\n");
414 found
= blkid_dev_has_tag(dev
, search_type
, search_value
);
415 printf("Device %s: (%s, %s) %s\n", blkid_dev_devname(dev
),
416 search_type
, search_value
? search_value
: "NULL",
417 found
? "FOUND" : "NOT FOUND");
420 printf("Device %s...\n", blkid_dev_devname(dev
));
422 iter
= blkid_tag_iterate_begin(dev
);
423 while (blkid_tag_next(iter
, &type
, &value
) == 0) {
424 printf("\tTag %s has value %s\n", type
, value
);
426 blkid_tag_iterate_end(iter
);
428 blkid_put_cache(cache
);