/** * Return the nearest region to \p geom that satisfy a \p constraint. * * Note that "nearest" is somewhat ambiguous. This function makes * no guarantees about how this ambiguity is resovled. * * \return PedGeometry, or NULL when a \p constrain cannot be satisfied */ PedGeometry* ped_constraint_solve_nearest ( const PedConstraint* constraint, const PedGeometry* geom) { PedSector start; PedSector end; PedGeometry* result; if (constraint == NULL) return NULL; PED_ASSERT (geom != NULL); PED_ASSERT (constraint->start_range->dev == geom->dev); start = _constraint_get_nearest_start_soln (constraint, geom->start); if (start == -1) return NULL; end = _constraint_get_nearest_end_soln (constraint, start, geom->end); if (end == -1) return NULL; result = ped_geometry_new (geom->dev, start, end - start + 1); if (!result) return NULL; PED_ASSERT (ped_constraint_is_solution (constraint, result)); return result; }
/** * Initializes a pre-allocated piece of memory to contain a constraint * with the supplied default values. * * \return \c 0 on failure. */ int ped_constraint_init ( PedConstraint* constraint, const PedAlignment* start_align, const PedAlignment* end_align, const PedGeometry* start_range, const PedGeometry* end_range, PedSector min_size, PedSector max_size) { PED_ASSERT (constraint != NULL); PED_ASSERT (start_range != NULL); PED_ASSERT (end_range != NULL); PED_ASSERT (min_size > 0); PED_ASSERT (max_size > 0); constraint->start_align = ped_alignment_duplicate (start_align); constraint->end_align = ped_alignment_duplicate (end_align); constraint->start_range = ped_geometry_duplicate (start_range); constraint->end_range = ped_geometry_duplicate (end_range); constraint->min_size = min_size; constraint->max_size = max_size; return 1; }
/* Signal handler for SIGSEGV using 'sigaction'. */ static void sa_sigsegv_handler (int signum, siginfo_t* info, void* ucontext) { fprintf (stderr, bug_msg, VERSION); _dump_history (); if (!info) abort (); sigaction (SIGSEGV, &sig_segv, NULL); switch (info->si_code) { case SEGV_MAPERR: fputs(_("\nError: SEGV_MAPERR (Address not mapped " "to object)\n"), stdout); PED_ASSERT(0); /* Force a backtrace */ break; case SEGV_ACCERR: fputs(_("\nError: SEGV_ACCERR (Invalid permissions " "for mapped object)\n"), stdout); break; default: fputs(_("\nError: A general SIGSEGV signal was " "encountered.\n"), stdout); PED_ASSERT(0); /* Force a backtrace */ break; } abort (); }
/* Same as fat_calc_sizes, except it only attempts to match a particular * cluster size. This is useful, because the FAT resizer can only shrink the * cluster size. */ int fat_calc_resize_sizes ( const PedGeometry* geom, PedSector align, FatType fat_type, PedSector root_dir_sectors, PedSector cluster_sectors, PedSector* out_cluster_sectors, FatCluster* out_cluster_count, PedSector* out_fat_size) { PED_ASSERT (geom != NULL); PED_ASSERT (out_cluster_sectors != NULL); PED_ASSERT (out_cluster_count != NULL); PED_ASSERT (out_fat_size != NULL); /* libparted can only reduce the cluster size at this point */ for (*out_cluster_sectors = cluster_sectors; *out_cluster_sectors >= fat_min_cluster_size (fat_type); *out_cluster_sectors /= 2) { if (calc_sizes (geom->length, align, fat_type, root_dir_sectors, *out_cluster_sectors, out_cluster_count, out_fat_size)) return 1; } return 0; }
/* 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; }
static int amiga_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state) { struct PartitionBlock *partition; PED_ASSERT (part != NULL); PED_ASSERT (part->disk_specific != NULL); partition = PART(part->disk_specific); switch (flag) { case PED_PARTITION_BOOT: if (state) partition->pb_Flags |= PED_CPU_TO_BE32(PBFF_BOOTABLE); else partition->pb_Flags &= ~(PED_CPU_TO_BE32(PBFF_BOOTABLE)); return 1; case PED_PARTITION_HIDDEN: if (state) partition->pb_Flags |= PED_CPU_TO_BE32(PBFF_NOMOUNT); else partition->pb_Flags &= ~(PED_CPU_TO_BE32(PBFF_NOMOUNT)); return 1; case PED_PARTITION_RAID: if (state) partition->pb_Flags |= PED_CPU_TO_BE32(PBFF_RAID); else partition->pb_Flags &= ~(PED_CPU_TO_BE32(PBFF_RAID)); return 1; case PED_PARTITION_LVM: if (state) partition->pb_Flags |= PED_CPU_TO_BE32(PBFF_LVM); else partition->pb_Flags &= ~(PED_CPU_TO_BE32(PBFF_LVM)); return 1; default: return 0; } }
static int bsd_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state) { // PedPartition* walk; // since -Werror, this unused variable would break build BSDPartitionData* bsd_data; PED_ASSERT (part != NULL); PED_ASSERT (part->disk_specific != NULL); PED_ASSERT (part->disk != NULL); bsd_data = part->disk_specific; switch (flag) { case PED_PARTITION_BOOT: bsd_data->boot = state; return 1; case PED_PARTITION_RAID: if (state) { bsd_data->lvm = 0; } bsd_data->raid = state; return 1; case PED_PARTITION_LVM: if (state) { bsd_data->raid = 0; } bsd_data->lvm = state; default: ; } return 0; }
static int pc98_alloc_metadata (PedDisk* disk) { PedPartition* new_part; PedConstraint* constraint_any = NULL; PedSector cyl_size; PED_ASSERT (disk != NULL); PED_ASSERT (disk->dev != NULL); constraint_any = ped_constraint_any (disk->dev); cyl_size = disk->dev->hw_geom.sectors * disk->dev->hw_geom.heads; new_part = ped_partition_new (disk, PED_PARTITION_METADATA, NULL, 0, cyl_size - 1); if (!new_part) goto error; if (!ped_disk_add_partition (disk, new_part, constraint_any)) { ped_partition_destroy (new_part); goto error; } ped_constraint_destroy (constraint_any); return 1; error: ped_constraint_destroy (constraint_any); return 0; }
static int amiga_alloc_metadata (PedDisk* disk) { PedPartition* new_part; PedConstraint* constraint_any = NULL; PED_ASSERT (disk != NULL); PED_ASSERT (disk->dev != NULL); constraint_any = ped_constraint_any (disk->dev); /* Allocate space for the RDB */ new_part = ped_partition_new (disk, PED_PARTITION_METADATA, NULL, 0, MAX_RDB_BLOCK); if (!new_part) goto error; if (!ped_disk_add_partition (disk, new_part, constraint_any)) { ped_partition_destroy (new_part); goto error; } ped_constraint_destroy (constraint_any); return 1; error: ped_constraint_destroy (constraint_any); return 0; }
static int amiga_partition_enumerate (PedPartition* part) { int i; PedPartition* p; PED_ASSERT (part != NULL); PED_ASSERT (part->disk != NULL); /* never change the partition numbers */ if (part->num != -1) return 1; for (i = 1; i <= AMIGA_MAX_PARTITIONS; i++) { p = ped_disk_get_partition (part->disk, i); if (!p) { part->num = i; return 1; } } /* failed to allocate a number */ #ifndef DISCOVER_ONLY ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("Unable to allocate a partition number.")); #endif return 0; }
static int bsd_alloc_metadata (PedDisk* disk) { PedPartition* new_part; PedConstraint* constraint_any = NULL; PED_ASSERT (disk != NULL); PED_ASSERT (disk->dev != NULL); constraint_any = ped_constraint_any (disk->dev); /* allocate 1 sector for the disk label at the start */ new_part = ped_partition_new (disk, PED_PARTITION_METADATA, NULL, 0, 0); if (!new_part) goto error; if (!ped_disk_add_partition (disk, new_part, constraint_any)) { ped_partition_destroy (new_part); goto error; } ped_constraint_destroy (constraint_any); return 1; error: ped_constraint_destroy (constraint_any); return 0; }
static PedGeometry* _generic_apfs_probe (PedGeometry* geom, uint32_t kind) { uint32_t *block; PedSector root; struct PartitionBlock * part; uint32_t blocksize = 1, reserved = 2; PED_ASSERT (geom != NULL); PED_ASSERT (geom->dev != NULL); if (geom->dev->sector_size != 512) return NULL; /* Finds the blocksize and reserved values of the partition block */ if (!(part = ped_malloc (PED_SECTOR_SIZE_DEFAULT*blocksize))) { ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("%s : Failed to allocate partition block\n"), __func__); goto error_part; } if (amiga_find_part(geom, part) != NULL) { reserved = PED_BE32_TO_CPU (part->de_Reserved); blocksize = PED_BE32_TO_CPU (part->de_SizeBlock) * PED_BE32_TO_CPU (part->de_SectorPerBlock) / 128; } free (part); /* Test boot block */ if (!(block = ped_malloc (PED_SECTOR_SIZE_DEFAULT*blocksize))) { ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("%s : Failed to allocate block\n"), __func__); goto error_block; } if (!ped_device_read (geom->dev, block, geom->start, blocksize)) { ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("%s : Couldn't read boot block %llu\n"), __func__, geom->start); goto error; } if (PED_BE32_TO_CPU (block[0]) != kind) { goto error; } /* Find and test the root block */ root = geom->start+reserved*blocksize; if (!ped_device_read (geom->dev, block, root, blocksize)) { ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("%s : Couldn't read root block %llu\n"), __func__, root); goto error; } if (_apfs_probe_root(block, blocksize, kind) == 1) { free(block); return ped_geometry_duplicate (geom); } error: free (block); error_block: error_part: return NULL; }
static int pc98_read (PedDisk* disk) { PED_ASSERT (disk != NULL); PED_ASSERT (disk->dev != NULL); ped_disk_delete_all (disk); return read_table (disk); }
static PedSector _GL_ATTRIBUTE_PURE legacy_start (const PedDisk* disk, const PC98RawPartition* raw_part) { PED_ASSERT (disk != NULL); PED_ASSERT (raw_part != NULL); return chs_to_sector (disk->dev, PED_LE16_TO_CPU(raw_part->cyl), raw_part->head, raw_part->sector); }
static void amiga_free (PedDisk* disk) { PED_ASSERT(disk != NULL); PED_ASSERT(disk->disk_specific != NULL); free (disk->disk_specific); _ped_disk_free (disk); }
static void amiga_partition_destroy (PedPartition* part) { PED_ASSERT (part != NULL); if (ped_partition_is_active (part)) { PED_ASSERT (part->disk_specific != NULL); free (part->disk_specific); } _ped_partition_free (part); }
void ped_disk_amiga_init () { PED_ASSERT (sizeof (struct AmigaBlock) != 3); PED_ASSERT (sizeof (struct RigidDiskBlock) != 64); PED_ASSERT (sizeof (struct PartitionBlock) != 64); PED_ASSERT (sizeof (struct LinkedBlock) != 5); PED_ASSERT (sizeof (struct Linked2Block) != 18); ped_disk_type_register (&amiga_disk_type); }
static const char* _GL_ATTRIBUTE_PURE pc98_partition_get_name (const PedPartition* part) { PC98PartitionData* pc98_data; PED_ASSERT (part != NULL); PED_ASSERT (part->disk_specific != NULL); pc98_data = part->disk_specific; return pc98_data->name; }
static void amiga_partition_set_name (PedPartition* part, const char* name) { struct PartitionBlock *partition; PED_ASSERT (part != NULL); PED_ASSERT (part->disk_specific != NULL); partition = PART(part->disk_specific); _amiga_set_bstr(name, partition->pb_DriveName, 32); }
static const char* amiga_partition_get_name (const PedPartition* part) { struct PartitionBlock *partition; PED_ASSERT (part != NULL); PED_ASSERT (part->disk_specific != NULL); partition = PART(part->disk_specific); return _amiga_get_bstr(partition->pb_DriveName); }
/* Reads in the boot sector (superblock), and does a minimum of sanity * checking. The goals are: * - to detect fat file systems, even if they are damaged [i.e. not * return an error / throw an exception] * - to fail detection if there's not enough information for * fat_boot_sector_probe_type() to work (or possibly crash on a divide-by-zero) */ int fat_boot_sector_read (FatBootSector* bs, const PedGeometry *geom) { PED_ASSERT (bs != NULL); PED_ASSERT (geom != NULL); if (!ped_geometry_read (geom, bs, 0, 1)) return 0; if (PED_LE16_TO_CPU (bs->boot_sign) != 0xAA55) { ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("File system has an invalid signature for a FAT " "file system.")); return 0; } if (!bs->system_id[0]) { ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("File system has an invalid signature for a FAT " "file system.")); return 0; } if (!bs->sector_size || PED_LE16_TO_CPU (bs->sector_size) % PED_SECTOR_SIZE_DEFAULT) { ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("File system has an invalid sector size for a FAT " "file system.")); return 0; } if (!bs->cluster_size) { ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("File system has an invalid cluster size for a FAT " "file system.")); return 0; } if (!bs->reserved) { ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("File system has an invalid number of reserved " "sectors for a FAT file system.")); return 0; } if (bs->fats < 1 || bs->fats > 4) { ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("File system has an invalid number of FATs.")); return 0; } return 1; }
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; }
static int _amiga_find_free_blocks(const PedDisk *disk, uint32_t *table, struct LinkedBlock *block, uint32_t first, uint32_t type) { PedSector next; PED_ASSERT(disk != NULL); PED_ASSERT(disk->dev != NULL); for (next = first; next != LINK_END; next = PED_BE32_TO_CPU(block->lk_Next)) { if (table[next] != IDNAME_FREE) { switch (ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_FIX | PED_EXCEPTION_IGNORE | PED_EXCEPTION_CANCEL, _("%s : Loop detected at block %d."), __func__, next)) { case PED_EXCEPTION_CANCEL : return 0; case PED_EXCEPTION_FIX : /* TODO : Need to add fixing code */ case PED_EXCEPTION_IGNORE : case PED_EXCEPTION_UNHANDLED : default : return 1; } } if (!_amiga_read_block (disk->dev, AMIGA(block), next, NULL)) { return 0; } if (PED_BE32_TO_CPU(block->lk_ID) != type) { switch (ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("%s : The %s list seems bad at block %s."), __func__, _amiga_block_id(PED_BE32_TO_CPU(block->lk_ID)), next)) { /* TODO : to more subtile things here */ case PED_EXCEPTION_CANCEL : case PED_EXCEPTION_UNHANDLED : default : return 0; } } table[next] = type; if (PED_BE32_TO_CPU(block->lk_ID) == IDNAME_FILESYSHEADER) { if (_amiga_find_free_blocks(disk, table, block, PED_BE32_TO_CPU(LNK2(block)->lk2_Linked), IDNAME_LOADSEG) == 0) return 0; } } return 1; }
int fat_calc_sizes (PedSector size, PedSector align, FatType fat_type, PedSector root_dir_sectors, PedSector* out_cluster_sectors, FatCluster* out_cluster_count, PedSector* out_fat_size) { PedSector cluster_sectors; PED_ASSERT (out_cluster_sectors != NULL); PED_ASSERT (out_cluster_count != NULL); PED_ASSERT (out_fat_size != NULL); for (cluster_sectors = fat_recommend_min_cluster_size (fat_type, size); cluster_sectors <= fat_max_cluster_size (fat_type); cluster_sectors *= 2) { if (calc_sizes (size, align, fat_type, root_dir_sectors, cluster_sectors, out_cluster_count, out_fat_size)) { *out_cluster_sectors = cluster_sectors; return 1; } } for (cluster_sectors = fat_recommend_min_cluster_size (fat_type, size); cluster_sectors >= fat_min_cluster_size (fat_type); cluster_sectors /= 2) { if (calc_sizes (size, align, fat_type, root_dir_sectors, cluster_sectors, out_cluster_count, out_fat_size)) { *out_cluster_sectors = cluster_sectors; return 1; } } /* only make the cluster size really small (<4k) if a bigger one is * isn't possible. Windows never makes FS's like this, but it * seems to work... (do more tests!) */ for (cluster_sectors = 4; cluster_sectors > 0; cluster_sectors /= 2) { if (calc_sizes (size, align, fat_type, root_dir_sectors, cluster_sectors, out_cluster_count, out_fat_size)) { *out_cluster_sectors = cluster_sectors; return 1; } } return 0; }
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; }
static void pc98_partition_set_name (PedPartition* part, const char* name) { PC98PartitionData* pc98_data; int i; PED_ASSERT (part != NULL); PED_ASSERT (part->disk_specific != NULL); pc98_data = part->disk_specific; strncpy (pc98_data->name, name, 16); pc98_data->name [16] = 0; for (i = strlen (pc98_data->name) - 1; pc98_data->name[i] == ' '; i--) pc98_data->name [i] = 0; }
static int bsd_write (const PedDisk* disk) { BSDDiskData* bsd_specific; BSDRawLabel* label; BSDPartitionData* bsd_data; PedPartition* part; int i; int max_part = 0; PED_ASSERT (disk != NULL); PED_ASSERT (disk->dev != NULL); bsd_specific = (BSDDiskData*) disk->disk_specific; label = (BSDRawLabel *) (bsd_specific->boot_code + BSD_LABEL_OFFSET); if (!bsd_specific->boot_code [0]) _probe_and_add_boot_code (disk); memset (label->d_partitions, 0, sizeof (BSDRawPartition) * BSD_MAXPARTITIONS); for (i = 1; i <= BSD_MAXPARTITIONS; i++) { part = ped_disk_get_partition (disk, i); if (!part) continue; bsd_data = part->disk_specific; label->d_partitions[i - 1].p_fstype = bsd_data->type; label->d_partitions[i - 1].p_offset = PED_CPU_TO_LE32 (part->geom.start); label->d_partitions[i - 1].p_size = PED_CPU_TO_LE32 (part->geom.length); max_part = i; } label->d_npartitions = PED_CPU_TO_LE16 (max_part) + 1; label->d_checksum = xbsd_dkcksum (label); alpha_bootblock_checksum (bsd_specific->boot_code); if (!ptt_write_sector (disk, bsd_specific->boot_code, sizeof (BSDDiskData))) goto error; return ped_device_sync (disk->dev); error: return 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); }
static void loop_free (PedDisk* disk) { PED_ASSERT (disk != NULL); _ped_disk_free (disk); }
static int dasd_partition_align (PedPartition* part, const PedConstraint* constraint) { DasdDiskSpecific* disk_specific; PED_ASSERT (part != NULL); disk_specific = part->disk->disk_specific; /* If formated in LDL, ignore metadata partition */ if (disk_specific->format_type == 1) return 1; if (_ped_partition_attempt_align(part, constraint, _primary_constraint(part->disk))) return 1; #ifndef DISCOVER_ONLY ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("Unable to satisfy all constraints on the partition.")); #endif return 0; }