/*
    libparted - a library for manipulating disk partitions
    Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/

#ifndef DISCOVER_ONLY

#include <config.h>

#include <parted/parted.h>
#include <parted/endian.h>
#include <parted/debug.h>
#include <stdint.h>

#if ENABLE_NLS
#  include <libintl.h>
#  define _(String) dgettext (PACKAGE, String)
#else
#  define _(String) (String)
#endif /* ENABLE_NLS */

#include "hfs.h"
#include "advfs_plus.h"

#include "file_plus.h"

/* Open the data fork of a file with its first eight extents and its CNID */
/* CNID and ext_desc must be in disc order, sect_nb in CPU order */
/* return null on failure */
HfsPPrivateFile*
hfsplus_file_open (PedFileSystem *fs, HfsPNodeID CNID,
		   HfsPExtDataRec ext_desc, PedSector sect_nb)
{
	HfsPPrivateFile* file;

	file = (HfsPPrivateFile*) ped_malloc (sizeof (HfsPPrivateFile));
	if (!file) return NULL;

	file->fs = fs;
	file->sect_nb = sect_nb;
	file->CNID = CNID;
	memcpy(file->first, ext_desc, sizeof (HfsPExtDataRec));
	file->start_cache = 0;

	return file;
}

/* Close an HFS+ file */
void
hfsplus_file_close (HfsPPrivateFile* file)
{
	ped_free (file);
}

/* warning : only works on data forks */
static int
hfsplus_get_extent_containing (HfsPPrivateFile* file, unsigned int block,
			       HfsPExtDataRec cache, uint32_t* ptr_start_cache)
{
	uint8_t			record[sizeof (HfsPExtentKey)
				       + sizeof (HfsPExtDataRec)];
	HfsPExtentKey		search;
	HfsPExtentKey*		ret_key = (HfsPExtentKey*) record;
	HfsPExtDescriptor*	ret_cache = (HfsPExtDescriptor*)
					      (record + sizeof (HfsPExtentKey));
	HfsPPrivateFSData* 	priv_data = (HfsPPrivateFSData*)
						file->fs->type_specific;

	search.key_length = PED_CPU_TO_BE16 (sizeof (HfsPExtentKey) - 2);
	search.type = HFS_DATA_FORK;
	search.pad = 0;
	search.file_ID = file->CNID;
	search.start = PED_CPU_TO_BE32 (block);

	if (!hfsplus_btree_search (priv_data->extents_file,
				   (HfsPPrivateGenericKey*) &search,
				   record, sizeof (record), NULL))
		return 0;

	if (ret_key->file_ID != search.file_ID || ret_key->type != search.type)
		return 0;

	memcpy (cache, ret_cache, sizeof(HfsPExtDataRec));
	*ptr_start_cache = PED_BE32_TO_CPU (ret_key->start);

	return 1;
}

/* find a sub extent contained in the desired area */
/* and with the same starting point */
/* return 0 in sector_count on error, or the physical area */
/* on the volume corresponding to the logical area in the file */
static HfsPPrivateExtent
hfsplus_file_find_extent (HfsPPrivateFile* file, PedSector sector,
			  unsigned int nb)
{
	HfsPPrivateExtent ret = {0,0};
	HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*)
					file->fs->type_specific;
	unsigned int	sect_by_block = PED_BE32_TO_CPU (
					    priv_data->vh->block_size)
					/ PED_SECTOR_SIZE_DEFAULT;
	unsigned int	i, s, vol_block, size;
	PedSector	sect_size;
	unsigned int	block  = sector / sect_by_block;
	unsigned int	offset = sector % sect_by_block;

	/* in the 8 first extent */
	for (s = 0, i = 0; i < HFSP_EXT_NB; i++) {
		if ((block >= s) && (block < s + PED_BE32_TO_CPU (
						file->first[i].block_count))) {
			vol_block = (block - s)
				    + PED_BE32_TO_CPU (file->first[i]
						       .start_block);
			size = PED_BE32_TO_CPU (file->first[i].block_count)
				+ s - block;
			goto plus_sector_found;
		}
		s += PED_BE32_TO_CPU (file->first[i].block_count);
	}

	/* in the 8 cached extent */
	if (file->start_cache && block >= file->start_cache)
	for (s = file->start_cache, i = 0; i < HFSP_EXT_NB; i++) {
		if ((block >= s) && (block < s + PED_BE32_TO_CPU (
						file->cache[i].block_count))) {
			vol_block = (block - s)
				    + PED_BE32_TO_CPU (file->cache[i]
						       .start_block);
			size = PED_BE32_TO_CPU (file->cache[i].block_count)
				+ s - block;
			goto plus_sector_found;
		}
		s += PED_BE32_TO_CPU (file->cache[i].block_count);
	}

	/* update cache */
	if (!hfsplus_get_extent_containing (file, block, file->cache,
					    &(file->start_cache))) {
		ped_exception_throw (
			PED_EXCEPTION_WARNING,
			PED_EXCEPTION_CANCEL,
			_("Could not update the extent cache for HFS+ file "
			  "with CNID %X."),
			PED_BE32_TO_CPU(file->CNID));
		return ret; /* ret == {0,0} */
	}

	/* ret == {0,0} */
	PED_ASSERT(file->start_cache && block >= file->start_cache, return ret);

	for (s = file->start_cache, i = 0; i < HFSP_EXT_NB; i++) {
		if ((block >= s) && (block < s + PED_BE32_TO_CPU (
						file->cache[i].block_count))) {
			vol_block = (block - s)
				    + PED_BE32_TO_CPU (file->cache[i]
						       .start_block);
			size = PED_BE32_TO_CPU (file->cache[i].block_count)
				+ s - block;
			goto plus_sector_found;
		}
		s += PED_BE32_TO_CPU (file->cache[i].block_count);
	}

	return ret;

