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