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