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