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