diff --git a/bsdfdisk/bsdfdisk-lib.pl b/bsdfdisk/bsdfdisk-lib.pl index b2d66e1ff..0719188ba 100644 --- a/bsdfdisk/bsdfdisk-lib.pl +++ b/bsdfdisk/bsdfdisk-lib.pl @@ -1,468 +1,538 @@ -# Functions for FreeBSD disk management - -use strict; -use warnings; -no warnings 'redefine'; -no warnings 'uninitialized'; -BEGIN { push(@INC, ".."); }; -use WebminCore; -&init_config(); -&foreign_require("mount"); -&foreign_require("fdisk"); -our (%text); - -sub check_fdisk -{ -foreach my $cmd ("fdisk", "disklabel") { - if (!&has_command($cmd)) { - return &text('index_ecmd', "$cmd"); - } - } -return undef; -} - -# list_disks_partitions() -# Returns a list of all disks, slices and partitions -sub list_disks_partitions -{ -my @rv; - -# Iterate over disk devices -foreach my $dev (glob("/dev/ada[0-9]"), glob("/dev/ada[0-9][0-9]"), - glob("/dev/ad[0-9]"), glob("/dev/ad[0-9][0-9]"), - glob("/dev/da[0-9]"), glob("/dev/da[0-9][0-9]")) { - next if (!-r $dev || -l $dev); - my $disk = { 'device' => $dev, - 'prefix' => $dev, - 'type' => $dev =~ /^\/dev\/da/ ? 'scsi' : 'ide', - 'slices' => [ ] }; - if ($dev =~ /^\/dev\/(.*)/) { - $disk->{'short'} = $1; - } - if ($dev =~ /^\/dev\/([a-z]+)(\d+)/) { - $disk->{'number'} = $2; - $disk->{'desc'} = &text('select_device', - uc($disk->{'type'}), "$2"); - } - $disk->{'index'} = scalar(@rv); - push(@rv, $disk); - - # Get size and slices - my $out = &backquote_command("fdisk ".quotemeta($dev)); - my @lines = split(/\r?\n/, $out); - my $slice; - for(my $i=0; $i<@lines; $i++) { - if ($lines[$i] =~ /cylinders=(\d+)\s+heads=(\d+)\s+sectors\/track=(\d+)\s+\((\d+)/) { - # Disk information - $disk->{'cylinders'} = $1; - $disk->{'heads'} = $2; - $disk->{'sectors'} = $3; - $disk->{'blksper'} = $4; - $disk->{'blocks'} = $disk->{'cylinders'} * - $disk->{'blksper'}; - $disk->{'blocksize'} = 512; # Guessed? - $disk->{'size'} = $disk->{'blocks'} * - $disk->{'blocksize'}; - } - elsif ($i+1 < @lines && - $lines[$i+1] !~ // && - $lines[$i] =~ /data\s+for\s+partition\s+(\d+)/) { - # Start of a slice - $slice = { 'number' => $1, - 'device' => $dev."s".$1, - 'index' => scalar(@{$disk->{'slices'}}) }; - if ($slice->{'device'} =~ /^\/dev\/([a-z]+)(\d+)s(\d+)/){ - $slice->{'desc'} = &text('select_slice', - uc($disk->{'type'}), "$2", "$3"); - } - push(@{$disk->{'slices'}}, $slice); - } - elsif ($lines[$i] =~ /sysid\s+(\d+)\s+\(0x([0-9a-f]+)/ && $slice) { - # Slice type - $slice->{'type'} = $2; - } - elsif ($lines[$i] =~ /start\s+(\d+),\s+size\s+(\d+)\s+\((.*)\)/ && $slice) { - # Slice start and size - $slice->{'startblock'} = $1; - $slice->{'blocks'} = $2; - $slice->{'size'} = &string_to_size("$3"); - $slice->{'active'} = $lines[$i] =~ /\(active\)/ ? 1 : 0; - } - elsif ($lines[$i] =~ /beg:\s+cyl\s+(\d+)/ && $slice) { - # Slice start - $slice->{'start'} = $1; - } - elsif ($lines[$i] =~ /end:\s+cyl\s+(\d+)/ && $slice) { - # Slice end - $slice->{'end'} = $1; - } - } - - # Get disk model from dmesg - open(DMESG, ") { - if (/^(\S+):\s+(\S+\s+)?<(.*)>/ && $1 eq $disk->{'short'}) { - $disk->{'model'} = $3; - } - elsif (/^(\S+):\s+(\d+)(\S+)\s+\((\d+)\s+(\d+)\s+byte\s+sectors/ && - $1 eq $disk->{'short'}) { - $disk->{'sectorsize'} = $5; - $disk->{'size'} = &string_to_size("$2 $3"); - } - } - close(DMESG); - - # Get partitions within slices - foreach my $slice (@{$disk->{'slices'}}) { - $slice->{'parts'} = [ ]; - next if (!-e $slice->{'device'}); - my $out = &backquote_command("disklabel ".$slice->{'device'}); - my @lines = split(/\r?\n/, $out); - foreach my $l (@lines) { - if ($l =~ /^\s*([a-z]):\s+(\d+)\s+(\d+)\s+(\S+)/) { - my $part = { 'letter' => $1, - 'blocks' => $2, - 'startblock' => $3, - 'type' => $4, - 'device' =>$slice->{'device'}.$1 }; - $part->{'size'} = $part->{'blocks'} * - $disk->{'blocksize'}; - $part->{'desc'} = &text('select_part', - uc($disk->{'type'}), - $disk->{'number'}, - $slice->{'number'}, - uc($part->{'letter'})); - next if ($part->{'type'} eq 'unused' && - $part->{'startblock'} == 0); - push(@{$slice->{'parts'}}, $part); - } - } - } - } - -return @rv; -} - -# string_to_size(str) -# Convert a string like 100 Meg to a number in bytes -sub string_to_size -{ -my ($str) = @_; -my ($n, $pfx) = split(/\s+/, $str); -if ($pfx =~ /^b/i) { - return $n; - } -if ($pfx =~ /^k/i) { - return $n * 1024; - } -if ($pfx =~ /^m/i) { - return $n * 1024 * 1024; - } -if ($pfx =~ /^g/i) { - return $n * 1024 * 1024 * 1024; - } -if ($pfx =~ /^t/i) { - return $n * 1024 * 1024 * 1024 * 1024; - } -return undef; -} - -# partition_select(name, value, mode, &found, disk-regexp) -# Returns HTML for a selector for a slice. The mode parameter means : -# 1 = disks -# 2 = disks, slices and partitions -# 3 = slices and partitions -sub partition_select -{ -my ($name, $value, $mode, $found, $diskre) = @_; -my @opts; -my @dlist = &list_disks_partitions(); -foreach my $d (@dlist) { - my $dev = $d->{'device'}; - next if ($diskre && $dev !~ /$diskre/); - if ($mode == 1 || $mode == 2) { - push(@opts, [ $dev, &partition_description($dev) ]); - } - if ($mode >= 2) { - foreach my $s (@{$d->{'slices'}}) { - push(@opts, [ $s->{'device'}, - &partition_description($s->{'device'}) ]); - foreach my $p (@{$s->{'parts'}}) { - push(@opts, [ $p->{'device'}, - &partition_description($p->{'device'}) ]); - } - } - } - } -if ($found && &indexof($value, map { $_->[0] } @opts) >= 0) { - $$found = 1; - } -return &ui_select($name, $value, \@opts); -} - -# partition_description(device) -# Returns a human-readable description for a device name -sub partition_description -{ -my ($dev) = @_; -if ($dev =~ /^\/dev\/([a-z]+)(\d+)$/) { - # A whole disk of some type - return &text('select_device', - $1 eq 'da' ? 'SCSI' : 'IDE', "$2"); - } -elsif ($dev =~ /^\/dev\/([a-z]+)(\d+)s(\d+)$/) { - # A slice within a disk - return &text('select_slice', - $1 eq 'da' ? 'SCSI' : 'IDE', "$2", "$3"); - } -elsif ($dev =~ /^\/dev\/([a-z]+)(\d+)s(\d+)([a-z])$/) { - # A partition within a slice - return &text('select_part', - $1 eq 'da' ? 'SCSI' : 'IDE', "$2", "$3", uc($4)); - } -else { - # No idea - return $dev; - } -} - -# execute_fdisk_commands(&disk, &commands) -# Run a series of commands on a disk via the fdisk config file -sub execute_fdisk_commands -{ -my ($disk, $cmds) = @_; -my $temp = &transname(); -my $fh = "TEMP"; -&open_tempfile($fh, ">$temp"); -foreach my $c (@$cmds) { - &print_tempfile($fh, $c."\n"); - } -&close_tempfile($fh); -my $out = &backquote_logged("fdisk -f $temp $disk->{'device'} &1"); -my $ex = $?; -&unlink_file($temp); -return $ex ? $out : undef; -} - -# delete_slice(&disk, &slice) -# Delete one slice from a disk -sub delete_slice -{ -my ($disk, $slice) = @_; -return &execute_fdisk_commands($disk, - [ "p $slice->{'number'} 0 0 0" ]); -} - -# create_slice(&disk, &slice) -# Add a slice to a disk -sub create_slice -{ -my ($disk, $slice) = @_; -my $type = hex($slice->{'type'}); -my $start = int($slice->{'startblock'} * $disk->{'blocksize'} / 1024); -my $length = int($slice->{'blocks'} * $disk->{'blocksize'} / 1024); -my $err = &execute_fdisk_commands($disk, - [ "p $slice->{'number'} $type ${start}K ${length}K" ]); -if (!$err) { - $slice->{'device'} = $disk->{'device'}."s".$slice->{'number'}; - } -return $err; -} - -# modify_slice(&disk, &old-slice, &slice) -# Apply type or size changes to a slice -sub modify_slice -{ -my ($disk, $oldslice, $slice) = @_; -if ($oldslice->{'type'} ne $slice->{'type'}) { - # Change the type - my $type = hex($slice->{'type'}); - my $start = int(($slice->{'startblock'} * $disk->{'blocksize'}) / 1024); - my $end = int((($slice->{'startblock'} + $slice->{'blocks'}) * - $disk->{'blocksize'}) / 1024); - my $err = &execute_fdisk_commands($disk, - [ "p $slice->{'number'} $type ${start}K ${end}K" ]); - return $err if ($err); - } -if (!$oldslice->{'active'} && $slice->{'active'}) { - # Make active - my $err = &execute_fdisk_commands($disk, - [ "a $slice->{'number'}" ]); - return $err if ($err); - } -return undef; -} - -# initialize_slice(&disk, &slice) -# After a slice is created, put a default label on it -sub initialize_slice -{ -my ($disk, $slice) = @_; -my $err = &backquote_logged("bsdlabel -w $slice->{'device'}"); -return $? ? $err : undef; -} - -sub list_partition_types -{ -return ( '4.2BSD', 'swap', 'unused', 'vinum' ); -} - -# save_partition(&disk, &slice, &part) -# Create or update a partition on some slice -sub save_partition -{ -my ($disk, $slice, $part) = @_; -my $out = &backquote_command("bsdlabel $slice->{'device'}"); -if ($? && $out =~ /no\s+valid\s+label/) { - # No label at all yet .. initialize - my $err = &initialize_slice($disk, $slice); - return "Failed to create initial disk label : $err" if ($err); - } - -# Edit or add a line in the existing label -my $wantline = " ".$part->{'letter'}.": ".$part->{'blocks'}." ". - $part->{'startblock'}." ".$part->{'type'}; -my @lines = split(/\r?\n/, $out); -my $found = 0; -for(my $i=0; $i<@lines; $i++) { - if ($lines[$i] =~ /^\s+(\S+):/ && $1 eq $part->{'letter'}) { - $lines[$i] = $wantline; - $found++; - last; - } - } -if (!$found) { - push(@lines, $wantline); - } -my $err = &save_partition_lines($slice, \@lines); -if (!$err && !$part->{'device'}) { - $part->{'device'} = $slice->{'device'}.$part->{'letter'}; - } -return $err; -} - -# delete_partition(&disk, &slice, &part) -# Delete a partition on some slice -sub delete_partition -{ -my ($disk, $slice, $part) = @_; - -# Fix up the line for the part being deleted -my $out = &backquote_command("bsdlabel $slice->{'device'}"); -my @lines = split(/\r?\n/, $out); -my $found = 0; -for(my $i=0; $i<@lines; $i++) { - if ($lines[$i] =~ /^\s+(\S+):/ && $1 eq $part->{'letter'}) { - splice(@lines, $i, 1); - } - } -return &save_partition_lines($slice, \@lines); -} - -# save_partition_lines(&slice, &lines) -# Feed the given lines to the bsdlabel command to update a slice's partition -# list. Returns undef on success or an error message on failure. -sub save_partition_lines -{ -my ($slice, $lines) = @_; - -# Write to a temp file -my $fh = "TEMP"; -my $temp = &transname(); -&open_tempfile($fh, ">$temp"); -foreach my $l (@$lines) { - &print_tempfile($fh, $l."\n"); - } -&close_tempfile($fh); - -# Apply the new label -my $out = &backquote_logged("bsdlabel -R $slice->{'device'} $temp"); -my $ex = $?; -&unlink_file($temp); -return $ex ? $out : undef; -} - -# create_filesystem(&disk, &slice, &part, &fs-details) -# Creates a new filesystem, and returns undef on success or the error output -# on failure. -sub create_filesystem -{ -my ($disk, $slice, $part, $newfs) = @_; -my $cmd = &get_create_filesystem_command($disk, $slice, $part, $newfs); -my $out = &backquote_logged("$cmd 2>&1 {'free'}) if ($newfs->{'free'} ne ''); -push(@cmd, "-t") if ($newfs->{'trim'}); -push(@cmd, "-L", quotemeta($newfs->{'label'})) if ($newfs->{'label'} ne ''); -push(@cmd, $part ? $part->{'device'} : $slice->{'device'}); -return join(" ", @cmd); -} - -# check_filesystem(&disk, &slice, &part) -# Checks the filesystem on some partition, and returns undef on success or -# the error output on failure. -sub check_filesystem -{ -my ($disk, $slice, $part) = @_; -my $cmd = &get_check_filesystem_command($disk, $slice, $part); -my $out = &backquote_logged("$cmd 2>&1 {'device'} : $slice->{'device'}; -my @cmd = "fsck"; -my @st = &fdisk::device_status($dev); -if (!@st) { - # Assume UFS type - push(@cmd, "-t", "ufs"); - } -push(@cmd, $dev); -return join(" ", @cmd); -} - -# show_filesystem_buttons(hiddens, &status, &part-or-slice) -# Show buttons to create a filesystem on a partition or slice -sub show_filesystem_buttons -{ -my ($hiddens, $st, $object) = @_; -print &ui_buttons_row( - "newfs_form.cgi", $text{'part_newfs'}, $text{'part_newfsdesc'}, - $hiddens); - -if (!@$st || $st->[1] ne 'swap') { - print &ui_buttons_row( - "fsck.cgi", $text{'part_fsck'}, $text{'part_fsckdesc'}, - $hiddens); - } - -if (!@$st) { - if ($object->{'type'} eq 'swap' || $object->{'type'} eq '82') { - print &ui_buttons_row("../mount/edit_mount.cgi", - $text{'part_newmount2'}, $text{'part_mountmsg2'}, - &ui_hidden("newdev", $object->{'device'}). - &ui_hidden("type", "swap")); - } - else { - print &ui_buttons_row("../mount/edit_mount.cgi", - $text{'part_newmount'}, $text{'part_mountmsg'}, - &ui_hidden("newdev", $object->{'device'}). - &ui_hidden("type", "ufs"), - &ui_textbox("newdir", undef, 20)); - } - } -} - -1; +# Functions for FreeBSD disk management + +use strict; +use warnings; +no warnings 'redefine'; +no warnings 'uninitialized'; +BEGIN { push(@INC, ".."); }; +use WebminCore; +&init_config(); +&foreign_require("mount"); +&foreign_require("fdisk"); +our (%text); + +sub check_fdisk +{ +foreach my $cmd ("fdisk", "disklabel", "gpart") { + if (!&has_command($cmd)) { + return &text('index_ecmd', "$cmd"); + } + } +return undef; +} + +# list_disks_partitions() +# Returns a list of all disks, slices and partitions +sub list_disks_partitions +{ +my @rv; + +# Iterate over disk devices +foreach my $dev (glob("/dev/ada[0-9]"), glob("/dev/ada[0-9][0-9]"), + glob("/dev/ad[0-9]"), glob("/dev/ad[0-9][0-9]"), + glob("/dev/nvd[0-9]"), glob("/dev/nvd[0-9][0-9]"), + glob("/dev/vtbd[0-9]"), glob("/dev/vtbd[0-9][0-9]"), + glob("/dev/md[0-9]"), glob("/dev/md[0-9][0-9]"), + glob("/dev/da[0-9]"), glob("/dev/da[0-9][0-9]")) { + next if (!-r $dev || -l $dev); + my $disk = { 'device' => $dev, + 'prefix' => $dev, + 'type' => $dev =~ /^\/dev\/da/ ? 'scsi' : 'ide', + 'slices' => [ ] }; + if ($dev =~ /^\/dev\/(.*)/) { + $disk->{'short'} = $1; + } + if ($dev =~ /^\/dev\/([a-z]+)(\d+)/) { + $disk->{'number'} = $2; + $disk->{'desc'} = &text('select_device', + uc($disk->{'type'}), "$2"); + } + $disk->{'index'} = scalar(@rv); + push(@rv, $disk); + + # Get size and slices + my $out; + my $sdev = 's'; + if (&has_command('gpart')) { + # Get size and slices with GPT support + $out = &backquote_command("gpart show -p ".quotemeta($dev)); + $sdev = 'p'; + } + else { + $out = &backquote_command("fdisk ".quotemeta($dev)); + } + if ($out =~ /Scheme:\s*GPT/i) { + $disk->{'type'} = 'gpt'; + } + my @lines = split(/\r?\n/, $out); + my $slice; + for(my $i=0; $i<@lines; $i++) { + if ($lines[$i] =~ /cylinders=(\d+)\s+heads=(\d+)\s+sectors\/track=(\d+)\s+\((\d+)/) { + # Disk information + $disk->{'cylinders'} = $1; + $disk->{'heads'} = $2; + $disk->{'sectors'} = $3; + $disk->{'blksper'} = $4; + $disk->{'blocks'} = $disk->{'cylinders'} * + $disk->{'blksper'}; + $disk->{'blocksize'} = 512; # Guessed? + $disk->{'size'} = $disk->{'blocks'} * + $disk->{'blocksize'}; + } + elsif ($i+1 < @lines && + $lines[$i+1] !~ // && + $lines[$i] =~ /data\s+for\s+partition\s+(\d+)/) { + # Start of a slice + $slice = { 'number' => $1, + 'device' => $dev."$sdev".$1, + 'index' => scalar(@{$disk->{'slices'}}) }; + if ($slice->{'device'} =~ /^\/dev\/([a-z]+)(\d+)[ps](\d+)/) { + $slice->{'desc'} = &text('select_slice', + uc($disk->{'type'}), "$2", "$3"); + } + push(@{$disk->{'slices'}}, $slice); + } + elsif ($lines[$i] =~ /sysid\s+(\d+)\s+\(0x([0-9a-f]+)/ && $slice) { + # Slice type + $slice->{'type'} = $2; + } + elsif ($lines[$i] =~ /start\s+(\d+),\s+size\s+(\d+)\s+\((.*)\)/ && $slice) { + # Slice start and size + $slice->{'startblock'} = $1; + $slice->{'blocks'} = $2; + $slice->{'size'} = &string_to_size("$3"); + $slice->{'active'} = $lines[$i] =~ /\(active\)/ ? 1 : 0; + } + elsif ($lines[$i] =~ /beg:\s+cyl\s+(\d+)/ && $slice) { + # Slice start + $slice->{'start'} = $1; + } + elsif ($lines[$i] =~ /end:\s+cyl\s+(\d+)/ && $slice) { + # Slice end + $slice->{'end'} = $1; + } + } + + # Get disk model from dmesg + open(DMESG, ") { + if (/^(\S+):\s+(\S+\s+)?<(.*)>/ && $1 eq $disk->{'short'}) { + $disk->{'model'} = $3; + } + elsif (/^(\S+):\s+(\d+)(\S+)\s+\((\d+)\s+(\d+)\s+byte\s+sectors/ && + $1 eq $disk->{'short'}) { + $disk->{'sectorsize'} = $5; + $disk->{'size'} = &string_to_size("$2 $3"); + } + } + close(DMESG); + + # Get partitions within slices + foreach my $slice (@{$disk->{'slices'}}) { + $slice->{'parts'} = [ ]; + next if (!-e $slice->{'device'}); + my $out; + if (&has_command('gpart')) { + $out = &backquote_command("gpart show -p ".$slice->{'device'}); + } + else { + $out = &backquote_command("disklabel ".$slice->{'device'}); + } + my @lines = split(/\r?\n/, $out); + foreach my $l (@lines) { + if ($l =~ /^\s*([a-z]):\s+(\d+)\s+(\d+)\s+(\S+)(\s+(\S+))?/) { + my $part = { 'letter' => $1, + 'blocks' => $2, + 'startblock' => $3, + 'type' => $4, + 'device' =>$slice->{'device'}.$1 }; + $part->{'label'} = $6 if ($6); + $part->{'size'} = $part->{'blocks'} * + $disk->{'blocksize'}; + $part->{'desc'} = &text('select_part', + uc($disk->{'type'}), + $disk->{'number'}, + $slice->{'number'}, + uc($part->{'letter'})); + next if ($part->{'type'} eq 'unused' && + $part->{'startblock'} == 0); + push(@{$slice->{'parts'}}, $part); + } + } + } + } + +return @rv; +} + +# string_to_size(str) +# Convert a string like 100 Meg to a number in bytes +sub string_to_size +{ +my ($str) = @_; +my ($n, $pfx) = split(/\s+/, $str); +if ($pfx =~ /^b/i) { + return $n; + } +if ($pfx =~ /^k/i) { + return $n * 1024; + } +if ($pfx =~ /^m/i) { + return $n * 1024 * 1024; + } +if ($pfx =~ /^g/i) { + return $n * 1024 * 1024 * 1024; + } +if ($pfx =~ /^t/i) { + return $n * 1024 * 1024 * 1024 * 1024; + } +return undef; +} + +# partition_select(name, value, mode, &found, disk-regexp) +# Returns HTML for a selector for a slice. The mode parameter means : +# 1 = disks +# 2 = disks, slices and partitions +# 3 = slices and partitions +sub partition_select +{ +my ($name, $value, $mode, $found, $diskre) = @_; +my @opts; +my @dlist = &list_disks_partitions(); +foreach my $d (@dlist) { + my $dev = $d->{'device'}; + next if ($diskre && $dev !~ /$diskre/); + if ($mode == 1 || $mode == 2) { + push(@opts, [ $dev, &partition_description($dev) ]); + } + if ($mode >= 2) { + foreach my $s (@{$d->{'slices'}}) { + push(@opts, [ $s->{'device'}, + &partition_description($s->{'device'}) ]); + foreach my $p (@{$s->{'parts'}}) { + push(@opts, [ $p->{'device'}, + &partition_description($p->{'device'}) ]); + } + } + } + } +if ($found && &indexof($value, map { $_->[0] } @opts) >= 0) { + $$found = 1; + } +return &ui_select($name, $value, \@opts); +} + +# partition_description(device) +# Returns a human-readable description for a device name +sub partition_description +{ +my ($dev) = @_; +if ($dev =~ /^\/dev\/([a-z]+)(\d+)$/) { + # A whole disk of some type + return &text('select_device', + $1 eq 'da' ? 'SCSI' : 'IDE', "$2"); + } +elsif ($dev =~ /^\/dev\/([a-z]+)(\d+)[ps](\d+)$/) { + # A slice within a disk + return &text('select_slice', + $1 eq 'da' ? 'SCSI' : 'IDE', "$2", "$3"); + } +elsif ($dev =~ /^\/dev\/([a-z]+)(\d+)[ps](\d+)([a-z])$/) { + # A partition within a slice + return &text('select_part', + $1 eq 'da' ? 'SCSI' : 'IDE', "$2", "$3", uc($4)); + } +else { + # No idea + return $dev; + } +} + +# execute_fdisk_commands(&disk, &commands) +# Run a series of commands on a disk via the fdisk config file +sub execute_fdisk_commands +{ +my ($disk, $cmds) = @_; +my $temp = &transname(); +my $fh = "TEMP"; +&open_tempfile($fh, ">$temp"); +foreach my $c (@$cmds) { + &print_tempfile($fh, $c."\n"); + } +&close_tempfile($fh); +my $out = &backquote_logged("fdisk -f $temp $disk->{'device'} &1"); +my $ex = $?; +&unlink_file($temp); +return $ex ? $out : undef; +} + +# delete_slice(&disk, &slice) +# Delete one slice from a disk +sub delete_slice +{ +my ($disk, $slice) = @_; +if ($disk->{'type'} eq 'gpt') { + return &backquote_logged("gpart delete -i $slice->{'number'} ". + "$disk->{'device'} 2>&1"); + } +return &execute_fdisk_commands($disk, + [ "p $slice->{'number'} 0 0 0" ]); +} + +# create_slice(&disk, &slice) +# Add a slice to a disk +sub create_slice +{ +my ($disk, $slice) = @_; +if ($disk->{'type'} eq 'gpt') { + my $cmd = "gpart add -t $slice->{'type'} -b $slice->{'startblock'} -s ". + "$slice->{'blocks'}"; + $cmd .= " -l $slice->{'label'}" if $slice->{'label'}; + $cmd .= " $disk->{'device'}"; + my $err = &backquote_logged("$cmd 2>&1"); + if (!$err) { + $slice->{'device'} = $disk->{'device'}."p".$slice->{'number'}; + } + return $err; + } +my $type = hex($slice->{'type'}); +my $start = int($slice->{'startblock'} * $disk->{'blocksize'} / 1024); +my $length = int($slice->{'blocks'} * $disk->{'blocksize'} / 1024); +my $err = &execute_fdisk_commands($disk, + [ "p $slice->{'number'} $type ${start}K ${length}K" ]); +if (!$err) { + $slice->{'device'} = $disk->{'device'}."s".$slice->{'number'}; + } +return $err; +} + +# modify_slice(&disk, &old-slice, &slice) +# Apply type or size changes to a slice +sub modify_slice +{ +my ($disk, $oldslice, $slice) = @_; +if ($disk->{'type'} eq 'gpt') { + if ($oldslice->{'type'} ne $slice->{'type'}) { + my $cmd = "gpart modify -i $slice->{'number'} -t $slice->{'type'}"; + $cmd .= " -l $slice->{'label'}" if $slice->{'label'}; + $cmd .= " $disk->{'device'}"; + return &backquote_logged("$cmd 2>&1"); + } + return undef; + } +if ($oldslice->{'type'} ne $slice->{'type'}) { + # Change the type + my $type = hex($slice->{'type'}); + my $start = int(($slice->{'startblock'} * $disk->{'blocksize'}) / 1024); + my $end = int((($slice->{'startblock'} + $slice->{'blocks'}) * + $disk->{'blocksize'}) / 1024); + my $err = &execute_fdisk_commands($disk, + [ "p $slice->{'number'} $type ${start}K ${end}K" ]); + return $err if ($err); + } +if (!$oldslice->{'active'} && $slice->{'active'}) { + # Make active + my $err = &execute_fdisk_commands($disk, + [ "a $slice->{'number'}" ]); + return $err if ($err); + } +return undef; +} + +# initialize_slice(&disk, &slice) +# After a slice is created, put a default label on it +sub initialize_slice +{ +my ($disk, $slice) = @_; +if ($disk->{'type'} eq 'gpt') { + return &backquote_logged("gpart create -s GPT $slice->{'device'} 2>&1"); + } +my $err = &backquote_logged("bsdlabel -w $slice->{'device'}"); +return $? ? $err : undef; +} + +sub list_partition_types +{ +return ( '4.2BSD', 'swap', 'unused', 'vinum', + 'freebsd-ufs', 'freebsd-swap', 'freebsd-zfs', + 'freebsd-boot', 'freebsd-raid', 'freebsd-label' ); +} + +# save_partition(&disk, &slice, &part) +# Create or update a partition on some slice +sub save_partition +{ +my ($disk, $slice, $part) = @_; +if ($disk->{'type'} eq 'gpt') { + my $cmd = "gpart add -t $part->{'type'}"; + $cmd .= " -b $part->{'startblock'}" if $part->{'startblock'}; + $cmd .= " -s $part->{'blocks'}" if $part->{'blocks'}; + $cmd .= " -l $part->{'label'}" if $part->{'label'}; + $cmd .= " " . $slice->{'device'}; + my $err = &backquote_logged("$cmd 2>&1"); + if (!$err) { + $part->{'device'} = $slice->{'device'}.$part->{'letter'}; + } + return $err; + } + +# Edit or add a line in the existing label +my $out = &backquote_command("bsdlabel $slice->{'device'}"); +if ($? && $out =~ /no\s+valid\s+label/) { + # No label at all yet .. initialize + my $err = &initialize_slice($disk, $slice); + return "Failed to create initial disk label : $err" if ($err); + } + +# Edit or add a line in the existing label +my $wantline = " ".$part->{'letter'}.": ".$part->{'blocks'}." ". + $part->{'startblock'}." ".$part->{'type'}; +$wantline .= " " . $part->{'label'} if ($part->{'label'}); + +my @lines = split(/\r?\n/, $out); +my $found = 0; +for(my $i=0; $i<@lines; $i++) { + if ($lines[$i] =~ /^\s+(\S+):/ && $1 eq $part->{'letter'}) { + $lines[$i] = $wantline; + $found++; + last; + } + } +if (!$found) { + push(@lines, $wantline); + } +my $err = &save_partition_lines($slice, \@lines); +if (!$err && !$part->{'device'}) { + $part->{'device'} = $slice->{'device'}.$part->{'letter'}; + } +return $err; +} + +# delete_partition(&disk, &slice, &part) +# Delete a partition on some slice +sub delete_partition +{ +my ($disk, $slice, $part) = @_; + +# Fix up the line for the part being deleted +if ($disk->{'type'} eq 'gpt') { + return &backquote_logged("gpart delete -i $part->{'letter'} $slice->{'device'} 2>&1"); + } +my $out = &backquote_command("bsdlabel $slice->{'device'}"); +my @lines = split(/\r?\n/, $out); +my $found = 0; +for(my $i=0; $i<@lines; $i++) { + if ($lines[$i] =~ /^\s+(\S+):/ && $1 eq $part->{'letter'}) { + splice(@lines, $i, 1); + } + } +return &save_partition_lines($slice, \@lines); +} + +# save_partition_lines(&slice, &lines) +# Feed the given lines to the bsdlabel command to update a slice's partition +# list. Returns undef on success or an error message on failure. +sub save_partition_lines +{ +my ($slice, $lines) = @_; + +# Write to a temp file +my $fh = "TEMP"; +my $temp = &transname(); +&open_tempfile($fh, ">$temp"); +foreach my $l (@$lines) { + &print_tempfile($fh, $l."\n"); + } +&close_tempfile($fh); + +# Apply the new label +my $out = &backquote_logged("bsdlabel -R $slice->{'device'} $temp"); +my $ex = $?; +&unlink_file($temp); +return $ex ? $out : undef; +} + +# create_filesystem(&disk, &slice, &part, &fs-details) +# Creates a new filesystem, and returns undef on success or the error output +# on failure. +sub create_filesystem +{ +my ($disk, $slice, $part, $newfs) = @_; +my $cmd = &get_create_filesystem_command($disk, $slice, $part, $newfs); +my $out = &backquote_logged("$cmd 2>&1 {'free'}) if ($newfs->{'free'} ne ''); +push(@cmd, "-t") if ($newfs->{'trim'}); +push(@cmd, "-L", quotemeta($newfs->{'label'})) if ($newfs->{'label'} ne ''); +push(@cmd, $part ? $part->{'device'} : $slice->{'device'}); +return join(" ", @cmd); +} + +# check_filesystem(&disk, &slice, &part) +# Checks the filesystem on some partition, and returns undef on success or +# the error output on failure. +sub check_filesystem +{ +my ($disk, $slice, $part) = @_; +my $cmd = &get_check_filesystem_command($disk, $slice, $part); +my $out = &backquote_logged("$cmd 2>&1 {'device'} : $slice->{'device'}; +my @cmd = "fsck"; +my @st = &fdisk::device_status($dev); +if (!@st) { + # Assume UFS type + push(@cmd, "-t", "ufs"); + } +push(@cmd, $dev); +return join(" ", @cmd); +} + +# show_filesystem_buttons(hiddens, &status, &part-or-slice) +# Show buttons to create a filesystem on a partition or slice +sub show_filesystem_buttons +{ +my ($hiddens, $st, $object) = @_; +print &ui_buttons_row( + "newfs_form.cgi", $text{'part_newfs'}, $text{'part_newfsdesc'}, + $hiddens); + +if (!@$st || $st->[1] ne 'swap') { + print &ui_buttons_row( + "fsck.cgi", $text{'part_fsck'}, $text{'part_fsckdesc'}, + $hiddens); + } + +if (!@$st) { + if ($object->{'type'} eq 'swap' || $object->{'type'} eq '82') { + print &ui_buttons_row("../mount/edit_mount.cgi", + $text{'part_newmount2'}, $text{'part_mountmsg2'}, + &ui_hidden("newdev", $object->{'device'}). + &ui_hidden("type", "swap")); + } + else { + print &ui_buttons_row("../mount/edit_mount.cgi", + $text{'part_newmount'}, $text{'part_mountmsg'}, + &ui_hidden("newdev", $object->{'device'}). + &ui_hidden("type", "ufs"), + &ui_textbox("newdir", undef, 20)); + } + } +} + +1; diff --git a/bsdfdisk/create_part.cgi b/bsdfdisk/create_part.cgi old mode 100755 new mode 100644 index 6b91d2d13..4e8436b6c --- a/bsdfdisk/create_part.cgi +++ b/bsdfdisk/create_part.cgi @@ -19,7 +19,7 @@ $slice || &error($text{'slice_egone'}); # Validate inputs, starting with slice number my $part = { }; -$in{'letter'} =~ /^[a-d]$/i || &error($text{'npart_eletter'}); +$in{'letter'} =~ /^[a-z]$/i || &error($text{'npart_eletter'}); $in{'letter'} = lc($in{'letter'}); my ($clash) = grep { $_->{'letter'} eq $in{'letter'} } @{$slice->{'parts'}}; $clash && &error(&text('npart_eclash', $in{'letter'})); @@ -29,15 +29,18 @@ $part->{'letter'} = $in{'letter'}; $in{'start'} =~ /^\d+$/ || &error($text{'nslice_estart'}); $in{'end'} =~ /^\d+$/ || &error($text{'nslice_eend'}); $in{'start'} < $in{'end'} || &error($text{'npart_erange'}); -$part->{'startblock'} = $in{'start'}; +$part->{'startblock'} = int($in{'start'}/2048)*2048; # 1MB alignment $part->{'blocks'} = $in{'end'} - $in{'start'}; # Slice type $part->{'type'} = $in{'type'}; +# Set partition properties +$part->{'label'} = $in{'label'} if ($in{'label'} =~ /^[a-zA-Z0-9._-]+$/); # Do the creation &ui_print_header($slice->{'desc'}, $text{'npart_title'}, ""); +# Create the partition print &text('npart_creating', $in{'letter'}, $slice->{'desc'}),"

