/*
    libparted
    Copyright (C) 1998, 1999, 2000, 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
*/

#include <config.h>
#include <string.h>

#include "fat.h"

#ifndef DISCOVER_ONLY

/* Note: this deals with file system start and end sectors, even if the physical
 * devices are different (eg for fat_copy())  Perhaps this is a hack, but it
 * works ;-)
 */
static int
calc_deltas (FatOpContext* ctx)
{
	PedFileSystem*	old_fs = ctx->old_fs;
	PedFileSystem*	new_fs = ctx->new_fs;
	FatSpecific*	old_fs_info = FAT_SPECIFIC (old_fs);
	FatSpecific*	new_fs_info = FAT_SPECIFIC (new_fs);
	PedSector	old_cluster_ofs;
	PedSector	new_cluster_ofs;
	PedSector	sector_delta;

	old_cluster_ofs = old_fs->geom->start + old_fs_info->cluster_offset;
	new_cluster_ofs = new_fs->geom->start + new_fs_info->cluster_offset;

	if (new_cluster_ofs > old_cluster_ofs) {
		ctx->start_move_dir = FAT_DIR_FORWARD;
		sector_delta = new_cluster_ofs - old_cluster_ofs;
	} else {
		ctx->start_move_dir = FAT_DIR_BACKWARD;
		sector_delta = old_cluster_ofs - new_cluster_ofs;
	}

	if (sector_delta % new_fs_info->cluster_sectors) {
		ped_exception_throw (
			PED_EXCEPTION_BUG, PED_EXCEPTION_CANCEL,
			_("Cluster start delta = %d, which is not a multiple "
			  "of the cluster size %d."),
			(int) sector_delta,
			(int) new_fs_info->cluster_sectors);
		return 0;
	}
	
	ctx->start_move_delta = sector_delta / ctx->frag_sectors;

#ifdef PED_VERBOSE
	printf ("Start move delta is: %d %s.\n",
		(int) ctx->start_move_delta,
		(ctx->start_move_dir == FAT_DIR_FORWARD)?
			"forwards" : "backwards");
#endif

	return 1;
}

FatOpContext*
fat_op_context_new (PedFileSystem* new_fs, PedFileSystem* old_fs)
{
	FatSpecific*	old_fs_info = FAT_SPECIFIC (old_fs);
	FatSpecific*	new_fs_info = FAT_SPECIFIC (new_fs);
	FatOpContext*	ctx;

	ctx = (FatOpContext*) ped_malloc (sizeof (FatOpContext));
	if (!ctx)
		goto error;

	ctx->frag_sectors = PED_MIN (old_fs_info->cluster_sectors,
				     new_fs_info->cluster_sectors);
	if (!fat_set_frag_sectors (new_fs, ctx->frag_sectors))
		goto error;
	if (!fat_set_frag_sectors (old_fs, ctx->frag_sectors))
		goto error;

	ctx->buffer_frags = old_fs_info->buffer_sectors / ctx->frag_sectors;
	ctx->buffer_map = (FatFragment*) ped_malloc (sizeof (FatFragment)
						     * ctx->buffer_frags);
	if (!ctx->buffer_map)
		goto error_free_ctx;

	ctx->remap = (FatFragment*) ped_malloc (sizeof (FatFragment)
						   * old_fs_info->frag_count);
	if (!ctx->remap)
		goto error_free_buffer_map;

	ctx->new_fs = new_fs;
	ctx->old_fs = old_fs;
	if (!calc_deltas (ctx))
		goto error_free_buffer_map;

	return ctx;

error_free_buffer_map:
	ped_free (ctx->buffer_map);
error_free_ctx:
	ped_free (ctx);
error:
	return NULL;
}

void
fat_op_context_destroy (FatOpContext* ctx)
{
	ped_free (ctx->buffer_map);
	ped_free (ctx->remap);
	ped_free (ctx);
}

FatFragment
fat_op_context_map_static_fragment (const FatOpContext* ctx, FatFragment frag)
{
	FatSpecific*	new_fs_info = FAT_SPECIFIC (ctx->new_fs);
	FatFragment	result;

	if (ctx->new_fs->geom->dev != ctx->old_fs->geom->dev)
		return -1;

	if (ctx->start_move_dir == FAT_DIR_FORWARD) {
		if (frag < ctx->start_move_delta)
			return -1;
		result = frag - ctx->start_move_delta;
	} else {
		result = frag + ctx->start_move_delta;
	}

	if (result >= new_fs_info->frag_count)
		return -1;

	return result;
}

