Пример #1
0
/* 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;
}
Пример #2
0
/**
 * If \p str contains a valid description of a location on \p dev, then
 * \p *sector is modified to describe the location and a geometry is created
 * in \p *range describing a 2 units large area centered on \p *sector.  If the
 * \p range as described here would be partially outside the device \p dev, the
 * geometry returned is the intersection between the former and the whole
 * device geometry.  If no units are specified, then the default unit is
 * assumed.
 *
 * \throws PED_EXCEPTION_ERROR if \p str contains invalid description of a
 * location
 * \throws PED_EXCEPTION_ERROR if location described by \p str
 * is outside of the device \p dev->path
 *
 * \return \c 1 if \p str is a valid location description, \c 0 otherwise.
 */
int
ped_unit_parse_custom (const char* str, const PedDevice* dev, PedUnit unit,
		       PedSector* sector, PedGeometry** range)
{
	char*     copy;
	char*     suffix;
	double    num;
	long long unit_size;
	PedSector radius;

	if (is_chs (str))
		return parse_chs (str, dev, sector, range);

	copy = ped_strdup (str);
	if (!copy)
		goto error;
	strip_string (copy);

	suffix = find_suffix (copy);
	unit = parse_unit_suffix (suffix, unit);
	suffix[0] = 0;

	if (sscanf (copy, "%lf", &num) != 1) {
		ped_exception_throw (
				PED_EXCEPTION_ERROR,
				PED_EXCEPTION_CANCEL,
				_("Invalid number."));
		goto error_free_copy;
	}
        if (num > 0 && num < 1) {
            ped_exception_throw (
                    PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
                    _("Use a smaller unit instead of a value < 1"));
            goto error_free_copy;
        }

	unit_size = ped_unit_get_size (dev, unit);
	radius = (ped_div_round_up (unit_size, dev->sector_size) / 2) - 1;
	if (radius < 0)
		radius = 0;
	/* If the user specifies units in a power of 2, e.g., 4MiB, as in
	       parted -s -- $dev mklabel gpt mkpart P-NAME 4MiB -34s
	   do not use 4MiB as the range.  Rather, presume that they
	   are specifying precisely the starting or ending number,
	   and treat "4MiB" just as we would treat "4194304B".  */
	if (is_power_of_2 (unit_size))
		radius = 0;

	*sector = num * unit_size / dev->sector_size;
	/* negative numbers count from the end */
	if (copy[0] == '-')
		*sector += dev->length;
	if (range) {
		*range = geometry_from_centre_radius (dev, *sector, radius);
		if (!*range) {
			ped_exception_throw (
				PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
				_("The location %s is outside of the "
				  "device %s."),
				str, dev->path);
			goto error_free_copy;
		}
	}
	*sector = clip (dev, *sector);

	free (copy);
	return 1;

error_free_copy:
	free (copy);
error:
	*sector = 0;
	if (range)
		*range = NULL;
	return 0;
}
Пример #3
0
int ext2_metadata_push(struct ext2_fs *fs, blk_t newsize)
{
	int   i;
	int   newgdblocks;
	blk_t newitoffset;

	newgdblocks = ped_div_round_up (newsize
                        - EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb),
			      EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb));
	newgdblocks = ped_div_round_up (newgdblocks
                        * sizeof(struct ext2_group_desc),
			      fs->blocksize);
	newitoffset = newgdblocks + 3;

	if (newitoffset <= fs->itoffset)
		return 1;

	for (i=0;i<fs->numgroups;i++)
	{
		blk_t diff;
		blk_t j;
		blk_t fromblock;
		blk_t start;

		start = (i * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb))
			+ EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb);

		if (EXT2_GROUP_INODE_TABLE(fs->gd[i]) >= start + newitoffset
		    && EXT2_GROUP_BLOCK_BITMAP(fs->gd[i]) >= start + newitoffset - 2
		    && EXT2_GROUP_INODE_BITMAP(fs->gd[i]) >= start + newitoffset - 1)
			continue;

		diff = newitoffset - (EXT2_GROUP_INODE_TABLE(fs->gd[i]) - start);

		/* inode table */
		fromblock = EXT2_GROUP_INODE_TABLE(fs->gd[i]) + fs->inodeblocks;

		if (fs->opt_debug)
		{
			for (j=0;j<diff;j++)
				if (!ext2_get_block_state(fs, fromblock+j))
				{
					fprintf(stderr,
						"error: block relocator "
						"should have relocated "
						"%i\n",
						fromblock);

					return 0;
				}
		}

		for (j=0;j<diff;j++)
			if (!ext2_set_block_state(fs, fromblock+j, 1, 0))
				return 0;

		if (!ext2_move_blocks(fs,
				      EXT2_GROUP_INODE_TABLE(fs->gd[i]),
				      fs->inodeblocks,
				      EXT2_GROUP_INODE_TABLE(fs->gd[i]) + diff))
			return 0;
		fs->gd[i].bg_inode_table = PED_CPU_TO_LE32 (
			EXT2_GROUP_INODE_TABLE(fs->gd[i]) + diff);
		fs->metadirty |= EXT2_META_GD;

		if (fs->opt_safe)
			if (!ext2_sync(fs))
				return 0;

		/* block bitmap and inode bitmap */
		fromblock = EXT2_GROUP_INODE_TABLE(fs->gd[i]);
		if (ext2_is_group_sparse(fs, i))
		{
			if (!ext2_copy_block(fs,
				EXT2_GROUP_INODE_BITMAP(fs->gd[i]),
				EXT2_GROUP_INODE_BITMAP(fs->gd[i]) + diff))
				return 0;
			fs->gd[i].bg_inode_bitmap = PED_CPU_TO_LE32 (
				EXT2_GROUP_INODE_BITMAP(fs->gd[i]) + diff);
                        fs->metadirty |= EXT2_META_GD;

			if (fs->opt_safe)
				if (!ext2_sync(fs))
					return 0;

			if (!ext2_copy_block(fs,
				EXT2_GROUP_BLOCK_BITMAP(fs->gd[i]),
				EXT2_GROUP_BLOCK_BITMAP(fs->gd[i])+diff))
				return 0;
			fs->gd[i].bg_block_bitmap = PED_CPU_TO_LE32 (
				EXT2_GROUP_BLOCK_BITMAP(fs->gd[i]) + diff);
			fs->metadirty |= EXT2_META_GD;

			if (fs->opt_safe)
				if (!ext2_sync(fs))
					return 0;

			fromblock = EXT2_GROUP_BLOCK_BITMAP(fs->gd[i]);
		}

		ext2_zero_blocks(fs, fromblock-diff, diff);
		for (j=0;j<diff;j++)
			if (!ext2_set_block_state(fs, fromblock+j-diff, 0, 0))
				return 0;

		if (fs->opt_verbose)
			fprintf(stderr,
				"ext2_metadata_push: group %i/%i\r",
				i+1, fs->numgroups);
	}

	fs->itoffset = newitoffset;

	if (fs->opt_verbose)
                fputc ('\n', stderr);

	return 1;
}