summaryrefslogtreecommitdiffstats
path: root/perl-install/devices.pm
blob: e3ecc318572a431e15ed677a62190e60ac86b0dd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
package devices; # $Id$

use diagnostics;
use strict;

use common;
use run_program;
use log;
use c;

sub size {
    my ($dev) = @_;
    sysopen(my $F, $dev, 0) or log::l("open $dev: $!"), return 0;

    my $valid_offset = sub { sysseek($F, $_[0], 0) && sysread($F, my $_a, 1) };

    #- first try getting the size nicely
    if (my $size = c::total_sectors(fileno $F)) {
	return $size * $common::SECTORSIZE;
    }

    #- sad it didn't work, well searching the size using the dichotomy algorithm!
    my $low = 0;
    my ($high, $mid);

    #- first find n where 2^n < size <= 2^n+1
    for ($high = 1; $high > 0 && $valid_offset->($high); $high *= 2) { $low = $high }

    while ($low < $high - 1) {
	$mid = int(($low + $high) / 2);
	$valid_offset->($mid) ? $low : $high = $mid;
    }
    $low + 1;
}

sub del_loop {
    my ($dev) = @_;
    run_program::run("losetup", "-d", $dev);
}
sub find_free_loop() {
    foreach (0..7) {
	my $dev = make("loop$_");
	sysopen(my $F, $dev, 2) or next;
	!ioctl($F, c::LOOP_GET_STATUS(), my $_tmp) && $! == 6 or next; #- 6 == ENXIO
	return $dev;
    }
    die "no free loop found";
}
sub set_loop {
    my ($file, $o_encrypt_key, $o_encryption) = @_;
    my $dev = find_free_loop();

    if ($o_encrypt_key && $o_encryption) {
	my $cmd = "losetup -p 0 -e $o_encryption $dev $file";
	log::l("calling $cmd");
	open(my $F, "|$cmd");
	print $F $o_encrypt_key;
	close $F or die "losetup failed";
    } else {
	run_program::run("losetup", $dev, $file) or return;
    }
    $dev;
}

