Ejemplo n.º 1
0
/*
 * Look for LABEL (name) in the FAT root directory.
 */
static unsigned char *search_fat_label(blkid_probe pr,
				uint64_t offset, uint32_t entries)
{
	struct vfat_dir_entry *ent, *dir = NULL;
	uint32_t i;

	DBG(DEBUG_LOWPROBE,
		printf("\tlook for label in root-dir "
			"(entries: %d, offset: %jd)\n", entries, offset));

	if (!blkid_probe_is_tiny(pr)) {
		/* large disk, read whole root directory */
		dir = (struct vfat_dir_entry *)
			blkid_probe_get_buffer(pr,
					offset,
					(blkid_loff_t) entries *
						sizeof(struct vfat_dir_entry));
		if (!dir)
			return NULL;
	}

	for (i = 0; i < entries; i++) {
		/*
		 * The root directory could be relatively large (4-16kB).
		 * Fortunately, the LABEL is usually the first entry in the
		 * directory. On tiny disks we call read() per entry.
		 */
		if (!dir)
			ent = (struct vfat_dir_entry *)
				blkid_probe_get_buffer(pr,
					(blkid_loff_t) offset + (i *
						sizeof(struct vfat_dir_entry)),
					sizeof(struct vfat_dir_entry));
		else
			ent = &dir[i];

		if (!ent || ent->name[0] == 0x00)
			break;

		if ((ent->name[0] == FAT_ENTRY_FREE) ||
		    (ent->cluster_high != 0 || ent->cluster_low != 0) ||
		    ((ent->attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME))
			continue;

		if ((ent->attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) ==
		    FAT_ATTR_VOLUME_ID) {
			DBG(DEBUG_LOWPROBE,
				printf("\tfound fs LABEL at entry %d\n", i));
			return ent->name;
		}
	}
	return NULL;
}
Ejemplo n.º 2
0
/*
 * 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.
 *
 * 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)
{
	struct list_head vals;
	int idx = -1;
	int count = 0;
	int intol = 0;
	int rc;

	INIT_LIST_HEAD(&vals);

	if (pr->flags & BLKID_FL_NOSCAN_DEV)
		return BLKID_PROBE_NONE;

	while ((rc = superblocks_probe(pr, chn)) == 0) {

		if (blkid_probe_is_tiny(pr) && !count)
			return BLKID_PROBE_OK;	/* floppy or so -- returns the first result. */

		count++;

		if (chn->idx >= 0 &&
		    idinfos[chn->idx]->usage & (BLKID_USAGE_RAID | BLKID_USAGE_CRYPTO))
			break;

		if (chn->idx >= 0 &&
		    !(idinfos[chn->idx]->flags & BLKID_IDINFO_TOLERANT))
			intol++;

		if (count == 1) {
			/* save the first result */
			blkid_probe_chain_save_values(pr, chn, &vals);
			idx = chn->idx;
		}
	}

	if (rc < 0)
		goto done;		/* error */

	if (count > 1 && intol) {
		DBG(LOWPROBE, ul_debug("ERROR: superblocks chain: "
			       "ambivalent result detected (%d filesystems)!",
			       count));
		rc = -2;		/* error, ambivalent result (more FS) */
		goto done;
	}
	if (!count) {
		rc = BLKID_PROBE_NONE;
		goto done;
	}

	if (idx != -1) {
		/* restore the first result */
		blkid_probe_chain_reset_values(pr, chn);
		blkid_probe_append_values_list(pr, &vals);
		chn->idx = idx;
	}

	/*
	 * The RAID device could be partitioned. The problem are RAID1 devices
	 * where the partition table is visible from underlaying devices. We
	 * have to ignore such partition tables.
	 */
	if (chn->idx >= 0 && idinfos[chn->idx]->usage & BLKID_USAGE_RAID)
		pr->prob_flags |= BLKID_PROBE_FL_IGNORE_PT;

	rc = BLKID_PROBE_OK;
done:
	blkid_probe_free_values_list(&vals);
	return rc;
}
Ejemplo n.º 3
0
/*
 * The blkid_do_probe() backend.
 */