\n"; my $err = &save_partition($disk, $slice, $part); if ($err) { diff --git a/bsdfdisk/create_slice.cgi b/bsdfdisk/create_slice.cgi old mode 100755 new mode 100644 index b9e7a1961..7194e8b6d --- a/bsdfdisk/create_slice.cgi +++ b/bsdfdisk/create_slice.cgi @@ -26,15 +26,17 @@ $slice->{'number'} = $in{'number'}; $in{'start'} =~ /^\d+$/ || &error($text{'nslice_estart'}); $in{'end'} =~ /^\d+$/ || &error($text{'nslice_eend'}); $in{'start'} < $in{'end'} || &error($text{'nslice_erange'}); -$slice->{'startblock'} = $in{'start'}; +$slice->{'startblock'} = int($in{'start'}/2048)*2048; # Align to 1MB $slice->{'blocks'} = $in{'end'} - $in{'start'}; # Slice type $slice->{'type'} = $in{'type'}; +$slice->{'label'} = $in{'label'} if ($in{'label'} =~ /^[a-zA-Z0-9._-]+$/); # Do the creation &ui_print_header($disk->{'desc'}, $text{'nslice_title'}, ""); +# Create the slice print &text('nslice_creating', $in{'number'}, $disk->{'desc'}),"

\n"; my $err = &create_slice($disk, $slice); if ($err) { diff --git a/bsdfdisk/edit_disk.cgi b/bsdfdisk/edit_disk.cgi old mode 100755 new mode 100644 index 66a94458b..65cbb4f10 --- a/bsdfdisk/edit_disk.cgi +++ b/bsdfdisk/edit_disk.cgi @@ -23,9 +23,9 @@ push(@info, &text('disk_dsize', &nice_size($disk->{'size'}))); if ($disk->{'model'}) { push(@info, &text('disk_model', $disk->{'model'})); } -push(@info, &text('disk_cylinders', $disk->{'cylinders'})); push(@info, &text('disk_blocks', $disk->{'blocks'})); push(@info, &text('disk_device', "$disk->{'device'}")); +push(@info, &text('disk_scheme', uc($disk->{'type'} || "MBR"))); print &ui_links_row(\@info),"

