|
|
|
#!/usr/bin/perl -w
|
|
|
|
|
|
|
|
# gBootRoot Copyright (C) 2000
|
|
|
|
# Jonathan Rosenbaum - mttrader@access.mountain.net
|
|
|
|
# http://the.netpedia.net/gBootRoot.html
|
|
|
|
|
|
|
|
# This program is free software; you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
# the Free Software Foundation; either version 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
|
|
|
|
|
|
|
|
use Gtk;
|
|
|
|
use strict;
|
|
|
|
|
|
|
|
init Gtk;
|
|
|
|
|
|
|
|
# Perhaps you are wondering where I learned how to program with Gtk-Perl?
|
|
|
|
# There is an excellent tutorial by Stephen Wilhelm at
|
|
|
|
# http://personal.riverusers.com/~swilhelm/perlgtk/. Please
|
|
|
|
# help support his development of this tutorial. Another good place
|
|
|
|
# to learn from is test.pl in the Gtk/samples directory included with
|
|
|
|
# Gtk-Perl.
|
|
|
|
|
|
|
|
# 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";
|
|
|
|
|
|
|
|
# CHANGES
|
|
|
|
# 1.0.3a - 08.23.2000
|
|
|
|
# * corrected bugs in norm_root_device (returned always 'hda1')
|
|
|
|
# a) now closes LIL
|
|
|
|
# b) chomps all lines in one go
|
|
|
|
# c) the 'default' value is just a label, not a dev
|
|
|
|
# d) sane regexp magic
|
|
|
|
# e) "there's one more bug(tm)": does not cope with multiple
|
|
|
|
# root device occurences (which might be present in each
|
|
|
|
# 'image=' block
|
|
|
|
# 1.0.3 - 08.09.2000
|
|
|
|
# * Tmp and mnt are now created on the fly,
|
|
|
|
# along with a new error function for mkdir(),
|
|
|
|
# Gtk clean-up for this, and clean-up by signal handler
|
|
|
|
# which should please Perlish and helpful Cristian.
|
|
|
|
#
|
|
|
|
# 1.0.2 - 08.06.2000
|
|
|
|
# * Changed logic slightly in submit() with returns rather
|
|
|
|
# than a scalar to resolve a minor bug caused by some
|
|
|
|
# changes in the previous version.
|
|
|
|
#
|
|
|
|
# 1.0.1 - 08.05.2000
|
|
|
|
# * Zas provided a correction for a Perl 5.6 error complaint.
|
|
|
|
# * Zas found some unecessary GDK lines causing some Gtk
|
|
|
|
# warnings; these were commented out.
|
|
|
|
# * Cristian Ionescu-Idbohrn found a bug caused by putting
|
|
|
|
# the Kernel or RootImage below the mount point. An error
|
|
|
|
# check and error dialog were added.
|
|
|
|
#
|
|
|
|
# 1.0.0 - 08.02.2000
|
|
|
|
# * First public release
|
|
|
|
#
|
|
|
|
|
|
|
|
#######################################################################
|
|
|
|
# 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
|
|
|
|
my $version = "v1.0.3";
|
|
|
|
my $date = "08.09.2000";
|
|
|
|
my $pwd = `pwd`; chomp $pwd;
|
|
|
|
use File::Basename;
|
|
|
|
|
|
|
|
my $initrd;
|
|
|
|
my $compress;
|
|
|
|
my $false = 0;
|
|
|
|
my $true = 1;
|
|
|
|
my $ok;
|
|
|
|
my $box2;
|
|
|
|
my $label;
|
|
|
|
my $order;
|
|
|
|
my $text_window;
|
|
|
|
my @container;
|
|
|
|
my @original_container;
|
|
|
|
my $file_dialog;
|
|
|
|
my $error_window;
|
|
|
|
my ($kernel,$root_image,$device,$size);
|
|
|
|
my $mtab;
|
|
|
|
my ($tmp,$mnt);
|
|
|
|
my $norm_root_device;
|
|
|
|
|
|
|
|
# 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;
|
|
|
|
|
|
|
|
if (!-d $tmp1) {
|
|
|
|
if (-e $tmp1) {
|
|
|
|
error_window(
|
|
|
|
"gBootRoot: ERROR: A file exists where $tmp1 should be");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
my @directory_parts = split(m,/,,$tmp1);
|
|
|
|
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 $tmp1");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!-d "$tmp1/gbootroot_tmp$$") {
|
|
|
|
$tmp = "$tmp1/gbootroot_tmp$$" if err_custom_perl(
|
|
|
|
"mkdir $tmp1/gbootroot_tmp$$",
|
|
|
|
"gBootRoot: ERROR: Could not make temporary directory") != 2;
|
|
|
|
}
|
|
|
|
if (!-d "$tmp1/gbootroot_mnt$$") {
|
|
|
|
$mnt = "$tmp1/gbootroot_mnt$$" if err_custom_perl(
|
|
|
|
"mkdir $tmp1/gbootroot_mnt$$",
|
|
|
|
"gBootRoot: ERROR: Could not make mount directory") != 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
my $window = new Gtk::Window("toplevel");
|
|
|
|
$window->set_title("gBootRoot");
|
|
|
|
$window->set_position('center');
|
|
|
|
$window->signal_connect( "destroy", sub {
|
|
|
|
unlink "$tmp/verbose", "$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");
|
|
|
|
#$window->window->set_decorations(['all', 'menu']); # Zas
|
|
|
|
#$window->window->set_functions(['all', 'resize']); # Zas
|
|
|
|
|
|
|
|
my $tooltips = new Gtk::Tooltips();
|
|
|
|
|
|
|
|
my $box1 = new Gtk::VBox($false,0);
|
|
|
|
$window->add($box1);
|
|
|
|
$box1->show();
|
|
|
|
|
|
|
|
# First row
|
|
|
|
hbox();
|
|
|
|
my $entry = entry($false);
|
|
|
|
|
|
|
|
# Menu - later this may be improved if new methods are added.
|
|
|
|
my $opt = new Gtk::OptionMenu();
|
|
|
|
$tooltips->set_tip( $opt, "Choose the Boot method.", "" );
|
|
|
|
my $menu = new Gtk::Menu();
|
|
|
|
my $item = new Gtk::MenuItem("Method -> lilo" );
|
|
|
|
$item->show();
|
|
|
|
$item->signal_connect( 'activate',sub { $entry->set_text("lilo");
|
|
|
|
$container[0] = "lilo"});
|
|
|
|
$menu->append( $item );
|
|
|
|
$opt->set_menu( $menu );
|
|
|
|
$box2->pack_start( $opt, $true, $true, 0 );
|
|
|
|
$opt->show();
|
|
|
|
$box2->show();
|
|
|
|
|
|
|
|
# Second row
|
|
|
|
hbox();
|
|
|
|
my $entry2 = entry($true,1);
|
|
|
|
button("Kernel Selection",$entry2,"Kernel Selection",1);
|
|
|
|
|
|
|
|
# Third row
|
|
|
|
hbox();
|
|
|
|
my $entry3 = entry($true,2);
|
|
|
|
button("Compressed Filesystem",$entry3,"Compressed Filesystem",2);
|
|
|
|
|
|
|
|
# In the future, if experimenters send in data, there will be two
|
|
|
|
# different devices.
|
|
|
|
# Fourth row
|
|
|
|
hbox();
|
|
|
|
my $entry4 = entry($true,3);
|
|
|
|
$entry4->set_text("/dev/fd0");
|
|
|
|
$container[3] = "/dev/fd0";
|
|
|
|
button("Device Selection",$entry4,"Device Selection",3,$true);
|
|
|
|
|
|
|
|
# Fifth row
|
|
|
|
hbox("what");
|
|
|
|
my $adj = new Gtk::Adjustment( 1440.0, 0.0, 360000000.0, 282.0, 360.0, 0.0 );
|
|
|
|
my $spinner = new Gtk::SpinButton( $adj, 0, 0 );
|
|
|
|
$tooltips->set_tip( $spinner, "Choose the Device Size.", "" );
|
|
|
|
$spinner->set_wrap( $true );
|
|
|
|
$spinner->set_numeric( $true );
|
|
|
|
$spinner->set_shadow_type( 'in' );
|
|
|
|
$spinner->show();
|
|
|
|
$container[4] = 1440;
|
|
|
|
$adj->signal_connect( "value_changed", sub {
|
|
|
|
$container[4] = $spinner->get_value_as_int();});
|
|
|
|
$box2->pack_start( $spinner, $true, $true, 0 );
|
|
|
|
label("Device Size");
|
|
|
|
|
|
|
|
# gz and bz2 radio buttons
|
|
|
|
my $rbutton = new Gtk::RadioButton( "gz" );
|
|
|
|
$tooltips->set_tip( $rbutton, "Choose Compression used on the Filesystem.", "" );
|
|
|
|
my $gz_toggle = $rbutton;
|
|
|
|
$rbutton->set_active( $true );
|
|
|
|
$box2->pack_start( $rbutton, $false, $false, 0 );
|
|
|
|
$rbutton->show();
|
|
|
|
$rbutton = new Gtk::RadioButton( "bz2", $rbutton );
|
|
|
|
$rbutton->set_usize(1,1);
|
|
|
|
$tooltips->set_tip( $rbutton, "Choose Compression used on the Filesystem.", "" );
|
|
|
|
my $bz2_toggle = $rbutton;
|
|
|
|
$box2->pack_start( $rbutton, $true, $true, 0);
|
|
|
|
$rbutton->show();
|
|
|
|
|
|
|
|
# Size status entry
|
|
|
|
my $entry5 = new Gtk::Entry();
|
|
|
|
$entry5->set_editable( $false );
|
|
|
|
$tooltips->set_tip( $entry5, "This shows room remaining on the Device.", "" );
|
|
|
|
$entry5->set_usize(15,20);
|
|
|
|
$box2->pack_start( $entry5, $true, $true, 0 );
|
|
|
|
$entry5->show();
|
|
|
|
|
|
|
|
# Separator
|
|
|
|
my $separator = new Gtk::HSeparator();
|
|
|
|
$box1->pack_start( $separator, $false, $true, 0 );
|
|
|
|
$separator->show();
|
|
|
|
|
|
|
|
# Status bar
|
|
|
|
my $align = new Gtk::Alignment( 0.5, 0.5, 0, 0 );
|
|
|
|
$box1->pack_start( $align, $false, $false, 5);
|
|
|
|
$align->show();
|
|
|
|
my $pbar = new Gtk::ProgressBar();
|
|
|
|
$pbar->set_usize(321,10); # 321 10
|
|
|
|
$align->add($pbar);
|
|
|
|
$pbar->show();
|
|
|
|
|
|
|
|
# Separator
|
|
|
|
$separator = new Gtk::HSeparator();
|
|
|
|
$box1->pack_start( $separator, $false, $true, 0 );
|
|
|
|
$separator->show();
|
|
|
|
|
|
|
|
# Submit button
|
|
|
|
hbox();
|
|
|
|
my $sbutton = new Gtk::Button("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 = new Gtk::Button("Close");
|
|
|
|
$cbutton->signal_connect( "clicked", sub {
|
|
|
|
unlink "$tmp/verbose", "$tmp/initrd_image.gz";
|
|
|
|
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 = new Gtk::Button("Help");
|
|
|
|
$hbutton->signal_connect( "clicked", \&create_text);
|
|
|
|
$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 {
|
|
|
|
$SIG{INT} = \&signal;
|
|
|
|
$SIG{ABRT} = \&signal;
|
|
|
|
$SIG{TERM} = \&signal;
|
|
|
|
$SIG{QUIT} = \&signal;
|
|
|
|
$SIG{KILL} = \&signal;
|
|
|
|
unlink "$tmp/verbose", "$tmp/initrd_image.gz";
|
|
|
|
rmdir "$tmp/initrd_mnt"; rmdir "$tmp", rmdir "$mnt";
|
|
|
|
Gtk->exit(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Cristian's idea - bug 111579 enh for brlilo
|
|
|
|
sub norm_root_device {
|
|
|
|
|
|
|
|
my $root_dev = 'hda1';
|
|
|
|
|
|
|
|
if (!-d $lilo_conf) {
|
|
|
|
if (-e $lilo_conf) {
|
|
|
|
open(LIL, $lilo_conf);
|
|
|
|
my @lilo_lines = <LIL>;
|
|
|
|
close(LIL);
|
|
|
|
chomp(@lilo_lines);
|
|
|
|
|
|
|
|
for (@lilo_lines) {
|
|
|
|
next if m/^\s*[#]/;
|
|
|
|
|
|
|
|
if (m#\s*root\s*=\s*/dev/(.+)\s*#) {
|
|
|
|
$root_dev = $1;
|
|
|
|
last;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#open(VFN, ">> $verbosefn") or die "Oops! Can't open $verbosefn,";
|
|
|
|
#print VFN "Root device found: $root_dev\n";
|
|
|
|
#close(VFN);
|
|
|
|
|
|
|
|
return $root_dev;
|
|
|
|
|
|
|
|
} # end sub norm_root_device
|
|
|
|
|
|
|
|
sub create_text {
|
|
|
|
|
|
|
|
if (not defined $text_window) {
|
|
|
|
$text_window = new Gtk::Window "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 = new Gtk::VBox( $false, 0 );
|
|
|
|
$text_window->add( $main_vbox );
|
|
|
|
$main_vbox->show();
|
|
|
|
|
|
|
|
my $vbox = new Gtk::VBox( $false, 10 );
|
|
|
|
$vbox->border_width( 10 );
|
|
|
|
$main_vbox->pack_start( $vbox, $true, $true, 0 );
|
|
|
|
$vbox->show();
|
|
|
|
|
|
|
|
my $table = new Gtk::Table( 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 = new Gtk::Text( undef, undef );
|
|
|
|
$text->set_editable($false);
|
|
|
|
$table->attach( $text, 0, 1, 0, 1,
|
|
|
|
[ 'expand', 'shrink', 'fill' ],
|
|
|
|
[ 'expand', 'shrink', 'fill' ],
|
|
|
|
0, 0 );
|
|
|
|
$text->show();
|
|
|
|
|
|
|
|
# Add a vertical scrollbar to the GtkText widget
|
|
|
|
my $vscrollbar = new Gtk::VScrollbar( $text->vadj );
|
|
|
|
$table->attach( $vscrollbar, 1, 2, 0, 1, 'fill',
|
|
|
|
[ 'expand', 'shrink', 'fill' ], 0, 0 );
|
|
|
|
$vscrollbar->show();
|
|
|
|
|
|
|
|
$text->freeze();
|
|
|
|
$text->insert( undef, undef, undef, help() );
|
|
|
|
$text->thaw();
|
|
|
|
|
|
|
|
my $separator = new Gtk::HSeparator();
|
|
|
|
$main_vbox->pack_start( $separator, $false, $true, 0 );
|
|
|
|
$separator->show();
|
|
|
|
|
|
|
|
$vbox = new Gtk::VBox( $false, 10 );
|
|
|
|
$vbox->border_width( 10 );
|
|
|
|
$main_vbox->pack_start( $vbox, $false, $true, 0 );
|
|
|
|
$vbox->show();
|
|
|
|
|
|
|
|
my $button = new Gtk::Button( "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
|
|
|
|
|
|
|
|
sub make_menu_item {
|
|
|
|
my( $name, $callback, $data ) = @_;
|
|
|
|
my $item;
|
|
|
|
|
|
|
|
$item = new Gtk::MenuItem( $name );
|
|
|
|
$item->signal_connect( "activate", $callback, $data );
|
|
|
|
$item->show();
|
|
|
|
|
|
|
|
return $item;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub fileselect {
|
|
|
|
|
|
|
|
my ($widget,$ent,$name,$order,$device) = @_;
|
|
|
|
|
|
|
|
if (not defined $file_dialog) {
|
|
|
|
# Create a new file selection widget
|
|
|
|
$file_dialog = new Gtk::FileSelection( "$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( "/dev/fd0" ) 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();
|
|
|
|
$entry->set_text($file);
|
|
|
|
$container[$order] = $file;
|
|
|
|
|
|
|
|
# auto-detect compression if system has file
|
|
|
|
if ($container[2]) {
|
|
|
|
my $file = system "which file > /dev/null 2>&1";
|
|
|
|
if ($file == 0) {
|
|
|
|
open(F,"file $container[2]|"); # no error check here
|
|
|
|
while (<F>) {
|
|
|
|
if (/gzip/) {
|
|
|
|
$gz_toggle->set_active( $true );
|
|
|
|
}
|
|
|
|
elsif (/bzip2/) {
|
|
|
|
$bz2_toggle->set_active( $true );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
destroy $file_dialog;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
# pulled from test.pl
|
|
|
|
sub destroy_window {
|
|
|
|
my($widget, $windowref, $w2) = @_;
|
|
|
|
$$windowref = undef;
|
|
|
|
$w2 = undef if defined $w2;
|
|
|
|
0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub hbox {
|
|
|
|
my $homogeneous;
|
|
|
|
defined $_[0] ? ($homogeneous = 0) : ($homogeneous = 1);
|
|
|
|
$box2 = new Gtk::HBox( $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 = new Gtk::Label( $text );
|
|
|
|
$label->set_justify( "fill" );
|
|
|
|
$box2->pack_start( $label, $false, $false, 5 );
|
|
|
|
$label->show();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
sub entry {
|
|
|
|
|
|
|
|
my($edit,$num) = @_;
|
|
|
|
|
|
|
|
my $entry = new Gtk::Entry();
|
|
|
|
$entry->set_editable( $edit );
|
|
|
|
# enter will have to be pressed, tried other solutions with a mess
|
|
|
|
$entry->signal_connect( "activate", sub {
|
|
|
|
$container[$num] = $entry->get_text();});
|
|
|
|
if (defined $num) {
|
|
|
|
my $todo;
|
|
|
|
if ($num == 1) {
|
|
|
|
$todo = "the Kernel";
|
|
|
|
}
|
|
|
|
elsif ($num == 2) {
|
|
|
|
$todo = "the Compressed Filesystem";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$todo = "the Device to use";
|
|
|
|
}
|
|
|
|
$tooltips->set_tip( $entry,
|
|
|
|
"Type in the location of $todo and press [Enter].", "" );
|
|
|
|
}
|
|
|
|
$box2->pack_start( $entry, $true, $true, 0 );
|
|
|
|
$entry->show();
|
|
|
|
|
|
|
|
return $entry;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
sub button {
|
|
|
|
|
|
|
|
my ($text,$ent,$name,$order,$device) = @_;
|
|
|
|
|
|
|
|
my $button = new Gtk::Button($text);
|
|
|
|
if ($order == 1) {
|
|
|
|
$tooltips->set_tip( $button, "Select the Kernel.", "" );
|
|
|
|
}
|
|
|
|
elsif ($order == 2) {
|
|
|
|
$tooltips->set_tip( $button, "Select the Compressed 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);
|
|
|
|
# comment this out for testing
|
|
|
|
unlink("$tmp/verbose");
|
|
|
|
open (MTAB, "/etc/mtab") or die "no mtab!\n";
|
|
|
|
while (<MTAB>) {
|
|
|
|
if (m,$mnt,) {
|
|
|
|
system "umount $mnt >> $tmp/verbose 2>&1";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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[0]) {
|
|
|
|
error_window("gBootRoot: ERROR: No method supplied");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (defined $container[1] && -e $container[1] && !-d $container[1]) {
|
|
|
|
$kernel = $container[1];
|
|
|
|
# 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[0]) {
|
|
|
|
error_window("gBootRoot: ERROR: Kernel not found");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (defined $container[2] && -e $container[2] && !-d $container[2] ) {
|
|
|
|
$root_image = $container[2];
|
|
|
|
if ($root_image =~ m,^$mnt,) {
|
|
|
|
# Bug revealed by Cristian Ionescu-Idbohrn <cii@axis.com>
|
|
|
|
error_window("gBootRoot: ERROR: Rootimage found below Device mount point: $mnt");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
elsif (defined $container[0] && defined $container[1]) {
|
|
|
|
error_window("gBootRoot: ERROR: Rootimage not found");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
# we need to check for this, too.
|
|
|
|
if (defined $container[3] && -e $container[3] && !-d $container[3] ) {
|
|
|
|
$device = $container[3];
|
|
|
|
}
|
|
|
|
elsif (defined $container[0] && defined $container[1]
|
|
|
|
&& defined $container[2]) {
|
|
|
|
error_window("gBootRoot: ERROR: Device not found");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (defined $container[4]) {
|
|
|
|
$size = $container[4];
|
|
|
|
}
|
|
|
|
|
|
|
|
# pretty unlikely
|
|
|
|
elsif (defined $container[0] && defined $container[1] &&
|
|
|
|
defined $container[2] && defined $container[3]) {
|
|
|
|
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[5] = $compress;
|
|
|
|
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;
|
|
|
|
splice(@temp_container,1,1);
|
|
|
|
my %diff;
|
|
|
|
grep($diff{$_}++,@temp_container);
|
|
|
|
my @diff = grep(!$diff{$_},@original_container);
|
|
|
|
if ($#diff >= 0) {
|
|
|
|
# unlink initrd_image.gz, do initrd()
|
|
|
|
$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[0],$root_image,$device,$size,$compress);
|
|
|
|
|
|
|
|
lilo();
|
|
|
|
}
|
|
|
|
|
|
|
|
} # end sub submit
|
|
|
|
|
|
|
|
sub error_window {
|
|
|
|
my ($error) = @_;
|
|
|
|
|
|
|
|
if (not defined $error_window) {
|
|
|
|
$error_window = new Gtk::Dialog;
|
|
|
|
$error_window->signal_connect("destroy", \&destroy_window, \$error_window);
|
|
|
|
$error_window->signal_connect("delete_event", \&destroy_window, \$error_window);
|
|
|
|
$error_window->set_title("gBootRoot ERROR");
|
|
|
|
$error_window->border_width(15);
|
|
|
|
my $label = new Gtk::Label($error);
|
|
|
|
$error_window->vbox->pack_start( $label, $true, $true, 15 );
|
|
|
|
$label->show();
|
|
|
|
my $button = new Gtk::Button("OK");
|
|
|
|
$button->signal_connect("clicked", sub {destroy $error_window});
|
|
|
|
$button->can_default(1);
|
|
|
|
$error_window->action_area->pack_start($button, $false, $false,0);
|
|
|
|
$button->grab_default;
|
|
|
|
$button->show;
|
|
|
|
}
|
|
|
|
if (!visible $error_window) {
|
|
|
|
show $error_window;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
destroy $error_window;
|
|
|
|
}
|
|
|
|
|
|
|
|
} # end sub error_window
|
|
|
|
|
|
|
|
sub errmk {
|
|
|
|
error_window("gBootRoot: ERROR: Could not make important directories") if $? != 0;
|
|
|
|
if (defined $error_window) {
|
|
|
|
if ($error_window->visible) {
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub errcp {
|
|
|
|
error_window("gBootRoot: ERROR: Could not copy over important stuff") if $? != 0;
|
|
|
|
if (defined $error_window) {
|
|
|
|
if ($error_window->visible) {
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub errum {
|
|
|
|
error_window("gBootRoot: ERROR: Could not umount the device") if $? != 0;
|
|
|
|
if (defined $error_window) {
|
|
|
|
if ($error_window->visible) {
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub errm {
|
|
|
|
error_window("gBootRoot: ERROR: Could not mount device") if $? != 0;
|
|
|
|
if (defined $error_window) {
|
|
|
|
if ($error_window->visible) {
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub errrm {
|
|
|
|
error_window("gBootRoot: ERROR: Could not remove a directory or file")
|
|
|
|
if $? != 0;
|
|
|
|
if (defined $error_window) {
|
|
|
|
if ($error_window->visible) {
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub err {
|
|
|
|
error_window("gBootRoot: ERROR: Not enough space after all") if ($? > 0);
|
|
|
|
if (defined $error_window) {
|
|
|
|
if ($error_window->visible) {
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub err_custom {
|
|
|
|
|
|
|
|
if (defined $_[2]) {
|
|
|
|
system("$_[0] > /dev/null 2>&1");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
system("$_[0] >> $tmp/verbose 2>&1");
|
|
|
|
}
|
|
|
|
error_window($_[1]) if ($? != 0);
|
|
|
|
if (defined $error_window) {
|
|
|
|
if ($error_window->visible) {
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub err_custom_perl {
|
|
|
|
|
|
|
|
if ((split(/ /, $_[0]))[0] eq "mkdir") {
|
|
|
|
my $two = (split(/ /, $_[0]))[1];
|
|
|
|
mkdir($two,0755); # Anyone allowed in
|
|
|
|
}
|
|
|
|
error_window($_[1]) if ($? != 0);
|
|
|
|
if (defined $error_window) {
|
|
|
|
if ($error_window->visible) {
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub lilo {
|
|
|
|
|
|
|
|
# Do a little cleanup just in case
|
|
|
|
system "rm $tmp/initrd_image.gz 2> /dev/null" if $ok == 1;
|
|
|
|
system "umount $tmp/initrd_mnt 2> /dev/null";
|
|
|
|
|
|
|
|
$kernel = $container[1];
|
|
|
|
$root_image = $container[2];
|
|
|
|
$device = $container[3];
|
|
|
|
$size = $container[4];
|
|
|
|
|
|
|
|
if ($ok == 1 || $ok == 2) {
|
|
|
|
my $value = initrd($kernel,$root_image,$device,$size);
|
|
|
|
mtab(0) if defined $value;
|
|
|
|
}
|
|
|
|
elsif ($ok == 0) {
|
|
|
|
mtab(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
} # end sub lilo
|
|
|
|
|
|
|
|
sub lilo_put_it_together {
|
|
|
|
|
|
|
|
my $B = "boot";
|
|
|
|
# Time to do a little calculations
|
|
|
|
my $device_size = (split(/\s+/,`df $mnt`))[8];
|
|
|
|
my $boot_size = (stat($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");
|
|
|
|
}
|
|
|
|
|
|
|
|
# Better do this first
|
|
|
|
#V#print "Copy over initrd ramdisk\n";
|
|
|
|
return if err_custom("cp $tmp/$initrd $mnt/$initrd","gBootRoot: ERROR: Could not copy over initrd") == 2;
|
|
|
|
pb($B,2);
|
|
|
|
|
|
|
|
#V#print "Copying over kernel\n";
|
|
|
|
return if
|
|
|
|
err_custom("rm -rf $mnt/lost+found; cp $kernel $mnt/kernel",
|
|
|
|
"gBootRoot: ERROR: Could not copy over the kernel") == 2;
|
|
|
|
pb($B,3);
|
|
|
|
|
|
|
|
#V#print "Making stuff for lilo\n";
|
|
|
|
return if err(system "mkdir $mnt/{boot,dev} >> $tmp/verbose 2>&1; cp -a /dev/{null,fd?,hda1} $mnt/dev >> $tmp/verbose 2>&1") == 2;
|
|
|
|
|
|
|
|
# Hopefully, this works, but have never tested it
|
|
|
|
if ($device !~ m,/dev/fd\d{1}$,) {
|
|
|
|
return if err(
|
|
|
|
system "cp -a $device $mnt/dev >> $tmp/verbose 2>&1") == 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
# This adds that next device
|
|
|
|
$norm_root_device = norm_root_device();
|
|
|
|
if (!-e "$mnt/dev/$norm_root_device") {
|
|
|
|
return if err(
|
|
|
|
system "cp -a /dev/$norm_root_device $mnt/dev >> $tmp/verbose 2>&1") == 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
#pb($B,3);
|
|
|
|
#V#print "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";
|
|
|
|
print LC brlilo($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
|
|
|
|
return if errum(system "umount $mnt >> $tmp/verbose 2>&1") == 2;
|
|
|
|
#V#print "Umount device\n";
|
|
|
|
#V#print "Remount device\n";
|
|
|
|
pb($B,6);
|
|
|
|
return if errm(system "mount -t ext2 $device $mnt >> $tmp/verbose 2>&1") == 2;
|
|
|
|
#V#print "Configuring lilo\n";
|
|
|
|
pb($B,7);
|
|
|
|
chdir("$mnt"); #"boot_root: ERROR: Could not change directories\n";
|
|
|
|
if (err_custom("lilo -v -C brlilo.conf -r $mnt",
|
|
|
|
"gBootRoot: ERROR: lilo failed") == 2) {
|
|
|
|
chdir($pwd); return;
|
|
|
|
}
|
|
|
|
$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";
|
|
|
|
|
|
|
|
#V#print "Umounting $mnt\n";
|
|
|
|
my $um = errum(system "umount $mnt >> $tmp/verbose 2>&1");
|
|
|
|
pb($B,10);
|
|
|
|
|
|
|
|
if ($ok == 1 || $ok == 2) {
|
|
|
|
return if
|
|
|
|
errrm(system "rmdir $tmp/initrd_mnt >> $tmp/verbose 2>&1") == 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Here's where we copy over that compressed filesystem
|
|
|
|
# We could separate $device = boot,root allowing two
|
|
|
|
# different devices to be used.
|
|
|
|
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 $device_size = (split(/\s+/,`df $mnt`))[8];
|
|
|
|
my $root_image_size = (stat($root_image))[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");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#V#print "Copy over the compressed filesystem\n";
|
|
|
|
return if errrm(system "rmdir $mnt/lost+found >> $tmp/verbose 2>&1") == 2;
|
|
|
|
my $broot_image = basename($root_image);
|
|
|
|
|
|
|
|
my $FS = "filesystem";
|
|
|
|
my $line_count = `wc -l < $root_image`; chomp $line_count;
|
|
|
|
my $half_line_count = $line_count/2;
|
|
|
|
my $count = 1;
|
|
|
|
open(CF, ">$mnt/$broot_image") or error_window(
|
|
|
|
"gBootRoot: ERROR: Could not copy over the root filesystem") and return;
|
|
|
|
open(CR, "$root_image") or error_window(
|
|
|
|
"gBootRoot: ERROR: Could not copy over the root filesystem") and return;
|
|
|
|
while (<CR>) {
|
|
|
|
print CF $_;
|
|
|
|
pb($FS,$count,$line_count) if $count < $half_line_count;
|
|
|
|
$count++;
|
|
|
|
}
|
|
|
|
close(CF); close(CR);
|
|
|
|
|
|
|
|
return if
|
|
|
|
err_custom("umount $mnt",
|
|
|
|
"gBootRoot: ERROR: Root disk did not properly umount") == 2;
|
|
|
|
pb($FS,$count,$line_count);
|
|
|
|
#V#print "Finished!\n";
|
|
|
|
|
|
|
|
} # end sub device 2
|
|
|
|
|
|
|
|
sub initrd_size {
|
|
|
|
|
|
|
|
my ($linuxrc_size) = @_;
|
|
|
|
my ($what,$lib);
|
|
|
|
#V#print "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.
|
|
|
|
# 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;
|
|
|
|
|
|
|
|
# add other executables here
|
|
|
|
my @initrd_stuff = qw(ash gzip mount umount);
|
|
|
|
foreach (@initrd_stuff) {
|
|
|
|
$initrd_size = $initrd_size + ((stat("/bin/$_"))[12]/2);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($compress eq "bzip2" && -e "/usr/bin/$compress") {
|
|
|
|
$initrd_size = $initrd_size + ((stat("/usr/bin/$compress"))[12]/2);
|
|
|
|
}
|
|
|
|
|
|
|
|
# lib sizes
|
|
|
|
open(L,"ldd /sbin/init|") or die "Oops, no init could be found :)\n"; # safe to use ldd
|
|
|
|
while (<L>) {
|
|
|
|
$lib = (split(/=>/,$_))[0];
|
|
|
|
$lib =~ s/\s+//;
|
|
|
|
$lib = basename($lib);
|
|
|
|
$lib =~ s/\s+$//;
|
|
|
|
open (SL,"ls -l /lib/$lib|") or die "humm: $!\n";
|
|
|
|
while (<SL>) {
|
|
|
|
# symbolic link
|
|
|
|
if (-l "/lib/$lib") {
|
|
|
|
$what = (split(/\s+/,$_))[10];
|
|
|
|
$initrd_size = $initrd_size + 1;
|
|
|
|
$initrd_size = $initrd_size + ((stat("/lib/$what"))[12]/2);
|
|
|
|
}
|
|
|
|
# no symbolic link
|
|
|
|
else {
|
|
|
|
$initrd_size = $initrd_size + ((stat("/lib/$lib"))[12]/2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$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);
|
|
|
|
my $I = "initrd";
|
|
|
|
|
|
|
|
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); close(LC);
|
|
|
|
pb($I,1);
|
|
|
|
my $size_needed = initrd_size((stat("$tmp/linuxrc"))[12]/2);
|
|
|
|
unlink("$tmp/linuxrc");
|
|
|
|
|
|
|
|
#print V "Using loop device to make initrd\n";
|
|
|
|
#V#print V "Make sure you have loop device capability in your running kernel\n";
|
|
|
|
system "dd if=/dev/zero of=$tmp/$initrd bs=1024 count=$size_needed >> $tmp/verbose 2>&1";
|
|
|
|
pb($I,2);
|
|
|
|
# no need to enter y every time
|
|
|
|
open(T,"|mke2fs -m0 -i8192 $tmp/$initrd >> $tmp/verbose 2>&1") or die "Problem here: $!\n"; print T "y\n"; close(T);
|
|
|
|
pb($I,3);
|
|
|
|
#V#print V "Mounting initrd in tmp\n";
|
|
|
|
|
|
|
|
return if errmk(system "mkdir $tmp/initrd_mnt >> $tmp/verbose 2>&1; mount -o loop -t ext2 $tmp/$initrd $tmp/initrd_mnt >> $tmp/verbose 2>&1") == 2;
|
|
|
|
pb($I,4);
|
|
|
|
|
|
|
|
#V#print "Putting everything together\n";
|
|
|
|
open(LC, ">$tmp/initrd_mnt/linuxrc") or die "Couldn't write linuxrc to loop device\n";
|
|
|
|
print LC initrd_heredoc($broot_image); close(LC);
|
|
|
|
# I could test this but somebody's system may do permissions differently
|
|
|
|
system "chmod 755 $tmp/initrd_mnt/linuxrc >> $tmp/verbose 2>&1";
|
|
|
|
system "rmdir $tmp/initrd_mnt/lost+found >> $tmp/verbose 2>&1";
|
|
|
|
pb($I,5);
|
|
|
|
|
|
|
|
#V#print "... the dirs\n";
|
|
|
|
return if errmk(system "mkdir $tmp/initrd_mnt/{bin,dev,etc,lib,mnt,proc,sbin,usr} >> $tmp/verbose 2>&1; mkdir $tmp/initrd_mnt/usr/lib >> $tmp/verbose 2>&1") == 2;
|
|
|
|
pb($I,6);
|
|
|
|
|
|
|
|
return if errcp(system "cp -a /dev/{console,null,ram0,ram1,tty0} $tmp/initrd_mnt/dev >> $tmp/verbose 2>&1") == 2;
|
|
|
|
return if errcp(system "cp -a $device $tmp/initrd_mnt/dev") == 2;
|
|
|
|
pb($I,7);
|
|
|
|
|
|
|
|
#V#print ".. the bins\n";
|
|
|
|
return if errcp(system "cp -a /bin/{ash,gzip,mount,umount} $tmp/initrd_mnt/bin >> $tmp/verbose 2>&1") == 2;
|
|
|
|
if ($compress eq "bzip2") {
|
|
|
|
if (-e "/usr/bin/$compress") {
|
|
|
|
return if errcp(system "cp -a /usr/bin/$compress $tmp/initrd_mnt/bin >> $tmp/verbose 2>&1") == 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# Testing init is sufficient for grabbing the correct libraries for the
|
|
|
|
# executables immediately above. This could be modified to test a
|
|
|
|
# list of executables.
|
|
|
|
#V#print ".. the libs\n";
|
|
|
|
open(L,"ldd /sbin/init|") or die "Oops, no init could be found :)\n"; # safe to use ldd
|
|
|
|
while (<L>) {
|
|
|
|
$lib = (split(/=>/,$_))[0];
|
|
|
|
$lib =~ s/\s+//;
|
|
|
|
$lib = basename($lib);
|
|
|
|
$lib =~ s/\s+$//;
|
|
|
|
open (SL,"ls -l /lib/$lib|") or die "humm: $!\n";
|
|
|
|
while (<SL>) {
|
|
|
|
# symbolic link
|
|
|
|
if (-l "/lib/$lib") {
|
|
|
|
$what = (split(/\s+/,$_))[10];
|
|
|
|
return if errcp(system "cp -a /lib/$lib $tmp/initrd_mnt/lib >> $tmp/verbose 2>&1") == 2;
|
|
|
|
return if errcp(system "cp -a /lib/$what $tmp/initrd_mnt/lib >> $tmp/verbose 2>&1") == 2;
|
|
|
|
}
|
|
|
|
# no symbolic link
|
|
|
|
else {
|
|
|
|
return if errcp(system "cp -a /lib/$lib $tmp/initrd_mnt/lib >> $tmp/verbose 2>&1") == 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#V#print "Determine run-time link bindings\n";
|
|
|
|
# Has a return code of 0 regardless
|
|
|
|
system "ldconfig -r $tmp/initrd_mnt";
|
|
|
|
#V#print "Umounting loop device, and compressing initrd";
|
|
|
|
return if errum(system "umount $tmp/initrd_mnt >> $tmp/verbose 2>&1") == 2;
|
|
|
|
system "gzip -f9 $tmp/$initrd >> $tmp/verbose 2>&1";
|
|
|
|
pb($I,10); # This takes the longest.
|
|
|
|
|
|
|
|
$initrd = $initrd . ".gz";
|
|
|
|
|
|
|
|
|
|
|
|
} # end sub initrd
|
|
|
|
|
|
|
|
sub mtab_window {
|
|
|
|
# Will just use a dialog box.
|
|
|
|
my ($dialog,$error,$count,$pattern) = @_;
|
|
|
|
|
|
|
|
if (not defined $mtab) {
|
|
|
|
$mtab = new Gtk::Dialog;
|
|
|
|
$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 = new Gtk::Label($dialog);
|
|
|
|
$label->set_justify( 'left' );
|
|
|
|
$label->set_pattern("_________") if defined $pattern;
|
|
|
|
$mtab->vbox->pack_start( $label, $true, $true, 15 );
|
|
|
|
$label->show();
|
|
|
|
my $button = new Gtk::Button("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 = new Gtk::Button("Cancel");
|
|
|
|
$button->signal_connect("clicked", sub { destroy $mtab} );
|
|
|
|
$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],1);
|
|
|
|
}
|
|
|
|
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],1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} # end sub mtab
|
|
|
|
|
|
|
|
|
|
|
|
sub mtab_check {
|
|
|
|
|
|
|
|
my($widget,$count) = @_;
|
|
|
|
|
|
|
|
my $dialog;
|
|
|
|
my $error = 1;
|
|
|
|
|
|
|
|
# Check to see if $device is mounted
|
|
|
|
open (MTAB, "/etc/mtab") or die "no mtab!\n";
|
|
|
|
while (<MTAB>) {
|
|
|
|
if (m,$device,) {
|
|
|
|
# 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) {
|
|
|
|
destroy $mtab;
|
|
|
|
system "mke2fs -m0 -i8192 $device $size >> $tmp/verbose 2>&1";
|
|
|
|
if ($? != 0) {
|
|
|
|
$dialog = "gBootRoot: ERROR: You need to insert a disk\n";
|
|
|
|
mtab_window($dialog,$error,$count);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
return if errm(system "mount -t ext2 $device $mnt >> $tmp/verbose 2>&1") == 2;
|
|
|
|
lilo_put_it_together() if $count == 0;
|
|
|
|
device2() if $count == 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
} # end sub mtab_check
|
|
|
|
|
|
|
|
|
|
|
|
sub initrd_heredoc {
|
|
|
|
|
|
|
|
my($broot_image) = @_;
|
|
|
|
|
|
|
|
# Here's where the initrd is put together using a loop device
|
|
|
|
# HEREDOC
|
|
|
|
my $initrd_exec = << "INITRD";
|
|
|
|
#!/bin/ash
|
|
|
|
|
|
|
|
export PATH=/bin:/sbin:/usr/bin:
|
|
|
|
|
|
|
|
echo Preparing to setup ramdisk.
|
|
|
|
|
|
|
|
mount -o remount,rw / 2>/dev/null
|
|
|
|
|
|
|
|
echo Mounting proc...
|
|
|
|
mount -t proc none /proc
|
|
|
|
|
|
|
|
echo -n 'Please insert the root floppy, and press [Enter]: '
|
|
|
|
read ENTER
|
|
|
|
|
|
|
|
echo Mounting $device readonly ...
|
|
|
|
mount -o ro -t ext2 $device /mnt
|
|
|
|
|
|
|
|
echo -n Copying new root to ramdisk .. please wait ...
|
|
|
|
$compress -cd /mnt/$broot_image > /dev/ram1
|
|
|
|
echo done.
|
|
|
|
|
|
|
|
echo -n Unmounting $device ...
|
|
|
|
umount /mnt
|
|
|
|
echo done.
|
|
|
|
|
|
|
|
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) = @_;
|
|
|
|
|
|
|
|
# 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"
|
|
|
|
initrd = $initrd
|
|
|
|
root = $device
|
|
|
|
label = bootdisk
|
|
|
|
read-write
|
|
|
|
|
|
|
|
# normalboot
|
|
|
|
image = kernel
|
|
|
|
root = /dev/$norm_root_device
|
|
|
|
label = normalboot
|
|
|
|
read-only
|
|
|
|
LILOCONF
|
|
|
|
|
|
|
|
return $brlilo;
|
|
|
|
|
|
|
|
} # end sub brlilo
|
|
|
|
|
|
|
|
|
|
|
|
sub message {
|
|
|
|
# HEREDOC
|
|
|
|
my $message = << "MESSAGE";
|
|
|
|
|
|
|
|
gBootRoot $version written by Jonathan Rosenbaum $date GNU GPL
|
|
|
|
mailto:mttrader\@access.mountain.net
|
|
|
|
|
|
|
|
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 written by Jonathan Rosenbaum $date GNU GPL
|
|
|
|
email:mttrader\@access.mountain.net
|
|
|
|
site -> http://the.netpedia.net/gBootRoot.html
|
|
|
|
|
|
|
|
gBootRoot is a Gtk+/Perl program useful for both beginners and advanced
|
|
|
|
GNU/Linux users. It makes the construction/development of emergency and
|
|
|
|
mini distributions simple.
|
|
|
|
|
|
|
|
- A GNU/Linux user can easily create an emergency Boot/Root set. There
|
|
|
|
are a multitude of pre-existing compressed filesystems readily available.
|
|
|
|
Please check the gBootRoot FAQ at the gBootRoot site listed above.
|
|
|
|
** If you are a developer please send me links to Kernel/Filesystems which
|
|
|
|
I can share with users of gBootRoot.
|
|
|
|
|
|
|
|
- A developer creating a mini distribution can concentrate his efforts on
|
|
|
|
perfecting the filesystem, and then he can use gBootRoot to quickly create a
|
|
|
|
Boot/Root set to run tests.
|
|
|
|
|
|
|
|
- Disk sets allow for more space to include interesting and necessary things.
|
|
|
|
The size of the Kernel is increasing every day making sets advantageous.
|
|
|
|
|
|
|
|
How to Use gBootRoot:
|
|
|
|
|
|
|
|
gBootRoot is similar to BootRoot, but it is more efficient
|
|
|
|
and powerful. 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".
|
|
|
|
|
|
|
|
There are 5 rows. The boot method column has only one choice "lilo."
|
|
|
|
Clicking on the menu on the right selects the 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.
|
|
|
|
|
|
|
|
NOTE:
|
|
|
|
Presently you need to press [Enter] on your keyboard to select what you
|
|
|
|
typed in, but one advantage of this is that gBootRoot understands shell
|
|
|
|
notation like ../twobelow/kernel. The only disadvantage of this is that my
|
|
|
|
program may be written up as an example in a GUI blooper book. :)
|
|
|
|
|
|
|
|
The third row allows you to select the compressed filesystem you are
|
|
|
|
providing, using either of the two ways mentioned before.
|
|
|
|
|
|
|
|
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.
|
|
|
|
If you choose the compressed filesystem with the file selector the program
|
|
|
|
should automatically detect the compression used, otherwise, click on the
|
|
|
|
appropriate radio button to choose either gzip or bzip2 compression.
|
|
|
|
|
|
|
|
Little things you may want to know:
|
|
|
|
|
|
|
|
* gBootRoot requires ash for initrd. Ash is a feather weight version of Bash.
|
|
|
|
|
|
|
|
HELP
|
|
|
|
|
|
|
|
}
|