ACC SHELL
{
import "Storage";
import "FileSystems";
import "FileUtils";
import "Directory";
import "SystemFilesCopy";
import "ProductFeatures";
import "ProductControl";
import "InstData";
import "String";
// --> Functions
define void Initialize ();
define map <string, map <string, integer> > FindTheBestFiles (map <string, map <string, integer> > files_found);
define void FindAndCopyNewestFiles (string copy_to, list <string> wanted_files, list <string> optional_files);
// --> Variables
// all partitions that can be used as a
list <map <string, any> > useful_partitions = [];
/* ******************************************************************************* */
// --> main()
Initialize();
if (SystemFilesCopy::GetUseControlFileDef()) {
y2milestone ("Using copy_to_system from control file");
// FATE #305019: configure the files to copy from a previous installation
// -> configuration moved to control file
list <map> copy_items = (list <map>) ProductFeatures::GetFeature ("globals", "copy_to_system");
foreach (map one_copy_item, copy_items, {
string copy_to_dir = tostring (one_copy_item["copy_to_dir"]:Directory::vardir);
list <string> mandatory_files = (list <string>) one_copy_item["mandatory_files"]:[];
list <string> optional_files = (list <string>) one_copy_item["optional_files"]:[];
FindAndCopyNewestFiles (copy_to_dir, mandatory_files, optional_files);
});
}
if (SystemFilesCopy::GetCopySystemFiles() != []) {
y2milestone ("Using additional copy_to_system");
foreach (map one_copy_item, SystemFilesCopy::GetCopySystemFiles(), {
string copy_to_dir = tostring (one_copy_item["copy_to_dir"]:Directory::vardir);
list <string> mandatory_files = (list <string>) one_copy_item["mandatory_files"]:[];
list <string> optional_files = (list <string>) one_copy_item["optional_files"]:[];
FindAndCopyNewestFiles (copy_to_dir, mandatory_files, optional_files);
});
}
// free the memory
useful_partitions = nil;
// at least some return
return `auto;
// <-- main()
/* ******************************************************************************* */
// --> Functions
/**
* Finds the newest files in the map
*
* @struct [
* "/dev/hda3" : $[
* "/etc/xyz" : 8445577887,
* "/etc/xzz" : 8445577888,
* ]
* ]
*/
define map <string, map <string, integer> > FindTheBestFiles (map <string, map <string, integer> > files_found) {
map <string, map <string, integer> > ret = $[];
integer max = 0;
// going through all partitions
foreach (string partition_name, map <string, integer> files_on_it, files_found, {
integer counter = 0;
integer filetimes = 0;
foreach (string filename, integer filetime, files_on_it, {
filetimes = filetimes + filetime;
counter = counter + 1;
});
// if there were some files on in
if (counter > 0) {
// average filetime (if more files were there)
filetimes = filetimes / counter;
// the current time is bigger (newer file) then the maximum found
if (filetimes > max) {
max = filetimes;
ret = $[];
ret[partition_name] = files_on_it;
}
}
});
return ret;
}
define void FindAndCopyNewestFiles (string copy_to, list <string> wanted_files, list <string> optional_files) {
y2milestone("Searching for files: %1", wanted_files);
string mnt_tmpdir = Directory::tmpdir + "/tmp_mnt_for_check";
mnt_tmpdir = SystemFilesCopy::CreateDirectoryIfMissing (mnt_tmpdir);
// CreateDirectory failed
if (mnt_tmpdir == nil) {
return nil;
}
map <string, map <string, integer> > files_found_on_partitions = $[];
foreach (map <string, any> partition, useful_partitions, {
string partition_device = (string) partition["device"]:"";
y2milestone("Mounting %1 to %2", partition_device, mnt_tmpdir);
string already_mounted = sformat ("grep '[\\t ]%1[\\t ]' /proc/mounts", mnt_tmpdir);
map am = (map) SCR::Execute (.target.bash_output, already_mounted);
if (am["exit"]:-1 == 0 && size (am["stdout"]:"") > 0) {
y2warning ("%1 is already mounted, trying to umount...", mnt_tmpdir);
if ((boolean) SCR::Execute (.target.umount, mnt_tmpdir) != true) {
y2error ("Cannot umount %1", mnt_tmpdir);
}
}
// mounting read-only
if (! (boolean) SCR::Execute(.target.mount, [partition_device, mnt_tmpdir], "-o ro")) {
y2error("Mounting falied!");
return;
}
boolean files_found = true;
map <string, integer> one_partition_files_found = $[];
foreach (string wanted_file, wanted_files, {
string filename_to_seek = mnt_tmpdir + wanted_file;
if (! FileUtils::Exists (filename_to_seek)) {
files_found = false;
return;
}
if (FileUtils::IsLink (filename_to_seek)) {
files_found = false;
return;
}
map file_attribs = (map) SCR::Read (.target.lstat, filename_to_seek);
if (file_attribs == nil || file_attribs == $[]) {
files_found = false;
return;
}
// checking for the acces-time
integer file_time = (integer) file_attribs["atime"]:nil;
if (file_time == nil || file_time == 0) {
files_found = false;
return;
}
// doesn't make sense to copy files with zero size
integer file_size = (integer) file_attribs["atime"]:nil;
if (file_size == nil || file_size == 0) {
files_found = false;
return;
}
one_partition_files_found[wanted_file] = file_time;
});
if (files_found) {
files_found_on_partitions[partition_device] = one_partition_files_found;
}
// bnc #427879
map exec = (map) SCR::Execute (.target.bash_output,
sformat ("fuser -v '%1' 2>&1", String::Quote (mnt_tmpdir))
);
if (exec["stdout"]:"" != "") {
y2error ("Processes in %1: %2", mnt_tmpdir, exec);
}
// umounting
y2milestone("Umounting %1", partition_device);
if (! (boolean) SCR::Execute(.target.umount, mnt_tmpdir)) {
y2error("Umount failed!");
}
});
y2milestone("Files found: %1", files_found_on_partitions);
map <string, map <string, integer> > ic_winner = $[];
// nothing found
if (size(files_found_on_partitions) == 0) {
y2milestone("No such files found");
// only one (easy)
} else if (size(files_found_on_partitions) == 1) {
ic_winner = files_found_on_partitions;
// more than one (getting the best ones)
} else {
ic_winner = FindTheBestFiles (files_found_on_partitions);
}
files_found_on_partitions = nil;
y2milestone("Selected files: %1", ic_winner);
// should be only one entry
foreach (string partition, map <string, integer> files, ic_winner, {
SystemFilesCopy::CopyFilesToTemp (
partition,
(list <string>) union (
maplist (string filename, integer filetime, files, { return filename; }),
optional_files
),
copy_to
);
});
}
/**
* Goes through disks and searches for usable partitions.
* Sets them to the 'useful_partitions' variable
*/
define void Initialize () {
y2milestone("Evaluating all current partitions");
map <string, map> target_map = (map <string, map>) Storage::GetTargetMap();
integer counter = -1;
foreach (string device_name, map device_descr, target_map, {
list <map <string, any> > partitons = (list <map <string, any> >) device_descr["partitions"]:[];
symbol filesystem = nil;
string devicename = nil;
foreach (map <string, any> partition, partitons, {
filesystem = (symbol) partition["used_fs"]:partition["detected_fs"]:nil;
devicename = (string) partition["device"]:nil;
if (filesystem == nil) {
y2milestone("Skipping partition %1, no FS detected", devicename);
return;
}
if (!contains(FileSystems::possible_root_fs, filesystem)) {
y2milestone("Skipping partition %1, %2 is not a root filesystem", devicename, filesystem);
return;
}
// adding the partition into the list of possible ones
counter = counter + 1;
useful_partitions[counter] = $[
"device" : partition["device"]:nil,
"fs" : filesystem,
];
});
});
y2milestone("Possible partitons: %1", useful_partitions);
}
}
ACC SHELL 2018