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