Beispiel #1
0
static int volume_id_probe_linux_raid0(struct volume_id *id, uint64_t off, uint64_t size)
{
	const uint8_t *buf;
	struct mdp0_super_block *mdp0;
	union {
		uint32_t ints[4];
		uint8_t bytes[16];
	} uuid;

	info("probing at offset 0x%" PRIx64 ", size 0x%" PRIx64 "\n", off, size);
	if (size < 0x10000)
		return -1;

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

	if (le32_to_cpu(mdp0->md_magic) == MD_SB_MAGIC) {
		uuid.ints[0] = bswap_32(mdp0->set_uuid0);
		if (le32_to_cpu(mdp0->minor_version >= 90)) {
			uuid.ints[1] = bswap_32(mdp0->set_uuid1);
			uuid.ints[2] = bswap_32(mdp0->set_uuid2);
			uuid.ints[3] = bswap_32(mdp0->set_uuid3);
		} else {
			uuid.ints[1] = 0;
			uuid.ints[2] = 0;
			uuid.ints[3] = 0;
		}
		volume_id_set_uuid(id, uuid.bytes, 0, UUID_MD);
		snprintf(id->type_version, sizeof(id->type_version)-1, "%u.%u.%u",
			 le32_to_cpu(mdp0->major_version),
			 le32_to_cpu(mdp0->minor_version),
			 le32_to_cpu(mdp0->patch_version));
	} else if (be32_to_cpu(mdp0->md_magic) == MD_SB_MAGIC) {
		uuid.ints[0] = mdp0->set_uuid0;
		if (be32_to_cpu(mdp0->minor_version >= 90)) {
			uuid.ints[1] = mdp0->set_uuid1;
			uuid.ints[2] = mdp0->set_uuid2;
			uuid.ints[3] = mdp0->set_uuid3;
		} else {
			uuid.ints[1] = 0;
			uuid.ints[2] = 0;
			uuid.ints[3] = 0;
		}
		volume_id_set_uuid(id, uuid.bytes, 0, UUID_MD);
		snprintf(id->type_version, sizeof(id->type_version)-1, "%u.%u.%u",
			 be32_to_cpu(mdp0->major_version),
			 be32_to_cpu(mdp0->minor_version),
			 be32_to_cpu(mdp0->patch_version));
	} else
		return -1;

	volume_id_set_usage(id, VOLUME_ID_RAID);
	id->type = "linux_raid_member";
	return 0;
}
int FAST_FUNC volume_id_probe_btrfs(struct volume_id *id /*,uint64_t off*/)
{
	// btrfs has superblocks at 64K, 64M and 256G
	// minimum btrfs size is 256M
	// so we never step out the device if we analyze
	// the first and the second superblocks
	struct btrfs_super_block *sb;
	unsigned off = 64;

	while (off < 64*1024*1024) {
		off *= 1024;
		dbg("btrfs: probing at offset 0x%x", off);

		sb = volume_id_get_buffer(id, off, sizeof(*sb));
		if (sb == NULL)
			return -1;

		if (memcmp(sb->magic, BTRFS_MAGIC, 8) != 0)
			return -1;
	}

	// N.B.: btrfs natively supports 256 (>VOLUME_ID_LABEL_SIZE) size labels
	volume_id_set_label_string(id, sb->label, VOLUME_ID_LABEL_SIZE);
	volume_id_set_uuid(id, sb->fsid, UUID_DCE);

	return 0;
}
Beispiel #3
0
int FAST_FUNC volume_id_probe_f2fs(struct volume_id *id /*,uint64_t off*/)
{
	struct f2fs_super_block *sb;

	// Go for primary super block (ignore second sb)
	dbg("f2fs: probing at offset 0x%x", F2FS_SB1_OFFSET);
	sb = volume_id_get_buffer(id, F2FS_SB1_OFFSET, sizeof(*sb));

	if (!sb)
		return -1;

	if (sb->magic != cpu_to_le32(F2FS_MAGIC))
		return -1;

	IF_FEATURE_BLKID_TYPE(id->type = "f2fs");

	// For version 1.0 we don't know sb structure and can't set label/uuid
	if (sb->major_ver == cpu_to_le16(1) && sb->minor_ver == cpu_to_le16(0))
		return 0;

	volume_id_set_label_unicode16(id, (uint8_t *)sb->volume_name,
				      LE, MIN(F2FS_LABEL_BYTES, VOLUME_ID_LABEL_SIZE));

	volume_id_set_uuid(id, sb->uuid, UUID_DCE);

	return 0;
}
Beispiel #4
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;
}
Beispiel #5
0
int volume_id_probe_ext(struct volume_id *id, uint64_t off)
{
    struct ext2_super_block *es;

    dbg("ext: probing at offset 0x%llx", (unsigned long long) off);

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

    if (es->magic[0] != 0123 || es->magic[1] != 0357) {
        dbg("ext: no magic found");
        return -1;
    }

//	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
//	volume_id_set_label_raw(id, es->volume_name, 16);
    volume_id_set_label_string(id, es->volume_name, 16);
    volume_id_set_uuid(id, es->uuid, UUID_DCE);
    dbg("ext: label '%s' uuid '%s'", id->label, id->uuid);

//	if ((le32_to_cpu(es->feature_compat) & EXT3_FEATURE_COMPAT_HAS_JOURNAL) != 0)
//		id->type = "ext3";
//	else
//		id->type = "ext2";

    return 0;
}
Beispiel #6
0
int volume_id_probe_lvm2(struct volume_id *id, uint64_t off, uint64_t size)
{
	const uint8_t *buf;
	unsigned int soff;
	struct lvm2_super_block *lvm;
	struct lvm2_pv_header *pvhdr;

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

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


	for (soff = 0; soff < LVM2LABEL_SCAN_SECTORS * 0x200; soff += 0x200) {
		lvm = (struct lvm2_super_block *) &buf[soff];

		if (memcmp(lvm->id, LVM2_LABEL_ID, 8) == 0)
			goto found;
	}

	return -1;

found:
	dbg("found at offset 0x%x (pv hdr offset 0x%x)\n",
	    soff, cpu_to_le32(lvm->offset_xl));
	soff += cpu_to_le32(lvm->offset_xl);
	pvhdr = (struct lvm2_pv_header *) &buf[soff];
	memcpy(id->type_version, lvm->type, 8);
	volume_id_set_usage(id, VOLUME_ID_RAID);
	volume_id_set_uuid(id, pvhdr->id, 0, UUID_LVM);
	id->type = "LVM2_member";

	return 0;
}
Beispiel #7
0
int FAST_FUNC volume_id_probe_nilfs(struct volume_id *id /*,uint64_t off*/)
{
	struct nilfs2_super_block *sb;

	// Primary super block
	dbg("nilfs: probing at offset 0x%x", NILFS_SB1_OFFSET);

	sb = volume_id_get_buffer(id, NILFS_SB1_OFFSET, sizeof(*sb));

	if (sb == NULL)
		return -1;

	if (sb->s_magic != NILFS_MAGIC)
		return -1;

	// The secondary superblock is not always used, so ignore it for now.
	// When used it is at 4K from the end of the partition (sb->s_dev_size - NILFS_SB2_OFFSET).

	volume_id_set_label_string(id, sb->s_volume_name, NILFS_LABEL_SIZE < VOLUME_ID_LABEL_SIZE ?
				NILFS_LABEL_SIZE : VOLUME_ID_LABEL_SIZE);
	volume_id_set_uuid(id, sb->s_uuid, UUID_DCE);

	if (sb->s_rev_level == 2)
		IF_FEATURE_BLKID_TYPE(id->type = "nilfs2");

	return 0;
}
Beispiel #8
0
int volume_id_probe_luks(struct volume_id *id, uint64_t off, uint64_t size)
{
	struct luks_phdr *header;

	header = (struct luks_phdr*) volume_id_get_buffer(id, off, LUKS_PHDR_SIZE);
	if (header == NULL)
		return -1;

	if (memcmp(header->magic, LUKS_MAGIC, LUKS_MAGIC_L))
		return -1;

	volume_id_set_usage(id, VOLUME_ID_CRYPTO);
	volume_id_set_uuid(id, header->uuid, 36, UUID_HEX_STRING);
	id->type = "crypto_LUKS";
	return 0;
}
int FAST_FUNC volume_id_probe_linux_swap(struct volume_id *id /*,uint64_t off*/)
{
#define off ((uint64_t)0)
	struct swap_header_v1_2 *sw;
	const uint8_t *buf;
	unsigned page;

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

	/* the swap signature is at the end of the PAGE_SIZE */
	for (page = 0x1000; page <= LARGEST_PAGESIZE; page <<= 1) {
			buf = volume_id_get_buffer(id, off + page-10, 10);
			if (buf == NULL)
				return -1;

			if (memcmp(buf, "SWAP-SPACE", 10) == 0) {
//				id->type_version[0] = '1';
//				id->type_version[1] = '\0';
				goto found;
			}

			if (memcmp(buf, "SWAPSPACE2", 10) == 0
			 || memcmp(buf, "S1SUSPEND", 9) == 0
			 || memcmp(buf, "S2SUSPEND", 9) == 0
			 || memcmp(buf, "ULSUSPEND", 9) == 0
			) {
				sw = volume_id_get_buffer(id, off, sizeof(struct swap_header_v1_2));
				if (sw == NULL)
					return -1;
//				id->type_version[0] = '2';
//				id->type_version[1] = '\0';
//				volume_id_set_label_raw(id, sw->volume_name, 16);
				volume_id_set_label_string(id, sw->volume_name, 16);
				volume_id_set_uuid(id, sw->uuid, UUID_DCE);
				goto found;
			}
	}
	return -1;

found:
//	volume_id_set_usage(id, VOLUME_ID_OTHER);
//	id->type = "swap";

	return 0;
}
Beispiel #10
0
int FAST_FUNC volume_id_probe_luks(struct volume_id *id /*,uint64_t off*/)
{
#define off ((uint64_t)0)
	struct luks_phdr *header;

	header = volume_id_get_buffer(id, off, sizeof(*header));
	if (header == NULL)
		return -1;

	if (memcmp(header->magic, LUKS_MAGIC, LUKS_MAGIC_L))
		return -1;

//	volume_id_set_usage(id, VOLUME_ID_CRYPTO);
	volume_id_set_uuid(id, header->uuid, UUID_DCE_STRING);
	id->type = "crypto_LUKS";

	return 0;
}
Beispiel #11
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;
}
Beispiel #12
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;
}
Beispiel #13
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;
}
Beispiel #14
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;
}
Beispiel #15
0
int volume_id_probe_jfs(struct volume_id *id, uint64_t off)
{
	struct jfs_super_block *js;

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

	js = 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, UUID_DCE);

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

	return 0;
}
Beispiel #16
0
int volume_id_probe_netware(struct volume_id *id, uint64_t off, uint64_t size)
{
	struct netware_super_block *nw;

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

	nw = (struct netware_super_block *) volume_id_get_buffer(id, off + NW_SUPERBLOCK_OFFSET, 0x200);
	if (nw == NULL)
		return -1;

	if (memcmp(nw->SBH_Signature, "SPB5", 4) != 0)
		return -1;

	volume_id_set_uuid(id, nw->SBH_PoolID, 0, UUID_DCE);

	snprintf(id->type_version, sizeof(id->type_version)-1, "%u.%02u",
		 le16_to_cpu(nw->SBH_VersionMediaMajor), le16_to_cpu(nw->SBH_VersionMediaMinor));

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

	return 0;
}
Beispiel #17
0
int volume_id_probe_ocfs2(struct volume_id *id, uint64_t off)
{
	struct ocfs2_super_block *os;

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

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

	if (memcmp(os->i_signature, "OCFSV2", 6) != 0) {
		return -1;
	}

//	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
//	volume_id_set_label_raw(id, os->s_label, OCFS2_MAX_VOL_LABEL_LEN < VOLUME_ID_LABEL_SIZE ?
//					OCFS2_MAX_VOL_LABEL_LEN : VOLUME_ID_LABEL_SIZE);
	volume_id_set_label_string(id, os->s_label, OCFS2_MAX_VOL_LABEL_LEN < VOLUME_ID_LABEL_SIZE ?
					OCFS2_MAX_VOL_LABEL_LEN : VOLUME_ID_LABEL_SIZE);
	volume_id_set_uuid(id, os->s_uuid, UUID_DCE);
//	id->type = "ocfs2";
	return 0;
}
Beispiel #18
0
int FAST_FUNC volume_id_probe_vfat(struct volume_id *id /*,uint64_t fat_partition_off*/)
{
#define fat_partition_off ((uint64_t)0)
	struct vfat_super_block *vs;
	struct vfat_dir_entry *dir;
	uint16_t sector_size_bytes;
	uint16_t dir_entries;
	uint32_t sect_count;
	uint16_t reserved_sct;
	uint32_t fat_size_sct;
	uint32_t root_cluster;
	uint32_t dir_size_sct;
	uint32_t cluster_count;
	uint64_t root_start_off;
	uint32_t start_data_sct;
	uint8_t *buf;
	uint32_t buf_size;
	uint8_t *label = NULL;
	uint32_t next_cluster;
	int maxloop;

	dbg("probing at offset 0x%llx", (unsigned long long) fat_partition_off);

	vs = volume_id_get_buffer(id, fat_partition_off, 0x200);
	if (vs == NULL)
		return -1;

	/* believe only that's fat, don't trust the version
	 * the cluster_count will tell us
	 */
	if (memcmp(vs->sysid, "NTFS", 4) == 0)
		return -1;

	if (memcmp(vs->type.fat32.magic, "MSWIN", 5) == 0)
		goto valid;

	if (memcmp(vs->type.fat32.magic, "FAT32   ", 8) == 0)
		goto valid;

	if (memcmp(vs->type.fat.magic, "FAT16   ", 8) == 0)
		goto valid;

	if (memcmp(vs->type.fat.magic, "MSDOS", 5) == 0)
		goto valid;

	if (memcmp(vs->type.fat.magic, "FAT12   ", 8) == 0)
		goto valid;

	/*
	 * There are old floppies out there without a magic, so we check
	 * for well known values and guess if it's a fat volume
	 */

	/* boot jump address check */
	if ((vs->boot_jump[0] != 0xeb || vs->boot_jump[2] != 0x90)
	 && vs->boot_jump[0] != 0xe9
	) {
		return -1;
	}

	/* heads check */
	if (vs->heads == 0)
		return -1;

	/* cluster size check */
	if (vs->sectors_per_cluster == 0
	 || (vs->sectors_per_cluster & (vs->sectors_per_cluster-1))
	) {
		return -1;
	}

	/* media check */
	if (vs->media < 0xf8 && vs->media != 0xf0)
		return -1;

	/* fat count*/
	if (vs->fats != 2)
		return -1;

 valid:
	/* sector size check */
	sector_size_bytes = le16_to_cpu(vs->sector_size_bytes);
	if (sector_size_bytes != 0x200 && sector_size_bytes != 0x400
	 && sector_size_bytes != 0x800 && sector_size_bytes != 0x1000
	) {
		return -1;
	}

	dbg("sector_size_bytes 0x%x", sector_size_bytes);
	dbg("sectors_per_cluster 0x%x", vs->sectors_per_cluster);

	reserved_sct = le16_to_cpu(vs->reserved_sct);
	dbg("reserved_sct 0x%x", reserved_sct);

	sect_count = le16_to_cpu(vs->sectors);
	if (sect_count == 0)
		sect_count = le32_to_cpu(vs->total_sect);
	dbg("sect_count 0x%x", sect_count);

	fat_size_sct = le16_to_cpu(vs->fat_length);
	if (fat_size_sct == 0)
		fat_size_sct = le32_to_cpu(vs->type.fat32.fat32_length);
	fat_size_sct *= vs->fats;
	dbg("fat_size_sct 0x%x", fat_size_sct);

	dir_entries = le16_to_cpu(vs->dir_entries);
	dir_size_sct = ((dir_entries * sizeof(struct vfat_dir_entry)) +
			(sector_size_bytes-1)) / sector_size_bytes;
	dbg("dir_size_sct 0x%x", dir_size_sct);

	cluster_count = sect_count - (reserved_sct + fat_size_sct + dir_size_sct);
	cluster_count /= vs->sectors_per_cluster;
	dbg("cluster_count 0x%x", cluster_count);

//	if (cluster_count < FAT12_MAX) {
//		strcpy(id->type_version, "FAT12");
//	} else if (cluster_count < FAT16_MAX) {
//		strcpy(id->type_version, "FAT16");
//	} else {
//		strcpy(id->type_version, "FAT32");
//		goto fat32;
//	}
	if (cluster_count >= FAT16_MAX)
		goto fat32;

	/* the label may be an attribute in the root directory */
	root_start_off = (reserved_sct + fat_size_sct) * sector_size_bytes;
	dbg("root dir start 0x%llx", (unsigned long long) root_start_off);
	dbg("expected entries 0x%x", dir_entries);

	buf_size = dir_entries * sizeof(struct vfat_dir_entry);
	buf = volume_id_get_buffer(id, fat_partition_off + root_start_off, buf_size);
	if (buf == NULL)
		goto ret;

	label = get_attr_volume_id((struct vfat_dir_entry*) buf, dir_entries);

	vs = volume_id_get_buffer(id, fat_partition_off, 0x200);
	if (vs == NULL)
		return -1;

	if (label != NULL && memcmp(label, "NO NAME    ", 11) != 0) {
//		volume_id_set_label_raw(id, label, 11);
		volume_id_set_label_string(id, label, 11);
	} else if (memcmp(vs->type.fat.label, "NO NAME    ", 11) != 0) {
//		volume_id_set_label_raw(id, vs->type.fat.label, 11);
		volume_id_set_label_string(id, vs->type.fat.label, 11);
	}
	volume_id_set_uuid(id, vs->type.fat.serno, UUID_DOS);
	goto ret;

 fat32:
	/* FAT32 root dir is a cluster chain like any other directory */
	buf_size = vs->sectors_per_cluster * sector_size_bytes;
	root_cluster = le32_to_cpu(vs->type.fat32.root_cluster);
	start_data_sct = reserved_sct + fat_size_sct;

	next_cluster = root_cluster;
	maxloop = 100;
	while (--maxloop) {
		uint64_t next_off_sct;
		uint64_t next_off;
		uint64_t fat_entry_off;
		int count;

		dbg("next_cluster 0x%x", (unsigned)next_cluster);
		next_off_sct = (uint64_t)(next_cluster - 2) * vs->sectors_per_cluster;
		next_off = (start_data_sct + next_off_sct) * sector_size_bytes;
		dbg("cluster offset 0x%llx", (unsigned long long) next_off);

		/* get cluster */
		buf = volume_id_get_buffer(id, fat_partition_off + next_off, buf_size);
		if (buf == NULL)
			goto ret;

		dir = (struct vfat_dir_entry*) buf;
		count = buf_size / sizeof(struct vfat_dir_entry);
		dbg("expected entries 0x%x", count);

		label = get_attr_volume_id(dir, count);
		if (label)
			break;

		/* get FAT entry */
		fat_entry_off = (reserved_sct * sector_size_bytes) + (next_cluster * sizeof(uint32_t));
		dbg("fat_entry_off 0x%llx", (unsigned long long)fat_entry_off);
		buf = volume_id_get_buffer(id, fat_partition_off + fat_entry_off, buf_size);
		if (buf == NULL)
			goto ret;

		/* set next cluster */
		next_cluster = le32_to_cpu(*(uint32_t*)buf) & 0x0fffffff;
		if (next_cluster < 2 || next_cluster > FAT32_MAX)
			break;
	}
	if (maxloop == 0)
		dbg("reached maximum follow count of root cluster chain, give up");

	vs = volume_id_get_buffer(id, fat_partition_off, 0x200);
	if (vs == NULL)
		return -1;

	if (label != NULL && memcmp(label, "NO NAME    ", 11) != 0) {
//		volume_id_set_label_raw(id, label, 11);
		volume_id_set_label_string(id, label, 11);
	} else if (memcmp(vs->type.fat32.label, "NO NAME    ", 11) != 0) {
//		volume_id_set_label_raw(id, vs->type.fat32.label, 11);
		volume_id_set_label_string(id, vs->type.fat32.label, 11);
	}
	volume_id_set_uuid(id, vs->type.fat32.serno, UUID_DOS);

 ret:
//	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
//	id->type = "vfat";

	return 0;
}
Beispiel #19
0
int volume_id_probe_ntfs(struct volume_id *id /*,uint64_t off*/)
{
#define off ((uint64_t)0)
	unsigned sector_size;
	unsigned cluster_size;
	uint64_t mft_cluster;
	uint64_t mft_off;
	unsigned mft_record_size;
	unsigned attr_type;
	unsigned attr_off;
	unsigned attr_len;
	unsigned val_off;
	unsigned val_len;
	struct master_file_table_record *mftr;
	struct ntfs_super_block *ns;
	const uint8_t *buf;
	const uint8_t *val;

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

	ns = 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, UUID_NTFS);

	sector_size = le16_to_cpu(ns->bytes_per_sector);
	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", sector_size);
	dbg("clustersize 0x%x", cluster_size);
	dbg("mftcluster  %llu", (unsigned long long) mft_cluster);
	dbg("mftoffset  0x%llx", (unsigned long long) mft_off);
	dbg("cluster per mft_record  %i", ns->cluster_per_mft_record);
	dbg("mft record size  %i", mft_record_size);

	buf = volume_id_get_buffer(id, off + mft_off + (MFT_RECORD_VOLUME * mft_record_size),
			 mft_record_size);
	if (buf == NULL)
		goto found;

	mftr = (struct master_file_table_record*) buf;

	dbg("mftr->magic '%c%c%c%c'", mftr->magic[0], mftr->magic[1], mftr->magic[2], mftr->magic[3]);
	if (memcmp(mftr->magic, "FILE", 4) != 0)
		goto found;

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

	while (1) {
		struct file_attribute *attr;

		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",
		    attr_type, attr_len, attr_off);

//		if (attr_type == MFT_RECORD_ATTR_VOLUME_INFO) {
//			struct volume_info *info;
//			dbg("found info, len %i", 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", 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);
		}
	}

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

	return 0;
}
Beispiel #20
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;
}