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