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 reset 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_ERRNO_H
101 #include <errno.h>
102 #endif
103 #include <inttypes.h>
104 #include <stdint.h>
105 #include <stdarg.h>
106
107 #ifdef HAVE_LIBUUID
108 # include <uuid.h>
109 #endif
110
111 #include "blkidP.h"
112 #include "all-io.h"
113 #include "sysfs.h"
114
115 /* chains */
116 extern const struct blkid_chaindrv superblocks_drv;
117 extern const struct blkid_chaindrv topology_drv;
118 extern const struct blkid_chaindrv partitions_drv;
119
120 /*
121 * All supported chains
122 */
123 static const struct blkid_chaindrv *chains_drvs[] = {
124 [BLKID_CHAIN_SUBLKS] = &superblocks_drv,
125 [BLKID_CHAIN_TOPLGY] = &topology_drv,
126 [BLKID_CHAIN_PARTS] = &partitions_drv
127 };
128
129 static void blkid_probe_reset_vals(blkid_probe pr);
130 static void blkid_probe_reset_buffer(blkid_probe pr);
131
132 /**
133 * blkid_new_probe:
134 *
135 * Returns: a pointer to the newly allocated probe struct or NULL in case of error.
136 */
blkid_new_probe(void)137 blkid_probe blkid_new_probe(void)
138 {
139 int i;
140 blkid_probe pr;
141
142 blkid_init_debug(0);
143 pr = calloc(1, sizeof(struct blkid_struct_probe));
144 if (!pr)
145 return NULL;
146
147 DBG(LOWPROBE, ul_debug("allocate a new probe %p", pr));
148
149 /* initialize chains */
150 for (i = 0; i < BLKID_NCHAINS; i++) {
151 pr->chains[i].driver = chains_drvs[i];
152 pr->chains[i].flags = chains_drvs[i]->dflt_flags;
153 pr->chains[i].enabled = chains_drvs[i]->dflt_enabled;
154 }
155 INIT_LIST_HEAD(&pr->buffers);
156 return pr;
157 }
158
159 /*
160 * Clone @parent, the new clone shares all, but except:
161 *
162 * - probing result
163 * - bufferes if another device (or offset) is set to the prober
164 */
blkid_clone_probe(blkid_probe parent)165 blkid_probe blkid_clone_probe(blkid_probe parent)
166 {
167 blkid_probe pr;
168
169 if (!parent)
170 return NULL;
171
172 DBG(LOWPROBE, ul_debug("allocate a probe clone"));
173
174 pr = blkid_new_probe();
175 if (!pr)
176 return NULL;
177
178 pr->fd = parent->fd;
179 pr->off = parent->off;
180 pr->size = parent->size;
181 pr->devno = parent->devno;
182 pr->disk_devno = parent->disk_devno;
183 pr->blkssz = parent->blkssz;
184 pr->flags = parent->flags;
185 pr->parent = parent;
186
187 pr->flags &= ~BLKID_FL_PRIVATE_FD;
188
189 return pr;
190 }
191
192
193
194 /**
195 * blkid_new_probe_from_filename:
196 * @filename: device or regular file
197 *
198 * This function is same as call open(filename), blkid_new_probe() and
199 * blkid_probe_set_device(pr, fd, 0, 0).
200 *
201 * The @filename is closed by blkid_free_probe() or by the
202 * blkid_probe_set_device() call.
203 *
204 * Returns: a pointer to the newly allocated probe struct or NULL in case of
205 * error.
206 */
blkid_new_probe_from_filename(const char * filename)207 blkid_probe blkid_new_probe_from_filename(const char *filename)
208 {
209 int fd = -1;
210 blkid_probe pr = NULL;
211
212 if (!filename)
213 return NULL;
214
215 fd = open(filename, O_RDONLY|O_CLOEXEC);
216 if (fd < 0)
217 return NULL;
218
219 pr = blkid_new_probe();
220 if (!pr)
221 goto err;
222
223 if (blkid_probe_set_device(pr, fd, 0, 0))
224 goto err;
225
226 pr->flags |= BLKID_FL_PRIVATE_FD;
227 return pr;
228 err:
229 if (fd >= 0)
230 close(fd);
231 blkid_free_probe(pr);
232 return NULL;
233 }
234
235 /**
236 * blkid_free_probe:
237 * @pr: probe
238 *
239 * Deallocates the probe struct, buffers and all allocated
240 * data that are associated with this probing control struct.
241 */
blkid_free_probe(blkid_probe pr)242 void blkid_free_probe(blkid_probe pr)
243 {
244 int i;
245
246 if (!pr)
247 return;
248
249 for (i = 0; i < BLKID_NCHAINS; i++) {
250 struct blkid_chain *ch = &pr->chains[i];
251
252 if (ch->driver->free_data)
253 ch->driver->free_data(pr, ch->data);
254 free(ch->fltr);
255 }
256
257 if ((pr->flags & BLKID_FL_PRIVATE_FD) && pr->fd >= 0)
258 close(pr->fd);
259 blkid_probe_reset_buffer(pr);
260 blkid_free_probe(pr->disk_probe);
261
262 DBG(LOWPROBE, ul_debug("free probe %p", pr));
263 free(pr);
264 }
265
266
267 /*
268 * Removes chain values from probing result.
269 */
blkid_probe_chain_reset_vals(blkid_probe pr,struct blkid_chain * chn)270 void blkid_probe_chain_reset_vals(blkid_probe pr, struct blkid_chain *chn)
271 {
272 int nvals = pr->nvals;
273 int i, x;
274
275 for (x = 0, i = 0; i < pr->nvals; i++) {
276 struct blkid_prval *v = &pr->vals[i];
277
278 if (v->chain != chn && x == i) {
279 x++;
280 continue;
281 }
282 if (v->chain == chn) {
283 --nvals;
284 continue;
285 }
286 memcpy(&pr->vals[x++], v, sizeof(struct blkid_prval));
287 }
288 pr->nvals = nvals;
289 }
290
blkid_probe_chain_reset_position(struct blkid_chain * chn)291 static void blkid_probe_chain_reset_position(struct blkid_chain *chn)
292 {
293 if (chn)
294 chn->idx = -1;
295 }
296
297 /*
298 * Copies chain values from probing result to @vals, the max size of @vals is
299 * @nvals and returns real number of values.
300 */
blkid_probe_chain_copy_vals(blkid_probe pr,struct blkid_chain * chn,struct blkid_prval * vals,int nvals)301 int blkid_probe_chain_copy_vals(blkid_probe pr, struct blkid_chain *chn,
302 struct blkid_prval *vals, int nvals)
303 {
304 int i, x;
305
306 for (x = 0, i = 0; i < pr->nvals && x < nvals; i++) {
307 struct blkid_prval *v = &pr->vals[i];
308
309 if (v->chain != chn)
310 continue;
311 memcpy(&vals[x++], v, sizeof(struct blkid_prval));
312 }
313 return x;
314 }
315
316 /*
317 * Appends values from @vals to the probing result
318 */
blkid_probe_append_vals(blkid_probe pr,struct blkid_prval * vals,int nvals)319 void blkid_probe_append_vals(blkid_probe pr, struct blkid_prval *vals, int nvals)
320 {
321 int i = 0;
322
323 while (i < nvals && pr->nvals < BLKID_NVALS) {
324 memcpy(&pr->vals[pr->nvals++], &vals[i++],
325 sizeof(struct blkid_prval));
326 }
327 }
328
blkid_probe_reset_vals(blkid_probe pr)329 static void blkid_probe_reset_vals(blkid_probe pr)
330 {
331 memset(pr->vals, 0, sizeof(pr->vals));
332 pr->nvals = 0;
333 }
334
blkid_probe_get_chain(blkid_probe pr)335 struct blkid_chain *blkid_probe_get_chain(blkid_probe pr)
336 {
337 return pr->cur_chain;
338 }
339
blkid_probe_get_probername(blkid_probe pr)340 static const char *blkid_probe_get_probername(blkid_probe pr)
341 {
342 struct blkid_chain *chn = blkid_probe_get_chain(pr);
343
344 if (chn && chn->idx >= 0 && chn->idx < chn->driver->nidinfos)
345 return chn->driver->idinfos[chn->idx]->name;
346
347 return NULL;
348 }
349
blkid_probe_get_binary_data(blkid_probe pr,struct blkid_chain * chn)350 void *blkid_probe_get_binary_data(blkid_probe pr, struct blkid_chain *chn)
351 {
352 int rc, org_prob_flags;
353 struct blkid_chain *org_chn;
354
355 if (!pr || !chn)
356 return NULL;
357
358 /* save the current setting -- the binary API has to be completely
359 * independent on the current probing status
360 */
361 org_chn = pr->cur_chain;
362 org_prob_flags = pr->prob_flags;
363
364 pr->cur_chain = chn;
365 pr->prob_flags = 0;
366 chn->binary = TRUE;
367 blkid_probe_chain_reset_position(chn);
368
369 rc = chn->driver->probe(pr, chn);
370
371 chn->binary = FALSE;
372 blkid_probe_chain_reset_position(chn);
373
374 /* restore the original setting
375 */
376 pr->cur_chain = org_chn;
377 pr->prob_flags = org_prob_flags;
378
379 if (rc != 0)
380 return NULL;
381
382 DBG(LOWPROBE, ul_debug("returning %s binary data", chn->driver->name));
383 return chn->data;
384 }
385
386
387 /**
388 * blkid_reset_probe:
389 * @pr: probe
390 *
391 * Zeroize probing results and resets the current probing (this has impact to
392 * blkid_do_probe() only). This function does not touch probing filters and
393 * keeps assigned device.
394 */
blkid_reset_probe(blkid_probe pr)395 void blkid_reset_probe(blkid_probe pr)
396 {
397 int i;
398
399 if (!pr)
400 return;
401
402 blkid_probe_reset_vals(pr);
403 blkid_probe_set_wiper(pr, 0, 0);
404
405 pr->cur_chain = NULL;
406
407 for (i = 0; i < BLKID_NCHAINS; i++)
408 blkid_probe_chain_reset_position(&pr->chains[i]);
409 }
410
411 /***
412 static int blkid_probe_dump_filter(blkid_probe pr, int chain)
413 {
414 struct blkid_chain *chn;
415 int i;
416
417 if (!pr || chain < 0 || chain >= BLKID_NCHAINS)
418 return -1;
419
420 chn = &pr->chains[chain];
421
422 if (!chn->fltr)
423 return -1;
424
425 for (i = 0; i < chn->driver->nidinfos; i++) {
426 const struct blkid_idinfo *id = chn->driver->idinfos[i];
427
428 DBG(LOWPROBE, ul_debug("%d: %s: %s",
429 i,
430 id->name,
431 blkid_bmp_get_item(chn->fltr, i)
432 ? "disabled" : "enabled <--"));
433 }
434 return 0;
435 }
436 ***/
437
438 /*
439 * Returns properly initialized chain filter
440 */
blkid_probe_get_filter(blkid_probe pr,int chain,int create)441 unsigned long *blkid_probe_get_filter(blkid_probe pr, int chain, int create)
442 {
443 struct blkid_chain *chn;
444
445 if (!pr || chain < 0 || chain >= BLKID_NCHAINS)
446 return NULL;
447
448 chn = &pr->chains[chain];
449
450 /* always when you touch the chain filter all indexes are reset and
451 * probing starts from scratch
452 */
453 blkid_probe_chain_reset_position(chn);
454 pr->cur_chain = NULL;
455
456 if (!chn->driver->has_fltr || (!chn->fltr && !create))
457 return NULL;
458
459 if (!chn->fltr)
460 chn->fltr = calloc(1, blkid_bmp_nbytes(chn->driver->nidinfos));
461 else
462 memset(chn->fltr, 0, blkid_bmp_nbytes(chn->driver->nidinfos));
463
464 /* blkid_probe_dump_filter(pr, chain); */
465 return chn->fltr;
466 }
467
468 /*
469 * Generic private functions for filter setting
470 */
__blkid_probe_invert_filter(blkid_probe pr,int chain)471 int __blkid_probe_invert_filter(blkid_probe pr, int chain)
472 {
473 size_t i;
474 struct blkid_chain *chn;
475
476 if (!pr)
477 return -1;
478
479 chn = &pr->chains[chain];
480
481 if (!chn->driver->has_fltr || !chn->fltr)
482 return -1;
483
484 for (i = 0; i < blkid_bmp_nwords(chn->driver->nidinfos); i++)
485 chn->fltr[i] = ~chn->fltr[i];
486
487 DBG(LOWPROBE, ul_debug("probing filter inverted"));
488 /* blkid_probe_dump_filter(pr, chain); */
489 return 0;
490 }
491
__blkid_probe_reset_filter(blkid_probe pr,int chain)492 int __blkid_probe_reset_filter(blkid_probe pr, int chain)
493 {
494 return blkid_probe_get_filter(pr, chain, FALSE) ? 0 : -1;
495 }
496
__blkid_probe_filter_types(blkid_probe pr,int chain,int flag,char * names[])497 int __blkid_probe_filter_types(blkid_probe pr, int chain, int flag, char *names[])
498 {
499 unsigned long *fltr;
500 struct blkid_chain *chn;
501 size_t i;
502
503 fltr = blkid_probe_get_filter(pr, chain, TRUE);
504 if (!fltr)
505 return -1;
506
507 chn = &pr->chains[chain];
508
509 for (i = 0; i < chn->driver->nidinfos; i++) {
510 int has = 0;
511 const struct blkid_idinfo *id = chn->driver->idinfos[i];
512 char **n;
513
514 for (n = names; *n; n++) {
515 if (!strcmp(id->name, *n)) {
516 has = 1;
517 break;
518 }
519 }
520 if (flag & BLKID_FLTR_ONLYIN) {
521 if (!has)
522 blkid_bmp_set_item(fltr, i);
523 } else if (flag & BLKID_FLTR_NOTIN) {
524 if (has)
525 blkid_bmp_set_item(fltr, i);
526 }
527 }
528
529 DBG(LOWPROBE, ul_debug("%s: a new probing type-filter initialized",
530 chn->driver->name));
531 /* blkid_probe_dump_filter(pr, chain); */
532 return 0;
533 }
534
blkid_probe_get_buffer(blkid_probe pr,blkid_loff_t off,blkid_loff_t len)535 unsigned char *blkid_probe_get_buffer(blkid_probe pr,
536 blkid_loff_t off, blkid_loff_t len)
537 {
538 struct list_head *p;
539 struct blkid_bufinfo *bf = NULL;
540
541 if (pr->size <= 0) {
542 errno = EINVAL;
543 return NULL;
544 }
545
546 if (pr->parent &&
547 pr->parent->devno == pr->devno &&
548 pr->parent->off <= pr->off &&
549 pr->parent->off + pr->parent->size >= pr->off + pr->size) {
550 /*
551 * This is a cloned prober and points to the same area as
552 * parent. Let's use parent's buffers.
553 *
554 * Note that pr->off (and pr->parent->off) is always from the
555 * beginig of the device.
556 */
557 return blkid_probe_get_buffer(pr->parent,
558 pr->off + off - pr->parent->off, len);
559 }
560
561 list_for_each(p, &pr->buffers) {
562 struct blkid_bufinfo *x =
563 list_entry(p, struct blkid_bufinfo, bufs);
564
565 if (x->off <= off && off + len <= x->off + x->len) {
566 DBG(LOWPROBE, ul_debug("\treuse buffer: off=%jd len=%jd pr=%p",
567 x->off, x->len, pr));
568 bf = x;
569 break;
570 }
571 }
572 if (!bf) {
573 ssize_t ret;
574
575 if (blkid_llseek(pr->fd, pr->off + off, SEEK_SET) < 0) {
576 errno = 0;
577 return NULL;
578 }
579
580 /* allocate info and space for data by why call */
581 bf = calloc(1, sizeof(struct blkid_bufinfo) + len);
582 if (!bf) {
583 errno = ENOMEM;
584 return NULL;
585 }
586
587 bf->data = ((unsigned char *) bf) + sizeof(struct blkid_bufinfo);
588 bf->len = len;
589 bf->off = off;
590 INIT_LIST_HEAD(&bf->bufs);
591
592 DBG(LOWPROBE, ul_debug("\tbuffer read: off=%jd len=%jd pr=%p",
593 off, len, pr));
594
595 ret = read(pr->fd, bf->data, len);
596 if (ret != (ssize_t) len) {
597 DBG(LOWPROBE, ul_debug("\tbuffer read: return %zd error %m", ret));
598 free(bf);
599 if (ret >= 0)
600 errno = 0;
601 return NULL;
602 }
603 list_add_tail(&bf->bufs, &pr->buffers);
604 }
605
606 errno = 0;
607 return off ? bf->data + (off - bf->off) : bf->data;
608 }
609
610
blkid_probe_reset_buffer(blkid_probe pr)611 static void blkid_probe_reset_buffer(blkid_probe pr)
612 {
613 uint64_t read_ct = 0, len_ct = 0;
614
615 if (!pr || list_empty(&pr->buffers))
616 return;
617
618 DBG(LOWPROBE, ul_debug("reseting probing buffers pr=%p", pr));
619
620 while (!list_empty(&pr->buffers)) {
621 struct blkid_bufinfo *bf = list_entry(pr->buffers.next,
622 struct blkid_bufinfo, bufs);
623 read_ct++;
624 len_ct += bf->len;
625 list_del(&bf->bufs);
626 free(bf);
627 }
628
629 DBG(LOWPROBE, ul_debug("buffers summary: %"PRIu64" bytes "
630 "by %"PRIu64" read() call(s)",
631 len_ct, read_ct));
632
633 INIT_LIST_HEAD(&pr->buffers);
634 }
635
636 /*
637 * Small devices need a special care.
638 */
blkid_probe_is_tiny(blkid_probe pr)639 int blkid_probe_is_tiny(blkid_probe pr)
640 {
641 return pr && (pr->flags & BLKID_FL_TINY_DEV);
642 }
643
644 /*
645 * CDROMs may fail when probed for RAID (last sector problem)
646 */
blkid_probe_is_cdrom(blkid_probe pr)647 int blkid_probe_is_cdrom(blkid_probe pr)
648 {
649 return pr && (pr->flags & BLKID_FL_CDROM_DEV);
650 }
651
652 /**
653 * blkid_probe_set_device:
654 * @pr: probe
655 * @fd: device file descriptor
656 * @off: begin of probing area
657 * @size: size of probing area (zero means whole device/file)
658 *
659 * Assigns the device to probe control struct, resets internal buffers and
660 * resets the current probing.
661 *
662 * Returns: -1 in case of failure, or 0 on success.
663 */
blkid_probe_set_device(blkid_probe pr,int fd,blkid_loff_t off,blkid_loff_t size)664 int blkid_probe_set_device(blkid_probe pr, int fd,
665 blkid_loff_t off, blkid_loff_t size)
666 {
667 struct stat sb;
668
669 if (!pr)
670 return -1;
671
672 blkid_reset_probe(pr);
673 blkid_probe_reset_buffer(pr);
674
675 if ((pr->flags & BLKID_FL_PRIVATE_FD) && pr->fd >= 0)
676 close(pr->fd);
677
678 pr->flags &= ~BLKID_FL_PRIVATE_FD;
679 pr->flags &= ~BLKID_FL_TINY_DEV;
680 pr->flags &= ~BLKID_FL_CDROM_DEV;
681 pr->prob_flags = 0;
682 pr->fd = fd;
683 pr->off = off;
684 pr->size = 0;
685 pr->devno = 0;
686 pr->disk_devno = 0;
687 pr->mode = 0;
688 pr->blkssz = 0;
689 pr->wipe_off = 0;
690 pr->wipe_size = 0;
691 pr->wipe_chain = NULL;
692
693 #if defined(POSIX_FADV_RANDOM) && defined(HAVE_POSIX_FADVISE)
694 /* Disable read-ahead */
695 posix_fadvise(fd, 0, 0, POSIX_FADV_RANDOM);
696 #endif
697 if (fstat(fd, &sb))
698 goto err;
699
700 if (!S_ISBLK(sb.st_mode) && !S_ISCHR(sb.st_mode) && !S_ISREG(sb.st_mode))
701 goto err;
702
703
704 pr->mode = sb.st_mode;
705 if (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode))
706 pr->devno = sb.st_rdev;
707
708 if (size)
709 pr->size = size;
710 else {
711 if (S_ISBLK(sb.st_mode)) {
712 if (blkdev_get_size(fd, (unsigned long long *) &pr->size)) {
713 DBG(LOWPROBE, ul_debug("failed to get device size"));
714 goto err;
715 }
716 } else if (S_ISCHR(sb.st_mode))
717 pr->size = 1; /* UBI devices are char... */
718 else if (S_ISREG(sb.st_mode))
719 pr->size = sb.st_size; /* regular file */
720
721 if (pr->off > pr->size)
722 goto err;
723
724 /* The probing area cannot be larger than whole device, pr->off
725 * is offset within the device */
726 pr->size -= pr->off;
727 }
728
729 if (pr->size <= 1440 * 1024 && !S_ISCHR(sb.st_mode))
730 pr->flags |= BLKID_FL_TINY_DEV;
731
732 if (S_ISBLK(sb.st_mode) && sysfs_devno_is_lvm_private(sb.st_rdev)) {
733 DBG(LOWPROBE, ul_debug("ignore private LVM device"));
734 pr->flags |= BLKID_FL_NOSCAN_DEV;
735 }
736
737 #ifdef CDROM_GET_CAPABILITY
738 else if (S_ISBLK(sb.st_mode) &&
739 !blkid_probe_is_tiny(pr) &&
740 blkid_probe_is_wholedisk(pr) &&
741 ioctl(fd, CDROM_GET_CAPABILITY, NULL) >= 0)
742 pr->flags |= BLKID_FL_CDROM_DEV;
743 #endif
744
745 DBG(LOWPROBE, ul_debug("ready for low-probing, offset=%jd, size=%jd",
746 pr->off, pr->size));
747 DBG(LOWPROBE, ul_debug("whole-disk: %s, regfile: %s",
748 blkid_probe_is_wholedisk(pr) ?"YES" : "NO",
749 S_ISREG(pr->mode) ? "YES" : "NO"));
750
751 return 0;
752 err:
753 DBG(LOWPROBE, ul_debug("failed to prepare a device for low-probing"));
754 return -1;
755
756 }
757
blkid_probe_get_dimension(blkid_probe pr,blkid_loff_t * off,blkid_loff_t * size)758 int blkid_probe_get_dimension(blkid_probe pr,
759 blkid_loff_t *off, blkid_loff_t *size)
760 {
761 if (!pr)
762 return -1;
763
764 *off = pr->off;
765 *size = pr->size;
766 return 0;
767 }
768
blkid_probe_set_dimension(blkid_probe pr,blkid_loff_t off,blkid_loff_t size)769 int blkid_probe_set_dimension(blkid_probe pr,
770 blkid_loff_t off, blkid_loff_t size)
771 {
772 if (!pr)
773 return -1;
774
775 DBG(LOWPROBE, ul_debug(
776 "changing probing area pr=%p: size=%llu, off=%llu "
777 "-to-> size=%llu, off=%llu",
778 pr,
779 (unsigned long long) pr->size,
780 (unsigned long long) pr->off,
781 (unsigned long long) size,
782 (unsigned long long) off));
783
784 pr->off = off;
785 pr->size = size;
786 pr->flags &= ~BLKID_FL_TINY_DEV;
787
788 if (pr->size <= 1440 * 1024 && !S_ISCHR(pr->mode))
789 pr->flags |= BLKID_FL_TINY_DEV;
790
791 blkid_probe_reset_buffer(pr);
792
793 return 0;
794 }
795
796 /*
797 * Check for matching magic value.
798 * Returns BLKID_PROBE_OK if found, BLKID_PROBE_NONE if not found
799 * or no magic present, or negative value on error.
800 */
blkid_probe_get_idmag(blkid_probe pr,const struct blkid_idinfo * id,blkid_loff_t * offset,const struct blkid_idmag ** res)801 int blkid_probe_get_idmag(blkid_probe pr, const struct blkid_idinfo *id,
802 blkid_loff_t *offset, const struct blkid_idmag **res)
803 {
804 const struct blkid_idmag *mag = NULL;
805 blkid_loff_t off = 0;
806
807 if (id)
808 mag = &id->magics[0];
809 if (res)
810 *res = NULL;
811
812 /* try to detect by magic string */
813 while(mag && mag->magic) {
814 unsigned char *buf;
815
816 off = (mag->kboff + (mag->sboff >> 10)) << 10;
817 buf = blkid_probe_get_buffer(pr, off, 1024);
818
819 if (!buf && errno)
820 return -errno;
821 if (buf && !memcmp(mag->magic,
822 buf + (mag->sboff & 0x3ff), mag->len)) {
823 DBG(LOWPROBE, ul_debug("\tmagic sboff=%u, kboff=%ld",
824 mag->sboff, mag->kboff));
825 if (offset)
826 *offset = off + (mag->sboff & 0x3ff);
827 if (res)
828 *res = mag;
829 return BLKID_PROBE_OK;
830 }
831 mag++;
832 }
833
834 if (id && id->magics[0].magic)
835 /* magic string(s) defined, but not found */
836 return BLKID_PROBE_NONE;
837
838 return BLKID_PROBE_OK;
839 }
840
blkid_probe_start(blkid_probe pr)841 static inline void blkid_probe_start(blkid_probe pr)
842 {
843 if (pr) {
844 DBG(LOWPROBE, ul_debug("%p: start probe", pr));
845 pr->cur_chain = NULL;
846 pr->prob_flags = 0;
847 blkid_probe_set_wiper(pr, 0, 0);
848 }
849 }
850
blkid_probe_end(blkid_probe pr)851 static inline void blkid_probe_end(blkid_probe pr)
852 {
853 if (pr) {
854 DBG(LOWPROBE, ul_debug("%p: end probe", pr));
855 pr->cur_chain = NULL;
856 pr->prob_flags = 0;
857 blkid_probe_set_wiper(pr, 0, 0);
858 }
859 }
860
861 /**
862 * blkid_do_probe:
863 * @pr: prober
864 *
865 * Calls probing functions in all enabled chains. The superblocks chain is
866 * enabled by default. The blkid_do_probe() stores result from only one
867 * probing function. It's necessary to call this routine in a loop to get
868 * results from all probing functions in all chains. The probing is reset
869 * by blkid_reset_probe() or by filter functions.
870 *
871 * This is string-based NAME=value interface only.
872 *
873 * <example>
874 * <title>basic case - use the first result only</title>
875 * <programlisting>
876 *
877 * if (blkid_do_probe(pr) == 0) {
878 * int nvals = blkid_probe_numof_values(pr);
879 * for (n = 0; n < nvals; n++) {
880 * if (blkid_probe_get_value(pr, n, &name, &data, &len) == 0)
881 * printf("%s = %s\n", name, data);
882 * }
883 * }
884 * </programlisting>
885 * </example>
886 *
887 * <example>
888 * <title>advanced case - probe for all signatures</title>
889 * <programlisting>
890 *
891 * while (blkid_do_probe(pr) == 0) {
892 * int nvals = blkid_probe_numof_values(pr);
893 * ...
894 * }
895 * </programlisting>
896 * </example>
897 *
898 * See also blkid_reset_probe().
899 *
900 * Returns: 0 on success, 1 when probing is done and -1 in case of error.
901 */
blkid_do_probe(blkid_probe pr)902 int blkid_do_probe(blkid_probe pr)
903 {
904 int rc = 1;
905
906 if (!pr)
907 return -1;
908
909 if (pr->flags & BLKID_FL_NOSCAN_DEV)
910 return 1;
911
912 do {
913 struct blkid_chain *chn = pr->cur_chain;
914
915 if (!chn) {
916 blkid_probe_start(pr);
917 chn = pr->cur_chain = &pr->chains[0];
918 }
919 /* we go to the next chain only when the previous probing
920 * result was nothing (rc == 1) and when the current chain is
921 * disabled or we are at end of the current chain (chain->idx +
922 * 1 == sizeof chain) or the current chain bailed out right at
923 * the start (chain->idx == -1)
924 */
925 else if (rc == 1 && (chn->enabled == FALSE ||
926 chn->idx + 1 == (int) chn->driver->nidinfos ||
927 chn->idx == -1)) {
928
929 size_t idx = chn->driver->id + 1;
930
931 if (idx < BLKID_NCHAINS)
932 chn = pr->cur_chain = &pr->chains[idx];
933 else {
934 blkid_probe_end(pr);
935 return 1; /* all chains already probed */
936 }
937 }
938
939 chn->binary = FALSE; /* for sure... */
940
941 DBG(LOWPROBE, ul_debug("chain probe %s %s (idx=%d)",
942 chn->driver->name,
943 chn->enabled? "ENABLED" : "DISABLED",
944 chn->idx));
945
946 if (!chn->enabled)
947 continue;
948
949 /* rc: -1 = error, 0 = success, 1 = no result */
950 rc = chn->driver->probe(pr, chn);
951
952 } while (rc == 1);
953
954 return rc;
955 }
956
957 /**
958 * blkid_do_wipe:
959 * @pr: prober
960 * @dryrun: if TRUE then don't touch the device.
961 *
962 * This function erases the current signature detected by @pr. The @pr has to
963 * be open in O_RDWR mode, BLKID_SUBLKS_MAGIC or/and BLKID_PARTS_MAGIC flags
964 * has to be enabled (if you want to errase also superblock with broken check
965 * sums then use BLKID_SUBLKS_BADCSUM too).
966 *
967 * After successful signature removing the @pr prober will be moved one step
968 * back and the next blkid_do_probe() call will again call previously called
969 * probing function.
970 *
971 * <example>
972 * <title>wipe all filesystems or raids from the device</title>
973 * <programlisting>
974 * fd = open(devname, O_RDWR|O_CLOEXEC);
975 * blkid_probe_set_device(pr, fd, 0, 0);
976 *
977 * blkid_probe_enable_superblocks(pr, 1);
978 * blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_MAGIC);
979 *
980 * while (blkid_do_probe(pr) == 0)
981 * blkid_do_wipe(pr, FALSE);
982 * </programlisting>
983 * </example>
984 *
985 * See also blkid_probe_step_back() if you cannot use this build-in wipe
986 * function, but you want to use libblkid probing as a source for wiping.
987 *
988 * Returns: 0 on success, and -1 in case of error.
989 */
blkid_do_wipe(blkid_probe pr,int dryrun)990 int blkid_do_wipe(blkid_probe pr, int dryrun)
991 {
992 const char *off = NULL;
993 size_t len = 0;
994 loff_t offset, l;
995 char buf[BUFSIZ];
996 int fd, rc = 0;
997 struct blkid_chain *chn;
998
999 if (!pr)
1000 return -1;
1001
1002 chn = pr->cur_chain;
1003 if (!chn)
1004 return -1;
1005
1006 switch (chn->driver->id) {
1007 case BLKID_CHAIN_SUBLKS:
1008 rc = blkid_probe_lookup_value(pr, "SBMAGIC_OFFSET", &off, NULL);
1009 if (!rc)
1010 rc = blkid_probe_lookup_value(pr, "SBMAGIC", NULL, &len);
1011 break;
1012 case BLKID_CHAIN_PARTS:
1013 rc = blkid_probe_lookup_value(pr, "PTMAGIC_OFFSET", &off, NULL);
1014 if (!rc)
1015 rc = blkid_probe_lookup_value(pr, "PTMAGIC", NULL, &len);
1016 break;
1017 default:
1018 return 0;
1019 }
1020
1021 if (rc || len == 0 || off == NULL)
1022 return 0;
1023
1024 offset = strtoll(off, NULL, 10);
1025 fd = blkid_probe_get_fd(pr);
1026 if (fd < 0)
1027 return -1;
1028
1029 if (len > sizeof(buf))
1030 len = sizeof(buf);
1031
1032 DBG(LOWPROBE, ul_debug(
1033 "do_wipe [offset=0x%jx, len=%zd, chain=%s, idx=%d, dryrun=%s]\n",
1034 offset, len, chn->driver->name, chn->idx, dryrun ? "yes" : "not"));
1035
1036 l = lseek(fd, offset, SEEK_SET);
1037 if (l == (off_t) -1)
1038 return -1;
1039
1040 memset(buf, 0, len);
1041
1042 if (!dryrun && len) {
1043 if (write_all(fd, buf, len))
1044 return -1;
1045 fsync(fd);
1046 return blkid_probe_step_back(pr);
1047 }
1048
1049 return 0;
1050 }
1051
1052 /**
1053 * blkid_probe_step_back:
1054 * @pr: prober
1055 *
1056 * This function move pointer to the probing chain one step back -- it means
1057 * that the previously used probing function will be called again in the next
1058 * blkid_do_probe() call.
1059 *
1060 * This is necessary for example if you erase or modify on-disk superblock
1061 * according to the current libblkid probing result.
1062 *
1063 * <example>
1064 * <title>wipe all superblock, but use libblkid only for probing</title>
1065 * <programlisting>
1066 * pr = blkid_new_probe_from_filename(devname);
1067 *
1068 * blkid_probe_enable_superblocks(pr, 1);
1069 * blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_MAGIC);
1070 *
1071 * blkid_probe_enable_partitions(pr, 1);
1072 * blkid_probe_set_partitions_flags(pr, BLKID_PARTS_MAGIC);
1073 *
1074 * while (blkid_do_probe(pr) == 0) {
1075 * const char *ostr = NULL;
1076 * size_t len = 0;
1077 *
1078 * // superblocks
1079 * if (blkid_probe_lookup_value(pr, "SBMAGIC_OFFSET", &ostr, NULL) == 0)
1080 * blkid_probe_lookup_value(pr, "SBMAGIC", NULL, &len);
1081 *
1082 * // partition tables
1083 * if (len == 0 && blkid_probe_lookup_value(pr, "PTMAGIC_OFFSET", &ostr, NULL) == 0)
1084 * blkid_probe_lookup_value(pr, "PTMAGIC", NULL, &len);
1085 *
1086 * if (!len || !str)
1087 * continue;
1088 *
1089 * // convert ostr to the real offset by off = strtoll(ostr, NULL, 10);
1090 * // use your stuff to errase @len bytes at the @off
1091 * ....
1092 *
1093 * // retry the last probing to check for backup superblocks ..etc.
1094 * blkid_probe_step_back(pr);
1095 * }
1096 * </programlisting>
1097 * </example>
1098 *
1099 * Returns: 0 on success, and -1 in case of error.
1100 */
blkid_probe_step_back(blkid_probe pr)1101 int blkid_probe_step_back(blkid_probe pr)
1102 {
1103 struct blkid_chain *chn;
1104
1105 if (!pr)
1106 return -1;
1107
1108 chn = pr->cur_chain;
1109 if (!chn)
1110 return -1;
1111
1112 blkid_probe_reset_buffer(pr);
1113
1114 if (chn->idx >= 0) {
1115 chn->idx--;
1116 DBG(LOWPROBE, ul_debug("step back: moving %s chain index to %d",
1117 chn->driver->name,
1118 chn->idx));
1119 }
1120
1121 if (chn->idx == -1) {
1122 /* blkid_do_probe() goes to the next chain if the index
1123 * of the current chain is -1, so we have to set the
1124 * chain pointer to the previous chain.
1125 */
1126 size_t idx = chn->driver->id > 0 ? chn->driver->id - 1 : 0;
1127
1128 DBG(LOWPROBE, ul_debug("step back: moving to previous chain"));
1129
1130 if (idx > 0)
1131 pr->cur_chain = &pr->chains[idx];
1132 else if (idx == 0)
1133 pr->cur_chain = NULL;
1134 }
1135
1136 return 0;
1137 }
1138
1139 /**
1140 * blkid_do_safeprobe:
1141 * @pr: prober
1142 *
1143 * This function gathers probing results from all enabled chains and checks
1144 * for ambivalent results (e.g. more filesystems on the device).
1145 *
1146 * This is string-based NAME=value interface only.
1147 *
1148 * Note about suberblocks chain -- the function does not check for filesystems
1149 * when a RAID signature is detected. The function also does not check for
1150 * collision between RAIDs. The first detected RAID is returned. The function
1151 * checks for collision between partition table and RAID signature -- it's
1152 * recommended to enable partitions chain together with superblocks chain.
1153 *
1154 * Returns: 0 on success, 1 if nothing is detected, -2 if ambivalen result is
1155 * detected and -1 on case of error.
1156 */
blkid_do_safeprobe(blkid_probe pr)1157 int blkid_do_safeprobe(blkid_probe pr)
1158 {
1159 int i, count = 0, rc = 0;
1160
1161 if (!pr)
1162 return -1;
1163 if (pr->flags & BLKID_FL_NOSCAN_DEV)
1164 return 1;
1165
1166 blkid_probe_start(pr);
1167
1168 for (i = 0; i < BLKID_NCHAINS; i++) {
1169 struct blkid_chain *chn;
1170
1171 chn = pr->cur_chain = &pr->chains[i];
1172 chn->binary = FALSE; /* for sure... */
1173
1174 DBG(LOWPROBE, ul_debug("chain safeprobe %s %s",
1175 chn->driver->name,
1176 chn->enabled? "ENABLED" : "DISABLED"));
1177
1178 if (!chn->enabled)
1179 continue;
1180
1181 blkid_probe_chain_reset_position(chn);
1182
1183 rc = chn->driver->safeprobe(pr, chn);
1184
1185 blkid_probe_chain_reset_position(chn);
1186
1187 /* rc: -2 ambivalent, -1 = error, 0 = success, 1 = no result */
1188 if (rc < 0)
1189 goto done; /* error */
1190 if (rc == 0)
1191 count++; /* success */
1192 }
1193
1194 done:
1195 blkid_probe_end(pr);
1196 if (rc < 0)
1197 return rc;
1198 return count ? 0 : 1;
1199 }
1200
1201 /**
1202 * blkid_do_fullprobe:
1203 * @pr: prober
1204 *
1205 * This function gathers probing results from all enabled chains. Same as
1206 * blkid_do_safeprobe() but does not check for collision between probing
1207 * result.
1208 *
1209 * This is string-based NAME=value interface only.
1210 *
1211 * Returns: 0 on success, 1 if nothing is detected or -1 on case of error.
1212 */
blkid_do_fullprobe(blkid_probe pr)1213 int blkid_do_fullprobe(blkid_probe pr)
1214 {
1215 int i, count = 0, rc = 0;
1216
1217 if (!pr)
1218 return -1;
1219 if (pr->flags & BLKID_FL_NOSCAN_DEV)
1220 return 1;
1221
1222 blkid_probe_start(pr);
1223
1224 for (i = 0; i < BLKID_NCHAINS; i++) {
1225 struct blkid_chain *chn;
1226
1227 chn = pr->cur_chain = &pr->chains[i];
1228 chn->binary = FALSE; /* for sure... */
1229
1230 DBG(LOWPROBE, ul_debug("chain fullprobe %s: %s",
1231 chn->driver->name,
1232 chn->enabled? "ENABLED" : "DISABLED"));
1233
1234 if (!chn->enabled)
1235 continue;
1236
1237 blkid_probe_chain_reset_position(chn);
1238
1239 rc = chn->driver->probe(pr, chn);
1240
1241 blkid_probe_chain_reset_position(chn);
1242
1243 /* rc: -1 = error, 0 = success, 1 = no result */
1244 if (rc < 0)
1245 goto done; /* error */
1246 if (rc == 0)
1247 count++; /* success */
1248 }
1249
1250 done:
1251 blkid_probe_end(pr);
1252 if (rc < 0)
1253 return rc;
1254 return count ? 0 : 1;
1255 }
1256
1257 /* same sa blkid_probe_get_buffer() but works with 512-sectors */
blkid_probe_get_sector(blkid_probe pr,unsigned int sector)1258 unsigned char *blkid_probe_get_sector(blkid_probe pr, unsigned int sector)
1259 {
1260 return pr ? blkid_probe_get_buffer(pr,
1261 ((blkid_loff_t) sector) << 9, 0x200) : NULL;
1262 }
1263
blkid_probe_assign_value(blkid_probe pr,const char * name)1264 struct blkid_prval *blkid_probe_assign_value(
1265 blkid_probe pr, const char *name)
1266 {
1267 struct blkid_prval *v;
1268
1269 if (!name)
1270 return NULL;
1271 if (pr->nvals >= BLKID_NVALS)
1272 return NULL;
1273
1274 v = &pr->vals[pr->nvals];
1275 v->name = name;
1276 v->chain = pr->cur_chain;
1277 pr->nvals++;
1278
1279 DBG(LOWPROBE, ul_debug("assigning %s [%s]", name, v->chain->driver->name));
1280 return v;
1281 }
1282
blkid_probe_reset_last_value(blkid_probe pr)1283 int blkid_probe_reset_last_value(blkid_probe pr)
1284 {
1285 struct blkid_prval *v;
1286
1287 if (pr == NULL || pr->nvals == 0)
1288 return -1;
1289
1290 v = &pr->vals[pr->nvals - 1];
1291
1292 DBG(LOWPROBE, ul_debug("un-assigning %s [%s]", v->name, v->chain->driver->name));
1293
1294 memset(v, 0, sizeof(struct blkid_prval));
1295 pr->nvals--;
1296
1297 return 0;
1298
1299 }
1300
blkid_probe_set_value(blkid_probe pr,const char * name,unsigned char * data,size_t len)1301 int blkid_probe_set_value(blkid_probe pr, const char *name,
1302 unsigned char *data, size_t len)
1303 {
1304 struct blkid_prval *v;
1305
1306 if (len > BLKID_PROBVAL_BUFSIZ)
1307 len = BLKID_PROBVAL_BUFSIZ;
1308
1309 v = blkid_probe_assign_value(pr, name);
1310 if (!v)
1311 return -1;
1312
1313 memcpy(v->data, data, len);
1314 v->len = len;
1315 return 0;
1316 }
1317
blkid_probe_vsprintf_value(blkid_probe pr,const char * name,const char * fmt,va_list ap)1318 int blkid_probe_vsprintf_value(blkid_probe pr, const char *name,
1319 const char *fmt, va_list ap)
1320 {
1321 struct blkid_prval *v;
1322 ssize_t len;
1323
1324 v = blkid_probe_assign_value(pr, name);
1325 if (!v)
1326 return -1;
1327
1328 len = vsnprintf((char *) v->data, sizeof(v->data), fmt, ap);
1329
1330 if (len <= 0 || (size_t) len >= sizeof(v->data)) {
1331 blkid_probe_reset_last_value(pr);
1332 return -1;
1333 }
1334 v->len = len + 1;
1335 return 0;
1336 }
1337
blkid_probe_sprintf_value(blkid_probe pr,const char * name,const char * fmt,...)1338 int blkid_probe_sprintf_value(blkid_probe pr, const char *name,
1339 const char *fmt, ...)
1340 {
1341 int rc;
1342 va_list ap;
1343
1344 va_start(ap, fmt);
1345 rc = blkid_probe_vsprintf_value(pr, name, fmt, ap);
1346 va_end(ap);
1347
1348 return rc;
1349 }
1350
blkid_probe_set_magic(blkid_probe pr,blkid_loff_t offset,size_t len,unsigned char * magic)1351 int blkid_probe_set_magic(blkid_probe pr, blkid_loff_t offset,
1352 size_t len, unsigned char *magic)
1353 {
1354 int rc = 0;
1355 struct blkid_chain *chn = blkid_probe_get_chain(pr);
1356
1357 if (!chn || !magic || !len || chn->binary)
1358 return 0;
1359
1360 switch (chn->driver->id) {
1361 case BLKID_CHAIN_SUBLKS:
1362 if (!(chn->flags & BLKID_SUBLKS_MAGIC))
1363 return 0;
1364 rc = blkid_probe_set_value(pr, "SBMAGIC", magic, len);
1365 if (!rc)
1366 rc = blkid_probe_sprintf_value(pr,
1367 "SBMAGIC_OFFSET", "%llu", (unsigned long long)offset);
1368 break;
1369 case BLKID_CHAIN_PARTS:
1370 if (!(chn->flags & BLKID_PARTS_MAGIC))
1371 return 0;
1372 rc = blkid_probe_set_value(pr, "PTMAGIC", magic, len);
1373 if (!rc)
1374 rc = blkid_probe_sprintf_value(pr,
1375 "PTMAGIC_OFFSET", "%llu", (unsigned long long)offset);
1376 break;
1377 default:
1378 break;
1379 }
1380
1381 return rc;
1382 }
1383
blkid_probe_verify_csum(blkid_probe pr,uint64_t csum,uint64_t expected)1384 int blkid_probe_verify_csum(blkid_probe pr, uint64_t csum, uint64_t expected)
1385 {
1386 if (csum != expected) {
1387 struct blkid_chain *chn = blkid_probe_get_chain(pr);
1388
1389 DBG(LOWPROBE, ul_debug(
1390 "incorrect checksum for type %s,"
1391 " got %jX, expected %jX",
1392 blkid_probe_get_probername(pr),
1393 csum, expected));
1394 /*
1395 * Accept bad checksum if BLKID_SUBLKS_BADCSUM flags is set
1396 */
1397 if (chn->driver->id == BLKID_CHAIN_SUBLKS
1398 && (chn->flags & BLKID_SUBLKS_BADCSUM)) {
1399 blkid_probe_set_value(pr, "SBBADCSUM", (unsigned char *) "1", 2);
1400 goto accept;
1401 }
1402 return 0; /* bad checksum */
1403 }
1404
1405 accept:
1406 return 1;
1407 }
1408
1409 /**
1410 * blkid_probe_get_devno:
1411 * @pr: probe
1412 *
1413 * Returns: block device number, or 0 for regular files.
1414 */
blkid_probe_get_devno(blkid_probe pr)1415 dev_t blkid_probe_get_devno(blkid_probe pr)
1416 {
1417 return pr->devno;
1418 }
1419
1420 /**
1421 * blkid_probe_get_wholedisk_devno:
1422 * @pr: probe
1423 *
1424 * Returns: device number of the wholedisk, or 0 for regular files.
1425 */
blkid_probe_get_wholedisk_devno(blkid_probe pr)1426 dev_t blkid_probe_get_wholedisk_devno(blkid_probe pr)
1427 {
1428 if (!pr->disk_devno) {
1429 dev_t devno, disk_devno = 0;
1430
1431 devno = blkid_probe_get_devno(pr);
1432 if (!devno)
1433 return 0;
1434
1435 if (blkid_devno_to_wholedisk(devno, NULL, 0, &disk_devno) == 0)
1436 pr->disk_devno = disk_devno;
1437 }
1438 return pr->disk_devno;
1439 }
1440
1441 /**
1442 * blkid_probe_is_wholedisk:
1443 * @pr: probe
1444 *
1445 * Returns: 1 if the device is whole-disk or 0.
1446 */
blkid_probe_is_wholedisk(blkid_probe pr)1447 int blkid_probe_is_wholedisk(blkid_probe pr)
1448 {
1449 dev_t devno, disk_devno;
1450
1451 devno = blkid_probe_get_devno(pr);
1452 if (!devno)
1453 return 0;
1454
1455 disk_devno = blkid_probe_get_wholedisk_devno(pr);
1456 if (!disk_devno)
1457 return 0;
1458
1459 return devno == disk_devno;
1460 }
1461
blkid_probe_get_wholedisk_probe(blkid_probe pr)1462 blkid_probe blkid_probe_get_wholedisk_probe(blkid_probe pr)
1463 {
1464 dev_t disk;
1465
1466 if (blkid_probe_is_wholedisk(pr))
1467 return NULL; /* this is not partition */
1468
1469 if (pr->parent)
1470 /* this is cloned blkid_probe, use parent's stuff */
1471 return blkid_probe_get_wholedisk_probe(pr->parent);
1472
1473 disk = blkid_probe_get_wholedisk_devno(pr);
1474
1475 if (pr->disk_probe && pr->disk_probe->devno != disk) {
1476 /* we have disk prober, but for another disk... close it */
1477 blkid_free_probe(pr->disk_probe);
1478 pr->disk_probe = NULL;
1479 }
1480
1481 if (!pr->disk_probe) {
1482 /* Open a new disk prober */
1483 char *disk_path = blkid_devno_to_devname(disk);
1484
1485 if (!disk_path)
1486 return NULL;
1487
1488 DBG(LOWPROBE, ul_debug("allocate a wholedisk probe"));
1489
1490 pr->disk_probe = blkid_new_probe_from_filename(disk_path);
1491
1492 free(disk_path);
1493
1494 if (!pr->disk_probe)
1495 return NULL; /* ENOMEM? */
1496 }
1497
1498 return pr->disk_probe;
1499 }
1500
1501 /**
1502 * blkid_probe_get_size:
1503 * @pr: probe
1504 *
1505 * This function returns size of probing area as defined by blkid_probe_set_device().
1506 * If the size of the probing area is unrestricted then this function returns
1507 * the real size of device. See also blkid_get_dev_size().
1508 *
1509 * Returns: size in bytes or -1 in case of error.
1510 */
blkid_probe_get_size(blkid_probe pr)1511 blkid_loff_t blkid_probe_get_size(blkid_probe pr)
1512 {
1513 return pr ? pr->size : -1;
1514 }
1515
1516 /**
1517 * blkid_probe_get_offset:
1518 * @pr: probe
1519 *
1520 * This function returns offset of probing area as defined by blkid_probe_set_device().
1521 *
1522 * Returns: offset in bytes or -1 in case of error.
1523 */
blkid_probe_get_offset(blkid_probe pr)1524 blkid_loff_t blkid_probe_get_offset(blkid_probe pr)
1525 {
1526 return pr ? pr->off : -1;
1527 }
1528
1529 /**
1530 * blkid_probe_get_fd:
1531 * @pr: probe
1532 *
1533 * Returns: file descriptor for assigned device/file or -1 in case of error.
1534 */
blkid_probe_get_fd(blkid_probe pr)1535 int blkid_probe_get_fd(blkid_probe pr)
1536 {
1537 return pr ? pr->fd : -1;
1538 }
1539
1540 /**
1541 * blkid_probe_get_sectorsize:
1542 * @pr: probe or NULL (for NULL returns 512)
1543 *
1544 * Returns: block device logical sector size (BLKSSZGET ioctl, default 512).
1545 */
blkid_probe_get_sectorsize(blkid_probe pr)1546 unsigned int blkid_probe_get_sectorsize(blkid_probe pr)
1547 {
1548 if (!pr)
1549 return DEFAULT_SECTOR_SIZE; /*... and good luck! */
1550
1551 if (pr->blkssz)
1552 return pr->blkssz;
1553
1554 if (S_ISBLK(pr->mode) &&
1555 blkdev_get_sector_size(pr->fd, (int *) &pr->blkssz) == 0)
1556 return pr->blkssz;
1557
1558 pr->blkssz = DEFAULT_SECTOR_SIZE;
1559 return pr->blkssz;
1560 }
1561
1562 /**
1563 * blkid_probe_get_sectors:
1564 * @pr: probe
1565 *
1566 * Returns: 512-byte sector count or -1 in case of error.
1567 */
blkid_probe_get_sectors(blkid_probe pr)1568 blkid_loff_t blkid_probe_get_sectors(blkid_probe pr)
1569 {
1570 return pr ? pr->size >> 9 : -1;
1571 }
1572
1573 /**
1574 * blkid_probe_numof_values:
1575 * @pr: probe
1576 *
1577 * Returns: number of values in probing result or -1 in case of error.
1578 */
blkid_probe_numof_values(blkid_probe pr)1579 int blkid_probe_numof_values(blkid_probe pr)
1580 {
1581 if (!pr)
1582 return -1;
1583 return pr->nvals;
1584 }
1585
1586 /**
1587 * blkid_probe_get_value:
1588 * @pr: probe
1589 * @num: wanted value in range 0..N, where N is blkid_probe_numof_values() - 1
1590 * @name: pointer to return value name or NULL
1591 * @data: pointer to return value data or NULL
1592 * @len: pointer to return value length or NULL
1593 *
1594 * Note, the @len returns length of the @data, including the terminating
1595 * '\0' character.
1596 *
1597 * Returns: 0 on success, or -1 in case of error.
1598 */
blkid_probe_get_value(blkid_probe pr,int num,const char ** name,const char ** data,size_t * len)1599 int blkid_probe_get_value(blkid_probe pr, int num, const char **name,
1600 const char **data, size_t *len)
1601 {
1602 struct blkid_prval *v = __blkid_probe_get_value(pr, num);
1603
1604 if (!v)
1605 return -1;
1606 if (name)
1607 *name = v->name;
1608 if (data)
1609 *data = (char *) v->data;
1610 if (len)
1611 *len = v->len;
1612
1613 DBG(LOWPROBE, ul_debug("returning %s value", v->name));
1614 return 0;
1615 }
1616
1617 /**
1618 * blkid_probe_lookup_value:
1619 * @pr: probe
1620 * @name: name of value
1621 * @data: pointer to return value data or NULL
1622 * @len: pointer to return value length or NULL
1623 *
1624 * Note, the @len returns length of the @data, including the terminating
1625 * '\0' character.
1626 *
1627 * Returns: 0 on success, or -1 in case of error.
1628 */
blkid_probe_lookup_value(blkid_probe pr,const char * name,const char ** data,size_t * len)1629 int blkid_probe_lookup_value(blkid_probe pr, const char *name,
1630 const char **data, size_t *len)
1631 {
1632 struct blkid_prval *v = __blkid_probe_lookup_value(pr, name);
1633
1634 if (!v)
1635 return -1;
1636 if (data)
1637 *data = (char *) v->data;
1638 if (len)
1639 *len = v->len;
1640 return 0;
1641 }
1642
1643 /**
1644 * blkid_probe_has_value:
1645 * @pr: probe
1646 * @name: name of value
1647 *
1648 * Returns: 1 if value exist in probing result, otherwise 0.
1649 */
blkid_probe_has_value(blkid_probe pr,const char * name)1650 int blkid_probe_has_value(blkid_probe pr, const char *name)
1651 {
1652 if (blkid_probe_lookup_value(pr, name, NULL, NULL) == 0)
1653 return 1;
1654 return 0;
1655 }
1656
__blkid_probe_get_value(blkid_probe pr,int num)1657 struct blkid_prval *__blkid_probe_get_value(blkid_probe pr, int num)
1658 {
1659 if (!pr || num < 0 || num >= pr->nvals)
1660 return NULL;
1661
1662 return &pr->vals[num];
1663 }
1664
__blkid_probe_lookup_value(blkid_probe pr,const char * name)1665 struct blkid_prval *__blkid_probe_lookup_value(blkid_probe pr, const char *name)
1666 {
1667 int i;
1668
1669 if (!pr || !pr->nvals || !name)
1670 return NULL;
1671
1672 for (i = 0; i < pr->nvals; i++) {
1673 struct blkid_prval *v = &pr->vals[i];
1674
1675 if (v->name && strcmp(name, v->name) == 0) {
1676 DBG(LOWPROBE, ul_debug("returning %s value", v->name));
1677 return v;
1678 }
1679 }
1680 return NULL;
1681 }
1682
1683
1684 /* converts DCE UUID (uuid[16]) to human readable string
1685 * - the @len should be always 37 */
1686 #ifdef HAVE_LIBUUID
blkid_unparse_uuid(const unsigned char * uuid,char * str,size_t len)1687 void blkid_unparse_uuid(const unsigned char *uuid, char *str,
1688 size_t len __attribute__((__unused__)))
1689 {
1690 uuid_unparse(uuid, str);
1691 }
1692 #else
blkid_unparse_uuid(const unsigned char * uuid,char * str,size_t len)1693 void blkid_unparse_uuid(const unsigned char *uuid, char *str, size_t len)
1694 {
1695 snprintf(str, len,
1696 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1697 uuid[0], uuid[1], uuid[2], uuid[3],
1698 uuid[4], uuid[5],
1699 uuid[6], uuid[7],
1700 uuid[8], uuid[9],
1701 uuid[10], uuid[11], uuid[12], uuid[13], uuid[14],uuid[15]);
1702 }
1703 #endif
1704
1705 /* like uuid_is_null() from libuuid, but works with arbitrary size of UUID */
blkid_uuid_is_empty(const unsigned char * buf,size_t len)1706 int blkid_uuid_is_empty(const unsigned char *buf, size_t len)
1707 {
1708 size_t i;
1709
1710 for (i = 0; i < len; i++)
1711 if (buf[i])
1712 return 0;
1713 return 1;
1714 }
1715
1716 /* Removes whitespace from the right-hand side of a string (trailing
1717 * whitespace).
1718 *
1719 * Returns size of the new string (without \0).
1720 */
blkid_rtrim_whitespace(unsigned char * str)1721 size_t blkid_rtrim_whitespace(unsigned char *str)
1722 {
1723 size_t i = strlen((char *) str);
1724
1725 while (i--) {
1726 if (!isspace(str[i]))
1727 break;
1728 }
1729 str[++i] = '\0';
1730 return i;
1731 }
1732
1733 /* Removes whitespace from the left-hand side of a string.
1734 *
1735 * Returns size of the new string (without \0).
1736 */
blkid_ltrim_whitespace(unsigned char * str)1737 size_t blkid_ltrim_whitespace(unsigned char *str)
1738 {
1739 size_t len;
1740 unsigned char *p;
1741
1742 for (p = str; p && isspace(*p); p++);
1743
1744 len = strlen((char *) p);
1745
1746 if (len && p > str)
1747 memmove(str, p, len + 1);
1748
1749 return len;
1750 }
1751 /*
1752 * Some mkfs-like utils wipe some parts (usually begin) of the device.
1753 * For example LVM (pvcreate) or mkswap(8). This information could be used
1754 * for later resolution to conflicts between superblocks.
1755 *
1756 * For example we found valid LVM superblock, LVM wipes 8KiB at the begin of
1757 * the device. If we found another signature (for example MBR) within the
1758 * wiped area then the signature has been added later and LVM superblock
1759 * should be ignore.
1760 *
1761 * Note that this heuristic is not 100% reliable, for example "pvcreate --zero
1762 * n" allows to keep the begin of the device unmodified. It's probably better
1763 * to use this heuristic for conflicts between superblocks and partition tables
1764 * than for conflicts between filesystem superblocks -- existence of unwanted
1765 * partition table is very unusual, because PT is pretty visible (parsed and
1766 * interpreted by kernel).
1767 *
1768 * Note that we usually expect only one signature on the device, it means that
1769 * we have to remember only one wiped area from previously successfully
1770 * detected signature.
1771 *
1772 * blkid_probe_set_wiper() -- defines wiped area (e.g. LVM)
1773 * blkid_probe_use_wiper() -- try to use area (e.g. MBR)
1774 *
1775 * Note that there is not relation between _wiper and blkid_to_wipe().
1776 *
1777 */
blkid_probe_set_wiper(blkid_probe pr,blkid_loff_t off,blkid_loff_t size)1778 void blkid_probe_set_wiper(blkid_probe pr, blkid_loff_t off, blkid_loff_t size)
1779 {
1780 struct blkid_chain *chn;
1781
1782 if (!pr)
1783 return;
1784
1785 if (!size) {
1786 DBG(LOWPROBE, ul_debug("zeroize wiper"));
1787 pr->wipe_size = pr->wipe_off = 0;
1788 pr->wipe_chain = NULL;
1789 return;
1790 }
1791
1792 chn = pr->cur_chain;
1793
1794 if (!chn || !chn->driver ||
1795 chn->idx < 0 || (size_t) chn->idx >= chn->driver->nidinfos)
1796 return;
1797
1798 pr->wipe_size = size;
1799 pr->wipe_off = off;
1800 pr->wipe_chain = chn;
1801
1802 DBG(LOWPROBE,
1803 ul_debug("wiper set to %s::%s off=%jd size=%jd",
1804 chn->driver->name,
1805 chn->driver->idinfos[chn->idx]->name,
1806 pr->wipe_off, pr->wipe_size));
1807 return;
1808 }
1809
1810 /*
1811 * Returns 1 if the <@off,@size> area was wiped
1812 */
blkid_probe_is_wiped(blkid_probe pr,struct blkid_chain ** chn,blkid_loff_t off,blkid_loff_t size)1813 int blkid_probe_is_wiped(blkid_probe pr, struct blkid_chain **chn,
1814 blkid_loff_t off, blkid_loff_t size)
1815 {
1816 if (!pr || !size)
1817 return 0;
1818
1819 if (pr->wipe_off <= off && off + size <= pr->wipe_off + pr->wipe_size) {
1820 if (chn)
1821 *chn = pr->wipe_chain;
1822 return 1;
1823 }
1824 return 0;
1825 }
1826
1827 /*
1828 * Try to use any area -- if the area has been previously wiped then the
1829 * previous probing result should be ignored (reseted).
1830 */
blkid_probe_use_wiper(blkid_probe pr,blkid_loff_t off,blkid_loff_t size)1831 void blkid_probe_use_wiper(blkid_probe pr, blkid_loff_t off, blkid_loff_t size)
1832 {
1833 struct blkid_chain *chn = NULL;
1834
1835 if (blkid_probe_is_wiped(pr, &chn, off, size) && chn) {
1836 DBG(LOWPROBE, ul_debug("previously wiped area modified "
1837 " -- ignore previous results"));
1838 blkid_probe_set_wiper(pr, 0, 0);
1839 blkid_probe_chain_reset_vals(pr, chn);
1840 }
1841 }
1842