bool LibPartedPartitionTable::commit(PedDisk* pd, quint32 timeout)
{
    if (pd == nullptr)
        return false;

    bool rval = ped_disk_commit_to_dev(pd);

    if (rval)
        rval = ped_disk_commit_to_os(pd);

    if (!ExternalCommand(QStringLiteral("udevadm"), QStringList() << QStringLiteral("settle") << QStringLiteral("--timeout=") + QString::number(timeout)).run() &&
            !ExternalCommand(QStringLiteral("udevsettle"), QStringList() << QStringLiteral("--timeout=") + QString::number(timeout)).run())
        sleep(timeout);

    return rval;
}
Beispiel #2
0
/**
 * Creates the boot- and the linux partition and formats the linux
 * partition with an ext2 filesystem
 *
 */
int create_partitions(const char* dev, unsigned long bootsector_size) {
  PedDisk* disk;
  PedDevice* device;
  PedPartition* boot_part;
  PedPartition* linux_part;
  PedFileSystemType* fs_type;
  PedTimer* timer;

  // get device from string e.g. "/dev/sdd"
  device = ped_device_get(dev);
  if(device == NULL) {
    return 0;
  }

  // create new partition table
  disk = ped_disk_new_fresh(device, ped_disk_type_get("msdos"));
  if(disk == NULL) {
    ped_device_destroy(device);
    return 0;
  }

  // get file system type (ext2)
  fs_type = ped_file_system_type_get(FILE_SYSTEM);

  // create partitions
  boot_part = ped_partition_new(disk, PED_PARTITION_NORMAL, fs_type, 0, bootsector_size / device->sector_size);
  linux_part = ped_partition_new(disk, PED_PARTITION_NORMAL, fs_type, bootsector_size / device->sector_size, device->length - 1);

  // add partitions to partition table
  PedConstraint* constraint = ped_constraint_any(device);
  ped_disk_add_partition(disk, linux_part, constraint);
  ped_disk_add_partition(disk, boot_part, constraint);
  ped_constraint_destroy(constraint);

  // create timer
  timer = ped_timer_new(create_ext2_timer, NULL);

  // create filesystem
  ped_file_system_create(&linux_part->geom, fs_type, timer);

  // commit to hardware
  ped_disk_commit_to_dev(disk);
  ped_disk_commit_to_os(disk);

  return 1;
}
void
gnome_format_create_partition(gchar *block_dev, gchar *fs, GError **error) {

        PedDevice *device;
        PedDisk *disk;
        PedFileSystemType *fs_type;
        PedPartition *part;
        
        ped_exception_set_handler(parted_exception_handler);
        
        try(device = ped_device_get(block_dev));
        try(disk = ped_disk_new(device));
        
        int last_part_num = ped_disk_get_last_partition_num(disk);
        if (last_part_num != -1) {
                // if partitions exist, delete them
                try(ped_disk_delete_all(disk));
        }

        long long end = device->length - 1;

        try(fs_type = ped_file_system_type_get(fs));
        
        // create new partition
        try(part = ped_partition_new(disk, PED_PARTITION_NORMAL, fs_type, 1, end));
        try(ped_disk_add_partition(disk, part, ped_constraint_any(device)));

        try(ped_file_system_create(&part->geom, fs_type, NULL));
                
        // commit changes
        try(ped_disk_commit_to_dev(disk));
        
        // this needs root priviliges
//        try(ped_disk_commit_to_os(disk));

#ifdef DEBUG
        printf("device.sector_size: %lld\n", device->sector_size);
        printf("device.length: %lld\n", device->length);
        printf("end: %lld\n", end);
#endif
        
        // free stuff
        ped_disk_destroy(disk);
        ped_device_destroy(device);
}
bool MParted::MParted_Core::commit() {
    if (!ped_disk_commit_to_dev(pedDisk))
        return false;

    bool success = ped_disk_commit_to_os(pedDisk);

    //Work around to try to alleviate problems caused by
    //  bug #604298 - Failure to inform kernel of partition changes
    //  If not successful the first time, try one more time.
    if (!success) {
        sleep(1);
        success = ped_disk_commit_to_os(pedDisk);
    }

    settleDevice(10);

    return success;
}
bool PartitionTable::commit_to_dev()
{
    return ped_disk_commit_to_dev( disk_ ) ? true : false ;
}
Beispiel #6
0
gboolean
part_create_partition_table (char *device_file, PartitionScheme scheme)
{
	PedDevice *device;
	PedDisk *disk;
	PedDiskType *disk_type;
	gboolean ret;

	ret = FALSE;

	HAL_INFO (("In part_create_partition_table: device_file=%s, scheme=%d", device_file, scheme));

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

	switch (scheme) {
	case PART_TYPE_MSDOS:
		disk_type = ped_disk_type_get ("msdos");
		break;
	case PART_TYPE_APPLE:
		disk_type = ped_disk_type_get ("mac");
		break;
	case PART_TYPE_GPT:
		disk_type = ped_disk_type_get ("gpt");
		break;
	default:
		disk_type = NULL;
		break;
	}

	if (disk_type == NULL) {
		HAL_INFO (("Unknown or unsupported partitioning scheme %d", scheme));
		goto out;
	}

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

	if (ped_disk_commit_to_dev (disk) == 0) {
		HAL_INFO (("ped_disk_commit_to_dev() failed"));
		goto out_ped_disk;
	}
	HAL_INFO (("committed to disk"));

	ret = TRUE;

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

out_ped_disk:
	ped_disk_destroy (disk);

out_ped_device:
	ped_device_destroy (device);

out:
	return ret;
}
Beispiel #7
0
gboolean
part_del_partition (char *device_file, guint64 offset)
{
	gboolean ret;
	PedDevice *device;
	PedDisk *disk;
	PedPartition *part;
	PartitionTable *p;
	gboolean is_extended;
	int n;

	HAL_INFO (("In part_del_partition: device_file=%s, offset=%lld", device_file, offset));
	
	ret = FALSE;


	/* sigh.. one would think that if you passed the sector of where the
	 * the beginning of the extended partition starts, then _by_sector
	 * would return the same as _extended_partition. 
	 *
	 * Sadly it's not so..
	 *
	 * So, check if the passed offset actually corresponds to a nested
	 * partition table...
	 */
	is_extended = FALSE;
	p = part_table_load_from_disk (device_file);
	if (p == NULL) {
		HAL_INFO (("Cannot load partition table from %s", device_file));
		goto out;
	}
	for (n = 0; n < part_table_get_num_entries (p); n++) {
		PartitionTable *nested;
		nested = part_table_entry_get_nested (p, n);
		if (nested != NULL) {
			if (part_table_get_offset (nested) == offset) {
				HAL_INFO (("partition to delete is an extended partition"));
				is_extended = TRUE;
			}
		}
	}
	part_table_free (p);

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

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

	if (is_extended) {
		part = ped_disk_extended_partition (disk);
	} else {
		part = ped_disk_get_partition_by_sector (disk, offset / 512);
	}

	if (part == NULL) {
		HAL_INFO (("ped_disk_get_partition_by_sector() failed"));
		goto out_ped_disk;
	}
				  
	HAL_INFO (("got partition - part->type=%d", part->type));
	/* allow only to delete primary, logical and extended partitions */
	if (! ((part->type == PED_PARTITION_NORMAL) ||
	       (part->type == PED_PARTITION_LOGICAL) ||
	       (part->type == PED_PARTITION_EXTENDED))) {
		HAL_INFO (("no data partition at given offset %lld for device %s", offset, device_file));
		goto out_ped_disk;
	}

	if (ped_disk_delete_partition (disk, part) == 0) {
		HAL_INFO (("ped_disk_delete_partition() failed"));
		goto out_ped_disk;
	}

	/* 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_disk;
	}
	HAL_INFO (("committed to disk"));

	ret = TRUE;

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

out_ped_disk:
	ped_disk_destroy (disk);

out_ped_device:
	ped_device_destroy (device);

out:
	return ret;
}
Beispiel #8
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;
}