From 106088ec7089a961767fb19d83e9dc09ae02e076 Mon Sep 17 00:00:00 2001 From: Pascal Rigaux Date: Tue, 21 Nov 2006 18:10:03 +0000 Subject: create urpm::removable out of urpm.pm --- gurpmi2 | 4 +- urpm.pm | 185 +-------------------------------------------------- urpm/media.pm | 9 +-- urpm/removable.pm | 195 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ urpmi | 4 +- urpmi.addmedia | 2 +- urpmi.update | 2 +- 7 files changed, 207 insertions(+), 194 deletions(-) create mode 100644 urpm/removable.pm diff --git a/gurpmi2 b/gurpmi2 index 0fe865b1..7a8172e5 100755 --- a/gurpmi2 +++ b/gurpmi2 @@ -220,7 +220,7 @@ sub do_install_3 () { $progressbar->set_size_request(300, -1); $vbox->pack_start($progressbar, 0, 0, 0); change_mainw($vbox); - $urpm->copy_packages_of_removable_media($list, \%sources, sub { + urpm::removable::copy_packages_of_removable_media($urpm, $list, \%sources, sub { my $w = Gtk2::MessageDialog->new($mainw, [qw(modal destroy-with-parent)], 'warning', 'ok-cancel', N("Please insert the medium named \"%s\" on device [%s]", $_[0], $_[1]) ); @@ -336,5 +336,5 @@ sub do_install_3 () { } urpm::sys::unlock_urpmi_db($urpm); urpm::sys::unlock_rpm_db($urpm); - $urpm->try_umounting_removables; + urpm::removable::try_umounting_removables($urpm); } diff --git a/urpm.pm b/urpm.pm index 565a9a45..efe60003 100644 --- a/urpm.pm +++ b/urpm.pm @@ -55,12 +55,6 @@ sub new { $self; } -#- returns the removable device name if it corresponds to an iso image, '' otherwise -sub is_iso { - my ($removable_dev) = @_; - $removable_dev && $removable_dev =~ /\.iso$/i; -} - sub protocol_from_url { my ($url) = @_; $url =~ m!^([^:_]*)[^:]*:! && $1; @@ -100,60 +94,6 @@ sub remove_obsolete_headers_in_cache { } } -sub try_mounting { - my ($urpm, $dir, $o_removable) = @_; - my %infos; - - my $is_iso = is_iso($o_removable); - my @mntpoints = $is_iso - #- note: for isos, we don't parse the fstab because it might not be declared in it. - #- so we try to remove suffixes from the dir name until the dir exists - ? ($dir = urpm::sys::trim_until_d($dir)) - : urpm::sys::find_mntpoints($dir = reduce_pathname($dir), \%infos); - foreach (grep { - ! $infos{$_}{mounted} && $infos{$_}{fs} ne 'supermount'; - } @mntpoints) - { - $urpm->{log}(N("mounting %s", $_)); - if ($is_iso) { - #- to mount an iso image, grab the first loop device - my $loopdev = urpm::sys::first_free_loopdev(); - sys_log("mount iso $_ on $o_removable"); - $loopdev and system('mount', $o_removable, $_, '-t', 'iso9660', '-o', "loop=$loopdev"); - } else { - sys_log("mount $_"); - system("mount '$_' 2>/dev/null"); - } - $o_removable && $infos{$_}{fs} ne 'supermount' and $urpm->{removable_mounted}{$_} = undef; - } - -e $dir; -} - -sub try_umounting { - my ($urpm, $dir) = @_; - my %infos; - - $dir = reduce_pathname($dir); - foreach (reverse grep { - $infos{$_}{mounted} && $infos{$_}{fs} ne 'supermount'; - } urpm::sys::find_mntpoints($dir, \%infos)) - { - $urpm->{log}(N("unmounting %s", $_)); - sys_log("umount $_"); - system("umount '$_' 2>/dev/null"); - delete $urpm->{removable_mounted}{$_}; - } - ! -e $dir; -} - -sub try_umounting_removables { - my ($urpm) = @_; - foreach (keys %{$urpm->{removable_mounted}}) { - $urpm->try_umounting($_); - } - delete $urpm->{removable_mounted}; -} - #- register local packages for being installed, keep track of source. sub register_rpms { my ($urpm, @files) = @_; @@ -595,7 +535,7 @@ sub download_source_packages { my %error_sources; urpm::sys::lock_urpmi_db($urpm, 'exclusive') if !$options{nolock}; - $urpm->copy_packages_of_removable_media($list, \%sources, $options{ask_for_medium}) or return; + urpm::removable::copy_packages_of_removable_media($urpm, $list, \%sources, $options{ask_for_medium}) or return; $urpm->download_packages_of_distant_media($list, \%sources, \%error_sources, %options); urpm::sys::unlock_urpmi_db($urpm) unless $options{nolock}; @@ -608,129 +548,6 @@ sub exlock_urpmi_db { urpm::sys::lock_urpmi_db($urpm, 'exclusive'); } -#- $list is a [ { pkg_id1 => url1, ... }, { ... }, ... ] -#- where there is one hash for each medium in {media} -sub copy_packages_of_removable_media { - my ($urpm, $list, $sources, $o_ask_for_medium) = @_; - my %removables; - - #- make sure everything is correct on input... - $urpm->{media} or return; - @{$urpm->{media}} == @$list or return; - - #- examine if given medium is already inside a removable device. - my $check_notfound = sub { - my ($id, $dir, $removable) = @_; - if ($dir) { - $urpm->try_mounting($dir, $removable); - -e $dir or return 2; - } - foreach (values %{$list->[$id]}) { - chomp; - my $dir_ = file_from_local_url($_) or next; - $dir_ =~ m!/.*/! or next; #- is this really needed?? - unless ($dir) { - $dir = $dir_; - $urpm->try_mounting($dir, $removable); - } - -r $dir_ or return 1; - } - 0; - }; - #- removable media have to be examined to keep mounted the one that has - #- more packages than others. - my $examine_removable_medium = sub { - my ($id, $device) = @_; - my $medium = $urpm->{media}[$id]; - if (my $dir = file_from_local_url($medium->{url})) { - #- the directory given does not exist and may be accessible - #- by mounting some other directory. Try to figure it out and mount - #- everything that might be necessary. - while ($check_notfound->($id, $dir, is_iso($medium->{removable}) ? $medium->{removable} : 'removable')) { - is_iso($medium->{removable}) || $o_ask_for_medium - or $urpm->{fatal}(4, N("medium \"%s\" is not selected", $medium->{name})); - $urpm->try_umounting($dir); - system("/usr/bin/eject '$device' 2>/dev/null"); - is_iso($medium->{removable}) - || $o_ask_for_medium->(remove_internal_name($medium->{name}), $medium->{removable}) - or $urpm->{fatal}(4, N("medium \"%s\" is not selected", $medium->{name})); - } - if (-e $dir) { - while (my ($i, $url) = each %{$list->[$id]}) { - chomp $url; - my ($filepath, $filename) = do { - my $f = file_from_local_url($url) or next; - $f =~ m!/.*/! or next; #- is this really needed?? - dirname($f), basename($f); - }; - if (-r $filepath) { - #- we should assume a possibly buggy removable device... - #- First, copy in partial cache, and if the package is still good, - #- transfer it to the rpms cache. - unlink "$urpm->{cachedir}/partial/$filename"; - if (copy_and_own($filepath, "$urpm->{cachedir}/partial/$filename") && - URPM::verify_rpm("$urpm->{cachedir}/partial/$filename", nosignatures => 1)) - { - #- now we can consider the file to be fine. - unlink "$urpm->{cachedir}/rpms/$filename"; - urpm::util::move("$urpm->{cachedir}/partial/$filename", "$urpm->{cachedir}/rpms/$filename"); - -r "$urpm->{cachedir}/rpms/$filename" and $sources->{$i} = "$urpm->{cachedir}/rpms/$filename"; - } - } - unless ($sources->{$i}) { - #- fallback to use other method for retrieving the file later. - $urpm->{error}(N("unable to read rpm file [%s] from medium \"%s\"", $filepath, $medium->{name})); - } - } - } else { - $urpm->{error}(N("medium \"%s\" is not selected", $medium->{name})); - } - } else { - #- we have a removable device that is not removable, well... - $urpm->{error}(N("inconsistent medium \"%s\" marked removable but not really", $medium->{name})); - } - }; - - foreach (0..$#$list) { - values %{$list->[$_]} or next; - my $medium = $urpm->{media}[$_]; - #- examine non removable device but that may be mounted. - if ($medium->{removable}) { - push @{$removables{$medium->{removable}} ||= []}, $_; - } elsif (my $dir = file_from_local_url($medium->{url})) { - -e $dir || $urpm->try_mounting($dir) or - $urpm->{error}(N("unable to access medium \"%s\"", $medium->{name})), next; - } - } - foreach my $device (keys %removables) { - next if $device =~ m![^a-zA-Z0-9_./-]!; #- bad path - #- Here we have only removable devices. - #- If more than one media uses this device, we have to sort - #- needed packages to copy the needed rpm files. - if (@{$removables{$device}} > 1) { - my @sorted_media = sort { values(%{$list->[$a]}) <=> values(%{$list->[$b]}) } @{$removables{$device}}; - - #- check if a removable device is already mounted (and files present). - if (my ($already_mounted_medium) = grep { !$check_notfound->($_) } @sorted_media) { - @sorted_media = grep { $_ ne $already_mounted_medium } @sorted_media; - unshift @sorted_media, $already_mounted_medium; - } - - #- mount all except the biggest one. - my $biggest = pop @sorted_media; - foreach (@sorted_media) { - $examine_removable_medium->($_, $device); - } - #- now mount the last one... - $removables{$device} = [ $biggest ]; - } - - $examine_removable_medium->($removables{$device}[0], $device); - } - - 1; -} - # TODO verify that files are downloaded from the right corresponding media #- options: quiet, callback, sub download_packages_of_distant_media { diff --git a/urpm/media.pm b/urpm/media.pm index e32ae406..c823a8d5 100644 --- a/urpm/media.pm +++ b/urpm/media.pm @@ -5,6 +5,7 @@ package urpm::media; use urpm 'file_from_local_url'; use urpm::msg; use urpm::util; +use urpm::removable; our @PER_MEDIA_OPT = qw( @@ -334,7 +335,7 @@ sub probe_removable_device { $urpm->{log}(N("too many mount points for removable medium \"%s\"", $medium->{name})); $urpm->{log}(N("taking removable device as \"%s\"", join ',', map { $infos{$_}{device} } @mntpoints)); } - if (urpm::is_iso($medium->{removable})) { + if (urpm::removable::is_iso($medium->{removable})) { $urpm->{log}(N("Medium \"%s\" is an ISO image, will be mounted on-the-fly", $medium->{name})); } elsif (@mntpoints) { if ($medium->{removable} && $medium->{removable} ne $infos{$mntpoints[-1]}{device}) { @@ -663,7 +664,7 @@ sub add_distrib_media { my $distribconf; if (my $dir = file_from_local_url($url)) { - $urpm->try_mounting($dir) + urpm::removable::try_mounting($urpm, $dir) or $urpm->{error}(N("unable to mount the distribution medium")), return (); $distribconf = MDV::Distribconf->new($dir, undef); $distribconf->load @@ -1272,11 +1273,11 @@ sub _update_medium__parse_if_unmodified__local { #- the directory given does not exist and may be accessible #- by mounting some other directory. Try to figure it out and mount #- everything that might be necessary. - $urpm->try_mounting( + urpm::removable::try_mounting($urpm, !$options->{force_building_hdlist} && $medium->{with_hdlist} ? _hdlist_dir($medium) : $dir, #- in case of an iso image, pass its name - urpm::is_iso($medium->{removable}) && $medium->{removable}, + urpm::removable::is_iso($medium->{removable}) && $medium->{removable}, ) or $urpm->{error}(N("unable to access medium \"%s\", this could happen if you mounted manually the directory when creating the medium.", $medium->{name})), return 'unmodified'; } diff --git a/urpm/removable.pm b/urpm/removable.pm new file mode 100644 index 00000000..783a2ba5 --- /dev/null +++ b/urpm/removable.pm @@ -0,0 +1,195 @@ +package urpm::removable; + +# $Id$ + +use urpm::msg; +use urpm::sys; +use urpm::util; +use urpm 'file_from_local_url'; + + + +#- returns the removable device name if it corresponds to an iso image, '' otherwise +sub is_iso { + my ($removable_dev) = @_; + $removable_dev && $removable_dev =~ /\.iso$/i; +} + +sub try_mounting { + my ($urpm, $dir, $o_removable) = @_; + my %infos; + + my $is_iso = is_iso($o_removable); + my @mntpoints = $is_iso + #- note: for isos, we don't parse the fstab because it might not be declared in it. + #- so we try to remove suffixes from the dir name until the dir exists + ? ($dir = urpm::sys::trim_until_d($dir)) + : urpm::sys::find_mntpoints($dir = reduce_pathname($dir), \%infos); + foreach (grep { + ! $infos{$_}{mounted} && $infos{$_}{fs} ne 'supermount'; + } @mntpoints) + { + $urpm->{log}(N("mounting %s", $_)); + if ($is_iso) { + #- to mount an iso image, grab the first loop device + my $loopdev = urpm::sys::first_free_loopdev(); + sys_log("mount iso $_ on $o_removable"); + $loopdev and system('mount', $o_removable, $_, '-t', 'iso9660', '-o', "loop=$loopdev"); + } else { + sys_log("mount $_"); + system("mount '$_' 2>/dev/null"); + } + $o_removable && $infos{$_}{fs} ne 'supermount' and $urpm->{removable_mounted}{$_} = undef; + } + -e $dir; +} + +sub try_umounting { + my ($urpm, $dir) = @_; + my %infos; + + $dir = reduce_pathname($dir); + foreach (reverse grep { + $infos{$_}{mounted} && $infos{$_}{fs} ne 'supermount'; + } urpm::sys::find_mntpoints($dir, \%infos)) + { + $urpm->{log}(N("unmounting %s", $_)); + sys_log("umount $_"); + system("umount '$_' 2>/dev/null"); + delete $urpm->{removable_mounted}{$_}; + } + ! -e $dir; +} + +sub try_umounting_removables { + my ($urpm) = @_; + foreach (keys %{$urpm->{removable_mounted}}) { + try_umounting($urpm, $_); + } + delete $urpm->{removable_mounted}; +} + +#- $list is a [ { pkg_id1 => url1, ... }, { ... }, ... ] +#- where there is one hash for each medium in {media} +sub copy_packages_of_removable_media { + my ($urpm, $list, $sources, $o_ask_for_medium) = @_; + my %removables; + + #- make sure everything is correct on input... + $urpm->{media} or return; + @{$urpm->{media}} == @$list or return; + + #- examine if given medium is already inside a removable device. + my $check_notfound = sub { + my ($id, $dir, $removable) = @_; + if ($dir) { + try_mounting($urpm, $dir, $removable); + -e $dir or return 2; + } + foreach (values %{$list->[$id]}) { + chomp; + my $dir_ = file_from_local_url($_) or next; + $dir_ =~ m!/.*/! or next; #- is this really needed?? + unless ($dir) { + $dir = $dir_; + try_mounting($urpm, $dir, $removable); + } + -r $dir_ or return 1; + } + 0; + }; + #- removable media have to be examined to keep mounted the one that has + #- more packages than others. + my $examine_removable_medium = sub { + my ($id, $device) = @_; + my $medium = $urpm->{media}[$id]; + if (my $dir = file_from_local_url($medium->{url})) { + #- the directory given does not exist and may be accessible + #- by mounting some other directory. Try to figure it out and mount + #- everything that might be necessary. + while ($check_notfound->($id, $dir, is_iso($medium->{removable}) ? $medium->{removable} : 'removable')) { + is_iso($medium->{removable}) || $o_ask_for_medium + or $urpm->{fatal}(4, N("medium \"%s\" is not selected", $medium->{name})); + try_umounting($urpm, $dir); + system("/usr/bin/eject '$device' 2>/dev/null"); + is_iso($medium->{removable}) + || $o_ask_for_medium->(remove_internal_name($medium->{name}), $medium->{removable}) + or $urpm->{fatal}(4, N("medium \"%s\" is not selected", $medium->{name})); + } + if (-e $dir) { + while (my ($i, $url) = each %{$list->[$id]}) { + chomp $url; + my ($filepath, $filename) = do { + my $f = file_from_local_url($url) or next; + $f =~ m!/.*/! or next; #- is this really needed?? + dirname($f), basename($f); + }; + if (-r $filepath) { + #- we should assume a possibly buggy removable device... + #- First, copy in partial cache, and if the package is still good, + #- transfer it to the rpms cache. + unlink "$urpm->{cachedir}/partial/$filename"; + if (copy_and_own($filepath, "$urpm->{cachedir}/partial/$filename") && + URPM::verify_rpm("$urpm->{cachedir}/partial/$filename", nosignatures => 1)) + { + #- now we can consider the file to be fine. + unlink "$urpm->{cachedir}/rpms/$filename"; + urpm::util::move("$urpm->{cachedir}/partial/$filename", "$urpm->{cachedir}/rpms/$filename"); + -r "$urpm->{cachedir}/rpms/$filename" and $sources->{$i} = "$urpm->{cachedir}/rpms/$filename"; + } + } + unless ($sources->{$i}) { + #- fallback to use other method for retrieving the file later. + $urpm->{error}(N("unable to read rpm file [%s] from medium \"%s\"", $filepath, $medium->{name})); + } + } + } else { + $urpm->{error}(N("medium \"%s\" is not selected", $medium->{name})); + } + } else { + #- we have a removable device that is not removable, well... + $urpm->{error}(N("inconsistent medium \"%s\" marked removable but not really", $medium->{name})); + } + }; + + foreach (0..$#$list) { + values %{$list->[$_]} or next; + my $medium = $urpm->{media}[$_]; + #- examine non removable device but that may be mounted. + if ($medium->{removable}) { + push @{$removables{$medium->{removable}} ||= []}, $_; + } elsif (my $dir = file_from_local_url($medium->{url})) { + -e $dir || try_mounting($urpm, $dir) or + $urpm->{error}(N("unable to access medium \"%s\"", $medium->{name})), next; + } + } + foreach my $device (keys %removables) { + next if $device =~ m![^a-zA-Z0-9_./-]!; #- bad path + #- Here we have only removable devices. + #- If more than one media uses this device, we have to sort + #- needed packages to copy the needed rpm files. + if (@{$removables{$device}} > 1) { + my @sorted_media = sort { values(%{$list->[$a]}) <=> values(%{$list->[$b]}) } @{$removables{$device}}; + + #- check if a removable device is already mounted (and files present). + if (my ($already_mounted_medium) = grep { !$check_notfound->($_) } @sorted_media) { + @sorted_media = grep { $_ ne $already_mounted_medium } @sorted_media; + unshift @sorted_media, $already_mounted_medium; + } + + #- mount all except the biggest one. + my $biggest = pop @sorted_media; + foreach (@sorted_media) { + $examine_removable_medium->($_, $device); + } + #- now mount the last one... + $removables{$device} = [ $biggest ]; + } + + $examine_removable_medium->($removables{$device}[0], $device); + } + + 1; +} + +1; diff --git a/urpmi b/urpmi index 01da1045..0431874d 100755 --- a/urpmi +++ b/urpmi @@ -592,7 +592,7 @@ unless ($local_sources || $list) { my %sources = %$local_sources; my %error_sources; -$urpm->copy_packages_of_removable_media( +urpm::removable::copy_packages_of_removable_media($urpm, $list, \%sources, (!$urpm->{options}{auto} || $allow_medium_change) && sub { my $msg = N("Please insert the medium named \"%s\" on device [%s]", $_[0], $_[1]); @@ -826,7 +826,7 @@ unless ($env || $nolock) { urpm::sys::unlock_rpm_db($urpm); #- try to umount removable device which may have been mounted. - $urpm->try_umounting_removables; + urpm::removable::try_umounting_removables($urpm); } #- restart urpmi if needed, keep command line for that. diff --git a/urpmi.addmedia b/urpmi.addmedia index 04b6fe71..1fbded3b 100755 --- a/urpmi.addmedia +++ b/urpmi.addmedia @@ -193,6 +193,6 @@ if ($options{distrib}) { } #- try to umount removable devices which may have been mounted. -$urpm->try_umounting_removables; +urpm::removable::try_umounting_removables($urpm); # vim:ts=8:sts=4:sw=4 diff --git a/urpmi.update b/urpmi.update index 0ed9d6c4..e86f4013 100755 --- a/urpmi.update +++ b/urpmi.update @@ -101,5 +101,5 @@ if (defined $options{ignore}) { } else { urpm::media::update_media($urpm, %options, callback => \&urpm::download::sync_logger); #- try to umount removable device which may have been mounted. - $urpm->try_umounting_removables; + urpm::removable::try_umounting_removables($urpm); } -- cgit v1.2.1