]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - shlibs/blkid/src/probe.c
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
[] =
98 # define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
101 /* filter bitmap macros */
102 #define blkid_bmp_wordsize (8 * sizeof(unsigned long))
103 #define blkid_bmp_idx_bit(item) (1UL << ((item) % blkid_bmp_wordsize))
104 #define blkid_bmp_idx_byte(item) ((item) / blkid_bmp_wordsize)
106 #define blkid_bmp_set_item(bmp, item) \
107 ((bmp)[ blkid_bmp_idx_byte(item) ] |= blkid_bmp_idx_bit(item))
109 #define blkid_bmp_unset_item(bmp, item) \
110 ((bmp)[ bmp_idx_byte(item) ] &= ~bmp_idx_bit(item))
112 #define blkid_bmp_get_item(bmp, item) \
113 ((bmp)[ blkid_bmp_idx_byte(item) ] & blkid_bmp_idx_bit(item))
115 #define blkid_bmp_size(max_items) \
116 (((max_items) + blkid_bmp_wordsize) / blkid_bmp_wordsize)
118 #define BLKID_FLTR_ITEMS ARRAY_SIZE(idinfos)
119 #define BLKID_FLTR_SIZE blkid_bmp_size(BLKID_FLTR_ITEMS)
122 static int blkid_probe_set_usage(blkid_probe pr
, int usage
);
124 int blkid_known_fstype(const char *fstype
)
131 for (i
= 0; i
< ARRAY_SIZE(idinfos
); i
++) {
132 const struct blkid_idinfo
*id
= idinfos
[i
];
133 if (strcmp(id
->name
, fstype
) == 0)
140 * Returns a pointer to the newly allocated probe struct
142 blkid_probe
blkid_new_probe(void)
145 return calloc(1, sizeof(struct blkid_struct_probe
));
149 * Deallocates probe struct, buffers and all allocated
150 * data that are associated with this probing control struct.
152 void blkid_free_probe(blkid_probe pr
)
162 static void blkid_probe_reset_vals(blkid_probe pr
)
164 memset(pr
->vals
, 0, sizeof(pr
->vals
));
168 static void blkid_probe_reset_idx(blkid_probe pr
)
173 void blkid_reset_probe(blkid_probe pr
)
177 DBG(DEBUG_LOWPROBE
, printf("reseting blkid_probe\n"));
179 memset(pr
->buf
, 0, pr
->buf_max
);
183 memset(pr
->sbbuf
, 0, BLKID_SB_BUFSIZ
);
185 blkid_probe_reset_vals(pr
);
186 blkid_probe_reset_idx(pr
);
190 * Note that we have two offsets:
192 * 1/ general device offset (pr->off), that's useful for example when we
193 * probe a partition from whole disk image:
194 * blkid-low --offset <partition_position> disk.img
196 * 2/ buffer offset (the 'off' argument), that useful for offsets in
199 * That means never use lseek(fd, 0, SEEK_SET), the zero position is always
200 * pr->off, so lseek(fd, pr->off, SEEK_SET).
203 unsigned char *blkid_probe_get_buffer(blkid_probe pr
,
204 blkid_loff_t off
, blkid_loff_t len
)
206 ssize_t ret_read
= 0;
208 if (off
< 0 || len
< 0) {
210 printf("unexpected offset or length of buffer requested\n"));
213 if (off
+ len
<= BLKID_SB_BUFSIZ
) {
215 pr
->sbbuf
= malloc(BLKID_SB_BUFSIZ
);
219 if (!pr
->sbbuf_len
) {
220 if (lseek(pr
->fd
, pr
->off
, SEEK_SET
) < 0)
222 ret_read
= read(pr
->fd
, pr
->sbbuf
, BLKID_SB_BUFSIZ
);
225 pr
->sbbuf_len
= ret_read
;
227 if (off
+ len
> pr
->sbbuf_len
)
229 return pr
->sbbuf
+ off
;
231 unsigned char *newbuf
= NULL
;
233 if (len
> pr
->buf_max
) {
234 newbuf
= realloc(pr
->buf
, len
);
242 if (newbuf
|| off
< pr
->buf_off
||
243 off
+ len
> pr
->buf_off
+ pr
->buf_len
) {
245 if (blkid_llseek(pr
->fd
, pr
->off
+ off
, SEEK_SET
) < 0)
248 ret_read
= read(pr
->fd
, pr
->buf
, len
);
249 if (ret_read
!= (ssize_t
) len
)
254 return off
? pr
->buf
+ (off
- pr
->buf_off
) : pr
->buf
;
259 * Assignes the device to probe control struct, resets internal buffers and
260 * reads 512 bytes from device to the buffers.
262 * Returns -1 in case of failure, or 0 on success.
264 int blkid_probe_set_device(blkid_probe pr
, int fd
,
265 blkid_loff_t off
, blkid_loff_t size
)
270 blkid_reset_probe(pr
);
284 if (S_ISBLK(sb
.st_mode
))
285 blkdev_get_size(fd
, (unsigned long long *) &pr
->size
);
287 pr
->size
= sb
.st_size
;
292 /* read SB to test if the device is readable */
293 if (!blkid_probe_get_buffer(pr
, 0, 0x200)) {
295 printf("failed to prepare a device for low-probing\n"));
299 DBG(DEBUG_LOWPROBE
, printf("ready for low-probing, offset=%zd, size=%zd\n",
304 int blkid_probe_set_request(blkid_probe pr
, int flags
)
312 int blkid_probe_reset_filter(blkid_probe pr
)
317 memset(pr
->fltr
, 0, BLKID_FLTR_SIZE
* sizeof(unsigned long));
318 blkid_probe_reset_idx(pr
);
325 * BLKID_FLTR_NOTIN - probe all filesystems which are NOT IN names[]
327 * BLKID_FLTR_ONLYIN - probe filesystem which are IN names[]
329 int blkid_probe_filter_types(blkid_probe pr
, int flag
, char *names
[])
336 pr
->fltr
= calloc(BLKID_FLTR_SIZE
, sizeof(unsigned long));
337 blkid_probe_reset_idx(pr
);
339 blkid_probe_reset_filter(pr
);
344 for (i
= 0; i
< ARRAY_SIZE(idinfos
); i
++) {
346 const struct blkid_idinfo
*id
= idinfos
[i
];
349 for (n
= names
; *n
; n
++) {
350 if (!strcmp(id
->name
, *n
)) {
355 /* The default is enable all filesystems,
356 * set relevant bitmap bit means disable the filesystem.
358 if (flag
& BLKID_FLTR_ONLYIN
) {
360 blkid_bmp_set_item(pr
->fltr
, i
);
361 } else if (flag
& BLKID_FLTR_NOTIN
) {
363 blkid_bmp_set_item(pr
->fltr
, i
);
366 DBG(DEBUG_LOWPROBE
, printf("a new probing type-filter initialized\n"));
373 * BLKID_FLTR_NOTIN - probe all filesystems which are NOT IN "usage"
375 * BLKID_FLTR_ONLYIN - probe filesystem which are IN "usage"
377 * where the "usage" is a set of filesystem according the usage flag (crypto,
378 * raid, filesystem, ...)
380 int blkid_probe_filter_usage(blkid_probe pr
, int flag
, int usage
)
387 pr
->fltr
= calloc(BLKID_FLTR_SIZE
, sizeof(unsigned long));
388 blkid_probe_reset_idx(pr
);
390 blkid_probe_reset_filter(pr
);
395 for (i
= 0; i
< ARRAY_SIZE(idinfos
); i
++) {
396 const struct blkid_idinfo
*id
= idinfos
[i
];
398 if (id
->usage
& usage
) {
399 if (flag
& BLKID_FLTR_NOTIN
)
400 blkid_bmp_set_item(pr
->fltr
, i
);
401 } else if (flag
& BLKID_FLTR_ONLYIN
)
402 blkid_bmp_set_item(pr
->fltr
, i
);
404 DBG(DEBUG_LOWPROBE
, printf("a new probing usage-filter initialized\n"));
409 int blkid_probe_invert_filter(blkid_probe pr
)
413 if (!pr
|| !pr
->fltr
)
415 for (i
= 0; i
< BLKID_FLTR_SIZE
; i
++)
416 pr
->fltr
[i
] = ~pr
->fltr
[i
];
418 blkid_probe_reset_idx(pr
);
419 DBG(DEBUG_LOWPROBE
, printf("probing filter inverted\n"));
424 * The blkid_do_probe() calls the probe functions. This routine could be used
425 * in a loop when you need to probe for all possible filesystems/raids.
427 * 1/ basic case -- use the first result:
429 * if (blkid_do_probe(pr) == 0) {
430 * int nvals = blkid_probe_numof_values(pr);
431 * for (n = 0; n < nvals; n++) {
432 * if (blkid_probe_get_value(pr, n, &name, &data, &len) == 0)
433 * printf("%s = %s\n", name, data);
437 * 2/ advanced case -- probe for all signatures (don't forget that some
438 * filesystems can co-exist on one volume (e.g. CD-ROM).
440 * while (blkid_do_probe(pr) == 0) {
441 * int nvals = blkid_probe_numof_values(pr);
445 * The internal probing index (pointer to the last probing function) is
446 * always reseted when you touch probing filter or set a new device. It
447 * means you cannot use:
449 * blkid_probe_invert_filter()
450 * blkid_probe_filter_usage()
451 * blkid_probe_filter_types()
452 * blkid_probe_reset_filter()
453 * blkid_probe_set_device()
455 * in the loop (e.g while()) when you iterate on all signatures.
457 int blkid_do_probe(blkid_probe pr
)
461 if (!pr
|| pr
->idx
< -1)
464 blkid_probe_reset_vals(pr
);
467 printf("--> starting probing loop [idx=%d]\n",
472 for ( ; i
< ARRAY_SIZE(idinfos
); i
++) {
473 const struct blkid_idinfo
*id
;
474 const struct blkid_idmag
*mag
;
479 if (pr
->fltr
&& blkid_bmp_get_item(pr
->fltr
, i
))
483 mag
= id
->magics
? &id
->magics
[0] : NULL
;
485 /* try to detect by magic string */
486 while(mag
&& mag
->magic
) {
490 idx
= mag
->kboff
+ (mag
->sboff
>> 10);
491 buf
= blkid_probe_get_buffer(pr
, idx
<< 10, 1024);
493 if (buf
&& !memcmp(mag
->magic
,
494 buf
+ (mag
->sboff
& 0x3ff), mag
->len
)) {
495 DBG(DEBUG_LOWPROBE
, printf(
496 "%s: magic sboff=%u, kboff=%ld\n",
497 id
->name
, mag
->sboff
, mag
->kboff
));
504 if (hasmag
== 0 && id
->magics
&& id
->magics
[0].magic
)
505 /* magic string(s) defined, but not found */
508 /* final check by probing function */
510 DBG(DEBUG_LOWPROBE
, printf(
511 "%s: call probefunc()\n", id
->name
));
512 if (id
->probefunc(pr
, mag
) != 0)
516 /* all cheks passed */
517 if (pr
->probreq
& BLKID_PROBREQ_TYPE
)
518 blkid_probe_set_value(pr
, "TYPE",
519 (unsigned char *) id
->name
,
520 strlen(id
->name
) + 1);
521 if (pr
->probreq
& BLKID_PROBREQ_USAGE
)
522 blkid_probe_set_usage(pr
, id
->usage
);
525 printf("<-- leaving probing loop (type=%s) [idx=%d]\n",
530 printf("<-- leaving probing loop (failed) [idx=%d]\n",
536 * This is the same function as blkid_do_probe(), but returns only one result
537 * (cannot be used in while()) and checks for ambivalen results (more
538 * filesystems on the device) -- in such case returns -2.
540 * The function does not check for filesystems when a RAID signature is
541 * detected. The function also does not check for collision between RAIDs. The
542 * first detected RAID is returned.
544 int blkid_do_safeprobe(blkid_probe pr
)
546 struct blkid_struct_probe first
;
551 while ((rc
= blkid_do_probe(pr
)) == 0) {
553 /* store the fist result */
554 memcpy(first
.vals
, pr
->vals
, sizeof(first
.vals
));
555 first
.nvals
= pr
->nvals
;
560 if (idinfos
[pr
->idx
]->usage
& BLKID_USAGE_RAID
)
562 if (!(idinfos
[pr
->idx
]->flags
& BLKID_IDINFO_TOLERANT
))
566 return rc
; /* error */
567 if (count
> 1 && intol
) {
569 printf("ERROR: ambivalent result detected (%d filesystems)!\n",
571 return -2; /* error, ambivalent result (more FS) */
574 return 1; /* nothing detected */
576 /* restore the first result */
577 memcpy(pr
->vals
, first
.vals
, sizeof(first
.vals
));
578 pr
->nvals
= first
.nvals
;
584 int blkid_probe_numof_values(blkid_probe pr
)
592 static struct blkid_prval
*blkid_probe_assign_value(
593 blkid_probe pr
, const char *name
)
595 struct blkid_prval
*v
;
599 if (pr
->nvals
>= BLKID_PROBVAL_NVALS
)
602 v
= &pr
->vals
[pr
->nvals
];
606 DBG(DEBUG_LOWPROBE
, printf("assigning %s\n", name
));
610 int blkid_probe_set_value(blkid_probe pr
, const char *name
,
611 unsigned char *data
, size_t len
)
613 struct blkid_prval
*v
;
615 if (len
> BLKID_PROBVAL_BUFSIZ
)
616 len
= BLKID_PROBVAL_BUFSIZ
;
618 v
= blkid_probe_assign_value(pr
, name
);
622 memcpy(v
->data
, data
, len
);
627 int blkid_probe_vsprintf_value(blkid_probe pr
, const char *name
,
628 const char *fmt
, va_list ap
)
630 struct blkid_prval
*v
;
633 v
= blkid_probe_assign_value(pr
, name
);
637 len
= vsnprintf((char *) v
->data
, sizeof(v
->data
), fmt
, ap
);
640 pr
->nvals
--; /* reset the latest assigned value */
647 int blkid_probe_set_version(blkid_probe pr
, const char *version
)
649 if (pr
->probreq
& BLKID_PROBREQ_VERSION
)
650 return blkid_probe_set_value(pr
, "VERSION",
651 (unsigned char *) version
, strlen(version
) + 1);
655 int blkid_probe_sprintf_version(blkid_probe pr
, const char *fmt
, ...)
659 if (pr
->probreq
& BLKID_PROBREQ_VERSION
) {
663 rc
= blkid_probe_vsprintf_value(pr
, "VERSION", fmt
, ap
);
669 static int blkid_probe_set_usage(blkid_probe pr
, int usage
)
673 if (usage
& BLKID_USAGE_FILESYSTEM
)
675 else if (usage
& BLKID_USAGE_RAID
)
677 else if (usage
& BLKID_USAGE_CRYPTO
)
679 else if (usage
& BLKID_USAGE_OTHER
)
684 return blkid_probe_set_value(pr
, "USAGE", (unsigned char *) u
, strlen(u
) + 1);
687 int blkid_probe_set_label(blkid_probe pr
, unsigned char *label
, size_t len
)
689 struct blkid_prval
*v
;
692 if (len
> BLKID_PROBVAL_BUFSIZ
)
693 len
= BLKID_PROBVAL_BUFSIZ
;
695 if ((pr
->probreq
& BLKID_PROBREQ_LABELRAW
) &&
696 blkid_probe_set_value(pr
, "LABEL_RAW", label
, len
) < 0)
698 if (!(pr
->probreq
& BLKID_PROBREQ_LABEL
))
700 v
= blkid_probe_assign_value(pr
, "LABEL");
704 memcpy(v
->data
, label
, len
);
707 /* remove trailing whitespace */
708 i
= strnlen((char *) v
->data
, len
);
710 if (!isspace(v
->data
[i
]))
718 static size_t encode_to_utf8(int enc
, unsigned char *dest
, size_t len
,
719 unsigned char *src
, size_t count
)
724 for (j
= i
= 0; i
+ 2 <= count
; i
+= 2) {
725 if (enc
== BLKID_ENC_UTF16LE
)
726 c
= (src
[i
+1] << 8) | src
[i
];
727 else /* BLKID_ENC_UTF16BE */
728 c
= (src
[i
] << 8) | src
[i
+1];
732 } else if (c
< 0x80) {
735 dest
[j
++] = (uint8_t) c
;
736 } else if (c
< 0x800) {
739 dest
[j
++] = (uint8_t) (0xc0 | (c
>> 6));
740 dest
[j
++] = (uint8_t) (0x80 | (c
& 0x3f));
744 dest
[j
++] = (uint8_t) (0xe0 | (c
>> 12));
745 dest
[j
++] = (uint8_t) (0x80 | ((c
>> 6) & 0x3f));
746 dest
[j
++] = (uint8_t) (0x80 | (c
& 0x3f));
753 int blkid_probe_set_utf8label(blkid_probe pr
, unsigned char *label
,
756 struct blkid_prval
*v
;
758 if ((pr
->probreq
& BLKID_PROBREQ_LABELRAW
) &&
759 blkid_probe_set_value(pr
, "LABEL_RAW", label
, len
) < 0)
761 if (!(pr
->probreq
& BLKID_PROBREQ_LABEL
))
763 v
= blkid_probe_assign_value(pr
, "LABEL");
767 v
->len
= encode_to_utf8(enc
, v
->data
, sizeof(v
->data
), label
, len
);
771 /* like uuid_is_null() from libuuid, but works with arbitrary size of UUID */
772 static int uuid_is_empty(const unsigned char *buf
, size_t len
)
776 for (i
= 0; i
< len
; i
++)
782 int blkid_probe_sprintf_uuid(blkid_probe pr
, unsigned char *uuid
,
783 size_t len
, const char *fmt
, ...)
788 if (len
> BLKID_PROBVAL_BUFSIZ
)
789 len
= BLKID_PROBVAL_BUFSIZ
;
791 if (uuid_is_empty(uuid
, len
))
794 if ((pr
->probreq
& BLKID_PROBREQ_UUIDRAW
) &&
795 blkid_probe_set_value(pr
, "UUID_RAW", uuid
, len
) < 0)
797 if (!(pr
->probreq
& BLKID_PROBREQ_UUID
))
801 rc
= blkid_probe_vsprintf_value(pr
, "UUID", fmt
, ap
);
804 /* convert to lower case (..be paranoid) */
807 struct blkid_prval
*v
= &pr
->vals
[pr
->nvals
];
809 for (i
= 0; i
< v
->len
; i
++)
810 if (v
->data
[i
] >= 'A' && v
->data
[i
] <= 'F')
811 v
->data
[i
] = (v
->data
[i
] - 'A') + 'a';
816 /* function to set UUIDs that are in suberblocks stored as strings */
817 int blkid_probe_strncpy_uuid(blkid_probe pr
, unsigned char *str
, size_t len
)
819 struct blkid_prval
*v
;
821 if (str
== NULL
|| *str
== '\0')
824 len
= strlen((char *) str
);
825 if (len
> BLKID_PROBVAL_BUFSIZ
)
826 len
= BLKID_PROBVAL_BUFSIZ
;
828 if ((pr
->probreq
& BLKID_PROBREQ_UUIDRAW
) &&
829 blkid_probe_set_value(pr
, "UUID_RAW", str
, len
) < 0)
831 if (!(pr
->probreq
& BLKID_PROBREQ_UUID
))
834 v
= blkid_probe_assign_value(pr
, "UUID");
836 memcpy((char *) v
->data
, str
, len
);
837 *(v
->data
+ len
) = '\0';
844 /* default _set_uuid function to set DCE UUIDs */
845 int blkid_probe_set_uuid_as(blkid_probe pr
, unsigned char *uuid
, const char *name
)
847 struct blkid_prval
*v
;
849 if (uuid_is_empty(uuid
, 16))
853 if ((pr
->probreq
& BLKID_PROBREQ_UUIDRAW
) &&
854 blkid_probe_set_value(pr
, "UUID_RAW", uuid
, 16) < 0)
856 if (!(pr
->probreq
& BLKID_PROBREQ_UUID
))
859 v
= blkid_probe_assign_value(pr
, "UUID");
861 v
= blkid_probe_assign_value(pr
, name
);
865 uuid_unparse(uuid
, (char *) v
->data
);
869 v
->len
= snprintf(v
->data
, sizeof(v
->data
),
870 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
871 uuid
[0], uuid
[1], uuid
[2], uuid
[3],
875 uuid
[10], uuid
[11], uuid
[12], uuid
[13], uuid
[14],uuid
[15]);
881 int blkid_probe_set_uuid(blkid_probe pr
, unsigned char *uuid
)
883 return blkid_probe_set_uuid_as(pr
, uuid
, NULL
);
886 int blkid_probe_get_value(blkid_probe pr
, int num
, const char **name
,
887 const char **data
, size_t *len
)
889 struct blkid_prval
*v
;
891 if (pr
== NULL
|| num
< 0 || num
>= pr
->nvals
)
898 *data
= (char *) v
->data
;
902 DBG(DEBUG_LOWPROBE
, printf("returning %s value\n", v
->name
));
906 int blkid_probe_lookup_value(blkid_probe pr
, const char *name
,
907 const char **data
, size_t *len
)
911 if (pr
== NULL
|| pr
->nvals
== 0 || name
== NULL
)
914 for (i
= 0; i
< pr
->nvals
; i
++) {
915 struct blkid_prval
*v
= &pr
->vals
[i
];
917 if (v
->name
&& strcmp(name
, v
->name
) == 0) {
919 *data
= (char *) v
->data
;
922 DBG(DEBUG_LOWPROBE
, printf("returning %s value\n", v
->name
));
929 int blkid_probe_has_value(blkid_probe pr
, const char *name
)
931 if (blkid_probe_lookup_value(pr
, name
, NULL
, NULL
) == 0)