示例#1
0
static int probe_exfat(blkid_probe pr, const struct blkid_idmag *mag)
{
	struct exfat_super_block *sb;
	struct exfat_entry_label *label;

	sb = blkid_probe_get_sb(pr, mag, struct exfat_super_block);
	if (!sb || !CLUSTER_SIZE(sb))
		return errno ? -errno : BLKID_PROBE_NONE;

	label = find_label(pr, sb);
	if (label)
		blkid_probe_set_utf8label(pr, label->name,
				min(label->length * 2, 30), BLKID_ENC_UTF16LE);
	else if (errno)
		return -errno;

	blkid_probe_sprintf_uuid(pr, sb->volume_serial, 4,
			"%02hhX%02hhX-%02hhX%02hhX",
			sb->volume_serial[3], sb->volume_serial[2],
			sb->volume_serial[1], sb->volume_serial[0]);

	blkid_probe_sprintf_version(pr, "%u.%u",
			sb->version.vermaj, sb->version.vermin);

	return BLKID_PROBE_OK;
}
示例#2
0
文件: zfs.c 项目: ArakniD/util-linux
static void zfs_extract_guid_name(blkid_probe pr, loff_t offset)
{
	struct nvlist *nvl;
	struct nvpair *nvp;
	size_t left = 4096;
	int found = 0;

	offset = (offset & ~(VDEV_LABEL_SIZE - 1)) + VDEV_LABEL_NVPAIR;

	/* Note that we currently assume that the desired fields are within
	 * the first 4k (left) of the nvlist.  This is true for all pools
	 * I've seen, and simplifies this code somewhat, because we don't
	 * have to handle an nvpair crossing a buffer boundary. */
	nvl = (struct nvlist *)blkid_probe_get_buffer(pr, offset, left);
	if (nvl == NULL)
		return;

	nvdebug("zfs_extract: nvlist offset %llu\n", offset);

	nvp = &nvl->nvl_nvpair;
	while (left > sizeof(*nvp) && nvp->nvp_size != 0 && found < 3) {
		int avail;   /* tracks that name/value data fits in nvp_size */
		int namesize;

		nvp->nvp_size = be32_to_cpu(nvp->nvp_size);
		nvp->nvp_namelen = be32_to_cpu(nvp->nvp_namelen);
		avail = nvp->nvp_size - nvp->nvp_namelen - sizeof(*nvp);

		nvdebug("left %zd nvp_size %u\n", left, nvp->nvp_size);
		if (left < nvp->nvp_size || avail < 0)
			break;

		namesize = (nvp->nvp_namelen + 3) & ~3;

		nvdebug("nvlist: size %u, namelen %u, name %*s\n",
			nvp->nvp_size, nvp->nvp_namelen, nvp->nvp_namelen,
			nvp->nvp_name);
		if (strncmp(nvp->nvp_name, "name", nvp->nvp_namelen) == 0) {
			struct nvstring *nvs = (void *)(nvp->nvp_name+namesize);

			nvs->nvs_type = be32_to_cpu(nvs->nvs_type);
			nvs->nvs_strlen = be32_to_cpu(nvs->nvs_strlen);
			if (nvs->nvs_strlen > UINT_MAX - sizeof(*nvs))
				break;
			avail -= nvs->nvs_strlen + sizeof(*nvs);
			nvdebug("nvstring: type %u string %*s\n", nvs->nvs_type,
				nvs->nvs_strlen, nvs->nvs_string);
			if (nvs->nvs_type == DATA_TYPE_STRING && avail >= 0)
				blkid_probe_set_label(pr, nvs->nvs_string,
						      nvs->nvs_strlen);
			found++;
		} else if (strncmp(nvp->nvp_name, "guid",
				   nvp->nvp_namelen) == 0) {
			struct nvuint64 *nvu = (void *)(nvp->nvp_name+namesize);
			uint64_t nvu_value;

			memcpy(&nvu_value, &nvu->nvu_value, sizeof(nvu_value));
			nvu->nvu_type = be32_to_cpu(nvu->nvu_type);
			nvu_value = be64_to_cpu(nvu_value);
			avail -= sizeof(*nvu);
			nvdebug("nvuint64: type %u value %"PRIu64"\n",
				nvu->nvu_type, nvu_value);
			if (nvu->nvu_type == DATA_TYPE_UINT64 && avail >= 0)
				blkid_probe_sprintf_value(pr, "UUID_SUB",
							  "%"PRIu64, nvu_value);
			found++;
		} else if (strncmp(nvp->nvp_name, "pool_guid",
				   nvp->nvp_namelen) == 0) {
			struct nvuint64 *nvu = (void *)(nvp->nvp_name+namesize);
			uint64_t nvu_value;

			memcpy(&nvu_value, &nvu->nvu_value, sizeof(nvu_value));
			nvu->nvu_type = be32_to_cpu(nvu->nvu_type);
			nvu_value = be64_to_cpu(nvu_value);
			avail -= sizeof(*nvu);
			nvdebug("nvuint64: type %u value %"PRIu64"\n",
				nvu->nvu_type, nvu_value);
			if (nvu->nvu_type == DATA_TYPE_UINT64 && avail >= 0)
				blkid_probe_sprintf_uuid(pr, (unsigned char *)
							 &nvu_value,
							 sizeof(nvu_value),
							 "%"PRIu64, nvu_value);
			found++;
		}
		if (left > nvp->nvp_size)
			left -= nvp->nvp_size;
		else
			left = 0;
		nvp = (struct nvpair *)((char *)nvp + nvp->nvp_size);
	}
}
示例#3
0
文件: vfat.c 项目: Artox/fstools
/* FAT label extraction from the root directory taken from Kay
 * Sievers's volume_id library */
