Coverage Report

Created: 2026-06-30 06:41

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