\n"; # Show partitions table @@ -41,6 +41,7 @@ if (@{$disk->{'slices'}}) { $text{'disk_start'}, $text{'disk_end'}, $text{'disk_use'}, + $text{'disk_label'}, ]); foreach my $p (@{$disk->{'slices'}}) { # Create images for the extent @@ -75,6 +76,7 @@ if (@{$disk->{'slices'}}) { $p->{'startblock'} + $p->{'blocks'} - 1, $use ? $use : $n ? &text('disk_scount', $n) : "", + $p->{'label'}, ]); } print &ui_columns_end(); diff --git a/bsdfdisk/edit_part.cgi b/bsdfdisk/edit_part.cgi old mode 100755 new mode 100644 index 87ff74a0b..9850b3981 --- a/bsdfdisk/edit_part.cgi +++ b/bsdfdisk/edit_part.cgi @@ -49,10 +49,14 @@ if ($canedit) { print &ui_table_row($text{'part_type'}, &ui_select("type", $part->{'type'}, [ &list_partition_types() ], 1, 0, 1)); + print &ui_table_row($text{'part_label'}, + &ui_textbox("label", $part->{'label'}, 20)); } else { print &ui_table_row($text{'part_type'}, $part->{'type'}); + print &ui_table_row($text{'part_label'}, + $part->{'label'}); } print &ui_table_row($text{'part_use'}, diff --git a/bsdfdisk/edit_slice.cgi b/bsdfdisk/edit_slice.cgi old mode 100755 new mode 100644 index 3a901154c..4bd3cef50 --- a/bsdfdisk/edit_slice.cgi +++ b/bsdfdisk/edit_slice.cgi @@ -41,16 +41,19 @@ print &ui_table_row($text{'slice_sstart'}, print &ui_table_row($text{'slice_send'}, $slice->{'startblock'} + $slice->{'blocks'} - 1); +# GPT type selection print &ui_table_row($text{'slice_stype'}, &ui_select("type", $slice->{'type'}, - [ sort { $a->[1] cmp $b->[1] } - map { [ $_, &fdisk::tag_name($_) ] } - &fdisk::list_tags() ])); + [ &list_partition_types() ])); print &ui_table_row($text{'slice_sactive'}, $slice->{'active'} ? $text{'yes'} : &ui_yesno_radio("active", $slice->{'active'})); +# Label field +print &ui_table_row($text{'slice_label'}, + &ui_textbox("label", $slice->{'label'}, 20)); +# Usage status print &ui_table_row($text{'slice_suse'}, !@st ? $text{'part_nouse'} : $st[2] ? &text('part_inuse', $use) : @@ -74,6 +77,7 @@ if (@{$slice->{'parts'}}) { $text{'slice_start'}, $text{'slice_end'}, $text{'slice_use'}, + $text{'slice_label'}, ]); foreach my $p (@{$slice->{'parts'}}) { # Create images for the extent @@ -104,6 +108,7 @@ if (@{$slice->{'parts'}}) { $p->{'startblock'}, $p->{'startblock'} + $p->{'blocks'} - 1, $use, + $p->{'label'}, ]); } print &ui_columns_end(); diff --git a/bsdfdisk/fsck.cgi b/bsdfdisk/fsck.cgi old mode 100755 new mode 100644 index b4f6a8b78..0858a6d4f --- a/bsdfdisk/fsck.cgi +++ b/bsdfdisk/fsck.cgi @@ -1,62 +1,62 @@ -#!/usr/local/bin/perl -# Check the filesystem on a partition - -use strict; -use warnings; -no warnings 'redefine'; -no warnings 'uninitialized'; -require './bsdfdisk-lib.pl'; -our (%in, %text, $module_name); -&ReadParse(); -&error_setup($text{'fsck_err'}); - -# Get the disk and slice -my @disks = &list_disks_partitions(); -my ($disk) = grep { $_->{'device'} eq $in{'device'} } @disks; -$disk || &error($text{'disk_egone'}); -my ($slice) = grep { $_->{'number'} eq $in{'slice'} } @{$disk->{'slices'}}; -$slice || &error($text{'slice_egone'}); -my ($object, $part); -if ($in{'part'} ne '') { - ($part) = grep { $_->{'letter'} eq $in{'part'} } - @{$slice->{'parts'}}; - $part || &error($text{'part_egone'}); - $object = $part; - } -else { - $object = $slice; - } - -&ui_print_unbuffered_header($object->{'desc'}, $text{'fsck_title'}, ""); - -# Do the creation -print &text('fsck_checking', "$object->{'device'}"),"
\n"; -print "

