summaryrefslogtreecommitdiffstats
path: root/perl-install/fs/type.pm
diff options
context:
space:
mode:
Diffstat (limited to 'perl-install/fs/type.pm')
-rw-r--r--perl-install/fs/type.pm316
1 files changed, 203 insertions, 113 deletions
diff --git a/perl-install/fs/type.pm b/perl-install/fs/type.pm
index ed6b4a571..141d5b5e2 100644
--- a/perl-install/fs/type.pm
+++ b/perl-install/fs/type.pm
@@ -1,15 +1,25 @@
-package fs::type; # $Id$
+package fs::type;
use diagnostics;
use strict;
use common;
+use devices;
+=head1 SYNOPSYS
+
+B<fs::type> enables to perform various tests on filesystem types.
+
+=head1 Functions
+
+=over
+
+=cut
our @ISA = qw(Exporter);
our @EXPORT = qw(
- isEmpty isExtended isTrueLocalFS isTrueFS isDos isSwap isOtherAvailableFS isRawLVM isRawRAID isRAID isLVM isMountableRW isNonMountable isPartOfLVM isPartOfRAID isPartOfLoopback isLoopback isMounted isBusy isSpecial isApple isAppleBootstrap isWholedisk isHiddenMacPart isFat_or_NTFS
- maybeFormatted set_isFormatted
+ isBlockCheckable isEmpty isExtended isFormatable isTrueLocalFS isTrueFS isDos isSwap isOtherAvailableFS isRawLVM isRawRAID isRawLUKS isRAID isLVM isLUKS isMountableRW isNonMountable isPartOfLVM isPartOfRAID isPartOfLoopback isLoopback isMounted isBusy isSpecial isApple isAppleBootstrap isBIOS_GRUB isESP isFat_or_NTFS isnormal_Fat_or_NTFS isRecovery
+ maybeFormatted set_isFormatted defaultFS
);
@@ -21,24 +31,25 @@ my (%type_name2pt_type, %type_name2fs_type, %fs_type2pt_type, %pt_type2fs_type,
0x82 => 'swap', 'Linux swap',
0x83 => 'ext2', 'Linux native',
0x83 => 'ext3', 'Journalised FS: ext3',
- 0x83 => 'reiserfs', 'Journalised FS: ReiserFS',
-if_(arch() =~ /ppc|i.86|ia64|x86_64/,
- 0x83 => 'xfs', 'Journalised FS: XFS',
+ 0x83 => 'ext4', 'Journalised FS: ext4',
+ 0x83 => 'btrfs', 'Journalised FS: Btrfs',
+(is_uefi() ?
+ (0xef => 'vfat', 'EFI System Partition') :
+ ('BIOS_GRUB' => 'BIOS_GRUB', 'BIOS boot or Empty partition')
),
-if_(arch() =~ /ppc|i.86/,
+if_(arch() =~ /i.86|x86_64/,
+ 0x83 => 'xfs', 'Journalised FS: XFS',
0x83 => 'jfs', 'Journalised FS: JFS',
-),
-if_(arch() =~ /i.86|ia64|x86_64/,
0x0b => 'vfat', 'FAT32',
-),
-if_(arch() =~ /ppc/,
- 0x401 => '', 'Apple Bootstrap',
- 0x402 => 'hfs', 'Apple HFS Partition',
- 0x41 => '', 'PPC PReP Boot',
+ 0x07 => 'ntfs-3g', 'NTFS-3G',
+ 0x07 => 'ntfs', 'NTFS',
+ 0x07 => 'ntfs3', 'NTFS3',
+ 0x07 => 'exfat', 'exFAT',
),
],
- less_important => [
+ non_fs_type => [
+ 0x83 => '', 'Encrypted',
0x8e => '', 'Linux Logical Volume Manager',
0xfd => '', 'Linux RAID',
],
@@ -50,34 +61,14 @@ if_(arch() =~ /ppc/,
0x85 => '', 'Linux extended',
],
- backward_compatibility => [
- 0x183 => 'reiserfs', 'reiserfs (deprecated)',
- 0x283 => 'xfs', 'xfs (deprecated)',
- 0x383 => 'jfs', 'jfs (deprecated)',
- 0x483 => 'ext3', 'ext3 (deprecated)',
- ],
-
other => [
- if_(arch() =~ /^ia64/,
- 0x100 => '', 'Various',
-), if_(arch() =~ /^ppc/,
- 0x401 => 'apple', 'Apple Partition',
-), if_(arch() =~ /^sparc/,
- 0x01 => 'ufs', 'SunOS boot',
- 0x02 => 'ufs', 'SunOS root',
- 0x03 => '', 'SunOS swap',
- 0x04 => 'ufs', 'SunOS usr',
- 0x05 => '', 'Whole disk',
- 0x06 => 'ufs', 'SunOS stand',
- 0x07 => 'ufs', 'SunOS var',
- 0x08 => 'ufs', 'SunOS home',
-), if_(arch() =~ /^i.86|x86_64/,
+ if_(arch() =~ /^i.86|x86_64/,
0x01 => 'vfat', 'FAT12',
0x02 => '', 'XENIX root',
0x03 => '', 'XENIX usr',
0x04 => 'vfat', 'FAT16 <32M',
0x06 => 'vfat', 'FAT16',
- 0x07 => (arch() =~ /^ppc/ ? 'hpfs' : 'ntfs'), 'NTFS (or HPFS)',
+ 0x07 => 'hpfs', 'HPFS',
0x08 => '', 'AIX',
),
0x09 => '', 'AIX bootable',
@@ -91,16 +82,14 @@ if_(arch() =~ /ppc/,
0x16 => '', 'Hidden FAT16',
0x17 => 'ntfs', 'Hidden HPFS/NTFS',
0x18 => '', 'AST SmartSleep',
- 0x1b => 'vfat', 'Hidden W95 FAT32',
- 0x1c => 'vfat', 'Hidden W95 FAT32 (LBA)',
- 0x1e => 'vfat', 'Hidden W95 FAT16 (LBA)',
+ 0x1b => 'vfat', 'Hidden W95 FAT32', # \
+ 0x1c => 'vfat', 'Hidden W95 FAT32 (LBA)', # > don't change label, it's used to know if it's not a boot partition in bootloader.pm
+ 0x1e => 'vfat', 'Hidden W95 FAT16 (LBA)', # /
0x24 => '', 'NEC DOS',
0x39 => '', 'Plan 9',
0x3c => '', 'PartitionMagic recovery',
0x40 => '', 'Venix 80286',
-if_(arch() !~ /ppc/,
0x41 => '', 'PPC PReP Boot',
-),
0x42 => '', 'SFS',
0x4d => '', 'QNX4.x',
0x4e => '', 'QNX4.x 2nd part',
@@ -121,9 +110,12 @@ if_(arch() !~ /ppc/,
0x75 => '', 'PC/IX',
0x80 => '', 'Old Minix',
0x81 => '', 'Minix / old Linux',
+ 0x83 => 'f2fs', 'Journalised FS: F2FS',
+ 0x83 => 'reiserfs', 'Journalised FS: ReiserFS',
+ 0x83 => 'nilfs2', 'Journalised FS: NILFS2',
0x84 => '', 'OS/2 hidden C: drive',
- 0x86 => '', 'NTFS volume set',
- 0x87 => '', 'NTFS volume set ',
+ 0x86 => '', 'NTFS volume set (0x86)',
+ 0x87 => '', 'NTFS volume set (0x87)',
0x93 => '', 'Amoeba',
0x94 => '', 'Amoeba BBT',
0x9f => '', 'BSD/OS',
@@ -138,6 +130,7 @@ if_(arch() !~ /ppc/,
0xb8 => '', 'BSDI swap',
0xbb => '', 'Boot Wizard hidden',
0xbe => '', 'Solaris boot',
+ 0xbf => '', 'Microsoft XBox OS Partitions',
0xc1 => '', 'DRDOS/sec (FAT-12)',
0xc4 => '', 'DRDOS/sec (FAT-16 < 32M)',
0xc6 => '', 'DRDOS/sec (FAT-16)',
@@ -151,7 +144,6 @@ if_(arch() !~ /ppc/,
0xe4 => '', 'SpeedStor (FAT-16)',
0xeb => 'befs', 'BeOS fs',
0xee => '', 'EFI GPT',
- 0xef => 'vfat', 'EFI (FAT-12/16/32)',
0xf0 => '', 'Linux/PA-RISC boot',
0xf4 => '', 'SpeedStor (large part.)',
0xf2 => '', 'DOS secondary',
@@ -178,16 +170,26 @@ if_(arch() !~ /ppc/,
}
-sub type_names() {
+sub type_names {
+ my ($expert, $o_hd) = @_;
my @l = @{$type_names{important}};
- push @l, @{$type_names{less_important}}, sort @{$type_names{other}} if $::expert;
- @l;
+ push @l, grep { $_ ne 'Encrypted' } @{$type_names{non_fs_type}};
+ push @l, sort @{$type_names{other}} if $expert;
+ # not show partition types which have no associated filesystem for LVM LV:
+ if ($o_hd && isLVM($o_hd)) {
+ @l = grep { $type_name2fs_type{$_} } @l;
+ @l = uniq_ { $type_name2fs_type{$_} } @l;
+ (@l, @{$type_names{non_fs_type}});
+ } else {
+ @l;
+ }
}
sub type_name2subpart {
my ($name) = @_;
exists $type_name2fs_type{$name} &&
- { fs_type => $type_name2fs_type{$name}, pt_type => $type_name2pt_type{$name} };
+ { type_name => $name,
+ fs_type => $type_name2fs_type{$name}, pt_type => $type_name2pt_type{$name} };
}
sub part2type_name {
@@ -248,24 +250,6 @@ sub set_type_subpart {
}
}
-
-my @partitions_signatures = (
- (map { [ 'Linux Logical Volume Manager', 0x200 * $_ + 0x18, "LVM2" ] } 0 .. 3),
- [ 'Linux Logical Volume Manager', 0, "HM\1\0" ],
- [ 'ext2', 0x438, "\x53\xEF" ],
- [ 'reiserfs', 0x10034, "ReIsErFs" ],
- [ 'reiserfs', 0x10034, "ReIsEr2Fs" ],
- [ 'xfs', 0, 'XFSB', 0x200, 'XAGF', 0x400, 'XAGI' ],
- [ 'jfs', 0x8000, 'JFS1' ],
- [ 'swap', 4086, "SWAP-SPACE" ],
- [ 'swap', 4086, "SWAPSPACE2" ],
- [ 'ntfs', 0x1FE, "\x55\xAA", 0x3, "NTFS" ],
- [ 'FAT32', 0x1FE, "\x55\xAA", 0x52, "FAT32" ],
-if_(arch() !~ /^sparc/,
- [ 'FAT16', 0x1FE, "\x55\xAA", 0x36, "FAT" ],
-),
-);
-
sub fs_type_from_magic {
my ($part) = @_;
if (exists $part->{fs_type_from_magic}) {
@@ -276,79 +260,157 @@ sub fs_type_from_magic {
}
}
+sub call_blkid {
+ my ($part) = @_;
+
+ # IMPORTANT: Always use the -p argument with blkid. See r7324 commit msg
+ my %h = map {
+ if_(/(.*?)=(.*)/, $1 => $2);
+ } run_program::get_stdout_raw({ timeout => 30 }, 'blkid', '2>', '/dev/null', '-o', 'udev', '-p', devices::make($part->{device}));
+
+ \%h;
+}
+
sub type_subpart_from_magic {
my ($part) = @_;
- my $dev = devices::make($part->{device});
-
- my $check_md = sub {
- my ($F) = @_;
- my $MD_RESERVED_SECTORS = 128;
- my $sector = round_down($part->{size}, $MD_RESERVED_SECTORS) - $MD_RESERVED_SECTORS; #- MD_NEW_SIZE_SECTORS($part->{size})
- if (c::lseek_sector(fileno $F, $sector, 0)) {
- my $tmp;
- my $signature = "\xfc\x4e\x2b\xa9";
- sysread($F, $tmp, length $signature);
- $tmp eq $signature and return "Linux RAID";
- }
- '';
- };
- my $t = typeFromMagic($dev,
- if_($part->{size}, $check_md),
- @partitions_signatures) or return;
-
- my $p = type_name2subpart($t) || fs_type2subpart($t) || internal_error("unknown name/fs $t");
- if ($p->{fs_type} eq 'ext2') {
- #- there is no magic to differentiate ext3 and ext2. Using libext2fs
- #- to check if it has a journal
- $p->{fs_type} = 'ext3' if c::is_ext3($dev);
+ my $ids = call_blkid($part);
+
+ my $p;
+ if ($ids->{ID_FS_USAGE} eq 'raid') {
+ my $name = {
+ linux_raid_member => "Linux RAID",
+ LVM1_member => 'Linux Logical Volume Manager',
+ LVM2_member => 'Linux Logical Volume Manager',
+ }->{$ids->{ID_FS_TYPE}};
+
+ $p = type_name2subpart($name) if $name;
+ } elsif ($ids->{ID_FS_USAGE} eq 'crypto') {
+ $p = type_name2subpart('Encrypted');
+ } elsif (my $fs_type = $ids->{ID_FS_TYPE}) {
+ $fs_type = 'ntfs-3g' if $fs_type eq 'ntfs';
+ $p = fs_type2subpart($fs_type) or log::l("unknown filesystem $fs_type returned by blkid");
+ }
+
+ if ($p) {
+ $p->{fs_type} = '' if $part->{pt_type} eq 'BIOS_GRUB' && $p->{fs_type} ne 'iso9660';
+ $part->{fs_type_from_magic} = $p->{fs_type};
+ $p->{device_LABEL} = $ids->{ID_FS_LABEL} if $ids->{ID_FS_LABEL};
+ $p->{device_UUID} = $ids->{ID_FS_UUID} if $ids->{ID_FS_UUID};
+ log::l("blkid gave: $p->{fs_type} $p->{device_UUID} $p->{device_LABEL}");
}
- $part->{fs_type_from_magic} = $p->{fs_type};
$p;
}
-
-sub isEmpty { !$_[0]{fs_type} && $_[0]{pt_type} == 0 }
-sub isEfi { arch() =~ /ia64/ && $_[0]{pt_type} == 0xef }
-sub isWholedisk { arch() =~ /^sparc/ && $_[0]{pt_type} == 5 }
-sub isExtended { arch() !~ /^sparc/ && ($_[0]{pt_type} == 5 || $_[0]{pt_type} == 0xf || $_[0]{pt_type} == 0x85) }
-sub isRawLVM { $_[0]{pt_type} == 0x8e }
-sub isRawRAID { $_[0]{pt_type} == 0xfd }
+# helpers
+sub defaultFS() { 'ext4' }
+sub true_local_fs_types() { qw(btrfs ext3 ext2 ext4 f2fs reiserfs xfs jfs) }
+
+sub isEmpty { !$_[0]{fs_type} && !$_[0]{pt_type} }
+sub isBIOS_GRUB { $_[0]{pt_type} eq 'BIOS_GRUB' }
+sub isESP { $_[0]{pt_type} == 0xef && member($_[0]{fs_type}, qw(fat32 vfat)) }
+sub isExtended { $_[0]{pt_type} == 5 || $_[0]{pt_type} == 0xf || $_[0]{pt_type} == 0x85 }
+sub isBlockCheckable { !member($_[0]{fs_type}, qw(btrfs hfs ntfs ntfs-3g reiserfs xfs)) }
+sub isRawLVM { $_[0]{pt_type} == 0x8e || $_[0]{type_name} eq 'Linux Logical Volume Manager' }
+sub isRawRAID { $_[0]{pt_type} == 0xfd || $_[0]{type_name} eq 'Linux RAID' }
+sub isRawLUKS { $_[0]{type_name} eq 'Encrypted' }
sub isSwap { $_[0]{fs_type} eq 'swap' }
-sub isDos { arch() !~ /^sparc/ && ${{ 1 => 1, 4 => 1, 6 => 1 }}{$_[0]{pt_type}} }
-sub isFat_or_NTFS { member($_[0]{fs_type}, 'vfat', 'ntfs') }
+sub isDos { ${{ 1 => 1, 4 => 1, 6 => 1 }}{$_[0]{pt_type}} }
+sub isFat_or_NTFS { member($_[0]{fs_type}, qw(vfat ntfs ntfs3 ntfs-3g)) }
+sub isnormal_Fat_or_NTFS { grep { isFat_or_NTFS($_) && !isESP($_) && !isRecovery($_) } @_ }
sub isApple { $_[0]{pt_type} == 0x401 && defined $_[0]{isDriver} }
sub isAppleBootstrap { $_[0]{pt_type} == 0x401 && defined $_[0]{isBoot} }
-sub isHiddenMacPart { defined $_[0]{isMap} }
+sub isRecovery {
+ isFat_or_NTFS($_[0]) && ($_[0]{type_name} =~ /^Hidden/ ||
+ $_[0]{pt_type} == 0x12 || # "Compaq diagnostics"
+ member($_[0]{device_LABEL} ,
+ # Extracted from /usr/lib/udev/rules.d/80-udisks2.rules
+ # Hopefuly we'll ask to udev/udisk2 someday
+ # generated by grep Recovery /usr/lib/udev/rules.d/80-udisks2.rules :
+ qw(Recovery RECOVERY Lenovo_Recovery HP_RECOVERY Recovery_Partition DellUtility DellRestore IBM_SERVICE SERVICEV001 SERVICEV002 SYSTEM_RESERVED System_Reserved WINRE_DRV DIAGS IntelRST),
+ # gathered over the years (Hald, mga#1371, mga#15999):
+ qw(PQSERVICE Packard_Bell Push_Button_Reset SYSTEM_DRV))
+ );
+}
+
+=item isTrueLocalFS($part)
+
+Like isTrueFS(), to make a distinction between ext3/reiserfs/... and NFS
+ => allow /home on NFS
+
+=cut
+
+sub isTrueFS { isTrueLocalFS($_[0]) || $_[0]{fs_type} eq 'nfs' }
-sub isTrueFS { isTrueLocalFS($_[0]) || member($_[0]{fs_type}, qw(nfs)) }
-sub isTrueLocalFS { member($_[0]{fs_type}, qw(ext2 reiserfs xfs jfs ext3)) }
+=item isTrueFS($part)
-sub isOtherAvailableFS { isEfi($_[0]) || isFat_or_NTFS($_[0]) || member($_[0]{fs_type}, 'ufs', 'hfs') } #- other OS that linux can access its filesystem
+Is is a general purpose file system with the right Unix properties
+
+=cut
+
+sub isTrueLocalFS { member($_[0]{fs_type}, true_local_fs_types()) }
+
+=item isOtherAvailableFS($part)
+
+Is it another OS that linux can access its filesystem
+
+=cut
+
+sub isOtherAvailableFS { isESP($_[0]) || isFat_or_NTFS($_[0]) || member($_[0]{fs_type}, 'ufs', 'hfs', 'iso9660', 'nilfs2', 'exfat') }
sub isMountableRW { (isTrueFS($_[0]) || isOtherAvailableFS($_[0])) && $_[0]{fs_type} ne 'ntfs' }
+sub cannotBeMountable {
+ my ($part) = @_;
+ isRawRAID($part) || isRawLUKS($part) || isRawLVM($part) || isBIOS_GRUB($part);
+}
+
+=item isFormatable($part)
+
+Is not a special sg that cannot be mounted/formatted (parts of RAID/LVM, BIOS_GRUB). Basically the reverse of cannotBeMountable().
+
+=cut
+
+sub isFormatable {
+ my ($part) = @_;
+ !cannotBeMountable($part);
+}
+
sub isNonMountable {
my ($part) = @_;
- isRawRAID($part) || isRawLVM($part) || $part->{fs_type} eq 'ntfs' && !$part->{isFormatted} && $part->{notFormatted};
+ cannotBeMountable($part) || $part->{fs_type} eq 'ntfs' && !$part->{isFormatted} && $part->{notFormatted};
}
sub isPartOfLVM { defined $_[0]{lvm} }
sub isPartOfRAID { defined $_[0]{raid} }
sub isPartOfLoopback { defined $_[0]{loopback} }
-sub isRAID { $_[0]{device} =~ /^md/ }
+sub isRAID { $_[0]{device} =~ /^md/ && defined $_[0]{level} }
sub isUBD { $_[0]{device} =~ /^ubd/ } #- should be always true during an $::uml_install
-sub isLVM { $_[0]{VG_name} }
+sub isLVM { $_[0]{VG_name} || $_[0]{lv_name} }
+sub isLUKS { defined $_[0]{dmcrypt_name} }
sub isLoopback { defined $_[0]{loopback_file} }
sub isMounted { $_[0]{isMounted} }
-sub isBusy { isMounted($_[0]) || isPartOfRAID($_[0]) || isPartOfLVM($_[0]) || isPartOfLoopback($_[0]) }
+sub isBusy { isMounted($_[0]) || isPartOfRAID($_[0]) || isPartOfLVM($_[0]) || $_[0]{dm_active} || isPartOfLoopback($_[0]) }
sub isSpecial { isRAID($_[0]) || isLVM($_[0]) || isLoopback($_[0]) || isUBD($_[0]) }
+=item is_dmraid($hd)
+
+Check that a disk (not a partition) is in a fake/soft RAID
+
+=cut
+
+sub is_dmraid { $_[0]{bus} =~ /^dmraid_/ }
+
sub can_be_this_fs_type {
my ($part, $fs_type) = @_;
- $part->{fs_type} && ($part->{fs_type} eq 'auto' || member($fs_type, split(':', $part->{fs_type})));
+ can_be_one_of_those_fs_types($part, $fs_type);
+}
+sub can_be_one_of_those_fs_types {
+ my ($part, @fs_types) = @_;
+ $part->{fs_type} or return;
+ $part->{fs_type} eq 'auto' || listlength(intersection(\@fs_types, [ split(':', $part->{fs_type}) ]));
}
sub maybeFormatted {
my ($part) = @_;
- $part->{isFormatted} || !$part->{notFormatted} && !$part->{bad_fs_type_magic};
+ $part->{isFormatted} || !$part->{notFormatted} && (!$part->{bad_fs_type_magic} || $part->{options} =~ /encrypted/);
}
sub set_isFormatted {
my ($part, $val) = @_;
@@ -358,9 +420,37 @@ sub set_isFormatted {
delete $part->{fs_type_from_magic};
}
-#- do this before modifying $part->{fs_type}
+=item check($fs_type, $_hd, $part)
+
+Called before before modifying $part->{fs_type}
+
+=cut
+
sub check {
my ($fs_type, $_hd, $part) = @_;
- $fs_type eq "jfs" && $part->{size} < 16 << 11 and die N("You can not use JFS for partitions smaller than 16MB");
- $fs_type eq "reiserfs" && $part->{size} < 32 << 11 and die N("You can not use ReiserFS for partitions smaller than 32MB");
+ $fs_type eq "jfs" && $part->{size} < MB(16) and die N("You cannot use JFS for partitions smaller than 16MB");
+ $fs_type eq "reiserfs" && $part->{size} < MB(32) and die N("You cannot use ReiserFS for partitions smaller than 32MB");
+ $fs_type eq "btrfs" && $part->{size} < MB(256) and die N("You cannot use btrfs for partitions smaller than 256MB");
+}
+
+sub guessed_by_mount() {
+ grep { $_ && !/nodev/ } chomp_(cat_('/etc/filesystems'));
}
+
+sub directories_needed_to_boot_not_ESP() {
+ qw(/ /usr /var /boot /tmp);
+}
+sub directories_needed_to_boot() {
+ directories_needed_to_boot_not_ESP(), '/boot/EFI';
+}
+
+sub carry_root_loopback {
+ my ($part) = @_;
+ any { $_->{mntpoint} eq '/' } @{$part->{loopback} || []};
+}
+
+=back
+
+=cut
+
+1;