]> git.ipfire.org Git - thirdparty/util-linux.git/blob - shlibs/blkid/src/probe.c
libblkid: consolidate magic strings detection code
[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 if (!S_ISBLK(sb.st_mode) && !S_ISCHR(sb.st_mode) && !S_ISREG(sb.st_mode))
630 goto err;
631
632 pr->mode = sb.st_mode;
633 if (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode))
634 pr->devno = sb.st_rdev;
635
636 if (size)
637 pr->size = size;
638 else {
639 if (S_ISBLK(sb.st_mode)) {
640 if (blkdev_get_size(fd, (unsigned long long *) &pr->size)) {
641 DBG(DEBUG_LOWPROBE, printf(
642 "failed to get device size\n"));
643 goto err;
644 }
645 } else if (S_ISCHR(sb.st_mode))
646 pr->size = 1; /* UBI devices are char... */
647 else if (S_ISREG(sb.st_mode))
648 pr->size = sb.st_size; /* regular file */
649
650 if (pr->off > pr->size)
651 goto err;
652
653 /* The probing area cannot be larger than whole device, pr->off
654 * is offset within the device */
655 pr->size -= pr->off;
656 }
657
658 if (pr->size <= 1440 * 1024 && !S_ISCHR(sb.st_mode))
659 pr->flags |= BLKID_TINY_DEV;
660
661 #ifdef CDROM_GET_CAPABILITY
662 if (S_ISBLK(sb.st_mode) && ioctl(fd, CDROM_GET_CAPABILITY, NULL) >= 0)
663 pr->flags |= BLKID_CDROM_DEV;
664 #endif
665
666 DBG(DEBUG_LOWPROBE, printf("ready for low-probing, offset=%jd, size=%jd\n",
667 pr->off, pr->size));
668 DBG(DEBUG_LOWPROBE, printf("whole-disk: %s, regfile: %s\n",
669 blkid_probe_is_wholedisk(pr) ?"YES" : "NO",
670 S_ISREG(pr->mode) ? "YES" : "NO"));
671
672 return 0;
673 err:
674 DBG(DEBUG_LOWPROBE,
675 printf("failed to prepare a device for low-probing\n"));
676 return -1;
677
678 }
679
680 int blkid_probe_get_dimension(blkid_probe pr,
681 blkid_loff_t *off, blkid_loff_t *size)
682 {
683 if (!pr)
684 return -1;
685
686 *off = pr->off;
687 *size = pr->size;
688 return 0;
689 }
690
691 int blkid_probe_set_dimension(blkid_probe pr,
692 blkid_loff_t off, blkid_loff_t size)
693 {
694 if (!pr)
695 return -1;
696
697 DBG(DEBUG_LOWPROBE, printf(
698 "changing probing area: size=%llu, off=%llu "
699 "-to-> size=%llu, off=%llu\n",
700 (unsigned long long) pr->size,
701 (unsigned long long) pr->off,
702 (unsigned long long) size,
703 (unsigned long long) off));
704
705 pr->off = off;
706 pr->size = size;
707 pr->flags &= ~BLKID_TINY_DEV;
708
709 if (pr->size <= 1440 * 1024 && !S_ISCHR(pr->mode))
710 pr->flags |= BLKID_TINY_DEV;
711
712 blkid_probe_reset_buffer(pr);
713
714 return 0;
715 }
716
717 int blkid_probe_get_idmag(blkid_probe pr, const struct blkid_idinfo *id,
718 blkid_loff_t *offset, const struct blkid_idmag **res)
719 {
720 const struct blkid_idmag *mag = NULL;
721 blkid_loff_t off = 0;
722
723 if (id)
724 mag = id->magics ? &id->magics[0] : NULL;
725 if (res)
726 *res = NULL;
727
728 /* try to detect by magic string */
729 while(mag && mag->magic) {
730 unsigned char *buf;
731
732 off = (mag->kboff + (mag->sboff >> 10)) << 10;
733 buf = blkid_probe_get_buffer(pr, off, 1024);
734
735 if (buf && !memcmp(mag->magic,
736 buf + (mag->sboff & 0x3ff), mag->len)) {
737 DBG(DEBUG_LOWPROBE, printf(
738 "\tmagic sboff=%u, kboff=%ld\n",
739 mag->sboff, mag->kboff));
740 if (offset)
741 *offset = off + (mag->sboff & 0x3ff);
742 if (res)
743 *res = mag;
744 return 0;
745 }
746 mag++;
747 }
748
749 if (id->magics && id->magics[0].magic)
750 /* magic string(s) defined, but not found */
751 return 1;
752
753 return 0;
754 }
755
756 static inline void blkid_probe_start(blkid_probe pr)
757 {
758 if (pr) {
759 pr->cur_chain = NULL;
760 pr->prob_flags = 0;
761 }
762 }
763
764 static inline void blkid_probe_end(blkid_probe pr)
765 {
766 if (pr) {
767 pr->cur_chain = NULL;
768 pr->prob_flags = 0;
769 }
770 }
771
772 /**
773 * blkid_do_probe:
774 * @pr: prober
775 *
776 * Calls probing functions in all enabled chains. The superblocks chain is
777 * enabled by default. The blkid_do_probe() stores result from only one
778 * probing function. It's necessary to call this routine in a loop to get
779 * results from all probing functions in all chains. The probing is reseted
780 * by blkid_reset_probe() or by filter functions.
781 *
782 * This is string-based NAME=value interface only.
783 *
784 * <example>
785 * <title>basic case - use the first result only</title>
786 * <programlisting>
787 *
788 * if (blkid_do_probe(pr) == 0) {
789 * int nvals = blkid_probe_numof_values(pr);
790 * for (n = 0; n < nvals; n++) {
791 * if (blkid_probe_get_value(pr, n, &name, &data, &len) == 0)
792 * printf("%s = %s\n", name, data);
793 * }
794 * }
795 * </programlisting>
796 * </example>
797 *
798 * <example>
799 * <title>advanced case - probe for all signatures</title>
800 * <programlisting>
801 *
802 * while (blkid_do_probe(pr) == 0) {
803 * int nvals = blkid_probe_numof_values(pr);
804 * ...
805 * }
806 * </programlisting>
807 * </example>
808 *
809 * See also blkid_reset_probe().
810 *
811 * Returns: 0 on success, 1 when probing is done and -1 in case of error.
812 */
813 int blkid_do_probe(blkid_probe pr)
814 {
815 int rc = 1;
816
817 if (!pr)
818 return -1;
819
820 do {
821 struct blkid_chain *chn = pr->cur_chain;
822
823 if (!chn) {
824 blkid_probe_start(pr);
825 chn = pr->cur_chain = &pr->chains[0];
826 }
827 /* we go to the next chain only when the previous probing
828 * result was nothing (rc == 1) and when the current chain is
829 * disabled or we are at end of the current chain (chain->idx +
830 * 1 == sizeof chain) or the current chain bailed out right at
831 * the start (chain->idx == -1)
832 */
833 else if (rc == 1 && (chn->enabled == FALSE ||
834 chn->idx + 1 == chn->driver->nidinfos ||
835 chn->idx == -1)) {
836
837 int idx = chn->driver->id + 1;
838
839 if (idx < BLKID_NCHAINS)
840 chn = pr->cur_chain = &pr->chains[idx];
841 else {
842 blkid_probe_end(pr);
843 return 1; /* all chains already probed */
844 }
845 }
846
847 chn->binary = FALSE; /* for sure... */
848
849 DBG(DEBUG_LOWPROBE, printf("chain probe %s %s (idx=%d)\n",
850 chn->driver->name,
851 chn->enabled? "ENABLED" : "DISABLED",
852 chn->idx));
853
854 if (!chn->enabled)
855 continue;
856
857 /* rc: -1 = error, 0 = success, 1 = no result */
858 rc = chn->driver->probe(pr, chn);
859
860 } while (rc == 1);
861
862 return rc;
863 }
864
865 /**
866 * blkid_do_safeprobe:
867 * @pr: prober
868 *
869 * This function gathers probing results from all enabled chains and checks
870 * for ambivalent results (e.g. more filesystems on the device).
871 *
872 * This is string-based NAME=value interface only.
873 *
874 * Note about suberblocks chain -- the function does not check for filesystems
875 * when a RAID signature is detected. The function also does not check for
876 * collision between RAIDs. The first detected RAID is returned. The function
877 * checks for collision between partition table and RAID signature -- it's
878 * recommended to enable partitions chain together with superblocks chain.
879 *
880 * Returns: 0 on success, 1 if nothing is detected, -2 if ambivalen result is
881 * detected and -1 on case of error.
882 */
883 int blkid_do_safeprobe(blkid_probe pr)
884 {
885 int i, count = 0, rc = 0;
886
887 if (!pr)
888 return -1;
889
890 blkid_probe_start(pr);
891
892 for (i = 0; i < BLKID_NCHAINS; i++) {
893 struct blkid_chain *chn;
894
895 chn = pr->cur_chain = &pr->chains[i];
896 chn->binary = FALSE; /* for sure... */
897
898 DBG(DEBUG_LOWPROBE, printf("chain safeprobe %s %s\n",
899 chn->driver->name,
900 chn->enabled? "ENABLED" : "DISABLED"));
901
902 if (!chn->enabled)
903 continue;
904
905 blkid_probe_chain_reset_position(chn);
906
907 rc = chn->driver->safeprobe(pr, chn);
908
909 blkid_probe_chain_reset_position(chn);
910
911 /* rc: -2 ambivalent, -1 = error, 0 = success, 1 = no result */
912 if (rc < 0)
913 goto done; /* error */
914 if (rc == 0)
915 count++; /* success */
916 }
917
918 done:
919 blkid_probe_end(pr);
920 if (rc < 0)
921 return rc;
922 return count ? 0 : 1;
923 }
924
925 /**
926 * blkid_do_fullprobe:
927 * @pr: prober
928 *
929 * This function gathers probing results from all enabled chains. Same as
930 * blkid_so_safeprobe() but does not check for collision between probing
931 * result.
932 *
933 * This is string-based NAME=value interface only.
934 *
935 * Returns: 0 on success, 1 if nothing is detected or -1 on case of error.
936 */
937 int blkid_do_fullprobe(blkid_probe pr)
938 {
939 int i, count = 0, rc = 0;
940
941 if (!pr)
942 return -1;
943
944 blkid_probe_start(pr);
945
946 for (i = 0; i < BLKID_NCHAINS; i++) {
947 int rc;
948 struct blkid_chain *chn;
949
950 chn = pr->cur_chain = &pr->chains[i];
951 chn->binary = FALSE; /* for sure... */
952
953 DBG(DEBUG_LOWPROBE, printf("chain fullprobe %s: %s\n",
954 chn->driver->name,
955 chn->enabled? "ENABLED" : "DISABLED"));
956
957 if (!chn->enabled)
958 continue;
959
960 blkid_probe_chain_reset_position(chn);
961
962 rc = chn->driver->probe(pr, chn);
963
964 blkid_probe_chain_reset_position(chn);
965
966 /* rc: -1 = error, 0 = success, 1 = no result */
967 if (rc < 0)
968 goto done; /* error */
969 if (rc == 0)
970 count++; /* success */
971 }
972
973 done:
974 blkid_probe_end(pr);
975 if (rc < 0)
976 return rc;
977 return count ? 0 : 1;
978 }
979
980 /* same sa blkid_probe_get_buffer() but works with 512-sectors */
981 unsigned char *blkid_probe_get_sector(blkid_probe pr, unsigned int sector)
982 {
983 return pr ? blkid_probe_get_buffer(pr,
984 ((blkid_loff_t) sector) << 9, 0x200) : NULL;
985 }
986
987 struct blkid_prval *blkid_probe_assign_value(
988 blkid_probe pr, const char *name)
989 {
990 struct blkid_prval *v;
991
992 if (!name)
993 return NULL;
994 if (pr->nvals >= BLKID_NVALS)
995 return NULL;
996
997 v = &pr->vals[pr->nvals];
998 v->name = name;
999 v->chain = pr->cur_chain;
1000 pr->nvals++;
1001
1002 DBG(DEBUG_LOWPROBE,
1003 printf("assigning %s [%s]\n", name, v->chain->driver->name));
1004 return v;
1005 }
1006
1007 int blkid_probe_reset_last_value(blkid_probe pr)
1008 {
1009 struct blkid_prval *v;
1010
1011 if (pr == NULL || pr->nvals == 0)
1012 return -1;
1013
1014 v = &pr->vals[pr->nvals - 1];
1015
1016 DBG(DEBUG_LOWPROBE,
1017 printf("un-assigning %s [%s]\n", v->name, v->chain->driver->name));
1018
1019 memset(v, 0, sizeof(struct blkid_prval));
1020 pr->nvals--;
1021
1022 return 0;
1023
1024 }
1025
1026 int blkid_probe_set_value(blkid_probe pr, const char *name,
1027 unsigned char *data, size_t len)
1028 {
1029 struct blkid_prval *v;
1030
1031 if (len > BLKID_PROBVAL_BUFSIZ)
1032 len = BLKID_PROBVAL_BUFSIZ;
1033
1034 v = blkid_probe_assign_value(pr, name);
1035 if (!v)
1036 return -1;
1037
1038 memcpy(v->data, data, len);
1039 v->len = len;
1040 return 0;
1041 }
1042
1043 int blkid_probe_vsprintf_value(blkid_probe pr, const char *name,
1044 const char *fmt, va_list ap)
1045 {
1046 struct blkid_prval *v;
1047 size_t len;
1048
1049 v = blkid_probe_assign_value(pr, name);
1050 if (!v)
1051 return -1;
1052
1053 len = vsnprintf((char *) v->data, sizeof(v->data), fmt, ap);
1054
1055 if (len <= 0) {
1056 blkid_probe_reset_last_value(pr);
1057 return -1;
1058 }
1059 v->len = len + 1;
1060 return 0;
1061 }
1062
1063 int blkid_probe_sprintf_value(blkid_probe pr, const char *name,
1064 const char *fmt, ...)
1065 {
1066 int rc;
1067 va_list ap;
1068
1069 va_start(ap, fmt);
1070 rc = blkid_probe_vsprintf_value(pr, name, fmt, ap);
1071 va_end(ap);
1072
1073 return rc;
1074 }
1075
1076 /**
1077 * blkid_probe_get_devno:
1078 * @pr: probe
1079 *
1080 * Returns: block device number, or 0 for regilar files.
1081 */
1082 dev_t blkid_probe_get_devno(blkid_probe pr)
1083 {
1084 return pr->devno;
1085 }
1086
1087 /**
1088 * blkid_probe_get_wholedisk_devno:
1089 * @pr: probe
1090 *
1091 * Returns: device number of the wholedisk, or 0 for regilar files.
1092 */
1093 dev_t blkid_probe_get_wholedisk_devno(blkid_probe pr)
1094 {
1095 if (!pr->disk_devno) {
1096 dev_t devno, disk_devno = 0;
1097
1098 devno = blkid_probe_get_devno(pr);
1099 if (!devno)
1100 return 0;
1101
1102 if (blkid_devno_to_wholedisk(devno, NULL, 0, &disk_devno) == 0)
1103 pr->disk_devno = disk_devno;
1104 }
1105 return pr->disk_devno;
1106 }
1107
1108 /**
1109 * blkid_probe_is_wholedisk:
1110 * @pr: probe
1111 *
1112 * Returns: 1 if the device is whole-disk or 0.
1113 */
1114 int blkid_probe_is_wholedisk(blkid_probe pr)
1115 {
1116 dev_t devno, disk_devno;
1117
1118 devno = blkid_probe_get_devno(pr);
1119 if (!devno)
1120 return 0;
1121
1122 disk_devno = blkid_probe_get_wholedisk_devno(pr);
1123 if (!disk_devno)
1124 return 0;
1125
1126 return devno == disk_devno;
1127 }
1128
1129 /**
1130 * blkid_probe_get_size:
1131 * @pr: probe
1132 *
1133 * This function returns size of probing area as defined by blkid_probe_set_device().
1134 * If the size of the probing area is unrestricted then this function returns
1135 * the real size of device. See also blkid_get_dev_size().
1136 *
1137 * Returns: size in bytes or -1 in case of error.
1138 */
1139 blkid_loff_t blkid_probe_get_size(blkid_probe pr)
1140 {
1141 return pr ? pr->size : -1;
1142 }
1143
1144 /**
1145 * blkid_probe_get_offset:
1146 * @pr: probe
1147 *
1148 * This function returns offset of probing area as defined by blkid_probe_set_device().
1149 *
1150 * Returns: offset in bytes or -1 in case of error.
1151 */
1152 blkid_loff_t blkid_probe_get_offset(blkid_probe pr)
1153 {
1154 return pr ? pr->off : -1;
1155 }
1156
1157 /**
1158 * blkid_probe_get_fd:
1159 * @pr: probe
1160 *
1161 * Returns: file descriptor for assigned device/file.
1162 */
1163 int blkid_probe_get_fd(blkid_probe pr)
1164 {
1165 return pr ? pr->fd : -1;
1166 }
1167
1168 /**
1169 * blkid_probe_get_sectorsize:
1170 * @pr: probe or NULL (for NULL returns 512)
1171 *
1172 * Returns: block device logical sector size (BLKSSZGET ioctl, default 512).
1173 */
1174 unsigned int blkid_probe_get_sectorsize(blkid_probe pr)
1175 {
1176 if (!pr)
1177 return DEFAULT_SECTOR_SIZE; /*... and good luck! */
1178
1179 if (pr->blkssz)
1180 return pr->blkssz;
1181
1182 if (S_ISBLK(pr->mode) &&
1183 blkdev_get_sector_size(pr->fd, (int *) &pr->blkssz) == 0)
1184 return pr->blkssz;
1185
1186 pr->blkssz = DEFAULT_SECTOR_SIZE;
1187 return pr->blkssz;
1188 }
1189
1190 /**
1191 * blkid_probe_numof_values:
1192 * @pr: probe
1193 *
1194 * Returns: number of values in probing result or -1 in case of error.
1195 */
1196 int blkid_probe_numof_values(blkid_probe pr)
1197 {
1198 if (!pr)
1199 return -1;
1200 return pr->nvals;
1201 }
1202
1203 /**
1204 * blkid_probe_get_value:
1205 * @pr: probe
1206 * @num: wanted value in range 0..N, where N is blkid_probe_numof_values() - 1
1207 * @name: pointer to return value name or NULL
1208 * @data: pointer to return value data or NULL
1209 * @len: pointer to return value length or NULL
1210 *
1211 * Note, the @len returns length of the @data, including the terminating
1212 * '\0' character.
1213 *
1214 * Returns: 0 on success, or -1 in case of error.
1215 */
1216 int blkid_probe_get_value(blkid_probe pr, int num, const char **name,
1217 const char **data, size_t *len)
1218 {
1219 struct blkid_prval *v = __blkid_probe_get_value(pr, num);
1220
1221 if (!v)
1222 return -1;
1223 if (name)
1224 *name = v->name;
1225 if (data)
1226 *data = (char *) v->data;
1227 if (len)
1228 *len = v->len;
1229
1230 DBG(DEBUG_LOWPROBE, printf("returning %s value\n", v->name));
1231 return 0;
1232 }
1233
1234 /**
1235 * blkid_probe_lookup_value:
1236 * @pr: probe
1237 * @name: name of value
1238 * @data: pointer to return value data or NULL
1239 * @len: pointer to return value length or NULL
1240 *
1241 * Note, the @len returns length of the @data, including the terminating
1242 * '\0' character.
1243 *
1244 * Returns: 0 on success, or -1 in case of error.
1245 */
1246 int blkid_probe_lookup_value(blkid_probe pr, const char *name,
1247 const char **data, size_t *len)
1248 {
1249 struct blkid_prval *v = __blkid_probe_lookup_value(pr, name);
1250
1251 if (!v)
1252 return -1;
1253 if (data)
1254 *data = (char *) v->data;
1255 if (len)
1256 *len = v->len;
1257 return 0;
1258 }
1259
1260 /**
1261 * blkid_probe_has_value:
1262 * @pr: probe
1263 * @name: name of value
1264 *
1265 * Returns: 1 if value exist in probing result, otherwise 0.
1266 */
1267 int blkid_probe_has_value(blkid_probe pr, const char *name)
1268 {
1269 if (blkid_probe_lookup_value(pr, name, NULL, NULL) == 0)
1270 return 1;
1271 return 0;
1272 }
1273
1274 struct blkid_prval *__blkid_probe_get_value(blkid_probe pr, int num)
1275 {
1276 if (pr == NULL || num < 0 || num >= pr->nvals)
1277 return NULL;
1278
1279 return &pr->vals[num];
1280 }
1281
1282 struct blkid_prval *__blkid_probe_lookup_value(blkid_probe pr, const char *name)
1283 {
1284 int i;
1285
1286 if (pr == NULL || pr->nvals == 0 || name == NULL)
1287 return NULL;
1288
1289 for (i = 0; i < pr->nvals; i++) {
1290 struct blkid_prval *v = &pr->vals[i];
1291
1292 if (v->name && strcmp(name, v->name) == 0) {
1293 DBG(DEBUG_LOWPROBE, printf("returning %s value\n", v->name));
1294 return v;
1295 }
1296 }
1297 return NULL;
1298 }
1299
1300
1301 /* converts DCE UUID (uuid[16]) to human readable string
1302 * - the @len should be always 37 */
1303 void blkid_unparse_uuid(const unsigned char *uuid, char *str, size_t len)
1304 {
1305 #ifdef HAVE_LIBUUID
1306 uuid_unparse(uuid, str);
1307 #else
1308 snprintf(str, len,
1309 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1310 uuid[0], uuid[1], uuid[2], uuid[3],
1311 uuid[4], uuid[5],
1312 uuid[6], uuid[7],
1313 uuid[8], uuid[9],
1314 uuid[10], uuid[11], uuid[12], uuid[13], uuid[14],uuid[15]);
1315 #endif
1316 }
1317
1318
1319 /* Removes whitespace from the right-hand side of a string (trailing
1320 * whitespace).
1321 *
1322 * Returns size of the new string (without \0).
1323 */
1324 size_t blkid_rtrim_whitespace(unsigned char *str)
1325 {
1326 size_t i = strlen((char *) str);
1327
1328 while (i--) {
1329 if (!isspace(str[i]))
1330 break;
1331 }
1332 str[++i] = '\0';
1333 return i;
1334 }
1335