2004-11-17 06:00:25 -07:00
|
|
|
#include "../include/GParted_Core.h"
|
|
|
|
|
|
|
|
namespace GParted
|
|
|
|
{
|
|
|
|
|
|
|
|
GParted_Core::GParted_Core( )
|
|
|
|
{
|
|
|
|
device = NULL ;
|
|
|
|
disk = NULL ;
|
|
|
|
c_partition = NULL ;
|
2004-11-21 14:49:38 -07:00
|
|
|
|
2004-11-17 06:00:25 -07:00
|
|
|
p_filesystem = NULL ;
|
|
|
|
textbuffer = Gtk::TextBuffer::create( ) ;
|
|
|
|
|
|
|
|
//get valid flags ...
|
2004-12-27 05:08:01 -07:00
|
|
|
for ( PedPartitionFlag flag = ped_partition_flag_next( (PedPartitionFlag) NULL ) ; flag ; flag = ped_partition_flag_next( flag ) )
|
2004-11-17 06:00:25 -07:00
|
|
|
flags .push_back( flag ) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GParted_Core::find_supported_filesystems( )
|
|
|
|
{
|
|
|
|
FILESYSTEMS .clear( ) ;
|
|
|
|
|
|
|
|
ext2 fs_ext2;
|
|
|
|
FILESYSTEMS .push_back( fs_ext2 .get_filesystem_support( ) ) ;
|
|
|
|
|
|
|
|
ext3 fs_ext3;
|
|
|
|
FILESYSTEMS .push_back( fs_ext3 .get_filesystem_support( ) ) ;
|
|
|
|
|
|
|
|
fat16 fs_fat16;
|
|
|
|
FILESYSTEMS .push_back( fs_fat16 .get_filesystem_support( ) ) ;
|
|
|
|
|
|
|
|
fat32 fs_fat32;
|
|
|
|
FILESYSTEMS .push_back( fs_fat32 .get_filesystem_support( ) ) ;
|
|
|
|
|
2004-12-14 15:49:44 -07:00
|
|
|
hfs fs_hfs;
|
|
|
|
FILESYSTEMS .push_back( fs_hfs .get_filesystem_support( ) ) ;
|
|
|
|
|
|
|
|
jfs fs_jfs;
|
|
|
|
FILESYSTEMS .push_back( fs_jfs .get_filesystem_support( ) ) ;
|
|
|
|
|
2004-11-17 06:00:25 -07:00
|
|
|
linux_swap fs_linux_swap;
|
|
|
|
FILESYSTEMS .push_back( fs_linux_swap .get_filesystem_support( ) ) ;
|
|
|
|
|
|
|
|
reiserfs fs_reiserfs;
|
|
|
|
FILESYSTEMS .push_back( fs_reiserfs .get_filesystem_support( ) ) ;
|
2004-11-21 14:49:38 -07:00
|
|
|
|
2004-11-23 09:20:59 -07:00
|
|
|
ntfs fs_ntfs;
|
|
|
|
FILESYSTEMS .push_back( fs_ntfs .get_filesystem_support( ) ) ;
|
|
|
|
|
2004-12-13 14:24:12 -07:00
|
|
|
xfs fs_xfs;
|
|
|
|
FILESYSTEMS .push_back( fs_xfs .get_filesystem_support( ) ) ;
|
|
|
|
|
2004-11-21 14:49:38 -07:00
|
|
|
//unknown filesystem (default when no match is found)
|
|
|
|
FS fs ; fs .filesystem = "unknown" ;
|
|
|
|
FILESYSTEMS .push_back( fs ) ;
|
2004-11-17 06:00:25 -07:00
|
|
|
}
|
|
|
|
|
2004-12-17 12:45:04 -07:00
|
|
|
void GParted_Core::get_devices( std::vector<Device> & devices )
|
2004-11-17 06:00:25 -07:00
|
|
|
{
|
|
|
|
devices .clear( ) ;
|
2004-11-27 16:31:19 -07:00
|
|
|
|
2004-11-17 06:00:25 -07:00
|
|
|
//try to find all available devices and put these in a list
|
|
|
|
ped_device_probe_all( );
|
|
|
|
|
|
|
|
Device temp_device ;
|
|
|
|
std::vector <Glib::ustring> device_paths ;
|
|
|
|
|
2004-12-03 03:53:01 -07:00
|
|
|
device = ped_device_get_next( NULL );
|
2004-11-17 06:00:25 -07:00
|
|
|
|
|
|
|
//in certain cases (e.g. when there's a cd in the cdrom-drive) ped_device_probe_all will find a 'ghost' device that has no name or contains
|
|
|
|
//random garbage. Those 2 checks try to prevent such a ghostdevice from being initialized.. (tested over a 1000 times with and without cd)
|
2004-12-03 03:53:01 -07:00
|
|
|
while ( device && strlen( device ->path ) > 6 && ( (Glib::ustring) device ->path ) .is_ascii( ) )
|
2004-11-17 06:00:25 -07:00
|
|
|
{
|
|
|
|
if ( open_device( device ->path, device ) )
|
|
|
|
device_paths .push_back( get_sym_path( device ->path ) ) ;
|
2004-12-17 12:45:04 -07:00
|
|
|
|
2004-12-03 03:53:01 -07:00
|
|
|
device = ped_device_get_next( device ) ;
|
2004-11-17 06:00:25 -07:00
|
|
|
}
|
|
|
|
close_device_and_disk( device, disk ) ;
|
|
|
|
|
|
|
|
for ( unsigned int t = 0 ; t < device_paths .size( ) ; t++ )
|
|
|
|
{
|
2004-11-27 16:31:19 -07:00
|
|
|
if ( open_device_and_disk( device_paths[ t ], device, disk, false ) )
|
2004-11-17 06:00:25 -07:00
|
|
|
{
|
2004-11-19 04:55:38 -07:00
|
|
|
temp_device .Reset( ) ;
|
|
|
|
|
2004-11-27 16:31:19 -07:00
|
|
|
//device info..
|
2004-11-17 06:00:25 -07:00
|
|
|
temp_device .path = device_paths[ t ] ;
|
|
|
|
temp_device .realpath = device ->path ;
|
|
|
|
temp_device .model = device ->model ;
|
|
|
|
temp_device .heads = device ->bios_geom .heads ;
|
|
|
|
temp_device .sectors = device ->bios_geom .sectors ;
|
|
|
|
temp_device .cylinders = device ->bios_geom .cylinders ;
|
|
|
|
temp_device .length = temp_device .heads * temp_device .sectors * temp_device .cylinders ;
|
2004-12-27 05:08:01 -07:00
|
|
|
temp_device .cylsize = Sector_To_MB( temp_device .heads * temp_device .sectors ) ;
|
|
|
|
|
|
|
|
//make sure cylsize is at least 1 MB
|
|
|
|
if ( temp_device .cylsize < 1 )
|
|
|
|
temp_device .cylsize = 1 ;
|
2004-11-27 16:31:19 -07:00
|
|
|
|
2004-12-27 05:08:01 -07:00
|
|
|
//normal harddisk
|
2004-11-27 16:31:19 -07:00
|
|
|
if ( disk )
|
|
|
|
{
|
|
|
|
temp_device .disktype = disk ->type ->name ;
|
|
|
|
temp_device .max_prims = ped_disk_get_max_primary_partition_count( disk ) ;
|
2004-11-29 08:27:33 -07:00
|
|
|
|
2004-12-17 12:45:04 -07:00
|
|
|
set_device_partitions( temp_device ) ;
|
2004-12-17 08:56:03 -07:00
|
|
|
|
2004-12-27 11:56:57 -07:00
|
|
|
if ( temp_device .highest_busy )
|
2004-11-29 08:27:33 -07:00
|
|
|
{
|
|
|
|
temp_device .readonly = ! ped_disk_commit_to_os( disk ) ;
|
|
|
|
sleep( 1 ) ;//this sucks, but it seems that after the commit test, the paths are removed and added again (which takes time..)
|
|
|
|
}
|
2004-11-27 16:31:19 -07:00
|
|
|
}
|
|
|
|
//harddisk without disklabel
|
|
|
|
else
|
|
|
|
{
|
2004-11-28 05:09:04 -07:00
|
|
|
temp_device .disktype = _("unrecognized") ;
|
2004-11-27 16:31:19 -07:00
|
|
|
temp_device .max_prims = -1 ;
|
|
|
|
|
|
|
|
Partition partition_temp ;
|
|
|
|
partition_temp .Set_Unallocated( 0, temp_device .length, false );
|
|
|
|
temp_device .device_partitions .push_back( partition_temp );
|
|
|
|
}
|
|
|
|
|
2004-11-17 06:00:25 -07:00
|
|
|
devices .push_back( temp_device ) ;
|
|
|
|
|
|
|
|
close_device_and_disk( device, disk ) ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-12-17 12:45:04 -07:00
|
|
|
void GParted_Core::set_device_partitions( Device & device )
|
2004-11-17 06:00:25 -07:00
|
|
|
{
|
|
|
|
int EXT_INDEX = -1 ;
|
|
|
|
|
|
|
|
//clear partitions
|
2004-11-19 04:55:38 -07:00
|
|
|
device .device_partitions .clear( ) ;
|
2004-11-17 06:00:25 -07:00
|
|
|
|
|
|
|
c_partition = ped_disk_next_partition( disk, NULL ) ;
|
|
|
|
while ( c_partition )
|
|
|
|
{
|
|
|
|
partition_temp .Reset( ) ;
|
|
|
|
|
|
|
|
switch ( c_partition ->type )
|
|
|
|
{
|
|
|
|
case PED_PARTITION_NORMAL:
|
|
|
|
case PED_PARTITION_LOGICAL:
|
|
|
|
if ( c_partition ->fs_type )
|
|
|
|
temp = c_partition ->fs_type ->name ;
|
|
|
|
else
|
|
|
|
{
|
2004-11-24 08:05:36 -07:00
|
|
|
temp = _("unknown") ;
|
2004-11-21 14:49:38 -07:00
|
|
|
partition_temp .error = _( "Unable to detect filesystem! Possible reasons are:" ) ;
|
|
|
|
partition_temp .error += "\n-";
|
|
|
|
partition_temp .error += _( "The filesystem is damaged" ) ;
|
|
|
|
partition_temp .error += "\n-" ;
|
|
|
|
partition_temp .error += _( "The filesystem is unknown to libparted" ) ;
|
|
|
|
partition_temp .error += "\n-";
|
|
|
|
partition_temp .error += _( "There is no filesystem available (unformatted)" ) ;
|
2004-11-17 06:00:25 -07:00
|
|
|
|
|
|
|
}
|
2004-12-13 04:17:40 -07:00
|
|
|
partition_temp .Set( device .path + num_to_str( c_partition ->num ),
|
2004-11-17 06:00:25 -07:00
|
|
|
c_partition ->num,
|
|
|
|
c_partition ->type == 0 ? GParted::PRIMARY : GParted::LOGICAL ,
|
|
|
|
temp, c_partition ->geom .start,
|
|
|
|
c_partition ->geom .end,
|
|
|
|
c_partition ->type,
|
|
|
|
ped_partition_is_busy( c_partition ) );
|
|
|
|
|
2004-12-17 12:45:04 -07:00
|
|
|
if ( partition_temp .filesystem != "linux-swap" )
|
2004-11-21 14:49:38 -07:00
|
|
|
{
|
|
|
|
Set_Used_Sectors( partition_temp ) ;
|
|
|
|
|
2004-12-12 07:57:04 -07:00
|
|
|
//the 'Unknown' filesystem warning overrules this one
|
2004-11-21 14:49:38 -07:00
|
|
|
if ( partition_temp .sectors_used == -1 && partition_temp .error .empty( ) )
|
|
|
|
{
|
|
|
|
partition_temp .error = _("Unable to read the contents of this filesystem!") ;
|
2004-12-15 03:33:12 -07:00
|
|
|
partition_temp .error += "\n" ;
|
|
|
|
partition_temp .error += _("Because of this some operations may be unavailable.") ;
|
2004-11-21 14:49:38 -07:00
|
|
|
}
|
|
|
|
}
|
2004-11-17 06:00:25 -07:00
|
|
|
|
|
|
|
partition_temp .flags = Get_Flags( c_partition ) ;
|
2004-11-21 14:49:38 -07:00
|
|
|
|
2004-12-27 11:56:57 -07:00
|
|
|
if ( partition_temp .busy && partition_temp .partition_number > device .highest_busy )
|
|
|
|
device .highest_busy = partition_temp .partition_number ;
|
|
|
|
|
2004-11-17 06:00:25 -07:00
|
|
|
break ;
|
|
|
|
|
|
|
|
case PED_PARTITION_EXTENDED:
|
2004-12-13 04:17:40 -07:00
|
|
|
partition_temp.Set( device .path + num_to_str( c_partition ->num ),
|
2004-11-17 06:00:25 -07:00
|
|
|
c_partition ->num ,
|
|
|
|
GParted::EXTENDED ,
|
|
|
|
"extended" ,
|
|
|
|
c_partition ->geom .start ,
|
|
|
|
c_partition ->geom .end ,
|
|
|
|
false ,
|
|
|
|
ped_partition_is_busy( c_partition ) );
|
|
|
|
|
|
|
|
partition_temp .flags = Get_Flags( c_partition ) ;
|
2004-11-19 04:55:38 -07:00
|
|
|
EXT_INDEX = device .device_partitions .size ( ) ;
|
2004-11-17 06:00:25 -07:00
|
|
|
break ;
|
|
|
|
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
|
2004-12-12 13:36:00 -07:00
|
|
|
//if there's an end, there's a partition ;)
|
|
|
|
if ( partition_temp .sector_end > -1 )
|
2004-11-17 06:00:25 -07:00
|
|
|
{
|
|
|
|
if ( ! partition_temp .inside_extended )
|
2004-11-19 04:55:38 -07:00
|
|
|
device .device_partitions .push_back( partition_temp );
|
2004-11-17 06:00:25 -07:00
|
|
|
else
|
2004-11-19 04:55:38 -07:00
|
|
|
device .device_partitions[ EXT_INDEX ] .logicals .push_back( partition_temp ) ;
|
2004-11-17 06:00:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//next partition (if any)
|
|
|
|
c_partition = ped_disk_next_partition ( disk, c_partition ) ;
|
|
|
|
}
|
2004-12-12 13:36:00 -07:00
|
|
|
|
|
|
|
if ( EXT_INDEX > -1 )
|
|
|
|
Insert_Unallocated( device .device_partitions[ EXT_INDEX ] .logicals, device .device_partitions[ EXT_INDEX ] .sector_start, device .device_partitions[ EXT_INDEX ] .sector_end, true ) ;
|
|
|
|
|
|
|
|
Insert_Unallocated( device .device_partitions, 0, device .length -1, false ) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GParted_Core::Insert_Unallocated( std::vector<Partition> & partitions, Sector start, Sector end, bool inside_extended )
|
|
|
|
{
|
2004-12-13 04:17:40 -07:00
|
|
|
partition_temp .Reset( ) ;
|
|
|
|
partition_temp .Set_Unallocated( 0, 0, inside_extended ) ;
|
2004-12-12 13:36:00 -07:00
|
|
|
|
|
|
|
//if there are no partitions at all..
|
|
|
|
if ( partitions .empty( ) )
|
|
|
|
{
|
2004-12-13 04:17:40 -07:00
|
|
|
partition_temp .sector_start = start ;
|
|
|
|
partition_temp .sector_end = end ;
|
2004-12-12 13:36:00 -07:00
|
|
|
|
2004-12-13 04:17:40 -07:00
|
|
|
partitions .push_back( partition_temp );
|
2004-12-12 13:36:00 -07:00
|
|
|
|
|
|
|
return ;
|
|
|
|
}
|
|
|
|
|
|
|
|
//start <---> first partition start
|
|
|
|
if ( (partitions .front( ) .sector_start - start) >= MEGABYTE )
|
|
|
|
{
|
2004-12-13 04:17:40 -07:00
|
|
|
partition_temp .sector_start = start ;
|
|
|
|
partition_temp .sector_end = partitions .front( ) .sector_start -1 ;
|
2004-12-12 13:36:00 -07:00
|
|
|
|
2004-12-13 04:17:40 -07:00
|
|
|
partitions .insert( partitions .begin( ), partition_temp );
|
2004-12-12 13:36:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//look for gaps in between
|
|
|
|
for ( unsigned int t =0 ; t < partitions .size( ) -1 ; t++ )
|
|
|
|
if ( ( partitions[ t +1 ] .sector_start - partitions[ t ] .sector_end ) >= MEGABYTE )
|
|
|
|
{
|
2004-12-13 04:17:40 -07:00
|
|
|
partition_temp .sector_start = partitions[ t ] .sector_end +1 ;
|
|
|
|
partition_temp .sector_end = partitions[ t +1 ] .sector_start -1 ;
|
2004-12-12 13:36:00 -07:00
|
|
|
|
2004-12-13 04:17:40 -07:00
|
|
|
partitions .insert( partitions .begin( ) + ++t, partition_temp );
|
2004-12-12 13:36:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//last partition end <---> end
|
|
|
|
if ( (end - partitions .back( ) .sector_end ) >= MEGABYTE )
|
|
|
|
{
|
2004-12-13 04:17:40 -07:00
|
|
|
partition_temp .sector_start = partitions .back( ) .sector_end +1 ;
|
|
|
|
partition_temp .sector_end = end ;
|
2004-12-12 13:36:00 -07:00
|
|
|
|
2004-12-13 04:17:40 -07:00
|
|
|
partitions .push_back( partition_temp );
|
2004-12-12 13:36:00 -07:00
|
|
|
}
|
2004-11-17 06:00:25 -07:00
|
|
|
}
|
|
|
|
|
2004-11-21 14:49:38 -07:00
|
|
|
int GParted_Core::get_estimated_time( const Operation & operation )
|
2004-11-17 06:00:25 -07:00
|
|
|
{
|
|
|
|
switch ( operation .operationtype )
|
|
|
|
{
|
|
|
|
case GParted::DELETE:
|
|
|
|
return 2 ; //i guess it'll never take more then 2 secs to delete a partition ;)
|
|
|
|
|
|
|
|
case GParted::CREATE:
|
|
|
|
case GParted::CONVERT:
|
|
|
|
set_proper_filesystem( operation .partition_new .filesystem ) ;
|
|
|
|
if ( p_filesystem )
|
|
|
|
return p_filesystem ->get_estimated_time( operation .partition_new .Get_Length_MB( ) ) ;
|
|
|
|
|
|
|
|
break ;
|
|
|
|
|
|
|
|
case GParted::RESIZE_MOVE:
|
|
|
|
set_proper_filesystem( operation .partition_new .filesystem ) ;
|
|
|
|
if ( p_filesystem )
|
|
|
|
return p_filesystem ->get_estimated_time( Abs( operation .partition_original .Get_Length_MB( ) - operation .partition_new .Get_Length_MB( ) ) ) ;
|
|
|
|
|
|
|
|
break ;
|
|
|
|
|
|
|
|
case GParted::COPY:
|
|
|
|
//lets take 10MB/s for the moment..
|
|
|
|
return operation .partition_new .Get_Length_MB( ) / 10 ;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1 ; //pulsing
|
|
|
|
}
|
|
|
|
|
|
|
|
void GParted_Core::Apply_Operation_To_Disk( Operation & operation )
|
|
|
|
{
|
|
|
|
switch ( operation .operationtype )
|
|
|
|
{
|
|
|
|
case DELETE:
|
2004-12-27 05:08:01 -07:00
|
|
|
if ( ! Delete( operation .device .path, operation .partition_original ) )
|
2004-11-17 06:00:25 -07:00
|
|
|
Show_Error( String::ucompose( _("Error while deleting %1"), operation .partition_original .partition ) ) ;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case CREATE:
|
2004-12-27 05:08:01 -07:00
|
|
|
if ( ! Create( operation .device, operation .partition_new ) )
|
2004-11-17 06:00:25 -07:00
|
|
|
Show_Error( String::ucompose( _("Error while creating %1"), operation .partition_new .partition ) );
|
|
|
|
|
|
|
|
break;
|
|
|
|
case RESIZE_MOVE:
|
2004-12-27 05:08:01 -07:00
|
|
|
if ( ! Resize( operation .device, operation .partition_original, operation .partition_new ) )
|
2004-11-17 06:00:25 -07:00
|
|
|
Show_Error( String::ucompose( _("Error while resizing/moving %1"), operation .partition_new .partition ) ) ;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case CONVERT:
|
2004-12-27 05:08:01 -07:00
|
|
|
if ( ! Convert_FS( operation .device .path, operation .partition_new ) )
|
2004-11-17 06:00:25 -07:00
|
|
|
Show_Error( String::ucompose( _("Error while converting filesystem of %1"), operation .partition_new .partition ) ) ;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case COPY:
|
2004-12-27 05:08:01 -07:00
|
|
|
if ( ! Copy( operation .device .path, operation .copied_partition_path, operation .partition_new ) )
|
2004-11-17 06:00:25 -07:00
|
|
|
Show_Error( String::ucompose( _("Error while copying %1"), operation .partition_new .partition ) ) ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-12-27 05:08:01 -07:00
|
|
|
bool GParted_Core::Create( const Device & device, Partition & new_partition )
|
2004-11-17 06:00:25 -07:00
|
|
|
{
|
|
|
|
if ( new_partition .type == GParted::EXTENDED )
|
2004-12-27 05:08:01 -07:00
|
|
|
return Create_Empty_Partition( device .path, new_partition ) ;
|
2004-11-17 06:00:25 -07:00
|
|
|
|
2004-12-27 05:08:01 -07:00
|
|
|
else if ( Create_Empty_Partition( device .path, new_partition, ( new_partition .Get_Length_MB( ) - device .cylsize ) < get_fs( new_partition .filesystem ) .MIN ) > 0 )
|
2004-11-17 06:00:25 -07:00
|
|
|
{
|
|
|
|
set_proper_filesystem( new_partition .filesystem ) ;
|
|
|
|
|
2004-11-28 07:30:15 -07:00
|
|
|
//most likely this means the user created an unformatted partition, however in theory, it could also screw some errorhandling.
|
|
|
|
if ( ! p_filesystem )
|
|
|
|
return true ;
|
|
|
|
|
2004-12-28 06:29:01 -07:00
|
|
|
return p_filesystem ->Create( new_partition ) ;
|
2004-11-17 06:00:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return false ;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool GParted_Core::Convert_FS( const Glib::ustring & device_path, const Partition & partition )
|
2004-11-25 12:21:42 -07:00
|
|
|
{
|
|
|
|
//remove all filesystem signatures...
|
|
|
|
if ( open_device_and_disk( device_path, device, disk ) )
|
|
|
|
{
|
|
|
|
c_partition = ped_disk_get_partition_by_sector( disk, (partition .sector_end + partition .sector_start) / 2 ) ;
|
2004-11-17 06:00:25 -07:00
|
|
|
|
2004-11-25 12:21:42 -07:00
|
|
|
if ( c_partition )
|
|
|
|
ped_file_system_clobber ( & c_partition ->geom ) ;
|
|
|
|
|
|
|
|
close_device_and_disk( device, disk ) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
set_proper_filesystem( partition .filesystem ) ;
|
|
|
|
|
2004-12-28 06:29:01 -07:00
|
|
|
return p_filesystem ->Create( partition ) ;
|
2004-11-17 06:00:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
bool GParted_Core::Delete( const Glib::ustring & device_path, const Partition & partition )
|
|
|
|
{
|
|
|
|
bool return_value = false ;
|
|
|
|
|
|
|
|
if ( open_device_and_disk( device_path, device, disk ) )
|
|
|
|
{
|
|
|
|
if ( partition .type == GParted::EXTENDED )
|
|
|
|
c_partition = ped_disk_extended_partition( disk ) ;
|
|
|
|
else
|
|
|
|
c_partition = ped_disk_get_partition_by_sector( disk, (partition .sector_end + partition .sector_start) / 2 ) ;
|
|
|
|
|
|
|
|
return_value = ( ped_disk_delete_partition( disk, c_partition ) && Commit( disk ) ) ;
|
|
|
|
close_device_and_disk( device, disk ) ;
|
2004-11-24 03:32:56 -07:00
|
|
|
|
|
|
|
sleep( 1 ) ;//paranoia give the OS some time to update nodes in /dev
|
2004-11-17 06:00:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return return_value ;
|
|
|
|
}
|
|
|
|
|
2004-12-27 05:08:01 -07:00
|
|
|
bool GParted_Core::Resize( const Device & device, const Partition & partition_old, const Partition & partition_new )
|
2004-11-17 06:00:25 -07:00
|
|
|
{
|
|
|
|
if ( partition_old .type == GParted::EXTENDED )
|
2004-12-27 05:08:01 -07:00
|
|
|
return Resize_Container_Partition( device .path, partition_old, partition_new, false ) ;
|
2004-11-21 14:49:38 -07:00
|
|
|
|
2004-12-28 05:59:46 -07:00
|
|
|
//these 2 still use libparted's resizer.
|
|
|
|
else if ( partition_old .filesystem == "fat16" || partition_old .filesystem == "fat32" )
|
2004-12-27 05:08:01 -07:00
|
|
|
return Resize_Normal_Using_Libparted( device .path, partition_old, partition_new ) ;
|
2004-11-21 14:49:38 -07:00
|
|
|
|
2004-12-28 05:59:46 -07:00
|
|
|
//use custom resize tools..
|
2004-11-17 06:00:25 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
set_proper_filesystem( partition_new .filesystem ) ;
|
2004-11-21 14:49:38 -07:00
|
|
|
|
|
|
|
if ( p_filesystem ->Check_Repair( partition_new ) )
|
|
|
|
{
|
|
|
|
//shrinking
|
2004-12-28 05:59:46 -07:00
|
|
|
if ( partition_new .Get_Length_MB( ) < partition_old .Get_Length_MB( ) )
|
2004-11-21 14:49:38 -07:00
|
|
|
{
|
2004-12-27 05:08:01 -07:00
|
|
|
p_filesystem ->cylinder_size = device .cylsize ;
|
2004-11-21 14:49:38 -07:00
|
|
|
|
|
|
|
if ( p_filesystem ->Resize( partition_new ) )
|
2004-12-28 05:59:46 -07:00
|
|
|
Resize_Container_Partition( device .path, partition_old, partition_new, ! get_fs( partition_new .filesystem ) .move ) ;
|
2004-11-21 14:49:38 -07:00
|
|
|
}
|
2004-12-28 05:59:46 -07:00
|
|
|
//growing/moving
|
|
|
|
else
|
|
|
|
Resize_Container_Partition( device .path, partition_old, partition_new, ! get_fs( partition_new .filesystem ) .move ) ;
|
2004-11-21 14:49:38 -07:00
|
|
|
|
|
|
|
|
|
|
|
p_filesystem ->Check_Repair( partition_new ) ;
|
|
|
|
|
|
|
|
p_filesystem ->Resize( partition_new, true ) ; //expand filesystem to fit exactly in partition
|
|
|
|
|
|
|
|
return p_filesystem ->Check_Repair( partition_new ) ;
|
|
|
|
}
|
2004-11-17 06:00:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return false ;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool GParted_Core::Copy( const Glib::ustring & dest_device_path, const Glib::ustring & src_part_path, Partition & partition_dest )
|
|
|
|
{
|
2004-12-20 12:09:48 -07:00
|
|
|
set_proper_filesystem( partition_dest .filesystem ) ;
|
|
|
|
|
|
|
|
Partition src_partition ;
|
|
|
|
src_partition .partition = src_part_path ;
|
|
|
|
|
|
|
|
if ( p_filesystem ->Check_Repair( src_partition ) )
|
|
|
|
if ( Create_Empty_Partition( dest_device_path, partition_dest, true ) > 0 )
|
|
|
|
return p_filesystem ->Copy( src_part_path, partition_dest .partition ) ;
|
2004-11-17 06:00:25 -07:00
|
|
|
|
|
|
|
return false ;
|
|
|
|
}
|
|
|
|
|
2004-11-27 16:31:19 -07:00
|
|
|
bool GParted_Core::Set_Disklabel( const Glib::ustring & device_path, const Glib::ustring & disklabel )
|
|
|
|
{
|
|
|
|
bool return_value = false ;
|
|
|
|
|
|
|
|
if ( open_device_and_disk( device_path, device, disk, false ) )
|
|
|
|
{
|
|
|
|
PedDiskType *type = NULL ;
|
|
|
|
type = ped_disk_type_get( disklabel .c_str( ) ) ;
|
|
|
|
|
|
|
|
if ( type )
|
|
|
|
{
|
|
|
|
disk = ped_disk_new_fresh ( device, type);
|
|
|
|
|
|
|
|
return_value = Commit( disk ) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
close_device_and_disk( device, disk ) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
return return_value ;
|
|
|
|
}
|
|
|
|
|
2004-12-25 14:40:18 -07:00
|
|
|
const std::vector<FS> & GParted_Core::get_filesystems( ) const
|
2004-11-17 06:00:25 -07:00
|
|
|
{
|
|
|
|
return FILESYSTEMS ;
|
|
|
|
}
|
|
|
|
|
2004-12-25 14:40:18 -07:00
|
|
|
const FS & GParted_Core::get_fs( const Glib::ustring & filesystem ) const
|
|
|
|
{
|
|
|
|
for ( unsigned int t = 0 ; t < FILESYSTEMS .size( ) ; t++ )
|
|
|
|
if ( FILESYSTEMS[ t ] .filesystem == filesystem )
|
|
|
|
return FILESYSTEMS[ t ] ;
|
|
|
|
|
|
|
|
return FILESYSTEMS .back( ) ;
|
|
|
|
}
|
|
|
|
|
2004-11-17 06:00:25 -07:00
|
|
|
Glib::RefPtr<Gtk::TextBuffer> GParted_Core::get_textbuffer( )
|
|
|
|
{
|
|
|
|
return textbuffer ;
|
|
|
|
}
|
|
|
|
|
|
|
|
Glib::ustring GParted_Core::get_sym_path( const Glib::ustring & real_path )
|
|
|
|
{
|
|
|
|
int major, minor, size;
|
|
|
|
char temp[4096], device_name[4096], short_path[4096] ;
|
|
|
|
|
|
|
|
FILE* proc_part_file = fopen ( "/proc/partitions", "r" );
|
|
|
|
if ( ! proc_part_file )
|
|
|
|
return real_path;
|
|
|
|
|
|
|
|
//skip first 2 useless rules of /proc/partitions
|
|
|
|
fgets( temp, 256, proc_part_file ); fgets( temp, 256, proc_part_file );
|
|
|
|
|
|
|
|
while ( fgets( temp, 4096, proc_part_file ) && sscanf(temp, "%d %d %d %255s", &major, &minor, &size, device_name ) == 4 )
|
|
|
|
{
|
|
|
|
strcpy( short_path, "/dev/" ); strcat( short_path, device_name );
|
|
|
|
realpath( short_path, device_name );
|
|
|
|
|
|
|
|
if ( real_path == device_name ) {
|
|
|
|
fclose ( proc_part_file );
|
|
|
|
return ( Glib::ustring( short_path ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//paranoia modus :)
|
|
|
|
fclose ( proc_part_file );
|
|
|
|
return real_path;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-11-21 14:49:38 -07:00
|
|
|
void GParted_Core::Set_Used_Sectors( Partition & partition )
|
2004-11-17 06:00:25 -07:00
|
|
|
{
|
2004-12-25 14:40:18 -07:00
|
|
|
//because 'unknown' is translated we need to call get_fs instead of using partition .filesystem directly
|
|
|
|
if ( get_fs( partition .filesystem ) .filesystem == "unknown" )
|
2004-11-21 14:49:38 -07:00
|
|
|
partition .Set_Unused( -1 ) ;
|
|
|
|
|
|
|
|
else if ( partition .busy )
|
2004-11-17 06:00:25 -07:00
|
|
|
{
|
2004-11-21 14:49:38 -07:00
|
|
|
system( ("df -k --sync " + partition .partition + " | grep " + partition .partition + " > /tmp/.tmp_gparted") .c_str( ) );
|
2004-11-17 06:00:25 -07:00
|
|
|
std::ifstream file_input( "/tmp/.tmp_gparted" );
|
|
|
|
|
2004-11-21 14:49:38 -07:00
|
|
|
//we need the 4th value
|
|
|
|
file_input >> temp; file_input >> temp; file_input >> temp;file_input >> temp;
|
|
|
|
if ( ! temp .empty( ) )
|
|
|
|
partition .Set_Unused( atoi( temp .c_str( ) ) * 1024/512 ) ;
|
|
|
|
|
|
|
|
file_input .close( );
|
|
|
|
system( "rm -f /tmp/.tmp_gparted" );
|
2004-11-17 06:00:25 -07:00
|
|
|
}
|
|
|
|
|
2004-12-25 14:40:18 -07:00
|
|
|
else if ( get_fs( partition .filesystem ) .read )
|
2004-11-21 14:49:38 -07:00
|
|
|
{
|
|
|
|
set_proper_filesystem( partition .filesystem ) ;
|
|
|
|
|
|
|
|
p_filesystem ->disk = disk ;
|
|
|
|
p_filesystem ->Set_Used_Sectors( partition ) ;
|
|
|
|
}
|
2004-11-17 06:00:25 -07:00
|
|
|
}
|
|
|
|
|
2004-11-19 04:55:38 -07:00
|
|
|
int GParted_Core::Create_Empty_Partition( const Glib::ustring & device_path, Partition & new_partition, bool copy )
|
2004-11-17 06:00:25 -07:00
|
|
|
{
|
|
|
|
new_partition .partition_number = 0 ;
|
2004-11-19 04:55:38 -07:00
|
|
|
|
2004-11-17 06:00:25 -07:00
|
|
|
if ( open_device_and_disk( device_path, device, disk ) )
|
|
|
|
{
|
|
|
|
PedPartitionType type;
|
|
|
|
PedPartition *c_part = NULL ;
|
|
|
|
PedConstraint *constraint = NULL ;
|
|
|
|
|
|
|
|
//create new partition
|
|
|
|
switch ( new_partition .type )
|
|
|
|
{
|
|
|
|
case 0 : type = PED_PARTITION_NORMAL; break ;
|
|
|
|
case 1 : type = PED_PARTITION_LOGICAL; break ;
|
|
|
|
case 2 : type = PED_PARTITION_EXTENDED; break ;
|
|
|
|
default : type = PED_PARTITION_FREESPACE; break ; //will never happen ;)
|
|
|
|
}
|
|
|
|
|
|
|
|
c_part = ped_partition_new ( disk, type, NULL, new_partition .sector_start, new_partition .sector_end ) ;
|
|
|
|
if ( c_part )
|
|
|
|
{
|
2004-12-28 05:59:46 -07:00
|
|
|
constraint = ped_constraint_any( device );
|
2004-11-19 04:55:38 -07:00
|
|
|
|
2004-11-17 06:00:25 -07:00
|
|
|
if ( constraint )
|
|
|
|
{
|
2004-11-19 04:55:38 -07:00
|
|
|
if ( copy )
|
|
|
|
constraint ->min_size = new_partition .sector_end - new_partition .sector_start ;
|
|
|
|
|
2004-11-17 06:00:25 -07:00
|
|
|
if ( ped_disk_add_partition ( disk, c_part, constraint ) && Commit( disk ) )
|
|
|
|
{
|
2004-11-25 12:21:42 -07:00
|
|
|
//remove all filesystem signatures...
|
|
|
|
ped_file_system_clobber ( & c_part ->geom ) ;
|
|
|
|
|
2004-11-17 06:00:25 -07:00
|
|
|
sleep( 1 ) ;//the OS needs some time to create the devicenode in /dev
|
2004-11-19 04:55:38 -07:00
|
|
|
|
2004-11-17 06:00:25 -07:00
|
|
|
new_partition .partition = ped_partition_get_path( c_part ) ;
|
|
|
|
new_partition .partition_number = c_part ->num ;
|
|
|
|
}
|
|
|
|
|
|
|
|
ped_constraint_destroy ( constraint );
|
|
|
|
}
|
2004-11-19 04:55:38 -07:00
|
|
|
|
2004-11-17 06:00:25 -07:00
|
|
|
}
|
2004-11-19 04:55:38 -07:00
|
|
|
|
2004-11-17 06:00:25 -07:00
|
|
|
close_device_and_disk( device, disk ) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
return new_partition .partition_number ;
|
|
|
|
}
|
|
|
|
|
2004-11-24 03:32:56 -07:00
|
|
|
bool GParted_Core::Resize_Container_Partition( const Glib::ustring & device_path, const Partition & partition_old, const Partition & partition_new, bool fixed_start )
|
2004-11-17 06:00:25 -07:00
|
|
|
{
|
|
|
|
bool return_value = false ;
|
|
|
|
|
2004-11-21 14:49:38 -07:00
|
|
|
PedConstraint *constraint = NULL ;
|
|
|
|
c_partition = NULL ;
|
|
|
|
|
2004-11-17 06:00:25 -07:00
|
|
|
if ( open_device_and_disk( device_path, device, disk ) )
|
|
|
|
{
|
2004-11-21 14:49:38 -07:00
|
|
|
if ( partition_old .type == GParted::EXTENDED )
|
|
|
|
c_partition = ped_disk_extended_partition( disk ) ;
|
|
|
|
else
|
|
|
|
c_partition = ped_disk_get_partition_by_sector( disk, (partition_old .sector_end + partition_old .sector_start) / 2 ) ;
|
2004-11-17 06:00:25 -07:00
|
|
|
|
2004-11-21 14:49:38 -07:00
|
|
|
if ( c_partition )
|
2004-11-17 06:00:25 -07:00
|
|
|
{
|
2004-11-21 14:49:38 -07:00
|
|
|
constraint = ped_constraint_any( device );
|
2004-11-24 03:32:56 -07:00
|
|
|
|
|
|
|
if ( fixed_start && constraint ) //create a constraint which keeps de startpoint intact and rounds the end to a cylinderboundary
|
|
|
|
{
|
|
|
|
ped_disk_set_partition_geom ( disk, c_partition, constraint, partition_new .sector_start, partition_new .sector_end ) ;
|
|
|
|
ped_constraint_destroy ( constraint );
|
|
|
|
constraint = NULL ;
|
|
|
|
|
|
|
|
ped_geometry_set_start ( & c_partition ->geom, partition_new .sector_start ) ;
|
|
|
|
constraint = ped_constraint_exact ( & c_partition ->geom ) ;
|
|
|
|
}
|
|
|
|
|
2004-11-17 06:00:25 -07:00
|
|
|
if ( constraint )
|
|
|
|
{
|
2004-11-22 08:59:40 -07:00
|
|
|
if ( ped_disk_set_partition_geom ( disk, c_partition, constraint, partition_new .sector_start, partition_new .sector_end ) )
|
2004-11-17 06:00:25 -07:00
|
|
|
return_value = Commit( disk ) ;
|
2004-11-21 14:49:38 -07:00
|
|
|
|
|
|
|
ped_constraint_destroy ( constraint );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
close_device_and_disk( device, disk ) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
sleep( 1 ) ; //the OS needs time to re-add the devicenode..
|
|
|
|
|
|
|
|
return return_value ;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool GParted_Core::Resize_Normal_Using_Libparted( const Glib::ustring & device_path, const Partition & partition_old, const Partition & partition_new )
|
|
|
|
{
|
|
|
|
bool return_value = false ;
|
|
|
|
|
|
|
|
PedFileSystem *fs = NULL ;
|
|
|
|
PedConstraint *constraint = NULL ;
|
|
|
|
c_partition = NULL ;
|
|
|
|
|
|
|
|
if ( open_device_and_disk( device_path, device, disk ) )
|
|
|
|
{
|
|
|
|
c_partition = ped_disk_get_partition_by_sector( disk, (partition_old .sector_end + partition_old .sector_start) / 2 ) ;
|
|
|
|
if ( c_partition )
|
|
|
|
{
|
|
|
|
fs = ped_file_system_open ( & c_partition ->geom );
|
|
|
|
if ( fs )
|
|
|
|
{
|
|
|
|
constraint = ped_file_system_get_resize_constraint ( fs );
|
|
|
|
if ( constraint )
|
|
|
|
{
|
|
|
|
if ( ped_disk_set_partition_geom ( disk, c_partition, constraint, partition_new .sector_start, partition_new .sector_end ) &&
|
|
|
|
ped_file_system_resize ( fs, & c_partition ->geom, NULL )
|
|
|
|
)
|
|
|
|
return_value = Commit( disk ) ;
|
|
|
|
|
|
|
|
ped_constraint_destroy ( constraint );
|
|
|
|
}
|
|
|
|
|
|
|
|
ped_file_system_close ( fs );
|
2004-11-17 06:00:25 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
close_device_and_disk( device, disk ) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
return return_value ;
|
|
|
|
}
|
|
|
|
|
|
|
|
Glib::ustring GParted_Core::Get_Flags( PedPartition *c_partition )
|
|
|
|
{
|
|
|
|
temp = "";
|
|
|
|
|
|
|
|
for ( unsigned short t = 0; t < flags .size( ) ; t++ )
|
|
|
|
if ( ped_partition_get_flag ( c_partition, flags[ t ] ) )
|
|
|
|
temp += (Glib::ustring) ped_partition_flag_get_name ( flags[ t ] ) + " ";
|
|
|
|
|
|
|
|
return temp ;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GParted_Core::Show_Error( Glib::ustring message )
|
|
|
|
{
|
|
|
|
message = "<span weight=\"bold\" size=\"larger\">" + message + "</span>\n\n" ;
|
|
|
|
message += _( "Be aware that the failure to apply this operation could affect other operations on the list." ) ;
|
|
|
|
Gtk::MessageDialog dialog( message ,true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true );
|
|
|
|
|
|
|
|
gdk_threads_enter( );
|
|
|
|
dialog .run( );
|
|
|
|
gdk_threads_leave( );
|
|
|
|
}
|
|
|
|
|
|
|
|
void GParted_Core::set_proper_filesystem( const Glib::ustring & filesystem )
|
|
|
|
{
|
|
|
|
//ugly, stupid, *aaargh* :-)
|
|
|
|
|
|
|
|
if ( ! p_filesystem )
|
|
|
|
delete p_filesystem ;
|
|
|
|
|
|
|
|
if ( filesystem == "ext2" )
|
|
|
|
p_filesystem = new ext2( ) ;
|
|
|
|
else if ( filesystem == "ext3" )
|
|
|
|
p_filesystem = new ext3( ) ;
|
|
|
|
else if ( filesystem == "fat16" )
|
|
|
|
p_filesystem = new fat16( ) ;
|
|
|
|
else if ( filesystem == "fat32" )
|
|
|
|
p_filesystem = new fat32( ) ;
|
2004-12-14 15:49:44 -07:00
|
|
|
else if ( filesystem == "hfs" )
|
|
|
|
p_filesystem = new hfs( ) ;
|
|
|
|
else if ( filesystem == "jfs" )
|
|
|
|
p_filesystem = new jfs( ) ;
|
2004-11-17 06:00:25 -07:00
|
|
|
else if ( filesystem == "linux-swap" )
|
|
|
|
p_filesystem = new linux_swap( ) ;
|
|
|
|
else if ( filesystem == "reiserfs" )
|
|
|
|
p_filesystem = new reiserfs( ) ;
|
2004-11-23 09:20:59 -07:00
|
|
|
else if ( filesystem == "ntfs" )
|
|
|
|
p_filesystem = new ntfs( ) ;
|
2004-12-13 14:24:12 -07:00
|
|
|
else if ( filesystem == "xfs" )
|
|
|
|
p_filesystem = new xfs( ) ;
|
2004-11-17 06:00:25 -07:00
|
|
|
else
|
|
|
|
p_filesystem = NULL ;
|
|
|
|
|
|
|
|
if ( p_filesystem )
|
|
|
|
p_filesystem ->textbuffer = textbuffer ;
|
|
|
|
}
|
|
|
|
|
|
|
|
} //GParted
|