Coverage Report

Created: 2024-05-21 06:33

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