예제 #1
0
파일: resize.c 프로젝트: Excito/parted
static int
fat_construct_converted_tree (FatOpContext* ctx)
{
	FatSpecific*		old_fs_info = FAT_SPECIFIC (ctx->old_fs);
	FatSpecific*		new_fs_info = FAT_SPECIFIC (ctx->new_fs);
	FatTraverseInfo*	old_trav_info;
	FatTraverseInfo*	new_trav_info;

	if (new_fs_info->fat_type == FAT_TYPE_FAT32) {
		new_trav_info = fat_traverse_begin (ctx->new_fs,
					    new_fs_info->root_cluster, "\\");
		old_trav_info = fat_traverse_begin (ctx->old_fs, FAT_ROOT,
						    "\\");
	} else {
		fat_clear_root_dir (ctx->new_fs);
		new_trav_info = fat_traverse_begin (ctx->new_fs, FAT_ROOT,
						    "\\");
		old_trav_info = fat_traverse_begin (ctx->old_fs,
					    old_fs_info->root_cluster, "\\");
	}
	if (!new_trav_info || !old_trav_info)
		return 0;
	if (!fat_convert_directory (ctx, old_trav_info, new_trav_info))
		return 0;
	return 1;
}
예제 #2
0
파일: resize.c 프로젝트: Excito/parted
/* copies the "hidden" sectors, between the boot sector and the FAT.  Required,
 * for the Windows 98 FAT32 boot loader
 */
int
_copy_hidden_sectors (FatOpContext* ctx)
{
	FatSpecific*    old_fs_info = FAT_SPECIFIC (ctx->old_fs);
	FatSpecific*    new_fs_info = FAT_SPECIFIC (ctx->new_fs);
	PedSector       first = 1;
	PedSector       last;
	PedSector       count;

	/* nothing to copy for FAT16 */
	if (old_fs_info->fat_type == FAT_TYPE_FAT16
			|| new_fs_info->fat_type == FAT_TYPE_FAT16)
		return 1;

	last = PED_MIN (old_fs_info->fat_offset, new_fs_info->fat_offset) - 1;
	count = last - first + 1;

	PED_ASSERT (count < BUFFER_SIZE);

	if (!ped_geometry_read (ctx->old_fs->geom, old_fs_info->buffer,
				first, count))
		return 0;
	if (!ped_geometry_write (ctx->new_fs->geom, old_fs_info->buffer,
				 first, count))
		return 0;
	return 1;
}
예제 #3
0
파일: resize.c 프로젝트: Excito/parted
/* when converting FAT32 -> FAT16
 * fat_duplicate clusters() duplicated the root directory unnecessarily.
 * Let's free it.
 *
 * This must be called AFTER fat_construct_new_fat().  (otherwise, our
 * changes just get overwritten)
 */
static int
free_root_dir (FatOpContext* ctx)
{
	FatSpecific*		old_fs_info = FAT_SPECIFIC (ctx->old_fs);
	FatSpecific*		new_fs_info = FAT_SPECIFIC (ctx->new_fs);
	FatCluster		old_cluster;
	FatFragment		i;

	PED_ASSERT (old_fs_info->fat_type == FAT_TYPE_FAT32);
	PED_ASSERT (new_fs_info->fat_type == FAT_TYPE_FAT16);

	for (old_cluster = old_fs_info->root_cluster;
	     !fat_table_is_eof (old_fs_info->fat, old_cluster);
	     old_cluster = fat_table_get (old_fs_info->fat, old_cluster)) {
		FatFragment old_frag;
		old_frag = fat_cluster_to_frag (ctx->old_fs, old_cluster);
		for (i = 0; i < new_fs_info->cluster_frags; i++) {
			FatFragment new_frag;
			FatCluster new_clst;
			new_frag = fat_op_context_map_fragment (ctx,
								old_frag + i);
			new_clst = fat_frag_to_cluster (ctx->old_fs, new_frag);
			if (!fat_table_set_avail (new_fs_info->fat, new_clst))
				return 0;
		}
	}

	return 1;
}
예제 #4
0
파일: resize.c 프로젝트: Excito/parted
/* This MUST be called BEFORE the fat_construct_new_fat(), because cluster
 * allocation depend on the old FAT.  The reason is, old clusters may
 * still be needed during the resize, (particularly clusters in the directory
 * tree) even if they will be discarded later.
 */
