summaryrefslogtreecommitdiffstats
path: root/lib/MGA/DrakISO/Loopback.pm
blob: ff5e3f58e3c7fccacb35c9f927e8ff8dd6bca677 (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
package MGA::DrakISO::Loopback;

use strict;

use MDK::Common;

use File::Temp;

use MGA::DrakISO::Mounts;
use MGA::DrakISO::Utils;

use Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(%loop_types);

my $loop_number = 0;
our %loop_types;
%loop_types = (
    squashfs => {
        read_only => 1,
        is_loopback => 1,
        modules => sub { "loop", best_squashfs4_compression($_[0]) ? "squashfs" : "squashfs_lzma" },
        extension => '-lzma.sqfs',
        build => sub {
            my ($build, $dir) = @_;
            my $dest = $build->get_builddir('loopbacks') . $dir->{path} . $loop_types{squashfs}{extension};
            mkdir_p(dirname($dest));
            my $root = $dir->{root} || $build->get_system_root;
            my $src = $root . $dir->{build_from};
            my $total = directory_usage($src);
            print "have to process " . int($total/1000000) . " MB\n";
            my $exclude_file = tmpnam();
            output_p($exclude_file, map { $root . "$_\n" }  grep { -e $root . $_ } @{$dir->{exclude} || []});
            my $sort = $build->{settings}{config_root} . '/' . $dir->{sort};
            my $squashfs4_comp = best_squashfs4_compression($build);
            run_($squashfs4_comp ? 'mksquashfs' : 'mksquashfs3', $src, $dest,
                 $squashfs4_comp ? ('-comp', $squashfs4_comp) : '-lzma',
                 '-noappend', '-b', '1048576',
                 #'-processors', 1,
                 '-ef', $exclude_file,
                 if_(-f $sort, '-sort', $sort),
            ) or die "unable to run mksquashfs\n";
            unlink $exclude_file;
        },
        mount => sub {
            my ($dir) = @_;
            $dir->{loop} = "/dev/loop" . $loop_number++;
            my $extension = $dir->{path} . $loop_types{squashfs}{extension};
            my $mountpoint = $dir->{mountpoint};
            (
                "/bin/losetup $dir->{loop} /live/media/loopbacks$extension",
                "nash-mount -o ro -t squashfs $dir->{loop} /live$mountpoint",
            );
        },
    },
    modules => {
        read_only => 1,
        delay_mount => 1,
        mount => sub {
            my ($dir) = @_;
            my $path = $dir->{path};
            my $mountpoint = $dir->{mountpoint};
            "sh -c 'modules=;"
                 . "for m in /live/media/loopbacks$path/*; do"
                 .   "n=\$(basename \$m);"
                 .   "n=\${n%.sqfs};"
                 .   "d=/live$mountpoint/\$n;"
                 .   "mkdir -p \$d;"
                 .   "mount -n -o loop,ro -t squashfs \$m \$d && modules=\$modules\$d=ro:;"
                 . "done;"
                 . "echo \$modules | sed -e s/:\$// > /live/$dir->{list}'";
        },
        pivot_clean => sub {
            my ($dir, $initrdroot) = @_;
            my $list = $dir->{list};
            my $mountpoint = $dir->{mountpoint};
            (
                "sh -c 'cd $initrdroot/live$mountpoint;"
                     . "for i in `ls -1`; do"
                     .   "mkdir -p /live$mountpoint/\$i;"
                     .   "mount -n --move \$i /live$mountpoint/\$i;"
                     .   "rmdir \$i;"
                     . "done;"
                     . "rmdir $initrdroot/live$mountpoint'",
                "sh -c 'mv $initrdroot/live/$list /live/'",
            );
        },
    },
    loopfs => {
        is_loopback => 1,
        modules => [],
        extension => '.loop',
        build => sub {
            my ($build, $dir) = @_;
            my $dest = $build->get_builddir('loopbacks') . $dir->{path} . $loop_types{loopfs}{extension};
            mkdir_p(dirname($dest));
            MGA::DrakISO::Utils::device_allocate_file($dest, $dir->{pre_allocate});
            MGA::DrakISO::Utils::device_mkfs($dest, $dir->{fs}) if !defined $dir->{min_size};
        },
        mount => sub {
            my ($dir) = @_;
            $dir->{loop} = "/dev/loop" . $loop_number++;
            my $sqfs = $MGA::DrakISO::Mounts::dir_distrib_sqfs->{mountpoint};
            my $fsck = "chroot </dev/tty1 /live/$sqfs /sbin/fsck $dir->{loop}";
            my $extension = $dir->{path} . $loop_types{loopfs}{extension};
            my $mountpoint = $dir->{mountpoint};
            (
                "losetup $dir->{loop} /live/media/loopbacks$extension",
                qq(sh -c "$fsck -a || $fsck -y"),
                "nash-mount -t $dir->{fs} $dir->{loop} /live$mountpoint",
            );
        },
    },
    plain => {
        skip_mkdir => 1,
        mount => sub { 
            my ($dir) = @_;
            my $mountpoint = $dir->{mountpoint};
            qq(sh -c "mkdir -p /live$mountpoint");
        },
    },
    partition => {
        files => [ '/sbin/fsck', '/sbin/blkid' ],
        mount => sub {
            my ($dir) = @_;
            my $fsck = "/bin/fsck";
            my $path = $dir->{path};
            my $mountpoint = $dir->{mountpoint};
            (
             qq(sh -c 'dev=`blkid -l -t $path -o device`; [ -z "\$dev" ] || $fsck -a \$dev || $fsck -y \$dev'),
             "nash-mount -t $dir->{fs} $path /live$mountpoint",
            );
        },
    },
    tmpfs => {
        mount => sub {
            my ($dir) = @_;
            my $mnt = '/live' . $dir->{mountpoint};
            my $mount_opts = $dir->{mount_opts} ? "-o $dir->{mount_opts}" : "";
            my $cmd = "mount -t tmpfs $mount_opts $mnt $mnt";
            $dir->{fallback} ? qq(sh -c 'if ! grep -q " $mnt " /proc/mounts; then $cmd; fi') : $cmd;
        },
    },
);

sub has_squashfs4_with {
    my ($build, $comp) = @_;
    my $ucomp = uc($comp);
    cat_($build->get_system_root . "/boot/config-" . $build->find_kernel->{version}) =~ /^CONFIG_SQUASHFS_$ucomp=y$/m;
}

sub mksquashfs4_compressors() {
    map { /^Compressors available/ .. /^$/ ? if_(/^\t(\w+)/, chomp_($1)) : () } `mksquashfs 2>&1`;
}

sub best_squashfs4_compression {
    my ($build) = @_;
    find { has_squashfs4_with($build, $_) } intersection([ mksquashfs4_compressors() ], [ qw(xz lzma) ]);
}

1;