]> git.ipfire.org Git - thirdparty/util-linux.git/blame_incremental - libblkid/src/probe.c
taskset: Accept 0 pid for current process
[thirdparty/util-linux.git] / libblkid / src / probe.c
... / ...
CommitLineData
1/*
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) == BLKID_PROBE_OK)
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/mman.h>
94#include <sys/types.h>
95#ifdef HAVE_LINUX_CDROM_H
96#include <linux/cdrom.h>
97#endif
98#ifdef HAVE_LINUX_BLKZONED_H
99#include <linux/blkzoned.h>
100#endif
101#ifdef HAVE_SYS_STAT_H
102#include <sys/stat.h>
103#endif
104#ifdef HAVE_ERRNO_H
105#include <errno.h>
106#endif
107#ifdef HAVE_LINUX_FD_H
108#include <linux/fd.h>
109#endif
110#include <inttypes.h>
111#include <stdint.h>
112#include <stdarg.h>
113#include <limits.h>
114#ifdef HAVE_OPAL_GET_STATUS
115#include <linux/sed-opal.h>
116#endif
117
118#include "blkidP.h"
119#include "all-io.h"
120#include "sysfs.h"
121#include "strutils.h"
122#include "list.h"
123#include "fileutils.h"
124
125/*
126 * All supported chains
127 */
128static const struct blkid_chaindrv *const chains_drvs[] = {
129 [BLKID_CHAIN_SUBLKS] = &superblocks_drv,
130 [BLKID_CHAIN_TOPLGY] = &topology_drv,
131 [BLKID_CHAIN_PARTS] = &partitions_drv
132};
133
134static void blkid_probe_reset_values(blkid_probe pr);
135
136/**
137 * blkid_new_probe:
138 *
139 * Returns: a pointer to the newly allocated probe struct or NULL in case of error.
140 */
141blkid_probe blkid_new_probe(void)
142{
143 int i;
144 blkid_probe pr;
145
146 pr = calloc(1, sizeof(struct blkid_struct_probe));
147 if (!pr)
148 return NULL;
149
150 DBG(LOWPROBE, ul_debug("allocate a new probe"));
151
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 INIT_LIST_HEAD(&pr->prunable_buffers);
160 INIT_LIST_HEAD(&pr->values);
161 INIT_LIST_HEAD(&pr->hints);
162 return pr;
163}
164
165/*
166 * Clone @parent, the new clone shares all, but except:
167 *
168 * - probing result
169 * - buffers if another device (or offset) is set to the prober
170 */
171blkid_probe blkid_clone_probe(blkid_probe parent)
172{
173 blkid_probe pr;
174
175 if (!parent)
176 return NULL;
177
178 DBG(LOWPROBE, ul_debug("allocate a probe clone"));
179
180 pr = blkid_new_probe();
181 if (!pr)
182 return NULL;
183
184 pr->fd = parent->fd;
185 pr->off = parent->off;
186 pr->size = parent->size;
187 pr->io_size = parent->io_size;
188 pr->devno = parent->devno;
189 pr->disk_devno = parent->disk_devno;
190 pr->blkssz = parent->blkssz;
191 pr->flags = parent->flags;
192 pr->zone_size = parent->zone_size;
193 pr->parent = parent;
194
195 pr->flags &= ~BLKID_FL_PRIVATE_FD;
196
197 return pr;
198}
199
200
201
202/**
203 * blkid_new_probe_from_filename:
204 * @filename: device or regular file
205 *
206 * This function is same as call open(filename), blkid_new_probe() and
207 * blkid_probe_set_device(pr, fd, 0, 0).
208 *
209 * The @filename is closed by blkid_free_probe() or by the
210 * blkid_probe_set_device() call.
211 *
212 * Returns: a pointer to the newly allocated probe struct or NULL in case of
213 * error.
214 */
215blkid_probe blkid_new_probe_from_filename(const char *filename)
216{
217 int fd;
218 blkid_probe pr = NULL;
219
220 fd = open(filename, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
221 if (fd < 0)
222 return NULL;
223
224 pr = blkid_new_probe();
225 if (!pr)
226 goto err;
227
228 if (blkid_probe_set_device(pr, fd, 0, 0))
229 goto err;
230
231 pr->flags |= BLKID_FL_PRIVATE_FD;
232 return pr;
233err:
234 close(fd);
235 blkid_free_probe(pr);
236 return NULL;
237}
238
239/**
240 * blkid_free_probe:
241 * @pr: probe
242 *
243 * Deallocates the probe struct, buffers and all allocated
244 * data that are associated with this probing control struct.
245 */
246void blkid_free_probe(blkid_probe pr)
247{
248 int i;
249
250 if (!pr)
251 return;
252
253 for (i = 0; i < BLKID_NCHAINS; i++) {
254 struct blkid_chain *ch = &pr->chains[i];
255
256 if (ch->driver->free_data)
257 ch->driver->free_data(pr, ch->data);
258 free(ch->fltr);
259 ch->fltr = NULL;
260 }
261
262 if ((pr->flags & BLKID_FL_PRIVATE_FD) && pr->fd >= 0)
263 close(pr->fd);
264 blkid_probe_reset_buffers(pr);
265 blkid_probe_reset_values(pr);
266 blkid_probe_reset_hints(pr);
267 blkid_free_probe(pr->disk_probe);
268
269 DBG(LOWPROBE, ul_debug("free probe"));
270 free(pr);
271}
272
273void blkid_probe_free_value(struct blkid_prval *v)
274{
275 if (!v)
276 return;
277
278 list_del(&v->prvals);
279 free(v->data);
280
281 DBG(LOWPROBE, ul_debug(" free value %s", v->name));
282 free(v);
283}
284
285/*
286 * Removes chain values from probing result.
287 */
288void blkid_probe_chain_reset_values(blkid_probe pr, struct blkid_chain *chn)
289{
290
291 struct list_head *p, *pnext;
292
293 if (list_empty(&pr->values))
294 return;
295
296 DBG(LOWPROBE, ul_debug("Resetting %s values", chn->driver->name));
297
298 list_for_each_safe(p, pnext, &pr->values) {
299 struct blkid_prval *v = list_entry(p,
300 struct blkid_prval, prvals);
301
302 if (v->chain == chn)
303 blkid_probe_free_value(v);
304 }
305}
306
307static void blkid_probe_chain_reset_position(struct blkid_chain *chn)
308{
309 chn->idx = -1;
310}
311
312/*
313 * Move chain values from probing result to @vals
314 */
315int blkid_probe_chain_save_values(blkid_probe pr, struct blkid_chain *chn,
316 struct list_head *vals)
317{
318 struct list_head *p, *pnext;
319 struct blkid_prval *v;
320
321 DBG(LOWPROBE, ul_debug("saving %s values", chn->driver->name));
322
323 list_for_each_safe(p, pnext, &pr->values) {
324
325 v = list_entry(p, struct blkid_prval, prvals);
326 if (v->chain != chn)
327 continue;
328
329 list_del_init(&v->prvals);
330 list_add_tail(&v->prvals, vals);
331 }
332 return 0;
333}
334
335/*
336 * Appends values from @vals to the probing result
337 */
338void blkid_probe_append_values_list(blkid_probe pr, struct list_head *vals)
339{
340 DBG(LOWPROBE, ul_debug("appending values"));
341
342 list_splice(vals, &pr->values);
343 INIT_LIST_HEAD(vals);
344}
345
346
347void blkid_probe_free_values_list(struct list_head *vals)
348{
349 if (!vals)
350 return;
351
352 DBG(LOWPROBE, ul_debug("freeing values list"));
353
354 while (!list_empty(vals)) {
355 struct blkid_prval *v = list_entry(vals->next, struct blkid_prval, prvals);
356 blkid_probe_free_value(v);
357 }
358}
359
360struct blkid_chain *blkid_probe_get_chain(blkid_probe pr)
361{
362 return pr->cur_chain;
363}
364
365static const char *blkid_probe_get_probername(blkid_probe pr)
366{
367 struct blkid_chain *chn = blkid_probe_get_chain(pr);
368
369 if (chn && chn->idx >= 0 && (unsigned)chn->idx < chn->driver->nidinfos)
370 return chn->driver->idinfos[chn->idx]->name;
371
372 return NULL;
373}
374
375void *blkid_probe_get_binary_data(blkid_probe pr, struct blkid_chain *chn)
376{
377 int rc, org_prob_flags;
378 struct blkid_chain *org_chn;
379
380 /* save the current setting -- the binary API has to be completely
381 * independent on the current probing status
382 */
383 org_chn = pr->cur_chain;
384 org_prob_flags = pr->prob_flags;
385
386 pr->cur_chain = chn;
387 pr->prob_flags = 0;
388 chn->binary = TRUE;
389 blkid_probe_chain_reset_position(chn);
390
391 rc = chn->driver->probe(pr, chn);
392
393 chn->binary = FALSE;
394 blkid_probe_chain_reset_position(chn);
395
396 /* restore the original setting
397 */
398 pr->cur_chain = org_chn;
399 pr->prob_flags = org_prob_flags;
400
401 if (rc != 0)
402 return NULL;
403
404 DBG(LOWPROBE, ul_debug("returning %s binary data", chn->driver->name));
405 return chn->data;
406}
407
408
409/**
410 * blkid_reset_probe:
411 * @pr: probe
412 *
413 * Zeroize probing results and resets the current probing (this has impact to
414 * blkid_do_probe() only). This function does not touch probing filters and
415 * keeps assigned device.
416 */
417void blkid_reset_probe(blkid_probe pr)
418{
419 int i;
420
421 blkid_probe_reset_values(pr);
422 blkid_probe_set_wiper(pr, 0, 0);
423
424 pr->cur_chain = NULL;
425
426 for (i = 0; i < BLKID_NCHAINS; i++)
427 blkid_probe_chain_reset_position(&pr->chains[i]);
428}
429
430/***
431static int blkid_probe_dump_filter(blkid_probe pr, int chain)
432{
433 struct blkid_chain *chn;
434 int i;
435
436 if (!pr || chain < 0 || chain >= BLKID_NCHAINS)
437 return -1;
438
439 chn = &pr->chains[chain];
440
441 if (!chn->fltr)
442 return -1;
443
444 for (i = 0; i < chn->driver->nidinfos; i++) {
445 const struct blkid_idinfo *id = chn->driver->idinfos[i];
446
447 DBG(LOWPROBE, ul_debug("%d: %s: %s",
448 i,
449 id->name,
450 blkid_bmp_get_item(chn->fltr, i)
451 ? "disabled" : "enabled <--"));
452 }
453 return 0;
454}
455***/
456
457/*
458 * Returns properly initialized chain filter
459 */
460unsigned long *blkid_probe_get_filter(blkid_probe pr, int chain, int create)
461{
462 struct blkid_chain *chn;
463
464 if (chain < 0 || chain >= BLKID_NCHAINS)
465 return NULL;
466
467 chn = &pr->chains[chain];
468
469 /* always when you touch the chain filter all indexes are reset and
470 * probing starts from scratch
471 */
472 blkid_probe_chain_reset_position(chn);
473 pr->cur_chain = NULL;
474
475 if (!chn->driver->has_fltr || (!chn->fltr && !create))
476 return NULL;
477
478 if (!chn->fltr)
479 chn->fltr = calloc(1, blkid_bmp_nbytes(chn->driver->nidinfos));
480 else
481 memset(chn->fltr, 0, blkid_bmp_nbytes(chn->driver->nidinfos));
482
483 /* blkid_probe_dump_filter(pr, chain); */
484 return chn->fltr;
485}
486
487/*
488 * Generic private functions for filter setting
489 */
490int __blkid_probe_invert_filter(blkid_probe pr, int chain)
491{
492 size_t i;
493 struct blkid_chain *chn;
494
495 chn = &pr->chains[chain];
496
497 if (!chn->driver->has_fltr || !chn->fltr)
498 return -1;
499
500 for (i = 0; i < blkid_bmp_nwords(chn->driver->nidinfos); i++)
501 chn->fltr[i] = ~chn->fltr[i];
502
503 DBG(LOWPROBE, ul_debug("probing filter inverted"));
504 /* blkid_probe_dump_filter(pr, chain); */
505 return 0;
506}
507
508int __blkid_probe_reset_filter(blkid_probe pr, int chain)
509{
510 return blkid_probe_get_filter(pr, chain, FALSE) ? 0 : -1;
511}
512
513int __blkid_probe_filter_types(blkid_probe pr, int chain, int flag, char *names[])
514{
515 unsigned long *fltr;
516 struct blkid_chain *chn;
517 size_t i;
518
519 fltr = blkid_probe_get_filter(pr, chain, TRUE);
520 if (!fltr)
521 return -1;
522
523 chn = &pr->chains[chain];
524
525 for (i = 0; i < chn->driver->nidinfos; i++) {
526 int has = 0;
527 const struct blkid_idinfo *id = chn->driver->idinfos[i];
528 char **n;
529
530 for (n = names; *n; n++) {
531 if (!strcmp(id->name, *n)) {
532 has = 1;
533 break;
534 }
535 }
536 if (has) {
537 if (flag & BLKID_FLTR_NOTIN)
538 blkid_bmp_set_item(fltr, i);
539 } else if (flag & BLKID_FLTR_ONLYIN)
540 blkid_bmp_set_item(fltr, i);
541 }
542
543 DBG(LOWPROBE, ul_debug("%s: a new probing type-filter initialized",
544 chn->driver->name));
545 /* blkid_probe_dump_filter(pr, chain); */
546 return 0;
547}
548
549static void remove_buffer(struct blkid_bufinfo *bf)
550{
551 list_del(&bf->bufs);
552
553 DBG(BUFFER, ul_debug(" remove buffer: [off=%"PRIu64", len=%"PRIu64"]",
554 bf->off, bf->len));
555 munmap(bf->data, bf->len);
556 free(bf);
557}
558
559static struct blkid_bufinfo *read_buffer(blkid_probe pr, uint64_t real_off, uint64_t len)
560{
561 ssize_t ret;
562 struct blkid_bufinfo *bf = NULL;
563
564 if (lseek(pr->fd, real_off, SEEK_SET) == (off_t) -1) {
565 errno = 0;
566 return NULL;
567 }
568
569 /* someone trying to overflow some buffers? */
570 if (len > ULONG_MAX - sizeof(struct blkid_bufinfo)) {
571 errno = ENOMEM;
572 return NULL;
573 }
574
575 /* allocate info and space for data by one malloc call */
576 bf = calloc(1, sizeof(struct blkid_bufinfo));
577 if (!bf) {
578 errno = ENOMEM;
579 return NULL;
580 }
581
582 bf->data = mmap(NULL, len, PROT_READ | PROT_WRITE,
583 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
584 if (bf->data == MAP_FAILED) {
585 free(bf);
586 errno = ENOMEM;
587 return NULL;
588 }
589
590 bf->len = len;
591 bf->off = real_off;
592 INIT_LIST_HEAD(&bf->bufs);
593
594 DBG(LOWPROBE, ul_debug("\tread: off=%"PRIu64" len=%"PRIu64"",
595 real_off, len));
596
597 ret = read(pr->fd, bf->data, len);
598 if (ret != (ssize_t) len) {
599 DBG(LOWPROBE, ul_debug("\tread failed: %m"));
600 remove_buffer(bf);
601
602 /* I/O errors on CDROMs are non-fatal to work with hybrid
603 * audio+data disks */
604 if (ret >= 0 || blkid_probe_is_cdrom(pr) || blkdid_probe_is_opal_locked(pr))
605 errno = 0;
606
607 return NULL;
608 }
609
610 if (mprotect(bf->data, len, PROT_READ))
611 DBG(LOWPROBE, ul_debug("\tmprotect failed: %m"));
612
613 return bf;
614}
615
616/*
617 * Search in buffers we already have in memory
618 */
619static struct blkid_bufinfo *get_cached_buffer(blkid_probe pr, uint64_t off, uint64_t len)
620{
621 uint64_t real_off = pr->off + off;
622 struct list_head *p;
623
624 list_for_each(p, &pr->buffers) {
625 struct blkid_bufinfo *x =
626 list_entry(p, struct blkid_bufinfo, bufs);
627
628 if (real_off >= x->off && real_off + len <= x->off + x->len) {
629 DBG(BUFFER, ul_debug("\treuse: off=%"PRIu64" len=%"PRIu64" (for off=%"PRIu64" len=%"PRIu64")",
630 x->off, x->len, real_off, len));
631 return x;
632 }
633 }
634 return NULL;
635}
636
637/*
638 * Mark smaller buffers that can be satisfied by bf as prunable
639 */
640static void mark_prunable_buffers(blkid_probe pr, const struct blkid_bufinfo *bf)
641{
642 struct list_head *p, *next;
643
644 list_for_each_safe(p, next, &pr->buffers) {
645 struct blkid_bufinfo *x =
646 list_entry(p, struct blkid_bufinfo, bufs);
647
648 if (bf->off <= x->off && bf->off + bf->len >= x->off + x->len) {
649 list_del(&x->bufs);
650 list_add(&x->bufs, &pr->prunable_buffers);
651 }
652 }
653}
654
655/*
656 * Remove buffers that are marked as prunable
657 */
658void blkid_probe_prune_buffers(blkid_probe pr)
659{
660 struct list_head *p, *next;
661
662 list_for_each_safe(p, next, &pr->prunable_buffers) {
663 struct blkid_bufinfo *x =
664 list_entry(p, struct blkid_bufinfo, bufs);
665
666 remove_buffer(x);
667 }
668}
669
670/*
671 * Zeroize in-memory data in already read buffer. The next blkid_probe_get_buffer()
672 * will return modified buffer. This is usable when you want to call the same probing
673 * function more than once and hide previously detected magic strings.
674 *
675 * See blkid_probe_hide_range().
676 */
677static int hide_buffer(blkid_probe pr, uint64_t off, uint64_t len)
678{
679 uint64_t real_off = pr->off + off;
680 struct list_head *p;
681 int ct = 0;
682
683 if (UINT64_MAX - len < off) {
684 DBG(BUFFER, ul_debug("\t hide-buffer overflow (ignore)"));
685 return -EINVAL;
686 }
687
688 list_for_each(p, &pr->buffers) {
689 struct blkid_bufinfo *x =
690 list_entry(p, struct blkid_bufinfo, bufs);
691 unsigned char *data;
692
693 if (real_off >= x->off && real_off + len <= x->off + x->len) {
694
695 assert(x->off <= real_off);
696 assert(x->off + x->len >= real_off + len);
697
698 data = real_off ? x->data + (real_off - x->off) : x->data;
699
700 DBG(BUFFER, ul_debug("\thiding: off=%"PRIu64" len=%"PRIu64,
701 off, len));
702 mprotect(x->data, x->len, PROT_READ | PROT_WRITE);
703 memset(data, 0, len);
704 mprotect(x->data, x->len, PROT_READ);
705 ct++;
706 }
707 }
708 return ct == 0 ? -EINVAL : 0;
709}
710
711
712/*
713 * Note that @off is offset within probing area, the probing area is defined by
714 * pr->off and pr->size.
715 */
716const unsigned char *blkid_probe_get_buffer(blkid_probe pr, uint64_t off, uint64_t len)
717{
718 struct blkid_bufinfo *bf = NULL;
719 uint64_t real_off, bias, len_align;
720
721 bias = off % pr->io_size;
722 off -= bias;
723 len += bias;
724
725 if (len % pr->io_size) {
726 len_align = pr->io_size - (len % pr->io_size);
727
728 if (pr->off + off + len + len_align <= pr->size)
729 len += len_align;
730 }
731
732 real_off = pr->off + off;
733
734 /*
735 DBG(BUFFER, ul_debug("\t>>>> off=%ju, real-off=%ju (probe <%ju..%ju>, len=%ju",
736 off, real_off, pr->off, pr->off + pr->size, len));
737 */
738 if (pr->size == 0 || pr->io_size == 0) {
739 errno = EINVAL;
740 return NULL;
741 }
742
743 if (UINT64_MAX - len < off || UINT64_MAX - len < real_off) {
744 DBG(BUFFER, ul_debug("\t read-buffer overflow (ignore)"));
745 return NULL;
746 }
747
748 if (len > 8388608 /* 8 Mib */ ) {
749 DBG(BUFFER, ul_debug("\t too large read request (ignore)"));
750 return NULL;
751 }
752
753 if (len == 0
754 || (!S_ISCHR(pr->mode) && (pr->size < off || pr->size < len))
755 || (!S_ISCHR(pr->mode) && (pr->off + pr->size < real_off + len))) {
756 DBG(BUFFER, ul_debug("\t read-buffer out of probing area (ignore)"));
757 errno = 0;
758 return NULL;
759 }
760
761 if (pr->parent &&
762 pr->parent->devno == pr->devno &&
763 pr->parent->off <= pr->off &&
764 pr->parent->off + pr->parent->size >= pr->off + pr->size) {
765 /*
766 * This is a cloned prober and points to the same area as
767 * parent. Let's use parent's buffers.
768 *
769 * Note that pr->off (and pr->parent->off) is always from the
770 * begin of the device.
771 */
772 return blkid_probe_get_buffer(pr->parent,
773 pr->off + off - pr->parent->off, len);
774 }
775
776 /* try buffers we already have in memory or read from device */
777 bf = get_cached_buffer(pr, off, len);
778 if (!bf) {
779 bf = read_buffer(pr, real_off, len);
780 if (!bf)
781 return NULL;
782
783 mark_prunable_buffers(pr, bf);
784 list_add_tail(&bf->bufs, &pr->buffers);
785 }
786
787 assert(bf->off <= real_off);
788 assert(bf->off + bf->len >= real_off + len);
789
790 errno = 0;
791 return real_off ? bf->data + (real_off - bf->off + bias) : bf->data + bias;
792}
793
794#ifdef O_DIRECT
795/*
796 * This is blkid_probe_get_buffer with the read done as an O_DIRECT operation.
797 * Note that @off is offset within probing area, the probing area is defined by
798 * pr->off and pr->size.
799 */
800const unsigned char *blkid_probe_get_buffer_direct(blkid_probe pr, uint64_t off, uint64_t len)
801{
802 const unsigned char *ret = NULL;
803 int flags, rc, olderrno;
804
805 flags = fcntl(pr->fd, F_GETFL);
806 rc = fcntl(pr->fd, F_SETFL, flags | O_DIRECT);
807 if (rc) {
808 DBG(LOWPROBE, ul_debug("fcntl F_SETFL failed to set O_DIRECT"));
809 errno = 0;
810 return NULL;
811 }
812 ret = blkid_probe_get_buffer(pr, off, len);
813 olderrno = errno;
814 rc = fcntl(pr->fd, F_SETFL, flags);
815 if (rc) {
816 DBG(LOWPROBE, ul_debug("fcntl F_SETFL failed to clear O_DIRECT"));
817 errno = olderrno;
818 }
819 return ret;
820}
821#endif
822
823/**
824 * blkid_probe_reset_buffers:
825 * @pr: prober
826 *
827 * libblkid reuse all already read buffers from the device. The buffers may be
828 * modified by blkid_probe_hide_range(). This function reset and free all
829 * cached buffers. The next blkid_do_probe() will read all data from the
830 * device.
831 *
832 * Since: 2.31
833 *
834 * Returns: <0 in case of failure, or 0 on success.
835 */
836int blkid_probe_reset_buffers(blkid_probe pr)
837{
838 uint64_t ct = 0, len = 0;
839
840 pr->flags &= ~BLKID_FL_MODIF_BUFF;
841
842 blkid_probe_prune_buffers(pr);
843
844 if (list_empty(&pr->buffers))
845 return 0;
846
847 DBG(BUFFER, ul_debug("Resetting probing buffers"));
848
849 while (!list_empty(&pr->buffers)) {
850 struct blkid_bufinfo *bf = list_entry(pr->buffers.next,
851 struct blkid_bufinfo, bufs);
852 ct++;
853 len += bf->len;
854
855 remove_buffer(bf);
856 }
857
858 DBG(LOWPROBE, ul_debug(" buffers summary: %"PRIu64" bytes by %"PRIu64" read() calls",
859 len, ct));
860
861 INIT_LIST_HEAD(&pr->buffers);
862
863 return 0;
864}
865
866/**
867 * blkid_probe_hide_range:
868 * @pr: prober
869 * @off: start of the range
870 * @len: size of the range
871 *
872 * This function modifies in-memory cached data from the device. The specified
873 * range is zeroized. This is usable together with blkid_probe_step_back().
874 * The next blkid_do_probe() will not see specified area.
875 *
876 * Note that this is usable for already (by library) read data, and this
877 * function is not a way how to hide any large areas on your device.
878 *
879 * The function blkid_probe_reset_buffers() reverts all.
880 *
881 * Since: 2.31
882 *
883 * Returns: <0 in case of failure, or 0 on success.
884 */
885int blkid_probe_hide_range(blkid_probe pr, uint64_t off, uint64_t len)
886{
887 int rc = hide_buffer(pr, off, len);
888
889 if (rc == 0)
890 pr->flags |= BLKID_FL_MODIF_BUFF;
891 return rc;
892}
893
894
895static void blkid_probe_reset_values(blkid_probe pr)
896{
897 if (list_empty(&pr->values))
898 return;
899
900 DBG(LOWPROBE, ul_debug("resetting results"));
901
902 while (!list_empty(&pr->values)) {
903 struct blkid_prval *v = list_entry(pr->values.next,
904 struct blkid_prval, prvals);
905 blkid_probe_free_value(v);
906 }
907
908 INIT_LIST_HEAD(&pr->values);
909}
910
911/*
912 * Small devices need a special care.
913 */
914int blkid_probe_is_tiny(blkid_probe pr)
915{
916 return (pr->flags & BLKID_FL_TINY_DEV);
917}
918
919/*
920 * CDROMs may fail when probed for RAID (last sector problem)
921 */
922int blkid_probe_is_cdrom(blkid_probe pr)
923{
924 return (pr->flags & BLKID_FL_CDROM_DEV);
925}
926
927int blkdid_probe_is_opal_locked(blkid_probe pr)
928{
929 if (!(pr->flags & BLKID_FL_OPAL_CHECKED)) {
930 pr->flags |= BLKID_FL_OPAL_CHECKED;
931
932#ifdef HAVE_OPAL_GET_STATUS
933 ssize_t ret;
934 struct opal_status st = { };
935 int errsv = errno;
936
937 /* If the device is locked with OPAL, we'll fail to read with I/O
938 * errors when probing deep into the block device. */
939 ret = ioctl(pr->fd, IOC_OPAL_GET_STATUS, &st);
940 if (ret == 0 && (st.flags & OPAL_FL_LOCKED)) {
941 pr->flags |= BLKID_FL_OPAL_LOCKED;
942 }
943
944 errno = errsv;
945#endif
946 }
947
948 return (pr->flags & BLKID_FL_OPAL_LOCKED);
949}
950
951#ifdef CDROM_GET_CAPABILITY
952
953static int is_sector_readable(int fd, uint64_t sector)
954{
955 char buf[512];
956 ssize_t sz;
957
958 if (lseek(fd, sector * 512, SEEK_SET) == (off_t) -1)
959 goto failed;
960
961 sz = read(fd, buf, sizeof(buf));
962 if (sz != (ssize_t) sizeof(buf))
963 goto failed;
964
965 return 1;
966failed:
967 DBG(LOWPROBE, ul_debug("CDROM: read sector %"PRIu64" failed %m", sector));
968 errno = 0;
969 return 0;
970}
971
972/*
973 * Linux kernel reports (BLKGETSIZE) cdrom device size greater than area
974 * readable by read(2). We have to reduce the probing area to avoid unwanted
975 * I/O errors in probing functions. It seems that unreadable are always last 2
976 * or 3 CD blocks (CD block size is 2048 bytes, it means 12 in 512-byte
977 * sectors). Linux kernel reports (CDROM_LAST_WRITTEN) also location of last
978 * written block, so we will reduce size based on it too.
979 */
980static void cdrom_size_correction(blkid_probe pr, uint64_t last_written)
981{
982 uint64_t n, nsectors = pr->size >> 9;
983
984 if (last_written && nsectors > ((last_written+1) << 2))
985 nsectors = (last_written+1) << 2;
986
987 for (n = nsectors - 12; n < nsectors; n++) {
988 if (!is_sector_readable(pr->fd, n))
989 goto failed;
990 }
991
992 DBG(LOWPROBE, ul_debug("CDROM: full size available"));
993 return;
994failed:
995 /* 'n' is the failed sector, reduce device size to n-1; */
996 DBG(LOWPROBE, ul_debug("CDROM: reduce size from %ju to %ju.",
997 (uintmax_t) pr->size,
998 (uintmax_t) n << 9));
999 pr->size = n << 9;
1000}
1001
1002#endif
1003
1004static uint64_t blkid_get_io_size(int fd)
1005{
1006 static const int ioctls[] = {
1007#ifdef BLKIOOPT
1008 BLKIOOPT,
1009#endif
1010#ifdef BLKIOMIN
1011 BLKIOMIN,
1012#endif
1013#ifdef BLKBSZGET
1014 BLKBSZGET,
1015#endif
1016 };
1017 unsigned int s;
1018 size_t i;
1019 int r;
1020
1021 for (i = 0; i < ARRAY_SIZE(ioctls); i++) {
1022 r = ioctl(fd, ioctls[i], &s);
1023 if (r == 0 && is_power_of_2(s) && s >= DEFAULT_SECTOR_SIZE)
1024 return min(s, 1U << 16);
1025 }
1026
1027 return DEFAULT_SECTOR_SIZE;
1028}
1029
1030/**
1031 * blkid_probe_set_device:
1032 * @pr: probe
1033 * @fd: device file descriptor
1034 * @off: begin of probing area
1035 * @size: size of probing area (zero means whole device/file)
1036 *
1037 * Assigns the device to probe control struct, resets internal buffers, resets
1038 * the current probing, and close previously associated device (if open by
1039 * libblkid).
1040 *
1041 * If @fd is < 0 than only resets the prober and returns 1. Note that
1042 * blkid_reset_probe() keeps the device associated with the prober, but
1043 * blkid_probe_set_device() does complete reset.
1044 *
1045 * Returns: -1 in case of failure, 0 on success and 1 on reset.
1046 */
1047int blkid_probe_set_device(blkid_probe pr, int fd,
1048 blkid_loff_t off, blkid_loff_t size)
1049{
1050 struct stat sb;
1051 uint64_t devsiz = 0;
1052 char *dm_uuid = NULL;
1053 int is_floppy = 0;
1054
1055 blkid_reset_probe(pr);
1056 blkid_probe_reset_buffers(pr);
1057
1058 if ((pr->flags & BLKID_FL_PRIVATE_FD) && pr->fd >= 0)
1059 close(pr->fd);
1060
1061 if (pr->disk_probe) {
1062 blkid_free_probe(pr->disk_probe);
1063 pr->disk_probe = NULL;
1064 }
1065
1066 pr->flags &= ~BLKID_FL_PRIVATE_FD;
1067 pr->flags &= ~BLKID_FL_TINY_DEV;
1068 pr->flags &= ~BLKID_FL_CDROM_DEV;
1069 pr->prob_flags = 0;
1070 pr->fd = fd;
1071 pr->off = (uint64_t) off;
1072 pr->size = 0;
1073 pr->io_size = DEFAULT_SECTOR_SIZE;
1074 pr->devno = 0;
1075 pr->disk_devno = 0;
1076 pr->mode = 0;
1077 pr->blkssz = 0;
1078 pr->wipe_off = 0;
1079 pr->wipe_size = 0;
1080 pr->wipe_chain = NULL;
1081 pr->zone_size = 0;
1082
1083 if (fd < 0)
1084 return 1;
1085
1086
1087#if defined(POSIX_FADV_RANDOM) && defined(HAVE_POSIX_FADVISE)
1088 /* Disable read-ahead */
1089 posix_fadvise(fd, 0, 0, POSIX_FADV_RANDOM);
1090#endif
1091 if (fstat(fd, &sb))
1092 goto err;
1093
1094 if (!S_ISBLK(sb.st_mode) && !S_ISCHR(sb.st_mode) && !S_ISREG(sb.st_mode)) {
1095 errno = EINVAL;
1096 goto err;
1097 }
1098
1099 pr->mode = sb.st_mode;
1100 if (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode))
1101 pr->devno = sb.st_rdev;
1102
1103 if (S_ISBLK(sb.st_mode)) {
1104 if (blkdev_get_size(fd, (unsigned long long *) &devsiz)) {
1105 DBG(LOWPROBE, ul_debug("failed to get device size"));
1106 goto err;
1107 }
1108 } else if (S_ISCHR(sb.st_mode)) {
1109 char buf[PATH_MAX];
1110
1111 if (!sysfs_chrdev_devno_to_devname(sb.st_rdev, buf, sizeof(buf))
1112 || strncmp(buf, "ubi", 3) != 0) {
1113 DBG(LOWPROBE, ul_debug("no UBI char device"));
1114 errno = EINVAL;
1115 goto err;
1116 }
1117 devsiz = 1; /* UBI devices are char... */
1118 } else if (S_ISREG(sb.st_mode))
1119 devsiz = sb.st_size; /* regular file */
1120
1121 pr->size = size ? (uint64_t)size : devsiz;
1122
1123 if (off && size == 0)
1124 /* only offset without size specified */
1125 pr->size -= (uint64_t) off;
1126
1127 if (pr->off + pr->size > devsiz) {
1128 DBG(LOWPROBE, ul_debug("area specified by offset and size is bigger than device"));
1129 errno = EINVAL;
1130 goto err;
1131 }
1132
1133 if (pr->size <= 1440 * 1024 && !S_ISCHR(sb.st_mode))
1134 pr->flags |= BLKID_FL_TINY_DEV;
1135
1136#ifdef FDGETFDCSTAT
1137 if (S_ISBLK(sb.st_mode)) {
1138 /*
1139 * Re-open without O_NONBLOCK for floppy device.
1140 *
1141 * Since kernel commit c7e9d0020361f4308a70cdfd6d5335e273eb8717
1142 * floppy drive works bad when opened with O_NONBLOCK.
1143 */
1144 struct floppy_fdc_state flst;
1145
1146 if (ioctl(fd, FDGETFDCSTAT, &flst) >= 0) {
1147 int flags = fcntl(fd, F_GETFL, 0);
1148
1149 if (flags < 0)
1150 goto err;
1151 if (flags & O_NONBLOCK) {
1152 flags &= ~O_NONBLOCK;
1153
1154 fd = ul_reopen(fd, flags | O_CLOEXEC);
1155 if (fd < 0)
1156 goto err;
1157
1158 pr->flags |= BLKID_FL_PRIVATE_FD;
1159 pr->fd = fd;
1160 }
1161 is_floppy = 1;
1162 }
1163 errno = 0;
1164 }
1165#endif
1166 if (S_ISBLK(sb.st_mode) &&
1167 !is_floppy &&
1168 sysfs_devno_is_dm_private(sb.st_rdev, &dm_uuid)) {
1169 DBG(LOWPROBE, ul_debug("ignore private device mapper device"));
1170 pr->flags |= BLKID_FL_NOSCAN_DEV;
1171 }
1172
1173#ifdef CDROM_GET_CAPABILITY
1174 else if (S_ISBLK(sb.st_mode) &&
1175 !blkid_probe_is_tiny(pr) &&
1176 !dm_uuid &&
1177 !is_floppy &&
1178 blkid_probe_is_wholedisk(pr)) {
1179
1180 long last_written = 0;
1181
1182 /*
1183 * pktcdvd.ko accepts only these ioctls:
1184 * CDROMEJECT CDROMMULTISESSION CDROMREADTOCENTRY
1185 * CDROM_LAST_WRITTEN CDROM_SEND_PACKET SCSI_IOCTL_SEND_COMMAND
1186 * So CDROM_GET_CAPABILITY cannot be used for detecting pktcdvd
1187 * devices. But CDROM_GET_CAPABILITY and CDROM_DRIVE_STATUS are
1188 * fast so use them for detecting if medium is present. In any
1189 * case use last written block form CDROM_LAST_WRITTEN.
1190 */
1191
1192 if (ioctl(fd, CDROM_GET_CAPABILITY, NULL) >= 0) {
1193# ifdef CDROM_DRIVE_STATUS
1194 switch (ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT)) {
1195 case CDS_TRAY_OPEN:
1196 case CDS_NO_DISC:
1197 errno = ENOMEDIUM;
1198 goto err;
1199 }
1200# endif
1201 pr->flags |= BLKID_FL_CDROM_DEV;
1202 }
1203
1204# ifdef CDROM_LAST_WRITTEN
1205 if (ioctl(fd, CDROM_LAST_WRITTEN, &last_written) == 0) {
1206 pr->flags |= BLKID_FL_CDROM_DEV;
1207 } else {
1208 if (errno == ENOMEDIUM)
1209 goto err;
1210 }
1211# endif
1212
1213 if (pr->flags & BLKID_FL_CDROM_DEV) {
1214 cdrom_size_correction(pr, last_written);
1215
1216# ifdef CDROMMULTISESSION
1217 if (!pr->off && blkid_probe_get_hint(pr, "session_offset", NULL) < 0) {
1218 struct cdrom_multisession multisession = { .addr_format = CDROM_LBA };
1219 if (ioctl(fd, CDROMMULTISESSION, &multisession) == 0 && multisession.xa_flag)
1220 blkid_probe_set_hint(pr, "session_offset", (multisession.addr.lba << 11));
1221 }
1222# endif
1223 }
1224 }
1225#endif
1226 free(dm_uuid);
1227
1228# ifdef BLKGETZONESZ
1229 if (S_ISBLK(sb.st_mode) && !is_floppy) {
1230 uint32_t zone_size_sector;
1231
1232 if (!ioctl(pr->fd, BLKGETZONESZ, &zone_size_sector))
1233 pr->zone_size = zone_size_sector << 9;
1234 }
1235# endif
1236
1237 if (S_ISBLK(sb.st_mode) && !is_floppy && !blkid_probe_is_tiny(pr))
1238 pr->io_size = blkid_get_io_size(fd);
1239
1240 DBG(LOWPROBE, ul_debug("ready for low-probing, offset=%"PRIu64", size=%"PRIu64", zonesize=%"PRIu64", iosize=%"PRIu64,
1241 pr->off, pr->size, pr->zone_size, pr->io_size));
1242 DBG(LOWPROBE, ul_debug("whole-disk: %s, regfile: %s",
1243 blkid_probe_is_wholedisk(pr) ?"YES" : "NO",
1244 S_ISREG(pr->mode) ? "YES" : "NO"));
1245
1246 return 0;
1247err:
1248 DBG(LOWPROBE, ul_debug("failed to prepare a device for low-probing"));
1249 return -1;
1250
1251}
1252
1253int blkid_probe_get_dimension(blkid_probe pr, uint64_t *off, uint64_t *size)
1254{
1255 *off = pr->off;
1256 *size = pr->size;
1257 return 0;
1258}
1259
1260int blkid_probe_set_dimension(blkid_probe pr, uint64_t off, uint64_t size)
1261{
1262 DBG(LOWPROBE, ul_debug(
1263 "changing probing area: size=%"PRIu64", off=%"PRIu64" "
1264 "-to-> size=%"PRIu64", off=%"PRIu64"",
1265 pr->size, pr->off, size, off));
1266
1267 pr->off = off;
1268 pr->size = size;
1269 pr->flags &= ~BLKID_FL_TINY_DEV;
1270
1271 if (pr->size <= 1440ULL * 1024ULL && !S_ISCHR(pr->mode))
1272 pr->flags |= BLKID_FL_TINY_DEV;
1273
1274 blkid_probe_reset_buffers(pr);
1275
1276 return 0;
1277}
1278
1279const unsigned char *blkid_probe_get_sb_buffer(blkid_probe pr, const struct blkid_idmag *mag, size_t size)
1280{
1281 uint64_t hint_offset, off;
1282
1283 if (mag->kboff >= 0) {
1284 if (!mag->hoff || blkid_probe_get_hint(pr, mag->hoff, &hint_offset) < 0)
1285 hint_offset = 0;
1286
1287 off = hint_offset + (mag->kboff << 10);
1288 } else {
1289 off = pr->size - (-mag->kboff << 10);
1290 }
1291
1292 return blkid_probe_get_buffer(pr, off, size);
1293}
1294
1295uint64_t blkid_probe_get_idmag_off(blkid_probe pr, const struct blkid_idmag *mag)
1296{
1297 if (mag->kboff >= 0)
1298 return mag->kboff << 10;
1299 else
1300 return pr->size - (-mag->kboff << 10);
1301}
1302
1303/*
1304 * Check for matching magic value.
1305 * Returns BLKID_PROBE_OK if found, BLKID_PROBE_NONE if not found
1306 * or no magic present, or negative value on error.
1307 */
1308int blkid_probe_get_idmag(blkid_probe pr, const struct blkid_idinfo *id,
1309 uint64_t *offset, const struct blkid_idmag **res)
1310{
1311 const struct blkid_idmag *mag = NULL;
1312 uint64_t off = 0;
1313
1314 if (id)
1315 mag = &id->magics[0];
1316 if (res)
1317 *res = NULL;
1318
1319 /* try to detect by magic string */
1320 while(mag && mag->magic) {
1321 const unsigned char *buf;
1322 long kboff;
1323 uint64_t hint_offset;
1324
1325 if (!mag->hoff || blkid_probe_get_hint(pr, mag->hoff, &hint_offset) < 0)
1326 hint_offset = 0;
1327
1328 /* If the magic is for zoned device, skip non-zoned device */
1329 if (mag->is_zoned && !pr->zone_size) {
1330 mag++;
1331 continue;
1332 }
1333
1334 if (!mag->is_zoned)
1335 kboff = mag->kboff;
1336 else
1337 kboff = ((mag->zonenum * pr->zone_size) >> 10) + mag->kboff_inzone;
1338
1339 if (kboff >= 0)
1340 off = hint_offset + (kboff << 10) + mag->sboff;
1341 else
1342 off = pr->size - (-kboff << 10) + mag->sboff;
1343 buf = blkid_probe_get_buffer(pr, off, mag->len);
1344
1345 if (!buf && errno)
1346 return -errno;
1347
1348 if (buf && !memcmp(mag->magic, buf, mag->len)) {
1349 DBG(LOWPROBE, ul_debug("\tmagic sboff=%u, kboff=%ld",
1350 mag->sboff, kboff));
1351 if (offset)
1352 *offset = off;
1353 if (res)
1354 *res = mag;
1355 return BLKID_PROBE_OK;
1356 }
1357 mag++;
1358 }
1359
1360 if (id && id->magics[0].magic)
1361 /* magic string(s) defined, but not found */
1362 return BLKID_PROBE_NONE;
1363
1364 return BLKID_PROBE_OK;
1365}
1366
1367static inline void blkid_probe_start(blkid_probe pr)
1368{
1369 DBG(LOWPROBE, ul_debug("start probe"));
1370 pr->cur_chain = NULL;
1371 pr->prob_flags = 0;
1372 blkid_probe_set_wiper(pr, 0, 0);
1373}
1374
1375static inline void blkid_probe_end(blkid_probe pr)
1376{
1377 DBG(LOWPROBE, ul_debug("end probe"));
1378 pr->cur_chain = NULL;
1379 pr->prob_flags = 0;
1380 blkid_probe_set_wiper(pr, 0, 0);
1381}
1382
1383/**
1384 * blkid_do_probe:
1385 * @pr: prober
1386 *
1387 * Calls probing functions in all enabled chains. The superblocks chain is
1388 * enabled by default. The blkid_do_probe() stores result from only one
1389 * probing function. It's necessary to call this routine in a loop to get
1390 * results from all probing functions in all chains. The probing is reset
1391 * by blkid_reset_probe() or by filter functions.
1392 *
1393 * This is string-based NAME=value interface only.
1394 *
1395 * <example>
1396 * <title>basic case - use the first result only</title>
1397 * <programlisting>
1398 * if (blkid_do_probe(pr) == BLKID_PROBE_OK) {
1399 * int nvals = blkid_probe_numof_values(pr);
1400 * for (n = 0; n < nvals; n++) {
1401 * if (blkid_probe_get_value(pr, n, &name, &data, &len) == 0)
1402 * printf("%s = %s\n", name, data);
1403 * }
1404 * }
1405 * </programlisting>
1406 * </example>
1407 *
1408 * <example>
1409 * <title>advanced case - probe for all signatures</title>
1410 * <programlisting>
1411 * while (blkid_do_probe(pr) == BLKID_PROBE_OK) {
1412 * int nvals = blkid_probe_numof_values(pr);
1413 * ...
1414 * }
1415 * </programlisting>
1416 * </example>
1417 *
1418 * See also blkid_reset_probe().
1419 *
1420 * Returns: 0 on success, 1 when probing is done and -1 in case of error.
1421 */
1422int blkid_do_probe(blkid_probe pr)
1423{
1424 int rc = 1;
1425
1426 if (pr->flags & BLKID_FL_NOSCAN_DEV)
1427 return BLKID_PROBE_NONE;
1428
1429 do {
1430 struct blkid_chain *chn = pr->cur_chain;
1431
1432 if (!chn) {
1433 blkid_probe_start(pr);
1434 chn = pr->cur_chain = &pr->chains[0];
1435 }
1436 /* we go to the next chain only when the previous probing
1437 * result was nothing (rc == 1) and when the current chain is
1438 * disabled or we are at end of the current chain (chain->idx +
1439 * 1 == sizeof chain) or the current chain bailed out right at
1440 * the start (chain->idx == -1)
1441 */
1442 else if (rc == 1 && (chn->enabled == FALSE ||
1443 chn->idx + 1 == (int) chn->driver->nidinfos ||
1444 chn->idx == -1)) {
1445
1446 size_t idx = chn->driver->id + 1;
1447
1448 if (idx < BLKID_NCHAINS)
1449 chn = pr->cur_chain = &pr->chains[idx];
1450 else {
1451 blkid_probe_end(pr);
1452 return BLKID_PROBE_NONE; /* all chains already probed */
1453 }
1454 }
1455
1456 chn->binary = FALSE; /* for sure... */
1457
1458 DBG(LOWPROBE, ul_debug("chain probe %s %s (idx=%d)",
1459 chn->driver->name,
1460 chn->enabled? "ENABLED" : "DISABLED",
1461 chn->idx));
1462
1463 if (!chn->enabled)
1464 continue;
1465
1466 /* rc: -1 = error, 0 = success, 1 = no result */
1467 rc = chn->driver->probe(pr, chn);
1468
1469 } while (rc == BLKID_PROBE_NONE);
1470
1471 if (rc < 0)
1472 return BLKID_PROBE_ERROR;
1473
1474 return rc;
1475}
1476
1477#ifdef HAVE_LINUX_BLKZONED_H
1478static int is_conventional(blkid_probe pr, uint64_t offset)
1479{
1480 struct blk_zone_report *rep = NULL;
1481 int ret;
1482 uint64_t zone_mask;
1483
1484 if (!pr->zone_size)
1485 return 1;
1486
1487 zone_mask = ~(pr->zone_size - 1);
1488 rep = blkdev_get_zonereport(blkid_probe_get_fd(pr),
1489 (offset & zone_mask) >> 9, 1);
1490 if (!rep)
1491 return -1;
1492
1493 if (rep->zones[0].type == BLK_ZONE_TYPE_CONVENTIONAL)
1494 ret = 1;
1495 else
1496 ret = 0;
1497
1498 free(rep);
1499
1500 return ret;
1501}
1502#else
1503static inline int is_conventional(blkid_probe pr __attribute__((__unused__)),
1504 uint64_t offset __attribute__((__unused__)))
1505{
1506 return 1;
1507}
1508#endif
1509
1510/**
1511 * blkid_do_wipe:
1512 * @pr: prober
1513 * @dryrun: if TRUE then don't touch the device.
1514 *
1515 * This function erases the current signature detected by @pr. The @pr has to
1516 * be open in O_RDWR mode, BLKID_SUBLKS_MAGIC or/and BLKID_PARTS_MAGIC flags
1517 * has to be enabled (if you want to erase also superblock with broken check
1518 * sums then use BLKID_SUBLKS_BADCSUM too).
1519 *
1520 * After successful signature removing the @pr prober will be moved one step
1521 * back and the next blkid_do_probe() call will again call previously called
1522 * probing function. All in-memory cached data from the device are always
1523 * reset.
1524 *
1525 * <example>
1526 * <title>wipe all filesystems or raids from the device</title>
1527 * <programlisting>
1528 * fd = open(devname, O_RDWR|O_CLOEXEC);
1529 * blkid_probe_set_device(pr, fd, 0, 0);
1530 *
1531 * blkid_probe_enable_superblocks(pr, 1);
1532 * blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_MAGIC);
1533 *
1534 * while (blkid_do_probe(pr) == 0)
1535 * blkid_do_wipe(pr, FALSE);
1536 * </programlisting>
1537 * </example>
1538 *
1539 * See also blkid_probe_step_back() if you cannot use this built-in wipe
1540 * function, but you want to use libblkid probing as a source for wiping.
1541 *
1542 * See also blkid_wipe_all() which works the same as the example above.
1543 *
1544 * Returns: 0 on success, and -1 in case of error.
1545 */
1546int blkid_do_wipe(blkid_probe pr, int dryrun)
1547{
1548 const char *off = NULL;
1549 size_t len = 0;
1550 uint64_t offset, magoff;
1551 int conventional;
1552 char buf[BUFSIZ];
1553 int fd, rc = 0;
1554 struct blkid_chain *chn;
1555
1556 chn = pr->cur_chain;
1557 if (!chn)
1558 return BLKID_PROBE_ERROR;
1559
1560 switch (chn->driver->id) {
1561 case BLKID_CHAIN_SUBLKS:
1562 rc = blkid_probe_lookup_value(pr, "SBMAGIC_OFFSET", &off, NULL);
1563 if (!rc)
1564 rc = blkid_probe_lookup_value(pr, "SBMAGIC", NULL, &len);
1565 break;
1566 case BLKID_CHAIN_PARTS:
1567 rc = blkid_probe_lookup_value(pr, "PTMAGIC_OFFSET", &off, NULL);
1568 if (!rc)
1569 rc = blkid_probe_lookup_value(pr, "PTMAGIC", NULL, &len);
1570 break;
1571 default:
1572 return BLKID_PROBE_OK;
1573 }
1574
1575 if (rc || len == 0 || off == NULL)
1576 return BLKID_PROBE_OK;
1577
1578 errno = 0;
1579 magoff = strtoumax(off, NULL, 10);
1580 if (errno)
1581 return BLKID_PROBE_OK;
1582
1583 offset = magoff + pr->off;
1584 fd = blkid_probe_get_fd(pr);
1585 if (fd < 0)
1586 return BLKID_PROBE_ERROR;
1587
1588 if (len > sizeof(buf))
1589 len = sizeof(buf);
1590
1591 rc = is_conventional(pr, offset);
1592 if (rc < 0)
1593 return BLKID_PROBE_ERROR;
1594 conventional = rc == 1;
1595
1596 DBG(LOWPROBE, ul_debug(
1597 "do_wipe [offset=0x%"PRIx64" (%"PRIu64"), len=%zu, chain=%s, idx=%d, dryrun=%s]\n",
1598 offset, offset, len, chn->driver->name, chn->idx, dryrun ? "yes" : "not"));
1599
1600 if (lseek(fd, offset, SEEK_SET) == (off_t) -1)
1601 return BLKID_PROBE_ERROR;
1602
1603 if (!dryrun && len) {
1604 if (conventional) {
1605 memset(buf, 0, len);
1606
1607 /* wipen on device */
1608 if (write_all(fd, buf, len))
1609 return BLKID_PROBE_ERROR;
1610 if (fsync(fd) != 0)
1611 return BLKID_PROBE_ERROR;
1612 } else {
1613#ifdef HAVE_LINUX_BLKZONED_H
1614 uint64_t zone_mask = ~(pr->zone_size - 1);
1615 struct blk_zone_range range = {
1616 .sector = (offset & zone_mask) >> 9,
1617 .nr_sectors = pr->zone_size >> 9,
1618 };
1619
1620 rc = ioctl(fd, BLKRESETZONE, &range);
1621 if (rc < 0)
1622 return BLKID_PROBE_ERROR;
1623#else
1624 /* Should not reach here */
1625 assert(0);
1626#endif
1627 }
1628
1629 pr->flags &= ~BLKID_FL_MODIF_BUFF; /* be paranoid */
1630
1631 return blkid_probe_step_back(pr);
1632
1633 }
1634
1635 if (dryrun) {
1636 /* wipe in memory only */
1637 blkid_probe_hide_range(pr, magoff, len);
1638 return blkid_probe_step_back(pr);
1639 }
1640
1641 return BLKID_PROBE_OK;
1642}
1643
1644/**
1645 * blkid_wipe_all:
1646 * @pr: prober
1647 *
1648 * This function erases all detectable signatures from &pr.
1649 * The @pr has to be open in O_RDWR mode. All other necessary configurations
1650 * will be enabled automatically.
1651 *
1652 * <example>
1653 * <title>wipe all filesystems or raids from the device</title>
1654 * <programlisting>
1655 * fd = open(devname, O_RDWR|O_CLOEXEC);
1656 * blkid_probe_set_device(pr, fd, 0, 0);
1657 *
1658 * blkid_wipe_all(pr);
1659 * </programlisting>
1660 * </example>
1661 *
1662 * Returns: 0 on success, and -1 in case of error.
1663 */
1664int blkid_wipe_all(blkid_probe pr)
1665{
1666 DBG(LOWPROBE, ul_debug("wiping all signatures"));
1667
1668 blkid_probe_enable_superblocks(pr, 1);
1669 blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_MAGIC |
1670 BLKID_SUBLKS_BADCSUM);
1671
1672 blkid_probe_enable_partitions(pr, 1);
1673 blkid_probe_set_partitions_flags(pr, BLKID_PARTS_MAGIC |
1674 BLKID_PARTS_FORCE_GPT);
1675
1676 while (blkid_do_probe(pr) == 0) {
1677 DBG(LOWPROBE, ul_debug("wiping one signature"));
1678 blkid_do_wipe(pr, 0);
1679 }
1680
1681 return BLKID_PROBE_OK;
1682}
1683
1684/**
1685 * blkid_probe_step_back:
1686 * @pr: prober
1687 *
1688 * This function move pointer to the probing chain one step back -- it means
1689 * that the previously used probing function will be called again in the next
1690 * blkid_do_probe() call.
1691 *
1692 * This is necessary for example if you erase or modify on-disk superblock
1693 * according to the current libblkid probing result.
1694 *
1695 * Note that blkid_probe_hide_range() changes semantic of this function and
1696 * cached buffers are not reset, but library uses in-memory modified
1697 * buffers to call the next probing function.
1698 *
1699 * <example>
1700 * <title>wipe all superblock, but use libblkid only for probing</title>
1701 * <programlisting>
1702 * pr = blkid_new_probe_from_filename(devname);
1703 *
1704 * blkid_probe_enable_superblocks(pr, 1);
1705 * blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_MAGIC);
1706 *
1707 * blkid_probe_enable_partitions(pr, 1);
1708 * blkid_probe_set_partitions_flags(pr, BLKID_PARTS_MAGIC);
1709 *
1710 * while (blkid_do_probe(pr) == BLKID_PROBE_OK) {
1711 * const char *ostr = NULL;
1712 * size_t len = 0;
1713 *
1714 * // superblocks
1715 * if (blkid_probe_lookup_value(pr, "SBMAGIC_OFFSET", &ostr, NULL) == 0)
1716 * blkid_probe_lookup_value(pr, "SBMAGIC", NULL, &len);
1717 *
1718 * // partition tables
1719 * if (len == 0 && blkid_probe_lookup_value(pr, "PTMAGIC_OFFSET", &ostr, NULL) == 0)
1720 * blkid_probe_lookup_value(pr, "PTMAGIC", NULL, &len);
1721 *
1722 * if (!len || !str)
1723 * continue;
1724 *
1725 * // convert ostr to the real offset by off = strtoll(ostr, NULL, 10);
1726 * // use your stuff to erase @len bytes at the @off
1727 * ....
1728 *
1729 * // retry the last probing to check for backup superblocks ..etc.
1730 * blkid_probe_step_back(pr);
1731 * }
1732 * </programlisting>
1733 * </example>
1734 *
1735 * Returns: 0 on success, and -1 in case of error.
1736 */
1737int blkid_probe_step_back(blkid_probe pr)
1738{
1739 struct blkid_chain *chn;
1740
1741 chn = pr->cur_chain;
1742 if (!chn)
1743 return -1;
1744
1745 if (!(pr->flags & BLKID_FL_MODIF_BUFF))
1746 blkid_probe_reset_buffers(pr);
1747
1748 if (chn->idx >= 0) {
1749 chn->idx--;
1750 DBG(LOWPROBE, ul_debug("step back: moving %s chain index to %d",
1751 chn->driver->name,
1752 chn->idx));
1753 }
1754
1755 if (chn->idx == -1) {
1756 /* blkid_do_probe() goes to the next chain if the index
1757 * of the current chain is -1, so we have to set the
1758 * chain pointer to the previous chain.
1759 */
1760 size_t idx = chn->driver->id > 0 ? chn->driver->id - 1 : 0;
1761
1762 DBG(LOWPROBE, ul_debug("step back: moving to previous chain"));
1763
1764 if (idx > 0)
1765 pr->cur_chain = &pr->chains[idx];
1766 else if (idx == 0)
1767 pr->cur_chain = NULL;
1768 }
1769
1770 return 0;
1771}
1772
1773/**
1774 * blkid_do_safeprobe:
1775 * @pr: prober
1776 *
1777 * This function gathers probing results from all enabled chains and checks
1778 * for ambivalent results (e.g. more filesystems on the device).
1779 *
1780 * This is string-based NAME=value interface only.
1781 *
1782 * Note about superblocks chain -- the function does not check for filesystems
1783 * when a RAID signature is detected. The function also does not check for
1784 * collision between RAIDs. The first detected RAID is returned. The function
1785 * checks for collision between partition table and RAID signature -- it's
1786 * recommended to enable partitions chain together with superblocks chain.
1787 *
1788 * Returns: 0 on success, 1 if nothing is detected, -2 if ambivalent result is
1789 * detected and -1 on case of error.
1790 */
1791int blkid_do_safeprobe(blkid_probe pr)
1792{
1793 int i, count = 0, rc = 0;
1794
1795 if (pr->flags & BLKID_FL_NOSCAN_DEV)
1796 return BLKID_PROBE_NONE;
1797
1798 blkid_probe_start(pr);
1799
1800 for (i = 0; i < BLKID_NCHAINS; i++) {
1801 struct blkid_chain *chn;
1802
1803 chn = pr->cur_chain = &pr->chains[i];
1804 chn->binary = FALSE; /* for sure... */
1805
1806 DBG(LOWPROBE, ul_debug("chain safeprobe %s %s",
1807 chn->driver->name,
1808 chn->enabled? "ENABLED" : "DISABLED"));
1809
1810 if (!chn->enabled)
1811 continue;
1812
1813 blkid_probe_chain_reset_position(chn);
1814
1815 rc = chn->driver->safeprobe(pr, chn);
1816
1817 blkid_probe_chain_reset_position(chn);
1818
1819 /* rc: -2 ambivalent, -1 = error, 0 = success, 1 = no result */
1820 if (rc < 0)
1821 goto done; /* error */
1822 if (rc == 0)
1823 count++; /* success */
1824 }
1825
1826done:
1827 blkid_probe_end(pr);
1828 if (rc < 0)
1829 return BLKID_PROBE_ERROR;
1830
1831 return count == 0 ? BLKID_PROBE_NONE : BLKID_PROBE_OK;
1832}
1833
1834/**
1835 * blkid_do_fullprobe:
1836 * @pr: prober
1837 *
1838 * This function gathers probing results from all enabled chains. Same as
1839 * blkid_do_safeprobe() but does not check for collision between probing
1840 * result.
1841 *
1842 * This is string-based NAME=value interface only.
1843 *
1844 * Returns: 0 on success, 1 if nothing is detected or -1 on case of error.
1845 */
1846int blkid_do_fullprobe(blkid_probe pr)
1847{
1848 int i, count = 0, rc = 0;
1849
1850 if (pr->flags & BLKID_FL_NOSCAN_DEV)
1851 return BLKID_PROBE_NONE;
1852
1853 blkid_probe_start(pr);
1854
1855 for (i = 0; i < BLKID_NCHAINS; i++) {
1856 struct blkid_chain *chn;
1857
1858 chn = pr->cur_chain = &pr->chains[i];
1859 chn->binary = FALSE; /* for sure... */
1860
1861 DBG(LOWPROBE, ul_debug("chain fullprobe %s: %s",
1862 chn->driver->name,
1863 chn->enabled? "ENABLED" : "DISABLED"));
1864
1865 if (!chn->enabled)
1866 continue;
1867
1868 blkid_probe_chain_reset_position(chn);
1869
1870 rc = chn->driver->probe(pr, chn);
1871
1872 blkid_probe_chain_reset_position(chn);
1873
1874 /* rc: -1 = error, 0 = success, 1 = no result */
1875 if (rc < 0)
1876 goto done; /* error */
1877 if (rc == 0)
1878 count++; /* success */
1879 }
1880
1881done:
1882 blkid_probe_end(pr);
1883 if (rc < 0)
1884 return BLKID_PROBE_ERROR;
1885
1886 return count == 0 ? BLKID_PROBE_NONE : BLKID_PROBE_OK;
1887}
1888
1889/* same sa blkid_probe_get_buffer() but works with 512-sectors */
1890const unsigned char *blkid_probe_get_sector(blkid_probe pr, unsigned int sector)
1891{
1892 return blkid_probe_get_buffer(pr, ((uint64_t) sector) << 9, 0x200);
1893}
1894
1895struct blkid_prval *blkid_probe_assign_value(blkid_probe pr, const char *name)
1896{
1897 struct blkid_prval *v;
1898
1899 v = calloc(1, sizeof(struct blkid_prval));
1900 if (!v)
1901 return NULL;
1902
1903 INIT_LIST_HEAD(&v->prvals);
1904 v->name = name;
1905 v->chain = pr->cur_chain;
1906 list_add_tail(&v->prvals, &pr->values);
1907
1908 DBG(LOWPROBE, ul_debug("assigning %s [%s]", name, v->chain->driver->name));
1909 return v;
1910}
1911
1912/* Note that value data is always terminated by zero to keep things robust,
1913 * this extra zero is not count to the value length. It's caller responsibility
1914 * to set proper value length (for strings we count terminator to the length,
1915 * for binary data it's without terminator).
1916 */
1917int blkid_probe_value_set_data(struct blkid_prval *v,
1918 const unsigned char *data, size_t len)
1919{
1920 v->data = calloc(1, len + 1); /* always terminate by \0 */
1921
1922 if (!v->data)
1923 return -ENOMEM;
1924 memcpy(v->data, data, len);
1925 v->len = len;
1926 return 0;
1927}
1928
1929int blkid_probe_set_value(blkid_probe pr, const char *name,
1930 const unsigned char *data, size_t len)
1931{
1932 struct blkid_prval *v;
1933
1934 v = blkid_probe_assign_value(pr, name);
1935 if (!v)
1936 return -1;
1937
1938 return blkid_probe_value_set_data(v, data, len);
1939}
1940
1941int blkid_probe_vsprintf_value(blkid_probe pr, const char *name,
1942 const char *fmt, va_list ap)
1943{
1944 struct blkid_prval *v;
1945 ssize_t len;
1946
1947 v = blkid_probe_assign_value(pr, name);
1948 if (!v)
1949 return -ENOMEM;
1950
1951 len = vasprintf((char **) &v->data, fmt, ap);
1952
1953 if (len <= 0) {
1954 blkid_probe_free_value(v);
1955 return len == 0 ? -EINVAL : -ENOMEM;
1956 }
1957 v->len = len + 1;
1958 return 0;
1959}
1960
1961int blkid_probe_sprintf_value(blkid_probe pr, const char *name,
1962 const char *fmt, ...)
1963{
1964 int rc;
1965 va_list ap;
1966
1967 va_start(ap, fmt);
1968 rc = blkid_probe_vsprintf_value(pr, name, fmt, ap);
1969 va_end(ap);
1970
1971 return rc;
1972}
1973
1974int blkid_probe_set_magic(blkid_probe pr, uint64_t offset,
1975 size_t len, const unsigned char *magic)
1976{
1977 int rc = 0;
1978 struct blkid_chain *chn = blkid_probe_get_chain(pr);
1979
1980 if (!chn || !len || chn->binary)
1981 return 0;
1982
1983 switch (chn->driver->id) {
1984 case BLKID_CHAIN_SUBLKS:
1985 if (!(chn->flags & BLKID_SUBLKS_MAGIC))
1986 return 0;
1987 rc = blkid_probe_set_value(pr, "SBMAGIC", magic, len);
1988 if (!rc)
1989 rc = blkid_probe_sprintf_value(pr,
1990 "SBMAGIC_OFFSET", "%llu", (unsigned long long)offset);
1991 break;
1992 case BLKID_CHAIN_PARTS:
1993 if (!(chn->flags & BLKID_PARTS_MAGIC))
1994 return 0;
1995 rc = blkid_probe_set_value(pr, "PTMAGIC", magic, len);
1996 if (!rc)
1997 rc = blkid_probe_sprintf_value(pr,
1998 "PTMAGIC_OFFSET", "%llu", (unsigned long long)offset);
1999 break;
2000 default:
2001 break;
2002 }
2003
2004 return rc;
2005}
2006
2007static void blkid_probe_log_csum_mismatch(blkid_probe pr, size_t n, const void *csum,
2008 const void *expected)
2009{
2010 char csum_hex[256];
2011 char expected_hex[sizeof(csum_hex)];
2012 int hex_size = min(sizeof(csum_hex), n * 2);
2013
2014 for (int i = 0; i < hex_size; i+=2) {
2015 sprintf(&csum_hex[i], "%02X", ((const unsigned char *) csum)[i / 2]);
2016 sprintf(&expected_hex[i], "%02X", ((const unsigned char *) expected)[i / 2]);
2017 }
2018
2019 DBG(LOWPROBE, ul_debug(
2020 "incorrect checksum for type %s,"
2021 " got %*s, expected %*s",
2022 blkid_probe_get_probername(pr),
2023 hex_size, csum_hex, hex_size, expected_hex));
2024}
2025
2026
2027int blkid_probe_verify_csum_buf(blkid_probe pr, size_t n, const void *csum,
2028 const void *expected)
2029{
2030 if (memcmp(csum, expected, n) != 0) {
2031 struct blkid_chain *chn = blkid_probe_get_chain(pr);
2032
2033 ON_DBG(LOWPROBE, blkid_probe_log_csum_mismatch(pr, n, csum, expected));
2034
2035 /*
2036 * Accept bad checksum if BLKID_SUBLKS_BADCSUM flags is set
2037 */
2038 if (chn && chn->driver->id == BLKID_CHAIN_SUBLKS
2039 && (chn->flags & BLKID_SUBLKS_BADCSUM)) {
2040 blkid_probe_set_value(pr, "SBBADCSUM", (unsigned char *) "1", 2);
2041 goto accept;
2042 }
2043 return 0; /* bad checksum */
2044 }
2045
2046accept:
2047 return 1;
2048}
2049
2050int blkid_probe_verify_csum(blkid_probe pr, uint64_t csum, uint64_t expected)
2051{
2052 return blkid_probe_verify_csum_buf(pr, sizeof(csum), &csum, &expected);
2053}
2054
2055/**
2056 * blkid_probe_get_devno:
2057 * @pr: probe
2058 *
2059 * Returns: block device number, or 0 for regular files.
2060 */
2061dev_t blkid_probe_get_devno(blkid_probe pr)
2062{
2063 return pr->devno;
2064}
2065
2066/**
2067 * blkid_probe_get_wholedisk_devno:
2068 * @pr: probe
2069 *
2070 * Returns: device number of the wholedisk, or 0 for regular files.
2071 */
2072dev_t blkid_probe_get_wholedisk_devno(blkid_probe pr)
2073{
2074 if (!pr->disk_devno) {
2075 dev_t devno, disk_devno = 0;
2076
2077 devno = blkid_probe_get_devno(pr);
2078 if (!devno)
2079 return 0;
2080
2081 if (blkid_devno_to_wholedisk(devno, NULL, 0, &disk_devno) == 0)
2082 pr->disk_devno = disk_devno;
2083 }
2084 return pr->disk_devno;
2085}
2086
2087/**
2088 * blkid_probe_is_wholedisk:
2089 * @pr: probe
2090 *
2091 * Returns: 1 if the device is whole-disk or 0.
2092 */
2093int blkid_probe_is_wholedisk(blkid_probe pr)
2094{
2095 dev_t devno, disk_devno;
2096
2097 devno = blkid_probe_get_devno(pr);
2098 if (!devno)
2099 return 0;
2100
2101 disk_devno = blkid_probe_get_wholedisk_devno(pr);
2102 if (!disk_devno)
2103 return 0;
2104
2105 return devno == disk_devno;
2106}
2107
2108blkid_probe blkid_probe_get_wholedisk_probe(blkid_probe pr)
2109{
2110 dev_t disk;
2111
2112 if (blkid_probe_is_wholedisk(pr))
2113 return NULL; /* this is not partition */
2114
2115 if (pr->parent)
2116 /* this is cloned blkid_probe, use parent's stuff */
2117 return blkid_probe_get_wholedisk_probe(pr->parent);
2118
2119 disk = blkid_probe_get_wholedisk_devno(pr);
2120
2121 if (pr->disk_probe && pr->disk_probe->devno != disk) {
2122 /* we have disk prober, but for another disk... close it */
2123 blkid_free_probe(pr->disk_probe);
2124 pr->disk_probe = NULL;
2125 }
2126
2127 if (!pr->disk_probe) {
2128 /* Open a new disk prober */
2129 char *disk_path = blkid_devno_to_devname(disk);
2130 int flags;
2131
2132 if (!disk_path)
2133 return NULL;
2134
2135 DBG(LOWPROBE, ul_debug("allocate a wholedisk probe"));
2136
2137 pr->disk_probe = blkid_new_probe_from_filename(disk_path);
2138
2139 free(disk_path);
2140
2141 if (!pr->disk_probe)
2142 return NULL; /* ENOMEM? */
2143
2144 flags = blkid_probe_get_partitions_flags(pr);
2145 if (flags & BLKID_PARTS_FORCE_GPT)
2146 blkid_probe_set_partitions_flags(pr->disk_probe,
2147 BLKID_PARTS_FORCE_GPT);
2148 }
2149
2150 return pr->disk_probe;
2151}
2152
2153/**
2154 * blkid_probe_get_size:
2155 * @pr: probe
2156 *
2157 * This function returns size of probing area as defined by blkid_probe_set_device().
2158 * If the size of the probing area is unrestricted then this function returns
2159 * the real size of device. See also blkid_get_dev_size().
2160 *
2161 * Returns: size in bytes or -1 in case of error.
2162 */
2163blkid_loff_t blkid_probe_get_size(blkid_probe pr)
2164{
2165 return (blkid_loff_t) pr->size;
2166}
2167
2168/**
2169 * blkid_probe_get_offset:
2170 * @pr: probe
2171 *
2172 * This function returns offset of probing area as defined by blkid_probe_set_device().
2173 *
2174 * Returns: offset in bytes or -1 in case of error.
2175 */
2176blkid_loff_t blkid_probe_get_offset(blkid_probe pr)
2177{
2178 return (blkid_loff_t) pr->off;
2179}
2180
2181/**
2182 * blkid_probe_get_fd:
2183 * @pr: probe
2184 *
2185 * Returns: file descriptor for assigned device/file or -1 in case of error.
2186 */
2187int blkid_probe_get_fd(blkid_probe pr)
2188{
2189 return pr->fd;
2190}
2191
2192/**
2193 * blkid_probe_get_sectorsize:
2194 * @pr: probe or NULL (for NULL returns 512)
2195 *
2196 * Returns: block device logical sector size (BLKSSZGET ioctl, default 512).
2197 */
2198unsigned int blkid_probe_get_sectorsize(blkid_probe pr)
2199{
2200 if (pr->blkssz)
2201 return pr->blkssz;
2202
2203 if (S_ISBLK(pr->mode) &&
2204 blkdev_get_sector_size(pr->fd, (int *) &pr->blkssz) == 0)
2205 return pr->blkssz;
2206
2207 pr->blkssz = DEFAULT_SECTOR_SIZE;
2208 return pr->blkssz;
2209}
2210
2211/**
2212 * blkid_probe_set_sectorsize:
2213 * @pr: probe
2214 * @sz: new size (to overwrite system default)
2215 *
2216 * Note that blkid_probe_set_device() resets this setting. Use it after
2217 * blkid_probe_set_device() and before any probing call.
2218 *
2219 * Since: 2.30
2220 *
2221 * Returns: 0 or <0 in case of error
2222 */
2223int blkid_probe_set_sectorsize(blkid_probe pr, unsigned int sz)
2224{
2225 pr->blkssz = sz;
2226 return 0;
2227}
2228
2229/**
2230 * blkid_probe_get_sectors:
2231 * @pr: probe
2232 *
2233 * Returns: 512-byte sector count or -1 in case of error.
2234 */
2235blkid_loff_t blkid_probe_get_sectors(blkid_probe pr)
2236{
2237 return (blkid_loff_t) (pr->size >> 9);
2238}
2239
2240/**
2241 * blkid_probe_numof_values:
2242 * @pr: probe
2243 *
2244 * Returns: number of values in probing result or -1 in case of error.
2245 */
2246int blkid_probe_numof_values(blkid_probe pr)
2247{
2248 int i = 0;
2249 struct list_head *p;
2250
2251 list_for_each(p, &pr->values)
2252 ++i;
2253 return i;
2254}
2255
2256/**
2257 * blkid_probe_get_value:
2258 * @pr: probe
2259 * @num: wanted value in range 0..N, where N is blkid_probe_numof_values() - 1
2260 * @name: pointer to return value name or NULL
2261 * @data: pointer to return value data or NULL
2262 * @len: pointer to return value length or NULL
2263 *
2264 * Note, the @len returns length of the @data, including the terminating
2265 * '\0' character.
2266 *
2267 * Returns: 0 on success, or -1 in case of error.
2268 */
2269int blkid_probe_get_value(blkid_probe pr, int num, const char **name,
2270 const char **data, size_t *len)
2271{
2272 struct blkid_prval *v = __blkid_probe_get_value(pr, num);
2273
2274 if (!v)
2275 return -1;
2276 if (name)
2277 *name = v->name;
2278 if (data)
2279 *data = (char *) v->data;
2280 if (len)
2281 *len = v->len;
2282
2283 DBG(LOWPROBE, ul_debug("returning %s value", v->name));
2284 return 0;
2285}
2286
2287/**
2288 * blkid_probe_lookup_value:
2289 * @pr: probe
2290 * @name: name of value
2291 * @data: pointer to return value data or NULL
2292 * @len: pointer to return value length or NULL
2293 *
2294 * Note, the @len returns length of the @data, including the terminating
2295 * '\0' character.
2296 *
2297 * Returns: 0 on success, or -1 in case of error.
2298 */
2299int blkid_probe_lookup_value(blkid_probe pr, const char *name,
2300 const char **data, size_t *len)
2301{
2302 struct blkid_prval *v = __blkid_probe_lookup_value(pr, name);
2303
2304 if (!v)
2305 return -1;
2306 if (data)
2307 *data = (char *) v->data;
2308 if (len)
2309 *len = v->len;
2310 return 0;
2311}
2312
2313/**
2314 * blkid_probe_has_value:
2315 * @pr: probe
2316 * @name: name of value
2317 *
2318 * Returns: 1 if value exist in probing result, otherwise 0.
2319 */
2320int blkid_probe_has_value(blkid_probe pr, const char *name)
2321{
2322 if (blkid_probe_lookup_value(pr, name, NULL, NULL) == 0)
2323 return 1;
2324 return 0;
2325}
2326
2327struct blkid_prval *__blkid_probe_get_value(blkid_probe pr, int num)
2328{
2329 int i = 0;
2330 struct list_head *p;
2331
2332 if (num < 0)
2333 return NULL;
2334
2335 list_for_each(p, &pr->values) {
2336 if (i++ != num)
2337 continue;
2338 return list_entry(p, struct blkid_prval, prvals);
2339 }
2340 return NULL;
2341}
2342
2343struct blkid_prval *__blkid_probe_lookup_value(blkid_probe pr, const char *name)
2344{
2345 struct list_head *p;
2346
2347 if (list_empty(&pr->values))
2348 return NULL;
2349
2350 list_for_each(p, &pr->values) {
2351 struct blkid_prval *v = list_entry(p, struct blkid_prval,
2352 prvals);
2353
2354 if (v->name && strcmp(name, v->name) == 0) {
2355 DBG(LOWPROBE, ul_debug("returning %s value", v->name));
2356 return v;
2357 }
2358 }
2359 return NULL;
2360}
2361
2362
2363/* converts DCE UUID (uuid[16]) to human readable string
2364 * - the @len should be always 37 */
2365void blkid_unparse_uuid(const unsigned char *uuid, char *str, size_t len)
2366{
2367 snprintf(str, len,
2368 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
2369 uuid[0], uuid[1], uuid[2], uuid[3],
2370 uuid[4], uuid[5],
2371 uuid[6], uuid[7],
2372 uuid[8], uuid[9],
2373 uuid[10], uuid[11], uuid[12], uuid[13], uuid[14],uuid[15]);
2374}
2375
2376/* like uuid_is_null() from libuuid, but works with arbitrary size of UUID */
2377int blkid_uuid_is_empty(const unsigned char *buf, size_t len)
2378{
2379 size_t i;
2380
2381 for (i = 0; i < len; i++)
2382 if (buf[i])
2383 return 0;
2384 return 1;
2385}
2386
2387/* Removes whitespace from the right-hand side of a string (trailing
2388 * whitespace).
2389 *
2390 * Returns size of the new string (without \0).
2391 */
2392size_t blkid_rtrim_whitespace(unsigned char *str)
2393{
2394 return rtrim_whitespace(str);
2395}
2396
2397/* Removes whitespace from the left-hand side of a string.
2398 *
2399 * Returns size of the new string (without \0).
2400 */
2401size_t blkid_ltrim_whitespace(unsigned char *str)
2402{
2403 return ltrim_whitespace(str);
2404}
2405
2406/*
2407 * Some mkfs-like utils wipe some parts (usually begin) of the device.
2408 * For example LVM (pvcreate) or mkswap(8). This information could be used
2409 * for later resolution to conflicts between superblocks.
2410 *
2411 * For example we found valid LVM superblock, LVM wipes 8KiB at the begin of
2412 * the device. If we found another signature (for example MBR) within the
2413 * wiped area then the signature has been added later and LVM superblock
2414 * should be ignore.
2415 *
2416 * Note that this heuristic is not 100% reliable, for example "pvcreate --zero n"
2417 * can be used to keep the begin of the device unmodified. It's probably better
2418 * to use this heuristic for conflicts between superblocks and partition tables
2419 * than for conflicts between filesystem superblocks -- existence of unwanted
2420 * partition table is very unusual, because PT is pretty visible (parsed and
2421 * interpreted by kernel).
2422 *
2423 * Note that we usually expect only one signature on the device, it means that
2424 * we have to remember only one wiped area from previously successfully
2425 * detected signature.
2426 *
2427 * blkid_probe_set_wiper() -- defines wiped area (e.g. LVM)
2428 * blkid_probe_use_wiper() -- try to use area (e.g. MBR)
2429 *
2430 * Note that there is not relation between _wiper and blkid_to_wipe().
2431 *
2432 */
2433void blkid_probe_set_wiper(blkid_probe pr, uint64_t off, uint64_t size)
2434{
2435 struct blkid_chain *chn;
2436
2437 if (!size) {
2438 DBG(LOWPROBE, ul_debug("zeroize wiper"));
2439 pr->wipe_size = pr->wipe_off = 0;
2440 pr->wipe_chain = NULL;
2441 return;
2442 }
2443
2444 chn = pr->cur_chain;
2445
2446 if (!chn || !chn->driver ||
2447 chn->idx < 0 || (size_t) chn->idx >= chn->driver->nidinfos)
2448 return;
2449
2450 pr->wipe_size = size;
2451 pr->wipe_off = off;
2452 pr->wipe_chain = chn;
2453
2454 DBG(LOWPROBE,
2455 ul_debug("wiper set to %s::%s off=%"PRIu64" size=%"PRIu64"",
2456 chn->driver->name,
2457 chn->driver->idinfos[chn->idx]->name,
2458 pr->wipe_off, pr->wipe_size));
2459}
2460
2461/*
2462 * Returns 1 if the <@off,@size> area was wiped
2463 */
2464int blkid_probe_is_wiped(blkid_probe pr, struct blkid_chain **chn, uint64_t off, uint64_t size)
2465{
2466 if (!size)
2467 return 0;
2468
2469 if (pr->wipe_off <= off && off + size <= pr->wipe_off + pr->wipe_size) {
2470 *chn = pr->wipe_chain;
2471 return 1;
2472 }
2473 return 0;
2474}
2475
2476/*
2477 * Try to use any area -- if the area has been previously wiped then the
2478 * previous probing result should be ignored (reset).
2479 */
2480void blkid_probe_use_wiper(blkid_probe pr, uint64_t off, uint64_t size)
2481{
2482 struct blkid_chain *chn = NULL;
2483
2484 if (blkid_probe_is_wiped(pr, &chn, off, size) && chn) {
2485 DBG(LOWPROBE, ul_debug("previously wiped area modified "
2486 " -- ignore previous results"));
2487 blkid_probe_set_wiper(pr, 0, 0);
2488 blkid_probe_chain_reset_values(pr, chn);
2489 }
2490}
2491
2492static struct blkid_hint *get_hint(blkid_probe pr, const char *name)
2493{
2494 struct list_head *p;
2495
2496 if (list_empty(&pr->hints))
2497 return NULL;
2498
2499 list_for_each(p, &pr->hints) {
2500 struct blkid_hint *h = list_entry(p, struct blkid_hint, hints);
2501
2502 if (h->name && strcmp(name, h->name) == 0)
2503 return h;
2504 }
2505 return NULL;
2506}
2507
2508/**
2509 * blkid_probe_set_hint:
2510 * @pr: probe
2511 * @name: hint name or NAME=value
2512 * @value: offset or another number
2513 *
2514 * Sets extra hint for low-level prober. If the hint is set by NAME=value
2515 * notation than @value is ignored. The functions blkid_probe_set_device()
2516 * and blkid_reset_probe() resets all hints.
2517 *
2518 * The hints are optional way how to force libblkid probing functions to check
2519 * for example another location.
2520 *
2521 * Returns: 0 on success, or -1 in case of error.
2522 */
2523int blkid_probe_set_hint(blkid_probe pr, const char *name, uint64_t value)
2524{
2525 struct blkid_hint *hint = NULL;
2526 char *n = NULL, *v = NULL;
2527
2528 if (strchr(name, '=')) {
2529 char *end = NULL;
2530
2531 if (blkid_parse_tag_string(name, &n, &v) != 0)
2532 goto done;
2533
2534 errno = 0;
2535 value = strtoumax(v, &end, 10);
2536
2537 if (errno || v == end || (end && *end))
2538 goto done;
2539 }
2540
2541 hint = get_hint(pr, n ? n : name);
2542 if (hint) {
2543 /* alter old hint */
2544 hint->value = value;
2545 DBG(LOWPROBE,
2546 ul_debug("updated hint '%s' to %"PRIu64"", hint->name, hint->value));
2547 } else {
2548 /* add a new hint */
2549 if (!n) {
2550 n = strdup(name);
2551 if (!n)
2552 goto done;
2553 }
2554 hint = malloc(sizeof(*hint));
2555 if (!hint)
2556 goto done;
2557
2558 hint->name = n;
2559 hint->value = value;
2560
2561 INIT_LIST_HEAD(&hint->hints);
2562 list_add_tail(&hint->hints, &pr->hints);
2563
2564 DBG(LOWPROBE,
2565 ul_debug("new hint '%s' is %"PRIu64"", hint->name, hint->value));
2566 n = NULL;
2567 }
2568done:
2569 free(n);
2570 free(v);
2571
2572 if (!hint)
2573 return errno ? -errno : -EINVAL;
2574 return 0;
2575}
2576
2577int blkid_probe_get_hint(blkid_probe pr, const char *name, uint64_t *value)
2578{
2579 struct blkid_hint *h = get_hint(pr, name);
2580
2581 if (!h)
2582 return -EINVAL;
2583 if (value)
2584 *value = h->value;
2585 return 0;
2586}
2587
2588/**
2589 * blkid_probe_reset_hints:
2590 * @pr: probe
2591 *
2592 * Removes all previously defined probinig hints. See also blkid_probe_set_hint().
2593 */
2594void blkid_probe_reset_hints(blkid_probe pr)
2595{
2596 if (list_empty(&pr->hints))
2597 return;
2598
2599 DBG(LOWPROBE, ul_debug("resetting hints"));
2600
2601 while (!list_empty(&pr->hints)) {
2602 struct blkid_hint *h = list_entry(pr->hints.next,
2603 struct blkid_hint, hints);
2604 list_del(&h->hints);
2605 free(h->name);
2606 free(h);
2607 }
2608
2609 INIT_LIST_HEAD(&pr->hints);
2610}