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