/*
 * volume_id - reads filesystem label and uuid
 *
 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
 *
 *	This library is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU Lesser General Public
 *	License as published by the Free Software Foundation; either
 *	version 2.1 of the License, or (at your option) any later version.
 *
 *	This library is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 *	Lesser General Public License for more details.
 *
 *	You should have received a copy of the GNU Lesser General Public
 *	License along with this library; if not, write to the Free Software
 *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#include "volume_id_internal.h"

struct hfs_finder_info{
	uint32_t	boot_folder;
	uint32_t	start_app;
	uint32_t	open_folder;
	uint32_t	os9_folder;
	uint32_t	reserved;
	uint32_t	osx_folder;
	uint8_t		id[8];
} __attribute__((__packed__));

struct hfs_mdb {
	uint8_t		signature[2];
	uint32_t	cr_date;
	uint32_t	ls_Mod;
	uint16_t	atrb;
	uint16_t	nm_fls;
	uint16_t	vbm_st;
	uint16_t	alloc_ptr;
	uint16_t	nm_al_blks;
	uint32_t	al_blk_size;
	uint32_t	clp_size;
	uint16_t	al_bl_st;
	uint32_t	nxt_cnid;
	uint16_t	free_bks;
	uint8_t		label_len;
	uint8_t		label[27];
	uint32_t	vol_bkup;
	uint16_t	vol_seq_num;
	uint32_t	wr_cnt;
	uint32_t	xt_clump_size;
	uint32_t	ct_clump_size;
	uint16_t	num_root_dirs;
	uint32_t	file_count;
	uint32_t	dir_count;
	struct hfs_finder_info finder_info;
	uint8_t		embed_sig[2];
	uint16_t	embed_startblock;
	uint16_t	embed_blockcount;
} __attribute__((__packed__));

struct hfsplus_bnode_descriptor {
	uint32_t	next;
	uint32_t	prev;
	uint8_t		type;
	uint8_t		height;
	uint16_t	num_recs;
	uint16_t	reserved;
} __attribute__((__packed__));

struct hfsplus_bheader_record {
	uint16_t	depth;
	uint32_t	root;
	uint32_t	leaf_count;
	uint32_t	leaf_head;
	uint32_t	leaf_tail;
	uint16_t	node_size;
} __attribute__((__packed__));

struct hfsplus_catalog_key {
	uint16_t	key_len;
	uint32_t	parent_id;
	uint16_t	unicode_len;
	uint8_t		unicode[255 * 2];
} __attribute__((__packed__));

struct hfsplus_extent {
	uint32_t	start_block;
	uint32_t	block_count;
} __attribute__((__packed__));

#define HFSPLUS_EXTENT_COUNT		8
struct hfsplus_fork {
	uint64_t	total_size;
	uint32_t	clump_size;
	uint32_t	total_blocks;
	struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
} __attribute__((__packed__));

struct hfsplus_vol_header {
	uint8_t		signature[2];
	uint16_t	version;
	uint32_t	attributes;
	uint32_t	last_mount_vers;
	uint32_t	reserved;
	uint32_t	create_date;
	uint32_t	modify_date;
	uint32_t	backup_date;
	uint32_t	checked_date;
	uint32_t	file_count;
	uint32_t	folder_count;
	uint32_t	blocksize;
	uint32_t	total_blocks;
	uint32_t	free_blocks;
	uint32_t	next_alloc;
	uint32_t	rsrc_clump_sz;
	uint32_t	data_clump_sz;
	uint32_t	next_cnid;
	uint32_t	write_count;
	uint64_t	encodings_bmp;
	struct hfs_finder_info finder_info;
	struct hfsplus_fork alloc_file;
	struct hfsplus_fork ext_file;
	struct hfsplus_fork cat_file;
	struct hfsplus_fork attr_file;
	struct hfsplus_fork start_file;
} __attribute__((__packed__));

#define HFS_SUPERBLOCK_OFFSET		0x400
#define HFS_NODE_LEAF			0xff
#define HFSPLUS_POR_CNID		1

int volume_id_probe_hfs_hfsplus(struct volume_id *id, uint64_t off)
{
	unsigned blocksize;
	unsigned cat_block;
	unsigned ext_block_start;
	unsigned ext_block_count;
	int ext;
	unsigned leaf_node_head;
	unsigned leaf_node_count;
	unsigned leaf_node_size;
	unsigned leaf_block;
	uint64_t leaf_off;
	unsigned alloc_block_size;
	unsigned alloc_first_block;
	unsigned embed_first_block;
	unsigned record_count;
	struct hfsplus_vol_header *hfsplus;
	struct hfsplus_bnode_descriptor *descr;
	struct hfsplus_bheader_record *bnode;
	struct hfsplus_catalog_key *key;
	unsigned label_len;
	struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
	struct hfs_mdb *hfs;
	const uint8_t *buf;

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

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

	hfs = (struct hfs_mdb *) buf;
	if (hfs->signature[0] != 'B' || hfs->signature[1] != 'D')
		goto checkplus;

	/* it may be just a hfs wrapper for hfs+ */
	if (hfs->embed_sig[0] == 'H' && hfs->embed_sig[1] == '+') {
		alloc_block_size = be32_to_cpu(hfs->al_blk_size);
		dbg("alloc_block_size 0x%x", alloc_block_size);

		alloc_first_block = be16_to_cpu(hfs->al_bl_st);
		dbg("alloc_first_block 0x%x", alloc_first_block);

		embed_first_block = be16_to_cpu(hfs->embed_startblock);
		dbg("embed_first_block 0x%x", embed_first_block);

		off += (alloc_first_block * 512) +
		       (embed_first_block * alloc_block_size);
		dbg("hfs wrapped hfs+ found at offset 0x%llx", (unsigned long long) off);

		buf = volume_id_get_buffer(id, off + HFS_SUPERBLOCK_OFFSET, 0x200);
		if (buf == NULL)
			return -1;
		goto checkplus;
	}

	if (hfs->label_len > 0 && hfs->label_len < 28) {
//		volume_id_set_label_raw(id, hfs->label, hfs->label_len);
		volume_id_set_label_string(id, hfs->label, hfs->label_len) ;
	}

	volume_id_set_uuid(id, hfs->finder_info.id, UUID_HFS);
