/* 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; }
/** * 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; }
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; }