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