/*
 * MS-DOS partition parsing code
 *
 * Copyright (C) 2009 Karel Zak <kzak@redhat.com>
 *
 * This file may be redistributed under the terms of the
 * GNU Lesser General Public License.
 *
 * Inspired by fdisk, partx, Linux kernel and libparted.
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>

#include "partitions.h"
#include "dos.h"
#include "aix.h"
#include "fat.h"

static const struct dos_subtypes {
	unsigned char type;
	const struct blkid_idinfo *id;
} dos_nested[] = {
	{ BLKID_FREEBSD_PARTITION, &bsd_pt_idinfo },
	{ BLKID_NETBSD_PARTITION, &bsd_pt_idinfo },
	{ BLKID_OPENBSD_PARTITION, &bsd_pt_idinfo },
	{ BLKID_UNIXWARE_PARTITION, &unixware_pt_idinfo },
	{ BLKID_SOLARIS_X86_PARTITION, &solaris_x86_pt_idinfo },
	{ BLKID_MINIX_PARTITION, &minix_pt_idinfo }
};

static inline int is_extended(struct dos_partition *p)
{
	return (p->sys_type == BLKID_DOS_EXTENDED_PARTITION ||
		p->sys_type == BLKID_W95_EXTENDED_PARTITION ||
		p->sys_type == BLKID_LINUX_EXTENDED_PARTITION);
}

static int parse_dos_extended(blkid_probe pr, blkid_parttable tab,
		uint32_t ex_start, uint32_t ex_size, int ssf)
{
	blkid_partlist ls = blkid_probe_get_partlist(pr);
	uint32_t cur_start = ex_start, cur_size = ex_size;
	unsigned char *data;
	int ct_nodata = 0;	/* count ext.partitions without data partitions */
	int i;

	while (1) {
		struct dos_partition *p, *p0;
		uint32_t start, size;

		if (++ct_nodata > 100)
			return 0;
		data = blkid_probe_get_sector(pr, cur_start);
		if (!data)
			goto leave;	/* malformed partition? */

		if (!is_valid_mbr_signature(data))
			goto leave;

		p0 = (struct dos_partition *) (data + BLKID_MSDOS_PT_OFFSET);

		/* Usually, the first entry is the real data partition,
		 * the 2nd entry is the next extended partition, or empty,
		 * and the 3rd and 4th entries are unused.
		 * However, DRDOS sometimes has the extended partition as
		 * the first entry (when the data partition is empty),
		 * and OS/2 seems to use all four entries.
		 * -- Linux kernel fs/partitions/dos.c
		 *
		 * See also http://en.wikipedia.org/wiki/Extended_boot_record
		 */

		/* Parse data partition */
		for (p = p0, i = 0; i < 4; i++, p++) {
			uint32_t abs_start;

			/* the start is relative to the parental ext.partition */
			start = dos_partition_start(p) * ssf;
			size = dos_partition_size(p) * ssf;
			abs_start = cur_start + start;	/* absolute start */

			if (!size || is_extended(p))
				continue;
			if (i >= 2) {
				/* extra checks to detect real data on
				 * 3rd and 4th entries */
				if (start + size > cur_size)
					continue;
				if (abs_start < ex_start)
					continue;
				if (abs_start + size > ex_start + ex_size)
					continue;
			}
			if (!blkid_partlist_add_partition(ls, tab, p->sys_type,
						abs_start, size))
				goto err;

			ct_nodata = 0;
		}
		/* The first nested ext.partition should be a link to the next
		 * logical partition. Everything other (recursive ext.partitions)
		 * is junk.
		 */
		for (p = p0, i = 0; i < 4; i++, p++) {
			start = dos_partition_start(p) * ssf;
			size = dos_partition_size(p) * ssf;

			if (size && is_extended(p))
				break;
		}
		if (i == 4)
			goto leave;

		cur_start = ex_start + start;
		cur_size = size;
	}
leave:
	return 0;
err:
	return -1;
}

