/*
 * 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 (memcmp(hfs->embed_sig, "H+", 2) == 0) {
		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;
}
