home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2007 January, February, March & April
/
Chip-Cover-CD-2007-02.iso
/
boot
/
i386
/
root
/
usr
/
share
/
YaST2
/
clients
/
inst_custom_part.ycp
< prev
next >
Wrap
Text File
|
2006-11-29
|
106KB
|
3,573 lines
/*
*************************************************************
*
* YaST2 SuSE Labs -o)
* -------------------- /\\
* _\_v
* www.suse.de / www.suse.com
* ----------------------------------------------------------
*
* Author: Michael Hager <mike@suse.de>
*
* Description: Partitioner for experts.
*
*
* Purpose:
* -Determing possible partitions.
* -Ask the user which partition to use.
* -Check the input and return error-messages.
* -Writing user_settings with the selected partitions.
*
* user_settings: used: targets
*
* external function: get_partition_info: get a list of current partitions
* check4partitions: read the disk-information
*
*
*************************************************************
$Id: inst_custom_part.ycp 33991 2006-11-02 16:14:26Z fehr $
*/
{
textdomain "storage";
import "Arch";
/* FIXME import "Bootloader";*/
import "Installation";
import "Mode";
import "Wizard";
import "Storage";
import "FileSystems";
import "Partitions";
import "Package";
import "Label";
import "Popup";
import "String";
import "Storage";
import "StorageDevices";
import "ProductFeatures";
list hitlist = [];
boolean hiterror = false;
include "partitioning/partition_defines.ycp";
include "partitioning/loop.ycp";
include "partitioning/lvm_ui_dialogs.ycp";
include "partitioning/lvm_pv_lib.ycp";
include "partitioning/raid_lib.ycp";
include "partitioning/raid_ui.ycp";
include "partitioning/custom_part_lib.ycp";
include "partitioning/custom_part_dialogs.ycp";
include "partitioning/custom_part_check_generated.ycp";
include "partitioning/evms_lib.ycp";
// Which columns show the main window have
boolean showT_dev = true; // show /dev/hda1
boolean showT_id = false; // s390 show FD01
boolean showT_cyl = true; // show start and endcyl
boolean showT_size = true; // show size of partition
boolean showT_format = true; // show format flag
boolean showT_fs = true; // show filesystem
boolean showT_mount = true; // show mountpoint
boolean showT_mby = true; // show mount by
boolean showT_Used = true; // show using entity
boolean showT_Label = true; // show assigned label
boolean showT_udev_id = true; // show persistent id
boolean showT_udev_path = true; // show persistent path
// hide some details in the table by default
boolean show_T_details = Storage::GetExpertDetail();
boolean show_disk = true;
boolean edit_cylinder = true;
boolean bsd_label = false;
boolean button_resize = true; // Should the "Resize Partition"-Button be shown in main window
boolean button_create = true; // Should the "Create Partition"-Button be shown in main window
boolean button_delete = true; // Should the "Delete Partition"-Button be shown in main window
boolean button_edit = true; // Should the "Edit Partition"-Button be shown in main window
boolean button_reread = true; // Should the "Reread Partition"-Button be shown in Expert menu
boolean button_raid = true; // Should the "RAID" -Button be shown in main window
boolean button_loop = true; // Should the "LOOP" -Button be shown in main window
boolean button_lvm = true; // Should the "LVM" -Button be shown in main window
// Should the "EVMS" -Button be shown in main window
boolean button_evms = ProductFeatures::GetBooleanFeature ("partitioning", "evms_config");
boolean button_expert = true; // Should the "EXPERT"-Button be shown in main window
boolean button_delete_parttable = true; // Should the "Delete partition table and disk label"
// -Button be shown in Expert menu
boolean button_adapt_mp = false; // Should the "Adapt mount points from
// existing /etc/fstab" -Button be shown in Expert menu
if( button_evms && Mode::normal() &&
SCR::Read( .target.size, "/usr/share/YaST2/clients/inst_evms.ycp" )<=0 )
button_evms = false;
y2milestone( "EVMS:%1", button_evms );
boolean test_mode = Mode::test ();
string boot_mode = "fritz";
/* FIXME string boot_mode = Bootloader::getLoaderType ();*/
string focusline = "";
string last_sel_disk = "";
////////////////////////////////////////////////
// Testmode, should be commented in release
// test_mode = true;
// test_mode = false;
// Arch::architecture () = "ppc";
// Arch::architecture () = "axp";
////////////////////////////////////////////////
if( Arch::ppc () )
{
showT_cyl = false;
bsd_label = false;
}
if( Arch::s390 () )
{
showT_id = true;
button_resize = false;
button_loop = false;
}
if( Arch::alpha () )
{
bsd_label = (boot_mode == "aboot");
}
if( Arch::sparc () )
{
bsd_label = true;
}
if( Stage::initial () )
{
button_adapt_mp = true;
}
if( Mode::repair () )
{
button_adapt_mp = false;
}
y2debug( "ARCHIT %1", Arch::architecture () );
////////////////////////////////////////////////////////////////////////
// DEFINES //
////////////////////////////////////////////////////////////////////////
/*---------------------------------------------------------------------
* Check if the numer is in the format <number>
*
* Returns true or false
*----------------------------------------------------------------------
*/
define boolean IsNumber( string input )
``{
integer n = 0;
while (n < size(input))
{
string erg = filterchars(substring(input, n,1), "0123456789.");
if (size(erg) != 1)
{
return(false);
}
n = n + 1;
}
return(true);
};
/*---------------------------------------------------------------------
* Check if the number is in the format [+]<number>[kKmMgGtT][bBoO]
*
* Returns true or false
*----------------------------------------------------------------------
*/
define boolean IsCylNumber( string input )
``{
if( substring( input, 0, 1) == "+")
{
input = substring( input, 1);
}
if( !IsNumber(input))
{
// check whether the last char is in "gGtTkKmM" or "bBoO"
string last_char = substring( input, size(input)-1, 1);
if( last_char == "b" || last_char == "B" ||
last_char == "o" || last_char == "O" )
{
input = substring( input, 0, size(input)-1);
// check whether the last char is in "gGtTkKmM"
last_char = substring( input, size(input)-1, 1);
}
string erg = filterchars(last_char, "kKmMgGtT");
if( size(erg) != 1)
{
// the last isn't in "kKmMgGtT"
return( false );
}
else
{
// the last is in "kKmMgGtT" check whether the rest is a number
return( IsNumber( substring(input, 0, size(input)-1)));
}
}
else
{
return( true );
}
};
/*---------------------------------------------------------------------
* Parse the end_partition String
* Input:
* - start_cylinder,
* - end of partition in
* valid is [+]<number>[kKmMgGtT][bBoO]
* insert a valid string! consistency must be already checked
* - size of a cylinder in byte
*
* Returns (endcylinder -startcylinder +1) as integer
*----------------------------------------------------------------------
*/
define integer ToEndRegion( string start_cyl, string end_part,
integer cyl_size )
``{
boolean is_add = false;
string input = end_part;
if( substring( input, 0, 1) == "+")
{
input = substring( input, 1);
is_add = true;
}
if ( !IsNumber(input))
{
is_add = true; // 44k is the same as +44k
// take last char
string last_char = substring( input, size(input)-1, 1);
// accept also +4kb or 7GB
if( last_char == "b" || last_char == "B" ||
last_char == "o" || last_char == "O" )
{
input = substring( input, 0, size(input)-1);
last_char = substring( input, size(input)-1, 1);
}
//integer base = tointeger(substring( input, 0, size(input)-1 ));
float base = tofloat(substring( input, 0, size(input)-1 ));
if( last_char == "k" || last_char == "K" )
{
return( tointeger((base*1024.0)/tofloat(cyl_size) +1.0 ));
}
if( last_char == "m" || last_char == "M" )
{
return( tointeger((base*1048576.0)/tofloat(cyl_size) +1.0 ));
}
if( last_char == "g" || last_char == "G" )
{
return( tointeger((base*1073741824.0)/tofloat(cyl_size) +1.0 ));
}
if( last_char == "t" || last_char == "T" )
{
return( tointeger((base*1099511627776.0)/tofloat(cyl_size) +1.0 ));
}
y2error("Error in parsing end_cylinder" );
return( tointeger(base) );
}
else
{
if (is_add)
{
return( tointeger(tofloat(input)) );
}
else
{
return( tointeger(tofloat(input))-tointeger(start_cyl)+1 );
}
}
};
/*---------------------------------------------------------------------
* tests which Partition types on a disk can be created
* for Intel-I386!
*
* Input: map disk // (the map out of the targets map)
* string dev // /dev/hda
*
* Return value: [ <primary_poss>, <extended_poss>, <logical_poss> ]
* boolean primary_poss; // Is a primary partition possible
* boolean extended_poss; // Is a extended partition possible
* boolean logical_poss; // Is a logical partition possible
*----------------------------------------------------------------------
* DESCRIPTION
*
* primary_part_is_possible = false; // can I create a primary part ?
* extended_part_is_possible = false; // can I create a extended part ?
* logial_part_is_possible = false; // ...
*
*
* if (one of the partitions <disk>1 <disk>2 <disk>3 <disk>4
* is not used )
* {
* primary_part_is_possible = true;
* }
*
* if primary_part_is_possible && (no extended partition exists)
* {
* extended_part_is_possible = true;
* }
*
* if (extended partition already exists) && (extended partition has
* space left)
* && (not more than 15 logical parts already exist)
* {
* logial_part_is_possible = true;
* }
*
*
* At the same time is not possible, that both "logial_part_is_possible"
* and "extended_part_is_possible" are true
* so we have 6 possible situations
*
* to show this we use
* "P" for primary_part_is_possible
* "E" for extended_part_is_possible
* "L" for logial_part_is_possible
*
* "p" for primary_part_is_possible == false
* "e" for extended_part_is_possible == false
* "l" for logial_part_is_possible == false
*
*
* PE : I can create a primary or exended part.
* PL : Extended part. exist. I can create a primary or a logical
* Pel : only a priary is possible, when the extended part. has no space left
*
* pE : Not possible, if "E" is possible always "P" is possible too.
* pL : only a logical is possible, if together 4 primary and extended
* partitions are already created
* pel : no partitions are possible
*
*----------------------------------------------------------------------
*/
define list CheckCreatePossibilities( string dev, map disk )
``{
string type = substring(dev, 5, 2);
boolean extended_exists = false;
symbol no_logical_cause = `no_ext;
symbol no_primary_cause = `dev_full;
symbol no_extended_cause = `dev_full;
boolean primary_is_possible = false;
boolean extended_is_possible = false;
boolean logical_is_possible = false;
list<map> primary_list =
filter( map part, disk["partitions"]:[],
``( part["type"]:`unknown == `primary ));
list<map> extended_list =
filter( map part, disk["partitions"]:[],
``( part["type"]:`unknown == `extended));
list<map> logical_list =
filter( map part, disk["partitions"]:[],
``( part["type"]:`unknown == `logical));
if( (size(extended_list) + size(primary_list)) < disk["max_primary"]:4 )
{
primary_is_possible = true;
}
if( primary_is_possible && (size(extended_list) == 0) &&
Partitions::HasExtended( disk["label"]:"") )
{
extended_is_possible = true;
}
if( size(extended_list) > 0 )
{
no_extended_cause = `already;
extended_exists = true;
}
if( disk["max_primary"]:4 > 4 )
{
logical_is_possible = false;
extended_is_possible = false;
no_logical_cause = `impossible;
no_extended_cause = `impossible;
}
if( extended_exists )
{
no_logical_cause = `no_extsp;
// test if extended partition has space left == a slot exists
boolean slot_exist = false;
// Start-End of the extended partition
integer start_ext_cyl = extended_list[0,"region",0]:0;
integer end_ext_cyl = extended_list[0,"region",1]:1 + start_ext_cyl-1;
// logical_cyl_list = [ <start_cyl.firstLogPart> , <end_cyl.firstLogPart> , <start.nextLogPart> ,....., <end.lastLogPart>]
//
// example: input: hda5:region [255,100] hda6:region[355,100] hda7[455,100]
// is al list generatated: logical_cyl_list = [255,354,355,454,455,555]
//
list logical_cyl_list =
sort(flatten(maplist( map part, logical_list,
``([part["region",0]:0,
part["region",0]:0 + part["region",1]:1-1 ]))));
// Look for a slot in the list of cylinders
integer n = 0;
if (size(logical_cyl_list) == 0 )
{
// no logical partitions exist
slot_exist = true;
}
else
{
repeat
{
if( n == 0 )
{
// first
if( logical_cyl_list[0]:0 != start_ext_cyl )
slot_exist = true;
}
else if( n == (size(logical_cyl_list)/2))
{
// last
if( logical_cyl_list[size(logical_cyl_list)-1]:0 !=
end_ext_cyl )
slot_exist = true;
}
else
{
//check if between logical partition n-1 and n is a slot
if( (logical_cyl_list[2*n-1]:0 + 1) != (logical_cyl_list[2*n]:0 ))
slot_exist = true;
}
n = n+1;
} until ( n == ( (size(logical_cyl_list)/2 +1)) || slot_exist );
}
if( slot_exist)
{
no_logical_cause = `to_many;
y2debug( "Logical: %1 %2", type, logical_cyl_list);
if( type == "hd" ) // EIDE supports 63 partitions
{
if (size(logical_cyl_list)/2 < 59 ) logical_is_possible = true;
}
if( type == "sd" ) // SCSI supports 15 partitions
{
if (size(logical_cyl_list)/2 < 11 ) logical_is_possible = true;
}
else
{
logical_is_possible = true;
}
}
}
return( [primary_is_possible, extended_is_possible, logical_is_possible,
no_primary_cause, no_extended_cause, no_logical_cause ]);
};
/*---------------------------------------------------------------------
* Find bigest slot
* return [start, end] or nil
*---------------------------------------------------------------------
*/
define list GetSlot( string dev, map disk )
``{
string type = substring(dev, 5, 2);
list<map> global_list = filter( map part, disk["partitions"]:[],
``( part["type"]:`unknown != `logical ));
if( bsd_label )
{
global_list = filter( map part, global_list, ``( part["nr"]:0 != 3 ));
}
list global_cyl_list =
sort(flatten(maplist( map part, global_list,
``([part["region",0]:0,
part["region",0]:0 + part["region",1]:1-1 ]))));
// Look for a slot in the list of cylinders
integer n = 0;
integer start_cyl = 0;
integer end_cyl = disk["cyl_count"]:1 - 1;
integer sl_start = 0;
integer sl_end = 0;
integer curr_start = 0;
integer curr_end = 0;
boolean slot_exist = false;
y2milestone( "global_cyl_list %1", global_cyl_list );
if( size(global_cyl_list) == 0 )
{
// no partition exist
return( [start_cyl, end_cyl]);
}
else
{
repeat
{
if( n == 0 )
{
// first
curr_start = start_cyl-1;
curr_end = global_cyl_list[0]:0;
}
else if ( n == (size(global_cyl_list)/2))
{
// last
curr_start = global_cyl_list[size(global_cyl_list)-1]:0;
curr_end = end_cyl+1;
}
else
{
//check if between global partition n-1 and n is a slot
curr_start = global_cyl_list[2*n-1]:0;
curr_end = global_cyl_list[2*n]:0;
}
y2milestone( "n curr_start %1 curr_end %2", curr_start, curr_end );
if( curr_start+1 < curr_end )
{
slot_exist = true;
y2debug( "A Slot at: %1 %2", curr_start, curr_end );
if( (curr_end-curr_start-2) >= (sl_end - sl_start) )
{
sl_start = curr_start+1;
sl_end = curr_end-1;
}
}
y2debug("SLOT- %1 %2 %3 %4", slot_exist, curr_start, curr_end, n );
n = n+1;
} until ( n == ( (size(global_cyl_list)/2 +1)));
}
if( slot_exist)
{
return( [sl_start, sl_end] );
}
else
{
return(nil);
}
};
/*---------------------------------------------------------------------
* test primary and extended slot
* return [start, end] or nil
* Input: start_cyl of the tested slot, /dev/hda1, diskmap
* return [max-end_cyl] or "nil" if its no valid start_cyl
* todo: GetSlo TestSlot should be one function
*---------------------------------------------------------------------
*/
define integer TestSlot( integer slot_start_cyl, string dev, map disk,
boolean bsd_label )
``{
string type = substring(dev, 5, 2);
list<map> global_list = filter( map part, disk["partitions"]:[],
``( part["type"]:`unknown != `logical ));
if( bsd_label )
{
global_list = filter( map part, global_list, ``( part["nr"]:0 != 3 ) );
}
list global_cyl_list =
sort(flatten(maplist( map part, global_list,
``([part["region",0]:0,
part["region",0]:0 + part["region",1]:1-1 ]))));
// Look for a slot in the list of cylinders
integer n = 0;
integer start_cyl = 0;
integer end_cyl = disk["cyl_count"]:1 - 1;
integer sl_start = 0;
integer sl_end = 0;
integer curr_start = 0;
integer curr_end = 0;
boolean slot_exist = false;
if( size(global_cyl_list) == 0 )
{
y2debug( "Testing Slot : disk empty");
if( start_cyl <= slot_start_cyl && slot_start_cyl <= end_cyl )
return( end_cyl );
}
else
{
repeat
{
if( n == 0 )
{
// first
curr_start = start_cyl-1;
curr_end = global_cyl_list[0]:0;
}
else if ( n == (size(global_cyl_list)/2))
{
// last
curr_start = global_cyl_list[size(global_cyl_list)-1]:0;
curr_end = end_cyl+1;
}
else
{
//check if between global partition n-1 and n is a slot
curr_start = global_cyl_list[2*n-1]:0;
curr_end = global_cyl_list[2*n]:0;
}
y2debug( "Testing Slot %1 < x < %2", curr_start, curr_end );
if( curr_start < slot_start_cyl && slot_start_cyl < curr_end )
{
// If the slot was found ...
y2debug( "X Slot at: %1 %2 ", curr_start, curr_end );
//////////////////
return( curr_end-1 );
//////////////////
}
y2debug("SLOT- %1 %2 %3 %4", slot_exist, curr_start, curr_end, n );
n = n+1;
} until ( n == ( (size(global_cyl_list)/2 +1)));
}
return(nil);
};
/*---------------------------------------------------------------------
* Find bigest slot for logical
* return [start, end] or nil
/*---------------------------------------------------------------------
*/
define list GetLogicalSlot( string dev, map disk )
``{
string type = substring(dev, 5, 2);
list<map> global_list = filter( map part, disk["partitions"]:[],
``( part["type"]:`unknown == `logical ));
map extended = (map)find( map part, disk["partitions"]:[],
``( part["type"]:`unknown == `extended ));
//////////////////////////////////
if (extended == nil)
{
return(nil);
}
//////////////////////////////////
list global_cyl_list =
sort(flatten(maplist( map part, global_list,
``([part["region",0]:0,
part["region",0]:0 + part["region",1]:1-1 ]))));
// Look for a slot in the list of cylinders
integer n = 0;
integer start_cyl = tointeger( extended["region",0]:0 );
integer end_cyl = start_cyl + tointeger(extended["region",1]:1)-1;
integer sl_start = 0;
integer sl_end = 0;
integer curr_start = 0;
integer curr_end = 0;
boolean slot_exist = false;
if (size(global_cyl_list) == 0 )
{
// no partition exist
return( [start_cyl, end_cyl]);
}
else
{
repeat
{
if( n == 0 )
{
// first
curr_start = start_cyl-1;
curr_end = global_cyl_list[0]:0;
}
else if ( n == (size(global_cyl_list)/2))
{
// last
curr_start = global_cyl_list[size(global_cyl_list)-1]:0;
curr_end = end_cyl+1;
}
else
{
//check if between global partition n-1 and n is a slot
curr_start = global_cyl_list[2*n-1]:0;
curr_end = global_cyl_list[2*n]:0;
}
if( curr_start+1 < curr_end )
{
slot_exist = true;
y2debug( "A Slot at: %1 %2 ", curr_start, curr_end );
if( (curr_end - curr_start -2) >= (sl_end - sl_start) )
{
sl_start = curr_start+1;
sl_end = curr_end-1;
}
}
y2debug("SLOT- %1 %2 %3 %4 ", slot_exist, curr_start, curr_end, n );
n = n+1;
} until ( n == ( (size(global_cyl_list)/2 +1)));
}
if (slot_exist)
{
return( [sl_start, sl_end] );
}
else
{
return(nil);
}
};
/*---------------------------------------------------------------------
* Check slot for logical partition
* Input: start_cyl of the tested slot, /dev/hda5, diskmap, in edit_mode or create_mode
*
* return [max-end_cyl] or nil if its no valisd start_cyl
*
* todo: GetLogicalSlot TestLogicalSlot should be one function
*---------------------------------------------------------------------
*/
define integer TestLogicalSlot( integer slot_start_cyl, string dev, map disk)
``{
string type = substring(dev, 5, 2);
list<map> global_list = filter( map part, disk["partitions"]:[],
``( part["type"]:`unknown == `logical ));
map extended = (map)find( map part, disk["partitions"]:[],
``( part["type"]:`unknown == `extended ));
list global_cyl_list =
sort(flatten(maplist( map part, global_list,
``([part["region",0]:0,
part["region",0]:0 + part["region",1]:1-1 ]))));
// Look for the slot in the list of cylinders
integer n = 0;
integer start_cyl = tointeger( extended["region",0]:0 );
integer end_cyl = start_cyl + tointeger( extended["region",1]:1-1 );
integer sl_start = 0;
integer sl_end = 0;
integer curr_start = 0;
integer curr_end = 0;
boolean slot_exist = false;
if (size(global_cyl_list) == 0 )
{
if( start_cyl <= slot_start_cyl && slot_start_cyl <= end_cyl )
return( end_cyl );
}
else
{
repeat
{
if( n == 0 )
{
// first
curr_start = start_cyl-1;
curr_end = global_cyl_list[0]:0;
}
else if ( n == (size(global_cyl_list)/2))
{
// last
curr_start = global_cyl_list[size(global_cyl_list)-1]:0;
curr_end = end_cyl+1;
}
else
{
//check if between global partition n-1 and n is a slot
curr_start = global_cyl_list[2*n-1]:0;
curr_end = global_cyl_list[2*n]:0;
}
y2debug( "Testing Slot %1 < x < %2 ", curr_start, curr_end );
if( curr_start < slot_start_cyl && slot_start_cyl < curr_end )
{
// If the slot was found ...
y2debug( "X Slot at: %1 %2 ", curr_start, curr_end );
//////////////////
return( curr_end -1);
//////////////////
}
y2debug("SLOT- %1 %2 %3 %4", slot_exist, curr_start, curr_end, n );
n = n+1;
} until ( n == ( (size(global_cyl_list)/2 +1)));
}
return(nil);
};
/*---------------------------------------------------------------------
* returns for nonnegative numbers a string with a minimum of 4 characters:
* 1 -> " 1"
* 22 -> " 22"
* 145 -> " 145"
* 2134 -> "2134"
* 34111 -> "34111"
*----------------------------------------------------------------------
*/
define string to4string( integer nb )
``{
if ( nb < 10 ) return( sformat( " %1", nb ));
if ( nb < 100 ) return( sformat( " %1", nb ));
if ( nb < 1000 ) return( sformat( " %1", nb ));
return( sformat( "%1", nb ));
};
define string usedByString( symbol ub_type, string used_by )
{
string ret = "";
if( ub_type == `UB_LVM )
ret = "LVM " + used_by;
else if( ub_type == `UB_EVMS )
ret = "EVMS " + used_by;
else if( ub_type == `UB_DM )
ret = "DM " + used_by;
else if( ub_type == `UB_DMRAID )
ret = "RAID " + used_by;
else if( ub_type != `UN_NONE )
ret = used_by;
return( ret );
}
/*---------------------------------------------------------------------
* Fill the selection box with ID 'selbox_id' inside widget tree
* 'widget' with disk and partition info from 'all_disks'.
*
* Return value:
* term contents = `VBox(`Label("Partitions"),
* `Table(`header("Device", "Start", "End", "Size", "F", "Type", "Mount", "RAID" , "LVM" ),
* [
* `item(`id("/dev/hda"), "/dev/hda", "8.5 GB", " ", "Seagate ST 48012", " ", "1", "1115" ,"", ""),
* `item(`id("1//dev/hda"), " /dev/hda1", "509.8 MB", " ", "FAT16", " ", "1", "65" ,"", ""),
* `item(`id("2//dev/hda"), " /dev/hda2", "666.7 MB", " ", "NTFS", " ", "66", "150" ,"", ""),
* `item(`id("3//dev/hda"), " /dev/hda3", "5.5 GB", " ", "Extended", " ", "301","1024" ,"", ""),
* `item(`id("4//dev/hda"), " /dev/hda5", "7.8 MB", "F", "Linux ", "/boot", "301","302" ,"", ""),
* `item(`id("5//dev/hda"), " /dev/hda6", "7.8 MB", "", "Linux LVM ", "", "303","304" ,"", "system"),
* `item(`id("6//dev/hda"), " /dev/hda7", "7.8 MB", "", "Linux RAID ", "", "305","307" ,"/dev/md1", ""),
* ] )) ;
*
* PPC: without Start End
*
*----------------------------------------------------------------------
*/
define list FillPartitionList(map<string,map> targets)
``{
list<term> table_input = [];
boolean log_mode = false;
// order should be md, then loop, then LVM, then EVMS
map disk_order = $[ `CT_DMRAID : 0, `CT_DISK : 1, `CT_MD : 2, `CT_LOOP : 3,
`CT_LVM : 4, `CT_EVMS : 5, `CT_DM : 6 ];
list<string> keys = maplist( string dev, map disk, targets,
``{return(dev);} );
keys = sort( string a, string b, keys,
``{
integer oa = disk_order[targets[a,"type"]:`CT_UNKNOWN]:6;
integer ob = disk_order[targets[b,"type"]:`CT_UNKNOWN]:6;
return( (oa==ob) ? (a<b) : (oa<ob) );
});
SCR::Write(.target.ycp,Storage::SaveDumpPath("targetMap_c"), targets );
foreach( string dev, keys,
``{
map disk = targets[dev]:$[];
boolean real_disk = Storage::IsPartitionable( disk );
integer cyl_count = disk["cyl_count"]:0;
integer cyl_size = disk["cyl_size"]:1000000;
string vendor = disk["vendor"]:"";
string model = disk["model"]:"";
string dev_size = ByteToHumanString(disk["size_k"]:0*1024);
string dev_start_cyl = to4string(0);
string dev_nb_cyl = to4string(cyl_count==0?cyl_count:(cyl_count-1));
string udev_id = mergestring( disk["udev_id"]:[], " ");
string udev_path = disk["udev_path"]:"";
if ( (model != "") && (vendor != "") )
vendor = vendor + "-" + model;
else
vendor = vendor + model;
// entry in column "Type" for a unknown disk
if( vendor == "" )
{
if (disk["bus"]:"" == "RAID")
{
vendor = "RAID "+dev;
}
else if( disk["type"]:`CT_UNKNOWN==`CT_LVM )
{
vendor = "LVM" + (disk["lvm2"]:false ? "2 " : " ") +
disk["name"]:"";
}
else if( disk["type"]:`CT_UNKNOWN==`CT_EVMS )
{
vendor = "EVMS " + disk["name"]:"";
}
else if( disk["type"]:`CT_UNKNOWN==`CT_DMRAID )
{
vendor = "BIOS RAID " + disk["name"]:"";
}
else
// label text
vendor = sformat( _("DISK %1"), substring( dev, 5 ));
}
boolean id_sw_raid_dev = (dev == "/dev/md");
/////////////////////////////////////////////////////////////
// Insert line for the entire disk into selection box widget
// Look, if for the architecture disk, and Cylinder are shown
if( !real_disk )
{
dev_nb_cyl = " -- ";
dev_start_cyl = " -- ";
}
if( show_disk &&
!(disk["type"]:`CT_UNKNOWN==`CT_DISK && !real_disk) &&
(disk["type"]:`CT_UNKNOWN==`CT_DISK ||
disk["type"]:`CT_UNKNOWN==`CT_DMRAID ||
disk["type"]:`CT_UNKNOWN==`CT_LVM ||
(disk["type"]:`CT_UNKNOWN==`CT_EVMS && size(disk["name"]:"")>0 &&
(!haskey( targets, "/dev/"+substring( disk["name"]:"", search( disk["name"]:"", "/")+1 ))||
disk["create"]:false))))
{
y2milestone( "disk:%1", disk );
term a = `item(`id(dev));
if( showT_dev ) a = add(a, dev );
if( showT_id ) a = add(a, sformat( " (%1)",
disk["bios_id"]:"" ) );
if( showT_size ) a = add(a, dev_size );
if( showT_format ) a = add(a, (disk["dasdfmt"]:false)?"X":" " );
if( showT_fs ) a = add(a, vendor);
if( showT_mount ) a = add(a, "" );
if( show_T_details && showT_mby ) a = add(a, "");
if( show_T_details && showT_cyl ) a = add(a, dev_start_cyl );
if( show_T_details && showT_cyl ) a = add(a, dev_nb_cyl );
if( showT_Used ) a = add(a, usedByString( disk["used_by_type"]:`UB_NONE,
disk["used_by"]:"" ));
if( showT_Label ) a = add(a, "");
if( show_T_details && showT_udev_id ) a = add(a, udev_id);
if( show_T_details && showT_udev_path ) a = add(a, udev_path);
table_input = add( table_input, a );
}
/////////////////////////////////////////////////////////////
// Now we come to the partitions ...
list<map> partitions = disk["partitions"]:[];
foreach( map partition, partitions,
``{
// dont show "system partitions"
string fstype = partition["fstype"]:"";
boolean hide = partition["fsid"]:0 == Partitions::fsid_mac_hidden ||
disk["used_by_type"]:`UB_NONE==`UB_DMRAID;
if( !hide && search( partition["device"]:"", "/dev/evms/" )==0 )
{
y2milestone( "evms p: %1", partition );
string d1 = evms_dev_disk( partition["device"]:"" );
y2milestone( "evms d1:%1", d1 );
integer val = search( d1, "/lvm/" );
if( val!=nil && val>0 )
{
d1 = "/dev/" + substring( d1, 9 );
}
else
{
val = search( d1, "/lvm2/" );
if( val!=nil && val>0 )
{
d1 = "/dev/" + substring( d1, 10 );
}
}
hide = size(partition["mount"]:"")==0;
if( hide )
{
y2milestone( "evms p: %1", Storage::GetPartition( targets, d1 ));
hide = (size(Storage::GetPartition( targets, d1 ))>0||
Storage::IsPartType(targets[d1,"type"]:`CT_UNKNOWN)) &&
!partition["evms_native"]:false;
}
y2milestone( "evms d1:%1 hide:%2", d1, hide );
}
if( !hide || log_mode )
{
string part_id = "";
string part_dev_name = partition["device"]:"";
string id = part_dev_name;
////////////////////////////////////////////////////////////
// Format other Colums:
integer start_cyl = partition["region",0]:0;
integer nb_cyl = partition["region",1]:0;
symbol type = partition["type"]:`unknown;
boolean format = partition["format"]:false;
boolean crypt_fs = partition["enc_type"]:`none != `none;
symbol used_fs = partition["used_fs"]:`unknown;
string mount_point = partition["mount"]:"";
symbol mount_by = partition["mountby"]:`device;
string filesystem_name = "";
string label = partition["label"]:"";
string udev_id = mergestring( partition["udev_id"]:[], " ");
string udev_path = partition["udev_path"]:"";
string used_by =
usedByString( partition["used_by_type"]:`UB_NONE,
partition["used_by"]:"" );
filesystem_name = partition["fstype"]:"";
if( format && partition["fsid"]:0 == Partitions::fsid_native)
{
string fs_name = FileSystems::GetName( used_fs, "Ext2" );
filesystem_name = filesystem_name + " (" + fs_name + ") ";
}
string format_flag = "";
if ( format ) format_flag = "F";
if ( crypt_fs ) format_flag = "C" + format_flag;
string bytes_of_part =
ByteToHumanString( partition["size_k"]:0*1024 );
/////////////////////////////////////////////////////
// Insert line for this partition into selection box widget
//
// Start- and EndCly are shown (intel) or not (ppc) ...
term a = `item(`id(id));
if( showT_dev ) a = add(a, part_dev_name );
if( showT_id ) a = add(a, part_id );
if( showT_size ) a = add(a, bytes_of_part);
if( showT_format ) a = add(a, format_flag);
if( showT_fs ) a = add(a, filesystem_name);
if( showT_mount )
{
string tmp = mount_point;
if( Mode::normal() && partition["inactive"]:false )
{
tmp = tmp + " *";
}
a = add(a, tmp );
}
if( show_T_details && showT_mby )
{
if (size (mount_point) > 0)
{
map tmp = $[ `device : "K", `uuid : "U", `label : "L",
`id : "I", `path : "P" ];
a = add(a, tmp[mount_by]:"");
}
else
a = add(a, "");
}
if( show_T_details && showT_cyl )
{
if( real_disk )
{
a = add(a, to4string(start_cyl));
integer num = start_cyl + nb_cyl - 1;
if( num<0 )
num=0;
a = add(a, to4string(num));
}
else
{
a = add(a, " -- ");
a = add(a, " -- ");
}
}
if( showT_Used ) a = add(a, used_by);
if( showT_Label ) a = add(a, label);
if( show_T_details && showT_udev_id ) a = add(a, udev_id);
if( show_T_details && showT_udev_path ) a = add(a, udev_path);
table_input = add( table_input, a );
}
else
{
// as deleted marked
// y2debug( "ddddddddddddd----");
}
});
});
return( table_input );
};
/*-------------------------------------------------------------------
*
* Now check start an end cylinder
* caution: there is no differenc in edit and create cause the partition, which is to edited,
* is not in the disk map!
*
* Check:
* A. Is start_cyl ist a number? no-> try again
* B. is start_cyl valid ( can the partition start there?) no -> try again
* (when this is tested, the maximal possible end cylinder is computed, too)
* C. Now we check the syntax of the endCylinder
* D. If the syntax is valid, the requested end cylinder is checked
* E. If it is not valid, the user gets a popup and the maximal possible end cylinder is set
*
* returns [<symbol>, <value>]
*
* [`ok, <effektive end cyl>]
* [`max, <max-value as str> ] // case E
* [`error, 0]
*-------------------------------------------------------------------
*/
define list TestStartEndCyl( string str_start_cyl, string str_end_part,
string dev, map disk, symbol type,
integer cyl_size, boolean bsd_label )
``{
integer max_end_cyl = 0;
string max_end_str = "";
symbol input = `ok;
integer int_start_cyl = tointeger(str_start_cyl);
integer int_end_cyl = 0;
y2milestone( "TestStartEndCyl start_cyl:%1 end_cyl:%2", str_start_cyl,
str_end_part );
////////////////////////////////// STEP A /////////////////////
if (!IsNumber( str_start_cyl ))
{
input = `error;
// error popup text
Popup::Error(_("Invalid input for the start of the partition.
Enter the start cylinder, for example, 77.
"));
}
else
{
////////////////////////////// STEP B /////////////////////
integer int_start_cyl = tointeger(str_start_cyl);
if ( type == `logical )
max_end_cyl = TestLogicalSlot( int_start_cyl, dev, disk );
else
max_end_cyl = TestSlot( int_start_cyl, dev, disk, bsd_label ); // primary && extended
if (max_end_cyl == nil)
{
// error popup text
Popup::Error(_("The value entered is invalid. Try again."));
input = `error;
}
if ( input == `ok )
{
////////////////////////// STEP C /////////////////////
if (!IsCylNumber(str_end_part))
{
input = `error;
// error popup text
Popup::Error(_("The value for the partition end is invalid.
Enter the end cylinder number (such as 77), an offset (like +122),
or the size of the partition (for example, +100M or 1.8GB )
"));
}
else
{
////////////////////// STEP D /////////////////////
int_end_cyl = int_start_cyl +
ToEndRegion( str_start_cyl, str_end_part,
cyl_size ) - 1;
if( int_end_cyl > max_end_cyl || int_end_cyl < int_start_cyl)
{
////////////////// STEP E /////////////////////
// error popup text, %1, %2, %3 is replaced by numeric value
string text = sformat( _("
The value of the end cylinder %1 was not valid.
The value must be between %2 and %3.
Use the maximum allowed value
or select No and enter a correct value yourself.
Use the maximum allowed value?
"),
int_end_cyl, int_start_cyl,
max_end_cyl );
boolean ans = Popup::YesNo( text );
if( ans )
{
max_end_str = sformat("%1", max_end_cyl);
input = `max;
}
else
{
input = `error;
}
}
}
}
}
// END Check
if ( input == `ok ) return( [`ok, int_end_cyl ]);
if ( input == `max ) return( [`max, max_end_str ]);
// if ( input == `error )
return( [`error, 0]);
};
/*---------------------------------------------------------------------
* Checks if the mountpoint is valid
* - /proc /mnt /lost+found contain Installation::sourcedir are not allowd
* - double entries are not allowed ( mountpoints with no / and "" are always allowed )
*
*----------------------------------------------------------------------
/**
* Dialog: "Create a partition Dialog"
* @parm new_val map that contains a partition
* @parm file_systems filesystem definitions
* @parm tilte title string
* @parm dev device string for the new/edit partition
* @parm disk a map with the disk data CAUTION: in Edit-Mode, the edited partition, must not be in this map!!
* @parm bsd_label
* @parm edit_size flag
* @parm cyl_size
* @return map modified partition or nil by cancel
*/
define map<string,any> EditOrCreatePartDlg( map<string,any> cur_val,
map<symbol,map> file_systems,
string title, map disk,
boolean bsd_label,
boolean edit_size,
integer cyl_size,
boolean installation )
``{
boolean create = cur_val["create"]:false;
string dev = cur_val["device"]:"";
boolean is_disk = cur_val["type"]:`primary == `primary ||
cur_val["type"]:`primary == `logical;
y2milestone( "EditOrCreatePartDlg cur_val:%1", cur_val );
y2milestone( "EditOrCreatePartDlg is_disk:%1", is_disk );
string helptextCR = getEditOrCreateHelptext( cur_val, !create );
//////////////////////////////////////////////////////////////////////
// Now create "main" dialog with all elements needed
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// right side of the main dialog
term field_dlg_right =
`VBox(
`Top( SizeDlg( cur_val, cyl_size, edit_size, is_disk )),
`VSpacing(1),
`ReplacePoint( `id(`mount_dlg_rp), MountDlg( cur_val, [] ))
);
////////////////////////////////////////////////////////////////////
// left side of the main dialog
term field_dlg_left =
`Top( `ReplacePoint( `id( `format_dlg_rp),
FormatDlg( cur_val, file_systems) ));
////////////////////////////////////////////////////////////////////
// Open main dialog for editing and creation of partitions
////////////////////////////////////////////////////////////////////
UI::OpenDialog( `opt(`decorated ),
`HBox(
`HWeight(30, `RichText( helptextCR )),
`HStretch(),
`HSpacing(1),
`HWeight(70,`VBox(
`Heading( title),
`VSpacing(1),
`VStretch(),
`HBox(
field_dlg_left,
`HSpacing(2),
field_dlg_right
),
`VSpacing(1),
`VStretch(),
`HBox(
`PushButton(`id(`ok), `opt(`default), Label::OKButton() ),
`PushButton(`id(`cancel), Label::CancelButton() )
)
)
),
`HSpacing(1),
`HStretch()
)
);
map<string,any> retval = cur_val;
symbol ret = `ok;
retval = HandlePartWidgetChanges( true, ret, file_systems, cur_val,
retval );
repeat
{
////////////////////////////////////////////////////////////
// Check the User input
ret = (symbol)UI::UserInput();
y2milestone( "EditOrCreatePartDlg UserInput ret:%1", ret );
if ( ret != `cancel )
{
retval = HandlePartWidgetChanges( false, ret, file_systems, cur_val,
retval );
}
////////////////////////////////////////////////////////////
// if the user has pushed the button ok
if ( ret == `ok )
{
/////////////////////////////////////////////////////////
// save mountpoint
retval["mount"] = String::CutBlanks( (string)UI::QueryWidget(`id(`mount_point),
`Value));
/////////////////////////////////////////////////////////
// add fstype to retval
integer fs_id = retval["fsid"]:0;
if( fs_id<256 )
{
retval["fstype"] = "";
foreach( symbol file_system_name, map file_system_map, file_systems, ``{
if( file_system_map[`fsid]:Partitions::fsid_native ==
fs_id )
retval["fstype"] = file_system_map[`fstype]:"";
});
if( retval["fstype"]:"" == "")
retval["fstype"] = Partitions::FsIdToString( fs_id );
}
if( create && edit_size )
{
////////////////////////////////////////////////////
// Get start and end cyl and check if the user input
// for start und end cyl are valid
list re = [];
string start_cyl = (string)UI::QueryWidget(`id(`start_cyl), `Value);
string end_part = (string)UI::QueryWidget(`id(`end_part), `Value);
re = TestStartEndCyl( start_cyl, end_part, dev, disk,
retval["type"]:`primary, cyl_size,
bsd_label );
if( re[0]:`error == `error )
{
UI::SetFocus(`id(`end_part));
ret = `again;
continue;
}
if( re[0]:`error == `max )
{
end_part = re[1]:"";
}
////////////////////////////////////////////////////
// add start_cyl and end_part to region and add region
// to retval
list region = [ tointeger( start_cyl ),
ToEndRegion( start_cyl, end_part, cyl_size )];
retval["region"] = region;
}
integer check_size = retval["size_k"]:0 * 1024;
if( is_disk )
check_size = retval["region",1]:0 * cyl_size;
if( !check_ok_fssize( check_size, retval ))
{
UI::SetFocus(`id(`end_part));
ret = `again;
continue;
}
map ret_mp = CheckOkMount( dev, cur_val, retval );
retval = ret_mp["map"]:$[];
if( !ret_mp["ok"]:false )
{
if( ret_mp["field"]:`none != `none )
UI::SetFocus(`id(ret_mp["field"]:`none));
ret = `again;
continue;
}
//////////////////////////////////////////////////////////////
// user changed fsid of existing partition
symbol par_type = cur_val["type"]:`empty;
y2milestone( "EditOrCreatePartDlg par_type %1", par_type );
y2milestone( "EditOrCreatePartDlg retval %1", cur_val );
y2milestone( "EditOrCreatePartDlg cur_val %1", retval );
if( retval["fsid"]:0 != cur_val["fsid"]:0 &&
(par_type==`primary||par_type==`logical||par_type==`extended)&&
!haskey( cur_val, "change_fsid") && !disk["readonly"]:false &&
!retval["create"]:false && disk["label"]:"msdos"!="gpt" )
{
// popup text
boolean ok = Popup::ContinueCancel(_("
You have changed the FSID of an existing partition.
In some cases, this could have serious consequences, especially
if you change the FSID of a partition belonging to a different
operating system. Only proceed if you know exactly
what you are doing.
"));
if (! ok )
{
UI::ReplaceWidget(`id(`fsid_dlg_rp),
FsidComboBox( cur_val, file_systems ));
UI::ChangeWidget(`id(`format), `CurrentButton,
`format_false );
ret = `again;
continue;
}
if( !haskey( cur_val, "change_fsid"))
{
retval["change_fsid"] = true;
retval["ori_fsid" ] = cur_val["fsid"]:0;
}
}
map ret_cr = CheckCryptOk( retval );
if( !ret_cr["ok"]:false )
{
ret = `retry;
}
else
{
retval = ret_cr["map"]:$[];
}
////////////////////////////////////////////////////////
// modified partition and partition is mounted
if( !installation && !arePartitionsEqual( cur_val, retval ) &&
!create )
{
string mounts = Storage::DeviceMounted( dev );
if( mounts != "" )
{
if( !UseChangedPartitionContinueCancelPopup() )
{
ret = `cancel;
}
}
}
}
} until ( ret == `ok || ret == `cancel );
y2milestone( "EditOrCreatePartDlg ret:%1 retval=%2", ret, retval );
UI::CloseDialog();
if ( ret == `cancel )
{
return( nil );
}
else
{
return( retval );
}
}
/**
* Dialog: "Resize a partition Dialog"
* @parm cur_val map that contains a partition
* @parm device device name of the resized partition
* @parm cyl_size size of a cylinder on the disk
* @return map modified partition or nil by cancel
*/
define map ResizePartDlg( map cur_val, string device, map disk, map possible )
``{
integer cyl_size = disk["cyl_size"]:0;
boolean test_simple_ui = false;
boolean win = Partitions::IsDosWinNtPartition( cur_val["fsid"]:0 );
boolean swap = !win && cur_val["fsid"]:0==Partitions::fsid_swap;
boolean simple_ui = false;
integer cyl_after = 0;
if( possible["extend"]:false )
{
cyl_after = Storage::FreeCylAfter( disk, cur_val );
}
integer av_space = cyl_after*cyl_size;
y2milestone( "ResizePartDlg dev:%1 cyl:%2 map:%3 win:%4 swap:%5",
device, cyl_size, cur_val, win, swap );
y2milestone( "ResizePartDlg cyl_after:%1 av_space:%2",
cyl_after, av_space );
integer min_free = 0;
integer new_size = 0;
integer shrink_size = 0;
integer new_min = 0;
map df = $[];
if( !swap && !cur_val["format"]:false )
{
df = Storage::GetFreeSpace( device, 0, cur_val["used_fs"]:`none, true );
if( size(df)==0 || !df["ok"]:false )
{
y2error( "failed GetFreeSpace %1 fs:%2", device,
cur_val["used_fs"]:`none );
string tmp = sformat(
_("Partition %1 cannot be resized
because the file system seems to be inconsistent.
"), device );
Popup::Error( tmp );
return( nil );
}
}
else
{
df["used"] = 0;
if( haskey( cur_val, "orig_size_k" ) && cur_val["resize"]:false )
{
df["df_free"] = cur_val["orig_size_k"]:0 * 1024;
}
else
{
df["df_free"] = cur_val["region",1]:0 * cyl_size;
}
df["free"] = df["df_free"]:0;
}
// label text
string unit = _("MB");
integer factor = 1024*1024;
if( df["df_free"]:0 > 15*1024*factor )
{
factor = factor * 1024;
unit = _("GB");
}
y2milestone( "ResizePartDlg factor:%1", factor );
if( haskey( cur_val, "win_max_length" ) && cur_val["resize"]:false )
{
new_min = cur_val["orig_size_k"]:0*1024/cyl_size - cur_val["win_max_length"]:0;
new_min = new_min*cyl_size / factor;
}
y2milestone( "ResizePartDlg min_lin:%1 df:%2", new_min, df );
integer used = df["used"]:0 / factor;
integer free = df["df_free"]:0 / factor;
integer not_shrink_free = 0;
// Labels for bar graph. "%1" will be replace with a numeric value.
string bargraph_label_used = "";
string bargraph_label_free = "";
string bargraph_label_new = "";
if( win )
{
// label text %1 is replaced by a number
bargraph_label_used = _("Windows\nUsed\n%1 ") + unit;
// label text %1 is replaced by a number
bargraph_label_free = _("Windows\nFree\n%1 ") + unit;
// label text %1 is replaced by a number
bargraph_label_new = _("Linux\nSize\n%1 ") + unit;
}
else
{
// label text %1 is replaced by a number
bargraph_label_used = _("Space\nUsed\n%1 ") + unit;
if( swap )
{
// label text %1 is replaced by a number
bargraph_label_free = _("Swap\nSpace\n%1 ") + unit;
}
else
{
// label text %1 is replaced by a number
bargraph_label_free = _("Space\nFree\n%1 ") + unit;
}
// label text, %1 is replaced by a number
bargraph_label_new = _("Unused\nDisk\n%1 ") + unit;
}
// Labels for input fields. "%1" will be replaced with the current unit (MB)
string field_label_free = "";
string field_label_new = "";
if( win )
{
// label text, %1 is replaced by a unit value ("MB")
field_label_free = sformat( _("Windows Free (%1)"), unit);
// label text, %1 is replaced by a unit value ("MB")
field_label_new = sformat( _("Linux Size (%1)"), unit);
}
else
{
// label text, %1 is replaced by a unit value ("MB")
field_label_new = sformat( _("Unused Disk (%1)"), unit);
if( swap )
{
// label text, %1 is replaced by a unit value ("MB")
field_label_free = sformat( _("Swap Space (%1) "), unit);
}
else
{
// label text, %1 is replaced by a unit value ("MB")
field_label_free = sformat( _("Space Free (%1)"), unit);
}
}
if( win )
{
min_free = free / 10;
if( df["df_free"]:0 != df["free"]:0 )
{
not_shrink_free = df["df_free"]:0 - df["free"]:0;
not_shrink_free = (not_shrink_free + factor - 1) / factor;
if( not_shrink_free > min_free )
{
min_free = not_shrink_free;
}
}
}
else
{
min_free = (factor==1024*1024)?5:1;
}
if( cur_val["used_fs"]:`none == `ntfs &&
not_shrink_free > df["free"]:0/factor/5 )
{
//Message text. %1 and %2 are numbers. %3 is the unit.
string ptext = sformat( _("Your NTFS file system has %1 %3 free space available. Due to limitations in
the NTFS resizer, the file system can only be shrunk by up to %2 %3.
To be able to shrink the file system more, boot your Windows
system and run a disk defragmentation program under Windows to move
the used blocks of the file system towards the start of the partition.
"),
free, df["free"]:0/factor, unit );
Popup::Message( ptext );
}
if( haskey( cur_val, "orig_size_k" ) && cur_val["resize"]:false )
{
shrink_size = (df["used"]:0+df["df_free"]:0)/factor -
cur_val["region",1]:0*cyl_size/factor;
y2milestone( "ResizePartDlg new_size_k:%1 shrink_size:%2",
cur_val["region,1"]:0*cyl_size/factor, shrink_size );
if( shrink_size>df["free"]:0/factor )
{
shrink_size = df["free"]:0/factor;
}
y2milestone( "ResizePartDlg shrink_size:%1", shrink_size );
}
av_space = av_space/factor;
y2milestone( "ResizePartDlg min_free:%1 free:%2 used:%3 shrink_size:%4 unit:%5",
min_free, free, used, shrink_size, unit );
string windows = "";
if( win )
{
// label text
windows = _("Windows");
}
// Help text for partition resizing -
// common part for both graphical mode (with bar graphs)
// and non-graphical mode (text only).
// %1 is OS label, such as Windows
string helptext = sformat( _("<p>
Choose the new size for your %1 partition.
</p>"), windows );
// help text (common to both modes), continued
// %1 is OS label, such as Windows
helptext = helptext + sformat( _("
<p>
The actual resizing is performed only after you confirm all your
settings in the last installation dialog. Until then, your %1
partition will remain untouched.
</p>"), windows );
// help text (common to both modes), continued
helptext = helptext + _("
<p>
If you decide not to resize your partition, press
<b>Do Not Resize</b>. This resets the values to the original
size of the partition.
</p>
");
if( UI::HasSpecialWidget(`Slider ) &&
UI::HasSpecialWidget(`BarGraph ) && !test_simple_ui )
{
// help text, continued - graphical mode only
// this text will be appended to the help text common to both modes.
helptext = helptext + _("
<p>
The upper bar graph displays the current situation.
The lower bar graph displays the situation after the installation (after
the partition resize).
</p>");
// help text (graphical mode), continued
helptext = helptext + _("
<p>
Drag the slider or enter a numeric value in either
input field to adjust the suggested value.
</p>");
////////////////////////////////////////////////////////////////////////////////////////////
// Open main dialog for resizing of partitions
////////////////////////////////////////////////////////////////////////////////////////////
term graph = nil;
if( win || cyl_after==0 )
{
graph = `BarGraph( [ used, free ],
[ bargraph_label_used, bargraph_label_free ] );
}
else
{
graph = `BarGraph( [ used, free, av_space ],
[ bargraph_label_used, bargraph_label_free,
bargraph_label_new ] );
}
y2milestone( "ResizePartDlg graph=%1", graph );
UI::OpenDialog( `opt(`decorated ),
`HBox(
`HWeight(30, `RichText( helptext )),
`HStretch(),
`HSpacing(1),
`HWeight(70,`VBox(
`HSpacing(50),
`VStretch(),
`VSpacing(1),
// Headline above bar graph that displays current partition size
`Left( `Label( _("Now")) ),
graph,
`VSpacing(1),
`VStretch(),
// Headline above bar graph that displays future partitions
`Left( `Label( _("After Installation") ) ),
`PartitionSplitter( `id(`linux_size),
used, free+av_space,
shrink_size+av_space, new_min, min_free,
bargraph_label_used,
bargraph_label_free,
bargraph_label_new,
field_label_free,
field_label_new ),
// Button text
`HBox( `PushButton(`id(`rem_resize), _("&Do Not Resize") )),
`VSpacing(1),
`HBox(
`PushButton(`id(`ok), `opt(`default), Label::OKButton() ),
`PushButton(`id(`cancel), Label::CancelButton() ))
))));
}
else
{
simple_ui = true;
// help text, continued - non-graphical mode only
// this help text will be appended to the help text common to both modes.
//%1 is OS label, such as Windows
helptext = helptext + sformat( _("
<p>Enter a value for the size to which to shrink the %1 partition.
</p>"), windows );
string used_label = "";
if( win )
{
// Label text
used_label = _("Windows Used");
}
else
{
// Label text
used_label = _("Used");
}
// help text (non-graphical mode), continued
//%1 is label text, such as Used. %2 is OS, such as Windows.
helptext = helptext + sformat(_("
<p>
<b>%1<b> is the size of the used part of your %2 partition.
</p>"), used_label, windows );
// help text (non-graphical mode), continued
helptext = helptext + _("
<p><b>Free</b> indicates the current free space (before shrinking)
of the partition.
</p>");
UI::OpenDialog( `opt(`decorated ),
`HBox(
`HWeight(30, `RichText( helptext )),
`HStretch(),
`HSpacing(1),
`HWeight(70,
`VBox(
`HBox(
// Label for used part of the partition in non-graphical mode
`HWeight(3, `Right(`Label(used_label))),
`HWeight(2, `Label(`opt(`outputField), sformat("%1", used ))),
`HWeight(3, `Left(`Label( unit )))),
`VSpacing(0.5),
`HBox(
// Label for free part of the partition in non-graphical mode
`HWeight(3, `Right(`Label(_("Free")))),
`HWeight(2, `Label(`opt(`outputField), sformat("%1", free ))),
`HWeight(3, `Left(`Label( unit )))),
`VSpacing(0.5),
`HBox(
// Edit field label for linux partition size in non-graphical mode
`HWeight(3, `Right(`Bottom(`Label(_("New Size"))))),
`HWeight(2, `IntField( `id(`linux_size), "",
used+min_free, used+free+av_space,
used+free-shrink_size)),
`HWeight(3, `Left(`Bottom(`Label( unit ))))),
// Button text
`HBox( `PushButton( `id(`rem_resize),
_("&Do Not Resize") )),
`VSpacing(1),
`HBox(
`PushButton( `id(`ok), `opt(`default),
Label::OKButton() ),
`PushButton( `id(`cancel),
Label::CancelButton() ))
))));
}
map retval = cur_val;
any ret = `ok;
repeat
{
/////////////////////////////////////////////////////////////
// Check the User input
ret = UI::UserInput();
y2milestone( "ResizePartDlg ret=%1", ret );
if( ret == `rem_resize )
{
if( simple_ui )
UI::ChangeWidget( `id(`linux_size), `Value, used+free );
else
UI::ChangeWidget( `id(`linux_size), `Value, av_space );
}
if( ret == `ok )
{
// Get the value the user adjusted. If s/he entered a value
// too big or too small this is automatically adjusted to the
// biggest/smallest value possible (by Qt).
shrink_size = (integer)UI::QueryWidget(`id(`linux_size), `Value);
y2milestone( "ResizePartDlg shrink_size %1", shrink_size );
if( simple_ui )
{
new_size = shrink_size;
}
else
{
new_size = used + free + av_space - shrink_size;
}
y2milestone( "ResizePartDlg Value:%1 New size:%2", shrink_size, new_size);
}
if( ret == `ok )
{
if( (!simple_ui && shrink_size != av_space) ||
(simple_ui && shrink_size != used+free) )
{
retval["resize"] = true;
list new_reg = [ retval["region",0]:0,
PartedSizeToCly( (tofloat(new_size*factor)), cyl_size ) ];
retval["region"] = new_reg;
}
else
{
retval["resize"] = false;
}
}
if( ret == `ok && !cur_val["format"]:false && retval["resize"]:false )
{
integer diff = 0;
if( haskey( retval, "orig_size_k" ))
diff = retval["region",1]:0 - retval["orig_size_k"]:0*1024/cyl_size;
else
diff = retval["region",1]:0 - cur_val["region",1]:0;
string mp = cur_val["inactive"]:false ? "" : cur_val["mount"]:"";
y2milestone( "ResizePartDlg diff %1 mp %2", diff, mp );
if( !CheckResizePossible( false, false, diff,
cur_val["used_fs"]:`unknown, mp ))
{
ret = `again;
}
}
y2milestone("ResizePartDlg ret = %1", retval );
}
until( ret == `ok || ret == `cancel );
UI::CloseDialog();
if( ret == `cancel )
{
return( nil );
}
else
{
return( retval );
}
}
/*---------------------------------------------------------------------
* Display "Create a extended partition Dialog"
*
* return: nil bei cancel
* [fsid,format,mount,start_cyl,end_cyl] bei ok
*
*----------------------------------------------------------------------
*/
define map CreateEditExtendedPartDlg( map new_val, string title, string dev,
map disk, integer cyl_size, boolean edit,
boolean bsd_label )
``{
string helptextCR = getCreateEditExtendedHelptext();
/////////////////////////////////////////////////////////////////////////////////////////
// title of the dialog
term header = `Heading(title);
UI::OpenDialog( `opt(`decorated ),
`VBox(
//`Heading(title),
header,
`VSpacing(0.5),
`HBox(
/// left side
`HWeight(50,`RichText( helptextCR )),
/// right side
// popup create partition: frame description Start/End Cylinder
`HWeight( 40, SizeDlg( new_val, cyl_size, true, true) )
),
`VSpacing(0.5),
`HBox(
// popup create partition:
`PushButton(`id(`ok), `opt(`default), Label::OKButton() ),
// popup create partition:
`PushButton(`id(`cancel), Label::CancelButton())
)
)
);
UI::SetFocus(`id(`start_cyl));
map return_value = $[];
symbol doit = `cancel;
repeat
{
//-------------------------------
// Check the User input
//-------------------------------
doit = (symbol)UI::UserInput();
if( doit != `cancel )
{
return_value = new_val;
list ret = [];
string start_cyl = (string)UI::QueryWidget( `id(`start_cyl), `Value);
string end_part = (string)UI::QueryWidget( `id(`end_part), `Value);
ret = TestStartEndCyl( start_cyl, end_part, dev, disk,
return_value["type"]:`primary,
cyl_size, bsd_label );
if (ret[0]:`error == `error )
{
doit = `again;
continue;
}
if (ret[0]:`error == `max )
{
end_part = ret[1]:"";
}
//////////////////////////////////////////////////////////////
// add start_cyl and end_part to region and add region to return_value
list region = [ tointeger( start_cyl ),
ToEndRegion( start_cyl, end_part, cyl_size )];
return_value["region"] = region;
}
} until( doit == `cancel || doit == `ok );
//------------------------------------------------------------------------------------
// Check if the start end cylinder are changed: PopUp // todo change logical cylinders
//------------------------------------------------------------------------------------
if( doit != `cancel && edit &&
return_value["region",0]:0 > new_val["region",0]:0 ||
return_value["region",1]:0 != new_val["region",1]:0 )
{
// warning popup text
Popup::Warning(_("You have changed the start or end cylinders.
Make sure that all logical partitions
fit into this new extended partition.
"));
}
UI::CloseDialog();
if( doit == `cancel )
{
return( nil );
}
else
{
return( return_value );
}
};
/*---------------------------------------------------------------------
* Dialog choose disk
* return /dev/xxx or nil if cancel
* what -> `create or `delete
*---------------------------------------------------------------------
*/
boolean SelDisk( symbol what, map disk )
{
return( (what==`delete||!disk["readonly"]:false) &&
Storage::IsPartitionable( disk ) &&
disk["used_by_type"]:`UB_NONE==`UB_NONE );
}
define string ChooseDisk( map<string,map> targetMap, string heading, symbol what )
``{
// Header Choose disk dialog
term diskgroup = `VBox();
list<string> disks = [];
integer n = 0;
string txt = "";
y2milestone( "ChooseDisk last_sel_disk:%1 what:%2", last_sel_disk, what );
disks = maplist( string dv, map ds,
filter( string dev, map disk, targetMap,
``(SelDisk(what,disk))),
``(dv));
y2milestone( "ChooseDisk disks:%1", disks );
disks = (list<string>)
merge( filter( string d, disks, ``(search(d,"/dev/mapper/")==0)),
filter( string d, disks, ``(search(d,"/dev/mapper/")!=0)) );
y2milestone( "ChooseDisk disks:%1", disks );
foreach( string dev, disks,
``{
txt = sformat( "&%1: %2", n+1, dev );
diskgroup = add( diskgroup, `Left( `RadioButton( `id(dev), txt,
dev==last_sel_disk )));
n = n + 1;
});
if( size(disks)>10 )
{
diskgroup = `VBox( `SelectionBox( `id(`disklist), _("Available &Disks"),
disks ));
}
else
{
diskgroup = `RadioButtonGroup( `id(`choosedisk), diskgroup );
}
if( size(disks) > 1 )
{
UI::OpenDialog( `opt(`decorated), `VBox(`Heading( heading ),
`VSpacing(0.5),
diskgroup,
`VSpacing(0.5),
`HBox(
// popup edit existing partition: OK
`PushButton(`id(`ok), `opt(`default), Label::OKButton() ),
// popup edit existing partition: Cancel
`PushButton(`id(`cancel), Label::CancelButton() )
)
)
);
if( UI::WidgetExists( `id(`disklist) ))
{
UI::ChangeWidget( `id(`disklist), `CurrentItem, last_sel_disk );
}
symbol ret = (symbol)UI::UserInput();
if( ret == `cancel)
{
UI::CloseDialog();
return( nil );
}
else
{
string r = "";
y2milestone( "ChooseDisk exits %1", UI::WidgetExists( `id(`disklist)) );
if( !UI::WidgetExists( `id(`disklist) ))
{
r = (string)UI::QueryWidget(`id(`choosedisk), `CurrentButton);
}
else
{
r = (string)UI::QueryWidget(`id(`disklist), `CurrentItem);
}
y2milestone( "ChooseDisk r %1", r );
UI::CloseDialog();
n=0;
if( what==`create && targetMap[r,"readonly"]:false )
{
Popup::Error( Partitions::RdonlyText( r, true ));
return( nil );
}
last_sel_disk = r;
y2milestone( "ChooseDisk last_sel_disk:%1", last_sel_disk );
return(r);
}
}
else if( size(disks) == 1 )
{
// if there is only one disk: no
return( disks[0]:"" );
}
else if( size(disks) == 0 )
{
string txt = _("There are no partitionable Disks available.");
if( Arch::s390() )
{
txt = txt + "\n" + _("You may use dasdfmt in Expert-Button to low level format disks.");
}
Popup::Error( txt );
return( "" );
}
};
define term RaidButton( integer num )
``{
list item_list = [];
item_list = add( item_list,
// menue entry text
`item( `id(`raid_wizard), _("&Create RAID...") ));
if( num>0 )
item_list = add( item_list,
// menu entry text
`item( `id(`raid_settings), _("&Edit RAID")));
// button text
return( `MenuButton( _("&RAID...") , item_list ));
};
define term LoopButton( integer num )
``{
list item_list = [];
item_list = add( item_list,
// menue entry text
`item( `id(`loop_create), _("&Create Crypt File") ));
if( num>0 )
item_list = add( item_list,
// menue entry text
`item( `id(`loop_edit), _("&Edit Crypt File")));
// button text
return( `MenuButton( _("Cr&ypt File...") , item_list ));
};
/*---------------------------------------------------------------------
* Dialog choose primary extended or logical Partition
* Input "PL", "PE" or "PEL"
* return `primary or `logical or `extended or `none
*---------------------------------------------------------------------
*/
define symbol ChoosePart( string usage )
``{
term PL = `VBox(
// button text
`Left( `RadioButton( `id(`primary ), _("&Primary Partition"), true )),
// button text
`Left( `RadioButton( `id(`logical ), _("&Logical Partition"), false ))
);
term PE = `VBox(
// button text
`Left( `RadioButton( `id(`primary ), _("&Primary Partition"), true )),
// button text
`Left( `RadioButton( `id(`extended ), _("&Extended Partition"), false ))
);
term PEL = `VBox(
// button text
`Left( `RadioButton( `id(`primary ), _("&Primary Partition"), true )),
// button text
`Left( `RadioButton( `id(`logical ), _("&Logical Partition"), false )),
// button text
`Left( `RadioButton( `id(`extended ), _("&Extended Partition"), false ))
);
term current = PEL; // default
if ( usage == "PL" ) current = PL;
if ( usage == "PE" ) current = PE;
UI::OpenDialog( `opt(`decorated ),
// heading in a popup dialog
`VBox(`Heading(_("Partition Type") ),
`VSpacing(0.5),
`RadioButtonGroup( `id(`choosePL), current ),
`VSpacing(0.5),
`HBox(
// popup edit existing partition: OK
`PushButton(`id(`ok), `opt(`default), Label::OKButton() ),
// popup edit existing partition: Cancel
`PushButton(`id(`cancel), Label::CancelButton() )
)
)
);
symbol ret = (symbol)UI::UserInput();
if (ret == `cancel)
{
UI::CloseDialog();
return(`none);
}
else
{
ret = (symbol)UI::QueryWidget(`id(`choosePL), `CurrentButton);
UI::CloseDialog();
return(ret);
}
};
/*---------------------------------------------------------------------
* Make a output string for "you can not create a partition, because: "
*---------------------------------------------------------------------
*/
define string FormatCauseLine( symbol cause )
``{
if( cause == `no_ext )
// complete sentence, appended after other complete sentences.
return( _("No extended partition exists."));
if( cause == `dev_full )
// complete sentence, appended after other complete sentences.
return( _("There are already four primary and extended partitions."));
if( cause == `no_extsp )
// complete sentence, appended after other complete sentences.
return( _("No space is left in the extended partition."));
if( cause == `to_many )
// complete sentence, appended after other complete sentences.
return( _("Too many logical drives already exist."));
if ( cause == `no_space )
// complete sentence, appended after other complete sentences.
return( _("No space remains."));
if ( cause == `already )
// complete sentence, appended after other complete sentences.
return( _("An extended partition already exists."));
return( "---" );
};
define term GetTableHeader () {
term header = `header();
// Column header
if ( showT_dev ) header = add( header, _("Device"));
// Column header
if ( showT_id ) header = add( header, _("ID"));
// Column header: centered / minimum = 11 characters /
// fill with space if needed
if ( showT_size ) header = add( header, `Right(_(" Size ")));
// Column header: centered / minimum = 3 characters /
// fill with space if needed
if ( showT_format ) header = add( header, `Right(_(" F ")));
// Column header
if ( showT_fs ) header = add( header, _("Type"));
// Column header: centered / minimum = 7 characters /
// fill with space if needed
if ( showT_mount ) header = add( header, _(" Mount "));
// Column header
if ( show_T_details && showT_mby ) header = add( header, _("Mount By"));
// Column header: minimum = 5 characters fill with space if needed
if ( show_T_details && showT_cyl ) header = add( header, `Right(_("Start")));
// Column header: minimum = 4 characters fill with space if needed
if ( show_T_details && showT_cyl ) header = add( header, `Right(_("End ")));
// Column header
if ( showT_Used ) header = add( header, `Left(_("Used By")));
// Column header
if ( showT_Label ) header = add( header, `Left(_("Label")));
// Column header
if ( show_T_details && showT_udev_id ) header = add( header, `Left(_("Device ID")));
// Column header
if ( show_T_details && showT_udev_path ) header = add( header, `Left(_("Device Path")));
return header;
}
/*---------------------------------------------------------------------
* Make a output string for "you can not create a partition, because: "
*---------------------------------------------------------------------
*/
define string FormatYouCannotCause( boolean primary_is_possible,
boolean extended_is_possible,
boolean logical_is_possible,
symbol no_primary_cause,
symbol no_extended_cause,
symbol no_logical_cause )
``{
string pri_line = "";
string ext_line = "";
string log_line = "";
y2milestone( "prim:%1 ext:%2 log:%3 (%4 %5 %6)", primary_is_possible,
extended_is_possible, logical_is_possible, no_primary_cause,
no_extended_cause, no_logical_cause );
if( primary_is_possible )
// complete sentence. gets combined with other sentences.
pri_line = _("A primary partition can be created.\n");
else
// complete sentence. gets combined with other sentences.
pri_line = _("A primary partition cannot be created.") + " " +
FormatCauseLine( no_primary_cause ) + "\n";
if( logical_is_possible )
// complete sentence. gets combined with other sentences.
log_line = _("A logical partition can be created.\n");
else
if( no_logical_cause != `impossible )
// complete sentence. gets combined with other sentences.
log_line = _("A logical partition cannot be created.") + " " +
FormatCauseLine( no_logical_cause ) +"\n" ;
if ( extended_is_possible )
// complete sentence. gets combined with other sentences.
ext_line = _("An extended partition can be created.\n");
else
if( no_logical_cause != `impossible )
// complete sentence. gets combined with other sentences.
ext_line = _("An extended partition cannot be created.") + " " +
FormatCauseLine( no_extended_cause ) +"\n";
return ( pri_line + ext_line + log_line );
};
/////////////////////////////////////////////////////////////////
// MAIN:
/////////////////////////////////////////////////////////////////
symbol ret = nil;
y2milestone( "Custom partitioner started" );
Storage::SetWizardKey("");
SCR::Write(.target.ycp, Storage::SaveDumpPath("targetMap_s"),
Storage::GetTargetMap() );
map<string,map> tg = Storage::GetTargetMap();
list table_list = FillPartitionList(tg);
if( !Storage::CheckBackupState("custom_part") )
{
Storage::CreateTargetBackup("custom_part");
}
/////////////////////////////////////////////////////////////////
/// MAIN DIALOG
/////////////////////////////////////////////////////////////////
// MAIN LAYOUT
// ---------------------------
term buttonline_a = `HBox();
// main dialog: Button Create partition
if( button_create )
buttonline_a = add( buttonline_a,
`PushButton(`id(`create), _("&Create")) );
// main dialog: Button Edit partition
if( button_edit )
buttonline_a = add( buttonline_a, `PushButton(`id(`edit), _("&Edit")));
// main dialog: Button Delete partition
if( button_delete )
buttonline_a = add( buttonline_a,
`PushButton(`id(`delete), _("&Delete")) );
// main dialog: Button Resize partition
if( button_resize )
buttonline_a = add( buttonline_a,
`PushButton(`id(`resize), _("Re&size")) );
list expert_item_list =[];
if( button_reread )
expert_item_list =
add( expert_item_list ,
// menu entry text
`item( `id (`reread), _("&Reread Partition Table")));
if( button_adapt_mp )
expert_item_list =
add( expert_item_list,
`item( `id (`adapt_mp),
// menu entry text
_("&Import Mount Points from Existing /etc/fstab")));
if ( button_delete_parttable )
expert_item_list =
add( expert_item_list,
`item( `id (`delete_parttable),
// menu entry text
_("Delete Partition &Table and Disk Label")));
if( Arch::s390 () )
{
expert_item_list =
add( expert_item_list,
`item( `id(`dasdfmt),
// menu entry text
_("Execute dasd&fmt on the DASD Device")));
buttonline_a = add( buttonline_a, `PushButton(`id(`dasdfmt),
//button text using case-senstive command name. dasdfmt should not normally be translated.
_("dasd&fmt")) );
}
term buttonline_b = `HBox();
if( button_lvm )
// main dialog: Button LVM
buttonline_b = add( buttonline_b, `PushButton(`id(`lvm), _("&LVM...")));
if( button_evms )
// main dialog: Button EVMS
buttonline_b = add( buttonline_b, `PushButton(`id(`evms), _("E&VMS...")));
// main dialog: Button RAID
if( button_raid )
buttonline_b =
add( buttonline_b,
`ReplacePoint( `id(`raid_button),
RaidButton(size(tg["/dev/md","partitions"]:[]))));
// main dialog: Button LOOP
if( button_loop )
buttonline_b =
add( buttonline_b,
`ReplacePoint( `id(`loop_button),
LoopButton(size(tg["/dev/loop","partitions"]:[]))));
if( button_expert) buttonline_b =
// main dialog: Menu-Button for Expert options
add( buttonline_b, `MenuButton ( _("E&xpert.."), expert_item_list ));
// check box
term details_checkbox = `Left (
`CheckBox (`id(`show_table_details), `opt(`notify), _("&Show Details"), show_T_details)
);
term contents = `VBox( `VSpacing(0.5),
`ReplacePoint(
`id(`table_rp),
`Table( `id(`table), `opt(`notify,`keepSorting),
GetTableHeader(), table_list )
),
details_checkbox,
buttonline_a,
buttonline_b ) ;
string help_text = "";
if( Arch::s390 () )
{
help_text = getMainHelptextS390();
}
else
{
help_text = getMainHelptext(Stage::initial());
}
// Main dialog: Header
string back_label = "";
string next_label = "";
if( Stage::initial () )
{
back_label = Label::BackButton();
next_label = Label::AcceptButton();
}
else
{
back_label = Label::QuitButton();
// button text
next_label = _("&Apply");
Wizard::HideAbortButton();
}
// heading text
Wizard::SetContentsButtons(_("Expert Partitioner"), contents, help_text,
back_label, next_label );
//////////////////////////////////////////////////////////////////
//// Loop for User Input ....
//////////////////////////////////////////////////////////////////
repeat
{
map<string,map> tg = Storage::GetTargetMap();
table_list = FillPartitionList(tg);
UI::ChangeWidget(`id(`table), `Items, table_list);
///////////////////////////////////////////////////////
// Now set the focus
// (only for "show_disk" cause I use the disk line)
if( show_disk )
{
UI::SetFocus( `id(`table));
focusline = Storage::GetLastUsed();
y2milestone( "focusline %1", focusline );
if( size(focusline)>0 )
{
UI::ChangeWidget(`id(`table), `CurrentItem, focusline);
}
}
ret = (symbol)Wizard::UserInput();
y2milestone( "USERINPUT: %1", ret);
if( ret==`show_table_details )
{
show_T_details = (boolean) UI::QueryWidget(`id(`show_table_details), `Value);
UI::ReplaceWidget( `id(`table_rp),
`Table( `id(`table), `opt(`notify,`keepSorting),
GetTableHeader(), [] ));
continue;
}
/////////////////////////////////////////////////////////////
//// CREATE
/////////////////////////////////////////////////////////////
else if( ret == `create)
{
string ddev = ChooseDisk( tg,
// popup text
_("Disk to Partition"),
`create );
if( ddev == nil || size(ddev)==0 )
{
ret = `again;
continue;
}
symbol create_type = `none;
map disk = tg[ddev]:$[];
list possibilities = CheckCreatePossibilities( ddev, disk );
y2milestone( "possibilities %1", possibilities );
boolean primary_is_possible = possibilities[0]:false;
boolean extended_is_possible = possibilities[1]:false;
boolean logical_is_possible = possibilities[2]:false;
symbol no_primary_cause = possibilities[3]:`no_space;
symbol no_extended_cause = possibilities[4]:`no_space;
symbol no_logical_cause = possibilities[5]:`no_space;
list log_slot = [];
list p_e_slot = [];
//////////////////////////////////////////////////////////
// Test if there is space left on the device
log_slot = GetLogicalSlot(ddev, disk);
y2milestone( "log_slot %1", log_slot );
p_e_slot = GetSlot(ddev, disk);
y2milestone( "p_e_slot %1", p_e_slot );
if ((log_slot == nil) && logical_is_possible )
no_logical_cause = `no_space;
if ((p_e_slot == nil) && primary_is_possible )
no_primary_cause = `no_space;
if ((p_e_slot == nil) && extended_is_possible)
no_extended_cause = `no_space;
if (log_slot == nil)
logical_is_possible = false;
if (p_e_slot == nil)
primary_is_possible = false;
if (p_e_slot == nil)
extended_is_possible = false;
/*----------------------------------------------------------------------
* Intel/Fdisk PPC/Fdisk
*
* At the same time is not possible, that both "logial_part_is_possible"
* and "extended_part_is_possible" are true
* so we have 6 possible situations
*
* to show this we use
* "P" for primary_part_is_possible
* "E" for extended_part_is_possible
* "L" for logial_part_is_possible
*
* "p" for primary_part_is_possible == false
* "e" for extended_part_is_possible == false
* "l" for logial_part_is_possible == false
*
*
* PE : I can create a primary or exended part.
* PL : Extended part. exist. I can create a primary or a logical
* Pel : only a priary is possible, when the extended part. has no space left
*
* pE : Not possible, if "E" is possible always "P" is possible too.
* pL : only a logical is possible, if together 4 primary and extended
* partitions are already created
* pel : no partitions are possible
*
* --------------------------------------------------------------------
*
* BSD-Labeling:
* "Pel" for primary_part_is_possible
* "pel" for primary_part_is_possible == false
*
*--------------------------------------------------------------------------*/
if( !primary_is_possible && !extended_is_possible &&
!logical_is_possible )
{
// ------pel--------
string text = "";
if( disk["label"]:"msdos" != "msdos" )
{
// popup text , %1 is replaced by a disk name e.g. /dev/hda
text = sformat( _("It is not possible to create a partition on %1."), ddev);
}
else
{
// popup text , %1 is replaced by a disk name e.g. /dev/hda
// %2 is replaced by an explanation
text = sformat( _("It is not possible to create a partition on %1.
%2
"), ddev,
FormatYouCannotCause( primary_is_possible,
extended_is_possible,
logical_is_possible,
no_primary_cause,
no_extended_cause,
no_logical_cause ));
}
Popup::Warning(text);
}
else if( !primary_is_possible && logical_is_possible )
{
//------pL----------
create_type = `logical;
}
else if( !primary_is_possible && extended_is_possible )
{
//------pE----------
create_type = `extended;
}
else if( primary_is_possible && !extended_is_possible &&
!logical_is_possible )
{
//------Pel----------
create_type = `primary;
}
else if ( primary_is_possible && extended_is_possible )
{
//------PE----------
create_type = ChoosePart("PE"); // ddev
}
else if ( primary_is_possible && logical_is_possible )
{
//------PL----------
create_type = ChoosePart("PL"); // popup
}
else
{
y2error("Error during partition check" );
create_type = ChoosePart("PEL"); // popup
}
if( create_type != `none )
{
list slot = (create_type!=`logical)?p_e_slot:log_slot;
y2milestone( "slot:%1", slot );
map r = Storage::NextPartition( disk["device"]:"",
create_type );
integer curr_nr = r["nr"]:0;
//---------------------------------------------------
// Present the Create-Popups ...
//---------------------------------------------------
string titleC = "";
// Popup Create Partition: Description of partition %1 is for example "/dev/hda"
if ( create_type == `primary ) titleC = sformat( _(" Create a Primary Partition on %1 "), ddev );
// Popup Create Partition: Description of partition %1 is for example "/dev/hda"
if ( create_type == `extended ) titleC = sformat( _(" Create an Extended Partition on %1 "), ddev );
// Popup Create Partition: Description of partition %1 is for example "/dev/hda"
if ( create_type == `logical ) titleC = sformat( _(" Create a Logical Partition on %1 "), ddev );
map<string,any> new_val =
$[
"create" : true,
"region" : [ slot[0]:0, slot[1]:0 - slot[0]:0+1 ],
"type" : create_type,
"nr" : curr_nr,
"device" : r["device"]:""
];
if( create_type == `extended )
{
new_val = (map<string,any>)union( new_val ,
$[
"fsid" : Partitions::fsid_extended_win,
"used_fs" : `unknown,
]);
new_val =
(map<string,any>)CreateEditExtendedPartDlg( new_val,
titleC,
ddev,
disk,
disk["cyl_size"]:1000000,
false,
bsd_label );
}
else
{
string mount_point_proposal =
GetMountPointProposal( Storage::GetTargetMap(), [] );
symbol used_fs = Partitions::DefaultFs();
if( mount_point_proposal == Partitions::BootMount() )
{
used_fs = Partitions::DefaultBootFs();
}
new_val =
(map<string,any>)union( new_val,
$[
"format" : true,
"fsid" : Partitions::fsid_native,
"mount" : mount_point_proposal,
"used_fs": used_fs,
]);
if( Mode::repair() )
{
new_val["format"] = false;
new_val["mount" ] = "";
}
new_val = EditOrCreatePartDlg( new_val,
FileSystems::GetAllFileSystems(true, true ),
titleC, disk,
bsd_label, edit_cylinder,
disk["cyl_size"]:1000000,
Stage::initial() );
}
if (new_val != nil)
{
// set focus to new partition
focusline = new_val["device"]:"";
Storage::CreatePartition( disk["device"]:"",
new_val["device"]:"",
new_val["type"]:`primary,
new_val["fsid"]:Partitions::fsid_native,
new_val["region",0]:0,
new_val["region",1]:0 );
Storage::ChangeVolumeProperties( new_val );
}
}
}
///////////////////////////////////////////////////////////////
//// EDIT
///////////////////////////////////////////////////////////////
if( ret == `edit || ret == `table )
{
map<string,any> part = $[];
string id = "";
id = (string)UI::QueryWidget(`id(`table), `CurrentItem);
// notify a line is selected
if( id != nil )
{
focusline = id;
if( !haskey( tg, id ) )
part = Storage::GetPartition( tg, id );
y2milestone( "current partition %1", part );
if( size(part)==0 )
{
if( tg[id,"type"]:`CT_UNKNOWN == `CT_LVM )
{
ret = `lvm;
}
else
{
TargetAllocationDlg(tg[id]:$[], id );
}
}
else if( part["type"]:`unknown == `lvm )
{
HandleEditLv( tg, id );
}
else if( part["type"]:`unknown == `sw_raid )
{
RaidExpertDlg( `settings, id, part,
FileSystems::GetAllFileSystems(true,true),
false, tg );
}
else if( part["type"]:`unknown == `evms )
{
map ad = edit_evms_volume( id, tg );
// has the user cancelled the dialog?
if( ad["ok"]:false && size( ad["targets"]:$[] )>0 )
{
Storage::SetTargetMap( ad["targets"]:$[] );
}
}
else if( part["type"]:`unknown == `loop )
{
ret = `loop_edit;
}
else
{
map new_val = $[];
map<string,any> disk = Storage::GetDisk( tg, id );
/////////////////////////////////////////////////////
// check if the partition can be deleted
if( !check_device_edit( part, bsd_label))
{
ret = `again;
continue;
}
list<map> partitions_without_current =
filter( map p, disk["partitions"]:[],
``(p["nr"]:(any)0!=part["nr"]:(any)0 ));
map<string,any> disk_without_current =
add( disk, "partitions", partitions_without_current);
//////////////////////////////////////
// There are three different Editors:
// - "normal"
// - extended
// - already existing
if( part["type"]:`primary == `extended )
{
if( part["create"]:false )
{
// header of the dialog edit a partition
string title = _("Edit an Extended Partition") +
" " + part["device"]:"";
new_val = CreateEditExtendedPartDlg( part,
title,
part["device"]:"",
disk_without_current,
disk["cyl_size"]:1000000,
true,
bsd_label
);
}
else
{
// error popup text
Popup::Error( _("An already-existing extended partition cannot be changed.
Delete this partition then create a new one using
the new parameters.
All data on this partition will be lost if you delete it."));
new_val = nil;
}
}
else
{
string title = "";
if( !part["create"]:false )
{
// header of the dialog to edit a partition %1 is replaced by device name (e.g. /dev/hda1)
title = sformat( _("Edit Existing Partition %1"),
part["device"]:"" );
if( part["type"]:`primary != `primary &&
part["type"]:`primary != `logical )
title = sformat( _("Edit Existing Device %1"),
part["device"]:"" );
}
else
{
// header of the dialog to edit a partition %1 is replaced by device name (e.g. /dev/hda1)
title = sformat( _("Edit Partition %1"),
part["device"]:"" );
}
new_val =
EditOrCreatePartDlg( part,
FileSystems::GetAllFileSystems(true, true) ,
title,
disk_without_current,
bsd_label, edit_cylinder,
disk["cyl_size"]:1000000,
Stage::initial() );
}
if( new_val != nil && size(new_val)>0 ) // not canceld
{
if( new_val["create"]:false )
Storage::UpdatePartition( new_val["device"]:"",
new_val["region",0]:0,
new_val["region",1]:0 );
if( !disk["readonly"]:false )
Storage::SetPartitionId( new_val["device"]:"",
new_val["fsid"]:Partitions::fsid_native );
Storage::ChangeVolumeProperties( new_val );
}
}
}
else
{
// popup text
Popup::Message(_("Select the partition to edit in the main dialog.") );
}
}
/////////////////////////////////////////////////////////////
// DELETE
/////////////////////////////////////////////////////////////
if (ret == `delete)
{
map<string,any> part = $[];
string id = (string)UI::QueryWidget( `id(`table), `CurrentItem);
map<string,any> disk = Storage::GetDisk( tg, id );
if( !haskey( tg, id ) )
part = Storage::GetPartition( tg, id );
y2milestone( "id:%1 part:%2", id, part );
if( !haskey( tg, id ) && size(part)==0 )
{
ret = `again;
continue;
}
if( disk["readonly"]:false )
{
Popup::Error( Partitions::RdonlyText( disk["device"]:"", true ));
ret = `again;
continue;
}
if( haskey( tg, id ) )
{
if( tg[id,"type"]:`CT_UNKNOWN == `CT_MD )
{
ret = `again;
continue;
}
else if( tg[id,"type"]:`CT_UNKNOWN == `CT_LVM )
{
string current_vg = substring( tg[id,"device"]:"", 5 );
HandleRemoveVg( tg, current_vg );
}
else if( tg[id,"type"]:`CT_UNKNOWN == `CT_DMRAID )
{
if( Popup::YesNo( sformat(_("Really delete BIOS RAID %1?"), id )))
{
if( deleteAllDevPartitions( disk, Stage::initial(), bsd_label ))
Storage::DeleteDmraid( id );
}
}
// YesNo popup text %1 is replaced by a disk name e.g. /dev/hda
else if( Popup::YesNo( sformat(_("Really delete all partitions on %1?"), id )))
{
focusline = id;
deleteAllDevPartitions( disk, Stage::initial(), bsd_label );
}
}
else if( part["type"]:`unknown==`lvm )
{
if( !check_device_delete( part, false, Stage::initial()))
{
ret = `again;
continue;
}
else
HandleRemoveLv( tg, id );
}
else
{
/////////////////////////////////////////////////////
// delete algorithm:
// if you find newly created (but until now not realy
// written) partition (sign: "create = true"): delete it
// else there must be already existing partition: mark it
// with "delete = true"
focusline = id;
y2milestone( "delete part %1", part );
/////////////////////////////////////////////////////
// check if the partition can be deleted
if( part["type"]:`primary == `extended &&
!check_extended_delete( disk, Stage::initial() ))
{
ret = `again;
continue;
}
if( part["type"]:`primary != `extended &&
!check_device_delete( part, bsd_label, Stage::initial()))
{
ret = `again;
continue;
}
/////////////////////////////////////////////////////
// now delete partition!!
// YesNo popup text, %1 is replaced by a device name e.g. /dev/hda1
if( Popup::YesNo( sformat(_("Really delete %1?"),
part["device"]:"" )))
{
if( search( id, "/dev/loop")==0 && size(part["fpath"]:"")>0 &&
Mode::normal() &&
// YesNo popup. %1 is path to a file
Popup::YesNo( sformat(_("\nShould the loop file %1 also be removed?
"), part["fpath"]:"" )))
{
Storage::DeleteLoop( disk["device"]:"",
part["fpath"]:"", true );
}
else
{
Storage::DeleteDevice( disk["device"]:"",
part["device"]:"" );
}
focusline = Storage::GetIdSmaller( disk["device"]:"",
part["nr"]:0 );
}
if( search( id, "/dev/md" )==0 )
{
map raid = Storage::GetDisk( Storage::GetTargetMap(), "/dev/md" );
UI::ReplaceWidget( `id(`raid_button),
RaidButton(size(raid["partitions"]:[])) );
}
else if( search( id, "/dev/loop" )==0 )
{
map dev = Storage::GetDisk( Storage::GetTargetMap(), "/dev/loop" );
UI::ReplaceWidget( `id(`loop_button),
LoopButton(size(dev["partitions"]:[])) );
}
}
}
/////////////////////////////////////////////////////////////
// RESIZE
/////////////////////////////////////////////////////////////
if (ret == `resize)
{
string id = (string)UI::QueryWidget(`id(`table), `CurrentItem);
focusline = id;
map part = $[];
map disk = Storage::GetDisk( tg, id );
if( !haskey( tg, id ) )
part = Storage::GetPartition( tg, id );
if( disk["readonly"]:false )
{
Popup::Error( Partitions::RdonlyText( disk["device"]:"", true ));
ret = `again;
continue;
}
y2milestone( "disk=%1", disk );
y2milestone( "RESIZE id=%1 part=%2", id, part );
map possible = Storage::IsResizable( part );
if( size(part)==0 ||
part["used_by_type"]:`UB_NONE == `UB_LVM ||
part["used_by_type"]:`UB_NONE == `UB_MD ||
part["type"]:`unknown == `sw_raid ||
part["type"]:`unknown == `loop ||
part["type"]:`unknown == `dm )
{
// popup text
Popup::Message(_("
You cannot resize a disk device, LVM volume group, LVM physical volume,
or MD device.
"));
}
else if( !part["format"]:false &&
!possible["extend"]:false && !possible["shrink"]:false )
{
// popup text
Popup::Message(_("
You cannot resize the selected partition because the file system
on this partition does not support resizing.
"));
}
else if( part["type"]:`unknown == `lvm )
{
HandleEditLv( tg, id );
}
else
{
map new_val = part;
if( Mode::normal() && new_val["used_fs"]:`none == `ntfs )
{
Package::InstallAll( ["ntfsprogs"] );
}
string dev = new_val["device"]:"";
if( new_val["ori_nr"]:0 > 0 &&
new_val["ori_nr"]:0 != new_val["nr"]:0 )
{
dev = Storage::GetDeviceName( disk["device"]:"", new_val["ori_nr"]:0 );
}
new_val = ResizePartDlg( new_val, dev, disk, possible );
if( new_val != nil )
{
integer size_change = part["region",1]:0 -
new_val["region",1]:0;
y2milestone( "region old=%1 new:%2", part["region"]:[],
new_val["region"]:[] );
y2milestone( "size_change=%1", size_change );
tg = Storage::SetPartition( tg, new_val );
Storage::SetTargetMap(tg);
if( size_change != 0 &&
Storage::CheckNextCreated( disk,
part["region"]:[0,0] ))
{
if( size_change < 0 )
{
// popup text
Popup::Message( _("
You decreased the size available for Linux partitions.
Linux partition sizes have been adapted accordingly.
Check the new sizes in the partition list.
"));
Storage::AdaptResize( disk["device"]:"",
part["region"]:[0,0],
size_change );
}
// popup text
else if( Popup::YesNo( _("
You decreased a partition that is followed by a newly-created partition.
Should the newly-created partition be automatically increased to use the
freed disk space?
")) )
{
Storage::AdaptResize( disk["device"]:"",
part["region"]:[0,0],
size_change );
}
}
}
}
}
boolean ask_reread = true;
/////////////////////////////////////////////////////////////
// Delete partition table and disk label
/////////////////////////////////////////////////////////////
if( ret == `delete_parttable )
{
string ddev = ChooseDisk( tg,
// heading text
_("Delete Partition Table"), `delete );
// not cancel
if( ddev != nil )
{
DDZeroPartitionTable(ddev);
}
}
if( Arch::s390 () && ret==`dasdfmt )
{
string id = (string)UI::QueryWidget(`id(`table), `CurrentItem);
map disk = tg[id]:$[];
y2milestone( "dasdfmt disk:%1", id );
if( haskey( tg, id ) && search( id, "/dev/dasd")==0 )
{
if( !disk["dasdfmt"]:false)
{
// popup text %1 is replaced by a dasd name e.g. /dev/dasda
boolean yn = Popup::YesNo(sformat(
_("Running dasdfmt deletes all data on the disk.
Really execute dasdfmt on disk %1?
"),id));
y2milestone( "yn=%1", yn );
if( yn )
{
Storage::InitializeDisk( id, true );
}
}
else
{
Popup::Message( _("The disk is no longer marked for dasdfmt.
Partitions currently present on this disk are again
displayed.
") );
Storage::InitializeDisk( id, false );
}
}
else
{
// popup text
Popup::Error( _("No DASD disk selected.
Select the DASD disk on which dasdfmt should be executed."));
}
}
/////////////////////////////////////////////////////////////
// REREAD
/////////////////////////////////////////////////////////////
if (ret == `reread)
{
boolean ret2 = true;
if( ask_reread )
// popup text
ret2 = Popup::YesNo(_("Rereading the partition table cancels all current changes. Really reread the partition table?"));
if( ret2 )
{
Storage::ReReadTargetMap();
}
}
/////////////////////////////////////////////////////////////
// Raid
/////////////////////////////////////////////////////////////
if( ret == `raid_wizard )
{
if( !check_raid_possible( tg ))
{
ret = `again;
continue;
}
}
if( ret == `loop_edit || ret == `loop_create )
{
string id = (string)UI::QueryWidget( `id(`table), `CurrentItem );
Storage::SetWizardKey( id );
if( ret == `loop_edit )
{
if( search( id, "/dev/loop" )!=0 )
{
// popup text
Popup::Message( _("Select a loop device entry.") );
ret = `again;
continue;
}
}
LoopSetup( ret==`loop_edit );
if( ret==`loop_create )
{
map dev = Storage::GetDisk( Storage::GetTargetMap(), "/dev/loop" );
UI::ReplaceWidget( `id(`loop_button),
LoopButton(size(dev["partitions"]:[])) );
}
}
/////////////////////////////////////////////////////////////
// LVM
/////////////////////////////////////////////////////////////
if (ret == `lvm)
{
if( !check_lvm_possible( tg ) )
{
ret = `again;
continue;
}
else if( Mode::normal () )
{
Package::InstallAll( ["lvm2"] );
}
}
/////////////////////////////////////////////////////////////
// Adapt mount points from existing /etc/fstab
/////////////////////////////////////////////////////////////
if (ret == `adapt_mp && Stage::initial() )
{
map<string,map> od = (map<string,map>)Storage::GetOndiskTarget();
list<list> fstab = scanAndReadExistingFstab( od );
y2milestone( "adapt_mp fstab %1", fstab );
list ti = maplist( list e, fstab,
``(AddFstabToData( od, (list<map>)e)[1]:$[]));
y2milestone( "adapt_mp ti %1", ti );
integer idx = FstabAddDialog( ti );
if( idx>=0 )
{
od = (map<string,map>)Storage::GetOndiskTarget();
y2milestone( "adapt_mp use fstab idx %1", idx );
ti = AddFstabToData( od, (list<map>)fstab[idx]:[] );
Storage::ResetOndiskTarget();
foreach( string d, map disk, ti[0]:$[],
``{
foreach( map p, disk["partitions"]:[],
``{
if( size(p["mount"]:"")>0 && p["enc_type"]:`none!=`none )
{
string pwd = DlgCreateCryptFs( p["device"]:"", 5, false );
if( pwd != nil && size(pwd)>0 )
Storage::SetCryptPwd( p["device"]:"", pwd );
}
});
});
Storage::SetTargetMap( ti[0]:$[] );
}
}
/////////////////////////////////////////////////////////////
// End of Actions, Now check the returncode
/////////////////////////////////////////////////////////////
if (ret == `next || ret == `back || ret == `raid || ret == `lvm ||
ret == `raid_settings || ret == `raid_wizard || ret == `evms )
{
symbol doagain = `next;
if( ret == `raid_wizard || ret == `raid_settings )
{
if( Storage::CheckBackupState("raid"))
Storage::DisposeTargetBackup("raid");
}
if( ret == `back &&
!Storage::EqualBackupStates( "custom_part", "", true ))
{
// popup text %1 will be replaces with button text
string txt = sformat( _("You have changed the partitioning.
These changes are lost if you exit the main dialog with %1.
Really quit the main dialog?
"),
deletechars(back_label,"&") );
if( !Popup::YesNo( txt ))
{
doagain = `again;
}
}
if( ret == `next )
{
boolean changed =
!Storage::EqualBackupStates( "custom_part", "", true );
y2milestone( "CheckNext ret=%1 changed=%2", ret, changed );
if( changed )
{
Storage::SetPartMode( "CUSTOM" );
}
}
if ( ret == `next )
{
list retval = check_created_partition_table( Storage::GetTargetMap(), true,
Stage::initial()&&!Mode::repair() );
Storage::SetTargetMap( retval[0]:$[] );
doagain = retval[1]:`next;
}
if( (ret==`abort || ret==`back || ret==`next) && doagain!=`again )
{
Storage::DisposeTargetBackup("custom_part");
}
if( doagain == `again ) ret = `again;
if( ret != `back )
{
if (ret == `apply) return `again;
}
if( (ret == `back||ret==`abort) && Storage::GetPartMode()=="NORMAL" )
{
Storage::SetPartMode( "CUSTOM" );
}
}
Storage::SetLastUsed( focusline );
y2milestone( "end main loop ret %1 focusline %2", ret, focusline );
} until (ret == `next || ret == `back || ret == `cancel ||
ret == `raid_wizard || ret == `raid_settings ||
ret == `evms ||
ret == `lvm || ret == `lvmlv || ret == `abort );
Wizard::RestoreNextButton();
if( (ret == `lvm || ret == `raid_wizard || ret == `raid_settings ||
ret == `evms) &&
!Stage::initial () )
{
Wizard::RestoreBackButton();
}
Storage::SetExpertDetail( show_T_details );
Storage::SaveExpertDetail();
Wizard::RestoreHelp( help_text );
SCR::Write(.target.ycp, Storage::SaveDumpPath("targetMap_e"),
Storage::GetTargetMap() );
//next by installation
if( Stage::initial () && ret == `next )
ret = `instnext;
//next in existing system
if( !Stage::initial () && ret == `next )
ret = `sysnext;
if( ret == `back )
ret = `backtoi;
if( ret == `raid_settings || ret == `raid_wizard )
Storage::Record();
return ret;
}