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