static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag)
{
	struct vfat_super_block *vs;
	struct msdos_super_block *ms;
	const unsigned char *vol_label = 0;
	unsigned char *vol_serno = NULL, vol_label_buf[11];
	uint16_t sector_size = 0, reserved;
	uint32_t cluster_count, fat_size;
	const char *version = NULL;

	ms = blkid_probe_get_sb(pr, mag, struct msdos_super_block);
	if (!ms)
		return errno ? -errno : 1;

	vs = blkid_probe_get_sb(pr, mag, struct vfat_super_block);
	if (!vs)
		return errno ? -errno : 1;

	if (!fat_valid_superblock(pr, mag, ms, vs, &cluster_count, &fat_size))
		return 1;

	sector_size = unaligned_le16(&ms->ms_sector_size);
	reserved =  le16_to_cpu(ms->ms_reserved);

	if (ms->ms_fat_length) {
		/* the label may be an attribute in the root directory */
		uint32_t root_start = (reserved + fat_size) * sector_size;
		uint32_t root_dir_entries = unaligned_le16(&vs->vs_dir_entries);

		vol_label = search_fat_label(pr, root_start, root_dir_entries);
		if (vol_label) {
			memcpy(vol_label_buf, vol_label, 11);
			vol_label = vol_label_buf;
		}

		if (!vol_label || !memcmp(vol_label, no_name, 11))
			vol_label = ms->ms_label;
		vol_serno = ms->ms_serno;

		blkid_probe_set_value(pr, "SEC_TYPE", (unsigned char *) "msdos",
                              sizeof("msdos"));

		if (cluster_count < FAT12_MAX)
			version = "FAT12";
		else if (cluster_count < FAT16_MAX)
			version = "FAT16";

	} else if (vs->vs_fat32_length) {
		unsigned char *buf;
		uint16_t fsinfo_sect;
		int maxloop = 100;

		/* Search the FAT32 root dir for the label attribute */
		uint32_t buf_size = vs->vs_cluster_size * sector_size;
		uint32_t start_data_sect = reserved + fat_size;
		uint32_t entries = le32_to_cpu(vs->vs_fat32_length) *
					sector_size / sizeof(uint32_t);
		uint32_t next = le32_to_cpu(vs->vs_root_cluster);

		while (next && next < entries && --maxloop) {
			uint32_t next_sect_off;
			uint64_t next_off, fat_entry_off;
			int count;

			next_sect_off = (next - 2) * vs->vs_cluster_size;
			next_off = (uint64_t)(start_data_sect + next_sect_off) *
				sector_size;

			count = buf_size / sizeof(struct vfat_dir_entry);

			vol_label = search_fat_label(pr, next_off, count);
			if (vol_label) {
				memcpy(vol_label_buf, vol_label, 11);
				vol_label = vol_label_buf;
				break;
			}

			/* get FAT entry */
			fat_entry_off = ((uint64_t) reserved * sector_size) +
				(next * sizeof(uint32_t));
			buf = blkid_probe_get_buffer(pr, fat_entry_off, buf_size);
			if (buf == NULL)
				break;

			/* set next cluster */
			next = le32_to_cpu(*((uint32_t *) buf)) & 0x0fffffff;
		}

		version = "FAT32";

		if (!vol_label || !memcmp(vol_label, no_name, 11))
			vol_label = vs->vs_label;
		vol_serno = vs->vs_serno;

		/*
		 * FAT32 should have a valid signature in the fsinfo block,
		 * but also allow all bytes set to '\0', because some volumes
		 * do not set the signature at all.
		 */
		fsinfo_sect = le16_to_cpu(vs->vs_fsinfo_sector);
		if (fsinfo_sect) {
			struct fat32_fsinfo *fsinfo;

			buf = blkid_probe_get_buffer(pr,
					(blkid_loff_t) fsinfo_sect * sector_size,
					sizeof(struct fat32_fsinfo));
			if (buf == NULL)
				return errno ? -errno : 1;

			fsinfo = (struct fat32_fsinfo *) buf;
			if (memcmp(fsinfo->signature1, "\x52\x52\x61\x41", 4) != 0 &&
			    memcmp(fsinfo->signature1, "\x52\x52\x64\x41", 4) != 0 &&
			    memcmp(fsinfo->signature1, "\x00\x00\x00\x00", 4) != 0)
				return 1;
			if (memcmp(fsinfo->signature2, "\x72\x72\x41\x61", 4) != 0 &&
			    memcmp(fsinfo->signature2, "\x00\x00\x00\x00", 4) != 0)
				return 1;
		}
	}

	if (vol_label && memcmp(vol_label, no_name, 11))
		blkid_probe_set_label(pr, (unsigned char *) vol_label, 11);

	/* We can't just print them as %04X, because they are unaligned */
	if (vol_serno)
		blkid_probe_sprintf_uuid(pr, vol_serno, 4, "%02X%02X-%02X%02X",
			vol_serno[3], vol_serno[2], vol_serno[1], vol_serno[0]);
	if (version)
		blkid_probe_set_version(pr, version);

	return 0;
}