Example #1
0
static int
calc_sizes (PedSector size, PedSector align, FatType fat_type,
	    PedSector root_dir_sectors, PedSector cluster_sectors,
	    FatCluster* out_cluster_count, PedSector* out_fat_size)
{
	PedSector	data_fat_space; /* space available to clusters + FAT */
	PedSector	fat_space;	/* space taken by each FAT */
	PedSector	cluster_space;	/* space taken by clusters */
	FatCluster	cluster_count;
	int		i;

	PED_ASSERT (out_cluster_count != NULL);
	PED_ASSERT (out_fat_size != NULL);

	data_fat_space = size - fat_min_reserved_sector_count (fat_type)
			 - align;
	if (fat_type == FAT_TYPE_FAT16)
		data_fat_space -= root_dir_sectors;

	fat_space = 0;
	for (i = 0; i < 2; i++) {
		if (fat_type == FAT_TYPE_FAT32)
			cluster_space = data_fat_space - fat_space;
		else
			cluster_space = data_fat_space - 2 * fat_space;

		cluster_count = cluster_space / cluster_sectors;
		fat_space = ped_div_round_up (cluster_count + 2,
					      entries_per_sector (fat_type));
	}

	cluster_space = data_fat_space - 2 * fat_space;
	cluster_count = cluster_space / cluster_sectors;

	/* looks like this should be part of the loop condition?
	 * Need to build the Big Table TM again to check
	 */
	if (fat_space < ped_div_round_up (cluster_count + 2,
				          entries_per_sector (fat_type))) {
		fat_space = ped_div_round_up (cluster_count + 2,
					      entries_per_sector (fat_type));
	}

	if (cluster_count > fat_max_cluster_count (fat_type)
	    || cluster_count < fat_min_cluster_count (fat_type))
		return 0;

	*out_cluster_count = cluster_count;
	*out_fat_size = fat_space;

	return 1;
}
Example #2
0
/*  Calculates the number of sectors needed to be added to cluster_offset,
    to make the cluster on the new file system match up with the ones
    on the old file system.
	However, some space is reserved by fat_calc_resize_sizes() and
    friends, to allow room for this space.  If too much of this space is left
    over, everyone will complain, so we have to be greedy, and use it all up...
 */
PedSector
fat_calc_align_sectors (const PedFileSystem* new_fs,
			const PedFileSystem* old_fs)
{
	FatSpecific*	old_fs_info = FAT_SPECIFIC (old_fs);
	FatSpecific*	new_fs_info = FAT_SPECIFIC (new_fs);
	PedSector	raw_old_meta_data_end;
	PedSector	new_meta_data_size;
	PedSector	min_new_meta_data_end;
	PedSector	new_data_size;
	PedSector	new_clusters_size;
	PedSector	align;

	new_meta_data_size
		= fat_min_reserved_sector_count (new_fs_info->fat_type)
		  + new_fs_info->fat_sectors * 2;

	if (new_fs_info->fat_type == FAT_TYPE_FAT16)
		new_meta_data_size += new_fs_info->root_dir_sector_count;

	raw_old_meta_data_end = old_fs->geom->start
				 + old_fs_info->cluster_offset;

	min_new_meta_data_end = new_fs->geom->start + new_meta_data_size;

	if (raw_old_meta_data_end > min_new_meta_data_end)
		align = (raw_old_meta_data_end - min_new_meta_data_end)
			% new_fs_info->cluster_sectors;
	else
		align = (new_fs_info->cluster_sectors
		         - (   (min_new_meta_data_end - raw_old_meta_data_end)
				% new_fs_info->cluster_sectors   ))
			% new_fs_info->cluster_sectors;

	new_data_size = new_fs->geom->length - new_meta_data_size;
	new_clusters_size = new_fs_info->cluster_count
				* new_fs_info->cluster_sectors;

	while (new_clusters_size + align + new_fs_info->cluster_sectors
			<= new_data_size)
		align += new_fs_info->cluster_sectors;

	return align;
}
Example #3
0
/*  Creates the PedFileSystem struct for the new resized file system, and
    sticks it in a FatOpContext.  At the end of the process, the original
    (ctx->old_fs) is destroyed, and replaced with the new one (ctx->new_fs).
 */