static int
alloc_root_dir (FatOpContext* ctx)
{
	FatSpecific*		old_fs_info = FAT_SPECIFIC (ctx->old_fs);
	FatSpecific*		new_fs_info = FAT_SPECIFIC (ctx->new_fs);
	FatCluster		i;
	FatCluster		cluster;
	FatCluster		cluster_count;

	PED_ASSERT (new_fs_info->fat_type == FAT_TYPE_FAT32);

	cluster_count = ped_div_round_up (
			   PED_MAX (16, old_fs_info->root_dir_sector_count),
			   new_fs_info->cluster_sectors);

	for (i = 0; i < cluster_count; i++) {
		cluster = fat_table_alloc_check_cluster (new_fs_info->fat,
							 ctx->new_fs);
		if (!cluster)
			return 0;
		ctx->new_root_dir [i] = cluster;
		clear_cluster (ctx->new_fs, cluster);
	}
	ctx->new_root_dir [i] = 0;
	new_fs_info->root_cluster = ctx->new_root_dir [0];
	return 1;
}
예제 #5
0
파일: resize.c 프로젝트: Excito/parted
int
fat_resize (PedFileSystem* fs, PedGeometry* geom, PedTimer* timer)
{
	FatSpecific*	fs_info = FAT_SPECIFIC (fs);
	FatSpecific*	new_fs_info;
	FatOpContext*	ctx;
	PedFileSystem*	new_fs;

	ctx = create_resize_context (fs, geom);
	if (!ctx)
		goto error;
	new_fs = ctx->new_fs;
	new_fs_info = FAT_SPECIFIC (new_fs);

	if (!fat_duplicate_clusters (ctx, timer))
		goto error_abort_ctx;
	if (fs_info->fat_type == FAT_TYPE_FAT16
			&& new_fs_info->fat_type == FAT_TYPE_FAT32) {
		if (!alloc_root_dir (ctx))
			goto error_abort_ctx;
	}
	if (!fat_construct_new_fat (ctx))
		goto error_abort_ctx;
	if (fs_info->fat_type == FAT_TYPE_FAT32
			&& new_fs_info->fat_type == FAT_TYPE_FAT16) {
		if (!free_root_dir (ctx))
			goto error_abort_ctx;
	}
	if (!fat_construct_dir_tree (ctx))
		goto error_abort_ctx;
	if (!fat_table_write_all (new_fs_info->fat, new_fs))
		goto error_abort_ctx;

	_copy_hidden_sectors (ctx);
	fat_boot_sector_generate (&new_fs_info->boot_sector, new_fs);
	fat_boot_sector_write (&new_fs_info->boot_sector, new_fs);
	if (new_fs_info->fat_type == FAT_TYPE_FAT32) {
		fat_info_sector_generate (&new_fs_info->info_sector, new_fs);
		fat_info_sector_write (&new_fs_info->info_sector, new_fs);
	}

	if (!resize_context_assimilate (ctx))
		goto error;

	return 1;

error_abort_ctx:
	resize_context_abort (ctx);
error:
	return 0;
}
예제 #6
0
파일: resize.c 프로젝트: Excito/parted
/*  For resize operations: determine if the file system must be FAT16 or FAT32,
 *  or either.  If the new file system must be FAT32, then query for
 *  confirmation.  If either file system can be used, query for which one.
 */
