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