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