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