597 lines
14 KiB
C
597 lines
14 KiB
C
/*
|
|
parted - a frontend to libparted
|
|
Copyright (C) 1999-2000 Andrew Clausen, Lennert Buytenhek and Red Hat, Inc.
|
|
|
|
Andrew Clausen <clausen@gnu.org>
|
|
Lennert Buytenhek <buytenh@gnu.org>
|
|
Matt Wilson, Red Hat Inc. <msw@redhat.com>
|
|
|
|
Modificated for Mario Teijeiro Otero <asimovi@teleline.es> for nparted
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#include <nparted.h>
|
|
|
|
int do_check (PedDevice** dev, int npart)
|
|
{
|
|
PedDisk* disk;
|
|
PedFileSystem* fs;
|
|
PedPartition* part;
|
|
|
|
disk = ped_disk_open (*dev);
|
|
if (!disk)
|
|
goto error;
|
|
|
|
part = ped_disk_get_partition (disk, npart);
|
|
if (!part) {
|
|
ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
|
|
_("Partition doesn't exist."));
|
|
goto error_close_disk;
|
|
}
|
|
fs = ped_file_system_open (&part->geom);
|
|
if (!fs)
|
|
goto error_close_disk;
|
|
ped_file_system_check (fs);
|
|
ped_file_system_close (fs);
|
|
ped_disk_close (disk);
|
|
return 1;
|
|
|
|
error_close_disk:
|
|
ped_disk_close (disk);
|
|
error:
|
|
return 0;
|
|
}
|
|
|
|
int do_cp (PedDevice** dev,int npart_src, char* dev_dest,int npart_dest)
|
|
{
|
|
PedDisk* src_disk = NULL;
|
|
PedDisk* dst_disk = NULL;
|
|
PedDevice* dst_device;
|
|
PedPartition* src = NULL;
|
|
PedPartition* dst = NULL;
|
|
PedFileSystem* src_fs = NULL;
|
|
|
|
src_disk = ped_disk_open (*dev);
|
|
if (!src_disk)
|
|
goto error;
|
|
|
|
/* figure out source partition */
|
|
src = ped_disk_get_partition (src_disk, npart_src);
|
|
if (!src) {
|
|
ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
|
|
_("Source partition doesn't exist."));
|
|
goto error_close_disk;
|
|
}
|
|
if (src->type == PED_PARTITION_EXTENDED) {
|
|
ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
|
|
_("Can't copy extended partitions."));
|
|
goto error_close_disk;
|
|
}
|
|
|
|
/* figure out target partition */
|
|
dst_device = ped_device_get (dev_dest);
|
|
if (!dst_device)
|
|
goto error_close_disk;
|
|
dst_disk = ped_disk_open (dst_device);
|
|
|
|
dst = ped_disk_get_partition (dst_disk, npart_dest);
|
|
if (!dst) {
|
|
ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
|
|
_("Destination partition doesn't exist."));
|
|
goto error_close_disk;
|
|
}
|
|
if (ped_partition_is_busy (dst)) {
|
|
if (ped_exception_throw (
|
|
PED_EXCEPTION_WARNING,
|
|
PED_EXCEPTION_IGNORE_CANCEL,
|
|
_("Destination partition is being used."))
|
|
!= PED_EXCEPTION_IGNORE)
|
|
goto error_close_disk;
|
|
}
|
|
dst->type = src->type;
|
|
|
|
/* do the copy */
|
|
src_fs = ped_file_system_open (&src->geom);
|
|
if (!src_fs)
|
|
goto error_close_disk;
|
|
if (!ped_file_system_copy (src_fs, &dst->geom))
|
|
goto error_close_fs;
|
|
ped_file_system_close (src_fs);
|
|
if (dst_disk && src_disk != dst_disk)
|
|
ped_disk_close (dst_disk);
|
|
ped_disk_close (src_disk);
|
|
return 1;
|
|
|
|
error_close_fs:
|
|
ped_file_system_close (src_fs);
|
|
error_close_disk:
|
|
if (dst_disk && src_disk != dst_disk)
|
|
ped_disk_close (dst_disk);
|
|
ped_disk_close (src_disk);
|
|
error:
|
|
return 0;
|
|
}
|
|
|
|
|
|
int do_mklabel (PedDevice** dev,char *label)
|
|
{
|
|
PedDisk* disk;
|
|
PedDiskType* type;
|
|
|
|
ped_exception_fetch_all ();
|
|
disk = ped_disk_open (*dev);
|
|
if (!disk) ped_exception_catch ();
|
|
ped_exception_leave_all ();
|
|
|
|
if (disk) {
|
|
if (ped_disk_is_busy (disk)) {
|
|
if (ped_exception_throw (
|
|
PED_EXCEPTION_WARNING,
|
|
PED_EXCEPTION_IGNORE_CANCEL,
|
|
_("Partition(s) on %s are being used."),
|
|
disk->dev->path)
|
|
!= PED_EXCEPTION_IGNORE) {
|
|
ped_disk_close (disk);
|
|
return 0;
|
|
}
|
|
}
|
|
ped_disk_close (disk);
|
|
}
|
|
|
|
type = ped_disk_type_get (label);
|
|
if (!type)
|
|
goto error_syntax;
|
|
|
|
ped_disk_create (*dev, type);
|
|
return 1;
|
|
|
|
error_syntax:
|
|
return 0;
|
|
}
|
|
|
|
int do_mkfs (PedDevice** dev,int npart, char *fs_type)
|
|
{
|
|
PedDisk* disk;
|
|
PedPartition* part;
|
|
PedFileSystemType* type;
|
|
PedFileSystem* fs;
|
|
|
|
disk = ped_disk_open (*dev);
|
|
if (!disk)
|
|
goto error;
|
|
|
|
part = ped_disk_get_partition (disk, npart);
|
|
if (!part) {
|
|
ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
|
|
_("Partition doesn't exist."));
|
|
goto error_close_disk;
|
|
}
|
|
if (ped_partition_is_busy (part)) {
|
|
if (ped_exception_throw (
|
|
PED_EXCEPTION_WARNING,
|
|
PED_EXCEPTION_IGNORE_CANCEL,
|
|
_("Partition is being used."))
|
|
!= PED_EXCEPTION_IGNORE)
|
|
goto error_close_disk;
|
|
}
|
|
|
|
if (!fs_type)
|
|
goto error_close_disk;
|
|
type = ped_file_system_type_get (fs_type);
|
|
if (!type) {
|
|
ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
|
|
_("Unknown filesystem type."));
|
|
goto error_close_disk;
|
|
}
|
|
|
|
fs = ped_file_system_create (&part->geom, type);
|
|
if (!fs)
|
|
goto error;
|
|
ped_file_system_close (fs);
|
|
|
|
if (!ped_partition_set_system (part, type))
|
|
goto error_close_disk;
|
|
if (!ped_disk_write (disk))
|
|
goto error_close_disk;
|
|
ped_disk_close (disk);
|
|
return 1;
|
|
error_close_disk:
|
|
ped_disk_close (disk);
|
|
error:
|
|
return 0;
|
|
}
|
|
|
|
int do_mkpart (PedDevice** dev,char ptype,char *ftype,PedSector start,PedSector end)
|
|
{
|
|
PedDisk* disk;
|
|
PedPartition* part;
|
|
PedPartitionType part_type;
|
|
PedFileSystemType* fs_type;
|
|
PedConstraint* constraint;
|
|
|
|
disk = ped_disk_open (*dev);
|
|
if (!disk)
|
|
goto error;
|
|
constraint = ped_constraint_any (disk);
|
|
if (!constraint)
|
|
goto error_close_disk;
|
|
|
|
switch (ptype) {
|
|
case 'p': part_type = PED_PARTITION_PRIMARY; break;
|
|
case 'e': part_type = PED_PARTITION_EXTENDED; break;
|
|
case 'l': part_type = PED_PARTITION_LOGICAL; break;
|
|
default: goto error_destroy_constraint;
|
|
}
|
|
|
|
if (part_type == PED_PARTITION_EXTENDED) {
|
|
fs_type = NULL;
|
|
} else {
|
|
if (!ftype) {
|
|
goto error_destroy_constraint;
|
|
}
|
|
|
|
fs_type = ped_file_system_type_get (ftype);
|
|
if (!fs_type) {
|
|
ped_exception_throw (PED_EXCEPTION_ERROR,
|
|
PED_EXCEPTION_CANCEL,
|
|
_("Unknown file system type."));
|
|
goto error_destroy_constraint;
|
|
}
|
|
}
|
|
|
|
part = ped_partition_new (disk, part_type, fs_type, start, end);
|
|
if (!part)
|
|
goto error_destroy_constraint;
|
|
if (!ped_disk_add_partition (disk, part, constraint))
|
|
goto error_destroy_part;
|
|
|
|
/* FIXME: ped_partition_new() doesn't probe the file system for
|
|
* what type of partition should be created. So we do it here.
|
|
* Question: SHOULD we probe the file system on
|
|
* ped_partition_new()? It only makes sense if someone accidently
|
|
* delete their partition...
|
|
*/
|
|
ped_partition_set_system (part, fs_type);
|
|
|
|
ped_disk_write (disk);
|
|
ped_constraint_destroy (constraint);
|
|
ped_disk_close (disk);
|
|
return 1;
|
|
|
|
error_destroy_part:
|
|
ped_partition_destroy (part);
|
|
error_destroy_constraint:
|
|
ped_constraint_destroy (constraint);
|
|
error_close_disk:
|
|
ped_disk_close (disk);
|
|
error:
|
|
return 0;
|
|
}
|
|
|
|
/* FIXME - this is a mess */
|
|
int do_mkpartfs (PedDevice** dev,char ptype,char *ftype,PedSector start, PedSector end)
|
|
{
|
|
PedDisk* disk;
|
|
PedPartition* part;
|
|
PedPartitionType part_type;
|
|
PedFileSystemType* fs_type;
|
|
PedFileSystem* fs;
|
|
PedConstraint* constraint;
|
|
|
|
disk = ped_disk_open (*dev);
|
|
if (!disk)
|
|
goto error;
|
|
constraint = ped_constraint_any (disk);
|
|
if (!constraint)
|
|
goto error_close_disk;
|
|
|
|
switch (ptype) {
|
|
case 'p': part_type = PED_PARTITION_PRIMARY; break;
|
|
case 'l': part_type = PED_PARTITION_LOGICAL; break;
|
|
case 'e':
|
|
default: goto error_destroy_constraint;
|
|
}
|
|
|
|
if (part_type == PED_PARTITION_EXTENDED) {
|
|
fs_type = NULL;
|
|
} else {
|
|
if (!ftype) {
|
|
goto error_destroy_constraint;
|
|
}
|
|
|
|
fs_type = ped_file_system_type_get (ftype);
|
|
|
|
if (!fs_type) {
|
|
ped_exception_throw (PED_EXCEPTION_ERROR,
|
|
PED_EXCEPTION_CANCEL,
|
|
_("Unknown file system type."));
|
|
goto error_destroy_constraint;
|
|
}
|
|
}
|
|
part = ped_partition_new (disk, part_type, fs_type, start, end);
|
|
|
|
if (!part)
|
|
goto error_destroy_constraint;
|
|
if (!ped_disk_add_partition (disk, part, constraint))
|
|
goto error_destroy_part;
|
|
|
|
fs = ped_file_system_create (&part->geom, fs_type);
|
|
if (!fs)
|
|
goto error_remove_part;
|
|
ped_file_system_close (fs);
|
|
|
|
/* set the system AGAIN, because if it's FAT16 or FAT32 (or whatever) will
|
|
* be known now.
|
|
*/
|
|
ped_partition_set_system (part, fs_type);
|
|
|
|
ped_disk_write (disk);
|
|
ped_constraint_destroy (constraint);
|
|
ped_disk_close (disk);
|
|
return 1;
|
|
|
|
error_remove_part:
|
|
ped_disk_delete_partition (disk, part);
|
|
goto error_close_disk;
|
|
error_destroy_part:
|
|
ped_partition_destroy (part);
|
|
error_destroy_constraint:
|
|
ped_constraint_destroy (constraint);
|
|
error_close_disk:
|
|
ped_disk_close (disk);
|
|
error:
|
|
return 0;
|
|
}
|
|
|
|
int do_move (PedDevice** dev,int part_src,PedSector start, PedSector end)
|
|
{
|
|
PedDisk* disk = NULL;
|
|
PedPartition* part = NULL;
|
|
PedGeometry old_geom;
|
|
PedConstraint* constraint;
|
|
PedFileSystem* fs = NULL;
|
|
|
|
disk = ped_disk_open (*dev);
|
|
if (!disk)
|
|
goto error;
|
|
|
|
part = ped_disk_get_partition (disk, part_src);
|
|
if (!part) {
|
|
ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
|
|
_("Partition doesn't exist."));
|
|
goto error_close_disk;
|
|
}
|
|
if (part->type == PED_PARTITION_EXTENDED) {
|
|
ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
|
|
_("Can't move extended partitions."));
|
|
goto error_close_disk;
|
|
}
|
|
|
|
if (ped_partition_is_busy (part)) {
|
|
if (ped_exception_throw (
|
|
PED_EXCEPTION_WARNING,
|
|
PED_EXCEPTION_IGNORE_CANCEL,
|
|
_("Partition is being used."))
|
|
!= PED_EXCEPTION_IGNORE)
|
|
goto error_close_disk;
|
|
}
|
|
|
|
/* NOTE: this gets aligned by ped_disk_set_partition_geom() */
|
|
|
|
old_geom = part->geom;
|
|
constraint = ped_constraint_any (disk);
|
|
if (!constraint)
|
|
goto error_close_disk;
|
|
if (!ped_disk_set_partition_geom (disk, part, constraint, start, end)) {
|
|
ped_constraint_destroy (constraint);
|
|
goto error_close_disk;
|
|
}
|
|
|
|
if (ped_geometry_test_overlap (&old_geom, &part->geom)) {
|
|
ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
|
|
_("Can't move a partition onto itself. Try using "
|
|
"resize, perhaps?"));
|
|
goto error_close_disk;
|
|
}
|
|
|
|
/* do the move */
|
|
fs = ped_file_system_open (&old_geom);
|
|
if (!fs)
|
|
goto error_close_disk;
|
|
if (!ped_file_system_copy (fs, &part->geom))
|
|
goto error_close_fs;
|
|
ped_file_system_close (fs);
|
|
if (!ped_disk_write (disk))
|
|
goto error_close_disk;
|
|
ped_disk_close (disk);
|
|
return 1;
|
|
|
|
error_close_fs:
|
|
ped_file_system_close (fs);
|
|
error_close_disk:
|
|
ped_disk_close (disk);
|
|
error:
|
|
return 0;
|
|
}
|
|
|
|
int do_name (PedDevice** dev, int npart,char *name)
|
|
{
|
|
PedDisk* disk;
|
|
PedPartition* part;
|
|
|
|
disk = ped_disk_open (*dev);
|
|
if (!disk)
|
|
goto error;
|
|
|
|
|
|
part = ped_disk_get_partition (disk, npart);
|
|
if (!part) {
|
|
ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
|
|
_("Partition doesn't exist."));
|
|
goto error_close_disk;
|
|
}
|
|
|
|
if (!name) {
|
|
goto error_close_disk;
|
|
}
|
|
|
|
if (!ped_partition_set_name (part, name))
|
|
goto error_close_disk;
|
|
if (!ped_disk_write (disk))
|
|
goto error_close_disk;
|
|
ped_disk_close (disk);
|
|
return 1;
|
|
|
|
error_close_disk:
|
|
ped_disk_close (disk);
|
|
error:
|
|
return 0;
|
|
}
|
|
|
|
int do_resize (PedDevice** dev,int npart, PedSector start, PedSector end)
|
|
{
|
|
PedDisk* disk;
|
|
PedPartition* part;
|
|
PedFileSystem* fs;
|
|
PedFileSystemType* fs_type;
|
|
PedConstraint* constraint;
|
|
|
|
disk = ped_disk_open (*dev);
|
|
if (!disk)
|
|
goto error;
|
|
|
|
part = ped_disk_get_partition (disk, npart);
|
|
if (!part) {
|
|
ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
|
|
_("Partition doesn't exist."));
|
|
goto error_close_disk;
|
|
}
|
|
if (ped_partition_is_busy (part)) {
|
|
if (ped_exception_throw (
|
|
PED_EXCEPTION_WARNING,
|
|
PED_EXCEPTION_IGNORE_CANCEL,
|
|
_("Partition is being used."))
|
|
!= PED_EXCEPTION_IGNORE)
|
|
goto error_close_disk;
|
|
}
|
|
|
|
|
|
if (part->type == PED_PARTITION_EXTENDED) {
|
|
constraint = ped_constraint_any (disk);
|
|
if (!ped_disk_set_partition_geom (disk, part, constraint,
|
|
start, end))
|
|
goto error_destroy_constraint;
|
|
ped_partition_set_system (part, NULL);
|
|
} else {
|
|
fs = ped_file_system_open (&part->geom);
|
|
if (!fs)
|
|
goto error_close_disk;
|
|
fs_type = fs->type;
|
|
constraint = ped_file_system_get_resize_constraint (fs);
|
|
if (!ped_disk_set_partition_geom (disk, part, constraint,
|
|
start, end))
|
|
goto error_close_fs;
|
|
if (!ped_file_system_resize (fs, &part->geom))
|
|
goto error_close_fs;
|
|
ped_file_system_close (fs);
|
|
ped_partition_set_system (part, fs_type);
|
|
}
|
|
|
|
ped_disk_write (disk);
|
|
ped_constraint_destroy (constraint);
|
|
ped_disk_close (disk);
|
|
return 1;
|
|
|
|
error_close_fs:
|
|
ped_file_system_close (fs);
|
|
error_destroy_constraint:
|
|
ped_constraint_destroy (constraint);
|
|
error_close_disk:
|
|
ped_disk_close (disk);
|
|
error:
|
|
return 0;
|
|
}
|
|
|
|
int do_rm (PedDevice** dev, int npart)
|
|
{
|
|
PedDisk* disk;
|
|
PedPartition* part;
|
|
|
|
disk = ped_disk_open (*dev);
|
|
if (!disk)
|
|
goto error;
|
|
|
|
part = ped_disk_get_partition (disk, npart);
|
|
if (!part) {
|
|
ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
|
|
_("Partition doesn't exist."));
|
|
goto error_close_disk;
|
|
}
|
|
if (ped_partition_is_busy (part)) {
|
|
if (ped_exception_throw (
|
|
PED_EXCEPTION_WARNING,
|
|
PED_EXCEPTION_IGNORE_CANCEL,
|
|
_("Partition is being used."))
|
|
!= PED_EXCEPTION_IGNORE)
|
|
goto error_close_disk;
|
|
}
|
|
|
|
ped_disk_delete_partition (disk, part);
|
|
ped_disk_write (disk);
|
|
ped_disk_close (disk);
|
|
return 1;
|
|
|
|
error_close_disk:
|
|
ped_disk_close (disk);
|
|
error:
|
|
return 0;
|
|
}
|
|
|
|
int do_set (PedDevice** dev, int npart, char *flag_name,int state)
|
|
{
|
|
PedDisk* disk;
|
|
PedPartition* part;
|
|
PedPartitionFlag flag;
|
|
|
|
disk = ped_disk_open (*dev);
|
|
if (!disk)
|
|
goto error;
|
|
|
|
part = ped_disk_get_partition (disk, npart);
|
|
if (!part) {
|
|
ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
|
|
_("Partition doesn't exist."));
|
|
goto error_close_disk;
|
|
}
|
|
|
|
if (!flag_name)
|
|
goto error_help;
|
|
flag = ped_partition_flag_get_by_name (flag_name);
|
|
if (!flag)
|
|
goto error_help;
|
|
|
|
if (!ped_partition_set_flag (part, flag, state))
|
|
goto error_close_disk;
|
|
if (!ped_disk_write (disk))
|
|
goto error_close_disk;
|
|
ped_disk_close (disk);
|
|
return 1;
|
|
|
|
error_help:
|
|
error_close_disk:
|
|
ped_disk_close (disk);
|
|
error:
|
|
return 0;
|
|
}
|