\n";
-my $cmd = &get_check_filesystem_command($disk, $slice, $part);
-&additional_log('exec', undef, $cmd);
-my $fh = "CMD";
-&open_execute_command($fh, $cmd, 2);
-while(<$fh>) {
-	print &html_escape($_);
-	}
-close($fh);
-print "
"; -if ($?) { - print $text{'fsck_failed'},"

\n"; - } -else { - print $text{'fsck_done'},"

\n"; - } -&webmin_log("fsck", $in{'part'} ne '' ? "part" : "object", - $object->{'device'}, $object); - -if ($in{'part'} ne '') { - &ui_print_footer("edit_part.cgi?device=$in{'device'}&". - "slice=$in{'slice'}&part=$in{'part'}", - $text{'part_return'}); - } -else { - &ui_print_footer("edit_slice.cgi?device=$in{'device'}&". - "slice=$in{'slice'}", - $text{'slice_return'}); - } +#!/usr/local/bin/perl +# Check the filesystem on a partition + +use strict; +use warnings; +no warnings 'redefine'; +no warnings 'uninitialized'; +require './bsdfdisk-lib.pl'; +our (%in, %text, $module_name); +&ReadParse(); +&error_setup($text{'fsck_err'}); + +# Get the disk and slice +my @disks = &list_disks_partitions(); +my ($disk) = grep { $_->{'device'} eq $in{'device'} } @disks; +$disk || &error($text{'disk_egone'}); +my ($slice) = grep { $_->{'number'} eq $in{'slice'} } @{$disk->{'slices'}}; +$slice || &error($text{'slice_egone'}); +my $object = $slice; + +# Handle partitions if specified +my $part; +if ($in{'part'} ne '') { + ($part) = grep { $_->{'letter'} eq $in{'part'} } + @{$slice->{'parts'}}; + $part || &error($text{'part_egone'}); + $object = $part; + } + +&ui_print_unbuffered_header($object->{'desc'}, $text{'fsck_title'}, ""); + +# Run filesystem check +print &text('fsck_checking', "$object->{'device'}"),"
\n"; +print "

