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