summaryrefslogtreecommitdiffstats
path: root/tools/drakx-in-chroot
blob: fe54207b792bf8b73d5285c0b0a57863e4455951 (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
#!/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);
    rm_rf(glob("$dir/*")) if $ENV{CLEAN};
}

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

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;
}