#!/usr/bin/perl use Cwd; use IO::Socket; use Time::Local; #------------------------------------------------------------------------------ # Calculate # Copyright ©2006-2010 Mir Calculate Ltd. # Program established: 12.04.2006г. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . #------------------------------------------------------------------------------ my %data; #объявим хэш переменных $data{"calcver"} = "1.4.0"; #Определим путь к программе if(!getpath()){exit;}; #Считаем входящие параметры и выполним простые действия if(!getarg()){savelog(); exit;}; #Проверим на ошибки if(!checkerrors()){savelog(); exit;}; #Определим систему для установки и обновления welcome(); #Соберем сведения о системе checksystem(); #------------------------------------------------------------------------------ # Выполним действия #------------------------------------------------------------------------------ #Покажем все переменные if(defined $data{arg}{'vars'}){ printvars(); #Выведем список переменных конфигурационных файлов #Покажем список пакетов, входящих в дополнение }elsif(defined $data{arg}{'L'}){ listadd(); #Соберем дополнение }elsif(defined $data{arg}{'M'}){ makeadd(); #Установка дополнений }elsif(defined $data{arg}{'addition'}){ addition(); #Сгенерируем новый initrd }elsif(defined $data{arg}{'initrd'}){ initrd(); #Размаскируем пакеты }elsif(defined $data{arg}{'unmask'}){ autounmask(); #Установим по необходимости видеодрайвер }elsif(defined $data{arg}{'video'}){ video(); #Настроим OpenGL }elsif(defined $data{arg}{'opengl'}){ opengl_set(); #Выполним обновления }elsif(defined $data{arg}{update}){ checkupdate(); #Покажем информацию о компьютере }elsif(defined $data{arg}{'hardware'}){ printhardware(); #Выведем конфигурацию ПК #Настроим серверы CDS }elsif(defined $data{arg}{'setup'}){ setupservers(); #настроим серверы #Выполним резервное копирование данных серверов }elsif(defined $data{arg}{'backup'}){ backupservers(); #настроим серверы #Управление пользователями }elsif(defined $data{arg}{'useradd'} || defined $data{arg}{'userdel'} || defined $data{arg}{'userpasswd'} || defined $data{arg}{'groupadd'} || defined $data{arg}{'groupdel'} || defined $data{arg}{'groupmod'}){ user(); #управление пользователями #Управление почтовыми ящиками }elsif(defined $data{arg}{'mailuseradd'} || defined $data{arg}{'mailuserdel'} || defined $data{arg}{'mailuserpasswd'} || defined $data{arg}{'mailgroupadd'} || defined $data{arg}{'mailgroupdel'}){ mail(); #управление пользователями #Наложим обновления профилей на текущую систему }elsif(defined $data{arg}{'profile'}){ update_profile(); #подключим swap if($data{'swapon'}){ swapon(); } #Выполним сборку новой системы }elsif($data{builder}){ if(defined $data{arg}{list}){ if(!list()){ beep(); } }elsif(defined $data{arg}{dependence}){ if(!dependence()){ beep(); } }elsif(defined $data{arg}{make}){ if(!make()){ beep(); }elsif(!makepkg()){ beep(); #}elsif(!makecalculate()){ # beet(); } }elsif(defined $data{arg}{pack}){ if(!packsystem()){ beep(); } }elsif(defined $data{arg}{iso} || defined $data{arg}{rebuild}){ if(!createiso()){ beep(); } }elsif(defined $data{arg}{'break'}){ if(!breakbuild()){ beep(); } }else{ #Создадим директорию сборки system "$data{path} mkdir $data{mount}"; #Соберем новый дистрибутив if(!checkready()){system "$data{path} rmdir $data{mount}";} #Выполним проверки перед установкой elsif(!extract()){system "$data{path} rmdir $data{mount}";} #Распакуем stage elsif(!configure()){} #Подготовим систему к сборке } #Выполним установку новой системы }elsif( $data{linux} && !defined $data{arg}{'updateonly'} && #отменим установку с hdd если мы загрузились в scratch режиме и образа обновления не нашли !($data{linux} eq 'scratch' && $data{load} eq '') ){ if(($data{load_cache} eq 'on' || $data{linux} eq 'scratch') && $data{type} eq 'flash' && $data{linux} !~ m/iso$/ ){ printmes("\n"); printmes(gettext('For installation on USB-Flash, reboot in normal mode')); printmes(".\n"); beep(); exit 1; } #Создадим директорию установки system "$data{path} mkdir $data{mount}"; #Установим новую версию системы if(!checkready()){} #Выполним проверки перед установкой elsif(!extract()){} #Распакуем систему elsif(!profiles()){} #Наложим обновления elsif(!setup()){} #Выполним общие настройки системы elsif(!loader()){} #Подготовим систему к перезагрузке elsif(!reboot()){} #Перезагрузим компьютер #Удалим директорию установки system "$data{path} rmdir $data{mount}"; #Выполним установку патчей }else{ if(%{$data{patches}}){ patch(); }else{ printmes("\n".gettext('No updates available')); printmes(".\n"); } } savelog(); exit; #------------------------------------------------------------------------------ # # Определим путь к программе # #------------------------------------------------------------------------------ sub getpath{ #---------------------------------------------------------------------- # Добавим по необходимости переменные пути #---------------------------------------------------------------------- { $data{path} = ''; if(":$ENV{PATH}:"!~m|:/sbin:|){ $data{path}.= "/sbin:"; } if(":$ENV{PATH}:"!~m|:/bin:|){ $data{path}.= "/bin:"; } if(":$ENV{PATH}:"!~m|:/usr/sbin:|){ $data{path}.= "/usr/sbin:"; } if(":$ENV{PATH}:"!~m|:/usr/bin:|){ $data{path}.= "/usr/bin:"; } if($data{path}){ $data{path} = "PATH=$data{path}\${PATH} && "; } } #---------------------------------------------------------------------- # Путь к директории calculate, последнюю доступную версию системы # $data{dir} #---------------------------------------------------------------------- { my $wd = &Cwd::cwd(); #добавим завершающий слеш в пути если его нет if(substr($wd,length($wd)-1) ne "/"){$wd.="/";} #удалим из файла запускаемой программы "./" my $file = $0; if(substr($file,0,2) eq "./"){$file = substr($file,2);} #склеим путь текущей директории с выполняемым файлом my $path; if(substr($file,0,1) eq "/"){ $path = $file; }else{ $path = $wd.$file; } #проверим на символическую ссылку my $link = `$data{path} file $path`; chomp $link; #получим информацию о файле запуска #если это символическая ссылка, сформируем путь if($link=~m/.+symbolic link to \`([^']+)'$/){ $link = $1; #путь к файлу if($link=~m/^\//){ $path = $link; #фактический путь при указании на прямой путь }else{ $path=~s/(.+)\/[^\/]+/$1/; #директория символической ссылки $path = "$path/$link"; #фактический путь при указании относительного пути в ссылке } } #получим путь к директории calculate $data{dir} = $path; $data{dir}=~s/(.+)\/[^\/]+/$1/; $data{dir}=~s/(.+)\/([^\/]+)/$1/; chdir($data{dir}); } return 1; } #------------------------------------------------------------------------------ # # Считаем входящие параметры и выполним простые действия # #------------------------------------------------------------------------------ sub getarg{ #краткое и полное название программы $data{"calcname"} = "Calculate"; $data{'calcinstall'} = "$data{calcname} $data{calcver}"; #---------------------------------------------------------------------- # Считаем параметры запуска # %{$data{arg}} %{$data{par}} #---------------------------------------------------------------------- { my $par = ''; #извлечем параметры слов my @arg; foreach(@ARGV){ if(/^\-\-([^\s=]+)=(.+)$/){ $data{arg}{$1} = $2; $par++;} elsif(/^\-\-([^\s]+)$/){$data{arg}{$1} = ''; $par++;} else{push @arg, $_} } #обработаем параметры букв и дополнительные параметры - слова или буквы разделеныне пробелами foreach(split "-", "@arg"){ if(!$_){next;} my ($var, $val, @par) = split " "; $data{arg}{$var} = "$val"; #параметры букв if(@par){ foreach(@par){$data{par}{$_} = '';} #дополнительные параметры } $par++; } if(!$par){$data{NOPAR}++;} } #Проверим переданные параметры { #Допустимые переменные my %arg = ( "a" => '', "addition" => '', "s" => '', "os" => '', "d" => '', "disk" => '', "b" => '', "build" => '', "f" => '', "force" => '', "U" => '', "updateonly" => '', "P" => '', "profile" => '', "l" => '', "list" => '', "c" => '', "configure" => '', "D" => '', "dependence" => '', "m" => '', "make" => '', "p" => '', "pack" => '', "iso" => '', "rebuild" => '', "break" => '', "L" => '', "M" => '', #"S" => '', "setup" => '', #"backup" => '', "useradd" => '', "userdel" => '', "userpasswd" => '', "groupadd" => '', "groupdel" => '', "groupmod" => '', # "mailuseradd" => '', # "mailuserdel" => '', # "mailuserpasswd" => '', # "mailgroupadd" => '', # "mailgroupdel" => '', "u" => '', "update" => '', "h" => '', "help" => '', "v" => '', "vars" => '', "H" => '', "hardware" => '', "V" => '', "version" => '', "translate" => '', "initrd" => '', "unmask" => '', "video" => '', "opengl" => '', "nodie" => '', #выводить минимум информации показывая неверно завершенную работу "softly" => '', #не вылетать при ошибке запускаемой программы "composite" => '', ); my @write = ( "builderdir", "cpus", "domain", "erase", "format", "gateway", "hostname", "iso", "ldap_base", "ldap_bind", "ldap_bindpw", "ldap_root", "linuxver", "makeopts", "march", "mbr", "menuconfig", "mesline", "mestitle", "mount", "move_fstab", "nfs", "ntp", "patchdir", "proxy", "server_url", "skipfirst", "swap", "tmpdir", "user_comment", "user_groups", "useradd", "userdel", "uuid", "mail", "video_drv", "video_resolution", "lang", "timezone", "type", "clock", "composite", "scheduler", "system", "swapon", "sleep", ); foreach(@write){$data{write}{$_} ++;} #Проверим переменные foreach(keys %{$data{arg}}){ if( !defined $arg{$_} && $_!~/^set\-/i ){errorarg($_); return "";} #Перенесем переданные значения if($_=~m/^set\-(.+)/){ if($data{write}{$1}){ $data{$1} = $data{arg}{$_}; }else{ printmes(gettext('Incorrect variable name')); printmes(" '$1' "); printmes(gettext('or value cannot be changed')); printmes(".\n"); printmes(gettext('Try')); printmes(" 'calculate --vars' "); printmes(gettext('for a print of all variables')); printmes(".\n"); beep(); return ""; } }elsif($_=~m/^SET\-(.+)/){ $data{$1} = $data{arg}{$_}; } } #Допустимые аргументы my %par = (); #Проверим аргументы foreach(keys %{$data{par}}){ if(!defined $par{$_}){errorarg(-$_); return "";} } } #---------------------------------------------------------------------- # Считаем параметры запуска, установим флаги действий #---------------------------------------------------------------------- if(defined $data{arg}{'a'} || defined $data{arg}{'addition'}){ if(!defined $data{arg}{'addition'}){$data{arg}{'addition'} = $data{arg}{'a'}} $data{CHECKSYSTEM_NOMES}++; $data{builder}++; $data{addition} = lc($data{arg}{'a'}); } if(defined $data{arg}{'s'} || defined $data{arg}{'os'}){ if(!defined $data{arg}{'os'}){$data{arg}{'os'} = $data{arg}{'s'}} } #Флаги установки и обновления системы if($data{arg}{d} || $data{arg}{'disk'}){ if(!$data{arg}{'disk'}){$data{arg}{'disk'} = $data{arg}{'d'}} } if(defined $data{arg}{'b'} || defined $data{arg}{build}){ if(!$data{arg}{build}){$data{arg}{build} = $data{arg}{'b'}} $data{scratch_ws} = "/workspace"; } if(defined $data{arg}{f} || defined $data{arg}{'force'}){ if(!defined $data{arg}{'force'}){$data{arg}{'force'} = $data{arg}{'f'}} } if(defined $data{arg}{U} || defined $data{arg}{'updateonly'}){ if(!defined $data{arg}{'updateonly'}){$data{arg}{'updateonly'} = $data{arg}{'U'}} $data{change}++; #флаг производимых в системе изменений } if(defined $data{arg}{P} || defined $data{arg}{'profile'}){ if(!defined $data{arg}{'profile'}){$data{arg}{'profile'} = $data{arg}{'P'}} $data{CHECKSYSTEM_NOMES}++; $data{change}++; #флаг производимых в системе изменений } #Флаги сборки системы if(defined $data{arg}{l} || defined $data{arg}{'list'}){ if(!defined $data{arg}{'list'}){$data{arg}{'list'} = $data{arg}{'l'}} $data{CHECKSYSTEM_NOMES}++; $data{builder}++; } if(defined $data{arg}{c} || defined $data{arg}{'configure'}){ if(!defined $data{arg}{'configure'}){$data{arg}{'configure'} = $data{arg}{'c'}} $data{builder}++; } if(defined $data{arg}{D} || defined $data{arg}{'dependence'}){ if(!defined $data{arg}{'dependence'}){$data{arg}{'dependence'} = $data{arg}{'D'}} $data{CHECKSYSTEM_NOMES}++; $data{builder}++; $data{builder_chroot}++; #флаг того что директория chroot должна быть создана предварительно } if(defined $data{arg}{m} || defined $data{arg}{'make'}){ if(!defined $data{arg}{'make'}){$data{arg}{'make'} = $data{arg}{'m'}} $data{builder}++; $data{builder_chroot}++; } if(defined $data{arg}{p} || defined $data{arg}{'pack'}){ if(!defined $data{arg}{'pack'}){$data{arg}{'pack'} = $data{arg}{'p'}} $data{CHECKSYSTEM_NOMES}++; $data{builder}++; $data{builder_chroot}++; } if(defined $data{arg}{'iso'}){ $data{CHECKSYSTEM_NOMES}++; $data{builder}++; $data{createiso}++; } if(defined $data{arg}{'rebuild'}){ $data{CHECKSYSTEM_NOMES}++; $data{builder}++; $data{createiso}++; } if(defined $data{arg}{'break'}){ $data{CHECKSYSTEM_NOMES}++; $data{builder}++; $data{builder_chroot}++; } #Сборка дополнений if(defined $data{arg}{'L'}){ $data{CHECKSYSTEM_NOMES}++; $data{builder}++; if($data{arg}{'L'}){$data{addition} = lc($data{arg}{'L'});} } if(defined $data{arg}{'M'}){ $data{CHECKSYSTEM_NOMES}++; $data{builder}++; if($data{arg}{'M'}){$data{addition} = lc($data{arg}{'M'});} } #Настройка сервера # if(defined $data{arg}{S} || defined $data{arg}{'setup'}){ # if(!defined $data{arg}{'setup'}){$data{arg}{'setup'} = $data{arg}{'S'}} # $data{CHECKSYSTEM_NOMES}++; # } # if(defined $data{arg}{'backup'}){ # $data{CHECKSYSTEM_NOMES}++; # } if(defined $data{arg}{'useradd'} || defined $data{arg}{'userdel'} || defined $data{arg}{'userpasswd'} || defined $data{arg}{'groupadd'} || defined $data{arg}{'groupdel'} || defined $data{arg}{'groupmod'}){ $data{CHECKSYSTEM_NOMES}++; } # if(defined $data{arg}{'mailuseradd'} || defined $data{arg}{'mailuserdel'} || defined $data{arg}{'mailuserpasswd'} || defined $data{arg}{'mailgroupadd'} || defined $data{arg}{'mailgroupdel'}){ # $data{CHECKSYSTEM_NOMES}++; # } #Флаг обновления системы if(defined $data{arg}{u} || defined $data{arg}{'update'}){ if(!defined $data{arg}{'update'}){$data{arg}{'update'} = $data{arg}{'u'}} $data{CHECKSYSTEM_NOMES}++; } #Флаги информационного вывода if(defined $data{arg}{h} || defined $data{arg}{'help'}){ if(!defined $data{arg}{'help'}){$data{arg}{'help'} = $data{arg}{'h'}} } if(defined $data{arg}{v} || defined $data{arg}{'vars'}){ if(!defined $data{arg}{'vars'}){$data{arg}{'vars'} = $data{arg}{'v'}} $data{CHECKSYSTEM_NOMES}++; } if(defined $data{arg}{H} || defined $data{arg}{'hardware'}){ if(!defined $data{arg}{'hardware'}){$data{arg}{'hardware'} = $data{arg}{'H'}} $data{CHECKSYSTEM_NOMES}++; } if(defined $data{arg}{V} || defined $data{arg}{'version'}){ if(!defined $data{arg}{'version'}){$data{arg}{'version'} = $data{arg}{'V'}} } if(defined $data{arg}{'initrd'}){ $data{CHECKSYSTEM_NOMES}++; } if(defined $data{arg}{'unmask'}){ $data{CHECKSYSTEM_NOMES}++; } if(defined $data{arg}{'video'}){ $data{CHECKSYSTEM_NOMES}++; } if(defined $data{arg}{'opengl'}){ $data{CHECKSYSTEM_NOMES}++; } #---------------------------------------------------------------------- # Выполним информационные команды #---------------------------------------------------------------------- if(defined $data{arg}{h} || defined $data{arg}{help}){ printmes("$data{'calcinstall'}\n\n"); printmes(gettext('Usage').": "); printmes("calculate ["); printmes(gettext('OPTION')); printmes("]...\n"); printmes("\n".gettext('Installation, compilation and updating of system')); printmes(".\n\n"); printmes(gettext('Mandatory arguments to long options are mandatory for short options too').".\n"); printmes(gettext('Similarly for optional arguments').".\n\n"); printmes(gettext('Location').":\n"); printmes(" -s, --os=[CLD|CLDG|CLDX|CLS|CSS|CDS] "); printmes(gettext('select operation system')); printmes(" (Calculate Linux Desktop KDE, Calculate Linux Desktop GNOME, Calculate Linux Desktop XFCE, Calculate Linux Scratch, Calculate Scratch Server, Calculate Directory Server)\n"); printmes(" -d, --disk=DISK\t"); printmes(gettext('installation or building system volume')."\n"); printmes(" -b, --build\t\t"); printmes(gettext('installation for assembling')."\n"); printmes(" -f, --force\t\t"); printmes(gettext('do not prompt before overwriting')."\n"); printmes("\n".gettext('Installation and Update').":\n"); printmes(" -a, --addition\t"); printmes(gettext('to establish additions')."\n"); printmes(" -U, --updateonly\t"); printmes(gettext('perform updates only')."\n"); printmes(" --set-[var]=value\t"); printmes(gettext('set config files parameter')."\n"); printmes(" --SET-[var]=value\t"); printmes(gettext('set config files parameter without check')."\n"); printmes(" -P, --profile=name[,name2...]\t"); printmes(gettext('apply configuration template (all - all templates)')."\n"); printmes("\n".gettext('System building').":\n"); printmes(" -l, --list\t\t"); printmes(gettext('show the package list incoming in the distributive file')."\n"); printmes(" -c, --configure\t"); printmes(gettext('prepare system for building')."\n"); printmes(" -D, --dependence\t"); printmes(gettext('check of dependences')."\n"); printmes(" -m, --make\t\t"); printmes(gettext('make system')."\n"); printmes(" -p, --pack\t\t"); printmes(gettext('pack the distribution package into the archive file')."\n"); printmes(" --iso\t\t\t"); printmes(gettext('create a loaded iso-image of system')."\n"); printmes(" --rebuild\t\t"); printmes(gettext('regenerate squashfs image on flash')."\n"); printmes(" --break\t\t"); printmes(gettext('break the system building')."\n"); printmes("\n".gettext('Additions assemble').":\n"); printmes(" -L [value]\t\t"); printmes(gettext('show the package list incoming in the addition')."\n"); printmes(" -M [value]\t\t"); printmes(gettext('make addition')."\n"); # printmes("\n".gettext('Setup server').":\n"); # printmes(" -S, --setup=[ldap|mail] "); printmes(gettext('setup and run servers')); # printmes("\n"); #, ftp, squid, apache # printmes(" --backup\t\t"); printmes(gettext('backup data of working servers')."\n"); # printmes("\n".gettext('Access management')); # printmes("\n ".gettext('User').":\n"); # printmes(" --useradd=value\t"); printmes(gettext('create a new user account')."\n"); # printmes(" --userdel=value\t"); printmes(gettext('delete a user account')."\n"); # printmes(" --userpasswd=value\t"); printmes(gettext('change user password')."\n"); # # printmes(" --groupadd=value\t"); printmes(gettext('create a new group')."\n"); # printmes(" --groupdel=value\t"); printmes(gettext('delete a group')."\n"); # printmes(" --groupmod=value [--set-useradd=value|--set-userdel=value] "); printmes(gettext('modify a group definition on the system')."\n"); # # printmes(" ".gettext('E-Mail').":\n"); # printmes(" --mailuseradd=value\t"); printmes(gettext('create a new email account')."\n"); # printmes(" --mailuserdel=value\t"); printmes(gettext('delete a email account')."\n"); # printmes(" --mailuserpasswd=value "); printmes(gettext('change a email account password')."\n"); # # printmes(" --mailgroupadd=value\t"); printmes(gettext('create a new email group')."\n"); # # printmes(" --mailgroupdel=value\t"); printmes(gettext('delete a email group')."\n"); # printmes("\n".gettext('Updating').":\n"); # printmes(" -u, --update\t\t"); printmes(gettext('download and install latest update available')."\n"); printmes("\n".gettext('Informative output').":\n"); printmes(" -h, --help\t\t"); printmes(gettext('display this help and exit')."\n"); printmes(" -v, --vars\t\t"); printmes(gettext('config files parameters')."\n"); printmes(" -H, --hardware\t"); printmes(gettext('show hardware information')."\n"); printmes(" -V, --version\t\t"); printmes(gettext('output version information and exit')."\n"); return ""; }elsif(defined $data{arg}{V} || defined $data{arg}{version}){ printmes("Copyright (C) 2006-2009 Mir Calculate Ltd.\n"); printmes(gettext('This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.')); printmes ("\n"); return ""; }elsif(defined $data{arg}{translate}){ printmes(gettext('Update lang translation file')); printmes("... "); if(-e "/usr/calculate/install"){ chdir("/usr/calculate/install"); #выполним локализацию пакета (для разработки) system "xgettext --join-existing --no-location --sort-output --language=Perl --from-code=UTF-8 --msgid-bugs-address=support@calculate.ru -o i18n/ru_RU/LC_MESSAGES/calculate.po calculate"; system "msgfmt -o i18n/ru_RU/LC_MESSAGES/calculate.mo i18n/ru_RU/LC_MESSAGES/calculate.po"; printmes(gettext('done')); printmes(".\n"); }else{ printmes(gettext('error')); printmes(".\n"); } return ""; } return 1; } #------------------------------------------------------------------------------ # # Отмонтируем все разделы диска если они монтированы к /media # #------------------------------------------------------------------------------ sub umountfrommedia{ # отмонтируем разделы у диска если они на /media # проверяем что все разделы диска замонтирована на media if(`$data{path} mount | grep -cP "$data{arg}{'disk'}\\S+ on /media"` == `$data{path} mount | grep -cP "$data{arg}{'disk'}\\S+ on /"`) { foreach(`$data{path} mount | grep -Po "$data{arg}{'disk'}\\S+"`) { chomp; printmes(' '.gettext('Unmounting volume')); printmes(" $_ "); printmes(gettext('from')); printmes( " /media..."); if( system("umount $_ &>/dev/null") ){ printmes(" ".gettext('error')."\n"); } else { printmes(" ".gettext('done')."\n"); } } } } #------------------------------------------------------------------------------ # # Проверим на ошибки # #------------------------------------------------------------------------------ sub checkerrors{ # флаг запущенного демона hald $data{hal} = ""; if(!system "lshal &>/dev/null"){$data{hal} = "on";} if(`mount | grep "on /mnt/scratch"` && $data{builder} && !$data{createiso} ){ printmes(gettext('Error')."! "); printmes(gettext('Unable prepare system for building in scratch mode').".\n"); return ""; } #---------------------------------------------------------------------- # Определим тип носителя #---------------------------------------------------------------------- if(!$data{'type'}){ $data{type} = check_removable(); } #в режиме scratch можно поставить только на жесткий диск if($data{type} eq "flash" && $data{scratch_ws}){ printmes(gettext('Scratch may be install only to hard drive')); printmes(".\n"); return ""; } #---------------------------------------------------------------------- # Предопределим диск для установки # инициируем: $data{data_install_set}, $data{partitions_dev} #---------------------------------------------------------------------- $data{data_install_set} = ""; $data{partitions_dev} = ""; if($data{arg}{'disk'}){ if($data{arg}{'disk'}!~m/^(\/dev\/)/ || !-e $data{arg}{'disk'}){ printmes(gettext('Incorrect partition')); printmes(" \"$data{arg}{'disk'}\".\n"); return ""; }elsif( $data{arg}{'disk'}!~m/[0-9]$/ || ($data{arg}{'disk'}=~m#^/dev/cciss/c[0-9]d[0-9]$#) ){ my $cciss; if($data{arg}{'disk'}=~m/cciss/){$cciss = "p";} # отмонтируем разделы диска из /media umountfrommedia(); if(`mount | grep "$data{arg}{'disk'}"` || `cat /proc/swaps | grep $data{arg}{'disk'}`){ printmes(gettext('On the disk is to mount partitions')."!\n"); beep(); return ""; } if($data{type} ne "flash"){ #проверим размер диска my $disk = $data{arg}{'disk'}; $disk =~m/\/([^\/]+)$/; $disk = "/sys/block/$1/size"; if(!-e $disk){ printmes(gettext('The size of the disk is not defined')."!\n"); beep(); return ""; }else{ open(F, $disk); my $size = ; close(F); chomp $size; $size*=512/1024/1024/1024; #переведем в гигабайты if($size < 45 && !defined $data{arg}{'vars'}){ printmes(gettext('The size of the disk is not sufficient to perform automatic partitioning')."!\n"); beep(); return ""; } } #устанавливаем во второй раздел диска $data{rootinstall} = $data{arg}{'disk'}.$cciss."2"; #раздел данных пятый $data{data_install_set} = $data{arg}{'disk'}.$cciss."5"; $data{partitions_dev} = $data{arg}{'disk'}; }else{ $data{rootinstall} = $data{arg}{'disk'}."1"; #устанавливаем в первый и единственный раздел $data{partitions_dev} = $data{arg}{'disk'}; } }else{ $data{rootinstall} = $data{arg}{'disk'}; } } #---------------------------------------------------------------------- # Проверим id пользователя, запустившего скрипт #---------------------------------------------------------------------- { my $id = `$data{path} id -u`; chomp $id; if($id > 0){ printmes(gettext('Only root can perform system installation')."!\n"); $data{NOLOG}++; #отключим лог, т.к. мы все равно в него ничего не сможем записать beep(); return ""; } } #---------------------------------------------------------------------- # Установим значение переменной в ram, в случае если установка профиля # производится в оперативную память (настройка сеанса CDROM), а также # load - носитель в значение ram в случае загрузки с CD/DVD # $data{location} # $data{scratch} #---------------------------------------------------------------------- $data{location} = ""; $data{load} = ""; if(`mount | grep "/dev/loop/0 on / type"` || `mount | grep "/dev/loop0 on / type"` || `mount | grep "/dev/loop0 on /newroot/mnt/livecd type"` ){ if(defined $data{arg}{'profile'}){ $data{location} = "ram"; } $data{load} = "ram"; } if(`mount | grep /mnt/scratch`){$data{scratch} = "on";} else{$data{scratch} = "off"} #---------------------------------------------------------------------- # Установим переменную полной загрузки системы в память # $data{load_cache} #---------------------------------------------------------------------- $data{load_cache} = "off"; if($data{load} eq "ram" && !`mount | grep " on /newroot/mnt/cdrom type "`){ $data{load_cache} = "on"; } #---------------------------------------------------------------------- # Путь к архиву образа #---------------------------------------------------------------------- #пути к архивам систем $data{linuxdir} = "/var/calculate/remote/linux"; #---------------------------------------------------------------------- # Определим и проверим директорию установки, директорию временных файлов #---------------------------------------------------------------------- my $tmpdir = ".tmp.".sprintf("%.0f", rand() * 9999999); if(!$data{tmpdir}){ if($data{createiso} && $data{load} eq 'ram'){ $data{tmpdir} = "$data{linuxdir}/$tmpdir"; }else{ $data{tmpdir} = "/var/calculate/tmp/$tmpdir"; } }else{ $data{tmpdir} .= "/$tmpdir"; } if(!$data{mount} && !defined $data{addition}){ if(!$data{builder}){ $data{mount} = "/mnt/install"; }else{ $data{mount} = "/mnt/builder"; } } if(defined $data{arg}{'unmask'}){ $data{'chroot'} = ''; }elsif(!$data{createiso}){ $data{'chroot'} = $data{mount}; }else{ $data{'chroot'} = "$data{tmpdir}/livecd"; } if(-e $data{mount} && !$data{builder_chroot} && !defined $data{arg}{'vars'} && !defined $data{arg}{'list'} && !$data{createiso}){ system "$data{path} rmdir $data{mount}" } if(-e $data{mount} && !$data{builder_chroot} && !defined $data{arg}{'vars'} && !defined $data{arg}{'list'} && !$data{createiso}){ printmes(gettext('Error')."! "); printmes(gettext('For continuation please remove directory')); printmes(" $data{mount} "); printmes(gettext('created by installer')."!\n"); beep(); return ""; }elsif($data{builder_chroot} && !defined $data{arg}{'vars'}){ my $mounts = 0; foreach(`$data{path} mount`){ if(/on\s+($data{chroot}\/[^\s]+)/){ $mounts++; } } if($mounts < 3){ printmes(gettext('For performance of operation it is necessary to configure system')); printmes(".\n"); printmes(gettext('Execute with parameter')); printmes(" \"--configure\".\n"); beep(); return ""; } } if($data{type} eq "flash" && !$data{partitions_dev}){ printmes(gettext('To install on USB-Flash, specify the device, not partition. For example "calculate -d /dev/sdb"')); printmes(".\n"); beep(); return ""; } #перечень возможных планировщиков @{$data{other}}{scheduler} = ['noop', 'cfq', 'deadline']; if( $data{scheduler} && ($data{scheduler} ne 'noop' && $data{scheduler} ne 'cfq' && $data{scheduler} ne 'deadline' ) ){ beep(); printmes(gettext('Wrong name of the Scheduler').".\n"); return ""; } return 1; } #------------------------------------------------------------------------------ # # Определим систему для установки или сборки # #------------------------------------------------------------------------------ sub welcome{ #---------------------------------------------------------------------- # Определим наименование устанавливаемой или обновляемой системы # %{$data{ver}}, $data{'calculate'}, $data{'calculatename'} #---------------------------------------------------------------------- #обозначение зарезервированных версий систем %{$data{ver}} = ( CLD => "Calculate Linux Desktop", CLDG => "Calculate Linux Desktop", CLDX => "Calculate Linux Desktop", CSS => "Calculate Scratch Server", CDS => "Calculate Directory Server", CLS => "Calculate Linux Scratch", CLSG => "Calculate Linux Scratch", ); %{$data{ver_desktop}} = ( CLD => "KDE", CLDG => "GNOME", CLDX => "XFCE", CLSG => "GNOME", ); #если передан параметр выбора системы, установим значения if($data{arg}{'os'}){ if($data{ver}{ uc($data{arg}{'os'}) }){ $data{'calculate'} = uc($data{arg}{'os'}); $data{'calculatename'} = $data{ver}{$data{calculate}}; }else{ $data{'calculate'} = $data{arg}{'os'}; # if(lc($data{'calculate'}) eq 'acoola'){$data{'calculate'} = "AcoolA";} $data{'calculatename'} = $data{'calculate'}; } #в противном случае определим по текущей #новым способом }elsif(getini(calculate)){ if($data{builder} && !defined $data{addition} && getini(calculate, 'chroot')){ $data{calculate} = getini(calculate, 'chroot'); }else{ $data{calculate} = getini(calculate); } $data{'calculatename'} = $data{ver}{$data{calculate}}; if(!$data{'calculatename'}){$data{'calculatename'} = $data{calculate}} }else{ #устанавливаемая или собираемая система по умолчанию if(!$data{'calculate'}){ $data{'calculate'} = "CLD"; $data{'calculatename'} = $data{ver}{$data{calculate}}; } } $data{'calculatesubname'} = ""; if($data{'calculate'}=~m/^CLD/){ @{$data{other}}{'calculatesubname'} = ["KDE", "XFCE"]; $data{'calculatesubname'} = $data{ver_desktop}{$data{calculate}}; }elsif($data{'calculate'}=~m/CLSG/){ $data{'calculatesubname'} = $data{ver_desktop}{$data{calculate}}; } #---------------------------------------------------------------------- # Получим тип системы # $data{system} #---------------------------------------------------------------------- if($data{'calculatename'}=~m/server/i || $data{'system'}=~m/server/i ){ $data{'system'} = 'server' }else{ $data{'system'} = 'desktop' } #---------------------------------------------------------------------- # Приветственное сообщение #---------------------------------------------------------------------- if($data{builder}){ printmes(gettext('Building')); printmes(" $data{'calculatename'}\n"); }elsif( defined $data{arg}{'opengl'} || defined $data{arg}{'initrd'} ){ #ничего не напишем }elsif( !defined $data{arg}{update} && !defined $data{arg}{'vars'} && !defined $data{arg}{'hardware'} && !defined $data{arg}{'profile'} && !defined $data{arg}{'setup'} && !defined $data{arg}{'backup'} && !defined $data{arg}{'useradd'} && !defined $data{arg}{'userdel'} && !defined $data{arg}{'userpasswd'} && !defined $data{arg}{'groupadd'} && !defined $data{arg}{'groupdel'} && !defined $data{arg}{'groupmod'} && # !defined $data{arg}{'mailuseradd'} && # !defined $data{arg}{'mailuserdel'} && # !defined $data{arg}{'mailuserpasswd'} && # !defined $data{arg}{'mailgroupadd'} && # !defined $data{arg}{'mailgroupdel'} !defined $data{arg}{'unmask'} ){ printmes(gettext('Installation')); printmes(" $data{calculatename} $data{'calculatesubname'}\n"); }else{ printmes("$data{calcinstall}\n"); } } #------------------------------------------------------------------------------ # # Соберем сведения о системе # #------------------------------------------------------------------------------ sub checksystem{ #отключим вывод сообщений if($data{CHECKSYSTEM_NOMES}){ $data{NOMES}++; }; printmes(gettext('Collecting system information')."\n"); #---------------------------------------------------------------------- # Выполним проверки доступности необходимых программ и определим пути # $data{exec_host}, $data{exec_nmap} #---------------------------------------------------------------------- if(!system "which host >/dev/null 2>&1"){$data{exec_host} = `which host`; chomp $data{exec_host};} if(!system "which nmap >/dev/null 2>&1"){$data{exec_nmap} = `which nmap`; chomp $data{exec_nmap};} if(!system "which wget >/dev/null 2>&1"){$data{exec_wget} = `which wget`; chomp $data{exec_wget};} #временная задержка перед выполнением операций над диском if($data{sleep}=~m/off/i || $data{sleep}=~m/no/i || $data{sleep}=~m/false/i){$data{sleep} = 0;} elsif($data{sleep} eq '' || $data{sleep}=~m/[^0-9]/){$data{sleep} = 10;} #подключение bar вместо cp if(-e "/usr/bin/bar"){ $data{run_bar} = "/usr/bin/bar"; }else{ $data{run_bar} = 'cp'; } #---------------------------------------------------------------------- # Считаем параметры ядра #---------------------------------------------------------------------- if($data{load} eq "ram" && -e "/proc/cmdline"){ #считаем параметры open(F, '/proc/cmdline'); my $cmdline = ; close(F); chomp $cmdline; $cmdline.=' '; #разобьем на переменные foreach(split / /,$cmdline){ if(/^calculate=(.+)/){ #разобьем на значения передаваемые для calculate ( $data{boot}{lang}, $data{boot}{keybd}, $data{boot}{timezone}, $data{boot}{video_resolution}, ) = split /,/,$1; last; } } $data{boot}{set} ++; } #---------------------------------------------------------------------- # Определим хэши паролей root/root, guest/guest # $data{hash_root}, $data{hash_guest} #---------------------------------------------------------------------- $data{hash_root} = 'root:$1$JMvNh5xg$VnV1DyJdTcwuZ0hp5YiJG0:14349:0:::::'; $data{hash_guest} = 'guest:$1$uSceexyH$vLQn4kh7NUzNqZtlrgEWF.:14349:0:99999:7:::'; #---------------------------------------------------------------------- # Определим тип операции # $data{pass} #---------------------------------------------------------------------- @{$data{other}}{'pass'} = ["profile", "builder", "install"]; if(defined $data{arg}{'profile'} || defined $data{arg}{'setup'}){ $data{pass} = "profile"; }elsif($data{builder}){ $data{pass} = "builder"; }else{ $data{pass} = "install"; } if(!$data{builder}){ if($data{erase} =~m/off/i ||$data{erase} =~m/no/i){ $data{erase} = "off"; }else{ $data{erase} = "on"; } }else{$data{erase} = "on";} #---------------------------------------------------------------------- # Определим номер версии клиента # $data{client} #---------------------------------------------------------------------- $data{client} = ""; my $clientfile = "/usr/lib/calculate/calculate-client/pym/cl_vars_client.py"; if($data{pass} eq "profile" && -e $clientfile){ $data{client} = `$data{path} cat $clientfile | grep " cl_ver "`; $data{client}=~s/.+'Calculate-client\s+([0-9\.]+).+/$1/; chomp $data{client}; } #---------------------------------------------------------------------- # Флаг выполнения make menuconfig ядра при сборке системы, # флаг пропуска первого пакета при возобновлении сборки. # $data{menuconfig}, $data{skipfirst} #---------------------------------------------------------------------- if($data{builder}){ if(!$data{menuconfig} || $data{menuconfig}=~m/^yes$/i || $data{menuconfig}=~m/^on$/i){ $data{menuconfig} = "on"; }else{ $data{menuconfig} = "off"; } if(!$data{skipfirst} || $data{skipfirst}=~m/^no$/i || $data{skipfirst}=~m/^off$/i){ $data{skipfirst} = "off"; }else{ $data{skipfirst} = "on"; } } #---------------------------------------------------------------------- # Определим графический режим фреймбуфера #---------------------------------------------------------------------- if(-e "/sys/class/graphics/fb0"){ $data{fb} = 'vesa'; }else{ $data{fb} = 'console'; } #---------------------------------------------------------------------- # Сгенерируем случайное время в минутах #---------------------------------------------------------------------- $data{rand_min} = sprintf("%.0f", rand() * 59); #---------------------------------------------------------------------- # Считаем имя компьютера # $data{hostname} #---------------------------------------------------------------------- printmes(" ".gettext('Computer name')); if(!$data{hostname}){ $data{hostname} = `$data{path} hostname -s 2>&1`; #упрощенный вариант, следует выполнять только если не указан домен в системе if($data{hostname}=~m/^hostname: /){ $data{hostname} = `$data{path} hostname 2>&1`; } if($data{hostname}=~m/^hostname: /){ $data{hostname} = $data{calculate}; printmes(": <"); printmes(gettext('undefined')); printmes(">\n"); }else{ chomp $data{hostname}; if($data{hostname} eq 'livecd'){$data{hostname} = $data{calculate};} printmes(": $data{hostname}\n"); } }else{ printmes(": $data{hostname}\n"); } #---------------------------------------------------------------------- # Определим домен # $data{domain} #---------------------------------------------------------------------- if(!$data{domain}){ $data{domain} = `$data{path} hostname -d 2>&1`; if($data{domain}=~m/^hostname: /){$data{domain} = "local";}else{chomp $data{domain};} } if($data{domain} ne 'local'){ printmes(" ".gettext('Domain name')); printmes(": $data{domain}\n"); } #---------------------------------------------------------------------- # Параметры пользователя по умолчанию #---------------------------------------------------------------------- if(!$data{user_comment}){$data{user_comment} = "CDS User";} if(!$data{user_groups}){$data{user_groups} = "";} if(!$data{mail} && $data{arg}{'mailuseradd'}){ $data{mail} = "$data{arg}{'mailuseradd'}\@$data{hostname}.$data{domain}"; }elsif($data{mail} && $data{mail}!~m/\@/ && $data{domain}){ $data{mail} = "$data{mail}\@$data{hostname}.$data{domain}"; } #---------------------------------------------------------------------- # Определим сетевые настройки: # шлюз, локальные интерфейсы, локальные сети, настройки /etc/conf.d/net, # сетевые устройства # $data{gateway}, $data{hostsallow}, $data{networks}, $data{netconf}, # $data{net_*} = on|off #---------------------------------------------------------------------- if(!$data{gateway}){ my $route = `$data{path} route -n | grep "^0.0.0.0"`; chomp $route; $route=~m/^0\.0\.0\.0\s+([0-9\.]+)\s.+\s+([^\s]+)$/; if($1){ $data{gateway} = $1; $data{gateway_dev} = $2; } } { printmes(" ".gettext('Network devices')); printmes(":"); #http://krow.net/dict/subnet.html my %net = ( "255.255.0.0" => "/16", "255.255.255.0" => "/24", "255.255.255.128" => "/25", "255.255.255.192" => "/26", "255.255.255.252" => "/30", "255.255.255.255" => "", ); #обнулим переменные my $sp = ""; my $dev = ""; my $dev_open = 1; my $br; my $gateway_dhcp; $data{netconf} = ""; $data{hostsallow} = ""; $data{networks} = ""; foreach(`ifconfig -a`){ #девайс if(/^([^\s]+)\s+.*Ethernet/){ if($dev_open == 0){ printmes("$br $dev (off)"); $data{"net_$dev"} = "off"; $br = ","; } $dev_open = 0; #девайс выключен, если не будет другой информации $dev = $1; } if(/inet addr:([0-9\.]+).+Bcast:.+Mask:([0-9\.]+)/){ my $addr = $1; my $mask = $2; my @ip = split /\./, $addr; if( $ip[0] == 10 || ($ip[0] == 172 && $ip[1] >= 16 && $ip[1] <= 31) || ($ip[0] == 192 && $ip[1] == 168) ){ $data{hostsallow} .= $sp.$addr.$net{$mask}; #определим сеть if($mask eq "255.255.255.255"){ $data{networks} .= $addr; }elsif($mask eq "255.255.255.252"){ $data{networks} .= "$ip[0].$ip[1].$ip[2].252".$net{$mask}; }elsif($mask eq "255.255.255.192"){ $data{networks} .= "$ip[0].$ip[1].$ip[2].192".$net{$mask}; }elsif($mask eq "255.255.255.128"){ $data{networks} .= "$ip[0].$ip[1].$ip[2].128".$net{$mask}; }elsif($mask eq "255.255.255.0"){ $data{networks} .= "$ip[0].$ip[1].$ip[2].0".$net{$mask}; }elsif($mask eq "255.255.0.0"){ $data{networks} .= "$ip[0].$ip[1].0.0".$net{$mask}; } $sp = " "; #определим получен ли IP через DHCP if( !-e "/var/lib/dhcpcd/dhcpcd-$dev.info" && !(-e "/var/lib/dhcp/dhclient.leases" && `grep $dev /var/lib/dhcp/dhclient.leases`) && !-e "/var/lib/dhcpcd/dhcpcd-$dev.lease" ){ $data{netconf} .= "\nconfig_$dev=( \"$addr$net{$mask}\" )"; printmes("$br $dev ($addr)"); }else{ $data{netconf} .= "\nconfig_$dev=( \"dhcp\" )"; if($dev eq $data{gateway_dev}){ $gateway_dhcp++; } printmes("$br $dev (DHCP)"); } $data{"net_$dev"} = "on"; $br = ","; }else{ $data{netconf} .= "\nconfig_$dev=( \"$addr$net{$mask}\" )"; } $dev_open = 1; if($data{calculate} ne "CLS" && $data{calculate} ne "CLSG"){ $data{netconf} .= "\nmodules_eth0=( \"!plug\" )"; } } } if($dev_open == 0){ printmes("$br $dev (off)"); $data{"net_$dev"} = "off"; } if($data{gateway_dev} && !$gateway_dhcp){ $data{netconf} .= "\nroutes_$data{gateway_dev}=( \"default gw $data{gateway}\" )"; } printmes("\n"); } if(!$data{netconf} && $data{load} eq "ram"){ $data{netconf} = "\nconfig_eth0=( \"dhcp\" )"; } #---------------------------------------------------------------------- # Получим версию обновляемой, наличие обновлений, название # устанавливаемой системы # $data{os}, $data{ospatch}, $data{ospatchsplit}, $data{linuxold} #---------------------------------------------------------------------- $data{os} = ''; $data{ospatch} = ''; $data{ospatchsplit} = ''; $data{linuxold} = ''; if(!$data{builder} || defined $data{addition} || $data{createiso}){ printmes(" ".gettext('Installed system').": "); if(getini(calculate) && getini(linuxver)){ $data{linuxold} = $data{ver}{getini(calculate)}; $data{os} = getini(linuxver); printmes("$data{linuxold} $data{os}\n"); if(getini(ospatch)){ $data{ospatch} = getini(ospatch); printmes(" ".gettext('Update')); printmes(": $data{ospatch}\n"); $data{ospatchsplit} = "-"; } # #для совместимости со старыми инсталляциями, проверим файл /etc/issue # }elsif(-e "/etc/issue" && `$data{path} cat /etc/issue | grep "Welcome to "`=~m#Welcome to \\n.\\O \(([a-zA-Z ]+) ([^\s\)]+)#){ # $data{linuxold} = $1; # { # my ($os, $patch) = split /-/, $2; #обрежем обновления # if($os > 0){ # $data{os} = "$os"; # if($patch){$data{ospatch} = $patch;} # } } # if(!$data{linuxold}){$data{linuxold} = $data{calcname};} # printmes("$data{linuxold} $data{os}\n"); # # if($data{ospatch}){ # printmes(" ".gettext('Update')); printmes(": $data{ospatch}\n"); # $data{ospatchsplit} = "-"; # } }elsif(-e "/etc/gentoo-release"){ $data{linuxold} = "Gentoo Linux"; printmes("$data{linuxold}\n"); }else{ $data{linuxold} = "Old Linux"; printmes("<"); printmes(gettext('undefined')); printmes(">\n"); } } printmes(gettext('Hardware')."\n"); #---------------------------------------------------------------------- # Получим производителя оборудования # $data{vendor}, $data{laptop}, $data{laptop_model} # $data{board_model}, $data{board_vendor} #---------------------------------------------------------------------- $data{laptop} = ""; if(-e "/sys/class/dmi/id/chassis_vendor"){ $data{vendor} = `cat /sys/class/dmi/id/chassis_vendor`; chomp($data{vendor}); if($data{vendor}=~m/^\s+$/ || $data{vendor}=~m/Chassis Manufacture/){ $data{vendor} = 'Chassis Manufacture'; } if( (-e "/sys/class/dmi/id/board_name" && `cat /sys/class/dmi/id/board_name | grep "Portable PC"`) || (-e "/sys/class/dmi/id/chassis_type" && (`cat /sys/class/dmi/id/chassis_type | grep "1"` || `cat /sys/class/dmi/id/chassis_type | grep "8"` || `cat /sys/class/dmi/id/chassis_type | grep "10"` ) ) ){ $data{laptop} = lc($data{vendor}); $data{laptop_model} = `cat /sys/class/dmi/id/product_name`; chomp ($data{laptop_model}); }elsif(-e "/sys/class/dmi/id/board_name" && -e "/sys/class/dmi/id/board_vendor"){ $data{board_model} = `cat /sys/class/dmi/id/board_name`; chomp ($data{board_model}); $data{board_vendor} = `cat /sys/class/dmi/id/board_vendor`; chomp ($data{board_vendor}); } } #---------------------------------------------------------------------- # Получим архитектуру процессора, файл stage, маску нестабильных файлов # $data{march}, $data{stage}, $data{unmask} #---------------------------------------------------------------------- { @{$data{other}}{'march'} = ["i686", "x86_64"]; printmes(" ".gettext('Machine hardware name')); printmes(":"); my $march = `$data{path} uname -m`; chomp $march; if($data{march} && $data{march} ne $march){ $data{dif_march} = "yes"; #флаг установки другой архитектуры }elsif(!$data{march}){ $data{march} = $march; } printmes(" $data{march}\n"); } if($data{march} eq 'i686'){ if($data{builder}){ $data{stage} = "stage3-i686"; } $data{unmask} = "~x86"; } elsif($data{march} eq 'x86_64'){ if($data{builder}){ $data{stage} = "stage3-amd64"; } $data{unmask} = "~amd64"; } elsif(!defined $data{arg}{'vars'}){ printmes("\n"); printmes(gettext('Machine hardware name')); printmes(" $data{march} "); printmes(gettext('not supported')); printmes(".\n"); printmes(gettext('Use value')); printmes(": \"i686\", \"x86_64\""); printmes(".\n"); beep(); exit; } #---------------------------------------------------------------------- # Определим версию последнего доступного образа системы, либо версию # собираемого образа, имя файла с образом, имя ISO-файла, который можно # собрать # $data{linuxver}, $data{linux}, $data{iso} #---------------------------------------------------------------------- #наложение профиля if(defined $data{arg}{'profile'}){ $data{linuxver} = $data{os}; #сборка системы }elsif($data{builder} && !$data{createiso} && !defined $data{addition}){ if(!$data{linuxver}){ if(getini("linuxver", "chroot")){ $data{linuxver} = getini("linuxver", "chroot"); }else{ #my $time = timelocal(localtime); #my ($month, $year) = (localtime($time))[4,5]; $month += 1; $year-=100; #$data{linuxver} = "$year.$month"; $data{linuxver} = "10.4"; 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(){ if(m/^KEYMAP="?([^"\n]+)"?/){ my $keymap = $1; foreach(keys %lang) { if( $lang{$_}[1] eq $keymap ) { $changekb = $_; last; } } last; } } close(F); } if($data{'arg'}{'set-lang'} || $data{'arg'}{'SET-lang'} || !$changekb){ $changekb = $data{lang}; } } #выберем язык и раскладку ($data{'locale'}, $data{'language'}, $data{'dictionary'}, ) = @{$lang{$data{lang}}}[0,9..10]; ($data{'keymap'}, $data{'dumpkeys_charset'}, $data{'consolefont'}, $data{'consoletranslation'}, $data{'xkblayout'}, $data{'kb_groups'}, $data{'kb_layout'}, $data{'country'}, ) = @{$lang{$changekb}}[1..8]; #неиспользуемые языки foreach(sort keys %lang){ if($lang{$_}[11] ne $data{language} && $lang{$_}[11]){ push(@{$data{clearlang}}, $lang{$_}[11]); } } printmes(" ".gettext('Language')); printmes(": $data{lang}\n"); printmes(" ".gettext('Keymap')); printmes(": $changekb\n"); #---------------------------------------------------------------------- # Временная зона #---------------------------------------------------------------------- #Системное время в гринвиче или локальное "UTC" или "local" if(!$data{clock} && -e "/etc/conf.d/hwclock"){ my $clock = `$data{path} cat /etc/conf.d/hwclock | grep "CLOCK="`; if($clock){ $clock=~m/\"([^\"]+)\"/; $data{clock} = $1; } } if(!$data{clock} && -e "/etc/conf.d/clock"){ my $clock = `$data{path} cat /etc/conf.d/clock | grep "CLOCK="`; if($clock){ $clock=~m/\"([^\"]+)\"/; $data{clock} = $1; } } if($data{clock}=~m/utc/i){$data{clock} = "UTC";} else{$data{clock} = "local";} if(!$data{timezone} && $data{boot}{timezone}){$data{timezone} = $data{boot}{timezone}} else{ if(!$data{timezone} && -e "/etc/timezone"){ $data{timezone} = `$data{path} cat /etc/timezone`; chomp $data{timezone}; } if(!$data{timezone} && -e "/etc/conf.d/clock"){ my $timezone = `$data{path} cat /etc/conf.d/clock | grep "TIMEZONE="`; if($timezone){ $timezone=~m/\"([^\"]+)\"/; $data{timezone} = $1; } } if(!$data{timezone} || ($data{timezone} && !-e "/usr/share/zoneinfo/$data{timezone}")){ $data{timezone} = "UTC"; } } printmes(" ".gettext('Timezone')); printmes(": $data{timezone}\n"); #---------------------------------------------------------------------- # Определим имя livecd.squashfs # $data{squash_cur}, $data{squash_del} #---------------------------------------------------------------------- my $revsquash = 0; #по умолчанию нулевая ревизия (к имени файла не подставляется) $data{squash_cur} = `cat /proc/cmdline | sed -nr 's/.*loop=\\/([^ ]+).*/\\1/p'`; chomp $data{squash_cur}; if(!$data{squash_cur} || $data{linux}=~m/iso$/){ $data{squash_cur} = "livecd.squashfs"; }else{ #определим ревизию $data{squash_cur}=~m/\.([0-9]+)$/; if($1){$revsquash = $1;} } $data{squash_del} = ""; if(-e "/mnt/flash/" && defined $data{arg}{rebuild}){ opendir(F, "/mnt/flash/"); foreach(readdir F){ if($_ eq "." || $_ eq ".."){next;} if($_=~m/^livecd\.squashfs\.?([0-9]+)?$/){ if($1 < $revsquash){$data{squash_del} = $_} } } closedir F; $revsquash ++; $data{squash_cur} = "livecd.squashfs.".$revsquash; } #---------------------------------------------------------------------- # Определим пакет тем для собираемой системы # $data{themes} #---------------------------------------------------------------------- if($data{builder}){ $data{themes} = ">media-gfx/calculate-".lc($data{calculate})."-themes-$data{linuxver}"; $data{themes}=~s/(.+\.?[^\.]+)(\.[0-9]+)?/$1-r9/; #обрежем подверсию #добавим ограничение на обновление темы для CLS, лежащий в основе других десктопов if($data{calculate} ne "CLS" && $data{system} eq 'desktop'){ my $cls = ">media-gfx/calculate-cls-themes-$data{linuxver}"; $cls=~s/(.+\.?[^\.]+)(\.[0-9]+)?/$1-r9/; #обрежем подверсию $data{themes}.="\n$cls"; } } #---------------------------------------------------------------------- # Определим количество процессоров # $data{cpus} #---------------------------------------------------------------------- { if(!$data{cpus}){ my (@cpus) = `$data{path} cat /proc/cpuinfo | grep processor`; $data{cpus} = @cpus; } printmes(" ".gettext('Quantity processors')); printmes(": ".$data{cpus}."\n"); } #---------------------------------------------------------------------- # Определим видеоадаптер # $data{video_drv}, $data{video}, $data{video_id} #---------------------------------------------------------------------- { #перечень поддерживаемых видеодрайверов @{$data{other}}{video_drv} = [ "fglrx", "intel", "nv", "nvidia", "radeon", "vesa", # "vboxvideo", "vmware" ]; my $drv; #определим драйвер видеокарты foreach(`$data{path} lspci | grep VGA`){ my $video = $_; #определим BusID $video=~m/^(.{2}):(.{2})\.([^\s+])/; $data{video_id} = "$1:$2:$3"; if($video=~m/GeForce/ || $video=~m/nVidia/){ if($video=~m/\[([^\]]+)\]/){$data{video} = $1;} elsif($video=~m/(GeForce.+) nForce/){$data{video} = $1;} elsif($video=~m/(GeForce.+) \(/){$data{video} = $1;} else{$data{video} = "GeForce";} $data{video} = "nVidia $data{video}"; if(!$data{video_drv}){ if( (($data{pass} eq "profile" && -e "/usr/lib/opengl/nvidia") || ($data{pass} eq "install" && ($data{calculate} ne "CLS" && $data{calculate} ne "CLSG" )) ) && ($data{load} ne "ram" || ($data{load} eq "ram" && !nvidia_mask()) ) ){ $drv = "nvidia"; }else{ $drv = "nv"; } }elsif($data{video_drv} eq 'nv' || $data{video_drv} eq 'nvidia'){ last; #завершим перебор, т.к. если есть другая видеокарта в системе, она нам явно не нужна } }elsif($video=~m/Intel/){ $video =~m/Intel Corporation ?(Mobile )([^\s,]+)?( Series)[\s,]/; if($2){$data{video} = "Intel $1$2$3";} else{$data{video} = "Intel";} if(!$data{video_drv}){ $drv = "intel"; }elsif($data{video_drv} eq 'intel'){ last; } }elsif($video=~m/ATI/){ $video =~m/ATI Technologies Inc ([^\(]+)\s*[\(|\s]?$/; if($1){ my $name = $1; chomp $name; $data{video} = "ATI $name"; }else{ $data{video} = "ATI"; } if(!$data{video_drv}){ #if( # ($data{pass} eq "profile" && -e "/usr/lib/opengl/ati") || # ($data{pass} eq "install" && # !($data{calculate} eq "CLD" && number_ver($data{linuxver}) < number_ver(9.6)) # ) #){ $drv = "radeon"; #}else{ # $drv = "fglrx"; #} }elsif( $data{video_drv} eq 'ati' || $data{video_drv} eq 'radeon' || $data{video_drv} eq 'radeonfb' || $data{video_drv} eq 'fglrx' ){ last; } }elsif($video=~m/VMware/i){ if(!$data{video_drv}){$drv = "vmware";} #}elsif($video=~m/VirtualBox/i && $data{calculate} eq "CLD"){ # if(!$data{video_drv}){$drv = "vboxvideo";} }else{ if(!$data{video_drv}){$drv = "vesa";} } #возьмем первую определившуюся видеокарту if(!$data{video_drv}){last;} } if($drv && !$data{video_drv}){$data{video_drv} = $drv} if($data{video} && !$data{builder}){ printmes(" ".gettext('Videocard')); printmes(": $data{video}\n"); } #определим opengl if(!$data{opengl}){ if($data{video_drv} eq "nvidia"){ $data{opengl} = "nvidia"; }elsif($data{video_drv} eq "fglrx"){ $data{opengl} = "ati"; }elsif( $data{video_drv} ne "vesa" && $data{video_drv} ne "vboxvideo" && $data{video_drv} ne "vmware" ){ $data{opengl} = "xorg-x11"; } } if($data{opengl} && !$data{run_opengl}){ $data{run_opengl} = "/usr/bin/eselect opengl set $data{opengl}" }else{ $data{run_opengl} = ""; } #сбросим BusID если в ПК одна видеокарта my @vga = `$data{path} lspci | grep VGA`; if($data{video_id} && @vga == 1){ $data{video_id} = ""; } } #---------------------------------------------------------------------- # Определим разрешение экрана # $data{resolution} #---------------------------------------------------------------------- { my $xlog = "/var/log/Xorg.0.log"; my $xconf = "/etc/X11/xorg.conf"; my $def_res = "1024x768"; if(!$data{video_resolution} && $data{boot}{set} && $data{pass} ne "install"){ $data{video_resolution} = $data{boot}{video_resolution}; if($data{video_resolution}!=~m/^[0-9]+x[0-9]+$/){$data{video_resolution} = 'auto'} }elsif(!$data{video_resolution}){ if(-e $xlog){ #считаем лог Xorg open (L, $xlog); my @xlog = ; 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 = ; close (L); my $log = join /\n/, @xconf; if($log=~m/Modes "([^\s"]+)[\s"]/){$data{video_resolution} = "$1";} } if($data{video_resolution} && !$data{builder}){ printmes(" ".gettext('Screen resolution')); printmes(": $data{video_resolution}\n"); } } if(!$data{video_resolution} && $data{video_drv} eq "vesa"){ $data{video_resolution} = "800x600" } if(!$data{video_resolution}){ $data{video_resolution} = $def_res; } } #---------------------------------------------------------------------- # Флаг включения композитного режима #---------------------------------------------------------------------- if(!$data{composite} && -e '/var/log/Xorg.0.log'){ if($data{video_drv} eq 'nvidia' || $data{video_drv} eq 'intel'){ open(F, '/var/log/Xorg.0.log'); foreach(){ if(m/Composite.*enabled/){$data{composite} = 'on'; last;} } close(F); } if(!$data{composite}){ $data{composite} = 'off'; } }elsif($data{composite}=~m/off/i || $data{composite}=~m/no/i || $data{composite}=~m/false/i){ $data{composite} = 'off'; }elsif($data{composite}=~m/on/i || $data{composite}=~m/yes/i || $data{composite}=~m/true/i){ $data{composite} = 'on'; }elsif($data{video_drv} eq 'nvidia' || $data{video_drv} eq 'intel'){ $data{composite} = 'on'; }else{ $data{composite} = 'off'; } #---------------------------------------------------------------------- # Определим наличие stage, portage # $data{stagepath}, $data{portagepath} #---------------------------------------------------------------------- if($data{builder} && !defined $data{addition} && !$data{createiso}){ $data{stagepath} = "/var/calculate/remote/stages"; #определим максимальную версию stage нашей архитектуры, либо подставим маску my $stage; opendir(STAGE, $data{stagepath}); foreach(readdir STAGE){ if($_ eq "." || $_ eq ".."){next;} if($_=~m/^$data{stage}/ && $stage lt $_){$stage = $_;} } closedir STAGE; if($stage){$data{stage} = $stage}else{$data{stage} = $data{stage}."-YYYYMMDD.tar.bz2"} #определим наличие CLS if($data{calculate} ne 'CLS' && $data{system} eq 'desktop'){ my $stage; opendir(STAGE, $data{linuxdir}); foreach(readdir STAGE){ if($_ eq "." || $_ eq ".."){next;} if($_=~m/^cls\-[0-9\.]+\-$data{march}\.iso$/ && $stage lt $_){$stage = $_;} } closedir STAGE; if($stage){$data{stage} = $stage} $data{menuconfig} = "off"; } if(!-e "$data{stagepath}/$data{stage}" && !-e "$data{linuxdir}/$data{stage}" && !defined $data{arg}{'vars'} ){ if(!-e $data{stagepath}){ printmes(" ".gettext('Create directory')); printmes(" stages..."); system "$data{path} mkdir $data{stagepath}"; printmes(" ".gettext('done')); printmes(".\n"); } printmes("\n"); printmes(gettext('To continue copy file')); printmes(" \"$data{stage}\" "); printmes(gettext('to directory')); printmes(" \"$data{stagepath}\".\n"); beep(); exit; } $data{portagepath} = "/var/calculate/remote/snapshots"; if(!-e $data{portagepath}){ printmes(" ".gettext('Create directory')); printmes(" snapshots..."); system "$data{path} mkdir $data{portagepath}"; printmes(" ".gettext('done')); printmes(".\n"); }else{ #найдем последнюю версию портежей my $last = 0; opendir(DIR, $data{portagepath}); foreach(readdir DIR){ if($_!~/^portage-([0-9]+).tar.bz2$/){next;} if($last < $1){$last = $1;} } closedir DIR; if($last){ $data{portage} = "portage-$last.tar.bz2"; } } if(!$data{portage} && !defined $data{arg}{'vars'} && $data{stage} !~m/iso$/){ printmes("\n"); printmes(gettext('To continue copy file')); printmes(" \"portage-YYYYMMDD.tar.bz2\"\n"); printmes(gettext('to directory')); printmes(" \"$data{portagepath}\".\n"); beep(); exit; } printmes(" ".gettext('Last available stage version')); printmes(": $data{stage}\n"); if($data{stage} !~m/iso$/){ printmes(" ".gettext('Last available portage version')); printmes(": $data{portage}\n"); } } #---------------------------------------------------------------------- # Пути к директориям пакетов сборки # @{$data{packages}) #---------------------------------------------------------------------- @{$data{packages}} = ( "$data{dir}/install/builder/packages", "/usr/calculate/share/builder/packages", ); #---------------------------------------------------------------------- # Получим список доступных патчей # $data{patchdir}, %{$data{patches}}, $data{patchlast} #---------------------------------------------------------------------- if($data{os}){ if(!$data{patchdir}){ $data{patchdir} = "/usr/calculate/share/patch"; #путь к директории обновлений } if($data{patchlast} eq ''){ $data{patchlast} = $data{ospatch}; } opendir(DIR, $data{patchdir}); foreach(readdir DIR){ if($_!~/^$data{calculate}\-$data{os}\-([0-9]+)$/){next;} #файлы с патчами должны быть в формате Система-версия-номер (прим. Drage-7.12-1) if($1 > $data{ospatch}){ ${$data{patches}{$_}}++; } if(!$data{arg}{"set-patchlast"} && substr($data{patchlast},1) < $1){$data{patchlast} = $1;} } closedir DIR; if(%{$data{patches}}){ printmes(" ".gettext('Available updates').": "); foreach(sort keys %{$data{patches}}){ printmes($_." "); } printmes("\n"); } } #---------------------------------------------------------------------- # Прекратим собирать сведения, # при обновлении системы, или упаковке в ISO образ #---------------------------------------------------------------------- if(defined $data{arg}{'updateonly'}){return '';} printmes(gettext('Location')."\n"); #---------------------------------------------------------------------- # Заголовок изменённых файлов # $data{mestitle} #---------------------------------------------------------------------- if(!$data{mestitle}){ $data{mestitle} = "# Changed by $data{calcname} "; $data{mestitle}.=$data{calcver}; } if(!$data{mesline}){$data{mesline} = "#------------------------------------------------------------------------------";} #---------------------------------------------------------------------- # Определим диск, с которого загружена система # $data{load} #---------------------------------------------------------------------- if(`$data{path} mount | grep "[0-9] on / type"`=~m/^(\/dev\/[^\s]+)/){ $data{rootload} = $1; printmes(" ".gettext('Working volume')); printmes(": $data{rootload}\n"); }else{ $data{rootload} = ""; printmes(" ".gettext('Working volume')); if($data{load} eq "ram"){ printmes(": ram\n"); }elsif(`$data{path} mount | grep "sd[a-f][0-9] on /newroot type"`){ printmes(": <"); printmes(gettext('scratch')); printmes(">\n"); }else{ printmes(": <"); printmes(gettext('undefined')); printmes(">\n"); } } #---------------------------------------------------------------------- # Определим диск для установки # $data{rootinstall} #---------------------------------------------------------------------- if( !$data{arg}{'profile'} && !$data{builder_chroot} && !defined $data{arg}{'update'} && !defined $data{arg}{'list'} && !defined $data{addition} && !$data{createiso} && !defined $data{arg}{'initrd'} && !defined $data{arg}{'opengl'} && !defined $data{arg}{'unmask'} ){ #выберем альтернативный диск для установки if(!$data{rootinstall} && getini("install.from")){ $data{rootinstall} = "/dev/".getini("install.from"); }elsif(!$data{rootinstall} && getini("install.devfrom")){ $data{rootinstall} = getini("install.devfrom"); }elsif(!$data{rootinstall}){ #проверим на схему 2-х /root разделов, предложив второй if($data{rootload} && $data{rootload}=~m/([23])$/){ my $install; if($1 == 2){ $install = 3; }else{ $install = 2; } #получим диск $install = substr($data{rootload},0,length($data{rootload})-1).$install; #проверим на существование и на доступность if(-e $install && !`mount | grep '^$install '`){ $data{rootinstall} = $install; } } } #проверим на существование диска if( !-e "$data{rootinstall}" && !defined $data{arg}{'vars'} && !$data{partitions_dev} ){ beep(); printmes("\n".gettext('Please specify installation volume')); printmes(" (... --disk=/dev/sdXX).\n"); savelog(); exit; } }elsif($data{builder_chroot}){ #определим подмонтированный раздел в который производится установка foreach(`$data{path} mount | grep "$data{mount} "`){ if(m#^(/dev/[^\s]+) on $data{mount} type#){ $data{rootinstall} = $1; last; } } }else{ $data{rootinstall} = $data{rootload}; } if(!$data{builder}){ printmes(" ".gettext('Installation volume')); }else{ printmes(" ".gettext('Volume for system building')); } printmes(": $data{rootinstall}"); #---------------------------------------------------------------------- # Определим является ли диск установки USB-HDD устройством # определим временную задержку для корректной инициализации root-раздела # USB устройства # $data{'removableinstall'}, $data{grub_delay} #---------------------------------------------------------------------- if($data{type} ne 'hdd'){ $data{'removableinstall'} = 'on'; if($data{type} eq 'flash'){ printmes(" (USB-Flash)"); }else{ printmes(" (USB-HDD)"); } if(!$data{grub_delay}){ $data{grub_delay} = " scandelay=5"; } }else{ $data{'removableinstall'} = 'off'; if(!$data{grub_delay}){ $data{grub_delay} = ""; } } printmes("\n"); #---------------------------------------------------------------------- # Определим является ли текущий диск USB-HDD устройством # $data{'removableload'} #---------------------------------------------------------------------- $data{'removableload'} = 'off'; if($data{load} ne 'ram' && $data{rootload}){ $data{rootload} =~m#/dev/(.+)#; my $disk = $1; if(-e "/dev/disk/by-id" && `LANG=C ls -la /dev/disk/by-id/ | grep $disk | grep ' usb-'`){ $data{'removableload'} = 'on'; } } #---------------------------------------------------------------------- # Укажем доступные варианты дисков для установки #---------------------------------------------------------------------- { my @disks; foreach(`$data{path} LANG=C fdisk -l 2>&1`){ if(m/^(\/dev\/[^\s]+)\s/ && !m/Extended$/ && !m/Linux swap/){ push (@disks, $1); } } @{$data{other}}{rootinstall} = [@disks]; } #---------------------------------------------------------------------- # Флаги переноса конфигурационных файлов #---------------------------------------------------------------------- if( (!$data{move_fstab} || $data{move_fstab}=~m/^yes$/i || $data{move_fstab}=~m/^on$/i) && ($data{'removableload'} eq $data{'removableinstall'}) && !$data{partitions_dev} ){ $data{move_fstab} = "on"; }else{ $data{move_fstab} = "off"; } #---------------------------------------------------------------------- # Флаг установки с использованием UUID #---------------------------------------------------------------------- if($data{uuid}=~m/^yes$/i || $data{uuid}=~m/^on$/i || (!$data{uuid} && $data{'removableload'} eq 'on') ){ $data{uuid} = "on"; }else{ $data{uuid} = "off"; } #---------------------------------------------------------------------- # Выбор планировщика #---------------------------------------------------------------------- if(!$data{scheduler}){ if( -e "/sys/block/sda/queue/scheduler" ) { my $scheduler = `cat /sys/block/sda/queue/scheduler`; $scheduler=~m/.*\[([^\]]+)\].*/; $data{scheduler} = $1; } if($data{'removableload'} eq 'on' || !$data{scheduler}){ if($data{system} eq 'server'){ $data{scheduler} = 'elevator'; } else{ $data{scheduler} = 'cfq'; } } } #---------------------------------------------------------------------- # Считаем uuid загрузочного диска, определим его метку # $data{uuid_load}, $data{root_load_set} #---------------------------------------------------------------------- $data{uuid_load} = ""; $data{root_load_set} = ""; if($data{'uuid'} eq 'on' && $data{rootload}){ $data{uuid_load} = uuid($data{rootload}, UUID); $data{root_load_set} = "UUID=$data{uuid_load}"; }else{ $data{root_load_set} = $data{rootload}; } #---------------------------------------------------------------------- # Считаем uuid установочного диска, определим его метку # $data{uuid_install}, $data{root_install_set} # после форматирования, значение изменится, # но для наложения профиля значение переменной root_install_set понадобится #---------------------------------------------------------------------- $data{uuid_install} = ""; $data{root_install_set} = ""; if($data{rootinstall}){ $data{uuid_install} = uuid($data{rootinstall}, UUID); if($data{'uuid'} eq 'on'){ $data{root_install_set} = "UUID=$data{uuid_install}"; }else{ $data{root_install_set} = $data{rootinstall}; if($data{root_install_set} =~m/cciss/){ $data{root_install_set} =~s#(/dev/cciss)/(.+)#$1!$2#; } } } #---------------------------------------------------------------------- # Определим параметр инф. узлов для файловой системы ext2/3 # для переменной $data{formatrun} #---------------------------------------------------------------------- my $node; { my @i = split "/", $data{rootinstall}; my $dev = @i[@i-1]; $dev=~m/^(.+)[0-9]+$/; $dev = "/sys/block/$1/$dev/size"; if(-e $dev){ open(F, $dev); my $size = ; 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 = ; 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(); close(F); if(@{$data{mount_dev}} && !$data{builder}){ printmes(" ".gettext('Mounted disks')); printmes(": @{$data{mount_dev}}\n"); } } #---------------------------------------------------------------------- # Определим наличие сети #---------------------------------------------------------------------- $data{lan} = "off"; foreach(`$data{path} LANG=C ifconfig -s`){ if(m/^Iface\s+/ || m/^lo\s+/){next;} $data{lan} = "on"; last; } #---------------------------------------------------------------------- # Определим наличие настроенных сетевых интерфейсов # $data{netstat} #---------------------------------------------------------------------- $data{netstat} = 'off'; foreach(`$data{path} route -n`){ if(!m/^127\.0\./ && m/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\s+/){ $data{netstat} = 'on'; last; } } #---------------------------------------------------------------------- # Определим сетевые сервисы # $data{proxy}, $data{useproxy}, $data{proxy_port}, $data{http_proxy}, # $data{nfs}, $data{ntp} #---------------------------------------------------------------------- $data{useproxy} = 'off'; $data{proxy_port} = ''; $data{http_proxy} = ''; $data{nfs} = ''; $data{ntp} = ''; if(!$data{builder} && $data{netstat} eq 'on' && !defined $data{arg}{'initrd'} && !defined $data{arg}{'opengl'} && !defined $data{arg}{'unmask'} && !defined $data{arg}{'video'} && $data{lan} eq 'on' && $data{domain} ne 'local'){ printmes(gettext('Network services')."\n"); #определим прокси-сервер if( $data{proxy} || ($data{exec_host} && $data{domain} && `$data{exec_host} proxy.$data{domain} | grep "has address"`) ){ my $proxy; if($data{proxy}){$proxy = $data{proxy};}else{$proxy = "proxy.$data{domain}";} foreach("3128","8080"){ if(IO::Socket::INET -> new(PeerAddr => "$proxy:$_", Proto => "tcp", Timeout => 1)){ $data{proxy} = $proxy; $data{proxy_port} = $_; printmes(" PROXY: $data{proxy}:$data{proxy_port}\n"); if(!$data{http_proxy}){$data{http_proxy} = "http://$data{proxy}:$data{proxy_port}/";} last; } } if($data{proxy} && !$data{proxy_port}){$data{proxy} = "";} } if($data{proxy}){$data{useproxy} = 'on'}else{$data{useproxy} = 'off'} #определим наличие сетевой файловой системы if( $data{exec_host} && !$data{nfs} && $data{domain} && `$data{exec_host} nfs.$data{domain} | grep "has address"` && IO::Socket::INET -> new(PeerAddr => "nfs.$data{domain}:2049", Proto => "tcp", Timeout => 1) ){ $data{nfs} = "nfs.$data{domain}"; } if($data{nfs}){printmes(" NFS: $data{nfs}\n");} #определим наличие локального сервера времени if(!$data{ntp}){ if( $data{exec_host} && $data{domain} && `$data{exec_host} ntp.$data{domain} | grep "has address"` ){ #определим не является ли компьютер сам источником времени my $ip, $iplan; $ip = `$data{exec_host} ntp.$data{domain} | grep "has address"`; $ip=~s/.+\s+([0-9\.]+)$/$1/; foreach(`LANG=C ifconfig | grep "inet addr:"`){ $iplan = $_; $iplan=~s/.+inet addr:([0-9\.]+)\s+.+/$1/; if($iplan eq $ip){last;} } if($iplan ne $ip){ $data{ntp} = "ntp.$data{domain}"; } } if(!$data{ntp}){$data{ntp} = "ntp0.zenon.net";} } printmes(" NTP: $data{ntp}\n"); } if(!$data{ntp}){$data{ntp} = "ntp0.zenon.net";} #---------------------------------------------------------------------- # Проверим наличие сервера CDS # $data{server_url}, $data{server} #---------------------------------------------------------------------- if(!$data{server_url}){ if(-e "/var/calculate/calculate2.env" || -e "/var/calculate/calculate.env"){ #считаем переменную адреса сервера if(-e "/var/calculate/calculate2.env"){open (F, "/var/calculate/calculate2.env");} else{open (F, "/var/calculate/calculate.env");} foreach(){ chomp; if(m/^cl_remote_host\s?=\s?(.+)$/){ $data{server_url} = $1; } } close (F); } } if(!$data{builder} && ($data{system} eq 'desktop') && $data{netstat} eq 'on' && !defined $data{arg}{'initrd'} && !defined $data{arg}{'opengl'} && !defined $data{arg}{'unmask'} && !defined $data{arg}{'video'} && $data{lan} eq 'on' && $data{server_url} ){ if( ( number_ver($data{linuxver}) >= number_ver('9.6') && `grep ldap /etc/nsswitch.conf` ) || ( $data{exec_nmap} && ( $data{server_url} =~m/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/i || ($data{exec_host} && `$data{exec_host} $data{server_url} | grep "address"`) ) && `$data{exec_nmap} --system-dns -p 389 $data{server_url} | grep open` ) ){ $data{server} = "CDS"; printmes(" ".gettext('Authentification')); printmes(": LDAP\n"); }else{ $data{server} = "off"; printmes(" ".gettext('Authentification')); printmes(": localhost\n"); } } #---------------------------------------------------------------------- # Настройки PDC # $data{samba_domain} #---------------------------------------------------------------------- if($data{calculate} eq "CDS"){ $data{samba_domain} = "CDS"; $data{samba_netbios} = "PDC-CDS"; } #---------------------------------------------------------------------- # Определим путь к LDAP-записям пользователей # $data{ldap_base}, $data{ldap_hash_encrypt}, $data{ldap_bindname}, $data{ldap_bind}, # $data{ldap_bindpw}, $data{ldap_bindpw_hash}, $data{ldap_root_tmp}, $data{ldap_rootpw_tmp}, # $data{ldap_rootname}, $data{ldap_root}, $data{ldap_rootpw}, $data{ldap_rootpw_hash} #---------------------------------------------------------------------- if(-e "/var/calculate/calculate2.env" || -e "/var/calculate/calculate.env"){ if(-e "/var/calculate/calculate2.env"){open (F, "/var/calculate/calculate2.env");} else{open (F, "/var/calculate/calculate.env");} foreach(){ chomp; #базовый суффикс if(m/^ld_services_dn\s?=\s?(.+)$/){ if(!$data{ldap_base}){$data{ldap_base} = "$1";} } if(m/^ld_unix_dn\s?=\s?(.+)$/){ if(!$data{ldap_root}){$data{ldap_root} = "$1";} } if(m/^ld_bind_dn\s?=\s?(.+)$/){ if(!$data{ldap_bind}){$data{ldap_bind} = "$1";} } if(m/^ld_bind_pw\s?=\s?(.+)$/){ if(!$data{ldap_bindpw}){$data{ldap_bindpw} = "$1";} } } close (F); } #базовый суффикс if($data{calculate} eq "CDS" || $data{server} eq "CDS"){ if(!$data{ldap_base}){$data{ldap_base} = "dc=CDS";} } #алгоритм шифрования паролей if($data{calculate} eq "CDS"){ $data{ldap_hash_encrypt}='{SSHA}'; } #пользовательский доступ к базе с доступом только для чтения if($data{calculate} eq "CDS" || $data{server} eq "CDS"){ $data{ldap_bindname} = "proxyuser"; if(!$data{ldap_bind}){ $data{ldap_bind} = "cn=$data{ldap_bindname},".$data{ldap_base}; } if(!$data{ldap_bindpw}){ $data{ldap_bindpw} = "CDS"; } } # if($data{calculate} eq "CDS"){ # $data{ldap_bindpw_hash} = `$data{path} slappasswd -s $data{ldap_bindpw} -h $data{ldap_hash_encrypt}`; # chomp $data{ldap_bindpw_hash}; # } #временный пользователь root для инициализации базы данных # if($data{calculate} eq "CDS"){ # $data{ldap_root_tmp} = "cn=ldaproot,".$data{ldap_base}; # $data{ldap_rootpw_tmp} = password(); # $data{ldap_rootpw_tmp_hash} = `$data{path} slappasswd -s $data{ldap_rootpw_tmp} -h $data{ldap_hash_encrypt}`; # chomp $data{ldap_rootpw_tmp_hash}; # } #постоянный пользователь root, прописываемый в базу при первой загрузке #с одновременным удалением временного root-а if($data{calculate} eq "CDS" || $data{server} eq "CDS"){ $data{ldap_rootname} = "ldapadmin"; if(!$data{ldap_root}){ $data{ldap_root} = "cn=$data{ldap_rootname},".$data{ldap_base}; } if(-e "/etc/smbldap-tools/smbldap_bind.conf"){ $data{ldap_rootpw} = `cat /etc/smbldap-tools/smbldap_bind.conf | grep masterPw`; chomp $data{ldap_rootpw}; $data{ldap_rootpw}=~s/[^=]+="(.+)"/$1/; } #если пароля нет, сгенерируем if(!$data{ldap_rootpw} || $data{ldap_rootpw} eq 'secret'){ $data{ldap_rootpw} = password(); } } # if($data{calculate} eq "CDS"){ # $data{ldap_rootpw_hash} = `$data{path} slappasswd -s $data{ldap_rootpw} -h $data{ldap_hash_encrypt}`; # chomp $data{ldap_rootpw_hash}; # } #---------------------------------------------------------------------- # Определим запущенные сервисы CDS # $data{up-*} #---------------------------------------------------------------------- if(!$data{builder} && $data{calculate} eq "CDS"){ foreach("ldap", "mail", "ftp"){ if(getini("up.$_") eq "on"){ $data{"up_".$_} = "on"; }else{ $data{"up_".$_} = "off"; } } } #---------------------------------------------------------------------- # Определим профили установки или сборки # @{$data{profile_install}}, @{$data{profile_share}} #---------------------------------------------------------------------- if(!$data{builder} && $data{type} ne "flash"){ printmes(gettext('Installation templates')."\n"); { #считаем базовые профили установки my %profiles; opendir(PROFILES, "$data{dir}/install/profile"); foreach(readdir PROFILES){ if($_ eq "." || $_ eq ".."){next;} $profiles{$_}++; } closedir PROFILES; #определим базовые профили установки my @profile; foreach(sort keys %profiles){ if( (m/^[0-9]/ || m/^$data{calculate}$/ || m/^$data{calculate}\?.+/ || m/^$data{system}$/ || m/^$data{system}\?.+/ ) && check_name($_) ){ push (@{$data{profile_install}}, "$data{dir}/install/profile/$_"); my $name = $_; $name=~s/^([^\?]+)\?(.+)/$1/; push (@profile, $name); } } printmes(" ".gettext('Basic')); printmes(": ".join (", ", @profile)."\n"); #считаем дополнительные профили установки my %profiles; opendir(PROFILES, "/usr/calculate/share/profile"); foreach(readdir PROFILES){ if($_ eq "." || $_ eq ".."){next;} $profiles{$_}++; } closedir PROFILES; #определим дополнительные профили установки #пропустим, если производится установка на извлекаемый диск #либо наоборот, с внешнего диска на ПК my @profile; if(!($data{pass} eq 'install' && $data{'removableload'} ne $data{'removableinstall'})){ foreach(sort keys %profiles){ if( (m/^[0-9]/ || $_=~m/^$data{calculate}$/ || m/^$data{system}$/) && check_name($_) ){ push (@{$data{profile_share}}, "/usr/calculate/share/profile/$_"); my $name = $_; $name=~s/^(.+)\?(.+)/$1/; push (@profile, $name); } } #проверим профили домена my ($i, $domain); foreach(reverse split /\./, "$data{hostname}.$data{domain}"){ $i++; if($domain){$domain = "$_.$domain"}else{$domain = "$_"} if($i > 1){ if($profiles{$domain}){ #если профиль присутствует на диске push (@{$data{profile_share}}, "/usr/calculate/share/profile/$domain"); push (@profile, $domain); } } } #проверим профиль компьютера if($data{hostname} && $profiles{$data{hostname}}){ push (@{$data{profile_share}}, "/usr/calculate/share/profile/$data{hostname}"); push (@profile, $data{hostname}); } } #покажем найденные профили if(@profile){ printmes(" ".gettext('Additional')); printmes(": ".join (", ", @profile)."\n"); } } }else{ #Считаем профили для различных этапов сборки my $path = "$data{dir}/install/builder/profile"; opendir(DIR, $path); foreach(readdir DIR){ if($_ eq "." || $_ eq ".."){next;} if( (m/^[0-9]/ && !defined $data{arg}{'pack'} && !$data{createiso}) || ($_ eq "IMG" && defined $data{arg}{'pack'}) || ($_ eq "ISO" && $data{createiso}) ){ push (@{$data{profile_install}}, "$path/$_"); } } closedir DIR; } #---------------------------------------------------------------------- # Определим путь к сборке дистрибутива в chroot окружении # $data{builder} #---------------------------------------------------------------------- #директория установки if(!$data{builderdir}){ $data{builderdir} = "/mnt/calculate"; } #---------------------------------------------------------------------- # Определим переменные окружения emerge и команду запуска emerge # $data{makeopts}, $data{distdir}, $data{pkgdir} # $data{emergerun1}, $data{emergerun2} #---------------------------------------------------------------------- { if(!$data{makeopts}){ my $makecpu; if($data{cpus} == 1){ $makecpu = $data{cpus}; }else{ $makecpu = $data{cpus} + 1; } $data{makeopts} = "-j$makecpu"; } if(!$data{distdir}){ $data{distdir} = "/var/calculate/remote/distfiles"; } if(!$data{pkgdir}){ $data{pkgdir} = "/var/calculate/remote/packages/$data{calculate}/$data{linuxver}/$data{march}"; } #$data{emergerun1} = ""; #$data{emergerun2} = ""; if($data{builder}){ if(!defined $data{addition}){ $data{emergerun1} = "$data{path} chroot $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 = ; close(U); open(G, "/etc/group") or die "Ошибка открытия файла: $!"; my @GROUP = ; 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=; $/ = $tmp; # close (F); # # my $checksum; # foreach(split "\n", $md5sum){ # my ($md5, $file) = split " "; # if($file eq $data{linux}){ # $checksum = $md5; # break; # } } # if($checksum){ # printmes(" ".gettext('Check the checksum')); printmes(": $data{linux}..."); # # if(system("$data{path} md5sum $data{linuxdir}/$data{linux} | grep $checksum &>/dev/null")){ # beep(); # printmes(" ".gettext('error').".\n"); # return ""; # }else{ # printmes(" ".gettext('done').".\n"); # } } } } return 1; } #------------------------------------------------------------------------------ # # Распакуем систему или stage, portage архивы # #------------------------------------------------------------------------------ sub extract{ if($data{sleep} > 0){ if($data{erase} eq 'on'){ printmes("\n".gettext('Volume formatting will start through')); }else{ printmes("\n".gettext('System will install over')); } printmes(" $data{sleep} "); printmes(gettext('seconds')); printmes(".\n"); printmes(gettext('Press')); printmes(" Ctrl+C "); printmes(gettext('to cancel')); printmes("... "); my $sleep = $data{sleep} - 1; if(system(q|echo -e -n "\a|.$data{sleep}.q|"; sleep 1; for ((i=|.$sleep.q|; $i>0; i--)); do echo -e -n "\a\b\b $i"; sleep 1; done; echo -e "\b\b ";|)){ printmes("\n"); return ""; } } if($data{erase} eq 'on'){ if(!$data{builder}){ printmes(gettext('Unpacking system')."\n"); }else{ printmes(gettext('Prepare installation volume')); printmes("\n"); } if($data{partitions_dev} && $data{type} ne "flash"){ printmes(" ".gettext('Perform hard disk partition')); printmes("... "); #выполним разбиение диска if(system("$data{path} cat /usr/calculate/install/config/fdisk.$data{system} | fdisk $data{partitions_dev} &>/dev/null")){ printmes(gettext('Error')); printmes("! "); return ""; } printmes(gettext('done').".\n"); # отмонтируем разделы если они примонтировались # в /media после разбиения диска umountfrommedia(); printmes(" ".gettext('Set up a Linux swap area')); printmes("... "); if(system("$data{path} mkswap $data{partitions_dev}1 &>/dev/null")){ printmes(gettext('Error')); printmes("! "); return ""; } printmes(gettext('done').".\n"); # После форматирования считаем uuid диска свопа, переопределим его метку my $uuid_swap = uuid("$data{partitions_dev}1", UUID); $data{swap} = "$data{partitions_dev}1"; $data{uuid_swap} = $uuid_swap; chomp $data{uuid_swap}; swapset(); #изменим $data{swapset} и $data{swap_resume} printmes(" ".gettext('Formatting a partition for the data')); printmes("... "); if(system("$data{formatrun} Data $data{partitions_dev}5 &>/dev/null")){ printmes(gettext('Error')); printmes("! "); return ""; } # проверим нужно ли менять id для раздела my $changeid=1; foreach(`fdisk -l 2>&1`) { if(m/^$data{partitions_dev}5\s+[*]?\s+\d+\s+\d+\s+\d+\s+$data{disktypeid}|GPT.*detected/) { $changeid=0; last; } } system("echo -e \"t\n5\n$data{disktypeid}\nw\n\" | fdisk $data{partitions_dev} &>/dev/null") if $changeid; printmes(gettext('done').".\n"); printmes(" ".gettext('Create a mount point "home" and "share"')); printmes("... "); my $mount_tmp = "/mnt/newdata-".sprintf("%.0f", rand() * 10000); if(system("mkdir $mount_tmp && mount $data{partitions_dev}5 $mount_tmp && mkdir -p $mount_tmp/share/linux $mount_tmp/home && umount $mount_tmp && rmdir $mount_tmp")){ printmes("\n"); printmes(gettext('Error')); printmes("! "); return ""; } printmes(gettext('done').".\n"); # После форматирования считаем uuid диска с данными, определим его метку # $data{uuid_data}, $data{data_install_set} $data{uuid_data} = uuid("$data{partitions_dev}5", UUID); chomp $data{uuid_data}; if($data{'uuid'} eq 'on'){ $data{data_install_set} = "UUID=$data{uuid_data}"; }else{ $data{data_install_set} = "$data{partitions_dev}5"; } }elsif($data{partitions_dev} && $data{type} eq "flash"){ printmes(" ".gettext('Perform hard disk partition')); printmes("... "); #выполним разбиение диска if(system("$data{path} cat /usr/calculate/install/config/fdisk.flash | fdisk $data{partitions_dev} &>/dev/null")){ printmes(gettext('Error')); printmes("! "); return ""; } printmes(gettext('done').".\n"); # отмонтируем разделы если они примонтировались # в /media после разбиения диска umountfrommedia(); } printmes(" ".gettext('Formatting new volume')); printmes("... "); { #отформатируем диск if(system("$data{formatrun} $data{calculate}-$data{linuxver} $data{rootinstall} &>/dev/null")){ printmes("\n"); printmes(gettext('Error')); printmes("! "); printmes(gettext('Volume formatting failed')); printmes(".\n"); return ""; } #установим соответствующий id для раздела if( $data{rootinstall} =~ m|^(/dev/[^/0-9]+)([0-9]?[0-9]?)$| ) { my $device = $1; my $devicenumber = $2; # проверим нужно ли менять id для раздела my $changeid=1; foreach(`fdisk -l 2>&1`) { if(m/^$data{rootinstall}\s+[*]?\s+\d+\s+\d+\s+\d+\s+$data{disktypeid}|GPT.*detected/) { $changeid=0; last; } } # проверим количество разделов на диске if( `fdisk -l $device | grep -c "^/dev"` == 1 ) { $devicenumber = ""; } system("echo -e \"t\n${devicenumber}\n$data{disktypeid}\nw\n\" | fdisk ${device} &>/dev/null") if $changeid; } } printmes(gettext('done').".\n"); } # После форматирования считаем uuid установочного диска, определим его метку # $data{uuid_install}, $data{root_install_set} $data{uuid_install} = uuid($data{rootinstall}, UUID); chomp $data{uuid_install}; if($data{'uuid'} eq 'on'){ $data{root_install_set} = "UUID=$data{uuid_install}"; }else{ $data{root_install_set} = $data{rootinstall}; } #подключим своп swapon(); printmes(" ".gettext('Mounting new volume')); printmes("... "); if(system "$data{path} mount $data{rootinstall} $data{mount}"){ printmes("\n"); printmes(gettext('Error')); printmes("! "); printmes(gettext('Mounting installation volume failed')); printmes(".\n"); return ""; } printmes(gettext('done').".\n"); #примонтируем iso если мы устанавливаем систему из iso образа диска #либо если мы собираем систему из CLS if($data{linux} =~m/iso$/ || ($data{builder} && $data{stage} =~m/iso$/)){ my $iso; if(!$data{builder}){$iso = $data{linux};} else{$iso = $data{stage};} printmes(" ".gettext('Mounting ISO file')); printmes("... "); if(system "$data{path} mkdir -p /mnt/cdrom && mount -o loop $data{linuxdir}/$iso /mnt/cdrom"){ printmes("\n\n".gettext('Error')."! "); beep(); system "$data{path} umount $data{mount}"; return ""; } printmes(gettext('done').".\n"); } #распакуем систему if(extract_exec()){ printmes("\n\n".gettext('Error')."! "); printmes(gettext('Unpacking image failed')); printmes(". "); printmes(gettext('Operation interrupted')); printmes(".\n"); beep(); printmes(gettext('Abort')); printmes("...\n"); printmes(gettext('Unmounting new volume')); printmes("..."); system "$data{path} rm -f $data{mount}/etc/calculate/calculate.ini"; #удалим информацию об неустановленной системе foreach( (0.2,0.5,1,2,4,8) ) { if(system "($data{path} fuser -m $data{mount} 2>&1) >/dev/null") { system "$data{path} umount $data{mount}"; last; } sleep($_); } if($data{linux} =~m/iso$/ || ($data{builder} && $data{stage} =~m/iso$/)){system "$data{path} umount /mnt/cdrom";} printmes(" ".gettext('done').".\n"); return ""; }else{ printmes(gettext('done').".\n"); } #отмонтируем /mnt/cdrom если мы устанавливали систему из файла ISO образа if($data{linux} =~m/iso$/ || ($data{builder} && $data{stage} =~m/iso$/)){ system "$data{path} umount /mnt/cdrom"; } if($data{builder} && $data{stage} !~m/iso$/){ printmes(" ".gettext('Unpack')); printmes(" $data{portage}..."); if(system("$data{path} tar -xjf $data{portagepath}/$data{portage} -C $data{mount}/usr")){ printmes("\n\n".gettext('Error')."! "); printmes(gettext('Unpacking image failed')); printmes(". "); printmes(gettext('Operation interrupted')); printmes(".\n"); beep(); printmes(gettext('Abort')); printmes("...\n"); printmes(gettext('Unmounting new volume')); printmes("..."); system "$data{path} rm -f $data{mount}/etc/calculate/calculate.ini"; #удалим информацию об неустановленной системе system "$data{path} umount $data{mount}"; printmes(" ".gettext('done').".\n"); return ""; } printmes(" ".gettext('done').".\n"); } #перенесем информацию из ISO для scratch if($data{scratch_ws}){ printmes(" ".gettext('Extract grub from squashfs')); printmes("... "); if(system("$data{path} unsquashfs -n -d $data{mount}$data{scratch_ws} -f $data{mount}/livecd.squashfs /boot &>/dev/null")){ printmes("\n\n".gettext('Error')."! "); beep(); return ""; } printmes(gettext('done').".\n"); } 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} -ns -nth -nc -s $count >/dev/null"); } else { return system("$data{path} cp -a $from/* $to/"); } } #------------------------------------------------------------------------------ # Выполним распаковку #------------------------------------------------------------------------------ sub extract_exec{ my $unpack; if(!$data{builder}){ printmes(gettext('Unpacking system image into new volume')); printmes("... "); if($data{linux} =~m/tar\.7z$/){$unpack = "$data{path} 7za x -so $data{linuxdir}/$data{linux} 2>/dev/null | tar xf - -C $data{mount}";} elsif($data{linux} =~m/tar\.lzma$/){$unpack = "$data{path} lzma -dc $data{linuxdir}/$data{linux} | tar -xf - -C $data{mount}";} elsif($data{linux} =~m/tar\.bz2$/){$unpack = "$data{path} tar -xjpf $data{linuxdir}/$data{linux} -C $data{mount}";} }else{ printmes(" ".gettext('Unpack')); printmes(" $data{stage}... "); if($data{stage} !~m/iso$/){ $unpack = "$data{path} tar -xjpf $data{stagepath}/$data{stage} -C $data{mount}"; } # else{ # $unpack = "$data{path} unsquashfs -d $data{mount} -f /mnt/cdrom/livecd.squashfs"; # } } #путь к squashfs в случае установки из ISO файла или с CD-ROM my $squashfs; if(-e "/mnt/cdrom/$data{squash_cur}"){$squashfs = "/mnt/cdrom/$data{squash_cur}";} elsif(-e "/mnt/squash/$data{squash_cur}"){$squashfs = "/mnt/squash/$data{squash_cur}";} elsif(-e "/mnt/$data{squash_cur}"){$squashfs = "/mnt/$data{squash_cur}";} elsif(-e "/mnt/flash/$data{squash_cur}"){$squashfs = "/mnt/flash/$data{squash_cur}";} if($unpack){ if($unpack =~m/unsquashfs/){$bar ++; printmes("\n");} #установка из архива return system($unpack); }elsif($squashfs){ if($data{type} eq "flash"){ #установка с ISO файла на флешку return system("$data{path} rsync -a /mnt/cdrom/ $data{mount}"); }elsif(!$data{scratch_ws}){ my $install_from; if($data{linux} =~ m/iso$/ || $data{stage} =~ m/iso$/ || ( $data{scratch} eq "on" && $data{load} eq "ram" )){ system "$data{path} mkdir /mnt/squashfs && mount -o loop $squashfs /mnt/squashfs"; $install_from = "/mnt/squashfs"; } else { $install_from = "/mnt/livecd"; } #установка с ISO файла на жесткий диск ($data{type} = "hdd" или "usb-hdd") my $count=int(`sed -rn \"\s/^files=(.*)\$/\\1/p\" $install_from/etc/calculate/calculate.ini`); if($count > 0 ) { $bar ++; printmes("\n"); } else { $bar = 0; } my $res = copy_with_progress($install_from,$data{mount},$count); if($install_from eq "/mnt/squashfs"){ system "$data{path} umount $install_from && rmdir $install_from"; } return $res; }elsif($data{scratch_ws}){ if($data{run_bar} =~m/bar/){$bar ++; printmes("\n");} #установка путем копирования ISO файла на жесткий диск (режим установки scratch) return system("$data{path} $data{run_bar} -ns $squashfs $data{mount}/livecd.squashfs"); } } return 1; } #------------------------------------------------------------------------------ # # Наложим обновления # #------------------------------------------------------------------------------ sub profiles{ if($data{type} ne "flash"){ my $create; printmes(gettext('Update config')."\n"); foreach(@{$data{profile_install}}, @{$data{profile_share}}){ profile($_); }; } return 1; } #------------------------------------------------------------------------------ # # Выполним общие настройки системы # #------------------------------------------------------------------------------ sub isotosys{ #подготовим флешку к загрузке if(($data{type} eq "flash" || defined $data{arg}{rebuild}) && !-e "$data{'chroot'}$target/syslinux" #проверим установку с флешки на флешку ){ my $target; if(defined $data{arg}{rebuild}){ $target = "/target"; } printmes(" ".gettext('Setting')); printmes(" syslinux..."); if( ! -e "$data{'chroot'}$target/syslinux" ) { system "$data{path} mv $data{'chroot'}$target/isolinux $data{'chroot'}$target/syslinux"; system "$data{path} mv $data{'chroot'}$target/syslinux/isolinux.cfg $data{'chroot'}$target/syslinux/syslinux.cfg"; system "$data{path} sed -i 's/doload=s/cdroot_type=vfat doload=vfat,nls_cp866,nls_utf8,s/' $data{'chroot'}$target/syslinux/syslinux.cfg"; system "$data{path} sed -i 's/isolinux.cfg/syslinux.cfg/' $data{'chroot'}$target/syslinux/timezone.cfg"; system "$data{path} sed -i 's/isolinux.cfg/syslinux.cfg/' $data{'chroot'}$target/syslinux/keymap.cfg"; system "$data{path} sed -i 's/isolinux.cfg/syslinux.cfg/' $data{'chroot'}$target/syslinux/lang.cfg"; if(-e "$data{'chroot'}$target/syslinux/vga.cfg") { system "$data{path} sed -i 's/isolinux.cfg/syslinux.cfg/' $data{'chroot'}$target/syslinux/vga.cfg"; } } printmes(" ".gettext('done').".\n"); return 1; } } #------------------------------------------------------------------------------ # # Выполним общие настройки системы # #------------------------------------------------------------------------------ sub setup{ printmes(gettext('System setup')."\n"); isotosys(); if($data{type} eq 'flash'){return 1;} #подготовим scratch диск к загрузке if($data{scratch_ws}){ printmes(" ".gettext('Setting')); printmes(" scratch..."); system "$data{path} mkdir $data{'chroot'}/calculate"; system "$data{path} mkdir $data{'chroot'}/delta"; system "$data{path} cp -a $data{'chroot'}$data{scratch_ws}/boot $data{'chroot'}"; printmes(" ".gettext('done').".\n"); } #вытащим из образа оригинальный inittab для последующей подмены if($data{scratch_ws}){ unsquash("/etc/inittab"); } #восстановим inittab my $inittab = "$data{chroot}$data{scratch_ws}/etc/inittab"; if(-e $inittab){ printmes(" ".gettext('Update')); printmes(" /etc/inittab..."); #восстановим оригинальный inittab, убрав автовход system("sed -i '/bin\\/bashlogin/d' $inittab"); system("sed -ir 's/#\\(c[1-6]:\\)/\\1/' $inittab"); printmes(" ".gettext('done').".\n"); } #Создадим initrd-файл if($data{removableinstall} eq 'off'){ initrd($data{chroot}); } #---------------------------------------------------------------------- # Запросим пароль root-а #---------------------------------------------------------------------- if(`$data{path} cat /etc/shadow | grep '$data{hash_root}'`){ printmes(gettext('Changing root password')); printmes("\n"); `passwd`; } #---------------------------------------------------------------------- # Перенесем пароль рута #---------------------------------------------------------------------- if($data{scratch_ws}){ unsquash("/etc/shadow","/etc/shadow-"); } system "$data{path} cat /etc/shadow | sed q > $data{'chroot'}$data{scratch_ws}/etc/shadow_new && $data{path} cat $data{'chroot'}$data{scratch_ws}/etc/shadow | sed 1d >> $data{'chroot'}$data{scratch_ws}/etc/shadow_new"; system "$data{path} cat /etc/shadow- | sed q > $data{'chroot'}$data{scratch_ws}/etc/shadow-_new && $data{path} cat $data{'chroot'}$data{scratch_ws}/etc/shadow- | sed 1d >> $data{'chroot'}$data{scratch_ws}/etc/shadow-_new"; system "$data{path} mv $data{'chroot'}$data{scratch_ws}/etc/shadow_new $data{'chroot'}$data{scratch_ws}/etc/shadow"; system "$data{path} mv $data{'chroot'}$data{scratch_ws}/etc/shadow-_new $data{'chroot'}$data{scratch_ws}/etc/shadow-"; system "$data{path} chmod 0700 $data{'chroot'}$data{scratch_ws}/etc/shadow"; system "$data{path} chmod 0700 $data{'chroot'}$data{scratch_ws}/etc/shadow-"; #---------------------------------------------------------------------- # Пропишем клиент в автозагрузку, если компьютер в домене #---------------------------------------------------------------------- if($data{server} eq "CDS" && -e "/etc/runlevels/default/client"){ system "$data{path} cp -a /etc/runlevels/default/client $data{'chroot'}$data{scratch_ws}/etc/runlevels/default/client"; } #---------------------------------------------------------------------- # Перенесем оригинальные ключи ssh #---------------------------------------------------------------------- if($data{load} ne "ram"){ printmes(" ".gettext('Copy original ssh keys')); printmes("..."); system "$data{path} cp -a /etc/ssh/ssh_host_* $data{'chroot'}$data{scratch_ws}/etc/ssh/"; printmes(" ".gettext('done').".\n"); } #---------------------------------------------------------------------- # Перенесем udev-правила, если в системе более одной сетевой карты #---------------------------------------------------------------------- { my $rule = "/etc/udev/rules.d"; if($data{net_eth1} && -e "$rule/70-persistent-net.rules"){ printmes(" ".gettext('Copy udev net rules')); printmes("..."); system "$data{path} mkdir -p $data{'chroot'}$data{scratch_ws}$rule"; system "$data{path} cp -a $rule/70-persistent-net.rules $data{'chroot'}$data{scratch_ws}$rule"; printmes(" ".gettext('done').".\n"); } } #---------------------------------------------------------------------- # Перенесем настройки wicd #---------------------------------------------------------------------- { my $wicd = "/etc/wicd"; if(-e "$wicd/manager-settings.conf" || -e "$wicd/wireless-settings.conf"){ printmes(" ".gettext('Copy wicd manager settings')); printmes("..."); system "$data{path} mkdir -p $data{'chroot'}$data{scratch_ws}$wicd"; if(-e $ms){system "$data{path} cp $wicd/manager-settings.conf $data{'chroot'}$data{scratch_ws}$wicd";} if(-e $ws){system "$data{path} cp $wicd/wireless-settings.conf $data{'chroot'}$data{scratch_ws}$wicd";} printmes(" ".gettext('done').".\n"); } } #---------------------------------------------------------------------- # Удалим файлы неиспользуемых локализаций #---------------------------------------------------------------------- { printmes(" ".gettext('Remove unused localization')); printmes("..."); clearlang(); printmes(" ".gettext('done').".\n"); } #---------------------------------------------------------------------- # Сохраним диск, с которого произвелась установка # за исключением установки с CD или с ПК на USB или с USB на ПК #---------------------------------------------------------------------- if( $data{load} ne "ram" && ($data{'removableload'} eq $data{'removableinstall'}) ){ if($data{scratch_ws}){ unsquash("/etc/calculate/calculate.ini"); } putini("install.devfrom" => $data{rootload}, "chroot"); } return 1; } #------------------------------------------------------------------------------ # # Подготовим систему к перезагрузке # #------------------------------------------------------------------------------ sub loader{ printmes(gettext('Prepare system for reboot')); printmes("\n"); #пропишем grub в автозагрузку, изменим MBR запись if($data{mbr} eq "on"){ printmes(" ".gettext('Change boot record')); printmes("..."); if($data{type} ne "flash"){ #chroot $data{'chroot'} if(system "$data{path} /sbin/grub --device-map=$data{'chroot'}/boot/grub/device.map --batch </dev/null\n". "root ($data{grubinstall})\n". "setup (hd0)\n". "quit\n". "EOF"){ printmes(" ".gettext('error').".\n"); }else{ printmes(" ".gettext('done')); printmes(".\n"); } }else{ #сделаем флешку загрузочной if(system "$data{path} dd if=/usr/share/syslinux/mbr.bin of=$data{partitions_dev} &>/dev/null"){ printmes(" ".gettext('error').".\n"); }else{ printmes(" ".gettext('done')); printmes(".\n"); } } } #Отмонтируем устанавливаемый диск printmes(" ".gettext('Unmount installed system volume')); printmes("..."); if(system("$data{path} umount $data{'chroot'}")){ printmes(" ".gettext('error').".\n"); return ""; }else{ printmes(" ".gettext('done')); printmes(".\n"); } #пропишем syslinux в автозагрузку if($data{type} eq "flash"){ printmes(" ".gettext('Create a boot partition')); printmes("..."); if(system "$data{path} syslinux $data{rootinstall}"){ printmes(" ".gettext('error').".\n"); return ""; }else{ printmes(" ".gettext('done')); printmes(".\n"); } } return 1; } #------------------------------------------------------------------------------ # # Перезагрузим компьютер # #------------------------------------------------------------------------------ sub reboot{ if($data{type} ne "flash"){ printmes(" ".gettext('Detect logged in users')); printmes("... "); printmes(gettext('done').".\n"); if(`$data{path} w -hs` || $data{load} eq "ram"){ printmes("\n".gettext('To apply changes you have to reboot').".\n"); }else{ printmes(" ".gettext('Perform reboot')); printmes("..."); system "$data{path} shutdown -r now"; printmes(" ".gettext('done').".\n"); } } return 1; } #------------------------------------------------------------------------------ # # Выведем список переменных конфигурационных файлов # #------------------------------------------------------------------------------ sub printvars{ printmes(gettext('Config files variables list').":\n"); my ($vars,$tab); foreach(sort keys %data){ #пропустим внутренние переменные if($_=~m/[A-Z]/ || $data{$_}=~m/^HASH/){next;} my $data; if($data{$_}=~m/^ARRAY/){$data = "@{$data{$_}}";}else{$data = $data{$_};} if(length(" #-$_-#") < 16){$tab = "\t";}else{$tab = "";} my $w = "r"; if(${$data{write}}{$_}){$w = "w";} my $other; if(@{$data{other}}{$_}){ my $skip = $data{$_}; foreach(@{${$data{other}}{$_}}){ if($_ eq $skip){next;} if($other){$other.=", ";} $other .= "$_"; } $other = " [$other]"; } printmes(" #-$_-#\t${tab}[$w] \"$data\"$other\n"); } return 1; } #------------------------------------------------------------------------------ # # Выведем конфигурацию ПК # #------------------------------------------------------------------------------ sub printhardware{ printmes(" ".gettext('Vendor')); printmes(": "); if($data{vendor}){ printmes(gettext($data{vendor}."\n")); }else{ printmes("<"); printmes(gettext('undefined')); printmes(">\n"); } if($data{laptop_model}){ printmes(" ".gettext('Model')); printmes(": "); printmes(gettext($data{laptop_model}."\n")); } if($data{board_model}){ printmes(" ".gettext('Motherboard')); printmes(": "); printmes("$data{board_model} ($data{board_vendor})\n"); } if($data{video}){ printmes(" ".gettext('Videocard')); printmes(": $data{video}\n"); } if($data{video_resolution}){ printmes(" ".gettext('Screen resolution')); printmes(": $data{video_resolution}\n"); } #получим информацию из hal if($data{hal} && -e "/usr/bin/hal-device"){ my (%hw, %hwlink); #параметры устройств и ссылки на идентификаторы устройств my (%hdd, %cdrom); #хэши доступных дисков { my ($udi); foreach(`/usr/bin/hal-device`){ chomp; if($_){ if(m/^[0-9]+: /){ $udi = $_; }else{ m/^\s*([^=]+) = ([^=]+)?(\(string\)|\(int\)|\(uint64\)|\(string list\))$/; my $var = $1; my $val = $2; $val =~s/^([^\s]+)\s+\(.+/$1/; #уберем значение в скобках $val =~s/^'([^']+)'\s+.+/$1/; #уберем кавычки $hw{$udi}{$var} = $val; #устройство-параметр - значение #определим устройства if(m#block.device = '/dev/(sd[a-z])'#){ $hwlink{$1} = $udi; #указатель на запись устройства hdd $hdd{$1}++; }elsif(m#block.device = '/dev/(sr[0-9])'#){ $hwlink{$1} = $udi; #указатель на запись устройства cd-rom $cdrom{$1}++; }elsif(m#linux.acpi_path = '/proc/acpi/processor/(CPU0)'#){ $hwlink{$1} = $udi; #указатель на запись устройства cd-rom } } } } } printmes(" ".gettext('Hard disks')); printmes(":\n"); foreach(sort keys %hdd){ my $size = sprintf("%0.0f",$hw{$hwlink{$_}}{'storage.size'}/1000000000); printmes(" $_: $size Gb ($hw{$hwlink{$_}}{'info.product'})\n"); } } } #------------------------------------------------------------------------------ # # Выведем сообщение в текущей локали # #------------------------------------------------------------------------------ sub printmes{ if($data{NOMES}){return "";} #флаг не печатать сообщения #определим наличие установленной программы gettext #и очистим файл лога if(!defined $date{gettext}){ my $gettext = `$data{path} which gettext`; chomp $gettext; if($gettext){ $date{gettext}++; } else{ $date{gettext}=''; } } #считаем входящее сообщение my $mes = $_[0]; $mes=~s/'/"/g; #ведем лог $data{LOG} .= $mes; if($date{gettext}){ my ($from, $after); #обрежем левые и правые отступы для перевода фразы if($mes=~m/^(\s*)(.+)([!?:\.]\s*)$/ || $mes=~m/^(\s*)(.+)(\s*)$/){ $from = $1; $mes = $2; $after = $3; } if($mes){ my $text; if($mes!~/^\-/){$text = "gettext -n -d calculate -s '$mes'";} else{$text = "echo -n '$mes'";} system "export TEXTDOMAINDIR='$data{dir}/install/i18n'; echo -n '$from'; $text; echo -n '$after'"; } }else{ print $mes; } return 1; } #------------------------------------------------------------------------------ # # Локализация. Процедура нужна для извлечения переводимых строк xgettext-ом # #------------------------------------------------------------------------------ sub gettext{ return $_[0]; } #------------------------------------------------------------------------------ # # Ведение log-файла # #------------------------------------------------------------------------------ sub savelog{ my $id = `$data{path} id -u`; chomp $id; if(!$data{NOLOG} && $id == 0){ if(!-e "/var/log/calculate"){ system "$data{path} mkdir -m 755 /var/log/calculate"; } open (F,">/var/log/calculate/install.log"); flock(F, 2); print F $data{LOG}; close (F); } return 1; } #------------------------------------------------------------------------------ # # Сообщение об ошибке неправильно введенного аргумента # #------------------------------------------------------------------------------ sub errorarg{ my $arg = $_[0]; printmes(gettext('Unrecognized option')); printmes(" '$arg'.\n"); printmes(gettext('Try')); printmes(" 'calculate --help' "); printmes(gettext('for more information')); printmes(".\n"); beep(); return 1; } #------------------------------------------------------------------------------ # # Наложим профили обновления # #------------------------------------------------------------------------------ sub profile{ my $profile = $_[0]; my $title = $_[1]; #обозначение профиля my $tmpdir; if(!-e $data{tmpdir}){ system "$data{path} mkdir -p '$data{tmpdir}'"; $tmpdir ++; } if(!$title){ $title = $profile; $title =~s/.+\/([^\/]+)\/[^\/]+\/([^\/]+)$/$1\/$2/; } $title=~s/^(.+)\?(.+)/$1/; printmes(" ".gettext('Apply template')); printmes(" \"$title\"..."); #Template file $data{title} = $data{mesline}."\n". $data{mestitle}."\n". qq|# Changes to profile "$title".\n|. $data{mesline}; #создадим пути и права доступа к файлам, аналогичные профилю my @dir = `$data{path} find "$profile" -type d`; foreach(@dir){ chomp; my $recpath; #по заданным маскам поменяем права на директории foreach(split "/", substr($_, length($profile))){ $recpath.= "$_/"; if(!-e $data{'chroot'}.$data{scratch_ws}.$recpath){ system qq|$data{path} mkdir -p $data{'chroot'}$data{scratch_ws}$recpath|; if($recpath=~m|/\.ssh/| || $recpath=~m|/^\/root$/|){ system qq|$data{path} chmod 0700 "$data{'chroot'}$data{scratch_ws}$recpath"|; } } } } #поменяем дополнительно права для scratch установки my $path = "$data{'chroot'}$data{scratch_ws}/root"; system qq|$data{path} mkdir -p "$path" && chmod 0700 "$path"|; $path = "$data{'chroot'}$data{scratch_ws}/tmp"; system qq|$data{path} mkdir -p "$path" && chmod 1777 "$path"|; #извлечем файлы профиля my @conf = `$data{path} find "$profile" -type f`; foreach(@conf){ chomp; my $allocation = $data{'chroot'}.$data{scratch_ws}.substr($_, length($profile)); #проверим имя файла фрофиля перед переносом в систему $allocation = check_name($allocation); if(!$allocation){next;} #сохраним обработанный файл в директории установки $allocation=~m/^(.*\/)([^\/]+)$/; my $namepath = $1; my $nameprof = $2; my $nameorig = $nameprof; #извлечем текстовый файл профиля if(`$data{path} file "$_" | grep text`){ $data{file}{name} = $_; #считаем файл open(C, $data{file}{name}); my (@conf) = ; 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) = ; close(C); #считаем оригинальный файл my @save = substitution([@original], [@conf]); open(C, ">".$namepath.substr($nameprof,1)); print C @save; close(C); }elsif(substr($nameprof,-5) eq ".diff"){ $nameorig = substr($nameprof,0,-5); if($data{pass} eq 'install' && $data{scratch_ws}){ #извлечем файл для объединения unsquash(substr($allocation, length($data{'chroot'}.$data{scratch_ws}),-5)); } open(C, ">$data{tmpdir}/$nameprof"); print C @conf; close(C); foreach(`LANG=C patch -N -r $data{tmpdir}/$nameorig.rej --no-backup-if-mismatch $namepath$nameorig $data{tmpdir}/$nameprof`){ if(m/FAILED/i){ printmes("\n".gettext('Error patching from')." $data{file}{name}\n"); last; } } }else{ system "$data{path} rm -f \"$allocation\""; #удалим на случай если стоит ссылка на другой файл open(C, ">$allocation"); print C @conf; close(C); } #сменим права доступа if(substr($allocation,-5) ne ".diff"){ if($allocation=~m|/ssh/|){ system "$data{path} chmod 600 $namepath$nameorig"; }elsif($allocation=~m|/etc/sudoers|){ system "$data{path} chmod 0440 $namepath$nameorig"; }elsif( $allocation=~m|/config/kdm/X| || $allocation=~m|/etc/cron\.| || $allocation=~m|/etc/init\.d/| || $allocation=~m|/etc/X11/gdm/| || $allocation=~m|/usr/local/bin/| || $allocation=~m|/etc/NetworkManager/dispatcher.d/| || $allocation=~m|/sbin/| || $allocation=~m|\.sh$| ){ system "$data{path} chmod 755 $namepath$nameorig"; } } }elsif(`$data{path} file "$_" | grep empty`){ system "$data{path} rm -f \"$allocation\""; if($data{scratch_ws} && $data{pass} eq "install"){ system "$data{path} touch \"$namepath.wh.$nameorig\""; } }else{ #перенесем без обработки бинарный файл `$data{path} cp -a "$_" "$allocation"`; } } #создадим символическую ссылку на Zoneinfo if(!$data{builder}){ if(!-e "$data{chroot}$data{scratch_ws}/tmp"){`$data{path} mkdir -m 1777 -p "$data{chroot}$data{scratch_ws}/tmp"`;} `$data{path} rm -rf $data{chroot}$data{scratch_ws}/tmp/localtime && ln -s /usr/share/zoneinfo/$data{timezone} $data{chroot}$data{scratch_ws}/tmp/localtime && mv $data{chroot}$data{scratch_ws}/tmp/localtime $data{chroot}$data{scratch_ws}/etc/ `; } #создадим символические ссылки аналогичные профилю my @dir = `$data{path} find "$profile" -type l`; foreach(@dir){ chomp; #уберем ссылки на несуществующие файлы `$data{path} file "$_"`=~m/\`([^']+)'/; my $dest = $1; #проверяем на существование только абсолютный путь if($dest=~m/^[\/]/){ if($data{pass} eq 'install' && $data{scratch_ws}){ #проверим существование в squash образе if(!checksquash($dest)){next;} }else{ #проверим в системе if(!-e "$data{'chroot'}$data{scratch_ws}$dest"){next;} } } #выделим путь из профиля my $allocation = $data{'chroot'}.$data{scratch_ws}.substr($_, length($profile)); #проверим имя файла фрофиля перед переносом в систему $allocation = check_name($allocation); if(!$allocation){next;} #скопируем ссылку if(-e $allocation){`$data{path} rm $allocation`} if($dest=~m/^[\/]/){ #правило 1: #абсолютную ссылку перенесем как есть system "$data{path} cp -a \"$_\" \"$allocation\""; }elsif($dest=~m/^[\~]/){ #правило 2: #вырежем ~ из имени ссылки и создадим относительную ссылку #получится относительная ссылка, которая не будет преобразована в абсолютную system "$data{path} ln -sf \"".substr($dest,1)."\" \"$allocation\""; }else{ #правило 3: #относительную ссылку преобразуем в абсолютную #мы ее указываем чтобы избежать проверки абсолютного пути system "$data{path} ln -sf \"/$dest\" \"$allocation\""; } } if(!$data{file}{error}){ printmes(" ".gettext('done').".\n"); }else{ printmes("\n"); $data{file}{error} = ''; } if($tmpdir){ system "$data{path} rm -rf '$data{tmpdir}'"; } } #------------------------------------------------------------------------------ # # Проверим на доступное обновление на сайте проекта # #------------------------------------------------------------------------------ sub checkupdate{ printmes(gettext('To upgrade Calculate Overlay launch `layman -S`')); printmes(".\n"); } #------------------------------------------------------------------------------ # # Подготовим систему к сборке # #------------------------------------------------------------------------------ sub configure{ #printmes(gettext('Perform checkouts')); printmes("\n"); #printmes(" ".gettext('New release number')); printmes("..."); $data{laymandir} = "/var/lib/layman"; if(!-e $data{laymandir}){$data{laymandir} = "/usr/local/portage/layman";} #если система собирается не из CLS if($data{stage} !~m/iso$/){ #------------------------------------- # выполним настройки в текущей системе #------------------------------------- printmes(" ".gettext('Load')); printmes(" calculate overlay..."); if(!`layman -l | grep calculate`){ system "layman -S &>/dev/null"; system "layman -a calculate &>/dev/null"; }else{ system "layman -S &>/dev/null"; } printmes(" ".gettext('done').".\n"); #Скопируем calculate overlay printmes(" ".gettext('Transfer calculate overlay to system')); printmes("..."); if(system " $data{path} mkdir -p $data{chroot}/var/lib/layman && $data{path} cp -a $data{laymandir}/calculate $data{chroot}/var/lib/layman && $data{path} cp $data{laymandir}/overlays.xml $data{chroot}/var/lib/layman "){ printmes(" ".gettext('error')."!\n"); umountbuild(); return ''; } printmes(" ".gettext('done').".\n"); } #Подмонтируем /proc printmes(" ".gettext('Mount')); printmes(" /proc..."); if(system "$data{path} mount -t proc none $data{chroot}/proc &>/dev/null"){ printmes(" ".gettext('error')."!\n"); umountbuild(); return ''; } printmes(" ".gettext('done').".\n"); #Подмонтируем /dev/shm printmes(" ".gettext('Mount')); printmes(" /dev/shm..."); if(system "$data{path} mount -o bind /dev/shm $data{chroot}/dev/shm &>/dev/null"){ printmes(" ".gettext('error')."!\n"); umountbuild(); return ''; } printmes(" ".gettext('done').".\n"); #Подмонтируем /dev/pts printmes(" ".gettext('Mount')); printmes(" /dev/pts..."); if(system "$data{path} mount -o bind /dev/pts $data{chroot}/dev/pts &>/dev/null"){ printmes(" ".gettext('error')."!\n"); umountbuild(); return ''; } printmes(" ".gettext('done').".\n"); #Наложим профили на распакованный образ profiles(); #Установим ссылку на профиль my $mask = substr($data{unmask}, 1); my $developer; if($data{linuxver} =~/[0-9]+\.[0-9]+\.[0-9]+/){$developer = "/developer"} system "$data{path} cd $data{chroot}/etc; rm make.profile; ln -sf ../var/lib/layman/calculate/profiles/calculate/$data{system}/$data{calculate}/$mask$developer make.profile"; #Подмонтируем /var/calculate/remote printmes(" ".gettext('Mount')); printmes(" /var/calculate/remote..."); if(system "$data{path} mount -o bind /var/calculate/remote $data{chroot}/var/calculate/remote &>/dev/null"){ printmes(" ".gettext('error')."!\n"); umountbuild(); return ''; } printmes(" ".gettext('done').".\n"); #Перенесем в calculate.ini некоторые переменные putini("linuxver" => $data{"linuxver"}, "chroot"); putini("calculate" => $data{"calculate"}, "chroot"); putini("system" => $data{"system"}, "chroot"); #Скопируем /etc/resolv.conf printmes(" ".gettext('Copy')); printmes(" /etc/resolv.conf..."); if(system "$data{path} cp /etc/resolv.conf $data{chroot}/etc/ &>/dev/null"){ beep(); printmes(" ".gettext('error')."!\n"); }else{ printmes(" ".gettext('done').".\n"); } #Пропатчим /etc/login.defs printmes(" ".gettext('Put a patch')); printmes(" /etc/login.defs..."); system "$data{path} cp $data{chroot}/etc/login.defs $data{chroot}/etc/login.defs.old"; if(system "$data{path} sed -i -r 's/^GID_MIN.*/GID_MIN\t\t\t 100/' $data{chroot}/etc/login.defs && $data{path} sed -i -r 's/^UID_MIN.*/UID_MIN\t\t\t 100/' $data{chroot}/etc/login.defs" ){ beep(); printmes(" ".gettext('error')."!\n"); }else{ printmes(" ".gettext('done').".\n"); } #chroot layman -S if($data{stage} =~m/iso$/){ printmes(" ".gettext('Perform calculate overlay update')); printmes("..."); if(system "$data{path} chroot $data{chroot} layman -S &>/dev/null"){ beep(); printmes(" ".gettext('error')."!\n"); }else{ printmes(" ".gettext('done').".\n"); } } # #Скопируем /etc/portage/bashrc # printmes(" ".gettext('Copy')); printmes(" /etc/portage/bashrc..."); # if(system "$data{path} cp -H --remove-destination /etc/portage/bashrc $data{chroot}/etc/portage/bashrc" # ){ # beep(); # printmes(" ".gettext('error')."!\n"); # }else{ # printmes(" ".gettext('done').".\n"); # } #chroot emerge --sync printmes(" ".gettext('Perform portages update')); printmes("..."); if(system "$data{emergerun1} --sync $data{emergerun2} &>/dev/null"){ beep(); printmes(" ".gettext('error')."!\n"); }else{ printmes(" ".gettext('done').".\n"); } #chroot emerge sys-apps/portage printmes(" ".gettext('Execute')); printmes(" emerge sys-apps/portage..."); if(system "$data{emergerun1} sys-apps/portage $data{emergerun2} &>/dev/null"){ printmes(" ".gettext('error')."!\n"); umountbuild(); return ''; }else{ printmes(" ".gettext('done').".\n"); } #chroot emerge sys-kernel/calculate-sources если система собирается не из CLS if($data{stage} !~m/iso$/){ printmes(" ".gettext('Install the kernel sources')); printmes("..."); if(system "USE=\"-vmlinuz\" $data{emergerun1} sys-kernel/calculate-sources $data{emergerun2} &>/dev/null"){ printmes(" ".gettext('error')."!\n"); umountbuild(); return ''; }else{ printmes(" ".gettext('done').".\n"); } } #если система собирается не из CLS if($data{stage} !~m/iso$/){ #chroot emerge sys-apps/v86d printmes(" ".gettext('Execute')); printmes(" emerge sys-apps/v86d..."); if(system "$data{emergerun1} sys-apps/v86d $data{emergerun2} &>/dev/null"){ printmes(" ".gettext('error')."!\n"); umountbuild(); return ''; }else{ printmes(" ".gettext('done').".\n"); } #chroot emerge sys-apps/openrc printmes(" ".gettext('Execute')); printmes(" emerge sys-apps/openrc..."); system "CLEAN_DELAY=0 $data{emergerun1} -C --backtrack=0 sys-apps/baselayout sys-apps/sysvinit $data{emergerun2} &>/dev/null"; system "$data{path} rm $data{chroot}/etc/init.d/depscan.sh $data{chroot}/etc/init.d/functions.sh $data{chroot}/etc/init.d/runscript.sh"; if(system "$data{emergerun1} sys-apps/openrc sys-apps/sysvinit sys-fs/udev sys-fs/e2fsprogs $data{emergerun2} &>/dev/null"){ printmes(" ".gettext('error')."!\n"); umountbuild(); return ''; }else{ system "$data{path} rm -f $data{chroot}/etc/runlevels/boot/network"; printmes(" ".gettext('done').".\n"); } #chroot emerge sys-apps/man-db printmes(" ".gettext('Execute')); printmes(" emerge sys-apps/man-db..."); system "CLEAN_DELAY=0 $data{emergerun1} -C --backtrack=0 sys-apps/man $data{emergerun2} &>/dev/null"; if(system "$data{emergerun1} sys-apps/man-db $data{emergerun2} &>/dev/null"){ printmes(" ".gettext('error')."!\n"); umountbuild(); return ''; }else{ printmes(" ".gettext('done').".\n"); } } #удалим ссылку net.eth0, т.к. во всех десктопах, кроме CLS будет использоваться networkmanager if($data{calculate} ne "CDS" && $data{calculate} ne "CSS" && $data{calculate} ne "CLS"){ system "$data{path} rm -f $data{chroot}/etc/init.d/net.eth0"; } #если система собирается не из CLS if($data{stage} !~m/iso$/){ if($data{system} eq 'desktop'){ #chroot groupadd games printmes(" ".gettext('Execute')); printmes(" groupadd -g 35 games..."); if(system "$data{path} chroot $data{chroot} /usr/sbin/groupadd -g 35 games &>/dev/null"){ printmes(" ".gettext('error')."!\n"); umountbuild(); return ''; }else{ printmes(" ".gettext('done').".\n"); } } #chroot groupadd plugdev printmes(" ".gettext('Execute')); printmes(" groupadd -g 440 plugdev..."); if(system "$data{path} chroot $data{chroot} /usr/sbin/groupadd -g 440 plugdev &>/dev/null"){ printmes(" ".gettext('error')."!\n"); umountbuild(); return ''; }else{ printmes(" ".gettext('done').".\n"); } #chroot groupadd scanner printmes(" ".gettext('Execute')); printmes(" groupadd -g 441 scanner..."); if(system "$data{path} chroot $data{chroot} /usr/sbin/groupadd -g 441 scanner &>/dev/null"){ printmes(" ".gettext('error')."!\n"); umountbuild(); return ''; }else{ printmes(" ".gettext('done').".\n"); } } #chroot useradd p2p if($data{calculate} eq "CDS"){ printmes(" ".gettext('Execute')); printmes(" useradd -g 100 p2p..."); if(system "$data{path} chroot $data{chroot} /usr/sbin/useradd -u 101 -g 100 -G wheel -c \"added by Calculate for p2p\" -s /sbin/bash p2p &>/dev/null"){ printmes(" ".gettext('error')."!\n"); umountbuild(); return ''; }else{ printmes(" ".gettext('done').".\n"); system "$data{path} chroot $data{chroot} /bin/mkdir -m 0700 /home/p2p"; system "$data{path} chroot $data{chroot} /bin/chown p2p:root /home/p2p"; } } beep(); printmes(gettext('All done')); printmes("! "); printmes(gettext('Ready for packages installation')); printmes(".\n"); return 1; } #------------------------------------------------------------------------------ # # Отмонтируем диски в случае прерывания сборки # #------------------------------------------------------------------------------ sub umountbuild{ printmes(gettext('Operation interrupted')); printmes(".\n"); printmes(gettext('Abort')); printmes("...\n"); beep(); #отмонтируем все директории и точку монтирования umount_build_all(); } #------------------------------------------------------------------------------ # # Покажем список пакетов для установки # #------------------------------------------------------------------------------ sub list{ printmes(gettext('Package list incoming in distributive file')); printmes("...\n"); #отобразим на экране список пакетов my $i = 0; foreach(packages()){ printmes("$_\n"); $i++; } printmes("\n"); printmes(gettext('All')); printmes(" $i "); printmes(gettext('packages')); printmes(".\n"); return 1; } #------------------------------------------------------------------------------ # # Вернем список пакетов для сборки # либо пакетов дополнений # #------------------------------------------------------------------------------ sub packages{ #отработаем случай размаскировки в текущей системе --unmask if(defined $data{arg}{'unmask'}){ return split ' ', $data{arg}{'unmask'}; } #определим директории для нашей конфигурации файлов со списком пакетов my @dir; if(!defined $data{addition} && !@{$data{packageslist}}){ foreach(@{$data{packages}}){ if(-e $_){ my $path_packages = $_; opendir(DIR, $path_packages); foreach(readdir DIR){ if($_ eq "." || $_ eq ".."){next;} if(check_name($_)){push(@dir, "$path_packages/$_");} } closedir DIR; if(!$chkdir){push(@dir, "$path_packages");} } } }elsif(@{$data{packageslist}}){ return @{$data{packageslist}}; }else{ #---------------------------------------------------------------------- # Пути к директориям пакетов дополнений # @{$data{packages}) #---------------------------------------------------------------------- @{$data{packages}} = ( "$data{dir}/install/builder/addition/$data{calculate}", "/usr/calculate/share/builder/addition/$data{calculate}", ); foreach(@{$data{packages}}){ if(-e "$_/$data{addition}"){ push(@dir, "$_/$data{addition}"); } } } #считаем список файлов пакетов my @files = (); foreach(@dir){ my $path = "$_"; opendir(DIR, $path); foreach(readdir DIR){ if($_ eq "." || $_ eq ".."){next;} push (@files, "$path/$_"); } closedir DIR; } #извлечем имена пакетов из файлов my %pack = (); foreach(@files){ $data{file}{name} = $_; open(R, $data{file}{name}); my @lines = ; close(R); foreach(convert(lines => [@lines], nocomment => yes)){ chomp $_; $pack{$_}++; } } #соберем список пакетов в массив my @packages; foreach(sort keys %pack){ push (@packages, $_); } # print ">@packages<"; return @packages; } #------------------------------------------------------------------------------ # # Проверка зависимостей устанавливаемых пакетов # #------------------------------------------------------------------------------ sub dependence{ my $hide = $_[0]; #скрыть вывод списка пакетов после проверки printmes(gettext('Check of dependences')); printmes("...\n"); my ($pack, $mask); while (($pack, $mask) = emerge_pretend()){ if($mask eq 'keywords'){ $pack = lastver($pack); #получим последнюю доступную версию пакета printmes(" ".gettext('Add')); printmes(" \"$pack $data{unmask}\" >> package.keywords/dependence\n"); my $keywords = "$data{'chroot'}/etc/portage/package.keywords/dependence"; if(!-e $keywords){system "echo '$data{mesline}\n$data{mestitle}\n$data{mesline}' >> $keywords";} system "echo '$pack $data{unmask}' >> $keywords"; }elsif($mask eq 'unmask'){ printmes(" ".gettext('Add')); printmes(" \"$pack\" >> package.unmask/dependence\n"); my $unmask = "$data{'chroot'}/etc/portage/package.unmask/dependence"; if(!-e $unmask){system "echo '$data{mesline}\n$data{mestitle}\n$data{mesline}' >> $unmask";} system "echo $pack >> $unmask"; }elsif($mask eq 'reverse'){ next; #пропустим звуковое предупреждение }else{ last; } beep(); } if($pack){ printmes("\n".gettext('All done')); printmes("!\n"); } if(!$hide){ my @packages = packages(); if(!defined $data{arg}{'unmask'}){ system "$data{emergerun1} -pqvtuD @packages $data{emergerun2}"; }else{ system "$data{emergerun1} -p @packages $data{emergerun2}"; } } if($pack){ return 1; }else{ return ''; } } #------------------------------------------------------------------------------ # По полному имени пакета вернем последнюю доступную версию - имя плюс версия #------------------------------------------------------------------------------ sub lastver{ my $pack = $_[0]; #имя пакета my ($tmp,$name) = split "/", $pack; #имя без категории my $overlays = `emerge --info | grep PORTDIR_OVERLAY`; $overlays =~s/PORTDIR_OVERLAY="(.*)"/$1/; chomp $overlays; my @overlays; foreach(split / /, $overlays){ push @overlays, $data{'chroot'}."$_/$pack"; } push @overlays, "$data{'chroot'}/usr/portage/$pack"; #получим список доступных пакетов с полными путями my @lastver; foreach(@overlays){ if(-e $_){ push (@lastver, `ls -la $_/*ebuild`); } } #определим максимальную версию из доступных пакета my $ver; my $last; #последняя доступная версия foreach(@lastver){ $ver = $_; my $p = $pack; $p=~s/\+/\\+/g; my $n = $name; $n=~s/\+/\\+/g; $ver=~s/.+$p\/$n\-(.+)\.ebuild$/$1/; #замаскируем + для регулярного выражения chomp $ver; if(!$last){$last = $ver; next;} #сравним версию my @ver = split /\./, $ver; my @last = split /\./, $last; for(my $i = 0; $i < @ver; $i ++){ #выполним дальнейшие преобразования операндов перед сравнением my $v = $ver[$i]; my $l = $last[$i]; #числа сравниваем как строки, поддерживая сравнение 9-r1 и 16 if($v=~/^\d+.*/ || $l=~/^\d+.*/){ if($v=~/^(\d+)(.*)$/){$v = sprintf("%05d", $1). "$2";} if($l=~/^(\d+)(.*)$/){$l = sprintf("%05d", $1). "$2";} #снизим приоритет беты, если вторая версия имеет тот же номер if($v=~/^\d+$/ || $l=~/^\d+$/){ my $v_b = $v; my $l_b = $l; $v_b=~s/^(\d+).*/$1/; $l_b=~s/^(\d+).*/$1/; if($v_b eq $l_b){ if($v_b ne $v && $v!~/^\d+\-r[0-9]+$/){$v = 0;} elsif($l_b ne $l && $l!~/^\d+\-r[0-9]+$/){$l = 0;} elsif(!defined $ver[$i+1] && defined $last[$i+1]){$v = 0;} elsif(!defined $ver[$i+1] && defined $last[$i+1]){$l = 0;} } } } if($v gt $l && $v!~m/999/){ $last = $ver; last; }elsif($l gt $v){last;} } } return "<=$pack-$last"; } #------------------------------------------------------------------------------ # # Проверим на возможность установки пакетов # #------------------------------------------------------------------------------ sub emerge_pretend{ my @packages = packages(); my $err; @packages = (@{$data{movie_pretend}}, @packages); #объединим со списком зависимых пакетов (дублируя расположим их сверху) my $softly; if(!defined $data{addition} && !defined $data{arg}{'unmask'}){$softly = "--softly";} my @check; push @check, `$data{emergerun1} -p --color n @packages $data{emergerun2} $softly 2>&1`; if(!defined $data{arg}{'unmask'}){ #вторая проверка на случай сборки на базе CLS push @check, `$data{emergerun1} -p --color n -uD world $data{emergerun2} $softly 2>&1`; } foreach(@check){ if(m/Error: The above package list contains packages which cannot be/ || m/resulting in a slot conflict:/ ){ $err++; last; }elsif(m/^- ([^ ]+)-[0-9\._pba-c]+(_pre[0-9]+)?(_rc[0-9]{1,2})?(-r[0-9]{1,2})?(_beta[0-9]{1,2})? .+masked by: package.mask/){ return $1, 'unmask'; }elsif(m/^- ([^ ]+)-[0-9\._pba-c]+(_pre[0-9]+)?(_rc[0-9]{1,2})?(-r[0-9]{1,2})?(_beta[0-9]{1,2})? .+masked by: $data{unmask} keyword/){ return $1, 'keywords'; }elsif(m/'([^ ]+)-[0-9\._pba-c]+(_pre[0-9]+)?(_rc[0-9]{1,2})?(-r[0-9]{1,2})?(_beta[0-9]{1,2})?'.+ pulled in by/ && !m/kde-base\/kdelibs-3.5/){ my $movie; #отметим зависимый пакет, который должен располагаться сверху списка, чтобы избежать ошибки foreach(@packages){ if(m/$1/){ push (@{$data{movie_pretend}}, $_); } } return $1, 'reverse'; }elsif($_=~m/!{3}/){ $err++; } } if($err){ printmes("\n".gettext('One of the packages not match your architecture')); printmes(".\n"); printmes(gettext('Please revise dependences of the packages by your own  using flags concealment of packages')); printmes(".\n"); return ''; } return 1; } #------------------------------------------------------------------------------ # # Соберем систему # #------------------------------------------------------------------------------ sub make{ printmes(gettext('Make system')."\n"); my $skipfirst; if($data{skipfirst} eq "on"){$skipfirst = " --skipfirst";} #закончим прерванное действие if(getini("run.make", "chroot")){ printmes(" ".gettext('Execute')); printmes(" emerge --resume".$skipfirst."...\n"); if(system "$data{emergerun1}$skipfirst --resume $data{emergerun2}"){ beep(); printmes(" ".gettext('error')."!\n"); return ''; }else{ printmes(" ".gettext('done').".\n"); getini("run.make", "chroot") } my $finish = getini("run.make", "chroot"); #считаем действие putini("run.make" => "", "chroot"); #сбросим успешную операцию #увеличим счётчик my $step = getini("run.make.step.$finish", "chroot"); $step++; putini("run.make.step.$finish" => $step, "chroot"); } #отобразим выполненные действия if(getini("run.make.step.system", "chroot")){ foreach(my $i = 0; $i < getini("run.make.step.system", "chroot"); $i ++){ printmes(" ".gettext('Execute')); printmes(" emerge -e system..."); printmes(" ".gettext('done')); printmes(".\n"); } } if(getini("run.make.step.newuse", "chroot")){ printmes(" ".gettext('Execute')); printmes(" emerge --newuse -D world..."); printmes(" ".gettext('done')); printmes(".\n"); } if(getini("run.make.step.update", "chroot")){ printmes(" ".gettext('Execute')); printmes(" emerge -upD world..."); printmes(" ".gettext('done')); printmes(".\n"); } #получим список пакетов world = "" my @world = packages(); my $finish = ''; while(!$finish){ if($data{stage} !~m/iso$/ && getini("run.make.step.system", "chroot") < 2){ printmes(" ".gettext('Execute')); printmes(" emerge -e system...\n"); putini("run.make" => "system", "chroot"); #сохраним выполняемое действие if(system "$data{emergerun1} -e system $data{emergerun2} --nodie"){ beep(); printmes(" ".gettext('error')."!\n"); return ''; }else{ #сбросим успешно выполненную операцию putini("run.make" => "", "chroot"); #увеличим счетчик проходов my $step = getini("run.make.step.system", "chroot"); $step ++; putini("run.make.step.system" => $step, "chroot"); printmes(" ".gettext('done').".\n"); } }elsif($data{stage} =~m/iso$/ && !getini("run.make.step.newuse", "chroot")){ printmes(" ".gettext('Execute')); printmes(" emerge --newuse -D world...\n"); if(system "$data{emergerun1} --newuse -D world $data{emergerun2} --nodie"){ beep(); printmes(" ".gettext('error')."!\n"); return ''; }else{ #отметим успешное выполнение putini("run.make.step.newuse" => 1, "chroot"); printmes(" ".gettext('done').".\n"); } }elsif($data{stage} =~m/iso$/ && !getini("run.make.step.update", "chroot")){ printmes(" ".gettext('Execute')); printmes(" emerge -uD world...\n"); if(system "$data{emergerun1} -uD world $data{emergerun2} --nodie"){ beep(); printmes(" ".gettext('error')."!\n"); return ''; }else{ #отметим успешное выполнение putini("run.make.step.update" => 1, "chroot"); printmes(" ".gettext('done').".\n"); } }else{ printmes(" ".gettext('Execute')); printmes(" emerge --noreplace world...\n"); if(system "$data{emergerun1} --noreplace @world $data{emergerun2} --nodie"){ beep(); printmes(" ".gettext('error')."!\n"); return ''; }else{ printmes(" ".gettext('done').".\n"); #The end check USE flags printmes(" ".gettext('Execute')); printmes(" emerge --newuse -D world...\n"); if(system "$data{emergerun1} --newuse -D world $data{emergerun2} --nodie"){ beep(); printmes(" ".gettext('error')."!\n"); return ''; }else{ printmes(" ".gettext('done').".\n"); } #сбросим успешно выполненную операцию putini("run.make" => "", "chroot"); #увеличим счетчик проходов my $step = getini("run.make.step.world", "chroot"); $step ++; putini("run.make.step.world" => $step, "chroot"); } $finish ++; } } return 1; } #------------------------------------------------------------------------------ # # Упакуем систему # #------------------------------------------------------------------------------ sub packsystem{ printmes(gettext('Packing the distribution package into the archive file').".\n"); #Вернем /etc/login.defs в прежнее состояние if(-e "$data{chroot}/etc/login.defs.old"){ printmes(" ".gettext('Restore')); printmes(" /etc/login.defs..."); system "$data{path} mv $data{chroot}/etc/login.defs.old $data{chroot}/etc/login.defs"; printmes(" ".gettext('done').".\n"); } #Установим пароль рута system "$data{path} chroot $data{'chroot'} sed -i -r 's/^root:.*/$data{hash_root}/' /etc/shadow"; system "$data{path} chroot $data{'chroot'} sed -i -r 's/^root:.*/$data{hash_root}/' /etc/shadow-"; #Добавим пользователя guest для десктопа # if($data{system} eq 'desktop' && $data{calculate} ne 'CLS' && !$data{createiso}){ # #Добавим пользователя guest # system "$data{path} chroot $data{'chroot'} groupadd --gid 1000 guest"; # system "$data{path} chroot $data{'chroot'} useradd --uid 1000 --gid 1000 --shell /bin/bash --groups audio,cdrom,plugdev,video,wheel,users guest"; #system "$data{path} chroot $data{'chroot'} mkdir -m 0700 /home/guest && chown guest. /home/guest"; # #Установим пароль пользователя guest # system "$data{path} chroot $data{'chroot'} sed -i -r 's/^guest:.*/$data{hash_guest}/' /etc/shadow"; # system "$data{path} chroot $data{'chroot'} sed -i -r 's/^guest:.*/$data{hash_guest}/' /etc/shadow-"; # } #Удалим записи сборки putini("run.make" => "", "chroot"); putini("run.make.step.system" => "", "chroot"); putini("run.make.step.world" => "", "chroot"); putini("run.make.step.newuse" => "", "chroot"); putini("run.make.step.update" => "", "chroot"); #Заменим устаревшие конфигурационные файлы printmes(" ".gettext('Replace outdated configuration files')); printmes("...\n"); if(system(qq|$data{path} chroot $data{'chroot'} /bin/bash -c "OVERWRITE_ALL='yes' etc-update"|)){ printmes(" ".gettext('error').".\n"); return ""; }else{ printmes(" ".gettext('done')); printmes(".\n"); } #Обновим базу портежей программы eix if(-e "$data{'chroot'}/usr/bin/eix-update"){ printmes(" ".gettext('Update portige base of eix programm')); printmes("..."); if(system(qq|$data{path} chroot $data{'chroot'} /bin/bash -c "eix-update &>/dev/null"|)){ printmes(" ".gettext('error').".\n"); }else{ printmes(" ".gettext('done')); printmes(".\n"); } } #Обновим базу PCI-устройств if(-e "$data{'chroot'}/usr/sbin/update-pciids"){ printmes(" ".gettext('Update PCI IDs')); printmes("..."); if(system("$data{path} chroot $data{'chroot'} update-pciids &>/dev/null")){ printmes(" ".gettext('error').".\n"); }else{ printmes(" ".gettext('done')); printmes(".\n"); } } #Обновим базу USB-устройств if(-e "$data{'chroot'}/usr/sbin/update-usbids"){ printmes(" ".gettext('Update USB IDs')); printmes("..."); if(system("$data{path} chroot $data{'chroot'} update-usbids &>/dev/null")){ printmes(" ".gettext('error').".\n"); }else{ printmes(" ".gettext('done')); printmes(".\n"); } } #Обновим антивирусную базу Clamav if(-e "$data{'chroot'}/usr/bin/freshclam"){ printmes(" ".gettext('Update Clamav antivirus database')); printmes("..."); if(system("$data{path} chroot $data{'chroot'} freshclam &>/dev/null")){ printmes(" ".gettext('error').".\n"); }else{ printmes(" ".gettext('done')); printmes(".\n"); } } #Сформируем базу module-rebuild if(-e "$data{'chroot'}/usr/sbin/module-rebuild populate"){ printmes(" ".gettext('Update module-rebuild database')); printmes("..."); if(system("$data{path} chroot $data{'chroot'} module-rebuild populate &>/dev/null")){ printmes(" ".gettext('error').".\n"); return ""; }else{ printmes(" ".gettext('done')); printmes(".\n"); } } #Выполним предварительное связывание пакетов if(-e "$data{'chroot'}/usr/sbin/prelink" && -e "$data{'chroot'}/etc/prelink.conf"){ printmes(" ".gettext('Execute prelinking packages')); printmes("..."); if(system("$data{path} chroot $data{'chroot'} prelink -afmR &>/dev/null")){ printmes(" ".gettext('error').".\n"); return ""; }else{ printmes(" ".gettext('done')); printmes(".\n"); } } #наложим профиль IMG profiles(); #Отмонтируем директории в точке монтирования printmes(" ".gettext('Umount directories')); printmes("..."); if(!umount_build_dirs()){ printmes(" ".gettext('error').".\n"); return ""; }else{ printmes(" ".gettext('done')); printmes(".\n"); } #Удалим временные файлы clearlog($data{chroot}); #Создадим архив системы printmes(" ".gettext('Create system archive file')); printmes("..."); chdir($data{'chroot'}); my $pathtar = "$data{linuxdir}/".lc($data{'calculate'})."-$data{linuxver}-$data{march}.tar.7z"; system "$data{path} rm -f $pathtar"; #удалим если такой файл есть if(system("$data{path} tar cf - . 2>/dev/null | 7za a -si $pathtar >/dev/null")){ printmes(" ".gettext('error').".\n"); return ""; }else{ system("$data{path} chmod 644 $data{linuxdir}/".lc($data{'calculate'})."-$data{linuxver}-$data{march}.tar.7z"); printmes(" ".gettext('done')); printmes(".\n"); } chdir($ENV{PWD}); #Создадим list-файл со списком собранных пакетов printmes(" ".gettext('Create')); printmes(" LIST "); printmes(gettext('file')); printmes("..."); my $path = "$data{'chroot'}/var/db/pkg"; my $list = "$data{linuxdir}/". lc($data{'calculate'})."-$data{linuxver}-$data{march}.list"; open LIST, ">$list"; opendir(T, $path); foreach(sort readdir T){ if($_ eq "." || $_ eq ".."){next;} my $type = $_; opendir(F, "$path/$type"); foreach(sort readdir F){ if($_ eq "." || $_ eq ".."){next;} print LIST "$type/$_\n"; } closedir F; } closedir T; close LIST; #упакуем в list.gz # system "$data{path} gzip $list"; printmes(" ".gettext('done')); printmes(".\n"); #Создадим DIGESTS-файл printmes(" ".gettext('Create')); printmes(" DIGESTS "); printmes(gettext('file')); printmes("..."); if(create_digests( "$data{linuxdir}/".lc($data{'calculate'}). "-$data{linuxver}-$data{march}.tar.7z" )){ printmes(" ".gettext('done')); printmes(".\n"); }else{ printmes(" ".gettext('error').".\n"); } #Отмонтируем chroot-диск printmes(" ".gettext('Umount chroot-disk')); printmes("..."); if(system("$data{path} umount $data{'chroot'}")){ printmes(" ".gettext('error').".\n"); # return ""; }else{ system("rmdir $data{'chroot'}"); printmes(" ".gettext('done')); printmes(".\n"); } printmes(gettext('All done')); printmes("!\n"); return 1; } #------------------------------------------------------------------------------ # Создадим DIGESTS-файл #------------------------------------------------------------------------------ sub create_digests{ my $file = $_[0]; my $name = $file; $name=~s/.*\/([^\/]+)$/$1/; my $digests = "$file.DIGESTS"; my $hash = get_hash("openssl md5 $file"); `echo "# MD5 HASH" > $digests`; `echo "$hash $name" >> $digests`; $hash = get_hash("openssl sha1 $file"); `echo "# SHA1 HASH" >> $digests`; `echo "$hash $name" >> $digests`; return 1; } #------------------------------------------------------------------------------ # Получим хэш из openssl #------------------------------------------------------------------------------ sub get_hash{ my $exec = $_[0]; my $hash = `$exec`; $hash =~m/= ([0-9a-f]+)$/; return $1; } #------------------------------------------------------------------------------ # # Удалим все файлы из указанной директории кроме .keep # #------------------------------------------------------------------------------ sub cleardir{ my $dir = $_[0]; opendir(DEL, $_); foreach(readdir DEL){ if($_ eq "." || $_ eq ".." || $_ eq ".keep"){next;} #printmes(gettext('Delete')); printmes(" $dir/$_\n"); system("$data{path} rm -rf $dir/$_"); } closedir DEL; } #------------------------------------------------------------------------------ # # Наложим обновления профилей на текущую систему # #------------------------------------------------------------------------------ sub update_profile{ #проверим на наличие профили foreach(split /,/, $data{arg}{'profile'}){ my $path, $profile; if(m/^([^\/]+)\/([^\/]+)$/){ $path = $1; $profile = $2; }else{ $profile = $_; } if($profile=~m/[^0-9a-z\/_\-*]/i){ printmes(gettext('Error')."! "); printmes(gettext('Invalid template')); printmes(" \"$_\".\n"); return "" } if(!$path && $_=~m/^all$/i){ @{$data{setprof}} = (@{$data{profile_install}}, @{$data{profile_share}}); next; }elsif($profile eq "*" && ($path eq "install" || $path eq "share")){ @{$data{setprof}} = @{$data{"profile_$path"}}; next; }elsif($path && -e "$data{dir}/$path/profile/$profile"){ push (@{$data{setprof}}, "$data{dir}/$path/profile/$profile"); }elsif(!$path && -e "$data{dir}/install/profile/$profile"){ push (@{$data{setprof}}, "$data{dir}/install/profile/$profile"); }elsif(!$path && -e "/usr/calculate/share/profile/$profile"){ push (@{$data{setprof}}, "/usr/calculate/share/profile/$profile"); }else{ printmes(gettext('Error')."! "); printmes(gettext('Invalid template')); printmes(" \"$_\".\n"); return "" } } if(!@{$data{setprof}}){ printmes(gettext('Error')."! "); printmes(gettext('Configuration template is not specified')); printmes(".\n"); return "" } #наложим выбранные профили на текущую систему $data{'chroot'} = ""; foreach(@{$data{setprof}}){profile($_);} return 1; } #------------------------------------------------------------------------------ # # Выполним строчные преобразования конфигурационных файлов # Хэш параметров: # lines - строки файла # nocomment - удалять комментарии # #------------------------------------------------------------------------------ sub convert{ my %par = ( nocomment => '', lines => '', @_, ); my @ext_comment; #в метки подставим переменные foreach(@{$par{lines}}){ my $i = 0; while($i==0){ #в метки подставим переменные if(m/#\-([^\$\@\-][^\#]+)\-#/i){ my $var = $1; #обработаем динамические переменные - #переменные, инициируемые при запросе my ($dynamic, $set) = dynamicvar($var); if($set){$data{$var} = $dynamic;} if(!defined $data{$var}){ printmes("\n".gettext('Not defined variable')); printmes(" #-$var-#, file \"$data{file}{name}\"."); $data{file}{error} ++; } s/#\-$var\-#/$data{$var}/g; }else{$i++} } push (@ext_comment, $_); } #обработаем блоки условий my @ext_block; my ($block, $pass); foreach(@ext_comment){ if($par{nocomment} && $_!~/[A-Za-z0-9#]/){next;} #пропустим пустые строки if($par{nocomment}){ $_=~s/^\s+(.)/$1/; #обрежем отступы от начала строки } #пропустим пакеты привязанные к архитектуре my ($block2, $pass2) = check_block($_); if($block2){ $block = $block2; $pass = $pass2; next; } #проверим на конец блока if($block && $_=~/^\s*#$block#\s*$/){$block = ''; next;} #пропустим если блок не соответствует условию if($block && $pass){next;} if($par{nocomment} && $_=~/^#/){next;} #пропустим строки с комментариями if($par{nocomment}){ $_=~s/^\s*([^#]+)#.*/$1/; #обрежем комментарии пакетов $_=~s/^(.*)([^\s]+)\s+$/$1$2/; #обрежем пробелы перед комментариями пакетов } push(@ext_block, $_); } return @ext_block; #вернем построчно } #------------------------------------------------------------------------------ # Сформируем динамические переменные - переменные, инициируемые при запросе #------------------------------------------------------------------------------ sub dynamicvar{ my $var = $_[0]; my $val = ""; my $set = ""; #список пакетов подлежащих размаскировке по заданной маске if($var=~m/^keywords:(.+)$/){ my $keywords = $1; $keywords =~s/A-Za-z0-9\-\.\_//m; foreach(packages()){ if(m/$keywords/){ $val.=lastver($_)." $data{unmask}\n"; } } #список установленных пакетов: `$data{path} find /var/db/pkg/ -type f | sed 's/-[0-9][0-9]*.*//' | uniq | sort` $set ++; }elsif($var=~m/^unmask:(.+)$/){ my $unmask = $1; $unmask =~s/A-Za-z0-9\-\.\_//m; foreach(packages()){ if(m/$unmask/){ $val.="$_\n"; } } $set ++; } return ($val, $set); } #------------------------------------------------------------------------------ # # Выполним сравнение имени файла с условием # Возвратим преобразованное имя файла без условия если принимается, либо ничего # #------------------------------------------------------------------------------ sub check_name{ my $filename = $_[0]; #проверим наличие регулярного выражения в файле if($filename=~m/^([^\?]+)\?(.+)/){ my $realname = $1; my $condition = $2; #проверим условия #разобьем условия ИЛИ foreach(split /\?/, $condition){ my $true = 1; #проверим условия И foreach(split /&/){ #считаем сравниваемые значения if(m/([^=>\<]+).+/$1/; #проверим условия #разобьем условия ИЛИ foreach(split /\?/, $condition){ my $true = 1; #проверим условия И foreach(split /&/){ m/([^=>" && (($type eq "num" && $a > $b) || ($type eq "char" && $a gt $b) || ($type eq "ver" && number_ver($a) > number_ver($b))) ){} elsif($chk eq "<=" && (($type eq "num" && $a <= $b) || ($type eq "char" && $a le $b) || ($type eq "ver" && number_ver($a) <= number_ver($b))) ){} elsif($chk eq ">=" && (($type eq "num" && $a >= $b) || ($type eq "char" && $a ge $b) || ($type eq "ver" && number_ver($a) >= number_ver($b))) ){} else{ return ''; } return 1; #условие было распознано и определено как верное } #------------------------------------------------------------------------------ # # Извлечем номер версии программы # Необходимо для численного сравнения версий, типа 7.8.1 # #------------------------------------------------------------------------------ sub number_ver{ my $num = $_[0]; $num=~m/([0-9]+)\.([0-9]+)\.?([0-9]+)?/; return $1 * 10000 + $2 * 100 + $3; } #------------------------------------------------------------------------------ # # Определим дополнительные монтируемые диски в fstab # #------------------------------------------------------------------------------ sub getdisk_fstab{ my (@mount_dev, @mount_dir, @mount_line); foreach(@_){ if(m/^\s*#/){next;} #определим устройства, сетевые диски и bind-монтирования if( m/^\s*(\/dev\/[^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([0-9])\s+([0-9])\s*$/ || m/^\s*([A-Za-z0-9\.]+:[^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([0-9])\s+([0-9])\s*$/ || m/^\s*(\/[^\s]+)\s+(\/[^\s]+)\s+([^\s]+)\s+(bind)\s+([0-9])\s+([0-9])\s*$/ ){ #пропустим системный раздел и устанавливаемый раздел if($1 eq "$data{rootload}"){next;} if($1 eq "$data{rootinstall}"){next;} if($1=~/:/ && $data{system} eq "desktop" && number_ver($data{linuxver}) > number_ver(9.5)){next;} #поскольку система ставится на один диск, исключим точки монтирования системных директорий if( $2 eq "/bin" || $2 eq "/boot" || $2 eq "/dev" || $2 eq "/etc" || $2 eq "/lib" || $2 eq "/opt" || $2 eq "/sbin" || $2 eq "/usr" || $2 eq "/var" ){next;} #пропустим своп-диск if($3=~/swap/i){next;} #пропустим loop-устройства if($1=~m/^\/dev\/loop[0-9]$/i){next;} push(@mount_dev, $1); #диски монтирования push(@mount_dir, $2); #пути монтирования push(@mount_line, $_); #fstab-строки } } return ([@mount_dev], [@mount_dir], [@mount_line]); } #------------------------------------------------------------------------------ # # Дополним fstab настройками старого профиля # #------------------------------------------------------------------------------ sub move_fstab{ my @lines = @_; my @newlines; #отличительные строки предыдущего fstab my ($mount_dev, $mount_dir, $mount_line) = getdisk_fstab(@lines); #заполним хэш для сравнения my $i = 0; my %check_disk; foreach(@{$mount_dev}){ $check_disk{"$_+${$mount_dir}[$i]"} = ${$mount_line}[$i]; $i++; } my $i = -1; foreach(@{$data{mount_dev}}){ $i++; if(!$check_disk{"$_+${$data{mountdir}}[$i]"}){ #если в старом профиле был примонтирован диск, #перенесем запись и создадим директорию пути push(@newlines, ${$data{mount_line}}[$i]); #пропустим создание директории, если она находится #внутри монтируемого диска my $skip = 0; my $k; foreach($k=0; $k<$i; $k++){ if(${$data{mountdir}}[$i]=~m/^${$data{mountdir}}[$k]/){ $skip++; } } #создадим директорию точки монтирования if(!-e "$data{'chroot'}$data{scratch_ws}${$data{mountdir}}[$i]" && !$skip){ system "$data{path} mkdir -p -m 755 $data{'chroot'}$data{scratch_ws}${$data{mountdir}}[$i]"; } } } return (@lines, @newlines); } #------------------------------------------------------------------------------ # # Прерывание сборки системы - отмонтирование дисков и удаление # установочной директории # #------------------------------------------------------------------------------ sub breakbuild{ printmes(gettext('Break the system building')); printmes("..."); #отмонтируем все директории и точку монтирования umount_build_all(); printmes(" ".gettext('done').".\n"); return 1; } #------------------------------------------------------------------------------ # # Отмонтируем все директории и точку монтирования # #------------------------------------------------------------------------------ sub umount_build_all{ #отмонтируем все директории в точке монтирования umount_build_dirs(); #отмонтируем и удалим директорию точки монтирования system "$data{path} umount -l $data{chroot}"; system "$data{path} rmdir $data{chroot}"; return 1; } #------------------------------------------------------------------------------ # # Отмонтируем все директории в точке монтирования # #------------------------------------------------------------------------------ sub umount_build_dirs{ foreach(`$data{path} mount`){ if(/on\s+($data{chroot}\/[^\s]+)/){ #отмонтируем с флагом -l system "$data{path} umount -l $1"; } } return 1; } #------------------------------------------------------------------------------ # # Создадим загружаемый iso-образ системы # #------------------------------------------------------------------------------ sub createiso{ #проверим что не запущен cl-builder if( #`mount | grep "on /mnt/builder/var/calculate/remote" #|| `mount | grep -c "devpts on /dev/pts "` != 1 `ps ax | grep -c "cl-builder"` > 2 ) { printmes(gettext('Error')."! "); printmes(gettext('Before proceeding, complete the program cl-builder')); printmes(".\n"); return ""; } #проверим что система загружена в Scratch режиме и на флешке if(defined $data{arg}{rebuild} && ($data{scratch} ne "on" || $data{load} ne "ram" || !-e "/mnt/flash")){ printmes(gettext('Error')."! "); printmes(gettext('The computer must be load from the flash in Scratch mode')); printmes(".\n"); return ""; } #образ не найден, найден ISO образ системы, загрузились в обычном режиме либо в память с CD или Flash if((!$data{linux} || $data{linux} =~m/iso$/ || $data{linux} eq 'livecd') && $data{scratch} eq "off"){ printmes(gettext('Error')."! "); printmes(gettext('The archive with image of system is not found')); printmes(".\n"); return ""; } #распакуем систему if($data{scratch} eq "off"){ printmes(" ".gettext('Unpacking system')); printmes("..."); }else{ printmes(" ".gettext('Mount Scratch system')); printmes("..."); } #создадим временную директорию system "$data{path} mkdir -p '$data{tmpdir}'"; #выберем команду распаковки в зависимости от типа архива my $unpack; if($data{scratch} eq "on"){ $unpack = "mount -o bind /mnt/builder $data{tmpdir}/livecd/calculate"; }elsif($data{linux} =~m/7z$/){ $unpack = "7za x -so $data{linuxdir}/$data{linux} 2>/dev/null | tar xf - -C $data{tmpdir}/livecd/calculate"; }elsif($data{linux} =~m/lzma$/){ $unpack = "lzma -dc $data{linuxdir}/$data{linux} | tar -xf - -C $data{tmpdir}/livecd/calculate"; }else{ $unpack = "tar -xjf $data{linuxdir}/$data{linux} -C $data{tmpdir}/livecd/calculate"; } if(system("mkdir -p $data{tmpdir}/livecd/calculate && $unpack")){ printmes(" ".gettext('error').".\n"); breakiso(); return ""; }else{ printmes(" ".gettext('done')); printmes(".\n"); } #наложим профили на распакованную систему profiles(); #выполним подмены { my $path = "$data{tmpdir}/livecd/calculate"; #поправим автовход в initrd system "$data{path} sed -i -e '/^c[0-9]/ s/^/#/' $path/etc/inittab"; system "$data{path} sed -i -e '/^s[01]/ s/^/#/' $path/etc/inittab"; for(my $i = 1; $i<=6; $i++){ system qq|echo "c$i:12345:respawn:/sbin/agetty -nl /bin/bashlogin 38400 tty$i linux" >> $path/etc/inittab|; } } #удалим следы пребывания в scratch clearlog("$data{tmpdir}/livecd/calculate/"); #преобразуем в sys формат isotosys(); #delete old squashfs if(defined $data{arg}{rebuild} && $data{squash_del}){ printmes(" ".gettext('Removing old image of system')); printmes("..."); if(system("rm /mnt/flash/$data{squash_del}")){ printmes(" ".gettext('error').".\n"); breakiso(); return ""; }else{ printmes(" ".gettext('done')); printmes(".\n"); } } #создадим livecd.squashfs my $squashfile; if(!defined $data{arg}{rebuild}){ $squashfile = "$data{tmpdir}/livecd/target/$data{squash_cur}"; }else{ $squashfile = "/mnt/flash/$data{squash_cur}" } printmes(" ".gettext('Count files for image')); printmes("..."); my $filesnum=int(`/usr/bin/find $data{tmpdir}/livecd/calculate/ | wc -l`); my $calc_ini="$data{tmpdir}/livecd/calculate/etc/calculate/calculate.ini"; system(qq{ grep ^files= $calc_ini &>/dev/null && sed -ri "s/(^files=)(.*)\$/\\1$filesnum/" $calc_ini || echo "files=$filesnum" >>$calc_ini } ); printmes(" ".gettext('done')); printmes(".\n"); printmes(" ".gettext('Packing system into squashfs format')); printmes("..."); if(system("/usr/bin/mksquashfs $data{tmpdir}/livecd/calculate/ $squashfile &>/dev/null")){ printmes(" ".gettext('error').".\n"); breakiso(); return ""; }else{ printmes(" ".gettext('done')); printmes(".\n"); } #подготовим к упаковке printmes(" ".gettext('Prepare syslinux')); printmes("..."); my $target = "$data{tmpdir}/livecd/target"; my $copyflash; my $isolinux = "isolinux"; if(defined $data{arg}{rebuild}){ $copyflash = "&& cp -r $target/* /mnt/flash/"; $isolinux = "syslinux"; } else { my $addsoft; { my $mempath = "$target/isolinux/memtest"; if(-e $mempath){$addsoft .= "&& cp -a $mempath $target/syslinux/";} } $copyflash = qq| $addsoft && cp -a $target/isolinux/isolinux.bin $target/syslinux/ && cp -a $target/isolinux/calcmenu.c32 $target/syslinux/ && cp $target/isolinux/boot.jpg $target/syslinux/ |; } #перенесем ядро и меню на флешку my $addsoft; { my $mempath = "$data{tmpdir}/livecd/calculate/boot/memtest86plus/memtest.bin"; if(-e $mempath){$addsoft .= "cp -rpL $mempath $target/$isolinux/memtest &&";} } if(system(qq| cp $data{tmpdir}/livecd/calculate/boot/vmlinuz $target/boot/vmlinuz && cp $data{tmpdir}/livecd/calculate/boot/initrd $target/boot/ && $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(){ 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=); system "stty echo" if (-t STDIN); print "\n"; printmes(gettext('Retype new password')); printmes(" :"); system "stty -echo" if (-t STDIN); chomp($pass2=); 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=; $/ = $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("..."); if(`mount | grep -c "on /proc type proc"` > 1) { printmes(" ".gettext('skip')."!\n"); return; } if(!initrd_clean($chroot)){ beep(); printmes(" ".gettext('error')."!\n"); } } #------------------------------------------------------------------------------ # Получить из конфигурации ядра список встроенных или внешних модулей #------------------------------------------------------------------------------ sub get_kernel_config{ # первый параметр текст конфигурации ядра # второй y или m (встроенный или внешний) my ($kconfig,$value) = @_; my @list=(); # получаем список опций из областей SCSI Transport, # File systems,Pseudo filesystems, # CDROM/DVD Filesystems, DOS/FAT/NT Filesystems foreach($kconfig =~ m/((?:[Ff]ile[s ][sy]|SCSI Transports).*?\n\n#)/sg) { # получаем список модулей foreach(m/^(.*)=${value}$/gm) { push(@list,$_."\n"); } } return @list; } #------------------------------------------------------------------------------ # Создадим урезанный по железу initrd файл #------------------------------------------------------------------------------ sub initrd_clean{ my $chroot = $_[0]; # получим список встроенных модулей в текущем ядре my @list_current_y=get_kernel_config(scalar `gzip -dc /proc/config.gz`,"y"); # получим имя файла конфигурации текущего ядра my $config=`file -L $chroot$data{scratch_ws}/boot/vmlinuz`; $config =~ s/^.*version ([^ ]+) .*$/$chroot$data{scratch_ws}\/boot\/config-\1/; # получим список внешних модулей в ядре в chroot my @list_chroot_m=get_kernel_config(scalar `cat $config`,"m"); # попытаемся найти одноименные модули @hash{@list_chroot_m}=(); @filtred=grep { exists $hash{$_} } @list_current_y; # если есть одноименные модули не делаем оптимизацию initrd if(@filtred) { printmes(" ".gettext('skip')); printmes(".\n"); return 1; } #найдем среди запущенных модулей не задействованные, которые можно удалить my %mod_dep; #хэш зависимостей, ключ - модуль, значение - модули его использующие my %mod_run; #хэш работающих модулей my %mod_all; #все модули foreach(`$path lsmod`){ if(m/^Module/){next;} if(m/^([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)?$/){ my $dep = 0; if($4){ foreach(split /,/, $4){ $dep ++; if($mod_dep{$_}){$mod_dep{$_}.=","} $mod_dep{$_}.="$1"; } } if($3 > $dep){ $mod_run{$1} ++; } $mod_all{$1} ++; } } #получим пути к модулям foreach(keys %mod_all){ my $type = `modinfo $_ | grep "filename:"`; chomp $type; $type=~m/^filename:\s+([^\s]+)$/; $mod_all{$_} = $1; } #уберем некоторые из работающих модулей foreach(keys %mod_run){ if( $mod_all{$_}!~m#/kernel/# || $mod_all{$_}=~m#/kernel/fs/cifs/# || $mod_all{$_}=~m#/kernel/fs/nfs/# ){delete $mod_run{$_};} } #объединим работающие модули с зависимостями foreach(keys %mod_run){ if($mod_dep{$_}){ foreach(split /,/, $mod_dep{$_}){ $mod_run{$_} ++; } } } #создадим временную директорию system "$data{path} mkdir -p '$data{tmpdir}'"; #распакуем initrd if(!-e "$chroot$data{scratch_ws}/tmp"){`mkdir -m 1777 "$chroot$data{scratch_ws}/tmp"`;} my $tmpdir = "$chroot$data{scratch_ws}/tmp/initrd"; `$data{path} rm -rf $tmpdir`; `$data{path} mkdir $tmpdir`; chdir($tmpdir); my $initrd = "$chroot/boot/initrd"; # скопируем initrd в initrd-install, если initrd-install отсутствует if(!-e "${initrd}-install") { # скопируем текущий initrd в initrd-install system("cp -aH ${initrd} ${initrd}-install"); } # подберем утилиту для распаковки my $archcmd; if(!system("which lzma &>/dev/null") && !system("lzma --force -t $chroot/boot/initrd-install &>/dev/null")) { $archcmd = "lzma"; } elsif(!system("which bzip2 &>/dev/null") && !system("bzip2 -t $chroot/boot/initrd-install &>/dev/null")) { $archcmd = "bzip2"; } else { $archcmd = "gzip"; } `$data{path} cp $chroot/boot/initrd-install $tmpdir/initrd-install`; `$data{path} $archcmd -dc $tmpdir/initrd-install | cpio -idv >/dev/null 2>&1`; `$data{path} rm $tmpdir/initrd-install`; #удалим неработающие модули из initrd, за некоторым исключением foreach(`$data{path} find $tmpdir/lib/modules/ -name *.ko`){ m/\/([^\/]+)\.ko$/; #проверим варианты где "-" либо "_" меняются в названии модуля и файла my $underline = $1; my $dash = $underline; $underline=~s/\-/\_/g; $dash =~s/_/\-/g; if(!$mod_run{$underline} && !$mod_run{$dash} && $1 ne 'squashfs' && $1 ne 'zlib_inflate' && $1 ne 'aufs' && $1 ne 'exportfs' && $1 ne 'unionfs' && $1 ne 'dm_mod' ){ `rm $_`; } } # извлечем из squash образа конфигурацию ядра my $curkernel; if($data{scratch_ws}){ unsquash("/usr/src/linux"); $curkernel = `readlink $chroot$data{scratch_ws}/usr/src/linux`; chomp($curkernel); unsquash("/usr/src/${curkernel}/.config") if $curkernel; }else{ $curkernel = `readlink $chroot/usr/src/linux`; chomp($curkernel); } # # проверим поддерживается ли ядром сжатие lzma и есть ли в наличии утилита lzma # if( -e "$chroot$data{scratch_ws}/usr/src/$curkernel/.config" && `cat $chroot$data{scratch_ws}/usr/src/linux/.config | \ # grep -Pc "^CONFIG_RD_LZMA=y|^CONFIG_INITRAMFS_COMPRESSION_LZMA=y"` == 2 && # !system("which lzma &>/dev/null") ) { # $archcmd = "lzma"; # } # else { $archcmd = "gzip"; # } #соберем распакованный initrd `$data{path} find * | cpio -o --quiet -H newc | $archcmd -9 > $chroot/boot/initrd`; chdir($ENV{PWD}); `$data{path} rm -rf $tmpdir`; printmes(" ".gettext('done')); printmes(".\n"); return 1; } #------------------------------------------------------------------------------ # Установка дополнений #------------------------------------------------------------------------------ sub addition{ my $path = "/usr/calculate/share/addition/"; my $find = lc($data{'calculate'})."\-(.*)-($data{os})\-$data{march}\.tar"; my $chk; if(-e $path){ foreach(`$data{path} find $path | sort`){ chomp $_; if($_=~m/\/$find$/){ #проверим на то, что обновление уже установлено if(!getini("addition.$1") || defined $data{arg}{'force'}){ printmes("\n ".gettext('Addition is found')); printmes(": ".ucfirst($1)." $2\n"); if($data{sleep} > 0){ printmes("\n".gettext('Installation of addition will begin through')); printmes(" $data{sleep} "); printmes(gettext('seconds')); printmes(".\n"); printmes(gettext('Press')); printmes(" Ctrl+C "); printmes(gettext('to cancel')); printmes("... "); my $sleep = $data{sleep} - 1; if(system(q|echo -e -n "\a|.$data{sleep}.q|"; sleep 1; for ((i=|.$sleep.q|; $i>0; i--)); do echo -e -n "\a\b\b $i"; sleep 1; done; echo -e "\b\b ";|)){ printmes("\n"); return ""; } } #распакуем дополнение printmes(" ".gettext('Unpack')); printmes("..."); my $extract; if(number_ver($data{os}) > number_ver(8.7)){ if(!-e $data{pkgdir}){system "$data{path} mkdir -p $data{pkgdir}";} $extract = $data{pkgdir}; }else{ $extract = "/"; } my $packages; #список пакетов foreach(`$data{path} tar -xvf $_ -C $extract`){ chomp; if(m/\/All\// || !m/tbz2/){next;} m/([^\/]+\/[^\/]+)\.tbz2$/; $packages .= " =$1"; #сформируем переменную для установки push(@{$data{packageslist}}, "=$1"); #сформируем массив для проверки зависимостей } printmes(" ".gettext('done')); printmes(".\n"); #проверим зависимости if(!dependence('hide')){ beep(); exit; } #проверим пакеты, которые нужно установить my @install; printmes(" ".gettext('Compare to the list of the established packages')); printmes("..."); foreach(`emerge -p$packages 2>&1`){ if( m/\[ebuild\s+N\s+\]/ || m/\[ebuild\s+U\s+\]/ || (defined $data{arg}{'force'} && m/\[ebuild\s+.+\]/) ){ m/\[ebuild[^\]]+\]\s+([^\s]+)/; #выделим пакет с версией push (@install, $1); } } printmes(" ".gettext('done')); printmes(".\n"); if(@install){ #установим необходимые пакеты printmes(gettext('Perform installation')); printmes(":\n"); my $num = 1; my $all = @install; foreach(@install){ #printmes(' '.gettext('Unpack')); printmes(" ($num "); printmes(gettext('of')); printmes(" $all) $_..."); if(system "$data{path} emerge --usepkg =$_ &>/dev/null"){ printmes(" ".gettext('error').".\n"); exit; }else{ printmes(" ".gettext('done')); printmes(".\n"); } $num ++; } } putini("addition.$1" => "$2"); $chk ++; #флаг успешного обновления } } } }else{ `$data{path} mkdir -p $path`; } if(!$chk){ printmes("\n".gettext('No updates available')); printmes(".\n"); }else{ printmes(gettext('All done')); printmes("!\n"); } } #------------------------------------------------------------------------------ # Покажем список пакетов входящих в дополнение #------------------------------------------------------------------------------ sub listadd{ if(!checkadd()){return "";} printmes(gettext('Package list incoming in the addition')); printmes(" \"".ucfirst($data{addition})."\"...\n"); #отобразим на экране список пакетов my $i = 0; foreach(packages()){ printmes("$_\n"); $i++; } printmes("\n"); printmes(gettext('All')); printmes(" $i "); printmes(gettext('packages')); printmes(".\n"); return 1; } #------------------------------------------------------------------------------ # Соберем пакет дополнения #------------------------------------------------------------------------------ sub makeadd{ if(number_ver($data{os}) <= number_ver(8.7)){ printmes(gettext('It is supported in systems of versions')); printmes(" > 8.7\n"); return ""; } if(!checkadd()){return "";} #проверим зависимости if(!dependence()){ beep(); exit; } if($data{sleep} > 0){ printmes("\n".gettext('Assembly of addition will begin through')); printmes(" 10 "); printmes(gettext('seconds')); printmes(".\n"); printmes(gettext('Press')); printmes(" Ctrl+C "); printmes(gettext('to cancel')); printmes("... "); my $sleep = $data{sleep} - 1; if(system(q|echo -e -n "\a|.$data{sleep}.q|"; sleep 1; for ((i=|.$sleep.q|; $i>0; i--)); do echo -e -n "\a\b\b $i"; sleep 1; done; echo -e "\b\b ";|)){ printmes("\n"); return ""; } } printmes(gettext('Make addition')."\n"); #создадим временную директорию system "$data{path} mkdir -p '$data{tmpdir}'"; my @packages = packages(); #получим список пакетов дополнения #путь к собираемым бинарным файлам пакетов дополнения my $pathadd = "$data{tmpdir}/packages/$data{addition}/$data{calculate}/$data{linuxver}/$data{march}"; #путь к архиву my $pathtar = "/usr/calculate/share/addition/". lc($data{'calculate'})."-$data{addition}-$data{linuxver}-$data{march}.tar"; #путь к LIST-файлу my $pathlist = "/usr/calculate/share/addition/". lc($data{'calculate'})."-$data{addition}-$data{linuxver}-$data{march}.list"; #соберем пакеты, без записи в world файл if(system "$data{path} PKGDIR=\"$pathadd\" emerge --buildpkg --oneshot --noreplace @packages"){ beep(); printmes(" ".gettext('error')."!\n"); return ''; return ""; }else{ printmes(" ".gettext('done').".\n"); } #упакуем в пакет дополнения скомпилированные программы printmes(" ".gettext('Packing addition')); printmes("..."); chdir($pathadd); if(system("$data{path} tar -cf $pathtar .")){ printmes(" ".gettext('error').".\n"); return ""; }else{ printmes(" ".gettext('done')); printmes(".\n"); } chdir($ENV{PWD}); #удалим бинарные файлы программ printmes(" ".gettext('Delete temporary files')); printmes("..."); if(system "rm -rf $data{tmpdir}"){ printmes(" ".gettext('error').".\n"); return ""; }else{ printmes(" ".gettext('done')); printmes(".\n"); } #деинсталлируем собранные пакеты, чтобы привести систему в первоначальный вид printmes(" ".gettext('Uninstall packages')); printmes("..."); my $packages, %list; #список пакетов foreach(`$data{path} tar -tf $pathtar`){ chomp; if(m/\/All\// || !m/tbz2/){next;} m/([^\/]+\/[^\/]+)\.tbz2$/; $packages .= " =$1"; $list{$1} ++; } if(system "$data{path} CLEAN_DELAY=0 emerge -C --backtrack=0 $packages &>/dev/null"){ printmes(" ".gettext('error').".\n"); return ""; }else{ printmes(" ".gettext('done')); printmes(".\n"); } #Создадим list-файл со списком собранных пакетов printmes(" ".gettext('Create')); printmes(" LIST "); printmes(gettext('file')); printmes("..."); open LIST, ">$pathlist"; foreach(sort keys %list){ print LIST "$_\n"; } close LIST; printmes(" ".gettext('done')); printmes(".\n"); #Создадим DIGESTS-файл printmes(" ".gettext('Create')); printmes(" DIGESTS "); printmes(gettext('file')); printmes("..."); if(create_digests($pathtar)){ printmes(" ".gettext('done')); printmes(".\n"); }else{ printmes(" ".gettext('error').".\n"); } printmes("\n".gettext('All done')); printmes("!\n"); return 1; } #------------------------------------------------------------------------------ # Проверим имя пакета дополнения #------------------------------------------------------------------------------ sub checkadd{ if(defined $data{addition} && packages()){ return 1; }elsif(!defined $data{addition}){ printmes(gettext('Addition name is not specified')); printmes(".\n"); }elsif(!packages()){ printmes(gettext('Packages addition')); printmes(" \"$data{addition}\" "); printmes(gettext('not found')); printmes(".\n"); } printmes(gettext('Try')); printmes(" 'calculate --help' "); printmes(gettext('for more information')); printmes(".\n"); beep(); return ""; } #------------------------------------------------------------------------------ # Установим по необходимости видеодрайвер #------------------------------------------------------------------------------ sub video{ printmes(gettext('Check the video driver')); printmes("... "); if( $data{video_drv} eq 'nvidia' && -e "/usr/portage/packages/x11-drivers" ){ my $filemask = "/etc/portage/package.mask/nvidia-drivers"; #создадим директорию package.mask для версий Calculate Linux < 9.2 if(-f "/etc/portage/package.mask"){ system "$data{path} mv /etc/portage/package.mask /etc/portage/package.mask2"; system "$data{path} mkdir /etc/portage/package.mask"; system "$data{path} mv /etc/portage/package.mask2 /etc/portage/package.mask/default"; } my $maskold; if(-f $filemask){ $maskold = `cat $filemask`; chomp $maskold; } my $mask = nvidia_mask(); printmes(gettext('done').".\n"); #обновим драйвер if($mask ne $maskold){ printmes(" ".gettext('Driver Installation for')); printmes(" \"$data{video}\"... "); system "echo '$mask' > $filemask"; if(system "PKGDIR=\"/usr/portage/packages\" emerge -k nvidia-drivers > /dev/null"){ #в случае неудачи, удалим маску system "rm $filemask"; printmes(gettext('error').".\n"); }else{ printmes(gettext('done').".\n"); } } }else{ printmes(gettext('done').".\n"); } } #------------------------------------------------------------------------------ # Маска для установки необходимой версии nvidia драйвера #------------------------------------------------------------------------------ sub nvidia_mask{ my $mask = `bash -c "function inherit { echo -n ''; };. /usr/portage/eclass/nvidia-driver.eclass && nvidia-driver-get-mask"`; chomp $mask; return $mask; } #------------------------------------------------------------------------------ # Звуковое предупреждение #------------------------------------------------------------------------------ sub beep{ # if(-e "/usr/bin/play" && -e "/usr/share/sounds/pop.wav"){ # `/usr/bin/play /usr/share/sounds/pop.wav 2>&1 >/dev/null`; # }else{ system "echo -e -n \"\a\""; # } } #------------------------------------------------------------------------------ # Соберем бинарные пакеты дополнений (nVideo драйвера) #------------------------------------------------------------------------------ sub makepkg{ if($data{system} eq "server" || $data{calculate} eq "CLS" || $data{calculate} eq "CLSG"){return 1;} printmes(gettext('Make nvidia drivers')."\n"); printmes(" ".gettext('nvidia-drivers-71.XX.XX')); printmes("... "); `echo ">x11-drivers/nvidia-drivers-72.00.00" > $data{'chroot'}/etc/portage/package.mask/nvidia`; if(system "PKGDIR=\"/usr/portage/packages\" $data{emergerun1} -b x11-drivers/nvidia-drivers $data{emergerun2} &>/dev/null"){ #beep(); printmes(gettext('error').".\n"); #return ''; }else{ printmes(gettext('done').".\n"); } printmes(" ".gettext('nvidia-drivers-96.XX.XX')); printmes("... "); `echo ">x11-drivers/nvidia-drivers-97.00.00" > $data{'chroot'}/etc/portage/package.mask/nvidia`; if(system "PKGDIR=\"/usr/portage/packages\" $data{emergerun1} -b x11-drivers/nvidia-drivers $data{emergerun2} &>/dev/null"){ beep(); printmes(gettext('error').".\n"); return ''; }else{ printmes(gettext('done').".\n"); } printmes(" ".gettext('nvidia-drivers-173.XX.XX')); printmes("... "); `echo ">x11-drivers/nvidia-drivers-174.00.00" > $data{'chroot'}/etc/portage/package.mask/nvidia`; if(system "PKGDIR=\"/usr/portage/packages\" $data{emergerun1} -b x11-drivers/nvidia-drivers $data{emergerun2} &>/dev/null"){ beep(); printmes(gettext('error').".\n"); return ''; }else{ printmes(gettext('done').".\n"); } printmes(" ".gettext('nvidia-drivers-last')); printmes("... "); `rm $data{'chroot'}/etc/portage/package.mask/nvidia`; if(system "$data{emergerun1} x11-drivers/nvidia-drivers $data{emergerun2} &>/dev/null"){ beep(); printmes(gettext('error').".\n"); return ''; }else{ printmes(gettext('done').".\n"); } return 1; } #------------------------------------------------------------------------------ # Соберем стабильную версию calculate #------------------------------------------------------------------------------ #sub makecalculate{ # if(`mount | grep $data{chroot}/usr/calculate/install`){ # #Отмонтируем /usr/calculate/install # printmes(" ".gettext('Umount')); printmes(" /usr/calculate/install..."); # if(system "$data{path} umount $data{chroot}/usr/calculate/install &>/dev/null"){ # printmes(" ".gettext('error')."!\n"); # return ''; # }else{ # printmes(" ".gettext('done').".\n"); # } # # #Установим calculate # printmes(" ".gettext('Execute')); printmes(" emerge sys-apps/calculate..."); # if(system "$data{path} chroot $data{chroot} emerge sys-apps/calculate &>/dev/null"){ # printmes(" ".gettext('error')."!\n"); # return ''; # }else{ # printmes(" ".gettext('done').".\n"); # } # } # return 1; #} #------------------------------------------------------------------------------ # Подключим своп #------------------------------------------------------------------------------ sub swapon{ if($data{swap} && !`cat /proc/swaps | grep "$data{swap}"`){ printmes(" ".gettext('Mounting swap')); printmes("... "); if(system "$data{path} swapon $data{swap}"){ printmes(gettext('Error')); printmes("! "); }else{ printmes(gettext('done').".\n"); } } return 1; } #------------------------------------------------------------------------------ # Определим USB устройства Flash и USB-HDD #------------------------------------------------------------------------------ sub check_removable{ my $dev = $data{arg}{'disk'}; if(!$dev || !$data{hal}){return "hdd";} $dev =~m#^(/dev/[^\/0-9]+)[0-9]?[0-9]?$#; my $disk = $1; if( !$disk ) { return "hdd"; } my $isusb = `$data{path} hal-find-by-property --key block.device --string $disk | xargs -I {} hal-get-property --udi '{}' --key storage.bus 2>/dev/null`; chomp($isusb); if( $isusb eq "usb" ) { my $isflash = `$data{path} hal-find-by-property --key block.device --string $disk | xargs -I {} hal-get-property --udi '{}' --key storage.removable 2>/dev/null`; chomp($isflash); if( $isflash eq "true" ) { return "flash"; } else { return "usb-hdd"; } } return "hdd"; } #------------------------------------------------------------------------------ # установим $data{swapset} и $data{swap_resume} #------------------------------------------------------------------------------ sub swapset{ if($data{swap}){ printmes(" ".gettext('Swap disk')); printmes(": $data{swap}\n"); if($data{'uuid'} eq 'on'){ $data{swapset} = qq|UUID=$data{uuid_swap}\tnone\t\tswap\tsw\t\t\t0 0|; $data{swap_resume} = "resume=UUID=$data{uuid_swap}"; }else{ $data{swapset} = qq|$data{swap}\tnone\t\tswap\tsw\t\t\t0 0|; $data{swap_resume} = "resume=$data{swap}"; } }else{ $data{swapset} = ""; $data{swap_resume} = "noresume"; } return 1; } #------------------------------------------------------------------------------ # извлечем из squashfs файлы #------------------------------------------------------------------------------ sub unsquash{ my $squash = "$data{mount}/livecd.squashfs"; system("$data{path} unsquashfs -n -d $data{mount}$data{scratch_ws} -f $squash @_ &>/dev/null"); } #------------------------------------------------------------------------------ # Проверим наличие файла в образе #------------------------------------------------------------------------------ sub checksquash{ my $file = $_[0]; my $squash = "$data{mount}/livecd.squashfs"; return !system("$data{path} unsquashfs -ls $squash $file | grep -P '^squashfs-root$file' &>/dev/null"); } #------------------------------------------------------------------------------ # удалим временные файлы #------------------------------------------------------------------------------ sub clearlog{ $chroot = $_[0]; printmes(" ".gettext('Delete temporary files')); printmes("..."); system("$data{path} rm -rf $chroot/etc/resolv.conf $chroot/etc/mtab $chroot/var/log/emerge* $chroot/var/log/genkernel.log $chroot/var/log/lastlog $chroot/var/log/prelink.log $chroot/var/log/wtmp $chroot/var/.locks $chroot/var/.svn-src $chroot/var/calculate/remote/distfiles/* $chroot/var/lib/gentoo/news/* $chroot/var/lib/portage/world $chroot/root/.viminfo $chroot/root/.bash_history $chroot/root/.subversion $chroot/var/calculate/tmp/*"); foreach( "$chroot/var/tmp/portage", "$chroot/tmp", "$chroot/var/log/clamav", "$chroot/var/log/calculate", "$chroot/var/log/portage/elog", ){ cleardir($_); } #Заново сформируем world foreach(packages()){ system "echo '$_' >> $chroot/var/lib/portage/world"; } printmes(" ".gettext('done')); printmes(".\n"); } #------------------------------------------------------------------------------ # Авторазмаскировка пакетов #------------------------------------------------------------------------------ sub autounmask{ dependence(); } #------------------------------------------------------------------------------ # Настроим OpenGL #------------------------------------------------------------------------------ sub opengl_set{ if($data{run_opengl}){ system "$data{run_opengl}"; } } #------------------------------------------------------------------------------ # Извлечем информацию о разделе # параметры - раздел, тип информации #------------------------------------------------------------------------------ sub uuid{ my $info = `$data{path} blkid $_[0] 2>/dev/null`; if($_[1] eq 'UUID'){ $info =~s/.*UUID="([^"]+)".*/$1/; }elsif($_[1] eq 'TYPE'){ $info =~s/.*TYPE="([^"]+)".*/$1/; } chomp $info; return $info; } #------------------------------------------------------------------------------ # Удалим файлы не используемую локализацию #------------------------------------------------------------------------------ sub clearlang{ my @remote; foreach( @{$data{clearlang}} ){ my $lang = $_; foreach( '/usr/lib/openoffice', '/usr/share/apps', '/usr/share/doc', '/usr/share/locale', '/usr/share/man', '/usr/share/vim', '/usr/share/xfce4/doc', '/usr/share/gnome/help' ){ if(-e "$data{'chroot'}$_"){ foreach(`find $data{'chroot'}$_ -type d -name $lang`){ chomp; system "rm -rf $_"; } } } } }