sub entry {
    my ($type, $major, $minor);
    local ($_) = @_;

    if (/^0x([\da-f]{3,4})$/i) {
	$type = c::S_IFBLK();
	($major, $minor) = unmakedev(hex $1);
    } elsif (/^sd(.)(\d{0,2})/) {
	$type = c::S_IFBLK();
	$major = 8;
	$minor = 16 * (ord($1) - ord('a')) + ($2 || 0);
    } elsif (/^hd(.)(\d{0,2})/) {
	$type = c::S_IFBLK();
	($major, $minor) =
	    @{ ${{'a' => [3, 0], 'b' => [3, 64],
		   'c' => [22,0], 'd' => [22,64],
		   'e' => [33,0], 'f' => [33,64],
		   'g' => [34,0], 'h' => [34,64],
		   'i' => [56,0], 'j' => [56,64],
		   'k' => [57,0], 'l' => [57,64],
                   'm' => [88,0], 'n' => [88,64],
                   'o' => [89,0], 'p' => [89,64],
                   'q' => [90,0], 'r' => [90,64],
                   's' => [91,0], 't' => [91,64],
	       }}{$1} or die "unknown device $_" };
	$minor += $2 || 0;
    } elsif (/^ram(.*)/) {
	$type = c::S_IFBLK();
	$major = 1;
	$minor = $1 eq '' ? 1 : $1;
    } elsif (m|^rd/c(\d+)d(\d+)(p(\d+))?|) {
	# dac 960 "rd/cXdXXpX"
        $type = c::S_IFBLK();
	$major = 48 + $1;
	$minor = 8 * $2 + $4;
    } elsif (m,(ida|cciss)/c(\d+)d(\d+)(?:p(\d+))?,) {
	# Compaq Smart Array "ida/c0d0{p1}"
	$type = c::S_IFBLK();
	$major = ($1 eq 'ida' ? 72 : 104) + $2;
	$minor = 16 * $3 + ($4 || 0);
    } elsif (m,(ataraid)/d(\d+)(?:p(\d+))?,) {
	# ATA raid "ataraid/d0{p1}"
	$type = c::S_IFBLK();
	$major = 114;
	$minor = 16 * $1 + ($2 || 0);
    } elsif (/(.*?)(\d+)$/) {
	    ($type, $major, $minor) =
	     @{ ${{"fd"          => [ c::S_IFBLK(), 2,  0  ],
		   "hidbp-mse-"  => [ c::S_IFCHR(), 10, 32 ],
		   "lp"          => [ c::S_IFCHR(), 6,  0  ],
		   "usb/lp"      => [ c::S_IFCHR(), 180, 0 ],
		   "input/event" => [ c::S_IFCHR(), 13, 64 ],
		   "loop"        => [ c::S_IFBLK(), 7,  0  ],
		   "md"          => [ c::S_IFBLK(), 9,  0  ],
		   "nst"         => [ c::S_IFCHR(), 9, 128 ],
		   "scd"         => [ c::S_IFBLK(), 11, 0  ],
		   "ttyS"        => [ c::S_IFCHR(), 4, 64  ],
		   "ubd/"        => [ c::S_IFBLK(), 98, 0  ],
	       }}{$1} };
	    $minor += $2;
    }
    unless ($type) {
	($type, $major, $minor) =
	     @{ ${{"aztcd"    => [ c::S_IFBLK(), 29, 0  ],
		   "bpcd"     => [ c::S_IFBLK(), 41, 0  ],
		   "cdu31a"   => [ c::S_IFBLK(), 15, 0  ],
		   "cdu535"   => [ c::S_IFBLK(), 24, 0  ],
		   "cm206cd"  => [ c::S_IFBLK(), 32, 0  ],
		   "gscd"     => [ c::S_IFBLK(), 16, 0  ],
		   "mcd"      => [ c::S_IFBLK(), 23, 0  ],
		   "mcdx"     => [ c::S_IFBLK(), 20, 0  ],
		   "mem"      => [ c::S_IFCHR(), 1,  1  ],
		   "optcd"    => [ c::S_IFBLK(), 17, 0  ],
		   "kbd"      => [ c::S_IFCHR(), 11, 0  ],
		   "psaux"    => [ c::S_IFCHR(), 10, 1  ],
		   "atibm"    => [ c::S_IFCHR(), 10, 3  ],
		   "random"   => [ c::S_IFCHR(), 1,  8  ],
		   "sbpcd"    => [ c::S_IFBLK(), 25, 0  ],
		   "sjcd"     => [ c::S_IFBLK(), 18, 0  ],
		   "tty"      => [ c::S_IFCHR(),  5, 0  ],
		   "usbmouse" => [ c::S_IFCHR(), 13, 63 ], #- aka /dev/input/mice
		   "adbmouse" => [ c::S_IFCHR(), 10, 10 ], #- PPC
		   "vcsa"     => [ c::S_IFCHR(), 7,  128 ],
		   "zero"     => [ c::S_IFCHR(), 1,  5  ],		     
		   "null"     => [ c::S_IFCHR(), 1,  3  ],		     
	       }}{$_} or die "unknown device $_ (caller is " . join(":", caller()) . ")" };
    }
    ($type, $major, $minor);
}


sub make($) {
    local $_ = my $file = $_[0];

    if (m,^(.*/(?:dev|tmp))/(.*),) {
	$_ = $2;
    } else {
	$file =~ m|^/| && -e $file or $file = "/tmp/$_";
	$file =~ m|^/| && -e $file or $file = "/dev/$_";
    }
    -e $file and return $file; #- assume nobody takes fun at creating files named as device

    my ($type, $major, $minor) = eval { entry($_) };
    $@ and die "unknown device $_ (caller is " . join(":", caller()) . ")";

    if ($file =~ m|/dev/| && -e '/dev/.devfsd') {
	#- argh, creating devices is no good with devfs...
	#- return the file even if the device file doesn't exist
	#- the caller will fail or not, better compatibility than raising an exception here
	return $file;
    }

    #- make a directory for this inode if needed.
    mkdir_p(dirname($file));

    syscall_('mknod', $file, $type | 0600, makedev($major, $minor)) or die "mknod failed (dev $_): $!";

    $file;
}


#- only isomorphic entries are allowed, 
#- i.e. entries which can go devfs -> normal and normal -> devfs
my %to_devfs = (
    psaux => 'misc/psaux',
    usbmouse => 'input/mice',
);
my %to_devfs_prefix = (
    ttyS => 'tts/',
);

sub to_devfs {
    my ($dev) = @_;
    if (my $r = $to_devfs{$dev}) { 
	return $r;
    } elsif ($dev =~ /(.*?)(\d+)$/) {
	my $r = $to_devfs_prefix{$1};
	return "$r$2" if $r;
    }
    undef;
}

