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