Coverage Report

Created: 2026-04-11 06:29

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