sub from_devfs {
    my ($dev) = @_;
    my %from_devfs = reverse %to_devfs;
    if (my $r = $from_devfs{$dev}) { 
	return $r;
    } elsif ($dev =~ /(.*?)(\d+)$/) {
	my %from_devfs_prefix = reverse %to_devfs_prefix;
	my $r = $from_devfs_prefix{$1};
	return "$r$2" if $r;
    }
    undef;
}

1;
pt">($o->{packages}) > 0; } #------------------------------------------------------------------------------ sub installPackages { my ($_clicked, $ent_number, $auto) = @_; installStepsCall($o, $auto, 'readBootloaderConfigBeforeInstall') if $ent_number == 1; installStepsCall($o, $auto, 'beforeInstallPackages'); installStepsCall($o, $auto, 'installPackages'); installStepsCall($o, $auto, 'afterInstallPackages'); } #------------------------------------------------------------------------------ sub miscellaneous { my ($clicked, $_ent_number, $auto) = @_; installStepsCall($o, $auto, 'miscellaneousBefore', $clicked); installStepsCall($o, $auto, 'miscellaneous', $clicked); installStepsCall($o, $auto, 'miscellaneousAfter', $clicked); } #------------------------------------------------------------------------------ sub summary { my ($_clicked, $ent_number, $auto) = @_; installStepsCall($o, $auto, 'summary', $ent_number == 1); } #------------------------------------------------------------------------------ sub configureNetwork { my ($_clicked, $_ent_number, $auto) = @_; #- get current configuration of network device. require network; eval { network::read_all_conf($o->{prefix}, $o->{netc} ||= {}, $o->{intf} ||= {}) }; installStepsCall($o, $auto, 'configureNetwork') if !$o->{isUpgrade}; } #------------------------------------------------------------------------------ sub installUpdates { my ($_clicked, $_ent_number, $auto) = @_; installStepsCall($o, $auto, 'installUpdates'); } #------------------------------------------------------------------------------ sub configureServices { my ($clicked, $_ent_number, $auto) = @_; installStepsCall($o, $auto, 'configureServices', $clicked); } #------------------------------------------------------------------------------ sub setRootPassword { my ($clicked, $_ent_number, $auto) = @_; return if $o->{isUpgrade}; installStepsCall($o, $auto, 'setRootPassword', $clicked); addToBeDone { install_any::setAuthentication($o) } 'installPackages'; } #------------------------------------------------------------------------------ sub addUser { my ($clicked, $_ent_number, $auto) = @_; return if $o->{isUpgrade} && !$clicked; installStepsCall($o, $auto, 'addUser', $clicked); } #------------------------------------------------------------------------------ sub createBootdisk { my ($clicked, $ent_number, $auto) = @_; modules::write_conf($o->{prefix}); installStepsCall($o, $auto, 'createBootdisk', $ent_number == 1, $clicked); } #------------------------------------------------------------------------------ sub setupBootloader { my ($_clicked, $ent_number, $auto) = @_; return if $::g_auto_install || $::uml_install; modules::write_conf($o->{prefix}); installStepsCall($o, $auto, 'setupBootloaderBefore') if $ent_number == 1; installStepsCall($o, $auto, 'setupBootloader'); local $ENV{DRAKX_PASSWORD} = $o->{bootloader}{password}; local $ENV{DURING_INSTALL} = 1; run_program::rooted($o->{prefix}, "/usr/sbin/msec", "-o", "run_commands=0", "-o", "log=stderr", $o->{security}); require security::various; security::various::config_libsafe($o->{prefix}, $o->{libsafe}); security::various::config_security_user($o->{prefix}, $o->{security_user}); } #------------------------------------------------------------------------------ sub configureX { my ($_clicked, $_ent_number, $auto) = @_; #- done here and also at the end of install2.pm, just in case... install_any::write_fstab($o); modules::write_conf($o->{prefix}); require pkgs; installStepsCall($o, $auto, 'configureX') if pkgs::packageByName($o->{packages}, 'XFree86')->flag_installed && !$o->{X}{disabled} || $::testing; } #------------------------------------------------------------------------------ sub exitInstall { my ($_clicked, $_xent_number, $auto) = @_; installStepsCall($o, $auto, 'exitInstall', getNextStep() eq 'exitInstall'); } sub start_i810fb { my ($vga) = cat_('/proc/cmdline') =~ /vga=(\S+)/; return if !$vga || listlength(cat_('/proc/fb')); my %vga_to_xres = (0x311 => '640', 0x314 => '800', 0x317 => '1024'); my $xres = $vga_to_xres{$vga} || '800'; log::l("trying to load i810fb module with xres <$xres> (vga was <$vga>)"); eval { any::ddcxinfos(); # keep the result otherwise ddcxinfos doesn't return good results afterwards modules::load([ 'i810fb', "xres=$xres", 'hsync1=32', 'hsync2=48', 'vsync1=50', 'vsync2=70', #- this sucking i810fb does not accept floating point numbers in hsync! 'vram=2', 'bpp=16', 'accel=1', 'mtrr=1', 'hwcur=1', 'xcon=4' ]); }; } #-###################################################################################### #- MAIN #-###################################################################################### sub main { $SIG{__DIE__} = sub { chomp(my $err = $_[0]); log::l("warning: $err") }; $SIG{SEGV} = sub { my $msg = "segmentation fault: seems like memory is missing as the install crashes"; print "$msg\n"; log::l($msg); $o->ask_warn('', $msg); setVirtual(1); require install_steps_auto_install; install_steps_auto_install_non_interactive::errorInStep(); }; $ENV{PERL_BADLANG} = 1; umask 022; $::isInstall = 1; $::isWizard = 1; $::no_ugtk_init = 1; $::expert = $::g_auto_install = 0; #- c::unlimit_core() unless $::testing; my ($cfg, $patch, @auto); my %cmdline; map { my ($n, $v) = split '='; $cmdline{$n} = $v || 1; } split ' ', cat_("/proc/cmdline"); my $opt; foreach (@_) { if (/^--?(.*)/) { $cmdline{$opt} = 1 if $opt; $opt = $1; } else { $cmdline{$opt} = $_ if $opt; $opt = ''; } } $cmdline{$opt} = 1 if $opt; map_each { my ($n, $v) = @_; my $f = ${{ oem => sub { $::oem = $v }, lang => sub { $o->{lang} = $v }, flang => sub { $o->{lang} = $v; push @auto, 'selectLanguage' }, method => sub { $o->{method} = $v }, pcmcia => sub { $o->{pcmcia} = $v }, vga16 => sub { $o->{vga16} = $v }, vga => sub { $o->{vga} = $v }, step => sub { $o->{steps}{first} = $v }, expert => sub { $::expert = $v }, meta_class => sub { $o->{meta_class} = $v }, lnx4win => sub { $o->{lnx4win} = 1 }, readonly => sub { $o->{partitioning}{readonly} = $v ne "0" }, display => sub { $o->{display} = $v }, askdisplay => sub { print "Please enter the X11 display to perform the install on ? "; $o->{display} = chomp_(scalar(<STDIN>)) }, security => sub { $o->{security} = $v }, live => sub { $::live = 1 }, noauto => sub { $::noauto = 1 }, test => sub { $::testing = 1 }, patch => sub { $patch = 1 }, defcfg => sub { $cfg = $v }, newt => sub { $o->{interactive} = "newt" }, text => sub { $o->{interactive} = "newt" }, stdio => sub { $o->{interactive} = "stdio" }, corporate => sub { $::corporate = 1 }, kickstart => sub { $::auto_install = $v }, uml_install => sub { $::uml_install = 1 }, auto_install => sub { $::auto_install = $v }, simple_themes => sub { $o->{simple_themes} = 1 }, useless_thing_accepted => sub { $o->{useless_thing_accepted} = 1 }, alawindows => sub { $o->{security} = 0; $o->{partitioning}{clearall} = 1; $o->{bootloader}{crushMbr} = 1 }, fdisk => sub { $o->{partitioning}{fdisk} = 1 }, g_auto_install => sub { $::testing = $::g_auto_install = 1; $o->{partitioning}{auto_allocate} = 1 }, nomouseprobe => sub { $o->{nomouseprobe} = $v }, blank => sub { $o->{blank} = $::blank = 1 }, updatemodules => sub { $o->{updatemodules} = 1 }, }}{lc $n}; &$f if $f; } %cmdline; if ($::testing) { $ENV{SHARE_PATH} ||= "/export/Mandrake/mdkinst/usr/share"; $ENV{SHARE_PATH} = "/usr/share" if !-e $ENV{SHARE_PATH}; } else { $ENV{SHARE_PATH} ||= "/usr/share"; } undef $::auto_install if $cfg; if ($::g_auto_install) { (my $root = `/bin/pwd`) =~ s|(/[^/]*){5}$||; symlinkf $root, "/tmp/image" or die "unable to create link /tmp/image"; $o->{method} ||= "cdrom"; $o->{mkbootdisk} = 0; } if (!$::testing && !$::live) { symlink "rhimage", "/tmp/image"; #- for compatibility with old stage1 unlink $_ foreach "/modules/modules.mar", "/sbin/stage1"; } print STDERR "in second stage install\n"; log::openLog(($::testing || $o->{localInstall}) && 'debug.log'); log::l("second stage install running (", any::drakx_version(), ")"); $o->{prefix} = $::prefix = $::testing ? "/tmp/test-perl-install" : $::live ? "" : "/mnt"; $o->{isUpgrade} = 1 if $::live; mkdir $o->{prefix}, 0755; devices::make("/dev/zero"); #- needed by ddcxinfos #- make sure we don't pick up any gunk from the outside world my $remote_path = "$o->{prefix}/sbin:$o->{prefix}/bin:$o->{prefix}/usr/sbin:$o->{prefix}/usr/bin:$o->{prefix}/usr/X11R6/bin"; $ENV{PATH} = "/usr/bin:/bin:/sbin:/usr/sbin:/usr/X11R6/bin:$remote_path" unless $::g_auto_install; eval { spawnShell() }; modules::load_dependencies(($::testing ? ".." : "") . "/modules/modules.dep"); modules::read_stage1_conf($_) foreach "/tmp/conf.modules", "/etc/modules.conf"; modules::read_already_loaded(); #- done before auto_install is called to allow the -IP feature on auto_install file name if (-e '/tmp/network') { require network; #- get stage1 network configuration if any. log::l('found /tmp/network'); $o->{netc} ||= {}; add2hash($o->{netc}, network::read_conf('/tmp/network')); if (my ($file) = glob_('/tmp/ifcfg-*')) { log::l("found network config file $file"); my $l = network::read_interface_conf($file); $o->{intf} ||= { $l->{DEVICE} => $l }; } if (-e '/etc/resolv.conf') { my $file = '/etc/resolv.conf'; log::l("found network config file $file"); add2hash($o->{netc}, network::read_resolv_conf($file)); } } #- done after module dependencies are loaded for "vfat depends on fat" if ($::auto_install) { if ($::auto_install =~ /-IP(\.pl)?$/) { my $ip = join('', map { sprintf "%02X", $_ } split '\.', $o->{intf}{IPADDR}); $::auto_install =~ s/-IP(\.pl)?$/-$ip$1/; } require install_steps_auto_install; eval { $o = $::o = install_any::loadO($o, $::auto_install) }; if ($@) { if ($o->{useless_thing_accepted}) { #- Pixel's hack to be able to fail through log::l("error using auto_install, continuing"); undef $::auto_install; } else { print "Error using auto_install\n$@\n"; install_steps_auto_install_non_interactive::errorInStep(); } } else { log::l("auto install config file loaded successfully"); } } $o->{interactive} ||= 'gtk' if !$::auto_install; if ($o->{interactive} eq "gtk" && availableMemory() < 22 * 1024) { log::l("switching to newt install cuz not enough memory"); $o->{interactive} = "newt"; } # perl_checker: require install_steps_gtk # perl_checker: require install_steps_newt # perl_checker: require install_steps_stdio require "install_steps_$o->{interactive}.pm" if $o->{interactive}; #- needed before accessing floppy (in case of usb floppy) modules::load_category('bus/usb'); #- oem patch should be read before to still allow patch or defcfg. eval { $o = $::o = install_any::loadO($o, "Mandrake/base/patch-oem.pl"); log::l("successfully read oem patch") }; #- patch should be read after defcfg in order to take precedance. eval { $o = $::o = install_any::loadO($o, $cfg); log::l("successfully read default configuration: $cfg") } if $cfg; eval { $o = $::o = install_any::loadO($o, "patch"); log::l("successfully read patch") } if $patch; eval { modules::load("af_packet") }; require harddrake::sound; harddrake::sound::configure_sound_slots(); #- needed very early for install_steps_gtk eval { $o->{mouse} = mouse::detect() } if !$o->{nomouseprobe} && !$o->{mouse} && !$::testing; $o->{lang} = lang::set($o->{lang}) if $o->{lang} ne 'en_US'; #- mainly for defcfg start_i810fb(); $o->{allowFB} = listlength(cat_("/proc/fb")); my $VERSION = cat__(install_any::getFile("VERSION")) or do { print "VERSION file missing\n"; sleep 5 }; $o->{lnx4win} = 1 if $VERSION =~ /lnx4win/i; $o->{meta_class} = 'desktop' if $VERSION =~ /desktop/i; $o->{meta_class} = 'firewall' if $VERSION =~ /firewall/i; $o->{meta_class} = 'server' if $VERSION =~ /server/i; if ($::oem) { $o->{partitioning}{use_existing_root} = 1; $o->{compssListLevel} = 4; push @auto, 'selectInstallClass', 'doPartitionDisks', 'choosePackages', 'configureTimezone', 'exitInstall'; } foreach (@auto) { my $s = $o->{steps}{/::(.*)/ ? $1 : $_} or next; $s->{auto} = $s->{hidden} = 1; } my $o_; while (1) { $o_ = $::auto_install ? install_steps_auto_install->new($o) : $o->{interactive} eq "stdio" ? install_steps_stdio->new($o) : $o->{interactive} eq "newt" ? install_steps_newt->new($o) : $o->{interactive} eq "gtk" ? install_steps_gtk->new($o) : die "unknown install type"; $o_ and last; $o->{interactive} = "newt"; require install_steps_newt; } $::o = $o = $o_; install_any::remove_unused() if common::usingRamdisk(); #-the main cycle my $clicked = 0; MAIN: for ($o->{step} = $o->{steps}{first};; $o->{step} = getNextStep()) { $o->{steps}{$o->{step}}{entered}++; $o->enteringStep($o->{step}); if ($o->{steps}{$o->{step}}{icon}) { $o->{icon} = $o->{steps}{$o->{step}}{icon} } else { undef $o->{icon} } eval { &{$install2::{$o->{step}}}($clicked || $o->{steps}{$o->{step}}{noauto}, $o->{steps}{$o->{step}}{entered}, $clicked ? 0 : $o->{steps}{$o->{step}}{auto}); }; my $err = $@; $o->kill_action; $clicked = 0; if ($err) { local $_ = $err; $o->kill_action; if (!/^already displayed/) { eval { $o->errorInStep($_) }; $o->{steps}{$o->{step}}{auto} = 0; $err = $@; $err and next; } $o->{step} = $o->{steps}{$o->{step}}{onError}; next MAIN unless $o->{steps}{$o->{step}}{reachable}; #- sanity check: avoid a step not reachable on error. redo MAIN; } $o->{steps}{$o->{step}}{done} = 1; $o->leavingStep($o->{step}); last if $o->{step} eq 'exitInstall'; } install_any::clean_postinstall_rpms(); install_any::log_sizes($o); install_any::remove_advertising($o); install_any::write_fstab($o); modules::write_conf($o->{prefix}); detect_devices::install_addons($o->{prefix}); #- mainly for auto_install's #- do not use run_program::xxx because it doesn't leave stdin/stdout unchanged system("bash", "-c", $o->{postInstallNonRooted}) if $o->{postInstallNonRooted}; system("chroot", $o->{prefix}, "bash", "-c", $o->{postInstall}) if $o->{postInstall}; install_any::ejectCdrom(); #- to ensure linuxconf doesn't cry against those files being in the future foreach ('/etc/modules.conf', '/etc/crontab', '/etc/sysconfig/mouse', '/etc/sysconfig/network', '/etc/X11/fs/config') { my $now = time() - 24 * 60 * 60; utime $now, $now, "$o->{prefix}/$_"; } $::live or install_any::killCardServices(); #- make sure failed upgrade will not hurt too much. install_steps::cleanIfFailedUpgrade($o); -e "$o->{prefix}/usr/sbin/urpmi.update" or eval { rm_rf("$o->{prefix}/var/lib/urpmi") }; #- copy latest log files eval { cp_af("/tmp/$_", "$o->{prefix}/root/drakx") foreach qw(ddebug.log stage1.log) }; #- ala pixel? :-) [fpons] common::sync(); common::sync(); log::l("installation complete, leaving"); log::l("files still open by install2: ", readlink($_)) foreach glob_("/proc/self/fd/*"); print "\n" x 80; } 1;