\n";
+my $cmd = &get_check_filesystem_command($disk, $slice, $part);
+&additional_log('exec', undef, $cmd);
+my $fh = "CMD";
+&open_execute_command($fh, $cmd, 2);
+while(<$fh>) {
+	print &html_escape($_);
+	}
+close($fh);
+print "
"; +if ($?) { + print $text{'fsck_failed'},"

\n"; + } +else { + print $text{'fsck_done'},"

\n"; + } +&webmin_log("fsck", $in{'part'} ne '' ? "part" : "object", + $object->{'device'}, $object); + +if ($in{'part'} ne '') { + &ui_print_footer("edit_part.cgi?device=$in{'device'}&". + "slice=$in{'slice'}&part=$in{'part'}", + $text{'part_return'}); + } +else { + &ui_print_footer("edit_slice.cgi?device=$in{'device'}&". + "slice=$in{'slice'}", + $text{'slice_return'}); + } diff --git a/bsdfdisk/index.cgi b/bsdfdisk/index.cgi old mode 100755 new mode 100644 index 589e62ee2..25f8e5866 --- a/bsdfdisk/index.cgi +++ b/bsdfdisk/index.cgi @@ -1,41 +1,43 @@ -#!/usr/local/bin/perl -# Show a list of disks - -use strict; -use warnings; -no warnings 'redefine'; -no warnings 'uninitialized'; -require './bsdfdisk-lib.pl'; -our (%in, %text, %config, $module_name); - -&ui_print_header(undef, $text{'index_title'}, "", "intro", 1, 1, 0, - &help_search_link("fdisk", "man")); - -my $err = &check_fdisk(); -if ($err) { - &ui_print_endpage(&text('index_problem', $err)); - } - -my @disks = &list_disks_partitions(); -@disks = sort { $a->{'device'} cmp $b->{'device'} } @disks; -if (@disks) { - print &ui_columns_start([ $text{'index_dname'}, - $text{'index_dsize'}, - $text{'index_dmodel'}, - $text{'index_dparts'} ]); - foreach my $d (@disks) { - print &ui_columns_row([ - "".&partition_description($d->{'device'})."", - &nice_size($d->{'size'}), - $d->{'model'}, - scalar(@{$d->{'slices'}}), - ]); - } - print &ui_columns_end(); - } -else { - print "$text{'index_none'}

