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