2
* probe.c - reads tags (LABEL, UUID, FS type, ..) from a block device
4
* Copyright (C) 2008 Karel Zak <kzak@redhat.com>
6
* This file may be redistributed under the terms of the
7
* GNU Lesser General Public License.
16
#include <sys/types.h>
17
#ifdef HAVE_SYS_STAT_H
20
#ifdef HAVE_SYS_MKDEV_H
21
#include <sys/mkdev.h>
30
# ifdef HAVE_UUID_UUID_H
31
# include <uuid/uuid.h>
39
#include "probers/probers.h"
41
static const struct blkid_idinfo *idinfos[] =
99
# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
102
/* filter bitmap macros */
103
#define blkid_bmp_wordsize (8 * sizeof(unsigned long))
104
#define blkid_bmp_idx_bit(item) (1UL << ((item) % blkid_bmp_wordsize))
105
#define blkid_bmp_idx_byte(item) ((item) / blkid_bmp_wordsize)
107
#define blkid_bmp_set_item(bmp, item) \
108
((bmp)[ blkid_bmp_idx_byte(item) ] |= blkid_bmp_idx_bit(item))
110
#define blkid_bmp_unset_item(bmp, item) \
111
((bmp)[ bmp_idx_byte(item) ] &= ~bmp_idx_bit(item))
113
#define blkid_bmp_get_item(bmp, item) \
114
((bmp)[ blkid_bmp_idx_byte(item) ] & blkid_bmp_idx_bit(item))
116
#define blkid_bmp_size(max_items) \
117
(((max_items) + blkid_bmp_wordsize) / blkid_bmp_wordsize)
119
#define BLKID_FLTR_ITEMS ARRAY_SIZE(idinfos)
120
#define BLKID_FLTR_SIZE blkid_bmp_size(BLKID_FLTR_ITEMS)
123
static int blkid_probe_set_usage(blkid_probe pr, int usage);
125
int blkid_known_fstype(const char *fstype)
132
for (i = 0; i < ARRAY_SIZE(idinfos); i++) {
133
const struct blkid_idinfo *id = idinfos[i];
134
if (strcmp(id->name, fstype) == 0)
141
* Returns a pointer to the newly allocated probe struct
143
blkid_probe blkid_new_probe(void)
146
return calloc(1, sizeof(struct blkid_struct_probe));
150
* Deallocates probe struct, buffers and all allocated
151
* data that are associated with this probing control struct.
153
void blkid_free_probe(blkid_probe pr)
163
static void blkid_probe_reset_vals(blkid_probe pr)
165
memset(pr->vals, 0, sizeof(pr->vals));
169
static void blkid_probe_reset_idx(blkid_probe pr)
174
void blkid_reset_probe(blkid_probe pr)
178
DBG(DEBUG_LOWPROBE, printf("reseting blkid_probe\n"));
180
memset(pr->buf, 0, pr->buf_max);
184
memset(pr->sbbuf, 0, BLKID_SB_BUFSIZ);
186
blkid_probe_reset_vals(pr);
187
blkid_probe_reset_idx(pr);
191
* Note that we have two offsets:
193
* 1/ general device offset (pr->off), that's useful for example when we
194
* probe a partition from whole disk image:
195
* blkid-low --offset <partition_position> disk.img
197
* 2/ buffer offset (the 'off' argument), that useful for offsets in
200
* That means never use lseek(fd, 0, SEEK_SET), the zero position is always
201
* pr->off, so lseek(fd, pr->off, SEEK_SET).
204
unsigned char *blkid_probe_get_buffer(blkid_probe pr,
205
blkid_loff_t off, blkid_loff_t len)
207
ssize_t ret_read = 0;
209
if (off < 0 || len < 0) {
211
printf("unexpected offset or length of buffer requested\n"));
214
if (off + len <= BLKID_SB_BUFSIZ) {
216
pr->sbbuf = malloc(BLKID_SB_BUFSIZ);
220
if (!pr->sbbuf_len) {
221
if (lseek(pr->fd, pr->off, SEEK_SET) < 0)
223
ret_read = read(pr->fd, pr->sbbuf, BLKID_SB_BUFSIZ);
226
pr->sbbuf_len = ret_read;
228
if (off + len > pr->sbbuf_len)
230
return pr->sbbuf + off;
232
unsigned char *newbuf = NULL;
234
if (len > pr->buf_max) {
235
newbuf = realloc(pr->buf, len);
243
if (newbuf || off < pr->buf_off ||
244
off + len > pr->buf_off + pr->buf_len) {
246
if (blkid_llseek(pr->fd, pr->off + off, SEEK_SET) < 0)
249
ret_read = read(pr->fd, pr->buf, len);
250
if (ret_read != (ssize_t) len)
255
return off ? pr->buf + (off - pr->buf_off) : pr->buf;
260
* Assignes the device to probe control struct, resets internal buffers and
261
* reads 512 bytes from device to the buffers.
263
* Returns -1 in case of failure, or 0 on success.
265
int blkid_probe_set_device(blkid_probe pr, int fd,
266
blkid_loff_t off, blkid_loff_t size)
271
blkid_reset_probe(pr);
285
if (S_ISBLK(sb.st_mode))
286
blkdev_get_size(fd, (unsigned long long *) &pr->size);
288
pr->size = sb.st_size;
293
/* read SB to test if the device is readable */
294
if (!blkid_probe_get_buffer(pr, 0, 0x200)) {
296
printf("failed to prepare a device for low-probing\n"));
300
DBG(DEBUG_LOWPROBE, printf("ready for low-probing, offset=%zd, size=%zd\n",
305
int blkid_probe_set_request(blkid_probe pr, int flags)
313
int blkid_probe_reset_filter(blkid_probe pr)
318
memset(pr->fltr, 0, BLKID_FLTR_SIZE * sizeof(unsigned long));
319
blkid_probe_reset_idx(pr);
326
* BLKID_FLTR_NOTIN - probe all filesystems which are NOT IN names[]
328
* BLKID_FLTR_ONLYIN - probe filesystem which are IN names[]
330
int blkid_probe_filter_types(blkid_probe pr, int flag, char *names[])
337
pr->fltr = calloc(BLKID_FLTR_SIZE, sizeof(unsigned long));
338
blkid_probe_reset_idx(pr);
340
blkid_probe_reset_filter(pr);
345
for (i = 0; i < ARRAY_SIZE(idinfos); i++) {
347
const struct blkid_idinfo *id = idinfos[i];
350
for (n = names; *n; n++) {
351
if (!strcmp(id->name, *n)) {
356
/* The default is enable all filesystems,
357
* set relevant bitmap bit means disable the filesystem.
359
if (flag & BLKID_FLTR_ONLYIN) {
361
blkid_bmp_set_item(pr->fltr, i);
362
} else if (flag & BLKID_FLTR_NOTIN) {
364
blkid_bmp_set_item(pr->fltr, i);
367
DBG(DEBUG_LOWPROBE, printf("a new probing type-filter initialized\n"));
374
* BLKID_FLTR_NOTIN - probe all filesystems which are NOT IN "usage"
376
* BLKID_FLTR_ONLYIN - probe filesystem which are IN "usage"
378
* where the "usage" is a set of filesystem according the usage flag (crypto,
379
* raid, filesystem, ...)
381
int blkid_probe_filter_usage(blkid_probe pr, int flag, int usage)
388
pr->fltr = calloc(BLKID_FLTR_SIZE, sizeof(unsigned long));
389
blkid_probe_reset_idx(pr);
391
blkid_probe_reset_filter(pr);
396
for (i = 0; i < ARRAY_SIZE(idinfos); i++) {
397
const struct blkid_idinfo *id = idinfos[i];
399
if (id->usage & usage) {
400
if (flag & BLKID_FLTR_NOTIN)
401
blkid_bmp_set_item(pr->fltr, i);
402
} else if (flag & BLKID_FLTR_ONLYIN)
403
blkid_bmp_set_item(pr->fltr, i);
405
DBG(DEBUG_LOWPROBE, printf("a new probing usage-filter initialized\n"));
410
int blkid_probe_invert_filter(blkid_probe pr)
414
if (!pr || !pr->fltr)
416
for (i = 0; i < BLKID_FLTR_SIZE; i++)
417
pr->fltr[i] = ~pr->fltr[i];
419
blkid_probe_reset_idx(pr);
420
DBG(DEBUG_LOWPROBE, printf("probing filter inverted\n"));
425
* The blkid_do_probe() calls the probe functions. This routine could be used
426
* in a loop when you need to probe for all possible filesystems/raids.
428
* 1/ basic case -- use the first result:
430
* if (blkid_do_probe(pr) == 0) {
431
* int nvals = blkid_probe_numof_values(pr);
432
* for (n = 0; n < nvals; n++) {
433
* if (blkid_probe_get_value(pr, n, &name, &data, &len) == 0)
434
* printf("%s = %s\n", name, data);
438
* 2/ advanced case -- probe for all signatures (don't forget that some
439
* filesystems can co-exist on one volume (e.g. CD-ROM).
441
* while (blkid_do_probe(pr) == 0) {
442
* int nvals = blkid_probe_numof_values(pr);
446
* The internal probing index (pointer to the last probing function) is
447
* always reseted when you touch probing filter or set a new device. It
448
* means you cannot use:
450
* blkid_probe_invert_filter()
451
* blkid_probe_filter_usage()
452
* blkid_probe_filter_types()
453
* blkid_probe_reset_filter()
454
* blkid_probe_set_device()
456
* in the loop (e.g while()) when you iterate on all signatures.
458
int blkid_do_probe(blkid_probe pr)
462
if (!pr || pr->idx < -1)
465
blkid_probe_reset_vals(pr);
468
printf("--> starting probing loop [idx=%d]\n",
473
for ( ; i < ARRAY_SIZE(idinfos); i++) {
474
const struct blkid_idinfo *id;
475
const struct blkid_idmag *mag;
480
if (pr->fltr && blkid_bmp_get_item(pr->fltr, i))
484
mag = id->magics ? &id->magics[0] : NULL;
486
/* try to detect by magic string */
487
while(mag && mag->magic) {
491
idx = mag->kboff + (mag->sboff >> 10);
492
buf = blkid_probe_get_buffer(pr, idx << 10, 1024);
494
if (buf && !memcmp(mag->magic,
495
buf + (mag->sboff & 0x3ff), mag->len)) {
496
DBG(DEBUG_LOWPROBE, printf(
497
"%s: magic sboff=%u, kboff=%ld\n",
498
id->name, mag->sboff, mag->kboff));
505
if (hasmag == 0 && id->magics && id->magics[0].magic)
506
/* magic string(s) defined, but not found */
509
/* final check by probing function */
511
DBG(DEBUG_LOWPROBE, printf(
512
"%s: call probefunc()\n", id->name));
513
if (id->probefunc(pr, mag) != 0)
517
/* all cheks passed */
518
if (pr->probreq & BLKID_PROBREQ_TYPE)
519
blkid_probe_set_value(pr, "TYPE",
520
(unsigned char *) id->name,
521
strlen(id->name) + 1);
522
if (pr->probreq & BLKID_PROBREQ_USAGE)
523
blkid_probe_set_usage(pr, id->usage);
526
printf("<-- leaving probing loop (type=%s) [idx=%d]\n",
531
printf("<-- leaving probing loop (failed) [idx=%d]\n",
537
* This is the same function as blkid_do_probe(), but returns only one result
538
* (cannot be used in while()) and checks for ambivalen results (more
539
* filesystems on the device) -- in such case returns -2.
541
* The function does not check for filesystems when a RAID signature is
542
* detected. The function also does not check for collision between RAIDs. The
543
* first detected RAID is returned.
545
int blkid_do_safeprobe(blkid_probe pr)
547
struct blkid_struct_probe first;
552
while ((rc = blkid_do_probe(pr)) == 0) {
554
/* store the fist result */
555
memcpy(first.vals, pr->vals, sizeof(first.vals));
556
first.nvals = pr->nvals;
561
if (idinfos[pr->idx]->usage & BLKID_USAGE_RAID)
563
if (!(idinfos[pr->idx]->flags & BLKID_IDINFO_TOLERANT))
567
return rc; /* error */
568
if (count > 1 && intol) {
570
printf("ERROR: ambivalent result detected (%d filesystems)!\n",
572
return -2; /* error, ambivalent result (more FS) */
575
return 1; /* nothing detected */
577
/* restore the first result */
578
memcpy(pr->vals, first.vals, sizeof(first.vals));
579
pr->nvals = first.nvals;
585
int blkid_probe_numof_values(blkid_probe pr)
593
static struct blkid_prval *blkid_probe_assign_value(
594
blkid_probe pr, const char *name)
596
struct blkid_prval *v;
600
if (pr->nvals >= BLKID_PROBVAL_NVALS)
603
v = &pr->vals[pr->nvals];
607
DBG(DEBUG_LOWPROBE, printf("assigning %s\n", name));
611
int blkid_probe_set_value(blkid_probe pr, const char *name,
612
unsigned char *data, size_t len)
614
struct blkid_prval *v;
616
if (len > BLKID_PROBVAL_BUFSIZ)
617
len = BLKID_PROBVAL_BUFSIZ;
619
v = blkid_probe_assign_value(pr, name);
623
memcpy(v->data, data, len);
628
int blkid_probe_vsprintf_value(blkid_probe pr, const char *name,
629
const char *fmt, va_list ap)
631
struct blkid_prval *v;
634
v = blkid_probe_assign_value(pr, name);
638
len = vsnprintf((char *) v->data, sizeof(v->data), fmt, ap);
641
pr->nvals--; /* reset the latest assigned value */
648
int blkid_probe_set_version(blkid_probe pr, const char *version)
650
if (pr->probreq & BLKID_PROBREQ_VERSION)
651
return blkid_probe_set_value(pr, "VERSION",
652
(unsigned char *) version, strlen(version) + 1);
656
int blkid_probe_sprintf_version(blkid_probe pr, const char *fmt, ...)
660
if (pr->probreq & BLKID_PROBREQ_VERSION) {
664
rc = blkid_probe_vsprintf_value(pr, "VERSION", fmt, ap);
670
static int blkid_probe_set_usage(blkid_probe pr, int usage)
674
if (usage & BLKID_USAGE_FILESYSTEM)
676
else if (usage & BLKID_USAGE_RAID)
678
else if (usage & BLKID_USAGE_CRYPTO)
680
else if (usage & BLKID_USAGE_OTHER)
685
return blkid_probe_set_value(pr, "USAGE", (unsigned char *) u, strlen(u) + 1);
688
int blkid_probe_set_label(blkid_probe pr, unsigned char *label, size_t len)
690
struct blkid_prval *v;
693
if (len > BLKID_PROBVAL_BUFSIZ)
694
len = BLKID_PROBVAL_BUFSIZ;
696
if ((pr->probreq & BLKID_PROBREQ_LABELRAW) &&
697
blkid_probe_set_value(pr, "LABEL_RAW", label, len) < 0)
699
if (!(pr->probreq & BLKID_PROBREQ_LABEL))
701
v = blkid_probe_assign_value(pr, "LABEL");
705
memcpy(v->data, label, len);
708
/* remove trailing whitespace */
709
i = strnlen((char *) v->data, len);
711
if (!isspace(v->data[i]))
719
static size_t encode_to_utf8(int enc, unsigned char *dest, size_t len,
720
unsigned char *src, size_t count)
725
for (j = i = 0; i + 2 <= count; i += 2) {
726
if (enc == BLKID_ENC_UTF16LE)
727
c = (src[i+1] << 8) | src[i];
728
else /* BLKID_ENC_UTF16BE */
729
c = (src[i] << 8) | src[i+1];
733
} else if (c < 0x80) {
736
dest[j++] = (uint8_t) c;
737
} else if (c < 0x800) {
740
dest[j++] = (uint8_t) (0xc0 | (c >> 6));
741
dest[j++] = (uint8_t) (0x80 | (c & 0x3f));
745
dest[j++] = (uint8_t) (0xe0 | (c >> 12));
746
dest[j++] = (uint8_t) (0x80 | ((c >> 6) & 0x3f));
747
dest[j++] = (uint8_t) (0x80 | (c & 0x3f));
754
int blkid_probe_set_utf8label(blkid_probe pr, unsigned char *label,
757
struct blkid_prval *v;
759
if ((pr->probreq & BLKID_PROBREQ_LABELRAW) &&
760
blkid_probe_set_value(pr, "LABEL_RAW", label, len) < 0)
762
if (!(pr->probreq & BLKID_PROBREQ_LABEL))
764
v = blkid_probe_assign_value(pr, "LABEL");
768
v->len = encode_to_utf8(enc, v->data, sizeof(v->data), label, len);
772
/* like uuid_is_null() from libuuid, but works with arbitrary size of UUID */
773
static int uuid_is_empty(const unsigned char *buf, size_t len)
777
for (i = 0; i < len; i++)
783
int blkid_probe_sprintf_uuid(blkid_probe pr, unsigned char *uuid,
784
size_t len, const char *fmt, ...)
789
if (len > BLKID_PROBVAL_BUFSIZ)
790
len = BLKID_PROBVAL_BUFSIZ;
792
if (uuid_is_empty(uuid, len))
795
if ((pr->probreq & BLKID_PROBREQ_UUIDRAW) &&
796
blkid_probe_set_value(pr, "UUID_RAW", uuid, len) < 0)
798
if (!(pr->probreq & BLKID_PROBREQ_UUID))
802
rc = blkid_probe_vsprintf_value(pr, "UUID", fmt, ap);
805
/* convert to lower case (..be paranoid) */
808
struct blkid_prval *v = &pr->vals[pr->nvals];
810
for (i = 0; i < v->len; i++)
811
if (v->data[i] >= 'A' && v->data[i] <= 'F')
812
v->data[i] = (v->data[i] - 'A') + 'a';
817
/* function to set UUIDs that are in suberblocks stored as strings */
818
int blkid_probe_strncpy_uuid(blkid_probe pr, unsigned char *str, size_t len)
820
struct blkid_prval *v;
822
if (str == NULL || *str == '\0')
825
len = strlen((char *) str);
826
if (len > BLKID_PROBVAL_BUFSIZ)
827
len = BLKID_PROBVAL_BUFSIZ;
829
if ((pr->probreq & BLKID_PROBREQ_UUIDRAW) &&
830
blkid_probe_set_value(pr, "UUID_RAW", str, len) < 0)
832
if (!(pr->probreq & BLKID_PROBREQ_UUID))
835
v = blkid_probe_assign_value(pr, "UUID");
837
memcpy((char *) v->data, str, len);
838
*(v->data + len) = '\0';
845
/* default _set_uuid function to set DCE UUIDs */
846
int blkid_probe_set_uuid_as(blkid_probe pr, unsigned char *uuid, const char *name)
848
struct blkid_prval *v;
850
if (uuid_is_empty(uuid, 16))
854
if ((pr->probreq & BLKID_PROBREQ_UUIDRAW) &&
855
blkid_probe_set_value(pr, "UUID_RAW", uuid, 16) < 0)
857
if (!(pr->probreq & BLKID_PROBREQ_UUID))
860
v = blkid_probe_assign_value(pr, "UUID");
862
v = blkid_probe_assign_value(pr, name);
866
uuid_unparse(uuid, (char *) v->data);
870
v->len = snprintf(v->data, sizeof(v->data),
871
"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
872
uuid[0], uuid[1], uuid[2], uuid[3],
876
uuid[10], uuid[11], uuid[12], uuid[13], uuid[14],uuid[15]);
882
int blkid_probe_set_uuid(blkid_probe pr, unsigned char *uuid)
884
return blkid_probe_set_uuid_as(pr, uuid, NULL);
887
int blkid_probe_get_value(blkid_probe pr, int num, const char **name,
888
const char **data, size_t *len)
890
struct blkid_prval *v;
892
if (pr == NULL || num < 0 || num >= pr->nvals)
899
*data = (char *) v->data;
903
DBG(DEBUG_LOWPROBE, printf("returning %s value\n", v->name));
907
int blkid_probe_lookup_value(blkid_probe pr, const char *name,
908
const char **data, size_t *len)
912
if (pr == NULL || pr->nvals == 0 || name == NULL)
915
for (i = 0; i < pr->nvals; i++) {
916
struct blkid_prval *v = &pr->vals[i];
918
if (v->name && strcmp(name, v->name) == 0) {
920
*data = (char *) v->data;
923
DBG(DEBUG_LOWPROBE, printf("returning %s value\n", v->name));
930
int blkid_probe_has_value(blkid_probe pr, const char *name)
932
if (blkid_probe_lookup_value(pr, name, NULL, NULL) == 0)