예제 #1
0
파일: exfat.c 프로젝트: JohnLih/util-linux
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
/* iso9660 [+ Microsoft Joliet Extension] */
static int probe_iso9660(blkid_probe pr, const struct blkid_idmag *mag)
{
	struct iso_volume_descriptor *iso;
	unsigned char label[32];
	int i;
	int off;

	if (strcmp(mag->magic, "CDROM") == 0)
		return probe_iso9660_hsfs(pr, mag);

	iso = blkid_probe_get_sb(pr, mag, struct iso_volume_descriptor);
	if (!iso)
		return -1;

	memcpy(label, iso->volume_id, sizeof(label));

	/* Joliet Extension */
	off = ISO_VD_OFFSET;
	for (i = 0; i < ISO_VD_MAX; i++) {
		iso = (struct iso_volume_descriptor *)
			blkid_probe_get_buffer(pr,
					off,
					sizeof(struct iso_volume_descriptor));

		if (iso == NULL || iso->vd_type == ISO_VD_END)
			break;
		if (iso->vd_type != ISO_VD_SUPPLEMENTARY)
			continue;

		if (memcmp(iso->escape_sequences, "%/@", 3) == 0 ||
		    memcmp(iso->escape_sequences, "%/C", 3) == 0 ||
		    memcmp(iso->escape_sequences, "%/E", 3) == 0) {

			blkid_probe_set_version(pr, "Joliet Extension");

			/* Is the Joliet (UTF16BE) label equal to the label in
			 * the PVD? If yes, use PVD label.  The Jolied version
			 * of the label could be trimed (because UTF16..).
			 */
			if (ascii_eq_utf16be(label, iso->volume_id, 32))
				break;

			blkid_probe_set_utf8label(pr,
					iso->volume_id,
					sizeof(iso->volume_id),
					BLKID_ENC_UTF16BE);
			goto has_label;
		}
		off += ISO_SECTOR_SIZE;
	}

	/* Joliet not found, let use standard iso label */
	blkid_probe_set_label(pr, label, sizeof(label));

has_label:
	return 0;
}
예제 #3
0
static int probe_hfsplus(blkid_probe pr, const struct blkid_idmag *mag)
{
	struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
	struct hfsplus_bnode_descriptor *descr;
	struct hfsplus_bheader_record *bnode;
	struct hfsplus_catalog_key *key;
	struct hfsplus_vol_header *hfsplus;
	struct hfs_mdb *sbd;
	unsigned int alloc_block_size;
	unsigned int alloc_first_block;
	unsigned int embed_first_block;
	unsigned int off = 0;
	unsigned int blocksize;
	unsigned int cat_block;
	unsigned int ext_block_start;
	unsigned int ext_block_count;
	unsigned int record_count;
	unsigned int leaf_node_head;
	unsigned int leaf_node_count;
	unsigned int leaf_node_size;
	unsigned int leaf_block;
	int ext;
	uint64_t leaf_off;
	unsigned char *buf;

	sbd = blkid_probe_get_sb(pr, mag, struct hfs_mdb);
	if (!sbd)
		return -1;

	/* Check for a HFS+ volume embedded in a HFS volume */
	if (memcmp(sbd->signature, "BD", 2) == 0) {
		if ((memcmp(sbd->embed_sig, "H+", 2) != 0) &&
		    (memcmp(sbd->embed_sig, "HX", 2) != 0))
			/* This must be an HFS volume, so fail */
			return 1;

		alloc_block_size = be32_to_cpu(sbd->al_blk_size);
		alloc_first_block = be16_to_cpu(sbd->al_bl_st);
		embed_first_block = be16_to_cpu(sbd->embed_startblock);
		off = (alloc_first_block * 512) +
			(embed_first_block * alloc_block_size);

		buf = blkid_probe_get_buffer(pr,
				off + (mag->kboff * 1024),
				sizeof(struct hfsplus_vol_header));
		hfsplus = (struct hfsplus_vol_header *) buf;

	} else
		hfsplus = blkid_probe_get_sb(pr, mag,
				struct hfsplus_vol_header);

	if (!hfsplus)
		return -1;

	if ((memcmp(hfsplus->signature, "H+", 2) != 0) &&
	    (memcmp(hfsplus->signature, "HX", 2) != 0))
		return 1;

	hfs_set_uuid(pr, hfsplus->finder_info.id, sizeof(hfsplus->finder_info.id));

	blocksize = be32_to_cpu(hfsplus->blocksize);
	if (blocksize < HFSPLUS_SECTOR_SIZE)
		return -1;

	memcpy(extents, hfsplus->cat_file.extents, sizeof(extents));
	cat_block = be32_to_cpu(extents[0].start_block);

	buf = blkid_probe_get_buffer(pr,
			off + ((blkid_loff_t) cat_block * blocksize), 0x2000);
	if (!buf)
		return 0;

	bnode = (struct hfsplus_bheader_record *)
		&buf[sizeof(struct hfsplus_bnode_descriptor)];

	leaf_node_head = be32_to_cpu(bnode->leaf_head);
	leaf_node_size = be16_to_cpu(bnode->node_size);
	leaf_node_count = be32_to_cpu(bnode->leaf_count);
	if (leaf_node_count == 0)
		return 0;

	leaf_block = (leaf_node_head * leaf_node_size) / blocksize;

	/* get physical location */
	for (ext = 0; ext < HFSPLUS_EXTENT_COUNT; ext++) {
		ext_block_start = be32_to_cpu(extents[ext].start_block);
		ext_block_count = be32_to_cpu(extents[ext].block_count);
		if (ext_block_count == 0)
			return 0;

		/* this is our extent */
		if (leaf_block < ext_block_count)
			break;

		leaf_block -= ext_block_count;
	}
	if (ext == HFSPLUS_EXTENT_COUNT)
		return 0;

	leaf_off = (ext_block_start + leaf_block) * blocksize;

	buf = blkid_probe_get_buffer(pr,
				(blkid_loff_t) off + leaf_off,
				leaf_node_size);
	if (!buf)
		return 0;

	descr = (struct hfsplus_bnode_descriptor *) buf;
	record_count = be16_to_cpu(descr->num_recs);
	if (record_count == 0)
		return 0;

	if (descr->type != HFS_NODE_LEAF)
		return 0;

	key = (struct hfsplus_catalog_key *)
		&buf[sizeof(struct hfsplus_bnode_descriptor)];

	if (be32_to_cpu(key->parent_id) != HFSPLUS_POR_CNID)
		return 0;

	blkid_probe_set_utf8label(pr, key->unicode,
			be16_to_cpu(key->unicode_len) * 2,
			BLKID_ENC_UTF16BE);
	return 0;
}