]> git.ipfire.org Git - thirdparty/util-linux.git/blame - shlibs/blkid/src/probe.c
libblkid: allow to read in sectors
[thirdparty/util-linux.git] / shlibs / blkid / 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,
19 * the librray provides superblocks, partitions and topology chains.
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).
23 * These filters are per-chain. For more details see the chain specific
24 * documenation.
25 *
26 * The low-level API provides two ways how access to probing results.
27 *
28 * 1. The NAME=value (tag) interface. This interface is older and returns all data
29 * as strings. This interface is generic for all chains.
30 *
31 * 2. The binary interfaces. These interfaces return data in the native formats.
32 * The interface is always specific to the probing chain.
33 */
34
35/**
36 * SECTION: lowprobe-tags
37 * @title: Low-level tags
38 * @short_description: generic NAME=value interface.
39 *
40 * The probing routines inside the chain are mutually exclusive by default --
41 * only few probing routines are marked as "tolerant". The "tolerant" probing
42 * routines are used for filesystem which can share the same device with any
43 * other filesystem. The blkid_do_safeprobe() checks for the "tolerant" flag.
44 *
45 * The SUPERBLOCKS chain is enabled by default. The all others chains is
46 * necessary to enable by blkid_probe_enable_'CHAINNAME'(). See chains specific
47 * documenation.
48 *
49 * The blkid_do_probe() function returns a result from only one probing
50 * routine, and the next call from the next probing routine. It means you need
51 * to call the function in loop, for example:
52 *
53 * <informalexample>
54 * <programlisting>
55 * while((blkid_do_probe(pr) == 0)
56 * ... use result ...
57 * </programlisting>
58 * </informalexample>
59 *
60 * The blkid_do_safeprobe() is the same as blkid_do_probe(), but returns only
61 * first probing result for every enabled chain. This function checks for
62 * ambivalent results (e.g. more "intolerant" filesystems superblocks on the
63 * device).
64 *
65 * The probing result is set of NAME=value pairs (the NAME is always unique).
66 */
67
a0948ffe
KZ
68#include <stdio.h>
69#include <string.h>
70#include <stdlib.h>
71#include <unistd.h>
72#include <fcntl.h>
73#include <ctype.h>
74#include <sys/types.h>
75#ifdef HAVE_SYS_STAT_H
76#include <sys/stat.h>
77#endif
78#ifdef HAVE_SYS_MKDEV_H
79#include <sys/mkdev.h>
80#endif
a0948ffe
KZ
81#ifdef HAVE_ERRNO_H
82#include <errno.h>
83#endif
51410fc6 84#include <stdint.h>
8c0dc071
KZ
85#include <stdarg.h>
86
51410fc6 87#ifdef HAVE_LIBUUID
8c0dc071
KZ
88# ifdef HAVE_UUID_UUID_H
89# include <uuid/uuid.h>
e5127179
KZ
90# else
91# include <uuid.h>
8c0dc071 92# endif
51410fc6 93#endif
a0948ffe 94
dc61d909 95#include "blkdev.h"
51410fc6 96#include "blkidP.h"
219227c2 97
52448df8
KZ
98/* chains */
99extern const struct blkid_chaindrv superblocks_drv;
100
101/*
102 * All supported chains
103 */
104static const struct blkid_chaindrv *chains_drvs[] = {
105 [BLKID_CHAIN_SUBLKS] = &superblocks_drv,
106};
107
108static void blkid_probe_reset_vals(blkid_probe pr);
109
52448df8
KZ
110/**
111 * blkid_new_probe:
112 *
113 * Returns: a pointer to the newly allocated probe struct.
a0948ffe 114 */
51410fc6 115blkid_probe blkid_new_probe(void)
a0948ffe 116{
52448df8
KZ
117 int i;
118 blkid_probe pr;
119
7a458332 120 blkid_init_debug(0);
52448df8
KZ
121 pr = calloc(1, sizeof(struct blkid_struct_probe));
122 if (!pr)
123 return NULL;
124
125 /* initialize chains */
126 for (i = 0; i < BLKID_NCHAINS; i++) {
127 pr->chains[i].driver = chains_drvs[i];
128 pr->chains[i].flags = chains_drvs[i]->dflt_flags;
129 pr->chains[i].enabled = chains_drvs[i]->dflt_enabled;
130 }
131 return pr;
a0948ffe
KZ
132}
133
52448df8
KZ
134/**
135 * blkid_free_probe:
136 * @pr: probe
137 *
138 * Deallocates the probe struct, buffers and all allocated
51410fc6 139 * data that are associated with this probing control struct.
a0948ffe 140 */
51410fc6 141void blkid_free_probe(blkid_probe pr)
a0948ffe 142{
52448df8
KZ
143 int i;
144
51410fc6
KZ
145 if (!pr)
146 return;
52448df8
KZ
147
148 for (i = 0; i < BLKID_NCHAINS; i++) {
149 struct blkid_chain *ch = &pr->chains[i];
150
151 if (ch->driver->free_data)
152 ch->driver->free_data(pr, ch->data);
153 free(ch->fltr);
154 }
51410fc6
KZ
155 free(pr->buf);
156 free(pr->sbbuf);
157 free(pr);
a0948ffe
KZ
158}
159
52448df8
KZ
160static void blkid_probe_reset_buffer(blkid_probe pr)
161{
162 DBG(DEBUG_LOWPROBE, printf("reseting blkid probe buffer\n"));
163 if (pr->buf)
164 memset(pr->buf, 0, pr->buf_max);
165 pr->buf_off = 0;
166 pr->buf_len = 0;
167 if (pr->sbbuf)
168 memset(pr->sbbuf, 0, BLKID_SB_BUFSIZ);
169 pr->sbbuf_len = 0;
170}
171
172
9bdf6885
KZ
173/*
174 * Removes chain values from probing result.
175 */
176void blkid_probe_chain_reset_vals(blkid_probe pr, struct blkid_chain *chn)
177{
178 int nvals = pr->nvals;
179 int i, x;
180
181 for (x = 0, i = 0; i < pr->nvals; i++) {
182 struct blkid_prval *v = &pr->vals[i];
183
184 if (v->chain != chn && x == i) {
185 x++;
186 continue;
187 }
188 if (v->chain == chn) {
189 --nvals;
190 continue;
191 }
192 memcpy(&pr->vals[x++], v, sizeof(struct blkid_prval));
193 }
194 pr->nvals = nvals;
195}
196
197/*
198 * Copies chain values from probing result to @vals, the max size of @vals is
199 * @nvals and returns real number of values.
200 */
201int blkid_probe_chain_copy_vals(blkid_probe pr, struct blkid_chain *chn,
202 struct blkid_prval *vals, int nvals)
203{
204 int i, x;
205
206 for (x = 0, i = 0; i < pr->nvals && x < nvals; i++) {
207 struct blkid_prval *v = &pr->vals[i];
208
209 if (v->chain != chn)
210 continue;
211 memcpy(&vals[x++], v, sizeof(struct blkid_prval));
212 }
213 return x;
214}
215
216/*
217 * Appends values from @vals to the probing result
218 */
219void blkid_probe_append_vals(blkid_probe pr, struct blkid_prval *vals, int nvals)
220{
221 int i = 0;
222
223 while (i < nvals && pr->nvals < BLKID_NVALS) {
224 memcpy(&pr->vals[pr->nvals++], &vals[i++],
225 sizeof(struct blkid_prval));
226 }
227}
228
51410fc6 229static void blkid_probe_reset_vals(blkid_probe pr)
a0948ffe 230{
51410fc6
KZ
231 memset(pr->vals, 0, sizeof(pr->vals));
232 pr->nvals = 0;
a0948ffe
KZ
233}
234
1c1726a7
KZ
235struct blkid_chain *blkid_probe_get_chain(blkid_probe pr)
236{
237 return pr->cur_chain;
238}
239
52448df8
KZ
240/**
241 * blkid_reset_probe:
242 * @pr: probe
243 *
244 * Cleanup probing result. This function does not touch probing filters
245 * and keeps assigned device.
246 */
51410fc6 247void blkid_reset_probe(blkid_probe pr)
a0948ffe 248{
52448df8
KZ
249 int i;
250
51410fc6
KZ
251 if (!pr)
252 return;
52448df8
KZ
253
254 blkid_probe_reset_buffer(pr);
51410fc6 255 blkid_probe_reset_vals(pr);
52448df8
KZ
256
257 for (i = 0; i < BLKID_NCHAINS; i++)
258 pr->chains[i].idx = -1;
a0948ffe
KZ
259}
260
46a734fd
KZ
261/***
262static int blkid_probe_dump_filter(blkid_probe pr, int chain)
263{
264 struct blkid_chain *chn;
265 int i;
266
267 if (!pr || chain < 0 || chain >= BLKID_NCHAINS)
268 return -1;
269
270 chn = &pr->chains[chain];
271
272 if (!chn->fltr)
273 return -1;
274
275 for (i = 0; i < chn->driver->nidinfos; i++) {
276 const struct blkid_idinfo *id = chn->driver->idinfos[i];
277
278 DBG(DEBUG_LOWPROBE, printf("%d: %s: %s\n",
279 i,
280 id->name,
281 blkid_bmp_get_item(chn->fltr, i)
282 ? "disabled" : "enabled <--"));
46a734fd
KZ
283 }
284 return 0;
285}
286***/
287
288/*
289 * Returns properly initialized chain filter
290 */
291unsigned long *blkid_probe_get_filter(blkid_probe pr, int chain, int create)
292{
293 struct blkid_chain *chn;
294
295 if (!pr || chain < 0 || chain >= BLKID_NCHAINS)
296 return NULL;
297
298 chn = &pr->chains[chain];
299
300 /* always when you touch the chain filter all indexes are reseted and
301 * probing starts from scratch
302 */
303 chn->idx = -1;
304 pr->cur_chain = NULL;
305
306 if (!chn->driver->has_fltr || (!chn->fltr && !create))
307 return NULL;
308
309 if (!chn->fltr)
310 chn->fltr = calloc(1, blkid_bmp_nbytes(chn->driver->nidinfos));
311 else
312 memset(chn->fltr, 0, blkid_bmp_nbytes(chn->driver->nidinfos));
313
314 /* blkid_probe_dump_filter(pr, chain); */
315 return chn->fltr;
316}
317
318/*
319 * Generic private functions for filter setting
320 */
321int __blkid_probe_invert_filter(blkid_probe pr, int chain)
322{
323 int i;
324 struct blkid_chain *chn;
325 unsigned long *fltr;
326
327 fltr = blkid_probe_get_filter(pr, chain, FALSE);
328 if (!fltr)
329 return -1;
330
331 chn = &pr->chains[chain];
332
333 for (i = 0; i < blkid_bmp_nwords(chn->driver->nidinfos); i++)
334 fltr[i] = ~fltr[i];
335
336 DBG(DEBUG_LOWPROBE, printf("probing filter inverted\n"));
337 /* blkid_probe_dump_filter(pr, chain); */
338 return 0;
339}
340
341int __blkid_probe_reset_filter(blkid_probe pr, int chain)
342{
343 return blkid_probe_get_filter(pr, chain, FALSE) ? 0 : -1;
344}
345
346int __blkid_probe_filter_types(blkid_probe pr, int chain, int flag, char *names[])
347{
348 unsigned long *fltr;
349 struct blkid_chain *chn;
350 int i;
351
352 fltr = blkid_probe_get_filter(pr, chain, TRUE);
353 if (!fltr)
354 return -1;
355
356 chn = &pr->chains[chain];
357
358 for (i = 0; i < chn->driver->nidinfos; i++) {
359 int has = 0;
360 const struct blkid_idinfo *id = chn->driver->idinfos[i];
361 char **n;
362
363 for (n = names; *n; n++) {
364 if (!strcmp(id->name, *n)) {
365 has = 1;
366 break;
367 }
368 }
369 if (flag & BLKID_FLTR_ONLYIN) {
370 if (!has)
371 blkid_bmp_set_item(fltr, i);
372 } else if (flag & BLKID_FLTR_NOTIN) {
373 if (has)
374 blkid_bmp_set_item(fltr, i);
375 }
376 }
377
378 DBG(DEBUG_LOWPROBE,
379 printf("%s: a new probing type-filter initialized\n",
380 chn->driver->name));
381 /* blkid_probe_dump_filter(pr, chain); */
382 return 0;
383}
384
51410fc6
KZ
385/*
386 * Note that we have two offsets:
387 *
388 * 1/ general device offset (pr->off), that's useful for example when we
389 * probe a partition from whole disk image:
390 * blkid-low --offset <partition_position> disk.img
391 *
392 * 2/ buffer offset (the 'off' argument), that useful for offsets in
393 * superbloks, ...
394 *
395 * That means never use lseek(fd, 0, SEEK_SET), the zero position is always
396 * pr->off, so lseek(fd, pr->off, SEEK_SET).
397 *
398 */
399unsigned char *blkid_probe_get_buffer(blkid_probe pr,
400 blkid_loff_t off, blkid_loff_t len)
a0948ffe 401{
51410fc6 402 ssize_t ret_read = 0;
a0948ffe 403
4884729a
KZ
404 if (off < 0 || len < 0) {
405 DBG(DEBUG_LOWPROBE,
406 printf("unexpected offset or length of buffer requested\n"));
407 return NULL;
408 }
51410fc6
KZ
409 if (off + len <= BLKID_SB_BUFSIZ) {
410 if (!pr->sbbuf) {
411 pr->sbbuf = malloc(BLKID_SB_BUFSIZ);
412 if (!pr->sbbuf)
413 return NULL;
414 }
415 if (!pr->sbbuf_len) {
416 if (lseek(pr->fd, pr->off, SEEK_SET) < 0)
417 return NULL;
418 ret_read = read(pr->fd, pr->sbbuf, BLKID_SB_BUFSIZ);
419 if (ret_read < 0)
420 ret_read = 0;
421 pr->sbbuf_len = ret_read;
422 }
423 if (off + len > pr->sbbuf_len)
424 return NULL;
425 return pr->sbbuf + off;
426 } else {
427 unsigned char *newbuf = NULL;
428
429 if (len > pr->buf_max) {
430 newbuf = realloc(pr->buf, len);
431 if (!newbuf)
432 return NULL;
433 pr->buf = newbuf;
434 pr->buf_max = len;
435 pr->buf_off = 0;
436 pr->buf_len = 0;
437 }
438 if (newbuf || off < pr->buf_off ||
439 off + len > pr->buf_off + pr->buf_len) {
440
441 if (blkid_llseek(pr->fd, pr->off + off, SEEK_SET) < 0)
442 return NULL;
443
444 ret_read = read(pr->fd, pr->buf, len);
445 if (ret_read != (ssize_t) len)
446 return NULL;
447 pr->buf_off = off;
448 pr->buf_len = len;
449 }
450 return off ? pr->buf + (off - pr->buf_off) : pr->buf;
451 }
a0948ffe
KZ
452}
453
52448df8
KZ
454/**
455 * blkid_probe_set_device:
456 * @pr: probe
457 * @fd: device file descriptor
458 * @off: begin of probing area
459 * @size: size of probing area
460 *
461 * Assigns the device to probe control struct, resets internal buffers and
51410fc6
KZ
462 * reads 512 bytes from device to the buffers.
463 *
52448df8 464 * Returns: -1 in case of failure, or 0 on success.
51410fc6
KZ
465 */
466int blkid_probe_set_device(blkid_probe pr, int fd,
467 blkid_loff_t off, blkid_loff_t size)
a0948ffe 468{
51410fc6
KZ
469 if (!pr)
470 return -1;
a0948ffe 471
51410fc6 472 blkid_reset_probe(pr);
a0948ffe 473
51410fc6
KZ
474 pr->fd = fd;
475 pr->off = off;
bb6c6673 476 pr->size = 0;
52448df8
KZ
477 pr->devno = 0;
478 pr->mode = 0;
479 pr->blkssz = 0;
dc61d909 480
bb6c6673 481 if (size)
dc61d909 482 pr->size = size;
bb6c6673
KZ
483 else {
484 struct stat sb;
485
486 if (fstat(fd, &sb))
487 return -1;
488
52448df8
KZ
489 pr->mode = sb.st_mode;
490
491 if (S_ISBLK(sb.st_mode)) {
bb6c6673 492 blkdev_get_size(fd, (unsigned long long *) &pr->size);
52448df8
KZ
493 pr->devno = sb.st_rdev;
494 } else
bb6c6673
KZ
495 pr->size = sb.st_size;
496 }
497 if (!pr->size)
498 return -1;
a0948ffe 499
51410fc6 500 /* read SB to test if the device is readable */
6644688a
KZ
501 if (!blkid_probe_get_buffer(pr, 0, 0x200)) {
502 DBG(DEBUG_LOWPROBE,
503 printf("failed to prepare a device for low-probing\n"));
51410fc6 504 return -1;
6644688a 505 }
a0948ffe 506
bb6c6673
KZ
507 DBG(DEBUG_LOWPROBE, printf("ready for low-probing, offset=%zd, size=%zd\n",
508 pr->off, pr->size));
a0948ffe
KZ
509 return 0;
510}
511
f319b5ca
KZ
512int blkid_probe_get_dimension(blkid_probe pr,
513 blkid_loff_t *off, blkid_loff_t *size)
514{
515 if (!pr)
516 return -1;
517
518 *off = pr->off;
519 *size = pr->size;
520 return 0;
521}
522
523int blkid_probe_set_dimension(blkid_probe pr,
524 blkid_loff_t off, blkid_loff_t size)
525{
526 if (!pr)
527 return -1;
528
529 DBG(DEBUG_LOWPROBE, printf(
530 "changing probing area: size=%llu, off=%llu "
531 "-to-> size=%llu, off=%llu\n",
532 (unsigned long long) pr->size,
533 (unsigned long long) pr->off,
534 (unsigned long long) size,
535 (unsigned long long) off));
536
537 pr->off = off;
538 pr->size = size;
539
540 blkid_probe_reset_buffer(pr);
541
542 return 0;
543}
544
0bffad47
KZ
545/**
546 * blkid_do_probe:
547 * @pr: prober
548 *
549 * Calls probing functions in all enabled chains. The superblocks chain is
550 * enabled by default. The blkid_do_probe() stores result from only one
551 * probing function. It's necessary to call this routine in a loop to get
552 * resuluts from all probing functions in all chains.
a0fc685c 553 *
0bffad47
KZ
554 * This is string-based NAME=value interface only.
555 *
556 * <example>
557 * <title>basic case - use the first result only</title>
558 * <programlisting>
a0fc685c
KZ
559 *
560 * if (blkid_do_probe(pr) == 0) {
561 * int nvals = blkid_probe_numof_values(pr);
562 * for (n = 0; n < nvals; n++) {
563 * if (blkid_probe_get_value(pr, n, &name, &data, &len) == 0)
564 * printf("%s = %s\n", name, data);
565 * }
566 * }
0bffad47
KZ
567 * </programlisting>
568 * </example>
a0fc685c 569 *
0bffad47
KZ
570 * <example>
571 * <title>advanced case - probe for all signatures</title>
572 * <programlisting>
a0fc685c
KZ
573 *
574 * while (blkid_do_probe(pr) == 0) {
575 * int nvals = blkid_probe_numof_values(pr);
576 * ...
577 * }
0bffad47
KZ
578 * </programlisting>
579 * </example>
a0fc685c 580 *
0bffad47 581 * See also blkid_reset_probe().
a0fc685c 582 *
0bffad47 583 * Returns: 0 on success, 1 when probing is done and -1 in case of error.
a0fc685c 584 */
51410fc6 585int blkid_do_probe(blkid_probe pr)
a0948ffe 586{
0bffad47 587 int rc = 1;
a0948ffe 588
0bffad47 589 if (!pr)
51410fc6 590 return -1;
a0948ffe 591
0bffad47
KZ
592 do {
593 struct blkid_chain *chn;
a0948ffe 594
0bffad47
KZ
595 if (!pr->cur_chain)
596 pr->cur_chain = &pr->chains[0];
597 else if (pr->cur_chain < &pr->chains[BLKID_NCHAINS - 1])
598 pr->cur_chain += sizeof(struct blkid_chain);
599 else
600 return 1; /* all chains already probed */
a0fc685c 601
0bffad47
KZ
602 chn = pr->cur_chain;
603 chn->binary = FALSE; /* for sure... */
6644688a 604
0bffad47
KZ
605 DBG(DEBUG_LOWPROBE, printf("chain probe %s %s\n",
606 chn->driver->name,
607 chn->enabled? "ENABLED" : "DISABLED"));
a0948ffe 608
0bffad47 609 if (!chn->enabled)
51410fc6 610 continue;
a0948ffe 611
0bffad47
KZ
612 /* rc: -1 = error, 0 = success, 1 = no result */
613 rc = chn->driver->probe(pr, chn);
a0948ffe 614
0bffad47 615 } while (rc == 1);
a0948ffe 616
0bffad47
KZ
617 return rc;
618}
a0948ffe 619
0bffad47
KZ
620/**
621 * blkid_do_safeprobe:
622 * @pr: prober
623 *
624 * This function gathers probing results from all enabled chains and checks
625 * for ambivalent results (e.g. more filesystems on the device).
626 *
627 * This is string-based NAME=value interface only.
628 *
629 * Note about suberblocks chain -- the function does not check for filesystems
630 * when a RAID signature is detected. The function also does not check for
631 * collision between RAIDs. The first detected RAID is returned.
632 *
633 * Returns: 0 on success, 1 if nothing is detected, -2 if ambivalen result is
634 * detected and -1 on case of error.
635 */
636int blkid_do_safeprobe(blkid_probe pr)
637{
638 int i, count = 0, rc = 0;
a0948ffe 639
0bffad47
KZ
640 if (!pr)
641 return -1;
a0948ffe 642
0bffad47
KZ
643 for (i = 0; i < BLKID_NCHAINS; i++) {
644 struct blkid_chain *chn;
a0948ffe 645
0bffad47
KZ
646 chn = pr->cur_chain = &pr->chains[i];
647 chn->binary = FALSE; /* for sure... */
a0948ffe 648
0bffad47
KZ
649 DBG(DEBUG_LOWPROBE, printf("chain safeprobe %s %s\n",
650 chn->driver->name,
651 chn->enabled? "ENABLED" : "DISABLED"));
652
653 if (!chn->enabled)
654 continue;
655
656 chn->idx = - 1;
657
658 /* rc: -2 ambivalent, -1 = error, 0 = success, 1 = no result */
659 rc = chn->driver->safeprobe(pr, chn);
660 if (rc < 0)
661 goto done; /* error */
662 if (rc == 0)
663 count++; /* success */
51410fc6 664 }
0bffad47
KZ
665
666done:
667 pr->cur_chain = NULL;
668 if (rc < 0)
669 return rc;
670 return count ? 0 : 1;
a0948ffe
KZ
671}
672
0bffad47
KZ
673/**
674 * blkid_do_fullprobe:
675 * @pr: prober
676 *
677 * This function gathers probing results from all enabled chains. Same as
678 * blkid_so_safeprobe() but does not check for collision between probing
679 * result.
680 *
681 * This is string-based NAME=value interface only.
7103157c 682 *
0bffad47 683 * Returns: 0 on success, 1 if nothing is detected or -1 on case of error.
a2f01a1c 684 */
0bffad47 685int blkid_do_fullprobe(blkid_probe pr)
a2f01a1c 686{
0bffad47 687 int i, count = 0, rc = 0;
7103157c 688
0bffad47
KZ
689 if (!pr)
690 return -1;
a2f01a1c 691
0bffad47
KZ
692 for (i = 0; i < BLKID_NCHAINS; i++) {
693 int rc;
694 struct blkid_chain *chn;
a2f01a1c 695
0bffad47
KZ
696 chn = pr->cur_chain = &pr->chains[i];
697 chn->binary = FALSE; /* for sure... */
698
699 DBG(DEBUG_LOWPROBE, printf("chain fullprobe %s: %s\n",
700 chn->driver->name,
701 chn->enabled? "ENABLED" : "DISABLED"));
702
703 if (!chn->enabled)
704 continue;
705
706 chn->idx = - 1;
707
708 /* rc: -1 = error, 0 = success, 1 = no result */
709 rc = chn->driver->probe(pr, chn);
710 if (rc < 0)
711 goto done; /* error */
712 if (rc == 0)
713 count++; /* success */
714 }
715
716done:
717 pr->cur_chain = NULL;
718 if (rc < 0)
719 return rc;
720 return count ? 0 : 1;
a2f01a1c
KZ
721}
722
ce011388
KZ
723/* same sa blkid_probe_get_buffer() but works with 512-sectors */
724unsigned char *blkid_probe_get_sector(blkid_probe pr, unsigned int sector)
725{
726 return pr ? blkid_probe_get_buffer(pr,
727 ((blkid_loff_t) sector) << 9, 0x200) : NULL;
728}
729
9bdf6885 730struct blkid_prval *blkid_probe_assign_value(
51410fc6 731 blkid_probe pr, const char *name)
a0948ffe 732{
51410fc6 733 struct blkid_prval *v;
a0948ffe 734
51410fc6
KZ
735 if (!name)
736 return NULL;
924fe747 737 if (pr->nvals >= BLKID_NVALS)
51410fc6 738 return NULL;
a0948ffe 739
51410fc6
KZ
740 v = &pr->vals[pr->nvals];
741 v->name = name;
9bdf6885 742 v->chain = pr->cur_chain;
51410fc6 743 pr->nvals++;
6644688a 744
9bdf6885
KZ
745 DBG(DEBUG_LOWPROBE,
746 printf("assigning %s [%s]\n", name, v->chain->driver->name));
51410fc6 747 return v;
a0948ffe
KZ
748}
749
51410fc6
KZ
750int blkid_probe_set_value(blkid_probe pr, const char *name,
751 unsigned char *data, size_t len)
a0948ffe 752{
51410fc6 753 struct blkid_prval *v;
a0948ffe 754
51410fc6
KZ
755 if (len > BLKID_PROBVAL_BUFSIZ)
756 len = BLKID_PROBVAL_BUFSIZ;
a0948ffe 757
51410fc6
KZ
758 v = blkid_probe_assign_value(pr, name);
759 if (!v)
760 return -1;
a0948ffe 761
51410fc6
KZ
762 memcpy(v->data, data, len);
763 v->len = len;
a0948ffe
KZ
764 return 0;
765}
766
51410fc6
KZ
767int blkid_probe_vsprintf_value(blkid_probe pr, const char *name,
768 const char *fmt, va_list ap)
a0948ffe 769{
51410fc6
KZ
770 struct blkid_prval *v;
771 size_t len;
a0948ffe 772
51410fc6
KZ
773 v = blkid_probe_assign_value(pr, name);
774 if (!v)
775 return -1;
a0948ffe 776
51410fc6 777 len = vsnprintf((char *) v->data, sizeof(v->data), fmt, ap);
a0948ffe 778
51410fc6
KZ
779 if (len <= 0) {
780 pr->nvals--; /* reset the latest assigned value */
781 return -1;
a0948ffe 782 }
51410fc6 783 v->len = len + 1;
a0948ffe
KZ
784 return 0;
785}
786
b3ee97a3
KZ
787/**
788 * blkid_probe_get_devno:
789 * @pr: probe
790 *
791 * Returns: block device number, or 0 for regilar files.
792 */
793dev_t blkid_probe_get_devno(blkid_probe pr)
794{
795 if (!pr->devno) {
796 struct stat sb;
797
798 if (fstat(pr->fd, &sb) == 0 && S_ISBLK(sb.st_mode))
799 pr->devno = sb.st_rdev;
800 }
801 return pr->devno;
802}
803
804/**
805 * blkid_probe_get_size:
806 * @pr: probe
807 *
808 * Returns: block device (or file) size in bytes or -1 in case of error.
809 */
810blkid_loff_t blkid_probe_get_size(blkid_probe pr)
811{
812 return pr ? pr->size : -1;
813}
814
815/**
816 * blkid_probe_get_sectorsize:
817 * @pr: probe
818 *
819 * Returns: block device hardware sector size (BLKSSZGET ioctl, default 512).
820 */
821unsigned int blkid_probe_get_sectorsize(blkid_probe pr)
822{
823 if (!pr)
824 return DEFAULT_SECTOR_SIZE; /*... and good luck! */
825 if (pr->blkssz)
826 return pr->blkssz;
827 if (!pr->mode) {
828 struct stat st;
829
830 if (fstat(pr->fd, &st))
831 goto fallback;
832 pr->mode = st.st_mode;
833 }
834 if (S_ISBLK(pr->mode)) {
835 if (blkdev_get_sector_size(pr->fd, (int *) &pr->blkssz))
836 goto fallback;
837
838 return pr->blkssz;
839 }
840
841fallback:
842 pr->blkssz = DEFAULT_SECTOR_SIZE;
843 return pr->blkssz;
844}
845
4d72b337
KZ
846/**
847 * blkid_probe_numof_values:
848 * @pr: probe
849 *
850 * Returns: number of values in probing result or -1 in case of error.
851 */
852int blkid_probe_numof_values(blkid_probe pr)
853{
854 if (!pr)
855 return -1;
856 return pr->nvals;
857}
858
81f73792
KZ
859/**
860 * blkid_probe_get_value:
861 * @pr: probe
862 * @num: wanted value in range 0..N, where N is blkid_probe_numof_values() - 1
863 * @name: pointer to return value name or NULL
864 * @data: pointer to return value data or NULL
865 * @len: pointer to return value length or NULL
866 *
867 * Returns: 0 on success, or -1 in case of error.
868 */
51410fc6 869int blkid_probe_get_value(blkid_probe pr, int num, const char **name,
6d042d0d 870 const char **data, size_t *len)
a0948ffe 871{
81f73792 872 struct blkid_prval *v = __blkid_probe_get_value(pr, num);
a0948ffe 873
81f73792 874 if (!v)
51410fc6 875 return -1;
51410fc6
KZ
876 if (name)
877 *name = v->name;
878 if (data)
6d042d0d 879 *data = (char *) v->data;
51410fc6
KZ
880 if (len)
881 *len = v->len;
6644688a
KZ
882
883 DBG(DEBUG_LOWPROBE, printf("returning %s value\n", v->name));
a0948ffe
KZ
884 return 0;
885}
a0948ffe 886
81f73792
KZ
887/**
888 * blkid_probe_lookup_value:
889 * @pr: probe
890 * @name: name of value
891 * @data: pointer to return value data or NULL
892 * @len: pointer to return value length or NULL
893 *
894 * Returns: 0 on success, or -1 in case of error.
895 */
51410fc6 896int blkid_probe_lookup_value(blkid_probe pr, const char *name,
6d042d0d 897 const char **data, size_t *len)
a0948ffe 898{
81f73792 899 struct blkid_prval *v = __blkid_probe_lookup_value(pr, name);
a0948ffe 900
81f73792 901 if (!v)
51410fc6 902 return -1;
81f73792
KZ
903 if (data)
904 *data = (char *) v->data;
905 if (len)
906 *len = v->len;
907 DBG(DEBUG_LOWPROBE, printf("returning %s value\n", v->name));
908 return 0;
a0948ffe
KZ
909}
910
81f73792
KZ
911/**
912 * blkid_probe_has_value:
913 * @pr: probe
914 * @name: name of value
915 *
916 * Returns: 1 if value exist in probing result, otherwise 0.
917 */
51410fc6 918int blkid_probe_has_value(blkid_probe pr, const char *name)
a0948ffe 919{
51410fc6
KZ
920 if (blkid_probe_lookup_value(pr, name, NULL, NULL) == 0)
921 return 1;
a0948ffe
KZ
922 return 0;
923}
924
1c1726a7
KZ
925struct blkid_prval *__blkid_probe_get_value(blkid_probe pr, int num)
926{
927 if (pr == NULL || num < 0 || num >= pr->nvals)
928 return NULL;
929
930 return &pr->vals[num];
931}
932
933struct blkid_prval *__blkid_probe_lookup_value(blkid_probe pr, const char *name)
934{
935 int i;
936
937 if (pr == NULL || pr->nvals == 0 || name == NULL)
938 return NULL;
939
940 for (i = 0; i < pr->nvals; i++) {
941 struct blkid_prval *v = &pr->vals[i];
942
943 if (v->name && strcmp(name, v->name) == 0) {
944 DBG(DEBUG_LOWPROBE, printf("returning %s value\n", v->name));
945 return v;
946 }
947 }
948 return NULL;
949}
950
201529bd
KZ
951
952/* converts DCE UUID (uuid[16]) to human readable string
953 * - the @len should be always 37 */
954void blkid_unparse_uuid(const unsigned char *uuid, char *str, size_t len)
955{
956#ifdef HAVE_LIBUUID
957 uuid_unparse(uuid, str);
958#else
959 snprintf(str, len,
960 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
961 uuid[0], uuid[1], uuid[2], uuid[3],
962 uuid[4], uuid[5],
963 uuid[6], uuid[7],
964 uuid[8], uuid[9],
965 uuid[10], uuid[11], uuid[12], uuid[13], uuid[14],uuid[15]);
966#endif
967}
968