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

#!/usr/bin/perl
use Cwd;
use IO::Socket;
use Time::Local;
#------------------------------------------------------------------------------
# Calculate
14 years ago
# 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; #объявим хэш переменных
14 years ago
$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(
15 years ago
$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" => '',
15 years ago
"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");
14 years ago
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(
15 years ago
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";
14 years ago
$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}";
15 years ago
$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}";
15 years ago
$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(
14 years ago
(($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'){
14 years ago
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(
15 years ago
!$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} = '';
15 years ago
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}){
14 years ago
if(-e "/var/calculate/calculate2.env" || -e "/var/calculate/calculate.env"){
#считаем переменную адреса сервера
14 years ago
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') &&
15 years ago
$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}
#----------------------------------------------------------------------
14 years ago
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"){
14 years ago
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("! ");
15 years ago
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);
14 years ago
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...");
14 years ago
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";
}
15 years ago
}
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/;
14 years ago
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{
14 years ago
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";
14 years ago
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");
}
}
14 years ago
# #Скопируем /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";}
15 years ago
my @check;
push @check, `$data{emergerun1} -p --color n @packages $data{emergerun2} $softly 2>&1`;
if(!defined $data{arg}{'unmask'}){
#вторая проверка на случай сборки на базе CLS
14 years ago
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;
14 years ago
}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';
14 years ago
}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';
14 years ago
}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 ++){
14 years ago
printmes(" ".gettext('Execute')); printmes(" emerge -e system...");
printmes(" ".gettext('done')); printmes(".\n");
} }
if(getini("run.make.step.newuse", "chroot")){
14 years ago
printmes(" ".gettext('Execute')); printmes(" emerge --newuse -D world...");
printmes(" ".gettext('done')); printmes(".\n");
}
if(getini("run.make.step.update", "chroot")){
14 years ago
printmes(" ".gettext('Execute')); printmes(" emerge -upD world...");
printmes(" ".gettext('done')); printmes(".\n");
}
#получим список пакетов world = ""
my @world = packages();
14 years ago
my $finish = '';
while(!$finish){
if($data{stage} !~m/iso$/ && getini("run.make.step.system", "chroot") < 2){
14 years ago
printmes(" ".gettext('Execute')); printmes(" emerge -e system...\n");
putini("run.make" => "system", "chroot"); #сохраним выполняемое действие
14 years ago
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")){
14 years ago
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")){
14 years ago
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");
14 years ago
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"){
14 years ago
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')."! ");
14 years ago
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')."! ");
14 years ago
printmes(gettext('Invalid template')); printmes(" \"$_\".\n");
return ""
}
}
if(!@{$data{setprof}}){
printmes(gettext('Error')."! ");
14 years ago
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}){
15 years ago
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}"
}
14 years ago
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|
14 years ago
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{
15 years ago
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("...");
14 years ago
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
14 years ago
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 $_";
} } } } }