diff options
Diffstat (limited to 'lib/MGA/DrakISO')
l--------- | lib/MGA/DrakISO/.perl_checker | 1 | ||||
-rw-r--r-- | lib/MGA/DrakISO/Config.pm | 100 | ||||
-rw-r--r-- | lib/MGA/DrakISO/CustomMedia.pm | 14 | ||||
-rw-r--r-- | lib/MGA/DrakISO/Live.pm | 70 | ||||
-rw-r--r-- | lib/MGA/DrakISO/Loopback.pm | 151 | ||||
-rw-r--r-- | lib/MGA/DrakISO/Media.pm | 88 | ||||
-rw-r--r-- | lib/MGA/DrakISO/Mounts.pm | 93 | ||||
-rw-r--r-- | lib/MGA/DrakISO/Progress.pm | 31 | ||||
-rw-r--r-- | lib/MGA/DrakISO/Storage.pm | 54 | ||||
-rw-r--r-- | lib/MGA/DrakISO/StorageFS.pm | 56 | ||||
-rw-r--r-- | lib/MGA/DrakISO/Utils.pm | 85 |
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; |