/*
    libparted - a library for manipulating disk partitions
    Copyright (C) 2004, 2005 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.h"

#include "file.h"

/* Open the data fork of a file with its first three extents and its CNID */
HfsPrivateFile*
hfs_file_open (PedFileSystem *fs, uint32_t CNID,
	       HfsExtDataRec ext_desc, PedSector sect_nb)
{
	HfsPrivateFile* file;

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

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

/* Close an HFS file */
void
hfs_file_close (HfsPrivateFile* file)
{
	ped_free (file);
}

/* warning : only works on data forks */
static int
hfs_get_extent_containing (HfsPrivateFile* file, unsigned int block,
			   HfsExtDataRec cache, uint16_t* ptr_start_cache)
{
	uint8_t			record[sizeof (HfsExtentKey)
				       + sizeof (HfsExtDataRec)];
	HfsExtentKey		search;
	HfsExtentKey*		ret_key = (HfsExtentKey*) record;
	HfsExtDescriptor*	ret_cache = (HfsExtDescriptor*)
					      (record + sizeof (HfsExtentKey));
	HfsPrivateFSData* 	priv_data = (HfsPrivateFSData*)
					      file->fs->type_specific;

	search.key_length = sizeof (HfsExtentKey) - 1;
	search.type = HFS_DATA_FORK;
	search.file_ID = file->CNID;
	search.start = PED_CPU_TO_BE16 (block);

	if (!hfs_btree_search (priv_data->extent_file, 
			       (HfsPrivateGenericKey*) &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(HfsExtDataRec));
	*ptr_start_cache = PED_BE16_TO_CPU (ret_key->start);

	return 1;
}

/* find and return the nth sector of a file */
/* return 0 on error */
static PedSector
hfs_file_find_sector (HfsPrivateFile* file, PedSector sector)
{
	HfsPrivateFSData* priv_data = (HfsPrivateFSData*)
				      file->fs->type_specific;
	unsigned int 	sect_by_block = PED_BE32_TO_CPU (
					    priv_data->mdb->block_size)
					/ PED_SECTOR_SIZE_DEFAULT;
	unsigned int 	i, s, vol_block;
	unsigned int 	block  = sector / sect_by_block;
	unsigned int	offset = sector % sect_by_block;

	/* in the three first extent */
	for (s = 0, i = 0; i < HFS_EXT_NB; i++) {
			if ((block >= s) && ( block < s + PED_BE16_TO_CPU (
						file->first[i].block_count))) {
			vol_block = (block - s) + PED_BE16_TO_CPU (
						    file->first[i].start_block);
			goto sector_found;
		}
		s += PED_BE16_TO_CPU (file->first[i].block_count);
	}

	/* in the three cached extent */
	if (file->start_cache && block >= file->start_cache)
	for (s = file->start_cache, i = 0; i < HFS_EXT_NB; i++) {
		if ((block >= s) && (block < s + PED_BE16_TO_CPU (
						file->cache[i].block_count))) {
			vol_block = (block - s) + PED_BE16_TO_CPU (
						    file->cache[i].start_block);
			goto sector_found;
		}
		s += PED_BE16_TO_CPU (file->cache[i].block_count);
	}

	/* update cache */
	if (!hfs_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 0;
	}

	/* in the three cached extent */
	PED_ASSERT(file->start_cache && block >= file->start_cache, return 0);
	for (s = file->start_cache, i = 0; i < HFS_EXT_NB; i++) {
		if ((block >= s) && (block < s + PED_BE16_TO_CPU (
						file->cache[i].block_count))) {
			vol_block = (block - s) + PED_BE16_TO_CPU (
						    file->cache[i].start_block);
			goto sector_found;
		}
		s += PED_BE16_TO_CPU (file->cache[i].block_count);
	}

	return 0;

    sector_found:
	return (PedSector) PED_BE16_TO_CPU (priv_data->mdb->start_block)
		+ (PedSector) vol_block * sect_by_block
		+ offset;
}

/* Read the nth sector of a file */
/* return 0 on error */
int
hfs_file_read_sector (HfsPrivateFile* file, void *buf, PedSector sector)
{
	PedSector	abs_sector;

	if (sector >= file->sect_nb) {
		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;
	}

	abs_sector = hfs_file_find_sector (file, sector);
	if (!abs_sector) {
		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;
	}

	return ped_geometry_read (file->fs->geom, buf, abs_sector, 1);
}

/* Write the nth sector of a file */
/* return 0 on error */
int
hfs_file_write_sector (HfsPrivateFile* file, void *buf, PedSector sector)
{
	PedSector	abs_sector;

	if (sector >= file->sect_nb) {
		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;
	}

	abs_sector = hfs_file_find_sector (file, sector);
	if (!abs_sector) {
		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;
	}

	return ped_geometry_write (file->fs->geom, buf, abs_sector, 1);
}

#endif /* !DISCOVER_ONLY */