//	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
//	id->type = "hfs";

	return 0;

 checkplus:
	hfsplus = (struct hfsplus_vol_header *) buf;
	if (hfs->signature[0] == 'H')
		if (hfs->signature[1] == '+' || hfs->signature[1] == 'X')
			goto hfsplus;
	return -1;

 hfsplus:
	volume_id_set_uuid(id, hfsplus->finder_info.id, UUID_HFS);

	blocksize = be32_to_cpu(hfsplus->blocksize);
	dbg("blocksize %u", blocksize);

	memcpy(extents, hfsplus->cat_file.extents, sizeof(extents));
	cat_block = be32_to_cpu(extents[0].start_block);
	dbg("catalog start block 0x%x", cat_block);

	buf = volume_id_get_buffer(id, off + (cat_block * blocksize), 0x2000);
	if (buf == NULL)
		goto found;

	bnode = (struct hfsplus_bheader_record *)
		&buf[sizeof(struct hfsplus_bnode_descriptor)];

	leaf_node_head = be32_to_cpu(bnode->leaf_head);
	dbg("catalog leaf node 0x%x", leaf_node_head);

	leaf_node_size = be16_to_cpu(bnode->node_size);
	dbg("leaf node size 0x%x", leaf_node_size);

	leaf_node_count = be32_to_cpu(bnode->leaf_count);
	dbg("leaf node count 0x%x", leaf_node_count);
	if (leaf_node_count == 0)
		goto found;

	leaf_block = (leaf_node_head * leaf_node_size) / blocksize;

	/* get physical location */
	for (ext = 0; ext < HFSPLUS_EXTENT_COUNT; ext++) {
		ext_block_start = be32_to_cpu(extents[ext].start_block);
		ext_block_count = be32_to_cpu(extents[ext].block_count);
		dbg("extent start block 0x%x, count 0x%x", ext_block_start, ext_block_count);

		if (ext_block_count == 0)
			goto found;

		/* this is our extent */
		if (leaf_block < ext_block_count)
			break;

		leaf_block -= ext_block_count;
	}
	if (ext == HFSPLUS_EXTENT_COUNT)
		goto found;
	dbg("found block in extent %i", ext);

	leaf_off = (ext_block_start + leaf_block) * blocksize;

	buf = volume_id_get_buffer(id, off + leaf_off, leaf_node_size);
	if (buf == NULL)
		goto found;

	descr = (struct hfsplus_bnode_descriptor *) buf;
	dbg("descriptor type 0x%x", descr->type);

	record_count = be16_to_cpu(descr->num_recs);
	dbg("number of records %u", record_count);
	if (record_count == 0)
		goto found;

	if (descr->type != HFS_NODE_LEAF)
		goto found;

	key = (struct hfsplus_catalog_key *)
		&buf[sizeof(struct hfsplus_bnode_descriptor)];

	dbg("parent id 0x%x", be32_to_cpu(key->parent_id));
	if (key->parent_id != cpu_to_be32(HFSPLUS_POR_CNID))
		goto found;

	label_len = be16_to_cpu(key->unicode_len) * 2;
	dbg("label unicode16 len %i", label_len);
//	volume_id_set_label_raw(id, key->unicode, label_len);
	volume_id_set_label_unicode16(id, key->unicode, BE, label_len);

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

	return 0;
}
