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