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