static int
get_fat_type (PedFileSystem* fs, const PedGeometry* new_geom,
	      FatType* out_fat_type)
{
	FatSpecific*		fs_info = FAT_SPECIFIC (fs);
	PedSector		fat16_cluster_sectors;
	PedSector		fat32_cluster_sectors;
	FatCluster		dummy_cluster_count;
	PedSector		dummy_fat_sectors;
	int			fat16_ok;
	int			fat32_ok;

	fat16_ok = fat_calc_resize_sizes (
				    new_geom,
				    fs_info->cluster_sectors,
				    FAT_TYPE_FAT16,
				    fs_info->root_dir_sector_count,
				    fs_info->cluster_sectors,
				    &fat16_cluster_sectors,
				    &dummy_cluster_count,
				    &dummy_fat_sectors);

	fat32_ok = fat_calc_resize_sizes (
				    new_geom,
				    fs_info->cluster_sectors,
				    FAT_TYPE_FAT32,
				    fs_info->root_dir_sector_count,
				    fs_info->cluster_sectors,
				    &fat32_cluster_sectors,
				    &dummy_cluster_count,
				    &dummy_fat_sectors);

	return ask_type (fs, fat16_ok, fat32_ok, out_fat_type);
}
예제 #7
0
static int
read_next_dir_buffer (FatTraverseInfo* trav_info)
{
	FatSpecific*	fs_info = FAT_SPECIFIC (trav_info->fs);

	PED_ASSERT (!trav_info->is_legacy_root_dir);

	trav_info->this_buffer = trav_info->next_buffer;

	if (trav_info->this_buffer < 2
	    || trav_info->this_buffer >= fs_info->cluster_count + 2) {
		ped_exception_throw (
			PED_EXCEPTION_ERROR,
			PED_EXCEPTION_CANCEL,
			"Cluster %ld in directory %s is outside file system!",
			(long) trav_info->this_buffer,
			trav_info->dir_name);
		return 0;
	}

	trav_info->next_buffer
		= fat_table_get (fs_info->fat, trav_info->this_buffer);

	return fat_read_cluster (trav_info->fs, (void *) trav_info->dir_entries,
				 trav_info->this_buffer);
}
예제 #8
0
파일: resize.c 프로젝트: Excito/parted
static void
clear_cluster (PedFileSystem* fs, FatCluster cluster)
{
	FatSpecific*		fs_info = FAT_SPECIFIC (fs);

	memset (fs_info->buffer, 0, fs_info->cluster_size);
	fat_write_cluster (fs, fs_info->buffer, cluster);
}
예제 #9
0
FatFragment
fat_cluster_to_frag (const PedFileSystem* fs, FatCluster cluster)
{
	FatSpecific*	fs_info = FAT_SPECIFIC (fs);

	PED_ASSERT (cluster >= 2 && cluster < fs_info->cluster_count + 2);

	return (cluster - 2) * fs_info->cluster_frags;
}
예제 #10
0
/* returns 1 if there are no more directory entries in the directory being
 * traversed, 0 otherwise.
 */