plus_sector_found:
	sect_size = (PedSector) size * sect_by_block - offset;
	ret.start_sector = vol_block * sect_by_block + offset;
	ret.sector_count = (sect_size < nb) ? sect_size : nb;
	return ret;
}

int
hfsplus_file_read(HfsPPrivateFile* file, void *buf, PedSector sector,
		  unsigned int nb)
{
	HfsPPrivateExtent phy_area;
	HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*)
					file->fs->type_specific;
        char *b = buf;

	if (sector+nb < sector /* detect overflow */
	    || sector+nb > file->sect_nb) /* out of file */ {
		ped_exception_throw (
			PED_EXCEPTION_ERROR,
			PED_EXCEPTION_CANCEL,
			_("Trying to read HFS+ file with CNID %X behind EOF."),
			PED_BE32_TO_CPU(file->CNID));
		return 0;
	}

	while (nb) {
		phy_area = hfsplus_file_find_extent(file, sector, nb);
		if (phy_area.sector_count == 0) {
			ped_exception_throw (
				PED_EXCEPTION_ERROR,
				PED_EXCEPTION_CANCEL,
				_("Could not find sector %lli of HFS+ file "
				  "with CNID %X."),
				sector, PED_BE32_TO_CPU(file->CNID));
			return 0;
		}
                if (!ped_geometry_read(priv_data->plus_geom, b,
				       phy_area.start_sector,
				       phy_area.sector_count))
			return 0;

		nb -= phy_area.sector_count; /* < nb anyway ... */
		sector += phy_area.sector_count;
                b += phy_area.sector_count * PED_SECTOR_SIZE_DEFAULT;
	}

	return 1;
}

int
hfsplus_file_write(HfsPPrivateFile* file, void *buf, PedSector sector,
		  unsigned int nb)
{
	HfsPPrivateExtent phy_area;
	HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*)
					file->fs->type_specific;
        char *b = buf;

	if (sector+nb < sector /* detect overflow */
	    || sector+nb > file->sect_nb) /* out of file */ {
		ped_exception_throw (
			PED_EXCEPTION_ERROR,
			PED_EXCEPTION_CANCEL,
			_("Trying to write HFS+ file with CNID %X behind EOF."),
			PED_BE32_TO_CPU(file->CNID));
		return 0;
	}

	while (nb) {
		phy_area = hfsplus_file_find_extent(file, sector, nb);
		if (phy_area.sector_count == 0) {
			ped_exception_throw (
				PED_EXCEPTION_ERROR,
				PED_EXCEPTION_CANCEL,
				_("Could not find sector %lli of HFS+ file "
				  "with CNID %X."),
				sector, PED_BE32_TO_CPU(file->CNID));
			return 0;
		}
                if (!ped_geometry_write(priv_data->plus_geom, b,
				       phy_area.start_sector,
				       phy_area.sector_count))
			return 0;

		nb -= phy_area.sector_count; /* < nb anyway ... */
		sector += phy_area.sector_count;
                b += phy_area.sector_count * PED_SECTOR_SIZE_DEFAULT;
	}

	return 1;
}

#endif /* !DISCOVER_ONLY */
