]> git.ipfire.org Git - thirdparty/util-linux.git/blame - libblkid/src/probe.c
swapon: (tests) abort test on failing commands
[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>
2bd739c9 74 * while((blkid_do_probe(pr) == BLKID_PROBE_OK)
4d72b337
KZ
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>
2b22ec96 93#include <sys/mman.h>
a0948ffe 94#include <sys/types.h>
55113b15
C
95#ifdef HAVE_LINUX_CDROM_H
96#include <linux/cdrom.h>
97#endif
b250fbbf
NA
98#ifdef HAVE_LINUX_BLKZONED_H
99#include <linux/blkzoned.h>
100#endif
a0948ffe
KZ
101#ifdef HAVE_SYS_STAT_H
102#include <sys/stat.h>
103#endif
a0948ffe
KZ
104#ifdef HAVE_ERRNO_H
105#include <errno.h>
106#endif
2d24f963
KZ
107#ifdef HAVE_LINUX_FD_H
108#include <linux/fd.h>
109#endif
c4206331 110#include <inttypes.h>
51410fc6 111#include <stdint.h>
8c0dc071 112#include <stdarg.h>
109df14f 113#include <limits.h>
a0cf9105
LB
114#ifdef HAVE_OPAL_GET_STATUS
115#include <linux/sed-opal.h>
116#endif
8c0dc071 117
51410fc6 118#include "blkidP.h"
e12c9866 119#include "all-io.h"
25472aaf 120#include "sysfs.h"
22e9e9c8 121#include "strutils.h"
6c4a7811 122#include "list.h"
2d24f963 123#include "fileutils.h"
219227c2 124
52448df8
KZ
125/*
126 * All supported chains
127 */
128static const struct blkid_chaindrv *chains_drvs[] = {
129 [BLKID_CHAIN_SUBLKS] = &superblocks_drv,
cc33d693 130 [BLKID_CHAIN_TOPLGY] = &topology_drv,
e4799a35 131 [BLKID_CHAIN_PARTS] = &partitions_drv
52448df8
KZ
132};
133
af17d349 134static void blkid_probe_reset_values(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
52448df8
KZ
146 pr = calloc(1, sizeof(struct blkid_struct_probe));
147 if (!pr)
148 return NULL;
149
63c9c05d 150 DBG(LOWPROBE, ul_debug("allocate a new probe"));
fd9f45e1 151
52448df8
KZ
152 /* initialize chains */
153 for (i = 0; i < BLKID_NCHAINS; i++) {
154 pr->chains[i].driver = chains_drvs[i];
155 pr->chains[i].flags = chains_drvs[i]->dflt_flags;
156 pr->chains[i].enabled = chains_drvs[i]->dflt_enabled;
157 }
15a8fb42 158 INIT_LIST_HEAD(&pr->buffers);
77b85278 159 INIT_LIST_HEAD(&pr->prunable_buffers);
af17d349 160 INIT_LIST_HEAD(&pr->values);
67719fbb 161 INIT_LIST_HEAD(&pr->hints);
52448df8 162 return pr;
a0948ffe
KZ
163}
164
fd9f45e1
KZ
165/*
166 * Clone @parent, the new clone shares all, but except:
167 *
168 * - probing result
9e930041 169 * - buffers if another device (or offset) is set to the prober
fd9f45e1
KZ
170 */
171blkid_probe blkid_clone_probe(blkid_probe parent)
172{
173 blkid_probe pr;
174
175 if (!parent)
176 return NULL;
177
c62a6311 178 DBG(LOWPROBE, ul_debug("allocate a probe clone"));
fd9f45e1
KZ
179
180 pr = blkid_new_probe();
181 if (!pr)
182 return NULL;
183
184 pr->fd = parent->fd;
185 pr->off = parent->off;
186 pr->size = parent->size;
187 pr->devno = parent->devno;
188 pr->disk_devno = parent->disk_devno;
189 pr->blkssz = parent->blkssz;
190 pr->flags = parent->flags;
b250fbbf 191 pr->zone_size = parent->zone_size;
fd9f45e1
KZ
192 pr->parent = parent;
193
6e650f88
KZ
194 pr->flags &= ~BLKID_FL_PRIVATE_FD;
195
fd9f45e1
KZ
196 return pr;
197}
198
199
200
f38db0cf
KZ
201/**
202 * blkid_new_probe_from_filename:
203 * @filename: device or regular file
204 *
205 * This function is same as call open(filename), blkid_new_probe() and
206 * blkid_probe_set_device(pr, fd, 0, 0).
207 *
208 * The @filename is closed by blkid_free_probe() or by the
209 * blkid_probe_set_device() call.
210 *
211 * Returns: a pointer to the newly allocated probe struct or NULL in case of
212 * error.
213 */
214blkid_probe blkid_new_probe_from_filename(const char *filename)
215{
1b504263 216 int fd;
f38db0cf
KZ
217 blkid_probe pr = NULL;
218
39f5af25 219 fd = open(filename, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
f38db0cf
KZ
220 if (fd < 0)
221 return NULL;
222
223 pr = blkid_new_probe();
224 if (!pr)
225 goto err;
226
227 if (blkid_probe_set_device(pr, fd, 0, 0))
228 goto err;
229
a9eef56c 230 pr->flags |= BLKID_FL_PRIVATE_FD;
f38db0cf
KZ
231 return pr;
232err:
351de28a 233 close(fd);
f38db0cf
KZ
234 blkid_free_probe(pr);
235 return NULL;
236}
237
52448df8
KZ
238/**
239 * blkid_free_probe:
240 * @pr: probe
241 *
242 * Deallocates the probe struct, buffers and all allocated
51410fc6 243 * data that are associated with this probing control struct.
a0948ffe 244 */
51410fc6 245void blkid_free_probe(blkid_probe pr)
a0948ffe 246{
52448df8
KZ
247 int i;
248
51410fc6
KZ
249 if (!pr)
250 return;
52448df8
KZ
251
252 for (i = 0; i < BLKID_NCHAINS; i++) {
253 struct blkid_chain *ch = &pr->chains[i];
254
255 if (ch->driver->free_data)
256 ch->driver->free_data(pr, ch->data);
257 free(ch->fltr);
5caa4117 258 ch->fltr = NULL;
52448df8 259 }
f38db0cf 260
a9eef56c 261 if ((pr->flags & BLKID_FL_PRIVATE_FD) && pr->fd >= 0)
f38db0cf 262 close(pr->fd);
d2b0c658 263 blkid_probe_reset_buffers(pr);
af17d349 264 blkid_probe_reset_values(pr);
67719fbb 265 blkid_probe_reset_hints(pr);
fd9f45e1
KZ
266 blkid_free_probe(pr->disk_probe);
267
63c9c05d 268 DBG(LOWPROBE, ul_debug("free probe"));
51410fc6 269 free(pr);
a0948ffe
KZ
270}
271
af17d349 272void blkid_probe_free_value(struct blkid_prval *v)
6c4a7811
OO
273{
274 if (!v)
275 return;
276
277 list_del(&v->prvals);
278 free(v->data);
af17d349
KZ
279
280 DBG(LOWPROBE, ul_debug(" free value %s", v->name));
6c4a7811
OO
281 free(v);
282}
52448df8 283
9bdf6885
KZ
284/*
285 * Removes chain values from probing result.
286 */
af17d349 287void blkid_probe_chain_reset_values(blkid_probe pr, struct blkid_chain *chn)
9bdf6885 288{
9bdf6885 289
6c4a7811 290 struct list_head *p, *pnext;
9bdf6885 291
7f787ced 292 if (list_empty(&pr->values))
6c4a7811
OO
293 return;
294
9e930041 295 DBG(LOWPROBE, ul_debug("Resetting %s values", chn->driver->name));
af17d349
KZ
296
297 list_for_each_safe(p, pnext, &pr->values) {
6c4a7811
OO
298 struct blkid_prval *v = list_entry(p,
299 struct blkid_prval, prvals);
300
301 if (v->chain == chn)
af17d349 302 blkid_probe_free_value(v);
9bdf6885 303 }
9bdf6885
KZ
304}
305
9e0f7bda
KZ
306static void blkid_probe_chain_reset_position(struct blkid_chain *chn)
307{
7f787ced 308 chn->idx = -1;
9e0f7bda
KZ
309}
310
9bdf6885 311/*
af17d349 312 * Move chain values from probing result to @vals
9bdf6885 313 */
af17d349
KZ
314int blkid_probe_chain_save_values(blkid_probe pr, struct blkid_chain *chn,
315 struct list_head *vals)
9bdf6885 316{
af17d349
KZ
317 struct list_head *p, *pnext;
318 struct blkid_prval *v;
6c4a7811 319
af17d349 320 DBG(LOWPROBE, ul_debug("saving %s values", chn->driver->name));
6c4a7811 321
af17d349 322 list_for_each_safe(p, pnext, &pr->values) {
9bdf6885 323
af17d349 324 v = list_entry(p, struct blkid_prval, prvals);
9bdf6885
KZ
325 if (v->chain != chn)
326 continue;
6c4a7811 327
84084dc3 328 list_del_init(&v->prvals);
af17d349 329 list_add_tail(&v->prvals, vals);
9bdf6885 330 }
6c4a7811 331 return 0;
9bdf6885
KZ
332}
333
334/*
335 * Appends values from @vals to the probing result
336 */
af17d349
KZ
337void blkid_probe_append_values_list(blkid_probe pr, struct list_head *vals)
338{
339 DBG(LOWPROBE, ul_debug("appending values"));
340
341 list_splice(vals, &pr->values);
342 INIT_LIST_HEAD(vals);
343}
344
345
346void blkid_probe_free_values_list(struct list_head *vals)
9bdf6885 347{
af17d349
KZ
348 if (!vals)
349 return;
350
351 DBG(LOWPROBE, ul_debug("freeing values list"));
352
353 while (!list_empty(vals)) {
354 struct blkid_prval *v = list_entry(vals->next, struct blkid_prval, prvals);
355 blkid_probe_free_value(v);
356 }
a0948ffe
KZ
357}
358
1c1726a7
KZ
359struct blkid_chain *blkid_probe_get_chain(blkid_probe pr)
360{
361 return pr->cur_chain;
362}
363
c89a1def
KZ
364static const char *blkid_probe_get_probername(blkid_probe pr)
365{
366 struct blkid_chain *chn = blkid_probe_get_chain(pr);
367
b9710f1f 368 if (chn && chn->idx >= 0 && (unsigned)chn->idx < chn->driver->nidinfos)
c89a1def
KZ
369 return chn->driver->idinfos[chn->idx]->name;
370
371 return NULL;
372}
373
22571ebb
KZ
374void *blkid_probe_get_binary_data(blkid_probe pr, struct blkid_chain *chn)
375{
c81e7008
KZ
376 int rc, org_prob_flags;
377 struct blkid_chain *org_chn;
22571ebb 378
c81e7008
KZ
379 /* save the current setting -- the binary API has to be completely
380 * independent on the current probing status
381 */
382 org_chn = pr->cur_chain;
383 org_prob_flags = pr->prob_flags;
384
22571ebb 385 pr->cur_chain = chn;
c81e7008 386 pr->prob_flags = 0;
22571ebb 387 chn->binary = TRUE;
9e0f7bda 388 blkid_probe_chain_reset_position(chn);
22571ebb
KZ
389
390 rc = chn->driver->probe(pr, chn);
391
392 chn->binary = FALSE;
9e0f7bda 393 blkid_probe_chain_reset_position(chn);
22571ebb 394
c81e7008
KZ
395 /* restore the original setting
396 */
397 pr->cur_chain = org_chn;
398 pr->prob_flags = org_prob_flags;
399
d7be1a74 400 if (rc != 0)
22571ebb
KZ
401 return NULL;
402
c62a6311 403 DBG(LOWPROBE, ul_debug("returning %s binary data", chn->driver->name));
22571ebb
KZ
404 return chn->data;
405}
406
407
52448df8
KZ
408/**
409 * blkid_reset_probe:
410 * @pr: probe
411 *
44ef90bc
KZ
412 * Zeroize probing results and resets the current probing (this has impact to
413 * blkid_do_probe() only). This function does not touch probing filters and
414 * keeps assigned device.
52448df8 415 */
51410fc6 416void blkid_reset_probe(blkid_probe pr)
a0948ffe 417{
52448df8
KZ
418 int i;
419
af17d349 420 blkid_probe_reset_values(pr);
89d39d22 421 blkid_probe_set_wiper(pr, 0, 0);
52448df8 422
44ef90bc
KZ
423 pr->cur_chain = NULL;
424
52448df8 425 for (i = 0; i < BLKID_NCHAINS; i++)
9e0f7bda 426 blkid_probe_chain_reset_position(&pr->chains[i]);
a0948ffe
KZ
427}
428
46a734fd
KZ
429/***
430static int blkid_probe_dump_filter(blkid_probe pr, int chain)
431{
432 struct blkid_chain *chn;
433 int i;
434
435 if (!pr || chain < 0 || chain >= BLKID_NCHAINS)
436 return -1;
437
438 chn = &pr->chains[chain];
439
440 if (!chn->fltr)
441 return -1;
442
443 for (i = 0; i < chn->driver->nidinfos; i++) {
444 const struct blkid_idinfo *id = chn->driver->idinfos[i];
445
c62a6311 446 DBG(LOWPROBE, ul_debug("%d: %s: %s",
46a734fd
KZ
447 i,
448 id->name,
449 blkid_bmp_get_item(chn->fltr, i)
450 ? "disabled" : "enabled <--"));
46a734fd
KZ
451 }
452 return 0;
453}
454***/
455
456/*
457 * Returns properly initialized chain filter
458 */
459unsigned long *blkid_probe_get_filter(blkid_probe pr, int chain, int create)
460{
461 struct blkid_chain *chn;
462
7f787ced 463 if (chain < 0 || chain >= BLKID_NCHAINS)
46a734fd
KZ
464 return NULL;
465
466 chn = &pr->chains[chain];
467
3b159691 468 /* always when you touch the chain filter all indexes are reset and
46a734fd
KZ
469 * probing starts from scratch
470 */
9e0f7bda 471 blkid_probe_chain_reset_position(chn);
46a734fd
KZ
472 pr->cur_chain = NULL;
473
474 if (!chn->driver->has_fltr || (!chn->fltr && !create))
475 return NULL;
476
477 if (!chn->fltr)
478 chn->fltr = calloc(1, blkid_bmp_nbytes(chn->driver->nidinfos));
479 else
480 memset(chn->fltr, 0, blkid_bmp_nbytes(chn->driver->nidinfos));
481
482 /* blkid_probe_dump_filter(pr, chain); */
483 return chn->fltr;
484}
485
486/*
487 * Generic private functions for filter setting
488 */
489int __blkid_probe_invert_filter(blkid_probe pr, int chain)
490{
c9f51c71 491 size_t i;
46a734fd 492 struct blkid_chain *chn;
46a734fd 493
46a734fd
KZ
494 chn = &pr->chains[chain];
495
e8fc977a
KZ
496 if (!chn->driver->has_fltr || !chn->fltr)
497 return -1;
498
46a734fd 499 for (i = 0; i < blkid_bmp_nwords(chn->driver->nidinfos); i++)
e8fc977a 500 chn->fltr[i] = ~chn->fltr[i];
46a734fd 501
c62a6311 502 DBG(LOWPROBE, ul_debug("probing filter inverted"));
46a734fd
KZ
503 /* blkid_probe_dump_filter(pr, chain); */
504 return 0;
505}
506
507int __blkid_probe_reset_filter(blkid_probe pr, int chain)
508{
509 return blkid_probe_get_filter(pr, chain, FALSE) ? 0 : -1;
510}
511
512int __blkid_probe_filter_types(blkid_probe pr, int chain, int flag, char *names[])
513{
514 unsigned long *fltr;
515 struct blkid_chain *chn;
c9f51c71 516 size_t i;
46a734fd
KZ
517
518 fltr = blkid_probe_get_filter(pr, chain, TRUE);
519 if (!fltr)
520 return -1;
521
522 chn = &pr->chains[chain];
523
524 for (i = 0; i < chn->driver->nidinfos; i++) {
525 int has = 0;
526 const struct blkid_idinfo *id = chn->driver->idinfos[i];
527 char **n;
528
529 for (n = names; *n; n++) {
530 if (!strcmp(id->name, *n)) {
531 has = 1;
532 break;
533 }
534 }
92a4d098
SK
535 if (has) {
536 if (flag & BLKID_FLTR_NOTIN)
46a734fd 537 blkid_bmp_set_item(fltr, i);
92a4d098
SK
538 } else if (flag & BLKID_FLTR_ONLYIN)
539 blkid_bmp_set_item(fltr, i);
46a734fd
KZ
540 }
541
c62a6311 542 DBG(LOWPROBE, ul_debug("%s: a new probing type-filter initialized",
46a734fd
KZ
543 chn->driver->name));
544 /* blkid_probe_dump_filter(pr, chain); */
545 return 0;
546}
547
2dc39ee6
TW
548static void remove_buffer(struct blkid_bufinfo *bf)
549{
550 list_del(&bf->bufs);
551
552 DBG(BUFFER, ul_debug(" remove buffer: [off=%"PRIu64", len=%"PRIu64"]",
553 bf->off, bf->len));
554 munmap(bf->data, bf->len);
555 free(bf);
556}
557
f12cd8d1 558static struct blkid_bufinfo *read_buffer(blkid_probe pr, uint64_t real_off, uint64_t len)
2355dd6a
KZ
559{
560 ssize_t ret;
561 struct blkid_bufinfo *bf = NULL;
562
a732e4a1 563 if (lseek(pr->fd, real_off, SEEK_SET) == (off_t) -1) {
2355dd6a
KZ
564 errno = 0;
565 return NULL;
566 }
567
568 /* someone trying to overflow some buffers? */
569 if (len > ULONG_MAX - sizeof(struct blkid_bufinfo)) {
570 errno = ENOMEM;
571 return NULL;
572 }
573
574 /* allocate info and space for data by one malloc call */
2b22ec96 575 bf = calloc(1, sizeof(struct blkid_bufinfo));
2355dd6a
KZ
576 if (!bf) {
577 errno = ENOMEM;
578 return NULL;
579 }
580
2b22ec96
TW
581 bf->data = mmap(NULL, len, PROT_READ | PROT_WRITE,
582 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
583 if (bf->data == MAP_FAILED) {
584 free(bf);
585 errno = ENOMEM;
586 return NULL;
587 }
588
2355dd6a
KZ
589 bf->len = len;
590 bf->off = real_off;
591 INIT_LIST_HEAD(&bf->bufs);
592
63c9c05d
KZ
593 DBG(LOWPROBE, ul_debug("\tread: off=%"PRIu64" len=%"PRIu64"",
594 real_off, len));
2355dd6a
KZ
595
596 ret = read(pr->fd, bf->data, len);
597 if (ret != (ssize_t) len) {
598 DBG(LOWPROBE, ul_debug("\tread failed: %m"));
2dc39ee6 599 remove_buffer(bf);
55ad13c2
KZ
600
601 /* I/O errors on CDROMs are non-fatal to work with hybrid
602 * audio+data disks */
a0cf9105 603 if (ret >= 0 || blkid_probe_is_cdrom(pr) || blkdid_probe_is_opal_locked(pr))
2355dd6a 604 errno = 0;
a0cf9105
LB
605#ifdef HAVE_OPAL_GET_STATUS
606 else {
607 struct opal_status st = { };
608
609 /* If the device is locked with OPAL, we'll fail to read with I/O
610 * errors when probing deep into the block device. Do not return
611 * an error, so that we can move on to different types of checks.*/
612 ret = ioctl(pr->fd, IOC_OPAL_GET_STATUS, &st);
613 if (ret == 0 && (st.flags & OPAL_FL_LOCKED)) {
614 pr->flags |= BLKID_FL_OPAL_LOCKED;
615 errno = 0;
616 }
617 }
618#endif
619
2355dd6a
KZ
620 return NULL;
621 }
622
2b22ec96
TW
623 if (mprotect(bf->data, len, PROT_READ))
624 DBG(LOWPROBE, ul_debug("\tmprotect failed: %m"));
625
2355dd6a
KZ
626 return bf;
627}
628
d2b0c658 629/*
bd0f347f 630 * Search in buffers we already have in memory
d2b0c658
KZ
631 */
632static struct blkid_bufinfo *get_cached_buffer(blkid_probe pr, uint64_t off, uint64_t len)
633{
634 uint64_t real_off = pr->off + off;
635 struct list_head *p;
636
637 list_for_each(p, &pr->buffers) {
638 struct blkid_bufinfo *x =
639 list_entry(p, struct blkid_bufinfo, bufs);
640
641 if (real_off >= x->off && real_off + len <= x->off + x->len) {
63c9c05d
KZ
642 DBG(BUFFER, ul_debug("\treuse: off=%"PRIu64" len=%"PRIu64" (for off=%"PRIu64" len=%"PRIu64")",
643 x->off, x->len, real_off, len));
d2b0c658
KZ
644 return x;
645 }
646 }
647 return NULL;
648}
649
77b85278
TW
650/*
651 * Mark smaller buffers that can be satisfied by bf as prunable
652 */
653static void mark_prunable_buffers(blkid_probe pr, const struct blkid_bufinfo *bf)
654{
655 struct list_head *p, *next;
656
657 list_for_each_safe(p, next, &pr->buffers) {
658 struct blkid_bufinfo *x =
659 list_entry(p, struct blkid_bufinfo, bufs);
660
661 if (bf->off <= x->off && bf->off + bf->len >= x->off + x->len) {
662 list_del(&x->bufs);
663 list_add(&x->bufs, &pr->prunable_buffers);
664 }
665 }
666}
667
668/*
669 * Remove buffers that are marked as prunable
670 */
671void blkid_probe_prune_buffers(blkid_probe pr)
672{
673 struct list_head *p, *next;
674
675 list_for_each_safe(p, next, &pr->prunable_buffers) {
676 struct blkid_bufinfo *x =
677 list_entry(p, struct blkid_bufinfo, bufs);
678
679 remove_buffer(x);
680 }
681}
682
d2b0c658
KZ
683/*
684 * Zeroize in-memory data in already read buffer. The next blkid_probe_get_buffer()
685 * will return modified buffer. This is usable when you want to call the same probing
686 * function more than once and hide previously detected magic strings.
687 *
688 * See blkid_probe_hide_range().
689 */
690static int hide_buffer(blkid_probe pr, uint64_t off, uint64_t len)
691{
692 uint64_t real_off = pr->off + off;
693 struct list_head *p;
694 int ct = 0;
695
106de261
KZ
696 if (UINT64_MAX - len < off) {
697 DBG(BUFFER, ul_debug("\t hide-buffer overflow (ignore)"));
698 return -EINVAL;
699 }
700
d2b0c658
KZ
701 list_for_each(p, &pr->buffers) {
702 struct blkid_bufinfo *x =
703 list_entry(p, struct blkid_bufinfo, bufs);
704 unsigned char *data;
705
706 if (real_off >= x->off && real_off + len <= x->off + x->len) {
707
708 assert(x->off <= real_off);
709 assert(x->off + x->len >= real_off + len);
710
711 data = real_off ? x->data + (real_off - x->off) : x->data;
712
b7fb7209 713 DBG(BUFFER, ul_debug("\thiding: off=%"PRIu64" len=%"PRIu64,
63c9c05d 714 off, len));
2b22ec96 715 mprotect(x->data, x->len, PROT_READ | PROT_WRITE);
d2b0c658 716 memset(data, 0, len);
2b22ec96 717 mprotect(x->data, x->len, PROT_READ);
d2b0c658
KZ
718 ct++;
719 }
720 }
721 return ct == 0 ? -EINVAL : 0;
722}
723
724
a674a0ab
KZ
725/*
726 * Note that @off is offset within probing area, the probing area is defined by
727 * pr->off and pr->size.
728 */
7eba8f98 729const unsigned char *blkid_probe_get_buffer(blkid_probe pr, uint64_t off, uint64_t len)
1ca17f91 730{
15a8fb42 731 struct blkid_bufinfo *bf = NULL;
f12cd8d1 732 uint64_t real_off = pr->off + off;
a674a0ab
KZ
733
734 /*
735 DBG(BUFFER, ul_debug("\t>>>> off=%ju, real-off=%ju (probe <%ju..%ju>, len=%ju",
736 off, real_off, pr->off, pr->off + pr->size, len));
737 */
f12cd8d1 738 if (pr->size == 0) {
00749bc3 739 errno = EINVAL;
88923b08 740 return NULL;
00749bc3 741 }
88923b08 742
106de261
KZ
743 if (UINT64_MAX - len < off || UINT64_MAX - len < real_off) {
744 DBG(BUFFER, ul_debug("\t read-buffer overflow (ignore)"));
745 return NULL;
746 }
747
65b1f3de
TW
748 if (len > 8388608 /* 8 Mib */ ) {
749 DBG(BUFFER, ul_debug("\t too large read request (ignore)"));
750 return NULL;
751 }
752
106de261
KZ
753 if (len == 0
754 || (!S_ISCHR(pr->mode) && (pr->size < off || pr->size < len))
755 || (!S_ISCHR(pr->mode) && (pr->off + pr->size < real_off + len))) {
756 DBG(BUFFER, ul_debug("\t read-buffer out of probing area (ignore)"));
a674a0ab
KZ
757 errno = 0;
758 return NULL;
759 }
760
fd9f45e1
KZ
761 if (pr->parent &&
762 pr->parent->devno == pr->devno &&
ac8874ca
KZ
763 pr->parent->off <= pr->off &&
764 pr->parent->off + pr->parent->size >= pr->off + pr->size) {
fd9f45e1
KZ
765 /*
766 * This is a cloned prober and points to the same area as
ac8874ca
KZ
767 * parent. Let's use parent's buffers.
768 *
769 * Note that pr->off (and pr->parent->off) is always from the
a674a0ab 770 * begin of the device.
fd9f45e1 771 */
ac8874ca
KZ
772 return blkid_probe_get_buffer(pr->parent,
773 pr->off + off - pr->parent->off, len);
774 }
fd9f45e1 775
d2b0c658
KZ
776 /* try buffers we already have in memory or read from device */
777 bf = get_cached_buffer(pr, off, len);
a674a0ab 778 if (!bf) {
e04f3860 779 bf = read_buffer(pr, real_off, len);
a674a0ab 780 if (!bf)
1ca17f91 781 return NULL;
1ca17f91 782
77b85278 783 mark_prunable_buffers(pr, bf);
15a8fb42 784 list_add_tail(&bf->bufs, &pr->buffers);
1ca17f91 785 }
15a8fb42 786
a674a0ab
KZ
787 assert(bf->off <= real_off);
788 assert(bf->off + bf->len >= real_off + len);
789
00749bc3 790 errno = 0;
a674a0ab 791 return real_off ? bf->data + (real_off - bf->off) : bf->data;
1ca17f91
KZ
792}
793
d2b0c658
KZ
794/**
795 * blkid_probe_reset_buffers:
796 * @pr: prober
797 *
311e33af 798 * libblkid reuse all already read buffers from the device. The buffers may be
d2b0c658 799 * modified by blkid_probe_hide_range(). This function reset and free all
311e33af 800 * cached buffers. The next blkid_do_probe() will read all data from the
d2b0c658
KZ
801 * device.
802 *
95fbd2db
KZ
803 * Since: 2.31
804 *
d2b0c658
KZ
805 * Returns: <0 in case of failure, or 0 on success.
806 */
807int blkid_probe_reset_buffers(blkid_probe pr)
a0948ffe 808{
2355dd6a 809 uint64_t ct = 0, len = 0;
15a8fb42 810
d2b0c658
KZ
811 pr->flags &= ~BLKID_FL_MODIF_BUFF;
812
77b85278
TW
813 blkid_probe_prune_buffers(pr);
814
7f787ced 815 if (list_empty(&pr->buffers))
d2b0c658 816 return 0;
15a8fb42 817
63c9c05d 818 DBG(BUFFER, ul_debug("Resetting probing buffers"));
15a8fb42
KZ
819
820 while (!list_empty(&pr->buffers)) {
821 struct blkid_bufinfo *bf = list_entry(pr->buffers.next,
822 struct blkid_bufinfo, bufs);
2355dd6a
KZ
823 ct++;
824 len += bf->len;
a674a0ab 825
2dc39ee6 826 remove_buffer(bf);
4884729a 827 }
15a8fb42 828
e04f3860 829 DBG(LOWPROBE, ul_debug(" buffers summary: %"PRIu64" bytes by %"PRIu64" read() calls",
2355dd6a 830 len, ct));
15a8fb42
KZ
831
832 INIT_LIST_HEAD(&pr->buffers);
d2b0c658
KZ
833
834 return 0;
835}
836
837/**
838 * blkid_probe_hide_range:
839 * @pr: prober
840 * @off: start of the range
841 * @len: size of the range
842 *
843 * This function modifies in-memory cached data from the device. The specified
844 * range is zeroized. This is usable together with blkid_probe_step_back().
845 * The next blkid_do_probe() will not see specified area.
846 *
847 * Note that this is usable for already (by library) read data, and this
848 * function is not a way how to hide any large areas on your device.
849 *
850 * The function blkid_probe_reset_buffers() reverts all.
851 *
95fbd2db
KZ
852 * Since: 2.31
853 *
d2b0c658
KZ
854 * Returns: <0 in case of failure, or 0 on success.
855 */
856int blkid_probe_hide_range(blkid_probe pr, uint64_t off, uint64_t len)
857{
858 int rc = hide_buffer(pr, off, len);
859
860 if (rc == 0)
861 pr->flags |= BLKID_FL_MODIF_BUFF;
862 return rc;
a0948ffe
KZ
863}
864
67719fbb 865
af17d349 866static void blkid_probe_reset_values(blkid_probe pr)
6c4a7811 867{
7f787ced 868 if (list_empty(&pr->values))
6c4a7811
OO
869 return;
870
63c9c05d 871 DBG(LOWPROBE, ul_debug("resetting results"));
6c4a7811 872
af17d349
KZ
873 while (!list_empty(&pr->values)) {
874 struct blkid_prval *v = list_entry(pr->values.next,
6c4a7811 875 struct blkid_prval, prvals);
af17d349 876 blkid_probe_free_value(v);
6c4a7811
OO
877 }
878
af17d349 879 INIT_LIST_HEAD(&pr->values);
6c4a7811
OO
880}
881
108013b4
KZ
882/*
883 * Small devices need a special care.
884 */
885int blkid_probe_is_tiny(blkid_probe pr)
886{
7f787ced 887 return (pr->flags & BLKID_FL_TINY_DEV);
108013b4
KZ
888}
889
55113b15
C
890/*
891 * CDROMs may fail when probed for RAID (last sector problem)
892 */
893int blkid_probe_is_cdrom(blkid_probe pr)
894{
7f787ced 895 return (pr->flags & BLKID_FL_CDROM_DEV);
55113b15
C
896}
897
a0cf9105
LB
898int blkdid_probe_is_opal_locked(blkid_probe pr)
899{
900 return (pr->flags & BLKID_FL_OPAL_LOCKED);
901}
902
332123f2
RM
903#ifdef CDROM_GET_CAPABILITY
904
bfebe74e
KZ
905static int is_sector_readable(int fd, uint64_t sector)
906{
907 char buf[512];
908 ssize_t sz;
909
a732e4a1 910 if (lseek(fd, sector * 512, SEEK_SET) == (off_t) -1)
bfebe74e
KZ
911 goto failed;
912
913 sz = read(fd, buf, sizeof(buf));
914 if (sz != (ssize_t) sizeof(buf))
915 goto failed;
916
917 return 1;
918failed:
eaaf0e7e 919 DBG(LOWPROBE, ul_debug("CDROM: read sector %"PRIu64" failed %m", sector));
bfebe74e
KZ
920 errno = 0;
921 return 0;
922}
923
924/*
6548ac6a
KZ
925 * Linux kernel reports (BLKGETSIZE) cdrom device size greater than area
926 * readable by read(2). We have to reduce the probing area to avoid unwanted
927 * I/O errors in probing functions. It seems that unreadable are always last 2
928 * or 3 CD blocks (CD block size is 2048 bytes, it means 12 in 512-byte
bfd4da56
PR
929 * sectors). Linux kernel reports (CDROM_LAST_WRITTEN) also location of last
930 * written block, so we will reduce size based on it too.
bfebe74e 931 */
bfd4da56 932static void cdrom_size_correction(blkid_probe pr, uint64_t last_written)
bfebe74e 933{
6548ac6a 934 uint64_t n, nsectors = pr->size >> 9;
bfebe74e 935
bfd4da56
PR
936 if (last_written && nsectors > ((last_written+1) << 2))
937 nsectors = (last_written+1) << 2;
938
bfebe74e
KZ
939 for (n = nsectors - 12; n < nsectors; n++) {
940 if (!is_sector_readable(pr->fd, n))
941 goto failed;
942 }
943
944 DBG(LOWPROBE, ul_debug("CDROM: full size available"));
945 return;
946failed:
947 /* 'n' is the failed sector, reduce device size to n-1; */
948 DBG(LOWPROBE, ul_debug("CDROM: reduce size from %ju to %ju.",
949 (uintmax_t) pr->size,
1bd62f72 950 (uintmax_t) n << 9));
bfebe74e
KZ
951 pr->size = n << 9;
952}
953
332123f2
RM
954#endif
955
52448df8
KZ
956/**
957 * blkid_probe_set_device:
958 * @pr: probe
959 * @fd: device file descriptor
960 * @off: begin of probing area
f38db0cf 961 * @size: size of probing area (zero means whole device/file)
52448df8 962 *
c4d6d1c5
KZ
963 * Assigns the device to probe control struct, resets internal buffers, resets
964 * the current probing, and close previously associated device (if open by
965 * libblkid).
51410fc6 966 *
c4d6d1c5
KZ
967 * If @fd is < 0 than only resets the prober and returns 1. Note that
968 * blkid_reset_probe() keeps the device associated with the prober, but
969 * blkid_probe_set_device() does complete reset.
970 *
971 * Returns: -1 in case of failure, 0 on success and 1 on reset.
51410fc6
KZ
972 */
973int blkid_probe_set_device(blkid_probe pr, int fd,
974 blkid_loff_t off, blkid_loff_t size)
a0948ffe 975{
90ec8d9c 976 struct stat sb;
f12cd8d1 977 uint64_t devsiz = 0;
884659b3 978 char *dm_uuid = NULL;
f5ea9eee 979 int is_floppy = 0;
90ec8d9c 980
51410fc6 981 blkid_reset_probe(pr);
d2b0c658 982 blkid_probe_reset_buffers(pr);
a0948ffe 983
a9eef56c 984 if ((pr->flags & BLKID_FL_PRIVATE_FD) && pr->fd >= 0)
f38db0cf
KZ
985 close(pr->fd);
986
c4d6d1c5
KZ
987 if (pr->disk_probe) {
988 blkid_free_probe(pr->disk_probe);
989 pr->disk_probe = NULL;
990 }
991
a9eef56c
KZ
992 pr->flags &= ~BLKID_FL_PRIVATE_FD;
993 pr->flags &= ~BLKID_FL_TINY_DEV;
994 pr->flags &= ~BLKID_FL_CDROM_DEV;
ccdf9fda 995 pr->prob_flags = 0;
51410fc6 996 pr->fd = fd;
f12cd8d1 997 pr->off = (uint64_t) off;
bb6c6673 998 pr->size = 0;
52448df8 999 pr->devno = 0;
ccdf9fda 1000 pr->disk_devno = 0;
52448df8
KZ
1001 pr->mode = 0;
1002 pr->blkssz = 0;
ccdf9fda
KZ
1003 pr->wipe_off = 0;
1004 pr->wipe_size = 0;
1005 pr->wipe_chain = NULL;
b250fbbf 1006 pr->zone_size = 0;
dc61d909 1007
c4d6d1c5
KZ
1008 if (fd < 0)
1009 return 1;
1010
2d24f963 1011
a67bb3bf
LT
1012#if defined(POSIX_FADV_RANDOM) && defined(HAVE_POSIX_FADVISE)
1013 /* Disable read-ahead */
1014 posix_fadvise(fd, 0, 0, POSIX_FADV_RANDOM);
1015#endif
90ec8d9c
KZ
1016 if (fstat(fd, &sb))
1017 goto err;
1018
a674a0ab 1019 if (!S_ISBLK(sb.st_mode) && !S_ISCHR(sb.st_mode) && !S_ISREG(sb.st_mode)) {
2355dd6a 1020 errno = EINVAL;
26eb5a59 1021 goto err;
a674a0ab 1022 }
20e1c3dc 1023
90ec8d9c
KZ
1024 pr->mode = sb.st_mode;
1025 if (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode))
1026 pr->devno = sb.st_rdev;
1027
a674a0ab
KZ
1028 if (S_ISBLK(sb.st_mode)) {
1029 if (blkdev_get_size(fd, (unsigned long long *) &devsiz)) {
1030 DBG(LOWPROBE, ul_debug("failed to get device size"));
108013b4 1031 goto err;
a674a0ab 1032 }
7eb6d9ce
KZ
1033 } else if (S_ISCHR(sb.st_mode)) {
1034 char buf[PATH_MAX];
1035
1036 if (!sysfs_chrdev_devno_to_devname(sb.st_rdev, buf, sizeof(buf))
1037 || strncmp(buf, "ubi", 3) != 0) {
1038 DBG(LOWPROBE, ul_debug("no UBI char device"));
1039 errno = EINVAL;
1040 goto err;
1041 }
a674a0ab 1042 devsiz = 1; /* UBI devices are char... */
7eb6d9ce 1043 } else if (S_ISREG(sb.st_mode))
a674a0ab
KZ
1044 devsiz = sb.st_size; /* regular file */
1045
b9710f1f 1046 pr->size = size ? (uint64_t)size : devsiz;
108013b4 1047
a674a0ab
KZ
1048 if (off && size == 0)
1049 /* only offset without size specified */
f12cd8d1 1050 pr->size -= (uint64_t) off;
a674a0ab
KZ
1051
1052 if (pr->off + pr->size > devsiz) {
1053 DBG(LOWPROBE, ul_debug("area specified by offset and size is bigger than device"));
1054 errno = EINVAL;
1055 goto err;
bb6c6673 1056 }
c1ba7962 1057
90ec8d9c 1058 if (pr->size <= 1440 * 1024 && !S_ISCHR(sb.st_mode))
a9eef56c 1059 pr->flags |= BLKID_FL_TINY_DEV;
d0465c3c 1060
f5ea9eee
KZ
1061#ifdef FDGETFDCSTAT
1062 if (S_ISBLK(sb.st_mode)) {
1063 /*
1064 * Re-open without O_NONBLOCK for floppy device.
1065 *
1066 * Since kernel commit c7e9d0020361f4308a70cdfd6d5335e273eb8717
1067 * floppy drive works bad when opened with O_NONBLOCK.
1068 */
1069 struct floppy_fdc_state flst;
1070
1071 if (ioctl(fd, FDGETFDCSTAT, &flst) >= 0) {
1072 int flags = fcntl(fd, F_GETFL, 0);
1073
1074 if (flags < 0)
1075 goto err;
1076 if (flags & O_NONBLOCK) {
1077 flags &= ~O_NONBLOCK;
1078
1079 fd = ul_reopen(fd, flags | O_CLOEXEC);
1080 if (fd < 0)
1081 goto err;
1082
1083 pr->flags |= BLKID_FL_PRIVATE_FD;
1084 pr->fd = fd;
1085 }
1086 is_floppy = 1;
1087 }
1088 errno = 0;
1089 }
1090#endif
884659b3 1091 if (S_ISBLK(sb.st_mode) &&
f5ea9eee 1092 !is_floppy &&
80ec018c
TA
1093 sysfs_devno_is_dm_private(sb.st_rdev, &dm_uuid)) {
1094 DBG(LOWPROBE, ul_debug("ignore private device mapper device"));
20e1c3dc
KZ
1095 pr->flags |= BLKID_FL_NOSCAN_DEV;
1096 }
1097
55113b15 1098#ifdef CDROM_GET_CAPABILITY
20e1c3dc 1099 else if (S_ISBLK(sb.st_mode) &&
a3ab71cf 1100 !blkid_probe_is_tiny(pr) &&
884659b3 1101 !dm_uuid &&
f5ea9eee 1102 !is_floppy &&
6b88a410
PR
1103 blkid_probe_is_wholedisk(pr)) {
1104
ed1f6f10
KZ
1105 long last_written = 0;
1106
3d725afa 1107 /*
6b88a410
PR
1108 * pktcdvd.ko accepts only these ioctls:
1109 * CDROMEJECT CDROMMULTISESSION CDROMREADTOCENTRY
1110 * CDROM_LAST_WRITTEN CDROM_SEND_PACKET SCSI_IOCTL_SEND_COMMAND
1111 * So CDROM_GET_CAPABILITY cannot be used for detecting pktcdvd
1112 * devices. But CDROM_GET_CAPABILITY and CDROM_DRIVE_STATUS are
1113 * fast so use them for detecting if medium is present. In any
1114 * case use last written block form CDROM_LAST_WRITTEN.
1115 */
bfebe74e 1116
6b88a410 1117 if (ioctl(fd, CDROM_GET_CAPABILITY, NULL) >= 0) {
dc30fd43 1118# ifdef CDROM_DRIVE_STATUS
6b88a410
PR
1119 switch (ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT)) {
1120 case CDS_TRAY_OPEN:
1121 case CDS_NO_DISC:
1122 errno = ENOMEDIUM;
1123 goto err;
1124 }
1125# endif
1126 pr->flags |= BLKID_FL_CDROM_DEV;
dc30fd43 1127 }
6b88a410
PR
1128
1129# ifdef CDROM_LAST_WRITTEN
c80b3f32 1130 if (ioctl(fd, CDROM_LAST_WRITTEN, &last_written) == 0) {
6b88a410 1131 pr->flags |= BLKID_FL_CDROM_DEV;
c80b3f32
JP
1132 } else {
1133 if (errno == ENOMEDIUM)
1134 goto err;
1135 }
dc30fd43 1136# endif
6b88a410
PR
1137
1138 if (pr->flags & BLKID_FL_CDROM_DEV) {
bfd4da56 1139 cdrom_size_correction(pr, last_written);
427ea355
PR
1140
1141# ifdef CDROMMULTISESSION
1142 if (!pr->off && blkid_probe_get_hint(pr, "session_offset", NULL) < 0) {
1143 struct cdrom_multisession multisession = { .addr_format = CDROM_LBA };
1144 if (ioctl(fd, CDROMMULTISESSION, &multisession) == 0 && multisession.xa_flag)
1145 blkid_probe_set_hint(pr, "session_offset", (multisession.addr.lba << 11));
1146 }
1147# endif
6b88a410 1148 }
bfebe74e 1149 }
55113b15 1150#endif
884659b3 1151 free(dm_uuid);
508e438b 1152
60d1f1a3 1153# ifdef BLKGETZONESZ
f5ea9eee 1154 if (S_ISBLK(sb.st_mode) && !is_floppy) {
b250fbbf
NA
1155 uint32_t zone_size_sector;
1156
1157 if (!ioctl(pr->fd, BLKGETZONESZ, &zone_size_sector))
1158 pr->zone_size = zone_size_sector << 9;
1159 }
1160# endif
1161
2964fd91
KZ
1162 DBG(LOWPROBE, ul_debug("ready for low-probing, offset=%"PRIu64", size=%"PRIu64", zonesize=%"PRIu64,
1163 pr->off, pr->size, pr->zone_size));
c62a6311 1164 DBG(LOWPROBE, ul_debug("whole-disk: %s, regfile: %s",
508e438b
KZ
1165 blkid_probe_is_wholedisk(pr) ?"YES" : "NO",
1166 S_ISREG(pr->mode) ? "YES" : "NO"));
1167
a0948ffe 1168 return 0;
0d17b1cf 1169err:
c62a6311 1170 DBG(LOWPROBE, ul_debug("failed to prepare a device for low-probing"));
0d17b1cf
KZ
1171 return -1;
1172
a0948ffe
KZ
1173}
1174
f12cd8d1 1175int blkid_probe_get_dimension(blkid_probe pr, uint64_t *off, uint64_t *size)
f319b5ca 1176{
f319b5ca
KZ
1177 *off = pr->off;
1178 *size = pr->size;
1179 return 0;
1180}
1181
f12cd8d1 1182int blkid_probe_set_dimension(blkid_probe pr, uint64_t off, uint64_t size)
f319b5ca 1183{
c62a6311 1184 DBG(LOWPROBE, ul_debug(
63c9c05d 1185 "changing probing area: size=%"PRIu64", off=%"PRIu64" "
fdbd7bb9 1186 "-to-> size=%"PRIu64", off=%"PRIu64"",
63c9c05d 1187 pr->size, pr->off, size, off));
f319b5ca
KZ
1188
1189 pr->off = off;
1190 pr->size = size;
a9eef56c 1191 pr->flags &= ~BLKID_FL_TINY_DEV;
88923b08 1192
f12cd8d1 1193 if (pr->size <= 1440ULL * 1024ULL && !S_ISCHR(pr->mode))
a9eef56c 1194 pr->flags |= BLKID_FL_TINY_DEV;
f319b5ca 1195
d2b0c658 1196 blkid_probe_reset_buffers(pr);
f319b5ca
KZ
1197
1198 return 0;
1199}
1200
7eba8f98 1201const unsigned char *blkid_probe_get_sb_buffer(blkid_probe pr, const struct blkid_idmag *mag, size_t size)
b5c5b420 1202{
2816a817 1203 uint64_t hint_offset, off;
b5c5b420 1204
2816a817
TW
1205 if (mag->kboff >= 0) {
1206 if (!mag->hoff || blkid_probe_get_hint(pr, mag->hoff, &hint_offset) < 0)
1207 hint_offset = 0;
b5c5b420 1208
2816a817
TW
1209 off = hint_offset + (mag->kboff << 10);
1210 } else {
1211 off = pr->size - (-mag->kboff << 10);
1212 }
1213
1214 return blkid_probe_get_buffer(pr, off, size);
b5c5b420
PR
1215}
1216
8d0ce083 1217/*
296d96e2
HR
1218 * Check for matching magic value.
1219 * Returns BLKID_PROBE_OK if found, BLKID_PROBE_NONE if not found
1220 * or no magic present, or negative value on error.
1221 */
c76e710b 1222int blkid_probe_get_idmag(blkid_probe pr, const struct blkid_idinfo *id,
f12cd8d1 1223 uint64_t *offset, const struct blkid_idmag **res)
c76e710b
KZ
1224{
1225 const struct blkid_idmag *mag = NULL;
f12cd8d1 1226 uint64_t off = 0;
c76e710b
KZ
1227
1228 if (id)
c03d12d8 1229 mag = &id->magics[0];
c76e710b
KZ
1230 if (res)
1231 *res = NULL;
1232
1233 /* try to detect by magic string */
1234 while(mag && mag->magic) {
7eba8f98 1235 const unsigned char *buf;
2816a817 1236 long kboff;
3e31657d 1237 uint64_t hint_offset;
c76e710b 1238
3e31657d
PR
1239 if (!mag->hoff || blkid_probe_get_hint(pr, mag->hoff, &hint_offset) < 0)
1240 hint_offset = 0;
c76e710b 1241
b250fbbf
NA
1242 /* If the magic is for zoned device, skip non-zoned device */
1243 if (mag->is_zoned && !pr->zone_size) {
1244 mag++;
1245 continue;
1246 }
1247
1248 if (!mag->is_zoned)
1249 kboff = mag->kboff;
1250 else
1251 kboff = ((mag->zonenum * pr->zone_size) >> 10) + mag->kboff_inzone;
1252
2816a817
TW
1253 if (kboff >= 0)
1254 off = hint_offset + ((kboff + (mag->sboff >> 10)) << 10);
1255 else
1256 off = pr->size - (-kboff << 10);
c76e710b
KZ
1257 buf = blkid_probe_get_buffer(pr, off, 1024);
1258
296d96e2
HR
1259 if (!buf && errno)
1260 return -errno;
a674a0ab 1261
c76e710b
KZ
1262 if (buf && !memcmp(mag->magic,
1263 buf + (mag->sboff & 0x3ff), mag->len)) {
a674a0ab 1264
2816a817 1265 DBG(LOWPROBE, ul_debug("\tmagic sboff=%u, kboff=%ld",
b250fbbf 1266 mag->sboff, kboff));
c76e710b
KZ
1267 if (offset)
1268 *offset = off + (mag->sboff & 0x3ff);
1269 if (res)
1270 *res = mag;
296d96e2 1271 return BLKID_PROBE_OK;
c76e710b
KZ
1272 }
1273 mag++;
1274 }
1275
c03d12d8 1276 if (id && id->magics[0].magic)
c76e710b 1277 /* magic string(s) defined, but not found */
296d96e2 1278 return BLKID_PROBE_NONE;
c76e710b 1279
296d96e2 1280 return BLKID_PROBE_OK;
c76e710b
KZ
1281}
1282
c81e7008
KZ
1283static inline void blkid_probe_start(blkid_probe pr)
1284{
63c9c05d 1285 DBG(LOWPROBE, ul_debug("start probe"));
7f787ced
KZ
1286 pr->cur_chain = NULL;
1287 pr->prob_flags = 0;
1288 blkid_probe_set_wiper(pr, 0, 0);
c81e7008
KZ
1289}
1290
1291static inline void blkid_probe_end(blkid_probe pr)
1292{
63c9c05d 1293 DBG(LOWPROBE, ul_debug("end probe"));
7f787ced
KZ
1294 pr->cur_chain = NULL;
1295 pr->prob_flags = 0;
1296 blkid_probe_set_wiper(pr, 0, 0);
c81e7008
KZ
1297}
1298
0bffad47
KZ
1299/**
1300 * blkid_do_probe:
1301 * @pr: prober
1302 *
1303 * Calls probing functions in all enabled chains. The superblocks chain is
1304 * enabled by default. The blkid_do_probe() stores result from only one
1305 * probing function. It's necessary to call this routine in a loop to get
3b159691 1306 * results from all probing functions in all chains. The probing is reset
44ef90bc 1307 * by blkid_reset_probe() or by filter functions.
a0fc685c 1308 *
0bffad47
KZ
1309 * This is string-based NAME=value interface only.
1310 *
1311 * <example>
1312 * <title>basic case - use the first result only</title>
1313 * <programlisting>
2bd739c9 1314 * if (blkid_do_probe(pr) == BLKID_PROBE_OK) {
a0fc685c
KZ
1315 * int nvals = blkid_probe_numof_values(pr);
1316 * for (n = 0; n < nvals; n++) {
1317 * if (blkid_probe_get_value(pr, n, &name, &data, &len) == 0)
1318 * printf("%s = %s\n", name, data);
1319 * }
1320 * }
0bffad47
KZ
1321 * </programlisting>
1322 * </example>
a0fc685c 1323 *
0bffad47
KZ
1324 * <example>
1325 * <title>advanced case - probe for all signatures</title>
1326 * <programlisting>
2bd739c9 1327 * while (blkid_do_probe(pr) == BLKID_PROBE_OK) {
a0fc685c
KZ
1328 * int nvals = blkid_probe_numof_values(pr);
1329 * ...
1330 * }
0bffad47
KZ
1331 * </programlisting>
1332 * </example>
a0fc685c 1333 *
0bffad47 1334 * See also blkid_reset_probe().
a0fc685c 1335 *
0bffad47 1336 * Returns: 0 on success, 1 when probing is done and -1 in case of error.
a0fc685c 1337 */
51410fc6 1338int blkid_do_probe(blkid_probe pr)
a0948ffe 1339{
0bffad47 1340 int rc = 1;
a0948ffe 1341
20e1c3dc 1342 if (pr->flags & BLKID_FL_NOSCAN_DEV)
2bd739c9 1343 return BLKID_PROBE_NONE;
20e1c3dc 1344
0bffad47 1345 do {
44ef90bc
KZ
1346 struct blkid_chain *chn = pr->cur_chain;
1347
c81e7008
KZ
1348 if (!chn) {
1349 blkid_probe_start(pr);
44ef90bc 1350 chn = pr->cur_chain = &pr->chains[0];
c81e7008 1351 }
44ef90bc
KZ
1352 /* we go to the next chain only when the previous probing
1353 * result was nothing (rc == 1) and when the current chain is
1354 * disabled or we are at end of the current chain (chain->idx +
046959cc
CW
1355 * 1 == sizeof chain) or the current chain bailed out right at
1356 * the start (chain->idx == -1)
44ef90bc
KZ
1357 */
1358 else if (rc == 1 && (chn->enabled == FALSE ||
c9f51c71 1359 chn->idx + 1 == (int) chn->driver->nidinfos ||
046959cc 1360 chn->idx == -1)) {
a0948ffe 1361
c9f51c71 1362 size_t idx = chn->driver->id + 1;
bd635f86
KZ
1363
1364 if (idx < BLKID_NCHAINS)
44ef90bc 1365 chn = pr->cur_chain = &pr->chains[idx];
c81e7008
KZ
1366 else {
1367 blkid_probe_end(pr);
2bd739c9 1368 return BLKID_PROBE_NONE; /* all chains already probed */
c81e7008 1369 }
bd635f86 1370 }
a0fc685c 1371
0bffad47 1372 chn->binary = FALSE; /* for sure... */
6644688a 1373
c62a6311 1374 DBG(LOWPROBE, ul_debug("chain probe %s %s (idx=%d)",
0bffad47 1375 chn->driver->name,
44ef90bc
KZ
1376 chn->enabled? "ENABLED" : "DISABLED",
1377 chn->idx));
a0948ffe 1378
0bffad47 1379 if (!chn->enabled)
51410fc6 1380 continue;
a0948ffe 1381
0bffad47
KZ
1382 /* rc: -1 = error, 0 = success, 1 = no result */
1383 rc = chn->driver->probe(pr, chn);
a0948ffe 1384
2bd739c9
KZ
1385 } while (rc == BLKID_PROBE_NONE);
1386
1387 if (rc < 0)
1388 return BLKID_PROBE_ERROR;
a0948ffe 1389
0bffad47
KZ
1390 return rc;
1391}
a0948ffe 1392
db221158
NA
1393#ifdef HAVE_LINUX_BLKZONED_H
1394static int is_conventional(blkid_probe pr, uint64_t offset)
1395{
1396 struct blk_zone_report *rep = NULL;
1397 int ret;
1398 uint64_t zone_mask;
1399
1400 if (!pr->zone_size)
1401 return 1;
1402
1403 zone_mask = ~(pr->zone_size - 1);
1404 rep = blkdev_get_zonereport(blkid_probe_get_fd(pr),
1405 (offset & zone_mask) >> 9, 1);
1406 if (!rep)
1407 return -1;
1408
1409 if (rep->zones[0].type == BLK_ZONE_TYPE_CONVENTIONAL)
1410 ret = 1;
1411 else
1412 ret = 0;
1413
1414 free(rep);
1415
1416 return ret;
1417}
1418#else
1419static inline int is_conventional(blkid_probe pr __attribute__((__unused__)),
1420 uint64_t offset __attribute__((__unused__)))
1421{
1422 return 1;
1423}
1424#endif
1425
2b89be6c
KZ
1426/**
1427 * blkid_do_wipe:
1428 * @pr: prober
1429 * @dryrun: if TRUE then don't touch the device.
1430 *
1431 * This function erases the current signature detected by @pr. The @pr has to
476b508e 1432 * be open in O_RDWR mode, BLKID_SUBLKS_MAGIC or/and BLKID_PARTS_MAGIC flags
9e930041 1433 * has to be enabled (if you want to erase also superblock with broken check
c93c2030 1434 * sums then use BLKID_SUBLKS_BADCSUM too).
2b89be6c
KZ
1435 *
1436 * After successful signature removing the @pr prober will be moved one step
1437 * back and the next blkid_do_probe() call will again call previously called
d2b0c658 1438 * probing function. All in-memory cached data from the device are always
73afd3f8 1439 * reset.
2b89be6c
KZ
1440 *
1441 * <example>
1442 * <title>wipe all filesystems or raids from the device</title>
1443 * <programlisting>
49a8f58e 1444 * fd = open(devname, O_RDWR|O_CLOEXEC);
2b89be6c
KZ
1445 * blkid_probe_set_device(pr, fd, 0, 0);
1446 *
1447 * blkid_probe_enable_superblocks(pr, 1);
1448 * blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_MAGIC);
1449 *
1450 * while (blkid_do_probe(pr) == 0)
1451 * blkid_do_wipe(pr, FALSE);
1452 * </programlisting>
1453 * </example>
1454 *
11026083 1455 * See also blkid_probe_step_back() if you cannot use this built-in wipe
cd0fe5c1
KZ
1456 * function, but you want to use libblkid probing as a source for wiping.
1457 *
1458 * Returns: 0 on success, and -1 in case of error.
2b89be6c
KZ
1459 */
1460int blkid_do_wipe(blkid_probe pr, int dryrun)
1461{
44765fdd 1462 const char *off = NULL;
2b89be6c 1463 size_t len = 0;
a732e4a1 1464 uint64_t offset, magoff;
db221158 1465 int conventional;
2b89be6c 1466 char buf[BUFSIZ];
f8054232 1467 int fd, rc = 0;
2b89be6c
KZ
1468 struct blkid_chain *chn;
1469
2b89be6c
KZ
1470 chn = pr->cur_chain;
1471 if (!chn)
2bd739c9 1472 return BLKID_PROBE_ERROR;
2b89be6c 1473
44765fdd
KZ
1474 switch (chn->driver->id) {
1475 case BLKID_CHAIN_SUBLKS:
1476 rc = blkid_probe_lookup_value(pr, "SBMAGIC_OFFSET", &off, NULL);
1477 if (!rc)
1478 rc = blkid_probe_lookup_value(pr, "SBMAGIC", NULL, &len);
1479 break;
1480 case BLKID_CHAIN_PARTS:
1481 rc = blkid_probe_lookup_value(pr, "PTMAGIC_OFFSET", &off, NULL);
1482 if (!rc)
1483 rc = blkid_probe_lookup_value(pr, "PTMAGIC", NULL, &len);
1484 break;
1485 default:
2bd739c9 1486 return BLKID_PROBE_OK;
44765fdd
KZ
1487 }
1488
1489 if (rc || len == 0 || off == NULL)
2bd739c9 1490 return BLKID_PROBE_OK;
2b89be6c 1491
0395e8f7 1492 errno = 0;
d2b0c658 1493 magoff = strtoumax(off, NULL, 10);
0395e8f7 1494 if (errno)
2bd739c9 1495 return BLKID_PROBE_OK;
0395e8f7 1496
d2b0c658 1497 offset = magoff + pr->off;
2b89be6c
KZ
1498 fd = blkid_probe_get_fd(pr);
1499 if (fd < 0)
2bd739c9 1500 return BLKID_PROBE_ERROR;
2b89be6c
KZ
1501
1502 if (len > sizeof(buf))
1503 len = sizeof(buf);
1504
db221158
NA
1505 rc = is_conventional(pr, offset);
1506 if (rc < 0)
2bd739c9 1507 return BLKID_PROBE_ERROR;
db221158
NA
1508 conventional = rc == 1;
1509
c62a6311 1510 DBG(LOWPROBE, ul_debug(
fdbd7bb9 1511 "do_wipe [offset=0x%"PRIx64" (%"PRIu64"), len=%zu, chain=%s, idx=%d, dryrun=%s]\n",
f12cd8d1 1512 offset, offset, len, chn->driver->name, chn->idx, dryrun ? "yes" : "not"));
2b89be6c 1513
a732e4a1 1514 if (lseek(fd, offset, SEEK_SET) == (off_t) -1)
2bd739c9 1515 return BLKID_PROBE_ERROR;
2b89be6c 1516
2b89be6c 1517 if (!dryrun && len) {
db221158
NA
1518 if (conventional) {
1519 memset(buf, 0, len);
1520
1521 /* wipen on device */
1522 if (write_all(fd, buf, len))
2bd739c9 1523 return BLKID_PROBE_ERROR;
133a0d70 1524 if (fsync(fd) != 0)
2bd739c9 1525 return BLKID_PROBE_ERROR;
db221158
NA
1526 } else {
1527#ifdef HAVE_LINUX_BLKZONED_H
1528 uint64_t zone_mask = ~(pr->zone_size - 1);
1529 struct blk_zone_range range = {
1530 .sector = (offset & zone_mask) >> 9,
1531 .nr_sectors = pr->zone_size >> 9,
1532 };
1533
1534 rc = ioctl(fd, BLKRESETZONE, &range);
1535 if (rc < 0)
2bd739c9 1536 return BLKID_PROBE_ERROR;
db221158
NA
1537#else
1538 /* Should not reach here */
1539 assert(0);
1540#endif
1541 }
1542
d2b0c658
KZ
1543 pr->flags &= ~BLKID_FL_MODIF_BUFF; /* be paranoid */
1544
1545 return blkid_probe_step_back(pr);
1546
042f62df
RP
1547 }
1548
1549 if (dryrun) {
d2b0c658
KZ
1550 /* wipe in memory only */
1551 blkid_probe_hide_range(pr, magoff, len);
cd0fe5c1
KZ
1552 return blkid_probe_step_back(pr);
1553 }
2b89be6c 1554
2bd739c9 1555 return BLKID_PROBE_OK;
cd0fe5c1 1556}
2b89be6c 1557
cd0fe5c1 1558/**
c0055e2a 1559 * blkid_probe_step_back:
cd0fe5c1
KZ
1560 * @pr: prober
1561 *
1562 * This function move pointer to the probing chain one step back -- it means
1563 * that the previously used probing function will be called again in the next
1564 * blkid_do_probe() call.
1565 *
1566 * This is necessary for example if you erase or modify on-disk superblock
1567 * according to the current libblkid probing result.
1568 *
d2b0c658 1569 * Note that blkid_probe_hide_range() changes semantic of this function and
311e33af 1570 * cached buffers are not reset, but library uses in-memory modified
d2b0c658
KZ
1571 * buffers to call the next probing function.
1572 *
cd0fe5c1
KZ
1573 * <example>
1574 * <title>wipe all superblock, but use libblkid only for probing</title>
1575 * <programlisting>
1576 * pr = blkid_new_probe_from_filename(devname);
1577 *
1578 * blkid_probe_enable_superblocks(pr, 1);
1579 * blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_MAGIC);
1580 *
2bb7a706
KZ
1581 * blkid_probe_enable_partitions(pr, 1);
1582 * blkid_probe_set_partitions_flags(pr, BLKID_PARTS_MAGIC);
1583 *
2bd739c9 1584 * while (blkid_do_probe(pr) == BLKID_PROBE_OK) {
cd0fe5c1
KZ
1585 * const char *ostr = NULL;
1586 * size_t len = 0;
1587 *
1588 * // superblocks
1589 * if (blkid_probe_lookup_value(pr, "SBMAGIC_OFFSET", &ostr, NULL) == 0)
1590 * blkid_probe_lookup_value(pr, "SBMAGIC", NULL, &len);
1591 *
1592 * // partition tables
1593 * if (len == 0 && blkid_probe_lookup_value(pr, "PTMAGIC_OFFSET", &ostr, NULL) == 0)
1594 * blkid_probe_lookup_value(pr, "PTMAGIC", NULL, &len);
1595 *
1596 * if (!len || !str)
1597 * continue;
1598 *
1599 * // convert ostr to the real offset by off = strtoll(ostr, NULL, 10);
9e930041 1600 * // use your stuff to erase @len bytes at the @off
cd0fe5c1
KZ
1601 * ....
1602 *
1603 * // retry the last probing to check for backup superblocks ..etc.
1604 * blkid_probe_step_back(pr);
1605 * }
1606 * </programlisting>
1607 * </example>
1608 *
1609 * Returns: 0 on success, and -1 in case of error.
1610 */
1611int blkid_probe_step_back(blkid_probe pr)
1612{
1613 struct blkid_chain *chn;
1614
cd0fe5c1
KZ
1615 chn = pr->cur_chain;
1616 if (!chn)
1617 return -1;
1618
d2b0c658
KZ
1619 if (!(pr->flags & BLKID_FL_MODIF_BUFF))
1620 blkid_probe_reset_buffers(pr);
cd0fe5c1
KZ
1621
1622 if (chn->idx >= 0) {
1623 chn->idx--;
c62a6311 1624 DBG(LOWPROBE, ul_debug("step back: moving %s chain index to %d",
cd0fe5c1
KZ
1625 chn->driver->name,
1626 chn->idx));
2b89be6c 1627 }
cd0fe5c1
KZ
1628
1629 if (chn->idx == -1) {
1630 /* blkid_do_probe() goes to the next chain if the index
1631 * of the current chain is -1, so we have to set the
1632 * chain pointer to the previous chain.
1633 */
1634 size_t idx = chn->driver->id > 0 ? chn->driver->id - 1 : 0;
1635
c62a6311 1636 DBG(LOWPROBE, ul_debug("step back: moving to previous chain"));
cd0fe5c1
KZ
1637
1638 if (idx > 0)
1639 pr->cur_chain = &pr->chains[idx];
1640 else if (idx == 0)
1641 pr->cur_chain = NULL;
1642 }
1643
2b89be6c
KZ
1644 return 0;
1645}
1646
0bffad47
KZ
1647/**
1648 * blkid_do_safeprobe:
1649 * @pr: prober
1650 *
1651 * This function gathers probing results from all enabled chains and checks
1652 * for ambivalent results (e.g. more filesystems on the device).
1653 *
1654 * This is string-based NAME=value interface only.
1655 *
9e930041 1656 * Note about superblocks chain -- the function does not check for filesystems
0bffad47 1657 * when a RAID signature is detected. The function also does not check for
c81e7008
KZ
1658 * collision between RAIDs. The first detected RAID is returned. The function
1659 * checks for collision between partition table and RAID signature -- it's
1660 * recommended to enable partitions chain together with superblocks chain.
0bffad47 1661 *
9e930041 1662 * Returns: 0 on success, 1 if nothing is detected, -2 if ambivalent result is
0bffad47
KZ
1663 * detected and -1 on case of error.
1664 */
1665int blkid_do_safeprobe(blkid_probe pr)
1666{
1667 int i, count = 0, rc = 0;
a0948ffe 1668
20e1c3dc 1669 if (pr->flags & BLKID_FL_NOSCAN_DEV)
2bd739c9 1670 return BLKID_PROBE_NONE;
a0948ffe 1671
c81e7008
KZ
1672 blkid_probe_start(pr);
1673
0bffad47
KZ
1674 for (i = 0; i < BLKID_NCHAINS; i++) {
1675 struct blkid_chain *chn;
a0948ffe 1676
0bffad47
KZ
1677 chn = pr->cur_chain = &pr->chains[i];
1678 chn->binary = FALSE; /* for sure... */
a0948ffe 1679
c62a6311 1680 DBG(LOWPROBE, ul_debug("chain safeprobe %s %s",
0bffad47
KZ
1681 chn->driver->name,
1682 chn->enabled? "ENABLED" : "DISABLED"));
1683
1684 if (!chn->enabled)
1685 continue;
1686
9e0f7bda 1687 blkid_probe_chain_reset_position(chn);
0bffad47 1688
0bffad47 1689 rc = chn->driver->safeprobe(pr, chn);
9e0f7bda
KZ
1690
1691 blkid_probe_chain_reset_position(chn);
1692
1693 /* rc: -2 ambivalent, -1 = error, 0 = success, 1 = no result */
0bffad47
KZ
1694 if (rc < 0)
1695 goto done; /* error */
1696 if (rc == 0)
1697 count++; /* success */
51410fc6 1698 }
0bffad47
KZ
1699
1700done:
c81e7008 1701 blkid_probe_end(pr);
0bffad47 1702 if (rc < 0)
2bd739c9
KZ
1703 return BLKID_PROBE_ERROR;
1704
1705 return count == 0 ? BLKID_PROBE_NONE : BLKID_PROBE_OK;
a0948ffe
KZ
1706}
1707
0bffad47
KZ
1708/**
1709 * blkid_do_fullprobe:
1710 * @pr: prober
1711 *
1712 * This function gathers probing results from all enabled chains. Same as
fd7c9e35 1713 * blkid_do_safeprobe() but does not check for collision between probing
0bffad47
KZ
1714 * result.
1715 *
1716 * This is string-based NAME=value interface only.
7103157c 1717 *
0bffad47 1718 * Returns: 0 on success, 1 if nothing is detected or -1 on case of error.
a2f01a1c 1719 */
0bffad47 1720int blkid_do_fullprobe(blkid_probe pr)
a2f01a1c 1721{
0bffad47 1722 int i, count = 0, rc = 0;
7103157c 1723
20e1c3dc 1724 if (pr->flags & BLKID_FL_NOSCAN_DEV)
2bd739c9 1725 return BLKID_PROBE_NONE;
a2f01a1c 1726
c81e7008
KZ
1727 blkid_probe_start(pr);
1728
0bffad47 1729 for (i = 0; i < BLKID_NCHAINS; i++) {
0bffad47 1730 struct blkid_chain *chn;
a2f01a1c 1731
0bffad47
KZ
1732 chn = pr->cur_chain = &pr->chains[i];
1733 chn->binary = FALSE; /* for sure... */
1734
c62a6311 1735 DBG(LOWPROBE, ul_debug("chain fullprobe %s: %s",
0bffad47
KZ
1736 chn->driver->name,
1737 chn->enabled? "ENABLED" : "DISABLED"));
1738
1739 if (!chn->enabled)
1740 continue;
1741
9e0f7bda 1742 blkid_probe_chain_reset_position(chn);
0bffad47 1743
0bffad47 1744 rc = chn->driver->probe(pr, chn);
9e0f7bda
KZ
1745
1746 blkid_probe_chain_reset_position(chn);
1747
1748 /* rc: -1 = error, 0 = success, 1 = no result */
0bffad47
KZ
1749 if (rc < 0)
1750 goto done; /* error */
1751 if (rc == 0)
1752 count++; /* success */
1753 }
1754
1755done:
c81e7008 1756 blkid_probe_end(pr);
0bffad47 1757 if (rc < 0)
2bd739c9
KZ
1758 return BLKID_PROBE_ERROR;
1759
1760 return count == 0 ? BLKID_PROBE_NONE : BLKID_PROBE_OK;
a2f01a1c
KZ
1761}
1762
ce011388 1763/* same sa blkid_probe_get_buffer() but works with 512-sectors */
7eba8f98 1764const unsigned char *blkid_probe_get_sector(blkid_probe pr, unsigned int sector)
ce011388 1765{
7f787ced 1766 return blkid_probe_get_buffer(pr, ((uint64_t) sector) << 9, 0x200);
ce011388
KZ
1767}
1768
7f787ced 1769struct blkid_prval *blkid_probe_assign_value(blkid_probe pr, const char *name)
a0948ffe 1770{
51410fc6 1771 struct blkid_prval *v;
6c4a7811 1772
08029093 1773 v = calloc(1, sizeof(struct blkid_prval));
6c4a7811 1774 if (!v)
51410fc6 1775 return NULL;
a0948ffe 1776
08029093 1777 INIT_LIST_HEAD(&v->prvals);
51410fc6 1778 v->name = name;
9bdf6885 1779 v->chain = pr->cur_chain;
af17d349 1780 list_add_tail(&v->prvals, &pr->values);
6644688a 1781
c62a6311 1782 DBG(LOWPROBE, ul_debug("assigning %s [%s]", name, v->chain->driver->name));
51410fc6 1783 return v;
a0948ffe
KZ
1784}
1785
6c4a7811 1786/* Note that value data is always terminated by zero to keep things robust,
3fd1f771
RM
1787 * this extra zero is not count to the value length. It's caller responsibility
1788 * to set proper value length (for strings we count terminator to the length,
6c4a7811
OO
1789 * for binary data it's without terminator).
1790 */
1791int blkid_probe_value_set_data(struct blkid_prval *v,
47afae0c 1792 const unsigned char *data, size_t len)
6c4a7811
OO
1793{
1794 v->data = calloc(1, len + 1); /* always terminate by \0 */
cdd5bada 1795
6c4a7811
OO
1796 if (!v->data)
1797 return -ENOMEM;
1798 memcpy(v->data, data, len);
1799 v->len = len;
cdd5bada 1800 return 0;
cdd5bada
KZ
1801}
1802
51410fc6 1803int blkid_probe_set_value(blkid_probe pr, const char *name,
47afae0c 1804 const unsigned char *data, size_t len)
a0948ffe 1805{
51410fc6 1806 struct blkid_prval *v;
a0948ffe 1807
51410fc6
KZ
1808 v = blkid_probe_assign_value(pr, name);
1809 if (!v)
1810 return -1;
a0948ffe 1811
6c4a7811 1812 return blkid_probe_value_set_data(v, data, len);
a0948ffe
KZ
1813}
1814
51410fc6
KZ
1815int blkid_probe_vsprintf_value(blkid_probe pr, const char *name,
1816 const char *fmt, va_list ap)
a0948ffe 1817{
51410fc6 1818 struct blkid_prval *v;
a23facd6 1819 ssize_t len;
a0948ffe 1820
51410fc6
KZ
1821 v = blkid_probe_assign_value(pr, name);
1822 if (!v)
6c4a7811 1823 return -ENOMEM;
a0948ffe 1824
6c4a7811 1825 len = vasprintf((char **) &v->data, fmt, ap);
a0948ffe 1826
6c4a7811 1827 if (len <= 0) {
af17d349 1828 blkid_probe_free_value(v);
6c4a7811 1829 return len == 0 ? -EINVAL : -ENOMEM;
a0948ffe 1830 }
51410fc6 1831 v->len = len + 1;
a0948ffe
KZ
1832 return 0;
1833}
1834
cc33d693
KZ
1835int blkid_probe_sprintf_value(blkid_probe pr, const char *name,
1836 const char *fmt, ...)
1837{
1838 int rc;
1839 va_list ap;
1840
1841 va_start(ap, fmt);
1842 rc = blkid_probe_vsprintf_value(pr, name, fmt, ap);
1843 va_end(ap);
1844
1845 return rc;
1846}
1847
f12cd8d1 1848int blkid_probe_set_magic(blkid_probe pr, uint64_t offset,
47afae0c 1849 size_t len, const unsigned char *magic)
3c83b3b2
KZ
1850{
1851 int rc = 0;
1852 struct blkid_chain *chn = blkid_probe_get_chain(pr);
1853
7f787ced 1854 if (!chn || !len || chn->binary)
3c83b3b2
KZ
1855 return 0;
1856
1857 switch (chn->driver->id) {
1858 case BLKID_CHAIN_SUBLKS:
1859 if (!(chn->flags & BLKID_SUBLKS_MAGIC))
1860 return 0;
1861 rc = blkid_probe_set_value(pr, "SBMAGIC", magic, len);
1862 if (!rc)
1863 rc = blkid_probe_sprintf_value(pr,
44064b3c 1864 "SBMAGIC_OFFSET", "%llu", (unsigned long long)offset);
3c83b3b2
KZ
1865 break;
1866 case BLKID_CHAIN_PARTS:
1867 if (!(chn->flags & BLKID_PARTS_MAGIC))
1868 return 0;
1869 rc = blkid_probe_set_value(pr, "PTMAGIC", magic, len);
1870 if (!rc)
1871 rc = blkid_probe_sprintf_value(pr,
44064b3c 1872 "PTMAGIC_OFFSET", "%llu", (unsigned long long)offset);
3c83b3b2
KZ
1873 break;
1874 default:
1875 break;
1876 }
1877
1878 return rc;
1879}
1880
8c408470
TW
1881static void blkid_probe_log_csum_mismatch(blkid_probe pr, size_t n, const void *csum,
1882 const void *expected)
c89a1def 1883{
8c408470
TW
1884 char csum_hex[256];
1885 char expected_hex[sizeof(csum_hex)];
1886 int hex_size = min(sizeof(csum_hex), n * 2);
1887
1888 for (int i = 0; i < hex_size; i+=2) {
1889 sprintf(&csum_hex[i], "%02X", ((const unsigned char *) csum)[i / 2]);
1890 sprintf(&expected_hex[i], "%02X", ((const unsigned char *) expected)[i / 2]);
1891 }
1892
1893 ul_debug(
1894 "incorrect checksum for type %s,"
1895 " got %*s, expected %*s",
1896 blkid_probe_get_probername(pr),
1897 hex_size, csum_hex, hex_size, expected_hex);
1898}
1899
1900
1901int blkid_probe_verify_csum_buf(blkid_probe pr, size_t n, const void *csum,
1902 const void *expected)
1903{
1904 if (memcmp(csum, expected, n) != 0) {
02f3c12a
GP
1905 struct blkid_chain *chn = blkid_probe_get_chain(pr);
1906
8c408470
TW
1907 ON_DBG(LOWPROBE, blkid_probe_log_csum_mismatch(pr, n, csum, expected));
1908
d88803a4
KZ
1909 /*
1910 * Accept bad checksum if BLKID_SUBLKS_BADCSUM flags is set
1911 */
ffbec06d 1912 if (chn && chn->driver->id == BLKID_CHAIN_SUBLKS
d88803a4
KZ
1913 && (chn->flags & BLKID_SUBLKS_BADCSUM)) {
1914 blkid_probe_set_value(pr, "SBBADCSUM", (unsigned char *) "1", 2);
1915 goto accept;
1916 }
1917 return 0; /* bad checksum */
c89a1def
KZ
1918 }
1919
d88803a4
KZ
1920accept:
1921 return 1;
c89a1def
KZ
1922}
1923
8c408470
TW
1924int blkid_probe_verify_csum(blkid_probe pr, uint64_t csum, uint64_t expected)
1925{
1926 return blkid_probe_verify_csum_buf(pr, sizeof(csum), &csum, &expected);
1927}
1928
b3ee97a3
KZ
1929/**
1930 * blkid_probe_get_devno:
1931 * @pr: probe
1932 *
3b159691 1933 * Returns: block device number, or 0 for regular files.
b3ee97a3
KZ
1934 */
1935dev_t blkid_probe_get_devno(blkid_probe pr)
1936{
b3ee97a3
KZ
1937 return pr->devno;
1938}
1939
601fb1c1
KZ
1940/**
1941 * blkid_probe_get_wholedisk_devno:
1942 * @pr: probe
1943 *
3b159691 1944 * Returns: device number of the wholedisk, or 0 for regular files.
601fb1c1
KZ
1945 */
1946dev_t blkid_probe_get_wholedisk_devno(blkid_probe pr)
1947{
1948 if (!pr->disk_devno) {
1949 dev_t devno, disk_devno = 0;
1950
1951 devno = blkid_probe_get_devno(pr);
1952 if (!devno)
1953 return 0;
1954
2bf68c93 1955 if (blkid_devno_to_wholedisk(devno, NULL, 0, &disk_devno) == 0)
601fb1c1
KZ
1956 pr->disk_devno = disk_devno;
1957 }
1958 return pr->disk_devno;
1959}
1960
1961/**
1962 * blkid_probe_is_wholedisk:
1963 * @pr: probe
1964 *
1965 * Returns: 1 if the device is whole-disk or 0.
1966 */
1967int blkid_probe_is_wholedisk(blkid_probe pr)
1968{
1969 dev_t devno, disk_devno;
1970
1971 devno = blkid_probe_get_devno(pr);
1972 if (!devno)
1973 return 0;
1974
1975 disk_devno = blkid_probe_get_wholedisk_devno(pr);
1976 if (!disk_devno)
1977 return 0;
1978
1979 return devno == disk_devno;
1980}
1981
fd9f45e1
KZ
1982blkid_probe blkid_probe_get_wholedisk_probe(blkid_probe pr)
1983{
1984 dev_t disk;
1985
1986 if (blkid_probe_is_wholedisk(pr))
1987 return NULL; /* this is not partition */
1988
1989 if (pr->parent)
1990 /* this is cloned blkid_probe, use parent's stuff */
1991 return blkid_probe_get_wholedisk_probe(pr->parent);
1992
1993 disk = blkid_probe_get_wholedisk_devno(pr);
1994
1995 if (pr->disk_probe && pr->disk_probe->devno != disk) {
1996 /* we have disk prober, but for another disk... close it */
1997 blkid_free_probe(pr->disk_probe);
1998 pr->disk_probe = NULL;
1999 }
2000
2001 if (!pr->disk_probe) {
2002 /* Open a new disk prober */
2003 char *disk_path = blkid_devno_to_devname(disk);
22769acf 2004 int flags;
fd9f45e1
KZ
2005
2006 if (!disk_path)
2007 return NULL;
2008
c62a6311 2009 DBG(LOWPROBE, ul_debug("allocate a wholedisk probe"));
fd9f45e1
KZ
2010
2011 pr->disk_probe = blkid_new_probe_from_filename(disk_path);
7eac65fc
KZ
2012
2013 free(disk_path);
2014
fd9f45e1
KZ
2015 if (!pr->disk_probe)
2016 return NULL; /* ENOMEM? */
22769acf
KZ
2017
2018 flags = blkid_probe_get_partitions_flags(pr);
2019 if (flags & BLKID_PARTS_FORCE_GPT)
2020 blkid_probe_set_partitions_flags(pr->disk_probe,
2021 BLKID_PARTS_FORCE_GPT);
fd9f45e1
KZ
2022 }
2023
2024 return pr->disk_probe;
2025}
2026
b3ee97a3
KZ
2027/**
2028 * blkid_probe_get_size:
2029 * @pr: probe
2030 *
30696241
KZ
2031 * This function returns size of probing area as defined by blkid_probe_set_device().
2032 * If the size of the probing area is unrestricted then this function returns
2033 * the real size of device. See also blkid_get_dev_size().
2034 *
2035 * Returns: size in bytes or -1 in case of error.
b3ee97a3
KZ
2036 */
2037blkid_loff_t blkid_probe_get_size(blkid_probe pr)
2038{
7f787ced 2039 return (blkid_loff_t) pr->size;
b3ee97a3
KZ
2040}
2041
56e961e2
KZ
2042/**
2043 * blkid_probe_get_offset:
2044 * @pr: probe
2045 *
2046 * This function returns offset of probing area as defined by blkid_probe_set_device().
2047 *
2048 * Returns: offset in bytes or -1 in case of error.
2049 */
2050blkid_loff_t blkid_probe_get_offset(blkid_probe pr)
2051{
7f787ced 2052 return (blkid_loff_t) pr->off;
56e961e2
KZ
2053}
2054
2055/**
2056 * blkid_probe_get_fd:
2057 * @pr: probe
2058 *
e3436956 2059 * Returns: file descriptor for assigned device/file or -1 in case of error.
56e961e2
KZ
2060 */
2061int blkid_probe_get_fd(blkid_probe pr)
2062{
7f787ced 2063 return pr->fd;
56e961e2
KZ
2064}
2065
b3ee97a3
KZ
2066/**
2067 * blkid_probe_get_sectorsize:
90ec8d9c 2068 * @pr: probe or NULL (for NULL returns 512)
b3ee97a3 2069 *
2a1dfbad 2070 * Returns: block device logical sector size (BLKSSZGET ioctl, default 512).
b3ee97a3
KZ
2071 */
2072unsigned int blkid_probe_get_sectorsize(blkid_probe pr)
2073{
b3ee97a3
KZ
2074 if (pr->blkssz)
2075 return pr->blkssz;
b3ee97a3 2076
90ec8d9c
KZ
2077 if (S_ISBLK(pr->mode) &&
2078 blkdev_get_sector_size(pr->fd, (int *) &pr->blkssz) == 0)
2079 return pr->blkssz;
b3ee97a3 2080
b3ee97a3
KZ
2081 pr->blkssz = DEFAULT_SECTOR_SIZE;
2082 return pr->blkssz;
2083}
2084
76fab513
KZ
2085/**
2086 * blkid_probe_set_sectorsize:
2087 * @pr: probe
2088 * @sz: new size (to overwrite system default)
2089 *
2090 * Note that blkid_probe_set_device() resets this setting. Use it after
2091 * blkid_probe_set_device() and before any probing call.
2092 *
ae4e2abc
KZ
2093 * Since: 2.30
2094 *
76fab513
KZ
2095 * Returns: 0 or <0 in case of error
2096 */
2097int blkid_probe_set_sectorsize(blkid_probe pr, unsigned int sz)
2098{
2099 pr->blkssz = sz;
2100 return 0;
2101}
2102
e8ae4947
DB
2103/**
2104 * blkid_probe_get_sectors:
2105 * @pr: probe
2106 *
2107 * Returns: 512-byte sector count or -1 in case of error.
2108 */
2109blkid_loff_t blkid_probe_get_sectors(blkid_probe pr)
2110{
7f787ced 2111 return (blkid_loff_t) (pr->size >> 9);
e8ae4947
DB
2112}
2113
4d72b337
KZ
2114/**
2115 * blkid_probe_numof_values:
2116 * @pr: probe
2117 *
2118 * Returns: number of values in probing result or -1 in case of error.
2119 */
2120int blkid_probe_numof_values(blkid_probe pr)
2121{
6c4a7811
OO
2122 int i = 0;
2123 struct list_head *p;
6c4a7811 2124
af17d349 2125 list_for_each(p, &pr->values)
6c4a7811
OO
2126 ++i;
2127 return i;
4d72b337
KZ
2128}
2129
81f73792
KZ
2130/**
2131 * blkid_probe_get_value:
2132 * @pr: probe
2133 * @num: wanted value in range 0..N, where N is blkid_probe_numof_values() - 1
2134 * @name: pointer to return value name or NULL
2135 * @data: pointer to return value data or NULL
2136 * @len: pointer to return value length or NULL
2137 *
c2dbd49b
KZ
2138 * Note, the @len returns length of the @data, including the terminating
2139 * '\0' character.
2140 *
81f73792
KZ
2141 * Returns: 0 on success, or -1 in case of error.
2142 */
51410fc6 2143int blkid_probe_get_value(blkid_probe pr, int num, const char **name,
6d042d0d 2144 const char **data, size_t *len)
a0948ffe 2145{
81f73792 2146 struct blkid_prval *v = __blkid_probe_get_value(pr, num);
a0948ffe 2147
81f73792 2148 if (!v)
51410fc6 2149 return -1;
51410fc6
KZ
2150 if (name)
2151 *name = v->name;
2152 if (data)
6d042d0d 2153 *data = (char *) v->data;
51410fc6
KZ
2154 if (len)
2155 *len = v->len;
6644688a 2156
c62a6311 2157 DBG(LOWPROBE, ul_debug("returning %s value", v->name));
a0948ffe
KZ
2158 return 0;
2159}
a0948ffe 2160
81f73792
KZ
2161/**
2162 * blkid_probe_lookup_value:
2163 * @pr: probe
2164 * @name: name of value
2165 * @data: pointer to return value data or NULL
2166 * @len: pointer to return value length or NULL
2167 *
c2dbd49b
KZ
2168 * Note, the @len returns length of the @data, including the terminating
2169 * '\0' character.
2170 *
81f73792
KZ
2171 * Returns: 0 on success, or -1 in case of error.
2172 */
51410fc6 2173int blkid_probe_lookup_value(blkid_probe pr, const char *name,
6d042d0d 2174 const char **data, size_t *len)
a0948ffe 2175{
81f73792 2176 struct blkid_prval *v = __blkid_probe_lookup_value(pr, name);
a0948ffe 2177
81f73792 2178 if (!v)
51410fc6 2179 return -1;
81f73792
KZ
2180 if (data)
2181 *data = (char *) v->data;
2182 if (len)
2183 *len = v->len;
81f73792 2184 return 0;
a0948ffe
KZ
2185}
2186
81f73792
KZ
2187/**
2188 * blkid_probe_has_value:
2189 * @pr: probe
2190 * @name: name of value
2191 *
2192 * Returns: 1 if value exist in probing result, otherwise 0.
2193 */
51410fc6 2194int blkid_probe_has_value(blkid_probe pr, const char *name)
a0948ffe 2195{
51410fc6
KZ
2196 if (blkid_probe_lookup_value(pr, name, NULL, NULL) == 0)
2197 return 1;
a0948ffe
KZ
2198 return 0;
2199}
2200
1c1726a7
KZ
2201struct blkid_prval *__blkid_probe_get_value(blkid_probe pr, int num)
2202{
6c4a7811
OO
2203 int i = 0;
2204 struct list_head *p;
2205
7f787ced 2206 if (num < 0)
1c1726a7
KZ
2207 return NULL;
2208
af17d349 2209 list_for_each(p, &pr->values) {
6c4a7811
OO
2210 if (i++ != num)
2211 continue;
2212 return list_entry(p, struct blkid_prval, prvals);
2213 }
2214 return NULL;
1c1726a7
KZ
2215}
2216
2217struct blkid_prval *__blkid_probe_lookup_value(blkid_probe pr, const char *name)
2218{
6c4a7811 2219 struct list_head *p;
1c1726a7 2220
7f787ced 2221 if (list_empty(&pr->values))
1c1726a7
KZ
2222 return NULL;
2223
af17d349 2224 list_for_each(p, &pr->values) {
6c4a7811
OO
2225 struct blkid_prval *v = list_entry(p, struct blkid_prval,
2226 prvals);
1c1726a7
KZ
2227
2228 if (v->name && strcmp(name, v->name) == 0) {
c62a6311 2229 DBG(LOWPROBE, ul_debug("returning %s value", v->name));
1c1726a7
KZ
2230 return v;
2231 }
2232 }
2233 return NULL;
2234}
2235
201529bd
KZ
2236
2237/* converts DCE UUID (uuid[16]) to human readable string
2238 * - the @len should be always 37 */
c9f51c71
KZ
2239void blkid_unparse_uuid(const unsigned char *uuid, char *str, size_t len)
2240{
201529bd
KZ
2241 snprintf(str, len,
2242 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
2243 uuid[0], uuid[1], uuid[2], uuid[3],
2244 uuid[4], uuid[5],
2245 uuid[6], uuid[7],
2246 uuid[8], uuid[9],
2247 uuid[10], uuid[11], uuid[12], uuid[13], uuid[14],uuid[15]);
201529bd
KZ
2248}
2249
9c06cdbf
KZ
2250/* like uuid_is_null() from libuuid, but works with arbitrary size of UUID */
2251int blkid_uuid_is_empty(const unsigned char *buf, size_t len)
2252{
2253 size_t i;
2254
2255 for (i = 0; i < len; i++)
2256 if (buf[i])
2257 return 0;
2258 return 1;
2259}
c2dbd49b
KZ
2260
2261/* Removes whitespace from the right-hand side of a string (trailing
2262 * whitespace).
2263 *
2264 * Returns size of the new string (without \0).
2265 */
2266size_t blkid_rtrim_whitespace(unsigned char *str)
2267{
22e9e9c8 2268 return rtrim_whitespace(str);
c2dbd49b
KZ
2269}
2270
fafe46bc
ZAK
2271/* Removes whitespace from the left-hand side of a string.
2272 *
2273 * Returns size of the new string (without \0).
2274 */
2275size_t blkid_ltrim_whitespace(unsigned char *str)
2276{
22e9e9c8 2277 return ltrim_whitespace(str);
fafe46bc 2278}
22e9e9c8 2279
8b7eae45
KZ
2280/*
2281 * Some mkfs-like utils wipe some parts (usually begin) of the device.
2282 * For example LVM (pvcreate) or mkswap(8). This information could be used
2283 * for later resolution to conflicts between superblocks.
2284 *
2285 * For example we found valid LVM superblock, LVM wipes 8KiB at the begin of
89d39d22
KZ
2286 * the device. If we found another signature (for example MBR) within the
2287 * wiped area then the signature has been added later and LVM superblock
2288 * should be ignore.
8b7eae45 2289 *
29e204d1
KZ
2290 * Note that this heuristic is not 100% reliable, for example "pvcreate --zero n"
2291 * can be used to keep the begin of the device unmodified. It's probably better
8b7eae45
KZ
2292 * to use this heuristic for conflicts between superblocks and partition tables
2293 * than for conflicts between filesystem superblocks -- existence of unwanted
2294 * partition table is very unusual, because PT is pretty visible (parsed and
2295 * interpreted by kernel).
89d39d22
KZ
2296 *
2297 * Note that we usually expect only one signature on the device, it means that
2298 * we have to remember only one wiped area from previously successfully
2299 * detected signature.
2300 *
2301 * blkid_probe_set_wiper() -- defines wiped area (e.g. LVM)
2302 * blkid_probe_use_wiper() -- try to use area (e.g. MBR)
2303 *
2304 * Note that there is not relation between _wiper and blkid_to_wipe().
2305 *
8b7eae45 2306 */
f12cd8d1 2307void blkid_probe_set_wiper(blkid_probe pr, uint64_t off, uint64_t size)
8b7eae45
KZ
2308{
2309 struct blkid_chain *chn;
2310
8b7eae45 2311 if (!size) {
c62a6311 2312 DBG(LOWPROBE, ul_debug("zeroize wiper"));
8b7eae45
KZ
2313 pr->wipe_size = pr->wipe_off = 0;
2314 pr->wipe_chain = NULL;
2315 return;
2316 }
2317
2318 chn = pr->cur_chain;
2319
2320 if (!chn || !chn->driver ||
c9f51c71 2321 chn->idx < 0 || (size_t) chn->idx >= chn->driver->nidinfos)
8b7eae45
KZ
2322 return;
2323
2324 pr->wipe_size = size;
2325 pr->wipe_off = off;
2326 pr->wipe_chain = chn;
2327
0540ea54 2328 DBG(LOWPROBE,
fdbd7bb9 2329 ul_debug("wiper set to %s::%s off=%"PRIu64" size=%"PRIu64"",
8b7eae45
KZ
2330 chn->driver->name,
2331 chn->driver->idinfos[chn->idx]->name,
2332 pr->wipe_off, pr->wipe_size));
8b7eae45
KZ
2333}
2334
2335/*
2336 * Returns 1 if the <@off,@size> area was wiped
2337 */
f12cd8d1 2338int blkid_probe_is_wiped(blkid_probe pr, struct blkid_chain **chn, uint64_t off, uint64_t size)
8b7eae45 2339{
7f787ced 2340 if (!size)
8b7eae45
KZ
2341 return 0;
2342
2343 if (pr->wipe_off <= off && off + size <= pr->wipe_off + pr->wipe_size) {
7f787ced 2344 *chn = pr->wipe_chain;
8b7eae45
KZ
2345 return 1;
2346 }
2347 return 0;
2348}
2349
89d39d22
KZ
2350/*
2351 * Try to use any area -- if the area has been previously wiped then the
9e930041 2352 * previous probing result should be ignored (reset).
89d39d22 2353 */
f12cd8d1 2354void blkid_probe_use_wiper(blkid_probe pr, uint64_t off, uint64_t size)
8b7eae45
KZ
2355{
2356 struct blkid_chain *chn = NULL;
2357
2358 if (blkid_probe_is_wiped(pr, &chn, off, size) && chn) {
c62a6311 2359 DBG(LOWPROBE, ul_debug("previously wiped area modified "
0540ea54 2360 " -- ignore previous results"));
8b7eae45 2361 blkid_probe_set_wiper(pr, 0, 0);
af17d349 2362 blkid_probe_chain_reset_values(pr, chn);
8b7eae45
KZ
2363 }
2364}
67719fbb 2365
b7bca244
KZ
2366static struct blkid_hint *get_hint(blkid_probe pr, const char *name)
2367{
2368 struct list_head *p;
2369
2370 if (list_empty(&pr->hints))
2371 return NULL;
2372
2373 list_for_each(p, &pr->hints) {
2374 struct blkid_hint *h = list_entry(p, struct blkid_hint, hints);
2375
2376 if (h->name && strcmp(name, h->name) == 0)
2377 return h;
2378 }
2379 return NULL;
2380}
2381
67719fbb 2382/**
248c239b 2383 * blkid_probe_set_hint:
67719fbb
KZ
2384 * @pr: probe
2385 * @name: hint name or NAME=value
2386 * @value: offset or another number
2387 *
2388 * Sets extra hint for low-level prober. If the hint is set by NAME=value
2389 * notation than @value is ignored. The functions blkid_probe_set_device()
2390 * and blkid_reset_probe() resets all hints.
2391 *
2392 * The hints are optional way how to force libblkid probing functions to check
2393 * for example another location.
2394 *
2395 * Returns: 0 on success, or -1 in case of error.
2396 */
2397int blkid_probe_set_hint(blkid_probe pr, const char *name, uint64_t value)
2398{
2399 struct blkid_hint *hint = NULL;
2400 char *n = NULL, *v = NULL;
2401
2402 if (strchr(name, '=')) {
2403 char *end = NULL;
2404
2405 if (blkid_parse_tag_string(name, &n, &v) != 0)
2406 goto done;
2407
2408 errno = 0;
2409 value = strtoumax(v, &end, 10);
2410
2411 if (errno || v == end || (end && *end))
2412 goto done;
b7bca244
KZ
2413 }
2414
2415 hint = get_hint(pr, n ? n : name);
2416 if (hint) {
2417 /* alter old hint */
2418 hint->value = value;
2419 DBG(LOWPROBE,
2420 ul_debug("updated hint '%s' to %"PRIu64"", hint->name, hint->value));
67719fbb 2421 } else {
b7bca244
KZ
2422 /* add a new hint */
2423 if (!n) {
2424 n = strdup(name);
2425 if (!n)
2426 goto done;
2427 }
2428 hint = malloc(sizeof(*hint));
2429 if (!hint)
67719fbb 2430 goto done;
67719fbb 2431
b7bca244
KZ
2432 hint->name = n;
2433 hint->value = value;
67719fbb 2434
b7bca244
KZ
2435 INIT_LIST_HEAD(&hint->hints);
2436 list_add_tail(&hint->hints, &pr->hints);
67719fbb 2437
b7bca244
KZ
2438 DBG(LOWPROBE,
2439 ul_debug("new hint '%s' is %"PRIu64"", hint->name, hint->value));
2440 n = NULL;
2441 }
67719fbb
KZ
2442done:
2443 free(n);
2444 free(v);
b7bca244 2445
67719fbb
KZ
2446 if (!hint)
2447 return errno ? -errno : -EINVAL;
2448 return 0;
2449}
2450
2451int blkid_probe_get_hint(blkid_probe pr, const char *name, uint64_t *value)
2452{
b7bca244 2453 struct blkid_hint *h = get_hint(pr, name);
67719fbb 2454
b7bca244 2455 if (!h)
67719fbb 2456 return -EINVAL;
b7bca244
KZ
2457 if (value)
2458 *value = h->value;
2459 return 0;
67719fbb
KZ
2460}
2461
248c239b
KZ
2462/**
2463 * blkid_probe_reset_hints:
95fbd2db 2464 * @pr: probe
248c239b
KZ
2465 *
2466 * Removes all previously defined probinig hints. See also blkid_probe_set_hint().
2467 */
2468void blkid_probe_reset_hints(blkid_probe pr)
67719fbb
KZ
2469{
2470 if (list_empty(&pr->hints))
2471 return;
2472
2473 DBG(LOWPROBE, ul_debug("resetting hints"));
2474
2475 while (!list_empty(&pr->hints)) {
2476 struct blkid_hint *h = list_entry(pr->hints.next,
2477 struct blkid_hint, hints);
2478 list_del(&h->hints);
2479 free(h->name);
2480 free(h);
2481 }
2482
2483 INIT_LIST_HEAD(&pr->hints);
2484}