\n"; - } - -&ui_print_footer("/", $text{'index'}); +#!/usr/local/bin/perl +# Show a list of disks + +use strict; +use warnings; +no warnings 'redefine'; +no warnings 'uninitialized'; +require './bsdfdisk-lib.pl'; +our (%in, %text, %config, $module_name); + +&ui_print_header(undef, $text{'index_title'}, "", "intro", 1, 1, 0, + &has_command('gpart') ? &help_search_link("gpart", "man") : + &help_search_link("fdisk", "man")); + +my $err = &check_fdisk(); +if ($err) { + &ui_print_endpage(&text('index_problem', $err)); + } + +my @disks = &list_disks_partitions(); +@disks = sort { $a->{'device'} cmp $b->{'device'} } @disks; +if (@disks) { + print &ui_columns_start([ $text{'index_dname'}, + $text{'index_dsize'}, + $text{'index_dmodel'}, + $text{'index_dparts'} ]); + foreach my $d (@disks) { + print &ui_columns_row([ + "".&partition_description($d->{'device'})."", + &nice_size($d->{'size'}), + $d->{'model'}, + scalar(@{$d->{'slices'}}), + uc($d->{'type'}), + ]); + } + print &ui_columns_end(); + } +else { + print "$text{'index_none'}

\n"; + } + +&ui_print_footer("/", $text{'index'}); diff --git a/bsdfdisk/log_parser.pl b/bsdfdisk/log_parser.pl old mode 100755 new mode 100644 index b49bd5cca..af17b2b94 --- a/bsdfdisk/log_parser.pl +++ b/bsdfdisk/log_parser.pl @@ -8,10 +8,15 @@ do 'bsdfdisk-lib.pl'; sub parse_webmin_log { my ($user, $script, $action, $type, $object, $p) = @_; -if ($type eq "slice" || $type eq "part") { +if ($type eq "slice" || $type eq "part" || $type eq "object") { return &text('log_'.$action.'_'.$type, "".&html_escape($object).""); } +if ($type eq "disk") { + return &text('log_'.$action.'_disk', + "".&html_escape($object).""); + } return undef; } +1; diff --git a/bsdfdisk/newfs.cgi b/bsdfdisk/newfs.cgi old mode 100755 new mode 100644 index 384030035..24de506ef --- a/bsdfdisk/newfs.cgi +++ b/bsdfdisk/newfs.cgi @@ -1,72 +1,72 @@ -#!/usr/local/bin/perl -# Create a filesystem on a partition - -use strict; -use warnings; -no warnings 'redefine'; -no warnings 'uninitialized'; -require './bsdfdisk-lib.pl'; -our (%in, %text, $module_name); -&ReadParse(); -&error_setup($text{'newfs_err'}); - -# Get the disk and slice -my @disks = &list_disks_partitions(); -my ($disk) = grep { $_->{'device'} eq $in{'device'} } @disks; -$disk || &error($text{'disk_egone'}); -my ($slice) = grep { $_->{'number'} eq $in{'slice'} } @{$disk->{'slices'}}; -$slice || &error($text{'slice_egone'}); -my ($object, $part); -if ($in{'part'} ne '') { - ($part) = grep { $_->{'letter'} eq $in{'part'} } - @{$slice->{'parts'}}; - $part || &error($text{'part_egone'}); - $object = $part; - } -else { - $object = $slice; - } - -# Validate inputs -my $newfs = { }; -$in{'free_def'} || $in{'free'} =~ /^\d+$/ && $in{'free'} <= 100 || - &error($text{'newfs_efree'}); -$newfs->{'free'} = $in{'free_def'} ? undef : $in{'free'}; -$newfs->{'trim'} = $in{'trim'}; -$in{'label_def'} || $in{'label'} =~ /^\S+$/ || - &error($text{'newfs_elabel'}); -$newfs->{'label'} = $in{'label_def'} ? undef : $in{'label'}; - -&ui_print_unbuffered_header($object->{'desc'}, $text{'newfs_title'}, ""); - -# Do the creation -print &text('newfs_creating', "$object->{'device'}"),"
\n"; -print "

