]> git.ipfire.org Git - thirdparty/util-linux.git/blob - shlibs/blkid/src/probe.c
libblkid: probe for (non-linux) RAIDs on whole devices only
[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 library 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 * Note that the previous probing result (binary or NAME=value) is always
39 * zeroized when a chain probing function is called. For example
40 *
41 * <informalexample>
42 * <programlisting>
43 * blkid_probe_enable_partitions(pr, TRUE);
44 * blkid_probe_enable_superblocks(pr, FALSE);
45 *
46 * blkid_do_safeprobe(pr);
47 * </programlisting>
48 * </informalexample>
49 *
50 * overwrites the previous probing result for the partitions chain, the superblocks
51 * result is not modified.
52 */
53
54 /**
55 * SECTION: lowprobe-tags
56 * @title: Low-level tags
57 * @short_description: generic NAME=value interface.
58 *
59 * The probing routines inside the chain are mutually exclusive by default --
60 * only few probing routines are marked as "tolerant". The "tolerant" probing
61 * routines are used for filesystem which can share the same device with any
62 * other filesystem. The blkid_do_safeprobe() checks for the "tolerant" flag.
63 *
64 * The SUPERBLOCKS chain is enabled by default. The all others chains is
65 * necessary to enable by blkid_probe_enable_'CHAINNAME'(). See chains specific
66 * documentation.
67 *
68 * The blkid_do_probe() function returns a result from only one probing
69 * routine, and the next call from the next probing routine. It means you need
70 * to call the function in loop, for example:
71 *
72 * <informalexample>
73 * <programlisting>
74 * while((blkid_do_probe(pr) == 0)
75 * ... use result ...
76 * </programlisting>
77 * </informalexample>
78 *
79 * The blkid_do_safeprobe() is the same as blkid_do_probe(), but returns only
80 * first probing result for every enabled chain. This function checks for
81 * ambivalent results (e.g. more "intolerant" filesystems superblocks on the
82 * device).
83 *
84 * The probing result is set of NAME=value pairs (the NAME is always unique).
85 */
86
87 #include <stdio.h>
88 #include <string.h>
89 #include <stdlib.h>
90 #include <unistd.h>
91 #include <fcntl.h>
92 #include <ctype.h>
93 #include <sys/types.h>
94 #ifdef HAVE_LINUX_CDROM_H
95 #include <linux/cdrom.h>
96 #endif
97 #ifdef HAVE_SYS_STAT_H
98 #include <sys/stat.h>
99 #endif
100 #ifdef HAVE_SYS_MKDEV_H
101 #include <sys/mkdev.h>
102 #endif
103 #ifdef HAVE_ERRNO_H
104 #include <errno.h>
105 #endif
106 #include <inttypes.h>
107 #include <stdint.h>
108 #include <stdarg.h>
109
110 #ifdef HAVE_LIBUUID
111 # ifdef HAVE_UUID_UUID_H
112 # include <uuid/uuid.h>
113 # else
114 # include <uuid.h>
115 # endif
116 #endif
117
118 #include "blkdev.h"
119 #include "blkidP.h"
120
121 /* chains */
122 extern const struct blkid_chaindrv superblocks_drv;
123 extern const struct blkid_chaindrv topology_drv;
124 extern const struct blkid_chaindrv partitions_drv;
125
126 /*
127 * All supported chains
128 */
129 static const struct blkid_chaindrv *chains_drvs[] = {
130 [BLKID_CHAIN_SUBLKS] = &superblocks_drv,
131 [BLKID_CHAIN_TOPLGY] = &topology_drv,
132 [BLKID_CHAIN_PARTS] = &partitions_drv
133 };
134
135 static void blkid_probe_reset_vals(blkid_probe pr);
136 static void blkid_probe_reset_buffer(blkid_probe pr);
137
138 /**
139 * blkid_new_probe:
140 *
141 * Returns: a pointer to the newly allocated probe struct.
142 */
143 blkid_probe blkid_new_probe(void)
144 {
145 int i;
146 blkid_probe pr;
147
148 blkid_init_debug(0);
149 pr = calloc(1, sizeof(struct blkid_struct_probe));
150 if (!pr)
151 return NULL;
152
153 /* initialize chains */
154 for (i = 0; i < BLKID_NCHAINS; i++) {
155 pr->chains[i].driver = chains_drvs[i];
156 pr->chains[i].flags = chains_drvs[i]->dflt_flags;
157 pr->chains[i].enabled = chains_drvs[i]->dflt_enabled;
158 }
159 INIT_LIST_HEAD(&pr->buffers);
160 return pr;
161 }
162
163 /**
164 * blkid_new_probe_from_filename:
165 * @filename: device or regular file
166 *
167 * This function is same as call open(filename), blkid_new_probe() and
168 * blkid_probe_set_device(pr, fd, 0, 0).
169 *
170 * The @filename is closed by blkid_free_probe() or by the
171 * blkid_probe_set_device() call.
172 *
173 * Returns: a pointer to the newly allocated probe struct or NULL in case of
174 * error.
175 */
176 blkid_probe blkid_new_probe_from_filename(const char *filename)
177 {
178 int fd = -1;
179 blkid_probe pr = NULL;
180
181 if (!filename)
182 return NULL;
183
184 fd = open(filename, O_RDONLY);
185 if (fd < 0)
186 return NULL;
187
188 pr = blkid_new_probe();
189 if (!pr)
190 goto err;
191
192 if (blkid_probe_set_device(pr, fd, 0, 0))
193 goto err;
194
195 pr->flags |= BLKID_PRIVATE_FD;
196 return pr;
197 err:
198 if (fd >= 0)
199 close(fd);
200 blkid_free_probe(pr);
201 return NULL;
202 }
203
204 /**
205 * blkid_free_probe:
206 * @pr: probe
207 *
208 * Deallocates the probe struct, buffers and all allocated
209 * data that are associated with this probing control struct.
210 */
211 void blkid_free_probe(blkid_probe pr)
212 {
213 int i;
214
215 if (!pr)
216 return;
217
218 for (i = 0; i < BLKID_NCHAINS; i++) {
219 struct blkid_chain *ch = &pr->chains[i];
220
221 if (ch->driver->free_data)
222 ch->driver->free_data(pr, ch->data);
223 free(ch->fltr);
224 }
225
226 if ((pr->flags & BLKID_PRIVATE_FD) && pr->fd >= 0)
227 close(pr->fd);
228 blkid_probe_reset_buffer(pr);
229 free(pr);
230 }
231
232
233 /*
234 * Removes chain values from probing result.
235 */
236 void blkid_probe_chain_reset_vals(blkid_probe pr, struct blkid_chain *chn)
237 {
238 int nvals = pr->nvals;
239 int i, x;
240
241 for (x = 0, i = 0; i < pr->nvals; i++) {
242 struct blkid_prval *v = &pr->vals[i];
243
244 if (v->chain != chn && x == i) {
245 x++;
246 continue;
247 }
248 if (v->chain == chn) {
249 --nvals;
250 continue;
251 }
252 memcpy(&pr->vals[x++], v, sizeof(struct blkid_prval));
253 }
254 pr->nvals = nvals;
255 }
256
257 static void blkid_probe_chain_reset_position(struct blkid_chain *chn)
258 {
259 if (chn)
260 chn->idx = -1;
261 }
262
263 /*
264 * Copies chain values from probing result to @vals, the max size of @vals is
265 * @nvals and returns real number of values.
266 */
267 int blkid_probe_chain_copy_vals(blkid_probe pr, struct blkid_chain *chn,
268 struct blkid_prval *vals, int nvals)
269 {
270 int i, x;
271
272 for (x = 0, i = 0; i < pr->nvals && x < nvals; i++) {
273 struct blkid_prval *v = &pr->vals[i];
274
275 if (v->chain != chn)
276 continue;
277 memcpy(&vals[x++], v, sizeof(struct blkid_prval));
278 }
279 return x;
280 }
281
282 /*
283 * Appends values from @vals to the probing result
284 */
285 void blkid_probe_append_vals(blkid_probe pr, struct blkid_prval *vals, int nvals)
286 {
287 int i = 0;
288
289 while (i < nvals && pr->nvals < BLKID_NVALS) {
290 memcpy(&pr->vals[pr->nvals++], &vals[i++],
291 sizeof(struct blkid_prval));
292 }
293 }
294
295 static void blkid_probe_reset_vals(blkid_probe pr)
296 {
297 memset(pr->vals, 0, sizeof(pr->vals));
298 pr->nvals = 0;
299 }
300
301 struct blkid_chain *blkid_probe_get_chain(blkid_probe pr)
302 {
303 return pr->cur_chain;
304 }
305
306 void *blkid_probe_get_binary_data(blkid_probe pr, struct blkid_chain *chn)
307 {
308 int rc, org_prob_flags;
309 struct blkid_chain *org_chn;
310
311 if (!pr || !chn)
312 return NULL;
313
314 /* save the current setting -- the binary API has to be completely
315 * independent on the current probing status
316 */
317 org_chn = pr->cur_chain;
318 org_prob_flags = pr->prob_flags;
319
320 pr->cur_chain = chn;
321 pr->prob_flags = 0;
322 chn->binary = TRUE;
323 blkid_probe_chain_reset_position(chn);
324
325 rc = chn->driver->probe(pr, chn);
326
327 chn->binary = FALSE;
328 blkid_probe_chain_reset_position(chn);
329
330 /* restore the original setting
331 */
332 pr->cur_chain = org_chn;
333 pr->prob_flags = org_prob_flags;
334
335 if (rc != 0)
336 return NULL;
337
338 DBG(DEBUG_LOWPROBE,
339 printf("returning %s binary data\n", chn->driver->name));
340 return chn->data;
341 }
342
343
344 /**
345 * blkid_reset_probe:
346 * @pr: probe
347 *
348 * Zeroize probing results and resets the current probing (this has impact to
349 * blkid_do_probe() only). This function does not touch probing filters and
350 * keeps assigned device.
351 */
352 void blkid_reset_probe(blkid_probe pr)
353 {
354 int i;
355
356 if (!pr)
357 return;
358
359 blkid_probe_reset_buffer(pr);
360 blkid_probe_reset_vals(pr);
361
362 pr->cur_chain = NULL;
363
364 for (i = 0; i < BLKID_NCHAINS; i++)
365 blkid_probe_chain_reset_position(&pr->chains[i]);
366 }
367
368 /***
369 static int blkid_probe_dump_filter(blkid_probe pr, int chain)
370 {
371 struct blkid_chain *chn;
372 int i;
373
374 if (!pr || chain < 0 || chain >= BLKID_NCHAINS)
375 return -1;
376
377 chn = &pr->chains[chain];
378
379 if (!chn->fltr)
380 return -1;
381
382 for (i = 0; i < chn->driver->nidinfos; i++) {
383 const struct blkid_idinfo *id = chn->driver->idinfos[i];
384
385 DBG(DEBUG_LOWPROBE, printf("%d: %s: %s\n",
386 i,
387 id->name,
388 blkid_bmp_get_item(chn->fltr, i)
389 ? "disabled" : "enabled <--"));
390 }
391 return 0;
392 }
393 ***/
394
395 /*
396 * Returns properly initialized chain filter
397 */
398 unsigned long *blkid_probe_get_filter(blkid_probe pr, int chain, int create)
399 {
400 struct blkid_chain *chn;
401
402 if (!pr || chain < 0 || chain >= BLKID_NCHAINS)
403 return NULL;
404
405 chn = &pr->chains[chain];
406
407 /* always when you touch the chain filter all indexes are reseted and
408 * probing starts from scratch
409 */
410 blkid_probe_chain_reset_position(chn);
411 pr->cur_chain = NULL;
412
413 if (!chn->driver->has_fltr || (!chn->fltr && !create))
414 return NULL;
415
416 if (!chn->fltr)
417 chn->fltr = calloc(1, blkid_bmp_nbytes(chn->driver->nidinfos));
418 else
419 memset(chn->fltr, 0, blkid_bmp_nbytes(chn->driver->nidinfos));
420
421 /* blkid_probe_dump_filter(pr, chain); */
422 return chn->fltr;
423 }
424
425 /*
426 * Generic private functions for filter setting
427 */
428 int __blkid_probe_invert_filter(blkid_probe pr, int chain)
429 {
430 int i;
431 struct blkid_chain *chn;
432 unsigned long *fltr;
433
434 fltr = blkid_probe_get_filter(pr, chain, FALSE);
435 if (!fltr)
436 return -1;
437
438 chn = &pr->chains[chain];
439
440 for (i = 0; i < blkid_bmp_nwords(chn->driver->nidinfos); i++)
441 fltr[i] = ~fltr[i];
442
443 DBG(DEBUG_LOWPROBE, printf("probing filter inverted\n"));
444 /* blkid_probe_dump_filter(pr, chain); */
445 return 0;
446 }
447
448 int __blkid_probe_reset_filter(blkid_probe pr, int chain)
449 {
450 return blkid_probe_get_filter(pr, chain, FALSE) ? 0 : -1;
451 }
452
453 int __blkid_probe_filter_types(blkid_probe pr, int chain, int flag, char *names[])
454 {
455 unsigned long *fltr;
456 struct blkid_chain *chn;
457 int i;
458
459 fltr = blkid_probe_get_filter(pr, chain, TRUE);
460 if (!fltr)
461 return -1;
462
463 chn = &pr->chains[chain];
464
465 for (i = 0; i < chn->driver->nidinfos; i++) {
466 int has = 0;
467 const struct blkid_idinfo *id = chn->driver->idinfos[i];
468 char **n;
469
470 for (n = names; *n; n++) {
471 if (!strcmp(id->name, *n)) {
472 has = 1;
473 break;
474 }
475 }
476 if (flag & BLKID_FLTR_ONLYIN) {
477 if (!has)
478 blkid_bmp_set_item(fltr, i);
479 } else if (flag & BLKID_FLTR_NOTIN) {
480 if (has)
481 blkid_bmp_set_item(fltr, i);
482 }
483 }
484
485 DBG(DEBUG_LOWPROBE,
486 printf("%s: a new probing type-filter initialized\n",
487 chn->driver->name));
488 /* blkid_probe_dump_filter(pr, chain); */
489 return 0;
490 }
491
492 unsigned char *blkid_probe_get_buffer(blkid_probe pr,
493 blkid_loff_t off, blkid_loff_t len)
494 {
495 struct list_head *p;
496 struct blkid_bufinfo *bf = NULL;
497
498 if (pr->size <= 0)
499 return NULL;
500
501 list_for_each(p, &pr->buffers) {
502 struct blkid_bufinfo *x =
503 list_entry(p, struct blkid_bufinfo, bufs);
504
505 if (x->off <= off && off + len <= x->off + x->len) {
506 DBG(DEBUG_LOWPROBE,
507 printf("\treuse buffer: off=%jd len=%jd\n",
508 x->off, x->len));
509 bf = x;
510 break;
511 }
512 }
513 if (!bf) {
514 ssize_t ret;
515
516 if (blkid_llseek(pr->fd, pr->off + off, SEEK_SET) < 0)
517 return NULL;
518
519 /* allocate info and space for data by why call */
520 bf = calloc(1, sizeof(struct blkid_bufinfo) + len);
521 if (!bf)
522 return NULL;
523
524 bf->data = ((unsigned char *) bf) + sizeof(struct blkid_bufinfo);
525 bf->len = len;
526 bf->off = off;
527 INIT_LIST_HEAD(&bf->bufs);
528
529 DBG(DEBUG_LOWPROBE,
530 printf("\tbuffer read: off=%jd len=%jd\n", off, len));
531
532 ret = read(pr->fd, bf->data, len);
533 if (ret != (ssize_t) len) {
534 free(bf);
535 return NULL;
536 }
537 list_add_tail(&bf->bufs, &pr->buffers);
538 }
539
540 return off ? bf->data + (off - bf->off) : bf->data;
541 }
542
543
544 static void blkid_probe_reset_buffer(blkid_probe pr)
545 {
546 uint64_t read_ct = 0, len_ct = 0;
547
548 if (!pr || list_empty(&pr->buffers))
549 return;
550
551 DBG(DEBUG_LOWPROBE, printf("reseting probing buffers\n"));
552
553 while (!list_empty(&pr->buffers)) {
554 struct blkid_bufinfo *bf = list_entry(pr->buffers.next,
555 struct blkid_bufinfo, bufs);
556
557 read_ct++;
558 len_ct += bf->len;
559 list_del(&bf->bufs);
560 free(bf);
561 }
562
563 DBG(DEBUG_LOWPROBE,
564 printf("buffers summary: %"PRIu64" bytes "
565 "by %"PRIu64" read() call(s)\n",
566 len_ct, read_ct));
567
568 INIT_LIST_HEAD(&pr->buffers);
569 }
570
571 /*
572 * Small devices need a special care.
573 */
574 int blkid_probe_is_tiny(blkid_probe pr)
575 {
576 return pr && (pr->flags & BLKID_TINY_DEV);
577 }
578
579 /*
580 * CDROMs may fail when probed for RAID (last sector problem)
581 */
582 int blkid_probe_is_cdrom(blkid_probe pr)
583 {
584 return pr && (pr->flags & BLKID_CDROM_DEV);
585 }
586
587 /**
588 * blkid_probe_set_device:
589 * @pr: probe
590 * @fd: device file descriptor
591 * @off: begin of probing area
592 * @size: size of probing area (zero means whole device/file)
593 *
594 * Assigns the device to probe control struct, resets internal buffers and
595 * resets the current probing.
596 *
597 * Returns: -1 in case of failure, or 0 on success.
598 */
599 int blkid_probe_set_device(blkid_probe pr, int fd,
600 blkid_loff_t off, blkid_loff_t size)
601 {
602 struct stat sb;
603
604 if (!pr)
605 return -1;
606
607 blkid_reset_probe(pr);
608
609 if ((pr->flags & BLKID_PRIVATE_FD) && pr->fd >= 0)
610 close(pr->fd);
611
612 pr->flags &= ~BLKID_PRIVATE_FD;
613 pr->flags &= ~BLKID_TINY_DEV;
614 pr->flags &= ~BLKID_CDROM_DEV;
615 pr->fd = fd;
616 pr->off = off;
617 pr->size = 0;
618 pr->devno = 0;
619 pr->mode = 0;
620 pr->blkssz = 0;
621
622 #if defined(POSIX_FADV_RANDOM) && defined(HAVE_POSIX_FADVISE)
623 /* Disable read-ahead */
624 posix_fadvise(fd, 0, 0, POSIX_FADV_RANDOM);
625 #endif
626 if (fstat(fd, &sb))
627 goto err;
628
629 pr->mode = sb.st_mode;
630 if (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode))
631 pr->devno = sb.st_rdev;
632
633 if (size)
634 pr->size = size;
635 else {
636 if (S_ISBLK(sb.st_mode)) {
637 if (blkdev_get_size(fd, (unsigned long long *) &pr->size)) {
638 DBG(DEBUG_LOWPROBE, printf(
639 "failed to get device size\n"));
640 goto err;
641 }
642 } else if (S_ISCHR(sb.st_mode))
643 pr->size = 1; /* UBI devices are char... */
644 else if (S_ISREG(sb.st_mode))
645 pr->size = sb.st_size; /* regular file */
646
647 if (pr->off > pr->size)
648 goto err;
649
650 /* The probing area cannot be larger than whole device, pr->off
651 * is offset within the device */
652 pr->size -= pr->off;
653 }
654
655 if (pr->size <= 1440 * 1024 && !S_ISCHR(sb.st_mode))
656 pr->flags |= BLKID_TINY_DEV;
657
658 #ifdef CDROM_GET_CAPABILITY
659 if (S_ISBLK(sb.st_mode) && ioctl(fd, CDROM_GET_CAPABILITY, NULL) >= 0)
660 pr->flags |= BLKID_CDROM_DEV;
661 #endif
662
663 DBG(DEBUG_LOWPROBE, printf("ready for low-probing, offset=%jd, size=%jd\n",
664 pr->off, pr->size));
665 DBG(DEBUG_LOWPROBE, printf("whole-disk: %s, regfile: %s\n",
666 blkid_probe_is_wholedisk(pr) ?"YES" : "NO",
667 S_ISREG(pr->mode) ? "YES" : "NO"));
668
669 return 0;
670 err:
671 DBG(DEBUG_LOWPROBE,
672 printf("failed to prepare a device for low-probing\n"));
673 return -1;
674
675 }
676
677 int blkid_probe_get_dimension(blkid_probe pr,
678 blkid_loff_t *off, blkid_loff_t *size)
679 {
680 if (!pr)
681 return -1;
682
683 *off = pr->off;
684 *size = pr->size;
685 return 0;
686 }
687
688 int blkid_probe_set_dimension(blkid_probe pr,
689 blkid_loff_t off, blkid_loff_t size)
690 {
691 if (!pr)
692 return -1;
693
694 DBG(DEBUG_LOWPROBE, printf(
695 "changing probing area: size=%llu, off=%llu "
696 "-to-> size=%llu, off=%llu\n",
697 (unsigned long long) pr->size,
698 (unsigned long long) pr->off,
699 (unsigned long long) size,
700 (unsigned long long) off));
701
702 pr->off = off;
703 pr->size = size;
704 pr->flags &= ~BLKID_TINY_DEV;
705
706 if (pr->size <= 1440 * 1024 && !S_ISCHR(pr->mode))
707 pr->flags |= BLKID_TINY_DEV;
708
709 blkid_probe_reset_buffer(pr);
710
711 return 0;
712 }
713
714 static inline void blkid_probe_start(blkid_probe pr)
715 {
716 if (pr) {
717 pr->cur_chain = NULL;
718 pr->prob_flags = 0;
719 }
720 }
721
722 static inline void blkid_probe_end(blkid_probe pr)
723 {
724 if (pr) {
725 pr->cur_chain = NULL;
726 pr->prob_flags = 0;
727 }
728 }
729
730 /**
731 * blkid_do_probe:
732 * @pr: prober
733 *
734 * Calls probing functions in all enabled chains. The superblocks chain is
735 * enabled by default. The blkid_do_probe() stores result from only one
736 * probing function. It's necessary to call this routine in a loop to get
737 * results from all probing functions in all chains. The probing is reseted
738 * by blkid_reset_probe() or by filter functions.
739 *
740 * This is string-based NAME=value interface only.
741 *
742 * <example>
743 * <title>basic case - use the first result only</title>
744 * <programlisting>
745 *
746 * if (blkid_do_probe(pr) == 0) {
747 * int nvals = blkid_probe_numof_values(pr);
748 * for (n = 0; n < nvals; n++) {
749 * if (blkid_probe_get_value(pr, n, &name, &data, &len) == 0)
750 * printf("%s = %s\n", name, data);
751 * }
752 * }
753 * </programlisting>
754 * </example>
755 *
756 * <example>
757 * <title>advanced case - probe for all signatures</title>
758 * <programlisting>
759 *
760 * while (blkid_do_probe(pr) == 0) {
761 * int nvals = blkid_probe_numof_values(pr);
762 * ...
763 * }
764 * </programlisting>
765 * </example>
766 *
767 * See also blkid_reset_probe().
768 *
769 * Returns: 0 on success, 1 when probing is done and -1 in case of error.
770 */
771 int blkid_do_probe(blkid_probe pr)
772 {
773 int rc = 1;
774
775 if (!pr)
776 return -1;
777
778 do {
779 struct blkid_chain *chn = pr->cur_chain;
780
781 if (!chn) {
782 blkid_probe_start(pr);
783 chn = pr->cur_chain = &pr->chains[0];
784 }
785 /* we go to the next chain only when the previous probing
786 * result was nothing (rc == 1) and when the current chain is
787 * disabled or we are at end of the current chain (chain->idx +
788 * 1 == sizeof chain) or the current chain bailed out right at
789 * the start (chain->idx == -1)
790 */
791 else if (rc == 1 && (chn->enabled == FALSE ||
792 chn->idx + 1 == chn->driver->nidinfos ||
793 chn->idx == -1)) {
794
795 int idx = chn->driver->id + 1;
796
797 if (idx < BLKID_NCHAINS)
798 chn = pr->cur_chain = &pr->chains[idx];
799 else {
800 blkid_probe_end(pr);
801 return 1; /* all chains already probed */
802 }
803 }
804
805 chn->binary = FALSE; /* for sure... */
806
807 DBG(DEBUG_LOWPROBE, printf("chain probe %s %s (idx=%d)\n",
808 chn->driver->name,
809 chn->enabled? "ENABLED" : "DISABLED",
810 chn->idx));
811
812 if (!chn->enabled)
813 continue;
814
815 /* rc: -1 = error, 0 = success, 1 = no result */
816 rc = chn->driver->probe(pr, chn);
817
818 } while (rc == 1);
819
820 return rc;
821 }
822
823 /**
824 * blkid_do_safeprobe:
825 * @pr: prober
826 *
827 * This function gathers probing results from all enabled chains and checks
828 * for ambivalent results (e.g. more filesystems on the device).
829 *
830 * This is string-based NAME=value interface only.
831 *
832 * Note about suberblocks chain -- the function does not check for filesystems
833 * when a RAID signature is detected. The function also does not check for
834 * collision between RAIDs. The first detected RAID is returned. The function
835 * checks for collision between partition table and RAID signature -- it's
836 * recommended to enable partitions chain together with superblocks chain.
837 *
838 * Returns: 0 on success, 1 if nothing is detected, -2 if ambivalen result is
839 * detected and -1 on case of error.
840 */
841 int blkid_do_safeprobe(blkid_probe pr)
842 {
843 int i, count = 0, rc = 0;
844
845 if (!pr)
846 return -1;
847
848 blkid_probe_start(pr);
849
850 for (i = 0; i < BLKID_NCHAINS; i++) {
851 struct blkid_chain *chn;
852
853 chn = pr->cur_chain = &pr->chains[i];
854 chn->binary = FALSE; /* for sure... */
855
856 DBG(DEBUG_LOWPROBE, printf("chain safeprobe %s %s\n",
857 chn->driver->name,
858 chn->enabled? "ENABLED" : "DISABLED"));
859
860 if (!chn->enabled)
861 continue;
862
863 blkid_probe_chain_reset_position(chn);
864
865 rc = chn->driver->safeprobe(pr, chn);
866
867 blkid_probe_chain_reset_position(chn);
868
869 /* rc: -2 ambivalent, -1 = error, 0 = success, 1 = no result */
870 if (rc < 0)
871 goto done; /* error */
872 if (rc == 0)
873 count++; /* success */
874 }
875
876 done:
877 blkid_probe_end(pr);
878 if (rc < 0)
879 return rc;
880 return count ? 0 : 1;
881 }
882
883 /**
884 * blkid_do_fullprobe:
885 * @pr: prober
886 *
887 * This function gathers probing results from all enabled chains. Same as
888 * blkid_so_safeprobe() but does not check for collision between probing
889 * result.
890 *
891 * This is string-based NAME=value interface only.
892 *
893 * Returns: 0 on success, 1 if nothing is detected or -1 on case of error.
894 */
895 int blkid_do_fullprobe(blkid_probe pr)
896 {
897 int i, count = 0, rc = 0;
898
899 if (!pr)
900 return -1;
901
902 blkid_probe_start(pr);
903
904 for (i = 0; i < BLKID_NCHAINS; i++) {
905 int rc;
906 struct blkid_chain *chn;
907
908 chn = pr->cur_chain = &pr->chains[i];
909 chn->binary = FALSE; /* for sure... */
910
911 DBG(DEBUG_LOWPROBE, printf("chain fullprobe %s: %s\n",
912 chn->driver->name,
913 chn->enabled? "ENABLED" : "DISABLED"));
914
915 if (!chn->enabled)
916 continue;
917
918 blkid_probe_chain_reset_position(chn);
919
920 rc = chn->driver->probe(pr, chn);
921
922 blkid_probe_chain_reset_position(chn);
923
924 /* rc: -1 = error, 0 = success, 1 = no result */
925 if (rc < 0)
926 goto done; /* error */
927 if (rc == 0)
928 count++; /* success */
929 }
930
931 done:
932 blkid_probe_end(pr);
933 if (rc < 0)
934 return rc;
935 return count ? 0 : 1;
936 }
937
938 /* same sa blkid_probe_get_buffer() but works with 512-sectors */
939 unsigned char *blkid_probe_get_sector(blkid_probe pr, unsigned int sector)
940 {
941 return pr ? blkid_probe_get_buffer(pr,
942 ((blkid_loff_t) sector) << 9, 0x200) : NULL;
943 }
944
945 struct blkid_prval *blkid_probe_assign_value(
946 blkid_probe pr, const char *name)
947 {
948 struct blkid_prval *v;
949
950 if (!name)
951 return NULL;
952 if (pr->nvals >= BLKID_NVALS)
953 return NULL;
954
955 v = &pr->vals[pr->nvals];
956 v->name = name;
957 v->chain = pr->cur_chain;
958 pr->nvals++;
959
960 DBG(DEBUG_LOWPROBE,
961 printf("assigning %s [%s]\n", name, v->chain->driver->name));
962 return v;
963 }
964
965 int blkid_probe_reset_last_value(blkid_probe pr)
966 {
967 struct blkid_prval *v;
968
969 if (pr == NULL || pr->nvals == 0)
970 return -1;
971
972 v = &pr->vals[pr->nvals - 1];
973
974 DBG(DEBUG_LOWPROBE,
975 printf("un-assigning %s [%s]\n", v->name, v->chain->driver->name));
976
977 memset(v, 0, sizeof(struct blkid_prval));
978 pr->nvals--;
979
980 return 0;
981
982 }
983
984 int blkid_probe_set_value(blkid_probe pr, const char *name,
985 unsigned char *data, size_t len)
986 {
987 struct blkid_prval *v;
988
989 if (len > BLKID_PROBVAL_BUFSIZ)
990 len = BLKID_PROBVAL_BUFSIZ;
991
992 v = blkid_probe_assign_value(pr, name);
993 if (!v)
994 return -1;
995
996 memcpy(v->data, data, len);
997 v->len = len;
998 return 0;
999 }
1000
1001 int blkid_probe_vsprintf_value(blkid_probe pr, const char *name,
1002 const char *fmt, va_list ap)
1003 {
1004 struct blkid_prval *v;
1005 size_t len;
1006
1007 v = blkid_probe_assign_value(pr, name);
1008 if (!v)
1009 return -1;
1010
1011 len = vsnprintf((char *) v->data, sizeof(v->data), fmt, ap);
1012
1013 if (len <= 0) {
1014 blkid_probe_reset_last_value(pr);
1015 return -1;
1016 }
1017 v->len = len + 1;
1018 return 0;
1019 }
1020
1021 int blkid_probe_sprintf_value(blkid_probe pr, const char *name,
1022 const char *fmt, ...)
1023 {
1024 int rc;
1025 va_list ap;
1026
1027 va_start(ap, fmt);
1028 rc = blkid_probe_vsprintf_value(pr, name, fmt, ap);
1029 va_end(ap);
1030
1031 return rc;
1032 }
1033
1034 /**
1035 * blkid_probe_get_devno:
1036 * @pr: probe
1037 *
1038 * Returns: block device number, or 0 for regilar files.
1039 */
1040 dev_t blkid_probe_get_devno(blkid_probe pr)
1041 {
1042 return pr->devno;
1043 }
1044
1045 /**
1046 * blkid_probe_get_wholedisk_devno:
1047 * @pr: probe
1048 *
1049 * Returns: device number of the wholedisk, or 0 for regilar files.
1050 */
1051 dev_t blkid_probe_get_wholedisk_devno(blkid_probe pr)
1052 {
1053 if (!pr->disk_devno) {
1054 dev_t devno, disk_devno = 0;
1055
1056 devno = blkid_probe_get_devno(pr);
1057 if (!devno)
1058 return 0;
1059
1060 if (blkid_devno_to_wholedisk(devno, NULL, 0, &disk_devno) == 0)
1061 pr->disk_devno = disk_devno;
1062 }
1063 return pr->disk_devno;
1064 }
1065
1066 /**
1067 * blkid_probe_is_wholedisk:
1068 * @pr: probe
1069 *
1070 * Returns: 1 if the device is whole-disk or 0.
1071 */
1072 int blkid_probe_is_wholedisk(blkid_probe pr)
1073 {
1074 dev_t devno, disk_devno;
1075
1076 devno = blkid_probe_get_devno(pr);
1077 if (!devno)
1078 return 0;
1079
1080 disk_devno = blkid_probe_get_wholedisk_devno(pr);
1081 if (!disk_devno)
1082 return 0;
1083
1084 return devno == disk_devno;
1085 }
1086
1087 /**
1088 * blkid_probe_get_size:
1089 * @pr: probe
1090 *
1091 * This function returns size of probing area as defined by blkid_probe_set_device().
1092 * If the size of the probing area is unrestricted then this function returns
1093 * the real size of device. See also blkid_get_dev_size().
1094 *
1095 * Returns: size in bytes or -1 in case of error.
1096 */
1097 blkid_loff_t blkid_probe_get_size(blkid_probe pr)
1098 {
1099 return pr ? pr->size : -1;
1100 }
1101
1102 /**
1103 * blkid_probe_get_offset:
1104 * @pr: probe
1105 *
1106 * This function returns offset of probing area as defined by blkid_probe_set_device().
1107 *
1108 * Returns: offset in bytes or -1 in case of error.
1109 */
1110 blkid_loff_t blkid_probe_get_offset(blkid_probe pr)
1111 {
1112 return pr ? pr->off : -1;
1113 }
1114
1115 /**
1116 * blkid_probe_get_fd:
1117 * @pr: probe
1118 *
1119 * Returns: file descriptor for assigned device/file.
1120 */
1121 int blkid_probe_get_fd(blkid_probe pr)
1122 {
1123 return pr ? pr->fd : -1;
1124 }
1125
1126 /**
1127 * blkid_probe_get_sectorsize:
1128 * @pr: probe or NULL (for NULL returns 512)
1129 *
1130 * Returns: block device logical sector size (BLKSSZGET ioctl, default 512).
1131 */
1132 unsigned int blkid_probe_get_sectorsize(blkid_probe pr)
1133 {
1134 if (!pr)
1135 return DEFAULT_SECTOR_SIZE; /*... and good luck! */
1136
1137 if (pr->blkssz)
1138 return pr->blkssz;
1139
1140 if (S_ISBLK(pr->mode) &&
1141 blkdev_get_sector_size(pr->fd, (int *) &pr->blkssz) == 0)
1142 return pr->blkssz;
1143
1144 pr->blkssz = DEFAULT_SECTOR_SIZE;
1145 return pr->blkssz;
1146 }
1147
1148 /**
1149 * blkid_probe_numof_values:
1150 * @pr: probe
1151 *
1152 * Returns: number of values in probing result or -1 in case of error.
1153 */
1154 int blkid_probe_numof_values(blkid_probe pr)
1155 {
1156 if (!pr)
1157 return -1;
1158 return pr->nvals;
1159 }
1160
1161 /**
1162 * blkid_probe_get_value:
1163 * @pr: probe
1164 * @num: wanted value in range 0..N, where N is blkid_probe_numof_values() - 1
1165 * @name: pointer to return value name or NULL
1166 * @data: pointer to return value data or NULL
1167 * @len: pointer to return value length or NULL
1168 *
1169 * Note, the @len returns length of the @data, including the terminating
1170 * '\0' character.
1171 *
1172 * Returns: 0 on success, or -1 in case of error.
1173 */
1174 int blkid_probe_get_value(blkid_probe pr, int num, const char **name,
1175 const char **data, size_t *len)
1176 {
1177 struct blkid_prval *v = __blkid_probe_get_value(pr, num);
1178
1179 if (!v)
1180 return -1;
1181 if (name)
1182 *name = v->name;
1183 if (data)
1184 *data = (char *) v->data;
1185 if (len)
1186 *len = v->len;
1187
1188 DBG(DEBUG_LOWPROBE, printf("returning %s value\n", v->name));
1189 return 0;
1190 }
1191
1192 /**
1193 * blkid_probe_lookup_value:
1194 * @pr: probe
1195 * @name: name of value
1196 * @data: pointer to return value data or NULL
1197 * @len: pointer to return value length or NULL
1198 *
1199 * Note, the @len returns length of the @data, including the terminating
1200 * '\0' character.
1201 *
1202 * Returns: 0 on success, or -1 in case of error.
1203 */
1204 int blkid_probe_lookup_value(blkid_probe pr, const char *name,
1205 const char **data, size_t *len)
1206 {
1207 struct blkid_prval *v = __blkid_probe_lookup_value(pr, name);
1208
1209 if (!v)
1210 return -1;
1211 if (data)
1212 *data = (char *) v->data;
1213 if (len)
1214 *len = v->len;
1215 return 0;
1216 }
1217
1218 /**
1219 * blkid_probe_has_value:
1220 * @pr: probe
1221 * @name: name of value
1222 *
1223 * Returns: 1 if value exist in probing result, otherwise 0.
1224 */
1225 int blkid_probe_has_value(blkid_probe pr, const char *name)
1226 {
1227 if (blkid_probe_lookup_value(pr, name, NULL, NULL) == 0)
1228 return 1;
1229 return 0;
1230 }
1231
1232 struct blkid_prval *__blkid_probe_get_value(blkid_probe pr, int num)
1233 {
1234 if (pr == NULL || num < 0 || num >= pr->nvals)
1235 return NULL;
1236
1237 return &pr->vals[num];
1238 }
1239
1240 struct blkid_prval *__blkid_probe_lookup_value(blkid_probe pr, const char *name)
1241 {
1242 int i;
1243
1244 if (pr == NULL || pr->nvals == 0 || name == NULL)
1245 return NULL;
1246
1247 for (i = 0; i < pr->nvals; i++) {
1248 struct blkid_prval *v = &pr->vals[i];
1249
1250 if (v->name && strcmp(name, v->name) == 0) {
1251 DBG(DEBUG_LOWPROBE, printf("returning %s value\n", v->name));
1252 return v;
1253 }
1254 }
1255 return NULL;
1256 }
1257
1258
1259 /* converts DCE UUID (uuid[16]) to human readable string
1260 * - the @len should be always 37 */
1261 void blkid_unparse_uuid(const unsigned char *uuid, char *str, size_t len)
1262 {
1263 #ifdef HAVE_LIBUUID
1264 uuid_unparse(uuid, str);
1265 #else
1266 snprintf(str, len,
1267 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1268 uuid[0], uuid[1], uuid[2], uuid[3],
1269 uuid[4], uuid[5],
1270 uuid[6], uuid[7],
1271 uuid[8], uuid[9],
1272 uuid[10], uuid[11], uuid[12], uuid[13], uuid[14],uuid[15]);
1273 #endif
1274 }
1275
1276
1277 /* Removes whitespace from the right-hand side of a string (trailing
1278 * whitespace).
1279 *
1280 * Returns size of the new string (without \0).
1281 */
1282 size_t blkid_rtrim_whitespace(unsigned char *str)
1283 {
1284 size_t i = strlen((char *) str);
1285
1286 while (i--) {
1287 if (!isspace(str[i]))
1288 break;
1289 }
1290 str[++i] = '\0';
1291 return i;
1292 }
1293