]>
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>
40 #include "superblocks/superblocks.h"
42 static const struct blkid_idinfo
*idinfos
[] =
100 # define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
103 #define BLKID_FLTR_ITEMS ARRAY_SIZE(idinfos)
104 #define BLKID_FLTR_SIZE blkid_bmp_nwords(BLKID_FLTR_ITEMS)
106 static int blkid_probe_set_usage(blkid_probe pr
, int usage
);
109 * Returns a pointer to the newly allocated probe struct
111 blkid_probe
blkid_new_probe(void)
114 return calloc(1, sizeof(struct blkid_struct_probe
));
118 * Deallocates probe struct, buffers and all allocated
119 * data that are associated with this probing control struct.
121 void blkid_free_probe(blkid_probe pr
)
132 * Removes chain values from probing result.
134 void blkid_probe_chain_reset_vals(blkid_probe pr
, struct blkid_chain
*chn
)
136 int nvals
= pr
->nvals
;
139 for (x
= 0, i
= 0; i
< pr
->nvals
; i
++) {
140 struct blkid_prval
*v
= &pr
->vals
[i
];
142 if (v
->chain
!= chn
&& x
== i
) {
146 if (v
->chain
== chn
) {
150 memcpy(&pr
->vals
[x
++], v
, sizeof(struct blkid_prval
));
156 * Copies chain values from probing result to @vals, the max size of @vals is
157 * @nvals and returns real number of values.
159 int blkid_probe_chain_copy_vals(blkid_probe pr
, struct blkid_chain
*chn
,
160 struct blkid_prval
*vals
, int nvals
)
164 for (x
= 0, i
= 0; i
< pr
->nvals
&& x
< nvals
; i
++) {
165 struct blkid_prval
*v
= &pr
->vals
[i
];
169 memcpy(&vals
[x
++], v
, sizeof(struct blkid_prval
));
175 * Appends values from @vals to the probing result
177 void blkid_probe_append_vals(blkid_probe pr
, struct blkid_prval
*vals
, int nvals
)
181 while (i
< nvals
&& pr
->nvals
< BLKID_NVALS
) {
182 memcpy(&pr
->vals
[pr
->nvals
++], &vals
[i
++],
183 sizeof(struct blkid_prval
));
187 static void blkid_probe_reset_vals(blkid_probe pr
)
189 memset(pr
->vals
, 0, sizeof(pr
->vals
));
193 struct blkid_chain
*blkid_probe_get_chain(blkid_probe pr
)
195 return pr
->cur_chain
;
198 static void blkid_probe_reset_idx(blkid_probe pr
)
203 void blkid_reset_probe(blkid_probe pr
)
207 DBG(DEBUG_LOWPROBE
, printf("reseting blkid_probe\n"));
209 memset(pr
->buf
, 0, pr
->buf_max
);
213 memset(pr
->sbbuf
, 0, BLKID_SB_BUFSIZ
);
215 blkid_probe_reset_vals(pr
);
216 blkid_probe_reset_idx(pr
);
220 static int blkid_probe_dump_filter(blkid_probe pr, int chain)
222 struct blkid_chain *chn;
225 if (!pr || chain < 0 || chain >= BLKID_NCHAINS)
228 chn = &pr->chains[chain];
233 for (i = 0; i < chn->driver->nidinfos; i++) {
234 const struct blkid_idinfo *id = chn->driver->idinfos[i];
236 DBG(DEBUG_LOWPROBE, printf("%d: %s: %s\n",
239 blkid_bmp_get_item(chn->fltr, i)
240 ? "disabled" : "enabled <--"));
248 * Returns properly initialized chain filter
250 unsigned long *blkid_probe_get_filter(blkid_probe pr
, int chain
, int create
)
252 struct blkid_chain
*chn
;
254 if (!pr
|| chain
< 0 || chain
>= BLKID_NCHAINS
)
257 chn
= &pr
->chains
[chain
];
259 /* always when you touch the chain filter all indexes are reseted and
260 * probing starts from scratch
263 pr
->cur_chain
= NULL
;
265 if (!chn
->driver
->has_fltr
|| (!chn
->fltr
&& !create
))
269 chn
->fltr
= calloc(1, blkid_bmp_nbytes(chn
->driver
->nidinfos
));
271 memset(chn
->fltr
, 0, blkid_bmp_nbytes(chn
->driver
->nidinfos
));
273 /* blkid_probe_dump_filter(pr, chain); */
278 * Generic private functions for filter setting
280 int __blkid_probe_invert_filter(blkid_probe pr
, int chain
)
283 struct blkid_chain
*chn
;
286 fltr
= blkid_probe_get_filter(pr
, chain
, FALSE
);
290 chn
= &pr
->chains
[chain
];
292 for (i
= 0; i
< blkid_bmp_nwords(chn
->driver
->nidinfos
); i
++)
295 DBG(DEBUG_LOWPROBE
, printf("probing filter inverted\n"));
296 /* blkid_probe_dump_filter(pr, chain); */
300 int __blkid_probe_reset_filter(blkid_probe pr
, int chain
)
302 return blkid_probe_get_filter(pr
, chain
, FALSE
) ? 0 : -1;
305 int __blkid_probe_filter_types(blkid_probe pr
, int chain
, int flag
, char *names
[])
308 struct blkid_chain
*chn
;
311 fltr
= blkid_probe_get_filter(pr
, chain
, TRUE
);
315 chn
= &pr
->chains
[chain
];
317 for (i
= 0; i
< chn
->driver
->nidinfos
; i
++) {
319 const struct blkid_idinfo
*id
= chn
->driver
->idinfos
[i
];
322 for (n
= names
; *n
; n
++) {
323 if (!strcmp(id
->name
, *n
)) {
328 if (flag
& BLKID_FLTR_ONLYIN
) {
330 blkid_bmp_set_item(fltr
, i
);
331 } else if (flag
& BLKID_FLTR_NOTIN
) {
333 blkid_bmp_set_item(fltr
, i
);
338 printf("%s: a new probing type-filter initialized\n",
340 /* blkid_probe_dump_filter(pr, chain); */
345 * Note that we have two offsets:
347 * 1/ general device offset (pr->off), that's useful for example when we
348 * probe a partition from whole disk image:
349 * blkid-low --offset <partition_position> disk.img
351 * 2/ buffer offset (the 'off' argument), that useful for offsets in
354 * That means never use lseek(fd, 0, SEEK_SET), the zero position is always
355 * pr->off, so lseek(fd, pr->off, SEEK_SET).
358 unsigned char *blkid_probe_get_buffer(blkid_probe pr
,
359 blkid_loff_t off
, blkid_loff_t len
)
361 ssize_t ret_read
= 0;
363 if (off
< 0 || len
< 0) {
365 printf("unexpected offset or length of buffer requested\n"));
368 if (off
+ len
<= BLKID_SB_BUFSIZ
) {
370 pr
->sbbuf
= malloc(BLKID_SB_BUFSIZ
);
374 if (!pr
->sbbuf_len
) {
375 if (lseek(pr
->fd
, pr
->off
, SEEK_SET
) < 0)
377 ret_read
= read(pr
->fd
, pr
->sbbuf
, BLKID_SB_BUFSIZ
);
380 pr
->sbbuf_len
= ret_read
;
382 if (off
+ len
> pr
->sbbuf_len
)
384 return pr
->sbbuf
+ off
;
386 unsigned char *newbuf
= NULL
;
388 if (len
> pr
->buf_max
) {
389 newbuf
= realloc(pr
->buf
, len
);
397 if (newbuf
|| off
< pr
->buf_off
||
398 off
+ len
> pr
->buf_off
+ pr
->buf_len
) {
400 if (blkid_llseek(pr
->fd
, pr
->off
+ off
, SEEK_SET
) < 0)
403 ret_read
= read(pr
->fd
, pr
->buf
, len
);
404 if (ret_read
!= (ssize_t
) len
)
409 return off
? pr
->buf
+ (off
- pr
->buf_off
) : pr
->buf
;
414 * Assignes the device to probe control struct, resets internal buffers and
415 * reads 512 bytes from device to the buffers.
417 * Returns -1 in case of failure, or 0 on success.
419 int blkid_probe_set_device(blkid_probe pr
, int fd
,
420 blkid_loff_t off
, blkid_loff_t size
)
425 blkid_reset_probe(pr
);
439 if (S_ISBLK(sb
.st_mode
))
440 blkdev_get_size(fd
, (unsigned long long *) &pr
->size
);
442 pr
->size
= sb
.st_size
;
447 /* read SB to test if the device is readable */
448 if (!blkid_probe_get_buffer(pr
, 0, 0x200)) {
450 printf("failed to prepare a device for low-probing\n"));
454 DBG(DEBUG_LOWPROBE
, printf("ready for low-probing, offset=%zd, size=%zd\n",
460 * The blkid_do_probe() calls the probe functions. This routine could be used
461 * in a loop when you need to probe for all possible filesystems/raids.
463 * 1/ basic case -- use the first result:
465 * if (blkid_do_probe(pr) == 0) {
466 * int nvals = blkid_probe_numof_values(pr);
467 * for (n = 0; n < nvals; n++) {
468 * if (blkid_probe_get_value(pr, n, &name, &data, &len) == 0)
469 * printf("%s = %s\n", name, data);
473 * 2/ advanced case -- probe for all signatures (don't forget that some
474 * filesystems can co-exist on one volume (e.g. CD-ROM).
476 * while (blkid_do_probe(pr) == 0) {
477 * int nvals = blkid_probe_numof_values(pr);
481 * The internal probing index (pointer to the last probing function) is
482 * always reseted when you touch probing filter or set a new device. It
483 * means you cannot use:
485 * blkid_probe_invert_filter()
486 * blkid_probe_filter_usage()
487 * blkid_probe_filter_types()
488 * blkid_probe_reset_filter()
489 * blkid_probe_set_device()
491 * in the loop (e.g while()) when you iterate on all signatures.
493 int blkid_do_probe(blkid_probe pr
)
497 if (!pr
|| pr
->idx
< -1)
500 blkid_probe_reset_vals(pr
);
503 printf("--> starting probing loop [idx=%d]\n",
508 for ( ; i
< ARRAY_SIZE(idinfos
); i
++) {
509 const struct blkid_idinfo
*id
;
510 const struct blkid_idmag
*mag
;
515 if (pr
->fltr
&& blkid_bmp_get_item(pr
->fltr
, i
))
519 mag
= id
->magics
? &id
->magics
[0] : NULL
;
521 /* try to detect by magic string */
522 while(mag
&& mag
->magic
) {
526 idx
= mag
->kboff
+ (mag
->sboff
>> 10);
527 buf
= blkid_probe_get_buffer(pr
, idx
<< 10, 1024);
529 if (buf
&& !memcmp(mag
->magic
,
530 buf
+ (mag
->sboff
& 0x3ff), mag
->len
)) {
531 DBG(DEBUG_LOWPROBE
, printf(
532 "%s: magic sboff=%u, kboff=%ld\n",
533 id
->name
, mag
->sboff
, mag
->kboff
));
540 if (hasmag
== 0 && id
->magics
&& id
->magics
[0].magic
)
541 /* magic string(s) defined, but not found */
544 /* final check by probing function */
546 DBG(DEBUG_LOWPROBE
, printf(
547 "%s: call probefunc()\n", id
->name
));
548 if (id
->probefunc(pr
, mag
) != 0)
552 /* all cheks passed */
553 if (pr
->probreq
& BLKID_PROBREQ_TYPE
)
554 blkid_probe_set_value(pr
, "TYPE",
555 (unsigned char *) id
->name
,
556 strlen(id
->name
) + 1);
557 if (pr
->probreq
& BLKID_PROBREQ_USAGE
)
558 blkid_probe_set_usage(pr
, id
->usage
);
561 printf("<-- leaving probing loop (type=%s) [idx=%d]\n",
566 printf("<-- leaving probing loop (failed) [idx=%d]\n",
572 * This is the same function as blkid_do_probe(), but returns only one result
573 * (cannot be used in while()) and checks for ambivalen results (more
574 * filesystems on the device) -- in such case returns -2.
576 * The function does not check for filesystems when a RAID signature is
577 * detected. The function also does not check for collision between RAIDs. The
578 * first detected RAID is returned.
580 int blkid_do_safeprobe(blkid_probe pr
)
582 struct blkid_struct_probe first
;
587 while ((rc
= blkid_do_probe(pr
)) == 0) {
589 /* store the fist result */
590 memcpy(first
.vals
, pr
->vals
, sizeof(first
.vals
));
591 first
.nvals
= pr
->nvals
;
596 if (idinfos
[pr
->idx
]->usage
& BLKID_USAGE_RAID
)
598 if (!(idinfos
[pr
->idx
]->flags
& BLKID_IDINFO_TOLERANT
))
602 return rc
; /* error */
603 if (count
> 1 && intol
) {
605 printf("ERROR: ambivalent result detected (%d filesystems)!\n",
607 return -2; /* error, ambivalent result (more FS) */
610 return 1; /* nothing detected */
612 /* restore the first result */
613 memcpy(pr
->vals
, first
.vals
, sizeof(first
.vals
));
614 pr
->nvals
= first
.nvals
;
620 int blkid_probe_numof_values(blkid_probe pr
)
627 struct blkid_prval
*blkid_probe_assign_value(
628 blkid_probe pr
, const char *name
)
630 struct blkid_prval
*v
;
634 if (pr
->nvals
>= BLKID_NVALS
)
637 v
= &pr
->vals
[pr
->nvals
];
639 v
->chain
= pr
->cur_chain
;
643 printf("assigning %s [%s]\n", name
, v
->chain
->driver
->name
));
647 int blkid_probe_set_value(blkid_probe pr
, const char *name
,
648 unsigned char *data
, size_t len
)
650 struct blkid_prval
*v
;
652 if (len
> BLKID_PROBVAL_BUFSIZ
)
653 len
= BLKID_PROBVAL_BUFSIZ
;
655 v
= blkid_probe_assign_value(pr
, name
);
659 memcpy(v
->data
, data
, len
);
664 int blkid_probe_vsprintf_value(blkid_probe pr
, const char *name
,
665 const char *fmt
, va_list ap
)
667 struct blkid_prval
*v
;
670 v
= blkid_probe_assign_value(pr
, name
);
674 len
= vsnprintf((char *) v
->data
, sizeof(v
->data
), fmt
, ap
);
677 pr
->nvals
--; /* reset the latest assigned value */
684 static int blkid_probe_set_usage(blkid_probe pr
, int usage
)
688 if (usage
& BLKID_USAGE_FILESYSTEM
)
690 else if (usage
& BLKID_USAGE_RAID
)
692 else if (usage
& BLKID_USAGE_CRYPTO
)
694 else if (usage
& BLKID_USAGE_OTHER
)
699 return blkid_probe_set_value(pr
, "USAGE", (unsigned char *) u
, strlen(u
) + 1);
702 int blkid_probe_get_value(blkid_probe pr
, int num
, const char **name
,
703 const char **data
, size_t *len
)
705 struct blkid_prval
*v
;
707 if (pr
== NULL
|| num
< 0 || num
>= pr
->nvals
)
714 *data
= (char *) v
->data
;
718 DBG(DEBUG_LOWPROBE
, printf("returning %s value\n", v
->name
));
722 int blkid_probe_lookup_value(blkid_probe pr
, const char *name
,
723 const char **data
, size_t *len
)
727 if (pr
== NULL
|| pr
->nvals
== 0 || name
== NULL
)
730 for (i
= 0; i
< pr
->nvals
; i
++) {
731 struct blkid_prval
*v
= &pr
->vals
[i
];
733 if (v
->name
&& strcmp(name
, v
->name
) == 0) {
735 *data
= (char *) v
->data
;
738 DBG(DEBUG_LOWPROBE
, printf("returning %s value\n", v
->name
));
745 int blkid_probe_has_value(blkid_probe pr
, const char *name
)
747 if (blkid_probe_lookup_value(pr
, name
, NULL
, NULL
) == 0)
752 struct blkid_prval
*__blkid_probe_get_value(blkid_probe pr
, int num
)
754 if (pr
== NULL
|| num
< 0 || num
>= pr
->nvals
)
757 return &pr
->vals
[num
];
760 struct blkid_prval
*__blkid_probe_lookup_value(blkid_probe pr
, const char *name
)
764 if (pr
== NULL
|| pr
->nvals
== 0 || name
== NULL
)
767 for (i
= 0; i
< pr
->nvals
; i
++) {
768 struct blkid_prval
*v
= &pr
->vals
[i
];
770 if (v
->name
&& strcmp(name
, v
->name
) == 0) {
771 DBG(DEBUG_LOWPROBE
, printf("returning %s value\n", v
->name
));
779 /* converts DCE UUID (uuid[16]) to human readable string
780 * - the @len should be always 37 */
781 void blkid_unparse_uuid(const unsigned char *uuid
, char *str
, size_t len
)
784 uuid_unparse(uuid
, str
);
787 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
788 uuid
[0], uuid
[1], uuid
[2], uuid
[3],
792 uuid
[10], uuid
[11], uuid
[12], uuid
[13], uuid
[14],uuid
[15]);