\n";
-my $cmd = &get_create_filesystem_command($disk, $slice, $part, $newfs);
-&additional_log('exec', undef, $cmd);
-my $fh = "CMD";
-&open_execute_command($fh, $cmd, 2);
-while(<$fh>) {
-	print &html_escape($_);
-	}
-close($fh);
-print "
"; -if ($?) { - print $text{'newfs_failed'},"

\n"; - } -else { - print $text{'newfs_done'},"

\n"; - &webmin_log("newfs", $in{'part'} ne '' ? "part" : "object", - $object->{'device'}, $object); - } - -if ($in{'part'} ne '') { - &ui_print_footer("edit_part.cgi?device=$in{'device'}&". - "slice=$in{'slice'}&part=$in{'part'}", - $text{'part_return'}); - } -else { - &ui_print_footer("edit_slice.cgi?device=$in{'device'}&". - "slice=$in{'slice'}", - $text{'slice_return'}); - } +#!/usr/local/bin/perl +# Create a filesystem on a partition + +use strict; +use warnings; +no warnings 'redefine'; +no warnings 'uninitialized'; +require './bsdfdisk-lib.pl'; +our (%in, %text, $module_name); +&ReadParse(); +&error_setup($text{'newfs_err'}); + +# Get the disk and slice +my @disks = &list_disks_partitions(); +my ($disk) = grep { $_->{'device'} eq $in{'device'} } @disks; +$disk || &error($text{'disk_egone'}); +my ($slice) = grep { $_->{'number'} eq $in{'slice'} } @{$disk->{'slices'}}; +$slice || &error($text{'slice_egone'}); +my $object = $slice; + +# Handle partitions if specified +my $part; +if ($in{'part'} ne '') { + ($part) = grep { $_->{'letter'} eq $in{'part'} } + @{$slice->{'parts'}}; + $part || &error($text{'part_egone'}); + $object = $part; + } + +# Validate inputs +my $newfs = { }; +$in{'free_def'} || $in{'free'} =~ /^\d+$/ && $in{'free'} <= 100 || + &error($text{'newfs_efree'}); +$newfs->{'free'} = $in{'free_def'} ? undef : $in{'free'}; +$newfs->{'trim'} = $in{'trim'}; +$in{'label_def'} || $in{'label'} =~ /^\S+$/ || + &error($text{'newfs_elabel'}); +$newfs->{'label'} = $in{'label_def'} ? undef : $in{'label'}; + +&ui_print_unbuffered_header($object->{'desc'}, $text{'newfs_title'}, ""); + +# Create the filesystem +print &text('newfs_creating', "$object->{'device'}"),"
\n"; +print "

\n";
+my $cmd = &get_create_filesystem_command($disk, $slice, $part, $newfs);
+&additional_log('exec', undef, $cmd);
+my $fh = "CMD";
+&open_execute_command($fh, $cmd, 2);
+while(<$fh>) {
+	print &html_escape($_);
+	}
+close($fh);
+print "
"; +if ($?) { + print $text{'newfs_failed'},"

\n"; + } +else { + print $text{'newfs_done'},"

