mirror of
https://github.com/webmin/webmin.git
synced 2026-02-11 17:44:28 +00:00
1228 lines
33 KiB
Perl
1228 lines
33 KiB
Perl
# fdisk-lib.pl
|
|
# Functions for disk management under linux
|
|
|
|
do '../web-lib.pl';
|
|
&init_config();
|
|
do '../ui-lib.pl';
|
|
&foreign_require("mount", "mount-lib.pl");
|
|
if (&foreign_check("raid")) {
|
|
&foreign_require("raid", "raid-lib.pl");
|
|
$raid_module++;
|
|
}
|
|
if (&foreign_check("lvm")) {
|
|
&foreign_require("lvm", "lvm-lib.pl");
|
|
$lvm_module++;
|
|
}
|
|
&foreign_require("proc", "proc-lib.pl");
|
|
%access = &get_module_acl();
|
|
$has_e2label = &has_command("e2label");
|
|
$has_xfs_db = &has_command("xfs_db");
|
|
$has_volid = &has_command("vol_id");
|
|
$has_reiserfstune = &has_command("reiserfstune");
|
|
$| = 1;
|
|
|
|
# list_disks_partitions([include-cds])
|
|
# Returns a structure containing the details of all disks and partitions
|
|
sub list_disks_partitions
|
|
{
|
|
if (defined(@list_disks_partitions_cache)) {
|
|
return @list_disks_partitions_cache;
|
|
}
|
|
|
|
local (@pscsi, @dscsi, $dscsi_mode);
|
|
if (-r "/proc/scsi/sg/devices" && -r "/proc/scsi/sg/device_strs") {
|
|
# Get device info from various /proc/scsi files
|
|
open(DEVICES, "/proc/scsi/sg/devices");
|
|
while(<DEVICES>) {
|
|
s/\r|\n//g;
|
|
local @l = split(/\t+/, $_);
|
|
push(@dscsi, { 'host' => $l[0],
|
|
'bus' => $l[1],
|
|
'target' => $l[2],
|
|
'lun' => $l[3],
|
|
'type' => $l[4] });
|
|
}
|
|
close(DEVICES);
|
|
local $i = 0;
|
|
open(DEVNAMES, "/proc/scsi/sg/device_strs");
|
|
while(<DEVNAMES>) {
|
|
s/\r|\n//g;
|
|
local @l = split(/\t+/, $_);
|
|
$dscsi[$i]->{'make'} = $l[0];
|
|
$dscsi[$i]->{'model'} = $l[1];
|
|
$i++;
|
|
}
|
|
close(DEVNAMES);
|
|
$dscsi_mode = 1;
|
|
@dscsi = grep { $_->{'type'} == 0 } @dscsi;
|
|
}
|
|
else {
|
|
# Check /proc/scsi/scsi for SCSI disk models
|
|
open(SCSI, "/proc/scsi/scsi");
|
|
local @lines = <SCSI>;
|
|
close(SCSI);
|
|
if ($lines[0] =~ /^Attached\s+domains/i) {
|
|
# New domains format
|
|
local $dscsi;
|
|
foreach (@lines) {
|
|
s/\s/ /g;
|
|
if (/Device:\s+(.*)(sd[a-z]+)\s+usage/) {
|
|
$dscsi = { 'dev' => $2 };
|
|
push(@dscsi, $dscsi);
|
|
}
|
|
elsif (/Device:/) {
|
|
$dscsi = undef;
|
|
}
|
|
elsif (/Vendor:\s+(\S+)\s+Model:\s+(\S+)/ && $dscsi) {
|
|
$dscsi->{'make'} = $1;
|
|
$dscsi->{'model'} = $2;
|
|
}
|
|
elsif (/Host:\s+scsi(\d+)\s+Channel:\s+(\d+)\s+Id:\s+(\d+)\s+Lun:\s+(\d+)/ && $dscsi) {
|
|
$dscsi->{'host'} = $1;
|
|
$dscsi->{'bus'} = $2;
|
|
$dscsi->{'target'} = $3;
|
|
$dscsi->{'lun'} = $4;
|
|
}
|
|
}
|
|
$dscsi_mode = 1;
|
|
}
|
|
else {
|
|
# Standard format
|
|
foreach (@lines) {
|
|
s/\s/ /g;
|
|
if (/^Host:/) {
|
|
push(@pscsi, $_);
|
|
}
|
|
elsif (/^\s+\S/ && @pscsi) {
|
|
$pscsi[$#pscsi] .= $_;
|
|
}
|
|
}
|
|
@pscsi = grep { /Type:\s+Direct-Access/i } @pscsi;
|
|
$dscsi_mode = 0;
|
|
}
|
|
}
|
|
|
|
local (@disks, @devs, $d);
|
|
if (open(PARTS, "/proc/partitions")) {
|
|
# The list of all disks can come from the kernel
|
|
local $sc = 0;
|
|
while(<PARTS>) {
|
|
if (/\d+\s+\d+\s+\d+\s+sd([a-z]+)\s/ ||
|
|
/\d+\s+\d+\s+\d+\s+(scsi\/host(\d+)\/bus(\d+)\/target(\d+)\/lun(\d+)\/disc)\s+/) {
|
|
# New or old style SCSI device
|
|
local $d = $1;
|
|
local ($host, $bus, $target, $lun) = ($2, $3, $4, $5);
|
|
if (!$dscsi_mode && $pscsi[$sc] =~ /USB-FDU/) {
|
|
# USB floppy with scsi emulation!
|
|
splice(@pscsi, $sc, 1);
|
|
next;
|
|
}
|
|
if ($host ne '') {
|
|
local $scsidev = "/dev/$d";
|
|
if (!-r $scsidev) {
|
|
push(@devs, "/dev/".
|
|
&number_to_device("sd", $sc));
|
|
}
|
|
else {
|
|
push(@devs, $scsidev);
|
|
}
|
|
}
|
|
else {
|
|
push(@devs, "/dev/sd$d");
|
|
}
|
|
$sc++;
|
|
}
|
|
elsif (/\d+\s+\d+\s+\d+\s+hd([a-z]+)\s/) {
|
|
# IDE disk (but skip CDs)
|
|
local $n = $1;
|
|
if (open(MEDIA, "/proc/ide/hd$n/media")) {
|
|
local $media = <MEDIA>;
|
|
close(MEDIA);
|
|
if ($media =~ /^disk/ && !$_[0]) {
|
|
push(@devs, "/dev/hd$n");
|
|
}
|
|
}
|
|
}
|
|
elsif (/\d+\s+\d+\s+\d+\s+(ide\/host(\d+)\/bus(\d+)\/target(\d+)\/lun(\d+)\/disc)\s+/) {
|
|
# New-style IDE disk
|
|
local $idedev = "/dev/$1";
|
|
local ($host, $bus, $target, $lun) = ($2, $3, $4, $5);
|
|
if (!-r $idedev) {
|
|
push(@devs, "/dev/".
|
|
&hbt_to_device($host, $bus, $target));
|
|
}
|
|
else {
|
|
push(@devs, "/dev/$1");
|
|
}
|
|
}
|
|
elsif (/\d+\s+\d+\s+\d+\s+(rd\/c(\d+)d\d+)\s/) {
|
|
# Mylex raid device
|
|
push(@devs, "/dev/$1");
|
|
}
|
|
elsif (/\d+\s+\d+\s+\d+\s+(ida\/c(\d+)d\d+)\s/) {
|
|
# Compaq raid device
|
|
push(@devs, "/dev/$1");
|
|
}
|
|
elsif (/\d+\s+\d+\s+\d+\s+(cciss\/c(\d+)d\d+)\s/) {
|
|
# Compaq Smart Array RAID
|
|
push(@devs, "/dev/$1");
|
|
}
|
|
elsif (/\d+\s+\d+\s+\d+\s+(ataraid\/disc(\d+)\/disc)\s+/) {
|
|
# Promise raid controller
|
|
push(@devs, "/dev/$1");
|
|
}
|
|
}
|
|
close(PARTS);
|
|
@devs = sort { ($b =~ /\/hd[a-z]+$/ ? 1 : 0) <=>
|
|
($a =~ /\/hd[a-z]+$/ ? 1 : 0) } @devs;
|
|
}
|
|
|
|
# Skip cd-rom drive, identified from symlink. Don't do this if we can identify
|
|
# cds by their media type though
|
|
if (!-d "/proc/ide") {
|
|
local @cdstat = stat("/dev/cdrom");
|
|
if (@cdstat && !$_[0]) {
|
|
@devs = grep { (stat($_))[1] != $cdstat[1] } @devs;
|
|
}
|
|
}
|
|
|
|
# Call fdisk to get partition and geometry information
|
|
local $devs = join(" ", @devs);
|
|
local ($disk, $m2);
|
|
open(FDISK, "fdisk -l $devs 2>/dev/null |");
|
|
while(<FDISK>) {
|
|
if (/Disk\s+([^ :]+):\s+(\d+)\s+\S+\s+(\d+)\s+\S+\s+(\d+)/ ||
|
|
($m2 = ($_ =~ /Disk\s+([^ :]+):\s+(.*)\s+bytes/))) {
|
|
# New disk section
|
|
if ($m2) {
|
|
$disk = { 'device' => $1,
|
|
'prefix' => $1 };
|
|
<FDISK> =~ /(\d+)\s+\S+\s+(\d+)\s+\S+\s+(\d+)/ || next;
|
|
$disk->{'heads'} = $1;
|
|
$disk->{'sectors'} = $2;
|
|
$disk->{'cylinders'} = $3;
|
|
}
|
|
else {
|
|
$disk = { 'device' => $1,
|
|
'prefix' => $1,
|
|
'heads' => $2,
|
|
'sectors' => $3,
|
|
'cylinders' => $4 };
|
|
}
|
|
$disk->{'index'} = scalar(@disks);
|
|
$disk->{'parts'} = [ ];
|
|
local @st = stat($disk->{'device'});
|
|
next if (@cdstat && $st[1] == $cdstat[1]);
|
|
if ($disk->{'device'} =~ /\/sd([a-z]+)$/) {
|
|
# Old-style SCSI disk
|
|
$disk->{'desc'} = &text('select_device', 'SCSI',uc($1));
|
|
local ($dscsi) = grep { $_->{'dev'} eq "sd$1" } @dscsi;
|
|
$disk->{'scsi'} = $dscsi ? &indexof($dscsi, @dscsi)
|
|
: ord(uc($1))-65;
|
|
$disk->{'type'} = 'scsi';
|
|
}
|
|
elsif ($disk->{'device'} =~ /\/hd([a-z]+)$/) {
|
|
# IDE disk
|
|
$disk->{'desc'} = &text('select_device', 'IDE', uc($1));
|
|
$disk->{'type'} = 'ide';
|
|
}
|
|
elsif ($disk->{'device'} =~ /\/(scsi\/host(\d+)\/bus(\d+)\/target(\d+)\/lun(\d+)\/disc)/) {
|
|
# New complete SCSI disk specification
|
|
$disk->{'host'} = $2;
|
|
$disk->{'bus'} = $3;
|
|
$disk->{'target'} = $4;
|
|
$disk->{'lun'} = $5;
|
|
$disk->{'desc'} = &text('select_scsi',
|
|
"$2", "$3", "$4", "$5");
|
|
|
|
# Work out the SCSI index for this disk
|
|
local $j;
|
|
if ($dscsi_mode) {
|
|
for($j=0; $j<@dscsi; $j++) {
|
|
if ($dscsi[$j]->{'host'} == $disk->{'host'} && $dscsi[$j]->{'bus'} == $disk->{'bus'} && $dscsi[$j]->{'target'} == $disk->{'target'} && $dscsi[$j]->{'lnun'} == $disk->{'lun'}) {
|
|
$disk->{'scsi'} = $j;
|
|
last;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
for($j=0; $j<@pscsi; $j++) {
|
|
if ($pscsi[$j] =~ /Host:\s+scsi(\d+).*Id:\s+(\d+)/i && $disk->{'host'} == $1 && $disk->{'target'} == $2) {
|
|
$disk->{'scsi'} = $j;
|
|
last;
|
|
}
|
|
}
|
|
}
|
|
$disk->{'type'} = 'scsi';
|
|
$disk->{'prefix'} =~ s/disc$/part/g;
|
|
}
|
|
elsif ($disk->{'device'} =~ /\/(ide\/host(\d+)\/bus(\d+)\/target(\d+)\/lun(\d+)\/disc)/) {
|
|
# New-style IDE specification
|
|
$disk->{'host'} = $2;
|
|
$disk->{'bus'} = $3;
|
|
$disk->{'target'} = $4;
|
|
$disk->{'lun'} = $5;
|
|
$disk->{'desc'} = &text('select_newide',
|
|
"$2", "$3", "$4", "$5");
|
|
$disk->{'type'} = 'ide';
|
|
$disk->{'prefix'} =~ s/disc$/part/g;
|
|
}
|
|
elsif ($disk->{'device'} =~ /\/(rd\/c(\d+)d(\d+))/) {
|
|
# Mylex raid device
|
|
local ($mc, $md) = ($2, $3);
|
|
$disk->{'desc'} = &text('select_mylex', $mc, $md);
|
|
open(RD, "/proc/rd/c$mc/current_status");
|
|
while(<RD>) {
|
|
if (/^Configuring\s+(.*)/i) {
|
|
$disk->{'model'} = $1;
|
|
}
|
|
elsif (/\s+(\S+):\s+([^, ]+)/ &&
|
|
$1 eq $disk->{'device'}) {
|
|
$disk->{'raid'} = $2;
|
|
}
|
|
}
|
|
close(RD);
|
|
$disk->{'type'} = 'raid';
|
|
$disk->{'prefix'} = $disk->{'device'}.'p';
|
|
}
|
|
elsif ($disk->{'device'} =~ /\/(ida\/c(\d+)d(\d+))/) {
|
|
# Compaq RAID device
|
|
local ($ic, $id) = ($2, $3);
|
|
$disk->{'desc'} = &text('select_cpq', $ic, $id);
|
|
open(IDA, -d "/proc/driver/array" ? "/proc/driver/array/ida$ic" : "/proc/driver/cpqarray/ida$ic");
|
|
while(<IDA>) {
|
|
if (/^(\S+):\s+(.*)/ && $1 eq "ida$ic") {
|
|
$disk->{'model'} = $2;
|
|
}
|
|
}
|
|
close(IDA);
|
|
$disk->{'type'} = 'raid';
|
|
$disk->{'prefix'} = $disk->{'device'}.'p';
|
|
}
|
|
elsif ($disk->{'device'} =~ /\/(cciss\/c(\d+)d(\d+))/) {
|
|
# Compaq Smart Array RAID
|
|
local ($ic, $id) = ($2, $3);
|
|
$disk->{'desc'} = &text('select_smart', $ic, $id);
|
|
open(CCI, "/proc/driver/cciss/cciss$ic");
|
|
while(<CCI>) {
|
|
if (/^\s*(\S+):\s*(.*)/ && $1 eq "cciss$ic") {
|
|
$disk->{'model'} = $2;
|
|
}
|
|
}
|
|
close(CCI);
|
|
$disk->{'type'} = 'raid';
|
|
$disk->{'prefix'} = $disk->{'device'}.'p';
|
|
}
|
|
elsif ($disk->{'device'} =~ /\/(ataraid\/disc(\d+)\/disc)/) {
|
|
# Promise RAID controller
|
|
local $dd = $2;
|
|
$disk->{'desc'} = &text('select_promise', $dd);
|
|
$disk->{'type'} = 'raid';
|
|
$disk->{'prefix'} =~ s/disc$/part/g;
|
|
}
|
|
push(@disks, $disk);
|
|
}
|
|
elsif (/^Units\s+=\s+cylinders\s+of\s+(\d+)\s+\*\s+(\d+)/) {
|
|
# Unit size for disk
|
|
$disk->{'bytes'} = $2;
|
|
$disk->{'cylsize'} = $disk->{'heads'} * $disk->{'sectors'} *
|
|
$disk->{'bytes'};
|
|
}
|
|
elsif (/(\/dev\/\S+?(\d+))[ \t*]+\d+\s+(\d+)\s+(\d+)\s+(\S+)\s+(\S{1,2})\s+(.*)/ || /(\/dev\/\S+?(\d+))[ \t*]+(\d+)\s+(\d+)\s+(\S+)\s+(\S{1,2})\s+(.*)/) {
|
|
# Partition within the current disk
|
|
local $part = { 'number' => $2,
|
|
'device' => $1,
|
|
'type' => $6,
|
|
'start' => $3,
|
|
'end' => $4,
|
|
'blocks' => int($5),
|
|
'extended' => $6 eq '5' || $6 eq 'f' ? 1 : 0,
|
|
'index' => scalar(@{$disk->{'parts'}}) };
|
|
$part->{'desc'} =
|
|
$part->{'device'} =~ /(.)d(\S)(\d+)$/ ?
|
|
&text('select_part', $1 eq 's' ? 'SCSI' : 'IDE', uc($2), "$3") :
|
|
$part->{'device'} =~ /scsi\/host(\d+)\/bus(\d+)\/target(\d+)\/lun(\d+)\/part(\d+)/ ?
|
|
&text('select_spart', "$1", "$2", "$3", "$4", "$5") :
|
|
$part->{'device'} =~ /ide\/host(\d+)\/bus(\d+)\/target(\d+)\/lun(\d+)\/part(\d+)/ ?
|
|
&text('select_snewide', "$1", "$2", "$3", "$4", "$5") :
|
|
$part->{'device'} =~ /rd\/c(\d+)d(\d+)p(\d+)$/ ?
|
|
&text('select_mpart', "$1", "$2", "$3") :
|
|
$part->{'device'} =~ /ida\/c(\d+)d(\d+)p(\d+)$/ ?
|
|
&text('select_cpart', "$1", "$2", "$3") :
|
|
$part->{'device'} =~ /cciss\/c(\d+)d(\d+)p(\d+)$/ ?
|
|
&text('select_smartpart', "$1", "$2", "$3") :
|
|
$part->{'device'} =~ /ataraid\/disc(\d+)\/part(\d+)$/ ?
|
|
&text('select_ppart', "$1", "$2") :
|
|
"???",
|
|
push(@{$disk->{'parts'}}, $part);
|
|
}
|
|
}
|
|
close(FDISK);
|
|
|
|
# Check /proc/ide for IDE disk models
|
|
foreach $d (@disks) {
|
|
if ($d->{'type'} eq 'ide') {
|
|
local $short;
|
|
if (defined($d->{'host'})) {
|
|
$short = &hbt_to_device($d->{'host'},
|
|
$d->{'bus'},
|
|
$d->{'target'});
|
|
}
|
|
else {
|
|
$short = $d->{'device'};
|
|
$short =~ s/^.*\///g;
|
|
}
|
|
if (open(MODEL, "/proc/ide/$short/model")) {
|
|
($d->{'model'} = <MODEL>) =~ s/\r|\n//g;
|
|
close(MODEL);
|
|
}
|
|
if (open(MEDIA, "/proc/ide/$short/media")) {
|
|
($d->{'media'} = <MEDIA>) =~ s/\r|\n//g;
|
|
close(MEDIA);
|
|
}
|
|
}
|
|
}
|
|
|
|
# Fill in SCSI information
|
|
foreach $d (@disks) {
|
|
if ($d->{'type'} eq 'scsi') {
|
|
local $s = $d->{'scsi'};
|
|
if ($dscsi_mode) {
|
|
# From other scsi files
|
|
$d->{'model'} = "$dscsi[$s]->{'make'} $dscsi[$s]->{'model'}";
|
|
$d->{'controller'} = $dscsi[$s]->{'host'};
|
|
$d->{'scsiid'} = $dscsi[$s]->{'target'};
|
|
}
|
|
else {
|
|
# From /proc/scsi/scsi lines
|
|
if ($pscsi[$s] =~ /Vendor:\s+(\S+).*Model:\s+(.*)\s+Rev:/i) {
|
|
$d->{'model'} = "$1 $2";
|
|
}
|
|
if ($pscsi[$s] =~ /Host:\s+scsi(\d+).*Id:\s+(\d+)/i) {
|
|
$d->{'controller'} = int($1);
|
|
$d->{'scsiid'} = int($2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@list_disks_partitions_cache = @disks;
|
|
return @disks;
|
|
}
|
|
|
|
# hbt_to_device(host, bus, target)
|
|
# Converts an IDE device specified as a host, bus and target to an hdX device
|
|
sub hbt_to_device
|
|
{
|
|
local ($host, $bus, $target) = @_;
|
|
local $num = $host*4 + $bus*2 + $target;
|
|
return &number_to_device("hd", $num);
|
|
}
|
|
|
|
# number_to_device(suffix, number)
|
|
sub number_to_device
|
|
{
|
|
local ($suffix, $num) = @_;
|
|
if ($num < 26) {
|
|
# Just a single letter
|
|
return $suffix.(('a' .. 'z')[$num]);
|
|
}
|
|
else {
|
|
# Two-letter format
|
|
local $first = int($num / 26);
|
|
local $second = $num % 26;
|
|
return $suffix.(('a' .. 'z')[$first]).(('a' .. 'z')[$second]);
|
|
}
|
|
}
|
|
|
|
# change_type(disk, partition, type)
|
|
# Changes the type of an existing partition
|
|
sub change_type
|
|
{
|
|
&open_fdisk("$_[0]");
|
|
&wprint("t\n");
|
|
local $rv = &wait_for($fh, 'Partition.*:', 'Selected partition');
|
|
&wprint("$_[1]\n") if ($rv == 0);
|
|
&wait_for($fh, 'Hex.*:');
|
|
&wprint("$_[2]\n");
|
|
&wait_for($fh, 'Command.*:');
|
|
&wprint("w\n"); sleep(1);
|
|
&close_fdisk();
|
|
undef(@list_disks_partitions_cache);
|
|
}
|
|
|
|
# delete_partition(disk, partition)
|
|
# Delete an existing partition
|
|
sub delete_partition
|
|
{
|
|
&open_fdisk("$_[0]");
|
|
&wprint("d\n");
|
|
local $rv = &wait_for($fh, 'Partition.*:', 'Selected partition');
|
|
&wprint("$_[1]\n") if ($rv == 0);
|
|
&wait_for($fh, 'Command.*:');
|
|
&wprint("w\n");
|
|
&wait_for($fh, 'Syncing'); sleep(3);
|
|
&close_fdisk();
|
|
undef(@list_disks_partitions_cache);
|
|
}
|
|
|
|
# create_partition(disk, partition, start, end, type)
|
|
# Create a new partition with the given extent and type
|
|
sub create_partition
|
|
{
|
|
&open_fdisk("$_[0]");
|
|
&wprint("n\n");
|
|
local $wf = &wait_for($fh, 'primary.*\r\n', 'First.*:');
|
|
if ($_[1] > 4) {
|
|
&wprint("l\n");
|
|
}
|
|
else {
|
|
&wprint("p\n");
|
|
local $wf2 = &wait_for($fh, 'Partition.*:', 'Selected partition');
|
|
&wprint("$_[1]\n") if ($wf2 == 0);
|
|
}
|
|
&wait_for($fh, 'First.*:') if ($wf != 1);
|
|
&wprint("$_[2]\n");
|
|
&wait_for($fh, 'Last.*:');
|
|
&wprint("$_[3]\n");
|
|
&wait_for($fh, 'Command.*:');
|
|
|
|
&wprint("t\n");
|
|
local $rv = &wait_for($fh, 'Partition.*:', 'Selected partition');
|
|
&wprint("$_[1]\n") if ($rv == 0);
|
|
&wait_for($fh, 'Hex.*:');
|
|
&wprint("$_[4]\n");
|
|
&wait_for($fh, 'Command.*:');
|
|
&wprint("w\n");
|
|
&wait_for($fh, 'Syncing'); sleep(3);
|
|
&close_fdisk();
|
|
undef(@list_disks_partitions_cache);
|
|
}
|
|
|
|
# create_extended(disk, partition, start, end)
|
|
sub create_extended
|
|
{
|
|
&open_fdisk("$_[0]");
|
|
&wprint("n\n");
|
|
&wait_for($fh, 'primary.*\r\n');
|
|
&wprint("e\n");
|
|
&wait_for($fh, 'Partition.*:');
|
|
&wprint("$_[1]\n");
|
|
&wait_for($fh, 'First.*:');
|
|
&wprint("$_[2]\n");
|
|
&wait_for($fh, 'Last.*:');
|
|
&wprint("$_[3]\n");
|
|
&wait_for($fh, 'Command.*:');
|
|
|
|
&wprint("w\n");
|
|
&wait_for($fh, 'Syncing'); sleep(3);
|
|
&close_fdisk();
|
|
undef(@list_disks_partitions_cache);
|
|
}
|
|
|
|
# list_tags()
|
|
# Returns a list of known partition tag numbers
|
|
sub list_tags
|
|
{
|
|
return sort { hex($a) <=> hex($b) } (keys %tags);
|
|
}
|
|
|
|
# tag_name(tag)
|
|
# Returns a human-readable version of a tag
|
|
sub tag_name
|
|
{
|
|
return $tags{$_[0]} ? $tags{$_[0]}
|
|
: $hidden_tags{$_[0]};
|
|
}
|
|
|
|
# conv_type(tag)
|
|
# Given a partition tag, returns the filesystem type (assuming it is supported)
|
|
sub conv_type
|
|
{
|
|
local @rv;
|
|
if ($_[0] eq "4" || $_[0] eq "6" ||
|
|
$_[0] eq "1" || $_[0] eq "e") { @rv = ( "msdos" ); }
|
|
elsif ($_[0] eq "b" || $_[0] eq "c") { @rv = ( "vfat" ); }
|
|
elsif ($_[0] eq "83") { @rv = ( "ext2", "ext3" ); }
|
|
elsif ($_[0] eq "82") { @rv = ( "swap" ); }
|
|
elsif ($_[0] eq "81") { @rv = ( "minix" ); }
|
|
else { return ( ); }
|
|
local %supp = map { $_, 1 } &mount::list_fstypes();
|
|
@rv = grep { $supp{$_} } @rv;
|
|
return wantarray ? @rv : $rv[0];
|
|
}
|
|
|
|
# fstype_name(type)
|
|
# Returns a readable name for a filesystem type
|
|
sub fstype_name
|
|
{
|
|
return $text{"fs_".$_[0]};
|
|
}
|
|
|
|
sub mkfs_options
|
|
{
|
|
if ($_[0] eq "ext2") {
|
|
&opt_input("ext2_b", $text{'bytes'}, 1);
|
|
&opt_input("ext2_f", $text{'bytes'}, 0);
|
|
&opt_input("ext2_i", "", 1);
|
|
&opt_input("ext2_m", "%", 0);
|
|
&opt_input("ext2_g", "", 1);
|
|
print "<td align=right><b>$text{'ext2_c'}</b></td>\n";
|
|
print "<td><input type=radio name=ext2_c value=1> $text{'yes'}\n";
|
|
print "<input type=radio name=ext2_c value=0 checked> $text{'no'}",
|
|
"</td> </tr>\n";
|
|
}
|
|
elsif ($_[0] eq "msdos" || $_[0] eq "vfat") {
|
|
&opt_input("msdos_ff", "", 1);
|
|
print "<td align=right><b>$text{'msdos_F'}</b></td>\n";
|
|
print "<td>",&ui_select("msdos_F", undef,
|
|
[ [ undef, $text{'default'} ],
|
|
[ 12 ], [ 16 ], [ 32 ],
|
|
[ "*", $text{'msdos_F_other'} ] ])," ",
|
|
&ui_textbox("msdos_F_other", undef, 4),"</td> </tr>\n";
|
|
&opt_input("msdos_i", "", 1);
|
|
&opt_input("msdos_n", "", 0);
|
|
&opt_input("msdos_r", "", 1);
|
|
&opt_input("msdos_s", "sectors", 0);
|
|
print "<tr> <td align=right><b>$text{'msdos_c'}</b></td>\n";
|
|
print "<td><input type=radio name=msdos_c value=1> $text{'yes'}\n";
|
|
print "<input type=radio name=msdos_c value=0 checked> $text{'no'}",
|
|
"</td> </tr>\n";
|
|
}
|
|
elsif ($_[0] eq "minix") {
|
|
&opt_input("minix_n", "", 1);
|
|
&opt_input("minix_i", "", 0);
|
|
&opt_input("minix_b", "", 1);
|
|
print "<td align=right><b>$text{'minix_c'}</b></td>\n";
|
|
print "<td><input type=radio name=msdos_c value=1> $text{'yes'}\n";
|
|
print "<input type=radio name=msdos_c value=0 checked> $text{'no'}",
|
|
"</td> </tr>\n";
|
|
}
|
|
elsif ($_[0] eq "reiserfs") {
|
|
print "<tr> <td><b>$text{'reiserfs_force'}</b></td>\n";
|
|
print "<td><input type=radio name=reiserfs_f value=1> $text{'yes'}\n";
|
|
print "<input type=radio name=reiserfs_f value=0 checked> ",
|
|
"$text{'no'}</td>\n";
|
|
|
|
print "<td><b>$text{'reiserfs_hash'}</b></td>\n";
|
|
print "<td><select name=reiserfs_h>\n";
|
|
print "<option value='' checked>$text{'default'}\n";
|
|
print "<option>rupasov\n";
|
|
print "<option>tea\n";
|
|
print "</select></td> </tr>\n";
|
|
}
|
|
elsif ($_[0] eq "ext3") {
|
|
&opt_input("ext2_b", $text{'bytes'}, 1);
|
|
&opt_input("ext2_f", $text{'bytes'}, 0);
|
|
&opt_input("ext2_i", "", 1);
|
|
&opt_input("ext2_m", "%", 0);
|
|
&opt_input("ext3_j", "MB", 1);
|
|
print "<td align=right><b>$text{'ext2_c'}</b></td>\n";
|
|
print "<td><input type=radio name=ext2_c value=1> $text{'yes'}\n";
|
|
print "<input type=radio name=ext2_c value=0 checked> $text{'no'}",
|
|
"</td> </tr>\n";
|
|
}
|
|
elsif ($_[0] eq "xfs") {
|
|
print "<tr> <td><b>$text{'xfs_force'}</b></td>\n";
|
|
print "<td><input type=radio name=xfs_f value=1> $text{'yes'}\n";
|
|
print "<input type=radio name=xfs_f value=0 checked> ",
|
|
"$text{'no'}</td>\n";
|
|
|
|
&opt_input("xfs_b", $text{'bytes'}, 0);
|
|
}
|
|
elsif ($_[0] eq "jfs") {
|
|
&opt_input("jfs_s", $text{'megabytes'}, 1);
|
|
print "<td align=right><b>$text{'jfs_c'}</b></td>\n";
|
|
print "<td><input type=radio name=jfs_c value=1> $text{'yes'}\n";
|
|
print "<input type=radio name=jfs_c value=0 checked> $text{'no'}",
|
|
"</td> </tr>\n";
|
|
}
|
|
elsif ($_[0] eq "fatx") {
|
|
# Has no options!
|
|
print "<tr> <td colspan=4>$text{'fatx_none'}</td> </tr>\n";
|
|
}
|
|
}
|
|
|
|
# mkfs_parse(type, device)
|
|
# Returns a command to build a new filesystem of the given type on the
|
|
# given device. Options are taken from %in.
|
|
sub mkfs_parse
|
|
{
|
|
local($cmd);
|
|
if ($_[0] eq "ext2") {
|
|
$cmd = "mkfs -t ext2";
|
|
$cmd .= &opt_check("ext2_b", '\d+', "-b");
|
|
$cmd .= &opt_check("ext2_f", '\d+', "-f");
|
|
$cmd .= &opt_check("ext2_i", '\d{4,}', "-i");
|
|
$cmd .= &opt_check("ext2_m", '\d+', "-m");
|
|
$cmd .= &opt_check("ext2_g", '\d+', "-g");
|
|
$cmd .= $in{'ext2_c'} ? " -c" : "";
|
|
$cmd .= " $_[1]";
|
|
}
|
|
elsif ($_[0] eq "msdos" || $_[0] eq "vfat") {
|
|
$cmd = "mkfs -t $_[0]";
|
|
$cmd .= &opt_check("msdos_ff", '[1-2]', "-f");
|
|
if ($in{'msdos_F'} eq '*') {
|
|
$in{'msdos_F_other'} =~ /^\d+$/ ||
|
|
&error(&text('opt_error', $in{'msdos_F_other'},
|
|
$text{'msdos_F'}));
|
|
$cmd .= " -F ".$in{'msdos_F_other'};
|
|
}
|
|
elsif ($in{'msdos_F'}) {
|
|
$cmd .= " -F ".$in{'msdos_F'};
|
|
}
|
|
$cmd .= &opt_check("msdos_i", '[0-9a-f]{8}', "-i");
|
|
$cmd .= &opt_check("msdos_n", '\S{1,11}', "-n");
|
|
$cmd .= &opt_check("msdos_r", '\d+', "-r");
|
|
$cmd .= &opt_check("msdos_s", '\d+', "-s");
|
|
$cmd .= $in{'msdos_c'} ? " -c" : "";
|
|
$cmd .= " $_[1]";
|
|
}
|
|
elsif ($_[0] eq "minix") {
|
|
local(@plist, $disk, $part, $i, @pinfo);
|
|
$cmd = "mkfs -t minix";
|
|
$cmd .= &opt_check("minix_n", '14|30', "-n ");
|
|
$cmd .= &opt_check("minix_i", '\d+', "-i ");
|
|
$cmd .= $in{'minix_c'} ? " -c" : "";
|
|
$cmd .= &opt_check("minix_b", '\d+', " ");
|
|
$cmd .= " $_[1]";
|
|
}
|
|
elsif ($_[0] eq "reiserfs") {
|
|
$cmd = "yes | mkreiserfs";
|
|
$cmd .= " -f" if ($in{'reiserfs_f'});
|
|
$cmd .= " -h $in{'reiserfs_h'}" if ($in{'reiserfs_h'});
|
|
$cmd .= " $_[1]";
|
|
}
|
|
elsif ($_[0] eq "ext3") {
|
|
if (&has_command("mkfs.ext3")) {
|
|
$cmd = "mkfs -t ext3";
|
|
$cmd .= &opt_check("ext3_j", '\d+', "-j");
|
|
}
|
|
elsif (&has_command("mke3fs")) {
|
|
$cmd = "mke3fs";
|
|
$cmd .= &opt_check("ext3_j", '\d+', "-j");
|
|
}
|
|
else {
|
|
$cmd = "mkfs.ext2 -j";
|
|
if (!$in{'ext3_j_def'}) {
|
|
$in{'ext3_j'} =~ /^\d+$/ ||
|
|
&error(&text('opt_error', $in{'ext3_j'},
|
|
$text{'ext3_j'}));
|
|
$cmd .= " -J size=$in{'ext3_j'}";
|
|
}
|
|
}
|
|
$cmd .= &opt_check("ext2_b", '\d+', "-b");
|
|
$cmd .= &opt_check("ext2_f", '\d+', "-f");
|
|
$cmd .= &opt_check("ext2_i", '\d{4,}', "-i");
|
|
$cmd .= &opt_check("ext2_m", '\d+', "-m");
|
|
$cmd .= $in{'ext2_c'} ? " -c" : "";
|
|
$cmd .= " $_[1]";
|
|
}
|
|
elsif ($_[0] eq "xfs") {
|
|
$cmd = "mkfs -t $_[0]";
|
|
$cmd .= " -f" if ($in{'xfs_f'});
|
|
$cmd .= " -b size=$in{'xfs_b'}" if (!$in{'xfs_b_def'});
|
|
$cmd .= " $_[1]";
|
|
}
|
|
elsif ($_[0] eq "jfs") {
|
|
$cmd = "mkfs -t $_[0] -q";
|
|
$cmd .= &opt_check("jfs_s", '\d+', "-s");
|
|
$cmd .= " -c" if ($in{'jfs_c'});
|
|
$cmd .= " $_[1]";
|
|
}
|
|
elsif ($_[0] eq "fatx") {
|
|
$cmd = "mkfs -t $_[0] $_[1]";
|
|
}
|
|
return $cmd;
|
|
}
|
|
|
|
# can_tune(type)
|
|
# Returns 1 if this filesystem type can be tuned
|
|
sub can_tune
|
|
{
|
|
return $_[0] eq "ext2" || $_[0] eq "ext3";
|
|
}
|
|
|
|
# tunefs_options(type)
|
|
# Output HTML for tuning options for some filesystem type
|
|
sub tunefs_options
|
|
{
|
|
if ($_[0] eq "ext2" || $_[0] eq "ext3") {
|
|
&opt_input("tunefs_c", "", 1);
|
|
|
|
print "<td align=right><b>$text{'tunefs_e'}</b></td> <td>\n";
|
|
print "<input type=radio name=tunefs_e_def value=1 checked> ",
|
|
"$text{'opt_default'}\n";
|
|
print " <input type=radio name=tunefs_e_def value=0>\n";
|
|
print "<select name=tunefs_e>\n";
|
|
print "<option value=continue> $text{'tunefs_continue'}\n";
|
|
print "<option value=remount-ro> $text{'tunefs_remount'}\n";
|
|
print "<option value=panic> $text{'tunefs_panic'}\n";
|
|
print "</select></td> </tr>\n";
|
|
|
|
print "<tr> <td align=right><b>$text{'tunefs_u'}</b></td> <td>\n";
|
|
print "<input type=radio name=tunefs_u_def value=1 checked> ",
|
|
"$text{'opt_default'}\n";
|
|
print " <input type=radio name=tunefs_u_def value=0>\n";
|
|
print "<input name=tunefs_u size=8> ",
|
|
&user_chooser_button("tunefs_u", 0),"</td>\n";
|
|
|
|
print "<td align=right><b>$text{'tunefs_g'}</b></td> <td>\n";
|
|
print "<input type=radio name=tunefs_g_def value=1 checked> ",
|
|
"$text{'opt_default'}\n";
|
|
print " <input type=radio name=tunefs_g_def value=0>\n";
|
|
print "<input name=tunefs_g size=8> ",
|
|
&group_chooser_button("tunefs_g", 0),"</td> </tr>\n";
|
|
|
|
&opt_input("tunefs_m", "%", 1);
|
|
$tsel = "<select name=tunefs_i_unit>\n".
|
|
"<option value=d> $text{'tunefs_days'}\n".
|
|
"<option value=w> $text{'tunefs_weeks'}\n".
|
|
"<option value=m> $text{'tunefs_months'}\n".
|
|
"</select>\n";
|
|
&opt_input("tunefs_i", $tsel, 0);
|
|
}
|
|
}
|
|
|
|
# tunefs_parse(type, device)
|
|
# Returns the tuning command based on user inputs
|
|
sub tunefs_parse
|
|
{
|
|
if ($_[0] eq "ext2" || $_[0] eq "ext3") {
|
|
$cmd = "tune2fs";
|
|
$cmd .= &opt_check("tunefs_c", '\d+', "-c");
|
|
$cmd .= $in{'tunefs_e_def'} ? "" : " -e$in{'tunefs_e'}";
|
|
$cmd .= $in{'tunefs_u_def'} ? "" : " -u".getpwnam($in{'tunefs_u'});
|
|
$cmd .= $in{'tunefs_g_def'} ? "" : " -g".getgrnam($in{'tunefs_g'});
|
|
$cmd .= &opt_check("tunefs_m",'\d+',"-m");
|
|
$cmd .= &opt_check("tunefs_i", '\d+', "-i").
|
|
($in{'tunefs_i_def'} ? "" : $in{'tunefs_i_unit'});
|
|
$cmd .= " $_[1]";
|
|
}
|
|
return $cmd;
|
|
}
|
|
|
|
# need_reboot(disk)
|
|
# Returns 1 if a reboot is needed after changing the partitions on some disk
|
|
sub need_reboot
|
|
{
|
|
local $un = `uname -r`;
|
|
return $un =~ /^2\.0\./ || $un =~ /^1\./ || $un =~ /^0\./;
|
|
}
|
|
|
|
# device_status(device)
|
|
# Returns an array of directory, type, mounted
|
|
sub device_status
|
|
{
|
|
@mounted = &foreign_call("mount", "list_mounted") if (!@mounted);
|
|
@mounts = &foreign_call("mount", "list_mounts") if (!@mounts);
|
|
local $label = &get_label($_[0]);
|
|
local $volid = &get_volid($_[0]);
|
|
|
|
local ($mounted) = grep { &same_file($_->[1], $_[0]) ||
|
|
$_->[1] eq "LABEL=$label" ||
|
|
$_->[1] eq "UUID=$volid" } @mounted;
|
|
local ($mount) = grep { &same_file($_->[1], $_[0]) ||
|
|
$_->[1] eq "LABEL=$label" ||
|
|
$_->[1] eq "UUID=$volid" } @mounts;
|
|
if ($mounted) { return ($mounted->[0], $mounted->[2], 1,
|
|
&indexof($mount, @mounts),
|
|
&indexof($mounted, @mounted)); }
|
|
elsif ($mount) { return ($mount->[0], $mount->[2], 0,
|
|
&indexof($mount, @mounts)); }
|
|
if ($raid_module) {
|
|
$raidconf = &foreign_call("raid", "get_raidtab") if (!$raidconf);
|
|
foreach $c (@$raidconf) {
|
|
foreach $d (&raid::find_value('device', $c->{'members'})) {
|
|
return ( $c->{'value'}, "raid", 1 ) if ($d eq $_[0]);
|
|
}
|
|
}
|
|
}
|
|
if ($lvm_module) {
|
|
if (!defined(@physical_volumes)) {
|
|
@physical_volumes = ();
|
|
foreach $vg (&foreign_call("lvm", "list_volume_groups")) {
|
|
push(@physical_volumes,
|
|
&foreign_call("lvm", "list_physical_volumes",
|
|
$vg->{'name'}));
|
|
}
|
|
}
|
|
foreach $pv (@physical_volumes) {
|
|
return ( $pv->{'vg'}, "lvm", 1)
|
|
if ($pv->{'device'} eq $_[0]);
|
|
}
|
|
}
|
|
return ();
|
|
}
|
|
|
|
# can_fsck(type)
|
|
# Returns 1 if some filesystem type can fsck'd
|
|
sub can_fsck
|
|
{
|
|
return ($_[0] eq "ext2" && &has_command("fsck.ext2") ||
|
|
$_[0] eq "ext3" && &has_command("fsck.ext3") ||
|
|
$_[0] eq "minix" && &has_command("fsck.minix"));
|
|
}
|
|
|
|
# fsck_command(type, device)
|
|
# Returns the fsck command to unconditionally check a filesystem
|
|
sub fsck_command
|
|
{
|
|
if ($_[0] eq "ext2" || $_[0] eq "ext3") {
|
|
return "fsck -t $_[0] -p $_[1]";
|
|
}
|
|
elsif ($_[0] eq "minix") {
|
|
return "fsck -t minix -a $_[1]";
|
|
}
|
|
}
|
|
|
|
# fsck_error(code)
|
|
# Returns a description of an exit code from fsck
|
|
sub fsck_error
|
|
{
|
|
return $text{"fsck_err$_[0]"} ? $text{"fsck_err$_[0]"}
|
|
: &text("fsck_unknown", $_[0]);
|
|
}
|
|
|
|
# partition_select(name, value, mode, [&found], [disk_regexp])
|
|
# Returns HTML for selecting a disk or partition
|
|
# mode 0 = floppies and disk partitions
|
|
# 1 = disks
|
|
# 2 = floppies and disks and disk partitions
|
|
# 3 = disk partitions
|
|
sub partition_select
|
|
{
|
|
local $rv = "<select name=$_[0]>\n";
|
|
local ($found, $d, $p);
|
|
if ($_[2] == 0 || $_[2] == 2) {
|
|
$rv .= sprintf "<option %s value=/dev/fd0>%s\n",
|
|
$_[1] eq "/dev/fd0" ? "selected" : "",
|
|
&text('select_fd', 0) if (!$_[4] || "/dev/fd0" =~ /$_[4]/);
|
|
$rv .= sprintf "<option %s value=/dev/fd1>%s\n",
|
|
$_[1] eq "/dev/fd1" ? "selected" : "",
|
|
&text('select_fd', 1) if (!$_[4] || "/dev/fd1" =~ /$_[4]/);
|
|
$found++ if ($_[1] =~ /^\/dev\/fd[01]$/);
|
|
}
|
|
local @dlist = &list_disks_partitions();
|
|
foreach $d (@dlist) {
|
|
local $dev = $d->{'device'};
|
|
next if ($_[4] && $dev !~ /$_[4]/);
|
|
if ($_[2] == 1 || $_[2] == 2) {
|
|
local $name = $d->{'desc'};
|
|
$name .= " ($d->{'model'})" if ($d->{'model'});
|
|
$rv .= sprintf "<option value=%s %s>%s\n",
|
|
$dev, $_[1] eq $dev ? "selected" : "", $name;
|
|
$found++ if ($dev eq $_[1]);
|
|
}
|
|
if ($_[2] == 0 || $_[2] == 2 || $_[2] == 3) {
|
|
foreach $p (@{$d->{'parts'}}) {
|
|
next if ($p->{'extended'});
|
|
local $name = $p->{'desc'};
|
|
$name .= " (".&tag_name($p->{'type'}).")"
|
|
if (&tag_name($p->{'type'}));
|
|
$rv .= sprintf "<option %s value=%s>%s\n",
|
|
$_[1] eq $p->{'device'} ? "selected" : "",
|
|
$p->{'device'}, $name;
|
|
$found++ if ($_[1] eq $p->{'device'});
|
|
}
|
|
}
|
|
}
|
|
if (!$found && $_[1] && !$_[3]) {
|
|
$rv .= "<option selected>$_[1]\n";
|
|
}
|
|
if ($_[3]) {
|
|
${$_[3]} = $found;
|
|
}
|
|
$rv .= "</select>\n";
|
|
return $rv;
|
|
}
|
|
|
|
# label_select(name, value, &found)
|
|
# Returns HTML for selecting a filesystem label
|
|
sub label_select
|
|
{
|
|
local $rv = "<select name=$_[0]>\n";
|
|
local @dlist = &list_disks_partitions();
|
|
local $any;
|
|
foreach $d (@dlist) {
|
|
local $dev = $d->{'device'};
|
|
foreach $p (@{$d->{'parts'}}) {
|
|
next if ($p->{'type'} ne '83');
|
|
local $label = &get_label($p->{'device'});
|
|
next if (!$label);
|
|
$rv .= sprintf "<option %s value=%s>%s (%s)\n",
|
|
$_[1] eq $label ? "selected" : "",
|
|
$label, $label, $p->{'desc'};
|
|
${$_[2]}++ if ($_[1] eq $label);
|
|
$any++;
|
|
}
|
|
}
|
|
if (!$found && $_[1] && !$_[2]) {
|
|
$rv .= "<option selected>$_[1]\n";
|
|
}
|
|
$rv .= "</select>\n";
|
|
return $any ? $rv : undef;
|
|
}
|
|
|
|
# volid_select(name, value, &found)
|
|
# Returns HTML for selecting a filesystem UUID
|
|
sub volid_select
|
|
{
|
|
local ($name, $value, $found) = @_;
|
|
local @dlist = &list_disks_partitions();
|
|
local @opts;
|
|
foreach my $d (@dlist) {
|
|
local $dev = $d->{'device'};
|
|
foreach $p (@{$d->{'parts'}}) {
|
|
next if ($p->{'type'} ne '83' && $p->{'type'} ne '82' &&
|
|
$p->{'type'} ne 'b' && $p->{'type'} ne 'c');
|
|
local $volid = &get_volid($p->{'device'});
|
|
next if (!$volid);
|
|
push(@opts, [ $volid, "$volid ($p->{'desc'})" ]);
|
|
$$found++ if ($value eq $volid);
|
|
}
|
|
}
|
|
if (@opts) {
|
|
return &ui_select($name, $value, \@opts, 1, 0, $value ? 1 : 0);
|
|
}
|
|
else {
|
|
return undef;
|
|
}
|
|
}
|
|
|
|
#############################################################################
|
|
# Internal functions
|
|
#############################################################################
|
|
sub open_fdisk
|
|
{
|
|
local $fpath = &check_fdisk();
|
|
($fh, $fpid) = &foreign_call("proc", "pty_process_exec", join(" ",$fpath, @_));
|
|
}
|
|
|
|
sub open_sfdisk
|
|
{
|
|
local $sfpath = &has_command("sfdisk");
|
|
($fh, $fpid) = &foreign_call("proc", "pty_process_exec", join(" ",$sfpath, @_));
|
|
}
|
|
|
|
sub check_fdisk
|
|
{
|
|
local $fpath = &has_command("fdisk");
|
|
&error(&text('open_error', "<tt>fdisk</tt>")) if (!$fpath);
|
|
return $fpath;
|
|
}
|
|
|
|
sub close_fdisk
|
|
{
|
|
close($fh); kill('TERM', $fpid);
|
|
}
|
|
|
|
sub wprint
|
|
{
|
|
syswrite($fh, $_[0], length($_[0]));
|
|
}
|
|
|
|
sub opt_input
|
|
{
|
|
print $_[2] ? "<tr>" : "";
|
|
print "<td align=right><b>$text{$_[0]}</b></td>\n";
|
|
print "<td nowrap><input type=radio name=$_[0]_def value=1 checked> ",
|
|
$text{'opt_default'},"\n";
|
|
print " <input type=radio name=$_[0]_def value=0>\n";
|
|
print "<input name=$_[0] size=6> $_[1]</td>";
|
|
print $_[2] ? "\n" : "</tr>\n";
|
|
}
|
|
|
|
sub opt_check
|
|
{
|
|
if ($in{"$_[0]_def"}) { return ""; }
|
|
elsif ($in{$_[0]} !~ /^$_[1]$/) {
|
|
&error(&text('opt_error', $in{$_[0]}, $text{$_[0]}));
|
|
}
|
|
else { return " $_[2] $in{$_[0]}"; }
|
|
}
|
|
|
|
%tags = ('0', 'Empty',
|
|
'1', 'FAT12',
|
|
'2', 'XENIX root',
|
|
'3', 'XENIX usr',
|
|
'4', 'FAT16 <32M',
|
|
'6', 'FAT16',
|
|
'7', 'NTFS',
|
|
'8', 'AIX',
|
|
'9', 'AIX bootable',
|
|
'a', 'OS/2 boot manager',
|
|
'b', 'Win95 FAT32',
|
|
'c', 'Win95 FAT32 LBA',
|
|
'e', 'Win95 FAT16 LBA',
|
|
'10', 'OPUS',
|
|
'11', 'Hidden FAT12',
|
|
'12', 'Compaq diagnostic',
|
|
'14', 'Hidden FAT16 < 32M',
|
|
'16', 'Hidden FAT16',
|
|
'17', 'Hidden NTFS',
|
|
'18', 'AST Windows swapfile',
|
|
'1b', 'Hidden Win95 FAT (1b)',
|
|
'1c', 'Hidden Win95 FAT (1c)',
|
|
'1e', 'Hidden Win95 FAT (1e)',
|
|
'24', 'NEC DOS',
|
|
'3c', 'PartitionMagic recovery',
|
|
'40', 'Venix 80286',
|
|
'41', 'PPC PReP boot',
|
|
'42', 'SFS',
|
|
'4d', 'QNX 4.x',
|
|
'4e', 'QNX 4.x 2nd partition',
|
|
'4f', 'QNX 4.x 3rd partition',
|
|
'50', 'OnTrack DM',
|
|
'51', 'OnTrack DM6 Aux1',
|
|
'52', 'CP/M',
|
|
'53', 'OnTrack DM6 Aux3',
|
|
'54', 'OnTrack DM6',
|
|
'55', 'EZ-Drive',
|
|
'56', 'Golden Bow',
|
|
'5c', 'Priam Edisk',
|
|
'61', 'SpeedStor',
|
|
'63', 'GNU HURD or SysV',
|
|
'64', 'Novell Netware 286',
|
|
'65', 'Novell Netware 386',
|
|
'70', 'DiskSecure Multi-Boot',
|
|
'75', 'PC/IX',
|
|
'80', 'Old Minix',
|
|
'81', 'Minix / Old Linux / Solaris',
|
|
'82', 'Linux swap',
|
|
'83', 'Linux',
|
|
'84', 'OS/2 hidden C: drive',
|
|
'85', 'Linux extended',
|
|
'86', 'NTFS volume set (86)',
|
|
'87', 'NTFS volume set (87)',
|
|
'8e', 'Linux LVM',
|
|
'93', 'Amoeba',
|
|
'94', 'Amoeba BBT',
|
|
'a0', 'IBM Thinkpad hibernation',
|
|
'a5', 'BSD/386',
|
|
'a6', 'OpenBSD',
|
|
'a7', 'NeXTSTEP',
|
|
'b7', 'BSDI filesystem',
|
|
'b8', 'BSDI swap',
|
|
'c1', 'DRDOS/sec FAT12',
|
|
'c4', 'DRDOS/sec FAT16 <32M',
|
|
'c6', 'DRDOS/sec FAT16',
|
|
'c7', 'Syrinx',
|
|
'db', 'CP/M / CTOS',
|
|
'e1', 'DOS access',
|
|
'e3', 'DOS read-only',
|
|
'e4', 'SpeedStor',
|
|
'eb', 'BeOS',
|
|
'f1', 'SpeedStor',
|
|
'f4', 'SpeedStor large partition',
|
|
'f2', 'DOS secondary',
|
|
'fd', 'Linux RAID',
|
|
'fe', 'LANstep',
|
|
'ff', 'BBT'
|
|
);
|
|
|
|
%hidden_tags = (
|
|
'5', 'Extended',
|
|
'f', 'Win95 extended LBA',
|
|
);
|
|
|
|
@space_type = ( '1', '4', '5', '6', 'b', 'c', 'e', '83' );
|
|
|
|
# can_edit_disk(device)
|
|
sub can_edit_disk
|
|
{
|
|
foreach (split(/\s+/, $access{'disks'})) {
|
|
return 1 if ($_ eq "*" || $_ eq $_[0]);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
# disk_space(device, [mountpoint])
|
|
# Returns the amount of total and free space for some filesystem, or an
|
|
# empty array if not appropriate.
|
|
sub disk_space
|
|
{
|
|
local $w = $_[1] || $_[0];
|
|
local $out = `df -k '$w'`;
|
|
if ($out =~ /Mounted on\s*\n\s*\S+\s+(\S+)\s+\S+\s+(\S+)/i) {
|
|
return ($1, $2);
|
|
}
|
|
elsif ($out =~ /Mounted on\s*\n\S+\s*\n\s+(\S+)\s+\S+\s+(\S+)/i) {
|
|
return ($1, $2);
|
|
}
|
|
else {
|
|
return ( );
|
|
}
|
|
}
|
|
|
|
# supported_filesystems()
|
|
# Returns a list of filesystem types that can have mkfs_options called on them
|
|
sub supported_filesystems
|
|
{
|
|
local @fstypes = ( "ext2" );
|
|
push(@fstypes, "ext3") if (&has_command("mkfs.ext3") ||
|
|
&has_command("mke3fs") ||
|
|
`mkfs.ext2 -h 2>&1` =~ /\[-j\]/);
|
|
push(@fstypes, "reiserfs") if (&has_command("mkreiserfs"));
|
|
push(@fstypes, "xfs") if (&has_command("mkfs.xfs"));
|
|
push(@fstypes, "jfs") if (&has_command("mkfs.jfs"));
|
|
push(@fstypes, "fatx") if (&has_command("mkfs.fatx"));
|
|
push(@fstypes, "msdos");
|
|
push(@fstypes, "vfat");
|
|
push(@fstypes, "minix");
|
|
return @fstypes;
|
|
}
|
|
|
|
# get_label(device, [type])
|
|
# Returns the XFS or EXT label for some device's filesystem
|
|
sub get_label
|
|
{
|
|
local $label;
|
|
if ($has_e2label) {
|
|
$label = `e2label $_[0] 2>&1`;
|
|
chop($label);
|
|
}
|
|
if (($? || $label !~ /\S/) && $has_xfs_db) {
|
|
$label = undef;
|
|
local $out = &backquote_with_timeout("xfs_db -x -p xfs_admin -c label -r $_[0] 2>&1", 5);
|
|
$label = $1 if ($out =~ /label\s*=\s*"(.*)"/ &&
|
|
$1 ne '(null)');
|
|
}
|
|
if (($? || $label !~ /\S/) && $has_reiserfstune) {
|
|
$label = undef;
|
|
local $out = &backquote_command("reiserfstune $_[0]");
|
|
if ($out =~ /LABEL:\s*(\S+)/) {
|
|
$label = $1;
|
|
}
|
|
}
|
|
return $? || $label !~ /\S/ ? undef : $label;
|
|
}
|
|
|
|
# get_volid(device)
|
|
# Returns the UUID for some device's filesystem
|
|
sub get_volid
|
|
{
|
|
if ($has_volid) {
|
|
local $out = &backquote_command("vol_id $_[0] 2>&1");
|
|
if ($out =~ /ID_FS_UUID=(\S+)/) {
|
|
return $1;
|
|
}
|
|
}
|
|
return undef;
|
|
}
|
|
|
|
# set_label(device, label, [type])
|
|
# Tries to set the label for some device's filesystem
|
|
sub set_label
|
|
{
|
|
if ($has_e2label && ($_[2] =~ /^ext[23]$/ || !$_[2])) {
|
|
&system_logged("e2label '$_[0]' '$_[1]' >/dev/null 2>&1");
|
|
return 1 if (!$?);
|
|
}
|
|
if ($has_xfs_db && ($_[2] eq "xfs" || !$_[2])) {
|
|
&system_logged("xfs_db -x -p xfs_admin -c \"label $_[1]\" $_[0] >/dev/null 2>&1");
|
|
return 1 if (!$?);
|
|
}
|
|
return 0;
|
|
}
|