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