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