]> git.ipfire.org Git - thirdparty/util-linux.git/blame - libblkid/src/probe.c
libblkid: check for multi-session CDROMs
[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
b9710f1f 392 if (chn && chn->idx >= 0 && (unsigned)chn->idx < chn->driver->nidinfos)
c89a1def
KZ
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
f12cd8d1 583static struct blkid_bufinfo *read_buffer(blkid_probe pr, uint64_t real_off, uint64_t len)
2355dd6a
KZ
584{
585 ssize_t ret;
586 struct blkid_bufinfo *bf = NULL;
587
588 if (blkid_llseek(pr->fd, real_off, SEEK_SET) < 0) {
589 errno = 0;
590 return NULL;
591 }
592
593 /* someone trying to overflow some buffers? */
594 if (len > ULONG_MAX - sizeof(struct blkid_bufinfo)) {
595 errno = ENOMEM;
596 return NULL;
597 }
598
599 /* allocate info and space for data by one malloc call */
600 bf = calloc(1, sizeof(struct blkid_bufinfo) + len);
601 if (!bf) {
602 errno = ENOMEM;
603 return NULL;
604 }
605
606 bf->data = ((unsigned char *) bf) + sizeof(struct blkid_bufinfo);
607 bf->len = len;
608 bf->off = real_off;
609 INIT_LIST_HEAD(&bf->bufs);
610
fdbd7bb9
RM
611 DBG(LOWPROBE, ul_debug("\tread %p: off=%"PRIu64" len=%"PRIu64"",
612 bf->data, real_off, len));
2355dd6a
KZ
613
614 ret = read(pr->fd, bf->data, len);
615 if (ret != (ssize_t) len) {
616 DBG(LOWPROBE, ul_debug("\tread failed: %m"));
617 free(bf);
618 if (ret >= 0)
619 errno = 0;
620 return NULL;
621 }
622
623 return bf;
624}
625
a674a0ab
KZ
626/*
627 * Note that @off is offset within probing area, the probing area is defined by
628 * pr->off and pr->size.
629 */
f12cd8d1 630unsigned char *blkid_probe_get_buffer(blkid_probe pr, uint64_t off, uint64_t len)
1ca17f91 631{
15a8fb42
KZ
632 struct list_head *p;
633 struct blkid_bufinfo *bf = NULL;
f12cd8d1 634 uint64_t real_off = pr->off + off;
a674a0ab
KZ
635
636 /*
637 DBG(BUFFER, ul_debug("\t>>>> off=%ju, real-off=%ju (probe <%ju..%ju>, len=%ju",
638 off, real_off, pr->off, pr->off + pr->size, len));
639 */
15a8fb42 640
f12cd8d1 641 if (pr->size == 0) {
00749bc3 642 errno = EINVAL;
88923b08 643 return NULL;
00749bc3 644 }
88923b08 645
a674a0ab
KZ
646 if (len == 0 || pr->off + pr->size < real_off + len) {
647 DBG(BUFFER, ul_debug("\t ignore: request out of probing area"));
648 errno = 0;
649 return NULL;
650 }
651
fd9f45e1
KZ
652 if (pr->parent &&
653 pr->parent->devno == pr->devno &&
ac8874ca
KZ
654 pr->parent->off <= pr->off &&
655 pr->parent->off + pr->parent->size >= pr->off + pr->size) {
fd9f45e1
KZ
656 /*
657 * This is a cloned prober and points to the same area as
ac8874ca
KZ
658 * parent. Let's use parent's buffers.
659 *
660 * Note that pr->off (and pr->parent->off) is always from the
a674a0ab 661 * begin of the device.
fd9f45e1 662 */
ac8874ca
KZ
663 return blkid_probe_get_buffer(pr->parent,
664 pr->off + off - pr->parent->off, len);
665 }
fd9f45e1 666
a674a0ab 667 /* try buffers we already have in memmory */
15a8fb42
KZ
668 list_for_each(p, &pr->buffers) {
669 struct blkid_bufinfo *x =
670 list_entry(p, struct blkid_bufinfo, bufs);
671
a674a0ab 672 if (real_off >= x->off && real_off + len <= x->off + x->len) {
fdbd7bb9 673 DBG(BUFFER, ul_debug("\treuse %p: off=%"PRIu64" len=%"PRIu64" (for off=%"PRIu64" len=%"PRIu64")",
f12cd8d1 674 x->data, x->off, x->len, real_off, len));
15a8fb42
KZ
675 bf = x;
676 break;
677 }
1ca17f91 678 }
1ca17f91 679
a674a0ab
KZ
680 /* not found; read from disk */
681 if (!bf) {
e04f3860 682 bf = read_buffer(pr, real_off, len);
a674a0ab 683 if (!bf)
1ca17f91 684 return NULL;
1ca17f91 685
15a8fb42 686 list_add_tail(&bf->bufs, &pr->buffers);
1ca17f91 687 }
15a8fb42 688
a674a0ab
KZ
689 assert(bf->off <= real_off);
690 assert(bf->off + bf->len >= real_off + len);
691
00749bc3 692 errno = 0;
a674a0ab 693 return real_off ? bf->data + (real_off - bf->off) : bf->data;
1ca17f91
KZ
694}
695
15a8fb42 696static void blkid_probe_reset_buffer(blkid_probe pr)
a0948ffe 697{
2355dd6a 698 uint64_t ct = 0, len = 0;
15a8fb42
KZ
699
700 if (!pr || list_empty(&pr->buffers))
701 return;
702
a674a0ab 703 DBG(BUFFER, ul_debug("reseting probing buffers pr=%p", pr));
15a8fb42
KZ
704
705 while (!list_empty(&pr->buffers)) {
706 struct blkid_bufinfo *bf = list_entry(pr->buffers.next,
707 struct blkid_bufinfo, bufs);
2355dd6a
KZ
708 ct++;
709 len += bf->len;
15a8fb42 710 list_del(&bf->bufs);
a674a0ab 711
fdbd7bb9
RM
712 DBG(BUFFER, ul_debug(" remove buffer: %p [off=%"PRIu64", len=%"PRIu64"]",
713 bf->data, bf->off, bf->len));
15a8fb42 714 free(bf);
4884729a 715 }
15a8fb42 716
e04f3860 717 DBG(LOWPROBE, ul_debug(" buffers summary: %"PRIu64" bytes by %"PRIu64" read() calls",
2355dd6a 718 len, ct));
15a8fb42
KZ
719
720 INIT_LIST_HEAD(&pr->buffers);
a0948ffe
KZ
721}
722
af17d349 723static void blkid_probe_reset_values(blkid_probe pr)
6c4a7811 724{
af17d349 725 if (!pr || list_empty(&pr->values))
6c4a7811
OO
726 return;
727
728 DBG(LOWPROBE, ul_debug("resetting results pr=%p", pr));
729
af17d349
KZ
730 while (!list_empty(&pr->values)) {
731 struct blkid_prval *v = list_entry(pr->values.next,
6c4a7811 732 struct blkid_prval, prvals);
af17d349 733 blkid_probe_free_value(v);
6c4a7811
OO
734 }
735
af17d349 736 INIT_LIST_HEAD(&pr->values);
6c4a7811
OO
737}
738
108013b4
KZ
739/*
740 * Small devices need a special care.
741 */
742int blkid_probe_is_tiny(blkid_probe pr)
743{
a9eef56c 744 return pr && (pr->flags & BLKID_FL_TINY_DEV);
108013b4
KZ
745}
746
55113b15
C
747/*
748 * CDROMs may fail when probed for RAID (last sector problem)
749 */
750int blkid_probe_is_cdrom(blkid_probe pr)
751{
a9eef56c 752 return pr && (pr->flags & BLKID_FL_CDROM_DEV);
55113b15
C
753}
754
bfebe74e
KZ
755static int is_sector_readable(int fd, uint64_t sector)
756{
757 char buf[512];
758 ssize_t sz;
759
760 if (blkid_llseek(fd, sector * 512, SEEK_SET) < 0)
761 goto failed;
762
763 sz = read(fd, buf, sizeof(buf));
764 if (sz != (ssize_t) sizeof(buf))
765 goto failed;
766
767 return 1;
768failed:
769 DBG(LOWPROBE, ul_debug("CDROM: read sector %ju failed %m", sector));
770 errno = 0;
771 return 0;
772}
773
774/*
a14cc9a5
KZ
775 * Issue #1:
776 *
777 * On hybrid mutil-session media (audio+data) we get I/O errors almost
778 * everywhere. The solution is to specify probing offset to the wanted
779 * session. Udev uses this way when it calls libblkid (the proper data session
780 * offset is based on ID_CDROM_MEDIA_SESSION_LAST_OFFSET from by udev cdrom_id
781 * tool).
782 *
783 * Unfortunately, it means that blkid will be blind when executed without a
784 * probing offset, to avoid this problem we use CDROMMULTISESSION ioctl to get
785 * last session offset. This way also uses iso9660 fyslesystem kernel driver
786 * when you mount mutil-session CD without a sesssion= mount option.
787 *
788 * Issue #2:
789 *
790 * Linux kernel reports (BLKGETSIZE) cdrom device size greater than area
791 * readable by read(2). We have to reduce the probing area to avoid unwanted
792 * I/O errors in probing functions. It seems that unreadable are always last 2
793 * or 3 CD blocks (CD block size is 2048 bytes, it means 12 in 512-byte
794 * sectors).
bfebe74e
KZ
795 */
796static void cdrom_size_correction(blkid_probe pr)
797{
a14cc9a5
KZ
798 uint64_t size, n, nsectors;
799
800 /* move offset */
801#ifdef CDROMMULTISESSION
802 if (pr->off == 0) {
803 struct cdrom_multisession ms_info = { 0 };
804 int i;
805
806 ms_info.addr_format = CDROM_LBA;
807 i = ioctl(pr->fd, CDROMMULTISESSION, (unsigned long) &ms_info);
808 if (i == 0 && ms_info.xa_flag) {
809 DBG(LOWPROBE, ul_debug("CDROM: multisession last session start: %u (CD sectors)", ms_info.addr.lba));
810
811 pr->off = (uint64_t) ms_info.addr.lba * 2048;
812 DBG(LOWPROBE, ul_debug("CDROM: moving probing offset from 0 to %ju", pr->off));
813
814 size = pr->size - pr->off;
815 DBG(LOWPROBE, ul_debug("CDROM: reduce probing size from %ju to %ju", pr->size, size));
816 pr->size = size;
817 }
818 }
819#endif
820
821 /* reduce size */
822 nsectors = pr->size >> 9;
bfebe74e
KZ
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;
831failed:
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,
1bd62f72 835 (uintmax_t) n << 9));
bfebe74e
KZ
836 pr->size = n << 9;
837}
838
52448df8
KZ
839/**
840 * blkid_probe_set_device:
841 * @pr: probe
842 * @fd: device file descriptor
843 * @off: begin of probing area
f38db0cf 844 * @size: size of probing area (zero means whole device/file)
52448df8
KZ
845 *
846 * Assigns the device to probe control struct, resets internal buffers and
44ef90bc 847 * resets the current probing.
51410fc6 848 *
52448df8 849 * Returns: -1 in case of failure, or 0 on success.
51410fc6
KZ
850 */
851int blkid_probe_set_device(blkid_probe pr, int fd,
852 blkid_loff_t off, blkid_loff_t size)
a0948ffe 853{
90ec8d9c 854 struct stat sb;
f12cd8d1 855 uint64_t devsiz = 0;
90ec8d9c 856
51410fc6
KZ
857 if (!pr)
858 return -1;
a0948ffe 859
51410fc6 860 blkid_reset_probe(pr);
ccdf9fda 861 blkid_probe_reset_buffer(pr);
a0948ffe 862
a9eef56c 863 if ((pr->flags & BLKID_FL_PRIVATE_FD) && pr->fd >= 0)
f38db0cf
KZ
864 close(pr->fd);
865
a9eef56c
KZ
866 pr->flags &= ~BLKID_FL_PRIVATE_FD;
867 pr->flags &= ~BLKID_FL_TINY_DEV;
868 pr->flags &= ~BLKID_FL_CDROM_DEV;
ccdf9fda 869 pr->prob_flags = 0;
51410fc6 870 pr->fd = fd;
f12cd8d1 871 pr->off = (uint64_t) off;
bb6c6673 872 pr->size = 0;
52448df8 873 pr->devno = 0;
ccdf9fda 874 pr->disk_devno = 0;
52448df8
KZ
875 pr->mode = 0;
876 pr->blkssz = 0;
ccdf9fda
KZ
877 pr->wipe_off = 0;
878 pr->wipe_size = 0;
879 pr->wipe_chain = NULL;
dc61d909 880
a67bb3bf
LT
881#if defined(POSIX_FADV_RANDOM) && defined(HAVE_POSIX_FADVISE)
882 /* Disable read-ahead */
883 posix_fadvise(fd, 0, 0, POSIX_FADV_RANDOM);
884#endif
90ec8d9c
KZ
885 if (fstat(fd, &sb))
886 goto err;
887
a674a0ab 888 if (!S_ISBLK(sb.st_mode) && !S_ISCHR(sb.st_mode) && !S_ISREG(sb.st_mode)) {
2355dd6a 889 errno = EINVAL;
26eb5a59 890 goto err;
a674a0ab 891 }
20e1c3dc 892
90ec8d9c
KZ
893 pr->mode = sb.st_mode;
894 if (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode))
895 pr->devno = sb.st_rdev;
896
a674a0ab
KZ
897 if (S_ISBLK(sb.st_mode)) {
898 if (blkdev_get_size(fd, (unsigned long long *) &devsiz)) {
899 DBG(LOWPROBE, ul_debug("failed to get device size"));
108013b4 900 goto err;
a674a0ab
KZ
901 }
902 } else if (S_ISCHR(sb.st_mode))
903 devsiz = 1; /* UBI devices are char... */
904 else if (S_ISREG(sb.st_mode))
905 devsiz = sb.st_size; /* regular file */
906
b9710f1f 907 pr->size = size ? (uint64_t)size : devsiz;
108013b4 908
a674a0ab
KZ
909 if (off && size == 0)
910 /* only offset without size specified */
f12cd8d1 911 pr->size -= (uint64_t) off;
a674a0ab
KZ
912
913 if (pr->off + pr->size > devsiz) {
914 DBG(LOWPROBE, ul_debug("area specified by offset and size is bigger than device"));
915 errno = EINVAL;
916 goto err;
bb6c6673 917 }
c1ba7962 918
90ec8d9c 919 if (pr->size <= 1440 * 1024 && !S_ISCHR(sb.st_mode))
a9eef56c 920 pr->flags |= BLKID_FL_TINY_DEV;
d0465c3c 921
39866431 922 if (S_ISBLK(sb.st_mode) && sysfs_devno_is_lvm_private(sb.st_rdev)) {
20e1c3dc
KZ
923 DBG(LOWPROBE, ul_debug("ignore private LVM device"));
924 pr->flags |= BLKID_FL_NOSCAN_DEV;
925 }
926
55113b15 927#ifdef CDROM_GET_CAPABILITY
20e1c3dc 928 else if (S_ISBLK(sb.st_mode) &&
a3ab71cf
KZ
929 !blkid_probe_is_tiny(pr) &&
930 blkid_probe_is_wholedisk(pr) &&
bfebe74e
KZ
931 ioctl(fd, CDROM_GET_CAPABILITY, NULL) >= 0) {
932
a9eef56c 933 pr->flags |= BLKID_FL_CDROM_DEV;
bfebe74e
KZ
934 cdrom_size_correction(pr);
935 }
55113b15 936#endif
508e438b 937
fdbd7bb9 938 DBG(LOWPROBE, ul_debug("ready for low-probing, offset=%"PRIu64", size=%"PRIu64"",
508e438b 939 pr->off, pr->size));
c62a6311 940 DBG(LOWPROBE, ul_debug("whole-disk: %s, regfile: %s",
508e438b
KZ
941 blkid_probe_is_wholedisk(pr) ?"YES" : "NO",
942 S_ISREG(pr->mode) ? "YES" : "NO"));
943
a0948ffe 944 return 0;
0d17b1cf 945err:
c62a6311 946 DBG(LOWPROBE, ul_debug("failed to prepare a device for low-probing"));
0d17b1cf
KZ
947 return -1;
948
a0948ffe
KZ
949}
950
f12cd8d1 951int blkid_probe_get_dimension(blkid_probe pr, uint64_t *off, uint64_t *size)
f319b5ca
KZ
952{
953 if (!pr)
954 return -1;
955
956 *off = pr->off;
957 *size = pr->size;
958 return 0;
959}
960
f12cd8d1 961int blkid_probe_set_dimension(blkid_probe pr, uint64_t off, uint64_t size)
f319b5ca
KZ
962{
963 if (!pr)
964 return -1;
965
c62a6311 966 DBG(LOWPROBE, ul_debug(
fdbd7bb9
RM
967 "changing probing area pr=%p: size=%"PRIu64", off=%"PRIu64" "
968 "-to-> size=%"PRIu64", off=%"PRIu64"",
f12cd8d1 969 pr, pr->size, pr->off, size, off));
f319b5ca
KZ
970
971 pr->off = off;
972 pr->size = size;
a9eef56c 973 pr->flags &= ~BLKID_FL_TINY_DEV;
88923b08 974
f12cd8d1 975 if (pr->size <= 1440ULL * 1024ULL && !S_ISCHR(pr->mode))
a9eef56c 976 pr->flags |= BLKID_FL_TINY_DEV;
f319b5ca
KZ
977
978 blkid_probe_reset_buffer(pr);
979
980 return 0;
981}
982
8d0ce083 983/*
296d96e2
HR
984 * Check for matching magic value.
985 * Returns BLKID_PROBE_OK if found, BLKID_PROBE_NONE if not found
986 * or no magic present, or negative value on error.
987 */
c76e710b 988int blkid_probe_get_idmag(blkid_probe pr, const struct blkid_idinfo *id,
f12cd8d1 989 uint64_t *offset, const struct blkid_idmag **res)
c76e710b
KZ
990{
991 const struct blkid_idmag *mag = NULL;
f12cd8d1 992 uint64_t off = 0;
c76e710b
KZ
993
994 if (id)
c03d12d8 995 mag = &id->magics[0];
c76e710b
KZ
996 if (res)
997 *res = NULL;
998
999 /* try to detect by magic string */
1000 while(mag && mag->magic) {
1001 unsigned char *buf;
1002
1003 off = (mag->kboff + (mag->sboff >> 10)) << 10;
1004 buf = blkid_probe_get_buffer(pr, off, 1024);
1005
296d96e2
HR
1006 if (!buf && errno)
1007 return -errno;
a674a0ab 1008
c76e710b
KZ
1009 if (buf && !memcmp(mag->magic,
1010 buf + (mag->sboff & 0x3ff), mag->len)) {
a674a0ab 1011
c62a6311 1012 DBG(LOWPROBE, ul_debug("\tmagic sboff=%u, kboff=%ld",
c76e710b
KZ
1013 mag->sboff, mag->kboff));
1014 if (offset)
1015 *offset = off + (mag->sboff & 0x3ff);
1016 if (res)
1017 *res = mag;
296d96e2 1018 return BLKID_PROBE_OK;
c76e710b
KZ
1019 }
1020 mag++;
1021 }
1022
c03d12d8 1023 if (id && id->magics[0].magic)
c76e710b 1024 /* magic string(s) defined, but not found */
296d96e2 1025 return BLKID_PROBE_NONE;
c76e710b 1026
296d96e2 1027 return BLKID_PROBE_OK;
c76e710b
KZ
1028}
1029
c81e7008
KZ
1030static inline void blkid_probe_start(blkid_probe pr)
1031{
1032 if (pr) {
c62a6311 1033 DBG(LOWPROBE, ul_debug("%p: start probe", pr));
c81e7008
KZ
1034 pr->cur_chain = NULL;
1035 pr->prob_flags = 0;
8b7eae45 1036 blkid_probe_set_wiper(pr, 0, 0);
c81e7008
KZ
1037 }
1038}
1039
1040static inline void blkid_probe_end(blkid_probe pr)
1041{
1042 if (pr) {
c62a6311 1043 DBG(LOWPROBE, ul_debug("%p: end probe", pr));
c81e7008
KZ
1044 pr->cur_chain = NULL;
1045 pr->prob_flags = 0;
8b7eae45 1046 blkid_probe_set_wiper(pr, 0, 0);
c81e7008
KZ
1047 }
1048}
1049
0bffad47
KZ
1050/**
1051 * blkid_do_probe:
1052 * @pr: prober
1053 *
1054 * Calls probing functions in all enabled chains. The superblocks chain is
1055 * enabled by default. The blkid_do_probe() stores result from only one
1056 * probing function. It's necessary to call this routine in a loop to get
3b159691 1057 * results from all probing functions in all chains. The probing is reset
44ef90bc 1058 * by blkid_reset_probe() or by filter functions.
a0fc685c 1059 *
0bffad47
KZ
1060 * This is string-based NAME=value interface only.
1061 *
1062 * <example>
1063 * <title>basic case - use the first result only</title>
1064 * <programlisting>
a0fc685c
KZ
1065 * if (blkid_do_probe(pr) == 0) {
1066 * int nvals = blkid_probe_numof_values(pr);
1067 * for (n = 0; n < nvals; n++) {
1068 * if (blkid_probe_get_value(pr, n, &name, &data, &len) == 0)
1069 * printf("%s = %s\n", name, data);
1070 * }
1071 * }
0bffad47
KZ
1072 * </programlisting>
1073 * </example>
a0fc685c 1074 *
0bffad47
KZ
1075 * <example>
1076 * <title>advanced case - probe for all signatures</title>
1077 * <programlisting>
a0fc685c
KZ
1078 * while (blkid_do_probe(pr) == 0) {
1079 * int nvals = blkid_probe_numof_values(pr);
1080 * ...
1081 * }
0bffad47
KZ
1082 * </programlisting>
1083 * </example>
a0fc685c 1084 *
0bffad47 1085 * See also blkid_reset_probe().
a0fc685c 1086 *
0bffad47 1087 * Returns: 0 on success, 1 when probing is done and -1 in case of error.
a0fc685c 1088 */
51410fc6 1089int blkid_do_probe(blkid_probe pr)
a0948ffe 1090{
0bffad47 1091 int rc = 1;
a0948ffe 1092
0bffad47 1093 if (!pr)
51410fc6 1094 return -1;
a0948ffe 1095
20e1c3dc
KZ
1096 if (pr->flags & BLKID_FL_NOSCAN_DEV)
1097 return 1;
1098
0bffad47 1099 do {
44ef90bc
KZ
1100 struct blkid_chain *chn = pr->cur_chain;
1101
c81e7008
KZ
1102 if (!chn) {
1103 blkid_probe_start(pr);
44ef90bc 1104 chn = pr->cur_chain = &pr->chains[0];
c81e7008 1105 }
44ef90bc
KZ
1106 /* we go to the next chain only when the previous probing
1107 * result was nothing (rc == 1) and when the current chain is
1108 * disabled or we are at end of the current chain (chain->idx +
046959cc
CW
1109 * 1 == sizeof chain) or the current chain bailed out right at
1110 * the start (chain->idx == -1)
44ef90bc
KZ
1111 */
1112 else if (rc == 1 && (chn->enabled == FALSE ||
c9f51c71 1113 chn->idx + 1 == (int) chn->driver->nidinfos ||
046959cc 1114 chn->idx == -1)) {
a0948ffe 1115
c9f51c71 1116 size_t idx = chn->driver->id + 1;
bd635f86
KZ
1117
1118 if (idx < BLKID_NCHAINS)
44ef90bc 1119 chn = pr->cur_chain = &pr->chains[idx];
c81e7008
KZ
1120 else {
1121 blkid_probe_end(pr);
bd635f86 1122 return 1; /* all chains already probed */
c81e7008 1123 }
bd635f86 1124 }
a0fc685c 1125
0bffad47 1126 chn->binary = FALSE; /* for sure... */
6644688a 1127
c62a6311 1128 DBG(LOWPROBE, ul_debug("chain probe %s %s (idx=%d)",
0bffad47 1129 chn->driver->name,
44ef90bc
KZ
1130 chn->enabled? "ENABLED" : "DISABLED",
1131 chn->idx));
a0948ffe 1132
0bffad47 1133 if (!chn->enabled)
51410fc6 1134 continue;
a0948ffe 1135
0bffad47
KZ
1136 /* rc: -1 = error, 0 = success, 1 = no result */
1137 rc = chn->driver->probe(pr, chn);
a0948ffe 1138
0bffad47 1139 } while (rc == 1);
a0948ffe 1140
0bffad47
KZ
1141 return rc;
1142}
a0948ffe 1143
2b89be6c
KZ
1144/**
1145 * blkid_do_wipe:
1146 * @pr: prober
1147 * @dryrun: if TRUE then don't touch the device.
1148 *
1149 * This function erases the current signature detected by @pr. The @pr has to
476b508e 1150 * be open in O_RDWR mode, BLKID_SUBLKS_MAGIC or/and BLKID_PARTS_MAGIC flags
c93c2030
KZ
1151 * has to be enabled (if you want to errase also superblock with broken check
1152 * sums then use BLKID_SUBLKS_BADCSUM too).
2b89be6c
KZ
1153 *
1154 * After successful signature removing the @pr prober will be moved one step
1155 * back and the next blkid_do_probe() call will again call previously called
1156 * probing function.
1157 *
1158 * <example>
1159 * <title>wipe all filesystems or raids from the device</title>
1160 * <programlisting>
49a8f58e 1161 * fd = open(devname, O_RDWR|O_CLOEXEC);
2b89be6c
KZ
1162 * blkid_probe_set_device(pr, fd, 0, 0);
1163 *
1164 * blkid_probe_enable_superblocks(pr, 1);
1165 * blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_MAGIC);
1166 *
1167 * while (blkid_do_probe(pr) == 0)
1168 * blkid_do_wipe(pr, FALSE);
1169 * </programlisting>
1170 * </example>
1171 *
cd0fe5c1
KZ
1172 * See also blkid_probe_step_back() if you cannot use this build-in wipe
1173 * function, but you want to use libblkid probing as a source for wiping.
1174 *
1175 * Returns: 0 on success, and -1 in case of error.
2b89be6c
KZ
1176 */
1177int blkid_do_wipe(blkid_probe pr, int dryrun)
1178{
44765fdd 1179 const char *off = NULL;
2b89be6c 1180 size_t len = 0;
f12cd8d1 1181 uint64_t offset, l;
2b89be6c 1182 char buf[BUFSIZ];
f8054232 1183 int fd, rc = 0;
2b89be6c
KZ
1184 struct blkid_chain *chn;
1185
1186 if (!pr)
1187 return -1;
1188
1189 chn = pr->cur_chain;
1190 if (!chn)
1191 return -1;
1192
44765fdd
KZ
1193 switch (chn->driver->id) {
1194 case BLKID_CHAIN_SUBLKS:
1195 rc = blkid_probe_lookup_value(pr, "SBMAGIC_OFFSET", &off, NULL);
1196 if (!rc)
1197 rc = blkid_probe_lookup_value(pr, "SBMAGIC", NULL, &len);
1198 break;
1199 case BLKID_CHAIN_PARTS:
1200 rc = blkid_probe_lookup_value(pr, "PTMAGIC_OFFSET", &off, NULL);
1201 if (!rc)
1202 rc = blkid_probe_lookup_value(pr, "PTMAGIC", NULL, &len);
1203 break;
1204 default:
1205 return 0;
1206 }
1207
1208 if (rc || len == 0 || off == NULL)
2b89be6c
KZ
1209 return 0;
1210
445e6b1e 1211 offset = strtoumax(off, NULL, 10) + pr->off;
2b89be6c
KZ
1212 fd = blkid_probe_get_fd(pr);
1213 if (fd < 0)
1214 return -1;
1215
1216 if (len > sizeof(buf))
1217 len = sizeof(buf);
1218
c62a6311 1219 DBG(LOWPROBE, ul_debug(
fdbd7bb9 1220 "do_wipe [offset=0x%"PRIx64" (%"PRIu64"), len=%zu, chain=%s, idx=%d, dryrun=%s]\n",
f12cd8d1 1221 offset, offset, len, chn->driver->name, chn->idx, dryrun ? "yes" : "not"));
2b89be6c 1222
f12cd8d1 1223 l = blkid_llseek(fd, offset, SEEK_SET);
b9710f1f 1224 if ((blkid_loff_t)l == (off_t) -1)
2b89be6c
KZ
1225 return -1;
1226
1227 memset(buf, 0, len);
1228
1229 if (!dryrun && len) {
1230 if (write_all(fd, buf, len))
1231 return -1;
1232 fsync(fd);
cd0fe5c1
KZ
1233 return blkid_probe_step_back(pr);
1234 }
2b89be6c 1235
cd0fe5c1
KZ
1236 return 0;
1237}
2b89be6c 1238
cd0fe5c1 1239/**
c0055e2a 1240 * blkid_probe_step_back:
cd0fe5c1
KZ
1241 * @pr: prober
1242 *
1243 * This function move pointer to the probing chain one step back -- it means
1244 * that the previously used probing function will be called again in the next
1245 * blkid_do_probe() call.
1246 *
1247 * This is necessary for example if you erase or modify on-disk superblock
1248 * according to the current libblkid probing result.
1249 *
1250 * <example>
1251 * <title>wipe all superblock, but use libblkid only for probing</title>
1252 * <programlisting>
1253 * pr = blkid_new_probe_from_filename(devname);
1254 *
1255 * blkid_probe_enable_superblocks(pr, 1);
1256 * blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_MAGIC);
1257 *
2bb7a706
KZ
1258 * blkid_probe_enable_partitions(pr, 1);
1259 * blkid_probe_set_partitions_flags(pr, BLKID_PARTS_MAGIC);
1260 *
cd0fe5c1
KZ
1261 * while (blkid_do_probe(pr) == 0) {
1262 * const char *ostr = NULL;
1263 * size_t len = 0;
1264 *
1265 * // superblocks
1266 * if (blkid_probe_lookup_value(pr, "SBMAGIC_OFFSET", &ostr, NULL) == 0)
1267 * blkid_probe_lookup_value(pr, "SBMAGIC", NULL, &len);
1268 *
1269 * // partition tables
1270 * if (len == 0 && blkid_probe_lookup_value(pr, "PTMAGIC_OFFSET", &ostr, NULL) == 0)
1271 * blkid_probe_lookup_value(pr, "PTMAGIC", NULL, &len);
1272 *
1273 * if (!len || !str)
1274 * continue;
1275 *
1276 * // convert ostr to the real offset by off = strtoll(ostr, NULL, 10);
1277 * // use your stuff to errase @len bytes at the @off
1278 * ....
1279 *
1280 * // retry the last probing to check for backup superblocks ..etc.
1281 * blkid_probe_step_back(pr);
1282 * }
1283 * </programlisting>
1284 * </example>
1285 *
1286 * Returns: 0 on success, and -1 in case of error.
1287 */
1288int blkid_probe_step_back(blkid_probe pr)
1289{
1290 struct blkid_chain *chn;
1291
1292 if (!pr)
1293 return -1;
1294
1295 chn = pr->cur_chain;
1296 if (!chn)
1297 return -1;
1298
1299 blkid_probe_reset_buffer(pr);
1300
1301 if (chn->idx >= 0) {
1302 chn->idx--;
c62a6311 1303 DBG(LOWPROBE, ul_debug("step back: moving %s chain index to %d",
cd0fe5c1
KZ
1304 chn->driver->name,
1305 chn->idx));
2b89be6c 1306 }
cd0fe5c1
KZ
1307
1308 if (chn->idx == -1) {
1309 /* blkid_do_probe() goes to the next chain if the index
1310 * of the current chain is -1, so we have to set the
1311 * chain pointer to the previous chain.
1312 */
1313 size_t idx = chn->driver->id > 0 ? chn->driver->id - 1 : 0;
1314
c62a6311 1315 DBG(LOWPROBE, ul_debug("step back: moving to previous chain"));
cd0fe5c1
KZ
1316
1317 if (idx > 0)
1318 pr->cur_chain = &pr->chains[idx];
1319 else if (idx == 0)
1320 pr->cur_chain = NULL;
1321 }
1322
2b89be6c
KZ
1323 return 0;
1324}
1325
0bffad47
KZ
1326/**
1327 * blkid_do_safeprobe:
1328 * @pr: prober
1329 *
1330 * This function gathers probing results from all enabled chains and checks
1331 * for ambivalent results (e.g. more filesystems on the device).
1332 *
1333 * This is string-based NAME=value interface only.
1334 *
1335 * Note about suberblocks chain -- the function does not check for filesystems
1336 * when a RAID signature is detected. The function also does not check for
c81e7008
KZ
1337 * collision between RAIDs. The first detected RAID is returned. The function
1338 * checks for collision between partition table and RAID signature -- it's
1339 * recommended to enable partitions chain together with superblocks chain.
0bffad47
KZ
1340 *
1341 * Returns: 0 on success, 1 if nothing is detected, -2 if ambivalen result is
1342 * detected and -1 on case of error.
1343 */
1344int blkid_do_safeprobe(blkid_probe pr)
1345{
1346 int i, count = 0, rc = 0;
a0948ffe 1347
0bffad47
KZ
1348 if (!pr)
1349 return -1;
20e1c3dc
KZ
1350 if (pr->flags & BLKID_FL_NOSCAN_DEV)
1351 return 1;
a0948ffe 1352
c81e7008
KZ
1353 blkid_probe_start(pr);
1354
0bffad47
KZ
1355 for (i = 0; i < BLKID_NCHAINS; i++) {
1356 struct blkid_chain *chn;
a0948ffe 1357
0bffad47
KZ
1358 chn = pr->cur_chain = &pr->chains[i];
1359 chn->binary = FALSE; /* for sure... */
a0948ffe 1360
c62a6311 1361 DBG(LOWPROBE, ul_debug("chain safeprobe %s %s",
0bffad47
KZ
1362 chn->driver->name,
1363 chn->enabled? "ENABLED" : "DISABLED"));
1364
1365 if (!chn->enabled)
1366 continue;
1367
9e0f7bda 1368 blkid_probe_chain_reset_position(chn);
0bffad47 1369
0bffad47 1370 rc = chn->driver->safeprobe(pr, chn);
9e0f7bda
KZ
1371
1372 blkid_probe_chain_reset_position(chn);
1373
1374 /* rc: -2 ambivalent, -1 = error, 0 = success, 1 = no result */
0bffad47
KZ
1375 if (rc < 0)
1376 goto done; /* error */
1377 if (rc == 0)
1378 count++; /* success */
51410fc6 1379 }
0bffad47
KZ
1380
1381done:
c81e7008 1382 blkid_probe_end(pr);
0bffad47
KZ
1383 if (rc < 0)
1384 return rc;
1385 return count ? 0 : 1;
a0948ffe
KZ
1386}
1387
0bffad47
KZ
1388/**
1389 * blkid_do_fullprobe:
1390 * @pr: prober
1391 *
1392 * This function gathers probing results from all enabled chains. Same as
fd7c9e35 1393 * blkid_do_safeprobe() but does not check for collision between probing
0bffad47
KZ
1394 * result.
1395 *
1396 * This is string-based NAME=value interface only.
7103157c 1397 *
0bffad47 1398 * Returns: 0 on success, 1 if nothing is detected or -1 on case of error.
a2f01a1c 1399 */
0bffad47 1400int blkid_do_fullprobe(blkid_probe pr)
a2f01a1c 1401{
0bffad47 1402 int i, count = 0, rc = 0;
7103157c 1403
0bffad47
KZ
1404 if (!pr)
1405 return -1;
20e1c3dc
KZ
1406 if (pr->flags & BLKID_FL_NOSCAN_DEV)
1407 return 1;
a2f01a1c 1408
c81e7008
KZ
1409 blkid_probe_start(pr);
1410
0bffad47 1411 for (i = 0; i < BLKID_NCHAINS; i++) {
0bffad47 1412 struct blkid_chain *chn;
a2f01a1c 1413
0bffad47
KZ
1414 chn = pr->cur_chain = &pr->chains[i];
1415 chn->binary = FALSE; /* for sure... */
1416
c62a6311 1417 DBG(LOWPROBE, ul_debug("chain fullprobe %s: %s",
0bffad47
KZ
1418 chn->driver->name,
1419 chn->enabled? "ENABLED" : "DISABLED"));
1420
1421 if (!chn->enabled)
1422 continue;
1423
9e0f7bda 1424 blkid_probe_chain_reset_position(chn);
0bffad47 1425
0bffad47 1426 rc = chn->driver->probe(pr, chn);
9e0f7bda
KZ
1427
1428 blkid_probe_chain_reset_position(chn);
1429
1430 /* rc: -1 = error, 0 = success, 1 = no result */
0bffad47
KZ
1431 if (rc < 0)
1432 goto done; /* error */
1433 if (rc == 0)
1434 count++; /* success */
1435 }
1436
1437done:
c81e7008 1438 blkid_probe_end(pr);
0bffad47
KZ
1439 if (rc < 0)
1440 return rc;
1441 return count ? 0 : 1;
a2f01a1c
KZ
1442}
1443
ce011388
KZ
1444/* same sa blkid_probe_get_buffer() but works with 512-sectors */
1445unsigned char *blkid_probe_get_sector(blkid_probe pr, unsigned int sector)
1446{
1447 return pr ? blkid_probe_get_buffer(pr,
f12cd8d1 1448 ((uint64_t) sector) << 9, 0x200) : NULL;
ce011388
KZ
1449}
1450
9bdf6885 1451struct blkid_prval *blkid_probe_assign_value(
51410fc6 1452 blkid_probe pr, const char *name)
a0948ffe 1453{
51410fc6 1454 struct blkid_prval *v;
51410fc6
KZ
1455 if (!name)
1456 return NULL;
6c4a7811
OO
1457
1458 v = blkid_probe_new_value();
1459 if (!v)
51410fc6 1460 return NULL;
a0948ffe 1461
51410fc6 1462 v->name = name;
9bdf6885 1463 v->chain = pr->cur_chain;
af17d349 1464 list_add_tail(&v->prvals, &pr->values);
6644688a 1465
c62a6311 1466 DBG(LOWPROBE, ul_debug("assigning %s [%s]", name, v->chain->driver->name));
51410fc6 1467 return v;
a0948ffe
KZ
1468}
1469
6c4a7811 1470static struct blkid_prval *blkid_probe_new_value(void)
cdd5bada 1471{
6c4a7811
OO
1472 struct blkid_prval *v = calloc(1, sizeof(struct blkid_prval));
1473 if (!v)
1474 return NULL;
cdd5bada 1475
6c4a7811 1476 INIT_LIST_HEAD(&v->prvals);
cdd5bada 1477
6c4a7811
OO
1478 return v;
1479}
cdd5bada 1480
6c4a7811 1481/* Note that value data is always terminated by zero to keep things robust,
3fd1f771
RM
1482 * this extra zero is not count to the value length. It's caller responsibility
1483 * to set proper value length (for strings we count terminator to the length,
6c4a7811
OO
1484 * for binary data it's without terminator).
1485 */
1486int blkid_probe_value_set_data(struct blkid_prval *v,
1487 unsigned char *data, size_t len)
1488{
1489 v->data = calloc(1, len + 1); /* always terminate by \0 */
cdd5bada 1490
6c4a7811
OO
1491 if (!v->data)
1492 return -ENOMEM;
1493 memcpy(v->data, data, len);
1494 v->len = len;
cdd5bada 1495 return 0;
cdd5bada
KZ
1496}
1497
51410fc6
KZ
1498int blkid_probe_set_value(blkid_probe pr, const char *name,
1499 unsigned char *data, size_t len)
a0948ffe 1500{
51410fc6 1501 struct blkid_prval *v;
a0948ffe 1502
51410fc6
KZ
1503 v = blkid_probe_assign_value(pr, name);
1504 if (!v)
1505 return -1;
a0948ffe 1506
6c4a7811 1507 return blkid_probe_value_set_data(v, data, len);
a0948ffe
KZ
1508}
1509
51410fc6
KZ
1510int blkid_probe_vsprintf_value(blkid_probe pr, const char *name,
1511 const char *fmt, va_list ap)
a0948ffe 1512{
51410fc6 1513 struct blkid_prval *v;
a23facd6 1514 ssize_t len;
a0948ffe 1515
51410fc6
KZ
1516 v = blkid_probe_assign_value(pr, name);
1517 if (!v)
6c4a7811 1518 return -ENOMEM;
a0948ffe 1519
6c4a7811 1520 len = vasprintf((char **) &v->data, fmt, ap);
a0948ffe 1521
6c4a7811 1522 if (len <= 0) {
af17d349 1523 blkid_probe_free_value(v);
6c4a7811 1524 return len == 0 ? -EINVAL : -ENOMEM;
a0948ffe 1525 }
51410fc6 1526 v->len = len + 1;
a0948ffe
KZ
1527 return 0;
1528}
1529
cc33d693
KZ
1530int blkid_probe_sprintf_value(blkid_probe pr, const char *name,
1531 const char *fmt, ...)
1532{
1533 int rc;
1534 va_list ap;
1535
1536 va_start(ap, fmt);
1537 rc = blkid_probe_vsprintf_value(pr, name, fmt, ap);
1538 va_end(ap);
1539
1540 return rc;
1541}
1542
f12cd8d1 1543int blkid_probe_set_magic(blkid_probe pr, uint64_t offset,
3c83b3b2
KZ
1544 size_t len, unsigned char *magic)
1545{
1546 int rc = 0;
1547 struct blkid_chain *chn = blkid_probe_get_chain(pr);
1548
1549 if (!chn || !magic || !len || chn->binary)
1550 return 0;
1551
1552 switch (chn->driver->id) {
1553 case BLKID_CHAIN_SUBLKS:
1554 if (!(chn->flags & BLKID_SUBLKS_MAGIC))
1555 return 0;
1556 rc = blkid_probe_set_value(pr, "SBMAGIC", magic, len);
1557 if (!rc)
1558 rc = blkid_probe_sprintf_value(pr,
44064b3c 1559 "SBMAGIC_OFFSET", "%llu", (unsigned long long)offset);
3c83b3b2
KZ
1560 break;
1561 case BLKID_CHAIN_PARTS:
1562 if (!(chn->flags & BLKID_PARTS_MAGIC))
1563 return 0;
1564 rc = blkid_probe_set_value(pr, "PTMAGIC", magic, len);
1565 if (!rc)
1566 rc = blkid_probe_sprintf_value(pr,
44064b3c 1567 "PTMAGIC_OFFSET", "%llu", (unsigned long long)offset);
3c83b3b2
KZ
1568 break;
1569 default:
1570 break;
1571 }
1572
1573 return rc;
1574}
1575
c89a1def
KZ
1576int blkid_probe_verify_csum(blkid_probe pr, uint64_t csum, uint64_t expected)
1577{
1578 if (csum != expected) {
02f3c12a
GP
1579 struct blkid_chain *chn = blkid_probe_get_chain(pr);
1580
c62a6311 1581 DBG(LOWPROBE, ul_debug(
c89a1def 1582 "incorrect checksum for type %s,"
fdbd7bb9 1583 " got %"PRIX64", expected %"PRIX64"",
c89a1def
KZ
1584 blkid_probe_get_probername(pr),
1585 csum, expected));
d88803a4
KZ
1586 /*
1587 * Accept bad checksum if BLKID_SUBLKS_BADCSUM flags is set
1588 */
1589 if (chn->driver->id == BLKID_CHAIN_SUBLKS
1590 && (chn->flags & BLKID_SUBLKS_BADCSUM)) {
1591 blkid_probe_set_value(pr, "SBBADCSUM", (unsigned char *) "1", 2);
1592 goto accept;
1593 }
1594 return 0; /* bad checksum */
c89a1def
KZ
1595 }
1596
d88803a4
KZ
1597accept:
1598 return 1;
c89a1def
KZ
1599}
1600
b3ee97a3
KZ
1601/**
1602 * blkid_probe_get_devno:
1603 * @pr: probe
1604 *
3b159691 1605 * Returns: block device number, or 0 for regular files.
b3ee97a3
KZ
1606 */
1607dev_t blkid_probe_get_devno(blkid_probe pr)
1608{
b3ee97a3
KZ
1609 return pr->devno;
1610}
1611
601fb1c1
KZ
1612/**
1613 * blkid_probe_get_wholedisk_devno:
1614 * @pr: probe
1615 *
3b159691 1616 * Returns: device number of the wholedisk, or 0 for regular files.
601fb1c1
KZ
1617 */
1618dev_t blkid_probe_get_wholedisk_devno(blkid_probe pr)
1619{
1620 if (!pr->disk_devno) {
1621 dev_t devno, disk_devno = 0;
1622
1623 devno = blkid_probe_get_devno(pr);
1624 if (!devno)
1625 return 0;
1626
2bf68c93 1627 if (blkid_devno_to_wholedisk(devno, NULL, 0, &disk_devno) == 0)
601fb1c1
KZ
1628 pr->disk_devno = disk_devno;
1629 }
1630 return pr->disk_devno;
1631}
1632
1633/**
1634 * blkid_probe_is_wholedisk:
1635 * @pr: probe
1636 *
1637 * Returns: 1 if the device is whole-disk or 0.
1638 */
1639int blkid_probe_is_wholedisk(blkid_probe pr)
1640{
1641 dev_t devno, disk_devno;
1642
1643 devno = blkid_probe_get_devno(pr);
1644 if (!devno)
1645 return 0;
1646
1647 disk_devno = blkid_probe_get_wholedisk_devno(pr);
1648 if (!disk_devno)
1649 return 0;
1650
1651 return devno == disk_devno;
1652}
1653
fd9f45e1
KZ
1654blkid_probe blkid_probe_get_wholedisk_probe(blkid_probe pr)
1655{
1656 dev_t disk;
1657
1658 if (blkid_probe_is_wholedisk(pr))
1659 return NULL; /* this is not partition */
1660
1661 if (pr->parent)
1662 /* this is cloned blkid_probe, use parent's stuff */
1663 return blkid_probe_get_wholedisk_probe(pr->parent);
1664
1665 disk = blkid_probe_get_wholedisk_devno(pr);
1666
1667 if (pr->disk_probe && pr->disk_probe->devno != disk) {
1668 /* we have disk prober, but for another disk... close it */
1669 blkid_free_probe(pr->disk_probe);
1670 pr->disk_probe = NULL;
1671 }
1672
1673 if (!pr->disk_probe) {
1674 /* Open a new disk prober */
1675 char *disk_path = blkid_devno_to_devname(disk);
1676
1677 if (!disk_path)
1678 return NULL;
1679
c62a6311 1680 DBG(LOWPROBE, ul_debug("allocate a wholedisk probe"));
fd9f45e1
KZ
1681
1682 pr->disk_probe = blkid_new_probe_from_filename(disk_path);
7eac65fc
KZ
1683
1684 free(disk_path);
1685
fd9f45e1
KZ
1686 if (!pr->disk_probe)
1687 return NULL; /* ENOMEM? */
1688 }
1689
1690 return pr->disk_probe;
1691}
1692
b3ee97a3
KZ
1693/**
1694 * blkid_probe_get_size:
1695 * @pr: probe
1696 *
30696241
KZ
1697 * This function returns size of probing area as defined by blkid_probe_set_device().
1698 * If the size of the probing area is unrestricted then this function returns
1699 * the real size of device. See also blkid_get_dev_size().
1700 *
1701 * Returns: size in bytes or -1 in case of error.
b3ee97a3
KZ
1702 */
1703blkid_loff_t blkid_probe_get_size(blkid_probe pr)
1704{
f12cd8d1 1705 return pr ? (blkid_loff_t) pr->size : -1;
b3ee97a3
KZ
1706}
1707
56e961e2
KZ
1708/**
1709 * blkid_probe_get_offset:
1710 * @pr: probe
1711 *
1712 * This function returns offset of probing area as defined by blkid_probe_set_device().
1713 *
1714 * Returns: offset in bytes or -1 in case of error.
1715 */
1716blkid_loff_t blkid_probe_get_offset(blkid_probe pr)
1717{
f12cd8d1 1718 return pr ? (blkid_loff_t) pr->off : -1;
56e961e2
KZ
1719}
1720
1721/**
1722 * blkid_probe_get_fd:
1723 * @pr: probe
1724 *
e3436956 1725 * Returns: file descriptor for assigned device/file or -1 in case of error.
56e961e2
KZ
1726 */
1727int blkid_probe_get_fd(blkid_probe pr)
1728{
1729 return pr ? pr->fd : -1;
1730}
1731
b3ee97a3
KZ
1732/**
1733 * blkid_probe_get_sectorsize:
90ec8d9c 1734 * @pr: probe or NULL (for NULL returns 512)
b3ee97a3 1735 *
2a1dfbad 1736 * Returns: block device logical sector size (BLKSSZGET ioctl, default 512).
b3ee97a3
KZ
1737 */
1738unsigned int blkid_probe_get_sectorsize(blkid_probe pr)
1739{
1740 if (!pr)
1741 return DEFAULT_SECTOR_SIZE; /*... and good luck! */
90ec8d9c 1742
b3ee97a3
KZ
1743 if (pr->blkssz)
1744 return pr->blkssz;
b3ee97a3 1745
90ec8d9c
KZ
1746 if (S_ISBLK(pr->mode) &&
1747 blkdev_get_sector_size(pr->fd, (int *) &pr->blkssz) == 0)
1748 return pr->blkssz;
b3ee97a3 1749
b3ee97a3
KZ
1750 pr->blkssz = DEFAULT_SECTOR_SIZE;
1751 return pr->blkssz;
1752}
1753
e8ae4947
DB
1754/**
1755 * blkid_probe_get_sectors:
1756 * @pr: probe
1757 *
1758 * Returns: 512-byte sector count or -1 in case of error.
1759 */
1760blkid_loff_t blkid_probe_get_sectors(blkid_probe pr)
1761{
f12cd8d1 1762 return pr ? (blkid_loff_t) (pr->size >> 9) : -1;
e8ae4947
DB
1763}
1764
4d72b337
KZ
1765/**
1766 * blkid_probe_numof_values:
1767 * @pr: probe
1768 *
1769 * Returns: number of values in probing result or -1 in case of error.
1770 */
1771int blkid_probe_numof_values(blkid_probe pr)
1772{
6c4a7811
OO
1773 int i = 0;
1774 struct list_head *p;
4d72b337
KZ
1775 if (!pr)
1776 return -1;
6c4a7811 1777
af17d349 1778 list_for_each(p, &pr->values)
6c4a7811
OO
1779 ++i;
1780 return i;
4d72b337
KZ
1781}
1782
81f73792
KZ
1783/**
1784 * blkid_probe_get_value:
1785 * @pr: probe
1786 * @num: wanted value in range 0..N, where N is blkid_probe_numof_values() - 1
1787 * @name: pointer to return value name or NULL
1788 * @data: pointer to return value data or NULL
1789 * @len: pointer to return value length or NULL
1790 *
c2dbd49b
KZ
1791 * Note, the @len returns length of the @data, including the terminating
1792 * '\0' character.
1793 *
81f73792
KZ
1794 * Returns: 0 on success, or -1 in case of error.
1795 */
51410fc6 1796int blkid_probe_get_value(blkid_probe pr, int num, const char **name,
6d042d0d 1797 const char **data, size_t *len)
a0948ffe 1798{
81f73792 1799 struct blkid_prval *v = __blkid_probe_get_value(pr, num);
a0948ffe 1800
81f73792 1801 if (!v)
51410fc6 1802 return -1;
51410fc6
KZ
1803 if (name)
1804 *name = v->name;
1805 if (data)
6d042d0d 1806 *data = (char *) v->data;
51410fc6
KZ
1807 if (len)
1808 *len = v->len;
6644688a 1809
c62a6311 1810 DBG(LOWPROBE, ul_debug("returning %s value", v->name));
a0948ffe
KZ
1811 return 0;
1812}
a0948ffe 1813
81f73792
KZ
1814/**
1815 * blkid_probe_lookup_value:
1816 * @pr: probe
1817 * @name: name of value
1818 * @data: pointer to return value data or NULL
1819 * @len: pointer to return value length or NULL
1820 *
c2dbd49b
KZ
1821 * Note, the @len returns length of the @data, including the terminating
1822 * '\0' character.
1823 *
81f73792
KZ
1824 * Returns: 0 on success, or -1 in case of error.
1825 */
51410fc6 1826int blkid_probe_lookup_value(blkid_probe pr, const char *name,
6d042d0d 1827 const char **data, size_t *len)
a0948ffe 1828{
81f73792 1829 struct blkid_prval *v = __blkid_probe_lookup_value(pr, name);
a0948ffe 1830
81f73792 1831 if (!v)
51410fc6 1832 return -1;
81f73792
KZ
1833 if (data)
1834 *data = (char *) v->data;
1835 if (len)
1836 *len = v->len;
81f73792 1837 return 0;
a0948ffe
KZ
1838}
1839
81f73792
KZ
1840/**
1841 * blkid_probe_has_value:
1842 * @pr: probe
1843 * @name: name of value
1844 *
1845 * Returns: 1 if value exist in probing result, otherwise 0.
1846 */
51410fc6 1847int blkid_probe_has_value(blkid_probe pr, const char *name)
a0948ffe 1848{
51410fc6
KZ
1849 if (blkid_probe_lookup_value(pr, name, NULL, NULL) == 0)
1850 return 1;
a0948ffe
KZ
1851 return 0;
1852}
1853
6c4a7811
OO
1854struct blkid_prval *blkid_probe_last_value(blkid_probe pr)
1855{
af17d349 1856 if (!pr || list_empty(&pr->values))
6c4a7811
OO
1857 return NULL;
1858
af17d349 1859 return list_last_entry(&pr->values, struct blkid_prval, prvals);
6c4a7811
OO
1860}
1861
1862
1c1726a7
KZ
1863struct blkid_prval *__blkid_probe_get_value(blkid_probe pr, int num)
1864{
6c4a7811
OO
1865 int i = 0;
1866 struct list_head *p;
1867
1868 if (!pr || num < 0)
1c1726a7
KZ
1869 return NULL;
1870
af17d349 1871 list_for_each(p, &pr->values) {
6c4a7811
OO
1872 if (i++ != num)
1873 continue;
1874 return list_entry(p, struct blkid_prval, prvals);
1875 }
1876 return NULL;
1c1726a7
KZ
1877}
1878
1879struct blkid_prval *__blkid_probe_lookup_value(blkid_probe pr, const char *name)
1880{
6c4a7811 1881 struct list_head *p;
1c1726a7 1882
af17d349 1883 if (!pr || list_empty(&pr->values) || !name)
1c1726a7
KZ
1884 return NULL;
1885
af17d349 1886 list_for_each(p, &pr->values) {
6c4a7811
OO
1887 struct blkid_prval *v = list_entry(p, struct blkid_prval,
1888 prvals);
1c1726a7
KZ
1889
1890 if (v->name && strcmp(name, v->name) == 0) {
c62a6311 1891 DBG(LOWPROBE, ul_debug("returning %s value", v->name));
1c1726a7
KZ
1892 return v;
1893 }
1894 }
1895 return NULL;
1896}
1897
201529bd
KZ
1898
1899/* converts DCE UUID (uuid[16]) to human readable string
1900 * - the @len should be always 37 */
201529bd 1901#ifdef HAVE_LIBUUID
c9f51c71
KZ
1902void blkid_unparse_uuid(const unsigned char *uuid, char *str,
1903 size_t len __attribute__((__unused__)))
1904{
201529bd 1905 uuid_unparse(uuid, str);
c9f51c71 1906}
201529bd 1907#else
c9f51c71
KZ
1908void blkid_unparse_uuid(const unsigned char *uuid, char *str, size_t len)
1909{
201529bd
KZ
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]);
201529bd 1917}
c9f51c71 1918#endif
201529bd 1919
9c06cdbf
KZ
1920/* like uuid_is_null() from libuuid, but works with arbitrary size of UUID */
1921int blkid_uuid_is_empty(const unsigned char *buf, size_t len)
1922{
1923 size_t i;
1924
1925 for (i = 0; i < len; i++)
1926 if (buf[i])
1927 return 0;
1928 return 1;
1929}
c2dbd49b
KZ
1930
1931/* Removes whitespace from the right-hand side of a string (trailing
1932 * whitespace).
1933 *
1934 * Returns size of the new string (without \0).
1935 */
1936size_t blkid_rtrim_whitespace(unsigned char *str)
1937{
22e9e9c8 1938 return rtrim_whitespace(str);
c2dbd49b
KZ
1939}
1940
fafe46bc
ZAK
1941/* Removes whitespace from the left-hand side of a string.
1942 *
1943 * Returns size of the new string (without \0).
1944 */
1945size_t blkid_ltrim_whitespace(unsigned char *str)
1946{
22e9e9c8 1947 return ltrim_whitespace(str);
fafe46bc 1948}
22e9e9c8 1949
8b7eae45
KZ
1950/*
1951 * Some mkfs-like utils wipe some parts (usually begin) of the device.
1952 * For example LVM (pvcreate) or mkswap(8). This information could be used
1953 * for later resolution to conflicts between superblocks.
1954 *
1955 * For example we found valid LVM superblock, LVM wipes 8KiB at the begin of
89d39d22
KZ
1956 * the device. If we found another signature (for example MBR) within the
1957 * wiped area then the signature has been added later and LVM superblock
1958 * should be ignore.
8b7eae45
KZ
1959 *
1960 * Note that this heuristic is not 100% reliable, for example "pvcreate --zero
1961 * n" allows to keep the begin of the device unmodified. It's probably better
1962 * to use this heuristic for conflicts between superblocks and partition tables
1963 * than for conflicts between filesystem superblocks -- existence of unwanted
1964 * partition table is very unusual, because PT is pretty visible (parsed and
1965 * interpreted by kernel).
89d39d22
KZ
1966 *
1967 * Note that we usually expect only one signature on the device, it means that
1968 * we have to remember only one wiped area from previously successfully
1969 * detected signature.
1970 *
1971 * blkid_probe_set_wiper() -- defines wiped area (e.g. LVM)
1972 * blkid_probe_use_wiper() -- try to use area (e.g. MBR)
1973 *
1974 * Note that there is not relation between _wiper and blkid_to_wipe().
1975 *
8b7eae45 1976 */
f12cd8d1 1977void blkid_probe_set_wiper(blkid_probe pr, uint64_t off, uint64_t size)
8b7eae45
KZ
1978{
1979 struct blkid_chain *chn;
1980
1981 if (!pr)
1982 return;
1983
1984 if (!size) {
c62a6311 1985 DBG(LOWPROBE, ul_debug("zeroize wiper"));
8b7eae45
KZ
1986 pr->wipe_size = pr->wipe_off = 0;
1987 pr->wipe_chain = NULL;
1988 return;
1989 }
1990
1991 chn = pr->cur_chain;
1992
1993 if (!chn || !chn->driver ||
c9f51c71 1994 chn->idx < 0 || (size_t) chn->idx >= chn->driver->nidinfos)
8b7eae45
KZ
1995 return;
1996
1997 pr->wipe_size = size;
1998 pr->wipe_off = off;
1999 pr->wipe_chain = chn;
2000
0540ea54 2001 DBG(LOWPROBE,
fdbd7bb9 2002 ul_debug("wiper set to %s::%s off=%"PRIu64" size=%"PRIu64"",
8b7eae45
KZ
2003 chn->driver->name,
2004 chn->driver->idinfos[chn->idx]->name,
2005 pr->wipe_off, pr->wipe_size));
2006 return;
2007}
2008
2009/*
2010 * Returns 1 if the <@off,@size> area was wiped
2011 */
f12cd8d1 2012int blkid_probe_is_wiped(blkid_probe pr, struct blkid_chain **chn, uint64_t off, uint64_t size)
8b7eae45
KZ
2013{
2014 if (!pr || !size)
2015 return 0;
2016
2017 if (pr->wipe_off <= off && off + size <= pr->wipe_off + pr->wipe_size) {
2018 if (chn)
2019 *chn = pr->wipe_chain;
2020 return 1;
2021 }
2022 return 0;
2023}
2024
89d39d22
KZ
2025/*
2026 * Try to use any area -- if the area has been previously wiped then the
2027 * previous probing result should be ignored (reseted).
2028 */
f12cd8d1 2029void blkid_probe_use_wiper(blkid_probe pr, uint64_t off, uint64_t size)
8b7eae45
KZ
2030{
2031 struct blkid_chain *chn = NULL;
2032
2033 if (blkid_probe_is_wiped(pr, &chn, off, size) && chn) {
c62a6311 2034 DBG(LOWPROBE, ul_debug("previously wiped area modified "
0540ea54 2035 " -- ignore previous results"));
8b7eae45 2036 blkid_probe_set_wiper(pr, 0, 0);
af17d349 2037 blkid_probe_chain_reset_values(pr, chn);
8b7eae45
KZ
2038 }
2039}