Coverage Report

Created: 2025-12-14 06:35

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