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