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