extern void blkid_free_dev(blkid_dev dev);
/* probe.c */
-unsigned char *blkid_probe_get_buffer(blkid_probe pr,
+extern int blkid_probe_is_tiny(blkid_probe pr);
+
+extern unsigned char *blkid_probe_get_buffer(blkid_probe pr,
blkid_loff_t off, blkid_loff_t len);
extern unsigned char *blkid_probe_get_sector(blkid_probe pr, unsigned int sector);
}
/*
+ * @off: offset within probing area
+ * @len: size of requested buffer
+ *
+ * The probing area is between pr->off and pr->size. The @off = 0 is pr->off, the
+ * max @len is pr->size.
+ *
* Note that we have two offsets:
*
* 1/ general device offset (pr->off), that's useful for example when we
* probe a partition from whole disk image:
- * blkid-low --offset <partition_position> disk.img
+ * blkid -O <partition_position> -S <size> disk.img
*
- * 2/ buffer offset (the 'off' argument), that useful for offsets in
+ * 2/ buffer offset (the @off argument), that useful for offsets in
* superbloks, ...
*
- * That means never use lseek(fd, 0, SEEK_SET), the zero position is always
- * pr->off, so lseek(fd, pr->off, SEEK_SET).
+ * That means never use lseek(fd, 0, SEEK_SET), the zero position is always
+ * pr->off, so lseek(fd, pr->off, SEEK_SET).
*
*/
unsigned char *blkid_probe_get_buffer(blkid_probe pr,
printf("unexpected offset or length of buffer requested\n"));
return NULL;
}
+
+ if (off + len > pr->size)
+ return NULL;
+
+ DBG(DEBUG_LOWPROBE,
+ printf("\tbuffer: offset=%jd size=%jd\n", off, len));
+
if (off + len <= BLKID_SB_BUFSIZ) {
if (!pr->sbbuf) {
pr->sbbuf = malloc(BLKID_SB_BUFSIZ);
}
if (newbuf || off < pr->buf_off ||
off + len > pr->buf_off + pr->buf_len) {
-
if (blkid_llseek(pr->fd, pr->off + off, SEEK_SET) < 0)
return NULL;
}
}
+/*
+ * Small devices need a special care.
+ */
+int blkid_probe_is_tiny(blkid_probe pr)
+{
+ return (pr && pr->size <= 1440 * 1024 && !S_ISCHR(pr->mode));
+}
+
/**
* blkid_probe_set_device:
* @pr: probe
if (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode))
pr->devno = sb.st_rdev;
+
+ if (pr->off > pr->size)
+ goto err;
+
+ /* The probing area cannot be larger than whole device, pr->off
+ * is offset within the device */
+ pr->size -= pr->off;
}
if (!pr->size)
printf("--> starting probing loop [SUBLKS idx=%d]\n",
chn->idx));
+ if (pr->size <= 1024 && !S_ISCHR(pr->mode))
+ /* Ignore very very small block devices or regular files (e.g.
+ * extended partitions). Note that size of the UBI char devices
+ * is 1 byte */
+ return 1;
+
i = chn->idx + 1;
for ( ; i < ARRAY_SIZE(idinfos); i++) {
id = idinfos[i];
mag = id->magics ? &id->magics[0] : NULL;
+ /* don't probe for RAIDs on floppies */
+ if ((id->usage & BLKID_USAGE_RAID) && blkid_probe_is_tiny(pr))
+ continue;
+
+ DBG(DEBUG_LOWPROBE, printf("[%d] %s:\n", i, id->name));
+
/* try to detect by magic string */
while(mag && mag->magic) {
unsigned char *buf;
if (buf && !memcmp(mag->magic,
buf + (mag->sboff & 0x3ff), mag->len)) {
DBG(DEBUG_LOWPROBE, printf(
- "%s: magic sboff=%u, kboff=%ld\n",
- id->name, mag->sboff, mag->kboff));
+ "\tmagic sboff=%u, kboff=%ld\n",
+ mag->sboff, mag->kboff));
hasmag = 1;
off += mag->sboff & 0x3ff;
break;
/* final check by probing function */
if (id->probefunc) {
- DBG(DEBUG_LOWPROBE, printf(
- "%s: call probefunc()\n", id->name));
+ DBG(DEBUG_LOWPROBE, printf("\tcall probefunc()\n"));
if (id->probefunc(pr, mag) != 0)
continue;
}
* The function does not check for filesystems when a RAID or crypto signature
* is detected. The function also does not check for collision between RAIDs
* and crypto devices. The first detected RAID or crypto device is returned.
+ *
+ * The function does not probe for ambivalent results on very small devices
+ * (e.g. floppies), on small devices the first detected filesystem is returned.
*/
static int superblocks_safeprobe(blkid_probe pr, struct blkid_chain *chn)
{
int rc;
while ((rc = superblocks_probe(pr, chn)) == 0) {
+
+ if (blkid_probe_is_tiny(pr) && !count)
+ /* floppy or so -- returns the first result. */
+ return 0;
+
if (!count) {
/* save the first result */
nvals = blkid_probe_chain_copy_vals(pr, chn, vals, nvals);