summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPascal Rigaux <pixel@mandriva.com>2008-02-29 16:41:41 +0000
committerPascal Rigaux <pixel@mandriva.com>2008-02-29 16:41:41 +0000
commit153ae8e46c5ee905c6bea275ef665c07456b209c (patch)
treeb5e22986de392c95a9d73d213936af5319d2798d
parent0525929f65bd633a8dbd14836a42669a80b09a7d (diff)
downloadurpmi-153ae8e46c5ee905c6bea275ef665c07456b209c.tar
urpmi-153ae8e46c5ee905c6bea275ef665c07456b209c.tar.gz
urpmi-153ae8e46c5ee905c6bea275ef665c07456b209c.tar.bz2
urpmi-153ae8e46c5ee905c6bea275ef665c07456b209c.tar.xz
urpmi-153ae8e46c5ee905c6bea275ef665c07456b209c.zip
o use hal to wait-for/mount cdroms:
you can now use more than one cdrom drive big commit, no time to split it... some details: - split urpm::removable into urpm::removable and urpm::cdrom - fix setting $urpm->{removable_mounted} - in try_mounting_non_cdroms(), check for local url, simpler than checking is_cdrom_url and then checking file_from_local_medium - fix _try_mounting_medium() not mounting non-cdrom anymore (regression introduced during devel) - even if urpmi says it wants cdroms in a given order, if you make a mistake, it will use the one you give (as a side-effect, it simplifies the sort on "already mounted" cdrom (cf _sort_media disappearing))
-rw-r--r--NEWS2
-rw-r--r--urpm/cdrom.pm237
-rw-r--r--urpm/removable.pm222
-rwxr-xr-xurpmi7
4 files changed, 296 insertions, 172 deletions
diff --git a/NEWS b/NEWS
index e67d9c8a..bba621e0 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,7 @@
- all tools:
o cdrom:// replaces removable://
+ o use hal to wait-for/mount cdroms:
+ you can now use more than one cdrom drive
- urpmf, urpmq:
o do not try to download xml-info if it's not available (#38125)
- urpmi.addmedia:
diff --git a/urpm/cdrom.pm b/urpm/cdrom.pm
new file mode 100644
index 00000000..ccbd29dd
--- /dev/null
+++ b/urpm/cdrom.pm
@@ -0,0 +1,237 @@
+package urpm::cdrom;
+
+# $Id$
+
+use urpm::msg;
+use urpm::sys;
+use urpm::util;
+use urpm::get_pkgs;
+use urpm::removable;
+use urpm 'file_from_local_medium';
+
+
+
+#- side-effects: $blists_url->[_]{medium}{mntpoint}
+sub _find_blist_url_matching {
+ my ($urpm, $blists_url, $mntpoint) = @_;
+
+ my @l;
+ foreach my $blist (@$blists_url) {
+ $blist->{medium}{mntpoint} and next;
+
+ # set it, then verify
+ $blist->{medium}{mntpoint} = $mntpoint;
+ if (-r urpm::removable::_file_or_synthesis_dir($blist->{medium}, $blist->{url})) {
+ $urpm->{log}("found cdrom $blist->{medium}{name} mounted in $mntpoint");
+ push @l, $blist;
+ } else {
+ delete $blist->{medium}{mntpoint};
+ }
+ }
+ @l;
+}
+
+#- side-effects: none
+sub _look_for_mounted_cdrom_in_mtab() {
+
+ map { $_->{mntpoint} }
+ grep { $_->{fs} eq 'iso9660' || $_->{fs} eq 'udf' } urpm::sys::read_mtab();
+}
+
+#- side-effects:
+#- + those of _try_mounting_cdrom_using_hal ($urpm->{cdrom_mounted}, "hal_mount")
+#- + those of _find_blist_url_matching ($blists_url->[_]{medium}{mntpoint})
+sub try_mounting_cdrom {
+ my ($urpm, $blists_url) = @_;
+
+ my @blists_url;
+
+ # first try without hal, it allows users where hal fails to work (with one CD only)
+ my @mntpoints = _look_for_mounted_cdrom_in_mtab();
+ @blists_url = map { _find_blist_url_matching($urpm, $blists_url, $_) } @mntpoints;
+
+ if (!@blists_url) {
+ @mntpoints = _try_mounting_cdrom_using_hal($urpm);
+ @blists_url = map { _find_blist_url_matching($urpm, $blists_url, $_) } @mntpoints;
+ }
+ @blists_url;
+}
+
+#- side-effects: $urpm->{cdrom_mounted}, "hal_mount"
+sub _try_mounting_cdrom_using_hal {
+ my ($urpm) = @_;
+
+ $urpm->{cdrom_mounted} = {}; # reset
+
+ require Hal::Cdroms;
+ my $hal_cdroms = Hal::Cdroms->new;
+ foreach my $hal_path ($hal_cdroms->list) {
+ my $mntpoint;
+ if ($mntpoint = $hal_cdroms->get_mount_point($hal_path)) {
+ } else {
+ $urpm->{log}("trying to mount $hal_path");
+ $mntpoint = $hal_cdroms->ensure_mounted($hal_path)
+ or $urpm->{error}("failed to mount $hal_path: $hal_cdroms->{error}"), next;
+ }
+ $urpm->{cdrom_mounted}{$hal_path} = $mntpoint;
+ }
+ values %{$urpm->{cdrom_mounted}};
+}
+
+#- side-effects:
+#- + those of try_mounting_cdrom ($urpm->{cdrom_mounted}, $blists_url->[_]{medium}{mntpoint}, "hal_mount")
+#- + those of _try_mounting_medium ($urpm->{cdrom_mounted}, $blists_url->[_]{medium}{mntpoint})
+sub _mount_cdrom_and_check {
+ my ($urpm, $blists) = @_;
+
+ my @matching_blists = try_mounting_cdrom($urpm, $blists) or return;
+ my @checked = grep { !_check_notfound($_) } @matching_blists;
+ $checked[0];
+}
+
+#- side-effects: none
+sub _check_notfound {
+ my ($blist) = @_;
+
+ $blist->{medium}{mntpoint} or return;
+
+ foreach (values %{$blist->{list}}) {
+ my $dir_ = _filepath($blist->{medium}, $_) or next;
+ -r $dir_ or return 1;
+ }
+ 0;
+}
+
+#- side-effects:
+#- + those of _eject_cdrom ($urpm->{cdrom_mounted}, "hal_umount", "hal_eject")
+sub _may_eject_cdrom {
+ my ($urpm) = @_;
+
+ my @paths = keys %{$urpm->{cdrom_mounted}};
+ @paths == 1 or return;
+
+ # only one cdrom mounted, we know it is the one to umount/eject
+ _eject_cdrom($urpm, $paths[0]);
+}
+
+
+#- side-effects: $urpm->{cdrom_mounted}, "hal_umount", "hal_eject"
+sub _eject_cdrom {
+ my ($urpm, $hal_path) = @_;
+
+ my $mntpoint = delete $urpm->{cdrom_mounted}{$hal_path};
+ $urpm->{debug} and $urpm->{debug}("umounting and ejecting $mntpoint (cdrom $hal_path)");
+
+ require Hal::Cdroms;
+ my $hal_cdroms = Hal::Cdroms->new;
+ $hal_cdroms->unmount($hal_path);
+ $hal_cdroms->eject($hal_path);
+ 1;
+}
+
+#- side-effects: "eject"
+#- + those of _mount_cdrom_and_check ($urpm->{cdrom_mounted}, $blists_url->[_]{medium}{mntpoint}, "hal_mount")
+#- + those of _may_eject_cdrom ($urpm->{cdrom_mounted}, "hal_umount", "hal_eject")
+sub _mount_cdrom {
+ my ($urpm, $blists, $ask_for_medium) = @_;
+
+ my $retry;
+
+ #- 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 (1) {
+
+ if (my $blist = _mount_cdrom_and_check($urpm, $blists)) {
+ return $blist;
+ }
+
+ # ask for the first one, it's ok if the user insert another wanted cdrom
+ my $medium = $blists->[0]{medium};
+
+ $retry++ and $urpm->{log}("wrong CDROM, wanted $medium->{name}");
+
+ $ask_for_medium
+ or $urpm->{fatal}(4, N("medium \"%s\" is not available", $medium->{name}));
+
+ _may_eject_cdrom($urpm);
+
+ $ask_for_medium->(remove_internal_name($medium->{name}))
+ or $urpm->{fatal}(4, N("medium \"%s\" is not available", $medium->{name}));
+ }
+}
+
+#- side-effects: none
+sub _filepath {
+ my ($medium, $url) = @_;
+
+ chomp $url;
+ my $filepath = file_from_local_medium($medium, $url) or return;
+ $filepath =~ m!/.*/! or return; #- is this really needed??
+ $filepath;
+}
+
+#- side-effects: "copy-move-files"
+sub _do_the_copy {
+ my ($urpm, $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.
+ my $filename = basename($filepath);
+ unlink "$urpm->{cachedir}/partial/$filename";
+ $urpm->{log}("copying $filepath");
+ copy_and_own($filepath, "$urpm->{cachedir}/partial/$filename") or return;
+ my $f = urpm::get_pkgs::verify_partial_rpm_and_move($urpm, $urpm->{cachedir}, $filename) or return;
+ $f;
+}
+
+#- side-effects: $sources
+#- + those of _do_the_copy: "copy-move-files"
+sub _copy_from_cdrom__if_needed {
+ my ($urpm, $blist, $sources, $want_copy) = @_;
+
+ while (my ($i, $url) = each %{$blist->{list}}) {
+ my $filepath = _filepath($blist->{medium}, $url) or next;
+
+ if (-r $filepath) {
+ $sources->{$i} = $want_copy ? _do_the_copy($urpm, $filepath) : $filepath;
+ } else {
+ #- fallback to use other method for retrieving the file later.
+ $urpm->{error}(N("unable to read rpm file [%s] from medium \"%s\"", $filepath, $blist->{medium}{name}));
+ }
+ }
+}
+
+#- $list is a [ { pkg_id1 => url1, ... }, { ... }, ... ]
+#- where there is one hash for each medium in {media}
+#-
+#- side-effects:
+#- + those of _may_eject_cdrom ($urpm->{cdrom_mounted}, "hal_umount", "hal_eject")
+#- + those of _mount_cdrom ($urpm->{cdrom_mounted}, $blists_url->[_]{medium}{mntpoint}, "hal_mount", "hal_eject")
+#- + those of _copy_from_cdrom__if_needed ("copy-move-files")
+sub copy_packages_of_removable_media {
+ my ($urpm, $list, $sources, $o_ask_for_medium) = @_;
+
+ my $blists = urpm::removable::create_blists($urpm->{media}, $list);
+ @$blists = grep { urpm::is_cdrom_url($_->{medium}{url}) } @$blists;
+
+ # we prompt for CDs used less first, since the last CD will be used directly
+ @$blists = sort { values(%{$a->{list}}) <=> values(%{$b->{list}}) } @$blists;
+
+ my $prev_medium;
+ while (@$blists) {
+ $prev_medium and delete $prev_medium->{mntpoint};
+ _may_eject_cdrom($urpm);
+
+ my $blist = _mount_cdrom($urpm, $blists, $o_ask_for_medium);
+ @$blists = grep { $_ != $blist } @$blists;
+
+ _copy_from_cdrom__if_needed($urpm, $blist, $sources, @$blists > 0);
+ $prev_medium = $blist->{medium};
+ }
+
+ 1;
+}
+
+1;
diff --git a/urpm/removable.pm b/urpm/removable.pm
index c7d8e74d..301aa59f 100644
--- a/urpm/removable.pm
+++ b/urpm/removable.pm
@@ -5,8 +5,7 @@ package urpm::removable;
use urpm::msg;
use urpm::sys;
use urpm::util;
-use urpm::get_pkgs;
-use urpm 'file_from_local_medium', 'is_local_medium';
+use urpm 'file_from_local_medium';
@@ -26,22 +25,32 @@ sub _file_or_synthesis_dir {
file_from_local_medium($medium, $o_url);
}
-#- side-effects: $medium->{mntpoint}
-sub _look_for_mounted_cdrom_in_mtab {
- my ($urpm, $medium, $o_url) = @_;
+#- side-effects: $blists_url->[_]{medium}{mntpoint}
+sub _find_blist_url_matching {
+ my ($urpm, $blists_url, $mntpoint) = @_;
+
+ my @l;
+ foreach my $blist (@$blists_url) {
+ $blist->{medium}{mntpoint} and next;
- my @mntpoints = map { $_->{mntpoint} }
- grep { $_->{fs} eq 'iso9660' || $_->{fs} eq 'udf' } urpm::sys::read_mtab();
- foreach (@mntpoints) {
# set it, then verify
- $medium->{mntpoint} = $_;
- if (-r _file_or_synthesis_dir($medium, $o_url)) {
- $urpm->{log}("using cdrom mounted in $_");
- return 1;
+ $blist->{medium}{mntpoint} = $mntpoint;
+ if (-r _file_or_synthesis_dir($blist->{medium}, $blist->{url})) {
+ $urpm->{log}("found cdrom $blist->{medium}{name} mounted in $mntpoint");
+ push @l, $blist;
+ } else {
+ delete $blist->{medium}{mntpoint};
}
}
- 0;
-}
+ @l;
+}
+
+#- side-effects: none
+sub _look_for_mounted_cdrom_in_mtab() {
+
+ map { $_->{mntpoint} }
+ grep { $_->{fs} eq 'iso9660' || $_->{fs} eq 'udf' } urpm::sys::read_mtab();
+}
#- side-effects:
#- + those of _try_mounting_medium ($medium->{mntpoint})
@@ -54,28 +63,33 @@ sub try_mounting_medium {
}
#- side-effects:
-#- + those of _look_for_mounted_cdrom_in_mtab ($medium->{mntpoint})
+#- + those of urpm::cdrom::try_mounting_cdrom ($urpm->{cdrom_mounted}, $medium->{mntpoint}, "hal_mount")
+#- + those of _try_mounting_local ($urpm->{removable_mounted}, "mount")
sub _try_mounting_medium {
my ($urpm, $medium, $o_url) = @_;
if (urpm::is_cdrom_url($medium->{url})) {
- _look_for_mounted_cdrom_in_mtab($urpm, $medium, $o_url);
+ urpm::cdrom::try_mounting_cdrom($urpm, [ { medium => $medium, url => $o_url } ]);
} else {
- -r _file_or_synthesis_dir($medium, $o_url);
+ _try_mounting_local($urpm, $medium, $o_url);
}
}
#- side-effects:
-#- + those of try_mounting_ ($urpm->{removable_mounted}, "mount")
-#- + those of try_mounting_iso ($urpm->{removable_mounted}, "mount")
-sub try_mounting {
- my ($urpm, $dir, $o_iso) = @_;
+#- + those of _try_mounting_using_fstab ($urpm->{removable_mounted}, "mount")
+#- + those of _try_mounting_iso ($urpm->{removable_mounted}, "mount")
+sub _try_mounting_local {
+ my ($urpm, $medium, $o_url) = @_;
+
+ my $dir = _file_or_synthesis_dir($medium, $o_url);
+ -e $dir and return 1;
- $o_iso ? try_mounting_iso($urpm, $dir, $o_iso) : try_mounting_($urpm, $dir);
+ $medium->{iso} ? _try_mounting_iso($urpm, $dir, $medium->{iso}) : _try_mounting_using_fstab($urpm, $dir);
+ -e $dir;
}
#- side-effects: $urpm->{removable_mounted}, "mount"
-sub try_mounting_iso {
+sub _try_mounting_iso {
my ($urpm, $dir, $iso) = @_;
#- note: for isos, we don't parse the fstab because it might not be declared in it.
@@ -89,13 +103,13 @@ sub try_mounting_iso {
my $loopdev = urpm::sys::first_free_loopdev();
sys_log("mount iso $mntpoint on $iso");
$loopdev and system('mount', $iso, $mntpoint, '-t', 'iso9660', '-o', "loop=$loopdev");
- $iso and $urpm->{removable_mounted}{$mntpoint} = undef;
+ $urpm->{removable_mounted}{$mntpoint} = undef;
}
-e $mntpoint;
}
#- side-effects: $urpm->{removable_mounted}, "mount"
-sub try_mounting_ {
+sub _try_mounting_using_fstab {
my ($urpm, $dir) = @_;
my $mntpoint = _non_mounted_mntpoint($dir);
@@ -104,6 +118,7 @@ sub try_mounting_ {
$urpm->{log}(N("mounting %s", $mntpoint));
sys_log("mount $mntpoint");
system("mount '$mntpoint' 2>/dev/null");
+ $urpm->{removable_mounted}{$mntpoint} = undef;
}
-e $dir;
}
@@ -147,125 +162,19 @@ sub try_umounting_removables {
}
#- side-effects:
-#- + those of _try_mounting_medium ($medium->{mntpoint})
-sub _mount_cdrom_and_check_notfound {
- my ($urpm, $blist, $medium) = @_;
-
- my ($first_url) = values %{$blist->{list}};
- _try_mounting_medium($urpm, $medium, $first_url) or return 1;
-
- _check_notfound($blist);
-}
-
-#- side-effects: none
-sub _check_notfound {
- my ($blist) = @_;
-
- $blist->{medium}{mntpoint} or return;
-
- foreach (values %{$blist->{list}}) {
- my $dir_ = _filepath($blist->{medium}, $_) or next;
- -r $dir_ or return 1;
- }
- 0;
-}
-
-#- side-effects: "eject"
-#- + those of _mount_cdrom_and_check_notfound ($urpm->{removable_mounted}, "mount")
-#- + those of try_umounting ($urpm->{removable_mounted}, "umount")
-sub _mount_cdrom {
- my ($urpm, $blist, $ask_for_medium) = @_;
- my $medium = $blist->{medium};
-
- #- 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 (_mount_cdrom_and_check_notfound($urpm, $blist, $medium)) {
- $ask_for_medium
- or $urpm->{fatal}(4, N("medium \"%s\" is not available", $medium->{name}));
-
- my $dir; # TODO
- try_umounting($urpm, $dir);
- system("/usr/bin/eject '$medium->{removable}' 2>/dev/null");
-
- $ask_for_medium->(remove_internal_name($medium->{name}))
- or $urpm->{fatal}(4, N("medium \"%s\" is not available", $medium->{name}));
- }
-}
-
-#- side-effects: none
-sub _filepath {
- my ($medium, $url) = @_;
-
- chomp $url;
- my $filepath = file_from_local_medium($medium, $url) or return;
- $filepath =~ m!/.*/! or return; #- is this really needed??
- $filepath;
-}
-
-#- side-effects: "copy-move-files"
-sub _do_the_copy {
- my ($urpm, $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.
- my $filename = basename($filepath);
- unlink "$urpm->{cachedir}/partial/$filename";
- $urpm->{log}("copying $filepath");
- copy_and_own($filepath, "$urpm->{cachedir}/partial/$filename") or return;
- my $f = urpm::get_pkgs::verify_partial_rpm_and_move($urpm, $urpm->{cachedir}, $filename) or return;
- $f;
-}
-
-#- side-effects: $sources
-#- + those of _mount_cdrom ($urpm->{removable_mounted}, "mount", "umount", "eject")
-#- + those of _do_the_copy: "copy-move-files"
-sub _copy_from_cdrom__if_needed {
- my ($urpm, $blist, $sources, $ask_for_medium, $want_copy) = @_;
-
- _mount_cdrom($urpm, $blist, $ask_for_medium);
-
- while (my ($i, $url) = each %{$blist->{list}}) {
- my $filepath = _filepath($blist->{medium}, $url) or next;
-
- if (-r $filepath) {
- $sources->{$i} = $want_copy ? _do_the_copy($urpm, $filepath) : $filepath;
- } else {
- #- fallback to use other method for retrieving the file later.
- $urpm->{error}(N("unable to read rpm file [%s] from medium \"%s\"", $filepath, $blist->{medium}{name}));
- }
- }
-}
-
-#- side-effects:
#- + those of try_mounting_non_cdrom ($urpm->{removable_mounted}, "mount")
sub try_mounting_non_cdroms {
my ($urpm, $list) = @_;
- my $blist = _create_blists($urpm->{media}, $list);
- my @used_media = map { $_->{medium} } @$blist;
+ my $blists = create_blists($urpm->{media}, $list);
- foreach my $medium (grep { !urpm::is_cdrom_url($_->{url}) } @used_media) {
- try_mounting_non_cdrom($urpm, $medium);
+ foreach my $blist (grep { urpm::file_from_local_url($_->{medium}{url}) } @$blists) {
+ try_mounting_medium($urpm, $blist->{medium}, $blist->{url});
}
}
-#- side-effects:
-#- + those of try_mounting_ ($urpm->{removable_mounted}, "mount")
-sub try_mounting_non_cdrom {
- my ($urpm, $medium) = @_;
-
- my $dir = file_from_local_medium($medium) or return;
-
- -e $dir || try_mounting($urpm, $dir, $medium->{iso}) or
- $urpm->{error}(N("unable to access medium \"%s\"", $medium->{name})), return;
-
- 1;
-}
-
#- side-effects: none
-sub _create_blists {
+sub create_blists {
my ($media, $list) = @_;
#- make sure everything is correct on input...
@@ -273,43 +182,16 @@ sub _create_blists {
@$media == @$list or return;
my $i;
- [ grep { %{$_->{list}} }
- map { { medium => $_, list => $list->[$i++] } } @$media ];
+ [ map {
+ my $list = $list->[$i++];
+ my ($url) = values %$list; # first url
+ $url ? { medium => $_, list => $list, url => $url } : ();
+ } @$media ];
}
-#- side-effects: none
-sub _sort_media {
- my (@l) = @_;
-
- if (@l > 1) {
- @l = sort { values(%{$a->{list}}) <=> values(%{$b->{list}}) } @l;
-
- #- check if a removable device is already mounted (and files present).
- if (my ($already_mounted) = grep { !_check_notfound($_) } @l) {
- @l = ($already_mounted, grep { $_ != $already_mounted } @l);
- }
- }
- @l;
-}
-
-#- $list is a [ { pkg_id1 => url1, ... }, { ... }, ... ]
-#- where there is one hash for each medium in {media}
-#-
-#- side-effects:
-#- + those of _copy_from_cdrom__if_needed ($urpm->{removable_mounted}, $sources, "mount", "umount", "eject", "copy-move-files")
-sub copy_packages_of_removable_media {
- my ($urpm, $list, $sources, $o_ask_for_medium) = @_;
-
- my $blists = _create_blists($urpm->{media}, $list);
- #- If more than one media uses this device, we have to sort
- #- needed packages to copy the needed rpm files.
- my @l = _sort_media(grep { urpm::is_cdrom_url($_->{medium}{url}) } @$blists);
-
- foreach my $blist (@l) {
- _copy_from_cdrom__if_needed($urpm, $blist, $sources, $o_ask_for_medium, @l > 1);
- }
-
- 1;
+sub copy_packages_of_removable_media {
+ require urpm::cdrom;
+ &urpm::cdrom::copy_packages_of_removable_media;
}
1;
diff --git a/urpmi b/urpmi
index 547af95e..d93b83c5 100755
--- a/urpmi
+++ b/urpmi
@@ -620,7 +620,6 @@ my $exit_code = urpm::main_loop::run($urpm, $state,
\@ask_unselect, \%requested, {
(!$urpm->{options}{auto} || $allow_medium_change ? (copy_removable => sub {
my $msg = N("Please insert the medium named \"%s\"", $_[0]);
- my $msg2 = N("Press Enter when ready...");
if ($ENV{DISPLAY} && $::gui) {
#- probably run from a drak tool
(my $gmessage) = grep { -x $_ } '/usr/X11R6/bin/gmessage', '/usr/bin/gmessage';
@@ -628,7 +627,11 @@ my $exit_code = urpm::main_loop::run($urpm, $state,
return system($gmessage, '-buttons', N("Ok") . ':1,' . N("Cancel") . ':0', "\n$msg\n");
}
}
- return defined message_input_("$msg\n$msg2 ");
+ print "$msg\n";
+
+ require Hal::Cdroms;
+ Hal::Cdroms->new->wait_for_insert;
+ 1;
}) : ()),
trans_log => sub {
# my ($mode, $file, $percent, $total, $eta, $speed) = @_;