From 6a1bb9f9a3e55d3675b3da2037582113550f4401 Mon Sep 17 00:00:00 2001 From: freesource Date: Mon, 17 Dec 2001 18:13:18 +0000 Subject: [PATCH] This is the beginning of better symbol control, ars will be dispensed with. Basically gbootroot has just one function start() called from BootRoot. Eventually BootRoot will be split further into ARS and ABS. This makes more sense then having one large gbootroot .. it just grew too much. --- BootRoot/BootRoot.pm | 4300 ++++++++++++++++++++++++++++++++++++++++++ gbootroot | 4247 +---------------------------------------- 2 files changed, 4309 insertions(+), 4238 deletions(-) create mode 100644 BootRoot/BootRoot.pm diff --git a/BootRoot/BootRoot.pm b/BootRoot/BootRoot.pm new file mode 100644 index 0000000..50f111c --- /dev/null +++ b/BootRoot/BootRoot.pm @@ -0,0 +1,4300 @@ +#!/usr/bin/perl -w + +########################################################################### +## +## BootRoot.pm +## Copyright (C) 2000, 2001 by Jonathan Rosenbaum +## + +## +## This program is free software; you may redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 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, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +## +############################################################################## + + +package BootRoot::BootRoot; +use vars qw(@ISA @EXPORT %EXPORT_TAGS); +use Exporter; +@ISA = qw(Exporter); +@EXPORT = qw(start); + +use strict; +use BootRoot::Yard; +use BootRoot::YardBox; +use BootRoot::Error; +use File::Basename; +use File::Find; +use File::Path; + + +# If you want gBootRoot to do it's stuff somewhere else, change the +# value for $tmp1. +my $tmp1 = "/tmp"; # tmp should be default - Cristian +my $lilo_conf = "/etc/lilo.conf"; +my $home = "$ENV{HOME}/.gbootroot"; +my $uml_xterm = "xterm -e"; +$main::editor = "emacs --font 6x13"; +$main::makefs = "mke2fs -F -m0 -i8192"; # Root Disk +$main::sudo = "sudo"; + + +# Don't edit from here, but you can if you want to change the HERE docs +# and/or the contents of initrd (in which case you need to make sure the +# right libraries are copied over to initrd and the size is checked). + +# I need to remember to edit this +# and to update scripts/Debian.yard if +# make_debian has been changed. +my $version = "1.3.0"; +my $date = "12.12.2001"; +my $gtk_perl_version = "0.7002"; +my $pwd = `pwd`; chomp $pwd; +my $home_rootfs = "$home/root_filesystem/"; +my $home_uml_kernel = "$home/uml_kernel/"; +my $modules_directory = "/lib/modules"; +if ( $> != 0 && -e "/usr/lib/bootroot/genext2fs" ) { + $main::makefs = "genext2fs -z -r0"; # -i8192 not a good idea +} +# This is for experimental stuff .. basically so I can test +# the boot fs as a normal user, since it's hard to create a boot disk +# with enough room using genext2fs. +my $busybox; + + +# Yard Stuff +my $home_yard = "$home/yard"; +my $template_dir = "$home_yard/templates/"; +my $home_yard_replacements = "$home_yard/Replacements"; +$main::global_yard = $home_yard; +$main::oldroot = "/OLDROOT"; +my $global_yard_replacements_arch_indep = + "/usr/share/gbootroot/yard/Replacements"; +my $global_yard_replacements_arch_dep = "/usr/lib/bootroot/yard/Replacements"; +my $global_yard_templates = "/usr/share/gbootroot/yard/templates"; +$ENV{'PATH'} = "$home_yard:" . $ENV{'PATH'}; + + +my $initrd; +my $compress; +my $false = 0; +my $true = 1; + +# Helps determine what procedure to follow for the Boot Disk +my $ok; + +my $box2; +my $label; +my $label_advanced; +my $separator; +my $order; +my $text_window; +my $verbosity_window; + +# Make @container verbose, also look in generate() +my @container; +use constant METHOD => 0 ; +use constant KERNEL => 1 ; +use constant ROOT_FS => 2 ; +use constant BOOT_DEVICE => 3 ; +use constant SIZE => 4 ; +use constant COMPRESS => 5 ; +use constant LIB_STRIP => 6 ; +use constant BIN_STRIP => 7 ; +use constant OBJCOPY_BOOL => 8 ; +use constant ABS_DEVICE => 9 ; +use constant ABS_OPT_DEVICE => 10 ; +use constant ABS_APPEND => 11 ; + +# The Selection values are used for button_fileselect_advanced +# since it shares fileselect and file_ok_sel with button. +# +# ABS: 12=Root_Device_Selection 13=UML_Kernel_Selection +# UML BOX: 14=Root_Fs_Selection +# +use constant MOD_STRIP => 15 ; +# +# ABS: 16=System.map_Selection + +my @original_container; +my $file_dialog; + +my $mtab; +# $old_mount is used for a little swapping magic when a normal user +# is using genext2fs and lilo. +my ($tmp, $mnt, $old_mount); +my $norm_root_device; +my ($hbox_advanced); +my $separator_advanced; + +my @entry_advanced; +my ($ea1,$ea2,$ea3,$ea4,$ea5,$ea6); # entry advanced boot +my ($ear1,$ear2,$ear3,$ear4); # entry advanced root +my ($eab1,$eab2,$eab3); # entry advanced uml +my $uml_window; +my $table_advanced; +my $table_advanced_root; +my ($spinner_advanced,$spinner_size); +my $button_count = 0; +my $button_count_root = 0; +my $obj_count = 0; +my $obj_count_root = 0; +my ($lib_strip_check,$bin_strip_check,$mod_strip_check); +my ($bz2_toggle,$gz_toggle); +my ($bz2_toggle_root,$gz_toggle_root,$compression_off); +#my ($main::combo); made this totally global +my ($adj2,$adj3); +my @strings; + +####### +####### +# Since the restructuring +####### +my $tooltips; +my $vbox_advanced; +my $vbox_advanced_root; +my $entry3; +my $box1; +my $entry5; +my $pbar; +my $rbutton; +my $verbosefn; + +# Value set by kernel_modules +my $kernel_version; + +# $entry_advanced[3] is the Root Device +# $filesystem_size and root_device_size are important globals for ARS, +# there weren't put into entry_advanced because they are spin buttons. +# $entry_advanced[4] is the Root Filename +# +my ($filesystem_size, $root_device_size); +# +# Carrries ARS values to other modules via ars(), another program just has to +# export ars and it can capture these values +my $ars = {}; # anonymous hash + + +# My own creation - the roots touch the ground if three lines are added. + my @xpm_data = ( +"32 45 3 1", +" c None", +". c SaddleBrown", +"X c black", +" ... ... ", +" ... ... ", +" ... ... ", +" ... ... ", +" ... ... ", +" ... ... ", +" ... ... ", +" ... ... ", +" ... ... ", +" ... .. ", +" ... ... ", +" ... ... ", +" .... ... ", +" .... ... ", +" .... ... ", +" .... ............. ", +" ..... ............. ", +" ...... ............. ", +" ....... ...", +"......... ..", +"................................", +"................................", +"............................... ", +"......... XXXXX ............ ", +"........ XXX .......... ", +"........ XXX ........ ", +" XXXXXX ", +" XXX XXX X XX XX ", +" X XXXXX X X X ", +" XX XXX X XX ", +" X XX X X ", +" X XX X XX X ", +" XX XX X XXXXX ", +" X XXXX XXX XXXXX X ", +" XX XX XX X XX ", +" X X X X X ", +" X XX X XX X ", +" X XX XX X ", +" X XX XXXXXXX XXX ", +" XX XX XXX ", +" XX XX XXXX XX XX ", +" XX XXX X XXXXXXX X ", +" X XXX X XX ", +" XX XXXXXXX XXX ", +" X XX X ", +" X X " + ); + + +# For distributions that don't adhere to the most recent FHS. +BEGIN { + + my $fhs = grep(/\/usr\/share\/perl5/,@INC); + + if ($fhs == 0) { + unshift(@INC,"/usr/share/perl5"); + } + + + my $sbin = grep(/\/sbin/,$ENV{'PATH'}); + if ($sbin == 0) { + $ENV{'PATH'} = "/sbin:" . $ENV{'PATH'}; + } + + $sbin = grep(/\/usr\/sbin/,$ENV{'PATH'}); + if ($sbin == 0) { + $ENV{'PATH'} = "/usr/sbin:" . $ENV{'PATH'}; + } + +} + +sub start { + +$SIG{INT} = \&signal; +$SIG{ABRT} = \&signal; +$SIG{TERM} = \&signal; +$SIG{QUIT} = \&signal; +$SIG{KILL} = \&signal; + +(undef,$container[KERNEL],$container[ABS_APPEND]) = gdkbirdaao(); + + +my ($sec,$min,$hour,$day,$month,$year) = (localtime)[0,1,2,3,4,5]; +my $time = sprintf("%02d:%02d:%02d-%02d-%02d-%04d", + $hour, $min, $sec, $month+1, $day, $year+1900); + +# Here's where stuff gets intersting, non-root users can create root_fs, +# which is great for UML, and a boot disk. + +if ( $> == 0 ) { + + if (!-d "$tmp1/gbootroot_tmp$time") { + $tmp = "$tmp1/gbootroot_tmp$time" if err_custom_perl( + "mkdir $tmp1/gbootroot_tmp$time", + "gBootRoot: ERROR: Could not make temporary directory") != 2; + } + if (!-d "$tmp1/gbootroot_mnt$time") { + $mnt = "$tmp1/gbootroot_mnt$time" if err_custom_perl( + "mkdir $tmp1/gbootroot_mnt$time", + "gBootRoot: ERROR: Could not make mount directory") != 2; + } + + # Why? + $tmp = "$tmp1/gbootroot_tmp$time"; + +} +else { + + # The Administrator just needs to add a line like the one below to the + # fstab for each non-root user who wants to be able to create root_fs. + # In this example, `id -u` has to be the actual effective numeric user + # id, and the root_fs has to always be named root_fs when it is being + # made, but it can be renamed afterwards. + # + # /tmp/gboot_non_root_`id -u`/root_fs \ + # /tmp/gboot_non_root_`id -u`/loopback \ + # auto defaults,noauto,user,loop 0 0 + # + # For the boot/root disks the administrator will have to give the user + # special su privileges (mknod) to make special devices. The $main::sudo + # variable can be set to sudo or super, fakeroot won't work. + # These include: /dev/{console,null,ram0,ram1,tty0} + # These two lines need to be added to create the boot_fs and the boot/root + # disk. In this example the user is locked into using one type of device + # for the boot/root + # + # /tmp/gboot_non_root_`id -u`/initrd_image \ + # /tmp/gboot_non_root_'id -u1`/initrd_mnt \ + # auto defaults,noauto,user,loop 0 0 + # + # + # For genext2fs this is the only line required, this is so that lilo can + # run. + # + # /dev/fd0 /tmp/gboot_not_root_mnt_`id -u` auto defaults,noauto,user 0 0 + + + my $user = $>; + + if (!-d "$tmp1/gboot_non_root_$user") { + $tmp = "$tmp1/gboot_non_root_$user" if err_custom_perl( + "mkdir $tmp1/gboot_non_root_$user", + "gBootRoot: ERROR: Could not make temporary directory") != 2; + } + $tmp = "$tmp1/gboot_non_root_$user"; + + if (!-d "$tmp1/gboot_non_root_mnt_$user") { + $mnt = "$tmp1/gboot_non_root_mnt_$user" if err_custom_perl( + "mkdir $tmp1/gboot_non_root_mnt_$user", + "gBootRoot: ERROR: Could not make mount directory") != 2; + } + $mnt = "$tmp1/gboot_non_root_mnt_$user"; + +} + + +# Verbosity is universal for all methods, and controlled by a scale slider. +# Yard +# 0 --> only the important messages. +# 1 --> all messages. +my $verbosity = 1; # info & sys use this as Global + +## One hard copy log file is saved for the session, and the user can also +## save from the verbosity box including saving a selection. + +$verbosefn = "$tmp/verbose"; # All verbosity +#my $verbosefn = "/tmp/verbose"; # Yard - always logged, but 0&1 = STDOUT + +# Need this before everything. +Gtk::Rc->parse("/etc/gbootroot/gbootrootrc"); + +verbosity_box(); +start_logging_output($verbosefn,$verbosity); # Yard "tmp dir name" + # "verbosity level" + +#------------------------------- +# USER DIRECTORIES +# /tmp +home_builder($tmp1); + +# $HOME/.gbootroot/root_filesystem +home_builder($home_rootfs); + +# $HOME/.gbootroot/uml_kernel +home_builder($home_uml_kernel); +symlink_builder("/usr/bin/linux","$home_uml_kernel/linux"); +if (!-e "$home_uml_kernel/.options") { + open(OPTIONS,">$home_uml_kernel/.options") + or die "Couldn't write $home_uml_kernel/.options at $?\n"; + print OPTIONS "root=/dev/ubd0 mem=16M\n"; + close(OPTIONS); +} + +# $HOME/.gbootroot/yard/templates +home_builder($template_dir); +if ( -d $global_yard_templates ) { + opendir(DIR,$global_yard_templates) if -d $template_dir; + # I decided this may be too restrictive, besides, everything + # is kept in its own directory. + #my @templates = grep { m,\.yard$, } readdir(DIR); + my @templates = grep { m,^\w+, } readdir(DIR); + closedir(DIR); + foreach ( @templates ) { + if (!-e "$template_dir/$_" && !-l "$template_dir/$_") { + symlink_builder("$global_yard_templates/$_","$template_dir/$_"); + } + } +} + +# Arch indep replacements repository +# $HOME/.gbootroot/yard/Replacements +home_builder($home_yard_replacements); +if ( -d $global_yard_replacements_arch_indep ) { + if (-d $home_yard_replacements) { + find sub { ( my $replacement = + $File::Find::name ) =~ s/$global_yard_replacements_arch_indep\///; + if (!-e "$home_yard_replacements/$replacement") { + + #system "cp -a $File::Find::name $home_yard_replacements/$replacement > /dev/null 2>&1"; + system "mkdir $home_yard_replacements/$replacement > /dev/null 2>&1" if -d $File::Find::name; + symlink_builder( $File::Find::name,"$home_yard_replacements/$replacement") if !-d $File::Find::name; + } + + }, $global_yard_replacements_arch_indep; + + + } +} + +# Arch dep replacements repository +if ( -d $global_yard_replacements_arch_dep ) { + if (-d $home_yard_replacements) { + find sub { ( my $replacement = + $File::Find::name ) =~ s/$global_yard_replacements_arch_dep\///; + if (!-e "$home_yard_replacements/$replacement") { + + #system "cp -a $File::Find::name $home_yard_replacements/$replacement > /dev/null 2>&1"; + system "mkdir $home_yard_replacements/$replacement > /dev/null 2>&1" if -d $File::Find::name; + symlink_builder( $File::Find::name,"$home_yard_replacements/$replacement") if !-d $File::Find::name; + } + + }, $global_yard_replacements_arch_dep; + + + } +} + + + +#------------------------------- + +# Gtk::check_version expects different arguments than .7004 so will have +# to check for the version instead. +# Right now >= 0.7002 is o.k. +#if (Gtk::check_version(undef,"1","0","7") =~ /too old/) { + +if (Gtk->major_version < 1) { + et(); +} +elsif (Gtk->micro_version < 7) { + et(); +} +elsif (Gtk->minor_version < 2) { + et(); +} + + +my $window = Gtk::Window->new("toplevel"); +# special policy +$window->set_policy( $false, $true, $true ); +$window->set_title("gBootRoot"); +$window->set_position('none'); +$window->signal_connect("destroy", + sub { + unlink "$verbosefn", "$tmp/initrd_image.gz"; + rmdir "$tmp/initrd_mnt"; + rmdir "$tmp"; + rmdir "$mnt"; + Gtk->exit(0); + }); +$window->border_width(1); +$window->realize; + +# Do the iconizing thing +# "xpm/circles.xpm" can be @pixmap within file if not create_from_xpm. +my ($circles,$mask) = Gtk::Gdk::Pixmap->create_from_xpm_d($window->window, + $window->style->white, + @xpm_data); +$window->window->set_icon(undef, $circles, $mask); +$window->window->set_icon_name("gBootRoot"); +# Zas - bug in gtk-perl < .7002 +$window->window->set_decorations(['all', 'menu']); +$window->window->set_functions(['all', 'resize']); + +$tooltips = Gtk::Tooltips->new(); + +$box1 = Gtk::VBox->new($false,0); +$window->add($box1); +$box1->show(); + +# First row +hbox(); +my $entry = entry($false,0); + +# Menu - later this may be improved if new methods are added. +my $opt = Gtk::OptionMenu->new(); +$tooltips->set_tip( $opt, "Choose the Boot method.", "" ); +my $menu = Gtk::Menu->new(); +my $item = Gtk::MenuItem->new("2 disk compression" ); +$item->show(); +# Eventually get_menu, or something totally different will be used. +$item->signal_connect( 'activate', + sub { $entry->set_text("2 disk compression"); + $container[METHOD] = "2 disk compression"; + two_disk_compression_check(); + kernel_modules(); }); +$menu->append( $item ); +$opt->set_menu( $menu ); +$box2->pack_start( $opt, $true, $true, 0 ); +$opt->show(); +$box2->show(); + +# Second row +# Get to look three places for kernel value +# default ( null|gdkkbirdaao) && entry() && fileselect->file_ok_sel +hbox(); +my $entry2 = entry($true,1); +$entry2->set_text($container[KERNEL]); +if ($container[KERNEL]) { + $ars->{kernel} = $container[KERNEL]; + ars($ars); + ars2($ars); +} +button("Kernel Selection",$entry2,"Kernel Selection",1); + +# Third row +hbox(); +$entry3 = entry($true,2); +button("Root Filesystem",$entry3,"Root Filesystem",2,$home_rootfs); + +# In the future, if experimenters send in data, there will be two +# different devices. +# Fourth row +hbox(); +my $entry4 = entry($true,3); +$container[BOOT_DEVICE] = "/dev/fd0"; +$entry4->set_text($container[BOOT_DEVICE]); +button("Device Selection",$entry4,"Device Selection",3,"/dev/fd0"); + +# Fifth row +hbox("what"); +my $adj = Gtk::Adjustment->new( 1440.0, 0.0, 360000000.0, 282.0, 360.0, 0.0 ); +my $spinner = Gtk::SpinButton->new( $adj, 0, 0 ); +$tooltips->set_tip( $spinner, "Choose the Device Size.\n" . +"Hint: Many 1440 floppy drives support 1722.\n", "" ); +$spinner->set_wrap( $true ); +$spinner->set_numeric( $true ); +$spinner->set_shadow_type( 'in' ); +$spinner->show(); +$container[SIZE] = 1440; # A better value - a rtbt trick. +$adj->signal_connect( "value_changed", sub { + $container[SIZE] = $spinner->get_value_as_int(); + $adj2->set_value($container[SIZE]) if defined $adj2;}); +$box2->pack_start( $spinner, $true, $true, 0 ); +#label("Device Size"); + +# gz and bz2 radio buttons +$rbutton = Gtk::RadioButton->new( "gz" ); +$tooltips->set_tip( $rbutton, "Choose Compression used on the Filesystem.", "" ); +$gz_toggle = $rbutton; +$rbutton->set_active( $true ); +$box2->pack_start( $rbutton, $false, $false, 0 ); +$rbutton->show(); +$rbutton = Gtk::RadioButton->new( "bz2", $rbutton ); +$rbutton->set_usize(1,1); +$tooltips->set_tip( $rbutton, "Choose Compression used on the Filesystem.", "" ); +$bz2_toggle = $rbutton; +$box2->pack_start( $rbutton, $true, $true, 0); +$rbutton->show(); + +# Verbosity adjustment +my $adj1 = Gtk::Adjustment->new( 2.0, 0.0, 2.0, 0.0, 1.0, 0.0 ); +my $verbosity_scale = Gtk::HScale->new($adj1); +$verbosity_scale->set_value_pos("right"); +$verbosity_scale->set_digits(0); +$tooltips->set_tip( $verbosity_scale, "Adjust the Verbosity Level.", "" ); +$verbosity_scale->show(); +# Verbosity Box can be turned on/off here +$adj1->signal_connect( "value_changed", sub { + $verbosity = $verbosity_scale->get_adjustment->value - 1; + verbosity($verbosity); + + if ($verbosity == -1) { + if ($verbosity_window) { + destroy $verbosity_window if visible $verbosity_window; + } + } + elsif (!$verbosity_window) { + close(LOGFILE); + verbosity_box(); + start_logging_output($verbosefn,$verbosity); + } + + } ); +$box2->pack_start( $verbosity_scale, $false, $false, 0); + +#start_logging_output($yard_temp,$verbosity); + +# Size status entry +$entry5 = Gtk::Entry->new(); +$entry5->set_editable( $false ); +$tooltips->set_tip( $entry5, "This shows room remaining on the Device.", "" ); +$entry5->set_usize(20,20); +$box2->pack_start( $entry5, $true, $true, 0 ); +$entry5->show(); + + +my $button_advanced; +########################### +# The ADVANCED BOOT SECTION +########################### +# Separator +$separator = Gtk::HSeparator->new(); +$box1->pack_start( $separator, $false, $true, 0 ); +$separator->show(); + +# This is cool how this works. +$vbox_advanced = Gtk::VBox->new($false,0); +$box1->add($vbox_advanced); +$vbox_advanced->show(); + +# The Advanced Boot Section button +hbox_advanced($vbox_advanced); +$button_advanced = Gtk::Button->new("Advanced Boot Section"); +$tooltips->set_tip( $button_advanced, + "Change settings for the Boot Disk Image.", "" ); +$button_advanced->signal_connect("clicked",\&advanced_boot_section ); +$hbox_advanced->pack_start( $button_advanced, $true, $true, 0 ); +$button_advanced->show(); + +########################### +# The ADVANCED ROOT SECTION +########################### +$vbox_advanced_root = Gtk::VBox->new($false,0); +$box1->add($vbox_advanced_root); +$vbox_advanced_root->show(); + +hbox_advanced($vbox_advanced_root); +$button_advanced = Gtk::Button->new("Advanced Root Section"); +$tooltips->set_tip( $button_advanced, + "Generate a Root Filesystem and/or use a different Root Device.", "" ); +$button_advanced->signal_connect("clicked",\&advanced_root_section ); +$hbox_advanced->pack_start( $button_advanced, $true, $true, 0 ); +$button_advanced->show(); +########################### + +############################# +# The ADVANCED KERNEL SECTION +############################# +my $vbox_advanced_kernel = Gtk::VBox->new($false,0); +$box1->add($vbox_advanced_kernel); +$vbox_advanced_kernel->show(); + +hbox_advanced($vbox_advanced_kernel); +$button_advanced = Gtk::Button->new("Advanced Kernel Section"); +$tooltips->set_tip( $button_advanced, + "Retrieve/Make Kernel Sources.", "" ); +#$button_advanced->signal_connect("clicked",\&advanced_root_section ); +$hbox_advanced->pack_start( $button_advanced, $true, $true, 0 ); +$button_advanced->show(); +############################# + + + +# Separator +$separator = Gtk::HSeparator->new(); +$box1->pack_start( $separator, $false, $true, 0 ); +$separator->show(); + +# Status bar +my $align = Gtk::Alignment->new( 0.5, 0.5, 0, 0 ); +$box1->pack_start( $align, $false, $false, 5); +$align->show(); +$pbar = Gtk::ProgressBar->new(); +$pbar->set_usize(321,10); # 321 10 +$align->add($pbar); +$pbar->show(); + +# Separator +$separator = Gtk::HSeparator->new(); +$box1->pack_start( $separator, $false, $true, 0 ); +$separator->show(); + +# Submit button +hbox(); +my $sbutton = Gtk::Button->new("Submit"); +$sbutton->signal_connect( "clicked", \&submit); +$tooltips->set_tip( $sbutton, "Generate the Boot/Root set.", "" ); +$sbutton->show(); +$box2->pack_start( $sbutton, $true, $true, 0 ); +$box2->show(); + +# Close button +my $cbutton = Gtk::Button->new("Close"); +$cbutton->signal_connect("clicked", + sub { + unlink "$verbosefn", "$tmp/initrd_image", + "$tmp/initrd_image.gz"; + system "umount $tmp/initrd_mnt > /dev/null 2>&1"; + rmdir "$tmp/initrd_mnt"; + rmdir "$tmp"; + rmdir "$mnt"; + Gtk->exit(0); + }); + +$tooltips->set_tip( $cbutton, "Exit gBootRoot.", "" ); +$cbutton->show(); +$box2->pack_start( $cbutton, $true, $true, 0 ); +$box2->show(); + +# Help button +my $hbutton = Gtk::Button->new("Help"); +$hbutton->signal_connect( "clicked", sub { create_text("help") }); +$tooltips->set_tip( $hbutton, "Help about gBootRoot.", "" ); +$hbutton->show(); +$box2->pack_start( $hbutton, $true, $true, 0 ); +$box2->show(); + +$window->show(); + +} # end start + +#---------------------------- + +sub et { + error_window("gBootRoot is presently being developed with gtk-perl" . + " version $gtk_perl_version.\nYou are using a" . + " version of gtk-perl < $gtk_perl_version." . + " You may still be able\n" . + " to use this program, but you may encounter problems." . + " See the FAQ\nfor places to get a newer gtk-perl version." . + " \n\nThe most common error reported:\n\"Can't locate" . + " object method\""); + #,"center"); + print "Using a version of gtk-perl < $gtk_perl_version\n"; +} + +# Basically so different users get the same things in +# their personal directories. +sub symlink_builder { + + my ($oldfile,$newfile) = @_; + + + if (!-e $newfile && !-l $newfile) { + my $error; + symlink($oldfile,$newfile) or + ($error = error("Can not make symlink to $oldfile + from $newfile.\n")); + } + +} + +sub home_builder { + + my ($home_builder) = @_; + + if (!-d $home_builder) { + if (-e $home_builder) { + error_window( + "gBootRoot: ERROR: A file exists where $home_builder should be"); + } + else { + my @directory_parts = split(m,/,,$home_builder); + my $placement = "/"; + for (1 .. $#directory_parts) { + $_ == 1 ? ($placement = "/$directory_parts[$_]") + : ($placement = $placement . "/" . $directory_parts[$_]); + -d $placement or err_custom_perl( + "mkdir $placement","gBootRoot: ERROR: Could not make $home_builder"); + } + } + } + +} # end home_builder + + +# This works on GNU/Linux +sub signal { + + unlink "$verbosefn", "$tmp/initrd_image.gz"; + system "umount $tmp/initrd_mnt > /dev/null 2>&1"; + rmdir "$tmp/initrd_mnt"; + rmdir "$tmp"; + rmdir "$mnt"; + + $SIG{INT} = \&signal; + $SIG{ABRT} = \&signal; + $SIG{TERM} = \&signal; + $SIG{QUIT} = \&signal; + $SIG{KILL} = \&signal; + + + Gtk->exit(0); +} + + +sub hbox_advanced { + $hbox_advanced = Gtk::HBox->new(1,1 ); + $hbox_advanced->border_width( 2 ); # was 10 + $hbox_advanced->set_usize(321, 20); + $_[0]->pack_start( $hbox_advanced, $false, $false, 0 ); + show $hbox_advanced; +} + +sub objcopy_right_click_advanced { + + my ( @data ) = @_; + my $event = pop( @data ); + + if ( ( defined( $event->{'type'} ) ) + and ( $event->{'type'} eq 'button_press' ) ) { + if ( $event->{'button'} == 3 ) { + if (defined $lib_strip_check) { + if ($obj_count == 0) { + $tooltips->set_tip( $lib_strip_check, + "This is generally a good idea." . + " Press the right mouse button to" . + " change from [objcopy --strip-all]" . + " to [objcopy --strip-debug].", "" ); + $obj_count++; + } + else { + $tooltips->set_tip( $lib_strip_check, + "This is generally a good idea." . + " Press the right mouse button to" . + " change from [objcopy --strip-debug]". + " to [objcopy --strip-all].", "" ); + $obj_count--; + } + } + } + } + +} # end obj_right_click_advanced + + +sub advanced_boot_section { + + if ($button_count == 0) { + #$vbox_advanced->set_usize(321,300); + my $boolean; + + # The table section + $table_advanced = Gtk::Table->new( 7, 3, $true ); + $vbox_advanced->pack_start( $table_advanced, $true, $true, 0 ); + $table_advanced->show(); + + #_______________________________________ + # lib_strip_check + #label_advanced("Stripping:",0,1,0,1,$table_advanced); + !defined $lib_strip_check ? ($boolean = 1) + : ($boolean = $lib_strip_check->get_active()); + $lib_strip_check = Gtk::CheckButton->new("Libraries"); + $lib_strip_check->set_active($boolean); + $lib_strip_check->signal_connect( "button_press_event", + \&objcopy_right_click_advanced); + $tooltips->set_tip( $lib_strip_check, + "This is generally a good idea. Press the" . + " right mouse button to change from" . + " [objcopy --strip-debug] to" . + " [objcopy --strip-all].", "" ); + $table_advanced->attach($lib_strip_check,0,1,0,1, + ['expand'],['fill','shrink'],0,0); + show $lib_strip_check; + + # bin_strip_check + !defined $bin_strip_check ? ($boolean = 1) + : ($boolean = $bin_strip_check->get_active()); + $bin_strip_check = Gtk::CheckButton->new("Binaries"); + $bin_strip_check->set_active($boolean); + $tooltips->set_tip( $bin_strip_check, + "This is generally a good idea." . + " [objcopy --strip-all]", "" ); + $table_advanced->attach($bin_strip_check,1,2,0,1, + ['expand'],['fill','shrink'],0,0); + show $bin_strip_check; + + + # mod_strip_check + !defined $mod_strip_check ? ($boolean = 1) + : ($boolean = $mod_strip_check->get_active()); + $mod_strip_check = Gtk::CheckButton->new("Modules"); + $mod_strip_check->set_active($boolean); + $tooltips->set_tip( $mod_strip_check, + "This is generally a good idea." . + " [objcopy --strip-debug]", "" ); + $table_advanced->attach($mod_strip_check,2,3,0,1, + ['expand'],['fill','shrink'],0,0); + show $mod_strip_check; + + + #_______________________________________ + # Development Drive + label_advanced("Devel Device:",0,1,1,2,$table_advanced); + $ea1 = entry_advanced(1,2,1,2,0,$table_advanced); + $tooltips->set_tip( $ea1, "If the device used for development" . + " is different than the actual boot" . + " device, use this field" . + " to indicate that device." . + " You will have to run" . + " lilo -v -C brlilo.conf -r" . + " \"device mount point\" manually at a" . + " later time on the actual" . + " boot device.", + "" ); + $ea1->set_text($container[BOOT_DEVICE]) if defined $container[BOOT_DEVICE]; + + #_______________________________________ + # Optional Device(s) + label_advanced("Opt. Device(s)",0,1,2,3,$table_advanced); + $ea2 = entry_advanced(1,3,2,3,1,$table_advanced); + $tooltips->set_tip( $ea2, "Add devices to the boot disk which are" . + " necessary for the kernel to function" . + " properly. Put a space between each" . + " device. For instance, /dev/fb0 for" . + " frame buffer devices.", + ""); + $ea2->set_text($entry_advanced[1]) if defined $entry_advanced[1]; + + + #_______________________________________ + # Kernel Module(s) + label_advanced("Kernel Module(s)",0,1,4,5,$table_advanced); + $ea3 = entry_advanced(1,3,4,5,11,$table_advanced); + $tooltips->set_tip( $ea3, "Add the modules found in" . + " /lib/modules/kernel-version which are" . + " necessary for the Boot Method to work" . + " properly. Kmod inserts the modules," . + " and kmod needs to be built into the" . + " kernel along with initrd and ramdisk." , + ""); + $ea3->set_text($entry_advanced[11]) if defined $entry_advanced[11]; + + #_______________________________________ + # Append Options + label_advanced("append =",0,1,3,4,$table_advanced); + $ea4 = entry_advanced(1,3,3,4,2,$table_advanced); + my $append; (undef,undef,$append) = gdkbirdaao(); + $tooltips->set_tip( $ea4, "Add append options to brlilo.conf.", ""); + # this will only show append if real + if (!defined $entry_advanced[2]) { + $ea4->set_text($append) if $append; + } + else { + $ea4->set_text($entry_advanced[2]) if $entry_advanced[2]; + } + + #_______________________________________ + # Kernel Version + label_advanced("Kernel Version:",0,1,5,6,$table_advanced); + $ea5 = entry_advanced(1,2,5,6,12,$table_advanced); + + $tooltips->set_tip( $ea5, "Override the kernel version number found" . + " in the kernel header. This will change" . + " the /lib/modules/kernel-version directory", + ""); + $ea5->set_text($entry_advanced[12]) if defined $entry_advanced[12]; + + + #_______________________________________ + # System.map + label_advanced("System.map:",0,1,6,7,$table_advanced); + $ea6 = entry_advanced(1,2,6,7,13,$table_advanced); + $tooltips->set_tip( $ea6, "When a non-running kernel is chosen it is " . + " important to include a copy of that" . + " kernel's System.map file so that depmod" . + " can use the correct set of kernel symbols" . + " to resolve kernel references in each" . + " module. This can be found in the" . + " kernel's source code after compilation.", + ""); + $ea6->set_text($entry_advanced[13]) if defined $entry_advanced[13]; + button_fileselect_advanced(2,3,6,7,"Selection",$ea6,"Selection",16, + $table_advanced,"/lib/modules/"); + + $button_count++; + } + else { + destroy $table_advanced; + $button_count--; + } + +} # end sub advanced_boot_section + +sub advanced_root_section { + + if ($button_count_root == 0) { + my $boolean; + + + $table_advanced_root = Gtk::Table->new( 9, 3, $true ); + # temp solution? + #$table_advanced_root->set_row_spacings( 3 ); + $vbox_advanced_root->pack_start( $table_advanced_root, $true, + $true, 0 ); + #_______________________________________ + # Root Device selection + # $::device $device already exist + label_advanced("Root Device:",0,1,0,1,$table_advanced_root); + # $_[4] shares with advanced_boot_sections @entry_advanced + $ear1 = entry_advanced(1,2,0,1,3,$table_advanced_root); + if ($entry_advanced[3]) { + $ear1->set_text($entry_advanced[3]); + } + else { + $ear1->set_text($container[BOOT_DEVICE]); + } + $tooltips->set_tip( $ear1, + "Type in the location of the Root Device to use.", + "" ); + # $order is important because it is put in $container[$order] + button_fileselect_advanced(2,3,0,1,"Selection",$ear1,"Selection",12, + $table_advanced_root,"/dev/fd0"); + + #_______________________________________ + # Root Device Size + # gBootRoot methods + label_advanced("Root Device Size:",0,1,1,2,$table_advanced_root); + $adj2 = Gtk::Adjustment->new( 1440.0, 0.0, 360000000.0, 282.0, + 360.0, 0.0 ); + $spinner_advanced = Gtk::SpinButton->new( $adj2, 0, 0 ); + $table_advanced_root->attach($spinner_advanced,1,2,1,2, + ['shrink','fill','expand'],['fill','shrink'], + 0,0); + $tooltips->set_tip( $spinner_advanced, + "Choose the Root Device Size.", + "" ); + $spinner_advanced->set_wrap( $true ); + $spinner_advanced->set_numeric( $true ); + $spinner_advanced->set_shadow_type( 'in' ); + $spinner_advanced->show(); + $root_device_size = 1440 if !$root_device_size; + $adj2->signal_connect( "value_changed", sub { + $root_device_size = $spinner_advanced->get_value_as_int();}); + # For some reason $container[SIZE] is tranforming into [3] when + # device selection is changed. & in ABS devel device doesn't keep + # state. + if ($root_device_size) { + $spinner_advanced->set_value($root_device_size); + } + else { + $adj2->set_value($container[SIZE]) if defined $adj2; + } + + + #_______________________________________ + # Root File Name + # gBootRoot methods + label_advanced("Root Filename:",0,1,2,3,$table_advanced_root); + $ear2 = entry_advanced(1,2,2,3,4,$table_advanced_root); + $ear2->set_text("root_fs") if !$entry_advanced[4]; + $ars->{filename} = "root_fs" if !$entry_advanced[4]; + $ear2->set_text($entry_advanced[4]) if $entry_advanced[4]; + $ars->{filename} = $entry_advanced[4] if $entry_advanced[4]; + ars($ars); + $tooltips->set_tip( $ear2, "Give the Root Filesystem file a name.", + "" ); + my $ear2_save = Gtk::CheckButton->new("save"); + $ear2_save->set_active($true); + +# "Save Root File. Press right button to change" . +# " the Directory the file is saved in.", + $tooltips->set_tip( $ear2_save, + "Saves the Root Filesystem in your" . + " $ENV{HOME}/.gbootroot/root_filesystem" . + " directory.", + "" ); + $table_advanced_root->attach($ear2_save,2,3,2,3, + ['expand'],['fill','shrink'],0,0); + show $ear2_save; + + + #_______________________________________ + # Filesystem Size + # $::fs_device + label_advanced("Filesystem Size:",0,1,3,4,$table_advanced_root); + $adj3 = Gtk::Adjustment->new( 4096.0, 0.0, 1000000000.0, 128.0, + 1024.0, 0.0 ); + $spinner_size = Gtk::SpinButton->new( $adj3, 0, 0 ); + $table_advanced_root->attach($spinner_size,1,2,3,4, + ['shrink','fill','expand'],['fill','shrink'], + 0,0); + $tooltips->set_tip( $spinner_size, + "Choose the Filesystem Size.", + "" ); + $spinner_size->set_wrap( $true ); + $spinner_size->set_numeric( $true ); + $spinner_size->set_shadow_type( 'in' ); + $spinner_size->show(); + $filesystem_size = 4096 if !$filesystem_size; + $ars->{filesystem_size} = $filesystem_size; + ars($ars); + $adj3->signal_connect( "value_changed", sub { + $filesystem_size = $spinner_size->get_value_as_int(); + $ars->{filesystem_size} = $filesystem_size; + ars($ars); + }); + $spinner_size->set_value($filesystem_size) if $filesystem_size; + + #_______________________________________ + # Compression + # gBootRoot methods + + + my $hbox_between = Gtk::HBox->new(0,1); + $table_advanced_root->attach($hbox_between,0,3,4,5, + ['fill'], + ['fill','shrink'],15,0 ); + $hbox_between->show; + + # label + my $label_compression = Gtk::Label->new( "Compression:" ); + $label_compression->set_justify( "right" ); + $hbox_between->pack_start( $label_compression, $false, $false, 0 ); + $label_compression->show(); + + # gz + $rbutton = Gtk::RadioButton->new( "gz" ); + $tooltips->set_tip( $rbutton, + "Choose Compression used on the Filesystem.", "" ); + $gz_toggle_root = $rbutton; + $rbutton->set_active( $true ); + $hbox_between->pack_start( $rbutton, $true, $false, 0 ); + $rbutton->show(); + + # bz2 + $rbutton = Gtk::RadioButton->new( "bz2", $rbutton ); + $tooltips->set_tip( $rbutton, + "Choose Compression used on the Filesystem.", "" ); + $bz2_toggle_root = $rbutton; + $hbox_between->pack_start( $rbutton, $true, $false, 0 ); + $rbutton->show(); + + # compression off + $compression_off = Gtk::CheckButton->new( "off"); + $tooltips->set_tip( $compression_off, + "Turn Compression off.", "" ); + $hbox_between->pack_start( $compression_off, $true, $false, 0 ); + $compression_off->set_active($true); + $compression_off->show(); + + #_______________________________________ + # UML Kernel + label_advanced("UML Kernel:",0,1,5,6,$table_advanced_root); + # $_[4] shares with advanced_boot_sections @entry_advanced + $ear3 = entry_advanced(1,2,5,6,5,$table_advanced_root); + $ear3->set_text("$home_uml_kernel" . "linux"); + $tooltips->set_tip( $ear3, + "If you have a User Mode Linux Kernel, type in" . + " the Kernel's location," . + " and any Kernel options desired afterwards.", + "" ); + button_fileselect_advanced(2,3,5,6,"Selection",$ear3,"Selection",13, + $table_advanced_root, $home_uml_kernel); + + #_______________________________________ + # Method + label_advanced("Method:",0,1,6,7,$table_advanced_root); + $ear4 = entry_advanced(1,2,6,7,6,$table_advanced_root); + $ear4->set_editable($false); + $tooltips->set_tip( $ear4, + "Choose the Root Filesystem Generation Method.", + "" ); + + my $opt_root = Gtk::OptionMenu->new(); + $tooltips->set_tip( $opt_root, + "Choose the Root Filesystem Generation Method.", + "" ); + my $menu_root = Gtk::Menu->new(); + + my $yard = Gtk::MenuItem->new("Yard" ); + + $menu_root->append( $yard ); + + $yard->signal_connect( 'activate', sub { + $ear4->set_text("yard"); + $entry_advanced[6] = $ear4->get_text(); + opendir(DIR,$template_dir) if -d $template_dir; + #@strings = grep { m,\.yard$, } readdir(DIR); + @strings = grep { m,^\w+, } readdir(DIR); + closedir(DIR); + $main::combo->set_popdown_strings( @strings ) if @strings; + } ); + + $ear4->set_text($entry_advanced[6]) if $entry_advanced[6]; + if ($yard) { + opendir(DIR,$template_dir) if -d $template_dir; + #@strings = grep { m,\.yard$, } readdir(DIR) if $yard; + @strings = grep { m,^\w+, } readdir(DIR) if $yard; + closedir(DIR) + } + + $yard->show(); + + $opt_root->set_menu( $menu_root ); + $table_advanced_root->attach($opt_root,2,3,6,7, + ['expand','fill'],['fill','shrink'],0,0); + $opt_root->show(); + + #_______________________________________ + # Template + # $::contents_file + label_advanced("Template:",0,1,7,8,$table_advanced_root); + $main::combo = Gtk::Combo->new(); + $main::combo->entry->set_text($entry_advanced[7]) if $entry_advanced[7]; + #$button_count_root_open = 1 + $button_count_root_open; + #print $button_count_root_open; + #if ($button_count_root_open > 1) { + # $main::combo->set_popdown_strings( @strings ) + # if $entry_advanced[7] ne ""; + #} + $tooltips->set_tip( Gtk::Combo::entry($main::combo), + "Choose a Template for the Method.", + "" ); + $entry_advanced[7] = $main::combo->entry->get_text(); # nothing selected + $main::combo->entry->signal_connect("changed", sub { + $entry_advanced[7] = $main::combo->entry->get_text(); + $ars->{template} = $entry_advanced[7]; + ars($ars); + } ); + $table_advanced_root->attach($main::combo,1,3,7,8, + ['expand','fill'],['fill','shrink'],0,0); + show $main::combo; + + #_______________________________________ + # Generate - UML - Accept buttons + $table_advanced_root->set_row_spacing( 7, 9); + + # The Generation process is determined by the method chosen. Yard - + # asks the user if they want to modify the template, and/or save a + # new template with modifications (to be added to Template menu). + my $generate_b = button_advanced(0,1,8,9,"Generate",$table_advanced_root); + $generate_b->signal_connect("clicked",\&Generate); + $tooltips->set_tip( $generate_b, "Generate Root Filesystem.", "" ); + + my $UML_b = button_advanced(1,2,8,9,"UML",$table_advanced_root); + + $UML_b->signal_connect("clicked", \¨_box); + $tooltips->set_tip( $UML_b, "Test Filesystem with User Mode Linux.", + "" ); + + # UML kernel doesn't look like a normal kernel + ##if (!-d $entry_advanced[5] && -f $entry_advanced[5]) { + ##$k_error = kernel_version_check($entry_advanced[5]); + ##return if $k_error && $k_error eq "ERROR";} + ## else { + ##error_window("Kernel Selection required"); + ##return; } + + # Will check to make sure that Filesystem fits device. + # Method determines whether or not compression is used. + my $accept_b = button_advanced(2,3,8,9,"Accept",$table_advanced_root); + $accept_b->signal_connect("clicked", \&accept_button, $ear2_save); + $tooltips->set_tip( $accept_b, "Accept Filesystem.", "" ); + + + $table_advanced_root->show(); + $button_count_root++; + + } + else { + destroy $table_advanced_root; + $button_count_root--; + } + + +} # end sub advanced_root_section + +sub uml_box { + + if (not defined $uml_window) { + + $uml_window = Gtk::Window->new("toplevel"); + $uml_window->signal_connect("destroy", \&destroy_window, + \$uml_window); + $uml_window->signal_connect("delete_event", \&destroy_window, + \$uml_window); + ##$uml_window->set_usize( 500, 95 ); # 450 175 || 500 600 + $uml_window->set_default_size( 500, 95 ); # 450 175 || 500 600 + $uml_window->set_policy( $true, $true, $false ); + $uml_window->set_title( "UML Box" ); + $uml_window->border_width(1); + + my $main_vbox = Gtk::VBox->new( $false, 0 ); + $uml_window->add( $main_vbox ); + $main_vbox->show(); + + ##my $table_uml = Gtk::Table->new( 4, 3, $true ); + my $table_uml = Gtk::Table->new( 4, 3, $false ); + ##$main_vbox->pack_start( $table_uml, $true, $true, 0 ); + $main_vbox->pack_start( $table_uml, $true, $false, 0 ); + $table_uml->show(); + + #_______________________________________ + # Xterm and execute options + label_advanced("Xterm:",0,1,0,1,$table_uml); + $eab1 = entry_advanced(1,2,0,1,8,$table_uml); + $eab1->set_text($uml_xterm); + $tooltips->set_tip( $eab1, + "Choose an xterm with " . + "its executable option switch.", + "" ); + + #_______________________________________ + # UML options + label_advanced("Options:",0,1,1,2,$table_uml); + $eab2 = Gtk::Combo->new(); + $table_uml->attach($eab2,1,3,1,2, + ['expand','fill'],['fill','shrink'],0,0); + open(OPTIONS,"$home_uml_kernel/.options"); + my @initial_options = ; + close(OPTIONS); chomp @initial_options; + $eab2->entry->set_text($initial_options[0]); + $entry_advanced[9] = $eab2->entry->get_text(); + $eab2->set_popdown_strings( @initial_options ) ; + $eab2->entry->signal_connect("changed", sub { + $entry_advanced[9] = $eab2->entry->get_text(); + open(OPTIONS,">$home_uml_kernel/.options"); + $entry_advanced[9] =~ s/\n//g; + $entry_advanced[9] =~ s/\s+$//g; + print OPTIONS "$entry_advanced[9]\n"; + foreach (@initial_options) { + if ($_ ne "$entry_advanced[9]") { + print OPTIONS "$_\n"; + } + } + close(OPTIONS); + } ); + $tooltips->set_tip( Gtk::Combo::entry($eab2), + "Enter uml command-line options.", + "" ); + $eab2->show(); + + + #_______________________________________ + # Root Filesystem defaults to generated one if found. + label_advanced("Root_Fs:",0,1,2,3,$table_uml); + $eab3 = entry_advanced(1,2,2,3,10,$table_uml); + button_fileselect_advanced(2,3,2,3,"Selection",$eab3,"Selection",14, + $table_uml,$home_rootfs); + $eab3->set_text("ubd0=$tmp/$entry_advanced[4]") + if -e "$tmp/$entry_advanced[4]"; + $tooltips->set_tip( $eab3, + "Choose an uncompressed root filesystem." . + "Append with ubd?=.", + "" ); + + $table_uml->set_row_spacing( 2, 4); + + #_______________________________________ + # Submit Button + my $submit_b = button_advanced(0,1,3,4,"Submit",$table_uml); + $tooltips->set_tip( $submit_b, + "Start uml kernel processes.", + "" ); + $submit_b->signal_connect("clicked", + sub { + # UML kernel = $entry_advanced[5] + # xterm -e linux ubd#=root_fs + # root=/dev/ubd# + open(OPTIONS,"$home_uml_kernel/.options"); + @initial_options = ; + close(OPTIONS); chomp @initial_options; + $eab2->set_popdown_strings( @initial_options ) ; + + my $pid; + if ($entry_advanced[8] && + $entry_advanced[10]) { + # Check to see if it actually exists + my $executable = (split(/\s+/,$entry_advanced[8]))[0]; + if (!find_file_in_path(basename($executable))) { + error_window("gBootRoot Error: " . + "Enter a valid xterm, and " . + "executable option."); + return; + } + if ($executable =~ m,/,) { + if (! -e $executable) { + error_window("gBootRoot Error: " . + "Enter a valid path for the xterm."); + return; + } + } + + unless ($pid = fork) { + unless (fork) { + if ($pid == 0) { + sys("$entry_advanced[8] $entry_advanced[5] $entry_advanced[9] $entry_advanced[10]"); + Gtk->_exit($pid); + } + + } + + } + waitpid($pid,0); + + } + else { + if (!$entry_advanced[8]) { + error_window("gBootRoot Error: " . + "Enter an xterm, and executable " . + "option."); + return; + } + if (!$entry_advanced[10]) { + error_window("gBootRoot Error: " . + "Enter the ubd?=Root_Filesystem " . + "and its location."); + return; + } + + } + + } ); + + + #_______________________________________ + # Cancel button also kills UML kernel if still open + my $abort_b = button_advanced(1,2,3,4,"Abort",$table_uml); + $tooltips->set_tip( $abort_b, + "Abort uml kernel processes." . + "This serves three purposes:\n" . + "1. Your creation doesn't boot.\n" . + "2. Your creation does work and" . + " you use something like" . + " `shutdown -h now`. When you are all done use" . + " Abort because it provides an excellent" . + " way to kill any ghost processes.\n" . + "3. Your creation gets weird, and you need to " . + "Abort its processes to shutdown it. ", + "" ); + $abort_b->signal_connect("clicked", + sub { + if ($entry_advanced[10]) { + # Most stuff + remove_matching_process($entry_advanced[10]); + # Debian + remove_matching_process("Virtual Console"); + # Good to remove uml_\w* + remove_matching_process('uml_\w*'); + # Again for good measure :) + remove_matching_process($entry_advanced[10]); + } + } ); + + #_______________________________________ + # Cancel button also kills UML kernel if still open + my $cancel_b = button_advanced(2,3,3,4,"Close",$table_uml); + $tooltips->set_tip( $cancel_b, + "Close uml box.", + "" ); + $cancel_b->signal_connect("clicked", + sub { + $uml_window->destroy() if $uml_window; + } ); + + } + if (!visible $uml_window) { + $uml_window->show(); + } else { + $uml_window->destroy; + } + +} + +sub remove_matching_process { + + my ($match_word) = @_; + + # Just an overkill + if ($match_word =~ m,/,) { + $match_word =~ s,/,\\/,g; + } + + my $ps = "ps auxw|"; + open(P,"$ps"); + while(

) { + # friendly approach + if (m,$match_word,) { + my $process = (split(/\s+/,$_,))[1]; + system "kill $process"; + # not so friendly approach + system "kill -9 $process"; + } + } + close(P); + +} # end remove_matching_process + +sub accept_button { + + my ($widget,$ear2_save) = @_; + + my($tool,$value); + if (-e "$tmp/$entry_advanced[4]" ) { + if (!$compression_off->active) { + if ($gz_toggle_root->active) { + $compress = "gzip"; + open(F,"file $tmp/$entry_advanced[4] |"); + while () { + if (/gzip/) { + info(0, "Already gzip compressed.\n"); + } + elsif (/bzip2/) { + info(0, "Already bzip2 compressed.\n"); + } + else { + system + "$compress -c9 $tmp/$entry_advanced[4] > $tmp/$entry_advanced[4].gz"; + $entry_advanced[4] = "$entry_advanced[4].gz"; + $entry3->set_text("$tmp/$entry_advanced[4]"); + } + } + close(F); + if ($ear2_save->active) { + if (-f "$home_rootfs/$entry_advanced[4]") { + save_as($entry_advanced[4]); + } + else { + return if errcp(sys("cp -a $tmp/$entry_advanced[4] $home_rootfs")) == 2; + } + } + else { + $ear2->set_text("$entry_advanced[4]"); + } + } + elsif ($bz2_toggle_root->active) { + $compress = "bzip2"; + open(F,"file $tmp/$entry_advanced[4] |"); + while () { + if (/gzip/) { + info(0, "Already gzip compressed.\n"); + } + elsif (/bzip2/) { + info(0, "Already bzip2 compressed.\n"); + } + else { + system + "$compress -c $tmp/$entry_advanced[4] > $tmp/$entry_advanced[4].bz2"; + $entry_advanced[4] = "$entry_advanced[4].bz2"; + $entry3->set_text("$tmp/$entry_advanced[4]"); + } + } + close(F); + if ($ear2_save->active) { + if (-f "$home_rootfs/$entry_advanced[4]") { + save_as($entry_advanced[4]); + } + else { + return if errcp(sys("cp -a $tmp/$entry_advanced[4] $home_rootfs")) == 2; + } + } + else { + $ear2->set_text("$entry_advanced[4]"); + } + } + } + else { # off + $entry3->set_text("$tmp/$entry_advanced[4]"); + if ($ear2_save->active) { + if (-f "$home_rootfs/$entry_advanced[4]") { + save_as($entry_advanced[4]); + } + else { + return if errcp(sys("cp -a $tmp/$entry_advanced[4] $home_rootfs")) == 2; + } + } + } + } + else { + error("$entry_advanced[4] doesn't exist; create it first.\n"); + } + +} # end accept_button + +my ($save_as); +sub save_as { + +# Will just use a dialog box. + + my ($template) = @_; + #my ($button); + + if (not defined $save_as) { + $save_as = Gtk::Dialog->new(); + $save_as->signal_connect("destroy", \&destroy_window, \$save_as); + $save_as->signal_connect("delete_event", \&destroy_window, \$save_as); + $save_as->signal_connect("key_press_event", sub { + my $event = pop @_; + if ($event->{'keyval'}) { + if ($event->{'keyval'} == 65307) { + $save_as->destroy; + } + } + }, + ); + $save_as->set_title("Save As"); + $save_as->border_width(12); + $save_as->set_position('center'); + + my $new_template = $template; + my $entry = Gtk::Entry->new(); + $entry->set_editable( $true ); + $entry->set_text($template) if $template; + $entry->signal_connect( "changed", sub { + $new_template = $entry->get_text(); + }); + $save_as->vbox->pack_start( $entry, $false, $false, 0); + $entry->show(); + + my $label = Gtk::Label->new(); + $label->set_justify( 'left' ); + $label->set_text("$template already exists, " . + "do\nyou want to write over it, " . + "or\nsave $new_template with a different name?"); + $save_as->vbox->pack_start( $label, $false, $false, 2 ); + $label->show(); + + my $button = Gtk::Button->new("OK"); + my $event_count = 0; + my $new_template_tmp = "nothing"; + $button->signal_connect("clicked", sub { + + $entry_advanced[4] = $new_template; + $ars->{filename} = $new_template; + ars($ars); + + # This is a renaming deal and this time doesn't exist in the archive + # or $tmp. + if (!-f "$home_rootfs/$new_template") { + if ($template ne $new_template) { + return if err_custom("mv $tmp/$template $tmp/$new_template", + "gBootRoot: ERROR: Could not rename $template to " . + "$new_template") == 2; + } + + return if errcp(sys("cp -a $tmp/$new_template $home_rootfs")) == 2; + $ear2->set_text($new_template); + $entry3->set_text("$tmp/$new_template"); + $save_as->destroy; + } + + # This is a write-over situation .. exists in $tmp and archive + elsif (-e "$tmp/$new_template" && -f "$tmp/$new_template" + && -f "$home_rootfs/$new_template" ) { + return if errcp(sys("cp -a $tmp/$new_template $home_rootfs")) == 2; + $ear2->set_text($new_template); + $entry3->set_text("$tmp/$new_template"); + $save_as->destroy; + } + + # Here the file trying to be renamed already exists in the archive + # but doesn't exist in $tmp + else { + + $label->set_text("$new_template already exists, " . + "do\nyou want to write over it, " . + "or\nsave $template with a different name?"); + + $event_count++; + my $event = pop(@_); + + if ($new_template eq $new_template_tmp) { + if ($event_count >= 2 && $event && $event eq "clicked") { + if ("$tmp/$template" ne "$tmp/$new_template") { + return if err_custom("mv $tmp/$template $tmp/$new_template", + "gBootRoot: ERROR: Could not rename $template to " . + "$new_template") == 2; + } + + return if errcp(sys("cp -a $tmp/$new_template $home_rootfs")) + == 2; + $event_count = 0; + $ear2->set_text($new_template); + $entry3->set_text("$tmp/$new_template"); + $save_as->destroy; + } + } + $new_template_tmp = $new_template; + } + },"clicked"); + $button->can_default(1); + $save_as->action_area->pack_start($button, $false, $false,0); + $button->grab_default; + $button->show; + + $button = Gtk::Button->new("Cancel"); + $button->signal_connect("clicked", sub { destroy $save_as} ); + $save_as->action_area->pack_start($button, $false, $false,0); + $button->show; + + } + if (!visible $save_as) { + show $save_as; + } + else { + destroy $save_as; + } + +} # end sub save_as + +# Coming - .config storage, auto-matic kernel locus, all stages +# /usr/src/linux* Possible integration with other Projects .. modules +# will be in the logical place. Before ABS. +sub advanced_kernel_section { + + +} # end sub advanced_kernel_section + +# Stuff univeral for all root filesystem methods +# Compression, UML Kernel, and Method only need to be known by the Dock. + + +sub Generate { + + # @entry_advanced + # 0 = Development Drive + # 1 = Optional Devices + # 2 = Append Options + #------------------ + # 3 = Root Device + # 4 = Root Filename + # 5 = UML Kernel + my $method = $entry_advanced[6]; # 6 = Method + # 7 = Template + # 8 = UML xterm + # 9 = UML options + # 10 = UML root_fs + #------------------ + # 11 = Kernel Modules .. from the Boot Method + # 12 = Kernel Version .. from the Boot Method + # 13 = System.map .. from the Boot Method + + # $root_device_size; + # $filesystem_size; + + # File select: function order: non-table = button->fileselect->file_ok_sel + # table = button_fileselect_advanced->fileselect->file_ok_sel + + $ars->{device} = $entry_advanced[3]; + $ars->{device_size} = $root_device_size; + $ars->{tmp} = $tmp; + $ars->{mnt} = $mnt; + $ars->{template_dir} = $template_dir; # static right now. + ars($ars); + + + my $template = $ars->{template}; + my $root_device = $ars->{device}; + my $root_filename = $ars->{filename}; + + if (!$root_device || $root_device eq "") { + error_window("gBootRoot: ERROR: Root Device not defined"); + return; + } + # devfs may change this .. it did, this is silly. +## if (!-b $root_device) { +## error_window("gBootRoot: ERROR: Not a valid Block Device"); +## return; +## } + + if (!$root_filename || $root_filename eq "") { + error_window("gBootRoot: ERROR: Root Filename not given"); + return; + } + if (!$method || $method eq "") { + error_window("gBootRoot: ERROR: Method must be supplied"); + return; + } + if (!$template || $template eq "") { + error_window("gBootRoot: ERROR: Template name not given"); + return; + } + + + if ($method eq "yard") { + if (!$main::yard_window) { + ##$ars->{kernel} = "" if !$entry2->get_text(); + ##ars($ars); + yard(); + } + } + + +} # end sub Generate + +sub button_advanced { + + # cretzu should like this + my ($left_attach,$right_attach,$top_attach, + $bottom_attach,$text,$widget) = @_; + my $button = Gtk::Button->new($text); + $widget->attach($button,$left_attach,$right_attach, + $top_attach,$bottom_attach, + ['shrink','fill','expand'],['fill','shrink'],2,2); + show $button; + return $button; + +} + +sub button_fileselect_advanced { + + # cretzu should like this + # $order does matter because it fills in $container[$order]. + my ($left_attach,$right_attach,$top_attach,$bottom_attach,$text,$ent, + $name,$order,$widget,$device) = @_; + + my $button = Gtk::Button->new($text); + $widget->attach($button,$left_attach,$right_attach, + $top_attach,$bottom_attach, + ['shrink','fill','expand'],['fill','shrink'],2,2); + + # example + if ($order == 12) { + $tooltips->set_tip( $button, "Select the Root Device.", "" ); + } + elsif ($order == 13) { + $tooltips->set_tip( $button, "Select the UML Kernel.", "" ); + } + elsif ($order == 14) { + $tooltips->set_tip( $button, "Select the Root Filesystem.", "" ); + } + elsif ($order == 16) { + $tooltips->set_tip( $button, "Select the System.map.", "" ); + } + + + $button->signal_connect( "clicked",\&fileselect,$ent,$name,$order,$device); + $button->show(); + + +} # end sub button_fileselect_advanced + + +sub entry_advanced { + + my $numa = $_[4]; + my $entry_advanced = Gtk::Entry->new(); + $entry_advanced->set_editable( $true ); + $entry_advanced->signal_connect( "changed", sub { + $entry_advanced[$numa] = $entry_advanced->get_text(); + if ($numa == 4) { + $ars->{filename} = $entry_advanced[$numa]; + ars($ars); + } + if ( $numa == 12 ) { + $ars->{kernel_version_choice} = $entry_advanced[$numa]; + ars($ars); + ars2($ars); + } + } ); + $entry_advanced->set_usize(100,20); + $_[5]->attach($entry_advanced,$_[0],$_[1],$_[2],$_[3], + ['shrink','fill','expand'],['fill','shrink'],0,0); + show $entry_advanced; + return $entry_advanced; + +} + +sub separator_advanced { + + $separator_advanced = Gtk::HSeparator->new(); + $_[0]->pack_start( $separator_advanced, $false, $true, 0 ); + $separator_advanced->show(); + +} + +sub label_advanced { + + my($text) = @_; + + $label_advanced = Gtk::Label->new( $text ); + $label_advanced->set_justify( "fill" ); + $_[5]->attach($label_advanced,$_[1],$_[2],$_[3],$_[4], ['expand'],['fill','shrink'],0,0); + $label_advanced->show(); + +} + +# I created two of these, one for help (eventually there may be a different +# approach), and one for verbosity. I am sure there is a better OO way to +# do it, though. +sub create_text { + + if (not defined $text_window) { + $text_window = Gtk::Window->new("toplevel"); + $text_window->signal_connect("destroy", \&destroy_window, + \$text_window); + $text_window->signal_connect("delete_event", \&destroy_window, + \$text_window); + $text_window->set_title("Help"); + $text_window->set_usize( 500, 600 ); + $text_window->set_policy( $true, $true, $false ); + $text_window->set_title( "gBootRoot Help" ); + $text_window->border_width(0); + + my $main_vbox = Gtk::VBox->new( $false, 0 ); + $text_window->add( $main_vbox ); + $main_vbox->show(); + + my $vbox = Gtk::VBox->new( $false, 10 ); + $vbox->border_width( 10 ); + $main_vbox->pack_start( $vbox, $true, $true, 0 ); + $vbox->show(); + + my $table = Gtk::Table->new( 2, 2, $false ); + $table->set_row_spacing( 0, 2 ); + $table->set_col_spacing( 0, 2 ); + $vbox->pack_start( $table, $true, $true, 0 ); + $table->show( ); + + # Create the GtkText widget + my $text = Gtk::Text->new( undef, undef ); + $text->set_editable($false); + $table->attach( $text, 0, 1, 0, 1, + [ 'expand', 'shrink', 'fill' ], + [ 'expand', 'shrink', 'fill' ], + 0, 0 ); + $text->grab_focus(); + $text->show(); + + # Add a vertical scrollbar to the GtkText widget + my $vscrollbar = Gtk::VScrollbar->new( $text->vadj ); + $table->attach( $vscrollbar, 1, 2, 0, 1, 'fill', + [ 'expand', 'shrink', 'fill' ], 0, 0 ); + #my $logadj = $vscrollbar->get_adjustment(); + #logadj($logadj); + #$vscrollbar->show(); + + $text->freeze(); + $text->insert( undef, undef, undef, help() ); + $text->thaw(); + + my $separator = Gtk::HSeparator->new(); + $main_vbox->pack_start( $separator, $false, $true, 0 ); + $separator->show(); + + $vbox = Gtk::VBox->new( $false, 10 ); + $vbox->border_width( 10 ); + $main_vbox->pack_start( $vbox, $false, $true, 0 ); + $vbox->show(); + + my $button = Gtk::Button->new( "Close" ); + $button->signal_connect( 'clicked', sub { destroy $text_window; } ); + $vbox->pack_start( $button, $true, $true, 0 ); + $button->can_default( $true ); + $button->grab_default(); + $button->show(); + } + if (!visible $text_window) { + show $text_window; + } else { + destroy $text_window; + } + +} # end sub create_text + +# This monster needs different behavior than create_text. +sub verbosity_box { + + + $verbosity_window = Gtk::Window->new("toplevel"); + $verbosity_window->signal_connect("destroy", \&destroy_window, + \$verbosity_window); + $verbosity_window->signal_connect("delete_event", \&destroy_window, + \$verbosity_window); + $verbosity_window->set_usize( 450, 175 ); # 500 600 + $verbosity_window->set_policy( $true, $true, $false ); + $verbosity_window->set_title( "Verbosity Box" ); + $verbosity_window->border_width(0); + + my $main_vbox = Gtk::VBox->new( $false, 0 ); + $verbosity_window->add( $main_vbox ); + $main_vbox->show(); + + my $vbox = Gtk::VBox->new( $false, 10 ); + $vbox->border_width( 10 ); + $main_vbox->pack_start( $vbox, $true, $true, 0 ); + $vbox->show(); + + my $table = Gtk::Table->new( 2, 2, $false ); + $table->set_row_spacing( 0, 2 ); + $table->set_col_spacing( 0, 2 ); + $vbox->pack_start( $table, $true, $true, 0 ); + $table->show( ); + + # Create the GtkText widget + my $text = Gtk::Text->new( undef, undef ); + $text->set_editable($false); + $table->attach( $text, 0, 1, 0, 1, + [ 'expand', 'shrink', 'fill' ], + [ 'expand', 'shrink', 'fill' ], + 0, 0 ); + $text->grab_focus(); + $text->show(); + my $red = Gtk::Gdk::Color->parse_color("red"); + my $blue = Gtk::Gdk::Color->parse_color("blue"); + text_insert($text,$red,$blue); # yard thing + + # Add a vertical scrollbar to the GtkText widget + my $vscrollbar = Gtk::VScrollbar->new( $text->vadj ); + $table->attach( $vscrollbar, 1, 2, 0, 1, 'fill', + [ 'expand', 'shrink', 'fill' ], 0, 0 ); + my $logadj = $vscrollbar->get_adjustment(); + logadj($logadj); + $vscrollbar->show(); + + my $separator = Gtk::HSeparator->new(); + $main_vbox->pack_start( $separator, $false, $true, 0 ); + $separator->show(); + + $vbox = Gtk::VBox->new( $false, 10 ); + $vbox->border_width( 10 ); + $main_vbox->pack_start( $vbox, $false, $true, 0 ); + $vbox->show(); + + #my $button = Gtk::Button->new( "Close" ); + #$button->signal_connect( 'clicked', + # sub { destroy $verbosity_window; } ); + #$vbox->pack_start( $button, $true, $true, 0 ); + #$button->can_default( $true ); + #$button->grab_default(); + #$button->show(); + + show $verbosity_window; + +} # end sub verbosity_box + +sub fileselect { + + my ($widget,$ent,$name,$order,$device) = @_; + + if (not defined $file_dialog) { + # Create a new file selection widget + $file_dialog = Gtk::FileSelection->new( "$name" ); + $file_dialog->signal_connect( "destroy", + \&destroy_window, \$file_dialog); + $file_dialog->signal_connect( "delete_event", + \&destroy_window, \$file_dialog); + + # Connect the ok_button to file_ok_sel function + $file_dialog->ok_button->signal_connect( "clicked", + \&file_ok_sel, + $file_dialog,$ent,$order); + + # Connect the cancel_button to destroy the widget + $file_dialog->cancel_button->signal_connect( "clicked", + sub { destroy $file_dialog } ); + $file_dialog->set_filename( $device ) if defined $device; + $file_dialog->set_position('mouse'); + + } + if (!visible $file_dialog) { + show $file_dialog; + } + else { + destroy $file_dialog; + } + +} # end sub fileselect + + +# Get the selected filename and print it to the text widget +sub file_ok_sel { + + my( $widget, $file_selection,$entry,$order) = @_; + my $file = $file_selection->get_filename(); + if ($order != 14) { + $entry->set_text($file); + } + else { + $entry->set_text("ubd0=$file"); + } + $container[$order] = $file; + if ($order == 1) { + $ars->{kernel} = $container[$order]; + ars($ars); + ars2($ars); + } + + # auto-detect compression if system has file + if ($container[ROOT_FS]) { + my $file = sys("which file > /dev/null 2>&1"); + if ($file == 0) { + open(F,"file $container[ROOT_FS] |"); # no error check + # here + while () { + if (/gzip/) { + $gz_toggle->set_active( $true ); + } + elsif (/bzip2/) { + $bz2_toggle->set_active( $true ); + } + else { + info(0, "Neither gz or bz2 compression found\n"); + } + } + close(F); + } + } + + destroy $file_dialog; + +} + +sub hbox { + my $homogeneous; + defined $_[0] ? ($homogeneous = 0) : ($homogeneous = 1); + $box2 = Gtk::HBox->new( $homogeneous, 5 ); + $box2->border_width( 2 ); # was 10 + $box1->pack_start( $box2, $true, $true, 0 ); + #$box1->pack_start( $box2, $false, $true, 0 ); + $box2->show(); +} + +sub label { + + my($text) = @_; + + $label = Gtk::Label->new( $text ); + $label->set_justify( "fill" ); + $box2->pack_start( $label, $false, $false, 5 ); + $label->show(); + +} + +sub entry { + + my($edit,$num) = @_; + + my $entry = Gtk::Entry->new(); + + $entry->set_editable( $false ) if $edit == 0; + + if ($num == 0) { + $entry->signal_connect( "activate", sub { + $container[$num] = $entry->get_text();}); + } + else { + $entry->signal_connect( "changed", sub { + $container[$num] = $entry->get_text(); + if ($num == 1) { + $ars->{kernel} = $container[$num]; + ars($ars); + ars2($ars); + } + # here's where types in entry3, types other places + if (defined $ea1 and $num == 3) { + $ea1->set_text($container[$num]); + } + if (defined $ear1 and $num == 3) { + $ear1->set_text($container[$num]); + } + + # auto-detect compression if system has file + if ($num == 2) { + my $file = sys("which file"); + if ($file == 0) { + if ($container[ROOT_FS]) { + open(F,"file $container[ROOT_FS] |"); # no error check here + while () { + if (/gzip/) { + $gz_toggle->set_active( $true ); + } + elsif (/bzip2/) { + $bz2_toggle->set_active( $true ); + } + else { + info(0, + "Neither gz or bz2 compression found\n"); + } + } + close(F); + } + } + } + }); + } + if (defined $num and $num != 0) { + my $todo; + if ($num == 1) { + $todo = "the Kernel"; + } + elsif ($num == 2) { + $todo = "the Compressed Filesystem"; + } + else { + $todo = "the Block Device to use"; + } + $tooltips->set_tip( $entry, + "Type in the location of $todo.", "" ); + } + $box2->pack_start( $entry, $true, $true, 0 ); + $entry->show(); + + return $entry; + +} + +sub button { + + my ($text,$ent,$name,$order,$device) = @_; + + my $button = Gtk::Button->new($text); + if ($order == 1) { + $tooltips->set_tip( $button, "Select the Kernel.", "" ); + } + elsif ($order == 2) { + $tooltips->set_tip( $button, "Select the Root Filesystem.", "" ); + } + else { + $tooltips->set_tip( $button, "Select the Device.", "" ); + } + $button->signal_connect( "clicked",\&fileselect,$ent,$name,$order,$device); + $button->show(); + $box2->pack_start( $button, $true, $true, 0 ); + $box2->show(); + +} + +sub submit { + + my($kernel, $root_image, $device, $size); + + # comment this out for testing + # Since only one filehandle is now used, this won't work + # anymore. + #unlink("$verbosefn"); + open (MTAB, "/etc/mtab") or die "no mtab!\n"; + while () { + if (m,$mnt,) { + sys("umount $mnt"); + } + } + close(MTAB); + $entry5->set_text(""); + pb("boot",0); + + if ($gz_toggle->active) { + $compress = "gzip"; + } + elsif ($bz2_toggle->active) { + $compress = "bzip2"; + } + + # Run some checks + if (!defined $container[METHOD]) { + error_window("gBootRoot: ERROR: No Method supplied"); + return; + } + else { + if ( $container[METHOD] eq "2 disk compression" ) { + my $rt = two_disk_compression_check(); + return if $rt; + } + } + + +if (defined $container[KERNEL] && -e $container[KERNEL] && + !-d $container[KERNEL]) { + $kernel = $container[KERNEL]; + # Better be sure it isn't in the mount directory + if ($kernel =~ m,^$mnt,) { + error_window("gBootRoot: ERROR: Kernel found below Device mount point: $mnt"); + return; + } + +} +elsif (defined $container[METHOD]) { + error_window("gBootRoot: ERROR: Kernel not found"); + return; +} +if (defined $container[ROOT_FS] && -e $container[ROOT_FS] && + !-d $container[ROOT_FS] ) { + $root_image = $container[ROOT_FS]; + if ($root_image =~ m,^$mnt,) { + # Bug revealed by Cristian Ionescu-Idbohrn + error_window( + "gBootRoot: ERROR: Rootimage found below Device mount point: $mnt"); + return; + } +} +elsif (defined $container[METHOD] && defined $container[KERNEL]) { + error_window("gBootRoot: ERROR: Root Filesystem not found"); + return; +} +# we need to check for this, too. +if (defined $container[BOOT_DEVICE] && -b $container[BOOT_DEVICE]) { + $device = $container[BOOT_DEVICE]; +} +elsif (defined $container[METHOD] && defined $container[KERNEL] + && defined $container[ROOT_FS]) { + error_window("gBootRoot: ERROR: Not a valid Block Device"); + return; +} +if (defined $container[SIZE]) { + $size = $container[SIZE]; +} + +# pretty unlikely +elsif (defined $container[METHOD] && defined $container[KERNEL] && + defined $container[ROOT_FS] && defined $container[BOOT_DEVICE]) { + error_window("gBootRoot: ERROR: No size specified"); + return; +} + + # kernel value can change without effecting initrd + # no sense doing this until important stuff is filled in + if (defined $kernel && defined $root_image && + defined $device && defined $size) { + $container[COMPRESS] = $compress; + + # 1 .. 4 - its a hash .. not too simple + !defined $lib_strip_check ? ($container[LIB_STRIP] = 1) + : ($container[LIB_STRIP] = $lib_strip_check->get_active()); + !$container[LIB_STRIP] ? ($container[LIB_STRIP] = 2) + : ($container[LIB_STRIP] = 1); + + !defined $bin_strip_check ? ($container[BIN_STRIP] = 3) + : ($container[BIN_STRIP] = + $bin_strip_check->get_active()); + !$container[BIN_STRIP] ? ($container[BIN_STRIP] = 4) + : ($container[BIN_STRIP] = 3); + + !defined $mod_strip_check ? ($container[MOD_STRIP] = 7) + : ($container[MOD_STRIP] = + $mod_strip_check->get_active()); + !$container[MOD_STRIP] ? ($container[MOD_STRIP] = 8) + : ($container[MOD_STRIP] = 7); + + + if ($container[LIB_STRIP] == 1) { + $obj_count == 0 ? ($container[OBJCOPY_BOOL] = 5) + : ($container[OBJCOPY_BOOL] = 6); + } + + + if (!defined $entry_advanced[0]) { + $container[ABS_DEVICE] = $device . "ea1"; + $entry_advanced[0] = $device; + } + else { + $container[ABS_DEVICE] = $entry_advanced[0] . "ea1"; + } + + # If ARS was never opened, root device defaults to boot device. + # This keeps the logic in the right place. + $entry_advanced[3] = $container[BOOT_DEVICE] if !$entry_advanced[3]; + + + # Works now .. whoosh! + if ($container[ABS_OPT_DEVICE]) { + if ($container[ABS_OPT_DEVICE] ne "") { + $container[ABS_OPT_DEVICE] = $entry_advanced[1] + if $entry_advanced[1]; + } + if (defined $entry_advanced[1] and $entry_advanced[1] eq "") { + $container[ABS_OPT_DEVICE] = ""; + } + elsif ($container[ABS_OPT_DEVICE] eq "") { + push(@original_container,$entry_advanced[1]); + } + } + else { + push(@original_container,$entry_advanced[1]) + if $entry_advanced[1]; + } + + # pretty complex and works properly even for !-e lilo.conf + if ($container[ABS_APPEND]) { + if ($container[ABS_APPEND] ne "") { + $container[ABS_APPEND] = $entry_advanced[2] + if $entry_advanced[2]; + } + if (defined $entry_advanced[2] and $entry_advanced[2] eq "") { + $container[ABS_APPEND] = ""; + } + elsif ($container[ABS_APPEND] eq "") { + push(@original_container,$entry_advanced[2]); + } + } + else { + push(@original_container,$entry_advanced[2]) + if $entry_advanced[2]; + } + + if (@original_container) { # defined array deprecate Perl 5.6 - zas@metaconcept.com + # a hash check isn't perfect for two values which are the same + # no need to check all the values + + my @temp_container = @container; + + # Got it! - how to deal with fields with no init value + if (defined $container[ABS_OPT_DEVICE] and + $container[ABS_OPT_DEVICE] eq "") { + $container[ABS_OPT_DEVICE] = $entry_advanced[1]; + } + if (!defined $container[ABS_OPT_DEVICE]) { + $container[ABS_OPT_DEVICE] = $entry_advanced[1]; + } + if (defined $container[ABS_APPEND] and + $container[ABS_APPEND] eq "") { + $container[ABS_APPEND] = $entry_advanced[2]; + } + if (!defined $container[ABS_APPEND]) { + $container[ABS_APPEND] = $entry_advanced[2]; + } + + # no sense looking at undef values + my (@temp_container2,@original_container2); + for (@temp_container) { + if ($_) { + push(@temp_container2,$_); + } + } + for (@original_container) { + if ($_) { + push(@original_container2,$_); + } + } + + @temp_container = @temp_container2; + @original_container = @original_container2; + + splice(@temp_container,1,1); + + # A test which I've had to run too often + #print "BEFORE @temp_container\nAFTER @original_container\n"; + + my %diff; + grep($diff{$_}++,@temp_container); + my @diff = grep(!$diff{$_},@original_container); + + if ($#diff >= 0) { + # unlink initrd_image.gz, do initrd_size() + $ok = 1; + $initrd = "initrd_image"; + } + else { + $ok = 0; + } + } + else { + $ok = 2; # this is actually first (1 = diff, 0 = same) + $initrd = "initrd_image"; + } + + # reset + @original_container = ( $container[METHOD], + $root_image, + $device, + $size, + $compress, + $container[LIB_STRIP], + $container[BIN_STRIP], + $container[MOD_STRIP], + $container[OBJCOPY_BOOL], + $container[ABS_DEVICE], + $container[ABS_OPT_DEVICE], + $container[ABS_APPEND] + ); + + kernel_modules(); + lilo(); # This is the default now, and the value for + # METHOD doesn't matter now. + } + +} # end sub submit + +sub lilo { + + # Do a little cleanup just in case + sys("rm $tmp/initrd_image.gz") if $ok == 1; + sys("umount $tmp/initrd_mnt"); + + my $kernel = $container[KERNEL]; + my $root_fs = $container[ROOT_FS]; + my $device = $container[BOOT_DEVICE]; + my $size = $container[SIZE]; + + if ($ok == 1 || $ok == 2) { + my $value = initrd($kernel,$root_fs,$device,$size); + mtab(0) if defined $value; + } + elsif ($ok == 0) { + mtab(0); + } + +} # end sub lilo + +sub lilo_put_it_together { + + my $B = "boot"; + my $fs_type = (split(/\s/,$main::makefs))[0]; + + # Time to do a little calculations + my $device_size; + if ( $fs_type ne "genext2fs" ) { + $device_size = (split(/\s+/,`df $mnt`))[8]; + } + else { + $device_size = $container[SIZE]; + } + my $boot_size = (stat($container[KERNEL]))[12]/2 + + (stat("$tmp/$initrd"))[12]/2; + my $remain_boot = $device_size - $boot_size; + pb($B,1); + + # A little output + if ($remain_boot =~ /^-+\d+$/) { + error_window("gBootRoot: ERROR: Not enough room: boot stuff = $boot_size k, device = $device_size k"); + return; + } + else { + $entry5->set_text("$remain_boot k"); + } + + + # If genext2fs is being used clean $tmp/bootdisk if any garbage is found, + # and temporarily rename $mnt to that directory. + #my $old_mount; + if ( $fs_type eq "genext2fs" ) { + if (-d "$tmp/bootdisk") { + sys("rm -rf $tmp/bootdisk"); + } + if (!-d "$tmp/bootdisk") { + return if errmk(sys("mkdir $tmp/bootdisk")) == 2; + } + $old_mount = $mnt; + $mnt = "$tmp/bootdisk/"; + } + + # Here everything is copied over either to the device or the the $mnt + # directory if genext2fs is used. + info(0, "Copy over initrd ramdisk\n"); + info(0, "Copy over initrd ramdisk .. $tmp/$initrd $mnt/$initrd\n"); + return if err_custom("cp $tmp/$initrd $mnt/$initrd", + "gBootRoot: ERROR: Could not copy over initrd") == 2; + pb($B,2); + + info(0, "Copying over kernel\n"); + if ( $fs_type ne "genext2fs" ) { + return if + err_custom("rm -rf $mnt/lost+found; cp $container[KERNEL] $mnt/kernel", "gBootRoot: ERROR: Could not copy over the kernel") == 2; + } + else { + return if + err_custom("cp $container[KERNEL] $mnt/kernel", "gBootRoot: ERROR: Could not copy over the kernel") == 2; + } + pb($B,3); + + info(0, "Making stuff for lilo\n"); + # will be 0 if mkdir fails, but 0 if cp succeeds ? + return if err(sys("mkdir $mnt/{boot,dev}")) == 2; + + # DEVICES SECTION + my @devices; + my $device_table = "$tmp/boot_device_table.txt"; + if ( $fs_type eq "genext2fs" ) { + + info(0, "Making $device_table for genext2fs\n"); + my $error; + unlink( $device_table ) if -e $device_table; + + # + # /dev is always needs to be made automatically + open(BootRoot::Yard::DEVICE_TABLE, ">$device_table") or + ($error = error("$device_table: $!")); + return "ERROR"if $error && $error eq "ERROR"; + + print BootRoot::Yard::DEVICE_TABLE + "# \t\t\t\t\t\t" . + "\t\t\t\n"; + print BootRoot::Yard::DEVICE_TABLE "/dev\t\td\t0755\t-\t-\t-\t-\t-\t-\t-\n"; + + # Keep a record of the devices required + @devices = qw(/dev/null /dev/fd0 /dev/fd1 /dev/hda1); + for ( split(" ", $container[BOOT_DEVICE] ) ) { + my @existing_device_test = grep ( /$_/, @devices ); + if ( !@existing_device_test ) { + push(@devices, $_ ) if $_; + } + } + + # This adds that next device if found in lilo.conf + ($norm_root_device) = gdkbirdaao(); + if ( $norm_root_device ) { + my @existing_device_test = + grep ( /\/dev\/$norm_root_device/, @devices ); + if ( !@existing_device_test ) { + push( @devices, "/dev/$norm_root_device" ); + } + } + + # For frame buffer devices and the like. + if ( $entry_advanced[1] ) { + for ( split(" ", $entry_advanced[1] ) ) { + my @existing_device_test = grep ( /$_/, @devices ); + if ( !@existing_device_test ) { + push(@devices, $_ ) if $_; + } + } + } + + + device_table( @devices ); + close(BootRoot::Yard::DEVICE_TABLE); + + } + else { + + info(0, "Copying over devices to $mnt/dev\n"); + + return if err(sys("cp -a /dev/{null,fd?,hda1} $mnt/dev")) == 2; + + # Hopefully, this works, but have never tested it -- o.k I did + if ($container[BOOT_DEVICE] !~ m,/dev/fd\d{1}$,) { + return if err(sys("cp -a $container[BOOT_DEVICE] $mnt/dev")) == 2; + } + + # This adds that next device if found in lilo.conf + ($norm_root_device) = gdkbirdaao(); + if (!-e "$mnt/dev/$norm_root_device") { + return if err(sys("cp -a /dev/$norm_root_device $mnt/dev")) == 2; + } + + # For frame buffer devices and the like. + if ($entry_advanced[1]) { + return if errcp(sys("cp -a $entry_advanced[1] $mnt/dev")) == 2; + } + + + } # end DEVICES SECTION + + info(0, "Copy over important lilo stuff\n"); + return if + err_custom("cp /boot/boot.b $mnt/boot", + "gBootRoot: ERROR: Not enough space or can't find /boot/boot.b") == 2; + pb($B,4); + # 3k sort of accounts for dev & dirs assuming dev is reasonable + $remain_boot = $remain_boot - (stat("/boot/boot.b"))[12]/2 - 3; + $entry5->set_text("$remain_boot k"); + + # Write out the HEREDOCS + open(LC, ">$mnt/brlilo.conf") or die "Couldn't write $mnt/brlilo.conf\n"; + if ( $> == 0 ) { + print LC brlilo($container[BOOT_DEVICE]); close(LC); + } + else { + print LC brlilo_non_root($container[BOOT_DEVICE]); close(LC); + } + + open(M, ">$mnt/message") or die "Couldn't write $mnt/message\n"; + print M message(); close(M); + pb($B,5); + $remain_boot = $remain_boot - ( (stat("$mnt/brlilo.conf"))[12]/2 + + (stat("$mnt/message"))[12]/2 ); + $entry5->set_text("$remain_boot k"); + + # Got to umount,mount, and umount again to make sure everything is + # copied over before doing lilo unless genext2fs in being used. + if ( $fs_type ne "genext2fs" ) { + return if errum(sys("umount $mnt")) == 2; + info(0, "Umount device\n"); + info(0, "Remount device\n"); + } + pb($B,6); + + + if ( $fs_type eq "genext2fs" ) { + + my $error; + + # When creating a fs on floppy, specifying -i causes genext2fs to fail, + # its better to just let the program figure out the inode size for now. + if ( + sys("/usr/lib/bootroot/$main::makefs -b $device_size -d $mnt -D $device_table $entry_advanced[0]") !~ + /^0$/ ) { + $error = error("Cannot $fs_type filesystem.\n"); + return "ERROR" if $error && $error eq "ERROR"; + } + + } + + + if ( $fs_type eq "genext2fs" ) { + $mnt = $old_mount; + } + + # Real device + if ( $> == 0 ) { + return if errm(sys("mount -t ext2 $entry_advanced[0] $mnt")) == 2; + } + else { + my $errm_value = errm(sys("mount $mnt")); + if ( $errm_value == 2 && $fs_type eq "genext2fs" ) { + info(0, "Ask your administrator to add this line to the" . + " fstab file:\n"); + info(0, "\n$entry_advanced[0]\t$mnt\tauto\tdefaults,noauto," . + "user\t0\t0\n\n"); + } + else { + return if $errm_value == 2; + } + } + + + info(0, "Configuring lilo\n"); + pb($B,7); + chdir("$mnt"); #"boot_root: ERROR: Could not change directories\n"; + + # This enforces that lilo is only wil run on a bootable drive, + # otherwise the user has to do it manually. + if ($container[BOOT_DEVICE] eq $entry_advanced[0]) { + + # root can happily chroot + if ( $> == 0 ) { + + if ( err_custom("lilo -v -C brlilo.conf -r $mnt", + "gBootRoot: ERROR: lilo failed") == 2 ) { + chdir($pwd); + return; + } + + } + + # At this point the normal user needs to be asked first if they have + # root lilo power, before going on. + else { + + # Ask the user if they have su lilo priviliges. + # Hopefully, password free, but that can be incorporated. + mtab(3); + do { + if ( $mtab == 2 ) { + undef $mtab; + chdir($pwd); + return if errum(sys("umount $mnt")) == 2; + return; + } + while (Gtk->events_pending) { Gtk->main_iteration; } + } while $mtab; + + # It's o.k. if lilo fails. + if ( err_custom("$main::sudo lilo -v -C $mnt/brlilo.conf -b $entry_advanced[0]", "gBootRoot: ERROR: lilo failed") == 2 ) { + chdir($pwd); + } + + } + + } + + + $remain_boot = $remain_boot - (stat("$mnt/boot/map"))[12]/2; + $entry5->set_text("$remain_boot k"); + pb($B,8); + + chdir($pwd); # or die "boot_root: ERROR: Could not change directories\n"; + + info(0, "Umounting $mnt\n"); + my $um = errum(sys("umount $mnt")); + pb($B,10); + + if ($ok == 1 || $ok == 2) { + if ( $fs_type ne "genext2fs" ) { + return if + errrm(sys("rmdir $tmp/initrd_mnt")) == 2; + } + } + +# Here's where we copy over that compressed filesystem +# We could separate $container[BOOT_DEVICE] = boot,root allowing two +# different devices to be used. -- now there is $entry_advanced[3] which +# is the ROOT_DEVICE +if ($um == 0 ) { + mtab(1); +} +else { + error_window("gBootRoot: ERROR: Boot disk was never umounted"); +} # copy over the compressed + +} # end sub lilo_put_it_together + +sub device2 { + + my $fs_type = (split(/\s/,$main::makefs))[0]; + + # Time to do a little calculations + my $device_size; + if ( $fs_type ne "genext2fs" ) { + $device_size = (split(/\s+/,`df $mnt`))[8]; + } + else { + if ( !$root_device_size ) { + $device_size = $container[SIZE]; + } + else { + $device_size = $root_device_size; + } + } + + my $root_image_size = (stat($container[ROOT_FS]))[12]/2; + my $remain_root = $device_size - $root_image_size; + + if ($remain_root =~ /^-+\d+$/) { + error_window("gBootRoot: ERROR: Not enough room: root stuff = $root_image_size k, device = $device_size k"); + } + else { + $entry5->set_text("$remain_root k"); + } + + info(0, "Copy over the compressed filesystem\n"); + if ( $fs_type ne "genext2fs" ) { + return if errrm(sys("rmdir $mnt/lost+found")) == 2; + } + my $broot_image = basename($container[ROOT_FS]); + + # Status output, use FH, or genext2fs to create disk. + #---------------------------------------------------- + my $FS = "filesystem"; + my $line_count = `wc -l < $container[ROOT_FS]`; chomp $line_count; + my $half_line_count = $line_count/2; + my $count = 1; + + if ( $fs_type ne "genext2fs" ) { + open(CF, ">$mnt/$broot_image") or error_window( + "gBootRoot: ERROR: Could not copy over the root filesystem") and return; + + open(CR, "$container[ROOT_FS]") or error_window( + "gBootRoot: ERROR: Could not copy over the root filesystem") and return; + + while () { + print CF $_; + pb($FS,$count,$line_count) if $count < $half_line_count; + $count++; + } + close(CF); + close(CR); + } + + # genext2fs + else { + + my $error; + + # If genext2fs is being used clean $tmp/rootdisk if any garbage is + # found. + if ( $fs_type eq "genext2fs" ) { + if (-d "$tmp/rootdisk") { + sys("rm -rf $tmp/rootdisk"); + } + if (!-d "$tmp/rootdisk") { + return if errmk(sys("mkdir $tmp/rootdisk")) == 2; + } + } + + return if errcp( sys("cp -a $container[ROOT_FS] $tmp/rootdisk") ) == 2; + + for ( $count .. $half_line_count ) { + pb($FS,$count,$line_count) if $count < $half_line_count; + $count++; + } + + + if ( + sys("/usr/lib/bootroot/$main::makefs -b $device_size -d $mnt $entry_advanced[3]") !~ + /^0$/ ) { + info( 0, "/usr/lib/bootroot/$main::makefs -b $device_size -d $tmp/rootdisk $entry_advanced[3]\n"); + $error = error("Cannot $fs_type filesystem.\n"); + return "ERROR" if $error && $error eq "ERROR"; + } + + + } + #------------------------------------------------------ + + if ( $fs_type ne "genext2fs" ) { + return if + err_custom("umount $mnt", + "gBootRoot: ERROR: Root disk did not properly umount") == 2; + } + + pb($FS,$count,$line_count); + info(0, "Finished!\n"); + +} # end sub device 2 + +# Checks if lib or bin is stripped, if not proceeds to strip. Returns +# full file path and strip result. Right now this is specific to initrd. +sub stripper { + + # stripper (program,bin|lib|mod); + if ((!defined $lib_strip_check && !defined $bin_strip_check + && !defined $mod_strip_check) or + ($lib_strip_check->active || $bin_strip_check->active + || $mod_strip_check->active)) { + + # DON'T DO THIS >/dev/null 2>&1`; + my $not_stripped = `file $_[0] 2> /dev/null`; + my $filename = basename($_[0]); + + if ($not_stripped =~ m,not stripped,) { + if (($_[1] eq "lib" && !defined $lib_strip_check) or + ($_[1] eq "lib" && $lib_strip_check->active)) { + # --strip-all works for initrd + if ($obj_count == 0) { + sys("objcopy --strip-debug -p $_[0] $tmp/$filename"); + info(1,"--strip-debug $filename\n"); + return ( "$tmp/$filename", 1 ); + } + elsif ($obj_count == 1) { + sys("objcopy --strip-all -p $_[0] $tmp/$filename"); + info(1,"--strip-all $filename\n"); + return ( "$tmp/$filename", 1 ); + } + } + elsif (($_[1] eq "bin" && !defined $bin_strip_check) or + ($_[1] eq "bin" && $bin_strip_check->active)) { + sys("objcopy --strip-all -p $_[0] $tmp/$filename"); + info(1,"--strip-all $filename\n"); + return ( "$tmp/$filename", 1 ); + } + elsif (($_[1] eq "mod" && !defined $mod_strip_check) or + ($_[1] eq "mod" && $mod_strip_check->active)) { + sys("objcopy --strip-debug -p $_[0] $tmp/$filename"); + info(1,"--strip-debug $filename\n"); + return ( "$tmp/$filename", 1 ); + } + } + else { + return ( $_[0], 0 ); + } + } + return ( $_[0], 0); + +} # end sub stripper + +sub two_disk_compression_check { + + my ($ash,$lilo,$bzip2,$file); + + if ( !find_file_in_path("ash") ) { + $ash = "ash"; + } + + if ( !find_file_in_path("lilo") ) { + $lilo = "lilo"; + } + + if ( !find_file_in_path("bzip2") ) { + $bzip2 = "bzip2"; + } + + if ( !find_file_in_path("file") ) { + $file = "file"; + } + + if ( $ash || + + $lilo || + + $bzip2 || + + $ash + + ) { + + error_window( + "Program(s) required by this method: $lilo $ash $bzip2 $file" + ); + + return 1; + } + + +} # end sub two_disk_compression_check + +sub kernel_modules { + + my (@modules, @modules_found); + + my $module_choices = $ea3->get_text() if $ea3; + my $kernel_version_choice = $ea5->get_text() if $ea5; + undef $kernel_version_choice if defined $kernel_version_choice eq ""; + undef $kernel_version_choice if !$kernel_version_choice; + + $kernel_version = kernel_version_check($container[KERNEL], + $kernel_version_choice); + #----------------------------- + # METHOD -> 2 DISK COMPRESSION + #----------------------------- + if ( $container[METHOD] eq "2 disk compression" ) { + + $entry_advanced[11] = "floppy"; + + if ($ea3) { + if ($module_choices eq "") { + $ea3->set_text("floppy"); + $module_choices = "floppy"; + } + else { + $ea3->set_text($ea3->get_text() . " floppy") + if $ea3->get_text() !~ /\s*floppy\s*/; + $module_choices = $ea3->get_text(); + } + } + else { + $module_choices = "floppy"; + } + + @modules = split(/\s+/, $module_choices); + + } + + info(1, "Modules: @modules\n"); + + + # Figure out modules path. + if ( @modules ) { + foreach my $module (@modules) { + finddepth sub { if ( $File::Find::name =~ m,/$module\.o$, ) { + push(@modules_found,$File::Find::name); + } }, + "$modules_directory/$kernel_version"; + + } + } + + $, = " "; + info(1,"Modules found:\n@modules_found\n"); + $, = ""; + + return @modules_found; + + +} # end sub kernel_modules + + +sub initrd_size { + + info(0,"Boot Method: 2 disk\n", + "Type: initrd boot disk with LILO/root filesystem disk\n"); + + my ($linuxrc_size) = @_; + my ($what,$lib); + my ($path,$value); + info(0, "Checking size needed for initrd\n"); + + # the size of the loop device should be at least 1.63% larger than what + # it will contain (i.e. 8192 inode), but to keep on the safe size it will + # be 2.00% larger. + + # Unforturnately, stat is being done on + # the actual live fs, whereas the loop filesystem may be different. In + # general the check is quite conservative and will always leave room. + # Stat seems to view things differently based on the situation, and + # -s file has another opinion, for now stat will be used and perhaps + # the actual filesystem in the future. Better extra room than too little. + + # 9 dirs = 1024 each (increase if modified) + # {ash,gzip,mount,umount} (required executables) + # bzip2 if $compress eq bzip2 (optional) + # 1 for ld.so.cache + + # change dir size if needed + my $dir_size = 9 + 1; + my $initrd_size = $dir_size + $linuxrc_size; + + # clean initrd_mnt if any garbage is found. + if (-d "$tmp/initrd_mnt") { + sys("rm -rf $tmp/initrd_mnt"); + } + if (!-d "$tmp/initrd_mnt") { + return if errmk(sys("mkdir $tmp/initrd_mnt")) == 2; + } + + # modules - see CVS:1.65 for previous non-size check. + my @modules = kernel_modules(); + if (@modules) { + + my $tool; + + # dirs sizes, just assuming 1024 + my $ds = mkpath("$tmp/initrd_mnt/lib/modules/$kernel_version"); + $initrd_size = $initrd_size + ($ds - 1); + + # copy over the modules + foreach my $stuff (@modules) { + ($path,$value) = stripper($stuff,"mod"); + + $value == 0 ? ($tool = "cp -a") : ($tool = "mv"); + if (!$path) { + info(1,"gBootRoot Error: Couldn't find $stuff\n"); + } + + # copy stuff to proper directory and unlink size tester + return if + errcp(sys("$tool $path $tmp/initrd_mnt/lib/modules/$kernel_version")) == 2; + unlink($path) if $value == 1; + } + + # Do the depmod operation + + if ($entry_advanced[13] && $entry_advanced[13] ne "") { + + if ( $> == 0 ) { + + return if err_custom("depmod -ae -F $entry_advanced[13] -b $tmp/initrd_mnt $kernel_version", "gBootRoot: ERROR: depmod failed") == 2; + + } + else { + + return if err_custom("depmod -aer -F $entry_advanced[13] -b $tmp/initrd_mnt $kernel_version", "gBootRoot: ERROR: depmod failed") == 2; + + + } + + } # $entry_advanced[13] defined + + else { + + if ( $> == 0 ) { + + return if err_custom("depmod -ae -b $tmp/initrd_mnt $kernel_version", "gBootRoot: ERROR: depmod failed") == 2; + + } + else { + + return if err_custom("depmod -aer -b $tmp/initrd_mnt $kernel_version", "gBootRoot: ERROR: depmod failed") == 2; + + } + + } + + + # Check all the files in the dirctory for their size, and unlink them. + opendir(DIR,"$tmp/initrd_mnt/lib/modules/$kernel_version") + or info(1,"Failed to open $tmp/initrd_mnt/$kernel_version"); + my @module_stuff = grep { /\w+/ } readdir(DIR); + close(DIR); + + # Figure out the size for all the stuff created by depmod and the + # modules included. + foreach my $stuff (@module_stuff) { + $initrd_size = $initrd_size + + ((stat("$tmp/initrd_mnt/lib/modules/$kernel_version/$stuff"))[12]/2); + unlink("$tmp/initrd_mnt/lib/modules/$kernel_version/$stuff"); + } + + + # The modules directory has to be removed here. + return if + errrm(sys("rmdir $tmp/initrd_mnt/lib/modules/$kernel_version")) == 2; + return if + errrm(sys("rmdir $tmp/initrd_mnt/lib/modules")) == 2; + return if + errrm(sys("rmdir $tmp/initrd_mnt/lib/")) == 2; + + + } # end if (@modules) + + + # This and libs should be user accessible + # add other executables here + my @initrd_stuff; + if (@modules) { + @initrd_stuff = qw(ash gzip mount umount modprobe insmod); + } + else { + @initrd_stuff = qw(ash gzip mount umount); + } + + foreach (@initrd_stuff) { + if ( !readlink($_) ) { + ($path,$value) = stripper(find_file_in_path($_),"bin"); + $initrd_size = $initrd_size + ((stat($path))[12]/2); + unlink($path) if $value == 1; + } + else { + $initrd_size = $initrd_size + + length(readlink(find_file_in_path($_))); + } + } + + if ($compress eq "bzip2" && -e find_file_in_path($compress)) { + ($path,$value) = stripper(find_file_in_path($compress),"bin"); + $initrd_size = $initrd_size + ((stat($path))[12]/2); + unlink($path) if $value == 1; + } + + my $lib_tester; + if ($bz2_toggle->active && -x find_file_in_path("bzip2") ) { + + $lib_tester = find_file_in_path("bzip2"); + + } + else { + + $lib_tester = find_file_in_path("init"); + + } + + my $dir; + + # lib sizes This is going to be improved later with library_dependencies + open(L,"ldd $lib_tester|") or die "Oops, no init could be found :)\n"; # safe to use ldd + while () { + my $place; + ($lib,$place) = (split(/=>/,$_))[0,1]; + $place = (split(" ",$place))[0]; + $lib =~ s/\s+//; + $lib = basename($lib); + $lib =~ s/\s+$//; + $dir = dirname($place); + + open (SL,"ls -l $dir/$lib|") or die "humm: $!\n"; + while () { + # symbolic link + if (-l "$dir/$lib") { + $what = (split(/\s+/,$_))[10]; + $initrd_size = $initrd_size + 1; + ($path,$value) = stripper("$dir/$lib","lib"); + $initrd_size = $initrd_size + ((stat($path))[12]/2); + unlink($path) if $value == 1; + } + # no symbolic link + else { + ($path,$value) = stripper("$dir/$lib","lib"); + $initrd_size = $initrd_size + ((stat($path))[12]/2); + unlink($path) if $value == 1; + } + } + } + + $initrd_size = $initrd_size + ($initrd_size * 0.02); + + # For perfection 1 (rounded up) is o.k., but for safety 10 would be + # better + $initrd_size = sprintf("%.f",$initrd_size) + 10; + return $initrd_size; + +} # end sub initrd_size + +sub pb { + + # Will have to count by hand + if ($_[0] eq "initrd") { + $pbar->configure( 10, 0, 10 ); + } + elsif ($_[0] eq "boot") { + $pbar->configure( 10, 0, 10 ); + } + elsif ($_[0] eq "filesystem") { + $pbar->configure($_[2], 0, $_[2]); + } + + $pbar->set_value($_[1]); + # Found this at Gnome .. + # http://www.uk.gnome.org/mailing-lists/archives/gtk-list/ + # 1999-October/0401.shtml + # Also, http://www.gtk.org/faq/ 5.14 + while (Gtk->events_pending) { Gtk->main_iteration; } + +} + +sub initrd { + + my($kernel,$root_image,$device,$size) = @_; + my($lib,$what,$path,$value,$tool); + my $I = "initrd"; + + # Basically this means the ARS was never opened or edited and the + # default behavior is to use the same device. + if ( !$entry_advanced[3] ) { + $device = $container[BOOT_DEVICE]; + } + else { + $device = $entry_advanced[3]; + } + + + my $fs_type = (split(/\s/,$main::makefs))[0]; + + if ( $fs_type eq "genext2fs" ) { + # Assuming busybox is being used, so bzip2 should still be standard + # just another link .. just for testing. + if ( $compress eq "bzip2" ) { + $compress = "bunzip2"; + } + } + + my $broot_image = basename($root_image); + open(LC, ">$tmp/linuxrc") or die "Couldn't write linuxrc to loop device\n"; + print LC initrd_heredoc($broot_image,$device); close(LC); + pb($I,1); + my $size_needed = initrd_size((stat("$tmp/linuxrc"))[12]/2); + unlink("$tmp/linuxrc"); + + + if ( $fs_type ne "genext2fs" ) { + + info(0, "Using loop device to make initrd\n"); + info(0, "Make sure you have loop device capability" . + " in your running kernel\n"); + sys("dd if=/dev/zero of=$tmp/$initrd bs=1024 count=$size_needed"); + pb($I,2); + # no need to enter y every time .. could use -F + my $error; + open(T,"|mke2fs -F -m0 -i8192 $tmp/$initrd >/dev/null 2>&1") or + ($error = error("Can not make ext2 filesystem on initrd.\n")); + return "ERROR" if $error && $error eq "ERROR"; + print T "y\n"; close(T); + pb($I,3); + info(0, "Mounting initrd in $tmp/initrd_mnt\n"); + + } + + # clean initrd_mnt if any garbage is found. + if (-d "$tmp/initrd_mnt") { + sys("rm -rf $tmp/initrd_mnt"); + } + if (!-d "$tmp/initrd_mnt") { + return if errmk(sys("mkdir $tmp/initrd_mnt")) == 2; + } + + + # Here the loop device is made on tmp, not mnt + if ( $fs_type eq "genext2fs" ) { + info(0, "Using genext2fs to make initrd rather than a loop device\n"); + } + + else { + if ( $> == 0 ) { + return if errm(sys("mount -o loop -t ext2 $tmp/$initrd $tmp/initrd_mnt")) == 2; + } + else { + return if errm(sys("mount $tmp/initrd_mnt")) == 2; + } + } + pb($I,4); + + info(0, "Putting everything together\n"); + if ( $fs_type eq "genext2fs" ) { + open(LC, ">$tmp/initrd_mnt/linuxrc") or die "Couldn't write linuxrc to $tmp/initrd_mnt\n"; + } + else { + open(LC, ">$tmp/initrd_mnt/linuxrc") or die "Couldn't write linuxrc to loop device\n"; + } + print LC initrd_heredoc($broot_image,$device); close(LC); + # I could test this but somebody's system may do permissions differently + sys("chmod 755 $tmp/initrd_mnt/linuxrc"); + if ($fs_type ne "genext2fs" ) { + sys("rmdir $tmp/initrd_mnt/lost+found"); + } + pb($I,5); + + info(0, "... the dirs\n"); + return if errmk( + sys("mkdir $tmp/initrd_mnt/{bin,dev,etc,lib,mnt,proc,sbin,usr}")) == 2; + return if errmk(sys("mkdir $tmp/initrd_mnt/usr/lib")) == 2; + pb($I,6); + + # Hopefully, this works, but have never tested it - o.k I did + if ( $fs_type ne "genext2fs" ) { + if ($container[BOOT_DEVICE] !~ m,/dev/fd\d{1}$,) { + return if err(sys("cp -a $container[BOOT_DEVICE] $mnt/dev")) == 2; + } + } + + # DEVICES SECTION + my @devices; + my $device_table = "$tmp/initrd_device_table.txt"; + if ( $fs_type eq "genext2fs" ) { + + info(0, "Making $device_table for genext2fs\n"); + my $error; + unlink( $device_table ) if -e $device_table; + + # + # /dev is always needs to be made automatically + open(BootRoot::Yard::DEVICE_TABLE, ">$device_table") or + ($error = error("$device_table: $!")); + return "ERROR"if $error && $error eq "ERROR"; + + print BootRoot::Yard::DEVICE_TABLE + "# \t\t\t\t\t\t" . + "\t\t\t\n"; + print BootRoot::Yard::DEVICE_TABLE "/dev\t\td\t0755\t-\t-\t-\t-\t-\t-\t-\n"; + + # Keep a record of the devices required + @devices = qw(/dev/console dev/null /dev/ram0 /dev/ram1 /dev/tty0); + for ( split(" ", $container[BOOT_DEVICE] ) ) { + push(@devices, $_ ) if $_; + } + + device_table( @devices ); + close(BootRoot::Yard::DEVICE_TABLE); + + } + + else { + + if ( $> == 0 ) { + info(0, "Copying over devices to $tmp/initrd_mnt/dev\n"); + return if errcp( + sys("cp -a /dev/{console,null,ram0,ram1,tty0} $tmp/initrd_mnt/dev") + ) == 2; + return if errcp( + sys("cp -a $container[BOOT_DEVICE] $tmp/initrd_mnt/dev")) == 2; + } + else { + info(0, "Mknod devices at $tmp/initrd_mnt/dev\n"); + # This could be replaced by a devfs. + sys("$main::sudo mknod c 5 1 $tmp/initrd_mnt/dev/console"); + sys("$main::sudo mknod c 1 3 $tmp/initrd_mnt/dev/null"); + sys("$main::sudo mknod b 1 0 $tmp/initrd_mnt/dev/ram0"); + sys("$main::sudo mknod b 1 1 $tmp/initrd_mnt/dev/ram1"); + sys("$main::sudo mknod c 4 0 $tmp/initrd_mnt/dev/tty0"); + sys("$main::sudo mknod b 2 0 $tmp/initrd_mnt/dev/fd0"); + } + + } # end DEVICES SECTION + + pb($I,7); + + # This and libs should be user accessible + info(0, ".. the modules\n"); + my @modules = kernel_modules(); + + if (@modules) { + + mkpath("$tmp/initrd_mnt/lib/modules/$kernel_version"); + + foreach my $stuff (@modules) { + ($path,$value) = stripper($stuff,"mod"); + $value == 0 ? ($tool = "cp -a") : ($tool = "mv"); + if (!$path) { + info(1,"gBootRoot Error: Couldn't find $stuff\n"); + } + return if + errcp(sys("$tool $path $tmp/initrd_mnt/lib/modules/$kernel_version")) == 2; + } + + if ($entry_advanced[13] && $entry_advanced[13] ne "") { + + if ( $> == 0 ) { + + info(1, "depmod -ae -F $entry_advanced[13] -b $tmp/initrd_mnt/lib/modules/$kernel_version $kernel_version\n"); + return if err_custom("depmod -ae -F $entry_advanced[13] -b $tmp/initrd_mnt $kernel_version", "gBootRoot: ERROR: depmod failed") == 2; + + } + else { + + info(1, "depmod -aer -F $entry_advanced[13] -b $tmp/initrd_mnt/lib/modules/$kernel_version $kernel_version\n"); + return if err_custom("depmod -aer -F $entry_advanced[13] -b $tmp/initrd_mnt $kernel_version", "gBootRoot: ERROR: depmod failed") == 2; + + } + + } # $entry_advanced[13] defined + else { + + if ( $> == 0 ) { + + info(1, "depmod -ae -b $tmp/initrd_mnt/lib/modules/$kernel_version $kernel_version\n"); + return if err_custom("depmod -ae -b $tmp/initrd_mnt $kernel_version", "gBootRoot: ERROR: depmod failed") == 2; + + } + else { + + info(1, "depmod -aer -b $tmp/initrd_mnt/lib/modules/$kernel_version $kernel_version\n"); + return if err_custom("depmod -aer -b $tmp/initrd_mnt $kernel_version", "gBootRoot: ERROR: depmod failed") == 2; + + } + + } + + } + + info(0, ".. the bins\n"); + my @initrd_stuff; + if (@modules) { + @initrd_stuff = qw(ash gzip mount umount modprobe insmod); + } + else { + @initrd_stuff = qw(ash gzip mount umount); + } + + # Will put the stuff in sbin because the is where the kernel looks for + # modprobe. + if ( ! $busybox ) { + + foreach (@initrd_stuff) { + ($path,$value) = stripper(find_file_in_path($_),"bin"); + $value == 0 ? ($tool = "cp -a") : ($tool = "mv"); + if (!$path) { + info(1,"gBootRoot Error: Couldn't find $_\n"); + } + return if errcp(sys("$tool $path $tmp/initrd_mnt/sbin")) == 2; + } + + if ($compress eq "bzip2" && -e find_file_in_path($compress)) { + ($path,$value) = stripper(find_file_in_path($compress),"bin"); + $value == 0 ? ($tool = "cp -a") : ($tool = "mv"); + return if errcp(sys("$tool $path $tmp/initrd_mnt/sbin")) == 2; + } + + # Testing if init is sufficient for grabbing the correct libraries for the + # executables immediately above. This could be modified to test a + # list of executables. Now bzip2 uses libbz2.so.1.0, so if bzip2 is + # present on the system this will be the tester instead, and size + # has to be figured out differently. + info(0, ".. the libs\n"); + + my $lib_tester; + if ($bz2_toggle->active && -x find_file_in_path("bzip2") ) { + + $lib_tester = find_file_in_path("bzip2"); + + } + else { + + $lib_tester = find_file_in_path("init"); + + } + + my $dir; + + open(L,"ldd $lib_tester|") or die "Oops, no $lib_tester could be found :)\n"; # safe to use ldd, this is going to be fixed later with library_dependencies + while () { + my $place; + ($lib,$place) = (split(/=>/,$_))[0,1]; + $place = (split(" ",$place))[0]; + $lib =~ s/\s+//; + $lib = basename($lib); + $lib =~ s/\s+$//; + $dir = dirname($place); + info(0,"$dir/$lib\n"); + open (SL,"ls -l $dir/$lib|") or die "humm: $!\n"; + while () { + # symbolic link + if (-l "$dir/$lib") { + $what = (split(/\s+/,$_))[10]; + ($path,$value) = stripper("$dir/$lib","lib"); + $value == 0 ? ($tool = "cp -a") : ($tool = "mv"); + return if errcp(sys("$tool $path $tmp/initrd_mnt$dir")) == 2; + ($path,$value) = stripper("$dir/$what","lib"); + $value == 0 ? ($tool = "cp -a") : ($tool = "mv"); + return if errcp(sys("$tool $path $tmp/initrd_mnt$dir")) == 2; + } + # no symbolic link + else { + ($path,$value) = stripper("$dir/$lib","lib"); + return if errcp(sys("cp -a $path $tmp/initrd_mnt$dir")) == 2; + } + } + } + + } # not busybox + + else { + + my $error; + + # busybox binary + $tool = "cp -a"; + $path = "/home/mttrader/busybox/busybox/busybox"; + return if errcp(sys("$tool $path $tmp/initrd_mnt/sbin")) == 2; + + #Currently defined functions: + # [, ash, bunzip2, busybox, echo, false, gzip, insmod, modprobe, + # mount, sh, test, true, umount + + my $target = "$tmp/initrd_mnt/sbin/busybox"; + my @busystuff = qw(ash sh bunzip2 echo gzip insmod modprobe mount + umount); + chdir("$tmp/initrd_mnt/sbin/"); + foreach ( @busystuff ) { + + symlink("busybox", "$tmp/initrd_mnt/sbin/$_" ); + + } + + # uClibc + mkpath("$tmp/initrd_mnt/usr/i386-linux-uclibc/lib"); + $path = "/usr/i386-linux-uclibc/lib/libuClibc-0.9.5.so"; + return if errcp(sys("$tool $path $tmp/initrd_mnt/usr/i386-linux-uclibc/lib")) == 2; + sys("chmod 755 $tmp/initrd_mnt/usr/i386-linux-uclibc/lib/libuClibc-0.9.5.so"); + chdir("$tmp/initrd_mnt/lib"); + symlink("../usr/i386-linux-uclibc/lib/libuClibc-0.9.5.so", "$tmp/initrd_mnt/lib/libc.so.0" ); + + $path = "/usr/i386-linux-uclibc/lib/ld-uClibc-0.9.5.so"; + return if errcp(sys("$tool $path $tmp/initrd_mnt/usr/i386-linux-uclibc/lib")) == 2; + sys("chmod 755 $tmp/initrd_mnt/usr/i386-linux-uclibc/lib/ld-uClibc-0.9.5.so"); + chdir("$tmp/initrd_mnt/usr/i386-linux-uclibc/lib"); + symlink("ld-uClibc-0.9.5.so", "$tmp/initrd_mnt/usr/i386-linux-uclibc/lib/ld-uClibc.so.0" ); + + } + + + info(0, "Determine run-time link bindings\n"); + # Has a return code of 0 regardless + # Also, produces false alarms even when it is working. + info(1, "Ignore warnings about missing directories\n"); + sys("ldconfig -v -r $tmp/initrd_mnt"); + + + if ( $fs_type eq "genext2fs" ) { + info(0, "Using genext2fs to contruct the initrd\n"); + # The -D option is unique to the newest unreleased version of + # genextfs modified by BusyBox maintainer Erick Andersen + # August 20, 2001. + + my $error; + + # genext2fs doesn't make accurate sized filesystems. + # this will be user adjustable in the future. + $size_needed = $size_needed + 1000; + + if ( + sys("/usr/lib/bootroot/$main::makefs -b $size_needed -d $tmp/initrd_mnt -D $device_table $tmp/$initrd") !~ + /^0$/ ) { + $error = error("Cannot $fs_type filesystem.\n"); + return "ERROR" if $error && $error eq "ERROR"; + } + + } + + else { + chdir($pwd); + info(0, "Umounting loop device, and compressing initrd\n"); + return if errum(sys("umount $tmp/initrd_mnt")) == 2; + } + + info(0, "Compressing initrd\n"); + sys("gzip -f9 $tmp/$initrd"); + + pb($I,10); # This takes the longest. + + $initrd = $initrd . ".gz"; + +} # end sub initrd + +# This was submitted by Cristian "cretzu." +sub gdkbirdaao { + + # Guess Default Kernel Boot Image Root Device And Append Options + #(gdbirdaao) + # + # We return a list with 3 elements: + # + # root device, kernel boot image path and append options + # + # The last list element (append options) could be returned as a list + # of options, but it probably might be cleaner if the caller splitted it. + # + # this should cover the following cases: + # + # 1. we have a 'root=...' somewhere above the 'image=...' block(s), and + # the image block may or may not have a root specified + # + # 2. there is no default label, in which case, we take the first one + # + # 3. there is a default label, and that's what we pick up + # + + my $ret_image_path = ''; + my $ret_root_dev = ''; + my $ret_append = ''; + + + # enough of the annoying "perhaps you are not root" + # ofcourse this test is always ran assuming lilo is used. + if ( $> == 0 ) { + + if ( !$container[METHOD] || + $container[METHOD] eq "2 disk compression" ) { + + if (-e $lilo_conf and !-d $lilo_conf) { + + my @lilo_lines; + open(LIL, $lilo_conf) or + warn "*** $lilo_conf not found\n"; + @lilo_lines = ; + close(LIL); + chomp(@lilo_lines); + + my $default_label = ''; + my %image_blocks; + my $image_block_name_prefix = 'ImageBlock'; + my $image_block_no = 1; + my $image_block_name = ''; + my $root_dev = ''; + + for (@lilo_lines) { + # ignore comment lines + next if m/^\s*[#]/; + + # cleanup whitespace + s/\s*//; + s/\s*$//; + s/\s*=\s*/=/; + + # 'default=whatever' returns just a label + if (m/default=(.+)\s*/) { + $default_label = $1; + } + # start of a new 'image=' + # image block or similar + elsif (m/(image|other)=(.+)\s*/) { + $image_block_name = + sprintf("%s%02d", + $image_block_name_prefix, + $image_block_no); + $image_blocks{$image_block_name} + {'kernel_image_path'} = $2; + $image_blocks{$image_block_name} + {'root_device'} = $root_dev; + $image_block_no += 1; + } + # image block label + elsif (m/label=(.+)\s*/) { + $image_blocks{$image_block_name} + {'block_label'} = $1; + } + # 'root=' + elsif (m#root=/dev/(.+)\s*#) { + # inside an image block + if ($image_block_name and + defined($image_blocks + {$image_block_name} + {'root_device'})) { + $image_blocks{$image_block_name} + {'root_device'} = $1; + } + # loose + else { + $root_dev = $1 if !$root_dev; + } + } + elsif (m#append=\"(.+)\"#) { + $image_blocks{$image_block_name} + {'append'} = $1; + } + else { + # Ignore everything else + } + } + + # we'll now find the kernel image and root device + foreach $image_block_name (sort keys %image_blocks) { + # Assume there's no specified default label; + # take the first + $ret_root_dev = + $image_blocks{$image_block_name}{'root_device'} + if !$ret_root_dev; + $ret_image_path = + $image_blocks{$image_block_name} + {'kernel_image_path'} + if !$ret_image_path; + $ret_append = + $image_blocks{$image_block_name}{'append'} + if !$ret_append; + + # do we have a default kernel? + if (defined $image_blocks{$image_block_name} + {'block_label'}) { + if ($image_blocks{$image_block_name} + {'block_label'} eq $default_label) { + # Found the block match for the default label + $ret_root_dev = + $image_blocks{$image_block_name} + {'root_device'}; + $ret_image_path = + $image_blocks{$image_block_name} + {'kernel_image_path'}; + $ret_append = $image_blocks + {$image_block_name}{'append'}; + last; + } + } + } + } + + + } # if METHOD eq 2 disk compression + + } # if not root + + # and some a small portion of paranoia + $ret_root_dev = 'hda1' if !$ret_root_dev; + + return ($ret_root_dev, $ret_image_path, $ret_append); + +} # end sub gdkbirdaao + +########### +# Mtab area +########### + +sub mtab_window { +# Will just use a dialog box. + my ($dialog,$error,$count,$pattern) = @_; + + if (not defined $mtab) { + $mtab = Gtk::Dialog->new(); + $mtab->signal_connect("destroy", \&destroy_window, \$mtab); + $mtab->signal_connect("delete_event", \&destroy_window, \$mtab); + $mtab->set_title("gBootRoot: Device check"); + $mtab->border_width(15); + $mtab->set_position('center'); + my $label = Gtk::Label->new($dialog); + $label->set_justify( 'left' ); + $label->set_pattern("_________") if $pattern == 9; + $label->set_pattern("_____") if $pattern == 5; + $mtab->vbox->pack_start( $label, $true, $true, 15 ); + $label->show(); + my $button = Gtk::Button->new("OK"); + $button->signal_connect("clicked", \&mtab_check, $count); + $button->can_default(1); + $mtab->action_area->pack_start($button, $false, $false,0); + $button->grab_default; + $button->show; + $button = Gtk::Button->new("Cancel"); + $button->signal_connect("clicked", sub { destroy $mtab; + $mtab = 2 if $count == 3; } ); + $mtab->action_area->pack_start($button, $false, $false,0); + $button->show; + } + if (!visible $mtab) { + show $mtab; + } + else { + destroy $mtab; + mtab_window($dialog,$error,$count) if $error == 0; + } + +} # end sub mtab_window + +sub mtab{ + +# /proc/mount could be used, but maybe there is no /proc +# Press OK when drive and storage medium are ready. The drive should not +# be mounted. + + if ($_[0] == 0) { + my $dialog = "BOOTDISK:\n" + ."Press OK when the drive and its storage medium is ready.\n" + ."The Boot Disk will now be made. All data already on\n" + ."the storage medium will be erased."; + mtab_window($dialog,1,$_[0],9); + } + elsif ($_[0] == 1) { + my $dialog = "ROOTDISK:\n" + ."Press OK when the drive and its storage medium is ready.\n" + ."The Root Disk will now be made. All data already on\n" + ."the storage medium will be erased."; + mtab_window($dialog,1,$_[0],9); + } + elsif ( $_[0] == 3 ) { + my $dialog = "LILO:\n" + ."Lilo will now be executed. In order for the bootloader\n" + ."to work properly you need superuser privileges to run lilo.\n" + ."See FAQ for ways to accomplish this. Even if you don't have\n" + ."privileges, the program will continue to make a boot disk.\n" + ."Lilo may be ran as root at a later time on the boot disk."; + mtab_window($dialog,3,$_[0],5); + } + + +} # end sub mtab + + +sub mtab_check { + + my($widget,$count) = @_; + + my $dialog; + my $error = 1; + + my $fs_type = (split(/\s/,$main::makefs))[0]; + +# Check to see if $device is mounted + + if ( $count < 3 ) { + open (MTAB, "/etc/mtab") or die "no mtab!\n"; + while () { + + if ($count == 1) { + + # ROOT_DEVICE + if ( m,$entry_advanced[3], ) { + # Safety Check: + $dialog = + "Please umount the device first.\nPress OK when you are ready."; + $error = 0; + } + + } + + elsif ( $count == 0 ) { + + # BOOT_DEVICE + if (m,$entry_advanced[0],) { + # Safety Check: + $dialog = + "Please umount the device first.\nPress OK when you are ready."; + $error = 0; + } + + } + + } + close(MTAB); + + } + + mtab_window($dialog,$error,$count) if $error == 0; + + # Make sure the drive and storage medium are accessible + # Keep asking until they are. + if ( $error == 1 && $fs_type ne "genext2fs" ) { + destroy $mtab; + + # $size has to be determined by boot disk or root disk + + # ROOT_DEVICE - test with a loop device + if ($count == 1) { + sys("mke2fs -F -m0 -i8192 $entry_advanced[3] $root_device_size"); + } + + + # BOOT_DEVICE + elsif ($count == 0) { + sys("mke2fs -F -m0 -i8192 $entry_advanced[0] $container[SIZE]"); + } + + if ($? != 0) { + $dialog = "gBootRoot: ERROR: You need to insert a disk\n"; + mtab_window($dialog,$error,$count); + return; + } + + # ROOT_DEVICE + if ($count == 1) { + if ( $> == 0 ) { + return if errm(sys("mount -t ext2 $entry_advanced[3] $mnt")) == 2; + } + else { + return if errm(sys("mount $mnt")) == 2; + } + } + + # BOOT_DEVICE + elsif ($count == 0) { + if ( $> == 0 ) { + return if errm(sys("mount -t ext2 $entry_advanced[0] $mnt")) == 2; + } + else { + return if errm(sys("mount $mnt")) == 2; + } + } + + + lilo_put_it_together() if $count == 0; # mtab(1) runs from here + device2() if $count == 1; + + } # if $error == 1 + + if ( $fs_type eq "genext2fs" && $error == 1 ) { + + destroy $mtab; + lilo_put_it_together() if $count == 0; # mtab(1) runs from here + device2() if $count == 1; + + } + + # Warned the user about something + if ( $error == 3 ) { + $mtab->destroy; + } + + +} # end sub mtab_check + +################## +# Here Doc Section +################## + +# This should be user accessible +# This should be called linuxrc. +sub initrd_heredoc { + + my($broot_image,$root_device) = @_; + +# Here's where the initrd is put together using a loop device +# HEREDOC +my $initrd_exec = << "INITRD"; +#!/sbin/ash + +export PATH=/bin:/sbin:/usr/bin: + +echo Preparing to setup ramdisk. + +# Before busybox experimentation this was the state of things: +# mount -o remount,rw / 2>/dev/null +# echo Mounting proc... +# mount -t proc none /proc + +echo Mounting proc... +mount -t proc none /proc + +echo Mounting $root_device readable-writable +mount -o remount,rw $root_device / + +echo -n 'Please insert the root floppy, and press [Enter]: ' +read ENTER + +echo Mounting $root_device readonly ... + +# -t causes busybox to fail here, -o doesn't help much either. +#mount -o ro -t ext2 $root_device /mnt +mount $root_device /mnt + +echo -n Copying new root to ramdisk .. please wait ... +$compress -cd /mnt/$broot_image > /dev/ram1 +echo done. + +echo -n Unmounting $root_device ... +umount /mnt +echo done. + +# Using change_root, eventually may change to pivot_root or +# give the user the choice. + +echo Changing to the new root. +echo 257 >/proc/sys/kernel/real-root-dev + +echo -n Unmounting proc ... +umount /proc +echo done. + +echo Continuing normal boot procedure from ramdisk. +INITRD + + return $initrd_exec; + +} # end sub initrd_heredoc + +sub brlilo { + + my ($device) = @_; + $entry_advanced[2] ? $entry_advanced[2] = $entry_advanced[2] + : $entry_advanced[2] = $container[ABS_APPEND]; + +# HEREDOC +my $brlilo = << "LILOCONF"; +boot = $device +message = message +delay = 50 +vga = normal +install = /boot/boot.b +map = /boot/map +backup = /dev/null +compact + +# bootdisk +image = kernel +append = "load_ramdisk=1 debug $entry_advanced[2]" +initrd = $initrd +root = $device +label = bootdisk +read-write + +# normalboot +image = kernel +append = "$entry_advanced[2]" +root = /dev/$norm_root_device +label = normalboot +read-only +LILOCONF + + return $brlilo; + +} # end sub brlilo + + +sub brlilo_non_root { + + my ($device) = @_; + $entry_advanced[2] ? $entry_advanced[2] = $entry_advanced[2] + : $entry_advanced[2] = $container[ABS_APPEND]; + +# HEREDOC +my $brlilo = << "LILOCONF"; +boot = $device +message = $old_mount/message +delay = 50 +vga = normal +install = $old_mount/boot/boot.b +map = $old_mount/boot/map +backup = /dev/null +compact + +# bootdisk +image = $old_mount/kernel +append = "load_ramdisk=1 debug $entry_advanced[2]" +initrd = $old_mount/$initrd +root = $device +label = bootdisk +read-write + +# normalboot +#image = kernel +#append = "$entry_advanced[2]" +#root = /dev/$norm_root_device +#label = normalboot +#read-only +LILOCONF + + return $brlilo; + +} # end sub brlilo_non_root + + +sub message { +# HEREDOC +my $message = << "MESSAGE"; + +gBootRoot $version $date GNU GPL +mailto: Jonathan Rosenbaum + +Press [Ctrl] to see the lilo prompt. + +Press [Tab] to see a list of boot options. + +bootdisk = This will boot a compressed root filesystem + on another floppy. +normalboot = This will boot up a specified filesystem. + default: /dev/$norm_root_device + Use root=/dev/(h or s)dXX + h = IDE Drive + s = SCSI Drive + +Trouble: Do not forget boot: option single +Fix a filesystem: e2fsck /dev/(h or s)dXX +Bad superblock: e2fsck -b 8192 /dev/(h or s)dXX + +MESSAGE + + return $message; + +} # end sub message + +sub help { + +<< "HELP"; + +gBootRoot $version $date GNU GPL + +Email contact -> Jonathan Rosenbaum + +Homepage -> http://gbootroot.sourceforge.net +Submit a Bug -> http://sourceforge.net/bugs/?group_id=9513 +Devel. & Releases -> http://sourceforge.net/projects/gbootroot + +Places to talk: + +gbootroot-{devel,user} mailing lists -> http://sourceforge.net/mail/?group_id=9513 +Help forum -> http://sourceforge.net/forum/forum.php?forum_id=29639 +Open forum -> http://sourceforge.net/forum/forum.php?forum_id=29638 + +gbootroot documentation and FAQ: + +/usr/share/doc/gbootroot/html/index.html + +How to Use gBootRoot: + +The most important button to familiarize yourself with is the Submit button +which starts the whole process; dialogs are presented as the process +continues asking you if you want to continue "OK" or stop "Cancel". + +The first row presently has only one Boot Method choice: "2 disk compression." +Clicking on the menu on the right selects the Boot Method. + +The second row allows you to select the kernel for the Boot/Root set. You +may either use the file selector button on the right hand side, or you may +type in the location on the left hand side. + +The third row allows you to select the compressed filesystem you are +providing, using either of the two ways mentioned before. You may use a +pre-made root filesystem or you may create one using one of the Methods +provided in the Advanced Root Section. + +The fourth row allows you to select the device you want to use. The default +device is the first floppy disk (/dev/fd0). + +The fifth row allows you to choose the size of the device being used. The +default size of 1440 assumes you are using a floppy drive (Note: You may want +to experiment with 1722 which works fine with many floppy drives.), but can +be used with other sized devices like tape drives. Click on the +appropriate radio button to choose either gzip or bzip2 compression if the +program doesn't automatically detect it. + +The slider bar on the right allows the output of the verbosity box to be +changed from the highest (2) to the lowest setting (1) or to be turned off (0) +or on again. At times it may be advantageous to turn off the verbosity box +since large quantities of output to this box may cause gbootroot to use too +much cpu power; however, output may still be found in the text file "verbose" +in /tmp/gbootroot_tmp'time-date'. + +Advanced Boot Section: + +Libraries & Binaries & Modules check boxes: Turn off and on the +stripping of symbols. The stripping behavior for libraries may be +changed by clicking on the right mouse button to change --strip-debug +to --strip-all. Binaries default to --strip-all and Modules default to +--strip-debug. + +"Devel Device" If the device used for development is different than the +actual boot device, use this field to indicate that device. You will have to +run lilo -v -C brlilo.conf -r "device mount point" manually at a later time +on the actual boot device. + +"Opt. Device" Add devices to the boot disk which are necessary for the +kernel to function properly. Put a space between each device. For instance, +/dev/fb0 for frame buffer devices. + +"append =" Add append options to brlilo.conf. If you are using a frame +buffer device you could add something like video=matrox:vesa:402,depth:16. + +"Kernel Module" Add the modules found in /lib/modules/kernel-version +which are necessary for the Boot Method to work properly. If these +modules aren't found in the modules directory it is assumed that they +either are in the kernel or they do not exist. In the case of 2 disk +compression, floppy needs to be included in the kernel or included as a +module. Kmod inserts the modules, and kmod needs to be built into the +kernel along with initrd and ramdisk." + +"Kernel Version" Override the kernel version number found in the +kernel header. This will change the /lib/modules/kernel-version +directory. + +System.map: When a non-running kernel is chosen it is important to +include a copy of that kernel's System.map file so that depmod can +use the correct set of kernel symbols to resolve kernel references +in each module. This can be found in the kernel's source code after +compilation. + +Advanced Root Section: + +"Root Device" This is the device used for the root filesystem when +constructing the Boot/Root set. You may choose a device which is different +than the Boot device, but presently only floppy devices are supported. + +"Root Device Size" The size of the actual media used for the Root Device. + +"Root Filename" The name give to the root filesystem when initially made +in the temporary creation location. The save button allows the creation to +be saved in the permanent default location when the Accept button is pressed. + +"Filesystem Size" Root Methods make the filesystem the size which is +specified here. + +"Compression" Off by default to allow user-mode-linux testing. Turn on +compression when you are ready to use a Boot Method which requires compression. + +"Method" The root filesystem creation method. + +"Template" The template associated with a Root Method. Not all Root Methods +have templates. + +"Generate" This puts the chosen Root Method in action. + +"UML" Abbreviation for user-mode-linux. This is a linux kernel which runs on +top of the host system's linux kernel and allows a you run a live root +filesystem. + +"Accept" This accepts the created root filesystem if it is found in the +temporary creation directory. The UML box and the main section will now +reflect the path to this root filesystem. You can now test with the UML +button or a put together a complete Boot/Root set with the Submit button. + +Advanced Kernel Section: + +Still in development. + + +Little things you may want to know: + +* gBootRoot requires ash for initrd. Ash is a feather weight version of Bash. + +HELP + +} + +1; diff --git a/gbootroot b/gbootroot index bb32cb8..51e93f4 100755 --- a/gbootroot +++ b/gbootroot @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/perl; # gBootRoot Copyright (C) 2000, 2001 # @@ -88,39 +88,6 @@ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# For distributions that don't adhere to the most recent FHS. -BEGIN { - - my $fhs = grep(/\/usr\/share\/perl5/,@INC); - - if ($fhs == 0) { - unshift(@INC,"/usr/share/perl5"); - } - - - my $sbin = grep(/\/sbin/,$ENV{'PATH'}); - if ($sbin == 0) { - $ENV{'PATH'} = "/sbin:" . $ENV{'PATH'}; - } - - $sbin = grep(/\/usr\/sbin/,$ENV{'PATH'}); - if ($sbin == 0) { - $ENV{'PATH'} = "/usr/sbin:" . $ENV{'PATH'}; - } - -} - -use Gtk; -use strict; -use BootRoot::Yard; -use BootRoot::YardBox; -use BootRoot::Error; -use File::Basename; -use File::Find; -use File::Path; -init Gtk; -set_locale Gtk; - # Perhaps you are wondering where to learn how to program with Gtk-Perl? # There is an excellent tutorial by Stephen Wilhelm at # http://personal.riverusers.com/~swilhelm/perlgtk/. Please @@ -129,142 +96,12 @@ set_locale Gtk; # Gtk-Perl. A good reference can be found at # http://projects.prosa.it/gtkperl/reference.html -# If you want gBootRoot to do it's stuff somewhere else, change the -# value for $tmp1. -my $tmp1 = "/tmp"; # tmp should be default - Cristian -my $lilo_conf = "/etc/lilo.conf"; -my $home = "$ENV{HOME}/.gbootroot"; -my $uml_xterm = "xterm -e"; -$main::editor = "emacs --font 6x13"; -$main::makefs = "mke2fs -F -m0 -i8192"; # Root Disk -$main::sudo = "sudo"; - # CHANGES # 1.3.0 - 12/07/2001 # * Moved Changes to a /usr/share/doc/gbootroot/Changes # from this version onwards. # ####################################################################### -# Don't edit from here, but you can if you want to change the HERE docs -# and/or the contents of initrd (in which case you need to make sure the -# right libraries are copied over to initrd and the size is checked). - -# I need to remember to edit this -# and to update scripts/Debian.yard if -# make_debian has been changed. -my $version = "1.3.0"; -my $date = "12.12.2001"; -my $gtk_perl_version = "0.7002"; -my $pwd = `pwd`; chomp $pwd; -my $home_rootfs = "$home/root_filesystem/"; -my $home_uml_kernel = "$home/uml_kernel/"; -my $modules_directory = "/lib/modules"; -if ( $> != 0 && -e "/usr/lib/bootroot/genext2fs" ) { - $main::makefs = "genext2fs -z -r0"; # -i8192 not a good idea -} -# This is for experimental stuff .. basically so I can test -# the boot fs as a normal user, since it's hard to create a boot disk -# with enough room using genext2fs. -my $busybox; - - -# Yard Stuff -my $home_yard = "$home/yard"; -my $template_dir = "$home_yard/templates/"; -my $home_yard_replacements = "$home_yard/Replacements"; -$main::global_yard = $home_yard; -$main::oldroot = "/OLDROOT"; -my $global_yard_replacements_arch_indep = - "/usr/share/gbootroot/yard/Replacements"; -my $global_yard_replacements_arch_dep = "/usr/lib/bootroot/yard/Replacements"; -my $global_yard_templates = "/usr/share/gbootroot/yard/templates"; -$ENV{'PATH'} = "$home_yard:" . $ENV{'PATH'}; - - -my $initrd; -my $compress; -my $false = 0; -my $true = 1; - -# Helps determine what procedure to follow for the Boot Disk -my $ok; - -my $box2; -my $label; -my $label_advanced; -my $separator; -my $order; -my $text_window; -my $verbosity_window; - -# Make @container verbose, also look in generate() -my @container; -use constant METHOD => 0 ; -use constant KERNEL => 1 ; -use constant ROOT_FS => 2 ; -use constant BOOT_DEVICE => 3 ; -use constant SIZE => 4 ; -use constant COMPRESS => 5 ; -use constant LIB_STRIP => 6 ; -use constant BIN_STRIP => 7 ; -use constant OBJCOPY_BOOL => 8 ; -use constant ABS_DEVICE => 9 ; -use constant ABS_OPT_DEVICE => 10 ; -use constant ABS_APPEND => 11 ; - -# The Selection values are used for button_fileselect_advanced -# since it shares fileselect and file_ok_sel with button. -# -# ABS: 12=Root_Device_Selection 13=UML_Kernel_Selection -# UML BOX: 14=Root_Fs_Selection -# -use constant MOD_STRIP => 15 ; -# -# ABS: 16=System.map_Selection - -my @original_container; -my $file_dialog; - -my $mtab; -# $old_mount is used for a little swapping magic when a normal user -# is using genext2fs and lilo. -my ($tmp, $mnt, $old_mount); -my $norm_root_device; -my ($hbox_advanced); -my $separator_advanced; - -my @entry_advanced; -my ($ea1,$ea2,$ea3,$ea4,$ea5,$ea6); # entry advanced boot -my ($ear1,$ear2,$ear3,$ear4); # entry advanced root -my ($eab1,$eab2,$eab3); # entry advanced uml -my $uml_window; -my $table_advanced; -my $table_advanced_root; -my ($spinner_advanced,$spinner_size); -my $button_count = 0; -my $button_count_root = 0; -my $obj_count = 0; -my $obj_count_root = 0; -my ($lib_strip_check,$bin_strip_check,$mod_strip_check); -my ($bz2_toggle,$gz_toggle); -my ($bz2_toggle_root,$gz_toggle_root,$compression_off); -#my ($main::combo); made this totally global -my ($adj2,$adj3); -my @strings; - -# Value set by kernel_modules -my $kernel_version; - -# $entry_advanced[3] is the Root Device -# $filesystem_size and root_device_size are important globals for ARS, -# there weren't put into entry_advanced because they are spin buttons. -# $entry_advanced[4] is the Root Filename -# -my ($filesystem_size, $root_device_size); -# -# Carrries ARS values to other modules via ars(), another program just has to -# export ars and it can capture these values -my $ars = {}; # anonymous hash # How the Boot/Root set is constructed for the 2 disk compression method: # @@ -292,161 +129,6 @@ my $ars = {}; # anonymous hash #10. The filesystem for the Root device is made, and then device2 is called # to copy over the root filesystem. -# My own creation - the roots touch the ground if three lines are added. - my @xpm_data = ( -"32 45 3 1", -" c None", -". c SaddleBrown", -"X c black", -" ... ... ", -" ... ... ", -" ... ... ", -" ... ... ", -" ... ... ", -" ... ... ", -" ... ... ", -" ... ... ", -" ... ... ", -" ... .. ", -" ... ... ", -" ... ... ", -" .... ... ", -" .... ... ", -" .... ... ", -" .... ............. ", -" ..... ............. ", -" ...... ............. ", -" ....... ...", -"......... ..", -"................................", -"................................", -"............................... ", -"......... XXXXX ............ ", -"........ XXX .......... ", -"........ XXX ........ ", -" XXXXXX ", -" XXX XXX X XX XX ", -" X XXXXX X X X ", -" XX XXX X XX ", -" X XX X X ", -" X XX X XX X ", -" XX XX X XXXXX ", -" X XXXX XXX XXXXX X ", -" XX XX XX X XX ", -" X X X X X ", -" X XX X XX X ", -" X XX XX X ", -" X XX XXXXXXX XXX ", -" XX XX XXX ", -" XX XX XXXX XX XX ", -" XX XXX X XXXXXXX X ", -" X XXX X XX ", -" XX XXXXXXX XXX ", -" X XX X ", -" X X " - ); - -$SIG{INT} = \&signal; -$SIG{ABRT} = \&signal; -$SIG{TERM} = \&signal; -$SIG{QUIT} = \&signal; -$SIG{KILL} = \&signal; - -(undef,$container[KERNEL],$container[ABS_APPEND]) = gdkbirdaao(); - - -my ($sec,$min,$hour,$day,$month,$year) = (localtime)[0,1,2,3,4,5]; -my $time = sprintf("%02d:%02d:%02d-%02d-%02d-%04d", - $hour, $min, $sec, $month+1, $day, $year+1900); - -# Here's where stuff gets intersting, non-root users can create root_fs, -# which is great for UML, and a boot disk. - -if ( $> == 0 ) { - - if (!-d "$tmp1/gbootroot_tmp$time") { - $tmp = "$tmp1/gbootroot_tmp$time" if err_custom_perl( - "mkdir $tmp1/gbootroot_tmp$time", - "gBootRoot: ERROR: Could not make temporary directory") != 2; - } - if (!-d "$tmp1/gbootroot_mnt$time") { - $mnt = "$tmp1/gbootroot_mnt$time" if err_custom_perl( - "mkdir $tmp1/gbootroot_mnt$time", - "gBootRoot: ERROR: Could not make mount directory") != 2; - } - - # Why? - $tmp = "$tmp1/gbootroot_tmp$time"; - -} -else { - - # The Administrator just needs to add a line like the one below to the - # fstab for each non-root user who wants to be able to create root_fs. - # In this example, `id -u` has to be the actual effective numeric user - # id, and the root_fs has to always be named root_fs when it is being - # made, but it can be renamed afterwards. - # - # /tmp/gboot_non_root_`id -u`/root_fs \ - # /tmp/gboot_non_root_`id -u`/loopback \ - # auto defaults,noauto,user,loop 0 0 - # - # For the boot/root disks the administrator will have to give the user - # special su privileges (mknod) to make special devices. The $main::sudo - # variable can be set to sudo or super, fakeroot won't work. - # These include: /dev/{console,null,ram0,ram1,tty0} - # These two lines need to be added to create the boot_fs and the boot/root - # disk. In this example the user is locked into using one type of device - # for the boot/root - # - # /tmp/gboot_non_root_`id -u`/initrd_image \ - # /tmp/gboot_non_root_'id -u1`/initrd_mnt \ - # auto defaults,noauto,user,loop 0 0 - # - # - # For genext2fs this is the only line required, this is so that lilo can - # run. - # - # /dev/fd0 /tmp/gboot_not_root_mnt_`id -u` auto defaults,noauto,user 0 0 - - - my $user = $>; - - if (!-d "$tmp1/gboot_non_root_$user") { - $tmp = "$tmp1/gboot_non_root_$user" if err_custom_perl( - "mkdir $tmp1/gboot_non_root_$user", - "gBootRoot: ERROR: Could not make temporary directory") != 2; - } - $tmp = "$tmp1/gboot_non_root_$user"; - - if (!-d "$tmp1/gboot_non_root_mnt_$user") { - $mnt = "$tmp1/gboot_non_root_mnt_$user" if err_custom_perl( - "mkdir $tmp1/gboot_non_root_mnt_$user", - "gBootRoot: ERROR: Could not make mount directory") != 2; - } - $mnt = "$tmp1/gboot_non_root_mnt_$user"; - -} - - -# Verbosity is universal for all methods, and controlled by a scale slider. -# Yard -# 0 --> only the important messages. -# 1 --> all messages. -my $verbosity = 1; # info & sys use this as Global - -## One hard copy log file is saved for the session, and the user can also -## save from the verbosity box including saving a selection. - -my $verbosefn = "$tmp/verbose"; # All verbosity -#my $verbosefn = "/tmp/verbose"; # Yard - always logged, but 0&1 = STDOUT - -# Need this before everything. -Gtk::Rc->parse("/etc/gbootroot/gbootrootrc"); - -verbosity_box(); -start_logging_output($verbosefn,$verbosity); # Yard "tmp dir name" - # "verbosity level" # While on the subject of error output: # @@ -503,3928 +185,17 @@ start_logging_output($verbosefn,$verbosity); # Yard "tmp dir name" # the command "mkdir." If mkdir is the command mkdir("directory",0755) is # called. -#------------------------------- -# USER DIRECTORIES -# /tmp -home_builder($tmp1); - -# $HOME/.gbootroot/root_filesystem -home_builder($home_rootfs); - -# $HOME/.gbootroot/uml_kernel -home_builder($home_uml_kernel); -symlink_builder("/usr/bin/linux","$home_uml_kernel/linux"); -if (!-e "$home_uml_kernel/.options") { - open(OPTIONS,">$home_uml_kernel/.options") - or die "Couldn't write $home_uml_kernel/.options at $?\n"; - print OPTIONS "root=/dev/ubd0 mem=16M\n"; - close(OPTIONS); -} - -# $HOME/.gbootroot/yard/templates -home_builder($template_dir); -if ( -d $global_yard_templates ) { - opendir(DIR,$global_yard_templates) if -d $template_dir; - # I decided this may be too restrictive, besides, everything - # is kept in its own directory. - #my @templates = grep { m,\.yard$, } readdir(DIR); - my @templates = grep { m,^\w+, } readdir(DIR); - closedir(DIR); - foreach ( @templates ) { - if (!-e "$template_dir/$_" && !-l "$template_dir/$_") { - symlink_builder("$global_yard_templates/$_","$template_dir/$_"); - } - } -} - -# Arch indep replacements repository -# $HOME/.gbootroot/yard/Replacements -home_builder($home_yard_replacements); -if ( -d $global_yard_replacements_arch_indep ) { - if (-d $home_yard_replacements) { - find sub { ( my $replacement = - $File::Find::name ) =~ s/$global_yard_replacements_arch_indep\///; - if (!-e "$home_yard_replacements/$replacement") { - - #system "cp -a $File::Find::name $home_yard_replacements/$replacement > /dev/null 2>&1"; - system "mkdir $home_yard_replacements/$replacement > /dev/null 2>&1" if -d $File::Find::name; - symlink_builder( $File::Find::name,"$home_yard_replacements/$replacement") if !-d $File::Find::name; - } - - }, $global_yard_replacements_arch_indep; - - - } -} - -# Arch dep replacements repository -if ( -d $global_yard_replacements_arch_dep ) { - if (-d $home_yard_replacements) { - find sub { ( my $replacement = - $File::Find::name ) =~ s/$global_yard_replacements_arch_dep\///; - if (!-e "$home_yard_replacements/$replacement") { - - #system "cp -a $File::Find::name $home_yard_replacements/$replacement > /dev/null 2>&1"; - system "mkdir $home_yard_replacements/$replacement > /dev/null 2>&1" if -d $File::Find::name; - symlink_builder( $File::Find::name,"$home_yard_replacements/$replacement") if !-d $File::Find::name; - } - - }, $global_yard_replacements_arch_dep; - - - } -} - - -# Basically so different users get the same things in -# their personal directories. -sub symlink_builder { +# Here's the program: - my ($oldfile,$newfile) = @_; - - - if (!-e $newfile && !-l $newfile) { - my $error; - symlink($oldfile,$newfile) or - ($error = error("Can not make symlink to $oldfile - from $newfile.\n")); - } - -} - -sub home_builder { - - my ($home_builder) = @_; - - if (!-d $home_builder) { - if (-e $home_builder) { - error_window( - "gBootRoot: ERROR: A file exists where $home_builder should be"); - } - else { - my @directory_parts = split(m,/,,$home_builder); - my $placement = "/"; - for (1 .. $#directory_parts) { - $_ == 1 ? ($placement = "/$directory_parts[$_]") - : ($placement = $placement . "/" . $directory_parts[$_]); - -d $placement or err_custom_perl( - "mkdir $placement","gBootRoot: ERROR: Could not make $home_builder"); - } - } - } - -} # end home_builder -#------------------------------- - -# Gtk::check_version expects different arguments than .7004 so will have -# to check for the version instead. -# Right now >= 0.7002 is o.k. -#if (Gtk::check_version(undef,"1","0","7") =~ /too old/) { - -if (Gtk->major_version < 1) { - et(); -} -elsif (Gtk->micro_version < 7) { - et(); -} -elsif (Gtk->minor_version < 2) { - et(); -} - -sub et { - error_window("gBootRoot is presently being developed with gtk-perl" . - " version $gtk_perl_version.\nYou are using a" . - " version of gtk-perl < $gtk_perl_version." . - " You may still be able\n" . - " to use this program, but you may encounter problems." . - " See the FAQ\nfor places to get a newer gtk-perl version." . - " \n\nThe most common error reported:\n\"Can't locate" . - " object method\""); - #,"center"); - print "Using a version of gtk-perl < $gtk_perl_version\n"; -} - -my $window = Gtk::Window->new("toplevel"); -# special policy -$window->set_policy( $false, $true, $true ); -$window->set_title("gBootRoot"); -$window->set_position('none'); -$window->signal_connect("destroy", - sub { - unlink "$verbosefn", "$tmp/initrd_image.gz"; - rmdir "$tmp/initrd_mnt"; - rmdir "$tmp"; - rmdir "$mnt"; - Gtk->exit(0); - }); -$window->border_width(1); -$window->realize; - -# Do the iconizing thing -# "xpm/circles.xpm" can be @pixmap within file if not create_from_xpm. -my ($circles,$mask) = Gtk::Gdk::Pixmap->create_from_xpm_d($window->window, - $window->style->white, - @xpm_data); -$window->window->set_icon(undef, $circles, $mask); -$window->window->set_icon_name("gBootRoot"); -# Zas - bug in gtk-perl < .7002 -$window->window->set_decorations(['all', 'menu']); -$window->window->set_functions(['all', 'resize']); - -my $tooltips = Gtk::Tooltips->new(); - -my $box1 = Gtk::VBox->new($false,0); -$window->add($box1); -$box1->show(); - -# First row -hbox(); -my $entry = entry($false,0); - -# Menu - later this may be improved if new methods are added. -my $opt = Gtk::OptionMenu->new(); -$tooltips->set_tip( $opt, "Choose the Boot method.", "" ); -my $menu = Gtk::Menu->new(); -my $item = Gtk::MenuItem->new("2 disk compression" ); -$item->show(); -# Eventually get_menu, or something totally different will be used. -$item->signal_connect( 'activate', - sub { $entry->set_text("2 disk compression"); - $container[METHOD] = "2 disk compression"; - two_disk_compression_check(); - kernel_modules(); }); -$menu->append( $item ); -$opt->set_menu( $menu ); -$box2->pack_start( $opt, $true, $true, 0 ); -$opt->show(); -$box2->show(); - -# Second row -# Get to look three places for kernel value -# default ( null|gdkkbirdaao) && entry() && fileselect->file_ok_sel -hbox(); -my $entry2 = entry($true,1); -$entry2->set_text($container[KERNEL]); -if ($container[KERNEL]) { - $ars->{kernel} = $container[KERNEL]; - ars($ars); - ars2($ars); -} -button("Kernel Selection",$entry2,"Kernel Selection",1); - -# Third row -hbox(); -my $entry3 = entry($true,2); -button("Root Filesystem",$entry3,"Root Filesystem",2,$home_rootfs); - -# In the future, if experimenters send in data, there will be two -# different devices. -# Fourth row -hbox(); -my $entry4 = entry($true,3); -$container[BOOT_DEVICE] = "/dev/fd0"; -$entry4->set_text($container[BOOT_DEVICE]); -button("Device Selection",$entry4,"Device Selection",3,"/dev/fd0"); - -# Fifth row -hbox("what"); -my $adj = Gtk::Adjustment->new( 1440.0, 0.0, 360000000.0, 282.0, 360.0, 0.0 ); -my $spinner = Gtk::SpinButton->new( $adj, 0, 0 ); -$tooltips->set_tip( $spinner, "Choose the Device Size.\n" . -"Hint: Many 1440 floppy drives support 1722.\n", "" ); -$spinner->set_wrap( $true ); -$spinner->set_numeric( $true ); -$spinner->set_shadow_type( 'in' ); -$spinner->show(); -$container[SIZE] = 1440; # A better value - a rtbt trick. -$adj->signal_connect( "value_changed", sub { - $container[SIZE] = $spinner->get_value_as_int(); - $adj2->set_value($container[SIZE]) if defined $adj2;}); -$box2->pack_start( $spinner, $true, $true, 0 ); -#label("Device Size"); - -# gz and bz2 radio buttons -my $rbutton = Gtk::RadioButton->new( "gz" ); -$tooltips->set_tip( $rbutton, "Choose Compression used on the Filesystem.", "" ); -$gz_toggle = $rbutton; -$rbutton->set_active( $true ); -$box2->pack_start( $rbutton, $false, $false, 0 ); -$rbutton->show(); -$rbutton = Gtk::RadioButton->new( "bz2", $rbutton ); -$rbutton->set_usize(1,1); -$tooltips->set_tip( $rbutton, "Choose Compression used on the Filesystem.", "" ); -$bz2_toggle = $rbutton; -$box2->pack_start( $rbutton, $true, $true, 0); -$rbutton->show(); - -# Verbosity adjustment -my $adj1 = Gtk::Adjustment->new( 2.0, 0.0, 2.0, 0.0, 1.0, 0.0 ); -my $verbosity_scale = Gtk::HScale->new($adj1); -$verbosity_scale->set_value_pos("right"); -$verbosity_scale->set_digits(0); -$tooltips->set_tip( $verbosity_scale, "Adjust the Verbosity Level.", "" ); -$verbosity_scale->show(); -# Verbosity Box can be turned on/off here -$adj1->signal_connect( "value_changed", sub { - $verbosity = $verbosity_scale->get_adjustment->value - 1; - verbosity($verbosity); - - if ($verbosity == -1) { - if ($verbosity_window) { - destroy $verbosity_window if visible $verbosity_window; - } - } - elsif (!$verbosity_window) { - close(LOGFILE); - verbosity_box(); - start_logging_output($verbosefn,$verbosity); - } - - } ); -$box2->pack_start( $verbosity_scale, $false, $false, 0); - -#start_logging_output($yard_temp,$verbosity); - -# Size status entry -my $entry5 = Gtk::Entry->new(); -$entry5->set_editable( $false ); -$tooltips->set_tip( $entry5, "This shows room remaining on the Device.", "" ); -$entry5->set_usize(20,20); -$box2->pack_start( $entry5, $true, $true, 0 ); -$entry5->show(); - - -my $button_advanced; -########################### -# The ADVANCED BOOT SECTION -########################### -# Separator -$separator = Gtk::HSeparator->new(); -$box1->pack_start( $separator, $false, $true, 0 ); -$separator->show(); - -# This is cool how this works. -my $vbox_advanced = Gtk::VBox->new($false,0); -$box1->add($vbox_advanced); -$vbox_advanced->show(); - -# The Advanced Boot Section button -hbox_advanced($vbox_advanced); -$button_advanced = Gtk::Button->new("Advanced Boot Section"); -$tooltips->set_tip( $button_advanced, - "Change settings for the Boot Disk Image.", "" ); -$button_advanced->signal_connect("clicked",\&advanced_boot_section ); -$hbox_advanced->pack_start( $button_advanced, $true, $true, 0 ); -$button_advanced->show(); - -########################### -# The ADVANCED ROOT SECTION -########################### -my $vbox_advanced_root = Gtk::VBox->new($false,0); -$box1->add($vbox_advanced_root); -$vbox_advanced_root->show(); - -hbox_advanced($vbox_advanced_root); -$button_advanced = Gtk::Button->new("Advanced Root Section"); -$tooltips->set_tip( $button_advanced, - "Generate a Root Filesystem and/or use a different Root Device.", "" ); -$button_advanced->signal_connect("clicked",\&advanced_root_section ); -$hbox_advanced->pack_start( $button_advanced, $true, $true, 0 ); -$button_advanced->show(); -########################### - -############################# -# The ADVANCED KERNEL SECTION -############################# -my $vbox_advanced_kernel = Gtk::VBox->new($false,0); -$box1->add($vbox_advanced_kernel); -$vbox_advanced_kernel->show(); - -hbox_advanced($vbox_advanced_kernel); -$button_advanced = Gtk::Button->new("Advanced Kernel Section"); -$tooltips->set_tip( $button_advanced, - "Retrieve/Make Kernel Sources.", "" ); -#$button_advanced->signal_connect("clicked",\&advanced_root_section ); -$hbox_advanced->pack_start( $button_advanced, $true, $true, 0 ); -$button_advanced->show(); -############################# - - - -# Separator -$separator = Gtk::HSeparator->new(); -$box1->pack_start( $separator, $false, $true, 0 ); -$separator->show(); - -# Status bar -my $align = Gtk::Alignment->new( 0.5, 0.5, 0, 0 ); -$box1->pack_start( $align, $false, $false, 5); -$align->show(); -my $pbar = Gtk::ProgressBar->new(); -$pbar->set_usize(321,10); # 321 10 -$align->add($pbar); -$pbar->show(); - -# Separator -$separator = Gtk::HSeparator->new(); -$box1->pack_start( $separator, $false, $true, 0 ); -$separator->show(); - -# Submit button -hbox(); -my $sbutton = Gtk::Button->new("Submit"); -$sbutton->signal_connect( "clicked", \&submit); -$tooltips->set_tip( $sbutton, "Generate the Boot/Root set.", "" ); -$sbutton->show(); -$box2->pack_start( $sbutton, $true, $true, 0 ); -$box2->show(); +use Gtk; +use strict; +use BootRoot::BootRoot; +init Gtk; +set_locale Gtk; -# Close button -my $cbutton = Gtk::Button->new("Close"); -$cbutton->signal_connect("clicked", - sub { - unlink "$verbosefn", "$tmp/initrd_image", - "$tmp/initrd_image.gz"; - system "umount $tmp/initrd_mnt > /dev/null 2>&1"; - rmdir "$tmp/initrd_mnt"; - rmdir "$tmp"; - rmdir "$mnt"; - Gtk->exit(0); - }); -$tooltips->set_tip( $cbutton, "Exit gBootRoot.", "" ); -$cbutton->show(); -$box2->pack_start( $cbutton, $true, $true, 0 ); -$box2->show(); +start(); -# Help button -my $hbutton = Gtk::Button->new("Help"); -$hbutton->signal_connect( "clicked", sub { create_text("help") }); -$tooltips->set_tip( $hbutton, "Help about gBootRoot.", "" ); -$hbutton->show(); -$box2->pack_start( $hbutton, $true, $true, 0 ); -$box2->show(); -$window->show(); main Gtk; -exit( 0 ); - -#---------------------------- - -# This works on GNU/Linux -sub signal { - - unlink "$verbosefn", "$tmp/initrd_image.gz"; - system "umount $tmp/initrd_mnt > /dev/null 2>&1"; - rmdir "$tmp/initrd_mnt"; - rmdir "$tmp"; - rmdir "$mnt"; - - $SIG{INT} = \&signal; - $SIG{ABRT} = \&signal; - $SIG{TERM} = \&signal; - $SIG{QUIT} = \&signal; - $SIG{KILL} = \&signal; - - - Gtk->exit(0); -} - -sub hbox_advanced { - $hbox_advanced = Gtk::HBox->new(1,1 ); - $hbox_advanced->border_width( 2 ); # was 10 - $hbox_advanced->set_usize(321, 20); - $_[0]->pack_start( $hbox_advanced, $false, $false, 0 ); - show $hbox_advanced; -} - -sub objcopy_right_click_advanced { - - my ( @data ) = @_; - my $event = pop( @data ); - - if ( ( defined( $event->{'type'} ) ) - and ( $event->{'type'} eq 'button_press' ) ) { - if ( $event->{'button'} == 3 ) { - if (defined $lib_strip_check) { - if ($obj_count == 0) { - $tooltips->set_tip( $lib_strip_check, - "This is generally a good idea." . - " Press the right mouse button to" . - " change from [objcopy --strip-all]" . - " to [objcopy --strip-debug].", "" ); - $obj_count++; - } - else { - $tooltips->set_tip( $lib_strip_check, - "This is generally a good idea." . - " Press the right mouse button to" . - " change from [objcopy --strip-debug]". - " to [objcopy --strip-all].", "" ); - $obj_count--; - } - } - } - } - -} # end obj_right_click_advanced - -sub advanced_boot_section { - - if ($button_count == 0) { - #$vbox_advanced->set_usize(321,300); - my $boolean; - - # The table section - $table_advanced = Gtk::Table->new( 7, 3, $true ); - $vbox_advanced->pack_start( $table_advanced, $true, $true, 0 ); - $table_advanced->show(); - - #_______________________________________ - # lib_strip_check - #label_advanced("Stripping:",0,1,0,1,$table_advanced); - !defined $lib_strip_check ? ($boolean = 1) - : ($boolean = $lib_strip_check->get_active()); - $lib_strip_check = Gtk::CheckButton->new("Libraries"); - $lib_strip_check->set_active($boolean); - $lib_strip_check->signal_connect( "button_press_event", - \&objcopy_right_click_advanced); - $tooltips->set_tip( $lib_strip_check, - "This is generally a good idea. Press the" . - " right mouse button to change from" . - " [objcopy --strip-debug] to" . - " [objcopy --strip-all].", "" ); - $table_advanced->attach($lib_strip_check,0,1,0,1, - ['expand'],['fill','shrink'],0,0); - show $lib_strip_check; - - # bin_strip_check - !defined $bin_strip_check ? ($boolean = 1) - : ($boolean = $bin_strip_check->get_active()); - $bin_strip_check = Gtk::CheckButton->new("Binaries"); - $bin_strip_check->set_active($boolean); - $tooltips->set_tip( $bin_strip_check, - "This is generally a good idea." . - " [objcopy --strip-all]", "" ); - $table_advanced->attach($bin_strip_check,1,2,0,1, - ['expand'],['fill','shrink'],0,0); - show $bin_strip_check; - - - # mod_strip_check - !defined $mod_strip_check ? ($boolean = 1) - : ($boolean = $mod_strip_check->get_active()); - $mod_strip_check = Gtk::CheckButton->new("Modules"); - $mod_strip_check->set_active($boolean); - $tooltips->set_tip( $mod_strip_check, - "This is generally a good idea." . - " [objcopy --strip-debug]", "" ); - $table_advanced->attach($mod_strip_check,2,3,0,1, - ['expand'],['fill','shrink'],0,0); - show $mod_strip_check; - - - #_______________________________________ - # Development Drive - label_advanced("Devel Device:",0,1,1,2,$table_advanced); - $ea1 = entry_advanced(1,2,1,2,0,$table_advanced); - $tooltips->set_tip( $ea1, "If the device used for development" . - " is different than the actual boot" . - " device, use this field" . - " to indicate that device." . - " You will have to run" . - " lilo -v -C brlilo.conf -r" . - " \"device mount point\" manually at a" . - " later time on the actual" . - " boot device.", - "" ); - $ea1->set_text($container[BOOT_DEVICE]) if defined $container[BOOT_DEVICE]; - - #_______________________________________ - # Optional Device(s) - label_advanced("Opt. Device(s)",0,1,2,3,$table_advanced); - $ea2 = entry_advanced(1,3,2,3,1,$table_advanced); - $tooltips->set_tip( $ea2, "Add devices to the boot disk which are" . - " necessary for the kernel to function" . - " properly. Put a space between each" . - " device. For instance, /dev/fb0 for" . - " frame buffer devices.", - ""); - $ea2->set_text($entry_advanced[1]) if defined $entry_advanced[1]; - - - #_______________________________________ - # Kernel Module(s) - label_advanced("Kernel Module(s)",0,1,4,5,$table_advanced); - $ea3 = entry_advanced(1,3,4,5,11,$table_advanced); - $tooltips->set_tip( $ea3, "Add the modules found in" . - " /lib/modules/kernel-version which are" . - " necessary for the Boot Method to work" . - " properly. Kmod inserts the modules," . - " and kmod needs to be built into the" . - " kernel along with initrd and ramdisk." , - ""); - $ea3->set_text($entry_advanced[11]) if defined $entry_advanced[11]; - - #_______________________________________ - # Append Options - label_advanced("append =",0,1,3,4,$table_advanced); - $ea4 = entry_advanced(1,3,3,4,2,$table_advanced); - my $append; (undef,undef,$append) = gdkbirdaao(); - $tooltips->set_tip( $ea4, "Add append options to brlilo.conf.", ""); - # this will only show append if real - if (!defined $entry_advanced[2]) { - $ea4->set_text($append) if $append; - } - else { - $ea4->set_text($entry_advanced[2]) if $entry_advanced[2]; - } - - #_______________________________________ - # Kernel Version - label_advanced("Kernel Version:",0,1,5,6,$table_advanced); - $ea5 = entry_advanced(1,2,5,6,12,$table_advanced); - - $tooltips->set_tip( $ea5, "Override the kernel version number found" . - " in the kernel header. This will change" . - " the /lib/modules/kernel-version directory", - ""); - $ea5->set_text($entry_advanced[12]) if defined $entry_advanced[12]; - - - #_______________________________________ - # System.map - label_advanced("System.map:",0,1,6,7,$table_advanced); - $ea6 = entry_advanced(1,2,6,7,13,$table_advanced); - $tooltips->set_tip( $ea6, "When a non-running kernel is chosen it is " . - " important to include a copy of that" . - " kernel's System.map file so that depmod" . - " can use the correct set of kernel symbols" . - " to resolve kernel references in each" . - " module. This can be found in the" . - " kernel's source code after compilation.", - ""); - $ea6->set_text($entry_advanced[13]) if defined $entry_advanced[13]; - button_fileselect_advanced(2,3,6,7,"Selection",$ea6,"Selection",16, - $table_advanced,"/lib/modules/"); - - $button_count++; - } - else { - destroy $table_advanced; - $button_count--; - } - -} # end sub advanced_boot_section - - - -sub advanced_root_section { - - if ($button_count_root == 0) { - my $boolean; - - - $table_advanced_root = Gtk::Table->new( 9, 3, $true ); - # temp solution? - #$table_advanced_root->set_row_spacings( 3 ); - $vbox_advanced_root->pack_start( $table_advanced_root, $true, - $true, 0 ); - #_______________________________________ - # Root Device selection - # $::device $device already exist - label_advanced("Root Device:",0,1,0,1,$table_advanced_root); - # $_[4] shares with advanced_boot_sections @entry_advanced - $ear1 = entry_advanced(1,2,0,1,3,$table_advanced_root); - if ($entry_advanced[3]) { - $ear1->set_text($entry_advanced[3]); - } - else { - $ear1->set_text($container[BOOT_DEVICE]); - } - $tooltips->set_tip( $ear1, - "Type in the location of the Root Device to use.", - "" ); - # $order is important because it is put in $container[$order] - button_fileselect_advanced(2,3,0,1,"Selection",$ear1,"Selection",12, - $table_advanced_root,"/dev/fd0"); - - #_______________________________________ - # Root Device Size - # gBootRoot methods - label_advanced("Root Device Size:",0,1,1,2,$table_advanced_root); - $adj2 = Gtk::Adjustment->new( 1440.0, 0.0, 360000000.0, 282.0, - 360.0, 0.0 ); - $spinner_advanced = Gtk::SpinButton->new( $adj2, 0, 0 ); - $table_advanced_root->attach($spinner_advanced,1,2,1,2, - ['shrink','fill','expand'],['fill','shrink'], - 0,0); - $tooltips->set_tip( $spinner_advanced, - "Choose the Root Device Size.", - "" ); - $spinner_advanced->set_wrap( $true ); - $spinner_advanced->set_numeric( $true ); - $spinner_advanced->set_shadow_type( 'in' ); - $spinner_advanced->show(); - $root_device_size = 1440 if !$root_device_size; - $adj2->signal_connect( "value_changed", sub { - $root_device_size = $spinner_advanced->get_value_as_int();}); - # For some reason $container[SIZE] is tranforming into [3] when - # device selection is changed. & in ABS devel device doesn't keep - # state. - if ($root_device_size) { - $spinner_advanced->set_value($root_device_size); - } - else { - $adj2->set_value($container[SIZE]) if defined $adj2; - } - - - #_______________________________________ - # Root File Name - # gBootRoot methods - label_advanced("Root Filename:",0,1,2,3,$table_advanced_root); - $ear2 = entry_advanced(1,2,2,3,4,$table_advanced_root); - $ear2->set_text("root_fs") if !$entry_advanced[4]; - $ars->{filename} = "root_fs" if !$entry_advanced[4]; - $ear2->set_text($entry_advanced[4]) if $entry_advanced[4]; - $ars->{filename} = $entry_advanced[4] if $entry_advanced[4]; - ars($ars); - $tooltips->set_tip( $ear2, "Give the Root Filesystem file a name.", - "" ); - my $ear2_save = Gtk::CheckButton->new("save"); - $ear2_save->set_active($true); - -# "Save Root File. Press right button to change" . -# " the Directory the file is saved in.", - $tooltips->set_tip( $ear2_save, - "Saves the Root Filesystem in your" . - " $ENV{HOME}/.gbootroot/root_filesystem" . - " directory.", - "" ); - $table_advanced_root->attach($ear2_save,2,3,2,3, - ['expand'],['fill','shrink'],0,0); - show $ear2_save; - - - #_______________________________________ - # Filesystem Size - # $::fs_device - label_advanced("Filesystem Size:",0,1,3,4,$table_advanced_root); - $adj3 = Gtk::Adjustment->new( 4096.0, 0.0, 1000000000.0, 128.0, - 1024.0, 0.0 ); - $spinner_size = Gtk::SpinButton->new( $adj3, 0, 0 ); - $table_advanced_root->attach($spinner_size,1,2,3,4, - ['shrink','fill','expand'],['fill','shrink'], - 0,0); - $tooltips->set_tip( $spinner_size, - "Choose the Filesystem Size.", - "" ); - $spinner_size->set_wrap( $true ); - $spinner_size->set_numeric( $true ); - $spinner_size->set_shadow_type( 'in' ); - $spinner_size->show(); - $filesystem_size = 4096 if !$filesystem_size; - $ars->{filesystem_size} = $filesystem_size; - ars($ars); - $adj3->signal_connect( "value_changed", sub { - $filesystem_size = $spinner_size->get_value_as_int(); - $ars->{filesystem_size} = $filesystem_size; - ars($ars); - }); - $spinner_size->set_value($filesystem_size) if $filesystem_size; - - #_______________________________________ - # Compression - # gBootRoot methods - - - my $hbox_between = Gtk::HBox->new(0,1); - $table_advanced_root->attach($hbox_between,0,3,4,5, - ['fill'], - ['fill','shrink'],15,0 ); - $hbox_between->show; - - # label - my $label_compression = Gtk::Label->new( "Compression:" ); - $label_compression->set_justify( "right" ); - $hbox_between->pack_start( $label_compression, $false, $false, 0 ); - $label_compression->show(); - - # gz - $rbutton = Gtk::RadioButton->new( "gz" ); - $tooltips->set_tip( $rbutton, - "Choose Compression used on the Filesystem.", "" ); - $gz_toggle_root = $rbutton; - $rbutton->set_active( $true ); - $hbox_between->pack_start( $rbutton, $true, $false, 0 ); - $rbutton->show(); - - # bz2 - $rbutton = Gtk::RadioButton->new( "bz2", $rbutton ); - $tooltips->set_tip( $rbutton, - "Choose Compression used on the Filesystem.", "" ); - $bz2_toggle_root = $rbutton; - $hbox_between->pack_start( $rbutton, $true, $false, 0 ); - $rbutton->show(); - - # compression off - $compression_off = Gtk::CheckButton->new( "off"); - $tooltips->set_tip( $compression_off, - "Turn Compression off.", "" ); - $hbox_between->pack_start( $compression_off, $true, $false, 0 ); - $compression_off->set_active($true); - $compression_off->show(); - - #_______________________________________ - # UML Kernel - label_advanced("UML Kernel:",0,1,5,6,$table_advanced_root); - # $_[4] shares with advanced_boot_sections @entry_advanced - $ear3 = entry_advanced(1,2,5,6,5,$table_advanced_root); - $ear3->set_text("$home_uml_kernel" . "linux"); - $tooltips->set_tip( $ear3, - "If you have a User Mode Linux Kernel, type in" . - " the Kernel's location," . - " and any Kernel options desired afterwards.", - "" ); - button_fileselect_advanced(2,3,5,6,"Selection",$ear3,"Selection",13, - $table_advanced_root, $home_uml_kernel); - - #_______________________________________ - # Method - label_advanced("Method:",0,1,6,7,$table_advanced_root); - $ear4 = entry_advanced(1,2,6,7,6,$table_advanced_root); - $ear4->set_editable($false); - $tooltips->set_tip( $ear4, - "Choose the Root Filesystem Generation Method.", - "" ); - - my $opt_root = Gtk::OptionMenu->new(); - $tooltips->set_tip( $opt_root, - "Choose the Root Filesystem Generation Method.", - "" ); - my $menu_root = Gtk::Menu->new(); - - my $yard = Gtk::MenuItem->new("Yard" ); - - $menu_root->append( $yard ); - - $yard->signal_connect( 'activate', sub { - $ear4->set_text("yard"); - $entry_advanced[6] = $ear4->get_text(); - opendir(DIR,$template_dir) if -d $template_dir; - #@strings = grep { m,\.yard$, } readdir(DIR); - @strings = grep { m,^\w+, } readdir(DIR); - closedir(DIR); - $main::combo->set_popdown_strings( @strings ) if @strings; - } ); - - $ear4->set_text($entry_advanced[6]) if $entry_advanced[6]; - if ($yard) { - opendir(DIR,$template_dir) if -d $template_dir; - #@strings = grep { m,\.yard$, } readdir(DIR) if $yard; - @strings = grep { m,^\w+, } readdir(DIR) if $yard; - closedir(DIR) - } - - $yard->show(); - - $opt_root->set_menu( $menu_root ); - $table_advanced_root->attach($opt_root,2,3,6,7, - ['expand','fill'],['fill','shrink'],0,0); - $opt_root->show(); - - #_______________________________________ - # Template - # $::contents_file - label_advanced("Template:",0,1,7,8,$table_advanced_root); - $main::combo = Gtk::Combo->new(); - $main::combo->entry->set_text($entry_advanced[7]) if $entry_advanced[7]; - #$button_count_root_open = 1 + $button_count_root_open; - #print $button_count_root_open; - #if ($button_count_root_open > 1) { - # $main::combo->set_popdown_strings( @strings ) - # if $entry_advanced[7] ne ""; - #} - $tooltips->set_tip( Gtk::Combo::entry($main::combo), - "Choose a Template for the Method.", - "" ); - $entry_advanced[7] = $main::combo->entry->get_text(); # nothing selected - $main::combo->entry->signal_connect("changed", sub { - $entry_advanced[7] = $main::combo->entry->get_text(); - $ars->{template} = $entry_advanced[7]; - ars($ars); - } ); - $table_advanced_root->attach($main::combo,1,3,7,8, - ['expand','fill'],['fill','shrink'],0,0); - show $main::combo; - - #_______________________________________ - # Generate - UML - Accept buttons - $table_advanced_root->set_row_spacing( 7, 9); - - # The Generation process is determined by the method chosen. Yard - - # asks the user if they want to modify the template, and/or save a - # new template with modifications (to be added to Template menu). - my $generate_b = button_advanced(0,1,8,9,"Generate",$table_advanced_root); - $generate_b->signal_connect("clicked",\&Generate); - $tooltips->set_tip( $generate_b, "Generate Root Filesystem.", "" ); - - my $UML_b = button_advanced(1,2,8,9,"UML",$table_advanced_root); - - $UML_b->signal_connect("clicked", \¨_box); - $tooltips->set_tip( $UML_b, "Test Filesystem with User Mode Linux.", - "" ); - - # UML kernel doesn't look like a normal kernel - ##if (!-d $entry_advanced[5] && -f $entry_advanced[5]) { - ##$k_error = kernel_version_check($entry_advanced[5]); - ##return if $k_error && $k_error eq "ERROR";} - ## else { - ##error_window("Kernel Selection required"); - ##return; } - - # Will check to make sure that Filesystem fits device. - # Method determines whether or not compression is used. - my $accept_b = button_advanced(2,3,8,9,"Accept",$table_advanced_root); - $accept_b->signal_connect("clicked", \&accept_button, $ear2_save); - $tooltips->set_tip( $accept_b, "Accept Filesystem.", "" ); - - - $table_advanced_root->show(); - $button_count_root++; - - } - else { - destroy $table_advanced_root; - $button_count_root--; - } - - -} # end sub advanced_root_section - -sub uml_box { - - if (not defined $uml_window) { - - $uml_window = Gtk::Window->new("toplevel"); - $uml_window->signal_connect("destroy", \&destroy_window, - \$uml_window); - $uml_window->signal_connect("delete_event", \&destroy_window, - \$uml_window); - ##$uml_window->set_usize( 500, 95 ); # 450 175 || 500 600 - $uml_window->set_default_size( 500, 95 ); # 450 175 || 500 600 - $uml_window->set_policy( $true, $true, $false ); - $uml_window->set_title( "UML Box" ); - $uml_window->border_width(1); - - my $main_vbox = Gtk::VBox->new( $false, 0 ); - $uml_window->add( $main_vbox ); - $main_vbox->show(); - - ##my $table_uml = Gtk::Table->new( 4, 3, $true ); - my $table_uml = Gtk::Table->new( 4, 3, $false ); - ##$main_vbox->pack_start( $table_uml, $true, $true, 0 ); - $main_vbox->pack_start( $table_uml, $true, $false, 0 ); - $table_uml->show(); - - #_______________________________________ - # Xterm and execute options - label_advanced("Xterm:",0,1,0,1,$table_uml); - $eab1 = entry_advanced(1,2,0,1,8,$table_uml); - $eab1->set_text($uml_xterm); - $tooltips->set_tip( $eab1, - "Choose an xterm with " . - "its executable option switch.", - "" ); - - #_______________________________________ - # UML options - label_advanced("Options:",0,1,1,2,$table_uml); - $eab2 = Gtk::Combo->new(); - $table_uml->attach($eab2,1,3,1,2, - ['expand','fill'],['fill','shrink'],0,0); - open(OPTIONS,"$home_uml_kernel/.options"); - my @initial_options = ; - close(OPTIONS); chomp @initial_options; - $eab2->entry->set_text($initial_options[0]); - $entry_advanced[9] = $eab2->entry->get_text(); - $eab2->set_popdown_strings( @initial_options ) ; - $eab2->entry->signal_connect("changed", sub { - $entry_advanced[9] = $eab2->entry->get_text(); - open(OPTIONS,">$home_uml_kernel/.options"); - $entry_advanced[9] =~ s/\n//g; - $entry_advanced[9] =~ s/\s+$//g; - print OPTIONS "$entry_advanced[9]\n"; - foreach (@initial_options) { - if ($_ ne "$entry_advanced[9]") { - print OPTIONS "$_\n"; - } - } - close(OPTIONS); - } ); - $tooltips->set_tip( Gtk::Combo::entry($eab2), - "Enter uml command-line options.", - "" ); - $eab2->show(); - - - #_______________________________________ - # Root Filesystem defaults to generated one if found. - label_advanced("Root_Fs:",0,1,2,3,$table_uml); - $eab3 = entry_advanced(1,2,2,3,10,$table_uml); - button_fileselect_advanced(2,3,2,3,"Selection",$eab3,"Selection",14, - $table_uml,$home_rootfs); - $eab3->set_text("ubd0=$tmp/$entry_advanced[4]") - if -e "$tmp/$entry_advanced[4]"; - $tooltips->set_tip( $eab3, - "Choose an uncompressed root filesystem." . - "Append with ubd?=.", - "" ); - - $table_uml->set_row_spacing( 2, 4); - - #_______________________________________ - # Submit Button - my $submit_b = button_advanced(0,1,3,4,"Submit",$table_uml); - $tooltips->set_tip( $submit_b, - "Start uml kernel processes.", - "" ); - $submit_b->signal_connect("clicked", - sub { - # UML kernel = $entry_advanced[5] - # xterm -e linux ubd#=root_fs - # root=/dev/ubd# - open(OPTIONS,"$home_uml_kernel/.options"); - @initial_options = ; - close(OPTIONS); chomp @initial_options; - $eab2->set_popdown_strings( @initial_options ) ; - - my $pid; - if ($entry_advanced[8] && - $entry_advanced[10]) { - # Check to see if it actually exists - my $executable = (split(/\s+/,$entry_advanced[8]))[0]; - if (!find_file_in_path(basename($executable))) { - error_window("gBootRoot Error: " . - "Enter a valid xterm, and " . - "executable option."); - return; - } - if ($executable =~ m,/,) { - if (! -e $executable) { - error_window("gBootRoot Error: " . - "Enter a valid path for the xterm."); - return; - } - } - - unless ($pid = fork) { - unless (fork) { - if ($pid == 0) { - sys("$entry_advanced[8] $entry_advanced[5] $entry_advanced[9] $entry_advanced[10]"); - Gtk->_exit($pid); - } - - } - - } - waitpid($pid,0); - - } - else { - if (!$entry_advanced[8]) { - error_window("gBootRoot Error: " . - "Enter an xterm, and executable " . - "option."); - return; - } - if (!$entry_advanced[10]) { - error_window("gBootRoot Error: " . - "Enter the ubd?=Root_Filesystem " . - "and its location."); - return; - } - - } - - } ); - - - #_______________________________________ - # Cancel button also kills UML kernel if still open - my $abort_b = button_advanced(1,2,3,4,"Abort",$table_uml); - $tooltips->set_tip( $abort_b, - "Abort uml kernel processes." . - "This serves three purposes:\n" . - "1. Your creation doesn't boot.\n" . - "2. Your creation does work and" . - " you use something like" . - " `shutdown -h now`. When you are all done use" . - " Abort because it provides an excellent" . - " way to kill any ghost processes.\n" . - "3. Your creation gets weird, and you need to " . - "Abort its processes to shutdown it. ", - "" ); - $abort_b->signal_connect("clicked", - sub { - if ($entry_advanced[10]) { - # Most stuff - remove_matching_process($entry_advanced[10]); - # Debian - remove_matching_process("Virtual Console"); - # Good to remove uml_\w* - remove_matching_process('uml_\w*'); - # Again for good measure :) - remove_matching_process($entry_advanced[10]); - } - } ); - - #_______________________________________ - # Cancel button also kills UML kernel if still open - my $cancel_b = button_advanced(2,3,3,4,"Close",$table_uml); - $tooltips->set_tip( $cancel_b, - "Close uml box.", - "" ); - $cancel_b->signal_connect("clicked", - sub { - $uml_window->destroy() if $uml_window; - } ); - - } - if (!visible $uml_window) { - $uml_window->show(); - } else { - $uml_window->destroy; - } - -} - -sub remove_matching_process { - - my ($match_word) = @_; - - # Just an overkill - if ($match_word =~ m,/,) { - $match_word =~ s,/,\\/,g; - } - - my $ps = "ps auxw|"; - open(P,"$ps"); - while(

) { - # friendly approach - if (m,$match_word,) { - my $process = (split(/\s+/,$_,))[1]; - system "kill $process"; - # not so friendly approach - system "kill -9 $process"; - } - } - close(P); - -} # end remove_matching_process - -sub accept_button { - - my ($widget,$ear2_save) = @_; - - my($tool,$value); - if (-e "$tmp/$entry_advanced[4]" ) { - if (!$compression_off->active) { - if ($gz_toggle_root->active) { - $compress = "gzip"; - open(F,"file $tmp/$entry_advanced[4] |"); - while () { - if (/gzip/) { - info(0, "Already gzip compressed.\n"); - } - elsif (/bzip2/) { - info(0, "Already bzip2 compressed.\n"); - } - else { - system - "$compress -c9 $tmp/$entry_advanced[4] > $tmp/$entry_advanced[4].gz"; - $entry_advanced[4] = "$entry_advanced[4].gz"; - $entry3->set_text("$tmp/$entry_advanced[4]"); - } - } - close(F); - if ($ear2_save->active) { - if (-f "$home_rootfs/$entry_advanced[4]") { - save_as($entry_advanced[4]); - } - else { - return if errcp(sys("cp -a $tmp/$entry_advanced[4] $home_rootfs")) == 2; - } - } - else { - $ear2->set_text("$entry_advanced[4]"); - } - } - elsif ($bz2_toggle_root->active) { - $compress = "bzip2"; - open(F,"file $tmp/$entry_advanced[4] |"); - while () { - if (/gzip/) { - info(0, "Already gzip compressed.\n"); - } - elsif (/bzip2/) { - info(0, "Already bzip2 compressed.\n"); - } - else { - system - "$compress -c $tmp/$entry_advanced[4] > $tmp/$entry_advanced[4].bz2"; - $entry_advanced[4] = "$entry_advanced[4].bz2"; - $entry3->set_text("$tmp/$entry_advanced[4]"); - } - } - close(F); - if ($ear2_save->active) { - if (-f "$home_rootfs/$entry_advanced[4]") { - save_as($entry_advanced[4]); - } - else { - return if errcp(sys("cp -a $tmp/$entry_advanced[4] $home_rootfs")) == 2; - } - } - else { - $ear2->set_text("$entry_advanced[4]"); - } - } - } - else { # off - $entry3->set_text("$tmp/$entry_advanced[4]"); - if ($ear2_save->active) { - if (-f "$home_rootfs/$entry_advanced[4]") { - save_as($entry_advanced[4]); - } - else { - return if errcp(sys("cp -a $tmp/$entry_advanced[4] $home_rootfs")) == 2; - } - } - } - } - else { - error("$entry_advanced[4] doesn't exist; create it first.\n"); - } - -} # end accept_button - -my ($save_as); -sub save_as { - -# Will just use a dialog box. - - my ($template) = @_; - #my ($button); - - if (not defined $save_as) { - $save_as = Gtk::Dialog->new(); - $save_as->signal_connect("destroy", \&destroy_window, \$save_as); - $save_as->signal_connect("delete_event", \&destroy_window, \$save_as); - $save_as->signal_connect("key_press_event", sub { - my $event = pop @_; - if ($event->{'keyval'}) { - if ($event->{'keyval'} == 65307) { - $save_as->destroy; - } - } - }, - ); - $save_as->set_title("Save As"); - $save_as->border_width(12); - $save_as->set_position('center'); - - my $new_template = $template; - my $entry = Gtk::Entry->new(); - $entry->set_editable( $true ); - $entry->set_text($template) if $template; - $entry->signal_connect( "changed", sub { - $new_template = $entry->get_text(); - }); - $save_as->vbox->pack_start( $entry, $false, $false, 0); - $entry->show(); - - my $label = Gtk::Label->new(); - $label->set_justify( 'left' ); - $label->set_text("$template already exists, " . - "do\nyou want to write over it, " . - "or\nsave $new_template with a different name?"); - $save_as->vbox->pack_start( $label, $false, $false, 2 ); - $label->show(); - - my $button = Gtk::Button->new("OK"); - my $event_count = 0; - my $new_template_tmp = "nothing"; - $button->signal_connect("clicked", sub { - - $entry_advanced[4] = $new_template; - $ars->{filename} = $new_template; - ars($ars); - - # This is a renaming deal and this time doesn't exist in the archive - # or $tmp. - if (!-f "$home_rootfs/$new_template") { - if ($template ne $new_template) { - return if err_custom("mv $tmp/$template $tmp/$new_template", - "gBootRoot: ERROR: Could not rename $template to " . - "$new_template") == 2; - } - - return if errcp(sys("cp -a $tmp/$new_template $home_rootfs")) == 2; - $ear2->set_text($new_template); - $entry3->set_text("$tmp/$new_template"); - $save_as->destroy; - } - - # This is a write-over situation .. exists in $tmp and archive - elsif (-e "$tmp/$new_template" && -f "$tmp/$new_template" - && -f "$home_rootfs/$new_template" ) { - return if errcp(sys("cp -a $tmp/$new_template $home_rootfs")) == 2; - $ear2->set_text($new_template); - $entry3->set_text("$tmp/$new_template"); - $save_as->destroy; - } - - # Here the file trying to be renamed already exists in the archive - # but doesn't exist in $tmp - else { - - $label->set_text("$new_template already exists, " . - "do\nyou want to write over it, " . - "or\nsave $template with a different name?"); - - $event_count++; - my $event = pop(@_); - - if ($new_template eq $new_template_tmp) { - if ($event_count >= 2 && $event && $event eq "clicked") { - if ("$tmp/$template" ne "$tmp/$new_template") { - return if err_custom("mv $tmp/$template $tmp/$new_template", - "gBootRoot: ERROR: Could not rename $template to " . - "$new_template") == 2; - } - - return if errcp(sys("cp -a $tmp/$new_template $home_rootfs")) - == 2; - $event_count = 0; - $ear2->set_text($new_template); - $entry3->set_text("$tmp/$new_template"); - $save_as->destroy; - } - } - $new_template_tmp = $new_template; - } - },"clicked"); - $button->can_default(1); - $save_as->action_area->pack_start($button, $false, $false,0); - $button->grab_default; - $button->show; - - $button = Gtk::Button->new("Cancel"); - $button->signal_connect("clicked", sub { destroy $save_as} ); - $save_as->action_area->pack_start($button, $false, $false,0); - $button->show; - - } - if (!visible $save_as) { - show $save_as; - } - else { - destroy $save_as; - } - -} # end sub save_as - -# Coming - .config storage, auto-matic kernel locus, all stages -# /usr/src/linux* Possible integration with other Projects .. modules -# will be in the logical place. Before ABS. -sub advanced_kernel_section { - - -} # end sub advanced_kernel_section - -# Stuff univeral for all root filesystem methods -# Compression, UML Kernel, and Method only need to be known by the Dock. - - -sub Generate { - - # @entry_advanced - # 0 = Development Drive - # 1 = Optional Devices - # 2 = Append Options - #------------------ - # 3 = Root Device - # 4 = Root Filename - # 5 = UML Kernel - my $method = $entry_advanced[6]; # 6 = Method - # 7 = Template - # 8 = UML xterm - # 9 = UML options - # 10 = UML root_fs - #------------------ - # 11 = Kernel Modules .. from the Boot Method - # 12 = Kernel Version .. from the Boot Method - # 13 = System.map .. from the Boot Method - - # $root_device_size; - # $filesystem_size; - - # File select: function order: non-table = button->fileselect->file_ok_sel - # table = button_fileselect_advanced->fileselect->file_ok_sel - - $ars->{device} = $entry_advanced[3]; - $ars->{device_size} = $root_device_size; - $ars->{tmp} = $tmp; - $ars->{mnt} = $mnt; - $ars->{template_dir} = $template_dir; # static right now. - ars($ars); - - - my $template = $ars->{template}; - my $root_device = $ars->{device}; - my $root_filename = $ars->{filename}; - - if (!$root_device || $root_device eq "") { - error_window("gBootRoot: ERROR: Root Device not defined"); - return; - } - # devfs may change this .. it did, this is silly. -## if (!-b $root_device) { -## error_window("gBootRoot: ERROR: Not a valid Block Device"); -## return; -## } - - if (!$root_filename || $root_filename eq "") { - error_window("gBootRoot: ERROR: Root Filename not given"); - return; - } - if (!$method || $method eq "") { - error_window("gBootRoot: ERROR: Method must be supplied"); - return; - } - if (!$template || $template eq "") { - error_window("gBootRoot: ERROR: Template name not given"); - return; - } - - - if ($method eq "yard") { - if (!$main::yard_window) { - ##$ars->{kernel} = "" if !$entry2->get_text(); - ##ars($ars); - yard(); - } - } - - -} # end sub Generate - -sub button_advanced { - - # cretzu should like this - my ($left_attach,$right_attach,$top_attach, - $bottom_attach,$text,$widget) = @_; - my $button = Gtk::Button->new($text); - $widget->attach($button,$left_attach,$right_attach, - $top_attach,$bottom_attach, - ['shrink','fill','expand'],['fill','shrink'],2,2); - show $button; - return $button; - -} - -sub button_fileselect_advanced { - - # cretzu should like this - # $order does matter because it fills in $container[$order]. - my ($left_attach,$right_attach,$top_attach,$bottom_attach,$text,$ent, - $name,$order,$widget,$device) = @_; - - my $button = Gtk::Button->new($text); - $widget->attach($button,$left_attach,$right_attach, - $top_attach,$bottom_attach, - ['shrink','fill','expand'],['fill','shrink'],2,2); - - # example - if ($order == 12) { - $tooltips->set_tip( $button, "Select the Root Device.", "" ); - } - elsif ($order == 13) { - $tooltips->set_tip( $button, "Select the UML Kernel.", "" ); - } - elsif ($order == 14) { - $tooltips->set_tip( $button, "Select the Root Filesystem.", "" ); - } - elsif ($order == 16) { - $tooltips->set_tip( $button, "Select the System.map.", "" ); - } - - - $button->signal_connect( "clicked",\&fileselect,$ent,$name,$order,$device); - $button->show(); - - -} # end sub button_fileselect_advanced - - -sub entry_advanced { - - my $numa = $_[4]; - my $entry_advanced = Gtk::Entry->new(); - $entry_advanced->set_editable( $true ); - $entry_advanced->signal_connect( "changed", sub { - $entry_advanced[$numa] = $entry_advanced->get_text(); - if ($numa == 4) { - $ars->{filename} = $entry_advanced[$numa]; - ars($ars); - } - if ( $numa == 12 ) { - $ars->{kernel_version_choice} = $entry_advanced[$numa]; - ars($ars); - ars2($ars); - } - } ); - $entry_advanced->set_usize(100,20); - $_[5]->attach($entry_advanced,$_[0],$_[1],$_[2],$_[3], - ['shrink','fill','expand'],['fill','shrink'],0,0); - show $entry_advanced; - return $entry_advanced; - -} - -sub separator_advanced { - - $separator_advanced = Gtk::HSeparator->new(); - $_[0]->pack_start( $separator_advanced, $false, $true, 0 ); - $separator_advanced->show(); - -} - -sub label_advanced { - - my($text) = @_; - - $label_advanced = Gtk::Label->new( $text ); - $label_advanced->set_justify( "fill" ); - $_[5]->attach($label_advanced,$_[1],$_[2],$_[3],$_[4], ['expand'],['fill','shrink'],0,0); - $label_advanced->show(); - -} - -# I created two of these, one for help (eventually there may be a different -# approach), and one for verbosity. I am sure there is a better OO way to -# do it, though. -sub create_text { - - if (not defined $text_window) { - $text_window = Gtk::Window->new("toplevel"); - $text_window->signal_connect("destroy", \&destroy_window, - \$text_window); - $text_window->signal_connect("delete_event", \&destroy_window, - \$text_window); - $text_window->set_title("Help"); - $text_window->set_usize( 500, 600 ); - $text_window->set_policy( $true, $true, $false ); - $text_window->set_title( "gBootRoot Help" ); - $text_window->border_width(0); - - my $main_vbox = Gtk::VBox->new( $false, 0 ); - $text_window->add( $main_vbox ); - $main_vbox->show(); - - my $vbox = Gtk::VBox->new( $false, 10 ); - $vbox->border_width( 10 ); - $main_vbox->pack_start( $vbox, $true, $true, 0 ); - $vbox->show(); - - my $table = Gtk::Table->new( 2, 2, $false ); - $table->set_row_spacing( 0, 2 ); - $table->set_col_spacing( 0, 2 ); - $vbox->pack_start( $table, $true, $true, 0 ); - $table->show( ); - - # Create the GtkText widget - my $text = Gtk::Text->new( undef, undef ); - $text->set_editable($false); - $table->attach( $text, 0, 1, 0, 1, - [ 'expand', 'shrink', 'fill' ], - [ 'expand', 'shrink', 'fill' ], - 0, 0 ); - $text->grab_focus(); - $text->show(); - - # Add a vertical scrollbar to the GtkText widget - my $vscrollbar = Gtk::VScrollbar->new( $text->vadj ); - $table->attach( $vscrollbar, 1, 2, 0, 1, 'fill', - [ 'expand', 'shrink', 'fill' ], 0, 0 ); - #my $logadj = $vscrollbar->get_adjustment(); - #logadj($logadj); - #$vscrollbar->show(); - - $text->freeze(); - $text->insert( undef, undef, undef, help() ); - $text->thaw(); - - my $separator = Gtk::HSeparator->new(); - $main_vbox->pack_start( $separator, $false, $true, 0 ); - $separator->show(); - - $vbox = Gtk::VBox->new( $false, 10 ); - $vbox->border_width( 10 ); - $main_vbox->pack_start( $vbox, $false, $true, 0 ); - $vbox->show(); - - my $button = Gtk::Button->new( "Close" ); - $button->signal_connect( 'clicked', sub { destroy $text_window; } ); - $vbox->pack_start( $button, $true, $true, 0 ); - $button->can_default( $true ); - $button->grab_default(); - $button->show(); - } - if (!visible $text_window) { - show $text_window; - } else { - destroy $text_window; - } - -} # end sub create_text - -# This monster needs different behavior than create_text. -sub verbosity_box { - - - $verbosity_window = Gtk::Window->new("toplevel"); - $verbosity_window->signal_connect("destroy", \&destroy_window, - \$verbosity_window); - $verbosity_window->signal_connect("delete_event", \&destroy_window, - \$verbosity_window); - $verbosity_window->set_usize( 450, 175 ); # 500 600 - $verbosity_window->set_policy( $true, $true, $false ); - $verbosity_window->set_title( "Verbosity Box" ); - $verbosity_window->border_width(0); - - my $main_vbox = Gtk::VBox->new( $false, 0 ); - $verbosity_window->add( $main_vbox ); - $main_vbox->show(); - - my $vbox = Gtk::VBox->new( $false, 10 ); - $vbox->border_width( 10 ); - $main_vbox->pack_start( $vbox, $true, $true, 0 ); - $vbox->show(); - - my $table = Gtk::Table->new( 2, 2, $false ); - $table->set_row_spacing( 0, 2 ); - $table->set_col_spacing( 0, 2 ); - $vbox->pack_start( $table, $true, $true, 0 ); - $table->show( ); - - # Create the GtkText widget - my $text = Gtk::Text->new( undef, undef ); - $text->set_editable($false); - $table->attach( $text, 0, 1, 0, 1, - [ 'expand', 'shrink', 'fill' ], - [ 'expand', 'shrink', 'fill' ], - 0, 0 ); - $text->grab_focus(); - $text->show(); - my $red = Gtk::Gdk::Color->parse_color("red"); - my $blue = Gtk::Gdk::Color->parse_color("blue"); - text_insert($text,$red,$blue); # yard thing - - # Add a vertical scrollbar to the GtkText widget - my $vscrollbar = Gtk::VScrollbar->new( $text->vadj ); - $table->attach( $vscrollbar, 1, 2, 0, 1, 'fill', - [ 'expand', 'shrink', 'fill' ], 0, 0 ); - my $logadj = $vscrollbar->get_adjustment(); - logadj($logadj); - $vscrollbar->show(); - - my $separator = Gtk::HSeparator->new(); - $main_vbox->pack_start( $separator, $false, $true, 0 ); - $separator->show(); - - $vbox = Gtk::VBox->new( $false, 10 ); - $vbox->border_width( 10 ); - $main_vbox->pack_start( $vbox, $false, $true, 0 ); - $vbox->show(); - - #my $button = Gtk::Button->new( "Close" ); - #$button->signal_connect( 'clicked', - # sub { destroy $verbosity_window; } ); - #$vbox->pack_start( $button, $true, $true, 0 ); - #$button->can_default( $true ); - #$button->grab_default(); - #$button->show(); - - show $verbosity_window; - -} # end sub verbosity_box - -sub fileselect { - - my ($widget,$ent,$name,$order,$device) = @_; - - if (not defined $file_dialog) { - # Create a new file selection widget - $file_dialog = Gtk::FileSelection->new( "$name" ); - $file_dialog->signal_connect( "destroy", - \&destroy_window, \$file_dialog); - $file_dialog->signal_connect( "delete_event", - \&destroy_window, \$file_dialog); - - # Connect the ok_button to file_ok_sel function - $file_dialog->ok_button->signal_connect( "clicked", - \&file_ok_sel, - $file_dialog,$ent,$order); - - # Connect the cancel_button to destroy the widget - $file_dialog->cancel_button->signal_connect( "clicked", - sub { destroy $file_dialog } ); - $file_dialog->set_filename( $device ) if defined $device; - $file_dialog->set_position('mouse'); - - } - if (!visible $file_dialog) { - show $file_dialog; - } - else { - destroy $file_dialog; - } - -} # end sub fileselect - - -# Get the selected filename and print it to the text widget -sub file_ok_sel { - - my( $widget, $file_selection,$entry,$order) = @_; - my $file = $file_selection->get_filename(); - if ($order != 14) { - $entry->set_text($file); - } - else { - $entry->set_text("ubd0=$file"); - } - $container[$order] = $file; - if ($order == 1) { - $ars->{kernel} = $container[$order]; - ars($ars); - ars2($ars); - } - - # auto-detect compression if system has file - if ($container[ROOT_FS]) { - my $file = sys("which file > /dev/null 2>&1"); - if ($file == 0) { - open(F,"file $container[ROOT_FS] |"); # no error check - # here - while () { - if (/gzip/) { - $gz_toggle->set_active( $true ); - } - elsif (/bzip2/) { - $bz2_toggle->set_active( $true ); - } - else { - info(0, "Neither gz or bz2 compression found\n"); - } - } - close(F); - } - } - - destroy $file_dialog; - -} - -sub hbox { - my $homogeneous; - defined $_[0] ? ($homogeneous = 0) : ($homogeneous = 1); - $box2 = Gtk::HBox->new( $homogeneous, 5 ); - $box2->border_width( 2 ); # was 10 - $box1->pack_start( $box2, $true, $true, 0 ); - #$box1->pack_start( $box2, $false, $true, 0 ); - $box2->show(); -} - -sub label { - - my($text) = @_; - - $label = Gtk::Label->new( $text ); - $label->set_justify( "fill" ); - $box2->pack_start( $label, $false, $false, 5 ); - $label->show(); - -} - -sub entry { - - my($edit,$num) = @_; - - my $entry = Gtk::Entry->new(); - - $entry->set_editable( $false ) if $edit == 0; - - if ($num == 0) { - $entry->signal_connect( "activate", sub { - $container[$num] = $entry->get_text();}); - } - else { - $entry->signal_connect( "changed", sub { - $container[$num] = $entry->get_text(); - if ($num == 1) { - $ars->{kernel} = $container[$num]; - ars($ars); - ars2($ars); - } - # here's where types in entry3, types other places - if (defined $ea1 and $num == 3) { - $ea1->set_text($container[$num]); - } - if (defined $ear1 and $num == 3) { - $ear1->set_text($container[$num]); - } - - # auto-detect compression if system has file - if ($num == 2) { - my $file = sys("which file"); - if ($file == 0) { - if ($container[ROOT_FS]) { - open(F,"file $container[ROOT_FS] |"); # no error check here - while () { - if (/gzip/) { - $gz_toggle->set_active( $true ); - } - elsif (/bzip2/) { - $bz2_toggle->set_active( $true ); - } - else { - info(0, - "Neither gz or bz2 compression found\n"); - } - } - close(F); - } - } - } - }); - } - if (defined $num and $num != 0) { - my $todo; - if ($num == 1) { - $todo = "the Kernel"; - } - elsif ($num == 2) { - $todo = "the Compressed Filesystem"; - } - else { - $todo = "the Block Device to use"; - } - $tooltips->set_tip( $entry, - "Type in the location of $todo.", "" ); - } - $box2->pack_start( $entry, $true, $true, 0 ); - $entry->show(); - - return $entry; - -} - -sub button { - - my ($text,$ent,$name,$order,$device) = @_; - - my $button = Gtk::Button->new($text); - if ($order == 1) { - $tooltips->set_tip( $button, "Select the Kernel.", "" ); - } - elsif ($order == 2) { - $tooltips->set_tip( $button, "Select the Root Filesystem.", "" ); - } - else { - $tooltips->set_tip( $button, "Select the Device.", "" ); - } - $button->signal_connect( "clicked",\&fileselect,$ent,$name,$order,$device); - $button->show(); - $box2->pack_start( $button, $true, $true, 0 ); - $box2->show(); - -} - -sub submit { - - my($kernel, $root_image, $device, $size); - - # comment this out for testing - # Since only one filehandle is now used, this won't work - # anymore. - #unlink("$verbosefn"); - open (MTAB, "/etc/mtab") or die "no mtab!\n"; - while () { - if (m,$mnt,) { - sys("umount $mnt"); - } - } - close(MTAB); - $entry5->set_text(""); - pb("boot",0); - - if ($gz_toggle->active) { - $compress = "gzip"; - } - elsif ($bz2_toggle->active) { - $compress = "bzip2"; - } - - # Run some checks - if (!defined $container[METHOD]) { - error_window("gBootRoot: ERROR: No Method supplied"); - return; - } - else { - if ( $container[METHOD] eq "2 disk compression" ) { - my $rt = two_disk_compression_check(); - return if $rt; - } - } - - -if (defined $container[KERNEL] && -e $container[KERNEL] && - !-d $container[KERNEL]) { - $kernel = $container[KERNEL]; - # Better be sure it isn't in the mount directory - if ($kernel =~ m,^$mnt,) { - error_window("gBootRoot: ERROR: Kernel found below Device mount point: $mnt"); - return; - } - -} -elsif (defined $container[METHOD]) { - error_window("gBootRoot: ERROR: Kernel not found"); - return; -} -if (defined $container[ROOT_FS] && -e $container[ROOT_FS] && - !-d $container[ROOT_FS] ) { - $root_image = $container[ROOT_FS]; - if ($root_image =~ m,^$mnt,) { - # Bug revealed by Cristian Ionescu-Idbohrn - error_window( - "gBootRoot: ERROR: Rootimage found below Device mount point: $mnt"); - return; - } -} -elsif (defined $container[METHOD] && defined $container[KERNEL]) { - error_window("gBootRoot: ERROR: Root Filesystem not found"); - return; -} -# we need to check for this, too. -if (defined $container[BOOT_DEVICE] && -b $container[BOOT_DEVICE]) { - $device = $container[BOOT_DEVICE]; -} -elsif (defined $container[METHOD] && defined $container[KERNEL] - && defined $container[ROOT_FS]) { - error_window("gBootRoot: ERROR: Not a valid Block Device"); - return; -} -if (defined $container[SIZE]) { - $size = $container[SIZE]; -} - -# pretty unlikely -elsif (defined $container[METHOD] && defined $container[KERNEL] && - defined $container[ROOT_FS] && defined $container[BOOT_DEVICE]) { - error_window("gBootRoot: ERROR: No size specified"); - return; -} - - # kernel value can change without effecting initrd - # no sense doing this until important stuff is filled in - if (defined $kernel && defined $root_image && - defined $device && defined $size) { - $container[COMPRESS] = $compress; - - # 1 .. 4 - its a hash .. not too simple - !defined $lib_strip_check ? ($container[LIB_STRIP] = 1) - : ($container[LIB_STRIP] = $lib_strip_check->get_active()); - !$container[LIB_STRIP] ? ($container[LIB_STRIP] = 2) - : ($container[LIB_STRIP] = 1); - - !defined $bin_strip_check ? ($container[BIN_STRIP] = 3) - : ($container[BIN_STRIP] = - $bin_strip_check->get_active()); - !$container[BIN_STRIP] ? ($container[BIN_STRIP] = 4) - : ($container[BIN_STRIP] = 3); - - !defined $mod_strip_check ? ($container[MOD_STRIP] = 7) - : ($container[MOD_STRIP] = - $mod_strip_check->get_active()); - !$container[MOD_STRIP] ? ($container[MOD_STRIP] = 8) - : ($container[MOD_STRIP] = 7); - - - if ($container[LIB_STRIP] == 1) { - $obj_count == 0 ? ($container[OBJCOPY_BOOL] = 5) - : ($container[OBJCOPY_BOOL] = 6); - } - - - if (!defined $entry_advanced[0]) { - $container[ABS_DEVICE] = $device . "ea1"; - $entry_advanced[0] = $device; - } - else { - $container[ABS_DEVICE] = $entry_advanced[0] . "ea1"; - } - - # If ARS was never opened, root device defaults to boot device. - # This keeps the logic in the right place. - $entry_advanced[3] = $container[BOOT_DEVICE] if !$entry_advanced[3]; - - - # Works now .. whoosh! - if ($container[ABS_OPT_DEVICE]) { - if ($container[ABS_OPT_DEVICE] ne "") { - $container[ABS_OPT_DEVICE] = $entry_advanced[1] - if $entry_advanced[1]; - } - if (defined $entry_advanced[1] and $entry_advanced[1] eq "") { - $container[ABS_OPT_DEVICE] = ""; - } - elsif ($container[ABS_OPT_DEVICE] eq "") { - push(@original_container,$entry_advanced[1]); - } - } - else { - push(@original_container,$entry_advanced[1]) - if $entry_advanced[1]; - } - - # pretty complex and works properly even for !-e lilo.conf - if ($container[ABS_APPEND]) { - if ($container[ABS_APPEND] ne "") { - $container[ABS_APPEND] = $entry_advanced[2] - if $entry_advanced[2]; - } - if (defined $entry_advanced[2] and $entry_advanced[2] eq "") { - $container[ABS_APPEND] = ""; - } - elsif ($container[ABS_APPEND] eq "") { - push(@original_container,$entry_advanced[2]); - } - } - else { - push(@original_container,$entry_advanced[2]) - if $entry_advanced[2]; - } - - if (@original_container) { # defined array deprecate Perl 5.6 - zas@metaconcept.com - # a hash check isn't perfect for two values which are the same - # no need to check all the values - - my @temp_container = @container; - - # Got it! - how to deal with fields with no init value - if (defined $container[ABS_OPT_DEVICE] and - $container[ABS_OPT_DEVICE] eq "") { - $container[ABS_OPT_DEVICE] = $entry_advanced[1]; - } - if (!defined $container[ABS_OPT_DEVICE]) { - $container[ABS_OPT_DEVICE] = $entry_advanced[1]; - } - if (defined $container[ABS_APPEND] and - $container[ABS_APPEND] eq "") { - $container[ABS_APPEND] = $entry_advanced[2]; - } - if (!defined $container[ABS_APPEND]) { - $container[ABS_APPEND] = $entry_advanced[2]; - } - - # no sense looking at undef values - my (@temp_container2,@original_container2); - for (@temp_container) { - if ($_) { - push(@temp_container2,$_); - } - } - for (@original_container) { - if ($_) { - push(@original_container2,$_); - } - } - - @temp_container = @temp_container2; - @original_container = @original_container2; - - splice(@temp_container,1,1); - - # A test which I've had to run too often - #print "BEFORE @temp_container\nAFTER @original_container\n"; - - my %diff; - grep($diff{$_}++,@temp_container); - my @diff = grep(!$diff{$_},@original_container); - - if ($#diff >= 0) { - # unlink initrd_image.gz, do initrd_size() - $ok = 1; - $initrd = "initrd_image"; - } - else { - $ok = 0; - } - } - else { - $ok = 2; # this is actually first (1 = diff, 0 = same) - $initrd = "initrd_image"; - } - - # reset - @original_container = ( $container[METHOD], - $root_image, - $device, - $size, - $compress, - $container[LIB_STRIP], - $container[BIN_STRIP], - $container[MOD_STRIP], - $container[OBJCOPY_BOOL], - $container[ABS_DEVICE], - $container[ABS_OPT_DEVICE], - $container[ABS_APPEND] - ); - - kernel_modules(); - lilo(); # This is the default now, and the value for - # METHOD doesn't matter now. - } - -} # end sub submit - -sub lilo { - - # Do a little cleanup just in case - sys("rm $tmp/initrd_image.gz") if $ok == 1; - sys("umount $tmp/initrd_mnt"); - - my $kernel = $container[KERNEL]; - my $root_fs = $container[ROOT_FS]; - my $device = $container[BOOT_DEVICE]; - my $size = $container[SIZE]; - - if ($ok == 1 || $ok == 2) { - my $value = initrd($kernel,$root_fs,$device,$size); - mtab(0) if defined $value; - } - elsif ($ok == 0) { - mtab(0); - } - -} # end sub lilo - -sub lilo_put_it_together { - - my $B = "boot"; - my $fs_type = (split(/\s/,$main::makefs))[0]; - - # Time to do a little calculations - my $device_size; - if ( $fs_type ne "genext2fs" ) { - $device_size = (split(/\s+/,`df $mnt`))[8]; - } - else { - $device_size = $container[SIZE]; - } - my $boot_size = (stat($container[KERNEL]))[12]/2 + - (stat("$tmp/$initrd"))[12]/2; - my $remain_boot = $device_size - $boot_size; - pb($B,1); - - # A little output - if ($remain_boot =~ /^-+\d+$/) { - error_window("gBootRoot: ERROR: Not enough room: boot stuff = $boot_size k, device = $device_size k"); - return; - } - else { - $entry5->set_text("$remain_boot k"); - } - - - # If genext2fs is being used clean $tmp/bootdisk if any garbage is found, - # and temporarily rename $mnt to that directory. - #my $old_mount; - if ( $fs_type eq "genext2fs" ) { - if (-d "$tmp/bootdisk") { - sys("rm -rf $tmp/bootdisk"); - } - if (!-d "$tmp/bootdisk") { - return if errmk(sys("mkdir $tmp/bootdisk")) == 2; - } - $old_mount = $mnt; - $mnt = "$tmp/bootdisk/"; - } - - # Here everything is copied over either to the device or the the $mnt - # directory if genext2fs is used. - info(0, "Copy over initrd ramdisk\n"); - info(0, "Copy over initrd ramdisk .. $tmp/$initrd $mnt/$initrd\n"); - return if err_custom("cp $tmp/$initrd $mnt/$initrd", - "gBootRoot: ERROR: Could not copy over initrd") == 2; - pb($B,2); - - info(0, "Copying over kernel\n"); - if ( $fs_type ne "genext2fs" ) { - return if - err_custom("rm -rf $mnt/lost+found; cp $container[KERNEL] $mnt/kernel", "gBootRoot: ERROR: Could not copy over the kernel") == 2; - } - else { - return if - err_custom("cp $container[KERNEL] $mnt/kernel", "gBootRoot: ERROR: Could not copy over the kernel") == 2; - } - pb($B,3); - - info(0, "Making stuff for lilo\n"); - # will be 0 if mkdir fails, but 0 if cp succeeds ? - return if err(sys("mkdir $mnt/{boot,dev}")) == 2; - - # DEVICES SECTION - my @devices; - my $device_table = "$tmp/boot_device_table.txt"; - if ( $fs_type eq "genext2fs" ) { - - info(0, "Making $device_table for genext2fs\n"); - my $error; - unlink( $device_table ) if -e $device_table; - - # - # /dev is always needs to be made automatically - open(BootRoot::Yard::DEVICE_TABLE, ">$device_table") or - ($error = error("$device_table: $!")); - return "ERROR"if $error && $error eq "ERROR"; - - print BootRoot::Yard::DEVICE_TABLE - "# \t\t\t\t\t\t" . - "\t\t\t\n"; - print BootRoot::Yard::DEVICE_TABLE "/dev\t\td\t0755\t-\t-\t-\t-\t-\t-\t-\n"; - - # Keep a record of the devices required - @devices = qw(/dev/null /dev/fd0 /dev/fd1 /dev/hda1); - for ( split(" ", $container[BOOT_DEVICE] ) ) { - my @existing_device_test = grep ( /$_/, @devices ); - if ( !@existing_device_test ) { - push(@devices, $_ ) if $_; - } - } - - # This adds that next device if found in lilo.conf - ($norm_root_device) = gdkbirdaao(); - if ( $norm_root_device ) { - my @existing_device_test = - grep ( /\/dev\/$norm_root_device/, @devices ); - if ( !@existing_device_test ) { - push( @devices, "/dev/$norm_root_device" ); - } - } - - # For frame buffer devices and the like. - if ( $entry_advanced[1] ) { - for ( split(" ", $entry_advanced[1] ) ) { - my @existing_device_test = grep ( /$_/, @devices ); - if ( !@existing_device_test ) { - push(@devices, $_ ) if $_; - } - } - } - - - device_table( @devices ); - close(BootRoot::Yard::DEVICE_TABLE); - - } - else { - - info(0, "Copying over devices to $mnt/dev\n"); - - return if err(sys("cp -a /dev/{null,fd?,hda1} $mnt/dev")) == 2; - - # Hopefully, this works, but have never tested it -- o.k I did - if ($container[BOOT_DEVICE] !~ m,/dev/fd\d{1}$,) { - return if err(sys("cp -a $container[BOOT_DEVICE] $mnt/dev")) == 2; - } - - # This adds that next device if found in lilo.conf - ($norm_root_device) = gdkbirdaao(); - if (!-e "$mnt/dev/$norm_root_device") { - return if err(sys("cp -a /dev/$norm_root_device $mnt/dev")) == 2; - } - - # For frame buffer devices and the like. - if ($entry_advanced[1]) { - return if errcp(sys("cp -a $entry_advanced[1] $mnt/dev")) == 2; - } - - - } # end DEVICES SECTION - - info(0, "Copy over important lilo stuff\n"); - return if - err_custom("cp /boot/boot.b $mnt/boot", - "gBootRoot: ERROR: Not enough space or can't find /boot/boot.b") == 2; - pb($B,4); - # 3k sort of accounts for dev & dirs assuming dev is reasonable - $remain_boot = $remain_boot - (stat("/boot/boot.b"))[12]/2 - 3; - $entry5->set_text("$remain_boot k"); - - # Write out the HEREDOCS - open(LC, ">$mnt/brlilo.conf") or die "Couldn't write $mnt/brlilo.conf\n"; - if ( $> == 0 ) { - print LC brlilo($container[BOOT_DEVICE]); close(LC); - } - else { - print LC brlilo_non_root($container[BOOT_DEVICE]); close(LC); - } - - open(M, ">$mnt/message") or die "Couldn't write $mnt/message\n"; - print M message(); close(M); - pb($B,5); - $remain_boot = $remain_boot - ( (stat("$mnt/brlilo.conf"))[12]/2 + - (stat("$mnt/message"))[12]/2 ); - $entry5->set_text("$remain_boot k"); - - # Got to umount,mount, and umount again to make sure everything is - # copied over before doing lilo unless genext2fs in being used. - if ( $fs_type ne "genext2fs" ) { - return if errum(sys("umount $mnt")) == 2; - info(0, "Umount device\n"); - info(0, "Remount device\n"); - } - pb($B,6); - - - if ( $fs_type eq "genext2fs" ) { - - my $error; - - # When creating a fs on floppy, specifying -i causes genext2fs to fail, - # its better to just let the program figure out the inode size for now. - if ( - sys("/usr/lib/bootroot/$main::makefs -b $device_size -d $mnt -D $device_table $entry_advanced[0]") !~ - /^0$/ ) { - $error = error("Cannot $fs_type filesystem.\n"); - return "ERROR" if $error && $error eq "ERROR"; - } - - } - - - if ( $fs_type eq "genext2fs" ) { - $mnt = $old_mount; - } - - # Real device - if ( $> == 0 ) { - return if errm(sys("mount -t ext2 $entry_advanced[0] $mnt")) == 2; - } - else { - my $errm_value = errm(sys("mount $mnt")); - if ( $errm_value == 2 && $fs_type eq "genext2fs" ) { - info(0, "Ask your administrator to add this line to the" . - " fstab file:\n"); - info(0, "\n$entry_advanced[0]\t$mnt\tauto\tdefaults,noauto," . - "user\t0\t0\n\n"); - } - else { - return if $errm_value == 2; - } - } - - - info(0, "Configuring lilo\n"); - pb($B,7); - chdir("$mnt"); #"boot_root: ERROR: Could not change directories\n"; - - # This enforces that lilo is only wil run on a bootable drive, - # otherwise the user has to do it manually. - if ($container[BOOT_DEVICE] eq $entry_advanced[0]) { - - # root can happily chroot - if ( $> == 0 ) { - - if ( err_custom("lilo -v -C brlilo.conf -r $mnt", - "gBootRoot: ERROR: lilo failed") == 2 ) { - chdir($pwd); - return; - } - - } - - # At this point the normal user needs to be asked first if they have - # root lilo power, before going on. - else { - - # Ask the user if they have su lilo priviliges. - # Hopefully, password free, but that can be incorporated. - mtab(3); - do { - if ( $mtab == 2 ) { - undef $mtab; - chdir($pwd); - return if errum(sys("umount $mnt")) == 2; - return; - } - while (Gtk->events_pending) { Gtk->main_iteration; } - } while $mtab; - - # It's o.k. if lilo fails. - if ( err_custom("$main::sudo lilo -v -C $mnt/brlilo.conf -b $entry_advanced[0]", "gBootRoot: ERROR: lilo failed") == 2 ) { - chdir($pwd); - } - - } - - } - - - $remain_boot = $remain_boot - (stat("$mnt/boot/map"))[12]/2; - $entry5->set_text("$remain_boot k"); - pb($B,8); - - chdir($pwd); # or die "boot_root: ERROR: Could not change directories\n"; - - info(0, "Umounting $mnt\n"); - my $um = errum(sys("umount $mnt")); - pb($B,10); - - if ($ok == 1 || $ok == 2) { - if ( $fs_type ne "genext2fs" ) { - return if - errrm(sys("rmdir $tmp/initrd_mnt")) == 2; - } - } - -# Here's where we copy over that compressed filesystem -# We could separate $container[BOOT_DEVICE] = boot,root allowing two -# different devices to be used. -- now there is $entry_advanced[3] which -# is the ROOT_DEVICE -if ($um == 0 ) { - mtab(1); -} -else { - error_window("gBootRoot: ERROR: Boot disk was never umounted"); -} # copy over the compressed - -} # end sub lilo_put_it_together - -sub device2 { - - my $fs_type = (split(/\s/,$main::makefs))[0]; - - # Time to do a little calculations - my $device_size; - if ( $fs_type ne "genext2fs" ) { - $device_size = (split(/\s+/,`df $mnt`))[8]; - } - else { - if ( !$root_device_size ) { - $device_size = $container[SIZE]; - } - else { - $device_size = $root_device_size; - } - } - - my $root_image_size = (stat($container[ROOT_FS]))[12]/2; - my $remain_root = $device_size - $root_image_size; - - if ($remain_root =~ /^-+\d+$/) { - error_window("gBootRoot: ERROR: Not enough room: root stuff = $root_image_size k, device = $device_size k"); - } - else { - $entry5->set_text("$remain_root k"); - } - - info(0, "Copy over the compressed filesystem\n"); - if ( $fs_type ne "genext2fs" ) { - return if errrm(sys("rmdir $mnt/lost+found")) == 2; - } - my $broot_image = basename($container[ROOT_FS]); - - # Status output, use FH, or genext2fs to create disk. - #---------------------------------------------------- - my $FS = "filesystem"; - my $line_count = `wc -l < $container[ROOT_FS]`; chomp $line_count; - my $half_line_count = $line_count/2; - my $count = 1; - - if ( $fs_type ne "genext2fs" ) { - open(CF, ">$mnt/$broot_image") or error_window( - "gBootRoot: ERROR: Could not copy over the root filesystem") and return; - - open(CR, "$container[ROOT_FS]") or error_window( - "gBootRoot: ERROR: Could not copy over the root filesystem") and return; - - while () { - print CF $_; - pb($FS,$count,$line_count) if $count < $half_line_count; - $count++; - } - close(CF); - close(CR); - } - - # genext2fs - else { - - my $error; - - # If genext2fs is being used clean $tmp/rootdisk if any garbage is - # found. - if ( $fs_type eq "genext2fs" ) { - if (-d "$tmp/rootdisk") { - sys("rm -rf $tmp/rootdisk"); - } - if (!-d "$tmp/rootdisk") { - return if errmk(sys("mkdir $tmp/rootdisk")) == 2; - } - } - - return if errcp( sys("cp -a $container[ROOT_FS] $tmp/rootdisk") ) == 2; - - for ( $count .. $half_line_count ) { - pb($FS,$count,$line_count) if $count < $half_line_count; - $count++; - } - - - if ( - sys("/usr/lib/bootroot/$main::makefs -b $device_size -d $mnt $entry_advanced[3]") !~ - /^0$/ ) { - info( 0, "/usr/lib/bootroot/$main::makefs -b $device_size -d $tmp/rootdisk $entry_advanced[3]\n"); - $error = error("Cannot $fs_type filesystem.\n"); - return "ERROR" if $error && $error eq "ERROR"; - } - - - } - #------------------------------------------------------ - - if ( $fs_type ne "genext2fs" ) { - return if - err_custom("umount $mnt", - "gBootRoot: ERROR: Root disk did not properly umount") == 2; - } - - pb($FS,$count,$line_count); - info(0, "Finished!\n"); - -} # end sub device 2 - -# Checks if lib or bin is stripped, if not proceeds to strip. Returns -# full file path and strip result. Right now this is specific to initrd. -sub stripper { - - # stripper (program,bin|lib|mod); - if ((!defined $lib_strip_check && !defined $bin_strip_check - && !defined $mod_strip_check) or - ($lib_strip_check->active || $bin_strip_check->active - || $mod_strip_check->active)) { - - # DON'T DO THIS >/dev/null 2>&1`; - my $not_stripped = `file $_[0] 2> /dev/null`; - my $filename = basename($_[0]); - - if ($not_stripped =~ m,not stripped,) { - if (($_[1] eq "lib" && !defined $lib_strip_check) or - ($_[1] eq "lib" && $lib_strip_check->active)) { - # --strip-all works for initrd - if ($obj_count == 0) { - sys("objcopy --strip-debug -p $_[0] $tmp/$filename"); - info(1,"--strip-debug $filename\n"); - return ( "$tmp/$filename", 1 ); - } - elsif ($obj_count == 1) { - sys("objcopy --strip-all -p $_[0] $tmp/$filename"); - info(1,"--strip-all $filename\n"); - return ( "$tmp/$filename", 1 ); - } - } - elsif (($_[1] eq "bin" && !defined $bin_strip_check) or - ($_[1] eq "bin" && $bin_strip_check->active)) { - sys("objcopy --strip-all -p $_[0] $tmp/$filename"); - info(1,"--strip-all $filename\n"); - return ( "$tmp/$filename", 1 ); - } - elsif (($_[1] eq "mod" && !defined $mod_strip_check) or - ($_[1] eq "mod" && $mod_strip_check->active)) { - sys("objcopy --strip-debug -p $_[0] $tmp/$filename"); - info(1,"--strip-debug $filename\n"); - return ( "$tmp/$filename", 1 ); - } - } - else { - return ( $_[0], 0 ); - } - } - return ( $_[0], 0); - -} # end sub stripper - -sub two_disk_compression_check { - - my ($ash,$lilo,$bzip2,$file); - - if ( !find_file_in_path("ash") ) { - $ash = "ash"; - } - - if ( !find_file_in_path("lilo") ) { - $lilo = "lilo"; - } - - if ( !find_file_in_path("bzip2") ) { - $bzip2 = "bzip2"; - } - - if ( !find_file_in_path("file") ) { - $file = "file"; - } - - if ( $ash || - - $lilo || - - $bzip2 || - - $ash - - ) { - - error_window( - "Program(s) required by this method: $lilo $ash $bzip2 $file" - ); - - return 1; - } - - -} # end sub two_disk_compression_check - -sub kernel_modules { - - my (@modules, @modules_found); - - my $module_choices = $ea3->get_text() if $ea3; - my $kernel_version_choice = $ea5->get_text() if $ea5; - undef $kernel_version_choice if defined $kernel_version_choice eq ""; - undef $kernel_version_choice if !$kernel_version_choice; - - $kernel_version = kernel_version_check($container[KERNEL], - $kernel_version_choice); - #----------------------------- - # METHOD -> 2 DISK COMPRESSION - #----------------------------- - if ( $container[METHOD] eq "2 disk compression" ) { - - $entry_advanced[11] = "floppy"; - - if ($ea3) { - if ($module_choices eq "") { - $ea3->set_text("floppy"); - $module_choices = "floppy"; - } - else { - $ea3->set_text($ea3->get_text() . " floppy") - if $ea3->get_text() !~ /\s*floppy\s*/; - $module_choices = $ea3->get_text(); - } - } - else { - $module_choices = "floppy"; - } - - @modules = split(/\s+/, $module_choices); - - } - - info(1, "Modules: @modules\n"); - - - # Figure out modules path. - if ( @modules ) { - foreach my $module (@modules) { - finddepth sub { if ( $File::Find::name =~ m,/$module\.o$, ) { - push(@modules_found,$File::Find::name); - } }, - "$modules_directory/$kernel_version"; - - } - } - - $, = " "; - info(1,"Modules found:\n@modules_found\n"); - $, = ""; - - return @modules_found; - - -} # end sub kernel_modules - - -sub initrd_size { - - info(0,"Boot Method: 2 disk\n", - "Type: initrd boot disk with LILO/root filesystem disk\n"); - - my ($linuxrc_size) = @_; - my ($what,$lib); - my ($path,$value); - info(0, "Checking size needed for initrd\n"); - - # the size of the loop device should be at least 1.63% larger than what - # it will contain (i.e. 8192 inode), but to keep on the safe size it will - # be 2.00% larger. - - # Unforturnately, stat is being done on - # the actual live fs, whereas the loop filesystem may be different. In - # general the check is quite conservative and will always leave room. - # Stat seems to view things differently based on the situation, and - # -s file has another opinion, for now stat will be used and perhaps - # the actual filesystem in the future. Better extra room than too little. - - # 9 dirs = 1024 each (increase if modified) - # {ash,gzip,mount,umount} (required executables) - # bzip2 if $compress eq bzip2 (optional) - # 1 for ld.so.cache - - # change dir size if needed - my $dir_size = 9 + 1; - my $initrd_size = $dir_size + $linuxrc_size; - - # clean initrd_mnt if any garbage is found. - if (-d "$tmp/initrd_mnt") { - sys("rm -rf $tmp/initrd_mnt"); - } - if (!-d "$tmp/initrd_mnt") { - return if errmk(sys("mkdir $tmp/initrd_mnt")) == 2; - } - - # modules - see CVS:1.65 for previous non-size check. - my @modules = kernel_modules(); - if (@modules) { - - my $tool; - - # dirs sizes, just assuming 1024 - my $ds = mkpath("$tmp/initrd_mnt/lib/modules/$kernel_version"); - $initrd_size = $initrd_size + ($ds - 1); - - # copy over the modules - foreach my $stuff (@modules) { - ($path,$value) = stripper($stuff,"mod"); - - $value == 0 ? ($tool = "cp -a") : ($tool = "mv"); - if (!$path) { - info(1,"gBootRoot Error: Couldn't find $stuff\n"); - } - - # copy stuff to proper directory and unlink size tester - return if - errcp(sys("$tool $path $tmp/initrd_mnt/lib/modules/$kernel_version")) == 2; - unlink($path) if $value == 1; - } - - # Do the depmod operation - - if ($entry_advanced[13] && $entry_advanced[13] ne "") { - - if ( $> == 0 ) { - - return if err_custom("depmod -ae -F $entry_advanced[13] -b $tmp/initrd_mnt $kernel_version", "gBootRoot: ERROR: depmod failed") == 2; - - } - else { - - return if err_custom("depmod -aer -F $entry_advanced[13] -b $tmp/initrd_mnt $kernel_version", "gBootRoot: ERROR: depmod failed") == 2; - - - } - - } # $entry_advanced[13] defined - - else { - - if ( $> == 0 ) { - - return if err_custom("depmod -ae -b $tmp/initrd_mnt $kernel_version", "gBootRoot: ERROR: depmod failed") == 2; - - } - else { - - return if err_custom("depmod -aer -b $tmp/initrd_mnt $kernel_version", "gBootRoot: ERROR: depmod failed") == 2; - - } - - } - - - # Check all the files in the dirctory for their size, and unlink them. - opendir(DIR,"$tmp/initrd_mnt/lib/modules/$kernel_version") - or info(1,"Failed to open $tmp/initrd_mnt/$kernel_version"); - my @module_stuff = grep { /\w+/ } readdir(DIR); - close(DIR); - - # Figure out the size for all the stuff created by depmod and the - # modules included. - foreach my $stuff (@module_stuff) { - $initrd_size = $initrd_size + - ((stat("$tmp/initrd_mnt/lib/modules/$kernel_version/$stuff"))[12]/2); - unlink("$tmp/initrd_mnt/lib/modules/$kernel_version/$stuff"); - } - - - # The modules directory has to be removed here. - return if - errrm(sys("rmdir $tmp/initrd_mnt/lib/modules/$kernel_version")) == 2; - return if - errrm(sys("rmdir $tmp/initrd_mnt/lib/modules")) == 2; - return if - errrm(sys("rmdir $tmp/initrd_mnt/lib/")) == 2; - - - } # end if (@modules) - - - # This and libs should be user accessible - # add other executables here - my @initrd_stuff; - if (@modules) { - @initrd_stuff = qw(ash gzip mount umount modprobe insmod); - } - else { - @initrd_stuff = qw(ash gzip mount umount); - } - - foreach (@initrd_stuff) { - if ( !readlink($_) ) { - ($path,$value) = stripper(find_file_in_path($_),"bin"); - $initrd_size = $initrd_size + ((stat($path))[12]/2); - unlink($path) if $value == 1; - } - else { - $initrd_size = $initrd_size + - length(readlink(find_file_in_path($_))); - } - } - - if ($compress eq "bzip2" && -e find_file_in_path($compress)) { - ($path,$value) = stripper(find_file_in_path($compress),"bin"); - $initrd_size = $initrd_size + ((stat($path))[12]/2); - unlink($path) if $value == 1; - } - - my $lib_tester; - if ($bz2_toggle->active && -x find_file_in_path("bzip2") ) { - - $lib_tester = find_file_in_path("bzip2"); - - } - else { - - $lib_tester = find_file_in_path("init"); - - } - - my $dir; - - # lib sizes This is going to be improved later with library_dependencies - open(L,"ldd $lib_tester|") or die "Oops, no init could be found :)\n"; # safe to use ldd - while () { - my $place; - ($lib,$place) = (split(/=>/,$_))[0,1]; - $place = (split(" ",$place))[0]; - $lib =~ s/\s+//; - $lib = basename($lib); - $lib =~ s/\s+$//; - $dir = dirname($place); - - open (SL,"ls -l $dir/$lib|") or die "humm: $!\n"; - while () { - # symbolic link - if (-l "$dir/$lib") { - $what = (split(/\s+/,$_))[10]; - $initrd_size = $initrd_size + 1; - ($path,$value) = stripper("$dir/$lib","lib"); - $initrd_size = $initrd_size + ((stat($path))[12]/2); - unlink($path) if $value == 1; - } - # no symbolic link - else { - ($path,$value) = stripper("$dir/$lib","lib"); - $initrd_size = $initrd_size + ((stat($path))[12]/2); - unlink($path) if $value == 1; - } - } - } - - $initrd_size = $initrd_size + ($initrd_size * 0.02); - - # For perfection 1 (rounded up) is o.k., but for safety 10 would be - # better - $initrd_size = sprintf("%.f",$initrd_size) + 10; - return $initrd_size; - -} # end sub initrd_size - -sub pb { - - # Will have to count by hand - if ($_[0] eq "initrd") { - $pbar->configure( 10, 0, 10 ); - } - elsif ($_[0] eq "boot") { - $pbar->configure( 10, 0, 10 ); - } - elsif ($_[0] eq "filesystem") { - $pbar->configure($_[2], 0, $_[2]); - } - - $pbar->set_value($_[1]); - # Found this at Gnome .. - # http://www.uk.gnome.org/mailing-lists/archives/gtk-list/ - # 1999-October/0401.shtml - # Also, http://www.gtk.org/faq/ 5.14 - while (Gtk->events_pending) { Gtk->main_iteration; } - -} - -sub initrd { - - my($kernel,$root_image,$device,$size) = @_; - my($lib,$what,$path,$value,$tool); - my $I = "initrd"; - - # Basically this means the ARS was never opened or edited and the - # default behavior is to use the same device. - if ( !$entry_advanced[3] ) { - $device = $container[BOOT_DEVICE]; - } - else { - $device = $entry_advanced[3]; - } - - - my $fs_type = (split(/\s/,$main::makefs))[0]; - - if ( $fs_type eq "genext2fs" ) { - # Assuming busybox is being used, so bzip2 should still be standard - # just another link .. just for testing. - if ( $compress eq "bzip2" ) { - $compress = "bunzip2"; - } - } - - my $broot_image = basename($root_image); - open(LC, ">$tmp/linuxrc") or die "Couldn't write linuxrc to loop device\n"; - print LC initrd_heredoc($broot_image,$device); close(LC); - pb($I,1); - my $size_needed = initrd_size((stat("$tmp/linuxrc"))[12]/2); - unlink("$tmp/linuxrc"); - - - if ( $fs_type ne "genext2fs" ) { - - info(0, "Using loop device to make initrd\n"); - info(0, "Make sure you have loop device capability" . - " in your running kernel\n"); - sys("dd if=/dev/zero of=$tmp/$initrd bs=1024 count=$size_needed"); - pb($I,2); - # no need to enter y every time .. could use -F - my $error; - open(T,"|mke2fs -F -m0 -i8192 $tmp/$initrd >/dev/null 2>&1") or - ($error = error("Can not make ext2 filesystem on initrd.\n")); - return "ERROR" if $error && $error eq "ERROR"; - print T "y\n"; close(T); - pb($I,3); - info(0, "Mounting initrd in $tmp/initrd_mnt\n"); - - } - - # clean initrd_mnt if any garbage is found. - if (-d "$tmp/initrd_mnt") { - sys("rm -rf $tmp/initrd_mnt"); - } - if (!-d "$tmp/initrd_mnt") { - return if errmk(sys("mkdir $tmp/initrd_mnt")) == 2; - } - - - # Here the loop device is made on tmp, not mnt - if ( $fs_type eq "genext2fs" ) { - info(0, "Using genext2fs to make initrd rather than a loop device\n"); - } - - else { - if ( $> == 0 ) { - return if errm(sys("mount -o loop -t ext2 $tmp/$initrd $tmp/initrd_mnt")) == 2; - } - else { - return if errm(sys("mount $tmp/initrd_mnt")) == 2; - } - } - pb($I,4); - - info(0, "Putting everything together\n"); - if ( $fs_type eq "genext2fs" ) { - open(LC, ">$tmp/initrd_mnt/linuxrc") or die "Couldn't write linuxrc to $tmp/initrd_mnt\n"; - } - else { - open(LC, ">$tmp/initrd_mnt/linuxrc") or die "Couldn't write linuxrc to loop device\n"; - } - print LC initrd_heredoc($broot_image,$device); close(LC); - # I could test this but somebody's system may do permissions differently - sys("chmod 755 $tmp/initrd_mnt/linuxrc"); - if ($fs_type ne "genext2fs" ) { - sys("rmdir $tmp/initrd_mnt/lost+found"); - } - pb($I,5); - - info(0, "... the dirs\n"); - return if errmk( - sys("mkdir $tmp/initrd_mnt/{bin,dev,etc,lib,mnt,proc,sbin,usr}")) == 2; - return if errmk(sys("mkdir $tmp/initrd_mnt/usr/lib")) == 2; - pb($I,6); - - # Hopefully, this works, but have never tested it - o.k I did - if ( $fs_type ne "genext2fs" ) { - if ($container[BOOT_DEVICE] !~ m,/dev/fd\d{1}$,) { - return if err(sys("cp -a $container[BOOT_DEVICE] $mnt/dev")) == 2; - } - } - - # DEVICES SECTION - my @devices; - my $device_table = "$tmp/initrd_device_table.txt"; - if ( $fs_type eq "genext2fs" ) { - - info(0, "Making $device_table for genext2fs\n"); - my $error; - unlink( $device_table ) if -e $device_table; - - # - # /dev is always needs to be made automatically - open(BootRoot::Yard::DEVICE_TABLE, ">$device_table") or - ($error = error("$device_table: $!")); - return "ERROR"if $error && $error eq "ERROR"; - - print BootRoot::Yard::DEVICE_TABLE - "# \t\t\t\t\t\t" . - "\t\t\t\n"; - print BootRoot::Yard::DEVICE_TABLE "/dev\t\td\t0755\t-\t-\t-\t-\t-\t-\t-\n"; - - # Keep a record of the devices required - @devices = qw(/dev/console dev/null /dev/ram0 /dev/ram1 /dev/tty0); - for ( split(" ", $container[BOOT_DEVICE] ) ) { - push(@devices, $_ ) if $_; - } - - device_table( @devices ); - close(BootRoot::Yard::DEVICE_TABLE); - - } - - else { - - if ( $> == 0 ) { - info(0, "Copying over devices to $tmp/initrd_mnt/dev\n"); - return if errcp( - sys("cp -a /dev/{console,null,ram0,ram1,tty0} $tmp/initrd_mnt/dev") - ) == 2; - return if errcp( - sys("cp -a $container[BOOT_DEVICE] $tmp/initrd_mnt/dev")) == 2; - } - else { - info(0, "Mknod devices at $tmp/initrd_mnt/dev\n"); - # This could be replaced by a devfs. - sys("$main::sudo mknod c 5 1 $tmp/initrd_mnt/dev/console"); - sys("$main::sudo mknod c 1 3 $tmp/initrd_mnt/dev/null"); - sys("$main::sudo mknod b 1 0 $tmp/initrd_mnt/dev/ram0"); - sys("$main::sudo mknod b 1 1 $tmp/initrd_mnt/dev/ram1"); - sys("$main::sudo mknod c 4 0 $tmp/initrd_mnt/dev/tty0"); - sys("$main::sudo mknod b 2 0 $tmp/initrd_mnt/dev/fd0"); - } - - } # end DEVICES SECTION - - pb($I,7); - - # This and libs should be user accessible - info(0, ".. the modules\n"); - my @modules = kernel_modules(); - - if (@modules) { - - mkpath("$tmp/initrd_mnt/lib/modules/$kernel_version"); - - foreach my $stuff (@modules) { - ($path,$value) = stripper($stuff,"mod"); - $value == 0 ? ($tool = "cp -a") : ($tool = "mv"); - if (!$path) { - info(1,"gBootRoot Error: Couldn't find $stuff\n"); - } - return if - errcp(sys("$tool $path $tmp/initrd_mnt/lib/modules/$kernel_version")) == 2; - } - - if ($entry_advanced[13] && $entry_advanced[13] ne "") { - - if ( $> == 0 ) { - - info(1, "depmod -ae -F $entry_advanced[13] -b $tmp/initrd_mnt/lib/modules/$kernel_version $kernel_version\n"); - return if err_custom("depmod -ae -F $entry_advanced[13] -b $tmp/initrd_mnt $kernel_version", "gBootRoot: ERROR: depmod failed") == 2; - - } - else { - - info(1, "depmod -aer -F $entry_advanced[13] -b $tmp/initrd_mnt/lib/modules/$kernel_version $kernel_version\n"); - return if err_custom("depmod -aer -F $entry_advanced[13] -b $tmp/initrd_mnt $kernel_version", "gBootRoot: ERROR: depmod failed") == 2; - - } - - } # $entry_advanced[13] defined - else { - - if ( $> == 0 ) { - - info(1, "depmod -ae -b $tmp/initrd_mnt/lib/modules/$kernel_version $kernel_version\n"); - return if err_custom("depmod -ae -b $tmp/initrd_mnt $kernel_version", "gBootRoot: ERROR: depmod failed") == 2; - - } - else { - - info(1, "depmod -aer -b $tmp/initrd_mnt/lib/modules/$kernel_version $kernel_version\n"); - return if err_custom("depmod -aer -b $tmp/initrd_mnt $kernel_version", "gBootRoot: ERROR: depmod failed") == 2; - - } - - } - - } - - info(0, ".. the bins\n"); - my @initrd_stuff; - if (@modules) { - @initrd_stuff = qw(ash gzip mount umount modprobe insmod); - } - else { - @initrd_stuff = qw(ash gzip mount umount); - } - - # Will put the stuff in sbin because the is where the kernel looks for - # modprobe. - if ( ! $busybox ) { - - foreach (@initrd_stuff) { - ($path,$value) = stripper(find_file_in_path($_),"bin"); - $value == 0 ? ($tool = "cp -a") : ($tool = "mv"); - if (!$path) { - info(1,"gBootRoot Error: Couldn't find $_\n"); - } - return if errcp(sys("$tool $path $tmp/initrd_mnt/sbin")) == 2; - } - - if ($compress eq "bzip2" && -e find_file_in_path($compress)) { - ($path,$value) = stripper(find_file_in_path($compress),"bin"); - $value == 0 ? ($tool = "cp -a") : ($tool = "mv"); - return if errcp(sys("$tool $path $tmp/initrd_mnt/sbin")) == 2; - } - - # Testing if init is sufficient for grabbing the correct libraries for the - # executables immediately above. This could be modified to test a - # list of executables. Now bzip2 uses libbz2.so.1.0, so if bzip2 is - # present on the system this will be the tester instead, and size - # has to be figured out differently. - info(0, ".. the libs\n"); - - my $lib_tester; - if ($bz2_toggle->active && -x find_file_in_path("bzip2") ) { - - $lib_tester = find_file_in_path("bzip2"); - - } - else { - - $lib_tester = find_file_in_path("init"); - - } - - my $dir; - - open(L,"ldd $lib_tester|") or die "Oops, no $lib_tester could be found :)\n"; # safe to use ldd, this is going to be fixed later with library_dependencies - while () { - my $place; - ($lib,$place) = (split(/=>/,$_))[0,1]; - $place = (split(" ",$place))[0]; - $lib =~ s/\s+//; - $lib = basename($lib); - $lib =~ s/\s+$//; - $dir = dirname($place); - info(0,"$dir/$lib\n"); - open (SL,"ls -l $dir/$lib|") or die "humm: $!\n"; - while () { - # symbolic link - if (-l "$dir/$lib") { - $what = (split(/\s+/,$_))[10]; - ($path,$value) = stripper("$dir/$lib","lib"); - $value == 0 ? ($tool = "cp -a") : ($tool = "mv"); - return if errcp(sys("$tool $path $tmp/initrd_mnt$dir")) == 2; - ($path,$value) = stripper("$dir/$what","lib"); - $value == 0 ? ($tool = "cp -a") : ($tool = "mv"); - return if errcp(sys("$tool $path $tmp/initrd_mnt$dir")) == 2; - } - # no symbolic link - else { - ($path,$value) = stripper("$dir/$lib","lib"); - return if errcp(sys("cp -a $path $tmp/initrd_mnt$dir")) == 2; - } - } - } - - } # not busybox - - else { - - my $error; - - # busybox binary - $tool = "cp -a"; - $path = "/home/mttrader/busybox/busybox/busybox"; - return if errcp(sys("$tool $path $tmp/initrd_mnt/sbin")) == 2; - - #Currently defined functions: - # [, ash, bunzip2, busybox, echo, false, gzip, insmod, modprobe, - # mount, sh, test, true, umount - - my $target = "$tmp/initrd_mnt/sbin/busybox"; - my @busystuff = qw(ash sh bunzip2 echo gzip insmod modprobe mount - umount); - chdir("$tmp/initrd_mnt/sbin/"); - foreach ( @busystuff ) { - - symlink("busybox", "$tmp/initrd_mnt/sbin/$_" ); - - } - - # uClibc - mkpath("$tmp/initrd_mnt/usr/i386-linux-uclibc/lib"); - $path = "/usr/i386-linux-uclibc/lib/libuClibc-0.9.5.so"; - return if errcp(sys("$tool $path $tmp/initrd_mnt/usr/i386-linux-uclibc/lib")) == 2; - sys("chmod 755 $tmp/initrd_mnt/usr/i386-linux-uclibc/lib/libuClibc-0.9.5.so"); - chdir("$tmp/initrd_mnt/lib"); - symlink("../usr/i386-linux-uclibc/lib/libuClibc-0.9.5.so", "$tmp/initrd_mnt/lib/libc.so.0" ); - - $path = "/usr/i386-linux-uclibc/lib/ld-uClibc-0.9.5.so"; - return if errcp(sys("$tool $path $tmp/initrd_mnt/usr/i386-linux-uclibc/lib")) == 2; - sys("chmod 755 $tmp/initrd_mnt/usr/i386-linux-uclibc/lib/ld-uClibc-0.9.5.so"); - chdir("$tmp/initrd_mnt/usr/i386-linux-uclibc/lib"); - symlink("ld-uClibc-0.9.5.so", "$tmp/initrd_mnt/usr/i386-linux-uclibc/lib/ld-uClibc.so.0" ); - - } - - - info(0, "Determine run-time link bindings\n"); - # Has a return code of 0 regardless - # Also, produces false alarms even when it is working. - info(1, "Ignore warnings about missing directories\n"); - sys("ldconfig -v -r $tmp/initrd_mnt"); - - - if ( $fs_type eq "genext2fs" ) { - info(0, "Using genext2fs to contruct the initrd\n"); - # The -D option is unique to the newest unreleased version of - # genextfs modified by BusyBox maintainer Erick Andersen - # August 20, 2001. - - my $error; - - # genext2fs doesn't make accurate sized filesystems. - # this will be user adjustable in the future. - $size_needed = $size_needed + 1000; - - if ( - sys("/usr/lib/bootroot/$main::makefs -b $size_needed -d $tmp/initrd_mnt -D $device_table $tmp/$initrd") !~ - /^0$/ ) { - $error = error("Cannot $fs_type filesystem.\n"); - return "ERROR" if $error && $error eq "ERROR"; - } - - } - - else { - chdir($pwd); - info(0, "Umounting loop device, and compressing initrd\n"); - return if errum(sys("umount $tmp/initrd_mnt")) == 2; - } - - info(0, "Compressing initrd\n"); - sys("gzip -f9 $tmp/$initrd"); - - pb($I,10); # This takes the longest. - - $initrd = $initrd . ".gz"; - -} # end sub initrd - -# This was submitted by Cristian "cretzu." -sub gdkbirdaao { - - # Guess Default Kernel Boot Image Root Device And Append Options - #(gdbirdaao) - # - # We return a list with 3 elements: - # - # root device, kernel boot image path and append options - # - # The last list element (append options) could be returned as a list - # of options, but it probably might be cleaner if the caller splitted it. - # - # this should cover the following cases: - # - # 1. we have a 'root=...' somewhere above the 'image=...' block(s), and - # the image block may or may not have a root specified - # - # 2. there is no default label, in which case, we take the first one - # - # 3. there is a default label, and that's what we pick up - # - - my $ret_image_path = ''; - my $ret_root_dev = ''; - my $ret_append = ''; - - - # enough of the annoying "perhaps you are not root" - # ofcourse this test is always ran assuming lilo is used. - if ( $> == 0 ) { - - if ( !$container[METHOD] || - $container[METHOD] eq "2 disk compression" ) { - - if (-e $lilo_conf and !-d $lilo_conf) { - - my @lilo_lines; - open(LIL, $lilo_conf) or - warn "*** $lilo_conf not found\n"; - @lilo_lines = ; - close(LIL); - chomp(@lilo_lines); - - my $default_label = ''; - my %image_blocks; - my $image_block_name_prefix = 'ImageBlock'; - my $image_block_no = 1; - my $image_block_name = ''; - my $root_dev = ''; - - for (@lilo_lines) { - # ignore comment lines - next if m/^\s*[#]/; - - # cleanup whitespace - s/\s*//; - s/\s*$//; - s/\s*=\s*/=/; - - # 'default=whatever' returns just a label - if (m/default=(.+)\s*/) { - $default_label = $1; - } - # start of a new 'image=' - # image block or similar - elsif (m/(image|other)=(.+)\s*/) { - $image_block_name = - sprintf("%s%02d", - $image_block_name_prefix, - $image_block_no); - $image_blocks{$image_block_name} - {'kernel_image_path'} = $2; - $image_blocks{$image_block_name} - {'root_device'} = $root_dev; - $image_block_no += 1; - } - # image block label - elsif (m/label=(.+)\s*/) { - $image_blocks{$image_block_name} - {'block_label'} = $1; - } - # 'root=' - elsif (m#root=/dev/(.+)\s*#) { - # inside an image block - if ($image_block_name and - defined($image_blocks - {$image_block_name} - {'root_device'})) { - $image_blocks{$image_block_name} - {'root_device'} = $1; - } - # loose - else { - $root_dev = $1 if !$root_dev; - } - } - elsif (m#append=\"(.+)\"#) { - $image_blocks{$image_block_name} - {'append'} = $1; - } - else { - # Ignore everything else - } - } - - # we'll now find the kernel image and root device - foreach $image_block_name (sort keys %image_blocks) { - # Assume there's no specified default label; - # take the first - $ret_root_dev = - $image_blocks{$image_block_name}{'root_device'} - if !$ret_root_dev; - $ret_image_path = - $image_blocks{$image_block_name} - {'kernel_image_path'} - if !$ret_image_path; - $ret_append = - $image_blocks{$image_block_name}{'append'} - if !$ret_append; - - # do we have a default kernel? - if (defined $image_blocks{$image_block_name} - {'block_label'}) { - if ($image_blocks{$image_block_name} - {'block_label'} eq $default_label) { - # Found the block match for the default label - $ret_root_dev = - $image_blocks{$image_block_name} - {'root_device'}; - $ret_image_path = - $image_blocks{$image_block_name} - {'kernel_image_path'}; - $ret_append = $image_blocks - {$image_block_name}{'append'}; - last; - } - } - } - } - - - } # if METHOD eq 2 disk compression - - } # if not root - - # and some a small portion of paranoia - $ret_root_dev = 'hda1' if !$ret_root_dev; - - return ($ret_root_dev, $ret_image_path, $ret_append); - -} # end sub gdkbirdaao - -########### -# Mtab area -########### - -sub mtab_window { -# Will just use a dialog box. - my ($dialog,$error,$count,$pattern) = @_; - - if (not defined $mtab) { - $mtab = Gtk::Dialog->new(); - $mtab->signal_connect("destroy", \&destroy_window, \$mtab); - $mtab->signal_connect("delete_event", \&destroy_window, \$mtab); - $mtab->set_title("gBootRoot: Device check"); - $mtab->border_width(15); - $mtab->set_position('center'); - my $label = Gtk::Label->new($dialog); - $label->set_justify( 'left' ); - $label->set_pattern("_________") if $pattern == 9; - $label->set_pattern("_____") if $pattern == 5; - $mtab->vbox->pack_start( $label, $true, $true, 15 ); - $label->show(); - my $button = Gtk::Button->new("OK"); - $button->signal_connect("clicked", \&mtab_check, $count); - $button->can_default(1); - $mtab->action_area->pack_start($button, $false, $false,0); - $button->grab_default; - $button->show; - $button = Gtk::Button->new("Cancel"); - $button->signal_connect("clicked", sub { destroy $mtab; - $mtab = 2 if $count == 3; } ); - $mtab->action_area->pack_start($button, $false, $false,0); - $button->show; - } - if (!visible $mtab) { - show $mtab; - } - else { - destroy $mtab; - mtab_window($dialog,$error,$count) if $error == 0; - } - -} # end sub mtab_window - -sub mtab{ - -# /proc/mount could be used, but maybe there is no /proc -# Press OK when drive and storage medium are ready. The drive should not -# be mounted. - - if ($_[0] == 0) { - my $dialog = "BOOTDISK:\n" - ."Press OK when the drive and its storage medium is ready.\n" - ."The Boot Disk will now be made. All data already on\n" - ."the storage medium will be erased."; - mtab_window($dialog,1,$_[0],9); - } - elsif ($_[0] == 1) { - my $dialog = "ROOTDISK:\n" - ."Press OK when the drive and its storage medium is ready.\n" - ."The Root Disk will now be made. All data already on\n" - ."the storage medium will be erased."; - mtab_window($dialog,1,$_[0],9); - } - elsif ( $_[0] == 3 ) { - my $dialog = "LILO:\n" - ."Lilo will now be executed. In order for the bootloader\n" - ."to work properly you need superuser privileges to run lilo.\n" - ."See FAQ for ways to accomplish this. Even if you don't have\n" - ."privileges, the program will continue to make a boot disk.\n" - ."Lilo may be ran as root at a later time on the boot disk."; - mtab_window($dialog,3,$_[0],5); - } - - -} # end sub mtab - - -sub mtab_check { - - my($widget,$count) = @_; - - my $dialog; - my $error = 1; - - my $fs_type = (split(/\s/,$main::makefs))[0]; - -# Check to see if $device is mounted - - if ( $count < 3 ) { - open (MTAB, "/etc/mtab") or die "no mtab!\n"; - while () { - - if ($count == 1) { - - # ROOT_DEVICE - if ( m,$entry_advanced[3], ) { - # Safety Check: - $dialog = - "Please umount the device first.\nPress OK when you are ready."; - $error = 0; - } - - } - - elsif ( $count == 0 ) { - - # BOOT_DEVICE - if (m,$entry_advanced[0],) { - # Safety Check: - $dialog = - "Please umount the device first.\nPress OK when you are ready."; - $error = 0; - } - - } - - } - close(MTAB); - - } - - mtab_window($dialog,$error,$count) if $error == 0; - - # Make sure the drive and storage medium are accessible - # Keep asking until they are. - if ( $error == 1 && $fs_type ne "genext2fs" ) { - destroy $mtab; - - # $size has to be determined by boot disk or root disk - - # ROOT_DEVICE - test with a loop device - if ($count == 1) { - sys("mke2fs -F -m0 -i8192 $entry_advanced[3] $root_device_size"); - } - - - # BOOT_DEVICE - elsif ($count == 0) { - sys("mke2fs -F -m0 -i8192 $entry_advanced[0] $container[SIZE]"); - } - - if ($? != 0) { - $dialog = "gBootRoot: ERROR: You need to insert a disk\n"; - mtab_window($dialog,$error,$count); - return; - } - - # ROOT_DEVICE - if ($count == 1) { - if ( $> == 0 ) { - return if errm(sys("mount -t ext2 $entry_advanced[3] $mnt")) == 2; - } - else { - return if errm(sys("mount $mnt")) == 2; - } - } - - # BOOT_DEVICE - elsif ($count == 0) { - if ( $> == 0 ) { - return if errm(sys("mount -t ext2 $entry_advanced[0] $mnt")) == 2; - } - else { - return if errm(sys("mount $mnt")) == 2; - } - } - - - lilo_put_it_together() if $count == 0; # mtab(1) runs from here - device2() if $count == 1; - - } # if $error == 1 - - if ( $fs_type eq "genext2fs" && $error == 1 ) { - - destroy $mtab; - lilo_put_it_together() if $count == 0; # mtab(1) runs from here - device2() if $count == 1; - - } - - # Warned the user about something - if ( $error == 3 ) { - $mtab->destroy; - } - - -} # end sub mtab_check - -################## -# Here Doc Section -################## - -# This should be user accessible -# This should be called linuxrc. -sub initrd_heredoc { - - my($broot_image,$root_device) = @_; - -# Here's where the initrd is put together using a loop device -# HEREDOC -my $initrd_exec = << "INITRD"; -#!/sbin/ash - -export PATH=/bin:/sbin:/usr/bin: - -echo Preparing to setup ramdisk. - -# Before busybox experimentation this was the state of things: -# mount -o remount,rw / 2>/dev/null -# echo Mounting proc... -# mount -t proc none /proc - -echo Mounting proc... -mount -t proc none /proc - -echo Mounting $root_device readable-writable -mount -o remount,rw $root_device / - -echo -n 'Please insert the root floppy, and press [Enter]: ' -read ENTER - -echo Mounting $root_device readonly ... - -# -t causes busybox to fail here, -o doesn't help much either. -#mount -o ro -t ext2 $root_device /mnt -mount $root_device /mnt - -echo -n Copying new root to ramdisk .. please wait ... -$compress -cd /mnt/$broot_image > /dev/ram1 -echo done. - -echo -n Unmounting $root_device ... -umount /mnt -echo done. - -# Using change_root, eventually may change to pivot_root or -# give the user the choice. - -echo Changing to the new root. -echo 257 >/proc/sys/kernel/real-root-dev - -echo -n Unmounting proc ... -umount /proc -echo done. - -echo Continuing normal boot procedure from ramdisk. -INITRD - - return $initrd_exec; - -} # end sub initrd_heredoc - -sub brlilo { - - my ($device) = @_; - $entry_advanced[2] ? $entry_advanced[2] = $entry_advanced[2] - : $entry_advanced[2] = $container[ABS_APPEND]; - -# HEREDOC -my $brlilo = << "LILOCONF"; -boot = $device -message = message -delay = 50 -vga = normal -install = /boot/boot.b -map = /boot/map -backup = /dev/null -compact - -# bootdisk -image = kernel -append = "load_ramdisk=1 debug $entry_advanced[2]" -initrd = $initrd -root = $device -label = bootdisk -read-write - -# normalboot -image = kernel -append = "$entry_advanced[2]" -root = /dev/$norm_root_device -label = normalboot -read-only -LILOCONF - - return $brlilo; - -} # end sub brlilo - - -sub brlilo_non_root { - - my ($device) = @_; - $entry_advanced[2] ? $entry_advanced[2] = $entry_advanced[2] - : $entry_advanced[2] = $container[ABS_APPEND]; - -# HEREDOC -my $brlilo = << "LILOCONF"; -boot = $device -message = $old_mount/message -delay = 50 -vga = normal -install = $old_mount/boot/boot.b -map = $old_mount/boot/map -backup = /dev/null -compact - -# bootdisk -image = $old_mount/kernel -append = "load_ramdisk=1 debug $entry_advanced[2]" -initrd = $old_mount/$initrd -root = $device -label = bootdisk -read-write - -# normalboot -#image = kernel -#append = "$entry_advanced[2]" -#root = /dev/$norm_root_device -#label = normalboot -#read-only -LILOCONF - - return $brlilo; - -} # end sub brlilo_non_root - - -sub message { -# HEREDOC -my $message = << "MESSAGE"; - -gBootRoot $version $date GNU GPL -mailto: Jonathan Rosenbaum - -Press [Ctrl] to see the lilo prompt. - -Press [Tab] to see a list of boot options. - -bootdisk = This will boot a compressed root filesystem - on another floppy. -normalboot = This will boot up a specified filesystem. - default: /dev/$norm_root_device - Use root=/dev/(h or s)dXX - h = IDE Drive - s = SCSI Drive - -Trouble: Do not forget boot: option single -Fix a filesystem: e2fsck /dev/(h or s)dXX -Bad superblock: e2fsck -b 8192 /dev/(h or s)dXX - -MESSAGE - - return $message; - -} # end sub message - -sub help { - -<< "HELP"; - -gBootRoot $version $date GNU GPL - -Email contact -> Jonathan Rosenbaum - -Homepage -> http://gbootroot.sourceforge.net -Submit a Bug -> http://sourceforge.net/bugs/?group_id=9513 -Devel. & Releases -> http://sourceforge.net/projects/gbootroot - -Places to talk: - -gbootroot-{devel,user} mailing lists -> http://sourceforge.net/mail/?group_id=9513 -Help forum -> http://sourceforge.net/forum/forum.php?forum_id=29639 -Open forum -> http://sourceforge.net/forum/forum.php?forum_id=29638 - -gbootroot documentation and FAQ: - -/usr/share/doc/gbootroot/html/index.html - -How to Use gBootRoot: - -The most important button to familiarize yourself with is the Submit button -which starts the whole process; dialogs are presented as the process -continues asking you if you want to continue "OK" or stop "Cancel". - -The first row presently has only one Boot Method choice: "2 disk compression." -Clicking on the menu on the right selects the Boot Method. - -The second row allows you to select the kernel for the Boot/Root set. You -may either use the file selector button on the right hand side, or you may -type in the location on the left hand side. - -The third row allows you to select the compressed filesystem you are -providing, using either of the two ways mentioned before. You may use a -pre-made root filesystem or you may create one using one of the Methods -provided in the Advanced Root Section. - -The fourth row allows you to select the device you want to use. The default -device is the first floppy disk (/dev/fd0). - -The fifth row allows you to choose the size of the device being used. The -default size of 1440 assumes you are using a floppy drive (Note: You may want -to experiment with 1722 which works fine with many floppy drives.), but can -be used with other sized devices like tape drives. Click on the -appropriate radio button to choose either gzip or bzip2 compression if the -program doesn't automatically detect it. - -The slider bar on the right allows the output of the verbosity box to be -changed from the highest (2) to the lowest setting (1) or to be turned off (0) -or on again. At times it may be advantageous to turn off the verbosity box -since large quantities of output to this box may cause gbootroot to use too -much cpu power; however, output may still be found in the text file "verbose" -in /tmp/gbootroot_tmp'time-date'. - -Advanced Boot Section: - -Libraries & Binaries & Modules check boxes: Turn off and on the -stripping of symbols. The stripping behavior for libraries may be -changed by clicking on the right mouse button to change --strip-debug -to --strip-all. Binaries default to --strip-all and Modules default to ---strip-debug. - -"Devel Device" If the device used for development is different than the -actual boot device, use this field to indicate that device. You will have to -run lilo -v -C brlilo.conf -r "device mount point" manually at a later time -on the actual boot device. - -"Opt. Device" Add devices to the boot disk which are necessary for the -kernel to function properly. Put a space between each device. For instance, -/dev/fb0 for frame buffer devices. - -"append =" Add append options to brlilo.conf. If you are using a frame -buffer device you could add something like video=matrox:vesa:402,depth:16. - -"Kernel Module" Add the modules found in /lib/modules/kernel-version -which are necessary for the Boot Method to work properly. If these -modules aren't found in the modules directory it is assumed that they -either are in the kernel or they do not exist. In the case of 2 disk -compression, floppy needs to be included in the kernel or included as a -module. Kmod inserts the modules, and kmod needs to be built into the -kernel along with initrd and ramdisk." - -"Kernel Version" Override the kernel version number found in the -kernel header. This will change the /lib/modules/kernel-version -directory. - -System.map: When a non-running kernel is chosen it is important to -include a copy of that kernel's System.map file so that depmod can -use the correct set of kernel symbols to resolve kernel references -in each module. This can be found in the kernel's source code after -compilation. - -Advanced Root Section: - -"Root Device" This is the device used for the root filesystem when -constructing the Boot/Root set. You may choose a device which is different -than the Boot device, but presently only floppy devices are supported. - -"Root Device Size" The size of the actual media used for the Root Device. - -"Root Filename" The name give to the root filesystem when initially made -in the temporary creation location. The save button allows the creation to -be saved in the permanent default location when the Accept button is pressed. - -"Filesystem Size" Root Methods make the filesystem the size which is -specified here. - -"Compression" Off by default to allow user-mode-linux testing. Turn on -compression when you are ready to use a Boot Method which requires compression. - -"Method" The root filesystem creation method. - -"Template" The template associated with a Root Method. Not all Root Methods -have templates. - -"Generate" This puts the chosen Root Method in action. - -"UML" Abbreviation for user-mode-linux. This is a linux kernel which runs on -top of the host system's linux kernel and allows a you run a live root -filesystem. - -"Accept" This accepts the created root filesystem if it is found in the -temporary creation directory. The UML box and the main section will now -reflect the path to this root filesystem. You can now test with the UML -button or a put together a complete Boot/Root set with the Submit button. - -Advanced Kernel Section: - -Still in development. - - -Little things you may want to know: - -* gBootRoot requires ash for initrd. Ash is a feather weight version of Bash. - -HELP - -} +exit( 0 ); \ No newline at end of file