diff options
Diffstat (limited to 'perl-install/diskdrake/hd_gtk.pm')
-rw-r--r-- | perl-install/diskdrake/hd_gtk.pm | 416 |
1 files changed, 275 insertions, 141 deletions
diff --git a/perl-install/diskdrake/hd_gtk.pm b/perl-install/diskdrake/hd_gtk.pm index d437799c5..ed3955ea7 100644 --- a/perl-install/diskdrake/hd_gtk.pm +++ b/perl-install/diskdrake/hd_gtk.pm @@ -1,36 +1,34 @@ -package diskdrake::hd_gtk; # $Id$ +package diskdrake::hd_gtk; use diagnostics; use strict; use common; -use resize_fat::main; -use my_gtk qw(:helpers :wrappers :ask); -use partition_table qw(:types); -use partition_table::raw; +use mygtk3 qw(gtknew); +use ugtk3 qw(:helpers :wrappers :create); +use partition_table; +use fs::type; use detect_devices; use diskdrake::interactive; use run_program; -use loopback; use devices; -use raid; -use any; use log; use fsedit; -use fs; +use feature qw(state); -my ($width, $height, $minwidth) = (400, 50, 5); -my ($all_hds, $in, $current_kind, $current_entry, $update_all); +my ($width, $height, $minwidth) = (400, 50, 16); +my ($all_hds, $in, $do_force_reload, $current_kind, $current_entry, $update_all); my ($w, @notebook, $done_button); -=begin -struct { +=head1 SYNOPSYS + + struct { string name # which is displayed in tab of the notebook bool no_auto # wether the kind can disappear after creation - string type # one of { 'hd', 'raid', 'lvm', 'loopback', 'removable', 'nfs', 'smb' } - hd | hd_lvm | part_raid[] | part_loopback[] | raw_hd[] val - + string type # one of { 'hd', 'raid', 'lvm', 'loopback', 'removable', 'nfs', 'smb', 'dmcrypt' } + hd | hd_lvm | part_raid[] | part_dmcrypt[] | part_loopback[] | raw_hd[] val + # widget main_box widget display_box @@ -38,64 +36,105 @@ struct { widget info_box } current_kind -part current_entry + part current_entry -notebook current_kind[] + notebook current_kind[] =cut +sub load_theme() { + my $css = "/usr/share/libDrakX/diskdrake.css"; + -r $css or $css = dirname(__FILE__) . "/../diskdrake.css"; + -r $css or $css = dirname(__FILE__) . "/../share/diskdrake.css"; + my $pl = Gtk3::CssProvider->new; + $pl->load_from_path($css); + Gtk3::StyleContext::add_provider_for_screen(Gtk3::Gdk::Screen::get_default(), $pl, Gtk3::STYLE_PROVIDER_PRIORITY_APPLICATION); +} + sub main { - ($in, $all_hds, my $nowizard) = @_; + ($in, $all_hds, $do_force_reload) = @_; @notebook = (); local $in->{grab} = 1; - $w = my_gtk->new('DiskDrake'); - my $rc = "/usr/share/libDrakX/diskdrake.rc"; - -r $rc or $rc = dirname(__FILE__) . "/../diskdrake.rc"; - -r $rc or $rc = dirname(__FILE__) . "/../share/diskdrake.rc"; - Gtk::Rc->parse($rc); + $w = ugtk3->new(N("Partitioning")); + mygtk3::register_main_window($w->{real_window}) if !$::isEmbedded && !$::isInstall; + + load_theme(); + $w->{window}->signal_connect('style-updated' => \&load_theme); # TODO # is_empty_array_ref($all_hds->{raids}) or raid::stopAll; # updateLoopback(); gtkadd($w->{window}, - gtkpack_(new Gtk::VBox(0,7), - 0, (my $filesystems_button_box = filesystems_button_box()), - 1, (my $notebook_widget = new Gtk::Notebook), - 0, (my $per_kind_action_box = new Gtk::HBox(0,0)), - 0, (my $general_action_box = new Gtk::HBox(0,0)), + gtkpack_(Gtk3::VBox->new(0,7), + 0, gtknew(($::isInstall ? ('Title1', 'label') : ('Label_Left', 'text')) + => N("Click on a partition, choose a filesystem type then choose an action"), + # workaround infamous 6 years old gnome bug #101968: + width => mygtk3::get_label_width() + ), + 1, (my $notebook_widget = Gtk3::Notebook->new), + 0, (my $per_kind_action_box = gtknew('HButtonBox', layout => 'edge')), + 0, Gtk3::HSeparator->new, + 0, (my $general_action_box = gtknew('HBox', spacing => 5)), ), ); - my $lock; + my ($lock, $initializing) = (undef, 1); $update_all = sub { + my ($o_refresh_gui) = @_; + state $not_first; + return if $initializing && $not_first; + $not_first = 1; $lock and return; $lock = 1; - partition_table::assign_device_numbers($_) foreach fsedit::all_hds($all_hds); + partition_table::assign_device_numbers($_) foreach fs::get::hds($all_hds); create_automatic_notebooks($notebook_widget); - general_action_box($general_action_box, $nowizard); + general_action_box($general_action_box); per_kind_action_box($per_kind_action_box, $current_kind); current_kind_changed($in, $current_kind); current_entry_changed($current_kind, $current_entry); $lock = 0; + if ($o_refresh_gui) { + my $new_page = $o_refresh_gui > 1 ? $notebook_widget->get_current_page : 0; + $notebook_widget->set_current_page(-1); + $notebook_widget->set_current_page($new_page); + } }; create_automatic_notebooks($notebook_widget); - $notebook_widget->signal_connect('switch_page' => sub { + $notebook_widget->signal_connect(switch_page => sub { $current_kind = $notebook[$_[2]]; $current_entry = ''; $update_all->(); }); + # ensure partitions bar is properly sized on first display: + $notebook_widget->signal_connect(realize => $update_all); $w->sync; + # add a bogus tab so that gtk+ displayed everything when there's only one disk: + $notebook_widget->prepend_page(Gtk3::Label->new, Gtk3::Label->new); + $notebook_widget->set_current_page(0); + # there's always at least one child (at least a button for create a new part on empty discs): + my @children = $current_kind->{display_box} ? $current_kind->{display_box}->get_children : (); + # workaround for $notebook_widget being realized too early: + if (!@children ||!$done_button) { + $notebook_widget->set_current_page(-1); + $notebook_widget->set_current_page(0); + undef $initializing; + $update_all->(2); + } + undef $initializing; + # remove bogus tab we added just to be sure gtk+ displayed everything: + $notebook_widget->remove_page(0); + # restore position when there's several disks: + $notebook_widget->set_current_page(0); $done_button->grab_focus; - $my_gtk::pop_it = 1; - $in->ask_okcancel(_("Read carefully!"), _("Please make a backup of your data first"), 1) or return - if $::isStandalone; - $in->ask_warn('', -_("If you plan to use aboot, be carefull to leave a free space (2048 sectors is enough) -at the beginning of the disk")) if (arch() eq 'alpha') and !$::isEmbedded; + if (!$::testing) { + $in->ask_from_list_(N("Read carefully"), N("Please make a backup of your data first"), + [ N_("Exit"), N_("Continue") ], N_("Continue")) eq N_("Continue") or return + if $::isStandalone; + } $w->main; } @@ -103,25 +142,38 @@ at the beginning of the disk")) if (arch() eq 'alpha') and !$::isEmbedded; sub try { my ($name, @args) = @_; my $f = $diskdrake::interactive::{$name} or die "unknown function $name"; - try_($name, \&{$f}, @args); + try_($name, \&$f, @args); } sub try_ { my ($name, $f, @args) = @_; - fsedit::undo_prepare($all_hds) if $name ne 'Undo'; - + my $dm_active_before = ($current_entry && $current_entry->{dm_active} && $current_entry->{dm_name}); my $v = eval { $f->($in, @args, $all_hds) }; if (my $err = $@) { - $err =~ /setstep/ and die ''; - $in->ask_warn(_("Error"), formatError($err)); + warn $err, "\n", backtrace() if $in->isa('interactive::gtk'); + $in->ask_warn(N("Error"), formatError($err)); + } + my $refresh = 0; + if ($v eq 'force_reload') { + $all_hds = $do_force_reload->(); + $refresh = 1; } - $current_entry = '' if !diskdrake::interactive::is_part_existing($current_entry, $all_hds); - $update_all->(); - - if ($v && member($name, 'Done', 'Wizard')) { - $::isEmbedded ? kill('USR1', $::CCPID) : Gtk->main_quit; + if (!diskdrake::interactive::is_part_existing($current_entry, $all_hds)) { + $current_entry = ''; + } elsif (!$dm_active_before && $current_entry->{dm_active} && $current_entry->{dm_name}) { + if (my $mapped_part = fs::get::device2part("mapper/$current_entry->{dm_name}", $all_hds->{dmcrypts})) { + $current_entry = $mapped_part; + $refresh = 2; + } } + $update_all->($refresh); + + Gtk3->main_quit if $v && member($name, 'Done'); +} + +sub get_action_box_size() { + $::isStandalone ? 200 : 150, $::isEmbedded ? 150 : 180; } ################################################################################ @@ -131,91 +183,108 @@ sub add_kind2notebook { my ($notebook_widget, $kind) = @_; die if $kind->{main_box}; - $kind->{display_box} = gtkset_usize(new Gtk::HBox(0,0), $width, $height); - $kind->{action_box} = gtkset_usize(new Gtk::VBox(0,0), 150, 180); - $kind->{info_box} = new Gtk::VBox(0,0); - $kind->{main_box} = - gtkpack_(new Gtk::VBox(0,7), - 0, $kind->{display_box}, - 1, gtkpack_(new Gtk::HBox(0,7), - 0, $kind->{action_box}, - 1, $kind->{info_box})); - my_gtk::add2notebook($notebook_widget, $kind->{name}, $kind->{main_box}); + $kind->{display_box} = gtkset_size_request(Gtk3::HBox->new(0,0), $width, $height); + $kind->{action_box} = gtkset_size_request(Gtk3::VBox->new, get_action_box_size()); + $kind->{info_box} = Gtk3::VBox->new(0,0); + my $box = + gtkpack_(Gtk3::VBox->new(0,7), + 0, create_scrolled_window($kind->{display_box}, [ 'automatic', 'never' ]), + 0, filesystems_button_box(), + 1, $kind->{info_box}); + $kind->{main_box} = gtknew('HBox', spacing => 5, children => [ + 1, $box, + 0, $kind->{action_box}, + ]); + ugtk3::add2notebook($notebook_widget, $kind->{name}, $kind->{main_box}); push @notebook, $kind; $kind; } +sub interactive_help() { + if ($::isInstall) { + $in->display_help({ interactive_help_id => 'diskdrake' }); + } else { + require run_program; + run_program::raw({ detach => 1 }, 'drakhelp', '--id', 'diskdrake'); + } +} + sub general_action_box { - my ($box, $nowizard) = @_; - $_->widget->destroy foreach $box->children; - my @actions = (if_($::isInstall && !$nowizard, __("Wizard")), + my ($box) = @_; + $_->destroy foreach $box->get_children; + + my $box_start = gtknew('HButtonBox', layout => 'start', children_tight => [ + gtknew('Install_Button', text => N("Help"), clicked => \&interactive_help) + ]); + + my @actions = ( diskdrake::interactive::general_possible_actions($in, $all_hds), - __("Done")); + N_("Done")); + my $box_end = gtknew('HButtonBox', layout => 'end', spacing => 5); foreach my $s (@actions) { - my $button = new Gtk::Button(translate($s)); + my $button = Gtk3::Button->new(translate($s)); $done_button = $button if $s eq 'Done'; - gtkadd($box, gtksignal_connect($button, clicked => sub { try($s) })); + gtkadd($box_end, gtksignal_connect($button, clicked => sub { try($s) })); } + gtkadd($box, $box_start, $box_end); } sub per_kind_action_box { my ($box, $kind) = @_; - $_->widget->destroy foreach $box->children; - - $kind->{type} =~ /hd|lvm/ or return; + $_->destroy foreach $box->get_children; - foreach my $s (diskdrake::interactive::hd_possible_actions($in, kind2hd($kind), $all_hds)) { + my @actions = (if_($kind->{type} =~ /hd|lvm/, diskdrake::interactive::hd_possible_actions_base($in)), + diskdrake::interactive::hd_possible_actions_extra($in)); + foreach my $s (@actions) { gtkadd($box, - gtksignal_connect(new Gtk::Button(translate($s)), + gtksignal_connect(Gtk3::Button->new(translate($s)), clicked => sub { try($s, kind2hd($kind)) })); } + # make sure a big translations window to resize (as by default all buttons have the same size): + $box->set_child_non_homogeneous($_, Glib::TRUE), "\n" foreach $box->get_children; } sub per_entry_action_box { my ($box, $kind, $entry) = @_; - $_->widget->destroy foreach $box->children; + $_->destroy foreach $box->get_children; if ($entry) { my @buttons = map { my $s = $_; - my $w = new Gtk::Button(translate($s)); + my $w = Gtk3::Button->new(translate($s)); $w->signal_connect(clicked => sub { try($s, kind2hd($kind), $entry) }); $w; } diskdrake::interactive::part_possible_actions($in, kind2hd($kind), $entry, $all_hds); - gtkadd($box, gtkadd(new Gtk::Frame(_("Choose action")), - createScrolledWindow(gtkpack__(new Gtk::VBox(0,0), @buttons)))) if @buttons; + gtkadd($box, create_scrolled_window(gtkpack__(Gtk3::VBox->new, @buttons), undef, 'none')) if @buttons; } else { - my $txt = !$::isStandalone && fsedit::is_one_big_fat($all_hds->{hds}) ? -_("You have one big FAT partition -(generally used by MicroSoft Dos/Windows). + my $txt = !$::isStandalone && fsedit::is_one_big_fat_or_NT($all_hds->{hds}) ? +N("You have one big Microsoft Windows partition. I suggest you first resize that partition -(click on it, then click on \"Resize\")") : _("Please click on a partition"); - gtkpack($box, gtktext_insert(new Gtk::Text, $txt)); +(click on it, then click on \"Resize\")") : N("Please click on a partition"); + gtkpack($box, gtktext_insert(Gtk3::TextView->new, $txt)); } } sub per_entry_info_box { my ($box, $kind, $entry) = @_; - $_->widget->destroy foreach $box->children; + $_->destroy foreach $box->get_children; my $info; if ($entry) { $info = diskdrake::interactive::format_part_info(kind2hd($kind), $entry); } elsif ($kind->{type} =~ /hd|lvm/) { $info = diskdrake::interactive::format_hd_info($kind->{val}); } - gtkpack($box, gtkadd(new Gtk::Frame(_("Details")), gtkset_justify(new Gtk::Label($info), 'left'))); + gtkpack($box, gtkadd(gtkcreate_frame(N("Details")), + gtknew('HBox', border_width => 5, children_loose => [ + gtkset_alignment(gtkset_justify(gtknew('Label', selectable => 1, text => $info), 'left'), 0, 0) ]))); } sub current_kind_changed { - my ($in, $kind) = @_; - - $_->widget->destroy foreach $kind->{display_box}->children; + my ($_in, $kind) = @_; - my $v = $kind->{val}; - my @parts = - $kind->{type} eq 'raid' ? grep { $_ } @$v : - $kind->{type} eq 'loopback' ? @$v : fsedit::get_fstab_and_holes($v); - my $totalsectors = - $kind->{type} =~ /raid|loopback/ ? sum(map { $_->{size} } @parts) : $v->{totalsectors}; + return if !$kind->{display_box}; + $_->destroy foreach $kind->{display_box}->get_children; + my @parts = kind2parts($kind); + my $totalsectors = kind2sectors($kind, @parts); create_buttons4partitions($kind, $totalsectors, @parts); } @@ -230,7 +299,6 @@ sub current_entry_changed { sub create_automatic_notebooks { my ($notebook_widget) = @_; - my @l = fsedit::all_hds($all_hds); $_->{marked} = 0 foreach @notebook; my $may_add = sub { @@ -242,39 +310,71 @@ sub create_automatic_notebooks { }; $may_add->(hd2kind($_)) foreach @{$all_hds->{hds}}; $may_add->(lvm2kind($_)) foreach @{$all_hds->{lvms}}; - $may_add->(raid2kind()) if grep { $_ } @{$all_hds->{raids}}; + $may_add->(raid2kind()) if @{$all_hds->{raids}}; $may_add->(loopback2kind()) if @{$all_hds->{loopbacks}}; - @notebook = grep_index { - my $b = $_->{marked} or $notebook_widget->remove_page($::i); - $b; + my $i = 0; + @notebook = grep { + if ($_->{marked}) { + $i++; + 1; + } else { + $notebook_widget->remove_page($i); + 0; + } } @notebook; - @notebook or die ''; + @notebook or $in->ask_warn(N("Error"), N("No hard disk drives found")), $in->exit(1); } ################################################################################ # parts: helpers ################################################################################ sub create_buttons4partitions { - my ($kind, $totalsectors, @parts) = @_; + my ($kind, $totalsectors, @all_parts) = @_; - $width = max($width, 0.9 * second($w->{window}->window->get_size)) if $w->{window}->window; + if ($w->{window}->get_window) { + my $windowwidth = $w->{window}->get_allocated_width; + $windowwidth = $::real_windowwidth if $windowwidth <= 1; + $width = $windowwidth - first(get_action_box_size()) - 25; + } + + my @parts = grep { $_->{size} > MB(2) || !isEmpty($_) } @all_parts; my $ratio = $totalsectors ? ($width - @parts * $minwidth) / $totalsectors : 1; - while (1) { + my $i = 1; + while ($i < 30) { + $i++; my $totalwidth = sum(map { $_->{size} * $ratio + $minwidth } @parts); $totalwidth <= $width and last; $ratio /= $totalwidth / $width * 1.1; } + my $current_button; + my $set_current_button = sub { + my ($w) = @_; + $current_button->set_active(0) if $current_button; + ($current_button = $w)->set_active(1); + }; + foreach my $entry (@parts) { - my $w = new Gtk::Button($entry->{mntpoint} || '') or die ''; - $w->signal_connect(focus_in_event => sub { current_entry_changed($kind, $entry) }); - $w->signal_connect(button_press_event => sub { current_entry_changed($kind, $entry) }); + if (isRawLUKS($entry) && $entry->{dm_active}) { + my $p = find { $entry->{dm_name} eq $_->{dmcrypt_name} } @{$all_hds->{dmcrypts}}; + $entry = $p if $p; + } + my $info = $entry->{mntpoint} || $entry->{device_LABEL} || ''; + $info .= "\n" . ($entry->{size} ? formatXiB($entry->{size}, 512) : N("Unknown")) if $info; + my $w = ($info ? Gtk3::ToggleButton->new_with_label($info) : Gtk3::ToggleButton->new) or internal_error('new_with_label'); + $info and $w->get_child->set_ellipsize('end'); + $w->set_tooltip_text($info); + $w->signal_connect(clicked => sub { + $current_button != $w or return; + current_entry_changed($kind, $entry); + $set_current_button->($w); + }); $w->signal_connect(key_press_event => sub { - my ($w, $e) = @_; - $e->{state} & 4 or return; - my $c = chr $e->{keyval}; + my (undef, $event) = @_; + member('control-mask', @{$event->state}) && $w == $current_button or return; + my $c = chr $event->keyval; foreach my $s (diskdrake::interactive::part_possible_actions($in, kind2hd($kind), $entry, $all_hds)) { ${{ @@ -289,10 +389,19 @@ sub create_buttons4partitions { last; } }); - $w->set_name("PART_" . type2name($entry->{type})); - $w->set_usize($entry->{size} * $ratio + $minwidth, 0); - gtkpack__($kind->{display_box}, $w); - $w->grab_focus if $current_entry && fsedit::is_same_part($current_entry, $entry); + if (isLUKS($entry) || isRawLUKS($entry)) { + $w->set_image(gtknew("Image", file => "security-strong")); + } + my @colorized_fs_types = qw(ext3 ext4 xfs swap vfat ntfs ntfs-3g exfat); + $w->set_name("PART_" . (isEmpty($entry) ? 'empty' : + $entry->{fs_type} && member($entry->{fs_type}, @colorized_fs_types) ? $entry->{fs_type} : + 'other')); + $w->set_size_request($entry->{size} * $ratio + $minwidth, 0); + gtkpack($kind->{display_box}, $w); + if ($current_entry && fsedit::are_same_partitions($current_entry, $entry)) { + $set_current_button->($w); + $w->grab_focus; + } } } @@ -300,18 +409,18 @@ sub create_buttons4partitions { ################################################################################ # disks: helpers ################################################################################ -sub current_hd { - $current_kind->{type} eq 'hd' or die 'current_hd called but $current_kind is not an hd'; +sub current_hd() { + $current_kind->{type} =~ /hd|lvm/ or die 'current_hd called but $current_kind is not an hd (' . $current_kind->{type} . ')'; $current_kind->{val}; } -sub current_part { +sub current_part() { current_hd(); $current_entry; } sub kind2hd { my ($kind) = @_; - $kind->{type} =~ /hd|lvm/ ? $kind->{val} : {} + $kind->{type} =~ /hd|lvm/ ? $kind->{val} : bless({}, 'partition_table::raw'); } sub hd2kind { @@ -320,43 +429,63 @@ sub hd2kind { } sub filesystems_button_box() { - my @types = (__("Ext2"), __("Journalised FS"), __("Swap"), arch() =~ /sparc/ ? __("SunOS") : arch() eq "ppc" ? __("HFS") : __("FAT"), - __("Other"), __("Empty")); - my %name2type = (Ext2 => 0x83, 'Journalised FS' => 0x483, Swap => 0x82, Other => 1, FAT => 0xb, HFS => 0x402); - - gtkpack(new Gtk::HBox(0,0), - _("Filesystem types:"), - map { my $w = new Gtk::Button(translate($_)); - my $t = $name2type{$_}; - $w->signal_connect(clicked => sub { try_('', \&createOrChangeType, $t, current_hd(), current_part()) }); - $w->can_focus(0); - $w->set_name($_); + my @types = (N_("Ext4"), N_("XFS"), N_("Swap"), N_("Windows"), + N_("Other"), N_("Empty")); + my %name2fs_type = (Ext3 => 'ext3', Ext4 => 'ext4', 'XFS' => 'xfs', Swap => 'swap', Other => 'other', "Windows" => 'vfat', HFS => 'hfs'); + + gtkpack(Gtk3::HBox->new, + map { + my $t = $name2fs_type{$_}; + my $w = gtknew('Button', text => translate($_), widget_name => 'PART_' . ($t || 'empty'), + tip => N("Filesystem types:"), + clicked => sub { try_('', \&createOrChangeType, $t, current_hd(), current_part()) }); + $w->set_can_focus(0); $w; } @types); } sub createOrChangeType { - my ($in, $type, $hd, $part, $all_hds) = @_; + my ($in, $fs_type, $hd, $part, $all_hds) = @_; - $part ||= !fsedit::get_fstab($hd) && - { type => 0, start => 1, size => $hd->{totalsectors} - 1 }; + $part ||= !fs::get::hds_fstab($hd) && + { pt_type => 0, start => 1, size => $hd->{totalsectors} - 1 }; $part or return; - if ($type == 1) { - $in->ask_warn('', _("Use ``%s'' instead", $part->{type} ? _("Type") : _("Create"))); - } elsif (!$type) { - $in->ask_warn('', _("Use ``%s'' instead", _("Delete"))) if $part->{type}; - } elsif ($part->{type}) { - return unless $::expert; - return if $type == $part->{type}; - isBusy($part) and $in->ask_warn('', _("Use ``Unmount'' first")), return; - diskdrake::interactive::ask_alldatawillbelost($in, $part, __("After changing type of partition %s, all data on this partition will be lost")) or return; - diskdrake::interactive::check_type($in, $type, $hd, $part) and fsedit::change_type($type, $hd, $part); - } else { - $part->{type} = $type; + if ($fs_type eq 'other') { + if (isEmpty($part)) { + try('Create', $hd, $part); + } else { + try('Type', $hd, $part); + } + } elsif (!$fs_type) { + if (isEmpty($part)) { + $in->ask_warn(N("Warning"), N("This partition is already empty")); + } else { + try('Delete', $hd, $part); + } + } elsif (isEmpty($part)) { + fs::type::set_fs_type($part, $fs_type); diskdrake::interactive::Create($in, $hd, $part, $all_hds); + } else { + return if $fs_type eq $part->{fs_type}; + $in->ask_warn('', isBusy($part) ? N("Use ``Unmount'' first") : N("Use ``%s'' instead (in expert mode)", N("Type"))); } } +sub kind2parts { + my ($kind) = @_; + my $v = $kind->{val}; + my @parts = + $kind->{type} eq 'raid' ? grep { $_ } @$v : + $kind->{type} eq 'loopback' ? @$v : fs::get::hds_fstab_and_holes($v); + @parts; +} + +sub kind2sectors { + my ($kind, @parts) = @_; + my $v = $kind->{val}; + $kind->{type} =~ /raid|loopback/ ? sum(map { $_->{size} } @parts) : $v->{totalsectors}; +} + ################################################################################ # lvms: helpers ################################################################################ @@ -368,14 +497,19 @@ sub lvm2kind { ################################################################################ # raids: helpers ################################################################################ -sub raid2kind { +sub raid2kind() { { type => 'raid', name => 'raid', val => $all_hds->{raids} }; } +sub raid2real_kind { + my ($raid) = @_; + { type => 'raid', name => 'raid', val => $raid }; +} + ################################################################################ # loopbacks: helpers ################################################################################ -sub loopback2kind { +sub loopback2kind() { { type => 'loopback', name => 'loopback', val => $all_hds->{loopbacks} }; } |