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