]> git.ipfire.org Git - thirdparty/util-linux.git/blob - shlibs/blkid/src/probe.c
libblkid: add missing comments to probe.c
[thirdparty/util-linux.git] / shlibs / blkid / src / probe.c
1 /*
2 * Low-level libblkid probing API
3 *
4 * Copyright (C) 2008-2009 Karel Zak <kzak@redhat.com>
5 *
6 * This file may be redistributed under the terms of the
7 * GNU Lesser General Public License.
8 */
9
10 /**
11 * SECTION: lowprobe
12 * @title: Low-level probing
13 * @short_description: low-level prober initialization
14 *
15 * The low-level probing routines always and directly read information from
16 * the selected (see blkid_probe_set_device()) device.
17 *
18 * The probing routines are grouped together into separate chains. Currently,
19 * the librray provides superblocks, partitions and topology chains.
20 *
21 * The probing routines is possible to filter (enable/disable) by type (e.g.
22 * fstype "vfat" or partype "gpt") or by usage flags (e.g. BLKID_USAGE_RAID).
23 * These filters are per-chain. For more details see the chain specific
24 * documenation.
25 *
26 * The low-level API provides two ways how access to probing results.
27 *
28 * 1. The NAME=value (tag) interface. This interface is older and returns all data
29 * as strings. This interface is generic for all chains.
30 *
31 * 2. The binary interfaces. These interfaces return data in the native formats.
32 * The interface is always specific to the probing chain.
33 */
34
35 /**
36 * SECTION: lowprobe-tags
37 * @title: Low-level tags
38 * @short_description: generic NAME=value interface.
39 *
40 * The probing routines inside the chain are mutually exclusive by default --
41 * only few probing routines are marked as "tolerant". The "tolerant" probing
42 * routines are used for filesystem which can share the same device with any
43 * other filesystem. The blkid_do_safeprobe() checks for the "tolerant" flag.
44 *
45 * The SUPERBLOCKS chain is enabled by default. The all others chains is
46 * necessary to enable by blkid_probe_enable_'CHAINNAME'(). See chains specific
47 * documenation.
48 *
49 * The blkid_do_probe() function returns a result from only one probing
50 * routine, and the next call from the next probing routine. It means you need
51 * to call the function in loop, for example:
52 *
53 * <informalexample>
54 * <programlisting>
55 * while((blkid_do_probe(pr) == 0)
56 * ... use result ...
57 * </programlisting>
58 * </informalexample>
59 *
60 * The blkid_do_safeprobe() is the same as blkid_do_probe(), but returns only
61 * first probing result for every enabled chain. This function checks for
62 * ambivalent results (e.g. more "intolerant" filesystems superblocks on the
63 * device).
64 *
65 * The probing result is set of NAME=value pairs (the NAME is always unique).
66 */
67
68 #include <stdio.h>
69 #include <string.h>
70 #include <stdlib.h>
71 #include <unistd.h>
72 #include <fcntl.h>
73 #include <ctype.h>
74 #include <sys/types.h>
75 #ifdef HAVE_SYS_STAT_H
76 #include <sys/stat.h>
77 #endif
78 #ifdef HAVE_SYS_MKDEV_H
79 #include <sys/mkdev.h>
80 #endif
81 #ifdef HAVE_ERRNO_H
82 #include <errno.h>
83 #endif
84 #include <stdint.h>
85 #include <stdarg.h>
86
87 #ifdef HAVE_LIBUUID
88 # ifdef HAVE_UUID_UUID_H
89 # include <uuid/uuid.h>
90 # else
91 # include <uuid.h>
92 # endif
93 #endif
94
95 #include "blkdev.h"
96 #include "blkidP.h"
97
98 /* chains */
99 extern const struct blkid_chaindrv superblocks_drv;
100
101 /*
102 * All supported chains
103 */
104 static const struct blkid_chaindrv *chains_drvs[] = {
105 [BLKID_CHAIN_SUBLKS] = &superblocks_drv,
106 };
107
108 static void blkid_probe_reset_vals(blkid_probe pr);
109
110 /**
111 * blkid_new_probe:
112 *
113 * Returns: a pointer to the newly allocated probe struct.
114 */
115 blkid_probe blkid_new_probe(void)
116 {
117 int i;
118 blkid_probe pr;
119
120 blkid_init_debug(0);
121 pr = calloc(1, sizeof(struct blkid_struct_probe));
122 if (!pr)
123 return NULL;
124
125 /* initialize chains */
126 for (i = 0; i < BLKID_NCHAINS; i++) {
127 pr->chains[i].driver = chains_drvs[i];
128 pr->chains[i].flags = chains_drvs[i]->dflt_flags;
129 pr->chains[i].enabled = chains_drvs[i]->dflt_enabled;
130 }
131 return pr;
132 }
133
134 /**
135 * blkid_free_probe:
136 * @pr: probe
137 *
138 * Deallocates the probe struct, buffers and all allocated
139 * data that are associated with this probing control struct.
140 */
141 void blkid_free_probe(blkid_probe pr)
142 {
143 int i;
144
145 if (!pr)
146 return;
147
148 for (i = 0; i < BLKID_NCHAINS; i++) {
149 struct blkid_chain *ch = &pr->chains[i];
150
151 if (ch->driver->free_data)
152 ch->driver->free_data(pr, ch->data);
153 free(ch->fltr);
154 }
155 free(pr->buf);
156 free(pr->sbbuf);
157 free(pr);
158 }
159
160 static void blkid_probe_reset_buffer(blkid_probe pr)
161 {
162 DBG(DEBUG_LOWPROBE, printf("reseting blkid probe buffer\n"));
163 if (pr->buf)
164 memset(pr->buf, 0, pr->buf_max);
165 pr->buf_off = 0;
166 pr->buf_len = 0;
167 if (pr->sbbuf)
168 memset(pr->sbbuf, 0, BLKID_SB_BUFSIZ);
169 pr->sbbuf_len = 0;
170 }
171
172
173 /*
174 * Removes chain values from probing result.
175 */
176 void blkid_probe_chain_reset_vals(blkid_probe pr, struct blkid_chain *chn)
177 {
178 int nvals = pr->nvals;
179 int i, x;
180
181 for (x = 0, i = 0; i < pr->nvals; i++) {
182 struct blkid_prval *v = &pr->vals[i];
183
184 if (v->chain != chn && x == i) {
185 x++;
186 continue;
187 }
188 if (v->chain == chn) {
189 --nvals;
190 continue;
191 }
192 memcpy(&pr->vals[x++], v, sizeof(struct blkid_prval));
193 }
194 pr->nvals = nvals;
195 }
196
197 /*
198 * Copies chain values from probing result to @vals, the max size of @vals is
199 * @nvals and returns real number of values.
200 */
201 int blkid_probe_chain_copy_vals(blkid_probe pr, struct blkid_chain *chn,
202 struct blkid_prval *vals, int nvals)
203 {
204 int i, x;
205
206 for (x = 0, i = 0; i < pr->nvals && x < nvals; i++) {
207 struct blkid_prval *v = &pr->vals[i];
208
209 if (v->chain != chn)
210 continue;
211 memcpy(&vals[x++], v, sizeof(struct blkid_prval));
212 }
213 return x;
214 }
215
216 /*
217 * Appends values from @vals to the probing result
218 */
219 void blkid_probe_append_vals(blkid_probe pr, struct blkid_prval *vals, int nvals)
220 {
221 int i = 0;
222
223 while (i < nvals && pr->nvals < BLKID_NVALS) {
224 memcpy(&pr->vals[pr->nvals++], &vals[i++],
225 sizeof(struct blkid_prval));
226 }
227 }
228
229 static void blkid_probe_reset_vals(blkid_probe pr)
230 {
231 memset(pr->vals, 0, sizeof(pr->vals));
232 pr->nvals = 0;
233 }
234
235 struct blkid_chain *blkid_probe_get_chain(blkid_probe pr)
236 {
237 return pr->cur_chain;
238 }
239
240 /**
241 * blkid_reset_probe:
242 * @pr: probe
243 *
244 * Cleanup probing result. This function does not touch probing filters
245 * and keeps assigned device.
246 */
247 void blkid_reset_probe(blkid_probe pr)
248 {
249 int i;
250
251 if (!pr)
252 return;
253
254 blkid_probe_reset_buffer(pr);
255 blkid_probe_reset_vals(pr);
256
257 for (i = 0; i < BLKID_NCHAINS; i++)
258 pr->chains[i].idx = -1;
259 }
260
261 /***
262 static int blkid_probe_dump_filter(blkid_probe pr, int chain)
263 {
264 struct blkid_chain *chn;
265 int i;
266
267 if (!pr || chain < 0 || chain >= BLKID_NCHAINS)
268 return -1;
269
270 chn = &pr->chains[chain];
271
272 if (!chn->fltr)
273 return -1;
274
275 for (i = 0; i < chn->driver->nidinfos; i++) {
276 const struct blkid_idinfo *id = chn->driver->idinfos[i];
277
278 DBG(DEBUG_LOWPROBE, printf("%d: %s: %s\n",
279 i,
280 id->name,
281 blkid_bmp_get_item(chn->fltr, i)
282 ? "disabled" : "enabled <--"));
283 }
284 return 0;
285 }
286 ***/
287
288 /*
289 * Returns properly initialized chain filter
290 */
291 unsigned long *blkid_probe_get_filter(blkid_probe pr, int chain, int create)
292 {
293 struct blkid_chain *chn;
294
295 if (!pr || chain < 0 || chain >= BLKID_NCHAINS)
296 return NULL;
297
298 chn = &pr->chains[chain];
299
300 /* always when you touch the chain filter all indexes are reseted and
301 * probing starts from scratch
302 */
303 chn->idx = -1;
304 pr->cur_chain = NULL;
305
306 if (!chn->driver->has_fltr || (!chn->fltr && !create))
307 return NULL;
308
309 if (!chn->fltr)
310 chn->fltr = calloc(1, blkid_bmp_nbytes(chn->driver->nidinfos));
311 else
312 memset(chn->fltr, 0, blkid_bmp_nbytes(chn->driver->nidinfos));
313
314 /* blkid_probe_dump_filter(pr, chain); */
315 return chn->fltr;
316 }
317
318 /*
319 * Generic private functions for filter setting
320 */
321 int __blkid_probe_invert_filter(blkid_probe pr, int chain)
322 {
323 int i;
324 struct blkid_chain *chn;
325 unsigned long *fltr;
326
327 fltr = blkid_probe_get_filter(pr, chain, FALSE);
328 if (!fltr)
329 return -1;
330
331 chn = &pr->chains[chain];
332
333 for (i = 0; i < blkid_bmp_nwords(chn->driver->nidinfos); i++)
334 fltr[i] = ~fltr[i];
335
336 DBG(DEBUG_LOWPROBE, printf("probing filter inverted\n"));
337 /* blkid_probe_dump_filter(pr, chain); */
338 return 0;
339 }
340
341 int __blkid_probe_reset_filter(blkid_probe pr, int chain)
342 {
343 return blkid_probe_get_filter(pr, chain, FALSE) ? 0 : -1;
344 }
345
346 int __blkid_probe_filter_types(blkid_probe pr, int chain, int flag, char *names[])
347 {
348 unsigned long *fltr;
349 struct blkid_chain *chn;
350 int i;
351
352 fltr = blkid_probe_get_filter(pr, chain, TRUE);
353 if (!fltr)
354 return -1;
355
356 chn = &pr->chains[chain];
357
358 for (i = 0; i < chn->driver->nidinfos; i++) {
359 int has = 0;
360 const struct blkid_idinfo *id = chn->driver->idinfos[i];
361 char **n;
362
363 for (n = names; *n; n++) {
364 if (!strcmp(id->name, *n)) {
365 has = 1;
366 break;
367 }
368 }
369 if (flag & BLKID_FLTR_ONLYIN) {
370 if (!has)
371 blkid_bmp_set_item(fltr, i);
372 } else if (flag & BLKID_FLTR_NOTIN) {
373 if (has)
374 blkid_bmp_set_item(fltr, i);
375 }
376 }
377
378 DBG(DEBUG_LOWPROBE,
379 printf("%s: a new probing type-filter initialized\n",
380 chn->driver->name));
381 /* blkid_probe_dump_filter(pr, chain); */
382 return 0;
383 }
384
385 /*
386 * Note that we have two offsets:
387 *
388 * 1/ general device offset (pr->off), that's useful for example when we
389 * probe a partition from whole disk image:
390 * blkid-low --offset <partition_position> disk.img
391 *
392 * 2/ buffer offset (the 'off' argument), that useful for offsets in
393 * superbloks, ...
394 *
395 * That means never use lseek(fd, 0, SEEK_SET), the zero position is always
396 * pr->off, so lseek(fd, pr->off, SEEK_SET).
397 *
398 */
399 unsigned char *blkid_probe_get_buffer(blkid_probe pr,
400 blkid_loff_t off, blkid_loff_t len)
401 {
402 ssize_t ret_read = 0;
403
404 if (off < 0 || len < 0) {
405 DBG(DEBUG_LOWPROBE,
406 printf("unexpected offset or length of buffer requested\n"));
407 return NULL;
408 }
409 if (off + len <= BLKID_SB_BUFSIZ) {
410 if (!pr->sbbuf) {
411 pr->sbbuf = malloc(BLKID_SB_BUFSIZ);
412 if (!pr->sbbuf)
413 return NULL;
414 }
415 if (!pr->sbbuf_len) {
416 if (lseek(pr->fd, pr->off, SEEK_SET) < 0)
417 return NULL;
418 ret_read = read(pr->fd, pr->sbbuf, BLKID_SB_BUFSIZ);
419 if (ret_read < 0)
420 ret_read = 0;
421 pr->sbbuf_len = ret_read;
422 }
423 if (off + len > pr->sbbuf_len)
424 return NULL;
425 return pr->sbbuf + off;
426 } else {
427 unsigned char *newbuf = NULL;
428
429 if (len > pr->buf_max) {
430 newbuf = realloc(pr->buf, len);
431 if (!newbuf)
432 return NULL;
433 pr->buf = newbuf;
434 pr->buf_max = len;
435 pr->buf_off = 0;
436 pr->buf_len = 0;
437 }
438 if (newbuf || off < pr->buf_off ||
439 off + len > pr->buf_off + pr->buf_len) {
440
441 if (blkid_llseek(pr->fd, pr->off + off, SEEK_SET) < 0)
442 return NULL;
443
444 ret_read = read(pr->fd, pr->buf, len);
445 if (ret_read != (ssize_t) len)
446 return NULL;
447 pr->buf_off = off;
448 pr->buf_len = len;
449 }
450 return off ? pr->buf + (off - pr->buf_off) : pr->buf;
451 }
452 }
453
454 /**
455 * blkid_probe_set_device:
456 * @pr: probe
457 * @fd: device file descriptor
458 * @off: begin of probing area
459 * @size: size of probing area
460 *
461 * Assigns the device to probe control struct, resets internal buffers and
462 * reads 512 bytes from device to the buffers.
463 *
464 * Returns: -1 in case of failure, or 0 on success.
465 */
466 int blkid_probe_set_device(blkid_probe pr, int fd,
467 blkid_loff_t off, blkid_loff_t size)
468 {
469 if (!pr)
470 return -1;
471
472 blkid_reset_probe(pr);
473
474 pr->fd = fd;
475 pr->off = off;
476 pr->size = 0;
477 pr->devno = 0;
478 pr->mode = 0;
479 pr->blkssz = 0;
480
481 if (size)
482 pr->size = size;
483 else {
484 struct stat sb;
485
486 if (fstat(fd, &sb))
487 return -1;
488
489 pr->mode = sb.st_mode;
490
491 if (S_ISBLK(sb.st_mode)) {
492 blkdev_get_size(fd, (unsigned long long *) &pr->size);
493 pr->devno = sb.st_rdev;
494 } else
495 pr->size = sb.st_size;
496 }
497 if (!pr->size)
498 return -1;
499
500 /* read SB to test if the device is readable */
501 if (!blkid_probe_get_buffer(pr, 0, 0x200)) {
502 DBG(DEBUG_LOWPROBE,
503 printf("failed to prepare a device for low-probing\n"));
504 return -1;
505 }
506
507 DBG(DEBUG_LOWPROBE, printf("ready for low-probing, offset=%zd, size=%zd\n",
508 pr->off, pr->size));
509 return 0;
510 }
511
512 /**
513 * blkid_do_probe:
514 * @pr: prober
515 *
516 * Calls probing functions in all enabled chains. The superblocks chain is
517 * enabled by default. The blkid_do_probe() stores result from only one
518 * probing function. It's necessary to call this routine in a loop to get
519 * resuluts from all probing functions in all chains.
520 *
521 * This is string-based NAME=value interface only.
522 *
523 * <example>
524 * <title>basic case - use the first result only</title>
525 * <programlisting>
526 *
527 * if (blkid_do_probe(pr) == 0) {
528 * int nvals = blkid_probe_numof_values(pr);
529 * for (n = 0; n < nvals; n++) {
530 * if (blkid_probe_get_value(pr, n, &name, &data, &len) == 0)
531 * printf("%s = %s\n", name, data);
532 * }
533 * }
534 * </programlisting>
535 * </example>
536 *
537 * <example>
538 * <title>advanced case - probe for all signatures</title>
539 * <programlisting>
540 *
541 * while (blkid_do_probe(pr) == 0) {
542 * int nvals = blkid_probe_numof_values(pr);
543 * ...
544 * }
545 * </programlisting>
546 * </example>
547 *
548 * See also blkid_reset_probe().
549 *
550 * Returns: 0 on success, 1 when probing is done and -1 in case of error.
551 */
552 int blkid_do_probe(blkid_probe pr)
553 {
554 int rc = 1;
555
556 if (!pr)
557 return -1;
558
559 do {
560 struct blkid_chain *chn;
561
562 if (!pr->cur_chain)
563 pr->cur_chain = &pr->chains[0];
564 else if (pr->cur_chain < &pr->chains[BLKID_NCHAINS - 1])
565 pr->cur_chain += sizeof(struct blkid_chain);
566 else
567 return 1; /* all chains already probed */
568
569 chn = pr->cur_chain;
570 chn->binary = FALSE; /* for sure... */
571
572 DBG(DEBUG_LOWPROBE, printf("chain probe %s %s\n",
573 chn->driver->name,
574 chn->enabled? "ENABLED" : "DISABLED"));
575
576 if (!chn->enabled)
577 continue;
578
579 /* rc: -1 = error, 0 = success, 1 = no result */
580 rc = chn->driver->probe(pr, chn);
581
582 } while (rc == 1);
583
584 return rc;
585 }
586
587 /**
588 * blkid_do_safeprobe:
589 * @pr: prober
590 *
591 * This function gathers probing results from all enabled chains and checks
592 * for ambivalent results (e.g. more filesystems on the device).
593 *
594 * This is string-based NAME=value interface only.
595 *
596 * Note about suberblocks chain -- the function does not check for filesystems
597 * when a RAID signature is detected. The function also does not check for
598 * collision between RAIDs. The first detected RAID is returned.
599 *
600 * Returns: 0 on success, 1 if nothing is detected, -2 if ambivalen result is
601 * detected and -1 on case of error.
602 */
603 int blkid_do_safeprobe(blkid_probe pr)
604 {
605 int i, count = 0, rc = 0;
606
607 if (!pr)
608 return -1;
609
610 for (i = 0; i < BLKID_NCHAINS; i++) {
611 struct blkid_chain *chn;
612
613 chn = pr->cur_chain = &pr->chains[i];
614 chn->binary = FALSE; /* for sure... */
615
616 DBG(DEBUG_LOWPROBE, printf("chain safeprobe %s %s\n",
617 chn->driver->name,
618 chn->enabled? "ENABLED" : "DISABLED"));
619
620 if (!chn->enabled)
621 continue;
622
623 chn->idx = - 1;
624
625 /* rc: -2 ambivalent, -1 = error, 0 = success, 1 = no result */
626 rc = chn->driver->safeprobe(pr, chn);
627 if (rc < 0)
628 goto done; /* error */
629 if (rc == 0)
630 count++; /* success */
631 }
632
633 done:
634 pr->cur_chain = NULL;
635 if (rc < 0)
636 return rc;
637 return count ? 0 : 1;
638 }
639
640 /**
641 * blkid_do_fullprobe:
642 * @pr: prober
643 *
644 * This function gathers probing results from all enabled chains. Same as
645 * blkid_so_safeprobe() but does not check for collision between probing
646 * result.
647 *
648 * This is string-based NAME=value interface only.
649 *
650 * Returns: 0 on success, 1 if nothing is detected or -1 on case of error.
651 */
652 int blkid_do_fullprobe(blkid_probe pr)
653 {
654 int i, count = 0, rc = 0;
655
656 if (!pr)
657 return -1;
658
659 for (i = 0; i < BLKID_NCHAINS; i++) {
660 int rc;
661 struct blkid_chain *chn;
662
663 chn = pr->cur_chain = &pr->chains[i];
664 chn->binary = FALSE; /* for sure... */
665
666 DBG(DEBUG_LOWPROBE, printf("chain fullprobe %s: %s\n",
667 chn->driver->name,
668 chn->enabled? "ENABLED" : "DISABLED"));
669
670 if (!chn->enabled)
671 continue;
672
673 chn->idx = - 1;
674
675 /* rc: -1 = error, 0 = success, 1 = no result */
676 rc = chn->driver->probe(pr, chn);
677 if (rc < 0)
678 goto done; /* error */
679 if (rc == 0)
680 count++; /* success */
681 }
682
683 done:
684 pr->cur_chain = NULL;
685 if (rc < 0)
686 return rc;
687 return count ? 0 : 1;
688 }
689
690 struct blkid_prval *blkid_probe_assign_value(
691 blkid_probe pr, const char *name)
692 {
693 struct blkid_prval *v;
694
695 if (!name)
696 return NULL;
697 if (pr->nvals >= BLKID_NVALS)
698 return NULL;
699
700 v = &pr->vals[pr->nvals];
701 v->name = name;
702 v->chain = pr->cur_chain;
703 pr->nvals++;
704
705 DBG(DEBUG_LOWPROBE,
706 printf("assigning %s [%s]\n", name, v->chain->driver->name));
707 return v;
708 }
709
710 int blkid_probe_set_value(blkid_probe pr, const char *name,
711 unsigned char *data, size_t len)
712 {
713 struct blkid_prval *v;
714
715 if (len > BLKID_PROBVAL_BUFSIZ)
716 len = BLKID_PROBVAL_BUFSIZ;
717
718 v = blkid_probe_assign_value(pr, name);
719 if (!v)
720 return -1;
721
722 memcpy(v->data, data, len);
723 v->len = len;
724 return 0;
725 }
726
727 int blkid_probe_vsprintf_value(blkid_probe pr, const char *name,
728 const char *fmt, va_list ap)
729 {
730 struct blkid_prval *v;
731 size_t len;
732
733 v = blkid_probe_assign_value(pr, name);
734 if (!v)
735 return -1;
736
737 len = vsnprintf((char *) v->data, sizeof(v->data), fmt, ap);
738
739 if (len <= 0) {
740 pr->nvals--; /* reset the latest assigned value */
741 return -1;
742 }
743 v->len = len + 1;
744 return 0;
745 }
746
747 /**
748 * blkid_probe_numof_values:
749 * @pr: probe
750 *
751 * Returns: number of values in probing result or -1 in case of error.
752 */
753 int blkid_probe_numof_values(blkid_probe pr)
754 {
755 if (!pr)
756 return -1;
757 return pr->nvals;
758 }
759
760 /**
761 * blkid_probe_get_value:
762 * @pr: probe
763 * @num: wanted value in range 0..N, where N is blkid_probe_numof_values() - 1
764 * @name: pointer to return value name or NULL
765 * @data: pointer to return value data or NULL
766 * @len: pointer to return value length or NULL
767 *
768 * Returns: 0 on success, or -1 in case of error.
769 */
770 int blkid_probe_get_value(blkid_probe pr, int num, const char **name,
771 const char **data, size_t *len)
772 {
773 struct blkid_prval *v = __blkid_probe_get_value(pr, num);
774
775 if (!v)
776 return -1;
777 if (name)
778 *name = v->name;
779 if (data)
780 *data = (char *) v->data;
781 if (len)
782 *len = v->len;
783
784 DBG(DEBUG_LOWPROBE, printf("returning %s value\n", v->name));
785 return 0;
786 }
787
788 /**
789 * blkid_probe_lookup_value:
790 * @pr: probe
791 * @name: name of value
792 * @data: pointer to return value data or NULL
793 * @len: pointer to return value length or NULL
794 *
795 * Returns: 0 on success, or -1 in case of error.
796 */
797 int blkid_probe_lookup_value(blkid_probe pr, const char *name,
798 const char **data, size_t *len)
799 {
800 struct blkid_prval *v = __blkid_probe_lookup_value(pr, name);
801
802 if (!v)
803 return -1;
804 if (data)
805 *data = (char *) v->data;
806 if (len)
807 *len = v->len;
808 DBG(DEBUG_LOWPROBE, printf("returning %s value\n", v->name));
809 return 0;
810 }
811
812 /**
813 * blkid_probe_has_value:
814 * @pr: probe
815 * @name: name of value
816 *
817 * Returns: 1 if value exist in probing result, otherwise 0.
818 */
819 int blkid_probe_has_value(blkid_probe pr, const char *name)
820 {
821 if (blkid_probe_lookup_value(pr, name, NULL, NULL) == 0)
822 return 1;
823 return 0;
824 }
825
826 struct blkid_prval *__blkid_probe_get_value(blkid_probe pr, int num)
827 {
828 if (pr == NULL || num < 0 || num >= pr->nvals)
829 return NULL;
830
831 return &pr->vals[num];
832 }
833
834 struct blkid_prval *__blkid_probe_lookup_value(blkid_probe pr, const char *name)
835 {
836 int i;
837
838 if (pr == NULL || pr->nvals == 0 || name == NULL)
839 return NULL;
840
841 for (i = 0; i < pr->nvals; i++) {
842 struct blkid_prval *v = &pr->vals[i];
843
844 if (v->name && strcmp(name, v->name) == 0) {
845 DBG(DEBUG_LOWPROBE, printf("returning %s value\n", v->name));
846 return v;
847 }
848 }
849 return NULL;
850 }
851
852
853 /* converts DCE UUID (uuid[16]) to human readable string
854 * - the @len should be always 37 */
855 void blkid_unparse_uuid(const unsigned char *uuid, char *str, size_t len)
856 {
857 #ifdef HAVE_LIBUUID
858 uuid_unparse(uuid, str);
859 #else
860 snprintf(str, len,
861 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
862 uuid[0], uuid[1], uuid[2], uuid[3],
863 uuid[4], uuid[5],
864 uuid[6], uuid[7],
865 uuid[8], uuid[9],
866 uuid[10], uuid[11], uuid[12], uuid[13], uuid[14],uuid[15]);
867 #endif
868 }
869