Exemple #1
0
static int volume_id_probe_linux_raid1(struct volume_id *id, uint64_t off, uint64_t size)
{
	const uint8_t *buf;
	struct mdp1_super_block *mdp1;

	info("probing at offset 0x%" PRIx64 ", size 0x%" PRIx64 "\n", off, size);

	buf = volume_id_get_buffer(id, off, 0x800);
	if (buf == NULL)
		return -1;
	mdp1 = (struct mdp1_super_block *) buf;

	if (le32_to_cpu(mdp1->magic) != MD_SB_MAGIC)
		return -1;

	if (le32_to_cpu(mdp1->major_version) != 1)
		return -1;

	volume_id_set_uuid(id, mdp1->set_uuid, 0, UUID_MD);
	volume_id_set_label_raw(id, mdp1->set_name, 32);
	volume_id_set_label_string(id, mdp1->set_name, 32);
	volume_id_set_usage(id, VOLUME_ID_RAID);
	id->type = "linux_raid_member";
	return 0;
}
Exemple #2
0
int volume_id_probe_sysv(struct volume_id *id, uint64_t off, uint64_t size)
{
	struct sysv_super *vs;
	struct xenix_super *xs;
	unsigned int boff;

	info("probing at offset 0x%llx", (unsigned long long) off);

	for (boff = 0x200; boff <= SYSV_MAX_BLOCKSIZE; boff <<= 1) {
		vs = (struct sysv_super *)
			volume_id_get_buffer(id, off + (boff * SYSV_SUPERBLOCK_BLOCK), 0x200);
		if (vs == NULL)
			return -1;

		if (vs->s_magic == cpu_to_le32(SYSV_MAGIC) || vs->s_magic == cpu_to_be32(SYSV_MAGIC)) {
			volume_id_set_label_raw(id, vs->s_fname, 6);
			volume_id_set_label_string(id, vs->s_fname, 6);
			id->type = "sysv";
			goto found;
		}
	}

	for (boff = 0x200; boff <= SYSV_MAX_BLOCKSIZE; boff <<= 1) {
		xs = (struct xenix_super *)
			volume_id_get_buffer(id, off + (boff + XENIX_SUPERBLOCK_BLOCK), 0x200);
		if (xs == NULL)
			return -1;

		if (xs->s_magic == cpu_to_le32(XENIX_MAGIC) || xs->s_magic == cpu_to_be32(XENIX_MAGIC)) {
			volume_id_set_label_raw(id, xs->s_fname, 6);
			volume_id_set_label_string(id, xs->s_fname, 6);
			id->type = "xenix";
			goto found;
		}
	}

	return -1;

found:
	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
	return 0;
}
Exemple #3
0
int volume_id_probe_ufs(struct volume_id *id, uint64_t off, uint64_t size)
{
	uint32_t magic;
	int i;
	struct ufs_super_block *ufs;
	int offsets[] = {0, 8, 64, 256, -1};

	info("probing at offset 0x%" PRIx64 "\n", off);

	for (i = 0; offsets[i] >= 0; i++) {	
		ufs = (struct ufs_super_block *) volume_id_get_buffer(id, off + (offsets[i] * 0x400), 0x800);
		if (ufs == NULL)
			return -1;

		dbg("offset 0x%x\n", offsets[i] * 0x400);
		magic = be32_to_cpu(ufs->fs_magic);
		if ((magic == UFS_MAGIC) ||
		    (magic == UFS2_MAGIC) ||
		    (magic == UFS_MAGIC_FEA) ||
		    (magic == UFS_MAGIC_LFN)) {
			dbg("magic 0x%08x(be)\n", magic);
			goto found;
		}
		magic = le32_to_cpu(ufs->fs_magic);
		if ((magic == UFS_MAGIC) ||
		    (magic == UFS2_MAGIC) ||
		    (magic == UFS_MAGIC_FEA) ||
		    (magic == UFS_MAGIC_LFN)) {
			dbg("magic 0x%08x(le)\n", magic);
			goto found;
		}
	}
	return -1;

found:
	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
	id->type = "ufs";
	switch (magic) {
	case UFS_MAGIC:
		strcpy(id->type_version, "1");
		break;
	case UFS2_MAGIC:
		strcpy(id->type_version, "2");
		volume_id_set_label_raw(id, ufs->fs_u11.fs_u2.fs_volname, 32);
		volume_id_set_label_string(id, ufs->fs_u11.fs_u2.fs_volname, 32);
		break;
	default:
		break;
	}

	return 0;
}
Exemple #4
0
int volume_id_probe_ext(struct volume_id *id, uint64_t off, uint64_t size)
{
	struct ext2_super_block *es;
	size_t bsize;

	info("probing at offset 0x%llx", (unsigned long long) off);

	es = (struct ext2_super_block *) volume_id_get_buffer(id, off + EXT_SUPERBLOCK_OFFSET, 0x200);
	if (es == NULL)
		return -1;

	if (es->s_magic != cpu_to_le16(EXT_SUPER_MAGIC))
		return -1;

	bsize = 0x400 << le32_to_cpu(es->s_log_block_size);
	dbg("ext blocksize 0x%zx", bsize);
	if (bsize < EXT3_MIN_BLOCK_SIZE || bsize > EXT3_MAX_BLOCK_SIZE) {
		dbg("invalid ext blocksize");
		return -1;
	}

	volume_id_set_label_raw(id, es->s_volume_name, 16);
	volume_id_set_label_string(id, es->s_volume_name, 16);
	volume_id_set_uuid(id, es->s_uuid, 0, UUID_DCE);
	snprintf(id->type_version, sizeof(id->type_version)-1, "%u.%u",
		 le32_to_cpu(es->s_rev_level), le16_to_cpu(es->s_minor_rev_level));

	/* check for external journal device */
	if ((le32_to_cpu(es->s_feature_incompat) & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) != 0) {
		volume_id_set_usage(id, VOLUME_ID_OTHER);
		id->type = "jbd";
		return 0;
	}

	/* check for ext2 / ext3 */
	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
	if ((le32_to_cpu(es->s_feature_compat) & EXT3_FEATURE_COMPAT_HAS_JOURNAL) != 0)
		id->type = "ext3";
	else
		id->type = "ext2";

	return 0;
}
Exemple #5
0
int volume_id_probe_btrfs(struct volume_id *id, uint64_t off, uint64_t size)
{
	const uint8_t *buf;
	struct btrfs_super_block *bfs;

	info("probing at offset 0x%" PRIx64 ", size 0x%" PRIx64 "\n", off, size);

	buf = volume_id_get_buffer(id, off + 0x10000, 0x200);
	if (buf == NULL)
		return -1;
	bfs = (struct btrfs_super_block *)buf;
	if (memcmp(bfs->magic, "_BHRfS_M", 8) != 0)
		return -1;
	volume_id_set_uuid(id, bfs->fsid, 0, UUID_DCE);
	volume_id_set_uuid_sub(id, bfs->dev_item.uuid, 0, UUID_DCE);
	volume_id_set_label_raw(id, bfs->label, 256);
	volume_id_set_label_string(id, bfs->label, 256);
	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
	id->type = "btrfs";
	return 0;
}
Exemple #6
0
int volume_id_probe_hpfs(struct volume_id *id, uint64_t off, uint64_t size)
{
	struct hpfs_super *hs;
	struct hpfs_spare_super *hss;
	struct hpfs_boot_block *hbb;
	uint8_t version;

	info("probing at offset 0x%" PRIx64 "\n", off);

	hs = (struct hpfs_super *) volume_id_get_buffer(id, off + HPFS_SUPERBLOCK_OFFSET, 0x400);
	if (hs == NULL)
		return -1;
	if (memcmp(hs->magic, "\x49\xe8\x95\xf9", 4) != 0)
		return -1;

	hss = (struct hpfs_spare_super *) volume_id_get_buffer(id, off + HPFS_SUPERBLOCK_SPARE_OFFSET, 0x200);
	if (hss == NULL)
		return -1;
	if (memcmp(hss->magic, "\x49\x18\x91\xf9", 4) != 0)
		return -1;

	version = hs->version;

	/* if boot block looks valid, read label and uuid from there */
	hbb = (struct hpfs_boot_block *) volume_id_get_buffer(id, off, 0x200);
	if (hbb == NULL)
		return -1;
	if (memcmp(hbb->magic, "\x55\xaa", 2) == 0 &&
	    memcmp(hbb->sig_hpfs, "HPFS", 4) == 0 &&
	    hbb->sig_28h == 0x28) {
		volume_id_set_label_raw(id, hbb->vol_label, 11);
		volume_id_set_label_string(id, hbb->vol_label, 11);
		volume_id_set_uuid(id, hbb->vol_serno, 0, UUID_DOS);
	}
	sprintf(id->type_version, "%u", version);
	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
	id->type = "hpfs";

	return 0;
}
Exemple #7
0
int volume_id_probe_jfs(struct volume_id *id, uint64_t off, uint64_t size)
{
	struct jfs_super_block *js;

	info("probing at offset 0x%" PRIx64 "\n", off);

	js = (struct jfs_super_block *) volume_id_get_buffer(id, off + JFS_SUPERBLOCK_OFFSET, 0x200);
	if (js == NULL)
		return -1;

	if (memcmp(js->magic, "JFS1", 4) != 0)
		return -1;

	volume_id_set_label_raw(id, js->label, 16);
	volume_id_set_label_string(id, js->label, 16);
	volume_id_set_uuid(id, js->uuid, 0, UUID_DCE);

	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
	id->type = "jfs";

	return 0;
}
Exemple #8
0
int volume_id_probe_iso9660(struct volume_id *id, uint64_t off, uint64_t size)
{
	uint8_t *buf;
	struct iso_volume_descriptor *is;
	struct high_sierra_volume_descriptor *hs;

	info("probing at offset 0x%llx", (unsigned long long) off);

	buf = volume_id_get_buffer(id, off + ISO_SUPERBLOCK_OFFSET, 0x200);
	if (buf == NULL)
		return -1;

	is = (struct iso_volume_descriptor *) buf;

	if (memcmp(is->id, "CD001", 5) == 0) {
		int vd_offset;
		int i;

		dbg("read label from PVD");
		volume_id_set_label_raw(id, is->volume_id, 32);
		volume_id_set_label_string(id, is->volume_id, 32);

		dbg("looking for SVDs");
		vd_offset = ISO_VD_OFFSET;
		for (i = 0; i < ISO_VD_MAX; i++) {
			uint8_t svd_label[64];

			is = (struct iso_volume_descriptor *) volume_id_get_buffer(id, off + vd_offset, 0x200);
			if (is == NULL || is->type == ISO_VD_END)
				break;
			if (is->type != ISO_VD_SUPPLEMENTARY)
				continue;

			dbg("found SVD at offset 0x%llx", (unsigned long long) (off + vd_offset));
			if (memcmp(is->escape_sequences, "%/@", 3) == 0||
			    memcmp(is->escape_sequences, "%/C", 3) == 0||
			    memcmp(is->escape_sequences, "%/E", 3) == 0) {
				dbg("Joliet extension found");
				volume_id_set_unicode16((char *)svd_label, sizeof(svd_label), is->volume_id, BE, 32);
				if (memcmp(id->label, svd_label, 16) == 0) {
					dbg("SVD label is identical, use the possibly longer PVD one");
					break;
				}

				volume_id_set_label_raw(id, is->volume_id, 32);
				volume_id_set_label_string(id, svd_label, 32);
				strcpy(id->type_version, "Joliet Extension");
				goto found;
			}
			vd_offset += ISO_SECTOR_SIZE;
		}
		goto found;
	}

	hs = (struct high_sierra_volume_descriptor *) buf;

	if (memcmp(hs->id, "CDROM", 5) == 0) {
		strcpy(id->type_version, "High Sierra");
		goto found;
	}

	return -1;

found:
	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
	id->type = "iso9660";

	return 0;
}
Exemple #9
0
int volume_id_probe_ntfs(struct volume_id *id, uint64_t off, uint64_t size)
{
	unsigned int sector_size;
	unsigned int cluster_size;
	uint64_t mft_cluster;
	uint64_t mft_off;
	unsigned int mft_record_size;
	unsigned int attr_type;
	unsigned int attr_off;
	unsigned int attr_len;
	unsigned int val_off;
	unsigned int val_len;
	const uint8_t *buf;
	const uint8_t *val;

	info("probing at offset 0x%" PRIx64 "\n", off);

	ns = (struct ntfs_super_block *) volume_id_get_buffer(id, off, 0x200);
	if (ns == NULL)
		return -1;

	if (memcmp(ns->oem_id, "NTFS", 4) != 0)
		return -1;

	volume_id_set_uuid(id, ns->volume_serial, 0, UUID_64BIT_LE);

	sector_size = le16_to_cpu(ns->bytes_per_sector);
	if (sector_size < 0x200)
		return -1;

	cluster_size = ns->sectors_per_cluster * sector_size;
	mft_cluster = le64_to_cpu(ns->mft_cluster_location);
	mft_off = mft_cluster * cluster_size;

	if (ns->cluster_per_mft_record < 0)
		/* size = -log2(mft_record_size); normally 1024 Bytes */
		mft_record_size = 1 << -ns->cluster_per_mft_record;
	else
		mft_record_size = ns->cluster_per_mft_record * cluster_size;

	dbg("sectorsize  0x%x\n", sector_size);
	dbg("clustersize 0x%x\n", cluster_size);
	dbg("mftcluster  %" PRIu64 "\n", mft_cluster);
	dbg("mftoffset  0x%" PRIx64 "\n", mft_off);
	dbg("cluster per mft_record  %i\n", ns->cluster_per_mft_record);
	dbg("mft record size  %i\n", mft_record_size);

	buf = volume_id_get_buffer(id, off + mft_off + (MFT_RECORD_VOLUME * mft_record_size),
			 mft_record_size);
	if (buf == NULL)
		return -1;

	mftr = (struct master_file_table_record*) buf;
	dbg("mftr->magic '%c%c%c%c'\n", mftr->magic[0], mftr->magic[1], mftr->magic[2], mftr->magic[3]);
	if (memcmp(mftr->magic, "FILE", 4) != 0)
		return -1;

	attr_off = le16_to_cpu(mftr->attrs_offset);
	dbg("file $Volume's attributes are at offset %i\n", attr_off);

	while (1) {
		attr = (struct file_attribute*) &buf[attr_off];
		attr_type = le32_to_cpu(attr->type);
		attr_len = le16_to_cpu(attr->len);
		val_off = le16_to_cpu(attr->value_offset);
		val_len = le32_to_cpu(attr->value_len);
		attr_off += attr_len;

		if (attr_len == 0)
			break;

		if (attr_off >= mft_record_size)
			break;

		if (attr_type == MFT_RECORD_ATTR_END)
			break;

		dbg("found attribute type 0x%x, len %i, at offset %i\n",
		    attr_type, attr_len, attr_off);

		if (attr_type == MFT_RECORD_ATTR_VOLUME_INFO) {
			dbg("found info, len %i\n", val_len);
			info = (struct volume_info*) (((uint8_t *) attr) + val_off);
			snprintf(id->type_version, sizeof(id->type_version)-1,
				 "%u.%u", info->major_ver, info->minor_ver);
		}

		if (attr_type == MFT_RECORD_ATTR_VOLUME_NAME) {
			dbg("found label, len %i\n", val_len);
			if (val_len > VOLUME_ID_LABEL_SIZE)
				val_len = VOLUME_ID_LABEL_SIZE;

			val = ((uint8_t *) attr) + val_off;
			volume_id_set_label_raw(id, val, val_len);
			volume_id_set_label_unicode16(id, val, LE, val_len);
		}
	}

	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
	id->type = "ntfs";
	/* we think this is ntfs, but we make sure no other signatures are found */
	id->force_unique_result = 1;
	return 0;
}