예제 #1
0
파일: isw_raid.c 프로젝트: AllardJ/Tomato
int volume_id_probe_intel_software_raid(struct volume_id *id, uint64_t off, uint64_t size)
{
	const uint8_t *buf;
	uint64_t meta_off;
	struct isw_meta *isw;

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

	if (size < 0x10000)
		return -1;

	meta_off = ((size / 0x200)-2) * 0x200;
	buf = volume_id_get_buffer(id, off + meta_off, 0x200);
	if (buf == NULL)
		return -1;

	isw = (struct isw_meta *) buf;
	if (memcmp(isw->sig, ISW_SIGNATURE, sizeof(ISW_SIGNATURE)-1) != 0)
		return -1;

	volume_id_set_usage(id, VOLUME_ID_RAID);
	memcpy(id->type_version, &isw->sig[sizeof(ISW_SIGNATURE)-1], 6);
	id->type = "isw_raid_member";

	return 0;
}
예제 #2
0
파일: linux_raid.c 프로젝트: OPSF/uClinux
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;
}
예제 #3
0
파일: lvm.c 프로젝트: OPSF/uClinux
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;
}
예제 #4
0
파일: squashfs.c 프로젝트: OPSF/uClinux
int volume_id_probe_squashfs(struct volume_id *id, uint64_t off, uint64_t size)
{
	struct squashfs_super *sqs;

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

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

	if (sqs->s_magic == SQUASHFS_MAGIC || sqs->s_magic == SQUASHFS_MAGIC_LZMA) {
		snprintf(id->type_version, sizeof(id->type_version), "%u.%u",
			 sqs->s_major, sqs->s_minor);
		goto found;
	}
	if (sqs->s_magic == bswap_32(SQUASHFS_MAGIC) || sqs->s_magic == bswap_32(SQUASHFS_MAGIC_LZMA)) {
		snprintf(id->type_version, sizeof(id->type_version), "%u.%u",
			 bswap_16(sqs->s_major), bswap_16(sqs->s_minor));
		goto found;
	}

	return -1;

found:
	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
	id->type = "squashfs";
	return 0;
}
예제 #5
0
파일: highpoint.c 프로젝트: OPSF/uClinux
int volume_id_probe_highpoint_45x_raid(struct volume_id *id, uint64_t off, uint64_t size)
{
	const uint8_t *buf;
	struct hpt45x_meta *hpt;
	uint64_t meta_off;
	uint32_t magic;

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

	if (size < 0x10000)
		return -1;

	meta_off = ((size / 0x200)-11) * 0x200;
	buf = volume_id_get_buffer(id, off + meta_off, 0x200);
	if (buf == NULL)
		return -1;

	hpt = (struct hpt45x_meta *) buf;
	magic = le32_to_cpu(hpt->magic);
	if (magic != HPT45X_MAGIC_OK && magic != HPT45X_MAGIC_BAD)
		return -1;

	volume_id_set_usage(id, VOLUME_ID_RAID);
	id->type = "highpoint_raid_member";

	return 0;
}
예제 #6
0
파일: linux_raid.c 프로젝트: OPSF/uClinux
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;
}
예제 #7
0
파일: ext.c 프로젝트: AllardJ/Tomato
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;
}
예제 #8
0
파일: ufs.c 프로젝트: OPSF/uClinux
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;
}
예제 #9
0
파일: minix.c 프로젝트: OPSF/uClinux
int volume_id_probe_minix(struct volume_id *id, uint64_t off, uint64_t size)
{
	uint8_t *buf;
	struct minix_super_block *ms;
	struct minix3_super_block *m3s;

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

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

	ms = (struct minix_super_block *) buf;

	if (ms->s_magic == MINIX_SUPER_MAGIC ||
	    ms->s_magic == bswap_16(MINIX_SUPER_MAGIC)) {
		strcpy(id->type_version, "1");
		goto found;
	}
	if (ms->s_magic == MINIX_SUPER_MAGIC2 ||
	    ms->s_magic == bswap_16(MINIX_SUPER_MAGIC2)) {
		strcpy(id->type_version, "1");
		goto found;
	}
	if (ms->s_magic == MINIX2_SUPER_MAGIC ||
	    ms->s_magic == bswap_16(MINIX2_SUPER_MAGIC)) {
		strcpy(id->type_version, "2");
		goto found;
	}
	if (ms->s_magic == MINIX2_SUPER_MAGIC2 ||
	    ms->s_magic == bswap_16(MINIX2_SUPER_MAGIC2)) {
		strcpy(id->type_version, "2");
		goto found;
	}

	m3s = (struct minix3_super_block *) buf;
	if (m3s->s_magic == MINIX3_SUPER_MAGIC ||
	    m3s->s_magic == bswap_16(MINIX3_SUPER_MAGIC)) {
		strcpy(id->type_version, "3");
		goto found;
	}
	goto exit;

found:
	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
	id->type = "minix";
	return 0;

exit:
	return -1;
}
예제 #10
0
파일: luks.c 프로젝트: AllardJ/Tomato
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;
}
예제 #11
0
파일: sysv.c 프로젝트: AllardJ/Tomato
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;
}
예제 #12
0
파일: hpfs.c 프로젝트: AllardJ/Tomato
int volume_id_probe_hpfs(struct volume_id *id, uint64_t off, uint64_t size)
{
	struct hpfs_super *hs;

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

	hs = (struct hpfs_super *) volume_id_get_buffer(id, off + HPFS_SUPERBLOCK_OFFSET, 0x200);
	if (hs == NULL)
		return -1;

	if (memcmp(hs->magic, "\x49\xe8\x95\xf9", 4) == 0) {
		sprintf(id->type_version, "%u", hs->version);

		volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
		id->type = "hpfs";
		return 0;
	}

	return -1;
}
예제 #13
0
파일: btrfs.c 프로젝트: OPSF/uClinux
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;
}
예제 #14
0
파일: lvm.c 프로젝트: OPSF/uClinux
int volume_id_probe_lvm1(struct volume_id *id, uint64_t off, uint64_t size)
{
	const uint8_t *buf;
	struct lvm1_super_block *lvm;

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

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

	lvm = (struct lvm1_super_block *) buf;

	if (memcmp(lvm->id, LVM1_MAGIC, 2) != 0)
		return -1;

	volume_id_set_usage(id, VOLUME_ID_RAID);
	id->type = "LVM1_member";

	return 0;
}
예제 #15
0
파일: minix.c 프로젝트: jhbsz/DIR-850L_A1
int volume_id_probe_minix(struct volume_id *id, uint64_t off, uint64_t size)
{
	struct minix_super_block *ms;

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

	ms = (struct minix_super_block *) volume_id_get_buffer(id, off + MINIX_SUPERBLOCK_OFFSET, 0x200);
	if (ms == NULL)
		return -1;

	if (le16_to_cpu(ms->s_magic) == 0x137f) {
		strcpy(id->type_version, "1");
		goto found;
	}

	if (le16_to_cpu(ms->s_magic) == 0x1387) {
		strcpy(id->type_version, "1");
		goto found;
	}

	if (le16_to_cpu(ms->s_magic) == 0x2468) {
		strcpy(id->type_version, "2");
		goto found;
	}

	if (le16_to_cpu(ms->s_magic) == 0x2478) {
		strcpy(id->type_version, "2");
		goto found;
	}

	goto exit;

found:
	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
	id->type = "minix";
	return 0;

exit:
	return -1;
}
예제 #16
0
파일: hpfs.c 프로젝트: OPSF/uClinux
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;
}
예제 #17
0
파일: jfs.c 프로젝트: OPSF/uClinux
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;
}
예제 #18
0
파일: highpoint.c 프로젝트: OPSF/uClinux
int volume_id_probe_highpoint_37x_raid(struct volume_id *id, uint64_t off, uint64_t size)
{
	const uint8_t *buf;
	struct hpt37x_meta *hpt;
	uint32_t magic;

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

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

	hpt = (struct hpt37x_meta *) buf;
	magic = le32_to_cpu(hpt->magic);
	if (magic != HPT37X_MAGIC_OK && magic != HPT37X_MAGIC_BAD)
		return -1;

	volume_id_set_usage(id, VOLUME_ID_RAID);
	id->type = "highpoint_raid_member";

	return 0;
}
예제 #19
0
파일: netware.c 프로젝트: OPSF/uClinux
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;
}
예제 #20
0
파일: ntfs.c 프로젝트: OPSF/uClinux
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;
}
예제 #21
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;
}