static PedGeometry* xfs_probe (PedGeometry* geom) { PedSector block_size; PedSector block_count; union { struct xfs_sb sb; char bytes [512]; } buf; if (geom->length < XFS_SB_DADDR + 1) return NULL; if (!ped_geometry_read (geom, &buf, XFS_SB_DADDR, 1)) return NULL; if (PED_LE32_TO_CPU (buf.sb.sb_magicnum) == XFS_SB_MAGIC) { block_size = PED_LE32_TO_CPU (buf.sb.sb_blocksize) / 512; block_count = PED_LE64_TO_CPU (buf.sb.sb_dblocks); return ped_geometry_new (geom->dev, geom->start, block_size * block_count); } if (PED_BE32_TO_CPU (buf.sb.sb_magicnum) == XFS_SB_MAGIC) { block_size = PED_BE32_TO_CPU (buf.sb.sb_blocksize) / 512; block_count = PED_BE64_TO_CPU (buf.sb.sb_dblocks); return ped_geometry_new (geom->dev, geom->start, block_size * block_count); } return NULL; }
static PedGeometry* ufs_probe_sun (PedGeometry* geom) { int8_t buf[512 * 3]; struct ufs_super_block *sb; if (geom->length < 5) return 0; if (!ped_geometry_read (geom, buf, 16, 3)) return 0; sb = (struct ufs_super_block *)buf; if (PED_BE32_TO_CPU(sb->fs_magic) == UFS_MAGIC) { PedSector block_size = PED_BE32_TO_CPU(sb->fs_bsize) / 512; PedSector block_count = PED_BE32_TO_CPU(sb->fs_size); return ped_geometry_new (geom->dev, geom->start, block_size * block_count); } if (PED_LE32_TO_CPU(sb->fs_magic) == UFS_MAGIC) { PedSector block_size = PED_LE32_TO_CPU(sb->fs_bsize) / 512; PedSector block_count = PED_LE32_TO_CPU(sb->fs_size); return ped_geometry_new (geom->dev, geom->start, block_size * block_count); } return NULL; }
bool LibPartedPartitionTable::resizeFileSystem(Report& report, const Partition& partition, qint64 newLength) { bool rval = false; #if defined LIBPARTED_FS_RESIZE_LIBRARY_SUPPORT if (PedGeometry* originalGeometry = ped_geometry_new(pedDevice(), partition.fileSystem().firstSector(), partition.fileSystem().length())) { if (PedFileSystem* pedFileSystem = ped_file_system_open(originalGeometry)) { if (PedGeometry* resizedGeometry = ped_geometry_new(pedDevice(), partition.fileSystem().firstSector(), newLength)) { PedTimer* pedTimer = ped_timer_new(pedTimerHandler, nullptr); rval = ped_file_system_resize(pedFileSystem, resizedGeometry, pedTimer); ped_timer_destroy(pedTimer); if (!rval) report.line() << xi18nc("@info:progress", "Could not resize file system on partition <filename>%1</filename>.", partition.deviceNode()); ped_geometry_destroy(resizedGeometry); } else report.line() << xi18nc("@info:progress", "Could not get geometry for resized partition <filename>%1</filename> while trying to resize the file system.", partition.deviceNode()); ped_file_system_close(pedFileSystem); } else report.line() << xi18nc("@info:progress", "Could not open partition <filename>%1</filename> while trying to resize the file system.", partition.deviceNode()); ped_geometry_destroy(originalGeometry); } else report.line() << xi18nc("@info:progress", "Could not read geometry for partition <filename>%1</filename> while trying to resize the file system.", partition.deviceNode()); #else Q_UNUSED(report); Q_UNUSED(partition); Q_UNUSED(newLength); #endif return rval; }
static int hfsplus_clobber (PedGeometry* geom) { unsigned int i = 1; uint8_t buf[PED_SECTOR_SIZE_DEFAULT]; HfsMasterDirectoryBlock *mdb; mdb = (HfsMasterDirectoryBlock *) buf; if (!ped_geometry_read (geom, buf, 2, 1)) return 0; if (PED_BE16_TO_CPU (mdb->signature) == HFS_SIGNATURE) { /* embedded hfs+ */ PedGeometry *embedded; i = PED_BE32_TO_CPU(mdb->block_size) / PED_SECTOR_SIZE_DEFAULT; embedded = ped_geometry_new ( geom->dev, (PedSector) geom->start + PED_BE16_TO_CPU (mdb->start_block) + (PedSector) PED_BE16_TO_CPU ( mdb->old_new.embedded.location.start_block ) * i, (PedSector) PED_BE16_TO_CPU ( mdb->old_new.embedded.location.block_count ) * i ); if (!embedded) i = 0; else { i = hfs_clobber (embedded); ped_geometry_destroy (embedded); } } /* non-embedded or envelop destroy as hfs */ return ( hfs_clobber (geom) && i ); }
static int loop_probe (const PedDevice* dev) { PedDisk *disk = loop_alloc (dev); if (!disk) goto error; void *buf; if (!ptt_read_sector (dev, 0, &buf)) goto error_destroy_disk; int found_sig = !strncmp (buf, LOOP_SIGNATURE, strlen (LOOP_SIGNATURE)); free (buf); int result; if (found_sig) { result = 1; } else { PedGeometry* geom; geom = ped_geometry_new (dev, 0, disk->dev->length); if (!geom) goto error_destroy_disk; result = ped_file_system_probe (geom) != NULL; ped_geometry_destroy (geom); } loop_free (disk); return result; error_destroy_disk: loop_free (disk); error: return 0; }
bool LibPartedPartitionTable::updateGeometry(Report& report, const Partition& partition, qint64 sector_start, qint64 sector_end) { Q_ASSERT(partition.devicePath() == QString::fromUtf8(pedDevice()->path)); bool rval = false; PedPartition* pedPartition = (partition.roles().has(PartitionRole::Extended)) ? ped_disk_extended_partition(pedDisk()) : ped_disk_get_partition_by_sector(pedDisk(), partition.firstSector()); if (pedPartition) { if (PedGeometry* pedGeometry = ped_geometry_new(pedDevice(), sector_start, sector_end - sector_start + 1)) { if (PedConstraint* pedConstraint = ped_constraint_exact(pedGeometry)) { if (ped_disk_set_partition_geom(pedDisk(), pedPartition, pedConstraint, sector_start, sector_end)) rval = true; else report.line() << xi18nc("@info:progress", "Could not set geometry for partition <filename>%1</filename> while trying to resize/move it.", partition.deviceNode()); ped_constraint_destroy(pedConstraint); } else report.line() << xi18nc("@info:progress", "Could not get constraint for partition <filename>%1</filename> while trying to resize/move it.", partition.deviceNode()); ped_geometry_destroy(pedGeometry); } else report.line() << xi18nc("@info:progress", "Could not get geometry for partition <filename>%1</filename> while trying to resize/move it.", partition.deviceNode()); } else report.line() << xi18nc("@info:progress", "Could not open partition <filename>%1</filename> while trying to resize/move it.", partition.deviceNode()); return rval; }
/** * Return the nearest region to \p geom that satisfy a \p constraint. * * Note that "nearest" is somewhat ambiguous. This function makes * no guarantees about how this ambiguity is resovled. * * \return PedGeometry, or NULL when a \p constrain cannot be satisfied */ PedGeometry* ped_constraint_solve_nearest ( const PedConstraint* constraint, const PedGeometry* geom) { PedSector start; PedSector end; PedGeometry* result; if (constraint == NULL) return NULL; PED_ASSERT (geom != NULL); PED_ASSERT (constraint->start_range->dev == geom->dev); start = _constraint_get_nearest_start_soln (constraint, geom->start); if (start == -1) return NULL; end = _constraint_get_nearest_end_soln (constraint, start, geom->end); if (end == -1) return NULL; result = ped_geometry_new (geom->dev, start, end - start + 1); if (!result) return NULL; PED_ASSERT (ped_constraint_is_solution (constraint, result)); return result; }
static PedGeometry *reiserfs_probe(PedGeometry *geom) { int i; reiserfs_super_block_t sb; PED_ASSERT(geom != NULL); for (i = 0; reiserfs_super_offset[i] != -1; i++) { if (reiserfs_super_offset[i] >= geom->length) continue; if (!ped_geometry_read (geom, &sb, reiserfs_super_offset[i], 1)) continue; if (strncmp(REISERFS_SIGNATURE, sb.s_magic, strlen(REISERFS_SIGNATURE)) == 0 || strncmp(REISER2FS_SIGNATURE, sb.s_magic, strlen(REISER2FS_SIGNATURE)) == 0 || strncmp(REISER3FS_SIGNATURE, sb.s_magic, strlen(REISER3FS_SIGNATURE)) == 0) { PedSector block_size; PedSector block_count; block_size = PED_LE16_TO_CPU(sb.s_blocksize) / PED_SECTOR_SIZE_DEFAULT; block_count = PED_LE32_TO_CPU(sb.s_block_count); return ped_geometry_new(geom->dev, geom->start, block_size * block_count); } } return NULL; }
static PedGeometry* jfs_probe (PedGeometry* geom) { union { struct superblock sb; char bytes[512]; } buf; /* FIXME: for now, don't even try to deal with larger sector size. */ if (geom->dev->sector_size != PED_SECTOR_SIZE_DEFAULT) return NULL; if (geom->length < JFS_SUPER_SECTOR + 1) return NULL; if (!ped_geometry_read (geom, &buf, JFS_SUPER_SECTOR, 1)) return NULL; if (strncmp (buf.sb.s_magic, JFS_MAGIC, 4) == 0) { PedSector block_size = PED_LE32_TO_CPU (buf.sb.s_pbsize) / 512; PedSector block_count = PED_LE64_TO_CPU (buf.sb.s_size); return ped_geometry_new (geom->dev, geom->start, block_size * block_count); } else { return NULL; } }
QString LibPartedPartitionTable::createPartition(Report& report, const Partition& partition) { Q_ASSERT(partition.devicePath() == QString::fromUtf8(pedDevice()->path)); QString rval = QString(); // According to libParted docs, PedPartitionType can be "nullptr if unknown". That's obviously wrong, // it's a typedef for an enum. So let's use something the libparted devs will hopefully never // use... PedPartitionType pedType = static_cast<PedPartitionType>(0xffffffff); if (partition.roles().has(PartitionRole::Extended)) pedType = PED_PARTITION_EXTENDED; else if (partition.roles().has(PartitionRole::Logical)) pedType = PED_PARTITION_LOGICAL; else if (partition.roles().has(PartitionRole::Primary)) pedType = PED_PARTITION_NORMAL; if (pedType == static_cast<int>(0xffffffff)) { report.line() << xi18nc("@info:progress", "Unknown partition role for new partition <filename>%1</filename> (roles: %2)", partition.deviceNode(), partition.roles().toString()); return QString(); } PedFileSystemType* pedFsType = (partition.roles().has(PartitionRole::Extended) || partition.fileSystem().type() == FileSystem::Unformatted) ? nullptr : getPedFileSystemType(partition.fileSystem().type()); PedPartition* pedPartition = ped_partition_new(pedDisk(), pedType, pedFsType, partition.firstSector(), partition.lastSector()); if (pedPartition == nullptr) { report.line() << xi18nc("@info:progress", "Failed to create new partition <filename>%1</filename>.", partition.deviceNode()); return QString(); } PedConstraint* pedConstraint = nullptr; PedGeometry* pedGeometry = ped_geometry_new(pedDevice(), partition.firstSector(), partition.length()); if (pedGeometry) pedConstraint = ped_constraint_exact(pedGeometry); ped_geometry_destroy(pedGeometry); if (pedConstraint == nullptr) { report.line() << i18nc("@info:progress", "Failed to create a new partition: could not get geometry for constraint."); return QString(); } if (ped_disk_add_partition(pedDisk(), pedPartition, pedConstraint)) { char *pedPath = ped_partition_get_path(pedPartition); rval = QString::fromUtf8(pedPath); free(pedPath); } else { report.line() << xi18nc("@info:progress", "Failed to add partition <filename>%1</filename> to device <filename>%2</filename>.", partition.deviceNode(), QString::fromUtf8(pedDisk()->dev->path)); report.line() << LibPartedBackend::lastPartedExceptionMessage(); } ped_constraint_destroy(pedConstraint); return rval; }
static PedGeometry* geometry_from_centre_radius (const PedDevice* dev, PedSector sector, PedSector radius) { PedSector start = clip (dev, sector - radius); PedSector end = clip (dev, sector + radius); if (sector - end > radius || start - sector > radius) return NULL; return ped_geometry_new (dev, start, end - start + 1); }
static int loop_read (PedDisk* disk) { PedDevice* dev = NULL; PedGeometry* geom; PedFileSystemType* fs_type; PedPartition* part; PedConstraint* constraint_any; PED_ASSERT (disk != NULL); dev = disk->dev; constraint_any = ped_constraint_any (dev); ped_disk_delete_all (disk); void *buf; if (!ptt_read_sector (dev, 0, &buf)) goto error; int found_sig = !strncmp (buf, LOOP_SIGNATURE, strlen (LOOP_SIGNATURE)); free (buf); if (found_sig) { ped_constraint_destroy (constraint_any); return 1; } geom = ped_geometry_new (dev, 0, dev->length); if (!geom) goto error; fs_type = ped_file_system_probe (geom); if (!fs_type) goto error_free_geom; part = ped_partition_new (disk, PED_PARTITION_NORMAL, fs_type, geom->start, geom->end); ped_geometry_destroy (geom); if (!part) goto error; part->fs_type = fs_type; if (!ped_disk_add_partition (disk, part, constraint_any)) goto error; ped_constraint_destroy (constraint_any); return 1; error_free_geom: ped_geometry_destroy (geom); error: ped_constraint_destroy (constraint_any); return 0; }
bool MParted::MParted_Core::resizePartition(MParted::Partition & partition_old, MParted::Partition & partition_new) { if (partition_new.getSectorLength() == partition_old.getSectorLength() && partition_new.sector_start == partition_old.sector_start) return true; // New and old partition have the same size and position. Hence skipping this operation bool return_value = false; PedConstraint *constraint = NULL; PedPartition *pedPartition = NULL; if (!openDeviceAndDisk(partition_old.devicePath)) return false; if (partition_old.type == MParted::TYPE_EXTENDED) pedPartition = ped_disk_extended_partition(pedDisk); else pedPartition = ped_disk_get_partition_by_sector(pedDisk, partition_old.getSector()); if (pedPartition) { if (partition_new.alignment == MParted::ALIGN_MEBIBYTE) { PedGeometry *geom = ped_geometry_new(pedDevice, partition_new.sector_start, partition_new.getSectorLength()); constraint = ped_constraint_exact(geom); } else { constraint = ped_constraint_any(pedDevice); } if (constraint) { if (ped_disk_set_partition_geom(pedDisk, pedPartition, constraint, partition_new.sector_start, partition_new.sector_end) && commit()) { partition_new.sector_start = pedPartition->geom.start; partition_new.sector_end = pedPartition->geom.end; return_value = true; } ped_constraint_destroy(constraint); } } closeDeviceAndDisk(); return return_value; }
static PedGeometry* ufs_probe_hp (PedGeometry* geom) { int8_t buf[1536]; struct ufs_super_block *sb; PedSector block_size; PedSector block_count; if (geom->length < 5) return 0; if (!ped_geometry_read (geom, buf, 16, 3)) return 0; sb = (struct ufs_super_block *)buf; /* Try sane bytesex */ switch (PED_BE32_TO_CPU(sb->fs_magic)) { case UFS_MAGIC_LFN: case UFS_MAGIC_FEA: case UFS_MAGIC_4GB: block_size = PED_BE32_TO_CPU(sb->fs_bsize) / 512; block_count = PED_BE32_TO_CPU(sb->fs_size); return ped_geometry_new (geom->dev, geom->start, block_size * block_count); } /* Try perverted bytesex */ switch (PED_LE32_TO_CPU(sb->fs_magic)) { case UFS_MAGIC_LFN: case UFS_MAGIC_FEA: case UFS_MAGIC_4GB: block_size = PED_LE32_TO_CPU(sb->fs_bsize) / 512; block_count = PED_LE32_TO_CPU(sb->fs_size); return ped_geometry_new (geom->dev, geom->start, block_size * block_count); } return NULL; }
int _ped_Geometry_init(_ped_Geometry *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"dev", "start", "length", "end", NULL}; PedDevice *device = NULL; long long start, length, end; self->dev = NULL; self->ped_geometry = NULL; if (kwds == NULL) { if (!PyArg_ParseTuple(args, "O!LL|L", &_ped_Device_Type_obj, &self->dev, &start, &length, &end)) { self->dev = NULL; return -1; } } else { if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!LL|L", kwlist, &_ped_Device_Type_obj, &self->dev, &start, &length, &end)) { self->dev = NULL; return -2; } } device = _ped_Device2PedDevice(self->dev); if (device == NULL) { self->dev = NULL; return -3; } self->ped_geometry = ped_geometry_new(device, start, length); if (self->ped_geometry == NULL) { if (partedExnRaised) { partedExnRaised = 0; if (!PyErr_ExceptionMatches(PartedException) && !PyErr_ExceptionMatches(PyExc_NotImplementedError)) { PyErr_SetString(CreateException, partedExnMessage); } } else { PyErr_SetString(CreateException, "Could not create new geometry"); } self->dev = NULL; return -3; } Py_INCREF(self->dev); return 0; }
PedPartition* create_and_add_partition(PedDisk* disk, PedPartitionType type, const PedFileSystemType* fs, PedSector start, PedSector end) { PedPartition* part = ped_partition_new (disk, type, fs, start, end); g_return_val_if_fail(part != NULL, FALSE); PedGeometry* geom = ped_geometry_new (disk->dev, start, end - start + 1); g_assert(geom != NULL); PedConstraint* constraint = ped_constraint_new_from_max (geom); g_assert(constraint != NULL); ped_disk_add_partition(disk, part, constraint); ped_constraint_destroy (constraint); ped_geometry_destroy (geom); return part; }
static PedGeometry* ntfs_probe (PedGeometry* geom) { char buf[512]; if (!ped_geometry_read (geom, buf, 0, 1)) return 0; if (strncmp (NTFS_SIGNATURE, buf + 3, strlen (NTFS_SIGNATURE)) == 0) return ped_geometry_new (geom->dev, geom->start, PED_LE64_TO_CPU (*(uint64_t*) (buf + 0x28))); else return NULL; }
int command_line_get_sector (const char* prompt, PedDevice* dev, PedSector* value, PedGeometry** range, char** raw_input) { char* def_str; char* input; int valid; def_str = ped_unit_format (dev, *value); input = command_line_get_word (prompt, *value ? def_str : NULL, NULL, 1); /* def_str might have rounded *value a little bit. If the user picked * the default, make sure the selected sector is identical to the * default. */ if (input && *value && !strcmp (input, def_str)) { if (range) { *range = ped_geometry_new (dev, *value, 1); free (def_str); free (input); return *range != NULL; } free (def_str); free (input); return 1; } free (def_str); if (!input) { *value = 0; if (range) *range = NULL; return 0; } valid = ped_unit_parse (input, dev, value, range); if (raw_input) *raw_input = input; else free (input); return valid; }
static PedGeometry* jfs_probe (PedGeometry* geom) { union { struct superblock sb; char bytes[512]; } buf; if (geom->length < JFS_SUPER_SECTOR + 1) return NULL; if (!ped_geometry_read (geom, &buf, JFS_SUPER_SECTOR, 1)) return NULL; if (strncmp (buf.sb.s_magic, JFS_MAGIC, 4) == 0) { PedSector block_size = PED_LE32_TO_CPU (buf.sb.s_pbsize) / 512; PedSector block_count = PED_LE64_TO_CPU (buf.sb.s_size); return ped_geometry_new (geom->dev, geom->start, block_size * block_count); } else { return NULL; } }
/* Used by hfsplus_probe and hfs_probe */ PedGeometry* hfs_and_wrapper_probe (PedGeometry* geom) { uint8_t buf[PED_SECTOR_SIZE_DEFAULT]; HfsMasterDirectoryBlock *mdb; PedGeometry* geom_ret; PedSector search, max; PED_ASSERT (geom != NULL); PED_ASSERT (hfsc_can_use_geom (geom)); mdb = (HfsMasterDirectoryBlock *) buf; /* is 5 an intelligent value ? */ if ((geom->length < 5) || (!ped_geometry_read (geom, buf, 2, 1)) || (mdb->signature != PED_CPU_TO_BE16 (HFS_SIGNATURE)) ) return NULL; search = ((PedSector) PED_BE16_TO_CPU (mdb->start_block) + ((PedSector) PED_BE16_TO_CPU (mdb->total_blocks) * (PED_BE32_TO_CPU (mdb->block_size) / PED_SECTOR_SIZE_DEFAULT ))); max = search + (PED_BE32_TO_CPU (mdb->block_size) / PED_SECTOR_SIZE_DEFAULT); if (!(geom_ret = ped_geometry_new (geom->dev, geom->start, search + 2))) return NULL; for (; search < max; search++) { if (!ped_geometry_set (geom_ret, geom_ret->start, search + 2) || !ped_geometry_read (geom_ret, buf, search, 1)) break; if (mdb->signature == PED_CPU_TO_BE16 (HFS_SIGNATURE)) return geom_ret; } ped_geometry_destroy (geom_ret); return NULL; }
void SystemPartitioner::init() { #if NONDESTRUCTIVE emit done(); return; #endif // Check # of harddisks to see if RAID0-ing them makes any sense ped_device_probe_all(); PedDevice *tmp=NULL; int disks=0; QString installsource(getenv("INSTALLSOURCE")); MSG("Install source is " + installsource); while((tmp=ped_device_get_next(tmp))) { // FIXME workaround for parted breakage // Skip CD-ROMs parted accidentally marks as harddisk QString p(tmp->path); if(!p.startsWith("/dev/sd") && (p.contains("/dev/scd") || p.contains("/dev/sr") || access(QFile::encodeName("/proc/ide/" + p.section('/', 2, 2) + "/cache"), R_OK))) continue; // It's not a good idea to install on a USB stick we're installing from... if(installsource.startsWith(p)) continue; MSG(QString("Found disk: ") + QString(tmp->path) + ":" + "/proc/ide/" + p.section('/', 2, 2) + "/" + "cache" + ":" + QString::number(access(QFile::encodeName("/proc/ide/" + p.section('/', 2, 2) + "/cache"), R_OK))); #if 0 // Check if the drive is actually there -- some empty CF // readers misidentify themselves... int fd=open(tmp->path, O_RDONLY); if(fd < 0) continue; char test; if(read(fd, &test, 1) <= 0) { close(fd); continue; } close(fd); #endif disks++; } ped_device_free_all(); // Grab all disks ped_device_probe_all(); PedFileSystemType const *ext3=ped_file_system_type_get("ext2"); // parted doesn't support ext3 creation yet, so we need this hack PedFileSystemType const *bootext3=ped_file_system_type_get("ext2"); PedFileSystemType const *swap=ped_file_system_type_get("linux-swap"); Meminfo m; unsigned long long swapsize=m.suggested_swap(); QStringList raidPartitions; PedDevice *dev=NULL; PedPartition *fspart=NULL; PedGeometry *fsgeo=NULL; setHelp(tr("Removing other OSes...")); resizeEvent(0); uint32_t bootsize=0; #ifndef NO_RAID0 if(disks>1) bootsize=32*1024*2; /* size is in 512 kB blocks --> we use 32 MB */ #endif while((dev=ped_device_get_next(dev))) { // FIXME workaround for parted breakage QString p(dev->path); if(!p.startsWith("/dev/sd") && (p.contains("/dev/scd") || p.contains("/dev/sr") || access(QFile::encodeName("/proc/ide/" + p.section('/', 2, 2) + "/cache"), R_OK))) continue; // It's not a good idea to install on a USB stick we're installing from... if(installsource.startsWith(p)) continue; //unsigned long long disksize=dev->length*dev->sector_size; PedDiskType *type=ped_disk_type_get("msdos"); PedDisk *disk=ped_disk_new_fresh(dev, type); PedGeometry *part=ped_geometry_new(dev, 0, dev->length); if(swapsize && _swap.isEmpty() && ((unsigned long long)part->length > swapsize + bootsize)) { // Split disk in swap and fs partitions PedGeometry *swapgeo=ped_geometry_new(dev, 0, swapsize); PedGeometry *bootgeo=NULL; uint32_t fssize=part->end - swapsize; uint32_t fsstart=swapsize+1; if(bootsize) { bootgeo=ped_geometry_new(dev, swapsize+1, bootsize); fssize -= bootsize; fsstart += bootsize; } fsgeo=ped_geometry_new(dev, fsstart, fssize); PedPartition *swappart=ped_partition_new(disk, (PedPartitionType)0, swap, swapgeo->start, swapgeo->end); PedPartition *bootpart=NULL; if(bootsize) bootpart=ped_partition_new(disk, (PedPartitionType)0, bootext3, bootgeo->start, bootgeo->end); fspart=ped_partition_new(disk, (PedPartitionType)0, ext3, fsgeo->start, fsgeo->end); if(bootsize) ped_partition_set_flag(fspart, PED_PARTITION_RAID, 1); ped_disk_add_partition(disk, swappart, ped_constraint_any(dev)); ped_disk_commit(disk); ped_geometry_destroy(swapgeo); setHelp(tr("Creating swap filesystem")); PedFileSystem *swapfs=ped_file_system_create(&(swappart->geom), swap, NULL /*timer->timer()*/); ped_file_system_close(swapfs); _swap = dev->path + QString::number(swappart->num); // Parted's swap creator is buggy QProcess::execute("/sbin/mkswap " + _swap); if(bootpart) { setHelp(tr("Creating boot filesystem")); ped_disk_add_partition(disk, bootpart, ped_constraint_any(dev)); ped_disk_commit(disk); PedFileSystem *bootfs=ped_file_system_create(&(bootpart->geom), bootext3, timer->timer()); ped_file_system_close(bootfs); ped_partition_set_flag(bootpart, PED_PARTITION_BOOT, 1); ped_geometry_destroy(bootgeo); QString devname=dev->path + QString::number(bootpart->num); _size.insert(devname, bootpart->geom.length); if(_rootfs == "ext3") { Ext3FS e3(devname); e3.addJournal(0); e3.setCheckInterval(0); e3.setCheckMountcount(-1); e3.setDirIndex(); } else { QProcess::execute("/sbin/mkfs." + _rootfs + " " + _mkfsopts + " " + devname); } if(!_postmkfs.isEmpty()) QProcess::execute(_postmkfs + " " + devname); _partitions.insert(devname, FileSystem("/boot", _rootfs)); } } else { // Grab the whole disk for filesystem fsgeo=ped_constraint_solve_max(ped_constraint_any(dev)); fspart=ped_partition_new(disk, (PedPartitionType)0, ext3, part->start, part->end); if(bootsize) ped_partition_set_flag(fspart, PED_PARTITION_RAID, 1); } ped_disk_add_partition(disk, fspart, ped_constraint_any(dev)); if(!bootsize) ped_partition_set_flag(fspart, PED_PARTITION_BOOT, 1); ped_disk_commit(disk); if(!bootsize) { setHelp(tr("Creating Linux filesystem")); PedFileSystem *fs=ped_file_system_create(&(fspart->geom), ext3, timer->timer()); _totalSize += fspart->geom.length; ped_file_system_close(fs); } ped_geometry_destroy(fsgeo); // Convert to ext3 and turn off checking QString devname=dev->path + QString::number(fspart->num); if(bootsize) raidPartitions.append(devname); else if(!_partitions.hasMountpoint("/")) _partitions.insert(devname, FileSystem("/", _rootfs)); else { QString mp(devname); mp.replace("/dev", "/mnt"); _partitions.insert(devname, FileSystem(mp, _rootfs)); } _size.insert(devname, fspart->geom.length); if(!bootsize) { if(_rootfs == "ext3") { Ext3FS e3(devname); e3.addJournal(0); e3.setCheckInterval(0); e3.setCheckMountcount(-1); e3.setDirIndex(); } else { QProcess::execute("/sbin/mkfs." + _rootfs + " " + _mkfsopts + " " + devname); } if(!_postmkfs.isEmpty()) QProcess::execute(_postmkfs + " " + devname); ped_disk_destroy(disk); } } if(bootsize) { setHelp(tr("Combining disks...")); // Make sure we can read the array we're building first... Modules::instance()->loadWithDeps("md"); Modules::instance()->loadWithDeps("raid0"); // Now create it FILE *f=fopen("/tmp/mdadm.conf", "w"); if(!f) QMessageBox::information(0, "debug", QString("Failed to create mdadm.conf: ") + strerror(errno)); fprintf(f, "DEVICE partitions"); fprintf(f, "ARRAY /dev/md0 name=ArkLinux devices=%s level=0 num-devices=%u\n", qPrintable(raidPartitions.join(",")), raidPartitions.count()); fprintf(f, "MAILADDR root@localhost\n"); fclose(f); QString command="/sbin/mdadm --create -e 1.2 --chunk=32 --level=0 --raid-devices=" + QString::number(raidPartitions.count()) + " --name=ArkLinux --force /dev/md0 " + raidPartitions.join(" "); QProcess::execute(command); if(_rootfs == "ext3") { QProcess::execute("/sbin/mke2fs -j /dev/md0"); Ext3FS e3("/dev/md0"); e3.setCheckInterval(0); e3.setCheckMountcount(-1); e3.setDirIndex(); } else { QProcess::execute("/sbin/mkfs." + _rootfs + " " + _mkfsopts + " /dev/md0"); } if(!_postmkfs.isEmpty()) QProcess::execute(_postmkfs + " /dev/md0"); _partitions.insert("/dev/md0", FileSystem("/", _rootfs)); _size.clear(); _size.insert("/dev/md0", _totalSize); } // We don't need a UI to take the whole system - we're done. emit done(); }
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; }
static int parse_chs (const char* str, const PedDevice* dev, PedSector* sector, PedGeometry** range) { PedSector cyl_size = dev->bios_geom.heads * dev->bios_geom.sectors; PedCHSGeometry chs; char* copy = ped_strdup (str); if (!copy) return 0; strip_string (copy); remove_punct (copy); if (sscanf (copy, "%d %d %d", &chs.cylinders, &chs.heads, &chs.sectors) != 3) { ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("\"%s\" has invalid syntax for locations."), copy); goto error_free_copy; } if (chs.heads >= dev->bios_geom.heads) { ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("The maximum head value is %d."), dev->bios_geom.heads - 1); goto error_free_copy; } if (chs.sectors >= dev->bios_geom.sectors) { ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("The maximum sector value is %d."), dev->bios_geom.sectors - 1); goto error_free_copy; } *sector = 1LL * chs.cylinders * cyl_size + chs.heads * dev->bios_geom.sectors + chs.sectors; if (*sector >= dev->length) { ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("The location %s is outside of the " "device %s."), str, dev->path); goto error_free_copy; } if (range) *range = ped_geometry_new (dev, *sector, 1); free (copy); return !range || *range != NULL; error_free_copy: free (copy); *sector = 0; if (range) *range = NULL; return 0; }
bool MParted::MParted_Core::createPartition(MParted::Partition & new_partition, MParted::Sector min_size) { new_partition.partitionNumber = 0; if (!openDeviceAndDisk(new_partition.devicePath)) return false; PedPartitionType type; PedPartition *pedPartition = NULL; PedConstraint *constraint = NULL; PedFileSystemType* fs_type = NULL; //create new partition switch (new_partition.type) { case MParted::TYPE_PRIMARY: type = PED_PARTITION_NORMAL; break; case MParted::TYPE_LOGICAL: type = PED_PARTITION_LOGICAL; break; case MParted::TYPE_EXTENDED: type = PED_PARTITION_EXTENDED; break; default: type = PED_PARTITION_FREESPACE; } if (new_partition.type != MParted::TYPE_EXTENDED) fs_type = ped_file_system_type_get("ext2"); pedPartition = ped_partition_new(pedDisk, type, fs_type, new_partition.sector_start, new_partition.sector_end); if (!pedPartition) { // Clean up closeDeviceAndDisk(); return false; } if (new_partition.alignment == MParted::ALIGN_MEBIBYTE) { PedGeometry *geom = ped_geometry_new(pedDevice, new_partition.sector_start, new_partition.getSectorLength()); if (geom) constraint = ped_constraint_exact(geom); } else { constraint = ped_constraint_any(pedDevice); } if (constraint) { if (min_size > 0 && new_partition.filesystem != MParted::FS_XFS) // Permit copying to smaller xfs partition constraint->min_size = min_size; if (ped_disk_add_partition(pedDisk, pedPartition, constraint) && commit()) { // Get partition path new_partition.path = Utils::charToStringFree(ped_partition_get_path(pedPartition)); // we have to free the result of ped_partition_get_path() new_partition.partitionNumber = pedPartition->num; new_partition.sector_start = pedPartition->geom.start; new_partition.sector_end = pedPartition->geom.end; } ped_constraint_destroy(constraint); } // Clean up closeDeviceAndDisk(); return (new_partition.partitionNumber > 0); }
bool CreatePartitionJob::run(Report& parent) { Q_ASSERT(partition().devicePath() == device().deviceNode()); bool rval = false; Report* report = jobStarted(parent); // According to libParted docs, PedPartitionType can be "NULL if unknown". That's obviously wrong, // it's a typedef for an enum. So let's use something the libparted devs will hopefully never // use... PedPartitionType pedType = static_cast<PedPartitionType>(0xffffffff); if (partition().roles().has(PartitionRole::Extended)) pedType = PED_PARTITION_EXTENDED; else if (partition().roles().has(PartitionRole::Logical)) pedType = PED_PARTITION_LOGICAL; else if (partition().roles().has(PartitionRole::Primary)) pedType = PED_PARTITION_NORMAL; if (pedType == static_cast<int>(0xffffffff)) { report->line() << i18nc("@info/plain", "Unknown partition role for new partition <filename>%1</filename> (roles: %2)", partition().deviceNode(), partition().roles().toString()); } else if (openPed(device().deviceNode())) { PedFileSystemType* pedFsType = (partition().roles().has(PartitionRole::Extended) || partition().fileSystem().type() == FileSystem::Unformatted) ? NULL : getPedFileSystemType(partition().fileSystem().type()); PedPartition* pedPartition = ped_partition_new(pedDisk(), pedType, pedFsType, partition().firstSector(), partition().lastSector()); if (pedPartition) { PedConstraint* pedConstraint = NULL; PedGeometry* pedGeometry = ped_geometry_new(pedDevice(), partition().firstSector(), partition().length()); if (pedGeometry) pedConstraint = ped_constraint_exact(pedGeometry); if (pedConstraint) { if (ped_disk_add_partition(pedDisk(), pedPartition, pedConstraint) && commit()) { partition().setNumber(pedPartition->num); partition().setState(Partition::StateNone); partition().setFirstSector(pedPartition->geom.start); partition().setLastSector(pedPartition->geom.end); rval = true; } else report->line() << i18nc("@info/plain", "Failed to add partition <filename>%1</filename> to device <filename>%2</filename>.", partition().deviceNode(), device().deviceNode()); ped_constraint_destroy(pedConstraint); } else report->line() << i18nc("@info/plain", "Failed to create a new partition: could not get geometry for constraint."); } else report->line() << i18nc("@info/plain", "Failed to create new partition <filename>%1</filename>.", partition().deviceNode()); closePed(); } else report->line() << i18nc("@info/plain", "Could not open device <filename>%1</filename> to create new partition <filename>%2</filename>.", device().deviceNode(), partition().deviceNode()); jobFinished(*report, rval); return rval; }
int hfsplus_resize (PedFileSystem* fs, PedGeometry* geom, PedTimer* timer) { HfsPPrivateFSData* priv_data; PedTimer* timer_plus; PedGeometry* embedded_geom; PedSector hgms; /* check preconditions */ PED_ASSERT (fs != NULL); PED_ASSERT (fs->geom != NULL); PED_ASSERT (geom != NULL); PED_ASSERT (fs->geom->dev == geom->dev); #ifdef DEBUG PED_ASSERT ((hgms = hfsplus_get_min_size (fs)) != 0); #else if ((hgms = hfsplus_get_min_size (fs)) == 0) return 0; #endif if (ped_geometry_test_equal(fs->geom, geom)) return 1; priv_data = (HfsPPrivateFSData*) fs->type_specific; if (fs->geom->start != geom->start || geom->length > fs->geom->length || geom->length < hgms) { ped_exception_throw ( PED_EXCEPTION_NO_FEATURE, PED_EXCEPTION_CANCEL, _("Sorry, HFS+ cannot be resized that way yet.")); return 0; } if (priv_data->wrapper) { PedSector red, hgee; HfsPrivateFSData* hfs_priv_data = (HfsPrivateFSData*) priv_data->wrapper->type_specific; unsigned int hfs_sect_block = PED_BE32_TO_CPU (hfs_priv_data->mdb->block_size) / PED_SECTOR_SIZE_DEFAULT; /* There is a wrapper so we must calculate the new geometry of the embedded HFS+ volume */ red = ( (fs->geom->length - geom->length + hfs_sect_block - 1) / hfs_sect_block ) * hfs_sect_block; /* Can't we shrink the hfs+ volume by the desired size ? */ hgee = hfsplus_get_empty_end (fs); if (!hgee) return 0; if (red > priv_data->plus_geom->length - hgee) { /* No, shrink hfs+ by the greatest possible value */ hgee = ((hgee + hfs_sect_block - 1) / hfs_sect_block) * hfs_sect_block; red = priv_data->plus_geom->length - hgee; } embedded_geom = ped_geometry_new (geom->dev, priv_data->plus_geom->start, priv_data->plus_geom->length - red); /* There is a wrapper so the resize process is a two stages process (embedded resizing then wrapper resizing) : we create a sub timer */ ped_timer_reset (timer); ped_timer_set_state_name (timer, _("shrinking embedded HFS+ volume")); ped_timer_update(timer, 0.0); timer_plus = ped_timer_new_nested (timer, 0.98); } else { /* No wrapper : the desired geometry is the desired HFS+ volume geometry */ embedded_geom = geom; timer_plus = timer; } /* Resize the HFS+ volume */ if (!hfsplus_volume_resize (fs, embedded_geom, timer_plus)) { if (timer_plus != timer) ped_timer_destroy_nested (timer_plus); ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("Resizing the HFS+ volume has failed.")); return 0; } if (priv_data->wrapper) { ped_geometry_destroy (embedded_geom); ped_timer_destroy_nested (timer_plus); ped_timer_set_state_name(timer, _("shrinking HFS wrapper")); timer_plus = ped_timer_new_nested (timer, 0.02); /* There's a wrapper : second stage = resizing it */ if (!hfsplus_wrapper_update (fs) || !hfs_resize (priv_data->wrapper, geom, timer_plus)) { ped_timer_destroy_nested (timer_plus); ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("Updating the HFS wrapper has failed.")); return 0; } ped_timer_destroy_nested (timer_plus); } ped_timer_update(timer, 1.0); return 1; }
PedFileSystem* hfsplus_open (PedGeometry* geom) { uint8_t buf[PED_SECTOR_SIZE_DEFAULT]; PedFileSystem* fs; HfsPVolumeHeader* vh; HfsPPrivateFSData* priv_data; PedGeometry* wrapper_geom; unsigned int map_sectors; if (!hfsc_can_use_geom (geom)) return NULL; fs = (PedFileSystem*) ped_malloc (sizeof (PedFileSystem)); if (!fs) goto hpo; vh = (HfsPVolumeHeader*) ped_malloc (sizeof (HfsPVolumeHeader)); if (!vh) goto hpo_fs; priv_data = (HfsPPrivateFSData*)ped_malloc (sizeof (HfsPPrivateFSData)); if (!priv_data) goto hpo_vh; fs->geom = ped_geometry_duplicate (geom); if (!fs->geom) goto hpo_pd; fs->type_specific = (void*) priv_data; if ((wrapper_geom = hfs_and_wrapper_probe (geom))) { HfsPrivateFSData* hfs_priv_data; PedSector abs_sect, length; unsigned int bs; ped_geometry_destroy (wrapper_geom); priv_data->wrapper = hfs_open(geom); if (!priv_data->wrapper) goto hpo_gm; hfs_priv_data = (HfsPrivateFSData*) priv_data->wrapper->type_specific; bs = PED_BE32_TO_CPU (hfs_priv_data->mdb->block_size) / PED_SECTOR_SIZE_DEFAULT; abs_sect = (PedSector) geom->start + (PedSector) PED_BE16_TO_CPU ( hfs_priv_data->mdb->start_block) + (PedSector) PED_BE16_TO_CPU ( hfs_priv_data->mdb->old_new .embedded.location.start_block ) * bs; length = (PedSector) PED_BE16_TO_CPU ( hfs_priv_data->mdb->old_new .embedded.location.block_count) * bs; priv_data->plus_geom = ped_geometry_new (geom->dev, abs_sect, length); if (!priv_data->plus_geom) goto hpo_wr; priv_data->free_geom = 1; } else { priv_data->wrapper = NULL; priv_data->plus_geom = fs->geom; priv_data->free_geom = 0; } if (!ped_geometry_read (priv_data->plus_geom, buf, 2, 1)) goto hpo_pg; memcpy (vh, buf, sizeof (HfsPVolumeHeader)); priv_data->vh = vh; if (vh->signature != PED_CPU_TO_BE16(HFSP_SIGNATURE) && vh->signature != PED_CPU_TO_BE16(HFSX_SIGNATURE)) { ped_exception_throw ( PED_EXCEPTION_BUG, PED_EXCEPTION_CANCEL, _("No valid HFS[+X] signature has been found while " "opening.")); goto hpo_pg; } if (vh->signature == PED_CPU_TO_BE16(HFSP_SIGNATURE) && vh->version != PED_CPU_TO_BE16(HFSP_VERSION)) { if (ped_exception_throw ( PED_EXCEPTION_NO_FEATURE, PED_EXCEPTION_IGNORE_CANCEL, _("Version %d of HFS+ isn't supported."), PED_BE16_TO_CPU(vh->version)) != PED_EXCEPTION_IGNORE) goto hpo_pg; } if (vh->signature == PED_CPU_TO_BE16(HFSX_SIGNATURE) && vh->version != PED_CPU_TO_BE16(HFSX_VERSION)) { if (ped_exception_throw ( PED_EXCEPTION_NO_FEATURE, PED_EXCEPTION_IGNORE_CANCEL, _("Version %d of HFSX isn't supported."), PED_BE16_TO_CPU(vh->version)) != PED_EXCEPTION_IGNORE) goto hpo_pg; } priv_data->jib_start_block = 0; priv_data->jl_start_block = 0; if (vh->attributes & PED_CPU_TO_BE32(1<<HFSP_JOURNALED)) { if (!hfsj_replay_journal(fs)) goto hpo_pg; } priv_data->bad_blocks_loaded = 0; priv_data->bad_blocks_xtent_nb = 0; priv_data->bad_blocks_xtent_list = NULL; priv_data->extents_file = hfsplus_file_open (fs, PED_CPU_TO_BE32 (HFS_XTENT_ID), vh->extents_file.extents, PED_BE64_TO_CPU ( vh->extents_file.logical_size ) / PED_SECTOR_SIZE_DEFAULT); if (!priv_data->extents_file) goto hpo_pg; priv_data->catalog_file = hfsplus_file_open (fs, PED_CPU_TO_BE32 (HFS_CATALOG_ID), vh->catalog_file.extents, PED_BE64_TO_CPU ( vh->catalog_file.logical_size ) / PED_SECTOR_SIZE_DEFAULT); if (!priv_data->catalog_file) goto hpo_ce; priv_data->attributes_file = hfsplus_file_open (fs, PED_CPU_TO_BE32 (HFSP_ATTRIB_ID), vh->attributes_file.extents, PED_BE64_TO_CPU ( vh->attributes_file.logical_size) / PED_SECTOR_SIZE_DEFAULT); if (!priv_data->attributes_file) goto hpo_cc; map_sectors = ( PED_BE32_TO_CPU (vh->total_blocks) + PED_SECTOR_SIZE_DEFAULT * 8 - 1 ) / (PED_SECTOR_SIZE_DEFAULT * 8); priv_data->dirty_alloc_map = (uint8_t*) ped_malloc ((map_sectors + 7) / 8); if (!priv_data->dirty_alloc_map) goto hpo_cl; memset(priv_data->dirty_alloc_map, 0, (map_sectors + 7) / 8); priv_data->alloc_map = (uint8_t*) ped_malloc (map_sectors * PED_SECTOR_SIZE_DEFAULT); if (!priv_data->alloc_map) goto hpo_dm; priv_data->allocation_file = hfsplus_file_open (fs, PED_CPU_TO_BE32 (HFSP_ALLOC_ID), vh->allocation_file.extents, PED_BE64_TO_CPU ( vh->allocation_file.logical_size) / PED_SECTOR_SIZE_DEFAULT); if (!priv_data->allocation_file) goto hpo_am; if (!hfsplus_file_read (priv_data->allocation_file, priv_data->alloc_map, 0, map_sectors)) { hfsplus_close(fs); return NULL; } fs->type = &hfsplus_type; fs->checked = ((PED_BE32_TO_CPU (vh->attributes) >> HFS_UNMOUNTED) & 1) && !((PED_BE32_TO_CPU (vh->attributes) >> HFSP_INCONSISTENT) & 1); return fs; /*--- clean error handling ---*/ hpo_am: free(priv_data->alloc_map); hpo_dm: free(priv_data->dirty_alloc_map); hpo_cl: hfsplus_file_close (priv_data->attributes_file); hpo_cc: hfsplus_file_close (priv_data->catalog_file); hpo_ce: hfsplus_file_close (priv_data->extents_file); hpo_pg: if (priv_data->free_geom) ped_geometry_destroy (priv_data->plus_geom); hpo_wr: if (priv_data->wrapper) hfs_close(priv_data->wrapper); hpo_gm: ped_geometry_destroy (fs->geom); hpo_pd: free(priv_data); hpo_vh: free(vh); hpo_fs: free(fs); hpo: return NULL; }
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; }