summaryrefslogtreecommitdiffstats
path: root/lib/MGA/DrakISO
diff options
context:
space:
mode:
Diffstat (limited to 'lib/MGA/DrakISO')
l---------lib/MGA/DrakISO/.perl_checker1
-rw-r--r--lib/MGA/DrakISO/Config.pm100
-rw-r--r--lib/MGA/DrakISO/CustomMedia.pm14
-rw-r--r--lib/MGA/DrakISO/Live.pm70
-rw-r--r--lib/MGA/DrakISO/Loopback.pm151
-rw-r--r--lib/MGA/DrakISO/Media.pm88
-rw-r--r--lib/MGA/DrakISO/Mounts.pm93
-rw-r--r--lib/MGA/DrakISO/Progress.pm31
-rw-r--r--lib/MGA/DrakISO/Storage.pm54
-rw-r--r--lib/MGA/DrakISO/StorageFS.pm56
-rw-r--r--lib/MGA/DrakISO/Utils.pm85
11 files changed, 743 insertions, 0 deletions
diff --git a/lib/MGA/DrakISO/.perl_checker b/lib/MGA/DrakISO/.perl_checker
new file mode 120000
index 0000000..6246b2f
--- /dev/null
+++ b/lib/MGA/DrakISO/.perl_checker
@@ -0,0 +1 @@
+../../../.perl_checker \ No newline at end of file
diff --git a/lib/MGA/DrakISO/Config.pm b/lib/MGA/DrakISO/Config.pm
new file mode 100644
index 0000000..a8b8e88
--- /dev/null
+++ b/lib/MGA/DrakISO/Config.pm
@@ -0,0 +1,100 @@
+package MGA::DrakISO::Config;
+
+use MDK::Common;
+use Pod::Usage;
+use Cwd 'getcwd';
+
+#- we bless Media objects here
+use MGA::DrakISO::Media;
+#- these modules can be used from config files
+use MGA::DrakISO::Mounts;
+use MGA::DrakISO::CustomMedia;
+
+our $default_config_root = '/etc/draklive';
+our $default_config_path = 'config/live.cfg';
+our $default_settings_path = 'config/settings.cfg';
+
+sub read_config {
+ my ($live, $config_root, $config_path, $settings_path) = @_;
+
+ if ($config_path && -e getcwd() . '/' . $config_path) {
+ $config_root = getcwd();
+ }
+ print "using $config_root as directory root\n";
+
+ add2hash($live->{settings} ||= {}, { getVarsFromSh($config_root . '/' . $settings_path) }) if $settings_path;
+ if ($config_path) {
+ #- don't use do(), since it can't see lexicals in the enclosing scope
+ my $cfg = eval(cat_($config_root . '/' . $config_path)) or die "unable to load $config_path: $@\n";
+ put_in_hash($live, $cfg);
+ print "loaded $config_path as config file\n";
+ }
+ $live->{settings}{config_root} = $config_root;
+}
+
+sub check_config {
+ my ($live) = @_;
+ unless (keys(%$live)) {
+ warn "no live definition\n";
+ Pod::Usage::pod2usage();
+ }
+ #- check for minimum requirements
+ ref $live->{media} && $live->{media}{storage} or die "no media storage definition\n";
+ ref $live->{system} or die "no system definition\n";
+}
+
+sub complete_config {
+ my ($live) = @_;
+
+ my $default_prefix = {
+ build => {
+ EFI => '/EFI',
+ boot => '/boot',
+ dist => '/dist',
+ files => '/files',
+ images => '/images',
+ initrd => '/initrd',
+ loopbacks => '/loopbacks',
+ modules => '/modules',
+ scripts => '/scripts',
+ },
+ media => {
+ EFI => '/EFI',
+ boot => '/boot',
+ hidden_boot => '/.boot',
+ loopbacks => '/loopbacks',
+ hidden_loopbacks => '/.loopbacks',
+ mnt => '/media',
+ },
+ live => {
+ mnt => '/live',
+ },
+ };
+
+ #- set unsupplied config dirs
+ add2hash($live->{prefix}{$_} ||= {}, $default_prefix->{$_}) foreach keys %$default_prefix;
+
+ $live->{settings}{builddir} ||= '/var/lib/draklive/build';
+ $live->{settings}{chroot} ||= '/var/lib/draklive/chroot';
+
+ $live->{settings}{arch} ||= chomp_(`rpm --eval '%{_target_cpu}'`);
+ $live->{media}{title} ||= "live";
+
+ $_ = MGA::DrakISO::Media::new($_) foreach (
+ $live->{media},
+ ($live->{replicator} ? $live->{replicator}{media} : ()),
+ ($live->{oem_rescue} ? $live->{oem_rescue}{media} : ()),
+ );
+
+ mkdir_p($live->get_builddir);
+ mkdir_p($live->get_system_root);
+ $live->{mnt} ||= $live->get_builddir . "/mnt";
+}
+
+sub dump_config {
+ my ($live) = @_;
+ use Data::Dumper;
+ print Data::Dumper->Dump([ $live ], [ "live" ]);
+}
+
+1;
diff --git a/lib/MGA/DrakISO/CustomMedia.pm b/lib/MGA/DrakISO/CustomMedia.pm
new file mode 100644
index 0000000..c01d480
--- /dev/null
+++ b/lib/MGA/DrakISO/CustomMedia.pm
@@ -0,0 +1,14 @@
+package MGA::DrakISO::CustomMedia;
+
+sub nfs_media {
+ my ($module, $client, $path) = @_;
+ (
+ fs => 'nfs',
+ modules => 'nfs',
+ extra_modules => [ $module ],
+ pre => "ifconfig eth0 $client up",
+ source => $path,
+ );
+}
+
+1;
diff --git a/lib/MGA/DrakISO/Live.pm b/lib/MGA/DrakISO/Live.pm
new file mode 100644
index 0000000..e92fc2c
--- /dev/null
+++ b/lib/MGA/DrakISO/Live.pm
@@ -0,0 +1,70 @@
+package MGA::DrakISO::Live;
+
+use MDK::Common;
+
+sub new {
+ my ($class) = @_;
+ bless {}, $class;
+}
+
+sub default_name_fields {
+ my ($live) = @_;
+ [ qw(name version product desktop),
+ if_($live->{settings}{region} ne 'all', region),
+ qw(arch media)
+ ];
+}
+
+sub get_name {
+ my ($live) = @_;
+ my $fields = $live->{name_fields} || default_name_fields($live);
+ join('-', grep { $_ } @{$live->{settings}}{@$fields});
+}
+
+sub get_set_suffix {
+ my ($live) = @_;
+ $live->{settings}{set} ? "-$live->{settings}{set}" : "";
+}
+
+sub get_builddir {
+ my ($live) = @_;
+ $live->{settings}{builddir} . '/' . $live->get_name . $live->get_set_suffix;
+}
+
+sub get_system_root {
+ my ($live) = @_;
+ $live->{settings}{chroot} . '/' . $live->get_name . $live->get_set_suffix;
+}
+
+sub get_media_prefix {
+ my ($live, $setting, $o_boot) = @_;
+ my $hidden = $live->{system}{hide_media_dirs} && $live->{media}->get_boot_setting('can_hide', { boot => $o_boot });
+ $live->{prefix}{media}{$hidden ? "hidden_$setting" : $setting};
+}
+
+sub find_kernel {
+ my ($live) = @_;
+ require bootloader;
+ local $::prefix = $live->get_system_root;
+ my @kernels = bootloader::get_kernels_and_labels();
+ my $kernel;
+ if ($live->{system}{kernel}) {
+ $kernel = find { $_->{version} eq $live->{system}{kernel} } @kernels;
+ $kernel or die "kernel $live->{system}{kernel} can not be found\n";
+ }
+ $kernel ||= first(@kernels) or die "no kernel can be found\n";
+}
+
+sub get_initrd_name {
+ my ($live) = @_;
+ 'initrd-' . $live->find_kernel->{version} . '.img';
+}
+
+sub get_lib_prefix {
+ my ($live) = @_;
+ my $lib_prefix = find { glob($live->get_system_root . $_ . '/libc.so.*') } qw(/lib64 /lib);
+ $lib_prefix or die 'unable to find system libraries in /lib or /lib64';
+ $lib_prefix;
+}
+
+1;
diff --git a/lib/MGA/DrakISO/Loopback.pm b/lib/MGA/DrakISO/Loopback.pm
new file mode 100644
index 0000000..c48f2b6
--- /dev/null
+++ b/lib/MGA/DrakISO/Loopback.pm
@@ -0,0 +1,151 @@
+package MGA::DrakISO::Loopback;
+
+use MDK::Common;
+use File::Temp;
+use MGA::DrakISO::Progress;
+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 ($live, $dir) = @_;
+ my $dest = $live->get_builddir . $live->{prefix}{build}{loopbacks} . $dir->{path} . $loop_types{squashfs}{extension};
+ mkdir_p(dirname($dest));
+ my $root = $dir->{root} || $live->get_system_root;
+ my $src = $root . $dir->{build_from};
+ my $total = directory_usage($src);
+ print "have to process " . int($total/1000000) . " MB\n";
+ my $progress = MGA::DrakISO::Progress->new($total, time(), 6);
+ my $exclude_file = tmpnam();
+ output_p($exclude_file, map { $root . "$_\n" } grep { -e $root . $_ } @{$dir->{exclude} || []});
+ my $sort = $live->{settings}{config_root} . '/' . $dir->{sort};
+ my $squashfs4_comp = best_squashfs4_compression($live);
+ run_foreach(sub {
+ if (/^mksquashfs: file .*, uncompressed size (\d+) bytes\s*(?:DUPLICATE|LINK)?$/) {
+ $progress->{current} += $1;
+ $progress->show(time());
+ }
+ },
+ $squashfs4_comp ? 'mksquashfs' : 'mksquashfs3', $src, $dest,
+ $squashfs4_comp ? ('-comp', $squashfs4_comp) : '-lzma',
+ '-noappend', '-no-progress', '-info', '-b', '1048576',
+ #'-processors', 1,
+ '-ef', $exclude_file,
+ if_(-f $sort, '-sort', $sort),
+ ) or die "unable to run mksquashfs\n";
+ $progress->end;
+ unlink $exclude_file;
+ },
+ mount => sub {
+ my ($live, $dir) = @_;
+ $dir->{loop} = "/dev/loop" . $loop_number++;
+ my $media_loopbacks = $live->get_media_prefix('loopbacks');
+ (
+ "/bin/losetup $dir->{loop} $live->{prefix}{live}{mnt}$live->{prefix}{media}{mnt}${media_loopbacks}$dir->{path}$loop_types{squashfs}{extension}",
+ "nash-mount -o ro -t squashfs $dir->{loop} $live->{prefix}{live}{mnt}$dir->{mountpoint}",
+ );
+ },
+ },
+ modules => {
+ read_only => 1,
+ delay_mount => 1,
+ mount => sub {
+ my ($live, $dir) = @_;
+ my $media_loopbacks = $live->get_media_prefix('loopbacks');
+ "sh -c 'modules=; for m in $live->{prefix}{live}{mnt}$live->{prefix}{media}{mnt}${media_loopbacks}$dir->{path}/*; do n=\$(basename \$m); n=\${n%.sqfs}; d=$live->{prefix}{live}{mnt}$dir->{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->{prefix}{live}{mnt}/$dir->{list}'";
+ },
+ pivot_clean => sub {
+ my ($live, $dir, $initrdroot) = @_;
+ (
+ "sh -c 'cd $initrdroot$live->{prefix}{live}{mnt}$dir->{mountpoint}; for i in `ls -1`; do mkdir -p $live->{prefix}{live}{mnt}$dir->{mountpoint}/\$i; mount -n --move \$i $live->{prefix}{live}{mnt}$dir->{mountpoint}/\$i; rmdir \$i; done; rmdir $initrdroot$live->{prefix}{live}{mnt}$dir->{mountpoint}'",
+ "sh -c 'mv $initrdroot$live->{prefix}{live}{mnt}/$dir->{list} $live->{prefix}{live}{mnt}/'",
+ );
+ },
+ },
+ loopfs => {
+ is_loopback => 1,
+ modules => [],
+ extension => '.loop',
+ build => sub {
+ my ($live, $dir) = @_;
+ my $dest = $live->get_builddir . $live->{prefix}{build}{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 ($live, $dir) = @_;
+ $dir->{loop} = "/dev/loop" . $loop_number++;
+ my $fsck = "chroot </dev/tty1 $live->{prefix}{live}{mnt}$dir_distrib_sqfs->{mountpoint} /sbin/fsck $dir->{loop}";
+ my $media_loopbacks = $live->get_media_prefix('loopbacks');
+ (
+ "losetup $dir->{loop} $live->{prefix}{live}{mnt}$live->{prefix}{media}{mnt}${media_loopbacks}$dir->{path}$loop_types{loopfs}{extension}",
+ qq(sh -c "$fsck -a || $fsck -y"),
+ "nash-mount -t $dir->{fs} $dir->{loop} $live->{prefix}{live}{mnt}$dir->{mountpoint}",
+ );
+ },
+ },
+ plain => {
+ skip_mkdir => 1,
+ mount => sub {
+ my ($live, $dir) = @_;
+ qq(sh -c "mkdir -p $live->{prefix}{live}{mnt}$dir->{mountpoint}");
+ },
+ },
+ partition => {
+ files => [ '/sbin/fsck', '/sbin/blkid' ],
+ mount => sub {
+ my ($live, $dir) = @_;
+ my $fsck = "/bin/fsck";
+ (
+ qq(sh -c 'dev=`blkid -l -t $dir->{path} -o device`; [ -z "\$dev" ] || $fsck -a \$dev || $fsck -y \$dev'),
+ "nash-mount -t $dir->{fs} $dir->{path} $live->{prefix}{live}{mnt}$dir->{mountpoint}",
+ );
+ },
+ },
+ tmpfs => {
+ mount => sub {
+ my ($live, $dir) = @_;
+ my $mnt = $live->{prefix}{live}{mnt} . $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 get_loop_modules {
+ my ($live, $type) = @_;
+ my $modules = $loop_types{$_}{modules};
+ my $type = ref $modules;
+ return $type eq 'CODE' ? $modules->($live) :
+ $type eq 'ARRAY' ? @$modules :
+ ();
+}
+
+sub has_squashfs4_with {
+ my ($live, $comp) = @_;
+ my $ucomp = uc($comp);
+ cat_($live->get_system_root . "/boot/config-" . $live->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 ($live) = @_;
+ find { has_squashfs4_with($live, $_) } intersection([ mksquashfs4_compressors() ], [ qw(xz lzma) ]);
+}
+
+1;
diff --git a/lib/MGA/DrakISO/Media.pm b/lib/MGA/DrakISO/Media.pm
new file mode 100644
index 0000000..97e21ab
--- /dev/null
+++ b/lib/MGA/DrakISO/Media.pm
@@ -0,0 +1,88 @@
+package MGA::DrakISO::Media;
+
+use MDK::Common;
+use MGA::DrakISO::Storage;
+use POSIX;
+use common;
+
+sub new {
+ my ($media) = @_;
+
+ bless $media, 'MGA::DrakISO::Media';
+
+ $media->{partitions} ||= [ { mntpoint => '/' } ];
+
+ foreach my $mntpoint (qw(/ OEM_RESCUE)) {
+ my $part = find { $_->{mntpoint} eq $mntpoint } @{$media->{partitions}};
+ $part->{fs_type} ||= $media->get_media_setting('fs');
+ if (my $label = $mntpoint eq '/' && $media->get_media_label) {
+ $part->{device_LABEL} ||= $label;
+ }
+ }
+
+ $media->{boot_entries} ||= [ '' => '' ];
+
+ $media;
+}
+
+sub get_initrd_path {
+ my ($media) = @_;
+ '/' . $media->{storage} . '/initrd.gz';
+}
+
+#- mainly for storage-specific subroutines
+sub get_storage_setting {
+ my ($media, $setting) = @_;
+ $MGA::DrakISO::Storage::storage_types{$media->{storage}}{$setting};
+}
+
+#- for actions that support an optional boot storage type
+sub get_boot_setting {
+ my ($media, $setting, $opts) = @_;
+ $opts->{boot} ? $MGA::DrakISO::Storage::storage_types{$opts->{boot}}{$setting} : get_media_setting($media, $setting);
+}
+
+#- for user-customisable media setting, that can override storage setting
+sub get_media_setting {
+ my ($media, $setting) = @_;
+ $media->{$setting} || $media->get_storage_setting($setting);
+}
+
+sub get_media_fs_module {
+ my ($media) = @_;
+ my $fs = $media->get_media_setting('fs');
+ $fs eq 'iso9660' ? 'isofs' : $fs eq 'ext2' ? @{[]} : $fs;
+}
+
+sub get_media_label {
+ my ($media) = @_;
+ first($media->get_media_setting('source') =~ /^LABEL=(.*)$/);
+}
+
+sub get_media_source_for_nash {
+ my ($media) = @_;
+ my $label = $media->get_media_label;
+ #- strip vfat labels to 11 chars and upper-case it
+ $label && $media->get_media_setting('fs') eq 'vfat' ?
+ 'LABEL=' . uc(substr($label, 0, 11)) :
+ $media->get_media_setting('source');
+}
+
+sub find_partition_index {
+ my ($media, $mntpoint) = @_;
+ eval { find_index { $_->{mntpoint} eq $mntpoint } @{$media->{partitions}} };
+}
+
+sub find_boot_partition_index {
+ my ($media) = @_;
+ $media->find_partition_index('/boot') || $media->find_partition_index('/');
+}
+
+sub supplement_slash_size {
+ my ($media, $total_size) = @_;
+ my $correction = 1.2;
+ my $slash = find { $_->{mntpoint} eq '/' } @{$media->{partitions}};
+ $slash->{size} ||= POSIX::ceil($total_size * $correction / $common::SECTORSIZE);
+}
+
+1;
diff --git a/lib/MGA/DrakISO/Mounts.pm b/lib/MGA/DrakISO/Mounts.pm
new file mode 100644
index 0000000..07cd5b6
--- /dev/null
+++ b/lib/MGA/DrakISO/Mounts.pm
@@ -0,0 +1,93 @@
+package MGA::DrakISO::Mounts;
+
+use MDK::Common;
+
+my $dir_distrib_sqfs = {
+ mountpoint => '/distrib',
+ type => 'squashfs',
+ path => '/distrib',
+ # perl -MMDK::Common -e 'print map_index { (32767 - $::i) . " $_" } grep { !m,^/(?:dev|proc|sys|live/distrib), } uniq(<>)' < bootlog.list > config/distrib.sort
+ sort => "config/distrib.sort",
+ build_from => '/',
+};
+my $dir_memory = {
+ mountpoint => '/memory',
+ type => 'tmpfs',
+ mount_opts => 'mode=755',
+};
+
+my $dir_modules = {
+ mountpoint => '/modules',
+ type => 'modules',
+ path => '/modules',
+ list => 'modules.lst',
+};
+
+#- use distro default
+our $default = {
+ dirs => [],
+};
+
+our $simple_union = {
+ root => '/union',
+ overlay => 'overlay',
+ dirs => [
+ {
+ mountpoint => '/media',
+ type => 'plain',
+ },
+ $dir_memory,
+ ],
+ };
+
+our $squash_rw_union = {
+ root => '/union',
+ overlay => 'overlay',
+ dirs => [
+ $dir_distrib_sqfs,
+ {
+ mountpoint => '/media/system',
+ type => 'plain',
+ },
+ ],
+ };
+
+sub volatile_squash_union {
+ my ($o_modules) = @_;
+ {
+ root => '/union',
+ overlay => 'overlay',
+ dirs => [
+ $dir_distrib_sqfs,
+ if_($o_modules, $dir_modules),
+ $dir_memory,
+ ],
+ };
+}
+
+sub squash_union {
+ my ($default_size, $o_min_size, $o_modules) = @_;
+ {
+ root => '/union',
+ overlay => 'overlay',
+ dirs => [
+ $dir_distrib_sqfs,
+ if_($o_modules, $dir_modules),
+ {
+ mountpoint => '/system',
+ type => 'loopfs',
+ pre_allocate => $default_size,
+ if_(defined $o_min_size, min_size => $o_min_size),
+ fs => 'ext2',
+ path => '/system'
+ },
+ {
+ mountpoint => '/system',
+ type => 'tmpfs',
+ fallback => 1,
+ },
+ ],
+ };
+}
+
+1;
diff --git a/lib/MGA/DrakISO/Progress.pm b/lib/MGA/DrakISO/Progress.pm
new file mode 100644
index 0000000..40e442e
--- /dev/null
+++ b/lib/MGA/DrakISO/Progress.pm
@@ -0,0 +1,31 @@
+package MGA::DrakISO::Progress;
+
+use POSIX qw(strftime);
+
+sub new {
+ my ($class, $total, $time, $o_exp_divide) = @_;
+ bless {
+ total => $total,
+ current => 0,
+ start_time => $time,
+ exp_divide => $o_exp_divide,
+ maxl => length($total) - $o_exp_divide,
+ }, $class;
+}
+
+sub show {
+ my ($progress, $time) = @_;
+ my $elapsed_time = $time - $progress->{start_time};
+ my $eta = $progress->{current} ? int($elapsed_time*$progress->{total}/$progress->{current}) : -1;
+ printf("\r%3d%% (%$progress->{maxl}s/%-$progress->{maxl}s), %8s/%8s (ETA)",
+ int(100*$progress->{current}/$progress->{total}),
+ (map { substr($_, 0, length($_)-$progress->{exp_divide}) } $progress->{current}, $progress->{total}),
+ (map { POSIX::strftime("%H:%M:%S", gmtime($_)) } $elapsed_time, $eta));
+}
+
+sub end {
+ my ($_progress) = @_;
+ print "\n";
+}
+
+1;
diff --git a/lib/MGA/DrakISO/Storage.pm b/lib/MGA/DrakISO/Storage.pm
new file mode 100644
index 0000000..6402cd2
--- /dev/null
+++ b/lib/MGA/DrakISO/Storage.pm
@@ -0,0 +1,54 @@
+package MGA::DrakISO::Storage;
+
+use detect_devices;
+
+our %storage_types = (
+ iso => {
+ modules => 'bus/firewire|usb disk/firewire|hardware_raid|ide|sata|scsi|usb',
+ fs => 'iso9660',
+ source => 'LABEL=MGAISOROOT',
+ read_only => 1,
+ create => \&main::create_iso_master,
+ },
+ cdrom => {
+ modules => 'bus/firewire|usb disk/firewire|hardware_raid|ide|sata|scsi|usb',
+ media_modules => 'disk/cdrom',
+ fs => 'iso9660',
+ can_hide => 0,
+ source => 'LABEL=MGACDROOT',
+ read_only => 1,
+ detect => \&detect_devices::burners,
+ create => \&main::create_cdrom_master,
+ format => \&main::format_cdrom_device,
+ record_needs_master => 1,
+ record => \&main::record_cdrom_master,
+ replicator => \&main::create_cdrom_replicator,
+ record_replicator => \&main::record_cdrom_replicator,
+ },
+ usb => {
+ modules => 'bus/usb disk/usb',
+ media_modules => 'disk/raw',
+ fs => 'vfat',
+ can_hide => 1,
+ bootloader => 'grub',
+ source => 'LABEL=MGAUSBROOT',
+ detect => sub { grep { detect_devices::isKeyUsb($_) } detect_devices::get() },
+ create => \&main::create_disk_master,
+ format => \&main::format_disk,
+ record => \&main::record_usb_master,
+ image => \&main::create_disk_image,
+ replicator => \&main::create_usb_replicator,
+ record_replicator => \&main::record_usb_replicator,
+ },
+ harddisk => {
+ fs => 'ext4',
+ bootloader => 'grub',
+ source => 'LABEL=MGAROOT',
+ create => \&main::create_disk_master,
+ format => \&main::format_disk,
+ record => \&main::record_harddisk_master,
+ image => \&main::create_disk_image,
+ },
+);
+
+1;
diff --git a/lib/MGA/DrakISO/StorageFS.pm b/lib/MGA/DrakISO/StorageFS.pm
new file mode 100644
index 0000000..05c62d4
--- /dev/null
+++ b/lib/MGA/DrakISO/StorageFS.pm
@@ -0,0 +1,56 @@
+package MGA::DrakISO::StorageFS;
+
+use MDK::Common;
+
+my %storage_fs;
+%storage_fs = (
+ generic => {
+ mount => sub {
+ my ($live, $media) = @_;
+ my @mount_options = (
+ if_($media->get_media_setting('read_only'), "ro"),
+ grep { $_ } $media->get_media_setting('mount_options'),
+ );
+ 'nash-mount' . if_(@mount_options, " -o " . join(",", @mount_options)) . " -t " . $media->get_media_setting('fs') .
+ " " . $media->get_media_source_for_nash . " $live->{prefix}{live}{mnt}$live->{prefix}{media}{mnt}";
+ },
+ },
+ nfs => {
+ files => [ '/sbin/ifconfig', '/bin/mount' ], #- needed to mount NFS (with nolock)
+ mount => sub {
+ my ($live, $media) = @_;
+ '/bin/mount -n -o ro,nolock -t nfs ' . $media->get_media_source_for_nash . " $live->{prefix}{live}{mnt}$live->{prefix}{media}{mnt}";
+ }
+ },
+ ext2 => {
+ files => [ '/sbin/fsck.ext2' ],
+ mount => sub {
+ my ($live, $media) = @_;
+ my $fsck = "/bin/fsck.ext2";
+ my $source = $media->get_media_setting('source');
+ qq(sh -c '$fsck -a $source || $fsck -y $source'),
+ $storage_fs{generic}{mount}->($live, $media);
+ },
+ },
+ vfat => {
+ #files => [ '/sbin/dosfsck' ],
+ mount => sub {
+ my ($live, $media) = @_;
+ #$storage_fs{generic}{mount}->($live, $media),
+ #qq(awk '\$2 == "$live->{prefix}{live}{mnt}$live->{prefix}{media}{mnt}" { system("umount " \$1 "; mount; echo dosfsck -a " \$1 "; dosfsck -a " \$1) }' /proc/mounts),
+ $storage_fs{generic}{mount}->($live, $media);
+ },
+ },
+);
+
+sub get_files {
+ my ($fs) = @_;
+ @{$storage_fs{$fs} && $storage_fs{$fs}{files} || []};
+}
+
+sub get_mount {
+ my ($fs) = @_;
+ $storage_fs{exists $storage_fs{$fs}{mount} ? $fs : 'generic'}{mount};
+}
+
+1;
diff --git a/lib/MGA/DrakISO/Utils.pm b/lib/MGA/DrakISO/Utils.pm
new file mode 100644
index 0000000..1f14241
--- /dev/null
+++ b/lib/MGA/DrakISO/Utils.pm
@@ -0,0 +1,85 @@
+package MGA::DrakISO::Utils;
+
+use MDK::Common;
+use common;
+use run_program;
+use IPC::Open3;
+use IO::Select;
+
+use Exporter;
+our @ISA = qw(Exporter);
+our @EXPORT = qw(directory_usage run_ run_foreach);
+
+sub directory_usage {
+ my ($dir, $o_apparent) = @_;
+ my $apparent = $o_apparent && "--apparent-size";
+ first(split /\s/, `du -s -B 1 $apparent $dir`);
+ }
+
+#- expand only if the pattern contains '*'
+#- and matches dot characters (like shell dotglob)
+sub glob__ {
+ my ($pattern) = @_;
+ $pattern =~ /\*/ ? glob_($pattern) : $pattern;
+}
+
+sub run_ {
+ my $options = ref $_[0] eq 'HASH' ? shift @_ : {};
+ my @cmd = @_;
+ $options->{timeout} ||= 'never';
+ if (arch() !~ /^arm/) {
+ my $targetarch = delete $options->{targetarch};
+ unshift @cmd, 'setarch', $targetarch if $targetarch;
+ }
+ print STDERR "running " . (exists $options->{root} && "(in chroot) ") . join(' ', @cmd) . "\n";
+ run_program::raw($options, @cmd);
+}
+
+sub run_foreach {
+ my ($foreach, @command) = @_;
+ print STDERR "running " . join(' ', @command) . "\n";
+ my $pid = open3(my $cmd_in, my $cmd_out, undef, @command);
+ my $selector = IO::Select->new($cmd_out);
+ while (my @ready = $selector->can_read) {
+ foreach my $fh (@ready) {
+ local $_ = scalar <$fh>;
+ return if /^open3:/;
+ $foreach->();
+ $selector->remove($fh) if eof($fh);
+ }
+ }
+ close($cmd_out);
+ close($cmd_in);
+ return waitpid($pid, 0) > 0 && !($? >> 8);
+}
+
+sub mtools_run_ {
+ local $ENV{MTOOLS_SKIP_CHECK} = 1;
+ &run_;
+}
+
+sub device_allocate_file {
+ my ($device, $size) = @_;
+ run_('dd', "of=$device", 'count=0', 'bs=1', "seek=" . removeXiBSuffix($size));
+}
+
+#- format $device as type $type
+# FIXME: use fs::format
+sub device_mkfs {
+ my ($device, $type, $o_label, $o_inode_size) = @_;
+ if ($type eq 'vfat') {
+ run_('mkfs.vfat', if_(defined $o_label, '-n', $o_label), $device);
+ } elsif (member($type, 'ext2', 'ext3', 'ext4')) {
+ run_("mkfs.$type", "-m", 0,
+ if_(defined $o_label, '-L', $o_label),
+ if_($o_inode_size, '-I', $o_inode_size),
+ if_(!-b $device, '-F'),
+ $device);
+ } elsif ($type eq 'swap') {
+ run_('mkswap', if_(defined $o_label, '-L', $o_label), $device);
+ } else {
+ die "unable to mkfs for unsupported media type $type\n";
+ }
+}
+
+1;