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
/
modules
/
OSRFstab.ycp
< prev
next >
Wrap
Text File
|
2006-11-29
|
60KB
|
2,291 lines
/**
* File:
* OSRFstab.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>
*
* Use:
* OSRFstab::LinuxPartitions ("/dev/hda1", "/dev/hda2", .. ]);
* OSRFstab::MountablePartitions( ..);
* OSRFstab::ValidRootPartitions( ..);
*
* OSRFstab::ReadFstab("/");
* OSRFstab::CheckRootEntry ("/dev/hda1",
* ["/dev/hda2"], ["/dev/hda3", "/dev/hda4" ]);
* OSRFstab::Repair();
*
* OSRFstab::Check(["/dev/hda2"], ["/dev/hda3", "/dev/hda4" ]);
* OSRFstab::Repair();
*
*
* $Id: OSRFstab.ycp 32906 2006-09-15 09:57:06Z jsuchome $
*/
{
module "OSRFstab";
import "FileSystems";
import "Storage";
import "StorageDevices";
import "Hotplug";
import "Partitions";
import "Mode";
import "Installation";
import "AsciiFile";
import "Initrd";
import "Report";
import "OSRFsck";
import "OSRLogFile";
import "OSRSystem";
import "OSRExecute";
import "OSRPopup";
import "Label";
import "Popup";
import "SuSERelease";
textdomain "repair";
string remove_label = _("Remove");
string ignore_label = _("Ignore");
string replace_label = _("Replace");
string create_label = _("Create");
string device_label = _("Device");
string mount_label = _("Mount Point");
string create_mp_label = _("Create Mount Point");
string state_label = _("State");
// fstab is file name
string fstab_line_label = _("fstab Line");
// button label
string b_ignore_label = _("&Ignore");
// button label
string b_create_label = _("&Create");
// button label
string b_remove_label = _("&Remove");
// button label
string b_change_mp_label = _("Change &Mount Point");
// button label
string b_replace_label = _("R&eplace");
global list<string> system_mount_points =
[ "/dev", "/lib", "/bin", "/etc", "/sbin" ];
/**
* The path
*/
global string fstabpath = "/etc/fstab";
/**
* The default fstab entries (as maps) -> set in constructor
*/
map <string,map> fstab_defaults = $[];
/**
* All digits
*/
string digits = "0123456789";
/**
* Line position to sense
*/
map pos2field = $[ 0: "spec",
1: "mount",
2: "vfstype",
3: "mntops",
4: "freq",
5: "passno" ];
/**
* Partitions which are swapable
*/
list<string> swapable_partition_list = [];
/**
* All checked partitions (OSRFsck)
*/
list<string> checked_partitions = [];
/**
@example of map describing /etc/fstab:
$[
"comment" : "^[ \t]*#.*",
"delim" : " \t",
"l" : $[
1 : $[
"fields" : ["/dev/hda2", "/", "reiserfs", "defaults", "1", "1"],
"line" :"/dev/hda2\t/\treiserfs\tdefaults 1 1"
],
2 : $[
"fields" : [
"/dev/hda3", "/local", "reiserfs", "defaults", "1", "2"],
"line" : "/dev/hda3\t/local\treiserfs\tdefaults 1 2"
],
3 : $[
"fields" : [ "/dev/hda1", "swap", "swap", "pri=42", "0", "0"],
"line" : "/dev/hda1\tswap\tswap\tpri=42 0 0"
],
4 : $[
"fields" : [
"devpts", "/dev/pts", "devpts", "mode=0620,gid=5","0", "0"],
"line" : "devpts\t/dev/pts\tdevpts\tmode=0620,gid=5 0 0"
],
...
14 : $[
"fields" : [
"nfs.suse.cz:/home", "/home", "nfs", "defaults", "0", "0"],
"line" : "nfs.suse.cz:/home\t/home\tnfs\tdefaults 0 0"
],
15 : $[
"comment":true,
"line":"#blah"
]
],
"widths" : [20, 20, 10, 21, 1, 1]
]
*/
map fstab = $[];
/**
* The root mount points e.g.: "/", "/mnt"
*/
string root_mountpoint = "";
/**
* All checked valid lines
* e.g.: [1,2,3];
*/
list<integer> valid_lines = [];
/**
* Not valid lines, e.g.:
* $[4: ["dev", false, true, true ,true ,true ,true ]],//spec error in line 4
*/
map not_valid_lines = $[];
/**
* Devices without fstab entry
* e.g.: ["/dev/hdb7"]
*/
list<string> missing_devs = [];
/**
* Constructor: initialize data structures with default values
*/
global define void OSRFstab () {
foreach (string type, [
"pts", "proc", "usb", "swap", "cdrom", "floppy",
"root", "zip", "dev", "nfs", "sys" ],
{
fstab_defaults [type] = FileSystems::GetFstabDefaultMap (type);
});
}
define void ResetSettings() {
missing_devs = [];
valid_lines = [];
not_valid_lines = $[];
}
global define void Reset() {
ResetSettings();
root_mountpoint = "";
fstab = $[];
swapable_partition_list = [];
checked_partitions = [];
}
/**
* @param key values of which key should be returned
* @param exists restrict the returned set only to the types with
* nonempty values of key 'exists'
*/
define list<string> fstab_default_exist (string exists, string key)
{
map <string,map> existing = filter (
string type, map desc, fstab_defaults, ``(desc[exists]:"" != ""));
return (list<string>) maplist (string type, map d, existing, ``(d[key]:""));
}
/**
* e.g.: transform a fstab list to a fstab map.
* list: ["/dev/hda6", "/", "reiserfs", "defaults", "1", "1"]
* map : $[ "spec":"/dev/hda6", "file":"/" ... ]
*/
define map fstabline2map (list<string> line)``{
map ret = $[];
integer pos = 0;
foreach (string e, line, ``{
ret [pos2field[pos]:""] = e;
pos = pos +1;
});
return ret;
}
/**
* Find the list of all valid linux-partitions in the target-map.
* @return list The list of names of valid linux-partitions.
*/
global define list<string> LinuxPartitions(list checked_partitions) ``{
if (Mode::test ()) return ["/dev/hda1", "/dev/hda2"];
if (size (checked_partitions) == 0) return [];
y2warning ("checked_partitions: %1", checked_partitions);
// e.g.: ["/dev/hda1", "/dev/hdb2"]
list<string> linux_partition_list = [];
foreach (string device , map description, Storage::GetTargetMap(), {
foreach (map partition, description["partitions"]:[], ``{
y2internal ("partition: %1", partition);
if ((partition["fsid"]:0 == Partitions::fsid_native ||
partition["type"]:`primary == `lvm ||
partition["type"]:`primary == `sw_raid))
{
// if the fsck functions have been executed
if (size (checked_partitions) != 0)
{
if (contains (checked_partitions,partition["device"]:""))
{
linux_partition_list = add (linux_partition_list,
partition["device"]:"");
}
}
else
{
linux_partition_list = add (linux_partition_list,
partition["device"]:"");
}
}
});
});
if (size ( linux_partition_list) == 0)
y2error("no linux partition found");
return linux_partition_list;
};
/**
* Returns a list of names of all mountable partitions out of
* the specified list.
* @param list linux_partition_list A list of valid linux-partitions out of
* which the mountable partitions are to be returned.
* @param m_point the test mountpoint
* @return list List of partition names successfully mounted to m_point.
*/
global define list<string> MountablePartitions(
list<string> linux_partition_list, string m_point) ``{
if (Mode::test () || size (linux_partition_list) == 0)
return linux_partition_list;
// e.g.: ["/dev/hda1"]
list<string> mount_possible_list = [];
integer i = 0;
foreach (string partition_item, linux_partition_list, ``{
if ((boolean) WFM::Execute (.local.mount,
[ partition_item, m_point, OSRExecute::OutputFile() ]))
{
mount_possible_list = add (mount_possible_list, partition_item);
if (!(boolean) WFM::Execute(.local.umount, m_point))
{
y2error("umounting partition %1 not possible",partition_item);
}
}
else
{
y2error("mounting partition %1 is not possible", partition_item);
}
i = i + 1;
});
return mount_possible_list;
};
/**
* Returns a list of names of all mountable partitions that contain
* a file /etc/fstab out of the specified list.
* @param list linux_partition_list A list of valid linux-partitions
* out of which the mountable partitions are to be returned.
* @return list The list of partition-names that were successfully mounted
* to /mnt and contain a filesystem table.
*/
global define list<map> ValidRootPartitions (
list<string> mount_possible_list, string mount_p)
{
if (Mode::test ())
return maplist (string p, mount_possible_list, ``($["device": p]));
if (size (mount_possible_list) == 0) return [];
// e.g.: [ "device" : "/dev/hda1", "label" : "SUSE Linux"]
list<map> valid_root_partitions = [];
list<string> fstab_found_partitions = [];
list<string> smpoints_found_partitions = [];
// mapping of device to the product label ($[ "/dev/hda1" : "SUSE Linux"])
map device2label = $[];
foreach (string partition_item, mount_possible_list, ``{
if (! (boolean) WFM::Execute(.local.mount,
[ partition_item, mount_p , OSRExecute::OutputFile() ]))
{
y2error("Partition: %1; not possible to mount to /mnt",
partition_item);
}
else
{
device2label[partition_item] =
SuSERelease::ReleaseInformation (mount_p);
// Check fstab exist
// use the .local.size agent instead of the .etc.fstab agent
// because it finds the fstab of currently mounted root partition
if (WFM::Read (.local.size, mount_p + fstabpath) > 0)
{
y2milestone("Partition %1: fstab found", partition_item);
fstab_found_partitions = add (fstab_found_partitions,
partition_item);
}
else
{
y2milestone("Partition: %1; no fstab found", partition_item);
}
// Check system mount points
boolean not_fount = false;
foreach (string mp, system_mount_points, ``{
if (mp != "/")
{
string cmd = sformat ("/usr/bin/test -d %1%2", mount_p,mp);
y2debug ("command: %1", cmd);
if (!OSRExecute::Command (.local.bash, cmd))
{
not_fount = true;
}
}
});
if (! not_fount)
{
y2milestone("system mount points found");
smpoints_found_partitions = add (smpoints_found_partitions,
partition_item);
}
else
y2warning("system mount points not found. Partition %1 could not be a root partition", partition_item);
}
// umount the partition
WFM::Execute(.local.umount, mount_p);
});
valid_root_partitions = maplist (string part, smpoints_found_partitions, {
return $[ "device" : part, "label" : device2label[part]:"?" ];
});
y2milestone("ValidRootPartitions return %1", valid_root_partitions);
return valid_root_partitions;
};
/**
* Read the fstab file.
*/
global define boolean ReadFstab(string mount_p , boolean strict)``{
root_mountpoint = mount_p;
fstab = Partitions::GetFstab( mount_p + fstabpath);
if (fstab == nil || size (fstab) == 0 || fstab["l"]:$[] == $[])
{
y2error("No fstab found !!");
if (strict) return false;
// yes/no popup headline, fstab is file name
if (Popup::YesNoHeadline(_("Cannot Read fstab"),
// yes/no popup text
_("
No existing fstab file found.
Create a new one?
")))
{
OSRExecute::Command (.local.bash,
sformat ("/bin/mv %1%2 %1%2.YaSTsave",root_mountpoint,fstabpath));
OSRExecute::Command (.local.bash,
sformat ("/bin/touch %1%2", root_mountpoint, fstabpath));
fstab = Partitions::GetFstab (mount_p + fstabpath);
return true;
}
return false;
}
else
{
y2milestone ("fstab :%1 ", fstab);
return true;
}
}
/**
* Removes blanks from a string.
*/
define string remove_blanks (string c) ``{
return ( mergestring (splitstring (c ," "), ""));
}
/**
* Cat the uuid from a string.
*/
define string uuid_string(list<string> line) ``{
if (substring (line[0]:"", 0, 4) == "UUID") {
return substring (line[0]:"", 5);
}
return "";
}
/**
* Cat the label from a string.
*/
define string label_string(list<string> line)``{
if (substring (line[0]:"", 0,5) =="LABEL") {
return substring (line[0]:"",6);
}
return "";
}
/**
* Check the spec (first) entry in a fstab line.
*/
define boolean check_fs_spec( list<string> line, map part)``{
string uuidstring = uuid_string (line);
string labelstring = label_string (line);
return (contains (checked_partitions, line[0]:"") ||
uuidstring == part["uuid"]:"!" ||
labelstring == part["label"]:"!"
);
}
/**
* Check the file (second) entry in a fstab line.
*/
define boolean check_fs_file(list<string> line)``{
if (line[1]:"" == nil || line[1]:"" == "")
return false;
string dir = line[1]:"";
if (dir == "" || dir == nil)
return false;
return (OSRExecute::Command (.local.bash,
sformat ("/usr/bin/test -d %1%2", root_mountpoint, dir)));
}
/**
* Check the filesystem type (third) entry in a fstab line.
*/
define boolean check_fs_vfstype(list<string> line, map part) ``{
if (line[2]:"" == nil || line[2]:"" == "") return false;
line[2] = remove_blanks (line[2]:"");
if (!(FileSystems::GetMountString (part["detected_fs"]:`unknown, "!")
== line[2]:""
|| line[2]:"" == "auto" || line[2]:"" == "subfs"))
{
return false;
}
return true;
}
/**
* Check the mount options (fourth) entry in a fstab line.
*/
define boolean check_fs_mntops(list<string> line) {
if (line[3]:"" == nil || line[3]:"" == "") return false;
map checked = FileSystems::CheckFstabOptions (remove_blanks(line[3]:""));
if (!checked["all_known"]:true)
{
y2error ("unknown mount options: %1",checked["unknown_options"]:"");
}
return checked["all_known"]:true;
}
/**
* Check the freq (fifth) entry in a fstab line.
*/
define boolean check_fs_freq(list<string> line, list<string> defaults)``{
if (line[4]:"" == nil || line[4]:"" == "") return false;
return (( size (filterchars (remove_blanks (line[4]:"0"), digits)) > 0) &&
( contains (defaults, remove_blanks (line[4]:"0"))));
}
/**
* Check the passno (sixth) entry in a fstab line.
*/
define boolean check_fs_passno(list<string> line, list<string> defaults)``{
if (line[5]:"" == nil || line[5]:"" == "")
return false;
if (size (filterchars (remove_blanks (line[5]:"0"), digits))
== size (remove_blanks (line[5]:"0")))
{
if (size (defaults) != 0)
{
return contains (defaults, remove_blanks (line[5]:"!"));
}
else
{
return true;
}
}
return false;
}
/**
* Returns the partition map for a device.
* cdrom, floppy and zip devices are support too.
*/
define map devname2part(string dev_name)``{
if (substring (dev_name, 0,1) != "/") return $[];
map ret = StorageDevices::GetCdromEntry( dev_name);
if (ret == $[] || ret == nil) {
ret = find(map e, StorageDevices::cddrives, ``(e["linkname"]:"" == dev_name));
// check link
if (ret == nil) {
OSRExecute::CommandOutput(.local.bash, sformat ("/bin/ls -l %1", dev_name));
list<string> std_dev_list = filter (string s, splitstring (OSRExecute::stdout, " "), ``( s != " "));
string link = std_dev_list[size (std_dev_list)-1]:"";
list linkl = splitstring (link , "\n");
link = linkl[0]:"";
y2milestone("link is %1", link);
if (! issubstring (link , "/dev"))
{
link = "/dev/" + link ;
}
y2milestone("new link %1", link);
ret = StorageDevices::GetCdromEntry( link);
if (ret == $[] || ret == nil)
{
//y2milestone(" StorageDevices :: %1 " ,StorageDevices::cddrives);
ret = find(map e, StorageDevices::cddrives, ``(e["linkname"]:"" == link));
}
y2milestone(" ret in check link %1", ret);
}
}
if (ret == $[] || ret == nil) {
ret = find(map e, StorageDevices::FloppyDrives, ``(e["dev_orig"]:(e["dev_name"]:"") == dev_name));
if (ret != $[] && ret != nil) ret["found"] = "floppy";
}
else {
ret["found"] = "cdrom";
}
if (ret == $[] || ret == nil)
{
list lret = maplist (string n, map m,
filter (string k, map e, (map<string,map>)StorageDevices::ZipDrives,
``(e["dev_orig"]:(e["dev_name"]:"") == dev_name)), ``(m));
ret = lret[0]:$[];
if (ret != $[] && ret != nil) ret["found"] = "zip";
}
if (ret == $[] || ret == nil)
{
ret = Storage::GetPartition( Storage::GetTargetMap(), dev_name );
if (ret != $[] && ret != nil) {
if (ret["device"]:"" == dev_name)
{
ret["dev_name"] = dev_name;
if (ret["fsid"]:0 == Partitions::fsid_swap) {
ret["found"] = "swap";
}
else {
ret["found"] ="dev";
}
if (ret["mount"]:"" == "/")
{
ret["found"] = "root";
}
}
else {
// Storage return default !!
ret = $[];
}
}
}
return ret;
};
/**
* Check if an entry for a device exist in the fstab.
*/
define boolean check_dev_entry(string p)``{
map part = devname2part(p);
map lines = filter (integer lnr, map line, fstab["l"]:$[], ``(
(line["fields",0]:"!" == p) ||
(line["fields",0]:"!" == part["linkname"]:"" &&
part["found"]:"" == "cdrom") ||
(line["fields",0]:"!" == "UUID=" + part["uuid"]:"") ||
(line["fields",0]:"!" == "LABEL=" + part["label"]:""))
);
if (size (lines) > 0)
{
y2milestone("found entry for %1 in the fstab", p);
return true;
}
else
{
y2warning ("no entry for %1 found in the fstab",p);
if (part["used_by"]:"" != "")
{
y2warning ("it is a device used by other entity (e.g. LVM, EVMS, MD): ignoring");
return true;
}
missing_devs = add (missing_devs, p);
missing_devs = toset (missing_devs);
return false;
}
}
/**
* Return the partition map for a special uuid.
*/
define map uuid2part(string uuidstring) {
map ret = $[];
foreach (string dn, checked_partitions, {
if (ret == $[]) {
map part = devname2part(dn);
if (part ["uuid"]:"" == uuidstring)
{
ret = devname2part(dn);
ret["wise"] = "uuid" ;
}
}
});
return ret;
}
/**
* Return the partition map for a special label.
*/
define map label2part(string labelstring) {
map ret = $[];
foreach (string dn, checked_partitions, {
if (ret == $[]) {
map part = devname2part(dn);
if (part ["label"]:"!" == labelstring) {
ret = devname2part( dn);
ret["wise"] = "label";
}
}
});
return ret;
}
/**
* Return the partition map for a fstab line.
*/
define map line2part(list<string> line) ``{
if (contains (fstab_default_exist ("spec", "spec"), line[0]:""))
return $[];
map ret = devname2part(line[0]:"");
if (ret == nil || ret == $[])
{
string uuidstring = uuid_string(line);
if (uuidstring != "")
ret = uuid2part (uuidstring);
if (ret == nil || ret == $[])
{
string labelstring = label_string(line);
if (labelstring != "")
ret = label2part( labelstring);
}
}
else
{
ret["wise"] = "dev";
}
y2milestone("line2part return: %1", ret);
return ret;
}
/**
* Check one fstab line and return false if
* the line contains errors.
*/
define boolean check_fstab_line( integer lnr)``{
map linemap = AsciiFile::GetLine(fstab, lnr);
list<string> line = linemap["fields"]:[];
// empty line ?
if (size (filter (string pos, line, ``( pos != "" && pos != " "))) == 0 ||
line == [])
{
y2milestone(" add empty line to valid_lines ");
valid_lines = add (valid_lines , lnr);
return true;
}
map part = line2part(line);
string type = "invalid";
boolean fs_spec = false;
boolean fs_file = false;
boolean fs_vfstype = false;
boolean fs_mntops = false;
boolean fs_freq = false;
boolean fs_passno = false;
if (part == nil || part == $[] || size (part)<=0)
{
if (line[0]:"" == fstab_defaults["usb","spec"]:"!")
{
if (Hotplug::haveUSB)
{
type = "usb";
fs_spec = true;
fs_file = (line[1]:"" == fstab_defaults[type,"mount"]:"!");
fs_vfstype = (line[2]:"" == fstab_defaults[type,"vfstype"]:"!");
fs_mntops = check_fs_mntops (line);
}
else
{
y2error("usb line in fstab but no usb found");
type = "usb";
fs_spec = false;
fs_file = true;
fs_vfstype = true;
fs_mntops = true;
}
}
else if (issubstring (line[0]:"", ":/"))
{
// nfs
type = "nfs";
fs_spec = true; // no check
fs_file = check_fs_file (line);
fs_vfstype = true; // no check
fs_mntops = true; // no check
}
else if (line[0]:"" == fstab_defaults["pts","spec"]:"!")
{
type = "pts";
fs_spec = true;
fs_file = check_fs_file (line);
fs_vfstype = ( line[2]:"" == fstab_defaults[type,"vfstype"]:"!");
fs_mntops = ( line[3]:"" != nil && line[3]:"" != "");
}
else if (line[0]:"" == fstab_defaults["proc","spec"]:"!")
{
type = "proc";
fs_spec = true;
fs_file = ( line[1]:"" == fstab_defaults[type,"mount"]:"!");
fs_vfstype = ( line[2]:"" == fstab_defaults[type,"vfstype"]:"!");
fs_mntops = ( line[3]:"" != nil && line[3]:"" != "");
}
else if (line[0]:"" == fstab_defaults["sys","spec"]:"!")
{
type = "sys";
fs_spec = true;
fs_file = ( line[1]:"" == fstab_defaults[type,"mount"]:"!");
fs_vfstype = ( line[2]:"" == fstab_defaults[type,"vfstype"]:"!");
fs_mntops = ( line[3]:"" != nil && line[3]:"" != "");
}
fs_freq = check_fs_freq (
line, [ tostring (fstab_defaults [type, "freq"]:0) ]);
fs_passno = check_fs_passno (
line, [ tostring (fstab_defaults [type, "passno"]:0) ]);
}
else
{
list<string> special_freq = [];
list<string> special_passno = [];
// cdrom floppy zip
if (part["found"]:"" == "floppy" ||
part["found"]:"" == "zip" ||
part["found"]:"" == "cdrom")
{
type = part["found"]:"";
fs_spec = true;
fs_file = check_fs_file(line);
fs_vfstype = check_fs_vfstype(line, part);
fs_mntops = check_fs_mntops( line);
}
else if (contains (checked_partitions, part["dev_name"]:"") &&
part["found"]:"" == "dev")
{
// check root first with CheckRootEntry!!
if (line[1]:"" == "/")
return true;
type = "dev";
fs_spec = true;
fs_file = check_fs_file(line);
fs_vfstype = check_fs_vfstype(line, part);
fs_mntops = check_fs_mntops( line);
special_passno = [ "2" ];
special_freq = [ "1" ];
// add mount point to target_map for later use (OSRBoot)
part["mount"] = line[1]:"";
Storage::ChangeVolumeProperties(part);
}
else if (contains (swapable_partition_list, part["dev_name"]:"") &&
part["found"]:"" == "swap")
{
type = "swap";
fs_file = true;
fs_spec = (line[1]:"" == "swap");
fs_vfstype = ( line[2]:"" == "swap");
// TODO the default could be checked by
// FileSystems::GetFstabDefaultMntops ("swap")
fs_mntops = check_fs_mntops (line);
}
else if (part["found"]:"" == "root")
{
fs_spec = true;
fs_file = true;
fs_vfstype = true;
fs_mntops = true;
fs_freq = true;
fs_passno = true;
}
else
{
y2error("not valid fstab entry found");
}
// not check for root
if (type != "" &&
contains (["dev", "swap","floppy", "zip", "cdrom"], type))
{
fs_freq = check_fs_freq (line,
add (special_freq, tostring (fstab_defaults [type, "freq"]:0)));
fs_passno = check_fs_passno (line,
add (special_passno,tostring(fstab_defaults[type,"passno"]:0)));
}
}
if (! fs_spec)
{
y2error("%1 spec not valid", line[0]:"");
}
if (! fs_file)
{
y2error("%1 file not valid", line[0]:"");
}
if (! fs_vfstype)
{
y2error("%1 fstype not valid",line[0]:"");
}
if (! fs_mntops)
{
y2error("%1 mntops not valid",line[0]:"");
}
if (! fs_freq)
{
y2error("%1 freq not valid",line[0]:"");
}
if (! fs_passno)
{
y2error("%1 passno not valid",line[0]:"");
}
if (fs_spec && fs_file && fs_vfstype && fs_mntops && fs_freq && fs_passno)
{
valid_lines = add (valid_lines , lnr);
y2milestone("fstab line nr %1 entry is valid", lnr);
}
else
{
y2error("fstab line nr %1 is not valid", lnr);
not_valid_lines [lnr] =
[type, fs_spec, fs_file, fs_vfstype, fs_mntops, fs_freq, fs_passno];
}
return (fs_spec && fs_file && fs_vfstype && fs_mntops && fs_freq &&
fs_passno);
}
/**
* All device that should be checked.
*/
define list<string> devices2check()``{
list<string> dev2check = (list<string>)
union (
union (checked_partitions, swapable_partition_list),
[
fstab_defaults ["usb", "spec"]:"",
fstab_defaults ["proc", "spec"]:"",
fstab_defaults ["pts", "spec"]:""
]
);
dev2check = (list<string>) union (dev2check,
maplist (map d, StorageDevices::cddrives,
``(d["dev_orig"]:(d["dev_name"]:""))));
dev2check = (list<string>) union (dev2check,
maplist (map d, StorageDevices::FloppyDrives,
``(d["dev_orig"]:(d["dev_name"]:""))));
dev2check = (list<string>) union (dev2check,
maplist (string k, map d, (map<string,map>) StorageDevices::ZipDrives,
``(d["dev_orig"]:(d["dev_name"]:""))));
return dev2check;
}
/**
* Check if all entries in the fstab are valid and
* if all found devices have an entry in the fstab.
*/
global define boolean Check(list<string> tswapable_partition_list,
list<string> tchecked_partitions) ``{
ResetSettings();
swapable_partition_list = tswapable_partition_list;
checked_partitions = tchecked_partitions;
// check all lines in existing fstab file
foreach (integer lnr, map line, fstab["l"]:$[], ``{
y2milestone("----check fstab line %1 ", lnr);
if (! contains (valid_lines, lnr))
check_fstab_line(lnr);
});
// check all mountable partitions + swap + usb+ proc +...
foreach (string p, devices2check(), ``{
y2milestone("-----check partition and usb,proc,pts %1", p);
check_dev_entry(p);
});
return ((size (missing_devs) == 0) && (size (not_valid_lines) == 0));
}
/**
* Build items for table in missing devices dialog.
*/
define list<term> missing_devs_items( map new_entries)``{
list<term> item_list = [];
foreach (string k, map<string,any> e, (map<string,map<string,any> >)new_entries, ``{
item_list = add (item_list, `item(`id(k), k, e["mount"]:""));
});
return item_list;
}
define string find_next_media_file(string type)``{
integer num = 0;
string mp = "/media/" + type;
while (true) {
if (AsciiFile::FindLineField(fstab, 1,mp) == [])
return mp;
else {
num = num + 1;
mp = sformat ("%1%2",mp,num);
}
}
}
define list<string> used_mount_points(map fstab)``{
list<string> ret = [];
foreach (integer lnr, map ldata, fstab["l"]:$[], ``{
ret = add (ret , ldata["fields", 1 ]:"");
});
return ret;
}
/**
* Build fstab entries for all existing devices that are not listed
* in the fstab.
*/
define map suggest_missing_entries()``{
if (Mode::test ()) return $[ "/dev/hda1" : $[ "mount" : "/hh" ]];
integer other_nr = 1; // count other mounts -> global for wirte_fstab
map new_entries = $[];
missing_devs = sort (string d1, string d2, missing_devs , ``( d1 < d2));
foreach (string dev, missing_devs, {
map part = devname2part(dev);
if (part != nil && part != $[] &&
contains (["dev", "swap", "root"], part["found"]:"" ))
{
part["device"] = dev;
integer nr = 1;
map fstabentry = Storage::onepartition2fstab(part,nr);
list<string> used_mountpoints = used_mount_points(fstab);
string start = "/data";
integer count = 2;
// fstabentry could be empty map for some partitions (e.g.
// with LVM group) -> suggest_missing_entries could report error 4
while (contains (used_mountpoints , fstabentry["mount"]:""))
{
// find new mount point
fstabentry["mount"] = sformat ("%1%2", start, count);
count = count + 1;
y2milestone("new mount point %1 ", fstabentry["mount"]:"");
}
if (size (fstabentry)>0)
{
new_entries[dev] = fstabentry;
}
}
else if (contains (fstab_default_exist ("spec", "spec"), dev))
{
string type = "";
foreach (string key, map descr, fstab_defaults, {
if (descr["spec"]:"" == dev)
type = key;
});
new_entries[dev] = fstabline2map ((list<string>)
FileSystems::GetFstabDefaultList (type));
}
else if (contains (["zip", "floppy"], part["found"]:""))
{
map fstline = fstabline2map ((list<string>)
FileSystems::GetFstabDefaultList (part["found"]:""));
fstline["spec"] = part["dev_orig"]:(part["dev_name"]:"");
fstline["mount"] = find_next_media_file (part["found"]:"");
new_entries[dev] = fstline;
}
else if ("cdrom" == part["found"]:"")
{
map ret = Storage::MakeCdromFstabEntry (part);
// new_entries[dev] = ret; // workaround for bug #185575
}
else {
y2error("creating an entry for %1 is not possible (3)", dev);
}
});
if (size (new_entries) == 0) {
y2error("creating fstab entries is not possible (4)");
}
else {
y2milestone("Suggested new fstab entries %1", new_entries);
}
return new_entries;
}
/**
* @param cmp:
* fstab line nr : mount point
* cmp : $[ 1 : "/hhh",
* 2 : "/mnt/uuu" ];
*
* @return create failed for mount points $[ 1 : "/hhh" ];
*/
global define map check_and_create_mount_points(map cmp) ``{
map failed = $[];
foreach (integer lnr, string missing_dir, (map<integer,string>) cmp, ``{
if (substring (missing_dir , 0,1) == "/")
{
list<string> subdirs = filter (string sdir, splitstring (missing_dir, "/"), ``( sdir != ""));
string mkdir = root_mountpoint + "/";
foreach (string sdir, subdirs, ``{
mkdir = mkdir + "/"+ sdir;
if (! OSRExecute::Command(.local.bash, sformat ("/usr/bin/test -d %1", mkdir)))
OSRExecute::Command(.local.bash, sformat ("/bin/mkdir %1", mkdir));
});
if (! OSRExecute::Command(.local.bash, sformat ("/usr/bin/test -d %1", root_mountpoint + missing_dir)))
{
failed[lnr] = missing_dir;
}
}
});
if (size (failed) == 0)
{
// popup message
Report::Message(_("
All missing mount points were
created successfully.
"));
}
else if (size (failed) > 1)
{
// error popup
Report::Error (sformat (_("
Could not create the
following mount points:
%1
"), mergestring ((list<string>)
maplist (integer lnr, string dir, (map<integer,string>) failed,``(dir)), "\n")));
}
else if (size (failed) == 1)
{
Report::Error(sformat (_("
Could not create the
mount point:
%1
"), mergestring ((list<string>)
maplist (integer lnr, string dir,(map<integer,string>) failed, ``(dir)), "\n")));
}
return failed;
}
/**
* Dialog for existing devices that are not listed in the fstab.
*/
define symbol SuggestMissingEntriesDialog()``{
map new_entries = suggest_missing_entries();
if (size (new_entries) == 0) return `error;
string help_text = _("
<P>No valid fstab entry was found
for the devices listed in the table.
</P>
<P>
Select the devices for which
to create a new fstab entry
and enter a mount point.
</P>
<P>After creating mount points for all
devices, press Repair
to continue.
</P>
");
help_text = help_text +
OSRPopup::build_label_description (device_label, _("The name of the device for which no valid fstab
entry was found.
")) +
OSRPopup::build_label_description (mount_label, _("The mount point for the found device. This
mount point is created in the file system. If you leave the mount point field empty, no fstab entry will be created.
")) +
OSRPopup::build_label_description (create_mp_label, _("Add a mount point for a device."));
OSRPopup::OpenSuggestDialog(_("Add fstab Entries"),
_("
Select the devices for which to
create a new fstab entry and enter a mount point.
"),
help_text,
`VBox(`Left(`Label(_("Devices without Valid fstab Entry"))),
`Table(`id(`table), `header(device_label, mount_label), missing_devs_items(new_entries)),
`Right(`PushButton(`id(`mountpoint), create_mp_label))) ,70 );
symbol ret = `ok;
repeat
{
ret = (symbol) UI::UserInput();
if (ret == `mountpoint)
{
string current = (string)UI::QueryWidget(`id(`table),`CurrentItem);
if (current != nil && current != "")
{
string text = OSRPopup::ChangeFieldDialog (
new_entries[current,"mount"]:"",
// TextEntry label, %1 is device label
sformat (_("
Mount Point for %1
"), new_entries[current,"spec"]:""));
if (text != nil)
{
new_entries[current,"mount"] = text;
UI::ChangeWidget(`id(`table),
`Items, missing_devs_items (new_entries));
}
}
}
if (ret == `ok)
{
integer changed_size = size (
filter (string k,map e, (map<string,map<string,any> >)new_entries, ``(
e["spec"]:"" != "" && e["mount"]:"" != ""))
);
if (changed_size == 0)
{
Report::Warning(_("
First create mount points
for the listed devices.
"));
ret = `notok;
continue;
}
else if (changed_size < size (new_entries))
{
// yes/no popup headline
if (!Popup::YesNoHeadline (_("Empty Mount Point"),
// yes/no popup text
_("
Valid mount points are required to
create fstab entries for devices.
You did not enter a mount point
for all devices. If you continue
now, fstab entries are only created
for devices with mount points.
Really continue?
")))
{
ret = `notok;
continue;
}
}
// create mount point (cmp)
map cmp = $[];
integer fack_lnr = 0;
foreach (string k, map e, (map<string,map<string,any> >)new_entries, ``{
if (e["spec"]:"" != "" && e["mount"]:"" != ""){
list<string> fstlist = [ k , e["mount"]:"",
e["vfstype"]:"", e["mntops"]:"",
sformat ("%1",e["freq"]:nil),
sformat ("%1",e["passno"]:nil) ];
cmp[fack_lnr] = e["mount"]:"";
fack_lnr = fack_lnr + 1;
AsciiFile::AppendLine( fstab, fstlist);
}
});
map failed = check_and_create_mount_points(cmp);
if (size (failed) > 0) ret = `error;
}
} until( ret == `ok || ret == `cancel || ret == `error);
UI::CloseDialog();
return ret;
}
/**
*
*/
define map suggest_create_mp()``{
// found fstab line without valid mount point, e.g. (not_valid_lines):
// $[4: ["dev", false, true, true ,true ,true ,true ]], //spec error
list<integer> cmpl = maplist (integer kk, list vv,
filter (integer k, list v, (map<integer,list>) not_valid_lines,
{
return
v[1]:true == true &&
v[2]:true == false &&
substring (fstab [4, "fields", 1]:"", 0, 1) == "/" &&
(fstab_defaults[v[0]:"","mount"]:"" == "" || v[0]:"" == "pts");
}),
``(kk)
);
if (Mode::test ()) cmpl = [1,2];
return AsciiFile::GetLines (fstab, cmpl);
}
/**
*
*/
define list<term> create_mp_items(map cmp)``{
list<term> ret = [];
foreach (integer lnr, map v, (map<integer,map<string,any> >)cmp, ``{
ret = add (ret,
`item (`id(lnr), create_label, v["fields",1]:"", v["fields",0]:""));
});
return ret;
}
/**
*
*/
define symbol SuggestCreateMp()``{
map missing_create_mp = suggest_create_mp();
if (size (missing_create_mp) == 0) return `ok;
// help text
string help_text = _("
<P>The /etc/fstab file does not contain
valid mount points for the listed devices.
</P>") +
//%1 is Ignore label and %2 is Create label
OSRPopup::build_label_description (state_label, sformat (_("
The status of a listed line can be switched between
%1 and %2. Mount points for a partition are only created
if the the status is %2.
"), ignore_label, create_label)) +
OSRPopup::build_label_description (mount_label, _("
This field contains the present entry
of the mount point in fstab.
Change this field to a valid mount point.
If you do not want to create the mount point,
select the corresponding line in the table and change
the status to ignore.
")) +
// %1 is Ignore label
OSRPopup::build_label_description (b_ignore_label, sformat (_("Change the status of the line to %1.
"),ignore_label)) +
// %1 is Create label
OSRPopup::build_label_description (b_create_label, sformat (_("Change the status of the line to %1.
"), create_label));
OSRPopup::OpenSuggestDialog( _("Create Mount Points"),
_("
Some mount points for fstab entries are missing in
the file system. Change the status of the
lines for which to create a mount point.
"),
help_text,
`VBox(`Left(`Label(_("Missing or Invalid Mount Points"))),
`Table(`id(`table), `header( state_label, mount_label, device_label ),
create_mp_items(missing_create_mp)),
`HBox(`PushButton(`id(`ignore), b_ignore_label),
`PushButton(`id(`create), b_create_label),
`Right(`PushButton(`id(`change), b_change_mp_label))),
`VSpacing(1)
), 50);
UI::SetFocus(`id(`table));
symbol ret = `ok;
map cmp = $[];
repeat
{
ret = (symbol) UI::UserInput();
integer current_item = (integer)
UI::QueryWidget(`id(`table), `CurrentItem);
if (ret == `ignore)
{
UI::ChangeWidget (`id(`table), `Item(current_item,0), ignore_label);
}
else if (ret == `create)
{
UI::ChangeWidget (`id(`table), `Item(current_item,0), create_label);
}
else if (ret == `change)
{
integer current = (integer)
UI::QueryWidget(`id(`table), `CurrentItem);
if (current != nil)
{
string text = OSRPopup::ChangeFieldDialog (
// TextEntry label, %1 is device
missing_create_mp [current,"fields",1]:"", sformat (_("
Mount Point for %1
"), missing_create_mp[current,"fields",0]:""));
if (text != nil)
{
missing_create_mp[current,"fields",1] = text;
UI::ChangeWidget (`id(`table), `Items,
create_mp_items (missing_create_mp));
}
}
}
else if (ret == `ok)
{
cmp = $[];
foreach (integer e, map lines, (map<integer,map>) missing_create_mp,
{
term it = (term) UI::QueryWidget(`id(`table), `Item(e));
if (it[1]:"" == create_label)
{
cmp[e] = lines["fields", 1]:"";
}
});
}
} until( ret == `ok || ret == `cancel);
UI::CloseDialog();
if (ret == `ok)
{
map failed = check_and_create_mount_points( cmp);
if (size (failed) == 0)
{
foreach (integer lnr, string dir, (map<integer,string>) cmp,``{
fstab["l",lnr,"fields",1] = dir;
// rebuild the hole entry
not_valid_lines[lnr,3] = false;
not_valid_lines[lnr,4] = false;
not_valid_lines[lnr,5] = false;
not_valid_lines[lnr,6] = false;
});
}
else if (size (failed) > 1)
{
// suggest to remove the line
foreach (integer lnr, string dir, (map<integer,string>) failed, ``{
not_valid_lines = filter (integer llnr, list<any> v, (map<integer,list<any> >)not_valid_lines,
``( llnr != lnr));
});
ret = `error;
}
else if (size (failed) == 1)
{
// suggest to remove the line
foreach (integer lnr, string dir, (map<integer,string>) failed, ``{
not_valid_lines = filter (integer llnr, list<any> v, (map<integer,list<any> >)not_valid_lines,
``( llnr != lnr));
});
ret = `error;
}
}
return ret;
}
/**
* Find all fstab entries (line nr) with not existing devices.
*/
define list<integer> suggest_remove_spec()``{
// spec not valid (false) -> remove
list<integer> rm = (list<integer>) maplist (integer n, list m,
filter (integer k, list<any>v, (map<integer,list<any> >)not_valid_lines, ``( v[1]:true == false)),
``(n));
return rm;
}
/**
* Build a item list for all fstab entries with not existing devices.
*/
define list<term> remove_spec_items(list<integer> rm_entries, string ignore_label)
{
list<term> ret = [];
foreach (integer lnr, rm_entries, {
map line = AsciiFile::GetLine (fstab, lnr);
ret = add (ret, `item (`id(lnr), ignore_label, line["line"]:""));
});
return ret;
}
/**
* Dialog for all fstab entries with not existing devices.
*/
define symbol SuggestRemoveSpecDialog()``{
list<integer> rm_entries = suggest_remove_spec();
if (size (rm_entries) == 0) return `ok;
string help_text = OSRPopup::build_label_description (state_label,
// help text in fstab dialog, %1 is Ignore label, %2 is Remove label
sformat (_("
The status of a listed line can be switched between
%1 and %2. fstab entries are only removed if the the status of the
corresponding line is %2.
"), ignore_label, remove_label)) +
// %1 is Ignore label
OSRPopup::build_label_description (b_ignore_label, sformat (_("Change the status of the line to %1.
"), ignore_label)) +
// %1 is Remove label
OSRPopup::build_label_description (b_remove_label, sformat (_("Change the status of the line to %1.
"), remove_label));
OSRPopup::OpenSuggestDialog(
// dialog caption, fstab is filename
_("Remove fstab Entries"),
// dialog text
_("Could not find existing devices for the following fstab lines.
To remove the lines from fstab, select them in the table and
change the status.
"),
help_text,
`VBox(
// label (table will follow)
`Left(`Label(_("Invalid or Obsolete Lines in fstab"))),
`Table(`id(`table),
`header(state_label, fstab_line_label),
remove_spec_items(rm_entries, ignore_label)),
`Left(`HBox(
`PushButton(`id(`ignore), b_ignore_label),
`PushButton(`id(`remove), b_remove_label)))
), 50);
UI::SetFocus(`id(`table));
symbol ret = `ok;
repeat
{
ret = (symbol) UI::UserInput();
integer current_item =
(integer) UI::QueryWidget(`id(`table), `CurrentItem);
if (ret == `ignore)
{
UI::ChangeWidget(`id(`table), `Item(current_item, 0), ignore_label);
}
else if (ret == `remove)
{
UI::ChangeWidget(`id(`table), `Item(current_item, 0), remove_label);
}
else if (ret == `ok)
{
list<integer> rm_list = [];
foreach (integer e, rm_entries, {
term it = (term) UI::QueryWidget(`id(`table), `Item(e));
if (it[1]:"" == remove_label)
{
rm_list = add (rm_list, e);
}
});
y2milestone("lines to remove %1", rm_list);
AsciiFile::RemoveLines(fstab, rm_list);
}
} until( ret == `ok || ret == `cancel);
UI::CloseDialog();
return ret;
};
/**
* Find all fstab lines with at least one invalid position
*/
define map suggest_modify()``{
y2milestone("starting modify suggestion");
/*
map modify_entries = filter (integer k, list<any> v, (map<integer,list<any> >)not_valid_lines,
``( v[1]:false == true));
*/
map modify_entries = filter (integer k, list v,
(map<integer,list>) not_valid_lines,``( v[1]:false == true));
if (size (modify_entries) == 0) return $[];
map nlines = $[];
foreach (integer lnr, list opts, (map<integer,list>) modify_entries,
{
map linemap = AsciiFile::GetLine (fstab, lnr);
list<string> line = linemap ["fields"]:[];
list<string> nline = [line[0]:""];
map part = line2part(line);
string type = opts[0]:"";
list default_line = FileSystems::GetFstabDefaultList (type);
if (opts[2]:true == false)
{
if (fstab_defaults [type,"mount"]:"" != "" && type != "pts")
{
nline = add (nline, fstab_defaults[type,"mount"]:"");
}
else
{
AsciiFile::RemoveLines(fstab, [ lnr ]);
return;
}
}
else
{
nline = add (nline , line[1]:"");
}
// invalid vfstype
if (opts[3]:true == false)
{
if (type == "dev" )
{
string detected_fs = FileSystems::GetMountString (
part["detected_fs"]:part["used_fs"]:`unknown, "");
if (detected_fs != "")
{
nline = add (nline, detected_fs);
}
else
{
y2error("could not repair the defect fstab line %1", line);
return;
}
}
else
{
// proc, usb, pts
string fs = fstab_defaults[type,"vfstype"]:"";
if (fs != "")
nline = add (nline, fs);
else
{
y2error("invalid type");
return;
}
}
}
else
{
nline = add (nline, line[2]:"");
}
integer i = 4;
while (i <= 6)
{
// invalid ops
if (opts[i]:true == false)
{
string str = default_line[i-1]:"";
if (str != "")
nline = add (nline, str);
else
{
y2error("not valid %2 for line %1 found", line,
pos2field[i-1]:"");
}
//set following pos to false
integer ii = i+1;
while (ii <=6)
{
opts[ii] = false;
ii = ii+1;
}
}
else
{
nline = add (nline, line[i-1]:"");
}
i = i +1;
}
nline = filter (string pos, nline, ``( pos != nil && pos != ""));
if (size (nline) == 6 && nline != line)
{
nlines[lnr] = nline;
}
else if (nline != line)
{
y2error("the size of the suggested fstab entry is to less");
}
});
return nlines;
}
/**
* Build a item list.
*/
define list<term> modify_items (map nlines, string ignore_label, boolean existing)
{
list<term> ret = [];
foreach (integer lnr, list<string> nline,(map<integer,list<string> >)nlines,
{
if (existing)
{
map linemap = AsciiFile::GetLine(fstab,lnr);
nline = linemap["fields"]:[];
}
ret = add (ret,`item(`id(lnr), ignore_label, mergestring(nline, ", ")));
});
return ret;
};
/**
* Dialog for all fstab entries that have at least one invalid entry.
*/
define symbol SuggestModifyDialog()``{
map nlines = suggest_modify();
if (size (nlines) == 0)
return `ok;
//label of table, fstab is filename
string existing_label = _("Existing fstab Lines");
//label of table, fstab is filename
string suggested_label = _("Suggested fstab Lines");
// help text, %1 is table label for Suggested. %2 is Replace button label
string help_text = sformat (_("
One or more existing fstab entries seem to
be invalid. Compare the suggested entry
with the existing one.
To replace an existing line with a suggested
line, select the corresponding line
in the %1 table and
press %2.
"), suggested_label, b_replace_label) +
//%1 is Ignore label, %2 is replace label
OSRPopup::build_label_description (state_label, sformat (_("
The status of a listed line can be switched between
%1 and %2. Lines are only replaced if the status is %2.
"), ignore_label, replace_label)) +
//%1 is Ignore label
OSRPopup::build_label_description (b_ignore_label, sformat (_("Change the status of the line to %1.
"), ignore_label)) +
//%1 is Replace label
OSRPopup::build_label_description (b_replace_label, sformat (_("Change the status of the line to %1.
"), replace_label));
// dialog headline
OSRPopup::OpenSuggestDialog (_("Change Existing fstab Entries"),
// dialog description
_("
One or more existing fstab entries seem invalid.
Compare the suggested entry with the existing one."),
help_text,
`VBox (
`Left(`Label(existing_label)),
`Table (`id(`table_e), `opt(`disabled),
`header (state_label, fstab_line_label),
modify_items (nlines, ignore_label, true)
),
`VSpacing(1),
`Left(`Label(suggested_label)),
`Table(`id(`table_s), `opt(`notify),
`header (state_label, fstab_line_label),
modify_items(nlines,ignore_label, false)
),
`Left (`HBox(
`PushButton(`id(`ignore), b_ignore_label),
`PushButton(`id(`replace),b_replace_label)
))
),
80
);
UI::SetFocus(`id(`table_s));
symbol ret = `ok;
repeat
{
ret = (symbol) UI::UserInput();
integer current_item =
(integer) UI::QueryWidget(`id(`table_s), `CurrentItem);
UI::ChangeWidget (`id(`table_e), `CurrentItem, current_item);
if (ret == `ignore)
{
UI::ChangeWidget(`id(`table_s), `Item(current_item,0),ignore_label);
UI::ChangeWidget(`id(`table_e), `Item(current_item,0),ignore_label);
}
else if (ret == `replace)
{
UI::ChangeWidget(`id(`table_s),`Item(current_item,0),replace_label);
UI::ChangeWidget(`id(`table_e),`Item(current_item,0),replace_label);
}
else if (ret == `ok)
{
integer changed_count = size (
filter (integer e, any ld, (map<integer,any>) nlines, {
term it = (term)UI::QueryWidget(`id(`table_s),`Item(e));
return (it[1]:"" == replace_label);
})
);
if (changed_count == 0)
{
Report::Warning(_("
Set the status of at least one
table entry to replace.
"));
ret = `notok;
continue;
}
else if (changed_count < size (nlines))
{
// yes/no popup headline
if (! Popup::YesNoHeadline (_("Not All Replaced"),
// yes/no popup text
_("
Only the fstab lines marked for replacement
are replaced. Really replace only the
selected lines?
")))
{
ret = `notok;
continue;
}
}
list<integer> rp_list = [];
foreach (integer e, any ld, (map<integer,any>) nlines, {
term it = (term) UI::QueryWidget (`id(`table_s),`Item (e));
if (it[1]:"" == replace_label)
{
rp_list = add (rp_list, e);
}
});
y2milestone("lines to remove %1", rp_list);
AsciiFile::RemoveLines(fstab, rp_list);
// save and reread before append fstab !!
// Remove don't resort list positions!!
AsciiFile::RewriteFile (fstab, root_mountpoint + fstabpath);
ReadFstab (root_mountpoint, true);
foreach (integer rp, rp_list, ``{
AsciiFile::AppendLine(fstab, nlines[rp]:[]);
});
}
} until( ret == `ok || ret == `cancel);
UI::CloseDialog();
return ret;
}
define symbol ret_worst_symbol(list<symbol> retl)``{
map symbol_weight = $[
`ok : 1,
`cancel : 2,
`error : 3,
`abort : 2
];
symbol ret = `ok;
foreach (symbol r, retl, ``{
if (symbol_weight[ret]:0 < symbol_weight[r]:-1)
ret = r;
});
return ret;
}
/**
* Repair the fstab. Call sub dialogs.
*/
global define symbol Repair () ``{
list<symbol> ret = [];
if (Mode::test ())
{
return `ok;
}
if (size (missing_devs) > 0) {
y2milestone ("-------------- missing devices: %1", missing_devs);
ret = add (ret, SuggestMissingEntriesDialog());
}
if (size (not_valid_lines) > 0) {
y2milestone ("-------------- not valid lines: %1", not_valid_lines);
ret = add (ret, SuggestCreateMp());
ret = add (ret, SuggestRemoveSpecDialog());
ret = add (ret, SuggestModifyDialog());
}
y2milestone("ret repair list %1", ret);
if ((size (filter (symbol r, ret, ``( r == `ok))) > 0))
{
AsciiFile::RewriteFile (fstab, root_mountpoint + fstabpath);
ResetSettings ();
ReadFstab (root_mountpoint, true);
}
else
{
y2milestone("new fstab was not written");
return `cancel;
}
return ret_worst_symbol(ret);
}
/**
*
*/
global define boolean CheckRootEntry (string dev_name,
list<string> tswapable_partition_list,
list<string> tchecked_partitions)``{
ResetSettings();
y2milestone("check root fstab entry");
swapable_partition_list = tswapable_partition_list;
checked_partitions = tchecked_partitions;
boolean ret = false;
map root_part = devname2part (dev_name);
list root_l_no = AsciiFile::FindLineField (fstab, 0, dev_name);
root_l_no = union (root_l_no,
AsciiFile::FindLineField (fstab, 0, "UUID=" + root_part["uuid"]:""));
root_l_no = union (root_l_no,
AsciiFile::FindLineField (fstab, 0, "LABEL=" + root_part["label"]:""));
// root_lines example:
// $[ 1 : $["fields":["/dev/hda3", "/", "reiserfs", "defaults", "1", "2"],
// "line":"/dev/hda3\t/\treiserfs\tdefaults 1 2" ]
// ]
map<integer,map> root_lines = $[];
foreach (integer n, (list<integer>) root_l_no, {
root_lines[n] = AsciiFile::GetLine(fstab, n);
});
root_lines =
filter (integer n, map l, root_lines, ``(l["fields",1]:"" == "/"));
if (size (root_lines) != 1)
{
y2error(" several or non root entries in fstab found");
y2error(" root lines %1", root_lines);
missing_devs = add (missing_devs, dev_name);
ret = false;
}
else
{
list keys = maplist (integer k, map v, root_lines,``(k));
integer root_line_key = keys[0]:1;
list<string> root_line = root_lines [root_line_key, "fields"]:[];
string type = "root";
boolean fs_vfstype = check_fs_vfstype (root_line, root_part);
boolean fs_mntops = check_fs_mntops (root_line);
boolean fs_freq = check_fs_freq (root_line,
[ tostring (fstab_defaults [type, "freq"]:0) ]);
boolean fs_passno = check_fs_passno (root_line,
[ tostring (fstab_defaults [type, "passno"]:0) ]);
if (! fs_vfstype)
{
y2error("root fstype not valid");
}
if (! fs_mntops)
{
y2error("root mntops not valid");
}
if (! fs_freq)
{
y2error("root freq not valid");
}
if (! fs_passno)
{
y2error("root passno not valid");
}
if (fs_vfstype && fs_mntops && fs_freq && fs_passno)
{
valid_lines = add (valid_lines, root_line_key);
y2milestone("root fstab line entry is valid");
}
else
{
y2error("root fstab line is not valid");
not_valid_lines [root_line_key] =
[ type, true, true, fs_vfstype, fs_mntops, fs_freq, fs_passno];
}
ret = (fs_vfstype && fs_mntops && fs_freq && fs_passno);
}
//for OSRBoot
root_part["mount"] = "/";
Storage::ChangeVolumeProperties(root_part);
//inst_prepdisk for OSRBoot!
foreach (string modname, (list<string>)FileSystems::GetNeededModules (
root_part["detected_fs"]:(root_part["used_fs"]:`ext2)), ``{
Initrd::AddModule (modname, "");
});
return ret;
}
/**
*
*/
global define string BootDev() ``{
map lines = fstab["l"]:$[];
list line = maplist (integer llineno, map llinedata,
filter (integer lineno, map<string,any> linedata, (map<integer,map<string,any> >) lines , ``(
linedata["fields", 1]:"" == "/boot")),
``(llinedata)
);
string ret = "";
if (size (line) == 1)
{
map part = line2part(line[0,"fields"]:[]);
ret = part["dev_name"]:part["device"]:"";
}
else
{
y2milestone("no /boot device in fstab");
}
if (ret == nil)
ret = "";
return ret;
}
/**
* ask user to select the root partition
*/
global define string SelectRoot (list<map> valid_root_partition_list) {
if (size (valid_root_partition_list) == 1)
return valid_root_partition_list[0,"device"]:"";
return OSRPopup::RadioButtonGroupText (
// popup headline
_("Select a Root Partition"),
// popup text (radio buttons wil follow
_("There are several valid root partitions in your system.
Select one item in the list.
"),
(list<list>) maplist (map entry, valid_root_partition_list, ``(
[
entry["device"]:"",
entry["label"]:""
]
)),
"",
"",
true
);
}
/**
*
*/
global define boolean ReadedSuccessfully() ``{
return ( fstab != nil && fstab != $[]);
}
/**
*
*/
global define list<map> UmountAll (list<map> umount_list) ``{
integer counter_error = 0;
list<map> just_umounted = [];
list<map> mnt_list = [];
mnt_list = filter (map s, umount_list, ``(
substring (s["file"]:s["mountpoint"]:"", 0, size (root_mountpoint))
== root_mountpoint)
);
mnt_list = sort (map x, map y, mnt_list, ``(
size (splitstring (x["file"]:x["mountpoint"]:"", "/")) >
size (splitstring (y["file"]:y["mountpoint"]:"" ,"/")))
);
y2milestone("partitions which should be umounted %1", mnt_list);
// umount all partitions from "/mnt" or deeper, as long as there are no
// more mounted partitions with mountpoint "/mnt..."
foreach (map current, mnt_list, ``{
if (OSRExecute::Command (.local.bash,
"/bin/umount "+ current["file"]:current["mountpoint"]:""))
{
just_umounted = add (just_umounted, $[
"partition" : current["spec"]:current["partition"]:"",
"mountpoint" : current["file"]:current["mountpoint"]:"" ]
);
}
else
{
y2error(" %1 could not be umounted",
current["file"]:current["mountpoint"]:"");
counter_error = counter_error +1;
}
});
if (counter_error == 0)
{
y2debug("All partitions were successfully umounted from /mnt...");
}
return just_umounted;
}
/**
*
*/
global define list<map> UmountAllFrom( string root)``{
if (root != "" && root != nil)
root_mountpoint = root;
list<map> just_umounted = [];
list<map> mounted_partitions = Partitions::CurMounted();
// filter swap partitions
mounted_partitions = filter (map p, mounted_partitions, ``(
p["file"]:"" != "swap" && findfirstof (p["spec"]:"", "/") == 0));
// filter the list of partitions that are mounted to "/mnt" or deeper
if (root_mountpoint != "/")
{
just_umounted = UmountAll( mounted_partitions);
}
return just_umounted;
}
/**
*
*/
global define list<map> RootDev(string root)``{
if (root != "" && root != nil)
root_mountpoint = root;
list<map> mounted = [];
if (! ReadedSuccessfully())
{
list<string> checked_partitions = filter (string s,
maplist (map p, OSRFsck::PossiblePartitions(), ``(p["device"]:"")),
``(s !=""));
list<string> linux_partition_list =
LinuxPartitions(checked_partitions);
list<string> mount_possible_list =
MountablePartitions (linux_partition_list, root_mountpoint);
list<map> valid_root_partitions =
ValidRootPartitions (mount_possible_list, root_mountpoint);
if (size (valid_root_partitions) == 0)
{
// error popup: no root partition found
Report::Error(_("
No valid root partition found.
Go back and select all scan
options. Afterwards, restart
scanning.
"));
return nil;
}
string root_partition = SelectRoot (valid_root_partitions);
y2milestone("selected root_partition %1" ,root_partition);
boolean mount = OSRExecute::Command (.local.bash,
sformat ("/bin/mount %1 %2", root_partition, root_mountpoint));
mounted = add (mounted, $[
"partition" : root_partition,
"mountpoint" : root_mountpoint,
"status" : mount ]
);
if (mount)
{
OSRSystem::ChangeRoot("/");
ReadFstab(root_mountpoint, true);
}
else
{
y2error("can not mount root partition");
}
}
y2milestone("RootDev in Fstab %1" ,mounted);
return mounted;
}
/**
* Mount all partitions specified in the fstab.
* If no fstab was readed try to find root partition
* and read fstab. Afterwards mount all partitions.
*/
global define list<map> MountAll(string root)``{
list<map> mounted = [];
if (root != "" && root != nil)
root_mountpoint = root;
if (OSRFsck::LoadAllFsModules())
{
y2milestone("kernel fs modules successful loaded");
}
else
{
y2error("loaded kernel modules returned an error");
}
// if fstab is not readed.
// Fstab functions are not called.
// user skiped execution of osr_module_partition,
// but need a root partition -> find root and
// read fstab.
list<map> t_mounted = RootDev(root_mountpoint);
if (t_mounted != nil && t_mounted != [])
mounted = (list<map>) union (mounted, t_mounted);
if (! ReadedSuccessfully())
{
Report::Error(_("
Cannot read the file /etc/fstab.
Initialization of the target system
is not possible. Go back
and select all scan options.
"));
return nil;
}
//sort fstab lines /mnt/hh/kk > /mnt/hh
list<map> lines = (list<map>) maplist (integer lnr, map linedata,
fstab["l"]:$[], ``(linedata));
foreach (map linedata, lines, ``{
list<string> line = linedata["fields"]:[];
map part = line2part (line);
// not mounted
if ((part["found"]:"" == "dev") &&
(!contains (["/dev/cdrecorder", "/dev/cdrom", "/dev/dvd",
"/media/cdrecorder", "/media/cdrom", "/media/dvd" ],
line[1]:"")) &&
(Storage::DeviceMounted(line[1]:"") == "")
&& ( line[1]:"" != "/"))
{
string mp = root_mountpoint + line[1]:"";
mounted = add (mounted , $[
"partition" : line[0]:"",
"mountpoint" : mp,
"status" : OSRExecute::Command (.local.bash,
sformat ("/bin/mount %1 %2", line[0]:"", mp))
]
);
}
});
OSRSystem::ChangeRoot(root_mountpoint);
y2milestone(" Mount all return %1", mounted);
return mounted;
}
}//EOF