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