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