/* YUCK * * If you remove a boot/root/swap partition, the disk->disk_specific * thing isn't updated. (Probably reflects a design bug somewhere...) * Anyway, the workaround is: flush stale flags whenever we allocate * new partition numbers, and before we write to disk. */ static void _flush_stale_flags (const PedDisk* disk) { DVHDiskData* dvh_disk_data = disk->disk_specific; if (dvh_disk_data->root && !ped_disk_get_partition (disk, dvh_disk_data->root)) dvh_disk_data->root = 0; if (dvh_disk_data->swap && !ped_disk_get_partition (disk, dvh_disk_data->swap)) dvh_disk_data->swap = 0; if (dvh_disk_data->boot && !ped_disk_get_partition (disk, dvh_disk_data->boot)) dvh_disk_data->boot = 0; }
static int loop_write (const PedDisk* disk) { size_t buflen = disk->dev->sector_size; char *buf = ped_malloc (buflen); if (buf == NULL) return 0; if (ped_disk_get_partition (disk, 1)) { if (!ped_device_read (disk->dev, buf, 0, 1)) { free (buf); return 0; } if (strncmp (buf, LOOP_SIGNATURE, strlen (LOOP_SIGNATURE)) != 0) { free (buf); return 1; } memset (buf, 0, strlen (LOOP_SIGNATURE)); return ped_device_write (disk->dev, buf, 0, 1); } memset (buf, 0, buflen); strcpy (buf, LOOP_SIGNATURE); int write_ok = ped_device_write (disk->dev, buf, 0, 1); free (buf); return write_ok; }
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 next_primary (PedDisk* disk) { int i; for (i=1; i<=MAX_PART_COUNT; i++) { if (!ped_disk_get_partition (disk, i)) return i; } return 0; }
static int dvh_partition_enumerate (PedPartition* part) { int i; /* never change the partition numbers */ if (part->num != -1) return 1; _flush_stale_flags (part->disk); if (part->type & PED_PARTITION_LOGICAL) { /* Bootfile */ for (i = 1 + NPARTAB; i <= NPARTAB + NVDIR; i++) { if (!ped_disk_get_partition (part->disk, i)) { part->num = i; return 1; } } PED_ASSERT (0); } else if (part->type & PED_PARTITION_EXTENDED) { /* Volheader */ part->num = PNUM_VOLHDR + 1; } else { for (i = 1; i <= NPARTAB; i++) { /* reserved for full volume partition */ if (i == PNUM_VOLUME + 1) continue; if (!ped_disk_get_partition (part->disk, i)) { part->num = i; return 1; } } ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("Too many primary partitions")); } return 0; }
static int _can_create_primary (const PedDisk* disk) { int i; for (i = 1; i <= ped_disk_get_max_primary_partition_count (disk); i++) { if (!ped_disk_get_partition (disk, i)) return 1; } return 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; }
int command_line_get_partition (const char* prompt, PedDisk* disk, PedPartition** value) { PedPartition* part; int ret; /* Flawed logic, doesn't seem to work?! check = ped_disk_next_partition (disk, part); part = ped_disk_next_partition (disk, check); if (part == NULL) { *value = check; printf (_("The (only) primary partition has " "been automatically selected\n")); return 1; } else { */ int num = (*value) ? (*value)->num : 0; ret = command_line_get_integer (prompt, &num); if ((!ret) || (num < 0)) { ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("Expecting a partition number.")); return 0; } part = ped_disk_get_partition (disk, num); if (!part) { ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("Partition doesn't exist.")); return 0; } *value = part; return 1; //} }
static int dasd_partition_enumerate (PedPartition* part) { int i; PedPartition* p; /* never change the partition numbers */ if (part->num != -1) return 1; for (i = 1; i <= USABLE_PARTITIONS; i++) { p = ped_disk_get_partition (part->disk, i); if (!p) { part->num = i; return 1; } } /* failed to allocate a number */ ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("Unable to allocate a dasd disklabel slot")); return 0; }
static int pc98_write (const PedDisk* disk) { PedPartition* part; int i; PED_ASSERT (disk != NULL); PED_ASSERT (disk->dev != NULL); void *s0; if (!ptt_read_sectors (disk->dev, 0, 2, &s0)) return 0; PC98RawTable *table = s0; if (!pc98_check_ipl_signature (table)) { memset (table->boot_code, 0, sizeof(table->boot_code)); memcpy (table->boot_code, MBR_BOOT_CODE, sizeof(MBR_BOOT_CODE)); } memset (table->partitions, 0, sizeof (table->partitions)); table->magic = PED_CPU_TO_LE16(PC9800_EXTFMT_MAGIC); for (i = 1; i <= MAX_PART_COUNT; i++) { part = ped_disk_get_partition (disk, i); if (!part) continue; if (!fill_raw_part (&table->partitions [i - 1], part)) return 0; } int write_ok = ped_device_write (disk->dev, table, 0, 2); free (s0); if (!write_ok) return 0; return ped_device_sync (disk->dev); }
static int bsd_partition_enumerate (PedPartition* part) { int i; PedPartition* p; /* never change the partition numbers */ if (part->num != -1) return 1; for (i = 1; i <= BSD_MAXPARTITIONS; 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 bsd disklabel slot.")); #endif return 0; }
static int dasd_alloc_metadata (PedDisk* disk) { PedPartition* new_part; PedConstraint* constraint_any = NULL; PedSector vtoc_end; LinuxSpecific* arch_specific; DasdDiskSpecific* disk_specific; PedPartition* part = NULL; /* initialize solely to placate gcc */ PedPartition* new_part2; PedSector trailing_meta_start, trailing_meta_end; PED_ASSERT (disk != NULL); PED_ASSERT (disk->dev != NULL); arch_specific = LINUX_SPECIFIC (disk->dev); disk_specific = disk->disk_specific; constraint_any = ped_constraint_any (disk->dev); /* For LDL or CMS, the leading metadata ends at the sector before the start of the first partition */ if (disk_specific->format_type == 1) { part = ped_disk_get_partition(disk, 1); if (part) vtoc_end = part->geom.start - 1; else vtoc_end = (PedSector) arch_specific->real_sector_size / (PedSector) disk->dev->sector_size * (PedSector) disk_specific->label_block; } else { if (disk->dev->type == PED_DEVICE_FILE) arch_specific->real_sector_size = disk->dev->sector_size; /* Mark the start of the disk as metadata. */ vtoc_end = (FIRST_USABLE_TRK * (long long) disk->dev->hw_geom.sectors * (long long) arch_specific->real_sector_size / (long long) disk->dev->sector_size) - 1; } new_part = ped_partition_new (disk,PED_PARTITION_METADATA,NULL,0,vtoc_end); if (!new_part) goto error; if (!ped_disk_add_partition (disk, new_part, constraint_any)) { ped_partition_destroy (new_part); goto error; } if (disk_specific->format_type == 1 && part) { /* For LDL or CMS there may be trailing metadata as well. For example: the last block of a CMS reserved file, the "recomp" area of a CMS minidisk that has been formatted and then formatted again with the RECOMP option specifying fewer than the maximum number of cylinders, a disk that was formatted at one size, backed up, then restored to a larger size disk, etc. */ trailing_meta_start = part->geom.end + 1; trailing_meta_end = (long long) disk->dev->length - 1; if (trailing_meta_end >= trailing_meta_start) { new_part2 = ped_partition_new (disk,PED_PARTITION_METADATA, NULL, trailing_meta_start, trailing_meta_end); if (!new_part2) { ped_partition_destroy (new_part); goto error; } if (!ped_disk_add_partition (disk, new_part2, constraint_any)) { ped_partition_destroy (new_part2); ped_partition_destroy (new_part); goto error; } } } ped_constraint_destroy (constraint_any); return 1; error: ped_constraint_destroy (constraint_any); return 0; }
static int dasd_write (const PedDisk* disk) { DasdPartitionData* dasd_data; PedPartition* part; int i; partition_info_t *p; LinuxSpecific* arch_specific; DasdDiskSpecific* disk_specific; struct fdasd_anchor anchor; partition_info_t *part_info[USABLE_PARTITIONS]; PED_ASSERT(disk != NULL); PED_ASSERT(disk->dev != NULL); arch_specific = LINUX_SPECIFIC (disk->dev); disk_specific = disk->disk_specific; PDEBUG; /* If not formated in CDL, don't write anything. */ if (disk_specific->format_type == 1) { ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("The partition table of DASD-LDL device cannot be changed.\n")); return 1; } /* initialize the anchor */ fdasd_initialize_anchor(&anchor); if (fdasd_get_geometry(disk->dev, &anchor, arch_specific->fd) == 0) goto error; fdasd_check_volume(&anchor, arch_specific->fd); memcpy(anchor.vlabel, &disk_specific->vlabel, sizeof(volume_label_t)); anchor.vlabel_changed++; if ((anchor.geo.cylinders * anchor.geo.heads) > BIG_DISK_SIZE) anchor.big_disk++; fdasd_recreate_vtoc(&anchor); for (i = 1; i <= USABLE_PARTITIONS; i++) { unsigned int start, stop; PDEBUG; part = ped_disk_get_partition(disk, i); if (!part) continue; PDEBUG; start = part->geom.start * disk->dev->sector_size / arch_specific->real_sector_size / disk->dev->hw_geom.sectors; stop = (part->geom.end + 1) * disk->dev->sector_size / arch_specific->real_sector_size / disk->dev->hw_geom.sectors - 1; PDEBUG; dasd_data = part->disk_specific; p = fdasd_add_partition(&anchor, start, stop); if (!p) { PDEBUG; goto error; } part_info[i - 1] = p; p->type = dasd_data->system; } PDEBUG; if (!fdasd_prepare_labels(&anchor, arch_specific->fd)) goto error; dasd_update_type(disk, &anchor, part_info); PDEBUG; if (!fdasd_write_labels(&anchor, arch_specific->fd)) goto error; fdasd_cleanup(&anchor); return 1; error: PDEBUG; fdasd_cleanup(&anchor); return 0; }
static int dasd_update_type (const PedDisk* disk, struct fdasd_anchor *anchor, partition_info_t *part_info[USABLE_PARTITIONS]) { PedPartition* part; LinuxSpecific* arch_specific; DasdDiskSpecific* disk_specific; arch_specific = LINUX_SPECIFIC(disk->dev); disk_specific = disk->disk_specific; PDEBUG; unsigned int i; for (i = 1; i <= USABLE_PARTITIONS; i++) { partition_info_t *p; char *ch = NULL; DasdPartitionData* dasd_data; PDEBUG; part = ped_disk_get_partition(disk, i); if (!part) continue; PDEBUG; dasd_data = part->disk_specific; p = part_info[i - 1]; if (!p ) { PDEBUG; continue; } vtoc_ebcdic_dec(p->f1->DS1DSNAM, p->f1->DS1DSNAM, 44); ch = strstr(p->f1->DS1DSNAM, "PART"); PDEBUG; if (ch == NULL) { vtoc_ebcdic_enc(p->f1->DS1DSNAM, p->f1->DS1DSNAM, 44); PDEBUG; continue; } ch += 9; switch (dasd_data->system) { case PARTITION_LINUX_LVM: PDEBUG; strncpy(ch, PART_TYPE_LVM, 6); break; case PARTITION_LINUX_RAID: PDEBUG; strncpy(ch, PART_TYPE_RAID, 6); break; case PARTITION_LINUX: PDEBUG; strncpy(ch, PART_TYPE_NATIVE, 6); break; case PARTITION_LINUX_SWAP: PDEBUG; strncpy(ch, PART_TYPE_SWAP, 6); break; default: PDEBUG; strncpy(ch, PART_TYPE_NATIVE, 6); break; } anchor->vtoc_changed++; vtoc_ebcdic_enc(p->f1->DS1DSNAM, p->f1->DS1DSNAM, 44); } return 1; }
static int dvh_write (const PedDisk* disk) { DVHDiskData* dvh_disk_data = disk->disk_specific; struct volume_header vh; int i; PED_ASSERT (dvh_disk_data != NULL); _flush_stale_flags (disk); memset (&vh, 0, sizeof (struct volume_header)); vh.vh_magic = PED_CPU_TO_BE32 (VHMAGIC); vh.vh_rootpt = PED_CPU_TO_BE16 (dvh_disk_data->root - 1); vh.vh_swappt = PED_CPU_TO_BE16 (dvh_disk_data->swap - 1); if (dvh_disk_data->boot) { PedPartition* boot_part; boot_part = ped_disk_get_partition (disk, dvh_disk_data->boot); strcpy (vh.vh_bootfile, ped_partition_get_name (boot_part)); } vh.vh_dp = dvh_disk_data->dev_params; /* Set up rudimentary device geometry */ vh.vh_dp.dp_cyls = PED_CPU_TO_BE16 ((short)disk->dev->bios_geom.cylinders); vh.vh_dp.dp_trks0 = PED_CPU_TO_BE16 ((short)disk->dev->bios_geom.heads); vh.vh_dp.dp_secs = PED_CPU_TO_BE16 ((short)disk->dev->bios_geom.sectors); vh.vh_dp.dp_secbytes = PED_CPU_TO_BE16 ((short)disk->dev->sector_size); for (i = 0; i < NPARTAB; i++) { PedPartition* part = ped_disk_get_partition (disk, i + 1); if (part) _generate_partition (part, &vh.vh_pt[i]); } /* whole disk partition * This is only ever written here, and never modified * (or even shown) as it must contain the entire disk, * and parted does not like overlapping partitions */ vh.vh_pt[PNUM_VOLUME].pt_nblks = PED_CPU_TO_BE32 (disk->dev->length); vh.vh_pt[PNUM_VOLUME].pt_firstlbn = PED_CPU_TO_BE32 (0); vh.vh_pt[PNUM_VOLUME].pt_type = PED_CPU_TO_BE32 (PTYPE_VOLUME); for (i = 0; i < NVDIR; i++) { PedPartition* part = ped_disk_get_partition (disk, i + 1 + NPARTAB); if (part) _generate_boot_file (part, &vh.vh_vd[i]); } vh.vh_csum = 0; vh.vh_csum = PED_CPU_TO_BE32 (_checksum ((uint32_t*) &vh, sizeof (struct volume_header))); return (ptt_write_sector (disk, &vh, sizeof vh) && ped_device_sync (disk->dev)); }
gboolean disk_resize_grow(const gchar* disk_path, GChildWatchFunc async_func_watcher, gpointer data) { char command[LINE_MAX] = { 0 }; int last_partition_num; const gchar* partition_path; PedDevice* dev = NULL; PedDisk* disk = NULL; gboolean result = false; PedPartition* partition; PedSector start; PedSector end; PedGeometry geometry_start; PedGeometry* geometry_end; PedConstraint* constraint; resize_fs = false; /* to handle exceptions, i.e Fix PMBR */ ped_exception_set_handler(disk_exception_handler); if (!disk_path) { LOG(MOD "Disk path is empty\n"); return false; } dev = ped_device_get(disk_path); if (!dev) { LOG(MOD "Cannot get device '%s'\n", disk_path); return false; } /* * verify disk, disk_exception_handler will called * if the disk has problems and it needs to be fixed * and resized */ disk = ped_disk_new(dev); if (!disk) { LOG(MOD "Cannot create a new disk '%s'\n", disk_path); return false; } if (!resize_fs) { /* do not resize filesystem, it is ok */ LOG(MOD "Nothing to do with '%s' disk\n", disk_path); return false; } LOG(MOD "Resizing filesystem disk '%s'\n", disk_path); last_partition_num = ped_disk_get_last_partition_num(disk); partition = ped_disk_get_partition(disk, last_partition_num); if (!partition) { LOG(MOD "Cannot get partition '%d' disk '%s'\n", last_partition_num, disk_path); return false; } start = partition->geom.start; end = (-PED_MEGABYTE_SIZE) / dev->sector_size + dev->length; geometry_start.dev = dev; geometry_start.start = start; geometry_start.end = end; geometry_start.length = 1; geometry_end = ped_geometry_new(dev, end, 1); if (!geometry_end) { LOG(MOD "Cannot get partition '%d' disk '%s'\n", last_partition_num, disk_path); return false; } constraint = ped_constraint_new(ped_alignment_any, ped_alignment_any, &geometry_start, geometry_end, 1, dev->length); if (!constraint) { LOG(MOD "Cannot create a new constraint disk '%s'\n", disk_path); goto fail1; } if (!ped_disk_set_partition_geom(disk, partition, constraint, start, end)) { LOG(MOD "Cannot set partition geometry disk '%s'\n", disk_path); goto fail2; } if (!ped_disk_commit(disk)) { LOG(MOD "Cannot write the partition table to disk '%s'\n", disk_path); goto fail2; } partition_path = ped_partition_get_path(partition); if (!partition_path) { LOG(MOD "Cannot get partition path disk '%s'\n", disk_path); goto fail2; } snprintf(command, LINE_MAX, RESIZEFS_PATH " %s", partition_path); exec_task_async(command, async_func_watcher, data); result = true; LOG(MOD "Resizing filesystem done\n"); fail2: ped_constraint_destroy (constraint); fail1: ped_geometry_destroy (geometry_end); return result; }