示例#1
0
文件: dvh.c 项目: Distrotech/parted
static int
dvh_alloc_metadata (PedDisk* disk)
{
	PedPartition* part;
	PedPartition* extended_part;
	PedPartitionType metadata_type;
	PED_ASSERT(disk != NULL);

	/* We don't need to "protect" the start of the disk from the volume
	 * header.
	 */
	extended_part = ped_disk_extended_partition (disk);
	if (extended_part && extended_part->geom.start == 0)
		metadata_type = PED_PARTITION_METADATA | PED_PARTITION_LOGICAL;
	else
		metadata_type = PED_PARTITION_METADATA;

	part = ped_partition_new (disk, metadata_type, NULL, 0, 0);
	if (!part)
		goto error;

	PedConstraint *constraint_exact
	  = ped_constraint_exact (&part->geom);
	bool ok = ped_disk_add_partition (disk, part, constraint_exact);
	ped_constraint_destroy (constraint_exact);
	if (ok)
		return 1;

	ped_partition_destroy (part);
error:
	return 0;
}
示例#2
0
文件: pc98.c 项目: Excito/parted
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;
}
示例#3
0
文件: rdb.c 项目: inteos/WBSAirback
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;
}
示例#4
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;
}
示例#5
0
文件: dvh.c 项目: Distrotech/parted
static PedDisk*
dvh_alloc (const PedDevice* dev)
{
	PedDisk*	disk;
	DVHDiskData*	dvh_disk_data;
	PedPartition*	volume_part;
	PedConstraint*	constraint_any;

	disk = _ped_disk_alloc (dev, &dvh_disk_type);
	if (!disk)
		goto error;

	disk->disk_specific = dvh_disk_data
		= ped_malloc (sizeof (DVHDiskData));
	if (!dvh_disk_data)
		goto error_free_disk;

	memset (&dvh_disk_data->dev_params, 0,
		sizeof (struct device_parameters));
	dvh_disk_data->swap = 0;
	dvh_disk_data->root = 0;
	dvh_disk_data->boot = 0;

	volume_part = ped_partition_new (disk, PED_PARTITION_EXTENDED, NULL,
					 0, PTYPE_VOLHDR_DFLTSZ - 1);
	if (!volume_part)
		goto error_free_disk_specific;
	volume_part->num = PNUM_VOLHDR + 1;
	constraint_any = ped_constraint_any (dev);
	if (!ped_disk_add_partition (disk, volume_part, constraint_any))
		goto error_destroy_constraint_any;
	ped_constraint_destroy (constraint_any);
	return disk;

error_destroy_constraint_any:
	ped_constraint_destroy (constraint_any);
	ped_partition_destroy (volume_part);
error_free_disk_specific:
	free (disk->disk_specific);
error_free_disk:
	free (disk);
error:
	return NULL;
}
示例#6
0
文件: dvh.c 项目: Distrotech/parted
/* try to make a reasonable volume header partition... */
static PedExceptionOption
_handle_no_volume_header (PedDisk* disk)
{
	PedExceptionOption	ret;
	PedPartition*		part;
	PedConstraint*		constraint;

	switch (ped_exception_throw (
		PED_EXCEPTION_WARNING,
		PED_EXCEPTION_FIX + PED_EXCEPTION_CANCEL,
		_("%s has no extended partition (volume header partition)."),
		disk->dev->path)) {
		case PED_EXCEPTION_UNHANDLED:
		case PED_EXCEPTION_FIX:
		default:
			part = ped_partition_new (
				disk, PED_PARTITION_EXTENDED, NULL,
				0, PTYPE_VOLHDR_DFLTSZ - 1);
			if (!part)
				goto error;
			part->num = PNUM_VOLHDR + 1;
			constraint = ped_constraint_any (part->disk->dev);
			if (!constraint)
				goto error_destroy_part;
			if (!ped_disk_add_partition (disk, part, constraint))
				goto error_destroy_constraint;
			ped_constraint_destroy (constraint);
			ret = PED_EXCEPTION_FIX;
			break;

		case PED_EXCEPTION_CANCEL:
			goto error;
	}
	return ret;

error_destroy_constraint:
	ped_constraint_destroy (constraint);
error_destroy_part:
	ped_partition_destroy (part);
error:
	return PED_EXCEPTION_CANCEL;
}
示例#7
0
文件: dasd.c 项目: bcl/parted
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;
}
示例#8
0
文件: dvh.c 项目: Distrotech/parted
static int
dvh_read (PedDisk* disk)
{
	DVHDiskData*		dvh_disk_data = disk->disk_specific;
	int			i;
	struct volume_header	vh;
	char			boot_name [BFNAMESIZE + 1];
#ifndef DISCOVER_ONLY
	int			write_back = 0;
#endif

	PED_ASSERT (dvh_disk_data != NULL);

	ped_disk_delete_all (disk);

	void *s0;
	if (!ptt_read_sector (disk->dev, 0, &s0))
		return 0;
	memcpy (&vh, s0, sizeof vh);
	free (s0);

	if (_checksum ((uint32_t*) &vh, sizeof (struct volume_header))) {
		if (ped_exception_throw (
			PED_EXCEPTION_ERROR,
			PED_EXCEPTION_IGNORE_CANCEL,
			_("Checksum is wrong, indicating the partition "
			  "table is corrupt."))
				== PED_EXCEPTION_CANCEL)
			return 0;
	}

	PED_ASSERT (PED_BE32_TO_CPU (vh.vh_magic) == VHMAGIC);

	dvh_disk_data->dev_params = vh.vh_dp;
	strncpy (boot_name, vh.vh_bootfile, BFNAMESIZE);
	boot_name[BFNAMESIZE] = 0;

	/* normal partitions */
	for (i = 0; i < NPARTAB; i++) {
		PedPartition* part;

		if (!vh.vh_pt[i].pt_nblks)
			continue;
		/* Skip the whole-disk partition, parted disklikes overlap */
		if (PED_BE32_TO_CPU (vh.vh_pt[i].pt_type) == PTYPE_VOLUME)
			continue;

		part = _parse_partition (disk, &vh.vh_pt[i]);
		if (!part)
			goto error_delete_all;

		part->fs_type = ped_file_system_probe (&part->geom);
		part->num = i + 1;

		if (PED_BE16_TO_CPU (vh.vh_rootpt) == i)
			ped_partition_set_flag (part, PED_PARTITION_ROOT, 1);
		if (PED_BE16_TO_CPU (vh.vh_swappt) == i)
			ped_partition_set_flag (part, PED_PARTITION_SWAP, 1);

		PedConstraint *constraint_exact
		  = ped_constraint_exact (&part->geom);
		bool ok = ped_disk_add_partition (disk, part, constraint_exact);
		ped_constraint_destroy (constraint_exact);
		if (!ok) {
			ped_partition_destroy (part);
			goto error_delete_all;
		}
	}

	if (!ped_disk_extended_partition (disk)) {
#ifdef DISCOVER_ONLY
		return 1;
#else
		switch (_handle_no_volume_header (disk)) {
			case PED_EXCEPTION_CANCEL:
				return 0;
			case PED_EXCEPTION_IGNORE:
				return 1;
			case PED_EXCEPTION_FIX:
				write_back = 1;
				break;
			default:
				break;
		}
#endif
	}

	/* boot partitions */
	for (i = 0; i < NVDIR; i++) {
		PedPartition* part;

		if (!vh.vh_vd[i].vd_nbytes)
			continue;

		part = _parse_boot_file (disk, &vh.vh_vd[i]);
		if (!part)
			goto error_delete_all;

		part->fs_type = ped_file_system_probe (&part->geom);
		part->num = NPARTAB + i + 1;

		if (!strcmp (boot_name, ped_partition_get_name (part)))
			ped_partition_set_flag (part, PED_PARTITION_BOOT, 1);

		PedConstraint *constraint_exact
		  = ped_constraint_exact (&part->geom);
		bool ok = ped_disk_add_partition (disk, part, constraint_exact);
		ped_constraint_destroy (constraint_exact);
		if (!ok) {
			ped_partition_destroy (part);
			goto error_delete_all;
		}
	}
#ifndef DISCOVER_ONLY
	if (write_back)
		dvh_write (disk);
#endif
	return 1;

error_delete_all:
	ped_disk_delete_all (disk);
	return 0;
}
示例#9
0
文件: rdb.c 项目: inteos/WBSAirback
/* We have already allocated a rdb, we are now reading it from the disk */
static int
amiga_read (PedDisk* disk)
{
	struct RigidDiskBlock *rdb;
	struct PartitionBlock *partition;
	uint32_t partblock;
	uint32_t partlist[AMIGA_MAX_PARTITIONS];
	PedSector cylblocks;
	int i;

	PED_ASSERT(disk != NULL);
	PED_ASSERT(disk->dev != NULL);
	PED_ASSERT(disk->dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0);
	PED_ASSERT(disk->disk_specific != NULL);
	rdb = RDSK(disk->disk_specific);

	if (_amiga_find_rdb (disk->dev, rdb) == AMIGA_RDB_NOT_FOUND) {
		ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
			_("%s : Didn't find rdb block, should never happen."), __func__);
		return 0;
	}

	/* Let's copy the rdb read geometry to the dev */
	/* FIXME: should this go into disk->dev->bios_geom instead? */
	disk->dev->hw_geom.cylinders = PED_BE32_TO_CPU (rdb->rdb_Cylinders);
	disk->dev->hw_geom.heads = PED_BE32_TO_CPU (rdb->rdb_Heads);
	disk->dev->hw_geom.sectors = PED_BE32_TO_CPU (rdb->rdb_Sectors);
	cylblocks = (PedSector) PED_BE32_TO_CPU (rdb->rdb_Heads) *
		(PedSector) PED_BE32_TO_CPU (rdb->rdb_Sectors);

	/* Remove all partitions in the former in memory table */
	ped_disk_delete_all (disk);

	/* Let's allocate a partition block */
	if (!(partition = ped_malloc (disk->dev->sector_size)))
		return 0;

	/* We initialize the hardblock free list to detect loops */
	for (i = 0; i < AMIGA_MAX_PARTITIONS; i++) partlist[i] = LINK_END;

	for (i = 1, partblock = PED_BE32_TO_CPU(rdb->rdb_PartitionList);
		i < AMIGA_MAX_PARTITIONS && partblock != LINK_END;
		i++, partblock = PED_BE32_TO_CPU(partition->pb_Next))
	{
		PedPartition *part;
		PedSector start, end;

		/* Let's look for loops in the partition table */
		if (_amiga_loop_check(partblock, partlist, i)) {
			break;
		}

		/* Let's allocate and read a partition block to get its geometry*/
		if (!_amiga_read_block (disk->dev, AMIGA(partition),
		                        (PedSector)partblock, NULL)) {
			free(partition);
			return 0;
		}

		start = ((PedSector) PED_BE32_TO_CPU (partition->de_LowCyl))
			* cylblocks;
		end = (((PedSector) PED_BE32_TO_CPU (partition->de_HighCyl))
			+ 1) * cylblocks - 1;

		/* We can now construct a new partition */
		if (!(part = ped_partition_new (disk, PED_PARTITION_NORMAL,
                                                NULL, start, end))) {
			free(partition);
			return 0;
		}
		/* And copy over the partition block */
		memcpy(part->disk_specific, partition, 256);

		part->num = i;
		part->type = 0;
		/* Let's probe what file system is present on the disk */
		part->fs_type = ped_file_system_probe (&part->geom);

		PedConstraint *constraint_exact
			= ped_constraint_exact (&part->geom);
		if (constraint_exact == NULL)
			return 0;
		bool ok = ped_disk_add_partition (disk, part, constraint_exact);
		ped_constraint_destroy (constraint_exact);
		if (!ok) {
			ped_partition_destroy(part);
			free(partition);
			return 0;
		}
	}
	free(partition);
	return 1;
}
示例#10
0
static gboolean
part_add_change_partition (char *device_file, 
			   guint64 start, guint64 size, 
			   guint64 new_start, guint64 new_size, 
			   guint64 *out_start, guint64 *out_size, 
			   char *type, char *label, char **flags,
			   int geometry_hps, int geometry_spt)
{
	int n;
	gboolean is_change;
	gboolean res;
	PedDevice *device;
	PedDisk *disk;
	PedPartition *part;
	PedConstraint* constraint;
	PedPartitionType ped_type;
	guint64 start_sector;
	guint64 end_sector;
	guint64 new_start_sector;
	guint64 new_end_sector;
	PartitionTable *p;
	PartitionTable *container_p;
	int container_entry;
	PartitionScheme scheme;
	guint8 mbr_flags = 0;
	guint8 mbr_part_type = 0;
	char *endp;
	guint64 gpt_attributes = 0;
	guint32 apm_status = 0;

	res = FALSE;

	is_change = FALSE;
	if (size == 0) {
		is_change = TRUE;
	}

	if (is_change) {
		HAL_INFO (("In part_change_partition: device_file=%s, start=%lld, new_start=%lld, new_size=%lld, type=%s", device_file, start, new_start, new_size, type));
	} else {
		HAL_INFO (("In part_add_partition: device_file=%s, start=%lld, size=%lld, type=%s", device_file, start, size, type));
	}

	/* first, find the kind of (embedded) partition table the new partition is going to be part of */
	p = part_table_load_from_disk (device_file);
	if (p == NULL) {
		HAL_INFO (("Cannot load partition table from %s", device_file));
		goto out;
	}

	part_table_find (p, start + 512, &container_p, &container_entry);
	scheme = part_table_get_scheme (container_p);

	if (is_change) {
		/* if changing, make sure there is a partition to change */
		if (container_entry < 0) {
			HAL_INFO (("Couldn't find partition to change"));
			goto out;
		}
	} else {
		/* if adding, make sure there is no partition in the way... */
		if (container_entry >= 0) {
			char *part_type;
			
			/* this might be Apple_Free if we're on PART_TYPE_APPLE */
			part_type = part_table_entry_get_type (p, container_entry);
			if (! (p->scheme == PART_TYPE_APPLE && part_type != NULL && (strcmp (part_type, "Apple_Free") == 0))) {
				part_table_free (p);
				HAL_INFO (("There is a partition in the way on %s", device_file));
				goto out;
			}
		}
	}

	HAL_INFO (("containing partition table scheme = %d", scheme));

	part_table_free (p);
	p = NULL;

	if (!is_change) {
		if (type == NULL) {
			HAL_INFO (("No type specified"));
			goto out;
		}
	}

	/* now that we know the partitoning scheme, sanity check type and flags */
	switch (scheme) {
	case PART_TYPE_MSDOS:
	case PART_TYPE_MSDOS_EXTENDED:
		mbr_flags = 0;
		if (flags != NULL) {
			for (n = 0; flags[n] != NULL; n++) {
				if (strcmp (flags[n], "boot") == 0) {
					mbr_flags |= 0x80;
				} else {
					HAL_INFO (("unknown flag '%s'", flags[n]));
					goto out;
				}
			}
		}

		if (type != NULL) {
			mbr_part_type = (guint8) (strtol (type, &endp, 0));
			if (*endp != '\0') {
				HAL_INFO (("invalid type '%s' given", type));
				goto out;
			}
		}

		if (label != NULL) {
			HAL_INFO (("labeled partitions not supported on MSDOS or MSDOS_EXTENDED"));
			goto out;
		}
		
		break;

	case PART_TYPE_GPT:
		gpt_attributes = 0;
		if (flags != NULL) {
			for (n = 0; flags[n] != NULL; n++) {
				if (strcmp (flags[n], "required") == 0) {
					gpt_attributes |= 1;
				} else {
					HAL_INFO (("unknown flag '%s'", flags[n]));
					goto out;
				}
			}
		}
		break;

	case PART_TYPE_APPLE:
		apm_status = 0;
		if (flags != NULL) {
			for (n = 0; flags[n] != NULL; n++) {
				if (strcmp (flags[n], "allocated") == 0) {
					apm_status |= (1<<1);
				} else if (strcmp (flags[n], "in_use") == 0) {
					apm_status |= (1<<2);
				} else if (strcmp (flags[n], "boot") == 0) {
					apm_status |= (1<<3);
				} else if (strcmp (flags[n], "allow_read") == 0) {
					apm_status |= (1<<4);
				} else if (strcmp (flags[n], "allow_write") == 0) {
					apm_status |= (1<<5);
				} else if (strcmp (flags[n], "boot_code_is_pic") == 0) {
					apm_status |= (1<<6);
				} else {
					HAL_INFO (("unknown flag '%s'", flags[n]));
					goto out;
				}
			}
		}
		break;

	default:
		HAL_INFO (("partitioning scheme %d not supported", scheme));
		goto out;
	}

	switch (scheme) {
	case PART_TYPE_MSDOS:
		if (mbr_part_type == 0x05 || mbr_part_type == 0x85 || mbr_part_type == 0x0f) {
			ped_type = PED_PARTITION_EXTENDED;
		} else {
			ped_type = PED_PARTITION_NORMAL;
		}
		break;

	case PART_TYPE_MSDOS_EXTENDED:
		ped_type = PED_PARTITION_LOGICAL;
		if (mbr_part_type == 0x05 || mbr_part_type == 0x85 || mbr_part_type == 0x0f) {
			HAL_INFO (("Cannot create an extended partition inside an extended partition"));
			goto out;
		}
		break;

	default:
		ped_type = PED_PARTITION_NORMAL;
		break;
	}

	/* now, create the partition */

	start_sector = start / 512;
	end_sector = (start + size) / 512 - 1;
	new_start_sector = new_start / 512;
	new_end_sector = (new_start + new_size) / 512 - 1;

	device = ped_device_get (device_file);
	if (device == NULL) {
		HAL_INFO (("ped_device_get() failed"));
		goto out;
	}
	HAL_INFO (("got it"));

	/* set drive geometry on libparted object if the user requested it */
	if (geometry_hps > 0 && geometry_spt > 0 ) {
		/* not sure this is authorized use of libparted, but, eh, it seems to work */
		device->hw_geom.cylinders = device->bios_geom.cylinders = device->length / geometry_hps / geometry_spt;
		device->hw_geom.heads = device->bios_geom.heads = geometry_hps;
		device->hw_geom.sectors = device->bios_geom.sectors = geometry_spt;
	}

	disk = ped_disk_new (device);
	if (disk == NULL) {
		HAL_INFO (("ped_disk_new() failed"));
		goto out_ped_device;
	}
	HAL_INFO (("got disk"));

	if (!is_change) {
		part = ped_partition_new (disk, 
					  ped_type,
					  NULL,
					  start_sector,
					  end_sector);
		if (part == NULL) {
			HAL_INFO (("ped_partition_new() failed"));
			goto out_ped_disk;
		}
		HAL_INFO (("new partition"));
	} else {
		part = ped_disk_get_partition_by_sector (disk,
							 start_sector);
		if (part == NULL) {
			HAL_INFO (("ped_partition_get_by_sector() failed"));
			goto out_ped_disk;
		}
		HAL_INFO (("got partition"));
	}
				  

	/* TODO HACK XXX FIXME UGLY BAD: This is super ugly abuse of
	 * libparted - we poke at their internal data structures - but
	 * there ain't nothing we can do about it until libparted
	 * provides API for this...
	 */
	if (scheme == PART_TYPE_GPT) {
		struct {
			efi_guid	type;
			efi_guid	uuid;
			char		name[37];
			int		lvm;
			int		raid;
			int		boot;
			int		hp_service;
			int             hidden;
			/* more stuff */
		} *gpt_data = (void *) part->disk_specific;

		if (type != NULL) {
			if (!set_le_guid ((guint8*) &gpt_data->type, type)) {
				HAL_INFO (("type '%s' for GPT appear to be malformed", type));
				goto out_ped_partition;
			}
		}

		if (flags != NULL) {
			if (gpt_attributes & 1) {
				gpt_data->hidden = 1;
			} else {
				gpt_data->hidden = 0;
			}
		}

	} else if (scheme == PART_TYPE_MSDOS || scheme == PART_TYPE_MSDOS_EXTENDED) {
		struct {
			unsigned char	system;
			int		boot;
			/* more stuff */
		} *dos_data = (void *) part->disk_specific;

		if (type != NULL) {
			dos_data->system = mbr_part_type;
		}
		if (flags != NULL) {
			if (mbr_flags & 0x80) {
				dos_data->boot = 1;
			} else {
				dos_data->boot = 0;
			}
		}

	} else if (scheme == PART_TYPE_APPLE) {
		struct {
			char            volume_name[33];	/* eg: "Games" */
			char            system_name[33];	/* eg: "Apple_Unix_SVR2" */
			char            processor_name[17];
			int             is_boot;
			int             is_driver;
			int             has_driver;
			int             is_root;
			int             is_swap;
			int             is_lvm;
			int             is_raid;
			PedSector       data_region_length;
			PedSector       boot_region_length;
			guint32         boot_base_address;
			guint32         boot_entry_address;
			guint32         boot_checksum;
			guint32         status;
			/* more stuff */
		} *mac_data = (void *) part->disk_specific;

		if (type != NULL) {
			memset (mac_data->system_name, 0, 33);
			strncpy (mac_data->system_name, type, 32);
		}

		if (flags != NULL) {
			mac_data->status = apm_status;
		}
	}

	if (label != NULL) {
		ped_partition_set_name (part, label);
	}

	if (geometry_hps > 0 && geometry_spt > 0 ) {
		/* respect drive geometry */
		constraint = ped_constraint_any (device);
	} else if (geometry_hps == -1 && geometry_spt == -1 ) {

		/* undocumented (or is it?) libparted usage again.. it appears that
		 * the probed geometry is stored in hw_geom
		 */
		device->bios_geom.cylinders = device->hw_geom.cylinders;
		device->bios_geom.heads     = device->hw_geom.heads;
		device->bios_geom.sectors   = device->hw_geom.sectors;

		constraint = ped_constraint_any (device);
	} else {
		PedGeometry *geo_start;
		PedGeometry *geo_end;

		/* ignore drive geometry */
		if (is_change) {
			geo_start = ped_geometry_new (device, new_start_sector, 1);
			geo_end = ped_geometry_new (device, new_end_sector, 1);
		} else {
			geo_start = ped_geometry_new (device, start_sector, 1);
			geo_end = ped_geometry_new (device, end_sector, 1);
		}

		constraint = ped_constraint_new (ped_alignment_any, ped_alignment_any,
						 geo_start, geo_end, 1, device->length);
	}

try_change_again:
	if (is_change) {
		if (ped_disk_set_partition_geom (disk,
						 part,
						 constraint,
						 new_start_sector, new_end_sector) == 0) {
			HAL_INFO (("ped_disk_set_partition_geom() failed"));
			goto out_ped_constraint;
		}
	} else {
		if (ped_disk_add_partition (disk,
					    part,
					    constraint) == 0) {
			HAL_INFO (("ped_disk_add_partition() failed"));
			goto out_ped_constraint;
		}
	}

	*out_start = part->geom.start * 512;
	*out_size = part->geom.length * 512;

	if (is_change) {
		/* make sure the resulting size is never smaller than requested
		 * (this is because one will resize the FS and *then* change the partition table)
		 */
		if (*out_size < new_size) {
			HAL_INFO (("new_size=%lld but resulting size, %lld, smaller than requested", new_size, *out_size));
			new_end_sector++;
			goto try_change_again;
		} else {
			HAL_INFO (("changed partition to start=%lld size=%lld", *out_start, *out_size));
		}
	} else {
		HAL_INFO (("added partition start=%lld size=%lld", *out_start, *out_size));
	}


	/* hmm, if we don't do this libparted crashes.. I assume that
	 * ped_disk_add_partition assumes ownership of the
	 * PedPartition when adding it... sadly this is not documented
	 * anywhere.. sigh..
	 */
	part = NULL;

	/* use commit_to_dev rather than just commit to avoid
	 * libparted sending BLKRRPART to the kernel - we want to do
	 * this ourselves... 
	 */
	if (ped_disk_commit_to_dev (disk) == 0) {
		HAL_INFO (("ped_disk_commit_to_dev() failed"));
		goto out_ped_constraint;
	}
	HAL_INFO (("committed to disk"));

	res = TRUE;

	ped_constraint_destroy (constraint);
	ped_disk_destroy (disk);
	ped_device_destroy (device);
	goto out;

out_ped_constraint:
	ped_constraint_destroy (constraint);

out_ped_partition:
	if (part != NULL) {
		ped_partition_destroy (part);
	}

out_ped_disk:
	ped_disk_destroy (disk);

out_ped_device:
	ped_device_destroy (device);

out:
	return res;
}