/*
 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
 * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
 *
 * This file may be redistributed under the terms of the
 * GNU Lesser General Public License.
 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <inttypes.h>

#include "superblocks.h"

struct ntfs_bios_parameters {
	uint16_t	sector_size;	/* Size of a sector in bytes. */
	uint8_t		sectors_per_cluster;	/* Size of a cluster in sectors. */
	uint16_t	reserved_sectors;	/* zero */
	uint8_t		fats;			/* zero */
	uint16_t	root_entries;		/* zero */
	uint16_t	sectors;		/* zero */
	uint8_t		media_type;		/* 0xf8 = hard disk */
	uint16_t	sectors_per_fat;	/* zero */
	uint16_t	sectors_per_track;	/* irrelevant */
	uint16_t	heads;			/* irrelevant */
	uint32_t	hidden_sectors;		/* zero */
	uint32_t	large_sectors;		/* zero */
} __attribute__ ((__packed__));

struct ntfs_super_block {
	uint8_t		jump[3];
	uint8_t		oem_id[8];	/* magic string */

	struct ntfs_bios_parameters	bpb;

	uint16_t	unused[2];
	uint64_t	number_of_sectors;
	uint64_t	mft_cluster_location;
	uint64_t	mft_mirror_cluster_location;
	int8_t		clusters_per_mft_record;
	uint8_t		reserved1[3];
	int8_t		cluster_per_index_record;
	uint8_t		reserved2[3];
	uint64_t	volume_serial;
	uint32_t	checksum;
} __attribute__((packed));

struct master_file_table_record {
	uint32_t	magic;
	uint16_t	usa_ofs;
	uint16_t	usa_count;
	uint64_t	lsn;
	uint16_t	sequence_number;
	uint16_t	link_count;
	uint16_t	attrs_offset;
	uint16_t	flags;
	uint32_t	bytes_in_use;
	uint32_t	bytes_allocated;
} __attribute__((__packed__));

struct file_attribute {
	uint32_t	type;
	uint32_t	len;
	uint8_t		non_resident;
	uint8_t		name_len;
	uint16_t	name_offset;
	uint16_t	flags;
	uint16_t	instance;
	uint32_t	value_len;
	uint16_t	value_offset;
} __attribute__((__packed__));

#define MFT_RECORD_VOLUME	3
#define NTFS_MAX_CLUSTER_SIZE	(64 * 1024)

enum {
	MFT_RECORD_ATTR_VOLUME_NAME		= 0x60,
	MFT_RECORD_ATTR_END			= 0xffffffff
};

static int probe_ntfs(blkid_probe pr, const struct blkid_idmag *mag)
{
	struct ntfs_super_block *ns;
	struct master_file_table_record *mft;

	uint32_t sectors_per_cluster, mft_record_size, attr_off;
	uint16_t sector_size;
	uint64_t nr_clusters, off;
	unsigned char *buf_mft;

	ns = blkid_probe_get_sb(pr, mag, struct ntfs_super_block);
	if (!ns)
		return errno ? -errno : 1;

	/*
	 * Check bios parameters block
	 */
	sector_size = le16_to_cpu(ns->bpb.sector_size);
	sectors_per_cluster = ns->bpb.sectors_per_cluster;

	if (sector_size < 256 || sector_size > 4096)
		return 1;

	switch (sectors_per_cluster) {
	case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128:
		break;
	default:
		return 1;
	}

	if ((uint16_t) le16_to_cpu(ns->bpb.sector_size) *
			ns->bpb.sectors_per_cluster > NTFS_MAX_CLUSTER_SIZE)
		return 1;

	/* Unused fields must be zero */
	if (le16_to_cpu(ns->bpb.reserved_sectors)
	    || le16_to_cpu(ns->bpb.root_entries)
	    || le16_to_cpu(ns->bpb.sectors)
	    || le16_to_cpu(ns->bpb.sectors_per_fat)
	    || le32_to_cpu(ns->bpb.large_sectors)
	    || ns->bpb.fats)
		return 1;

	if ((uint8_t) ns->clusters_per_mft_record < 0xe1
	    || (uint8_t) ns->clusters_per_mft_record > 0xf7) {

		switch (ns->clusters_per_mft_record) {
		case 1: case 2: case 4: case 8: case 16: case 32: case 64:
			break;
		default:
			return 1;
		}
	}

	if (ns->clusters_per_mft_record > 0)
		mft_record_size = ns->clusters_per_mft_record *
				  sectors_per_cluster * sector_size;
	else
		mft_record_size = 1 << (0 - ns->clusters_per_mft_record);

	nr_clusters = le64_to_cpu(ns->number_of_sectors) / sectors_per_cluster;

	if ((le64_to_cpu(ns->mft_cluster_location) > nr_clusters) ||
	    (le64_to_cpu(ns->mft_mirror_cluster_location) > nr_clusters))
		return 1;


	off = le64_to_cpu(ns->mft_cluster_location) * sector_size *
		sectors_per_cluster;

	DBG(LOWPROBE, ul_debug("NTFS: sector_size=%d, mft_record_size=%d, "
			"sectors_per_cluster=%d, nr_clusters=%ju "
			"cluster_offset=%jd",
			(int) sector_size, mft_record_size,
			sectors_per_cluster, nr_clusters,
			off));

	buf_mft = blkid_probe_get_buffer(pr, off, mft_record_size);
	if (!buf_mft)
		return errno ? -errno : 1;

	if (memcmp(buf_mft, "FILE", 4))
		return 1;

	off += MFT_RECORD_VOLUME * mft_record_size;

	buf_mft = blkid_probe_get_buffer(pr, off, mft_record_size);
	if (!buf_mft)
		return errno ? -errno : 1;

	if (memcmp(buf_mft, "FILE", 4))
		return 1;

	mft = (struct master_file_table_record *) buf_mft;
	attr_off = le16_to_cpu(mft->attrs_offset);

	while (attr_off < mft_record_size &&
	       attr_off <= le32_to_cpu(mft->bytes_allocated)) {

		uint32_t attr_len;
		struct file_attribute *attr;

		attr = (struct file_attribute *) (buf_mft + attr_off);
		attr_len = le32_to_cpu(attr->len);
		if (!attr_len)
			break;

		if (le32_to_cpu(attr->type) == MFT_RECORD_ATTR_END)
			break;
		if (le32_to_cpu(attr->type) == MFT_RECORD_ATTR_VOLUME_NAME) {
			unsigned int val_off = le16_to_cpu(attr->value_offset);
			unsigned int val_len = le32_to_cpu(attr->value_len);
			unsigned char *val = ((uint8_t *) attr) + val_off;

			blkid_probe_set_utf8label(pr, val, val_len, BLKID_ENC_UTF16LE);
			break;
		}

		if (UINT_MAX - attr_len < attr_off)
			break;
		attr_off += attr_len;
	}

	blkid_probe_sprintf_uuid(pr,
			(unsigned char *) &ns->volume_serial,
			sizeof(ns->volume_serial),
			"%016" PRIX64, le64_to_cpu(ns->volume_serial));
	return 0;
}


const struct blkid_idinfo ntfs_idinfo =
{
	.name		= "ntfs",
	.usage		= BLKID_USAGE_FILESYSTEM,
	.probefunc	= probe_ntfs,
	.magics		=
	{
		{ .magic = "NTFS    ", .len = 8, .sboff = 3 },
		{ NULL }
	}
};

