summaryrefslogtreecommitdiffstats
path: root/tools/drakx-in-chroot
blob: 8cce1985950f44c0291631f1f7edd062d62da6db (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
#!/usr/bin/perl

use MDK::Common;

my $SLASH_LOCATION = '/tmp/drakx-in-chroot';

my $verbose = 0;
my $prefix_ROOTED = '/mnt';
my $IMAGE_LOCATION_ROOTED = '/tmp/image';
my $STAGE2_LOCATION_ROOTED = '/tmp/stage2';
my $LIVE_LOCATION_REL = 'install/stage2/live/';
my $CLP_LOCATION_REL = 'install/stage2/';
my $CLP_FILE_REL = $CLP_LOCATION_REL . 'mdkinst.clp';

@ARGV >= 2 or die "usage: drakx-in-chroot <repository> <dir to install to> [options]\n";

(my $repository, my $dir, @ARGV) = @ARGV;
my $STAGE2_LOCATION = $SLASH_LOCATION . $STAGE2_LOCATION_ROOTED;

my $sudo;
if ($>) {
    $sudo = "sudo";
    $ENV{PATH} = "/sbin:/usr/sbin:$ENV{PATH}";
}

undef $ENV{TMPDIR}; # prevent packdrake faillure on creating temporary files

if (-d $SLASH_LOCATION) {
    umount_all() == 0 or die "$SLASH_LOCATION is busy\n";
    sys("$sudo rm -rf $SLASH_LOCATION/var/lib/rpm $SLASH_LOCATION/dev/mapper");
    rm_rf($SLASH_LOCATION);
}

mkdir_p("$SLASH_LOCATION$_") foreach '/dev', '/dev/usb', '/etc', '/var', '/proc', $STAGE2_LOCATION_ROOTED, $IMAGE_LOCATION_ROOTED, $prefix_ROOTED;

sys("$sudo rm -rf $dir") if $ENV{CLEAN};
-e $dir or sys("$sudo mkdir -p $dir");

if (-d "$repository/$LIVE_LOCATION_REL") {
    sys("$sudo mount -o bind $repository/$LIVE_LOCATION_REL $STAGE2_LOCATION");
} elsif (-e "$repository/$CLP_FILE_REL") {
    my $dev = find_free_loop();
    sys("$sudo modprobe gzloop");
    sys("$sudo losetup -r -e gz $dev $repository/$CLP_FILE_REL");
    sys("$sudo mount -r $dev $STAGE2_LOCATION");
}

sys("$sudo mount -o bind $dir $SLASH_LOCATION$prefix_ROOTED");
sys("$sudo mount -o bind $repository $SLASH_LOCATION$IMAGE_LOCATION_ROOTED");
sys("$sudo mount -t proc none $SLASH_LOCATION/proc");
create_initial_symlinks();
create_initial_devices();

output("$SLASH_LOCATION/etc/hosts", "127.0.0.1 localhost\n") if ! -e "$SLASH_LOCATION/etc/hosts";

my $Xnest_pid;
if (whereis_binary('Xnest')) {
    my $DISPLAY = ':8';
    $Xnest_pid = fork();
    if (!$Xnest_pid) {
	exec 'Xnest', $DISPLAY, '-ac', '-geometry', '800x600' or die "Xnest failed\n";
    }
    $ENV{DISPLAY} = 'localhost' . $DISPLAY;
}

if (my $pid = fork()) {
    waitpid $pid, 0;
    umount_all() == 0 or warn "umounting failed\n";
    kill 15, $Xnest_pid;
} else {
    $ENV{HOME} = '/';
    # to kept sync with gi/mdk-stage1/init.c::env:
    $ENV{LD_LIBRARY_PATH}='/lib:/usr/lib:/mnt/lib:/mnt/usr/lib:/usr/X11R6/lib:/mnt/usr/X11R6/lib:/lib64:/usr/lib64:/usr/X11R6/lib64:/mnt/lib64:/mnt/usr/lib64:/mnt/usr/X11R6/lib64';
    my $cmd = join(' ', "/usr/bin/runinstall2 --local_install", @ARGV);
    exec "$sudo chroot $SLASH_LOCATION $cmd" or die "exec $cmd in $SLASH_LOCATION failed\n";
}

sub system_verbose { warn join(' ', @_), "\n" if $verbose; system(@_) }
sub sys { &system_verbose; $? and die qq(running "@_" failed: $?\n) }

sub find_free_loop() {
    foreach (0..255) {
	my $dev = "/dev/loop$_";
	system("$sudo losetup $dev >/dev/null 2>&1") != 0 or next;
	warn "found free loop $dev\n";
	return $dev;
    }
    die "no free loop found";
}

sub create_initial_symlinks() {
    foreach (cat_or_die("$STAGE2_LOCATION/usr/share/symlinks")) {
	my ($from, $to_) = split;
	my $to = $SLASH_LOCATION . ($to_ || $from);
	$from = "$STAGE2_LOCATION_ROOTED$from" if !$to_;
	if (! -l $to) {
	    symlink $from, $to or die "symlinking $to failed\n";
	}
    }
}

sub create_initial_devices() {
    foreach (cat_or_die("$STAGE2_LOCATION/usr/share/devices")) {
	my ($node, $type, $major, $minor) = split;
	sys("$sudo mknod $SLASH_LOCATION$node $type $major $minor") if ! -e "$SLASH_LOCATION$node";
    }
}

sub umount_all() {
    my $err;
    my @procs = ('/proc/bus/usb', '/proc', '/sys');
    foreach ((map { "$prefix_ROOTED$_" } @procs, ''), @procs, $STAGE2_LOCATION_ROOTED, $IMAGE_LOCATION_ROOTED) {
	my $dir = "$SLASH_LOCATION$_";
	rmdir $dir;
	if (-d $dir) {
	    if (m!/proc/bus/usb! || begins_with($_, $prefix_ROOTED)) {
		system_verbose "$sudo umount $dir 2>/dev/null";
		next;
	    }
	    my ($loop) = cat_('/proc/mounts') =~ m!^(/dev/loop\d+) .*\Q$dir\E !m;
	    system_verbose "$sudo umount $dir";
	    sys("$sudo losetup -d $loop") if $loop;
	}
	rmdir $dir;
	if (-d $dir) {
	    warn "$dir is busy\n";
	    $err++;
	}
    }
    $err;
}