static int
is_last_buffer (FatTraverseInfo* trav_info) {
	FatSpecific*	fs_info = FAT_SPECIFIC (trav_info->fs);

	if (trav_info->is_legacy_root_dir)
		return 1;
	else
		return fat_table_is_eof (fs_info->fat, trav_info->next_buffer);
}
예제 #11
0
PedSector
fat_frag_to_sector (const PedFileSystem* fs, FatFragment frag)
{
	FatSpecific*	fs_info = FAT_SPECIFIC (fs);

	PED_ASSERT (frag >= 0 && frag < fs_info->frag_count);

	return frag * fs_info->frag_sectors + fs_info->cluster_offset;
}
예제 #12
0
FatFragment
fat_sector_to_frag (const PedFileSystem* fs, PedSector sector)
{
	FatSpecific*	fs_info = FAT_SPECIFIC (fs);

	PED_ASSERT (sector >= fs_info->cluster_offset);

	return (sector - fs_info->cluster_offset) / fs_info->frag_sectors;
}
예제 #13
0
int
fat_is_sector_in_clusters (const PedFileSystem* fs, PedSector sector)
{
	FatSpecific*	fs_info = FAT_SPECIFIC (fs);

	return sector >= fs_info->cluster_offset
	       && sector < fs_info->cluster_offset
	      		   + fs_info->cluster_sectors * fs_info->cluster_count;
}
예제 #14
0
FatCluster
fat_frag_to_cluster (const PedFileSystem* fs, FatFragment frag)
{
	FatSpecific*	fs_info = FAT_SPECIFIC (fs);

	PED_ASSERT (frag >= 0 && frag < fs_info->frag_count);

	return frag / fs_info->cluster_frags + 2;
}
예제 #15
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;
}
예제 #16
0
FatCluster
fat_sector_to_cluster (const PedFileSystem* fs, PedSector sector)
{
	FatSpecific*	fs_info = FAT_SPECIFIC (fs);

	PED_ASSERT (sector >= fs_info->cluster_offset);

	return (sector - fs_info->cluster_offset) / fs_info->cluster_sectors
		+ 2;
}
예제 #17
0
PedSector
fat_cluster_to_sector (const PedFileSystem* fs, FatCluster cluster)
{
	FatSpecific*	fs_info = FAT_SPECIFIC (fs);

	PED_ASSERT (cluster >= 2 && cluster < fs_info->cluster_count + 2);

	return (cluster - 2) * fs_info->cluster_sectors
		+ fs_info->cluster_offset;
}
예제 #18
0
FatTraverseInfo*
fat_traverse_begin (PedFileSystem* fs, FatCluster start_cluster,
		    const char* dir_name)
{
	FatSpecific*		fs_info = FAT_SPECIFIC (fs);
	FatTraverseInfo*	trav_info;

	trav_info = (FatTraverseInfo*) ped_malloc (sizeof (FatTraverseInfo));
	if (!trav_info)
		goto error;

	trav_info->dir_name = strdup (dir_name);
	if (!trav_info->dir_name)
		goto error_free_trav_info;

	trav_info->fs = fs;
	trav_info->is_legacy_root_dir
		= (fs_info->fat_type == FAT_TYPE_FAT16) && (start_cluster == 0);
	trav_info->dirty = 0;
	trav_info->eof = 0;
	trav_info->current_entry = -1;

	if (trav_info->is_legacy_root_dir) {
		trav_info->buffer_size = 512 * fs_info->root_dir_sector_count;
	} else {
		trav_info->next_buffer = start_cluster;
		trav_info->buffer_size = fs_info->cluster_size;
	}

	trav_info->dir_entries
		= (FatDirEntry*) ped_malloc (trav_info->buffer_size);
	if (!trav_info->dir_entries)
		goto error_free_dir_name;

	if (trav_info->is_legacy_root_dir) {
		if (!ped_geometry_read (fs->geom, trav_info->dir_entries,
					fs_info->root_dir_offset,
					fs_info->root_dir_sector_count))
			goto error_free_dir_entries;
	} else {
		if (!read_next_dir_buffer (trav_info))
			goto error_free_dir_entries;
	}

	return trav_info;

error_free_dir_entries:
	free (trav_info->dir_entries);
error_free_dir_name:
	free (trav_info->dir_name);
error_free_trav_info:
	free (trav_info);
error:
	return NULL;
}
예제 #19
0
파일: bootsector.c 프로젝트: bcl/parted
int
fat_info_sector_write (const FatInfoSector* is, PedFileSystem *fs)
{
	FatSpecific*	fs_info = FAT_SPECIFIC (fs);

	PED_ASSERT (is != NULL);

	if (!ped_geometry_write (fs->geom, is, fs_info->info_sector_offset, 1))
		return 0;
	return ped_geometry_sync (fs->geom);
}
예제 #20
0
파일: resize.c 프로젝트: Excito/parted
/*
    Constructs the new directory tree for new (FAT32) file systems.
*/
static int
fat_construct_root (FatOpContext* ctx)
{
	FatSpecific*		new_fs_info = FAT_SPECIFIC (ctx->new_fs);
	FatTraverseInfo*	trav_info;

	trav_info = fat_traverse_begin (ctx->new_fs, new_fs_info->root_cluster,
					"\\");
	fat_construct_directory (ctx, trav_info);
	return 1;
}
예제 #21
0
파일: resize.c 프로젝트: Excito/parted
static int
duplicate_legacy_root_dir (FatOpContext* ctx)
{
	FatSpecific*		old_fs_info = FAT_SPECIFIC (ctx->old_fs);
	FatSpecific*		new_fs_info = FAT_SPECIFIC (ctx->new_fs);

	PED_ASSERT (old_fs_info->root_dir_sector_count
			== new_fs_info->root_dir_sector_count);

	if (!ped_geometry_read (ctx->old_fs->geom, old_fs_info->buffer,
				old_fs_info->root_dir_offset,
				old_fs_info->root_dir_sector_count))
		return 0;

	if (!ped_geometry_write (ctx->new_fs->geom, old_fs_info->buffer,
				 new_fs_info->root_dir_offset,
				 new_fs_info->root_dir_sector_count))
		return 0;

	return 1;
}
예제 #22
0
파일: fatio.c 프로젝트: NekPoN/parted
int
fat_write_fragments (PedFileSystem* fs, char* buf, FatFragment frag,
                     FatFragment count)
{
    FatSpecific*	fs_info = FAT_SPECIFIC (fs);
    PedSector	sector = fat_frag_to_sector (fs, frag);
    PedSector	sector_count = count * fs_info->frag_sectors;

    PED_ASSERT (frag >= 0 && frag < fs_info->frag_count);

    return ped_geometry_write (fs->geom, buf, sector, sector_count);
}
예제 #23
0
파일: fatio.c 프로젝트: NekPoN/parted
int
fat_read_clusters (PedFileSystem* fs, char *buf, FatCluster cluster,
                   FatCluster count)
{
    FatSpecific*	fs_info = FAT_SPECIFIC (fs);
    PedSector	sector = fat_cluster_to_sector (fs, cluster);
    PedSector	sector_count = count * fs_info->cluster_sectors;

    PED_ASSERT (cluster >= 2
                && cluster + count - 1 < fs_info->cluster_count + 2);

    return ped_geometry_read (fs->geom, buf, sector, sector_count);
}
예제 #24
0
파일: resize.c 프로젝트: Excito/parted
static int
resize_context_assimilate (FatOpContext* ctx)
{
	FatSpecific*	old_fs_info = FAT_SPECIFIC (ctx->old_fs);
	FatSpecific*	new_fs_info = FAT_SPECIFIC (ctx->new_fs);

	fat_free_buffers (ctx->old_fs);
	fat_table_destroy (old_fs_info->fat);
	free (old_fs_info);
	ped_geometry_destroy (ctx->old_fs->geom);

	ctx->old_fs->type_specific = ctx->new_fs->type_specific;
	ctx->old_fs->geom = ctx->new_fs->geom;
	ctx->old_fs->type = (new_fs_info->fat_type == FAT_TYPE_FAT16)
				? &fat16_type
			       	: &fat32_type;

	free (ctx->new_fs);

	fat_op_context_destroy (ctx);

	return 1;
}
예제 #25
0
static int
write_root_dir (FatTraverseInfo* trav_info)
{
	FatSpecific*	fs_info = FAT_SPECIFIC (trav_info->fs);

	if (!ped_geometry_write (trav_info->fs->geom, trav_info->dir_entries,
				 fs_info->root_dir_offset,
				 fs_info->root_dir_sector_count))
		return 0;
	if (!ped_geometry_sync (trav_info->fs->geom))
		return 0;
	trav_info->dirty = 0;
	return 1;
}
예제 #26
0
파일: resize.c 프로젝트: Excito/parted
/*
    Constructs the new directory tree to match the new file locations.
*/
static int
fat_construct_dir_tree (FatOpContext* ctx)
{
	FatSpecific*		new_fs_info = FAT_SPECIFIC (ctx->new_fs);
	FatSpecific*		old_fs_info = FAT_SPECIFIC (ctx->old_fs);

	if (new_fs_info->fat_type == old_fs_info->fat_type) {
		switch (old_fs_info->fat_type) {
                        case FAT_TYPE_FAT12:
                        PED_ASSERT (0);
                        break;

			case FAT_TYPE_FAT16:
			return fat_construct_legacy_root (ctx);

			case FAT_TYPE_FAT32:
			return fat_construct_root (ctx);
		}
	} else {
		return fat_construct_converted_tree (ctx);
	}

	return 0;
}
예제 #27
0
파일: resize.c 프로젝트: Excito/parted
static int
resize_context_abort (FatOpContext* ctx)
{
	FatSpecific*	new_fs_info = FAT_SPECIFIC (ctx->new_fs);

	fat_free_buffers (ctx->new_fs);
	fat_table_destroy (new_fs_info->fat);
	free (new_fs_info);
	ped_geometry_destroy (ctx->new_fs->geom);
	free (ctx->new_fs);

	fat_op_context_destroy (ctx);

	return 1;
}
예제 #28
0
파일: bootsector.c 프로젝트: bcl/parted
int
fat_boot_sector_set_boot_code (FatBootSector** bsp, const PedFileSystem* fs)
{
	FatSpecific*	fs_info = FAT_SPECIFIC (fs);

	PED_ASSERT (bsp != NULL);
	*bsp = ped_malloc (fs->geom->dev->sector_size);
	FatBootSector *bs = *bsp;
	PED_ASSERT (bs != NULL);

	memset (bs, 0, 512);
	memcpy (bs->boot_jump, FAT_BOOT_JUMP, 3);
	memcpy (bs->u.fat32.boot_code, FAT_BOOT_CODE, FAT_BOOT_CODE_LENGTH);
	return 1;
}
예제 #29
0
파일: bootsector.c 프로젝트: bcl/parted
int
fat_boot_sector_write (const FatBootSector* bs, PedFileSystem* fs)
{
	FatSpecific*	fs_info = FAT_SPECIFIC (fs);

	PED_ASSERT (bs != NULL);

	if (!ped_geometry_write (fs->geom, bs, 0, 1))
		return 0;
	if (fs_info->fat_type == FAT_TYPE_FAT32) {
		if (!ped_geometry_write (fs->geom, bs,
					 fs_info->boot_sector_backup_offset, 1))
			return 0;
	}
	return ped_geometry_sync (fs->geom);
}
예제 #30
0
int
fat_dir_entry_has_first_cluster (FatDirEntry* dir_entry, PedFileSystem* fs)
{
	FatSpecific*	fs_info = FAT_SPECIFIC (fs);
	FatCluster	first_cluster;

	if (!fat_dir_entry_is_file (dir_entry)
		&& !fat_dir_entry_is_directory (dir_entry))
		return 0;

	first_cluster = fat_dir_entry_get_first_cluster (dir_entry, fs);
	if (first_cluster == 0
		|| fat_table_is_eof (fs_info->fat, first_cluster))
		return 0;

	return 1;
}