int nvals, n;
size_t len;
int fd;
+ int rc = 0;
fd = open(devname, O_RDONLY);
if (fd < 0) {
if (blkid_probe_set_device(pr, fd, offset, size))
goto error;
- if (blkid_do_probe(pr))
+ rc = blkid_do_safeprobe(pr);
+ if (rc)
goto error;
nvals = blkid_probe_numof_values(pr);
print_value(output, n + 1, NULL, (char *) data, name, len);
}
+ close(fd);
return 0;
error:
+ if (rc == -2)
+ fprintf(stderr, "%s: ambivalent result "
+ "(probably more filesystems on the device)\n",
+ devname);
close(fd);
return -1;
}
extern int blkid_probe_reset_filter(blkid_probe pr);
extern int blkid_do_probe(blkid_probe pr);
+extern int blkid_do_safeprobe(blkid_probe pr);
+
extern int blkid_probe_numof_values(blkid_probe pr);
extern int blkid_probe_get_value(blkid_probe pr, int num, const char **name,
unsigned char **data, size_t *len);
blkid_devno_to_devname;
blkid_dev_set_search;
blkid_do_probe;
+ blkid_do_safeprobe;
blkid_encode_string;
blkid_find_dev_with_tag;
blkid_free_probe;
*/
struct blkid_idinfo
{
- const char *name; /* FS/RAID name */
- int usage; /* BLKID_USAGE_* flag */
+ const char *name; /* FS/RAID name */
+ int usage; /* BLKID_USAGE_* flag */
+ int flags; /* BLKID_IDINFO_* flags */
- /* probe function */
+ /* probe function */
int (*probefunc)(blkid_probe pr, const struct blkid_idmag *mag);
struct blkid_idmag magics[]; /* NULL or array with magic strings */
#define BLKID_NONE_MAGIC {{ NULL }}
+/*
+ * tolerant FS - can share the same device with more filesystems (e.g. typical
+ * on CD-ROMs). We need this flag to detect ambivalent results (e.g. valid fat
+ * and valid linux swap on the same device).
+ */
+#define BLKID_IDINFO_TOLERANT (1 << 1)
+
/*
* Minimum number of seconds between device probes, even when reading
* from the cache. This is to avoid re-probing all devices which were
memset(pr->buf, 0, pr->buf_max);
pr->buf_off = 0;
pr->buf_len = 0;
+ pr->idx = 0;
if (pr->sbbuf)
memset(pr->sbbuf, 0, BLKID_SB_BUFSIZ);
pr->sbbuf_len = 0;
DBG(DEBUG_LOWPROBE, printf("*** starting probing loop\n"));
- for (i = 0; i < ARRAY_SIZE(idinfos); i++) {
+ for ( ; i < ARRAY_SIZE(idinfos); i++) {
const struct blkid_idinfo *id;
const struct blkid_idmag *mag;
int hasmag = 0;
return 1;
}
+/*
+ * This is the same function as blkid_do_probe(), but returns only one result
+ * (cannot be used in while()) and checks for ambivalen results (more
+ * filesystems on the device) -- in such case returns -2.
+ */
+int blkid_do_safeprobe(blkid_probe pr)
+{
+ struct blkid_struct_probe first;
+ int count = 0;
+ int intol = 0;
+ int rc;
+
+ while ((rc = blkid_do_probe(pr)) == 0) {
+ if (!count) {
+ /* store the fist result */
+ memcpy(first.vals, pr->vals, sizeof(first.vals));
+ first.nvals = pr->nvals;
+ first.idx = pr->idx;
+ }
+ if (!(idinfos[pr->idx]->flags & BLKID_IDINFO_TOLERANT))
+ intol++;
+ count++;
+ }
+ if (rc < 0)
+ return rc; /* error */
+ if (count > 1 && intol)
+ return -2; /* error, ambivalent result (more FS) */
+ if (!count)
+ return 1; /* nothing detected */
+
+ /* restore the first result */
+ memcpy(pr->vals, first.vals, sizeof(first.vals));
+ pr->nvals = first.nvals;
+ pr->idx = first.idx;
+
+ return 0;
+}
+
int blkid_probe_numof_values(blkid_probe pr)
{
if (!pr)
.name = "iso9660",
.usage = BLKID_USAGE_FILESYSTEM,
.probefunc = probe_iso9660,
+ .flags = BLKID_IDINFO_TOLERANT,
.magics =
{
{ .magic = "CD001", .len = 5, .kboff = 32, .sboff = 1 },
.name = "udf",
.usage = BLKID_USAGE_FILESYSTEM,
.probefunc = probe_udf,
+ .flags = BLKID_IDINFO_TOLERANT,
.magics =
{
{ .magic = "BEA01", .len = 5, .kboff = 32, .sboff = 1 },
/*
* Probe for all types.
*/
- if (blkid_do_probe(cache->probe)) {
- /* found nothing */
+ if (blkid_do_safeprobe(cache->probe)) {
+ /* found nothing or error */
blkid_free_dev(dev);
dev = NULL;
}