From bc854d48563ff30ba4c55914baa8db0a271790e5 Mon Sep 17 00:00:00 2001 From: Joel Granados Moreno Date: Thu, 16 Jul 2009 20:16:43 +0200 Subject: [PATCH] Add duplicate functionality to dasd type lables. * libparted/labels/dasd.c (dasd_alloc): Add the errno to the exception message to ease debugging. (dasd_partition_duplicate): New function. (dasd_duplicate): Include all the dasd specific structures in the duplicate disk. (dasd_partition_new): Handle the case when malloc fails because of lack of memory. (dasd_disk_ops): Add the new dasd_partition_duplicate hook. --- libparted/labels/dasd.c | 234 ++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 222 insertions(+), 12 deletions(-) diff --git a/libparted/labels/dasd.c b/libparted/labels/dasd.c index ec73d09..e87daba 100644 --- a/libparted/labels/dasd.c +++ b/libparted/labels/dasd.c @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -58,6 +59,9 @@ extern void ped_disk_dasd_init (); extern void ped_disk_dasd_done (); +static PedPartition* dasd_partition_new (const PedDisk*, PedPartitionType, + const PedFileSystemType*, + PedSector, PedSector); #define DASD_NAME "dasd" @@ -104,7 +108,8 @@ dasd_alloc (const PedDevice* dev) &disk_specific->real_sector_size) == -1) { ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("Unable to determine the block " - "size of this dasd")); + "size of this dasd - %s"), + strerror(errno)); free(disk_specific); free(disk); return NULL; @@ -113,19 +118,216 @@ dasd_alloc (const PedDevice* dev) return disk; } +static PedPartition* +dasd_partition_duplicate (const PedPartition* part, PedDisk* disk) +{ + PedPartition* walk; + PedPartition* new_part; + format1_label_t* new_format1; + partition_info_t* new_part_info; + partition_info_t* old_part_info; + DasdPartitionData* old_dasd_data; + DasdPartitionData* temp_dasd_data; + DasdDiskSpecific* old_disk_specific; + partition_info_t* old_anchor_first; + partition_info_t* old_anchor_last; + char* error_message; + + /* Initialize old_* variables. */ + old_dasd_data = (DasdPartitionData*) part->disk_specific; + old_part_info = (partition_info_t*) old_dasd_data->part_info; + old_disk_specific = (DasdDiskSpecific*) part->disk->disk_specific; + old_anchor_first = (partition_info_t*) old_disk_specific->anchor->first; + old_anchor_last = (partition_info_t*) old_disk_specific->anchor->last; + /* The default error message. */ + error_message = "Could not allocate memory for dasd specific structure."; + + /* Handle the DasdPartitionData->partition_info_t->format1_label_t pointer. */ + new_format1 = (format1_label_t*) ped_malloc (sizeof (format1_label_t)); + if (!new_format1) + goto error; + memcpy (new_format1, old_part_info->f1, sizeof (format1_label_t)); + + /* Handle the DasdPartitionData->partition_info_t pointer. */ + new_part_info = (partition_info_t*) ped_malloc (sizeof (partition_info_t)); + if (!new_part_info) + goto error_free_format1; + memcpy (new_part_info, old_part_info, sizeof (partition_info_t)); + new_part_info->f1 = new_format1; + new_part_info->next = NULL; + new_part_info->prev = NULL; + + /* Try to set new_part_info->next, new_part_info->prev, + * disk->disk_specific->anchor->first & disk->disk_specific->anchor->last + * when disk is not NULL. + */ + if (disk) + { + /* Handle the next and prev pointers. */ + /* Look for the prev. */ + if (old_part_info->prev == NULL || part->prev == NULL) + new_part_info->prev = NULL; + else + { + for (walk = disk->part_list ; walk ; walk = walk->next) + { + /* Identify the partition by start and length sectors. */ + if (walk->geom.start == part->prev->geom.start + && walk->geom.length == part->prev->geom.length) + { + /* Verify the new_part_info->prev and the walk->next. */ + temp_dasd_data = (DasdPartitionData*) walk->disk_specific; + new_part_info->prev = (partition_info_t*) temp_dasd_data->part_info; + ((partition_info_t*)temp_dasd_data->part_info)->next = new_part_info; + break; + } + } + } + + /* Look for the next. */ + if (old_part_info->next == NULL || part->next == NULL) + new_part_info->next = NULL; + else + { + for (walk = disk->part_list ; walk ; walk = walk->next) + { + /* Identify the partition by start and length sectors. */ + if (walk->geom.start == part->next->geom.start + && walk->geom.length == part->next->geom.length) + { + /* Verify the new_part_info->next and the walk->prev. */ + temp_dasd_data = (DasdPartitionData*) walk->disk_specific; + new_part_info->next = (partition_info_t*) temp_dasd_data->part_info; + ((partition_info_t*)temp_dasd_data->part_info)->prev = new_part_info; + break; + } + } + } + + /* Handle the DasdDiskSpecific->fdasd_anchor->last && + * Handle the DasdDiskSpecific->fdasd_anchor->first. */ + if ( old_anchor_first->start_trk == new_part_info->start_trk + && old_anchor_first->len_trk == new_part_info->len_trk) + ((DasdDiskSpecific*) disk->disk_specific)->anchor->first = new_part_info; + else if ( old_anchor_last->start_trk == new_part_info->start_trk + && old_anchor_last->len_trk == new_part_info->len_trk) + ((DasdDiskSpecific*) disk->disk_specific)->anchor->last = new_part_info; + } + + /* Create new partition. Allocates memory for DasdPartitionData. */ + new_part = dasd_partition_new (part->disk, part->type, part->fs_type, + part->geom.start, part->geom.end); + if (!new_part) + goto error_free_part_info; + new_part->num = part->num; + + /* Handle the DasdPartitionData pointer. */ + memcpy (new_part->disk_specific, old_dasd_data, sizeof (DasdPartitionData)); + ((DasdPartitionData*)new_part->disk_specific)->part_info = new_part_info; + + return new_part; + +error_free_part_info: + free(new_part_info); +error_free_format1: + free(new_format1); +error: + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _(error_message)); + return NULL; +} + static PedDisk* dasd_duplicate (const PedDisk* disk) { - PedDisk* new_disk; - - new_disk = ped_disk_new_fresh(disk->dev, &dasd_disk_type); - - if (!new_disk) - return NULL; - - new_disk->disk_specific = NULL; - - return new_disk; + PedDisk* new_disk; + DasdDiskSpecific* old_disk_specific; + fdasd_anchor_t* new_anchor; + fdasd_anchor_t* old_anchor; + format4_label_t* new_format4; + format5_label_t* new_format5; + format7_label_t* new_format7; + volume_label_t* new_volume; + char* error_message; + + /* Initialize old_* variables. */ + old_disk_specific = disk->disk_specific; + old_anchor = old_disk_specific->anchor; + /* The default error message. */ + error_message = "Could not allocate memory for dasd specific structure."; + + /* Handle DasdDiskSpecific->fdasd_anchor->format4_label_t. */ + new_format4 = (format4_label_t*) ped_malloc (sizeof (format4_label_t)); + if (!new_format4) + goto error; + memcpy (new_format4, old_disk_specific->anchor->f4, sizeof (format4_label_t)); + + /* Handle DasdDiskSpecific->fdasd_anchor->format5_label_t. */ + new_format5 = (format5_label_t*) ped_malloc (sizeof (format5_label_t)); + if (!new_format5) + goto error_free_format4; + memcpy (new_format5, old_disk_specific->anchor->f5, sizeof (format5_label_t)); + + /* Handle DasdDiskSpecific->fdasd_anchor->format7_label_t. */ + new_format7 = (format7_label_t*) ped_malloc (sizeof (format7_label_t)); + if (!new_format7) + goto error_free_format5; + memcpy (new_format7, old_disk_specific->anchor->f7, sizeof (format7_label_t)); + + /* Handle DasdDiskSpecific->fdasd_anchor->volume_label_t. */ + new_volume = (volume_label_t*) ped_malloc (sizeof (volume_label_t)); + if (!new_volume) + goto error_free_format7; + memcpy (new_volume, old_disk_specific->anchor->vlabel, + sizeof (volume_label_t)); + + /* Handle DasdDiskSpecific->fdasd_anchor. */ + if (! (new_anchor = (fdasd_anchor_t*) ped_malloc (sizeof (fdasd_anchor_t)))) + goto error_free_volume; + memcpy (new_anchor, old_anchor, sizeof (fdasd_anchor_t)); + new_anchor->f4 = new_format4; + new_anchor->f5 = new_format5; + new_anchor->f7 = new_format7; + new_anchor->vlabel = new_volume; + /* We dont have last and first info yet. */ + new_anchor->last = NULL; + new_anchor->first = NULL; + + /* Handle new disk creation. ped_disk_new_fresh allocates memory for + * new_disk->disk_specific. */ + /* We need to make sure that the device is open for reading. */ + if (!ped_device_open(disk->dev)) + { + error_message = "Could not open device for dasd disk duplication"; + goto error_free_anchor; + } + new_disk = ped_disk_new_fresh (disk->dev, &dasd_disk_type); + if (!ped_device_close(disk->dev)) + { + error_message = "Could not close device for dasd disk duplication"; + goto error_free_anchor; + } + if (!new_disk) + goto error_free_anchor; + memcpy (new_disk->disk_specific, old_disk_specific, sizeof(DasdDiskSpecific)); + ((DasdDiskSpecific*)new_disk->disk_specific)->anchor = new_anchor; + + return new_disk; + +error_free_anchor: + free(new_anchor); +error_free_volume: + free(new_volume); +error_free_format7: + free(new_format7); +error_free_format5: + free(new_format5); +error_free_format4: + free(new_format4); +error: + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _(error_message)); + return NULL; } static void @@ -551,12 +753,20 @@ dasd_partition_new (const PedDisk* disk, PedPartitionType part_type, goto error; part->disk_specific = ped_malloc (sizeof (DasdPartitionData)); + if (!part->disk_specific) + goto error_free_part; return part; +error_free_part: + free(part); error: return 0; } +/* + * Frees the memory of an active partition. Active here is whatever + * ped_partition_is_active returns. + */ static void dasd_partition_destroy (PedPartition* part) { @@ -818,6 +1028,7 @@ static PedDiskOps dasd_disk_ops = { partition_set_system: dasd_partition_set_system, partition_new: dasd_partition_new, + partition_duplicate: dasd_partition_duplicate, partition_destroy: dasd_partition_destroy, partition_set_flag: dasd_partition_set_flag, partition_get_flag: dasd_partition_get_flag, @@ -831,7 +1042,6 @@ static PedDiskOps dasd_disk_ops = { get_max_primary_partition_count: dasd_get_max_primary_partition_count, get_max_supported_partition_count: dasd_get_max_supported_partition_count, - partition_duplicate: NULL }; static PedDiskType dasd_disk_type = { -- 1.6.0.6