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