static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn)
{
	size_t i;
	int rc = BLKID_PROBE_NONE;

	if (!pr || chn->idx < -1)
		return -EINVAL;

	blkid_probe_chain_reset_values(pr, chn);

	if (pr->flags & BLKID_FL_NOSCAN_DEV)
		return BLKID_PROBE_NONE;

	if (pr->size <= 0 || (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 BLKID_PROBE_NONE;

	DBG(LOWPROBE, ul_debug("--> starting probing loop [SUBLKS idx=%d]",
		chn->idx));

	i = chn->idx < 0 ? 0 : chn->idx + 1U;

	for ( ; i < ARRAY_SIZE(idinfos); i++) {
		const struct blkid_idinfo *id;
		const struct blkid_idmag *mag = NULL;
		uint64_t off = 0;

		chn->idx = i;
		id = idinfos[i];

		if (chn->fltr && blkid_bmp_get_item(chn->fltr, i)) {
			DBG(LOWPROBE, ul_debug("filter out: %s", id->name));
			rc = BLKID_PROBE_NONE;
			continue;
		}

		if (id->minsz && id->minsz > pr->size) {
			rc = BLKID_PROBE_NONE;
			continue;	/* the device is too small */
		}

		/* don't probe for RAIDs, swap or journal on CD/DVDs */
		if ((id->usage & (BLKID_USAGE_RAID | BLKID_USAGE_OTHER)) &&
		    blkid_probe_is_cdrom(pr)) {
			rc = BLKID_PROBE_NONE;
			continue;
		}

		/* don't probe for RAIDs on floppies */
		if ((id->usage & BLKID_USAGE_RAID) && blkid_probe_is_tiny(pr)) {
			rc = BLKID_PROBE_NONE;
			continue;
		}

		DBG(LOWPROBE, ul_debug("[%zd] %s:", i, id->name));

		rc = blkid_probe_get_idmag(pr, id, &off, &mag);
		if (rc < 0)
			break;
		if (rc != BLKID_PROBE_OK)
			continue;

		/* final check by probing function */
		if (id->probefunc) {
			DBG(LOWPROBE, ul_debug("\tcall probefunc()"));
			rc = id->probefunc(pr, mag);
			if (rc != BLKID_PROBE_OK) {
				blkid_probe_chain_reset_values(pr, chn);
				if (rc < 0)
					break;
				continue;
			}
		}

		/* all cheks passed */
		if (chn->flags & BLKID_SUBLKS_TYPE)
			rc = blkid_probe_set_value(pr, "TYPE",
				(unsigned char *) id->name,
				strlen(id->name) + 1);

		if (!rc)
			rc = blkid_probe_set_usage(pr, id->usage);

		if (!rc && mag)
			rc = blkid_probe_set_magic(pr, off, mag->len,
					(unsigned char *) mag->magic);
		if (rc) {
			blkid_probe_chain_reset_values(pr, chn);
			DBG(LOWPROBE, ul_debug("failed to set result -- ignore"));
			continue;
		}

		DBG(LOWPROBE, ul_debug("<-- leaving probing loop (type=%s) [SUBLKS idx=%d]",
			id->name, chn->idx));
		return BLKID_PROBE_OK;
	}

	DBG(LOWPROBE, ul_debug("<-- leaving probing loop (failed=%d) [SUBLKS idx=%d]",
			rc, chn->idx));
	return rc;
}
Ejemplo n.º 4
0
/*
 * 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.
 *
 * 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)
{
	struct blkid_prval vals[BLKID_NVALS_SUBLKS];
	int nvals = BLKID_NVALS_SUBLKS;
	int idx = -1;
	int count = 0;
	int intol = 0;
	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;

		count++;

		if (chn->idx >= 0 &&
		    idinfos[chn->idx]->usage & (BLKID_USAGE_RAID | BLKID_USAGE_CRYPTO))
			break;

		if (chn->idx >= 0 &&
		    !(idinfos[chn->idx]->flags & BLKID_IDINFO_TOLERANT))
			intol++;

		if (count == 1) {
			/* save the first result */
			nvals = blkid_probe_chain_copy_vals(pr, chn, vals, nvals);
			idx = chn->idx;
		}
	}

	if (rc < 0)
		return rc;		/* error */

	if (count > 1 && intol) {
		DBG(LOWPROBE, ul_debug("ERROR: superblocks chain: "
			       "ambivalent result detected (%d filesystems)!",
			       count));
		return -2;		/* error, ambivalent result (more FS) */
	}
	if (!count)
		return 1;		/* nothing detected */

	if (idx != -1) {
		/* restore the first result */
		blkid_probe_chain_reset_vals(pr, chn);
		blkid_probe_append_vals(pr, vals, nvals);
		chn->idx = idx;
	}

	/*
	 * The RAID device could be partitioned. The problem are RAID1 devices
	 * where the partition table is visible from underlaying devices. We
	 * have to ignore such partition tables.
	 */
	if (chn->idx >= 0 && idinfos[chn->idx]->usage & BLKID_USAGE_RAID)
		pr->prob_flags |= BLKID_PROBE_FL_IGNORE_PT;

	return 0;
}