You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
calculate-utils-1/install/calculate

7261 lines
264 KiB

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#!/usr/bin/perl
use Cwd;
use IO::Socket;
use Time::Local;
#------------------------------------------------------------------------------
# Calculate
# Copyright ©2006-2010 Mir Calculate Ltd.
# Program established: 12.04.2006г.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#------------------------------------------------------------------------------
my %data; #объявим хэш переменных
$data{"calcver"} = "1.4.0";
#Определим путь к программе
if(!getpath()){exit;};
#Считаем входящие параметры и выполним простые действия
if(!getarg()){savelog(); exit;};
#Проверим на ошибки
if(!checkerrors()){savelog(); exit;};
#Определим систему для установки и обновления
welcome();
#Соберем сведения о системе
checksystem();
#------------------------------------------------------------------------------
# Выполним действия
#------------------------------------------------------------------------------
#Покажем все переменные
if(defined $data{arg}{'vars'}){
printvars(); #Выведем список переменных конфигурационных файлов
#Покажем список пакетов, входящих в дополнение
}elsif(defined $data{arg}{'L'}){
listadd();
#Соберем дополнение
}elsif(defined $data{arg}{'M'}){
makeadd();
#Установка дополнений
}elsif(defined $data{arg}{'addition'}){
addition();
#Сгенерируем новый initrd
}elsif(defined $data{arg}{'initrd'}){
initrd();
#Размаскируем пакеты
}elsif(defined $data{arg}{'unmask'}){
autounmask();
#Установим по необходимости видеодрайвер
}elsif(defined $data{arg}{'video'}){
video();
#Настроим OpenGL
}elsif(defined $data{arg}{'opengl'}){
opengl_set();
#Выполним обновления
}elsif(defined $data{arg}{update}){
checkupdate();
#Покажем информацию о компьютере
}elsif(defined $data{arg}{'hardware'}){
printhardware(); #Выведем конфигурацию ПК
#Настроим серверы CDS
}elsif(defined $data{arg}{'setup'}){
setupservers(); #настроим серверы
#Выполним резервное копирование данных серверов
}elsif(defined $data{arg}{'backup'}){
backupservers(); #настроим серверы
#Управление пользователями
}elsif(defined $data{arg}{'useradd'} || defined $data{arg}{'userdel'} || defined $data{arg}{'userpasswd'} || defined $data{arg}{'groupadd'} || defined $data{arg}{'groupdel'} || defined $data{arg}{'groupmod'}){
user(); #управление пользователями
#Управление почтовыми ящиками
}elsif(defined $data{arg}{'mailuseradd'} || defined $data{arg}{'mailuserdel'} || defined $data{arg}{'mailuserpasswd'} || defined $data{arg}{'mailgroupadd'} || defined $data{arg}{'mailgroupdel'}){
mail(); #управление пользователями
#Наложим обновления профилей на текущую систему
}elsif(defined $data{arg}{'profile'}){
update_profile();
#подключим swap
if($data{'swapon'}){
swapon();
}
#Выполним сборку новой системы
}elsif($data{builder}){
if(defined $data{arg}{list}){
if(!list()){
beep();
}
}elsif(defined $data{arg}{dependence}){
if(!dependence()){
beep();
}
}elsif(defined $data{arg}{make}){
if(!make()){
beep();
}elsif(!makepkg()){
beep();
#}elsif(!makecalculate()){
# beet();
}
}elsif(defined $data{arg}{pack}){
if(!packsystem()){
beep();
}
}elsif(defined $data{arg}{iso} || defined $data{arg}{rebuild}){
if(!createiso()){
beep();
}
}elsif(defined $data{arg}{'break'}){
if(!breakbuild()){
beep();
}
}else{
#Создадим директорию сборки
system "$data{path} mkdir $data{mount}";
#Соберем новый дистрибутив
if(!checkready()){system "$data{path} rmdir $data{mount}";} #Выполним проверки перед установкой
elsif(!extract()){system "$data{path} rmdir $data{mount}";} #Распакуем stage
elsif(!configure()){} #Подготовим систему к сборке
}
#Выполним установку новой системы
}elsif(
$data{linux} && !defined $data{arg}{'updateonly'} &&
#отменим установку с hdd если мы загрузились в scratch режиме и образа обновления не нашли
!($data{linux} eq 'scratch' && $data{load} eq '')
){
if(($data{load_cache} eq 'on' || $data{linux} eq 'scratch') && $data{type} eq 'flash' &&
$data{linux} !~ m/iso$/ ){
printmes("\n");
printmes(gettext('For installation on USB-Flash, reboot in normal mode'));
printmes(".\n");
beep(); exit 1;
}
#Создадим директорию установки
system "$data{path} mkdir $data{mount}";
#Установим новую версию системы
if(!checkready()){} #Выполним проверки перед установкой
elsif(!extract()){} #Распакуем систему
elsif(!profiles()){} #Наложим обновления
elsif(!setup()){} #Выполним общие настройки системы
elsif(!loader()){} #Подготовим систему к перезагрузке
elsif(!reboot()){} #Перезагрузим компьютер
#Удалим директорию установки
system "$data{path} rmdir $data{mount}";
#Выполним установку патчей
}else{
if(%{$data{patches}}){
patch();
}else{
printmes("\n".gettext('No updates available')); printmes(".\n");
}
}
savelog();
exit;
#------------------------------------------------------------------------------
#
# Определим путь к программе
#
#------------------------------------------------------------------------------
sub getpath{
#----------------------------------------------------------------------
# Добавим по необходимости переменные пути
#----------------------------------------------------------------------
{
$data{path} = '';
if(":$ENV{PATH}:"!~m|:/sbin:|){ $data{path}.= "/sbin:"; }
if(":$ENV{PATH}:"!~m|:/bin:|){ $data{path}.= "/bin:"; }
if(":$ENV{PATH}:"!~m|:/usr/sbin:|){ $data{path}.= "/usr/sbin:"; }
if(":$ENV{PATH}:"!~m|:/usr/bin:|){ $data{path}.= "/usr/bin:"; }
if($data{path}){ $data{path} = "PATH=$data{path}\${PATH} && "; }
}
#----------------------------------------------------------------------
# Путь к директории calculate, последнюю доступную версию системы
# $data{dir}
#----------------------------------------------------------------------
{
my $wd = &Cwd::cwd();
#добавим завершающий слеш в пути если его нет
if(substr($wd,length($wd)-1) ne "/"){$wd.="/";}
#удалим из файла запускаемой программы "./"
my $file = $0; if(substr($file,0,2) eq "./"){$file = substr($file,2);}
#склеим путь текущей директории с выполняемым файлом
my $path; if(substr($file,0,1) eq "/"){ $path = $file; }else{ $path = $wd.$file; }
#проверим на символическую ссылку
my $link = `$data{path} file $path`; chomp $link; #получим информацию о файле запуска
#если это символическая ссылка, сформируем путь
if($link=~m/.+symbolic link to \`([^']+)'$/){
$link = $1; #путь к файлу
if($link=~m/^\//){
$path = $link; #фактический путь при указании на прямой путь
}else{
$path=~s/(.+)\/[^\/]+/$1/; #директория символической ссылки
$path = "$path/$link"; #фактический путь при указании относительного пути в ссылке
}
}
#получим путь к директории calculate
$data{dir} = $path; $data{dir}=~s/(.+)\/[^\/]+/$1/;
$data{dir}=~s/(.+)\/([^\/]+)/$1/;
chdir($data{dir});
}
return 1;
}
#------------------------------------------------------------------------------
#
# Считаем входящие параметры и выполним простые действия
#
#------------------------------------------------------------------------------
sub getarg{
#краткое и полное название программы
$data{"calcname"} = "Calculate";
$data{'calcinstall'} = "$data{calcname} $data{calcver}";
#----------------------------------------------------------------------
# Считаем параметры запуска
# %{$data{arg}} %{$data{par}}
#----------------------------------------------------------------------
{
my $par = '';
#извлечем параметры слов
my @arg; foreach(@ARGV){
if(/^\-\-([^\s=]+)=(.+)$/){ $data{arg}{$1} = $2; $par++;}
elsif(/^\-\-([^\s]+)$/){$data{arg}{$1} = ''; $par++;}
else{push @arg, $_}
}
#обработаем параметры букв и дополнительные параметры - слова или буквы разделеныне пробелами
foreach(split "-", "@arg"){
if(!$_){next;}
my ($var, $val, @par) = split " ";
$data{arg}{$var} = "$val"; #параметры букв
if(@par){
foreach(@par){$data{par}{$_} = '';} #дополнительные параметры
}
$par++;
}
if(!$par){$data{NOPAR}++;}
}
#Проверим переданные параметры
{
#Допустимые переменные
my %arg = (
"a" => '', "addition" => '',
"s" => '', "os" => '',
"d" => '', "disk" => '',
"b" => '', "build" => '',
"f" => '', "force" => '',
"U" => '', "updateonly" => '',
"P" => '', "profile" => '',
"l" => '', "list" => '',
"c" => '', "configure" => '',
"D" => '', "dependence" => '',
"m" => '', "make" => '',
"p" => '', "pack" => '',
"iso" => '',
"rebuild" => '',
"break" => '',
"L" => '',
"M" => '',
#"S" => '', "setup" => '',
#"backup" => '',
"useradd" => '',
"userdel" => '',
"userpasswd" => '',
"groupadd" => '',
"groupdel" => '',
"groupmod" => '',
# "mailuseradd" => '',
# "mailuserdel" => '',
# "mailuserpasswd" => '',
# "mailgroupadd" => '',
# "mailgroupdel" => '',
"u" => '', "update" => '',
"h" => '', "help" => '',
"v" => '', "vars" => '',
"H" => '', "hardware" => '',
"V" => '', "version" => '',
"translate" => '',
"initrd" => '',
"unmask" => '',
"video" => '',
"opengl" => '',
"nodie" => '', #выводить минимум информации показывая неверно завершенную работу
"softly" => '', #не вылетать при ошибке запускаемой программы
"composite" => '',
);
my @write = (
"builderdir",
"cpus",
"domain",
"erase",
"format",
"gateway",
"hostname",
"iso",
"ldap_base",
"ldap_bind",
"ldap_bindpw",
"ldap_root",
"linuxver",
"makeopts",
"march",
"mbr",
"menuconfig",
"mesline",
"mestitle",
"mount",
"move_fstab",
"nfs",
"ntp",
"patchdir",
"proxy",
"server_url",
"skipfirst",
"swap",
"tmpdir",
"user_comment",
"user_groups",
"useradd",
"userdel",
"uuid",
"mail",
"video_drv",
"video_resolution",
"lang",
"timezone",
"type",
"clock",
"composite",
"scheduler",
"system",
"swapon",
"sleep",
);
foreach(@write){$data{write}{$_} ++;}
#Проверим переменные
foreach(keys %{$data{arg}}){
if( !defined $arg{$_} &&
$_!~/^set\-/i
){errorarg($_); return "";}
#Перенесем переданные значения
if($_=~m/^set\-(.+)/){
if($data{write}{$1}){
$data{$1} = $data{arg}{$_};
}else{
printmes(gettext('Incorrect variable name'));
printmes(" '$1' ");
printmes(gettext('or value cannot be changed'));
printmes(".\n");
printmes(gettext('Try')); printmes(" 'calculate --vars' "); printmes(gettext('for a print of all variables'));
printmes(".\n");
beep();
return "";
}
}elsif($_=~m/^SET\-(.+)/){
$data{$1} = $data{arg}{$_};
}
}
#Допустимые аргументы
my %par = ();
#Проверим аргументы
foreach(keys %{$data{par}}){
if(!defined $par{$_}){errorarg(-$_); return "";}
}
}
#----------------------------------------------------------------------
# Считаем параметры запуска, установим флаги действий
#----------------------------------------------------------------------
if(defined $data{arg}{'a'} || defined $data{arg}{'addition'}){
if(!defined $data{arg}{'addition'}){$data{arg}{'addition'} = $data{arg}{'a'}}
$data{CHECKSYSTEM_NOMES}++; $data{builder}++;
$data{addition} = lc($data{arg}{'a'});
}
if(defined $data{arg}{'s'} || defined $data{arg}{'os'}){
if(!defined $data{arg}{'os'}){$data{arg}{'os'} = $data{arg}{'s'}}
}
#Флаги установки и обновления системы
if($data{arg}{d} || $data{arg}{'disk'}){
if(!$data{arg}{'disk'}){$data{arg}{'disk'} = $data{arg}{'d'}}
}
if(defined $data{arg}{'b'} || defined $data{arg}{build}){
if(!$data{arg}{build}){$data{arg}{build} = $data{arg}{'b'}}
$data{scratch_ws} = "/workspace";
}
if(defined $data{arg}{f} || defined $data{arg}{'force'}){
if(!defined $data{arg}{'force'}){$data{arg}{'force'} = $data{arg}{'f'}}
}
if(defined $data{arg}{U} || defined $data{arg}{'updateonly'}){
if(!defined $data{arg}{'updateonly'}){$data{arg}{'updateonly'} = $data{arg}{'U'}}
$data{change}++; #флаг производимых в системе изменений
}
if(defined $data{arg}{P} || defined $data{arg}{'profile'}){
if(!defined $data{arg}{'profile'}){$data{arg}{'profile'} = $data{arg}{'P'}}
$data{CHECKSYSTEM_NOMES}++; $data{change}++; #флаг производимых в системе изменений
}
#Флаги сборки системы
if(defined $data{arg}{l} || defined $data{arg}{'list'}){
if(!defined $data{arg}{'list'}){$data{arg}{'list'} = $data{arg}{'l'}}
$data{CHECKSYSTEM_NOMES}++; $data{builder}++;
}
if(defined $data{arg}{c} || defined $data{arg}{'configure'}){
if(!defined $data{arg}{'configure'}){$data{arg}{'configure'} = $data{arg}{'c'}}
$data{builder}++;
}
if(defined $data{arg}{D} || defined $data{arg}{'dependence'}){
if(!defined $data{arg}{'dependence'}){$data{arg}{'dependence'} = $data{arg}{'D'}}
$data{CHECKSYSTEM_NOMES}++; $data{builder}++; $data{builder_chroot}++; #флаг того что директория chroot должна быть создана предварительно
}
if(defined $data{arg}{m} || defined $data{arg}{'make'}){
if(!defined $data{arg}{'make'}){$data{arg}{'make'} = $data{arg}{'m'}}
$data{builder}++; $data{builder_chroot}++;
}
if(defined $data{arg}{p} || defined $data{arg}{'pack'}){
if(!defined $data{arg}{'pack'}){$data{arg}{'pack'} = $data{arg}{'p'}}
$data{CHECKSYSTEM_NOMES}++; $data{builder}++; $data{builder_chroot}++;
}
if(defined $data{arg}{'iso'}){
$data{CHECKSYSTEM_NOMES}++; $data{builder}++;
$data{createiso}++;
}
if(defined $data{arg}{'rebuild'}){
$data{CHECKSYSTEM_NOMES}++; $data{builder}++;
$data{createiso}++;
}
if(defined $data{arg}{'break'}){
$data{CHECKSYSTEM_NOMES}++; $data{builder}++; $data{builder_chroot}++;
}
#Сборка дополнений
if(defined $data{arg}{'L'}){
$data{CHECKSYSTEM_NOMES}++; $data{builder}++;
if($data{arg}{'L'}){$data{addition} = lc($data{arg}{'L'});}
}
if(defined $data{arg}{'M'}){
$data{CHECKSYSTEM_NOMES}++; $data{builder}++;
if($data{arg}{'M'}){$data{addition} = lc($data{arg}{'M'});}
}
#Настройка сервера
# if(defined $data{arg}{S} || defined $data{arg}{'setup'}){
# if(!defined $data{arg}{'setup'}){$data{arg}{'setup'} = $data{arg}{'S'}}
# $data{CHECKSYSTEM_NOMES}++;
# }
# if(defined $data{arg}{'backup'}){
# $data{CHECKSYSTEM_NOMES}++;
# }
if(defined $data{arg}{'useradd'} || defined $data{arg}{'userdel'} || defined $data{arg}{'userpasswd'} || defined $data{arg}{'groupadd'} || defined $data{arg}{'groupdel'} || defined $data{arg}{'groupmod'}){
$data{CHECKSYSTEM_NOMES}++;
}
# if(defined $data{arg}{'mailuseradd'} || defined $data{arg}{'mailuserdel'} || defined $data{arg}{'mailuserpasswd'} || defined $data{arg}{'mailgroupadd'} || defined $data{arg}{'mailgroupdel'}){
# $data{CHECKSYSTEM_NOMES}++;
# }
#Флаг обновления системы
if(defined $data{arg}{u} || defined $data{arg}{'update'}){
if(!defined $data{arg}{'update'}){$data{arg}{'update'} = $data{arg}{'u'}}
$data{CHECKSYSTEM_NOMES}++;
}
#Флаги информационного вывода
if(defined $data{arg}{h} || defined $data{arg}{'help'}){
if(!defined $data{arg}{'help'}){$data{arg}{'help'} = $data{arg}{'h'}}
}
if(defined $data{arg}{v} || defined $data{arg}{'vars'}){
if(!defined $data{arg}{'vars'}){$data{arg}{'vars'} = $data{arg}{'v'}}
$data{CHECKSYSTEM_NOMES}++;
}
if(defined $data{arg}{H} || defined $data{arg}{'hardware'}){
if(!defined $data{arg}{'hardware'}){$data{arg}{'hardware'} = $data{arg}{'H'}}
$data{CHECKSYSTEM_NOMES}++;
}
if(defined $data{arg}{V} || defined $data{arg}{'version'}){
if(!defined $data{arg}{'version'}){$data{arg}{'version'} = $data{arg}{'V'}}
}
if(defined $data{arg}{'initrd'}){
$data{CHECKSYSTEM_NOMES}++;
}
if(defined $data{arg}{'unmask'}){
$data{CHECKSYSTEM_NOMES}++;
}
if(defined $data{arg}{'video'}){
$data{CHECKSYSTEM_NOMES}++;
}
if(defined $data{arg}{'opengl'}){
$data{CHECKSYSTEM_NOMES}++;
}
#----------------------------------------------------------------------
# Выполним информационные команды
#----------------------------------------------------------------------
if(defined $data{arg}{h} || defined $data{arg}{help}){
printmes("$data{'calcinstall'}\n\n");
printmes(gettext('Usage').": ");
printmes("calculate [");
printmes(gettext('OPTION'));
printmes("]...\n");
printmes("\n".gettext('Installation, compilation and updating of system')); printmes(".\n\n");
printmes(gettext('Mandatory arguments to long options are mandatory for short options too').".\n");
printmes(gettext('Similarly for optional arguments').".\n\n");
printmes(gettext('Location').":\n");
printmes(" -s, --os=[CLD|CLDG|CLDX|CLS|CSS|CDS] "); printmes(gettext('select operation system')); printmes(" (Calculate Linux Desktop KDE, Calculate Linux Desktop GNOME, Calculate Linux Desktop XFCE, Calculate Linux Scratch, Calculate Scratch Server, Calculate Directory Server)\n");
printmes(" -d, --disk=DISK\t"); printmes(gettext('installation or building system volume')."\n");
printmes(" -b, --build\t\t"); printmes(gettext('installation for assembling')."\n");
printmes(" -f, --force\t\t"); printmes(gettext('do not prompt before overwriting')."\n");
printmes("\n".gettext('Installation and Update').":\n");
printmes(" -a, --addition\t"); printmes(gettext('to establish additions')."\n");
printmes(" -U, --updateonly\t"); printmes(gettext('perform updates only')."\n");
printmes(" --set-[var]=value\t"); printmes(gettext('set config files parameter')."\n");
printmes(" --SET-[var]=value\t"); printmes(gettext('set config files parameter without check')."\n");
printmes(" -P, --profile=name[,name2...]\t"); printmes(gettext('apply configuration template (all - all templates)')."\n");
printmes("\n".gettext('System building').":\n");
printmes(" -l, --list\t\t"); printmes(gettext('show the package list incoming in the distributive file')."\n");
printmes(" -c, --configure\t"); printmes(gettext('prepare system for building')."\n");
printmes(" -D, --dependence\t"); printmes(gettext('check of dependences')."\n");
printmes(" -m, --make\t\t"); printmes(gettext('make system')."\n");
printmes(" -p, --pack\t\t"); printmes(gettext('pack the distribution package into the archive file')."\n");
printmes(" --iso\t\t\t"); printmes(gettext('create a loaded iso-image of system')."\n");
printmes(" --rebuild\t\t"); printmes(gettext('regenerate squashfs image on flash')."\n");
printmes(" --break\t\t"); printmes(gettext('break the system building')."\n");
printmes("\n".gettext('Additions assemble').":\n");
printmes(" -L [value]\t\t"); printmes(gettext('show the package list incoming in the addition')."\n");
printmes(" -M [value]\t\t"); printmes(gettext('make addition')."\n");
# printmes("\n".gettext('Setup server').":\n");
# printmes(" -S, --setup=[ldap|mail] "); printmes(gettext('setup and run servers'));
# printmes("\n"); #, ftp, squid, apache
# printmes(" --backup\t\t"); printmes(gettext('backup data of working servers')."\n");
# printmes("\n".gettext('Access management'));
# printmes("\n ".gettext('User').":\n");
# printmes(" --useradd=value\t"); printmes(gettext('create a new user account')."\n");
# printmes(" --userdel=value\t"); printmes(gettext('delete a user account')."\n");
# printmes(" --userpasswd=value\t"); printmes(gettext('change user password')."\n");
#
# printmes(" --groupadd=value\t"); printmes(gettext('create a new group')."\n");
# printmes(" --groupdel=value\t"); printmes(gettext('delete a group')."\n");
# printmes(" --groupmod=value [--set-useradd=value|--set-userdel=value] "); printmes(gettext('modify a group definition on the system')."\n");
#
# printmes(" ".gettext('E-Mail').":\n");
# printmes(" --mailuseradd=value\t"); printmes(gettext('create a new email account')."\n");
# printmes(" --mailuserdel=value\t"); printmes(gettext('delete a email account')."\n");
# printmes(" --mailuserpasswd=value "); printmes(gettext('change a email account password')."\n");
# # printmes(" --mailgroupadd=value\t"); printmes(gettext('create a new email group')."\n");
# # printmes(" --mailgroupdel=value\t"); printmes(gettext('delete a email group')."\n");
# printmes("\n".gettext('Updating').":\n");
# printmes(" -u, --update\t\t"); printmes(gettext('download and install latest update available')."\n");
printmes("\n".gettext('Informative output').":\n");
printmes(" -h, --help\t\t"); printmes(gettext('display this help and exit')."\n");
printmes(" -v, --vars\t\t"); printmes(gettext('config files parameters')."\n");
printmes(" -H, --hardware\t"); printmes(gettext('show hardware information')."\n");
printmes(" -V, --version\t\t"); printmes(gettext('output version information and exit')."\n");
return "";
}elsif(defined $data{arg}{V} || defined $data{arg}{version}){
printmes("Copyright (C) 2006-2009 Mir Calculate Ltd.\n");
printmes(gettext('This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.')); printmes ("\n");
return "";
}elsif(defined $data{arg}{translate}){
printmes(gettext('Update lang translation file')); printmes("... ");
if(-e "/usr/calculate/install"){
chdir("/usr/calculate/install");
#выполним локализацию пакета (для разработки)
system "xgettext --join-existing --no-location --sort-output --language=Perl --from-code=UTF-8 --msgid-bugs-address=support@calculate.ru -o i18n/ru_RU/LC_MESSAGES/calculate.po calculate";
system "msgfmt -o i18n/ru_RU/LC_MESSAGES/calculate.mo i18n/ru_RU/LC_MESSAGES/calculate.po";
printmes(gettext('done')); printmes(".\n");
}else{
printmes(gettext('error')); printmes(".\n");
}
return "";
}
return 1;
}
#------------------------------------------------------------------------------
#
# Отмонтируем все разделы диска если они монтированы к /media
#
#------------------------------------------------------------------------------
sub umountfrommedia{
# отмонтируем разделы у диска если они на /media
# проверяем что все разделы диска замонтирована на media
if(`$data{path} mount | grep -cP "$data{arg}{'disk'}\\S+ on /media"` ==
`$data{path} mount | grep -cP "$data{arg}{'disk'}\\S+ on /"`) {
foreach(`$data{path} mount | grep -Po "$data{arg}{'disk'}\\S+"`) {
chomp;
printmes(' '.gettext('Unmounting volume'));
printmes(" $_ ");
printmes(gettext('from'));
printmes( " /media...");
if( system("umount $_ &>/dev/null") ){
printmes(" ".gettext('error')."\n");
}
else {
printmes(" ".gettext('done')."\n");
}
}
}
}
#------------------------------------------------------------------------------
#
# Проверим на ошибки
#
#------------------------------------------------------------------------------
sub checkerrors{
# флаг запущенного демона hald
$data{hal} = ""; if(!system "lshal &>/dev/null"){$data{hal} = "on";}
if(`mount | grep "on /mnt/scratch"` && $data{builder} && !$data{createiso} ){
printmes(gettext('Error')."! ");
printmes(gettext('Unable prepare system for building in scratch mode').".\n");
return "";
}
#----------------------------------------------------------------------
# Определим тип носителя
#----------------------------------------------------------------------
if(!$data{'type'}){
$data{type} = check_removable();
}
#в режиме scratch можно поставить только на жесткий диск
if($data{type} eq "flash" && $data{scratch_ws}){
printmes(gettext('Scratch may be install only to hard drive')); printmes(".\n");
return "";
}
#----------------------------------------------------------------------
# Предопределим диск для установки
# инициируем: $data{data_install_set}, $data{partitions_dev}
#----------------------------------------------------------------------
$data{data_install_set} = "";
$data{partitions_dev} = "";
if($data{arg}{'disk'}){
if($data{arg}{'disk'}!~m/^(\/dev\/)/ || !-e $data{arg}{'disk'}){
printmes(gettext('Incorrect partition'));
printmes(" \"$data{arg}{'disk'}\".\n");
return "";
}elsif(
$data{arg}{'disk'}!~m/[0-9]$/ ||
($data{arg}{'disk'}=~m#^/dev/cciss/c[0-9]d[0-9]$#)
){
my $cciss; if($data{arg}{'disk'}=~m/cciss/){$cciss = "p";}
# отмонтируем разделы диска из /media
umountfrommedia();
if(`mount | grep "$data{arg}{'disk'}"` || `cat /proc/swaps | grep $data{arg}{'disk'}`){
printmes(gettext('On the disk is to mount partitions')."!\n");
beep(); return "";
}
if($data{type} ne "flash"){
#проверим размер диска
my $disk = $data{arg}{'disk'};
$disk =~m/\/([^\/]+)$/;
$disk = "/sys/block/$1/size";
if(!-e $disk){
printmes(gettext('The size of the disk is not defined')."!\n");
beep(); return "";
}else{
open(F, $disk);
my $size = <F>;
close(F);
chomp $size;
$size*=512/1024/1024/1024; #переведем в гигабайты
if($size < 45 && !defined $data{arg}{'vars'}){
printmes(gettext('The size of the disk is not sufficient to perform automatic partitioning')."!\n");
beep(); return "";
} }
#устанавливаем во второй раздел диска
$data{rootinstall} = $data{arg}{'disk'}.$cciss."2";
#раздел данных пятый
$data{data_install_set} = $data{arg}{'disk'}.$cciss."5";
$data{partitions_dev} = $data{arg}{'disk'};
}else{
$data{rootinstall} = $data{arg}{'disk'}."1"; #устанавливаем в первый и единственный раздел
$data{partitions_dev} = $data{arg}{'disk'};
}
}else{
$data{rootinstall} = $data{arg}{'disk'};
}
}
#----------------------------------------------------------------------
# Проверим id пользователя, запустившего скрипт
#----------------------------------------------------------------------
{
my $id = `$data{path} id -u`; chomp $id;
if($id > 0){
printmes(gettext('Only root can perform system installation')."!\n");
$data{NOLOG}++; #отключим лог, т.к. мы все равно в него ничего не сможем записать
beep(); return "";
} }
#----------------------------------------------------------------------
# Установим значение переменной в ram, в случае если установка профиля
# производится в оперативную память (настройка сеанса CDROM), а также
# load - носитель в значение ram в случае загрузки с CD/DVD
# $data{location}
# $data{scratch}
#----------------------------------------------------------------------
$data{location} = "";
$data{load} = "";
if(`mount | grep "/dev/loop/0 on / type"` ||
`mount | grep "/dev/loop0 on / type"` ||
`mount | grep "/dev/loop0 on /newroot/mnt/livecd type"`
){
if(defined $data{arg}{'profile'}){
$data{location} = "ram";
}
$data{load} = "ram";
}
if(`mount | grep /mnt/scratch`){$data{scratch} = "on";}
else{$data{scratch} = "off"}
#----------------------------------------------------------------------
# Установим переменную полной загрузки системы в память
# $data{load_cache}
#----------------------------------------------------------------------
$data{load_cache} = "off";
if($data{load} eq "ram" && !`mount | grep " on /newroot/mnt/cdrom type "`){
$data{load_cache} = "on";
}
#----------------------------------------------------------------------
# Путь к архиву образа
#----------------------------------------------------------------------
#пути к архивам систем
$data{linuxdir} = "/var/calculate/remote/linux";
#----------------------------------------------------------------------
# Определим и проверим директорию установки, директорию временных файлов
#----------------------------------------------------------------------
my $tmpdir = ".tmp.".sprintf("%.0f", rand() * 9999999);
if(!$data{tmpdir}){
if($data{createiso} && $data{load} eq 'ram'){
$data{tmpdir} = "$data{linuxdir}/$tmpdir";
}else{
$data{tmpdir} = "/var/calculate/tmp/$tmpdir";
}
}else{
$data{tmpdir} .= "/$tmpdir";
}
if(!$data{mount} && !defined $data{addition}){
if(!$data{builder}){
$data{mount} = "/mnt/install";
}else{
$data{mount} = "/mnt/builder";
} }
if(defined $data{arg}{'unmask'}){
$data{'chroot'} = '';
}elsif(!$data{createiso}){
$data{'chroot'} = $data{mount};
}else{
$data{'chroot'} = "$data{tmpdir}/livecd";
}
if(-e $data{mount} && !$data{builder_chroot} && !defined $data{arg}{'vars'} && !defined $data{arg}{'list'} && !$data{createiso}){
system "$data{path} rmdir $data{mount}"
}
if(-e $data{mount} && !$data{builder_chroot} && !defined $data{arg}{'vars'} && !defined $data{arg}{'list'} && !$data{createiso}){
printmes(gettext('Error')."! ");
printmes(gettext('For continuation please remove directory'));
printmes(" $data{mount} ");
printmes(gettext('created by installer')."!\n");
beep(); return "";
}elsif($data{builder_chroot} && !defined $data{arg}{'vars'}){
my $mounts = 0;
foreach(`$data{path} mount`){
if(/on\s+($data{chroot}\/[^\s]+)/){
$mounts++;
} }
if($mounts < 3){
printmes(gettext('For performance of operation it is necessary to configure system')); printmes(".\n");
printmes(gettext('Execute with parameter')); printmes(" \"--configure\".\n");
beep(); return "";
} }
if($data{type} eq "flash" && !$data{partitions_dev}){
printmes(gettext('To install on USB-Flash, specify the device, not partition. For example "calculate -d /dev/sdb"')); printmes(".\n");
beep(); return "";
}
#перечень возможных планировщиков
@{$data{other}}{scheduler} = ['noop', 'cfq', 'deadline'];
if(
$data{scheduler} &&
($data{scheduler} ne 'noop' &&
$data{scheduler} ne 'cfq' &&
$data{scheduler} ne 'deadline'
)
){
beep();
printmes(gettext('Wrong name of the Scheduler').".\n");
return "";
}
return 1;
}
#------------------------------------------------------------------------------
#
# Определим систему для установки или сборки
#
#------------------------------------------------------------------------------
sub welcome{
#----------------------------------------------------------------------
# Определим наименование устанавливаемой или обновляемой системы
# %{$data{ver}}, $data{'calculate'}, $data{'calculatename'}
#----------------------------------------------------------------------
#обозначение зарезервированных версий систем
%{$data{ver}} = (
CLD => "Calculate Linux Desktop",
CLDG => "Calculate Linux Desktop",
CLDX => "Calculate Linux Desktop",
CSS => "Calculate Scratch Server",
CDS => "Calculate Directory Server",
CLS => "Calculate Linux Scratch",
CLSG => "Calculate Linux Scratch",
);
%{$data{ver_desktop}} = (
CLD => "KDE",
CLDG => "GNOME",
CLDX => "XFCE",
CLSG => "GNOME",
);
#если передан параметр выбора системы, установим значения
if($data{arg}{'os'}){
if($data{ver}{ uc($data{arg}{'os'}) }){
$data{'calculate'} = uc($data{arg}{'os'});
$data{'calculatename'} = $data{ver}{$data{calculate}};
}else{
$data{'calculate'} = $data{arg}{'os'};
# if(lc($data{'calculate'}) eq 'acoola'){$data{'calculate'} = "AcoolA";}
$data{'calculatename'} = $data{'calculate'};
}
#в противном случае определим по текущей
#новым способом
}elsif(getini(calculate)){
if($data{builder} && !defined $data{addition} && getini(calculate, 'chroot')){
$data{calculate} = getini(calculate, 'chroot');
}else{
$data{calculate} = getini(calculate);
}
$data{'calculatename'} = $data{ver}{$data{calculate}};
if(!$data{'calculatename'}){$data{'calculatename'} = $data{calculate}}
}else{
#устанавливаемая или собираемая система по умолчанию
if(!$data{'calculate'}){
$data{'calculate'} = "CLD";
$data{'calculatename'} = $data{ver}{$data{calculate}};
}
}
$data{'calculatesubname'} = "";
if($data{'calculate'}=~m/^CLD/){
@{$data{other}}{'calculatesubname'} = ["KDE", "XFCE"];
$data{'calculatesubname'} = $data{ver_desktop}{$data{calculate}};
}elsif($data{'calculate'}=~m/CLSG/){
$data{'calculatesubname'} = $data{ver_desktop}{$data{calculate}};
}
#----------------------------------------------------------------------
# Получим тип системы
# $data{system}
#----------------------------------------------------------------------
if($data{'calculatename'}=~m/server/i ||
$data{'system'}=~m/server/i
){
$data{'system'} = 'server'
}else{
$data{'system'} = 'desktop'
}
#----------------------------------------------------------------------
# Приветственное сообщение
#----------------------------------------------------------------------
if($data{builder}){
printmes(gettext('Building')); printmes(" $data{'calculatename'}\n");
}elsif(
defined $data{arg}{'opengl'} ||
defined $data{arg}{'initrd'}
){
#ничего не напишем
}elsif(
!defined $data{arg}{update} &&
!defined $data{arg}{'vars'} &&
!defined $data{arg}{'hardware'} &&
!defined $data{arg}{'profile'} &&
!defined $data{arg}{'setup'} &&
!defined $data{arg}{'backup'} &&
!defined $data{arg}{'useradd'} &&
!defined $data{arg}{'userdel'} &&
!defined $data{arg}{'userpasswd'} &&
!defined $data{arg}{'groupadd'} &&
!defined $data{arg}{'groupdel'} &&
!defined $data{arg}{'groupmod'} &&
# !defined $data{arg}{'mailuseradd'} &&
# !defined $data{arg}{'mailuserdel'} &&
# !defined $data{arg}{'mailuserpasswd'} &&
# !defined $data{arg}{'mailgroupadd'} &&
# !defined $data{arg}{'mailgroupdel'}
!defined $data{arg}{'unmask'}
){
printmes(gettext('Installation'));
printmes(" $data{calculatename} $data{'calculatesubname'}\n");
}else{
printmes("$data{calcinstall}\n");
}
}
#------------------------------------------------------------------------------
#
# Соберем сведения о системе
#
#------------------------------------------------------------------------------
sub checksystem{
#отключим вывод сообщений
if($data{CHECKSYSTEM_NOMES}){
$data{NOMES}++;
};
printmes(gettext('Collecting system information')."\n");
#----------------------------------------------------------------------
# Выполним проверки доступности необходимых программ и определим пути
# $data{exec_host}, $data{exec_nmap}
#----------------------------------------------------------------------
if(!system "which host >/dev/null 2>&1"){$data{exec_host} = `which host`; chomp $data{exec_host};}
if(!system "which nmap >/dev/null 2>&1"){$data{exec_nmap} = `which nmap`; chomp $data{exec_nmap};}
if(!system "which wget >/dev/null 2>&1"){$data{exec_wget} = `which wget`; chomp $data{exec_wget};}
#временная задержка перед выполнением операций над диском
if($data{sleep}=~m/off/i || $data{sleep}=~m/no/i || $data{sleep}=~m/false/i){$data{sleep} = 0;}
elsif($data{sleep} eq '' || $data{sleep}=~m/[^0-9]/){$data{sleep} = 10;}
#подключение bar вместо cp
if(-e "/usr/bin/bar"){ $data{run_bar} = "/usr/bin/bar -ns"; }else{ $data{run_bar} = 'cp'; }
#----------------------------------------------------------------------
# Считаем параметры ядра
#----------------------------------------------------------------------
if($data{load} eq "ram" && -e "/proc/cmdline"){
#считаем параметры
open(F, '/proc/cmdline');
my $cmdline = <F>;
close(F);
chomp $cmdline; $cmdline.=' ';
#разобьем на переменные
foreach(split / /,$cmdline){
if(/^calculate=(.+)/){
#разобьем на значения передаваемые для calculate
(
$data{boot}{lang},
$data{boot}{keybd},
$data{boot}{timezone},
$data{boot}{video_resolution},
) = split /,/,$1;
last;
} }
$data{boot}{set} ++;
}
#----------------------------------------------------------------------
# Определим хэши паролей root/root, guest/guest
# $data{hash_root}, $data{hash_guest}
#----------------------------------------------------------------------
$data{hash_root} = 'root:$1$JMvNh5xg$VnV1DyJdTcwuZ0hp5YiJG0:14349:0:::::';
$data{hash_guest} = 'guest:$1$uSceexyH$vLQn4kh7NUzNqZtlrgEWF.:14349:0:99999:7:::';
#----------------------------------------------------------------------
# Определим тип операции
# $data{pass}
#----------------------------------------------------------------------
@{$data{other}}{'pass'} = ["profile", "builder", "install"];
if(defined $data{arg}{'profile'} || defined $data{arg}{'setup'}){
$data{pass} = "profile";
}elsif($data{builder}){
$data{pass} = "builder";
}else{
$data{pass} = "install";
}
if(!$data{builder}){
if($data{erase} =~m/off/i ||$data{erase} =~m/no/i){
$data{erase} = "off";
}else{
$data{erase} = "on";
}
}else{$data{erase} = "on";}
#----------------------------------------------------------------------
# Определим номер версии клиента
# $data{client}
#----------------------------------------------------------------------
$data{client} = "";
my $clientfile = "/usr/lib/calculate/calculate-client/pym/cl_vars_client.py";
if($data{pass} eq "profile" && -e $clientfile){
$data{client} = `$data{path} cat $clientfile | grep " cl_ver "`;
$data{client}=~s/.+'Calculate-client\s+([0-9\.]+).+/$1/;
chomp $data{client};
}
#----------------------------------------------------------------------
# Флаг выполнения make menuconfig ядра при сборке системы,
# флаг пропуска первого пакета при возобновлении сборки.
# $data{menuconfig}, $data{skipfirst}
#----------------------------------------------------------------------
if($data{builder}){
if(!$data{menuconfig} || $data{menuconfig}=~m/^yes$/i || $data{menuconfig}=~m/^on$/i){
$data{menuconfig} = "on";
}else{
$data{menuconfig} = "off";
}
if(!$data{skipfirst} || $data{skipfirst}=~m/^no$/i || $data{skipfirst}=~m/^off$/i){
$data{skipfirst} = "off";
}else{
$data{skipfirst} = "on";
}
}
#----------------------------------------------------------------------
# Определим графический режим фреймбуфера
#----------------------------------------------------------------------
if(-e "/sys/class/graphics/fb0"){
$data{fb} = 'vesa';
}else{
$data{fb} = 'console';
}
#----------------------------------------------------------------------
# Сгенерируем случайное время в минутах
#----------------------------------------------------------------------
$data{rand_min} = sprintf("%.0f", rand() * 59);
#----------------------------------------------------------------------
# Считаем имя компьютера
# $data{hostname}
#----------------------------------------------------------------------
printmes(" ".gettext('Computer name'));
if(!$data{hostname}){
$data{hostname} = `$data{path} hostname -s 2>&1`;
#упрощенный вариант, следует выполнять только если не указан домен в системе
if($data{hostname}=~m/^hostname: /){
$data{hostname} = `$data{path} hostname 2>&1`;
}
if($data{hostname}=~m/^hostname: /){
$data{hostname} = $data{calculate};
printmes(": <"); printmes(gettext('undefined')); printmes(">\n");
}else{
chomp $data{hostname};
if($data{hostname} eq 'livecd'){$data{hostname} = $data{calculate};}
printmes(": $data{hostname}\n");
}
}else{
printmes(": $data{hostname}\n");
}
#----------------------------------------------------------------------
# Определим домен
# $data{domain}
#----------------------------------------------------------------------
if(!$data{domain}){
$data{domain} = `$data{path} hostname -d 2>&1`;
if($data{domain}=~m/^hostname: /){$data{domain} = "local";}else{chomp $data{domain};}
}
if($data{domain} ne 'local'){
printmes(" ".gettext('Domain name')); printmes(": $data{domain}\n");
}
#----------------------------------------------------------------------
# Параметры пользователя по умолчанию
#----------------------------------------------------------------------
if(!$data{user_comment}){$data{user_comment} = "CDS User";}
if(!$data{user_groups}){$data{user_groups} = "";}
if(!$data{mail} && $data{arg}{'mailuseradd'}){
$data{mail} = "$data{arg}{'mailuseradd'}\@$data{hostname}.$data{domain}";
}elsif($data{mail} && $data{mail}!~m/\@/ && $data{domain}){
$data{mail} = "$data{mail}\@$data{hostname}.$data{domain}";
}
#----------------------------------------------------------------------
# Определим сетевые настройки:
# шлюз, локальные интерфейсы, локальные сети, настройки /etc/conf.d/net,
# сетевые устройства
# $data{gateway}, $data{hostsallow}, $data{networks}, $data{netconf},
# $data{net_*} = on|off
#----------------------------------------------------------------------
if(!$data{gateway}){
my $route = `$data{path} route -n | grep "^0.0.0.0"`;
chomp $route;
$route=~m/^0\.0\.0\.0\s+([0-9\.]+)\s.+\s+([^\s]+)$/;
if($1){
$data{gateway} = $1;
$data{gateway_dev} = $2;
}
}
{
printmes(" ".gettext('Network devices')); printmes(":");
#http://krow.net/dict/subnet.html
my %net = (
"255.255.0.0" => "/16",
"255.255.255.0" => "/24",
"255.255.255.128" => "/25",
"255.255.255.192" => "/26",
"255.255.255.252" => "/30",
"255.255.255.255" => "",
);
#обнулим переменные
my $sp = ""; my $dev = ""; my $dev_open = 1; my $br; my $gateway_dhcp;
$data{netconf} = ""; $data{hostsallow} = ""; $data{networks} = "";
foreach(`ifconfig -a`){
#девайс
if(/^([^\s]+)\s+.*Ethernet/){
if($dev_open == 0){
printmes("$br $dev (off)");
$data{"net_$dev"} = "off";
$br = ",";
}
$dev_open = 0; #девайс выключен, если не будет другой информации
$dev = $1;
}
if(/inet addr:([0-9\.]+).+Bcast:.+Mask:([0-9\.]+)/){
my $addr = $1; my $mask = $2;
my @ip = split /\./, $addr;
if(
$ip[0] == 10 ||
($ip[0] == 172 && $ip[1] >= 16 && $ip[1] <= 31) ||
($ip[0] == 192 && $ip[1] == 168)
){
$data{hostsallow} .= $sp.$addr.$net{$mask};
#определим сеть
if($mask eq "255.255.255.255"){
$data{networks} .= $addr;
}elsif($mask eq "255.255.255.252"){
$data{networks} .= "$ip[0].$ip[1].$ip[2].252".$net{$mask};
}elsif($mask eq "255.255.255.192"){
$data{networks} .= "$ip[0].$ip[1].$ip[2].192".$net{$mask};
}elsif($mask eq "255.255.255.128"){
$data{networks} .= "$ip[0].$ip[1].$ip[2].128".$net{$mask};
}elsif($mask eq "255.255.255.0"){
$data{networks} .= "$ip[0].$ip[1].$ip[2].0".$net{$mask};
}elsif($mask eq "255.255.0.0"){
$data{networks} .= "$ip[0].$ip[1].0.0".$net{$mask};
}
$sp = " ";
#определим получен ли IP через DHCP
if(
!-e "/var/lib/dhcpcd/dhcpcd-$dev.info" &&
!(-e "/var/lib/dhcp/dhclient.leases" && `grep $dev /var/lib/dhcp/dhclient.leases`) &&
!-e "/var/lib/dhcpcd/dhcpcd-$dev.lease"
){
$data{netconf} .= "\nconfig_$dev=( \"$addr$net{$mask}\" )";
printmes("$br $dev ($addr)");
}else{
$data{netconf} .= "\nconfig_$dev=( \"dhcp\" )";
if($dev eq $data{gateway_dev}){
$gateway_dhcp++;
}
printmes("$br $dev (DHCP)");
}
$data{"net_$dev"} = "on";
$br = ",";
}else{
$data{netconf} .= "\nconfig_$dev=( \"$addr$net{$mask}\" )";
}
$dev_open = 1;
if($data{calculate} ne "CLS" && $data{calculate} ne "CLSG"){
$data{netconf} .= "\nmodules_eth0=( \"!plug\" )";
}
} }
if($dev_open == 0){
printmes("$br $dev (off)");
$data{"net_$dev"} = "off";
}
if($data{gateway_dev} && !$gateway_dhcp){
$data{netconf} .= "\nroutes_$data{gateway_dev}=( \"default gw $data{gateway}\" )";
}
printmes("\n");
}
if(!$data{netconf} && $data{load} eq "ram"){
$data{netconf} = "\nconfig_eth0=( \"dhcp\" )";
}
#----------------------------------------------------------------------
# Получим версию обновляемой, наличие обновлений, название
# устанавливаемой системы
# $data{os}, $data{ospatch}, $data{ospatchsplit}, $data{linuxold}
#----------------------------------------------------------------------
$data{os} = ''; $data{ospatch} = ''; $data{ospatchsplit} = '';
$data{linuxold} = '';
if(!$data{builder} || defined $data{addition} || $data{createiso}){
printmes(" ".gettext('Installed system').": ");
if(getini(calculate) && getini(linuxver)){
$data{linuxold} = $data{ver}{getini(calculate)};
$data{os} = getini(linuxver);
printmes("$data{linuxold} $data{os}\n");
if(getini(ospatch)){
$data{ospatch} = getini(ospatch);
printmes(" ".gettext('Update')); printmes(": $data{ospatch}\n");
$data{ospatchsplit} = "-";
}
# #для совместимости со старыми инсталляциями, проверим файл /etc/issue
# }elsif(-e "/etc/issue" && `$data{path} cat /etc/issue | grep "Welcome to "`=~m#Welcome to \\n.\\O \(([a-zA-Z ]+) ([^\s\)]+)#){
# $data{linuxold} = $1;
# {
# my ($os, $patch) = split /-/, $2; #обрежем обновления
# if($os > 0){
# $data{os} = "$os";
# if($patch){$data{ospatch} = $patch;}
# } }
# if(!$data{linuxold}){$data{linuxold} = $data{calcname};}
# printmes("$data{linuxold} $data{os}\n");
#
# if($data{ospatch}){
# printmes(" ".gettext('Update')); printmes(": $data{ospatch}\n");
# $data{ospatchsplit} = "-";
# }
}elsif(-e "/etc/gentoo-release"){
$data{linuxold} = "Gentoo Linux";
printmes("$data{linuxold}\n");
}else{
$data{linuxold} = "Old Linux";
printmes("<"); printmes(gettext('undefined')); printmes(">\n");
} }
printmes(gettext('Hardware')."\n");
#----------------------------------------------------------------------
# Получим производителя оборудования
# $data{vendor}, $data{laptop}, $data{laptop_model}
# $data{board_model}, $data{board_vendor}
#----------------------------------------------------------------------
$data{laptop} = "";
if(-e "/sys/class/dmi/id/chassis_vendor"){
$data{vendor} = `cat /sys/class/dmi/id/chassis_vendor`; chomp($data{vendor});
if($data{vendor}=~m/^\s+$/ || $data{vendor}=~m/Chassis Manufacture/){
$data{vendor} = 'Chassis Manufacture';
}
if(
(-e "/sys/class/dmi/id/board_name" && `cat /sys/class/dmi/id/board_name | grep "Portable PC"`) ||
(-e "/sys/class/dmi/id/chassis_type" &&
(`cat /sys/class/dmi/id/chassis_type | grep "1"` ||
`cat /sys/class/dmi/id/chassis_type | grep "8"` ||
`cat /sys/class/dmi/id/chassis_type | grep "10"`
) )
){
$data{laptop} = lc($data{vendor});
$data{laptop_model} = `cat /sys/class/dmi/id/product_name`;
chomp ($data{laptop_model});
}elsif(-e "/sys/class/dmi/id/board_name" && -e "/sys/class/dmi/id/board_vendor"){
$data{board_model} = `cat /sys/class/dmi/id/board_name`;
chomp ($data{board_model});
$data{board_vendor} = `cat /sys/class/dmi/id/board_vendor`;
chomp ($data{board_vendor});
}
}
#----------------------------------------------------------------------
# Получим архитектуру процессора, файл stage, маску нестабильных файлов
# $data{march}, $data{stage}, $data{unmask}
#----------------------------------------------------------------------
{
@{$data{other}}{'march'} = ["i686", "x86_64"];
printmes(" ".gettext('Machine hardware name')); printmes(":");
my $march = `$data{path} uname -m`; chomp $march;
if($data{march} && $data{march} ne $march){
$data{dif_march} = "yes"; #флаг установки другой архитектуры
}elsif(!$data{march}){
$data{march} = $march;
}
printmes(" $data{march}\n");
}
if($data{march} eq 'i686'){
if($data{builder}){
$data{stage} = "stage3-i686";
}
$data{unmask} = "~x86";
}
elsif($data{march} eq 'x86_64'){
if($data{builder}){
$data{stage} = "stage3-amd64";
}
$data{unmask} = "~amd64";
}
elsif(!defined $data{arg}{'vars'}){
printmes("\n");
printmes(gettext('Machine hardware name'));
printmes(" $data{march} ");
printmes(gettext('not supported')); printmes(".\n");
printmes(gettext('Use value'));
printmes(": \"i686\", \"x86_64\"");
printmes(".\n");
beep();
exit;
}
#----------------------------------------------------------------------
# Определим версию последнего доступного образа системы, либо версию
# собираемого образа, имя файла с образом, имя ISO-файла, который можно
# собрать
# $data{linuxver}, $data{linux}, $data{iso}
#----------------------------------------------------------------------
#наложение профиля
if(defined $data{arg}{'profile'}){
$data{linuxver} = $data{os};
#сборка системы
}elsif($data{builder} && !$data{createiso} && !defined $data{addition}){
if(!$data{linuxver}){
if(getini("linuxver", "chroot")){
$data{linuxver} = getini("linuxver", "chroot");
}else{
#my $time = timelocal(localtime);
#my ($month, $year) = (localtime($time))[4,5]; $month += 1; $year-=100;
#$data{linuxver} = "$year.$month";
$data{linuxver} = "10.9";
my $point, $subver;
while (-e
$data{linuxdir}.
lc($data{'calculate'})."-$data{linuxver}".
$point.$subver.
"-$data{march}.tar.bz2" ||
-e
$data{linuxdir}.
lc($data{'calculate'})."-$data{linuxver}".
$point.$subver.
"-$data{march}.tar.lzma" ||
-e
$data{linuxdir}.
lc($data{'calculate'})."-$data{linuxver}".
$point.$subver.
"-$data{march}.tar.7z" ||
-e
$data{linuxdir}.
lc($data{'calculate'})."-$data{linuxver}".
$point.$subver.
"-$data{march}.iso"
){
$point = ".";
$subver+=1;
}
$data{linuxver} = "$data{linuxver}$point$subver";
} }
$data{linux} = lc($data{'calculate'})."-$data{linuxver}-$data{march}.tar.bz2";
#установка системы
}elsif(-e $data{linuxdir}){
my $find = "\/".lc($data{'calculate'})."\-.*\-$data{march}\.";
my $ver = lc($data{'calculate'})."-\([^-]+)-$data{march}"; #шаблон сравнения
my $mask;
if($data{type} eq "flash" || $data{scratch_ws}){
$mask = "iso";
}elsif($data{createiso}){
$mask = "tar\.7z|tar\.lzma|tar\.bz2";
}else{
$mask = "iso|tar\.7z|tar\.lzma|tar\.bz2";
}
foreach(`$data{path} find "$data{linuxdir}/"`){
if(/$find($mask)$/){
chomp;
my $path = $_;
my $filetype = $1;
if(!$data{linux}){$data{linux} = $path; next;}
#выделим номера сравниваемых версий
$path=~m/$ver/;
my $change = $1;
$data{linux}=~m/$ver/;
my $cur = $1;
$data{linux}=~m/$find($mask)$/;
my $curfiletype = $1;
if(number_ver($cur) < number_ver($change) || ( number_ver($cur) == number_ver($change)
&& index($mask,$curfiletype) > index($mask,$filetype))){$data{linux} = $path;}
} }
if($data{linux}){
#обрежем путь
$data{linux}=~s/^.*\/([^\/]+)$/$1/;
#выделим номер версии
$data{linux}=~m/^[^\-]+\-([^\-]+)\-.+/;
$data{linuxver} = $1;
}elsif($data{scratch} eq "on" && $data{dif_march} ne 'yes' && getini('calculate') eq $data{calculate}){
$data{linuxver} = $data{os};
$data{linux} = "scratch";
}elsif($data{load} eq "ram" && $data{dif_march} ne 'yes' && getini('calculate') eq $data{calculate}){
$data{linuxver} = $data{os};
$data{linux} = "livecd";
}
if(!$data{iso} && $data{linuxver}){
$data{iso} = lc($data{'calculate'})."-$data{linuxver}-$data{march}.iso";
}else{$data{iso} = "";}
}
#----------------------------------------------------------------------
# Язык, локаль, консольный шрифт
# http://gentoo-wiki.com/TIP_Speak_Your_Language
#----------------------------------------------------------------------
#system: locale, keymap, dumpkeys_charset, consolefont, consoletranslation, xkblayout
#KDE: kb_groups, kb_layout, country, language, dictionary
#system: langdir
my %lang = (
#Belarussian
'be_BY' => ["be_BY.UTF-8", "by", "koi8-u", "Cyr_a8x16", "", "us,by",
"by(winkeys):us", "us,by(winkeys)", "by", "ru", "ru",
"ru"],
#Bulgarian
'bg_BG' => ["bg_BG.UTF-8","bg_bds-utf8","","ter-m14n","","us,bg",
"","us,bg","bg","bg_BG","bg","bg"],
#Belgian
'fr_BE' => ["fr_BE.UTF-8", "be-latin1", "", "lat9w-16", "", "us,be",
"", "us,be", "be", "en_US", "en"],
#Brazilian Portuguese
'pt_BR' => ["pt_BR.UTF-8", "br-abnt2", "", "lat9w-16", "", "pt,us",
"", "us,pt", "br", "pt_BR", "en",
"pt-BR"],
#Canadian French
'fr_CA' => ["fr_CA.UTF-8", "cf", "", "default8x16", "8859-1_to_uni", "us,ca_enhanced",
"", "us,ca(fr)", "ca", "en_US", "en"],
#Danish
'da_DK' => ["da_DK.UTF-8", "dk-latin1", "", "lat0-16", "", "us,dk",
"", "us,dk", "dk", "da", "da"],
#French
'fr_FR' => ["fr_FR.UTF-8", "fr-latin9", "", "lat0-16", "", "fr,us",
"", "us,fr(latin9)", "fr", "en_US", "en",
"fr"],
#German
'de_DE' => ["de_DE.UTF-8", "de-latin1", "", "lat9w-16", "", "de,us",
"", "us,de", "de", "de", "de",
"de"],
#Icelandic
'is_IS' => ["is_IS.UTF-8", "is-latin1", "", "cp850-8x16", "8859-1_to_uni", "us,is",
"", "us,is", "is", "en_US", "en"],
#Italian
'it_IT' => ["it_IT.UTF-8", "it", "", "default8x16", "8859-15_to_uni", "us,it",
"", "us,it", "it", "it", "it",
"it"],
#Norwegian
'nn_NO' => ["nn_NO.UTF-8", "no-latin1", "", "lat9w-16", "", "us,no",
"", "us,no", "no", "nn", "en"],
#Polish
'pl_PL' => ["pl_PL.UTF-8", "pl", "", "lat2-16", "8859-2_to_uni", "us,pl",
"", "us,pl", "pl", "pl", "pl",
"pl"],
#Russian
'ru_RU' => ["ru_RU.UTF-8", "-u ruwin_cplk-UTF-8", "", "ter-k14n", "", "us,ru(winkeys)",
"ru(winkeys):us", "us,ru(winkeys)", "ru", "ru", "en",
"ru"],
#Spanish
'es_ES' => ["es_ES.UTF-8", "es euro2", "", "lat0-16", "", "es,us",
"", "us,es", "es", "es", "es",
"es"],
#Swedish
'sv_SE' => ["sv_SE.UTF-8", "sv-latin1", "", "lat0-16", "", "us,se",
"", "us,se", "se", "sv", "sv"],
#Ukrainian
'uk_UA' => ["uk_UA.UTF-8", "ua-utf", "koi8-u", "ter-v14n", "", "us,ua",
"ua(winkeys):us", "us,ua(winkeys)", "ua", "uk", "uk",
"uk"],
#United Kingdom/British
'en_GB' => ["en_GB.UTF-8", "uk", "", "LatArCyrHeb-16", "", "us,gb",
"", "us,gb", "gb", "en_US", "en_GB"],
#United State/English
'en_US' => ["en_US.UTF-8", "us", "", "LatArCyrHeb-16", "", "us",
"", "us", "us", "en_US", "en_US"],
);
@{$data{other}}{lang} = ["bg_BG", "en_US", "de_DE", "es_ES", "fr_FR", "it_IT", "pl_PL", "pt_BR", "ru_RU", "uk_UA"];
# предыдущих версиях присутствуют проблемы с ruwin_cplk-UTF-8
if( number_ver($data{linuxver}) < number_ver('10.2') ) {
$lang{"ru_RU"} = ["ru_RU.UTF-8", "-u ru4", "koi8-r", "ter-k14n", "", "us,ru(winkeys)",
"ru(winkeys):us", "us,ru(winkeys)", "ru", "ru", "en"];
}
if(!$data{lang} && $data{boot}{lang}){
$data{lang}=$data{boot}{lang};
}elsif(!$data{lang}){
if(!$data{builder}){
$ENV{LANG}=~m/^([^\.]+)\./;
$data{'lang'} = $1;
}else{
$data{'lang'} = 'en_US';
} }
#проверим на корректность введенного значения и на наличие поддержки
if(!$lang{$data{lang}}){$data{lang}="en_US";}
#поддержка языков в приложениях
if($data{pass} eq 'builder'){
#$data{linguas} = "be be_BY da de en en_GB es fr it nb nn pl pt_BR ru se sv uk";
$data{linguas} = "bg en de es fr it pl pt_BR ru uk";
}else{
foreach(keys %lang){
if($_ eq $data{'lang'}){
$data{linguas} = "en ".$lang{$_}[9];
last;
} } }
#установим раскладку
my $changekb;
if($data{boot}{keybd}){$changekb = $data{boot}{keybd};}
else{
#получим раскладку из файла /etc/conf.d/keymaps
if(-e '/etc/conf.d/keymaps'){
open(F, '/etc/conf.d/keymaps');
foreach(<F>){
if(m/^KEYMAP="?([^"\n]+)"?/){
my $keymap = $1;
foreach(keys %lang) {
if( $lang{$_}[1] eq $keymap ) {
$changekb = $_;
last;
} }
last;
} }
close(F);
}
if($data{'arg'}{'set-lang'} || $data{'arg'}{'SET-lang'} || !$changekb){
$changekb = $data{lang};
}
}
#выберем язык и раскладку
($data{'locale'},
$data{'language'},
$data{'dictionary'},
) = @{$lang{$data{lang}}}[0,9..10];
($data{'keymap'},
$data{'dumpkeys_charset'},
$data{'consolefont'},
$data{'consoletranslation'},
$data{'xkblayout'},
$data{'kb_groups'},
$data{'kb_layout'},
$data{'country'},
) = @{$lang{$changekb}}[1..8];
#неиспользуемые языки
foreach(sort keys %lang){
if($lang{$_}[11] ne $data{language} && $lang{$_}[11]){
push(@{$data{clearlang}}, $lang{$_}[11]);
} }
printmes(" ".gettext('Language')); printmes(": $data{lang}\n");
printmes(" ".gettext('Keymap')); printmes(": $changekb\n");
#----------------------------------------------------------------------
# Временная зона
#----------------------------------------------------------------------
#Системное время в гринвиче или локальное "UTC" или "local"
if(!$data{clock} && -e "/etc/conf.d/hwclock"){
my $clock = `$data{path} cat /etc/conf.d/hwclock | grep "CLOCK="`;
if($clock){
$clock=~m/\"([^\"]+)\"/;
$data{clock} = $1;
} }
if(!$data{clock} && -e "/etc/conf.d/clock"){
my $clock = `$data{path} cat /etc/conf.d/clock | grep "CLOCK="`;
if($clock){
$clock=~m/\"([^\"]+)\"/;
$data{clock} = $1;
} }
if($data{clock}=~m/utc/i){$data{clock} = "UTC";}
else{$data{clock} = "local";}
if(!$data{timezone} && $data{boot}{timezone}){$data{timezone} = $data{boot}{timezone}}
else{
if(!$data{timezone} && -e "/etc/timezone"){
$data{timezone} = `$data{path} cat /etc/timezone`;
chomp $data{timezone};
}
if(!$data{timezone} && -e "/etc/conf.d/clock"){
my $timezone = `$data{path} cat /etc/conf.d/clock | grep "TIMEZONE="`;
if($timezone){
$timezone=~m/\"([^\"]+)\"/;
$data{timezone} = $1;
} }
if(!$data{timezone} || ($data{timezone} && !-e "/usr/share/zoneinfo/$data{timezone}")){
$data{timezone} = "UTC";
} }
printmes(" ".gettext('Timezone')); printmes(": $data{timezone}\n");
#----------------------------------------------------------------------
# Определим имя livecd.squashfs
# $data{squash_cur}, $data{squash_del}
#----------------------------------------------------------------------
my $revsquash = 0; #по умолчанию нулевая ревизия (к имени файла не подставляется)
$data{squash_cur} = `cat /proc/cmdline | sed -nr 's/.*loop=\\/([^ ]+).*/\\1/p'`; chomp $data{squash_cur};
if(!$data{squash_cur} || $data{linux}=~m/iso$/){
$data{squash_cur} = "livecd.squashfs";
}else{
#определим ревизию
$data{squash_cur}=~m/\.([0-9]+)$/;
if($1){$revsquash = $1;}
}
$data{squash_del} = "";
if(-e "/mnt/flash/" && defined $data{arg}{rebuild}){
opendir(F, "/mnt/flash/");
foreach(readdir F){
if($_ eq "." || $_ eq ".."){next;}
if($_=~m/^livecd\.squashfs\.?([0-9]+)?$/){
if($1 < $revsquash){$data{squash_del} = $_}
}
}
closedir F;
$revsquash ++;
$data{squash_cur} = "livecd.squashfs.".$revsquash;
}
#----------------------------------------------------------------------
# Определим пакет тем для собираемой системы
# $data{themes}
#----------------------------------------------------------------------
if($data{builder}){
$data{themes} = ">media-gfx/calculate-".lc($data{calculate})."-themes-$data{linuxver}";
$data{themes}=~s/(.+\.?[^\.]+)(\.[0-9]+)?/$1-r9/; #обрежем подверсию
#добавим ограничение на обновление темы для CLS, лежащий в основе других десктопов
if($data{calculate} ne "CLS" && $data{system} eq 'desktop'){
my $cls = ">media-gfx/calculate-cls-themes-$data{linuxver}";
$cls=~s/(.+\.?[^\.]+)(\.[0-9]+)?/$1-r9/; #обрежем подверсию
$data{themes}.="\n$cls";
} }
#----------------------------------------------------------------------
# Определим количество процессоров
# $data{cpus}
#----------------------------------------------------------------------
{
if(!$data{cpus}){
my (@cpus) = `$data{path} cat /proc/cpuinfo | grep processor`;
$data{cpus} = @cpus;
}
printmes(" ".gettext('Quantity processors')); printmes(": ".$data{cpus}."\n");
}
#----------------------------------------------------------------------
# Определим видеоадаптер
# $data{video_drv}, $data{video}, $data{video_id}
#----------------------------------------------------------------------
{
#перечень поддерживаемых видеодрайверов
@{$data{other}}{video_drv} = [
"fglrx",
"intel",
"nv",
"nvidia",
"radeon",
"vesa",
# "vboxvideo",
"vmware"
];
my $drv; #определим драйвер видеокарты
foreach(`$data{path} lspci | grep VGA`){
my $video = $_;
#определим BusID
$video=~m/^(.{2}):(.{2})\.([^\s+])/;
$data{video_id} = "$1:$2:$3";
if($video=~m/GeForce/ || $video=~m/nVidia/){
if($video=~m/\[([^\]]+)\]/){$data{video} = $1;}
elsif($video=~m/(GeForce.+) nForce/){$data{video} = $1;}
elsif($video=~m/(GeForce.+) \(/){$data{video} = $1;}
else{$data{video} = "GeForce";}
$data{video} = "nVidia $data{video}";
if(!$data{video_drv}){
if(
(($data{pass} eq "profile" && -e "/usr/lib/opengl/nvidia") ||
($data{pass} eq "install" &&
($data{calculate} ne "CLS" &&
$data{calculate} ne "CLSG"
))
) &&
($data{load} ne "ram" ||
($data{load} eq "ram" && !nvidia_mask())
)
){
$drv = "nvidia";
}else{
$drv = "nv";
}
}elsif($data{video_drv} eq 'nv' || $data{video_drv} eq 'nvidia'){
last; #завершим перебор, т.к. если есть другая видеокарта в системе, она нам явно не нужна
}
}elsif($video=~m/Intel/){
$video =~m/Intel Corporation ?(Mobile )([^\s,]+)?( Series)[\s,]/;
if($2){$data{video} = "Intel $1$2$3";}
else{$data{video} = "Intel";}
if(!$data{video_drv}){
$drv = "intel";
}elsif($data{video_drv} eq 'intel'){
last;
}
}elsif($video=~m/ATI/){
$video =~m/ATI Technologies Inc ([^\(]+)\s*[\(|\s]?$/;
if($1){
my $name = $1; chomp $name;
$data{video} = "ATI $name";
}else{
$data{video} = "ATI";
}
if(!$data{video_drv}){
#if(
# ($data{pass} eq "profile" && -e "/usr/lib/opengl/ati") ||
# ($data{pass} eq "install" &&
# !($data{calculate} eq "CLD" && number_ver($data{linuxver}) < number_ver(9.6))
# )
#){
$drv = "radeon";
#}else{
# $drv = "fglrx";
#}
}elsif( $data{video_drv} eq 'ati' ||
$data{video_drv} eq 'radeon' ||
$data{video_drv} eq 'radeonfb' ||
$data{video_drv} eq 'fglrx'
){
last;
}
}elsif($video=~m/VMware/i){
if(!$data{video_drv}){$drv = "vmware";}
#}elsif($video=~m/VirtualBox/i && $data{calculate} eq "CLD"){
# if(!$data{video_drv}){$drv = "vboxvideo";}
}else{
if(!$data{video_drv}){$drv = "vesa";}
}
#возьмем первую определившуюся видеокарту
if(!$data{video_drv}){last;}
}
if($drv && !$data{video_drv}){$data{video_drv} = $drv}
if($data{video} && !$data{builder}){
printmes(" ".gettext('Videocard'));
printmes(": $data{video}\n");
}
#определим opengl
if(!$data{opengl}){
if($data{video_drv} eq "nvidia"){
$data{opengl} = "nvidia";
}elsif($data{video_drv} eq "fglrx"){
$data{opengl} = "ati";
}elsif( $data{video_drv} ne "vesa" &&
$data{video_drv} ne "vboxvideo" &&
$data{video_drv} ne "vmware"
){
$data{opengl} = "xorg-x11";
}
}
if($data{opengl} && !$data{run_opengl}){
$data{run_opengl} = "/usr/bin/eselect opengl set $data{opengl}"
}else{
$data{run_opengl} = "";
}
#сбросим BusID если в ПК одна видеокарта
my @vga = `$data{path} lspci | grep VGA`;
if($data{video_id} && @vga == 1){ $data{video_id} = ""; }
}
#----------------------------------------------------------------------
# Определим разрешение экрана
# $data{resolution}
#----------------------------------------------------------------------
{
my $xlog = "/var/log/Xorg.0.log";
my $xconf = "/etc/X11/xorg.conf";
my $def_res = "1024x768";
if(!$data{video_resolution} && $data{boot}{set} && $data{pass} ne "install"){
$data{video_resolution} = $data{boot}{video_resolution};
if($data{video_resolution}!=~m/^[0-9]+x[0-9]+$/){$data{video_resolution} = 'auto'}
}elsif(!$data{video_resolution}){
if(-e $xlog){
#считаем лог Xorg
open (L, $xlog);
my @xlog = <L>;
close (L);
my $log = join /\n/, @xlog;
if($log=~m/Virtual screen size determined to be ([0-9]+)\s*x\s*([0-9]+)/){$data{video_resolution} = "$1x$2";}
elsif($log=~m/Setting mode "([0-9\@x]+)"/){$data{video_resolution} = "$1";}
elsif($log=~m/Output ([\S]+) using initial mode ([0-9\@x]+)/){$data{video_resolution} = "$2";} #VGA|LVDS|DFP2|DVI0
elsif($log=~m/Virtual size is ([0-9\@x]+) /){$data{video_resolution} = "$1";}
else{$data{video_resolution} = $def_res;}
}elsif(-e $xconf){
#считаем настройки xorg.conf
open (L, $xconf);
my @xconf = <L>;
close (L);
my $log = join /\n/, @xconf;
if($log=~m/Modes "([^\s"]+)[\s"]/){$data{video_resolution} = "$1";}
}
if($data{video_resolution} && !$data{builder}){
printmes(" ".gettext('Screen resolution'));
printmes(": $data{video_resolution}\n");
}
}
if(!$data{video_resolution} && $data{video_drv} eq "vesa"){
$data{video_resolution} = "800x600"
}
if(!$data{video_resolution}){
$data{video_resolution} = $def_res;
}
}
#----------------------------------------------------------------------
# Флаг включения композитного режима
#----------------------------------------------------------------------
if(!$data{composite} && -e '/var/log/Xorg.0.log'){
if($data{video_drv} eq 'nvidia' || $data{video_drv} eq 'intel'){
open(F, '/var/log/Xorg.0.log');
foreach(<F>){
if(m/Composite.*enabled/){$data{composite} = 'on'; last;}
}
close(F);
}
if(!$data{composite}){ $data{composite} = 'off'; }
}elsif($data{composite}=~m/off/i || $data{composite}=~m/no/i || $data{composite}=~m/false/i){
$data{composite} = 'off';
}elsif($data{composite}=~m/on/i || $data{composite}=~m/yes/i || $data{composite}=~m/true/i){
$data{composite} = 'on';
}elsif($data{video_drv} eq 'nvidia' || $data{video_drv} eq 'intel'){
$data{composite} = 'on';
}else{
$data{composite} = 'off';
}
#----------------------------------------------------------------------
# Определим наличие stage, portage
# $data{stagepath}, $data{portagepath}
#----------------------------------------------------------------------
if($data{builder} && !defined $data{addition} && !$data{createiso}){
$data{stagepath} = "/var/calculate/remote/stages";
#определим максимальную версию stage нашей архитектуры, либо подставим маску
my $stage;
opendir(STAGE, $data{stagepath});
foreach(readdir STAGE){
if($_ eq "." || $_ eq ".."){next;}
if($_=~m/^$data{stage}/ && $stage lt $_){$stage = $_;}
}
closedir STAGE;
if($stage){$data{stage} = $stage}else{$data{stage} = $data{stage}."-YYYYMMDD.tar.bz2"}
#определим наличие CLS
if($data{calculate} ne 'CLS' && $data{system} eq 'desktop'){
my $stage;
opendir(STAGE, $data{linuxdir});
foreach(readdir STAGE){
if($_ eq "." || $_ eq ".."){next;}
if($_=~m/^cls\-[0-9\.]+\-$data{march}\.iso$/ && $stage lt $_){$stage = $_;}
}
closedir STAGE;
if($stage){$data{stage} = $stage}
$data{menuconfig} = "off";
}
if(!-e "$data{stagepath}/$data{stage}" && !-e "$data{linuxdir}/$data{stage}" &&
!defined $data{arg}{'vars'}
){
if(!-e $data{stagepath}){
printmes(" ".gettext('Create directory')); printmes(" stages...");
system "$data{path} mkdir $data{stagepath}";
printmes(" ".gettext('done')); printmes(".\n");
}
printmes("\n");
printmes(gettext('To continue copy file'));
printmes(" \"$data{stage}\" ");
printmes(gettext('to directory')); printmes(" \"$data{stagepath}\".\n");
beep();
exit;
}
$data{portagepath} = "/var/calculate/remote/snapshots";
if(!-e $data{portagepath}){
printmes(" ".gettext('Create directory')); printmes(" snapshots...");
system "$data{path} mkdir $data{portagepath}";
printmes(" ".gettext('done')); printmes(".\n");
}else{
#найдем последнюю версию портежей
my $last = 0;
opendir(DIR, $data{portagepath});
foreach(readdir DIR){
if($_!~/^portage-([0-9]+).tar.bz2$/){next;}
if($last < $1){$last = $1;}
}
closedir DIR;
if($last){
$data{portage} = "portage-$last.tar.bz2";
}
}
if(!$data{portage} && !defined $data{arg}{'vars'} && $data{stage} !~m/iso$/){
printmes("\n");
printmes(gettext('To continue copy file'));
printmes(" \"portage-YYYYMMDD.tar.bz2\"\n");
printmes(gettext('to directory')); printmes(" \"$data{portagepath}\".\n");
beep();
exit;
}
printmes(" ".gettext('Last available stage version')); printmes(": $data{stage}\n");
if($data{stage} !~m/iso$/){
printmes(" ".gettext('Last available portage version')); printmes(": $data{portage}\n");
}
}
#----------------------------------------------------------------------
# Пути к директориям пакетов сборки
# @{$data{packages})
#----------------------------------------------------------------------
@{$data{packages}} = (
"$data{dir}/install/builder/packages",
"/usr/calculate/share/builder/packages",
);
#----------------------------------------------------------------------
# Получим список доступных патчей
# $data{patchdir}, %{$data{patches}}, $data{patchlast}
#----------------------------------------------------------------------
if($data{os}){
if(!$data{patchdir}){
$data{patchdir} = "/usr/calculate/share/patch"; #путь к директории обновлений
}
if($data{patchlast} eq ''){
$data{patchlast} = $data{ospatch};
}
opendir(DIR, $data{patchdir});
foreach(readdir DIR){
if($_!~/^$data{calculate}\-$data{os}\-([0-9]+)$/){next;} #файлы с патчами должны быть в формате Система-версия-номер (прим. Drage-7.12-1)
if($1 > $data{ospatch}){
${$data{patches}{$_}}++;
}
if(!$data{arg}{"set-patchlast"} && substr($data{patchlast},1) < $1){$data{patchlast} = $1;}
}
closedir DIR;
if(%{$data{patches}}){
printmes(" ".gettext('Available updates').": ");
foreach(sort keys %{$data{patches}}){
printmes($_." ");
}
printmes("\n");
}
}
#----------------------------------------------------------------------
# Прекратим собирать сведения,
# при обновлении системы, или упаковке в ISO образ
#----------------------------------------------------------------------
if(defined $data{arg}{'updateonly'}){return '';}
printmes(gettext('Location')."\n");
#----------------------------------------------------------------------
# Заголовок изменённых файлов
# $data{mestitle}
#----------------------------------------------------------------------
if(!$data{mestitle}){
$data{mestitle} = "# Changed by $data{calcname} ";
$data{mestitle}.=$data{calcver};
}
if(!$data{mesline}){$data{mesline} = "#------------------------------------------------------------------------------";}
#----------------------------------------------------------------------
# Определим диск, с которого загружена система
# $data{load}
#----------------------------------------------------------------------
if(`$data{path} mount | grep "[0-9] on / type"`=~m/^(\/dev\/[^\s]+)/){
$data{rootload} = $1;
printmes(" ".gettext('Working volume')); printmes(": $data{rootload}\n");
}else{
$data{rootload} = "";
printmes(" ".gettext('Working volume'));
if($data{load} eq "ram"){
printmes(": ram\n");
}elsif(`$data{path} mount | grep "sd[a-f][0-9] on /newroot type"`){
printmes(": <"); printmes(gettext('scratch')); printmes(">\n");
}else{
printmes(": <"); printmes(gettext('undefined')); printmes(">\n");
}
}
#----------------------------------------------------------------------
# Определим диск для установки
# $data{rootinstall}
#----------------------------------------------------------------------
if(
!$data{arg}{'profile'} && !$data{builder_chroot} && !defined $data{arg}{'update'} && !defined $data{arg}{'list'} && !defined $data{addition} && !$data{createiso} && !defined $data{arg}{'initrd'} && !defined $data{arg}{'opengl'} && !defined $data{arg}{'unmask'}
){
#выберем альтернативный диск для установки
if(!$data{rootinstall} && getini("install.from")){
$data{rootinstall} = "/dev/".getini("install.from");
}elsif(!$data{rootinstall} && getini("install.devfrom")){
$data{rootinstall} = getini("install.devfrom");
}elsif(!$data{rootinstall}){
#проверим на схему 2-х /root разделов, предложив второй
if($data{rootload} && $data{rootload}=~m/([23])$/){
my $install;
if($1 == 2){
$install = 3;
}else{
$install = 2;
}
#получим диск
$install = substr($data{rootload},0,length($data{rootload})-1).$install;
#проверим на существование и на доступность
if(-e $install && !`mount | grep '^$install '`){
$data{rootinstall} = $install;
} } }
#проверим на существование диска
if(
!-e "$data{rootinstall}" &&
!defined $data{arg}{'vars'} &&
!$data{partitions_dev}
){
beep();
printmes("\n".gettext('Please specify installation volume'));
printmes(" (... --disk=/dev/sdXX).\n");
savelog();
exit;
}
}elsif($data{builder_chroot}){
#определим подмонтированный раздел в который производится установка
foreach(`$data{path} mount | grep "$data{mount} "`){
if(m#^(/dev/[^\s]+) on $data{mount} type#){
$data{rootinstall} = $1;
last;
} }
}else{
$data{rootinstall} = $data{rootload};
}
if(!$data{builder}){
printmes(" ".gettext('Installation volume'));
}else{
printmes(" ".gettext('Volume for system building'));
}
printmes(": $data{rootinstall}");
#----------------------------------------------------------------------
# Определим является ли диск установки USB-HDD устройством
# определим временную задержку для корректной инициализации root-раздела
# USB устройства
# $data{'removableinstall'}, $data{grub_delay}
#----------------------------------------------------------------------
if($data{type} ne 'hdd'){
$data{'removableinstall'} = 'on';
if($data{type} eq 'flash'){
printmes(" (USB-Flash)");
}else{
printmes(" (USB-HDD)");
}
if(!$data{grub_delay}){
$data{grub_delay} = " scandelay=5";
}
}else{
$data{'removableinstall'} = 'off';
if(!$data{grub_delay}){
$data{grub_delay} = "";
}
}
printmes("\n");
#----------------------------------------------------------------------
# Определим является ли текущий диск USB-HDD устройством
# $data{'removableload'}
#----------------------------------------------------------------------
$data{'removableload'} = 'off';
if($data{load} ne 'ram' && $data{rootload}){
$data{rootload} =~m#/dev/(.+)#;
my $disk = $1;
if(-e "/dev/disk/by-id" && `LANG=C ls -la /dev/disk/by-id/ | grep $disk | grep ' usb-'`){
$data{'removableload'} = 'on';
} }
#----------------------------------------------------------------------
# Укажем доступные варианты дисков для установки
#----------------------------------------------------------------------
{
my @disks;
foreach(`$data{path} LANG=C fdisk -l 2>&1`){
if(m/^(\/dev\/[^\s]+)\s/ && !m/Extended$/ && !m/Linux swap/){
push (@disks, $1);
} }
@{$data{other}}{rootinstall} = [@disks];
}
#----------------------------------------------------------------------
# Флаги переноса конфигурационных файлов
#----------------------------------------------------------------------
if( (!$data{move_fstab} || $data{move_fstab}=~m/^yes$/i || $data{move_fstab}=~m/^on$/i)
&&
($data{'removableload'} eq $data{'removableinstall'})
&&
!$data{partitions_dev}
){
$data{move_fstab} = "on";
}else{
$data{move_fstab} = "off";
}
#----------------------------------------------------------------------
# Флаг установки с использованием UUID
#----------------------------------------------------------------------
if($data{uuid}=~m/^yes$/i || $data{uuid}=~m/^on$/i ||
(!$data{uuid} && $data{'removableload'} eq 'on')
){
$data{uuid} = "on";
}else{
$data{uuid} = "off";
}
#----------------------------------------------------------------------
# Выбор планировщика
#----------------------------------------------------------------------
if(!$data{scheduler}){
if( -e "/sys/block/sda/queue/scheduler" ) {
my $scheduler = `cat /sys/block/sda/queue/scheduler`;
$scheduler=~m/.*\[([^\]]+)\].*/;
$data{scheduler} = $1;
}
if($data{'removableload'} eq 'on' || !$data{scheduler}){
if($data{system} eq 'server'){ $data{scheduler} = 'elevator'; }
else{ $data{scheduler} = 'cfq'; }
}
}
#----------------------------------------------------------------------
# Считаем uuid загрузочного диска, определим его метку
# $data{uuid_load}, $data{root_load_set}
#----------------------------------------------------------------------
$data{uuid_load} = "";
$data{root_load_set} = "";
if($data{'uuid'} eq 'on' && $data{rootload}){
$data{uuid_load} = uuid($data{rootload}, UUID);
$data{root_load_set} = "UUID=$data{uuid_load}";
}else{
$data{root_load_set} = $data{rootload};
}
#----------------------------------------------------------------------
# Считаем uuid установочного диска, определим его метку
# $data{uuid_install}, $data{root_install_set}
# после форматирования, значение изменится,
# но для наложения профиля значение переменной root_install_set понадобится
#----------------------------------------------------------------------
$data{uuid_install} = "";
$data{root_install_set} = "";
if($data{rootinstall}){
$data{uuid_install} = uuid($data{rootinstall}, UUID);
if($data{'uuid'} eq 'on'){
$data{root_install_set} = "UUID=$data{uuid_install}";
}else{
$data{root_install_set} = $data{rootinstall};
if($data{root_install_set} =~m/cciss/){
$data{root_install_set} =~s#(/dev/cciss)/(.+)#$1!$2#;
} } }
#----------------------------------------------------------------------
# Определим параметр инф. узлов для файловой системы ext2/3
# для переменной $data{formatrun}
#----------------------------------------------------------------------
my $node;
{
my @i = split "/", $data{rootinstall};
my $dev = @i[@i-1]; $dev=~m/^(.+)[0-9]+$/;
$dev = "/sys/block/$1/$dev/size";
if(-e $dev){
open(F, $dev);
my $size = <F>;
close(F);
chomp $size;
$size*=512/1024/1024/1024; #переведем в гигабайты
#исправим кол-во нод (инф. узлов) для ext2/3
#чтобы система успешно установилась
if($size < 8){
$node = "-N 500000 ";
} } }
#----------------------------------------------------------------------
# Выберем доступную утилиту форматирования
#----------------------------------------------------------------------
if($data{calculate} eq "CSS"){
@{$data{other}}{'format'} = ["ext2", "ext3", "ext4", "reiserfs"];
}else{
@{$data{other}}{'format'} = ["ext2", "ext3", "ext4", "jfs", "reiserfs", "xfs"];
}
if($data{type} eq "flash"){$data{'format'} = 'vfat';}
if(!$data{'format'} && !defined $data{arg}{'list'} && !defined $data{addition}){
my $format;
if($data{rootinstall}){
$format = uuid($data{rootinstall}, TYPE);
}
if($format =~m/ext2/){$data{'format'} = 'ext2';}
elsif($format =~m/ext3/){$data{'format'} = 'ext3';}
elsif($format =~m/ext4/){$data{'format'} = 'ext4';}
elsif($format =~m/jfs/){$data{'format'} = 'jfs';}
elsif($format =~m/reiserfs/){$data{'format'} = 'reiserfs';}
# elsif($format =~m/reiser4/){$data{'format'} = 'reiser4';}
elsif($format =~m/xfs/){$data{'format'} = 'xfs';}
else{$data{'format'} = 'reiserfs';}
}
my %formatrun = (
"ext2" => "/sbin/mkfs.ext2 $node-L",
"ext3" => "/sbin/mkfs.ext3 $node-L",
"ext4" => "/sbin/mkfs.ext4 $node-L",
"jfs" => "/sbin/mkfs.jfs -f -L $label",
"reiserfs" => "/sbin/mkfs.reiserfs -f -l",
# "reiser4" => "/sbin/mkfs.reiser4 -y -L",
"xfs" => "/sbin/mkfs.xfs -f -L",
"vfat" => "/usr/sbin/mkfs.vfat -F 32 -n",
);
my %fsid = ( "ext2" => "83",
"ext3" => "83",
"ext4" => "83",
"jfs" => "83",
"reiserfs" => "83",
"xfs" => "83",
"vfat" => "b" );
if($formatrun{$data{'format'}} && (-e "/sbin/mkfs.$data{'format'}" || -e "/usr/sbin/mkfs.$data{'format'}")){
$data{formatrun} = $formatrun{$data{'format'}};
}else{
if(-e "/sbin/mkfs.reiserfs"){ $data{'format'} = 'reiserfs'; }
elsif(-e "/sbin/mkfs.ext4"){ $data{'format'} = 'ext4'; }
elsif(-e "/sbin/mkfs.ext3"){ $data{'format'} = 'ext3'; }
elsif(-e "/sbin/mkfs.ext2"){ $data{'format'} = 'ext2'; }
elsif(-e "/sbin/mkfs.xfs"){ $data{'format'} = 'xfs'; }
elsif(-e "/sbin/mkfs.jfs"){ $data{'format'} = 'jfs'; }
# elsif(-e "/sbin/mkfs.reiser4"){ $data{'format'} = 'reiser4'; }
# elsif(-e "/sbin/mkfs.vfat"){ $data{'format'} = 'vfat'; }
else{ $data{NOMES} = ""; printmes("\n".gettext('Error')."! ".gettext('Formatting utility not found').".\n"); return ""; }
$data{formatrun} = $formatrun{$data{'format'}};
}
$data{disktypeid} = $fsid{$data{'format'}};
printmes(" ".gettext('File system')); printmes(": $data{'format'}\n");
#----------------------------------------------------------------------
# Установим $data{partitions_fdisk}
#----------------------------------------------------------------------
$data{partitions_fdisk} = "";
if($data{data_install_set}){
my $acl; if($data{'format'} ne 'xfs'){$acl = "acl,";}
$data{partitions_fdisk} =
" /var/calculate auto ${acl}noatime 0 0\n".
"/var/calculate/home /home auto bind 0 0\n".
"/var/calculate/share /usr/calculate/share auto bind 0 0\n\n";
}
#----------------------------------------------------------------------
# Хэш доступных grub-у дисков, диск и загрузочный раздел grub-а
# диск для установки граба
# %{$data{grub_map}}, пример: hd0 => sda, ..
# $data{grubinstall}, $data{grubload}
#----------------------------------------------------------------------
{
my $num = 0;
my ($grub,$dev);
foreach(`$data{path} LANG=C fdisk -l 2>&1 | grep "/dev/"`){
if(m/^Disk (\/dev\/[^:]+)\:/){
$grub = "hd".$num; $dev = $1;
$data{"grub_map"}{$grub} = $dev;
$num ++;
#получим $data{grubinstall} альтернативным способом, если диск не разбит, нижняя цепочка не сработает
if($data{partitions_dev} && $data{partitions_dev} eq $dev){
$data{grubinstall} = "$grub,1";
}
}elsif(m/^(\/dev\/[^\s]+)/ && $dev){
my $disk = $1;
$disk =~m/^$dev(.+)/;
#для совместимости со SCSI, учтем имена дисков c0d0p1
my $dn = $1; $dn=~m/([0-9]+)$/; #уберем если есть из номера диска букву p
my $grubdn = $1 - 1;
if($data{rootinstall}=~m/$dev$dn/){
if($data{'removableinstall'} eq 'on'){
$data{grubinstall} = "hd0,$grubdn"; #загрузочный диск grub
}else{
$data{grubinstall} = "$grub,$grubdn"; #загрузочный диск grub
}
}elsif($data{rootload}=~m/$dev$dn/){
$data{grubload} = "$grub,$grubdn"; #диск для установки
}
}
}
}
#----------------------------------------------------------------------
# Считаем меню граба grub.conf для переноса настроек
# $data{grub_another}
#----------------------------------------------------------------------
$data{grub_another} = "";
if($data{load} ne "ram" && $data{'removableload'} eq $data{'removableinstall'}){
my $grub = "/boot/grub/grub.conf";
if(-e $grub){
open(F, $grub);
my @lines = <F>;
close(F);
my $config, $record, $skip;
foreach(@lines){
if(/^#/){next;}
if(m/^\s*title[\s|=]+/){
if($record && !$skip){
$config.= $record;
}
$record = $_;
$skip = '';
}else{
if(m/[^\s]/ && $record){
if($data{rootinstall} && m/^\s*kernel .*root=$data{rootinstall}/){
$skip ++; #проскочим эту запись
}
$record.= "$_";
} } }
if($record && !$skip){ $config.= $record;}
$data{grub_another} = "\n".$config;
}else{
my $oldmarch = `$data{path} uname -m`; chomp $oldmarch;
my $os; if($data{os}){ $os = " $data{os}"; }
$data{grub_another} =
"\ntitle $data{linuxold}$os $oldmarch\n".
"root ($data{grubload})\n".
"kernel /boot/vmlinuz root=$data{root_load_set}";
} }
#----------------------------------------------------------------------
# Флаг установки MBR записи для загрузки системы
# $data{mbr}
#----------------------------------------------------------------------
if(!$data{mbr} || $data{mbr}=~m/^yes$/i || $data{mbr}=~m/^on$/i){
$data{mbr} = "on";
}else{
$data{mbr} = "off";
}
#----------------------------------------------------------------------
# Диски файла devicemap для grub-а
# $data{DEVICEMAP}
#----------------------------------------------------------------------
if(%{$data{grub_map}}){
foreach(sort keys %{$data{grub_map}}){
if($data{'removableinstall'} eq 'on'){
if($data{rootinstall}=~m/^$data{grub_map}{$_}/){
$data{devicemap} = "(hd0) $data{grub_map}{$_}\n";
last;
} }
$data{devicemap} .= "($_) $data{grub_map}{$_}\n";
}
chomp $data{devicemap};
}else{
$data{devicemap} = "\n";
}
#----------------------------------------------------------------------
# Определим раздел свопа, сформируем строку fstab
# $data{swap}, $data{uuid_swap}
#----------------------------------------------------------------------
if(!$data{builder}){
if(!$data{swap} && $data{rootinstall}){
#поищем своп на устанавливаемом HDD
foreach(`$data{path} LANG=C fdisk -l 2>&1 | grep "Linux swap"`){
m/^(\/dev\/[^\s]+)([0-9])/;
my $swap = $1.$2;
if($data{rootinstall}=~/^$1/){
my $uuid_swap = uuid($swap, UUID);
if($uuid_swap eq '' && !`cat /proc/swaps | grep "^$swap"`){
`$data{path} mkswap $swap > /dev/null`;
$uuid_swap = uuid($swap, UUID);
}
$data{swap} = $swap;
$data{uuid_swap} = $uuid_swap;
chomp $data{uuid_swap};
last;
} } } }
swapset(); #установим $data{swapset} и $data{swap_resume}
#----------------------------------------------------------------------
# С текущей системы определим дополнительные монтируемые диски
# (в том числе сетевые), пути монтирования
# @{$data{mount_dev}}, @{$data{mountdir}}, @{$data{mount_line}}
#----------------------------------------------------------------------
my $fstab = "/etc/fstab";
if(-e $fstab){
open(F, $fstab);
($data{mount_dev}, $data{mountdir}, $data{mount_line}) = getdisk_fstab(<F>);
close(F);
if(@{$data{mount_dev}} && !$data{builder}){
printmes(" ".gettext('Mounted disks')); printmes(": @{$data{mount_dev}}\n");
}
}
#----------------------------------------------------------------------
# Определим наличие сети
#----------------------------------------------------------------------
$data{lan} = "off";
foreach(`$data{path} LANG=C ifconfig -s`){
if(m/^Iface\s+/ || m/^lo\s+/){next;}
$data{lan} = "on";
last;
}
#----------------------------------------------------------------------
# Определим наличие настроенных сетевых интерфейсов
# $data{netstat}
#----------------------------------------------------------------------
$data{netstat} = 'off';
foreach(`$data{path} route -n`){
if(!m/^127\.0\./ && m/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\s+/){
$data{netstat} = 'on';
last;
} }
#----------------------------------------------------------------------
# Определим сетевые сервисы
# $data{proxy}, $data{useproxy}, $data{proxy_port}, $data{http_proxy},
# $data{nfs}, $data{ntp}
#----------------------------------------------------------------------
$data{useproxy} = 'off'; $data{proxy_port} = '';
$data{http_proxy} = ''; $data{nfs} = ''; $data{ntp} = '';
if(!$data{builder} && $data{netstat} eq 'on' && !defined $data{arg}{'initrd'} && !defined $data{arg}{'opengl'} && !defined $data{arg}{'unmask'} && !defined $data{arg}{'video'} && $data{lan} eq 'on' && $data{domain} ne 'local'){
printmes(gettext('Network services')."\n");
#определим прокси-сервер
if(
$data{proxy} ||
($data{exec_host} && $data{domain} && `$data{exec_host} proxy.$data{domain} | grep "has address"`)
){
my $proxy;
if($data{proxy}){$proxy = $data{proxy};}else{$proxy = "proxy.$data{domain}";}
foreach("3128","8080"){
if(IO::Socket::INET -> new(PeerAddr => "$proxy:$_", Proto => "tcp", Timeout => 1)){
$data{proxy} = $proxy;
$data{proxy_port} = $_;
printmes(" PROXY: $data{proxy}:$data{proxy_port}\n");
if(!$data{http_proxy}){$data{http_proxy} = "http://$data{proxy}:$data{proxy_port}/";}
last;
} }
if($data{proxy} && !$data{proxy_port}){$data{proxy} = "";}
}
if($data{proxy}){$data{useproxy} = 'on'}else{$data{useproxy} = 'off'}
#определим наличие сетевой файловой системы
if(
$data{exec_host} &&
!$data{nfs} &&
$data{domain} &&
`$data{exec_host} nfs.$data{domain} | grep "has address"` &&
IO::Socket::INET -> new(PeerAddr => "nfs.$data{domain}:2049", Proto => "tcp", Timeout => 1)
){
$data{nfs} = "nfs.$data{domain}";
}
if($data{nfs}){printmes(" NFS: $data{nfs}\n");}
#определим наличие локального сервера времени
if(!$data{ntp}){
if(
$data{exec_host} &&
$data{domain} &&
`$data{exec_host} ntp.$data{domain} | grep "has address"`
){
#определим не является ли компьютер сам источником времени
my $ip, $iplan;
$ip = `$data{exec_host} ntp.$data{domain} | grep "has address"`;
$ip=~s/.+\s+([0-9\.]+)$/$1/;
foreach(`LANG=C ifconfig | grep "inet addr:"`){
$iplan = $_;
$iplan=~s/.+inet addr:([0-9\.]+)\s+.+/$1/;
if($iplan eq $ip){last;}
}
if($iplan ne $ip){
$data{ntp} = "ntp.$data{domain}";
}
}
if(!$data{ntp}){$data{ntp} = "ntp0.zenon.net";}
}
printmes(" NTP: $data{ntp}\n");
}
if(!$data{ntp}){$data{ntp} = "ntp0.zenon.net";}
#----------------------------------------------------------------------
# Проверим наличие сервера CDS
# $data{server_url}, $data{server}
#----------------------------------------------------------------------
if(!$data{server_url}){
if(-e "/var/calculate/calculate2.env" || -e "/var/calculate/calculate.env"){
#считаем переменную адреса сервера
if(-e "/var/calculate/calculate2.env"){open (F, "/var/calculate/calculate2.env");}
else{open (F, "/var/calculate/calculate.env");}
foreach(<F>){
chomp;
if(m/^cl_remote_host\s?=\s?(.+)$/){
$data{server_url} = $1;
}
}
close (F);
}
}
if(!$data{builder} && ($data{system} eq 'desktop') &&
$data{netstat} eq 'on' && !defined $data{arg}{'initrd'} && !defined $data{arg}{'opengl'} && !defined $data{arg}{'unmask'} && !defined $data{arg}{'video'} && $data{lan} eq 'on' && $data{server_url}
){
if(
(
number_ver($data{linuxver}) >= number_ver('9.6') &&
`grep ldap /etc/nsswitch.conf`
)
||
(
$data{exec_nmap} &&
(
$data{server_url} =~m/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/i ||
($data{exec_host} &&
`$data{exec_host} $data{server_url} | grep "address"`)
)
&&
`$data{exec_nmap} --system-dns -p 389 $data{server_url} | grep open`
)
){
$data{server} = "CDS";
printmes(" ".gettext('Authentification'));
printmes(": LDAP\n");
}else{
$data{server} = "off";
printmes(" ".gettext('Authentification'));
printmes(": localhost\n");
} }
#----------------------------------------------------------------------
# Настройки PDC
# $data{samba_domain}
#----------------------------------------------------------------------
if($data{calculate} eq "CDS"){
$data{samba_domain} = "CDS";
$data{samba_netbios} = "PDC-CDS";
}
#----------------------------------------------------------------------
# Определим путь к LDAP-записям пользователей
# $data{ldap_base}, $data{ldap_hash_encrypt}, $data{ldap_bindname}, $data{ldap_bind},
# $data{ldap_bindpw}, $data{ldap_bindpw_hash}, $data{ldap_root_tmp}, $data{ldap_rootpw_tmp},
# $data{ldap_rootname}, $data{ldap_root}, $data{ldap_rootpw}, $data{ldap_rootpw_hash}
#----------------------------------------------------------------------
if(-e "/var/calculate/calculate2.env" || -e "/var/calculate/calculate.env"){
if(-e "/var/calculate/calculate2.env"){open (F, "/var/calculate/calculate2.env");}
else{open (F, "/var/calculate/calculate.env");}
foreach(<F>){
chomp;
#базовый суффикс
if(m/^ld_services_dn\s?=\s?(.+)$/){
if(!$data{ldap_base}){$data{ldap_base} = "$1";}
}
if(m/^ld_unix_dn\s?=\s?(.+)$/){
if(!$data{ldap_root}){$data{ldap_root} = "$1";}
}
if(m/^ld_bind_dn\s?=\s?(.+)$/){
if(!$data{ldap_bind}){$data{ldap_bind} = "$1";}
}
if(m/^ld_bind_pw\s?=\s?(.+)$/){
if(!$data{ldap_bindpw}){$data{ldap_bindpw} = "$1";}
}
}
close (F);
}
#базовый суффикс
if($data{calculate} eq "CDS" || $data{server} eq "CDS"){
if(!$data{ldap_base}){$data{ldap_base} = "dc=CDS";}
}
#алгоритм шифрования паролей
if($data{calculate} eq "CDS"){
$data{ldap_hash_encrypt}='{SSHA}';
}
#пользовательский доступ к базе с доступом только для чтения
if($data{calculate} eq "CDS" || $data{server} eq "CDS"){
$data{ldap_bindname} = "proxyuser";
if(!$data{ldap_bind}){
$data{ldap_bind} = "cn=$data{ldap_bindname},".$data{ldap_base};
}
if(!$data{ldap_bindpw}){
$data{ldap_bindpw} = "CDS";
}
}
# if($data{calculate} eq "CDS"){
# $data{ldap_bindpw_hash} = `$data{path} slappasswd -s $data{ldap_bindpw} -h $data{ldap_hash_encrypt}`;
# chomp $data{ldap_bindpw_hash};
# }
#временный пользователь root для инициализации базы данных
# if($data{calculate} eq "CDS"){
# $data{ldap_root_tmp} = "cn=ldaproot,".$data{ldap_base};
# $data{ldap_rootpw_tmp} = password();
# $data{ldap_rootpw_tmp_hash} = `$data{path} slappasswd -s $data{ldap_rootpw_tmp} -h $data{ldap_hash_encrypt}`;
# chomp $data{ldap_rootpw_tmp_hash};
# }
#постоянный пользователь root, прописываемый в базу при первой загрузке
#с одновременным удалением временного root-а
if($data{calculate} eq "CDS" || $data{server} eq "CDS"){
$data{ldap_rootname} = "ldapadmin";
if(!$data{ldap_root}){
$data{ldap_root} = "cn=$data{ldap_rootname},".$data{ldap_base};
}
if(-e "/etc/smbldap-tools/smbldap_bind.conf"){
$data{ldap_rootpw} = `cat /etc/smbldap-tools/smbldap_bind.conf | grep masterPw`;
chomp $data{ldap_rootpw};
$data{ldap_rootpw}=~s/[^=]+="(.+)"/$1/;
}
#если пароля нет, сгенерируем
if(!$data{ldap_rootpw} || $data{ldap_rootpw} eq 'secret'){
$data{ldap_rootpw} = password();
}
}
# if($data{calculate} eq "CDS"){
# $data{ldap_rootpw_hash} = `$data{path} slappasswd -s $data{ldap_rootpw} -h $data{ldap_hash_encrypt}`;
# chomp $data{ldap_rootpw_hash};
# }
#----------------------------------------------------------------------
# Определим запущенные сервисы CDS
# $data{up-*}
#----------------------------------------------------------------------
if(!$data{builder} && $data{calculate} eq "CDS"){
foreach("ldap", "mail", "ftp"){
if(getini("up.$_") eq "on"){
$data{"up_".$_} = "on";
}else{
$data{"up_".$_} = "off";
} } }
#----------------------------------------------------------------------
# Определим профили установки или сборки
# @{$data{profile_install}}, @{$data{profile_share}}
#----------------------------------------------------------------------
if(!$data{builder} && $data{type} ne "flash"){
printmes(gettext('Installation templates')."\n");
{
#считаем базовые профили установки
my %profiles;
opendir(PROFILES, "$data{dir}/install/profile");
foreach(readdir PROFILES){
if($_ eq "." || $_ eq ".."){next;}
$profiles{$_}++;
}
closedir PROFILES;
#определим базовые профили установки
my @profile;
foreach(sort keys %profiles){
if(
(m/^[0-9]/ ||
m/^$data{calculate}$/ || m/^$data{calculate}\?.+/ ||
m/^$data{system}$/ || m/^$data{system}\?.+/
) &&
check_name($_)
){
push (@{$data{profile_install}}, "$data{dir}/install/profile/$_");
my $name = $_; $name=~s/^([^\?]+)\?(.+)/$1/;
push (@profile, $name);
} }
printmes(" ".gettext('Basic'));
printmes(": ".join (", ", @profile)."\n");
#считаем дополнительные профили установки
my %profiles;
opendir(PROFILES, "/usr/calculate/share/profile");
foreach(readdir PROFILES){
if($_ eq "." || $_ eq ".."){next;}
$profiles{$_}++;
}
closedir PROFILES;
#определим дополнительные профили установки
#пропустим, если производится установка на извлекаемый диск
#либо наоборот, с внешнего диска на ПК
my @profile;
if(!($data{pass} eq 'install' && $data{'removableload'} ne $data{'removableinstall'})){
foreach(sort keys %profiles){
if(
(m/^[0-9]/ || $_=~m/^$data{calculate}$/ || m/^$data{system}$/) &&
check_name($_)
){
push (@{$data{profile_share}}, "/usr/calculate/share/profile/$_");
my $name = $_; $name=~s/^(.+)\?(.+)/$1/;
push (@profile, $name);
} }
#проверим профили домена
my ($i, $domain);
foreach(reverse split /\./, "$data{hostname}.$data{domain}"){
$i++;
if($domain){$domain = "$_.$domain"}else{$domain = "$_"}
if($i > 1){
if($profiles{$domain}){ #если профиль присутствует на диске
push (@{$data{profile_share}}, "/usr/calculate/share/profile/$domain");
push (@profile, $domain);
} } }
#проверим профиль компьютера
if($data{hostname} && $profiles{$data{hostname}}){
push (@{$data{profile_share}}, "/usr/calculate/share/profile/$data{hostname}");
push (@profile, $data{hostname});
}
}
#покажем найденные профили
if(@profile){
printmes(" ".gettext('Additional'));
printmes(": ".join (", ", @profile)."\n");
} }
}else{
#Считаем профили для различных этапов сборки
my $path = "$data{dir}/install/builder/profile";
opendir(DIR, $path);
foreach(readdir DIR){
if($_ eq "." || $_ eq ".."){next;}
if(
(m/^[0-9]/ && !defined $data{arg}{'pack'} && !$data{createiso}) ||
($_ eq "IMG" && defined $data{arg}{'pack'}) ||
($_ eq "ISO" && $data{createiso})
){
push (@{$data{profile_install}}, "$path/$_");
} }
closedir DIR;
}
#----------------------------------------------------------------------
# Определим путь к сборке дистрибутива в chroot окружении
# $data{builder}
#----------------------------------------------------------------------
#директория установки
if(!$data{builderdir}){
$data{builderdir} = "/mnt/calculate";
}
#----------------------------------------------------------------------
# Определим переменные окружения emerge и команду запуска emerge
# $data{makeopts}, $data{distdir}, $data{pkgdir}
# $data{emergerun1}, $data{emergerun2}
#----------------------------------------------------------------------
{
if(!$data{makeopts}){
my $makecpu;
if($data{cpus} == 1){
$makecpu = $data{cpus};
}else{
$makecpu = $data{cpus} + 1;
}
$data{makeopts} = "-j$makecpu";
}
if(!$data{distdir}){
$data{distdir} = "/var/calculate/remote/distfiles";
}
if(!$data{pkgdir}){
$data{pkgdir} = "/var/calculate/remote/packages/$data{calculate}/$data{linuxver}/$data{march}";
}
#$data{emergerun1} = "";
#$data{emergerun2} = "";
if($data{builder}){
if(!defined $data{addition}){
$data{emergerun1} = "$data{path} CHROOT=on chroot $data{chroot} /bin/bash -c \"$data{emergerun1} /usr/bin/emerge";
$data{emergerun2} = "\"";
}else{
$data{emergerun1} = "$data{emergerun1} /usr/bin/emerge";
}
}elsif(defined $data{arg}{'unmask'}){
$data{emergerun1} = "/usr/bin/emerge";
} }
#----------------------------------------------------------------------
# Определим ссылки на исходники программ
# $data{gentoo_mirrors}
#----------------------------------------------------------------------
if(!$data{gentoo_mirrors}){
if($data{language} eq 'ru'){
$data{gentoo_mirrors} = "http://mirror.yandex.ru/gentoo-distfiles http://distfiles.gentoo.org http://distro.ibiblio.org/pub/linux/distributions/gentoo";
}else{
$data{gentoo_mirrors} = '';
}
}
#----------------------------------------------------------------------
# Определим USB устройства
# $data{usb_*}
#----------------------------------------------------------------------
{
foreach(`$data{path} lsusb 2>/dev/null`){
m/^Bus [0-9]+ Device [0-9]+: ID [0-9a-f]+:[0-9a-f]+ (.+)$/i;
if($1=~m/Hewlett-Packard/){
$data{"usb_hp"} = "yes";
}elsif($1=~m/Bluetooth/){
$data{"usb_bluetooth"} = "yes";
}
}
}
#----------------------------------------------------------------------
# Команда создания учетных записей пользователей
# $data{run_user}
#----------------------------------------------------------------------
$data{run_user} = "";
if($data{'removableload'} eq $data{'removableinstall'}){
open(U, "/etc/passwd") or die "Ошибка открытия файла: $!"; my @PASSWD = <U>; close(U);
open(G, "/etc/group") or die "Ошибка открытия файла: $!"; my @GROUP = <G>; close(G);
my($USER,$TMP,$IDUSER,$IDGROUP,$COMMENT,$HOMEDIR,$SHELL) = (0..6);
my($gGROUP,$gTMP,$gIDGROUP,$gUSERS) = (0..3);
my $newuser = 0;
foreach(@PASSWD){
chomp; my @user = split /:/;
#извлечем пользователей, добавленных после установки системы
if($user[$IDUSER] >= 500 && $user[$IDUSER] < 65000 && $user[$IDUSER] != 999){
#соберем информацию по группам, в которые пользователь входит
my @grp;
foreach(@GROUP){
chomp; my @group = split /:/;
#определим принадлежность пользователя группе
if($group[$gUSERS] && ",$group[$gUSERS],"=~m/,$user[$USER],/){
push (@grp, $group[$gGROUP]);
}
}
my $groups; if(@grp){$groups = join ",", @grp; $groups = "--groups $groups";}
$data{run_user} = "\n/usr/sbin/useradd --uid $user[$IDUSER] --gid $user[$IDGROUP] --home-dir $user[$HOMEDIR] --shell $user[$SHELL] $groups $user[$USER]".$data{run_user};
#добавим создание групп на случай, если их не существует
my $ugroups;
my @gname = split / /, `$data{path} id -Gn $user[$USER]`;
my @gid = split / /, `$data{path} id -G $user[$USER]`;
foreach($i = 0; $i < @gid; $i ++){
if($gid[$i] >= 500){ #пропустим системные группы
chomp $gid[$i]; chomp $gname[$i];
$ugroups .= "\n/usr/sbin/groupadd -f -g $gid[$i] $gname[$i]";
} }
$data{run_user} = $ugroups.$data{run_user};
$newuser++;
} } }
$data{NOMES} = ""; #включим вывод сообщений
return 1;
}
#------------------------------------------------------------------------------
#
# Установим патчи на текущую систему
#
#------------------------------------------------------------------------------
sub patch{
printmes(gettext('Apply patches')."\n");
foreach(sort keys %{$data{patches}}){
printmes(" ".gettext('Run')); printmes(" $_...\n");
if(system "$data{patchdir}/$_"){
beep();
printmes(gettext('error').".\n");
return "";
}else{
printmes(" ".gettext('done').".\n");
} }
printmes(gettext('Finishing installation')."\n");
printmes(" ".gettext('Update')); printmes(" calculate.ini...");
putini(ospatch => $data{patchlast});
printmes(" ".gettext('done').".\n");
return 1;
}
#------------------------------------------------------------------------------
#
# Выполним проверки перед установкой
#
#------------------------------------------------------------------------------
sub checkready{
if(!$data{builder}){
printmes(gettext('Perform pre-install checkups')."\n");
}
#----------------------------------------------------------------------
# Отмонтируем раздел для устаноки если он примонтирован к /media
#----------------------------------------------------------------------
if(`$data{path} mount | grep "$data{rootinstall} on /media"`
&& `$data{path} mount | grep -c "$data{rootinstall} on "` == 1 ){
printmes(' '.gettext('Unmounting volume'));
printmes(" $data{rootinstall} ");
printmes(gettext('from'));
printmes( " /media...");
if( system("umount $data{rootinstall} &>/dev/null") ){
printmes(" ".gettext('error')."\n");
}
else {
printmes(" ".gettext('done')."\n");
}
}
#----------------------------------------------------------------------
# Проверим, используется ли раздел для установки
#----------------------------------------------------------------------
if(`$data{path} mount | grep $data{rootinstall}`){
printmes("\n".gettext('Error')."! ");
printmes(gettext('Disk'));
printmes(" $data{rootinstall} ");
printmes(gettext('mounted').".\n");
printmes(gettext('Please unmount disk or specify another volume')."!\n");
return "";
}
#----------------------------------------------------------------------
# Определим наличие обновлений
#----------------------------------------------------------------------
if(!$data{builder}){
printmes(" ".gettext('Update found'));
printmes(": $data{'calculatename'} $data{linuxver}");
if($data{'calculatesubname'}){printmes(" $data{'calculatesubname'}");}
printmes("\n");
}
#----------------------------------------------------------------------
# Проверим поддержку Calculate
#----------------------------------------------------------------------
if(!$data{builder}){
if(
(($data{calculate} eq "CLD" &&
number_ver($data{linuxver}) > number_ver('10.4.99')) ||
($data{calculate} eq "CLDG" &&
number_ver($data{linuxver}) > number_ver('10.4.99')) ||
($data{calculate} eq "CLDX" &&
number_ver($data{linuxver}) > number_ver('10.4.99')) ||
($data{calculate} eq "CLS" &&
number_ver($data{linuxver}) > number_ver('10.4.99')) ||
($data{calculate} eq "CLSG" &&
number_ver($data{linuxver}) > number_ver('10.0.9')) ||
($data{calculate} eq "CSS" &&
number_ver($data{linuxver}) > number_ver('10.4.99')) ||
($data{calculate} eq "CDS" &&
number_ver($data{linuxver}) > number_ver('10.4.99'))
) && !defined $data{arg}{'force'}
){
printmes("\n".gettext('To install the system update program Calculate. Launch "layman -S && emerge calculate"')); printmes(".\n");
beep(); return "";
}
if(
number_ver($data{linuxver}) <= number_ver('9.6') && !defined $data{arg}{'force'}
){
printmes("\n".gettext('The program supports the installation Calculate Linux versions from 9.7 and above')); printmes(".\n");
beep(); return "";
}
if(
number_ver($data{linuxver}) < number_ver('9.8') && $data{scratch_ws}
){
printmes("\n".gettext('You can install in Scratch mode Calculate Linux versions 9.8 or higher')); printmes(".\n");
beep(); return "";
}
}
#----------------------------------------------------------------------
# Проверим путь к архиву образа
#----------------------------------------------------------------------
if(!$data{builder} && $data{load} ne "ram" && !-e "$data{linuxdir}/$data{linux}"){
printmes("\n");
printmes(gettext('To continue copy file'));
printmes(" \"$data{linux}\" ");
printmes("\n".gettext('to directory')); printmes(" \"$data{linuxdir}\".\n");
beep();
return "";
}
#----------------------------------------------------------------------
# Проверим на загруженное обновление
# Примонтируем новый раздел для проверки
#----------------------------------------------------------------------
if(!defined $data{arg}{'force'} && !$data{builder}){
if(!system "$data{path} mount $data{rootinstall} $data{mount} &>/dev/null"){
if( getini('calculate', 'chroot') eq $data{calculate} &&
getini('linuxver', 'chroot') eq $data{linuxver})
{
#Отмонтируем новый раздел
system("$data{path} umount $data{mount}");
printmes("\n".gettext('Update'));
printmes(" $data{calculatename} $data{linuxver} ");
printmes(gettext('is already installed')); printmes(". ");
printmes(gettext('Please reboot')); printmes(".\n");
beep(); return "";
}
#Отмонтируем новый раздел
system("$data{path} umount $data{mount}");
}
}
#----------------------------------------------------------------------
# Последняя проверка -
# сверим контрольную сумму файла обновления
#----------------------------------------------------------------------
# if(!$data{builder} && $data{linux}){
#
# my $md5file = "$data{tmpdir}/md5sum.txt";
# # if(!-e $md5file){
# # beep();
# # printmes(" ".gettext('error').".\n");
# # printmes("\n".gettext('File not found'));
# # printmes(": \"$md5file\".\n");
# # return "";
# # }
#
# if(-e $md5file){
# #считаем файл контрольных сумм пакетов
# open (F, $md5file);
# my $tmp = $/; undef $/; my $md5sum=<F>; $/ = $tmp;
# close (F);
#
# my $checksum;
# foreach(split "\n", $md5sum){
# my ($md5, $file) = split " ";
# if($file eq $data{linux}){
# $checksum = $md5;
# break;
# } }
# if($checksum){
# printmes(" ".gettext('Check the checksum')); printmes(": $data{linux}...");
#
# if(system("$data{path} md5sum $data{linuxdir}/$data{linux} | grep $checksum &>/dev/null")){
# beep();
# printmes(" ".gettext('error').".\n");
# return "";
# }else{
# printmes(" ".gettext('done').".\n");
# } } } }
return 1;
}
#------------------------------------------------------------------------------
#
# Распакуем систему или stage, portage архивы
#
#------------------------------------------------------------------------------
sub extract{
if($data{sleep} > 0){
if($data{erase} eq 'on'){
printmes("\n".gettext('Volume formatting will start through'));
}else{
printmes("\n".gettext('System will install over'));
}
printmes(" $data{sleep} "); printmes(gettext('seconds')); printmes(".\n");
printmes(gettext('Press')); printmes(" Ctrl+C "); printmes(gettext('to cancel')); printmes("... ");
my $sleep = $data{sleep} - 1;
if(system(q|echo -e -n "\a|.$data{sleep}.q|"; sleep 1; for ((i=|.$sleep.q|; $i>0; i--)); do echo -e -n "\a\b\b $i"; sleep 1; done; echo -e "\b\b ";|)){
printmes("\n"); return "";
} }
if($data{erase} eq 'on'){
if(!$data{builder}){
printmes(gettext('Unpacking system')."\n");
}else{
printmes(gettext('Prepare installation volume')); printmes("\n");
}
if($data{partitions_dev} && $data{type} ne "flash"){
printmes(" ".gettext('Perform hard disk partition')); printmes("... ");
#выполним разбиение диска
if(system("$data{path} cat /usr/calculate/install/config/fdisk.$data{system} | fdisk $data{partitions_dev} &>/dev/null")){
printmes(gettext('Error')); printmes("! ");
return "";
}
printmes(gettext('done').".\n");
# отмонтируем разделы если они примонтировались
# в /media после разбиения диска
umountfrommedia();
printmes(" ".gettext('Set up a Linux swap area')); printmes("... ");
if(system("$data{path} mkswap $data{partitions_dev}1 &>/dev/null")){
printmes(gettext('Error')); printmes("! ");
return "";
}
printmes(gettext('done').".\n");
# После форматирования считаем uuid диска свопа, переопределим его метку
my $uuid_swap = uuid("$data{partitions_dev}1", UUID);
$data{swap} = "$data{partitions_dev}1";
$data{uuid_swap} = $uuid_swap;
chomp $data{uuid_swap};
swapset(); #изменим $data{swapset} и $data{swap_resume}
printmes(" ".gettext('Formatting a partition for the data')); printmes("... ");
if(system("$data{formatrun} Data $data{partitions_dev}5 &>/dev/null")){
printmes(gettext('Error')); printmes("! ");
return "";
}
# проверим нужно ли менять id для раздела
my $changeid=1;
foreach(`fdisk -l 2>&1`) {
if(m/^$data{partitions_dev}5\s+[*]?\s+\d+\s+\d+\s+\d+\s+$data{disktypeid}|GPT.*detected/) {
$changeid=0;
last;
}
}
system("echo -e \"t\n5\n$data{disktypeid}\nw\n\" | fdisk $data{partitions_dev} &>/dev/null") if $changeid;
printmes(gettext('done').".\n");
printmes(" ".gettext('Create a mount point "home" and "share"')); printmes("... ");
my $mount_tmp = "/mnt/newdata-".sprintf("%.0f", rand() * 10000);
if(system("mkdir $mount_tmp && mount $data{partitions_dev}5 $mount_tmp && mkdir -p $mount_tmp/share/linux $mount_tmp/home && umount $mount_tmp && rmdir $mount_tmp")){
printmes("\n"); printmes(gettext('Error')); printmes("! ");
return "";
}
printmes(gettext('done').".\n");
# После форматирования считаем uuid диска с данными, определим его метку
# $data{uuid_data}, $data{data_install_set}
$data{uuid_data} = uuid("$data{partitions_dev}5", UUID);
chomp $data{uuid_data};
if($data{'uuid'} eq 'on'){
$data{data_install_set} = "UUID=$data{uuid_data}";
}else{
$data{data_install_set} = "$data{partitions_dev}5";
}
}elsif($data{partitions_dev} && $data{type} eq "flash"){
printmes(" ".gettext('Perform hard disk partition')); printmes("... ");
#выполним разбиение диска
if(system("$data{path} cat /usr/calculate/install/config/fdisk.flash | fdisk $data{partitions_dev} &>/dev/null")){
printmes(gettext('Error')); printmes("! ");
return "";
}
printmes(gettext('done').".\n");
# отмонтируем разделы если они примонтировались
# в /media после разбиения диска
umountfrommedia();
}
printmes(" ".gettext('Formatting new volume')); printmes("... ");
{
#отформатируем диск
if(system("$data{formatrun} $data{calculate}-$data{linuxver} $data{rootinstall} &>/dev/null")){
printmes("\n"); printmes(gettext('Error')); printmes("! ");
printmes(gettext('Volume formatting failed')); printmes(".\n");
return "";
}
#установим соответствующий id для раздела
if( $data{rootinstall} =~ m|^(/dev/[^/0-9]+)([0-9]?[0-9]?)$| ) {
my $device = $1;
my $devicenumber = $2;
# проверим нужно ли менять id для раздела
my $changeid=1;
foreach(`fdisk -l 2>&1`) {
if(m/^$data{rootinstall}\s+[*]?\s+\d+\s+\d+\s+\d+\s+$data{disktypeid}|GPT.*detected/) {
$changeid=0;
last;
}
}
# проверим количество разделов на диске
if( `fdisk -l $device | grep -c "^/dev"` == 1 ) {
$devicenumber = "";
}
system("echo -e \"t\n${devicenumber}\n$data{disktypeid}\nw\n\" | fdisk ${device} &>/dev/null") if $changeid;
}
}
printmes(gettext('done').".\n");
}
# После форматирования считаем uuid установочного диска, определим его метку
# $data{uuid_install}, $data{root_install_set}
$data{uuid_install} = uuid($data{rootinstall}, UUID);
chomp $data{uuid_install};
if($data{'uuid'} eq 'on'){
$data{root_install_set} = "UUID=$data{uuid_install}";
}else{
$data{root_install_set} = $data{rootinstall};
}
#подключим своп
swapon();
printmes(" ".gettext('Mounting new volume')); printmes("... ");
if(system "$data{path} mount $data{rootinstall} $data{mount}"){
printmes("\n"); printmes(gettext('Error')); printmes("! ");
printmes(gettext('Mounting installation volume failed')); printmes(".\n"); return "";
}
printmes(gettext('done').".\n");
#примонтируем iso если мы устанавливаем систему из iso образа диска
#либо если мы собираем систему из CLS
if($data{linux} =~m/iso$/ || ($data{builder} && $data{stage} =~m/iso$/)){
my $iso;
if(!$data{builder}){$iso = $data{linux};}
else{$iso = $data{stage};}
printmes(" ".gettext('Mounting ISO file')); printmes("... ");
if(system "$data{path} mkdir -p /mnt/cdrom && mount -o loop $data{linuxdir}/$iso /mnt/cdrom"){
printmes("\n\n".gettext('Error')."! ");
beep();
system "$data{path} umount $data{mount}";
return "";
}
printmes(gettext('done').".\n");
}
#распакуем систему
if(extract_exec()){
printmes("\n\n".gettext('Error')."! ");
printmes(gettext('Unpacking image failed')); printmes(". ");
printmes(gettext('Operation interrupted')); printmes(".\n");
beep();
printmes(gettext('Abort')); printmes("...\n");
printmes(gettext('Unmounting new volume')); printmes("...");
system "$data{path} rm -f $data{mount}/etc/calculate/calculate.ini"; #удалим информацию об неустановленной системе
foreach( (0.2,0.5,1,2,4,8) ) {
if(system "($data{path} fuser -m $data{mount} 2>&1) >/dev/null") {
system "$data{path} umount $data{mount}";
last;
}
sleep($_);
}
if($data{linux} =~m/iso$/ || ($data{builder} && $data{stage} =~m/iso$/)){system "$data{path} umount /mnt/cdrom";}
printmes(" ".gettext('done').".\n");
return "";
}else{
printmes(gettext('done').".\n");
}
#отмонтируем /mnt/cdrom если мы устанавливали систему из файла ISO образа
if($data{linux} =~m/iso$/ || ($data{builder} && $data{stage} =~m/iso$/)){
system "$data{path} umount /mnt/cdrom";
}
if($data{builder} && $data{stage} !~m/iso$/){
printmes(" ".gettext('Unpack')); printmes(" $data{portage}...");
if(system("$data{path} tar -xjf $data{portagepath}/$data{portage} -C $data{mount}/usr")){
printmes("\n\n".gettext('Error')."! ");
printmes(gettext('Unpacking image failed')); printmes(". ");
printmes(gettext('Operation interrupted')); printmes(".\n");
beep();
printmes(gettext('Abort')); printmes("...\n");
printmes(gettext('Unmounting new volume')); printmes("...");
system "$data{path} rm -f $data{mount}/etc/calculate/calculate.ini"; #удалим информацию об неустановленной системе
system "$data{path} umount $data{mount}";
printmes(" ".gettext('done').".\n");
return "";
}
printmes(" ".gettext('done').".\n");
}
#перенесем информацию из ISO для scratch
if($data{scratch_ws}){
printmes(" ".gettext('Extract grub from squashfs')); printmes("... ");
if(system("$data{path} unsquashfs -n -d $data{mount}$data{scratch_ws} -f $data{mount}/livecd.squashfs /boot &>/dev/null")){
printmes("\n\n".gettext('Error')."! ");
beep();
return "";
}
printmes(gettext('done').".\n");
printmes(" ".gettext('Create symlink for kernel and initrd')); printmes("... ");
my $initramfile=`ls $data{mount}$data{scratch_ws}/boot/initr* 2>/dev/null`;
if($initramfile) {
$initramfile=`basename $initramfile`;
chomp($initramfile);
if(system("$data{path} ln -sf $initramfile $data{mount}$data{scratch_ws}/boot/initrd")){
printmes("\n\n".gettext('Error')."! ");
beep();
return "";
}
}
my $vmlinuzfile=`ls $data{mount}$data{scratch_ws}/boot/vmlinuz* 2>/dev/null`;
if($vmlinuzfile) {
$vmlinuzfile=`basename $vmlinuzfile`;
chomp($vmlinuzfile);
if(system("$data{path} ln -sf $vmlinuzfile $data{mount}$data{scratch_ws}/boot/vmlinuz &>/dev/null")){
printmes("\n\n".gettext('Error')."! ");
beep();
return "";
}
}
printmes(gettext('done').".\n");
}
return 1;
};
#------------------------------------------------------------------------------
# Выполнить копирование с прогресс баром если возможно
#------------------------------------------------------------------------------
sub copy_with_progress{
my ($from, $to, $count) = @_;
if( $data{run_bar} ne "cp" && $count > 0 ) {
$count = $count - 2;
return system("$data{path} cp -av $from/* $to/ | ".
"cut -b 1000 | $data{run_bar} -nth -nc -s $count >/dev/null");
}
else {
return system("$data{path} cp -a $from/* $to/");
}
}
#------------------------------------------------------------------------------
# Выполним распаковку
#------------------------------------------------------------------------------
sub extract_exec{
my $unpack;
if(!$data{builder}){
printmes(gettext('Unpacking system image into new volume')); printmes("... ");
if($data{linux} =~m/tar\.7z$/){$unpack = "$data{path} 7za x -so $data{linuxdir}/$data{linux} 2>/dev/null | tar xf - -C $data{mount}";}
elsif($data{linux} =~m/tar\.lzma$/){$unpack = "$data{path} lzma -dc $data{linuxdir}/$data{linux} | tar -xf - -C $data{mount}";}
elsif($data{linux} =~m/tar\.bz2$/){$unpack = "$data{path} tar -xjpf $data{linuxdir}/$data{linux} -C $data{mount}";}
}else{
printmes(" ".gettext('Unpack')); printmes(" $data{stage}... ");
if($data{stage} !~m/iso$/){
$unpack = "$data{path} tar -xjpf $data{stagepath}/$data{stage} -C $data{mount}";
}
# else{
# $unpack = "$data{path} unsquashfs -d $data{mount} -f /mnt/cdrom/livecd.squashfs";
# }
}
#путь к squashfs в случае установки из ISO файла или с CD-ROM
my $squashfs;
if(-e "/mnt/cdrom/$data{squash_cur}"){$squashfs = "/mnt/cdrom/$data{squash_cur}";}
elsif(-e "/mnt/squash/$data{squash_cur}"){$squashfs = "/mnt/squash/$data{squash_cur}";}
elsif(-e "/mnt/$data{squash_cur}"){$squashfs = "/mnt/$data{squash_cur}";}
elsif(-e "/mnt/flash/$data{squash_cur}"){$squashfs = "/mnt/flash/$data{squash_cur}";}
if($unpack){
if($unpack =~m/unsquashfs/){$bar ++; printmes("\n");}
#установка из архива
return system($unpack);
}elsif($squashfs){
if($data{type} eq "flash"){
#установка с ISO файла на флешку
return system("$data{path} rsync -a /mnt/cdrom/ $data{mount}");
}elsif(!$data{scratch_ws}){
my $install_from;
if($data{linux} =~ m/iso$/ || $data{stage} =~ m/iso$/ ||
( $data{scratch} eq "on" && $data{load} eq "ram" )){
system "$data{path} mkdir /mnt/squashfs && mount -o loop $squashfs /mnt/squashfs";
$install_from = "/mnt/squashfs";
} else {
$install_from = "/mnt/livecd";
}
#установка с ISO файла на жесткий диск ($data{type} = "hdd" или "usb-hdd")
my $count=int(`sed -rn \"\s/^files=(.*)\$/\\1/p\" $install_from/etc/calculate/calculate.ini`);
if($count > 0 ) {
$bar ++; printmes("\n");
} else {
$bar = 0;
}
my $res = copy_with_progress($install_from,$data{mount},$count);
if($install_from eq "/mnt/squashfs"){
system "$data{path} umount $install_from && rmdir $install_from";
}
return $res;
}elsif($data{scratch_ws}){
if($data{run_bar} =~m/bar/){$bar ++; printmes("\n");}
#установка путем копирования ISO файла на жесткий диск (режим установки scratch)
return system("$data{path} $data{run_bar} $squashfs $data{mount}/livecd.squashfs");
} }
return 1;
}
#------------------------------------------------------------------------------
#
# Наложим обновления
#
#------------------------------------------------------------------------------
sub profiles{
if($data{type} ne "flash"){
my $create;
printmes(gettext('Update config')."\n");
foreach(@{$data{profile_install}}, @{$data{profile_share}}){
profile($_);
};
}
return 1;
}
#------------------------------------------------------------------------------
#
# Выполним общие настройки системы
#
#------------------------------------------------------------------------------
sub isotosys{
#подготовим флешку к загрузке
if(($data{type} eq "flash" || defined $data{arg}{rebuild}) &&
!-e "$data{'chroot'}$target/syslinux" #проверим установку с флешки на флешку
){
my $target;
if(defined $data{arg}{rebuild}){
$target = "/target";
}
printmes(" ".gettext('Setting')); printmes(" syslinux...");
if( ! -e "$data{'chroot'}$target/syslinux" ) {
system "$data{path} mv $data{'chroot'}$target/isolinux $data{'chroot'}$target/syslinux";
system "$data{path} mv $data{'chroot'}$target/syslinux/isolinux.cfg $data{'chroot'}$target/syslinux/syslinux.cfg";
system "$data{path} sed -i 's/doload=s/cdroot_type=vfat doload=vfat,nls_cp866,nls_utf8,s/' $data{'chroot'}$target/syslinux/syslinux.cfg";
system "$data{path} sed -i 's/isolinux.cfg/syslinux.cfg/' $data{'chroot'}$target/syslinux/timezone.cfg";
system "$data{path} sed -i 's/isolinux.cfg/syslinux.cfg/' $data{'chroot'}$target/syslinux/keymap.cfg";
system "$data{path} sed -i 's/isolinux.cfg/syslinux.cfg/' $data{'chroot'}$target/syslinux/lang.cfg";
if(-e "$data{'chroot'}$target/syslinux/vga.cfg") {
system "$data{path} sed -i 's/isolinux.cfg/syslinux.cfg/' $data{'chroot'}$target/syslinux/vga.cfg";
}
}
printmes(" ".gettext('done').".\n");
return 1;
}
}
#------------------------------------------------------------------------------
#
# Выполним общие настройки системы
#
#------------------------------------------------------------------------------
sub setup{
printmes(gettext('System setup')."\n");
isotosys();
if($data{type} eq 'flash'){return 1;}
#подготовим scratch диск к загрузке
if($data{scratch_ws}){
printmes(" ".gettext('Setting')); printmes(" scratch...");
system "$data{path} mkdir $data{'chroot'}/calculate";
system "$data{path} mkdir $data{'chroot'}/delta";
system "$data{path} cp -a $data{'chroot'}$data{scratch_ws}/boot $data{'chroot'}";
printmes(" ".gettext('done').".\n");
}
#вытащим из образа оригинальный inittab для последующей подмены
if($data{scratch_ws}){ unsquash("/etc/inittab"); }
#восстановим inittab
my $inittab = "$data{chroot}$data{scratch_ws}/etc/inittab";
if(-e $inittab){
printmes(" ".gettext('Update')); printmes(" /etc/inittab...");
#восстановим оригинальный inittab, убрав автовход
system("sed -i '/bin\\/bashlogin/d' $inittab");
system("sed -ir 's/#\\(c[1-6]:\\)/\\1/' $inittab");
printmes(" ".gettext('done').".\n");
}
#Создадим initrd-файл
if($data{removableinstall} eq 'off'){
initrd($data{chroot});
}
#----------------------------------------------------------------------
# Запросим пароль root-а
#----------------------------------------------------------------------
if(`$data{path} cat /etc/shadow | grep '$data{hash_root}'`){
printmes(gettext('Changing root password')); printmes("\n");
`passwd`;
}
#----------------------------------------------------------------------
# Перенесем пароль рута
#----------------------------------------------------------------------
if($data{scratch_ws}){ unsquash("/etc/shadow","/etc/shadow-"); }
system "$data{path} cat /etc/shadow | sed q > $data{'chroot'}$data{scratch_ws}/etc/shadow_new &&
$data{path} cat $data{'chroot'}$data{scratch_ws}/etc/shadow | sed 1d >> $data{'chroot'}$data{scratch_ws}/etc/shadow_new";
system "$data{path} cat /etc/shadow- | sed q > $data{'chroot'}$data{scratch_ws}/etc/shadow-_new &&
$data{path} cat $data{'chroot'}$data{scratch_ws}/etc/shadow- | sed 1d >> $data{'chroot'}$data{scratch_ws}/etc/shadow-_new";
system "$data{path} mv $data{'chroot'}$data{scratch_ws}/etc/shadow_new $data{'chroot'}$data{scratch_ws}/etc/shadow";
system "$data{path} mv $data{'chroot'}$data{scratch_ws}/etc/shadow-_new $data{'chroot'}$data{scratch_ws}/etc/shadow-";
system "$data{path} chmod 0700 $data{'chroot'}$data{scratch_ws}/etc/shadow";
system "$data{path} chmod 0700 $data{'chroot'}$data{scratch_ws}/etc/shadow-";
#----------------------------------------------------------------------
# Пропишем клиент в автозагрузку, если компьютер в домене
#----------------------------------------------------------------------
if($data{server} eq "CDS" && -e "/etc/runlevels/default/client"){
system "$data{path} cp -a /etc/runlevels/default/client $data{'chroot'}$data{scratch_ws}/etc/runlevels/default/client";
}
#----------------------------------------------------------------------
# Перенесем оригинальные ключи ssh
#----------------------------------------------------------------------
if($data{load} ne "ram"){
printmes(" ".gettext('Copy original ssh keys')); printmes("...");
system "$data{path} cp -a /etc/ssh/ssh_host_* $data{'chroot'}$data{scratch_ws}/etc/ssh/";
printmes(" ".gettext('done').".\n");
}
#----------------------------------------------------------------------
# Перенесем udev-правила, если в системе более одной сетевой карты
#----------------------------------------------------------------------
{
my $rule = "/etc/udev/rules.d";
if($data{net_eth1} && -e "$rule/70-persistent-net.rules"){
printmes(" ".gettext('Copy udev net rules')); printmes("...");
system "$data{path} mkdir -p $data{'chroot'}$data{scratch_ws}$rule";
system "$data{path} cp -a $rule/70-persistent-net.rules $data{'chroot'}$data{scratch_ws}$rule";
printmes(" ".gettext('done').".\n");
} }
#----------------------------------------------------------------------
# Перенесем настройки wicd
#----------------------------------------------------------------------
{
my $wicd = "/etc/wicd";
if(-e "$wicd/manager-settings.conf" || -e "$wicd/wireless-settings.conf"){
printmes(" ".gettext('Copy wicd manager settings')); printmes("...");
system "$data{path} mkdir -p $data{'chroot'}$data{scratch_ws}$wicd";
if(-e $ms){system "$data{path} cp $wicd/manager-settings.conf $data{'chroot'}$data{scratch_ws}$wicd";}
if(-e $ws){system "$data{path} cp $wicd/wireless-settings.conf $data{'chroot'}$data{scratch_ws}$wicd";}
printmes(" ".gettext('done').".\n");
} }
#----------------------------------------------------------------------
# Удалим файлы неиспользуемых локализаций
#----------------------------------------------------------------------
{
printmes(" ".gettext('Remove unused localization')); printmes("...");
clearlang();
printmes(" ".gettext('done').".\n");
}
#----------------------------------------------------------------------
# Сохраним диск, с которого произвелась установка
# за исключением установки с CD или с ПК на USB или с USB на ПК
#----------------------------------------------------------------------
if( $data{load} ne "ram" &&
($data{'removableload'} eq $data{'removableinstall'})
){
if($data{scratch_ws}){
unsquash("/etc/calculate/calculate.ini");
}
putini("install.devfrom" => $data{rootload}, "chroot");
}
return 1;
}
#------------------------------------------------------------------------------
#
# Подготовим систему к перезагрузке
#
#------------------------------------------------------------------------------
sub loader{
printmes(gettext('Prepare system for reboot')); printmes("\n");
#пропишем grub в автозагрузку, изменим MBR запись
if($data{mbr} eq "on"){
printmes(" ".gettext('Change boot record')); printmes("...");
if($data{type} ne "flash"){
#chroot $data{'chroot'}
if(system "$data{path} /sbin/grub --device-map=$data{'chroot'}/boot/grub/device.map --batch <<EOF &>/dev/null\n".
"root ($data{grubinstall})\n".
"setup (hd0)\n".
"quit\n".
"EOF"){
printmes(" ".gettext('error').".\n");
}else{
printmes(" ".gettext('done')); printmes(".\n");
}
}else{
#сделаем флешку загрузочной
if(system "$data{path} dd if=/usr/share/syslinux/mbr.bin of=$data{partitions_dev} &>/dev/null"){
printmes(" ".gettext('error').".\n");
}else{
printmes(" ".gettext('done')); printmes(".\n");
} } }
#Отмонтируем устанавливаемый диск
printmes(" ".gettext('Unmount installed system volume')); printmes("...");
if(system("$data{path} umount $data{'chroot'}")){
printmes(" ".gettext('error').".\n");
return "";
}else{
printmes(" ".gettext('done')); printmes(".\n");
}
#пропишем syslinux в автозагрузку
if($data{type} eq "flash"){
printmes(" ".gettext('Create a boot partition')); printmes("...");
if(system "$data{path} syslinux $data{rootinstall}"){
printmes(" ".gettext('error').".\n");
return "";
}else{
printmes(" ".gettext('done')); printmes(".\n");
}
}
return 1;
}
#------------------------------------------------------------------------------
#
# Перезагрузим компьютер
#
#------------------------------------------------------------------------------
sub reboot{
if($data{type} ne "flash"){
printmes(" ".gettext('Detect logged in users')); printmes("... "); printmes(gettext('done').".\n");
if(`$data{path} w -hs` || $data{load} eq "ram"){
printmes("\n".gettext('To apply changes you have to reboot').".\n");
}else{
printmes(" ".gettext('Perform reboot')); printmes("...");
system "$data{path} shutdown -r now";
printmes(" ".gettext('done').".\n");
}
}
return 1;
}
#------------------------------------------------------------------------------
#
# Выведем список переменных конфигурационных файлов
#
#------------------------------------------------------------------------------
sub printvars{
printmes(gettext('Config files variables list').":\n");
my ($vars,$tab);
foreach(sort keys %data){
#пропустим внутренние переменные
if($_=~m/[A-Z]/ || $data{$_}=~m/^HASH/){next;}
my $data;
if($data{$_}=~m/^ARRAY/){$data = "@{$data{$_}}";}else{$data = $data{$_};}
if(length(" #-$_-#") < 16){$tab = "\t";}else{$tab = "";}
my $w = "r"; if(${$data{write}}{$_}){$w = "w";}
my $other; if(@{$data{other}}{$_}){
my $skip = $data{$_};
foreach(@{${$data{other}}{$_}}){
if($_ eq $skip){next;}
if($other){$other.=", ";}
$other .= "$_";
}
$other = " [$other]";
}
printmes(" #-$_-#\t${tab}[$w] \"$data\"$other\n");
}
return 1;
}
#------------------------------------------------------------------------------
#
# Выведем конфигурацию ПК
#
#------------------------------------------------------------------------------
sub printhardware{
printmes(" ".gettext('Vendor')); printmes(": ");
if($data{vendor}){
printmes(gettext($data{vendor}."\n"));
}else{
printmes("<"); printmes(gettext('undefined')); printmes(">\n");
}
if($data{laptop_model}){
printmes(" ".gettext('Model')); printmes(": ");
printmes(gettext($data{laptop_model}."\n"));
}
if($data{board_model}){
printmes(" ".gettext('Motherboard')); printmes(": ");
printmes("$data{board_model} ($data{board_vendor})\n");
}
if($data{video}){
printmes(" ".gettext('Videocard'));
printmes(": $data{video}\n");
}
if($data{video_resolution}){
printmes(" ".gettext('Screen resolution'));
printmes(": $data{video_resolution}\n");
}
#получим информацию из hal
if($data{hal} && -e "/usr/bin/hal-device"){
my (%hw, %hwlink); #параметры устройств и ссылки на идентификаторы устройств
my (%hdd, %cdrom); #хэши доступных дисков
{
my ($udi);
foreach(`/usr/bin/hal-device`){
chomp;
if($_){
if(m/^[0-9]+: /){
$udi = $_;
}else{
m/^\s*([^=]+) = ([^=]+)?(\(string\)|\(int\)|\(uint64\)|\(string list\))$/;
my $var = $1; my $val = $2;
$val =~s/^([^\s]+)\s+\(.+/$1/; #уберем значение в скобках
$val =~s/^'([^']+)'\s+.+/$1/; #уберем кавычки
$hw{$udi}{$var} = $val; #устройство-параметр - значение
#определим устройства
if(m#block.device = '/dev/(sd[a-z])'#){
$hwlink{$1} = $udi; #указатель на запись устройства hdd
$hdd{$1}++;
}elsif(m#block.device = '/dev/(sr[0-9])'#){
$hwlink{$1} = $udi; #указатель на запись устройства cd-rom
$cdrom{$1}++;
}elsif(m#linux.acpi_path = '/proc/acpi/processor/(CPU0)'#){
$hwlink{$1} = $udi; #указатель на запись устройства cd-rom
}
} } } }
printmes(" ".gettext('Hard disks')); printmes(":\n");
foreach(sort keys %hdd){
my $size = sprintf("%0.0f",$hw{$hwlink{$_}}{'storage.size'}/1000000000);
printmes(" $_: $size Gb ($hw{$hwlink{$_}}{'info.product'})\n");
}
}
}
#------------------------------------------------------------------------------
#
# Выведем сообщение в текущей локали
#
#------------------------------------------------------------------------------
sub printmes{
if($data{NOMES}){return "";} #флаг не печатать сообщения
#определим наличие установленной программы gettext
#и очистим файл лога
if(!defined $date{gettext}){
my $gettext = `$data{path} which gettext`; chomp $gettext;
if($gettext){ $date{gettext}++; }
else{ $date{gettext}=''; }
}
#считаем входящее сообщение
my $mes = $_[0];
$mes=~s/'/"/g;
#ведем лог
$data{LOG} .= $mes;
if($date{gettext}){
my ($from, $after);
#обрежем левые и правые отступы для перевода фразы
if($mes=~m/^(\s*)(.+)([!?:\.]\s*)$/ || $mes=~m/^(\s*)(.+)(\s*)$/){
$from = $1; $mes = $2; $after = $3;
}
if($mes){
my $text;
if($mes!~/^\-/){$text = "gettext -n -d calculate -s '$mes'";}
else{$text = "echo -n '$mes'";}
system "export TEXTDOMAINDIR='$data{dir}/install/i18n'; echo -n '$from'; $text; echo -n '$after'";
}
}else{
print $mes;
}
return 1;
}
#------------------------------------------------------------------------------
#
# Локализация. Процедура нужна для извлечения переводимых строк xgettext-ом
#
#------------------------------------------------------------------------------
sub gettext{
return $_[0];
}
#------------------------------------------------------------------------------
#
# Ведение log-файла
#
#------------------------------------------------------------------------------
sub savelog{
my $id = `$data{path} id -u`; chomp $id;
if(!$data{NOLOG} && $id == 0){
if(!-e "/var/log/calculate"){
system "$data{path} mkdir -m 755 /var/log/calculate";
}
open (F,">/var/log/calculate/install.log"); flock(F, 2); print F $data{LOG}; close (F);
}
return 1;
}
#------------------------------------------------------------------------------
#
# Сообщение об ошибке неправильно введенного аргумента
#
#------------------------------------------------------------------------------
sub errorarg{
my $arg = $_[0];
printmes(gettext('Unrecognized option')); printmes(" '$arg'.\n");
printmes(gettext('Try')); printmes(" 'calculate --help' "); printmes(gettext('for more information'));
printmes(".\n");
beep();
return 1;
}
#------------------------------------------------------------------------------
#
# Наложим профили обновления
#
#------------------------------------------------------------------------------
sub profile{
my $profile = $_[0];
my $title = $_[1]; #обозначение профиля
my $tmpdir; if(!-e $data{tmpdir}){
system "$data{path} mkdir -p '$data{tmpdir}'";
$tmpdir ++;
}
if(!$title){ $title = $profile; $title =~s/.+\/([^\/]+)\/[^\/]+\/([^\/]+)$/$1\/$2/; }
$title=~s/^(.+)\?(.+)/$1/;
printmes(" ".gettext('Apply template')); printmes(" \"$title\"...");
#Template file
$data{title} =
$data{mesline}."\n".
$data{mestitle}."\n".
qq|# Changes to profile "$title".\n|.
$data{mesline};
#создадим пути и права доступа к файлам, аналогичные профилю
my @dir = `$data{path} find "$profile" -type d`;
foreach(@dir){
chomp;
my $recpath; #по заданным маскам поменяем права на директории
foreach(split "/", substr($_, length($profile))){
$recpath.= "$_/";
if(!-e $data{'chroot'}.$data{scratch_ws}.$recpath){
system qq|$data{path} mkdir -p $data{'chroot'}$data{scratch_ws}$recpath|;
if($recpath=~m|/\.ssh/| || $recpath=~m|/^\/root$/|){
system qq|$data{path} chmod 0700 "$data{'chroot'}$data{scratch_ws}$recpath"|;
} } } }
#поменяем дополнительно права для scratch установки
my $path = "$data{'chroot'}$data{scratch_ws}/root";
system qq|$data{path} mkdir -p "$path" && chmod 0700 "$path"|;
$path = "$data{'chroot'}$data{scratch_ws}/tmp";
system qq|$data{path} mkdir -p "$path" && chmod 1777 "$path"|;
#извлечем файлы профиля
my @conf = `$data{path} find "$profile" -type f`;
foreach(@conf){
chomp;
my $allocation = $data{'chroot'}.$data{scratch_ws}.substr($_, length($profile));
#проверим имя файла фрофиля перед переносом в систему
$allocation = check_name($allocation); if(!$allocation){next;}
#сохраним обработанный файл в директории установки
$allocation=~m/^(.*\/)([^\/]+)$/;
my $namepath = $1;
my $nameprof = $2;
my $nameorig = $nameprof;
#извлечем текстовый файл профиля
if(`$data{path} file "$_" | grep text`){
$data{file}{name} = $_;
#считаем файл
open(C, $data{file}{name}); my (@conf) = <C>; close(C);
#преобразуем файл
@conf = convert(lines => [@conf]);
#выполним подмены настройками из старой системы
if($data{pass} ne "builder"){
if(
$allocation eq $data{'chroot'}.$data{scratch_ws}.'/etc/fstab' &&
@{$data{mount_line}} &&
$data{'move_fstab'} eq 'on'
){
@conf = move_fstab(@conf);
}
}
if($data{pass} eq 'install' && $data{scratch_ws} &&
(substr($nameprof,0,1) eq "~" || substr($nameprof,0,1) eq "^")
){
#извлечем файл для объединения
unsquash(substr($namepath.substr($nameprof,1), length($data{'chroot'}.$data{scratch_ws})));
}
if(substr($nameprof,0,1) eq "^"){
$nameorig = substr($nameprof,1);
#допишем в конец файла без значка
open(C, ">>".$namepath.$nameorig); print C @conf; close(C);
}elsif(substr($nameprof,0,1) eq "~"){
$nameorig = substr($nameprof,1);
#подменим переменные конфигурационного файла новыми значениями
open(C, $namepath.$nameorig); my (@original) = <C>; close(C); #считаем оригинальный файл
my @save = substitution([@original], [@conf]);
open(C, ">".$namepath.substr($nameprof,1)); print C @save; close(C);
}elsif(substr($nameprof,-5) eq ".diff"){
$nameorig = substr($nameprof,0,-5);
if($data{pass} eq 'install' && $data{scratch_ws}){
#извлечем файл для объединения
unsquash(substr($allocation, length($data{'chroot'}.$data{scratch_ws}),-5));
}
open(C, ">$data{tmpdir}/$nameprof"); print C @conf; close(C);
foreach(`LANG=C patch -N -r $data{tmpdir}/$nameorig.rej --no-backup-if-mismatch $namepath$nameorig $data{tmpdir}/$nameprof`){
if(m/FAILED/i){
printmes("\n".gettext('Error patching from')." $data{file}{name}\n");
last;
} }
}else{
system "$data{path} rm -f \"$allocation\""; #удалим на случай если стоит ссылка на другой файл
open(C, ">$allocation"); print C @conf; close(C);
}
#сменим права доступа
if(substr($allocation,-5) ne ".diff"){
if($allocation=~m|/ssh/|){
system "$data{path} chmod 600 $namepath$nameorig";
}elsif($allocation=~m|/etc/sudoers|){
system "$data{path} chmod 0440 $namepath$nameorig";
}elsif( $allocation=~m|/config/kdm/X| ||
$allocation=~m|/etc/cron\.| ||
$allocation=~m|/etc/init\.d/| ||
$allocation=~m|/etc/X11/gdm/| ||
$allocation=~m|/usr/local/bin/| ||
$allocation=~m|/etc/NetworkManager/dispatcher.d/| ||
$allocation=~m|/sbin/| ||
$allocation=~m|\.sh$|
){
system "$data{path} chmod 755 $namepath$nameorig";
} }
}elsif(`$data{path} file "$_" | grep empty`){
system "$data{path} rm -f \"$allocation\"";
if($data{scratch_ws} && $data{pass} eq "install"){
system "$data{path} touch \"$namepath.wh.$nameorig\"";
}
}else{
#перенесем без обработки бинарный файл
`$data{path} cp -a "$_" "$allocation"`;
}
}
#создадим символическую ссылку на Zoneinfo
if(!$data{builder}){
if(!-e "$data{chroot}$data{scratch_ws}/tmp"){`$data{path} mkdir -m 1777 -p "$data{chroot}$data{scratch_ws}/tmp"`;}
`$data{path} rm -rf $data{chroot}$data{scratch_ws}/tmp/localtime &&
ln -s /usr/share/zoneinfo/$data{timezone} $data{chroot}$data{scratch_ws}/tmp/localtime &&
mv $data{chroot}$data{scratch_ws}/tmp/localtime $data{chroot}$data{scratch_ws}/etc/
`;
}
#создадим символические ссылки аналогичные профилю
my @dir = `$data{path} find "$profile" -type l`;
foreach(@dir){
chomp;
#уберем ссылки на несуществующие файлы
`$data{path} file "$_"`=~m/\`([^']+)'/;
my $dest = $1;
#проверяем на существование только абсолютный путь
if($dest=~m/^[\/]/){
if($data{pass} eq 'install' && $data{scratch_ws}){
#проверим существование в squash образе
if(!checksquash($dest)){next;}
}else{
#проверим в системе
if(!-e "$data{'chroot'}$data{scratch_ws}$dest"){next;}
} }
#выделим путь из профиля
my $allocation = $data{'chroot'}.$data{scratch_ws}.substr($_, length($profile));
#проверим имя файла фрофиля перед переносом в систему
$allocation = check_name($allocation); if(!$allocation){next;}
#скопируем ссылку
if(-e $allocation){`$data{path} rm $allocation`}
if($dest=~m/^[\/]/){
#правило 1:
#абсолютную ссылку перенесем как есть
system "$data{path} cp -a \"$_\" \"$allocation\"";
}elsif($dest=~m/^[\~]/){
#правило 2:
#вырежем ~ из имени ссылки и создадим относительную ссылку
#получится относительная ссылка, которая не будет преобразована в абсолютную
system "$data{path} ln -sf \"".substr($dest,1)."\" \"$allocation\"";
}else{
#правило 3:
#относительную ссылку преобразуем в абсолютную
#мы ее указываем чтобы избежать проверки абсолютного пути
system "$data{path} ln -sf \"/$dest\" \"$allocation\"";
}
}
if(!$data{file}{error}){
printmes(" ".gettext('done').".\n");
}else{
printmes("\n");
$data{file}{error} = '';
}
if($tmpdir){
system "$data{path} rm -rf '$data{tmpdir}'";
}
}
#------------------------------------------------------------------------------
#
# Проверим на доступное обновление на сайте проекта
#
#------------------------------------------------------------------------------
sub checkupdate{
printmes(gettext('To upgrade Calculate Overlay launch `layman -S`')); printmes(".\n");
}
#------------------------------------------------------------------------------
#
# Подготовим систему к сборке
#
#------------------------------------------------------------------------------
sub configure{
#printmes(gettext('Perform checkouts')); printmes("\n");
#printmes(" ".gettext('New release number')); printmes("...");
$data{laymandir} = "/var/lib/layman";
if(!-e $data{laymandir}){$data{laymandir} = "/usr/local/portage/layman";}
#если система собирается не из CLS
if($data{stage} !~m/iso$/){
#-------------------------------------
# выполним настройки в текущей системе
#-------------------------------------
printmes(" ".gettext('Load')); printmes(" calculate overlay...");
if(!`layman -l | grep calculate`){
system "layman -S &>/dev/null";
system "layman -a calculate &>/dev/null";
}else{
system "layman -S &>/dev/null";
}
printmes(" ".gettext('done').".\n");
#Скопируем calculate overlay
printmes(" ".gettext('Transfer calculate overlay to system')); printmes("...");
if(system "
$data{path} mkdir -p $data{chroot}/var/lib/layman &&
$data{path} cp -a $data{laymandir}/calculate $data{chroot}/var/lib/layman &&
$data{path} cp $data{laymandir}/overlays.xml $data{chroot}/var/lib/layman
"){
printmes(" ".gettext('error')."!\n");
umountbuild(); return '';
}
printmes(" ".gettext('done').".\n");
}
#Подмонтируем /proc
printmes(" ".gettext('Mount')); printmes(" /proc...");
if(system "$data{path} mount -t proc none $data{chroot}/proc &>/dev/null"){
printmes(" ".gettext('error')."!\n");
umountbuild(); return '';
}
printmes(" ".gettext('done').".\n");
#Подмонтируем /dev/shm
printmes(" ".gettext('Mount')); printmes(" /dev/shm...");
if(system "$data{path} mount -o bind /dev/shm $data{chroot}/dev/shm &>/dev/null"){
printmes(" ".gettext('error')."!\n");
umountbuild(); return '';
}
printmes(" ".gettext('done').".\n");
#Подмонтируем /dev/pts
printmes(" ".gettext('Mount')); printmes(" /dev/pts...");
if(system "$data{path} mount -o bind /dev/pts $data{chroot}/dev/pts &>/dev/null"){
printmes(" ".gettext('error')."!\n");
umountbuild(); return '';
}
printmes(" ".gettext('done').".\n");
#Наложим профили на распакованный образ
profiles();
#Установим ссылку на профиль
my $mask = substr($data{unmask}, 1);
my $developer; if($data{linuxver} =~/[0-9]+\.[0-9]+\.[0-9]+/){$developer = "/developer"}
system "$data{path} cd $data{chroot}/etc; rm make.profile; ln -sf ../var/lib/layman/calculate/profiles/calculate/$data{system}/$data{calculate}/$mask$developer make.profile";
#Подмонтируем /var/calculate/remote
printmes(" ".gettext('Mount')); printmes(" /var/calculate/remote...");
if(system "$data{path} mount -o bind /var/calculate/remote $data{chroot}/var/calculate/remote &>/dev/null"){
printmes(" ".gettext('error')."!\n");
umountbuild(); return '';
}
printmes(" ".gettext('done').".\n");
#Перенесем в calculate.ini некоторые переменные
putini("linuxver" => $data{"linuxver"}, "chroot");
putini("calculate" => $data{"calculate"}, "chroot");
putini("system" => $data{"system"}, "chroot");
#Скопируем /etc/resolv.conf
printmes(" ".gettext('Copy')); printmes(" /etc/resolv.conf...");
if(system "$data{path} cp /etc/resolv.conf $data{chroot}/etc/ &>/dev/null"){
beep();
printmes(" ".gettext('error')."!\n");
}else{
printmes(" ".gettext('done').".\n");
}
#Пропатчим /etc/login.defs
printmes(" ".gettext('Put a patch')); printmes(" /etc/login.defs...");
system "$data{path} cp $data{chroot}/etc/login.defs $data{chroot}/etc/login.defs.old";
if(system "$data{path} sed -i -r 's/^GID_MIN.*/GID_MIN\t\t\t 100/' $data{chroot}/etc/login.defs &&
$data{path} sed -i -r 's/^UID_MIN.*/UID_MIN\t\t\t 100/' $data{chroot}/etc/login.defs"
){
beep();
printmes(" ".gettext('error')."!\n");
}else{
printmes(" ".gettext('done').".\n");
}
#chroot layman -S
if($data{stage} =~m/iso$/){
printmes(" ".gettext('Perform calculate overlay update')); printmes("...");
if(system "$data{path} chroot $data{chroot} layman -S &>/dev/null"){
beep();
printmes(" ".gettext('error')."!\n");
}else{
printmes(" ".gettext('done').".\n");
}
}
# #Скопируем /etc/portage/bashrc
# printmes(" ".gettext('Copy')); printmes(" /etc/portage/bashrc...");
# if(system "$data{path} cp -H --remove-destination /etc/portage/bashrc $data{chroot}/etc/portage/bashrc"
# ){
# beep();
# printmes(" ".gettext('error')."!\n");
# }else{
# printmes(" ".gettext('done').".\n");
# }
#chroot emerge --sync
printmes(" ".gettext('Perform portages update')); printmes("...");
if(system "$data{emergerun1} --sync $data{emergerun2} &>/dev/null"){
beep();
printmes(" ".gettext('error')."!\n");
}else{
printmes(" ".gettext('done').".\n");
}
#chroot emerge sys-apps/portage
printmes(" ".gettext('Execute')); printmes(" emerge sys-apps/portage...");
if(system "$data{emergerun1} sys-apps/portage $data{emergerun2} &>/dev/null"){
printmes(" ".gettext('error')."!\n"); umountbuild();
return '';
}else{
printmes(" ".gettext('done').".\n");
}
#chroot emerge sys-kernel/calculate-sources если система собирается не из CLS
if($data{stage} !~m/iso$/){
printmes(" ".gettext('Install the kernel sources')); printmes("...");
if(system "USE=\"-vmlinuz\" $data{emergerun1} sys-kernel/calculate-sources $data{emergerun2} &>/dev/null"){
printmes(" ".gettext('error')."!\n");
umountbuild(); return '';
}else{
printmes(" ".gettext('done').".\n");
} }
#если система собирается не из CLS
if($data{stage} !~m/iso$/){
#chroot emerge sys-apps/v86d
printmes(" ".gettext('Execute')); printmes(" emerge sys-apps/v86d...");
if(system "$data{emergerun1} sys-apps/v86d $data{emergerun2} &>/dev/null"){
printmes(" ".gettext('error')."!\n");
umountbuild(); return '';
}else{
printmes(" ".gettext('done').".\n");
}
#chroot emerge sys-apps/openrc
printmes(" ".gettext('Execute')); printmes(" emerge sys-apps/openrc...");
system "CLEAN_DELAY=0 $data{emergerun1} -C --backtrack=0 sys-apps/baselayout sys-apps/sysvinit $data{emergerun2} &>/dev/null";
system "$data{path} rm $data{chroot}/etc/init.d/depscan.sh $data{chroot}/etc/init.d/functions.sh $data{chroot}/etc/init.d/runscript.sh";
if(system "$data{emergerun1} sys-apps/openrc sys-apps/sysvinit sys-fs/udev sys-fs/e2fsprogs $data{emergerun2} &>/dev/null"){
printmes(" ".gettext('error')."!\n");
umountbuild();
return '';
}else{
system "$data{path} rm -f $data{chroot}/etc/runlevels/boot/network";
printmes(" ".gettext('done').".\n");
}
#chroot emerge sys-apps/man-db
printmes(" ".gettext('Execute')); printmes(" emerge sys-apps/man-db...");
system "CLEAN_DELAY=0 $data{emergerun1} -C --backtrack=0 sys-apps/man $data{emergerun2} &>/dev/null";
if(system "$data{emergerun1} sys-apps/man-db $data{emergerun2} &>/dev/null"){
printmes(" ".gettext('error')."!\n");
umountbuild();
return '';
}else{
printmes(" ".gettext('done').".\n");
}
}
#удалим ссылку net.eth0, т.к. во всех десктопах, кроме CLS будет использоваться networkmanager
if($data{calculate} ne "CDS" && $data{calculate} ne "CSS" && $data{calculate} ne "CLS"){
system "$data{path} rm -f $data{chroot}/etc/init.d/net.eth0";
}
#если система собирается не из CLS
if($data{stage} !~m/iso$/){
if($data{system} eq 'desktop'){
#chroot groupadd games
printmes(" ".gettext('Execute')); printmes(" groupadd -g 35 games...");
if(system "$data{path} chroot $data{chroot} /usr/sbin/groupadd -g 35 games &>/dev/null"){
printmes(" ".gettext('error')."!\n");
umountbuild(); return '';
}else{
printmes(" ".gettext('done').".\n");
} }
#chroot groupadd plugdev
printmes(" ".gettext('Execute')); printmes(" groupadd -g 440 plugdev...");
if(system "$data{path} chroot $data{chroot} /usr/sbin/groupadd -g 440 plugdev &>/dev/null"){
printmes(" ".gettext('error')."!\n");
umountbuild(); return '';
}else{
printmes(" ".gettext('done').".\n");
}
#chroot groupadd scanner
printmes(" ".gettext('Execute')); printmes(" groupadd -g 441 scanner...");
if(system "$data{path} chroot $data{chroot} /usr/sbin/groupadd -g 441 scanner &>/dev/null"){
printmes(" ".gettext('error')."!\n");
umountbuild(); return '';
}else{
printmes(" ".gettext('done').".\n");
}
}
#chroot useradd p2p
if($data{calculate} eq "CDS"){
printmes(" ".gettext('Execute')); printmes(" useradd -g 100 p2p...");
if(system "$data{path} chroot $data{chroot} /usr/sbin/useradd -u 101 -g 100 -G wheel -c \"added by Calculate for p2p\" -s /sbin/bash p2p &>/dev/null"){
printmes(" ".gettext('error')."!\n");
umountbuild(); return '';
}else{
printmes(" ".gettext('done').".\n");
system "$data{path} chroot $data{chroot} /bin/mkdir -m 0700 /home/p2p";
system "$data{path} chroot $data{chroot} /bin/chown p2p:root /home/p2p";
} }
beep();
printmes(gettext('All done')); printmes("! ");
printmes(gettext('Ready for packages installation')); printmes(".\n");
return 1;
}
#------------------------------------------------------------------------------
#
# Отмонтируем диски в случае прерывания сборки
#
#------------------------------------------------------------------------------
sub umountbuild{
printmes(gettext('Operation interrupted')); printmes(".\n");
printmes(gettext('Abort')); printmes("...\n");
beep();
#отмонтируем все директории и точку монтирования
umount_build_all();
}
#------------------------------------------------------------------------------
#
# Покажем список пакетов для установки
#
#------------------------------------------------------------------------------
sub list{
printmes(gettext('Package list incoming in distributive file')); printmes("...\n");
#отобразим на экране список пакетов
my $i = 0;
foreach(packages()){
printmes("$_\n");
$i++;
}
printmes("\n");
printmes(gettext('All')); printmes(" $i "); printmes(gettext('packages'));
printmes(".\n");
return 1;
}
#------------------------------------------------------------------------------
#
# Вернем список пакетов для сборки
# либо пакетов дополнений
#
#------------------------------------------------------------------------------
sub packages{
#отработаем случай размаскировки в текущей системе --unmask
if(defined $data{arg}{'unmask'}){
return split ' ', $data{arg}{'unmask'};
}
#определим директории для нашей конфигурации файлов со списком пакетов
my @dir;
if(!defined $data{addition} && !@{$data{packageslist}}){
foreach(@{$data{packages}}){
if(-e $_){
my $path_packages = $_;
opendir(DIR, $path_packages);
foreach(readdir DIR){
if($_ eq "." || $_ eq ".."){next;}
if(check_name($_)){push(@dir, "$path_packages/$_");}
}
closedir DIR;
if(!$chkdir){push(@dir, "$path_packages");}
} }
}elsif(@{$data{packageslist}}){
return @{$data{packageslist}};
}else{
#----------------------------------------------------------------------
# Пути к директориям пакетов дополнений
# @{$data{packages})
#----------------------------------------------------------------------
@{$data{packages}} = (
"$data{dir}/install/builder/addition/$data{calculate}",
"/usr/calculate/share/builder/addition/$data{calculate}",
);
foreach(@{$data{packages}}){
if(-e "$_/$data{addition}"){
push(@dir, "$_/$data{addition}");
} } }
#считаем список файлов пакетов
my @files = ();
foreach(@dir){
my $path = "$_";
opendir(DIR, $path);
foreach(readdir DIR){
if($_ eq "." || $_ eq ".."){next;}
push (@files, "$path/$_");
}
closedir DIR;
}
#извлечем имена пакетов из файлов
my %pack = ();
foreach(@files){
$data{file}{name} = $_;
open(R, $data{file}{name});
my @lines = <R>;
close(R);
foreach(convert(lines => [@lines], nocomment => yes)){
chomp $_;
$pack{$_}++;
}
}
#соберем список пакетов в массив
my @packages;
foreach(sort keys %pack){
push (@packages, $_);
}
# print ">@packages<";
return @packages;
}
#------------------------------------------------------------------------------
#
# Проверка зависимостей устанавливаемых пакетов
#
#------------------------------------------------------------------------------
sub dependence{
my $hide = $_[0]; #скрыть вывод списка пакетов после проверки
printmes(gettext('Check of dependences')); printmes("...\n");
my ($pack, $mask);
while (($pack, $mask) = emerge_pretend()){
if($mask eq 'keywords'){
$pack = lastver($pack); #получим последнюю доступную версию пакета
printmes(" ".gettext('Add')); printmes(" \"$pack $data{unmask}\" >> package.keywords/dependence\n");
my $keywords = "$data{'chroot'}/etc/portage/package.keywords/dependence";
if(!-e $keywords){system "echo '$data{mesline}\n$data{mestitle}\n$data{mesline}' >> $keywords";}
system "echo '$pack $data{unmask}' >> $keywords";
}elsif($mask eq 'unmask'){
printmes(" ".gettext('Add')); printmes(" \"$pack\" >> package.unmask/dependence\n");
my $unmask = "$data{'chroot'}/etc/portage/package.unmask/dependence";
if(!-e $unmask){system "echo '$data{mesline}\n$data{mestitle}\n$data{mesline}' >> $unmask";}
system "echo $pack >> $unmask";
}elsif($mask eq 'reverse'){
next; #пропустим звуковое предупреждение
}else{
last;
}
beep();
}
if($pack){
printmes("\n".gettext('All done')); printmes("!\n");
}
if(!$hide){
my @packages = packages();
if(!defined $data{arg}{'unmask'}){
system "$data{emergerun1} -pqvtuD @packages $data{emergerun2}";
}else{
system "$data{emergerun1} -p @packages $data{emergerun2}";
} }
if($pack){
return 1;
}else{
return '';
}
}
#------------------------------------------------------------------------------
# По полному имени пакета вернем последнюю доступную версию - имя плюс версия
#------------------------------------------------------------------------------
sub lastver{
my $pack = $_[0]; #имя пакета
my ($tmp,$name) = split "/", $pack; #имя без категории
my $overlays = `emerge --info | grep PORTDIR_OVERLAY`;
$overlays =~s/PORTDIR_OVERLAY="(.*)"/$1/; chomp $overlays;
my @overlays;
foreach(split / /, $overlays){
push @overlays, $data{'chroot'}."$_/$pack";
}
push @overlays, "$data{'chroot'}/usr/portage/$pack";
#получим список доступных пакетов с полными путями
my @lastver;
foreach(@overlays){
if(-e $_){
push (@lastver, `ls -la $_/*ebuild`);
} }
#определим максимальную версию из доступных пакета
my $ver;
my $last; #последняя доступная версия
foreach(@lastver){
$ver = $_;
my $p = $pack; $p=~s/\+/\\+/g;
my $n = $name; $n=~s/\+/\\+/g;
$ver=~s/.+$p\/$n\-(.+)\.ebuild$/$1/; #замаскируем + для регулярного выражения
chomp $ver;
if(!$last){$last = $ver; next;}
#сравним версию
my @ver = split /\./, $ver;
my @last = split /\./, $last;
for(my $i = 0; $i < @ver; $i ++){
#выполним дальнейшие преобразования операндов перед сравнением
my $v = $ver[$i];
my $l = $last[$i];
#числа сравниваем как строки, поддерживая сравнение 9-r1 и 16
if($v=~/^\d+.*/ || $l=~/^\d+.*/){
if($v=~/^(\d+)(.*)$/){$v = sprintf("%05d", $1). "$2";}
if($l=~/^(\d+)(.*)$/){$l = sprintf("%05d", $1). "$2";}
#снизим приоритет беты, если вторая версия имеет тот же номер
if($v=~/^\d+$/ || $l=~/^\d+$/){
my $v_b = $v; my $l_b = $l;
$v_b=~s/^(\d+).*/$1/; $l_b=~s/^(\d+).*/$1/;
if($v_b eq $l_b){
if($v_b ne $v && $v!~/^\d+\-r[0-9]+$/){$v = 0;}
elsif($l_b ne $l && $l!~/^\d+\-r[0-9]+$/){$l = 0;}
elsif(!defined $ver[$i+1] && defined $last[$i+1]){$v = 0;}
elsif(!defined $ver[$i+1] && defined $last[$i+1]){$l = 0;}
} } }
if($v gt $l && $v!~m/999/){
$last = $ver; last;
}elsif($l gt $v){last;}
}
}
return "<=$pack-$last";
}
#------------------------------------------------------------------------------
#
# Проверим на возможность установки пакетов
#
#------------------------------------------------------------------------------
sub emerge_pretend{
my @packages = packages();
my $err;
@packages = (@{$data{movie_pretend}}, @packages); #объединим со списком зависимых пакетов (дублируя расположим их сверху)
my $softly; if(!defined $data{addition} && !defined $data{arg}{'unmask'}){$softly = "--softly";}
my @check;
push @check, `$data{emergerun1} -p --color n @packages $data{emergerun2} $softly 2>&1`;
if(!defined $data{arg}{'unmask'}){
#вторая проверка на случай сборки на базе CLS
push @check, `$data{emergerun1} -p --color n -uD world $data{emergerun2} $softly 2>&1`;
}
foreach(@check){
if(m/Error: The above package list contains packages which cannot be/ ||
m/resulting in a slot conflict:/
){
$err++; last;
}elsif(m/^- ([^ ]+)-[0-9\._pba-c]+(_pre[0-9]+)?(_rc[0-9]{1,2})?(-r[0-9]{1,2})?(_beta[0-9]{1,2})? .+masked by: package.mask/){
return $1, 'unmask';
}elsif(m/^- ([^ ]+)-[0-9\._pba-c]+(_pre[0-9]+)?(_rc[0-9]{1,2})?(-r[0-9]{1,2})?(_beta[0-9]{1,2})? .+masked by: $data{unmask} keyword/){
return $1, 'keywords';
}elsif(m/'([^ ]+)-[0-9\._pba-c]+(_pre[0-9]+)?(_rc[0-9]{1,2})?(-r[0-9]{1,2})?(_beta[0-9]{1,2})?'.+ pulled in by/
&& !m/kde-base\/kdelibs-3.5/){
my $movie; #отметим зависимый пакет, который должен располагаться сверху списка, чтобы избежать ошибки
foreach(@packages){
if(m/$1/){
push (@{$data{movie_pretend}}, $_);
} }
return $1, 'reverse';
}elsif($_=~m/!{3}/){
$err++;
}
}
if($err){
printmes("\n".gettext('One of the packages not match your architecture'));
printmes(".\n"); printmes(gettext('Please revise dependences of the packages by your own  using flags concealment of packages'));
printmes(".\n");
return '';
}
return 1;
}
#------------------------------------------------------------------------------
#
# Соберем систему
#
#------------------------------------------------------------------------------
sub make{
printmes(gettext('Make system')."\n");
my $skipfirst; if($data{skipfirst} eq "on"){$skipfirst = " --skipfirst";}
#закончим прерванное действие
if(getini("run.make", "chroot")){
printmes(" ".gettext('Execute')); printmes(" emerge --resume".$skipfirst."...\n");
if(system "$data{emergerun1}$skipfirst --resume $data{emergerun2}"){
beep();
printmes(" ".gettext('error')."!\n"); return '';
}else{
printmes(" ".gettext('done').".\n");
getini("run.make", "chroot")
}
my $finish = getini("run.make", "chroot"); #считаем действие
putini("run.make" => "", "chroot"); #сбросим успешную операцию
#увеличим счётчик
my $step = getini("run.make.step.$finish", "chroot"); $step++;
putini("run.make.step.$finish" => $step, "chroot");
}
#отобразим выполненные действия
if(getini("run.make.step.system", "chroot")){
foreach(my $i = 0; $i < getini("run.make.step.system", "chroot"); $i ++){
printmes(" ".gettext('Execute')); printmes(" emerge -e system...");
printmes(" ".gettext('done')); printmes(".\n");
} }
if(getini("run.make.step.newuse", "chroot")){
printmes(" ".gettext('Execute')); printmes(" emerge --newuse -D world...");
printmes(" ".gettext('done')); printmes(".\n");
}
if(getini("run.make.step.update", "chroot")){
printmes(" ".gettext('Execute')); printmes(" emerge -upD world...");
printmes(" ".gettext('done')); printmes(".\n");
}
#получим список пакетов world = ""
my @world = packages();
my $finish = '';
while(!$finish){
if($data{stage} !~m/iso$/ && getini("run.make.step.system", "chroot") < 2){
printmes(" ".gettext('Execute')); printmes(" emerge -e system...\n");
putini("run.make" => "system", "chroot"); #сохраним выполняемое действие
if(system "$data{emergerun1} -e system $data{emergerun2} --nodie"){
beep();
printmes(" ".gettext('error')."!\n"); return '';
}else{
#сбросим успешно выполненную операцию
putini("run.make" => "", "chroot");
#увеличим счетчик проходов
my $step = getini("run.make.step.system", "chroot"); $step ++;
putini("run.make.step.system" => $step, "chroot");
printmes(" ".gettext('done').".\n");
}
}elsif($data{stage} =~m/iso$/ && !getini("run.make.step.newuse", "chroot")){
printmes(" ".gettext('Execute')); printmes(" emerge --newuse -D world...\n");
if(system "$data{emergerun1} --newuse -D world $data{emergerun2} --nodie"){
beep(); printmes(" ".gettext('error')."!\n"); return '';
}else{
#отметим успешное выполнение
putini("run.make.step.newuse" => 1, "chroot");
printmes(" ".gettext('done').".\n");
}
}elsif($data{stage} =~m/iso$/ && !getini("run.make.step.update", "chroot")){
printmes(" ".gettext('Execute')); printmes(" emerge -uD world...\n");
if(system "$data{emergerun1} -uD world $data{emergerun2} --nodie"){
beep(); printmes(" ".gettext('error')."!\n"); return '';
}else{
#отметим успешное выполнение
putini("run.make.step.update" => 1, "chroot");
printmes(" ".gettext('done').".\n");
}
}else{
printmes(" ".gettext('Execute')); printmes(" emerge --noreplace world...\n");
if(system "$data{emergerun1} --noreplace @world $data{emergerun2} --nodie"){
beep();
printmes(" ".gettext('error')."!\n"); return '';
}else{
printmes(" ".gettext('done').".\n");
#The end check USE flags
printmes(" ".gettext('Execute')); printmes(" emerge --newuse -D world...\n");
if(system "$data{emergerun1} --newuse -D world $data{emergerun2} --nodie"){
beep(); printmes(" ".gettext('error')."!\n"); return '';
}else{
printmes(" ".gettext('done').".\n");
}
#сбросим успешно выполненную операцию
putini("run.make" => "", "chroot");
#увеличим счетчик проходов
my $step = getini("run.make.step.world", "chroot"); $step ++;
putini("run.make.step.world" => $step, "chroot");
}
$finish ++;
}
}
return 1;
}
#------------------------------------------------------------------------------
#
# Упакуем систему
#
#------------------------------------------------------------------------------
sub packsystem{
printmes(gettext('Packing the distribution package into the archive file').".\n");
#Вернем /etc/login.defs в прежнее состояние
if(-e "$data{chroot}/etc/login.defs.old"){
printmes(" ".gettext('Restore')); printmes(" /etc/login.defs...");
system "$data{path} mv $data{chroot}/etc/login.defs.old $data{chroot}/etc/login.defs";
printmes(" ".gettext('done').".\n");
}
#Установим пароль рута
system "$data{path} chroot $data{'chroot'} sed -i -r 's/^root:.*/$data{hash_root}/' /etc/shadow";
system "$data{path} chroot $data{'chroot'} sed -i -r 's/^root:.*/$data{hash_root}/' /etc/shadow-";
#Добавим пользователя guest для десктопа
# if($data{system} eq 'desktop' && $data{calculate} ne 'CLS' && !$data{createiso}){
# #Добавим пользователя guest
# system "$data{path} chroot $data{'chroot'} groupadd --gid 1000 guest";
# system "$data{path} chroot $data{'chroot'} useradd --uid 1000 --gid 1000 --shell /bin/bash --groups audio,cdrom,plugdev,video,wheel,users guest";
#system "$data{path} chroot $data{'chroot'} mkdir -m 0700 /home/guest && chown guest. /home/guest";
# #Установим пароль пользователя guest
# system "$data{path} chroot $data{'chroot'} sed -i -r 's/^guest:.*/$data{hash_guest}/' /etc/shadow";
# system "$data{path} chroot $data{'chroot'} sed -i -r 's/^guest:.*/$data{hash_guest}/' /etc/shadow-";
# }
#Удалим записи сборки
putini("run.make" => "", "chroot");
putini("run.make.step.system" => "", "chroot");
putini("run.make.step.world" => "", "chroot");
putini("run.make.step.newuse" => "", "chroot");
putini("run.make.step.update" => "", "chroot");
#Заменим устаревшие конфигурационные файлы
printmes(" ".gettext('Replace outdated configuration files')); printmes("...\n");
if(system(qq|$data{path} chroot $data{'chroot'} /bin/bash -c "OVERWRITE_ALL='yes' etc-update"|)){
printmes(" ".gettext('error').".\n");
return "";
}else{
printmes(" ".gettext('done')); printmes(".\n");
}
#Обновим базу портежей программы eix
if(-e "$data{'chroot'}/usr/bin/eix-update"){
printmes(" ".gettext('Update portige base of eix programm')); printmes("...");
if(system(qq|$data{path} chroot $data{'chroot'} /bin/bash -c "eix-update &>/dev/null"|)){
printmes(" ".gettext('error').".\n");
}else{
printmes(" ".gettext('done')); printmes(".\n");
} }
#Обновим базу PCI-устройств
if(-e "$data{'chroot'}/usr/sbin/update-pciids"){
printmes(" ".gettext('Update PCI IDs')); printmes("...");
if(system("$data{path} chroot $data{'chroot'} update-pciids &>/dev/null")){
printmes(" ".gettext('error').".\n");
}else{
printmes(" ".gettext('done')); printmes(".\n");
} }
#Обновим базу USB-устройств
if(-e "$data{'chroot'}/usr/sbin/update-usbids"){
printmes(" ".gettext('Update USB IDs')); printmes("...");
if(system("$data{path} chroot $data{'chroot'} update-usbids &>/dev/null")){
printmes(" ".gettext('error').".\n");
}else{
printmes(" ".gettext('done')); printmes(".\n");
} }
#Обновим антивирусную базу Clamav
if(-e "$data{'chroot'}/usr/bin/freshclam"){
printmes(" ".gettext('Update Clamav antivirus database')); printmes("...");
if(system("$data{path} chroot $data{'chroot'} freshclam &>/dev/null")){
printmes(" ".gettext('error').".\n");
}else{
printmes(" ".gettext('done')); printmes(".\n");
} }
#Сформируем базу module-rebuild
if(-e "$data{'chroot'}/usr/sbin/module-rebuild populate"){
printmes(" ".gettext('Update module-rebuild database')); printmes("...");
if(system("$data{path} chroot $data{'chroot'} module-rebuild populate &>/dev/null")){
printmes(" ".gettext('error').".\n");
return "";
}else{
printmes(" ".gettext('done')); printmes(".\n");
} }
#Выполним предварительное связывание пакетов
if(-e "$data{'chroot'}/usr/sbin/prelink" && -e "$data{'chroot'}/etc/prelink.conf"){
printmes(" ".gettext('Execute prelinking packages')); printmes("...");
if(system("$data{path} chroot $data{'chroot'} prelink -afmR &>/dev/null")){
printmes(" ".gettext('error').".\n");
return "";
}else{
printmes(" ".gettext('done')); printmes(".\n");
} }
#наложим профиль IMG
profiles();
#Отмонтируем директории в точке монтирования
printmes(" ".gettext('Umount directories')); printmes("...");
if(!umount_build_dirs()){
printmes(" ".gettext('error').".\n");
return "";
}else{
printmes(" ".gettext('done')); printmes(".\n");
}
#Удалим временные файлы
clearlog($data{chroot});
#Создадим архив системы
printmes(" ".gettext('Create system archive file')); printmes("...");
chdir($data{'chroot'});
my $pathtar = "$data{linuxdir}/".lc($data{'calculate'})."-$data{linuxver}-$data{march}.tar.7z";
system "$data{path} rm -f $pathtar"; #удалим если такой файл есть
if(system("$data{path} tar cf - . 2>/dev/null | 7za a -si $pathtar >/dev/null")){
printmes(" ".gettext('error').".\n");
return "";
}else{
system("$data{path} chmod 644 $data{linuxdir}/".lc($data{'calculate'})."-$data{linuxver}-$data{march}.tar.7z");
printmes(" ".gettext('done')); printmes(".\n");
}
chdir($ENV{PWD});
#Создадим list-файл со списком собранных пакетов
printmes(" ".gettext('Create')); printmes(" LIST "); printmes(gettext('file')); printmes("...");
my $path = "$data{'chroot'}/var/db/pkg";
my $list = "$data{linuxdir}/".
lc($data{'calculate'})."-$data{linuxver}-$data{march}.list";
open LIST, ">$list";
opendir(T, $path);
foreach(sort readdir T){
if($_ eq "." || $_ eq ".."){next;}
my $type = $_;
opendir(F, "$path/$type");
foreach(sort readdir F){
if($_ eq "." || $_ eq ".."){next;}
print LIST "$type/$_\n";
}
closedir F;
}
closedir T;
close LIST;
#упакуем в list.gz
# system "$data{path} gzip $list";
printmes(" ".gettext('done')); printmes(".\n");
#Создадим DIGESTS-файл
printmes(" ".gettext('Create')); printmes(" DIGESTS "); printmes(gettext('file')); printmes("...");
if(create_digests(
"$data{linuxdir}/".lc($data{'calculate'}).
"-$data{linuxver}-$data{march}.tar.7z"
)){
printmes(" ".gettext('done')); printmes(".\n");
}else{
printmes(" ".gettext('error').".\n");
}
#Отмонтируем chroot-диск
printmes(" ".gettext('Umount chroot-disk')); printmes("...");
if(system("$data{path} umount $data{'chroot'}")){
printmes(" ".gettext('error').".\n");
# return "";
}else{
system("rmdir $data{'chroot'}");
printmes(" ".gettext('done')); printmes(".\n");
}
printmes(gettext('All done')); printmes("!\n");
return 1;
}
#------------------------------------------------------------------------------
# Создадим DIGESTS-файл
#------------------------------------------------------------------------------
sub create_digests{
my $file = $_[0];
my $name = $file; $name=~s/.*\/([^\/]+)$/$1/;
my $digests = "$file.DIGESTS";
my $hash = get_hash("openssl md5 $file");
`echo "# MD5 HASH" > $digests`;
`echo "$hash $name" >> $digests`;
$hash = get_hash("openssl sha1 $file");
`echo "# SHA1 HASH" >> $digests`;
`echo "$hash $name" >> $digests`;
return 1;
}
#------------------------------------------------------------------------------
# Получим хэш из openssl
#------------------------------------------------------------------------------
sub get_hash{
my $exec = $_[0];
my $hash = `$exec`;
$hash =~m/= ([0-9a-f]+)$/;
return $1;
}
#------------------------------------------------------------------------------
#
# Удалим все файлы из указанной директории кроме .keep
#
#------------------------------------------------------------------------------
sub cleardir{
my $dir = $_[0];
opendir(DEL, $_);
foreach(readdir DEL){
if($_ eq "." || $_ eq ".." || $_ eq ".keep"){next;}
#printmes(gettext('Delete')); printmes(" $dir/$_\n");
system("$data{path} rm -rf $dir/$_");
}
closedir DEL;
}
#------------------------------------------------------------------------------
#
# Наложим обновления профилей на текущую систему
#
#------------------------------------------------------------------------------
sub update_profile{
#проверим на наличие профили
foreach(split /,/, $data{arg}{'profile'}){
my $path, $profile;
if(m/^([^\/]+)\/([^\/]+)$/){
$path = $1; $profile = $2;
}else{
$profile = $_;
}
if($profile=~m/[^0-9a-z\/_\-*]/i){
printmes(gettext('Error')."! ");
printmes(gettext('Invalid template')); printmes(" \"$_\".\n");
return ""
}
if(!$path && $_=~m/^all$/i){
@{$data{setprof}} = (@{$data{profile_install}}, @{$data{profile_share}});
next;
}elsif($profile eq "*" && ($path eq "install" || $path eq "share")){
@{$data{setprof}} = @{$data{"profile_$path"}};
next;
}elsif($path && -e "$data{dir}/$path/profile/$profile"){
push (@{$data{setprof}}, "$data{dir}/$path/profile/$profile");
}elsif(!$path && -e "$data{dir}/install/profile/$profile"){
push (@{$data{setprof}}, "$data{dir}/install/profile/$profile");
}elsif(!$path && -e "/usr/calculate/share/profile/$profile"){
push (@{$data{setprof}}, "/usr/calculate/share/profile/$profile");
}else{
printmes(gettext('Error')."! ");
printmes(gettext('Invalid template')); printmes(" \"$_\".\n");
return ""
}
}
if(!@{$data{setprof}}){
printmes(gettext('Error')."! ");
printmes(gettext('Configuration template is not specified')); printmes(".\n");
return ""
}
#наложим выбранные профили на текущую систему
$data{'chroot'} = "";
foreach(@{$data{setprof}}){profile($_);}
return 1;
}
#------------------------------------------------------------------------------
#
# Выполним строчные преобразования конфигурационных файлов
# Хэш параметров:
# lines - строки файла
# nocomment - удалять комментарии
#
#------------------------------------------------------------------------------
sub convert{
my %par = (
nocomment => '',
lines => '',
@_,
);
my @ext_comment;
#в метки подставим переменные
foreach(@{$par{lines}}){
my $i = 0;
while($i==0){
#в метки подставим переменные
if(m/#\-([^\$\@\-][^\#]+)\-#/i){
my $var = $1;
#обработаем динамические переменные -
#переменные, инициируемые при запросе
my ($dynamic, $set) = dynamicvar($var);
if($set){$data{$var} = $dynamic;}
if(!defined $data{$var}){
printmes("\n".gettext('Not defined variable')); printmes(" #-$var-#, file \"$data{file}{name}\".");
$data{file}{error} ++;
}
s/#\-$var\-#/$data{$var}/g;
}else{$i++}
}
push (@ext_comment, $_);
}
#обработаем блоки условий
my @ext_block;
my ($block, $pass);
foreach(@ext_comment){
if($par{nocomment} && $_!~/[A-Za-z0-9#]/){next;} #пропустим пустые строки
if($par{nocomment}){
$_=~s/^\s+(.)/$1/; #обрежем отступы от начала строки
}
#пропустим пакеты привязанные к архитектуре
my ($block2, $pass2) = check_block($_);
if($block2){
$block = $block2;
$pass = $pass2;
next;
}
#проверим на конец блока
if($block && $_=~/^\s*#$block#\s*$/){$block = ''; next;}
#пропустим если блок не соответствует условию
if($block && $pass){next;}
if($par{nocomment} && $_=~/^#/){next;} #пропустим строки с комментариями
if($par{nocomment}){
$_=~s/^\s*([^#]+)#.*/$1/; #обрежем комментарии пакетов
$_=~s/^(.*)([^\s]+)\s+$/$1$2/; #обрежем пробелы перед комментариями пакетов
}
push(@ext_block, $_);
}
return @ext_block; #вернем построчно
}
#------------------------------------------------------------------------------
# Сформируем динамические переменные - переменные, инициируемые при запросе
#------------------------------------------------------------------------------
sub dynamicvar{
my $var = $_[0];
my $val = "";
my $set = "";
#список пакетов подлежащих размаскировке по заданной маске
if($var=~m/^keywords:(.+)$/){
my $keywords = $1; $keywords =~s/A-Za-z0-9\-\.\_//m;
foreach(packages()){
if(m/$keywords/){
$val.=lastver($_)." $data{unmask}\n";
}
}
#список установленных пакетов: `$data{path} find /var/db/pkg/ -type f | sed 's/-[0-9][0-9]*.*//' | uniq | sort`
$set ++;
}elsif($var=~m/^unmask:(.+)$/){
my $unmask = $1; $unmask =~s/A-Za-z0-9\-\.\_//m;
foreach(packages()){
if(m/$unmask/){
$val.="$_\n";
}
}
$set ++;
}
return ($val, $set);
}
#------------------------------------------------------------------------------
#
# Выполним сравнение имени файла с условием
# Возвратим преобразованное имя файла без условия если принимается, либо ничего
#
#------------------------------------------------------------------------------
sub check_name{
my $filename = $_[0];
#проверим наличие регулярного выражения в файле
if($filename=~m/^([^\?]+)\?(.+)/){
my $realname = $1;
my $condition = $2;
#проверим условия
#разобьем условия ИЛИ
foreach(split /\?/, $condition){
my $true = 1;
#проверим условия И
foreach(split /&/){
#считаем сравниваемые значения
if(m/([^=><!]+)([=><!]+)([^=><!]+)?/){
if(!check_var($1,$3,$2)){$true = 0; break;}
}
}
if($true){
return $realname; #вернем файл соответствующий условиям
}
}
return "";
}else{
return $filename; #вернем файл без условий
} }
#------------------------------------------------------------------------------
#
# Выполним сравнение условного оператора в тексте
# Возвратим завершение блока условия и флаг проверки
#
#------------------------------------------------------------------------------
sub check_block{
my $block = $_[0];
#выделим регулярное выражения из блока условия
if($block=~m/^\s*#\?([^#]+)#\s*$/){
my $condition = $1;
my $endif = $1; #конец блока условия
$endif=~s/^([^\!\=\>\<]+).+/$1/;
#проверим условия
#разобьем условия ИЛИ
foreach(split /\?/, $condition){
my $true = 1;
#проверим условия И
foreach(split /&/){
m/([^=><!]+)([=><!]+)([^=><!]+)?/;
if(!check_var($1,$3,$2)){$true = 0; break;}
}
if($true){
return $endif, 0; #вернем конец блока условия и флаг совпадения
}
}
return $endif, 1; #вернем конец блока условия и флаг не совпадения
}
return '','';
}
#------------------------------------------------------------------------------
#
# Выполним сравнение
#
#------------------------------------------------------------------------------
sub check_var{
my ($a, $b, $chk) = @_;
$a = $data{$a}; #извлечем значение переменной
#определим тип сравниваемых значений
my $type;
if($a=~m/[^\.0-9]/ || $b=~m/[^\.0-9]/){
$type = "char";
}else{
#определим тип - номер версии
if(
$a=~/\..+\./ || $b=~/\..+\./ ||
$a=~/\.[0-9][0-9]$/ || $b=~/\.[0-9][0-9]$/
){
$type = "ver";
}else{
$type = "num";
} }
#проверим условие
if($chk eq "=" &&
$a eq $b
){}
#проверим условие
elsif($chk eq "!=" &&
$a ne $b
){}
elsif($chk eq "<" &&
(($type eq "num" && $a < $b) ||
($type eq "char" && $a lt $b) ||
($type eq "ver" && number_ver($a) < number_ver($b)))
){}
elsif($chk eq ">" &&
(($type eq "num" && $a > $b) ||
($type eq "char" && $a gt $b) ||
($type eq "ver" && number_ver($a) > number_ver($b)))
){}
elsif($chk eq "<=" &&
(($type eq "num" && $a <= $b) ||
($type eq "char" && $a le $b) ||
($type eq "ver" && number_ver($a) <= number_ver($b)))
){}
elsif($chk eq ">=" &&
(($type eq "num" && $a >= $b) ||
($type eq "char" && $a ge $b) ||
($type eq "ver" && number_ver($a) >= number_ver($b)))
){}
else{
return '';
}
return 1; #условие было распознано и определено как верное
}
#------------------------------------------------------------------------------
#
# Извлечем номер версии программы
# Необходимо для численного сравнения версий, типа 7.8.1
#
#------------------------------------------------------------------------------
sub number_ver{
my $num = $_[0];
$num=~m/([0-9]+)\.([0-9]+)\.?([0-9]+)?/;
return $1 * 10000 + $2 * 100 + $3;
}
#------------------------------------------------------------------------------
#
# Определим дополнительные монтируемые диски в fstab
#
#------------------------------------------------------------------------------
sub getdisk_fstab{
my (@mount_dev, @mount_dir, @mount_line);
foreach(@_){
if(m/^\s*#/){next;}
#определим устройства, сетевые диски и bind-монтирования
if(
m/^\s*(\/dev\/[^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([0-9])\s+([0-9])\s*$/ ||
m/^\s*([A-Za-z0-9\.]+:[^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([0-9])\s+([0-9])\s*$/ ||
m/^\s*(\/[^\s]+)\s+(\/[^\s]+)\s+([^\s]+)\s+(bind)\s+([0-9])\s+([0-9])\s*$/
){
#пропустим системный раздел и устанавливаемый раздел
if($1 eq "$data{rootload}"){next;}
if($1 eq "$data{rootinstall}"){next;}
if($1=~/:/ && $data{system} eq "desktop" && number_ver($data{linuxver}) > number_ver(9.5)){next;}
#поскольку система ставится на один диск, исключим точки монтирования системных директорий
if(
$2 eq "/bin" ||
$2 eq "/boot" ||
$2 eq "/dev" ||
$2 eq "/etc" ||
$2 eq "/lib" ||
$2 eq "/opt" ||
$2 eq "/sbin" ||
$2 eq "/usr" ||
$2 eq "/var"
){next;}
#пропустим своп-диск
if($3=~/swap/i){next;}
#пропустим loop-устройства
if($1=~m/^\/dev\/loop[0-9]$/i){next;}
push(@mount_dev, $1); #диски монтирования
push(@mount_dir, $2); #пути монтирования
push(@mount_line, $_); #fstab-строки
} }
return ([@mount_dev], [@mount_dir], [@mount_line]);
}
#------------------------------------------------------------------------------
#
# Дополним fstab настройками старого профиля
#
#------------------------------------------------------------------------------
sub move_fstab{
my @lines = @_;
my @newlines; #отличительные строки предыдущего fstab
my ($mount_dev, $mount_dir, $mount_line) = getdisk_fstab(@lines);
#заполним хэш для сравнения
my $i = 0;
my %check_disk; foreach(@{$mount_dev}){
$check_disk{"$_+${$mount_dir}[$i]"} = ${$mount_line}[$i];
$i++;
}
my $i = -1;
foreach(@{$data{mount_dev}}){
$i++;
if(!$check_disk{"$_+${$data{mountdir}}[$i]"}){
#если в старом профиле был примонтирован диск,
#перенесем запись и создадим директорию пути
push(@newlines, ${$data{mount_line}}[$i]);
#пропустим создание директории, если она находится
#внутри монтируемого диска
my $skip = 0; my $k;
foreach($k=0; $k<$i; $k++){
if(${$data{mountdir}}[$i]=~m/^${$data{mountdir}}[$k]/){
$skip++;
} }
#создадим директорию точки монтирования
if(!-e "$data{'chroot'}$data{scratch_ws}${$data{mountdir}}[$i]" && !$skip){
system "$data{path} mkdir -p -m 755 $data{'chroot'}$data{scratch_ws}${$data{mountdir}}[$i]";
} } }
return (@lines, @newlines);
}
#------------------------------------------------------------------------------
#
# Прерывание сборки системы - отмонтирование дисков и удаление
# установочной директории
#
#------------------------------------------------------------------------------
sub breakbuild{
printmes(gettext('Break the system building')); printmes("...");
#отмонтируем все директории и точку монтирования
umount_build_all();
printmes(" ".gettext('done').".\n");
return 1;
}
#------------------------------------------------------------------------------
#
# Отмонтируем все директории и точку монтирования
#
#------------------------------------------------------------------------------
sub umount_build_all{
#отмонтируем все директории в точке монтирования
umount_build_dirs();
#отмонтируем и удалим директорию точки монтирования
system "$data{path} umount -l $data{chroot}";
system "$data{path} rmdir $data{chroot}";
return 1;
}
#------------------------------------------------------------------------------
#
# Отмонтируем все директории в точке монтирования
#
#------------------------------------------------------------------------------
sub umount_build_dirs{
foreach(`$data{path} mount`){
if(/on\s+($data{chroot}\/[^\s]+)/){
#отмонтируем с флагом -l
system "$data{path} umount -l $1";
} }
return 1;
}
#------------------------------------------------------------------------------
#
# Создадим загружаемый iso-образ системы
#
#------------------------------------------------------------------------------
sub createiso{
#проверим что не запущен cl-builder
if(
#`mount | grep "on /mnt/builder/var/calculate/remote"
#|| `mount | grep -c "devpts on /dev/pts "` != 1
`ps ax | grep -c "cl-builder"` > 2
) {
printmes(gettext('Error')."! ");
printmes(gettext('Before proceeding, complete the program cl-builder')); printmes(".\n");
return "";
}
#проверим что система загружена в Scratch режиме и на флешке
if(defined $data{arg}{rebuild} &&
($data{scratch} ne "on" || $data{load} ne "ram" || !-e "/mnt/flash")){
printmes(gettext('Error')."! ");
printmes(gettext('The computer must be load from the flash in Scratch mode')); printmes(".\n");
return "";
}
#образ не найден, найден ISO образ системы, загрузились в обычном режиме либо в память с CD или Flash
if((!$data{linux} || $data{linux} =~m/iso$/ || $data{linux} eq 'livecd') && $data{scratch} eq "off"){
printmes(gettext('Error')."! ");
printmes(gettext('The archive with image of system is not found')); printmes(".\n");
return "";
}
#распакуем систему
if($data{scratch} eq "off"){
printmes(" ".gettext('Unpacking system')); printmes("...");
}else{
printmes(" ".gettext('Mount Scratch system')); printmes("...");
}
#создадим временную директорию
system "$data{path} mkdir -p '$data{tmpdir}'";
#выберем команду распаковки в зависимости от типа архива
my $unpack;
if($data{scratch} eq "on"){
$unpack = "mount -o bind /mnt/builder $data{tmpdir}/livecd/calculate";
}elsif($data{linux} =~m/7z$/){
$unpack = "7za x -so $data{linuxdir}/$data{linux} 2>/dev/null | tar xf - -C $data{tmpdir}/livecd/calculate";
}elsif($data{linux} =~m/lzma$/){
$unpack = "lzma -dc $data{linuxdir}/$data{linux} | tar -xf - -C $data{tmpdir}/livecd/calculate";
}else{
$unpack = "tar -xjf $data{linuxdir}/$data{linux} -C $data{tmpdir}/livecd/calculate";
}
if(system("mkdir -p $data{tmpdir}/livecd/calculate && $unpack")){
printmes(" ".gettext('error').".\n");
breakiso();
return "";
}else{
printmes(" ".gettext('done')); printmes(".\n");
}
#наложим профили на распакованную систему
profiles();
#выполним подмены
{
my $path = "$data{tmpdir}/livecd/calculate";
#поправим автовход в initrd
system "$data{path} sed -i -e '/^c[0-9]/ s/^/#/' $path/etc/inittab";
system "$data{path} sed -i -e '/^s[01]/ s/^/#/' $path/etc/inittab";
for(my $i = 1; $i<=6; $i++){
system qq|echo "c$i:12345:respawn:/sbin/agetty -nl /bin/bashlogin 38400 tty$i linux" >> $path/etc/inittab|;
}
}
#удалим следы пребывания в scratch
clearlog("$data{tmpdir}/livecd/calculate/");
#преобразуем в sys формат
isotosys();
#delete old squashfs
if(defined $data{arg}{rebuild} && $data{squash_del}){
printmes(" ".gettext('Removing old image of system')); printmes("...");
if(system("rm /mnt/flash/$data{squash_del}")){
printmes(" ".gettext('error').".\n");
breakiso();
return "";
}else{
printmes(" ".gettext('done')); printmes(".\n");
}
}
#создадим livecd.squashfs
my $squashfile;
if(!defined $data{arg}{rebuild}){
$squashfile = "$data{tmpdir}/livecd/target/$data{squash_cur}";
}else{
$squashfile = "/mnt/flash/$data{squash_cur}"
}
printmes(" ".gettext('Count files for image')); printmes("...");
my $filesnum=int(`/usr/bin/find $data{tmpdir}/livecd/calculate/ | wc -l`);
my $calc_ini="$data{tmpdir}/livecd/calculate/etc/calculate/calculate.ini";
system(qq{ grep ^files= $calc_ini &>/dev/null &&
sed -ri "s/(^files=)(.*)\$/\\1$filesnum/" $calc_ini ||
echo "files=$filesnum" >>$calc_ini
}
);
printmes(" ".gettext('done')); printmes(".\n");
printmes(" ".gettext('Packing system into squashfs format')); printmes("...");
if(system("/usr/bin/mksquashfs $data{tmpdir}/livecd/calculate/ $squashfile &>/dev/null")){
printmes(" ".gettext('error').".\n");
breakiso();
return "";
}else{
printmes(" ".gettext('done')); printmes(".\n");
}
#подготовим к упаковке
printmes(" ".gettext('Prepare syslinux')); printmes("...");
my $target = "$data{tmpdir}/livecd/target";
my $copyflash;
my $isolinux = "isolinux";
if(defined $data{arg}{rebuild}){
$copyflash = "&& cp -r $target/* /mnt/flash/";
$isolinux = "syslinux";
}
else {
my $addsoft;
{
my $mempath = "$target/isolinux/memtest";
if(-e $mempath){$addsoft .= "&& cp -a $mempath $target/syslinux/";}
}
$copyflash = qq| $addsoft &&
cp -a $target/isolinux/isolinux.bin $target/syslinux/ &&
cp -a $target/isolinux/calcmenu.c32 $target/syslinux/ &&
cp $target/isolinux/boot.jpg $target/syslinux/
|;
}
#перенесем ядро и меню на флешку
my $addsoft;
{
my $mempath = "$data{tmpdir}/livecd/calculate/boot/memtest86plus/memtest.bin";
if(-e $mempath){$addsoft .= "cp -rpL $mempath $target/$isolinux/memtest &&";}
}
if(system(qq|
cp $data{tmpdir}/livecd/calculate/boot/vmlinuz-* $target/boot/vmlinuz &&
cp $data{tmpdir}/livecd/calculate/boot/initramfs-*-install $target/boot/initrd &&
$addsoft
cp -a $data{tmpdir}/livecd/calculate/usr/share/syslinux/isolinux.bin $target/$isolinux/ &&
cp -a $data{tmpdir}/livecd/calculate/usr/share/syslinux/calcmenu.c32 $target/$isolinux/ &&
cp $data{tmpdir}/livecd/calculate/boot/boot.jpg $target/$isolinux/ $copyflash
|)){
printmes(" ".gettext('error').".\n");
breakiso();
return "";
}else{
printmes(" ".gettext('done')); printmes(".\n");
}
#удалим файлы распакованной системы
my $deltmp;
if($data{scratch} eq "off"){
printmes(" ".gettext('Delete temporary files')); printmes("...");
$deltmp = "rm -rf $data{tmpdir}/livecd/calculate";
}else{
printmes(" ".gettext('Unmount Scratch system')); printmes("...");
$deltmp = "umount $data{tmpdir}/livecd/calculate";
}
if(system($deltmp)){
printmes(" ".gettext('error').".\n");
breakiso();
return "";
}else{
printmes(" ".gettext('done')); printmes(".\n");
}
#создадим iso-образ
if(!defined $data{arg}{rebuild}){
printmes(" ".gettext('Create iso-image')); printmes("...");
chdir("$data{tmpdir}/livecd");
if(system("mkisofs -b isolinux/isolinux.bin -no-emul-boot -boot-load-size 4 -boot-info-table -iso-level 4 -hide boot.catalog -o $data{linuxdir}/$data{iso} target/ &>/dev/null")){
printmes(" ".gettext('error').".\n");
breakiso();
return "";
}else{
printmes(" ".gettext('done')); printmes(".\n");
}
chdir($ENV{PWD});
}
#удалим временные файлы
printmes(" ".gettext('Delete temporary files')); printmes("...");
if(system("rm -rf $data{tmpdir}")){
printmes(" ".gettext('error').".\n");
breakiso();
return "";
}else{
printmes(" ".gettext('done')); printmes(".\n");
}
#Создадим DIGESTS-файл
if(!defined $data{arg}{rebuild}){
printmes(" ".gettext('Create')); printmes(" DIGESTS "); printmes(gettext('file')); printmes("...");
if(create_digests("$data{linuxdir}/$data{iso}")){
printmes(" ".gettext('done')); printmes(".\n");
}else{
printmes(" ".gettext('error').".\n");
}
}
#синхронизируем флешку, т.к. отмонтировать диск при перезагрузке не получится
if(defined $data{arg}{rebuild}){
printmes(" ".gettext('Sync file systems')); printmes("...");
`sync`;
printmes(" ".gettext('done')); printmes(".\n");
}
return 1;
}
#------------------------------------------------------------------------------
#
# Отмонтируем диски в случае прерывания сборки
#
#------------------------------------------------------------------------------
sub breakiso{
printmes(gettext('Operation interrupted')); printmes(".\n");
printmes(gettext('Abort')); printmes("...");
my $umount_scratch;
if($data{scratch} eq "on" && `mount | grep $data{tmpdir}/livecd/calculate`){
$umount_scratch = "umount $data{tmpdir}/livecd/calculate && ";
}
#отмонтируем все директории и точку монтирования
system $umount_scratch."rm -rf \"$data{tmpdir}\"";
printmes(" ".gettext('done').".\n");
}
#------------------------------------------------------------------------------
# Подменим переменные конфигурационного файла новыми значениями
# Праметры: массив строк конфигурационного файла, массив переменных
# с присвоенными значениями
#------------------------------------------------------------------------------
sub substitution{
my ($original, $conf) = @_;
#заполним хэш новыми значениями переменных
my %conf;
my $part = "default";
foreach(@{$conf}){
if(m/^\s*\[([^\]]+)\]\s*$/){$part = $1; next;}
if(m/^\s*([^#][^\s=]+)([\s=].*)$/){
$conf{$part}{$1} = $2;
chomp $conf{$part}{$1};
#выполним преобразования
my $var = $1;
$conf{$part}{$var}=~s/\\n/\n/g;
$conf{$part}{$var}=~s/\\t/\t/g;
} }
#сформируем готовые строки
my @substitution;
my $part = "default";
foreach(@{$original}){
if(m/^\s*\[([^\]]+)\]\s*$/){
#перенесем новые переменные обработанного блока
foreach(sort keys %{$conf{$part}}){
push(@substitution, "$_$conf{$part}{$_}\n");
}
delete $conf{$part}; #удалим перенесенный блок переменных
push(@substitution, "$_");
$part = $1; next;
}
if(m/^\s*([;]*)([^\s=]+)([\s=].*)$/ && defined $conf{$part}{$2}){
#подменим значение
push(@substitution, "$2$conf{$part}{$2}\n");
delete $conf{$part}{$2};
}else{
push(@substitution, $_);
} }
#перенесем новые переменные последнего блока
foreach(sort keys %{$conf{$part}}){
push(@substitution, "$_$conf{$part}{$_}\n");
}
delete $conf{$part}; #удалим перенесенный блок переменных
#создадим новые блоки
my $part;
my $new;
foreach(sort keys %conf){
$part = $_;
foreach(sort keys %{$conf{$_}}){
if($new ne $part){
push(@substitution, "[$part]\n");
$new = $part;
}
push(@substitution, "$_$conf{$part}{$_}\n");
} }
return @substitution;
}
#------------------------------------------------------------------------------
# Чтение хэша переменных
# Работать с хэшем следует через getini() и putini()
# Параметр: [chroot]
#------------------------------------------------------------------------------
sub loadini{
my $path, $system;
if($_[0] ne "chroot"){
if(!$data{pathini}){
$data{pathini} = "/etc/calculate/calculate.ini";
}
$path = $data{pathini};
$system = "ini";
}elsif($_[0] eq "chroot"){
if(!$data{pathini_chroot}){
$data{pathini_chroot} = "$data{chroot}$data{scratch_ws}/etc/calculate/calculate.ini";
}
$path = $data{pathini_chroot};
$system = "ini_chroot";
if(!$data{chroot}){print "Eroror loadini: No chroot path!\n";}
}else{print "Eroror loadini: Incorrect parameters!\n";}
if(-e $path){
#считаем дополнительные профили установки
open(INI, $path);
foreach(<INI>){
if(m/^\s*#/){next;}
chomp;
m/^([^=]+)=([^=]+)$/;
if($1 ne ''){
$data{$system}{$1} = $2;
}
}
close(INI);
}
}
#------------------------------------------------------------------------------
# Чтение переменной хэша переменных среды
# Параметр: имя переменной, [chroot]
#------------------------------------------------------------------------------
sub getini{
loadini($_[1]); #загрузим параметры, если они еще не загружены
my $system;
if($_[1] ne "chroot"){$system = "ini";}else{$system = "ini_chroot";}
return $data{$system}{$_[0]};
}
#------------------------------------------------------------------------------
# Запись переменной в файл хэша переменных среды
# Параметры: переменная => значение, [chroot]
#------------------------------------------------------------------------------
sub putini{
loadini($_[2]); #загрузим параметры, если они еще не загружены
my $system, $path;
if($_[2] ne "chroot"){
$system = "ini";
$path = $data{pathini};
}else{
$system = "ini_chroot";
$path = $data{pathini_chroot};
}
$data{$system}{$_[0]} = $_[1];
open INI,">$path" or die "Can't open $f : $!";
foreach(sort keys %{$data{$system}}){
if($data{$system}{$_} ne ""){
print INI "$_=$data{$system}{$_}\n";
} }
close (INI);
}
#------------------------------------------------------------------------------
# Генерация пароля
#------------------------------------------------------------------------------
sub password{
my %data = (
lengh => 8,
char => char, #[symbol|char] генерируемые знаки
@_,
);
my $passwd, $cpas;
foreach(my $i = 0; $i < 8; $i++){
if($data{char} eq 'char'){
while (
$cpas < 48 ||
($cpas > 57 && $cpas < 65) ||
($cpas > 90 && $cpas < 97)
){
$cpas = sprintf("%0.0f", rand() * 122);
}
$passwd .= chr($cpas); $cpas = 0;
}else{
while ($cpas < 35 && $cpas < 126){
$cpas = sprintf("%0.0f", rand() * 126);
}
$passwd .= chr($cpas); $cpas = 0;
}
}
return $passwd;
}
#------------------------------------------------------------------------------
# Выполним проверки на совместимость
# Параметр: система и номер поддерживаемой версии
#------------------------------------------------------------------------------
sub checkos{
my ($os,$ver) = @_;
if($data{calculate} ne "$os"){
printmes(gettext('Error')."! ");
printmes(gettext('Command is supported only in'));
printmes(" $data{ver}{$os}.\n"); beep(); return "";
}
if(number_ver($data{os}) < number_ver($ver)){
printmes(gettext('Error')."! ");
printmes(gettext('Command is supported on system not below version'));
printmes(" $ver.\n"); beep(); return "";
}
return 1;
}
#------------------------------------------------------------------------------
# Настроим серверы CDS
#------------------------------------------------------------------------------
sub setupservers{
#выполним проверки на совместимость
if(!checkos("CDS", "8.3")){return "";}
#дополнительные проверки
if($data{arg}{setup}!~m/^ldap$/i && $data{up_ldap} eq "off"){
not_setup_server("LDAP"); return "";
}
if($data{arg}{setup}=~m/^ldap$/i){
if($data{up_ldap} eq "on"){
printmes(gettext('Error')."! ");
printmes(gettext('Server is already adjusted')); printmes(".\n");
beep(); return "";
}
#проверка запущенного LDAP с остановкой
if(
-e "/var/run/samba/smbd.pid" ||
-e "/var/run/samba/nmbd.pid" ||
-e "/var/run/openldap/slapd.pid"
){
printmes(gettext('Error')."! ");
printmes(gettext('Before start stop working LDAP and SAMBA servers'));
printmes(".\n"); beep(); return "";
}
#установим флаг наличия сервера
$data{up_ldap} = "on";
#наложим профиль CDS
$data{'chroot'} = ""; #все изменения проводим загруженной системе
$data{setupldap} = "on";
profile("/usr/calculate/install/profile/CDS");
$data{setupldap} = "";
#запустим LDAP-сервер
system "/etc/init.d/slapd start";
#настроим базовую структуру сервера и добавим базовых пользователей
printmes(" ".gettext('Setup base structure of a LDAP server')); printmes("...");
if(!ldapmodify(add_file => qq#/etc/calculate/ldif/ldap_base.ldif#, root_tmp => ok)){
printmes(" ".gettext('error').".\n");
beep(); return "";
}else{
printmes(" ".gettext('done')); printmes(".\n");
}
#настроим SAMBA-структуру в LDAP-сервере
system "/usr/sbin/smbldap-populate";
#добавим базовые группы в LDAP
printmes(" ".gettext('Add UNIX groups in a LDAP server')); printmes("...");
if(!ldapmodify(add_file => qq#/etc/calculate/ldif/ldap_groups.ldif#, root_tmp => ok)){
printmes(" ".gettext('error').".\n");
beep(); return "";
}else{
printmes(" ".gettext('done')); printmes(".\n");
}
#настроим LDAP (без флага настроек setupldap), пропишем серверы в автозагрузку
profile("/usr/calculate/install/profile/CDS");
#перезапустим LDAP-сервер
system "/etc/init.d/slapd restart";
#пропишем в самбу пароль администратора LDAP для управления пользователями
system "/usr/bin/smbpasswd -w $data{ldap_rootpw}";
#запустим SAMBA-сервер
system "/etc/init.d/samba start";
#сохраним произведенные изменения в calculate.ini
putini("up.ldap" => "on");
printmes(gettext('All done')); printmes("!\n");
}elsif($data{arg}{setup}=~m/^mail$/i){
if($data{up_mail} eq "on"){
printmes(gettext('Error')."! ");
printmes(gettext('Server is already adjusted')); printmes(".\n");
beep(); return "";
}
#установим флаг наличия сервера
$data{up_mail} = "on";
#наложим выбранные профиль CDS
$data{'chroot'} = ""; profile("/usr/calculate/install/profile/CDS");
#перезапустим LDAP-сервер
system "/etc/init.d/slapd restart";
#добавим структуру почтового сервера
printmes(" ".gettext('Add email support in a LDAP server')); printmes("...");
if(!ldapmodify(add_file => qq#/etc/calculate/ldif/mail.ldif#)){
printmes(" ".gettext('error').".\n");
beep(); return "";
}else{
printmes(" ".gettext('done')); printmes(".\n");
}
#создадим базу aliases
system "$data{path} newaliases";
#запустим MAIL-сервер
system "/etc/init.d/postfix start";
#запустим IMAP-сервер
system "/etc/init.d/dovecot start";
#сохраним произведенные изменения в calculate.ini
putini("up.mail" => "on");
printmes(gettext('All done')); printmes("!\n");
}elsif($data{arg}{setup}=~m/^ftp$/i){
}else{
printmes(gettext('Error')."! ");
printmes(gettext('The name of a server is incorrectly specified'));
printmes(".\n");
printmes(gettext('Try')); printmes(" 'calculate --help' "); printmes(gettext('for more information'));
printmes(".\n");
beep(); return "";
}
}
#------------------------------------------------------------------------------
# Выполним резервное копирование данных серверов
#------------------------------------------------------------------------------
sub backupservers{
#выполним проверки на совместимость
if(!checkos("CDS", "8.3")){return "";}
printmes(" ".gettext('Backup LDAP server')); printmes("...");
#сделаем резервную копию LDAP
if(!ldapsearch(backup_file => "/var/CDS/backup/ldap.ldif", where => "$data{'ldap_base'}")){
printmes(" ".gettext('error').".\n");
beep(); return "";
}else{
printmes(" ".gettext('done')); printmes(".\n");
}
}
#------------------------------------------------------------------------------
# Управление пользователями и группами
#------------------------------------------------------------------------------
sub user{
#выполним проверки на совместимость
if(!checkos("CDS", "8.3")){return "";}
#проверим на настроенный сервис
if($data{up_ldap} eq "off"){not_setup_server("LDAP"); return "";}
if($data{arg}{'useradd'}){
#проверим на существование учетной записи пользователя
printmes(" ".gettext('Check existing user account')); printmes("...");
if(check_user($data{arg}{'useradd'})){
printmes(" ".gettext('error').".\n");
beep(); return "";
}else{
printmes(" ".gettext('done')); printmes(".\n");
}
my $groups; if($data{'user_groups'}){$groups = "-G $data{'user_groups'}";}
my $comment; if($data{'user_comment'}){$comment = "-c \"$data{'user_comment'}\"";}
if(system "$data{path} smbldap-useradd -a $groups $comment $data{arg}{'useradd'}"){
beep(); return "";
}
#создадим почтовую директорию и перенесем туда базовую структуру
copyskel("mail" => "/var/CDS/mail");
#создадим директорию UNIX-профиля
copyskel("profiles" => "/var/CDS/profiles");
#создадим домашнюю директорию и перенесем туда базовую структуру
copyskel("home" => "/var/CDS/share");
#создадим директорию WINNT-профиля и перенесем туда базовую структуру netlogon
copyskel("winnt/netlogon" => "/var/CDS/winnt/netlogon");
copyskel("winnt/profiles" => "/var/CDS/winnt/profiles");
printmes(gettext('All done')); printmes("! ");
printmes(gettext('User is added to system')); printmes(".\n");
}elsif($data{arg}{'userdel'}){
if(userdel($data{arg}{'userdel'})){
printmes(gettext('All done')); printmes("! ");
printmes(gettext('User is removed from system')); printmes(".\n");
}
}elsif($data{arg}{'userpasswd'}){
if(system "$data{path} smbldap-passwd $data{arg}{'userpasswd'}"){
beep(); return "";
}
}elsif($data{arg}{'groupadd'}){
#проверим на существование группы доступа
printmes(" ".gettext('Check existing group')); printmes("...");
if(check_group($data{arg}{'groupadd'})){
printmes(" ".gettext('error').".\n");
beep(); return "";
}else{
printmes(" ".gettext('done')); printmes(".\n");
}
#вычислим последний доступный ID группы
my $maxgid = 999; #на 1 меньше минимального ID группы
foreach(ldapsearch(where => "ou=Groups,$data{'ldap_base'}", grep => "gidNumber:")){
if(m/^gidNumber:\s+([0-9]+)$/){
if($maxgid < $1){$maxgid = $1;}
}
}
$maxgid += 1; #прибавим 1 к последнему использованному номеру группы
#создадим группу
if(!ldapmodify(add => qq#
dn: cn=$data{arg}{'groupadd'},ou=Groups,$data{'ldap_base'}
objectClass: posixGroup
objectClass: sambaGroupMapping
cn: $data{arg}{'groupadd'}
gidNumber: $maxgid
sambaSID: S-1-5-21-4205727931-4131263253-1851132050-$maxgid
sambaGroupType: 2
displayName: $data{arg}{'groupadd'}#)){
printmes(gettext('Error')); printmes("!\n");
beep(); return "";
}else{
printmes(gettext('All done')); printmes("!\n");
}
}elsif($data{arg}{'groupdel'}){
if(!ldapdelete("cn=$data{arg}{'groupdel'},ou=Groups,$data{'ldap_base'}")){
printmes(gettext('Error')); printmes("!\n");
beep(); return "";
}else{
printmes(gettext('All done')); printmes("!\n");
}
}elsif($data{arg}{'groupmod'}){
if(defined $data{useradd} && $data{useradd} eq "" ||
defined $data{userdel} && $data{userdel} eq "" ||
!$data{useradd} && !$data{userdel}
){
printmes(gettext('Login of the user is not specified').".\n");
printmes(gettext('Try')); printmes(" 'calculate --help' "); printmes(gettext('for more information'));
printmes(".\n");
beep(); return "";
}
#проверим на существование группы доступа
printmes(" ".gettext('Check existing group')); printmes("...");
if(!check_group($data{arg}{'groupmod'})){
printmes(" ".gettext('error').".\n");
beep(); return "";
}else{
printmes(" ".gettext('done')); printmes(".\n");
}
#проверим на существование учетной записи пользователя
{
my @users;
if($data{useradd}){push(@users,$data{useradd});}
if($data{userdel}){push(@users,$data{userdel});}
printmes(" ".gettext('Check existing user account')); printmes("...");
if(!check_user(@users)){
printmes(" ".gettext('error').".\n");
beep(); return "";
}else{
printmes(" ".gettext('done')); printmes(".\n");
}
}
#проверим на существование группы у добавляемых пользователей
if($data{useradd}){
printmes(" ".gettext('Check up presence of the user in group')); printmes("...");
if(check_groupuser($data{arg}{'groupmod'}, $data{useradd})){
printmes(" ".gettext('error').".\n");
beep(); return "";
}else{
printmes(" ".gettext('done')); printmes(".\n");
} }
#проверим на существование группы у удаляемых пользователей
if($data{userdel}){
printmes(" ".gettext('Check up presence of the user in group')); printmes("...");
if(!check_groupuser($data{arg}{'groupmod'}, $data{userdel})){
printmes(" ".gettext('error').".\n");
beep(); return "";
}else{
printmes(" ".gettext('done')); printmes(".\n");
} }
#добавим пользователя в группу
if($data{useradd}){
ldapmodify(replace => qq#dn: "cn=$data{arg}{'groupmod'},ou=Groups,$data{'ldap_base'}"
add: memberUid
memberUid: $data{useradd}#);
}
#удалим пользователя из группы
if($data{userdel}){
ldapmodify(replace => qq#dn: "cn=$data{arg}{'groupmod'},ou=Groups,$data{'ldap_base'}"
delete: memberUid
memberUid: $data{userdel}#);
}
printmes(gettext('All done')); printmes("!\n");
}else{
printmes(gettext('Error')."! ");
if(defined $data{arg}{'useradd'} || defined $data{arg}{'userdel'} || defined $data{arg}{'userpasswd'}){
printmes(gettext('Login of the user is not specified'));
}else{
printmes(gettext('Group is not specified'));
}
printmes(".\n"); beep(); return "";
}
}
#------------------------------------------------------------------------------
# Перенос skel-файлов
#------------------------------------------------------------------------------
sub copyskel{
my ($skel, $dir) = @_;
my $user = $data{arg}{'useradd'};
system "$data{path} cp -a $data{dir}/install/skel/$skel $dir/$user";
system "$data{path} chown -R `$data{path} id -u $user`:`$data{path} id -g $user` $dir/$user";
system "$data{path} chmod 0700 $dir/$user";
}
#------------------------------------------------------------------------------
# Ошибка - не настроен необходимый сервер
# параметр: имя сервера
#------------------------------------------------------------------------------
sub not_setup_server{
printmes(gettext('Error')."! ");
printmes(gettext('Before performance adjust a'));
printmes(" $_[0] ");
printmes(gettext('server')); printmes(".\n");
printmes(gettext('Try')); printmes(" 'calculate --help' "); printmes(gettext('for more information'));
printmes(".\n");
beep();
}
#------------------------------------------------------------------------------
# Управление почтовыми ящиками
# #------------------------------------------------------------------------------
# sub mail{
# #проверим на настроенный сервис
# if($data{up_mail} eq "off"){not_setup_server("MAIL"); return "";}
#
# #выполним проверки на совместимость
# if(!checkos("CDS", "8.3")){return "";}
#
# if($data{arg}{'mailuseradd'}){
# #проверим на наличие пользователя в LDAP-сервере
# printmes(" ".gettext('Check existing user account')); printmes("...");
#
# if(!ldapsearch(check => yes, where => "uid=$data{arg}{'mailuseradd'},ou=Users,$data{'ldap_base'}", grep => "dn:")){
# printmes(" ".gettext('error').".\n");
# beep(); return "";
# }else{
# printmes(" ".gettext('done')); printmes(".\n");
# }
#
# #проверим на существование почтового ящика
# printmes(" ".gettext('Check existing email account')); printmes("...");
# if(check_email($data{arg}{'mailuseradd'})){
# printmes(" ".gettext('error').".\n");
# beep(); return "";
# }else{
# printmes(" ".gettext('done')); printmes(".\n");
# }
#
# #добавим почтовый ящик в LDAP-сервер
# printmes(" ".gettext('Create a new email account')); printmes("...");
# if(!ldapmodify(add => qq#
# dn: uid=$data{arg}{'mailuseradd'},ou=Users,ou=Mail,$data{'ldap_base'}
# objectClass: inetOrgPerson
# objectClass: qmailUser
# uid: $data{arg}{'mailuseradd'}
# cn: CDS Mail User
# sn: CDS Mail User
# accountStatus: active
# mailMessageStore: $data{arg}{'mailuseradd'}/
# mail: $data{arg}{'mailuseradd'}\@$data{hostname}.$data{domain}
# mailAlternateAddress: $data{'mail'}
# userPassword: {crypt}x#)){
# printmes(" ".gettext('error').".\n");
# beep(); return "";
# }else{
# printmes(" ".gettext('done')); printmes(".\n");
# }
# printmes(gettext('All done')); printmes("!\n");
#
# }elsif($data{arg}{'mailuserdel'}){
# if(mailuserdel($data{arg}{'mailuserdel'})){
# printmes(gettext('All done')); printmes("!\n");
# }
# }elsif($data{arg}{'mailuserpasswd'}){
# #проверим на существование почтового ящика
# printmes(" ".gettext('Check existing email account')); printmes("...");
# if(!check_email($data{arg}{'mailuserpasswd'})){
# printmes(" ".gettext('error').".\n");
# beep(); return "";
# }else{
# printmes(" ".gettext('done')); printmes(".\n");
# }
#
# #введем пароль
# my $passwd = inputpasswd($data{arg}{'mailuserpasswd'});
#
# #изменим почтовый пароль
# printmes(" ".gettext('Change a email account password')); printmes("...");
# if(!ldapmodify(replace => qq#dn: uid=$data{arg}{'mailuserpasswd'},ou=Users,ou=Mail,$data{'ldap_base'}
# userPassword: #.`$data{path} slappasswd -s $passwd -h {SSHA}`)){
# printmes(" ".gettext('error').".\n");
# beep(); return "";
# }else{
# printmes(" ".gettext('done')); printmes(".\n");
# }
# printmes(gettext('All done')); printmes("!\n");
#
# }elsif($data{arg}{'mailgroupadd'}){
#
# }elsif($data{arg}{'mailgroupdel'}){
#
# }else{
# printmes(gettext('Error')."! ");
# if(defined $data{arg}{'mailuseradd'} || defined $data{arg}{'mailuserdel'} || defined $data{arg}{'mailuserpasswd'}){
# printmes(gettext('Login of the email user is not specified'));
# }else{
# printmes(gettext('Group is not specified'));
# }
# printmes(".\n"); beep(); return "";
# }
#
# }
#------------------------------------------------------------------------------
# Проверим на существование учетной записи пользователя
# Параметр: логин пользователя, [логин пользователя]
#------------------------------------------------------------------------------
sub check_user{
my @login = @_;
foreach(@login){
if(!ldapsearch(check => yes, where => "uid=$_,ou=Users,$data{'ldap_base'}", grep => "dn:")){
return ""; #пользователя нет
} }
return 1; #пользователь есть
}
#------------------------------------------------------------------------------
# Проверим на существование группы доступа
# Параметр: группа, [группа]
#------------------------------------------------------------------------------
sub check_group{
my @group = @_;
foreach(@group){
if(!ldapsearch(check => yes, where => "cn=$_,ou=Groups,$data{'ldap_base'}", grep => "dn:")){
return ""; #пользователя нет
}
}
return 1; #пользователь есть
}
#------------------------------------------------------------------------------
# Проверим на существование почтового ящика
# Параметр: логин пользователя
#------------------------------------------------------------------------------
sub check_email{
my $login = $_[0];
if(!ldapsearch(check => yes, where => "$login,ou=Users,ou=Mail,$data{'ldap_base'}", grep => "dn:")){
return ""; #ящика нет
}else{
return 1; #ящик есть
}
}
#------------------------------------------------------------------------------
# Проверим на существование группы у пользователя
# Параметр: группа, логин пользователя
#------------------------------------------------------------------------------
sub check_groupuser{
my ($group, $login) = @_;
if(!ldapsearch(check => yes, where => "cn=$group,ou=Groups,$data{'ldap_base'}", grep => "memberUid:", filter => "(memberUid=$login)")){
return ""; #группы нет
}
return 1; #группа есть
}
#------------------------------------------------------------------------------
# Удалим пользователя из системы
# Параметр: имя пользователя
#------------------------------------------------------------------------------
sub userdel{
my $login = $_[0];
#проверим на существование учетной записи пользователя
printmes(" ".gettext('Check existing user account')); printmes("...");
if(!check_user($login)){
printmes(" ".gettext('error').".\n");
beep(); return "";
}else{
printmes(" ".gettext('done')); printmes(".\n");
}
#удалим пользователя из сервисов
mailuserdel($login, soft); #почтовый аккаунт
#удалим пользователя со всех групп, где он есть
printmes(" ".gettext('Remove the user from groups')); printmes("...");
#получим список групп пользователя
foreach(ldapsearch(where => "ou=Groups,$data{'ldap_base'}", grep => "cn:", filter => "(memberUid=$login)")){
m/^cn:\s+(.+)$/;
#удалим пользователя из группы
ldapmodify(replace => qq#dn: "cn=$1,ou=Groups,$data{'ldap_base'}"
delete: memberUid
memberUid: $login#);
}
printmes(" ".gettext('done')); printmes(".\n");
#удалим пользователя из главной записи
if(!ldapdelete("uid=$login,ou=Users,$data{'ldap_base'}")){
printmes(" ".gettext('error').".\n");
beep(); return "";
}
#удалим файлы пользователя
system "rm -rf /var/CDS/mail/$login";
system "rm -rf /var/CDS/profiles/$login";
system "rm -rf /var/CDS/share/$login";
system "rm -rf /var/CDS/winnt/netlogon/$login";
system "rm -rf /var/CDS/winnt/profiles/$login";
return 1;
}
#------------------------------------------------------------------------------
# Удалим почтовый ящик пользователя
# Параметр: имя пользователя, [soft] - не выдавать ошибку в случае отсутствия ящика
#------------------------------------------------------------------------------
sub mailuserdel{
my ($login, $soft) = @_;
#проверим на существование почтового ящика
printmes(" ".gettext('Check existing email account')); printmes("...");
if(!check_email($login)){
if($soft){
printmes(" ".gettext('done')); printmes(".\n");
return "";
}
printmes(" ".gettext('error').".\n");
beep(); return "";
}
printmes(" ".gettext('done')); printmes(".\n");
#удалим почтовый ящик
printmes(" ".gettext('Delete a email account')); printmes("...");
if(!ldapdelete("uid=$login,ou=Users,ou=Mail,$data{'ldap_base'}")){
printmes(" ".gettext('error').".\n");
beep(); return "";
}else{
printmes(" ".gettext('done')); printmes(".\n");
}
return 1;
}
#------------------------------------------------------------------------------
# Введем пароль пользователя
# Параметр: логин пользователя
#------------------------------------------------------------------------------
sub inputpasswd{
my $login = $_[0];
my $pass,$pass2;
if($login){
printmes(gettext('Changing password for')); printmes(" \"$login\"\n");
}
printmes(gettext('New password')); printmes(" :");
system "stty -echo" if (-t STDIN);
chomp($pass=<STDIN>);
system "stty echo" if (-t STDIN);
print "\n";
printmes(gettext('Retype new password')); printmes(" :");
system "stty -echo" if (-t STDIN);
chomp($pass2=<STDIN>);
system "stty echo" if (-t STDIN);
print "\n";
if ($pass ne $pass2) {
printmes(gettext('New passwords do not match')); printmes("!\n");
beep(); return "";
}elsif($pass eq '') {
printmes(gettext('Password not entered')); printmes("!\n");
beep(); return "";
}else{
return $pass;
}
}
#------------------------------------------------------------------------------
# Изменение и добавление LDAP-записи
#------------------------------------------------------------------------------
sub ldapmodify{
my %ldap = (
replace => "",
add => "",
replace_file => "",
add_file => "",
root_tmp => "",
@_,
);
my $ldif, $add, $file;
if($ldap{replace}){
$ldif = qq#echo "$ldap{replace}" |#;
}elsif($ldap{add}){
$ldif = qq#echo "$ldap{add}" |#;
$add = "-a";
}elsif($ldap{replace_file}){
$file = qq#-f "$ldap{replace_file}"#;
}elsif($ldap{add_file}){
$file = qq#-f "$ldap{add_file}"#;
$add = "-a";
}
my $auth;
if(!$ldap{root_tmp}){
$auth = qq#-D "$data{ldap_root}" -w $data{ldap_rootpw}#;
}else{
$auth = qq#-D "$data{ldap_root_tmp}" -w $data{ldap_rootpw_tmp}#;
}
if(system qq#$ldif $data{path} ldapmodify $add -x $auth $file -h localhost &>/dev/null#){
printmes(" ".gettext('error').".\n");
beep(); return "";
}else{
return 1;
}
}
#------------------------------------------------------------------------------
# Удалим LDAP-запись
# Параметр: запись
#------------------------------------------------------------------------------
sub ldapdelete{
my $delete = $_[0];
if(system qq#$data{path} ldapdelete "$delete" -x -D $data{ldap_root} -w $data{ldap_rootpw} -h localhost >/dev/null 2>&1#){
return "";
}else{
return 1;
}
}
#------------------------------------------------------------------------------
# Поиск LDAP-записей
# Возвращает массив строк
#------------------------------------------------------------------------------
sub ldapsearch{
my %ldap = (
where => "",
filter => "",
grep => "",
check => "",
backup_file => "",
@_,
);
if($ldap{backup_file}){
if(system qq#$data{path} ldapsearch -LLL -b "$ldap{where}" -LLL -x -D $data{ldap_root} -w $data{ldap_rootpw} -h localhost "(objectclass=*)" > $ldap{backup_file}#){
return "";
}else{
return 1;
}
}
my $filter; if($ldap{filter}){$filter = qq#"$ldap{filter}"#;}
my $grep; if($ldap{grep}){$grep = qq#| grep "$ldap{grep}"#;}
my $ldif = qq#$data{path} ldapsearch $filter -b "$ldap{where}" -x -D $data{ldap_root} -w $data{ldap_rootpw} -h localhost $grep $obj#;
if($ldap{check}){
if(system "$ldif >/dev/null 2>&1"){
return ""; #записи нет
}else{
return 1; #запись есть
}
}else{
return `$ldif`; #вернем массив найденных результатов
}
}
#------------------------------------------------------------------------------
# Сверим контрольные суммы исходного файла с файлом DIGEST
#------------------------------------------------------------------------------
sub check_digests{
my $file = $_[0];
my $digests = "$_[0].DIGESTS";
#считаем контрольные суммы
open (F, $digests);
my $tmp = $/; undef $/; my $lines=<F>; $/ = $tmp;
close (F);
my $type;
foreach(split "\n", $lines){
if(/^#\s+([^\s]+)\s+HASH/){$type = $1; next;}
my $hash = $_;
if($type eq "MD5"){
if(!`openssl md5 $file | grep $hash`){return "";}
}elsif($type eq "SHA1"){
if(!`openssl sha1 $file | grep $hash`){return "";}
}
}
return 1;
}
#------------------------------------------------------------------------------
# Создадим новый initrd файл
#------------------------------------------------------------------------------
sub initrd{
my $chroot = $_[0];
printmes(gettext('Create new initrd file')); printmes("...");
printmes(" ".gettext('skip')."!\n");
return;
if(`mount | grep -c "on /proc type proc"` > 1) {
printmes(" ".gettext('skip')."!\n");
return;
}
if(!initrd_clean($chroot)){
beep();
printmes(" ".gettext('error')."!\n");
}
}
#------------------------------------------------------------------------------
# Получить из конфигурации ядра список встроенных или внешних модулей
#------------------------------------------------------------------------------
sub get_kernel_config{
# первый параметр текст конфигурации ядра
# второй y или m (встроенный или внешний)
my ($kconfig,$value) = @_;
my @list=();
# получаем список опций из областей SCSI Transport,
# File systems,Pseudo filesystems,
# CDROM/DVD Filesystems, DOS/FAT/NT Filesystems
foreach($kconfig =~ m/((?:[Ff]ile[s ][sy]|SCSI Transports).*?\n\n#)/sg) {
# получаем список модулей
foreach(m/^(.*)=${value}$/gm) {
push(@list,$_."\n");
}
}
return @list;
}
#------------------------------------------------------------------------------
# Создадим урезанный по железу initrd файл
#------------------------------------------------------------------------------
sub initrd_clean{
my $chroot = $_[0];
# получим список встроенных модулей в текущем ядре
my @list_current_y=get_kernel_config(scalar `gzip -dc /proc/config.gz`,"y");
# получим имя файла конфигурации текущего ядра
my $config=`file -L $chroot$data{scratch_ws}/boot/vmlinuz`;
$config =~ s/^.*version ([^ ]+) .*$/$chroot$data{scratch_ws}\/boot\/config-\1/;
# получим список внешних модулей в ядре в chroot
my @list_chroot_m=get_kernel_config(scalar `cat $config`,"m");
# попытаемся найти одноименные модули
@hash{@list_chroot_m}=();
@filtred=grep { exists $hash{$_} } @list_current_y;
# если есть одноименные модули не делаем оптимизацию initrd
if(@filtred) {
printmes(" ".gettext('skip')); printmes(".\n");
return 1;
}
#найдем среди запущенных модулей не задействованные, которые можно удалить
my %mod_dep; #хэш зависимостей, ключ - модуль, значение - модули его использующие
my %mod_run; #хэш работающих модулей
my %mod_all; #все модули
foreach(`$path lsmod`){
if(m/^Module/){next;}
if(m/^([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)?$/){
my $dep = 0;
if($4){
foreach(split /,/, $4){
$dep ++;
if($mod_dep{$_}){$mod_dep{$_}.=","}
$mod_dep{$_}.="$1";
}
}
if($3 > $dep){
$mod_run{$1} ++;
}
$mod_all{$1} ++;
}
}
#получим пути к модулям
foreach(keys %mod_all){
my $type = `modinfo $_ | grep "filename:"`;
chomp $type;
$type=~m/^filename:\s+([^\s]+)$/;
$mod_all{$_} = $1;
}
#уберем некоторые из работающих модулей
foreach(keys %mod_run){
if(
$mod_all{$_}!~m#/kernel/# ||
$mod_all{$_}=~m#/kernel/fs/cifs/# ||
$mod_all{$_}=~m#/kernel/fs/nfs/#
){delete $mod_run{$_};}
}
#объединим работающие модули с зависимостями
foreach(keys %mod_run){
if($mod_dep{$_}){
foreach(split /,/, $mod_dep{$_}){
$mod_run{$_} ++;
}
}
}
#создадим временную директорию
system "$data{path} mkdir -p '$data{tmpdir}'";
#распакуем initrd
if(!-e "$chroot$data{scratch_ws}/tmp"){`mkdir -m 1777 "$chroot$data{scratch_ws}/tmp"`;}
my $tmpdir = "$chroot$data{scratch_ws}/tmp/initrd";
`$data{path} rm -rf $tmpdir`;
`$data{path} mkdir $tmpdir`;
chdir($tmpdir);
my $initrd = "$chroot/boot/initrd";
# скопируем initrd в initrd-install, если initrd-install отсутствует
if(!-e "${initrd}-install") {
# скопируем текущий initrd в initrd-install
system("cp -aH ${initrd} ${initrd}-install");
}
# подберем утилиту для распаковки
my $archcmd;
if(!system("which lzma &>/dev/null")
&& !system("lzma --force -t $chroot/boot/initrd-install &>/dev/null")) {
$archcmd = "lzma";
}
elsif(!system("which bzip2 &>/dev/null")
&& !system("bzip2 -t $chroot/boot/initrd-install &>/dev/null")) {
$archcmd = "bzip2";
}
else {
$archcmd = "gzip";
}
`$data{path} cp $chroot/boot/initrd-install $tmpdir/initrd-install`;
`$data{path} $archcmd -dc $tmpdir/initrd-install | cpio -idv >/dev/null 2>&1`;
`$data{path} rm $tmpdir/initrd-install`;
#удалим неработающие модули из initrd, за некоторым исключением
foreach(`$data{path} find $tmpdir/lib/modules/ -name *.ko`){
m/\/([^\/]+)\.ko$/;
#проверим варианты где "-" либо "_" меняются в названии модуля и файла
my $underline = $1; my $dash = $underline;
$underline=~s/\-/\_/g; $dash =~s/_/\-/g;
if(!$mod_run{$underline} && !$mod_run{$dash} &&
$1 ne 'squashfs' &&
$1 ne 'zlib_inflate' &&
$1 ne 'aufs' &&
$1 ne 'exportfs' &&
$1 ne 'unionfs' &&
$1 ne 'dm_mod'
){
`rm $_`;
}
}
# извлечем из squash образа конфигурацию ядра
my $curkernel;
if($data{scratch_ws}){
unsquash("/usr/src/linux");
$curkernel = `readlink $chroot$data{scratch_ws}/usr/src/linux`;
chomp($curkernel);
unsquash("/usr/src/${curkernel}/.config") if $curkernel;
}else{
$curkernel = `readlink $chroot/usr/src/linux`;
chomp($curkernel);
}
# # проверим поддерживается ли ядром сжатие lzma и есть ли в наличии утилита lzma
# if( -e "$chroot$data{scratch_ws}/usr/src/$curkernel/.config" && `cat $chroot$data{scratch_ws}/usr/src/linux/.config | \
# grep -Pc "^CONFIG_RD_LZMA=y|^CONFIG_INITRAMFS_COMPRESSION_LZMA=y"` == 2 &&
# !system("which lzma &>/dev/null") ) {
# $archcmd = "lzma";
# }
# else {
$archcmd = "gzip";
# }
#соберем распакованный initrd
`$data{path} find * | cpio -o --quiet -H newc | $archcmd -9 > $chroot/boot/initrd`;
chdir($ENV{PWD});
`$data{path} rm -rf $tmpdir`;
printmes(" ".gettext('done')); printmes(".\n");
return 1;
}
#------------------------------------------------------------------------------
# Установка дополнений
#------------------------------------------------------------------------------
sub addition{
my $path = "/usr/calculate/share/addition/";
my $find = lc($data{'calculate'})."\-(.*)-($data{os})\-$data{march}\.tar";
my $chk;
if(-e $path){
foreach(`$data{path} find $path | sort`){
chomp $_;
if($_=~m/\/$find$/){
#проверим на то, что обновление уже установлено
if(!getini("addition.$1") || defined $data{arg}{'force'}){
printmes("\n ".gettext('Addition is found'));
printmes(": ".ucfirst($1)." $2\n");
if($data{sleep} > 0){
printmes("\n".gettext('Installation of addition will begin through')); printmes(" $data{sleep} "); printmes(gettext('seconds')); printmes(".\n");
printmes(gettext('Press')); printmes(" Ctrl+C "); printmes(gettext('to cancel')); printmes("... ");
my $sleep = $data{sleep} - 1;
if(system(q|echo -e -n "\a|.$data{sleep}.q|"; sleep 1; for ((i=|.$sleep.q|; $i>0; i--)); do echo -e -n "\a\b\b $i"; sleep 1; done; echo -e "\b\b ";|)){
printmes("\n"); return "";
} }
#распакуем дополнение
printmes(" ".gettext('Unpack')); printmes("...");
my $extract;
if(number_ver($data{os}) > number_ver(8.7)){
if(!-e $data{pkgdir}){system "$data{path} mkdir -p $data{pkgdir}";}
$extract = $data{pkgdir};
}else{
$extract = "/";
}
my $packages; #список пакетов
foreach(`$data{path} tar -xvf $_ -C $extract`){
chomp;
if(m/\/All\// || !m/tbz2/){next;}
m/([^\/]+\/[^\/]+)\.tbz2$/;
$packages .= " =$1"; #сформируем переменную для установки
push(@{$data{packageslist}}, "=$1"); #сформируем массив для проверки зависимостей
}
printmes(" ".gettext('done')); printmes(".\n");
#проверим зависимости
if(!dependence('hide')){
beep();
exit;
}
#проверим пакеты, которые нужно установить
my @install;
printmes(" ".gettext('Compare to the list of the established packages')); printmes("...");
foreach(`emerge -p$packages 2>&1`){
if(
m/\[ebuild\s+N\s+\]/ || m/\[ebuild\s+U\s+\]/ ||
(defined $data{arg}{'force'} && m/\[ebuild\s+.+\]/)
){
m/\[ebuild[^\]]+\]\s+([^\s]+)/; #выделим пакет с версией
push (@install, $1);
}
}
printmes(" ".gettext('done')); printmes(".\n");
if(@install){
#установим необходимые пакеты
printmes(gettext('Perform installation')); printmes(":\n");
my $num = 1;
my $all = @install;
foreach(@install){
#printmes(' '.gettext('Unpack'));
printmes(" ($num ");
printmes(gettext('of'));
printmes(" $all) $_...");
if(system "$data{path} emerge --usepkg =$_ &>/dev/null"){
printmes(" ".gettext('error').".\n");
exit;
}else{
printmes(" ".gettext('done')); printmes(".\n");
}
$num ++;
}
}
putini("addition.$1" => "$2");
$chk ++; #флаг успешного обновления
} } }
}else{
`$data{path} mkdir -p $path`;
}
if(!$chk){
printmes("\n".gettext('No updates available')); printmes(".\n");
}else{
printmes(gettext('All done')); printmes("!\n");
}
}
#------------------------------------------------------------------------------
# Покажем список пакетов входящих в дополнение
#------------------------------------------------------------------------------
sub listadd{
if(!checkadd()){return "";}
printmes(gettext('Package list incoming in the addition')); printmes(" \"".ucfirst($data{addition})."\"...\n");
#отобразим на экране список пакетов
my $i = 0;
foreach(packages()){
printmes("$_\n");
$i++;
}
printmes("\n");
printmes(gettext('All')); printmes(" $i "); printmes(gettext('packages'));
printmes(".\n");
return 1;
}
#------------------------------------------------------------------------------
# Соберем пакет дополнения
#------------------------------------------------------------------------------
sub makeadd{
if(number_ver($data{os}) <= number_ver(8.7)){
printmes(gettext('It is supported in systems of versions'));
printmes(" > 8.7\n");
return "";
}
if(!checkadd()){return "";}
#проверим зависимости
if(!dependence()){
beep();
exit;
}
if($data{sleep} > 0){
printmes("\n".gettext('Assembly of addition will begin through')); printmes(" 10 "); printmes(gettext('seconds')); printmes(".\n");
printmes(gettext('Press')); printmes(" Ctrl+C "); printmes(gettext('to cancel')); printmes("... ");
my $sleep = $data{sleep} - 1;
if(system(q|echo -e -n "\a|.$data{sleep}.q|"; sleep 1; for ((i=|.$sleep.q|; $i>0; i--)); do echo -e -n "\a\b\b $i"; sleep 1; done; echo -e "\b\b ";|)){
printmes("\n"); return "";
} }
printmes(gettext('Make addition')."\n");
#создадим временную директорию
system "$data{path} mkdir -p '$data{tmpdir}'";
my @packages = packages(); #получим список пакетов дополнения
#путь к собираемым бинарным файлам пакетов дополнения
my $pathadd = "$data{tmpdir}/packages/$data{addition}/$data{calculate}/$data{linuxver}/$data{march}";
#путь к архиву
my $pathtar = "/usr/calculate/share/addition/".
lc($data{'calculate'})."-$data{addition}-$data{linuxver}-$data{march}.tar";
#путь к LIST-файлу
my $pathlist = "/usr/calculate/share/addition/".
lc($data{'calculate'})."-$data{addition}-$data{linuxver}-$data{march}.list";
#соберем пакеты, без записи в world файл
if(system "$data{path} PKGDIR=\"$pathadd\" emerge --buildpkg --oneshot --noreplace @packages"){
beep();
printmes(" ".gettext('error')."!\n"); return '';
return "";
}else{
printmes(" ".gettext('done').".\n");
}
#упакуем в пакет дополнения скомпилированные программы
printmes(" ".gettext('Packing addition')); printmes("...");
chdir($pathadd);
if(system("$data{path} tar -cf $pathtar .")){
printmes(" ".gettext('error').".\n");
return "";
}else{
printmes(" ".gettext('done')); printmes(".\n");
}
chdir($ENV{PWD});
#удалим бинарные файлы программ
printmes(" ".gettext('Delete temporary files')); printmes("...");
if(system "rm -rf $data{tmpdir}"){
printmes(" ".gettext('error').".\n");
return "";
}else{
printmes(" ".gettext('done')); printmes(".\n");
}
#деинсталлируем собранные пакеты, чтобы привести систему в первоначальный вид
printmes(" ".gettext('Uninstall packages')); printmes("...");
my $packages, %list; #список пакетов
foreach(`$data{path} tar -tf $pathtar`){
chomp;
if(m/\/All\// || !m/tbz2/){next;}
m/([^\/]+\/[^\/]+)\.tbz2$/;
$packages .= " =$1";
$list{$1} ++;
}
if(system "$data{path} CLEAN_DELAY=0 emerge -C --backtrack=0 $packages &>/dev/null"){
printmes(" ".gettext('error').".\n");
return "";
}else{
printmes(" ".gettext('done')); printmes(".\n");
}
#Создадим list-файл со списком собранных пакетов
printmes(" ".gettext('Create')); printmes(" LIST "); printmes(gettext('file')); printmes("...");
open LIST, ">$pathlist";
foreach(sort keys %list){
print LIST "$_\n";
}
close LIST;
printmes(" ".gettext('done')); printmes(".\n");
#Создадим DIGESTS-файл
printmes(" ".gettext('Create')); printmes(" DIGESTS "); printmes(gettext('file')); printmes("...");
if(create_digests($pathtar)){
printmes(" ".gettext('done')); printmes(".\n");
}else{
printmes(" ".gettext('error').".\n");
}
printmes("\n".gettext('All done')); printmes("!\n");
return 1;
}
#------------------------------------------------------------------------------
# Проверим имя пакета дополнения
#------------------------------------------------------------------------------
sub checkadd{
if(defined $data{addition} && packages()){
return 1;
}elsif(!defined $data{addition}){
printmes(gettext('Addition name is not specified')); printmes(".\n");
}elsif(!packages()){
printmes(gettext('Packages addition'));
printmes(" \"$data{addition}\" ");
printmes(gettext('not found')); printmes(".\n");
}
printmes(gettext('Try')); printmes(" 'calculate --help' "); printmes(gettext('for more information'));
printmes(".\n");
beep();
return "";
}
#------------------------------------------------------------------------------
# Установим по необходимости видеодрайвер
#------------------------------------------------------------------------------
sub video{
printmes(gettext('Check the video driver')); printmes("... ");
if(
$data{video_drv} eq 'nvidia'
&&
-e "/usr/portage/packages/x11-drivers"
){
my $filemask = "/etc/portage/package.mask/nvidia-drivers";
#создадим директорию package.mask для версий Calculate Linux < 9.2
if(-f "/etc/portage/package.mask"){
system "$data{path} mv /etc/portage/package.mask /etc/portage/package.mask2";
system "$data{path} mkdir /etc/portage/package.mask";
system "$data{path} mv /etc/portage/package.mask2 /etc/portage/package.mask/default";
}
my $maskold;
if(-f $filemask){
$maskold = `cat $filemask`;
chomp $maskold;
}
my $mask = nvidia_mask();
printmes(gettext('done').".\n");
#обновим драйвер
if($mask ne $maskold){
printmes(" ".gettext('Driver Installation for')); printmes(" \"$data{video}\"... ");
system "echo '$mask' > $filemask";
if(system "PKGDIR=\"/usr/portage/packages\" emerge -k nvidia-drivers > /dev/null"){
#в случае неудачи, удалим маску
system "rm $filemask";
printmes(gettext('error').".\n");
}else{
printmes(gettext('done').".\n");
}
}
}else{
printmes(gettext('done').".\n");
}
}
#------------------------------------------------------------------------------
# Маска для установки необходимой версии nvidia драйвера
#------------------------------------------------------------------------------
sub nvidia_mask{
my $mask = `bash -c "function inherit { echo -n ''; };. /usr/portage/eclass/nvidia-driver.eclass && nvidia-driver-get-mask"`;
chomp $mask;
return $mask;
}
#------------------------------------------------------------------------------
# Звуковое предупреждение
#------------------------------------------------------------------------------
sub beep{
# if(-e "/usr/bin/play" && -e "/usr/share/sounds/pop.wav"){
# `/usr/bin/play /usr/share/sounds/pop.wav 2>&1 >/dev/null`;
# }else{
system "echo -e -n \"\a\"";
# }
}
#------------------------------------------------------------------------------
# Соберем бинарные пакеты дополнений (nVideo драйвера)
#------------------------------------------------------------------------------
sub makepkg{
if($data{system} eq "server" || $data{calculate} eq "CLS" || $data{calculate} eq "CLSG"){return 1;}
printmes(gettext('Make nvidia drivers')."\n");
printmes(" ".gettext('nvidia-drivers-71.XX.XX')); printmes("... ");
`echo ">x11-drivers/nvidia-drivers-72.00.00" > $data{'chroot'}/etc/portage/package.mask/nvidia`;
if(system "PKGDIR=\"/usr/portage/packages\" $data{emergerun1} -b x11-drivers/nvidia-drivers $data{emergerun2} &>/dev/null"){
#beep();
printmes(gettext('error').".\n");
#return '';
}else{
printmes(gettext('done').".\n");
}
printmes(" ".gettext('nvidia-drivers-96.XX.XX')); printmes("... ");
`echo ">x11-drivers/nvidia-drivers-97.00.00" > $data{'chroot'}/etc/portage/package.mask/nvidia`;
if(system "PKGDIR=\"/usr/portage/packages\" $data{emergerun1} -b x11-drivers/nvidia-drivers $data{emergerun2} &>/dev/null"){
beep();
printmes(gettext('error').".\n"); return '';
}else{
printmes(gettext('done').".\n");
}
printmes(" ".gettext('nvidia-drivers-173.XX.XX')); printmes("... ");
`echo ">x11-drivers/nvidia-drivers-174.00.00" > $data{'chroot'}/etc/portage/package.mask/nvidia`;
if(system "PKGDIR=\"/usr/portage/packages\" $data{emergerun1} -b x11-drivers/nvidia-drivers $data{emergerun2} &>/dev/null"){
beep();
printmes(gettext('error').".\n"); return '';
}else{
printmes(gettext('done').".\n");
}
printmes(" ".gettext('nvidia-drivers-last')); printmes("... ");
`rm $data{'chroot'}/etc/portage/package.mask/nvidia`;
if(system "$data{emergerun1} x11-drivers/nvidia-drivers $data{emergerun2} &>/dev/null"){
beep();
printmes(gettext('error').".\n"); return '';
}else{
printmes(gettext('done').".\n");
}
return 1;
}
#------------------------------------------------------------------------------
# Соберем стабильную версию calculate
#------------------------------------------------------------------------------
#sub makecalculate{
# if(`mount | grep $data{chroot}/usr/calculate/install`){
# #Отмонтируем /usr/calculate/install
# printmes(" ".gettext('Umount')); printmes(" /usr/calculate/install...");
# if(system "$data{path} umount $data{chroot}/usr/calculate/install &>/dev/null"){
# printmes(" ".gettext('error')."!\n");
# return '';
# }else{
# printmes(" ".gettext('done').".\n");
# }
#
# #Установим calculate
# printmes(" ".gettext('Execute')); printmes(" emerge sys-apps/calculate...");
# if(system "$data{path} chroot $data{chroot} emerge sys-apps/calculate &>/dev/null"){
# printmes(" ".gettext('error')."!\n");
# return '';
# }else{
# printmes(" ".gettext('done').".\n");
# }
# }
# return 1;
#}
#------------------------------------------------------------------------------
# Подключим своп
#------------------------------------------------------------------------------
sub swapon{
if($data{swap} && !`cat /proc/swaps | grep "$data{swap}"`){
printmes(" ".gettext('Mounting swap')); printmes("... ");
if(system "$data{path} swapon $data{swap}"){
printmes(gettext('Error')); printmes("! ");
}else{
printmes(gettext('done').".\n");
} }
return 1;
}
#------------------------------------------------------------------------------
# Определим USB устройства Flash и USB-HDD
#------------------------------------------------------------------------------
sub check_removable{
my $dev = $data{arg}{'disk'};
if(!$dev || !$data{hal}){return "hdd";}
$dev =~m#^(/dev/[^\/0-9]+)[0-9]?[0-9]?$#;
my $disk = $1;
if( !$disk ) {
return "hdd";
}
my $isusb = `$data{path} hal-find-by-property --key block.device --string $disk | xargs -I {} hal-get-property --udi '{}' --key storage.bus 2>/dev/null`;
chomp($isusb);
if( $isusb eq "usb" ) {
my $isflash = `$data{path} hal-find-by-property --key block.device --string $disk | xargs -I {} hal-get-property --udi '{}' --key storage.removable 2>/dev/null`;
chomp($isflash);
if( $isflash eq "true" ) { return "flash"; }
else { return "usb-hdd"; }
}
return "hdd";
}
#------------------------------------------------------------------------------
# установим $data{swapset} и $data{swap_resume}
#------------------------------------------------------------------------------
sub swapset{
if($data{swap}){
printmes(" ".gettext('Swap disk')); printmes(": $data{swap}\n");
if($data{'uuid'} eq 'on'){
$data{swapset} = qq|UUID=$data{uuid_swap}\tnone\t\tswap\tsw\t\t\t0 0|;
$data{swap_resume} = "resume=UUID=$data{uuid_swap}";
}else{
$data{swapset} = qq|$data{swap}\tnone\t\tswap\tsw\t\t\t0 0|;
$data{swap_resume} = "resume=$data{swap}";
}
}else{
$data{swapset} = "";
$data{swap_resume} = "noresume";
}
return 1;
}
#------------------------------------------------------------------------------
# извлечем из squashfs файлы
#------------------------------------------------------------------------------
sub unsquash{
my $squash = "$data{mount}/livecd.squashfs";
system("$data{path} unsquashfs -n -d $data{mount}$data{scratch_ws} -f $squash @_ &>/dev/null");
}
#------------------------------------------------------------------------------
# Проверим наличие файла в образе
#------------------------------------------------------------------------------
sub checksquash{
my $file = $_[0];
my $squash = "$data{mount}/livecd.squashfs";
return !system("$data{path} unsquashfs -ls $squash $file | grep -P '^squashfs-root$file' &>/dev/null");
}
#------------------------------------------------------------------------------
# удалим временные файлы
#------------------------------------------------------------------------------
sub clearlog{
$chroot = $_[0];
printmes(" ".gettext('Delete temporary files')); printmes("...");
system("$data{path} rm -rf $chroot/etc/resolv.conf $chroot/etc/mtab $chroot/var/log/emerge* $chroot/var/log/genkernel.log $chroot/var/log/lastlog $chroot/var/log/prelink.log $chroot/var/log/wtmp $chroot/var/.locks $chroot/var/.svn-src $chroot/var/calculate/remote/distfiles/* $chroot/var/lib/gentoo/news/* $chroot/var/lib/portage/world $chroot/root/.viminfo $chroot/root/.bash_history $chroot/root/.subversion $chroot/var/calculate/tmp/*");
foreach(
"$chroot/var/tmp/portage",
"$chroot/tmp",
"$chroot/var/log/clamav",
"$chroot/var/log/calculate",
"$chroot/var/log/portage/elog",
){
cleardir($_);
}
#Заново сформируем world
foreach(packages()){
system "echo '$_' >> $chroot/var/lib/portage/world";
}
printmes(" ".gettext('done')); printmes(".\n");
}
#------------------------------------------------------------------------------
# Авторазмаскировка пакетов
#------------------------------------------------------------------------------
sub autounmask{
dependence();
}
#------------------------------------------------------------------------------
# Настроим OpenGL
#------------------------------------------------------------------------------
sub opengl_set{
if($data{run_opengl}){
system "$data{run_opengl}";
}
}
#------------------------------------------------------------------------------
# Извлечем информацию о разделе
# параметры - раздел, тип информации
#------------------------------------------------------------------------------
sub uuid{
my $info = `$data{path} blkid $_[0] 2>/dev/null`;
if($_[1] eq 'UUID'){
$info =~s/.*UUID="([^"]+)".*/$1/;
}elsif($_[1] eq 'TYPE'){
$info =~s/.*TYPE="([^"]+)".*/$1/;
}
chomp $info;
return $info;
}
#------------------------------------------------------------------------------
# Удалим файлы не используемую локализацию
#------------------------------------------------------------------------------
sub clearlang{
my @remote;
foreach(
@{$data{clearlang}}
){
my $lang = $_;
foreach(
'/usr/lib/openoffice',
'/usr/share/apps',
'/usr/share/doc',
'/usr/share/locale',
'/usr/share/man',
'/usr/share/vim',
'/usr/share/xfce4/doc',
'/usr/share/gnome/help'
){
if(-e "$data{'chroot'}$_"){
foreach(`find $data{'chroot'}$_ -type d -name $lang`){
chomp;
system "rm -rf $_";
} } } } }