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