static FatOpContext*
create_resize_context (PedFileSystem* fs, const PedGeometry* new_geom)
{
	FatSpecific*	fs_info = FAT_SPECIFIC (fs);
	FatSpecific*	new_fs_info;
	PedFileSystem*	new_fs;
	PedSector	new_cluster_sectors;
	FatCluster	new_cluster_count;
	PedSector	new_fat_sectors;
	FatType		new_fat_type;
	PedSector	root_dir_sector_count;
	FatOpContext*	context;

	/* hypothetical number of root dir sectors, if we end up using
	 * FAT16
	 */
	if (fs_info->root_dir_sector_count)
		root_dir_sector_count = fs_info->root_dir_sector_count;
	else
		root_dir_sector_count = FAT_ROOT_DIR_ENTRY_COUNT
						* sizeof (FatDirEntry) / 512;

	if (!get_fat_type (fs, new_geom, &new_fat_type))
		return 0;

	fat_calc_resize_sizes (new_geom, fs_info->cluster_sectors, new_fat_type,
		root_dir_sector_count, fs_info->cluster_sectors,
		&new_cluster_sectors, &new_cluster_count, &new_fat_sectors);

	if (!fat_check_resize_geometry (fs, new_geom, new_cluster_sectors,
				        new_cluster_count))
		goto error;

	new_fs = fat_alloc (new_geom);
	if (!new_fs)
		goto error;

	new_fs_info = FAT_SPECIFIC (new_fs);
	if (!new_fs_info)
		goto error_free_new_fs;

/* preserve boot code, etc. */
	memcpy (&new_fs_info->boot_sector, &fs_info->boot_sector,
		sizeof (FatBootSector));
	memcpy (&new_fs_info->info_sector, &fs_info->info_sector,
		sizeof (FatInfoSector));

	new_fs_info->logical_sector_size = fs_info->logical_sector_size;
	new_fs_info->sector_count = new_geom->length;

	new_fs_info->sectors_per_track = fs_info->sectors_per_track;
	new_fs_info->heads = fs_info->heads;

	new_fs_info->cluster_size = new_cluster_sectors * 512;
	new_fs_info->cluster_sectors = new_cluster_sectors;
	new_fs_info->cluster_count = new_cluster_count;
	new_fs_info->dir_entries_per_cluster = fs_info->dir_entries_per_cluster;

	new_fs_info->fat_type = new_fat_type;
	new_fs_info->fat_table_count = 2;
	new_fs_info->fat_sectors = new_fat_sectors;

	/* what about copying? */
	new_fs_info->serial_number = fs_info->serial_number;

	if (new_fs_info->fat_type == FAT_TYPE_FAT32) {
		new_fs_info->info_sector_offset	= 1;
		new_fs_info->boot_sector_backup_offset = 6;

		new_fs_info->root_dir_offset = 0;
		new_fs_info->root_dir_entry_count = 0;
		new_fs_info->root_dir_sector_count = 0;

		/* we add calc_align_sectors to push the cluster_offset
		   forward, to keep the clusters aligned between the new
		   and old file systems
		 */
		new_fs_info->fat_offset
			= fat_min_reserved_sector_count (FAT_TYPE_FAT32)
			  + fat_calc_align_sectors (new_fs, fs);

		new_fs_info->cluster_offset
			= new_fs_info->fat_offset
			  + 2 * new_fs_info->fat_sectors;
	} else {
		new_fs_info->root_dir_sector_count = root_dir_sector_count;
		new_fs_info->root_dir_entry_count
			= root_dir_sector_count * 512 / sizeof (FatDirEntry);

		new_fs_info->fat_offset
			= fat_min_reserved_sector_count (FAT_TYPE_FAT16)
			  + fat_calc_align_sectors (new_fs, fs);

		new_fs_info->root_dir_offset = new_fs_info->fat_offset
					       + 2 * new_fs_info->fat_sectors;

		new_fs_info->cluster_offset = new_fs_info->root_dir_offset
					  + new_fs_info->root_dir_sector_count;
	}

	new_fs_info->total_dir_clusters = fs_info->total_dir_clusters;

	context = fat_op_context_new (new_fs, fs);
	if (!context)
		goto error_free_new_fs_info;

	if (!fat_op_context_create_initial_fat (context))
		goto error_free_context;

	if (!fat_alloc_buffers (new_fs))
		goto error_free_fat;

	return context;

error_free_fat:
	fat_table_destroy (new_fs_info->fat);
error_free_context:
	free (context);
error_free_new_fs_info:
	free (new_fs_info);
error_free_new_fs:
	free (new_fs);
error:
	return NULL;
}