home *** CD-ROM | disk | FTP | other *** search
Text File | 2006-11-29 | 39.0 KB | 1,397 lines |
- /**
- * File:
- * OSRPtbl.ycp
- *
- * Module:
- * YaST OS Repair. Automatic error detection & repair tool for Linux.
- *
- * Summary:
- * YaST OS Repair. Automatic error detection & repair tool for Linux.
- *
- * Author:
- * Johannes Buchhold <jbuch@suse.de>
- *
- * $Id: OSRPtbl.ycp 24138 2005-07-18 15:30:14Z jsuchome $
- */
- {
- module "OSRPtbl";
-
- import "OSRExecute";
- import "OSRFloppy";
- import "OSRPopup";
- import "OSRCommon";
-
- import "Storage";
- import "StorageDevices";
- import "Mode";
- import "Report";
-
- import "Label";
- import "Popup";
-
- include "partitioning/partition_defines.ycp";
-
- textdomain "repair";
-
-
- string s_ignore_label = _("Ignore");
- string s_recover_label = _("Recover");
-
-
- define string floppy_help_text ();
- define string gpart_help_text ();
- define string original_help_text ();
-
- define symbol restore_from_floppy ();
- define symbol restore_original();
- define symbol expert_restore_with_gpart ();
- global define symbol RestoreWithGpart ();
-
- /**
- * All repair methods
- */
- map repair_methods = $[
- `floppy : $[
- "header" : _("&Copy Saved Partition Table from Floppy"),
- "help" : floppy_help_text,
- "method" : restore_from_floppy
- ],
- `gpart : $[
- "header" : _("Have &gpart Suggest Partition Table"),
- "help" : gpart_help_text,
- "method" : RestoreWithGpart,
- "default" : true
- ],
- `gpart_e : $[
- "header" : _("Have g&part Suggest Partition Table (Expert Mode)"),
- "help" : gpart_help_text,
- "method" : expert_restore_with_gpart,
- "default" : true
- ],
- `original : $[
- "header" : _("&Restore Original Partition Table"),
- "help" : original_help_text,
- "method" : restore_original,
- "enabled" : false
- ]
- ];
-
- /**
- * The harddisk name. e.g.: /dev/hda
- */
- string target = "";
-
- /**
- * The path of the harddisk (for fdisk calls). e.g.: .dev.hda.
- */
- path target_scrpath = .;
-
-
- /**
- * At the first call of the OSRPtbl module the constructor saves all
- * mbr's to the YaST"2.tmp Directory. The names of the randomly
- * created mbr files are stored in the map backup_dev_filenames.
- */
- map backup_dev_filenames = $[];
-
-
- /**
- * backup_mbr_status is true, if all mbr's are successfully stored
- * to the tmp directory.
- */
- boolean backup_mbr_status = false;
-
-
- /**
- * Expert options for gpart
- */
- string gpart_expert_options = "";
-
-
- global define void Reset()``{
- target = "";
- target_scrpath = .;
- gpart_expert_options = "";
- }
-
- global define void OSRPtbl()``{
-
- if (! StorageDevices::FloppyPresent )
- {
- // filter floppy repair methode
- y2milestone("filter floppy repair methode. No floppy found");
- repair_methods = filter (symbol r, map<any,any> d, (map<symbol,map<any,any> >)repair_methods, ``(
- r != `floppy ));
- }
- }
-
- /**
- * Help text for the floppy repair method.
- */
- define string floppy_help_text() ``{
- //%1 is device label, such as /dev/hda
- return sformat(_("
- <p><h3>No Partition Table Found for Hard Disk %1</h3></BR>
-
- The repair system will search for a valid partition table of disk %1
- on the inserted floppy disk. If it cannot find
- one, it will start the program gpart to guess the lost
- partition table. You can decide if the information gpart
- finds is valid for your system.</p>
- "),target ) +
-
- _("<p>gpart may be of some help when the primary partition table
- has been lost or destroyed, but it can, under no circumstances,
- replace proper disk and partition table backups. To save the
- master boot record (MBR) including the primary partition
- table to the file /tmp/hda.mbr, enter the command
-
- <pre>
- dd if=/dev/hda of=/tmp/hda.mbr bs=512 count=1
- </pre>
-
- replacing /dev/hda with the block device name of the disk
- in question. This should be done for all disks in the system.
- To restore the primary partition table without overwriting
- the MBR, enter
-
- <pre>
- dd if=/tmp/hda.mbr of=/dev/hda bs=1 count=64 skip=446 seek=446
- </pre></p>
- ") +
-
- _("<p>Warning: Make sure that all parameters are entered as shown
- and the disk device is correct. Failing to do so may
- result in severe corruption of the file system. The saved file
- should be stored in a safe place like a floppy disk.</p>
- ") +
-
- _("<p>From the manual page of gpart:<br>
- \"It should be stressed that gpart does a very heuristic
- job, never believe its output without any plausability
- checks. It can be easily right in its guesswork but it can
- also be terribly wrong. You have been warned.\"</p>");
-
- };
-
- /**
- * Help for gpart
- */
- define string gpart_help_text()``{
- //%1 is device label, such as /dev/hda
- return sformat(_("
- <P><h3>No Partition Table Found for Hard Disk %1</h3><BR>
-
- The repair system will start gpart to guess the primary partition
- table of disk %1.</p>
- "), target) +
-
- _("<p>gpart may be of some help when the primary partition table
- was lost or destroyed, but it can, under no circumstances,
- replace proper disk and partition table backups. To save the
- master boot record (MBR) including the primary partition
- table to the file /tmp/hda.mbr, enter
-
- <pre>
- dd if=/dev/hda of=/tmp/hda.mbr bs=512 count=1
- </pre>
-
- replacing /dev/hda with the block device name of the disk
- in question. This should be done for all disks in the system.
- To restore the primary partition table without overwriting
- the MBR, enter
-
- <pre>
- dd if=/tmp/hda.mbr of=/dev/hda bs=1 count=64 skip=446 seek=446
- </pre></p>
- ") +
-
- _("<p>Warning: Make sure that all parameters are typed as shown
- and the disk device is correct. Failing to do so may
- result in severe corruption of the file system. The saved file
- should be stored in a safe place like a floppy disk.</p>
- ") +
-
- _("<p>From the manual page of gpart:<br>
- \"It should be stressed that gpart does a very heuristic
- job, never believe its output without any plausability
- checks. It can be easily right in its guesswork but it can
- also be terribly wrong. You have been warned.\"</p>");
-
- }
-
-
- /**
- * Help text for restoring orginal mbr's
- */
- define string original_help_text()``{
- //%1 is device label, such as /dev/hda
- return sformat(_("
- Before starting any scan or repair sequence,
- a backup of the original partition table
- of the device %1 is created.
- "), target );
-
- }
-
- /**
- * Save all mbr's to tmp directory and saves the path names
- * in the map backup_dev_filenames.
- */
- define void SavePtbl()``{
- y2milestone("Saving all mbr's to tmp directory");
-
- // save all current ptbl's to tmp directory
- map<string,map> tg = filter( string k, map disk, Storage::GetTargetMap(), ``(Storage::IsRealDisk(disk)));
- list<string> devlist = maplist( string k, map disk, tg, ``(k));
-
- if (devlist != nil && devlist != [] ) {
- integer ok = 0;
- foreach(string dev, devlist, ``{
-
- // build mbr backup string
- string randompart = sformat("%1/%2_%3.mbr",
- WFM::Read(.local.tmpdir,"" ),
- mergestring(splitstring(dev,"/"),"_") ,
- random(100000));
-
- if (OSRExecute::Command(.local.bash, sformat("/bin/dd if=%1 of=%2 count=1 bs=512",dev,randompart ))){
- ok =ok+1;
- backup_dev_filenames[dev] = randompart;
- }
- });
-
- if (ok == size(devlist)) backup_mbr_status = true;
- }
- else {
- y2error("Emtpy devive list. No harddisk found.");
- }
- }
-
- /**
- * Check reparired mbr.
- */
- define boolean CheckRestoredPtbl(string target) ``{
- y2milestone("checking restored ptl");
-
- list partition_table = Storage::GetTargetMap()[target,"partitions"]:[];
-
- if ((partition_table != nil) && (partition_table != []))
- {
- y2milestone("restoring was successful. Reread Storage");
- // o.k., partition table successfully reverted.
- Storage::ReReadTargetMap();
- // popup message
- Report::Message(_("
- Partition table successfully repaired.
- "));
- return true;
- }
- else {
- // popup message
- Report::Message(_("
- Partition table was not successfully repaired.
- "));
- }
- return false;
- }
-
- /**
- * Build the file name for reading partition list from floppy.
- */
- define string build_file_name( string key )``{
- return sformat("%2/%1",mergestring(splitstring(key, "/"),"_") , OSRFloppy::mount_point);
- }
-
- /**
- * Need mounted floppy
- */
- define list<map> read_part_list_from_floppy(string target)``{
- return (list<map>) WFM::Read(.local.ycp, build_file_name(target)+".ycp");
- }
-
- /**
- * Show
- */
- define list<map> FoundPtblDialog (list<map> partitions, string dev, string repair_tool, boolean whole_mbr )``{
-
- y2milestone("Found partitions for recovering %1", partitions );
-
- string label_status = _("Status");
- string label_name = _("Name");
- //File System ID
- string label_fsid = _("FSID");
- string label_start = _("Start");
- string label_end = _("End");
- string label_size = _("Size");
- string label_whole = _("Restore the Entire Master Boot Record");
-
- list<term> items = [];
- foreach (map n,partitions, {
-
- if (n["region",1]:0 != 1)
- {
- map mdev = Storage::GetTargetMap()[dev]:$[];
- items = add (items, `item (`id(sformat("%1", n["nr"]:1)),
- s_ignore_label,
- dev + n["nr"]:1,
- n["fsid"]:131,
- sformat ("%1", n["region",0]:0),
- sformat ("%1", n["region",1]:0 + n["region",0]:0 - 1),
- ByteToHumanString (n["size_k"]:0 * 1024)
- ));
- }
- });
-
- // help_text first sentence.
- string help_text = _("<P>The table in the center of the dialog shows the partitions
- that could be recovered.</P>
- ") +
-
- // %1 is Ignore label
- OSRPopup::build_label_description( OSRPopup::ignore_label, sformat(_("Change the status of a partition to %1."), s_ignore_label )) +
- // %1 is Recover label
- OSRPopup::build_label_description( OSRPopup::recover_label, sformat(_("Change the status of a partition to %1."), s_recover_label)) +
-
- //%1 is Recover label
- OSRPopup::build_label_description( OSRPopup::repair_label, sformat(_("If you have changed the status of all partitions for recovering
- to %1, press Repair to execute the recovery process.
- "), s_recover_label)) +
-
- // help_text description for table column, %1 ignore, %2 recover
- OSRPopup::build_label_description( label_status, sformat(_("The status of a listed partition
- can be switched between %1 and %2. Only
- partitions with the status
- %2 are recovered.
- "), s_ignore_label, s_recover_label )) +
-
- OSRPopup::build_label_description( label_name, _("Name of the partition that could be
- recovered.
- ")) +
-
- OSRPopup::build_label_description( label_fsid, _("The file system ID of the partition.
- For example, 131 is a normal Linux partition and 6, 11, 12, and 14 are fat and fat32 partitions.
- ")) +
-
- OSRPopup::build_label_description( label_start, _("The start cylinder of the partition.")) +
-
- OSRPopup::build_label_description( label_end, _("The end cylinder of the partition.")) +
-
- OSRPopup::build_label_description( label_size, _("Size of the partition."));
-
- term whole_term = `Empty();
- if (whole_mbr )
- {
- whole_term = `Left(`CheckBox(`id(`whole_mbr), `opt(`notify), label_whole ,false));
- OSRPopup::build_label_description( label_whole, _("Select this option to
- recover the entire master boot record with all partitions.
- "));
- }
-
-
- // dialog caption
- OSRPopup::OpenSuggestDialog(_("Recover Lost Partitions"),
- // dialog text, %1 is device label
- sformat(_("
- The following partitions were found on device %1.
- To recover a partition, select the entry
- in the table and press Recover.
- "), dev),
- help_text,
- `VBox(`Table(`id(`table), `header(label_status, label_name, label_fsid, label_start, label_end, label_size ), items ),
- `Left(`HBox(
- `PushButton(`id(`ignore), OSRPopup::ignore_label ),
- `PushButton(`id(`recover), OSRPopup::recover_label )
- )),
- whole_term
- ),
- 40);
- UI::SetFocus(`id(`table));
-
- any ret = `ok;
- list<map> recover = [];
- repeat
- {
- ret = UI::UserInput();
-
- string current_item = (string)UI::QueryWidget(`id(`table),`CurrentItem);
- term it = (term) UI::QueryWidget (`id(`table), `Item (current_item));
- string current_value = it[1]:"";
-
- map current_part = find (map part, partitions, ``(
- sformat("%1", part["nr"]:"") == current_item ));
-
- if (current_part == nil || current_part == $[] )
- y2error(" partition not found");
-
- if (ret == `ignore )
- {
- if (current_part["type"]:`unknown == `extended )
- {
- foreach (map part,
- filter (map p, partitions,``(p["type"]:`unknown==`logical)),
- ``{
- UI::ChangeWidget(`id(`table),
- `Item(sformat("%1", part["nr"]:""), 0), s_ignore_label);
- });
- }
- UI::ChangeWidget(`id(`table),`Item(current_item, 0),s_ignore_label);
- }
- if (ret == `recover )
- {
- if (current_part["type"]:`unknown == `logical )
- {
- map extended = find (map part, partitions, ``(
- part["type"]:`unknown == `extended ));
- UI::ChangeWidget(`id(`table),
- `Item(sformat("%1", extended["nr"]:""), 0),s_recover_label);
- }
- UI::ChangeWidget(`id(`table),`Item(current_item,0),s_recover_label);
- }
- if (ret == `whole_mbr )
- {
- UI::ChangeWidget(`id(`table), `Enabled,
- !(boolean) UI::QueryWidget(`id(`whole_mbr), `Value ));
- }
-
- if ( ret == `ok )
- {
- recover = filter (map n, partitions, {
- term it = (term) UI::QueryWidget (
- `id(`table), `Item(sformat("%1", n["nr"]:1)));
- return (it[1]:"" == s_recover_label);
- });
-
- y2milestone( "all selected items %1", recover );
-
- if (whole_mbr )
- {
- if ((boolean)UI::QueryWidget(`id(`whole_mbr ), `Value ))
- recover = [ $["whole_mbr":$[]] ];
- }
- }
- } until( ret == `ok || ret == `cancel );
-
- UI::CloseDialog();
- return recover;
- }
-
-
- /**
- * Call fdisk
- */
- define boolean fdisk_call(string disk_dev, list<map> torecover )``{
-
- UI::OpenDialog(`VBox(`VSpacing(1),
- `Label(_("Recovering partition table...")),
- `VSpacing(1)));
-
- boolean result = true;
-
- if (! Mode::test () )
- {
- /////////////////////////////////////////////////////
- map<string,map> tg = Storage::GetTargetMap();
- tg[disk_dev,"partitions"] = torecover;
- Storage::SetTargetMap(tg);
- Storage::CommitChanges();
- /////////////////////////////////////////////////////
- repair_methods[ `original, "enabled"] = true;
-
- Storage::ReReadTargetMap();
- }
- else {
- y2milestone("fdisk call not executed. Mode::test () = true !!!");
- }
-
- UI::CloseDialog();
-
- return result;
- };
-
-
-
-
- /**
- * Restore lost mbr with a backup from floppy.
- */
- define symbol restore_from_floppy( )``{
-
- //%1 is device label, such as /dev/hda
- string error_message_start = sformat(_("No primary partition table was found on hard disk %1."), target );
- //%1 is device label, such as /dev/hda
- string error_message = sformat(_("
-
- If you have a floppy with some
- up-to-date system information from a former rescue
- session, insert it in your drive and press Repair.
-
- Press Skip and repair manually if you have a
- backup of the partition table of disk %1.
-
- Press Help to learn how to
- make a backup of a partition table manually
- and how to restore it.
- "), target);
-
-
- // this can't be repaired without a floppy drive, so the user must not be asked again
- // to repair via floppy
- if (! OSRCommon::RequireBoolean("has_floppy"))
- {
- // display that no floppy drive was detected
- Report::Message(_("
- Cannot detect a floppy drive
- in your system. A backup copy of the
- primary partition table could not be
- read.
- "));
- return `error;
- }
- else {
- if (! OSRPopup::Repair(_("Error Detected"), error_message_start + error_message, floppy_help_text())) return `cancel;
-
- if (OSRFloppy::Open(true, 2))
- {
- OSRFloppy::NextStep(_("Searching for partition table..."));
- list<map> found_partitions = read_part_list_from_floppy(target);
- list to_recover = [];
-
- if (found_partitions != nil && found_partitions != [] ) {
- to_recover = FoundPtblDialog(found_partitions, target, "Floppy", true );
-
- boolean revert = false;
-
- if (size(to_recover ) == 0 ) {
- Report::Warning(_("
- Could not find a valid partition table.
- Insert another floppy disk and
- try again or have gpart suggest a
- partition table.
- "));
- OSRFloppy::Close();
- return `cancel;
- }
- else if (haskey( to_recover[0]:$[], "whole_mbr")) {
-
- y2milestone("recover the whole mbr");
-
- if (WFM::Read(.local.size, build_file_name(target)+".mbr" ) == 512 )
- {
- OSRFloppy::NextStep(_("Restoring old partition table..."));
-
- // copy the backup of the primary partition table to the target device
- revert = OSRExecute::Command(.local.bash,
- sformat("/bin/dd if=%1.mbr of=%2 bs=1 count=512", build_file_name(target ),target ));
-
- // call block device ioctls: reread the partition table (important after having
- // changed the partition table!)
- OSRExecute::Command(.target.bash, sformat("/sbin/blockdev --rereadpt %1", target));
- }
- else {
- Report::Error(_("
- Could not find a valid master boot
- record on the floppy disk. Insert
- another floppy disk and try again or
- have gpart suggest the partition table.
- "));
- OSRFloppy::Close();
- return `error;
- }
- }
-
- OSRFloppy::Close();
-
- if (! haskey( to_recover[0]:$[], "whole_mbr") ) {
- list<map> new_to_recover = [];
- foreach(map<string,any> p, (list<map<string,any> >)to_recover, ``{
- p["create"] = true;
- new_to_recover = add(new_to_recover, p);
- });
- revert = fdisk_call( target, new_to_recover );
- }
-
- if (revert )
- {
- if (CheckRestoredPtbl(target) ) {
- return `ok;
- }
- }
-
- // error message
- Report::Error(_("
- Restoring the partition table
- was not successful.
- Insert another floppy disk
- and try again or have gpart
- suggest the partition table.
- "));
- return `error;
- }
- }
- else
- {
- // error message
- Report::Error (_("
- Either no floppy disk is inserted in
- the drive or the inserted floppy is not
- correctly formatted. Insert
- another floppy disk and try again or
- have gpart suggest the partition table.
- "));
- }
-
- OSRFloppy::Close();
- }
- return `cancel;
- }
-
- /**
- * Cat the fsid from a line.
- */
- define integer gpart_cat_fsid(string line)``{
- string sub = substring( line, find(line, ":"), find(line,"(")-find(line,":") );
- string allow = "0123456789";
- sub = filterchars( sub, allow);
- return tointeger(sub);
- }
-
- /**
- * Cat the geometry from a line.
- */
- define map gpart_cat_geometry( string line)``{
- string allow = "0123456789/";
-
- string sub1 = substring( line, find(line, "d"), size(line));
- list<string> split = splitstring(sub1, "-" );
- string start = filterchars(split[0]:"", allow);
- string end = filterchars(split[1]:"", allow);
- list<string> s = splitstring( start, "/");
- list<string> e = splitstring( end, "/");
-
- map ret = $[ "start": $[ "c" : tointeger( s[0]:"0"),
- "h" : tointeger( s[1]:"0"),
- "s" : tointeger( s[2]:"0") ],
- "end" : $[ "c" : tointeger( e[0]:"0"),
- "h" : tointeger( e[1]:"0"),
- "s" : tointeger( e[2]:"0") ]];
-
- y2milestone("retmap gemetry %1", ret);
- return ret;
- };
-
-
- /**
- * Dialog with expert gpart options.
- */
- define symbol expert_restore_with_gpart() {
-
-
- // checkbox label
- string full_label = _("Full Scan");
- // button label
- string start_label = _("Start Detection");
-
-
- map maindev = Storage::GetTargetMap()[target]:$[];
- integer cyl_count = maindev["cyl_count"]:0;
- gpart_expert_options = "";
-
- map symbol_2_option = $[
- `extended : "-E",
- `skip_errors : "-e",
- `full_scan : "-f"
- ];
-
- // help text label
- string help_text = _("<P>
- <BIG><B>Help for Expert Mode</B></BIG>
- </P>
- ") +
- // help text (restorng partition)
- OSRPopup::build_label_description (full_label, _("
- <P>When a possible partition is found,
- gpart normally skips all sectors this entry seems
- to occupy and continues the scan from the end of
- the last possible partition. The disk scan can take
- quite a while when using this option. Be patient.</P>
- "));
-
- UI::OpenDialog( `HBox(
- `HWeight(2, `RichText(`id(`help), help_text )),
- `HWeight(4,
- `HBox(
- `HSpacing(2),
- `VBox(
- // headline label, gpart is command
- `Heading(_("Scan Options for gpart")),
- `VSpacing(3),
- // checkbox label
- `Left(`CheckBox(`id(`extended), _("Do Not Try to &Identify Extended Partition Tables"))),
- // checkbox label
- `Left(`CheckBox(`id(`skip_errors), _("Do Not &Skip Disk Read Errors"))),
- `Left(`CheckBox(`id(`full_scan), full_label )),
- `VSpacing(4),
- `HBox(
- `PushButton(`id(`ok), start_label ),
- `PushButton(`id(`cancel), Label::CancelButton())
- )
- ),
- `HSpacing(2)
- )
- )
- ));
-
- UI::SetFocus(`id(`extended));
-
- symbol ret = `ok;
- repeat
- {
- ret = (symbol) UI::UserInput();
-
- if (ret == `ok ) {
-
- //build expert options
- foreach (symbol key, string option, (map<symbol,string>)symbol_2_option, ``{
- gpart_expert_options = gpart_expert_options +
- ((boolean)UI::QueryWidget(`id(key), `Value)
- ? " " + option + " " : "");
- });
-
- y2milestone("gpart options %1", gpart_expert_options );
- }
- } until( ret == `ok || ret == `cancel );
- UI::CloseDialog();
-
- if (ret == `ok ) ret = RestoreWithGpart ();
-
- gpart_expert_options = "";
- return ret;
- }
-
-
- define map compare_found_with_existing ( list<map> found_partitions,
- list<map> existing_partitions,
- string target) ``{
- map ret = $[];
-
- foreach(map paritition, found_partitions, ``{
-
- map matching = find(map e_part, existing_partitions, ``(e_part["region"]:[] == paritition["region"]:[0]));
-
- if (matching != nil && matching != $[] )
- {
- ret["match"] = add(ret["match"]:[], paritition );
- y2milestone("found paritition %1 matchs with exiting paritition %2", paritition["device"]:"", matching["device"]:"");
- }
- else
- {
- integer found_start = paritition["region",0]:0;
- integer found_end = paritition["region",0]:0 + paritition["region", 1]:0 -1;
- foreach(map e_part, existing_partitions, ``{
- integer existing_start = e_part["region", 0]:0;
- integer existing_end = e_part["region", 0]:0 + e_part["region", 1]:0 -1;
-
- if ((existing_start >= found_start && existing_start <= found_end) ||
- (existing_end >= found_start && existing_end <= found_end) ||
- (existing_start >= found_start && existing_end <= found_end) ||
- (existing_start <= found_start && existing_end >= found_end)
- )
- {
- paritition["overlap"] = add(paritition["overlap"]:[], e_part );
- y2milestone("found paritition %1 overlaps with exiting paritition %2", paritition["device"]:"", e_part["device"]:"");
- }
- });
- if (paritition["overlap"]:[] != [] )
- {
- ret["overlap"] = add(ret["overlap"]:[], paritition);
-
- }
- else
- {
- ret["free"] = add(ret["free"]:[], paritition );
- y2milestone("found free paritition space for %1", paritition["device"]:"");
- }
- }
- });
- if (size(ret) > 0 )
- {
- ret["existing"] = existing_partitions;
- }
- return ret;
- }
-
- /**
- * return partition information (to be shown to user)
- */
- define string partition_info (map part, string dev) {
-
- map maindev = Storage::GetTargetMap()[target]:$[];
- return
- // partition info 1/3, %1,%2 are numbers
- sformat (_("Cylinders %1-%2, "),
- part["region", 0]:0, part["region",0]:0 + part["region",1]:0 -1) +
- // partition info 2/3, %1 is partition ID (number)
- sformat(_("ID %1, "), part["fsid"]:131) +
- // partition info 3/3, %1 is partition size (number)
- sformat (_("Size %1"), ByteToHumanString (
- part["region",1]:0 * maindev["cyl_size"]:0));
- }
-
- /**
- * Compare an existing partition table with the gpart output
- */
- define list<map> ComparePtblDialog (map compared, string target,
- string repair_tool) ``{
-
- term part_items = `VBox();
- list<list> part_list = [];
- list<map> found_free_parts = compared["free"]:[];
- list<map> overlap_parts = compared["overlap"]:[];
-
- //number to text
- map number2text = $[
- // label: partition number
- 1 : _("First Partition Found"),
- 2 : _("Second Partition Found"),
- 3 : _("Third Partition Found"),
- 4 : _("Fourth Partition Found")
- ];
-
- foreach (map free_part, found_free_parts, ``{
- integer nr = free_part["nr"]:0;
- part_list = add (part_list, [
- nr,
- `Left (
- `CheckBox(`id(free_part["device"]:""),
- //%1 is number. %2 is text like "First Partition Found", %3 is partition info
- sformat (_("&%1: %2: %3"), nr, number2text[nr]:"",
- partition_info (free_part, target)),
- true
- )
- )
- ]);
- });
-
- foreach (map overlap_part, overlap_parts, ``{
- integer nr = overlap_part["nr"]:0;
- list<string> del_text_parts = maplist (map e_part,
- overlap_part["overlap"]:[], ``{
- return sformat (
- // label: %1 is device name, %2,%3 numbers
- _("Partition %1 must be deleted to recover cylinders %2-%3."),
- e_part["device"]:"",
- overlap_part["region",0]:0,
- overlap_part["region",0]:0 + overlap_part["region",1]:0 - 1);
- });
-
- part_list = add (part_list, [
- nr,
- `Left (`VBox (
- `Left (
- `CheckBox (`id(overlap_part["device"]:""),
- //%1 in number, %2 is text like "Second Partition Found", %3 is partition info
- sformat(_("&%1: %2: %3"), nr, number2text[nr]:"",
- partition_info (overlap_part, target)),
- false)
- ),
- `VSpacing(0.5),
- `Left (
- // heading
- `Heading (_("Conflicts with Existing Partitions"))
- ),
- `Left (
- `Label (mergestring (del_text_parts, "\n"))
- )
- ))
- ]);
- });
-
- part_list = sort (list l, list q, part_list, ``( l[0]:0 < q[0]:0 ));
- foreach (list part, part_list , ``{
- part_items = add (part_items, part[1]:`Empty());
- part_items = add (part_items, `VSpacing(2));
- });
-
- // gpart found only existing partitions.
- if (size( found_free_parts ) == 0 && size( overlap_parts ) == 0 )
- {
- // popup message
- Report::Message(_("No lost partition found."));
- return [];
- }
-
- // help text of partition recovery 1/2
- string help_text = _("
- <p>
- Read the following points carefully
- and select only the partition that should
- really be recovered.
- </P>
- ") +
-
- // help text of partition recovery 2/2
- _("<P><B>Use caution.</B> Sometimes an existing partition must
- be deleted to recover another partition.</P>
- ") +
-
- OSRPopup::build_label_description (OSRPopup::repair_label,
- // help text for button
- _("Start the recovery process."));
-
- string message = "";
- // popup headline
- OSRPopup::OpenSuggestDialog (_("Recover Previously Existing Partitions"),
- message,
- help_text,
- `HBox (`HSpacing(1), part_items, `HSpacing(1)),
- (size(found_free_parts) + size(overlap_parts)) * 15
- );
-
- any ret = `ok;
- list<map> recover = [];
- repeat
- {
- ret = UI::UserInput();
-
- if ( ret == `ok )
- {
- foreach (map free_part, found_free_parts, ``{
- if ((boolean)
- UI::QueryWidget(`id(free_part["device"]:""), `Value))
- {
- recover = add (recover, free_part );
- }
- });
- foreach (map overlap_part, overlap_parts, ``{
- if ((boolean)
- UI::QueryWidget(`id(overlap_part["device"]:""), `Value))
- {
- // warning popup, %1 is device name, %2 list of partitions
- if (Popup::ContinueCancel (sformat(_("
- Recovering the selected partition %1 is only
- possible by deleting the following partitions:
- %2
- Press Continue to delete the partitions
- and recover %1."),
- overlap_part["device"]:"",
- mergestring (
- maplist (map o_part, overlap_part["overlap"]:[],
- ``(o_part["device"]:"")),
- " "
- )
- )))
- {
- foreach (map delpart, overlap_part["overlap"]:[], ``{
- delpart["delete"] = true;
- delpart = filter (string key, any d,
- (map<string,any>) delpart,``(key != "overlap"));
- recover = (list<map>) union (recover, [delpart]);
- });
- overlap_part = filter (string key, any d,
- (map<string,any>)overlap_part,``(key != "overlap"));
- recover = add (recover, overlap_part );
- }
- else //popup canceled
- {
- UI::ChangeWidget (`id(overlap_part["device"]:""),
- `Value, false);
- recover = [];
- ret = `again;
- }
- }
- });
- list<map> existing_partitions = compared["existing"]:[];
- list used_nrs = maplist (
- map ep,existing_partitions,``(ep["nr"]:0));
- list delete_nrs = maplist (
- map dpp, filter (map dp, recover, ``(dp["delete"]:false)),
- ``(dpp["nr"]:0)
- );
-
- used_nrs = filter (integer nr, (list<integer>) used_nrs, ``(
- !contains(delete_nrs, nr)));
-
- list<integer> primary_pos = [1,2,3,4];
- list<integer> free_primary = filter (integer nr, primary_pos, ``(
- !contains (used_nrs, nr)));
-
- // check partition nr's
- foreach(map part, recover , {
- if (part["delete"]:false != true && ret != `again )
- {
- // partition nr is used by a other partition.
- if (contains (used_nrs, part["nr"]:0))
- {
- if (size (free_primary) > 0)
- {
- y2milestone("move partition nr %1 to a free primary position", part["nr"]:0);
- part["nr"] = free_primary[0]:0;
- free_primary = remove (free_primary, 0);
- }
- else
- {
- y2error("no free primary slot found. locical search not supported");
- // error popup, %1 is paritition number, %2 info
- Report::Error(sformat(_("
- Recovering the partition %1 (%2) is not
- possible. The partition number conflicts
- with an existing partition. Solving the
- conflict is not possible.
- "), part["nr"]:0, partition_info (part, target)));
-
- UI::ChangeWidget(`id(part["device"]:""), `Value, false);
- ret = `again;
- }
- }
- }
- });
- }
- } until ( ret == `ok || ret == `cancel );
-
- UI::CloseDialog();
- return recover;
- }
-
-
- /**
- * Restoring a partition tables with gpart.
- */
- global define symbol RestoreWithGpart () ``{
-
- /////////////////////////////////////////////////////////////////////////
- //
- // Repair partition table with gpart
- //
- /////////////////////////////////////////////////////////////////////////
- list<map> found_partitions = [];
- string gpart_file = (string) SCR::Read(.target.tmpdir) + "/gpart";
- WFM::Execute (.local.bash, sformat("if /usr/bin/test -e %1; then /bin/rm %1; else /bin/echo %1 not exist; fi;", gpart_file));
-
- string gpart_command = "/usr/bin/gpart "+ gpart_expert_options +" "+ target;
-
- term contents = `HBox(`HSpacing(0.5),
- `VBox (
- `Left (`HBox (
- // headline of partition scan popup
- `HWeight (30, `Heading(_("Search for Lost Partitions"))),
- `HWeight (30, `HSpacing(4))
- )),
- `VSpacing(1),
- // addtional info for partition scan
- `Left (`Label (_("This can take a lot of time depending on the
- system performance and the hard disk size.")
- )),
- // label text (device name follows)
- `Left (`Label(_("Hard Disk: ") + target)),
- `VSpacing(0.5),
- `VSpacing(1),
- // button label
- `HBox (
- `PushButton(`id(`start) , _("&Start")),
- `PushButton (`id(`cancel), Label::CancelButton())
- )
- ),
- `HSpacing(0.5)
- );
-
- UI::OpenDialog (contents);
-
- if (UI::UserInput () != `start )
- {
- UI::CloseDialog();
- return `cancel;
- }
-
- UI::ChangeWidget(`id(`start), `Enabled, false);
- UI::ChangeWidget(`id(`cancel), `Enabled, false);
- // FIXME action cannot be cancelled! -> use background or callback
- // progress doesn't have sence!
-
- UI::BusyCursor();
- if (OSRExecute::CommandProgress (.target.bash_output, gpart_command, gpart_file))
- {
- string file = (string) WFM::Read(.local.string, gpart_file );
- // display the results in a window
- string partitions_out = substring (file,
- find (file, "\nPrimary partition(1)"),
- (size(file) - find (file, "\nPrimary partition(1)"))
- );
- string partition1 = substring(partitions_out,
- find(partitions_out, "\nPrimary partition(1)"),
- (find(partitions_out, "\nPrimary partition(2)") -
- find(partitions_out, "\nPrimary partition(1)"))
- );
-
- string partition2 = substring (partitions_out,
- find (partitions_out, "\nPrimary partition(2)"),
- (find(partitions_out, "\nPrimary partition(3)") -
- find(partitions_out, "\nPrimary partition(2)"))
- );
-
- string partition3 = substring (partitions_out,
- find(partitions_out, "\nPrimary partition(3)"),
- (find(partitions_out, "\nPrimary partition(4)") -
- find(partitions_out, "\nPrimary partition(3)"))
- );
-
- string partition4 = substring(partitions_out,
- find(partitions_out, "\nPrimary partition(4)"),
- (size(partitions_out)-find(partitions_out,"\nPrimary partition(4)"))
- );
-
- list gpart_partitions = [partition1, partition2, partition3,partition4];
-
- integer index = 0;
- while ((index >= 0) && (index < size(gpart_partitions)))
- {
- map partition = $[];
- string p = gpart_partitions[index]:"";
- list<string> p_list = splitstring(p, "\n");
-
- foreach (string line, p_list, ``{
- if (issubstring(line, "type: "))
- {
- partition["fsid"] = gpart_cat_fsid(line );
- }
- else if (issubstring( line, "chs:"))
- {
- map geometry = gpart_cat_geometry( line );
- integer s = geometry["start","c"]:0;
- integer l = geometry["end","c"]:0 - s + 1;
- partition["region"] = [s,l];
- }
- partition["nr"] = index +1;
- partition["type"] = `primary;
- partition["create"] = true;
- partition["device"] = Storage::GetDeviceName(target, index + 1);
- });
-
- index = index + 1;
-
- if (partition["region",1]:0 != 0 && partition["fsid"]:0 != 0)
- {
- found_partitions = add(found_partitions, partition );
- }
- }
- }
-
- UI::CloseDialog();
- UI::NormalCursor();
-
- if (size (found_partitions) == 0)
- {
- // error popup, %1 is device
- Report::Error(sformat(_("
- No valid partitions found for the
- partition table of %1. If there were
- some partitions on the disk, you can try
- to restore them manually. To do
- that, enter the cylinder values
- in fdisk or the partitioning tool.
- "), target));
- return `error;
- }
- else
- {
- map compared = compare_found_with_existing (
- found_partitions,
- (list<map>) Storage::GetTargetMap()[target, "partitions"]:[],
- target);
- list<map> torecover = ComparePtblDialog (compared, target, "Gpart");
-
- if (size (torecover) < 1 || Mode::test ())
- return `cancel;
-
- if (fdisk_call (target, torecover))
- {
- if (CheckRestoredPtbl (target))
- {
- return `ok;
- }
- }
- else
- {
- // error popup message
- Report::Error(_("Partition table was not successfully repaired."));
- return `error;
- }
- }
- return `error;
- }
-
- /**
- * Restore saved mbr.
- */
- define boolean write_original(list<string> to_reset, boolean whole_mbr )``{
- if (Mode::test () ) return true;
-
- y2milestone("write orginal master boot record");
-
- integer ok = 0 ;
- foreach(string dev, to_reset , ``{
-
- if ( backup_dev_filenames[dev]:"" != "" ) {
- string command = sformat("/bin/dd if=%1 of=%2 ", backup_dev_filenames[dev]:"", dev );
-
- if (whole_mbr ) command = command + "count=1 bs=512";
- else command = command + "bs=1 count=64 skip=446 seek=446";
-
- if (OSRExecute::Command(.local.bash,command)) {
- ok = ok + 1;
- Report::Message(sformat(_("Writing the backup of %1 was successful."), dev));
- }
- else {
- Report::Message(sformat(_("Writing the backup of %1 was not successful."), dev));
- }
- repair_methods[ `original, "enabled"] = true;
- }
- else {
- y2error("No entry in backup map found");
- }
-
- });
- return ( ok == size(to_reset));
- }
-
-
- /**
- * Restore saved mbr.
- */
- define symbol restore_original()``{
-
- //%1 is device label, such as /dev/hda
- string header = sformat(_("Restore Original Partition Table of %1"), target);
- string ok_label = mergestring(splitstring(Label::OKButton(), "&"),"");
-
- //%1 is OK button label, %2 is device like /dev/hda
- string message = original_help_text() + sformat(_("
- If you press %1, the partition table
- of %2 will be replaced with
- the backup.
- "), ok_label, target );
-
- if (Popup::YesNoHeadline(header, message ))
- {
- if (! Mode::test () )
- {
- if (write_original([target], true )) return `ok;
- else return `error;
- }
- else {
- return `ok;
- }
- }
- return `cancel;
- }
-
- /**
- * Write partition info of given disk to floppy (needs mounted floppy)
- */
- global define boolean WritePartitionsInfo2Floppy (string key, list parts) {
-
- if (Mode::test () ) return true;
-
- boolean write_error = false;
- string file = build_file_name (key);
-
- // set the dd-command
- string command = sformat("dd if=%1 of=%2.mbr bs=512 count=1", key, file);
-
- // write mbr to floppy
- OSRExecute::Command (.local.bash, command);
-
- // write partition list to floppy
- WFM::Write (.local.ycp, file+".ycp", parts);
-
- if (!(WFM::Read(.local.size, file + ".mbr") == 512 &&
- WFM::Read(.local.size, file + ".ycp") != 0 ))
- {
- write_error = true;
- }
-
- return (!write_error);
- }
-
-
- /**
- * Main Dialog for repairing deleted/not valid partition tables.
- *
- * @parm t_target the target e.g.: /dev/hda
- *
- */
- global define symbol MainPtblRepairDialog(string t_target) ``{
-
- //Save all mbr's to tmp directory.
- SavePtbl();
-
- target = t_target;
-
- term r_options = `VBox(`Left(`Label(_("Select a repair method or skip repairing."))),`VSpacing(0.5));
-
- foreach(symbol ro, map<string,any> rd, (map<symbol,map<string,any> >)repair_methods, ``{
- term r_button = `RadioButton(`id( ro ));
- if (! rd["enabled"]:true ) r_button = add( r_button , `opt(`disabled));
- r_button = add( r_button , rd["header"]:"");
- r_button = add( r_button, rd["default"]:false );
- r_options = add( r_options , `Left( r_button ));
- });
- //%1 is device label, such as /dev/hda
- string error_text = sformat(_("
- No partition table was found for hard disk %1.
- If at least one partition should exist for %1,
- select one of the following repair methods. If
- no partition ever existed on this hard disk,
- skip the repair.
-
- "), target);
-
- //%1 is device label, such as /dev/hda
- if (! OSRPopup::OpenMainRepairDialog( sformat(_("Repair Partition Table of %1"),target ), error_text, r_options ))
- {
- y2error("could not open main dialog");
- return `error;
- }
- symbol ret = `ok;
- repeat {
- ret = (symbol) UI::UserInput();
- symbol selected = (symbol) UI::QueryWidget(`id(`rb), `CurrentButton);
-
- if (ret == `help )
- {
- string () help_f =
- repair_methods[selected,"help"]:OSRCommon::EmptyString;
- Popup::LongText (OSRPopup::help_headline,
- `RichText ( help_f () ), 50, 20);
- }
- else if (ret == `ok )
- {
- UI::CloseDialog();
- symbol () f =
- repair_methods [selected,"method"]:OSRCommon::SymbolError;
- ret = f ();
-
- if (ret != `ok )
- {
- if (! OSRPopup::OpenMainRepairDialog (
- // dialog headline, %1 is device label live /dev/hda
- sformat(_("Repair Partition Table of %1"), target ),
- error_text, r_options ))
- {
- y2error("could not open main dialog");
- return `error;
- }
- ret = `again;
- }
- }
- } until( ret == `cancel || ret == `abort || ret == `ok );
- if (ret != `ok ) UI::CloseDialog();
- return ret;
- }
-
- global define void SetTarget(string ttarget)``{
- target = ttarget;
- }
-
- }//EOF
-