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