Coverage Report

Created: 2026-07-16 06:59

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