\n"; + &webmin_log("newfs", $in{'part'} ne '' ? "part" : "object", + $object->{'device'}, $object); + } + +if ($in{'part'} ne '') { + &ui_print_footer("edit_part.cgi?device=$in{'device'}&". + "slice=$in{'slice'}&part=$in{'part'}", + $text{'part_return'}); + } +else { + &ui_print_footer("edit_slice.cgi?device=$in{'device'}&". + "slice=$in{'slice'}", + $text{'slice_return'}); + } diff --git a/bsdfdisk/newfs_form.cgi b/bsdfdisk/newfs_form.cgi old mode 100755 new mode 100644 index 7466a2448..66b422578 --- a/bsdfdisk/newfs_form.cgi +++ b/bsdfdisk/newfs_form.cgi @@ -9,22 +9,20 @@ require './bsdfdisk-lib.pl'; our (%in, %text, $module_name); &ReadParse(); -# Get the disk and slice +# Get the disk and partition details my @disks = &list_disks_partitions(); my ($disk) = grep { $_->{'device'} eq $in{'device'} } @disks; $disk || &error($text{'disk_egone'}); my ($slice) = grep { $_->{'number'} eq $in{'slice'} } @{$disk->{'slices'}}; $slice || &error($text{'slice_egone'}); -my $object; +my $object = $slice; + if ($in{'part'} ne '') { my ($part) = grep { $_->{'letter'} eq $in{'part'} } @{$slice->{'parts'}}; $part || &error($text{'part_egone'}); $object = $part; } -else { - $object = $slice; - } &ui_print_header($object->{'desc'}, $text{'newfs_title'}, ""); @@ -35,16 +33,20 @@ print &ui_hidden("part", $in{'part'}); print &ui_table_start($text{'newfs_header'}, undef, 2); print &ui_table_row($text{'part_device'}, - "$object->{'device'}"); + "$object->{'device'}") if ($object->{'device'}); +# Free blocks percentage print &ui_table_row($text{'newfs_free'}, - &ui_opt_textbox("free", undef, 4, $text{'newfs_deffree'})."%"); + &ui_opt_textbox("free", undef, 4, $text{'newfs_free_def'}, + $text{'newfs_free_pc'})." %"); +# Enable TRIM support print &ui_table_row($text{'newfs_trim'}, &ui_yesno_radio("trim", 0)); +# Filesystem label print &ui_table_row($text{'newfs_label'}, - &ui_opt_textbox("label", undef, 20, $text{'newfs_none'})); + &ui_opt_textbox("label", undef, 20, $text{'newfs_label_def'})); print &ui_table_end(); print &ui_form_end([ [ undef, $text{'newfs_create'} ] ]); diff --git a/bsdfdisk/part_form.cgi b/bsdfdisk/part_form.cgi old mode 100755 new mode 100644 index f6eb6fefe..d90f40b6b --- a/bsdfdisk/part_form.cgi +++ b/bsdfdisk/part_form.cgi @@ -32,11 +32,11 @@ while($used{$l}) { print &ui_table_row($text{'npart_letter'}, &ui_textbox("letter", $l, 4)); -# Slice size in blocks +# Available space in blocks print &ui_table_row($text{'npart_diskblocks'}, $slice->{'blocks'}); -# Start and end blocks (defaults to last part) +# Start and end blocks calculation my ($start, $end) = (0, $slice->{'blocks'}); foreach my $p (sort { $a->{'startblock'} cmp $b->{'startblock'} } @{$slice->{'parts'}}) { @@ -47,11 +47,15 @@ print &ui_table_row($text{'nslice_start'}, print &ui_table_row($text{'nslice_end'}, &ui_textbox("end", $end, 10)); -# Partition type +# Partition type selection print &ui_table_row($text{'npart_type'}, - &ui_select("type", '4.2BSD', + &ui_select("type", 'freebsd-ufs', [ &list_partition_types() ])); +# Partition label (optional) +print &ui_table_row($text{'npart_label'}, + &ui_textbox("label", "", 20)); + print &ui_table_end(); print &ui_form_end([ [ undef, $text{'create'} ] ]); diff --git a/bsdfdisk/save_part.cgi b/bsdfdisk/save_part.cgi old mode 100755 new mode 100644 index fda89d07b..adf3bae34 --- a/bsdfdisk/save_part.cgi +++ b/bsdfdisk/save_part.cgi @@ -26,9 +26,19 @@ if (@st && $st[2]) { &error(&text('part_esave', $use)); } -# Make the change +# Update partition properties $part->{'type'} = $in{'type'}; -my $err = &save_partition($disk, $slice, $part); +my $err; +if (defined($in{'label'})) { + my $oldpart = { %$part }; + $part->{'label'} = $in{'label'} if defined($in{'label'}); + # Apply changes using gpart + $err = &modify_partition($disk, $slice, $oldpart, $part); + } +else { + $err = &save_partition($disk, $slice, $part); + } + &error($err) if ($err); &webmin_log("modify", "part", $part->{'device'}, $part); diff --git a/bsdfdisk/save_slice.cgi b/bsdfdisk/save_slice.cgi old mode 100755 new mode 100644 index 69cbda19f..c3533a693 --- a/bsdfdisk/save_slice.cgi +++ b/bsdfdisk/save_slice.cgi @@ -8,7 +8,7 @@ no warnings 'uninitialized'; require './bsdfdisk-lib.pl'; our (%in, %text, $module_name); &ReadParse(); -&error_setup($text{'slice_err'}); +&error_setup($text{'save_err'}); # Get the disk and slice my @disks = &list_disks_partitions(); @@ -17,14 +17,24 @@ $disk || &error($text{'disk_egone'}); my ($slice) = grep { $_->{'number'} eq $in{'slice'} } @{$disk->{'slices'}}; $slice || &error($text{'slice_egone'}); -# Apply changes -my $oldslice = { %$slice }; -$slice->{'type'} = $in{'type'}; -if (!$slice->{'active'}) { - $slice->{'active'} = $in{'active'}; +if ($in{'delete'}) { + # Delete the slice + my $err = &delete_slice($disk, $slice); + &error($err) if ($err); + &webmin_log("delete", "slice", $slice->{'device'}, $slice); + } +else { + # Validate inputs + $in{'type'} =~ /^\S+$/ || &error($text{'save_etype'}); + $in{'label'} =~ /^[a-zA-Z0-9._-]+$/ || &error($text{'save_elabel'}); + + # Update the slice + my $oldslice = { %$slice }; + $slice->{'type'} = $in{'type'}; + $slice->{'label'} = $in{'label'}; + my $err = &modify_slice($disk, $oldslice, $slice); + &error($err) if ($err); + &webmin_log("modify", "slice", $slice->{'device'}, $slice); } -my $err = &modify_slice($disk, $oldslice, $slice); -&error($err) if ($err); -&webmin_log("modify", "slice", $slice->{'device'}, $slice); &redirect("edit_disk.cgi?device=$in{'device'}"); diff --git a/bsdfdisk/slice_form.cgi b/bsdfdisk/slice_form.cgi old mode 100755 new mode 100644 index 904310e43..cdab779d7 --- a/bsdfdisk/slice_form.cgi +++ b/bsdfdisk/slice_form.cgi @@ -34,8 +34,8 @@ print &ui_table_row($text{'nslice_diskblocks'}, $disk->{'blocks'}); # Start and end blocks (defaults to last slice+1) -my ($start, $end) = (63, $disk->{'blocks'}); -foreach my $s (sort { $a->{'startblock'} cmp $b->{'startblock'} } +my ($start, $end) = (2048, $disk->{'blocks'}); +foreach my $s (sort { $a->{'startblock'} <=> $b->{'startblock'} } @{$disk->{'slices'}}) { $start = $s->{'startblock'} + $s->{'blocks'} + 1; } @@ -44,14 +44,16 @@ print &ui_table_row($text{'nslice_start'}, print &ui_table_row($text{'nslice_end'}, &ui_textbox("end", $end, 10)); -# Slice type +# GPT partition type print &ui_table_row($text{'nslice_type'}, - &ui_select("type", 'a5', - [ sort { $a->[1] cmp $b->[1] } - map { [ $_, &fdisk::tag_name($_) ] } - &fdisk::list_tags() ])); + &ui_select("type", 'freebsd-ufs', + [ &list_partition_types() ])); -# Also create partition? +# Partition label +print &ui_table_row($text{'nslice_label'}, + &ui_textbox("label", "", 20)); + +# Create filesystem option print &ui_table_row($text{'nslice_makepart'}, &ui_yesno_radio("makepart", 1));