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