| /* -*- Mode: c; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- |
| |
| libparted - a library for manipulating disk partitions |
| Copyright (C) 2000, 2001, 2007 Free Software Foundation, Inc. |
| |
| This program is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2 of the License, or |
| (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program; if not, write to the Free Software |
| Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| |
| Contributor: Phil Knirsch <phil@redhat.de> |
| Harald Hoyer <harald@redhat.de> |
| */ |
| |
| #include <config.h> |
| |
| #include <stdio.h> |
| #include <errno.h> |
| #include <ctype.h> |
| #include <time.h> |
| #include <fcntl.h> |
| #include <unistd.h> |
| |
| #include <sys/stat.h> |
| #include <sys/ioctl.h> |
| #include <parted/parted.h> |
| #include <parted/endian.h> |
| #include <parted/debug.h> |
| |
| #include <parted/vtoc.h> |
| #include <parted/fdasd.h> |
| #include <parted/linux.h> |
| |
| #include <libintl.h> |
| #if ENABLE_NLS |
| # define _(String) dgettext (PACKAGE, String) |
| #else |
| # define _(String) (String) |
| #endif /* ENABLE_NLS */ |
| |
| #define PARTITION_LINUX_SWAP 0x82 |
| #define PARTITION_LINUX 0x83 |
| #define PARTITION_LINUX_EXT 0x85 |
| #define PARTITION_LINUX_LVM 0x8e |
| #define PARTITION_LINUX_RAID 0xfd |
| #define PARTITION_LINUX_LVM_OLD 0xfe |
| |
| extern void ped_disk_dasd_init (); |
| extern void ped_disk_dasd_done (); |
| |
| #define DASD_NAME "dasd" |
| |
| typedef struct { |
| int type; |
| int system; |
| int raid; |
| int lvm; |
| void *part_info; |
| } DasdPartitionData; |
| |
| typedef struct { |
| unsigned int real_sector_size; |
| unsigned int format_type; |
| /* IBM internal dasd structure (i guess ;), required. */ |
| struct fdasd_anchor *anchor; |
| } DasdDiskSpecific; |
| |
| static int dasd_probe (const PedDevice *dev); |
| static int dasd_clobber (PedDevice* dev); |
| static int dasd_read (PedDisk* disk); |
| static int dasd_write (const PedDisk* disk); |
| |
| static PedPartition* dasd_partition_new (const PedDisk* disk, |
| PedPartitionType part_type, |
| const PedFileSystemType* fs_type, |
| PedSector start, |
| PedSector end); |
| static void dasd_partition_destroy (PedPartition* part); |
| static int dasd_partition_set_flag (PedPartition* part, |
| PedPartitionFlag flag, |
| int state); |
| static int dasd_partition_get_flag (const PedPartition* part, |
| PedPartitionFlag flag); |
| static int dasd_partition_is_flag_available (const PedPartition* part, |
| PedPartitionFlag flag); |
| static int dasd_partition_align (PedPartition* part, |
| const PedConstraint* constraint); |
| static int dasd_partition_enumerate (PedPartition* part); |
| static int dasd_get_max_primary_partition_count (const PedDisk* disk); |
| |
| static PedDisk* dasd_alloc (const PedDevice* dev); |
| static PedDisk* dasd_duplicate (const PedDisk* disk); |
| static void dasd_free (PedDisk* disk); |
| static int dasd_partition_set_system (PedPartition* part, |
| const PedFileSystemType* fs_type); |
| static int dasd_alloc_metadata (PedDisk* disk); |
| |
| static PedDiskOps dasd_disk_ops = { |
| probe: dasd_probe, |
| clobber: dasd_clobber, |
| read: dasd_read, |
| write: dasd_write, |
| |
| alloc: dasd_alloc, |
| duplicate: dasd_duplicate, |
| free: dasd_free, |
| partition_set_system: dasd_partition_set_system, |
| |
| partition_new: dasd_partition_new, |
| partition_destroy: dasd_partition_destroy, |
| partition_set_flag: dasd_partition_set_flag, |
| partition_get_flag: dasd_partition_get_flag, |
| partition_is_flag_available: dasd_partition_is_flag_available, |
| partition_set_name: NULL, |
| partition_get_name: NULL, |
| partition_align: dasd_partition_align, |
| partition_enumerate: dasd_partition_enumerate, |
| |
| alloc_metadata: dasd_alloc_metadata, |
| get_max_primary_partition_count: dasd_get_max_primary_partition_count, |
| |
| partition_duplicate: NULL |
| }; |
| |
| static PedDiskType dasd_disk_type = { |
| next: NULL, |
| name: "dasd", |
| ops: &dasd_disk_ops, |
| features: 0 |
| }; |
| |
| static PedDisk* |
| dasd_alloc (const PedDevice* dev) |
| { |
| PedDisk* disk; |
| LinuxSpecific* arch_specific; |
| DasdDiskSpecific *disk_specific; |
| |
| PED_ASSERT (dev != NULL, return NULL); |
| |
| arch_specific = LINUX_SPECIFIC (dev); |
| disk = _ped_disk_alloc (dev, &dasd_disk_type); |
| if (!disk) |
| return NULL; |
| |
| disk->disk_specific = disk_specific = ped_malloc(sizeof(DasdDiskSpecific)); |
| if (!disk->disk_specific) { |
| ped_free (disk); |
| return NULL; |
| } |
| |
| /* because we lie to parted we have to compensate with the |
| real sector size. Record that now. */ |
| if (ioctl(arch_specific->fd, BLKSSZGET, |
| &disk_specific->real_sector_size) == -1) { |
| ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, |
| _("Unable to determine the block " |
| "size of this dasd")); |
| ped_free(disk_specific); |
| ped_free(disk); |
| return NULL; |
| } |
| |
| return disk; |
| } |
| |
| 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; |
| } |
| |
| static void |
| dasd_free (PedDisk* disk) |
| { |
| PED_ASSERT(disk != NULL, return); |
| |
| _ped_disk_free(disk); |
| } |
| |
| |
| void |
| ped_disk_dasd_init () |
| { |
| ped_disk_type_register(&dasd_disk_type); |
| } |
| |
| void |
| ped_disk_dasd_done () |
| { |
| ped_disk_type_unregister(&dasd_disk_type); |
| } |
| |
| static int |
| dasd_probe (const PedDevice *dev) |
| { |
| char *errstr = 0; |
| LinuxSpecific* arch_specific; |
| struct fdasd_anchor anchor; |
| |
| PED_ASSERT(dev != NULL, return 0); |
| PED_ASSERT((dev->type == PED_DEVICE_DASD |
| || dev->type == PED_DEVICE_VIODASD), return 0); |
| |
| arch_specific = LINUX_SPECIFIC(dev); |
| |
| /* add partition test here */ |
| fdasd_initialize_anchor(&anchor); |
| |
| fdasd_get_geometry(&anchor, arch_specific->fd); |
| |
| fdasd_check_api_version(&anchor, arch_specific->fd); |
| |
| if (fdasd_check_volume(&anchor, arch_specific->fd)) |
| goto error_cleanup; |
| |
| fdasd_cleanup(&anchor); |
| |
| return 1; |
| |
| error_cleanup: |
| fdasd_cleanup(&anchor); |
| ped_exception_throw(PED_EXCEPTION_ERROR,PED_EXCEPTION_IGNORE_CANCEL,errstr); |
| |
| return 0; |
| } |
| |
| static int |
| dasd_clobber (PedDevice* dev) |
| { |
| LinuxSpecific* arch_specific; |
| struct fdasd_anchor anchor; |
| |
| PED_ASSERT(dev != NULL, return 0); |
| |
| arch_specific = LINUX_SPECIFIC(dev); |
| |
| fdasd_initialize_anchor(&anchor); |
| fdasd_get_geometry(&anchor, arch_specific->fd); |
| |
| fdasd_recreate_vtoc(&anchor); |
| fdasd_write_labels(&anchor, arch_specific->fd); |
| |
| return 1; |
| } |
| |
| static int |
| dasd_read (PedDisk* disk) |
| { |
| int i; |
| char str[20]; |
| PedDevice* dev; |
| PedPartition* part; |
| PedSector start, end; |
| PedConstraint* constraint_exact; |
| partition_info_t *p; |
| LinuxSpecific* arch_specific; |
| DasdDiskSpecific* disk_specific; |
| |
| PDEBUG; |
| |
| PED_ASSERT (disk != NULL, return 0); |
| PDEBUG; |
| PED_ASSERT (disk->dev != NULL, return 0); |
| PDEBUG; |
| |
| dev = disk->dev; |
| |
| arch_specific = LINUX_SPECIFIC(dev); |
| disk_specific = disk->disk_specific; |
| |
| disk_specific->anchor = ped_malloc(sizeof(fdasd_anchor_t)); |
| |
| PDEBUG; |
| |
| fdasd_initialize_anchor(disk_specific->anchor); |
| |
| fdasd_get_geometry(disk_specific->anchor, arch_specific->fd); |
| |
| /* check dasd for labels and vtoc */ |
| if (fdasd_check_volume(disk_specific->anchor, arch_specific->fd)) |
| goto error_close_dev; |
| |
| if ((disk_specific->anchor->geo.cylinders |
| * disk_specific->anchor->geo.heads) > BIG_DISK_SIZE) |
| disk_specific->anchor->big_disk++; |
| |
| ped_disk_delete_all (disk); |
| |
| if (strncmp(disk_specific->anchor->vlabel->volkey, |
| vtoc_ebcdic_enc ("LNX1", str, 4), 4) == 0) { |
| DasdPartitionData* dasd_data; |
| |
| /* LDL format, old one */ |
| disk_specific->format_type = 1; |
| start = 24; |
| end = (long long)(long long) disk_specific->anchor->geo.cylinders |
| * (long long)disk_specific->anchor->geo.heads |
| * (long long)disk->dev->hw_geom.sectors |
| * (long long)disk_specific->real_sector_size |
| / (long long)disk->dev->sector_size - 1; |
| part = ped_partition_new (disk, PED_PARTITION_PROTECTED, NULL, start, end); |
| if (!part) |
| goto error_close_dev; |
| |
| part->num = 1; |
| part->fs_type = ped_file_system_probe (&part->geom); |
| dasd_data = part->disk_specific; |
| dasd_data->raid = 0; |
| dasd_data->lvm = 0; |
| dasd_data->type = 0; |
| |
| if (!ped_disk_add_partition (disk, part, NULL)) |
| goto error_close_dev; |
| |
| return 1; |
| } |
| |
| /* CDL format, newer */ |
| disk_specific->format_type = 2; |
| |
| p = disk_specific->anchor->first; |
| PDEBUG; |
| |
| for (i = 1 ; i <= USABLE_PARTITIONS; i++) { |
| char *ch = p->f1->DS1DSNAM; |
| DasdPartitionData* dasd_data; |
| |
| |
| if (p->used != 0x01) |
| continue; |
| |
| PDEBUG; |
| |
| start = (long long)(long long) p->start_trk |
| * (long long) disk->dev->hw_geom.sectors |
| * (long long) disk_specific->real_sector_size |
| / (long long) disk->dev->sector_size; |
| end = (long long)((long long) p->end_trk + 1) |
| * (long long) disk->dev->hw_geom.sectors |
| * (long long) disk_specific->real_sector_size |
| / (long long) disk->dev->sector_size - 1; |
| part = ped_partition_new(disk, 0, NULL, start, end); |
| PDEBUG; |
| |
| if (!part) |
| goto error_close_dev; |
| |
| PDEBUG; |
| |
| part->num = i; |
| part->fs_type = ped_file_system_probe(&part->geom); |
| |
| vtoc_ebcdic_dec(p->f1->DS1DSNAM, p->f1->DS1DSNAM, 44); |
| ch = strstr(p->f1->DS1DSNAM, "PART"); |
| |
| if (ch != NULL) { |
| strncpy(str, ch+9, 6); |
| str[6] = '\0'; |
| } |
| |
| dasd_data = part->disk_specific; |
| |
| if (strncmp(PART_TYPE_RAID, str, 6) == 0) |
| ped_partition_set_flag(part, PED_PARTITION_RAID, 1); |
| else |
| ped_partition_set_flag(part, PED_PARTITION_RAID, 0); |
| |
| if (strncmp(PART_TYPE_LVM, str, 6) == 0) |
| ped_partition_set_flag(part, PED_PARTITION_LVM, 1); |
| else |
| ped_partition_set_flag(part, PED_PARTITION_LVM, 0); |
| |
| if (strncmp(PART_TYPE_SWAP, str, 6) == 0) { |
| dasd_data->system = PARTITION_LINUX_SWAP; |
| PDEBUG; |
| } |
| |
| vtoc_ebcdic_enc(p->f1->DS1DSNAM, p->f1->DS1DSNAM, 44); |
| |
| dasd_data->part_info = (void *) p; |
| dasd_data->type = 0; |
| |
| constraint_exact = ped_constraint_exact (&part->geom); |
| if (!constraint_exact) |
| goto error_close_dev; |
| if (!ped_disk_add_partition(disk, part, constraint_exact)) |
| goto error_close_dev; |
| ped_constraint_destroy(constraint_exact); |
| |
| if (p->fspace_trk > 0) { |
| start = (long long)((long long) p->end_trk + 1) |
| * (long long) disk->dev->hw_geom.sectors |
| * (long long) disk_specific->real_sector_size |
| / (long long) disk->dev->sector_size; |
| end = (long long)((long long) p->end_trk + 1 + p->fspace_trk) |
| * (long long) disk->dev->hw_geom.sectors |
| * (long long) disk_specific->real_sector_size |
| / (long long) disk->dev->sector_size - 1; |
| part = ped_partition_new (disk, 0, NULL, start, end); |
| |
| if (!part) |
| goto error_close_dev; |
| |
| part->type = PED_PARTITION_FREESPACE; |
| constraint_exact = ped_constraint_exact(&part->geom); |
| |
| if (!constraint_exact) |
| goto error_close_dev; |
| if (!ped_disk_add_partition(disk, part, constraint_exact)) |
| goto error_close_dev; |
| |
| ped_constraint_destroy (constraint_exact); |
| } |
| |
| p = p->next; |
| } |
| |
| PDEBUG; |
| return 1; |
| |
| error_close_dev: |
| PDEBUG; |
| return 0; |
| } |
| |
| static int |
| dasd_update_type (const PedDisk* disk) |
| { |
| PedPartition* part; |
| LinuxSpecific* arch_specific; |
| DasdDiskSpecific* disk_specific; |
| |
| arch_specific = LINUX_SPECIFIC(disk->dev); |
| disk_specific = disk->disk_specific; |
| |
| PDEBUG; |
| |
| for (part = ped_disk_next_partition(disk, NULL); part; |
| part = ped_disk_next_partition(disk, part)) { |
| partition_info_t *p; |
| char *ch = NULL; |
| DasdPartitionData* dasd_data; |
| |
| PDEBUG; |
| |
| if (part->type & PED_PARTITION_FREESPACE |
| || part->type & PED_PARTITION_METADATA) |
| continue; |
| |
| PDEBUG; |
| |
| dasd_data = part->disk_specific; |
| p = dasd_data->part_info; |
| |
| 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; |
| } |
| |
| disk_specific->anchor->vtoc_changed++; |
| vtoc_ebcdic_enc(p->f1->DS1DSNAM, p->f1->DS1DSNAM, 44); |
| } |
| |
| return 1; |
| } |
| |
| static int |
| dasd_write (const PedDisk* disk) |
| { |
| DasdPartitionData* dasd_data; |
| PedPartition* part; |
| int i; |
| partition_info_t *p; |
| LinuxSpecific* arch_specific; |
| DasdDiskSpecific* disk_specific; |
| PED_ASSERT(disk != NULL, return 0); |
| PED_ASSERT(disk->dev != NULL, return 0); |
| |
| arch_specific = LINUX_SPECIFIC (disk->dev); |
| disk_specific = disk->disk_specific; |
| |
| PDEBUG; |
| |
| /* If formated in LDL, don't write anything. */ |
| if (disk_specific->format_type == 1) |
| return 1; |
| |
| /* XXX re-initialize anchor? */ |
| fdasd_initialize_anchor(disk_specific->anchor); |
| fdasd_get_geometry(disk_specific->anchor, arch_specific->fd); |
| |
| /* check dasd for labels and vtoc */ |
| if (fdasd_check_volume(disk_specific->anchor, arch_specific->fd)) |
| goto error; |
| |
| if ((disk_specific->anchor->geo.cylinders |
| * disk_specific->anchor->geo.heads) > BIG_DISK_SIZE) |
| disk_specific->anchor->big_disk++; |
| |
| fdasd_recreate_vtoc(disk_specific->anchor); |
| |
| for (i = 1; i <= USABLE_PARTITIONS; i++) { |
| unsigned int start, stop; |
| int type; |
| |
| PDEBUG; |
| part = ped_disk_get_partition(disk, i); |
| if (!part) |
| continue; |
| |
| PDEBUG; |
| |
| start = part->geom.start * disk->dev->sector_size |
| / disk_specific->real_sector_size / disk->dev->hw_geom.sectors; |
| stop = (part->geom.end + 1) |
| * disk->dev->sector_size / disk_specific->real_sector_size |
| / disk->dev->hw_geom.sectors - 1; |
| |
| PDEBUG; |
| dasd_data = part->disk_specific; |
| |
| type = dasd_data->type; |
| PDEBUG; |
| |
| p = fdasd_add_partition(disk_specific->anchor, start, stop); |
| if (!p) { |
| PDEBUG; |
| return 0; |
| } |
| dasd_data->part_info = (void *) p; |
| p->type = dasd_data->system; |
| } |
| |
| PDEBUG; |
| |
| if (!fdasd_prepare_labels(disk_specific->anchor, arch_specific->fd)) |
| return 0; |
| |
| dasd_update_type(disk); |
| PDEBUG; |
| |
| if (!fdasd_write_labels(disk_specific->anchor, arch_specific->fd)) |
| return 0; |
| |
| return 1; |
| |
| error: |
| PDEBUG; |
| return 0; |
| } |
| |
| static PedPartition* |
| dasd_partition_new (const PedDisk* disk, PedPartitionType part_type, |
| const PedFileSystemType* fs_type, |
| PedSector start, PedSector end) |
| { |
| PedPartition* part; |
| |
| part = _ped_partition_alloc(disk, part_type, fs_type, start, end); |
| if (!part) |
| goto error; |
| |
| part->disk_specific = ped_malloc (sizeof (DasdPartitionData)); |
| return part; |
| |
| error: |
| return 0; |
| } |
| |
| static void |
| dasd_partition_destroy (PedPartition* part) |
| { |
| PED_ASSERT(part != NULL, return); |
| |
| if (ped_partition_is_active(part)) |
| ped_free(part->disk_specific); |
| ped_free(part); |
| } |
| |
| static int |
| dasd_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state) |
| { |
| DasdPartitionData* dasd_data; |
| |
| PED_ASSERT(part != NULL, return 0); |
| PED_ASSERT(part->disk_specific != NULL, return 0); |
| dasd_data = part->disk_specific; |
| |
| switch (flag) { |
| case PED_PARTITION_RAID: |
| if (state) |
| dasd_data->lvm = 0; |
| dasd_data->raid = state; |
| return ped_partition_set_system(part, part->fs_type); |
| case PED_PARTITION_LVM: |
| if (state) |
| dasd_data->raid = 0; |
| dasd_data->lvm = state; |
| return ped_partition_set_system(part, part->fs_type); |
| default: |
| return 0; |
| } |
| } |
| |
| static int |
| dasd_partition_get_flag (const PedPartition* part, PedPartitionFlag flag) |
| { |
| DasdPartitionData* dasd_data; |
| |
| PED_ASSERT (part != NULL, return 0); |
| PED_ASSERT (part->disk_specific != NULL, return 0); |
| dasd_data = part->disk_specific; |
| |
| switch (flag) { |
| case PED_PARTITION_RAID: |
| return dasd_data->raid; |
| case PED_PARTITION_LVM: |
| return dasd_data->lvm; |
| default: |
| return 0; |
| } |
| } |
| |
| static int |
| dasd_partition_is_flag_available (const PedPartition* part, |
| PedPartitionFlag flag) |
| { |
| switch (flag) { |
| case PED_PARTITION_RAID: |
| return 1; |
| case PED_PARTITION_LVM: |
| return 1; |
| default: |
| return 0; |
| } |
| } |
| |
| |
| static int |
| dasd_get_max_primary_partition_count (const PedDisk* disk) |
| { |
| DasdDiskSpecific* disk_specific; |
| |
| disk_specific = disk->disk_specific; |
| /* If formated in LDL, maximum partition number is 1 */ |
| if (disk_specific->format_type == 1) |
| return 1; |
| |
| return USABLE_PARTITIONS; |
| } |
| |
| static PedConstraint* |
| _primary_constraint (PedDisk* disk) |
| { |
| PedAlignment start_align; |
| PedAlignment end_align; |
| PedGeometry max_geom; |
| PedSector sector_size; |
| LinuxSpecific* arch_specific; |
| DasdDiskSpecific* disk_specific; |
| |
| PDEBUG; |
| |
| arch_specific = LINUX_SPECIFIC (disk->dev); |
| disk_specific = disk->disk_specific; |
| sector_size = disk_specific->real_sector_size / disk->dev->sector_size; |
| |
| if (!ped_alignment_init (&start_align, 0, |
| disk->dev->hw_geom.sectors * sector_size)) |
| return NULL; |
| if (!ped_alignment_init (&end_align, -1, |
| disk->dev->hw_geom.sectors * sector_size)) |
| return NULL; |
| if (!ped_geometry_init (&max_geom, disk->dev, 0, disk->dev->length)) |
| return NULL; |
| |
| return ped_constraint_new(&start_align, &end_align, &max_geom, |
| &max_geom, 1, disk->dev->length); |
| } |
| |
| static int |
| dasd_partition_align (PedPartition* part, const PedConstraint* constraint) |
| { |
| DasdDiskSpecific* disk_specific; |
| |
| PED_ASSERT (part != NULL, return 0); |
| |
| 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; |
| } |
| |
| 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 |
| dasd_partition_set_system (PedPartition* part, |
| const PedFileSystemType* fs_type) |
| { |
| DasdPartitionData* dasd_data = part->disk_specific; |
| PedSector cyl_size; |
| |
| cyl_size=part->disk->dev->hw_geom.sectors * part->disk->dev->hw_geom.heads; |
| PDEBUG; |
| |
| part->fs_type = fs_type; |
| |
| if (dasd_data->lvm) { |
| dasd_data->system = PARTITION_LINUX_LVM; |
| PDEBUG; |
| return 1; |
| } |
| |
| if (dasd_data->raid) { |
| dasd_data->system = PARTITION_LINUX_RAID; |
| PDEBUG; |
| return 1; |
| } |
| |
| if (!fs_type) { |
| dasd_data->system = PARTITION_LINUX; |
| PDEBUG; |
| } else if (!strcmp (fs_type->name, "linux-swap")) { |
| dasd_data->system = PARTITION_LINUX_SWAP; |
| PDEBUG; |
| } else { |
| dasd_data->system = PARTITION_LINUX; |
| PDEBUG; |
| } |
| |
| return 1; |
| } |
| |
| static int |
| dasd_alloc_metadata (PedDisk* disk) |
| { |
| PedPartition* new_part; |
| PedConstraint* constraint_any = NULL; |
| PedSector vtoc_end; |
| LinuxSpecific* arch_specific; |
| DasdDiskSpecific* disk_specific; |
| |
| PED_ASSERT (disk != NULL, goto error); |
| PED_ASSERT (disk->dev != NULL, goto error); |
| |
| arch_specific = LINUX_SPECIFIC (disk->dev); |
| disk_specific = disk->disk_specific; |
| |
| constraint_any = ped_constraint_any (disk->dev); |
| |
| /* If formated in LDL, the real partition starts at sector 24. */ |
| if (disk_specific->format_type == 1) |
| vtoc_end = 23; |
| else |
| /* Mark the start of the disk as metadata. */ |
| vtoc_end = (FIRST_USABLE_TRK * (long long) disk->dev->hw_geom.sectors |
| * (long long) disk_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; |
| } |
| |
| ped_constraint_destroy (constraint_any); |
| return 1; |
| |
| error: |
| ped_constraint_destroy (constraint_any); |
| return 0; |
| } |