static int probe_dos_pt(blkid_probe pr, const struct blkid_idmag *mag)
{
	int i;
	int ssf;
	blkid_parttable tab = NULL;
	blkid_partlist ls;
	struct dos_partition *p0, *p;
	unsigned char *data;
	uint32_t start, size;

	data = blkid_probe_get_sector(pr, 0);
	if (!data)
		goto nothing;

	/* ignore disks with AIX magic number -- for more details see aix.c */
	if (memcmp(data, BLKID_AIX_MAGIC_STRING, BLKID_AIX_MAGIC_STRLEN) == 0)
		goto nothing;

	/*
	 * Now that the 55aa signature is present, this is probably
	 * either the boot sector of a FAT filesystem or a DOS-type
	 * partition table.
	 */
	{
		struct msdos_super_block *ms =
				(struct msdos_super_block *) data;

		if (ms->ms_fats && ms->ms_reserved &&
		    ms->ms_cluster_size &&
		    blkid_fat_valid_media(ms) &&
		    blkid_fat_valid_sectorsize(ms, NULL))
			goto nothing;		/* FAT */
	}

	p0 = (struct dos_partition *) (data + BLKID_MSDOS_PT_OFFSET);

	/*
	 * Reject PT where boot indicator is not 0 or 0x80.
	 */
	for (p = p0, i = 0; i < 4; i++, p++)
		if (p->boot_ind != 0 && p->boot_ind != 0x80)
			goto nothing;

	/*
	 * GPT uses valid MBR
	 */
	for (p = p0, i = 0; i < 4; i++, p++) {
		if (p->sys_type == BLKID_GPT_PARTITION)
			goto nothing;
	}

	/*
	 * Well, all checks pass, it's MS-DOS partiton table
	 */
	if (blkid_partitions_need_typeonly(pr))
		/* caller does not ask for details about partitions */
		return 0;

	ls = blkid_probe_get_partlist(pr);

	/* sector size factor (the start and size are in the real sectors, but
	 * we need to convert all sizes to 512 logical sectors
	 */
	ssf = blkid_probe_get_sectorsize(pr) / 512;

	/* allocate a new partition table */
	tab = blkid_partlist_new_parttable(ls, "dos", BLKID_MSDOS_PT_OFFSET);
	if (!tab)
		goto err;

	/* Parse primary partitions */
	for (p = p0, i = 0; i < 4; i++, p++) {
		start = dos_partition_start(p) * ssf;
		size = dos_partition_size(p) * ssf;

		if (!size)
			continue;
		if (!blkid_partlist_add_partition(ls, tab, p->sys_type,
							start, size))
			goto err;
	}

	/* Linux uses partition numbers greater than 4
	 * for all logical partition and all nested partition tables (bsd, ..)
	 */
	blkid_partlist_set_partno(ls, 5);

	/* Parse logical partitions */
	for (p = p0, i = 0; i < 4; i++, p++) {
		start = dos_partition_start(p) * ssf;
		size = dos_partition_size(p) * ssf;

		if (!size)
			continue;
		if (is_extended(p) &&
		    parse_dos_extended(pr, tab, start, size, ssf) == -1)
			goto err;
	}

	/* Parse subtypes (nested partitions) */
	for (p = p0, i = 0; i < 4; i++, p++) {
		int n;

		if (!dos_partition_size(p) || is_extended(p))
			continue;

		for (n = 0; n < ARRAY_SIZE(dos_nested); n++) {
			if (dos_nested[n].type != p->sys_type)
				continue;

			if (blkid_partitions_do_subprobe(pr,
					blkid_partlist_get_partition(ls, i),
					dos_nested[n].id) == -1)
				goto err;
			break;
		}
	}

	return 0;

nothing:
	return 1;
err:
	return -1;
}


const struct blkid_idinfo dos_pt_idinfo =
{
	.name		= "dos",
	.probefunc	= probe_dos_pt,
	.magics		=
	{
		/* DOS master boot sector:
		 *
		 *     0 | Code Area
		 *   440 | Optional Disk signature
		 *   446 | Partition table
		 *   510 | 0x55
		 *   511 | 0xAA
		 */
		{ .magic = "\x55\xAA", .len = 2, .sboff = 510 },
		{ NULL }
	}
};