FatCluster
fat_op_context_map_static_cluster (const FatOpContext* ctx, FatCluster clst)
{
	FatFragment	mapped_frag;

	mapped_frag = fat_op_context_map_static_fragment (ctx,
				fat_cluster_to_frag (ctx->old_fs, clst)); 
	if (mapped_frag != -1)
		return fat_frag_to_cluster (ctx->new_fs, mapped_frag);
	else
		return 0;
}

FatFragment
fat_op_context_map_fragment (const FatOpContext* ctx, FatFragment frag)
{
	return ctx->remap [frag];
}

FatCluster
fat_op_context_map_cluster (const FatOpContext* ctx, FatCluster clst)
{
	FatFragment	mapped_frag;

	mapped_frag = fat_op_context_map_fragment (ctx,
				fat_cluster_to_frag (ctx->old_fs, clst)); 
	if (mapped_frag != -1)
		return fat_frag_to_cluster (ctx->new_fs, mapped_frag);
	else
		return 0;
}

/* This function sets the initial fat for the new resized file system.
   This is in *NO WAY* a proper FAT table - all it does is:
	a) mark bad clusters as bad.
	b) mark used clusters (that is, clusters from the original FS that are
	   reachable from the resized one).  Marks as EOF (i.e. used, end of
	   file chain).
	c) mark original file system metadata as EOF (i.e. used), to prevent
	   it from being clobbered.  This will leave the original file system
	   intact, until the partition table is modified, if the start of
	   the partition is moved.

   The FATs are rebuilt *properly* after cluster relocation.  This here is
   only to mark clusters as used, so when cluster relocation occurs, clusters
   aren't relocated on top of ones marked in a, b or c.
*/
int
fat_op_context_create_initial_fat (FatOpContext* ctx)
{
	FatSpecific*	old_fs_info = FAT_SPECIFIC (ctx->old_fs);
	FatSpecific*	new_fs_info = FAT_SPECIFIC (ctx->new_fs);
	FatCluster	clst;
	FatCluster	new_clst;
	PedSector	sect;
	PedSector	new_sect;
	FatFragment	frag;
	FatFragment	new_frag;
	FatClusterFlag	frag_flag;

	new_fs_info->fat = fat_table_new (
		new_fs_info->fat_type,
		new_fs_info->fat_sectors * 512
			/ fat_table_entry_size (new_fs_info->fat_type));
	if (!new_fs_info->fat)
		return 0;

	if (!fat_table_set_cluster_count (new_fs_info->fat,
					  new_fs_info->cluster_count))
		return 0;

/* mark bad and used clusters */
	for (frag = 0; frag < old_fs_info->frag_count; frag++) {
		frag_flag = fat_get_fragment_flag (ctx->old_fs, frag);
		if (frag_flag == FAT_FLAG_FREE)
			continue;

		new_frag = fat_op_context_map_static_fragment (ctx, frag);
		if (new_frag == -1)
			continue;

		new_clst = fat_frag_to_cluster (ctx->new_fs, new_frag);
		PED_ASSERT (new_clst != 0, return 0);

		if (frag_flag == FAT_FLAG_BAD) {
			if (!fat_table_set_bad (new_fs_info->fat, new_clst))
				return 0;
		} else {
			if (!fat_table_set_eof (new_fs_info->fat, new_clst))
				return 0;
		}
	}

/* mark metadata regions that map to clusters on the new FS */
	for (sect = 0; sect < old_fs_info->cluster_offset; sect++) {
		new_sect = ped_geometry_map (ctx->new_fs->geom,
					     ctx->old_fs->geom, sect);
		if (new_sect == -1
		    || !fat_is_sector_in_clusters (ctx->new_fs, new_sect))
			continue;

		clst = fat_sector_to_cluster (ctx->new_fs, new_sect);
		PED_ASSERT (clst != 0, return 0);

		if (!fat_table_set_eof (new_fs_info->fat, clst))
			return 0;
	}

	return 1;
}

#endif /* !DISCOVER_ONLY */
