diff options
Diffstat (limited to 'perl-install/devices.pm')
| -rw-r--r-- | perl-install/devices.pm | 227 |
1 files changed, 99 insertions, 128 deletions
diff --git a/perl-install/devices.pm b/perl-install/devices.pm index 513c1714a..8ea66bd82 100644 --- a/perl-install/devices.pm +++ b/perl-install/devices.pm @@ -1,4 +1,4 @@ -package devices; # $Id$ +package devices; # $Id: devices.pm 270810 2010-09-09 08:11:23Z bor $ use diagnostics; use strict; @@ -8,31 +8,6 @@ use run_program; use log; use c; -sub size { - my ($dev) = @_; - sysopen(my $F, $dev, 0) or log::l("open $dev: $!"), return 0; - - my $valid_offset = sub { sysseek($F, $_[0], 0) && sysread($F, my $_a, 1) }; - - #- first try getting the size nicely - if (my $size = c::total_sectors(fileno $F)) { - return $size * $common::SECTORSIZE; - } - - #- sad it did not work, well searching the size using the dichotomy algorithm! - my $low = 0; - my ($high, $mid); - - #- first find n where 2^n < size <= 2^n+1 - for ($high = 1; $high > 0 && $valid_offset->($high); $high *= 2) { $low = $high } - - while ($low < $high - 1) { - $mid = int(($low + $high) / 2); - $valid_offset->($mid) ? $low : $high = $mid; - } - $low + 1; -} - sub del_loop { my ($dev) = @_; run_program::run("losetup", "-d", $dev); @@ -48,23 +23,25 @@ sub find_free_loop() { } sub set_loop { my ($file, $o_encrypt_key, $o_encryption) = @_; + require modules; eval { modules::load('loop') }; my $dev = find_free_loop(); if ($o_encrypt_key && $o_encryption) { - eval { modules::load('cryptoloop', arch() =~ /i.86/ ? 'aes-i586' : 'aes') }; + eval { modules::load('cryptoloop', list_modules::category2modules('various/crypto')) }; my $cmd = "losetup -p 0 -e $o_encryption $dev $file"; log::l("calling $cmd"); open(my $F, "|$cmd"); print $F $o_encrypt_key; close $F or die "losetup failed"; } else { - run_program::run("losetup", $dev, $file) or return; + run_program::run("losetup", $dev, $file) + || run_program::run("losetup", "-r", $dev, $file) or return; } $dev; } -sub find_clp_loop { +sub find_compressed_image { my ($name) = @_; foreach (0..255) { my $dev = make("loop$_"); @@ -75,12 +52,18 @@ sub find_clp_loop { undef; } +sub get_dynamic_major { + my ($name) = @_; + cat_('/proc/devices') =~ /^(\d+) \Q$name\E$/m && $1; +} + sub init_device_mapper() { + require modules; eval { modules::load('dm-mod') }; make('urandom'); my $control = '/dev/mapper/control'; if (! -e $control) { - my ($major) = cat_('/proc/devices') =~ /(\d+) misc$/m or return; + my ($major) = get_dynamic_major('misc') or return; my ($minor) = cat_('/proc/misc') =~ /(\d+) device-mapper$/m or return; mkdir_p(dirname($control)); syscall_('mknod', $control, c::S_IFCHR() | 0600, makedev($major, $minor)) or die "mknod $control failed: $!"; @@ -94,25 +77,6 @@ sub entry { if (/^0x([\da-f]{3,4})$/i) { $type = c::S_IFBLK(); ($major, $minor) = unmakedev(hex $1); - } elsif (/^sd(.)(\d{0,2})/) { - $type = c::S_IFBLK(); - $major = 8; - $minor = 16 * (ord($1) - ord('a')) + ($2 || 0); - } elsif (/^hd(.)(\d{0,2})/) { - $type = c::S_IFBLK(); - ($major, $minor) = - @{ ${{'a' => [3, 0], 'b' => [3, 64], - 'c' => [22,0], 'd' => [22,64], - 'e' => [33,0], 'f' => [33,64], - 'g' => [34,0], 'h' => [34,64], - 'i' => [56,0], 'j' => [56,64], - 'k' => [57,0], 'l' => [57,64], - 'm' => [88,0], 'n' => [88,64], - 'o' => [89,0], 'p' => [89,64], - 'q' => [90,0], 'r' => [90,64], - 's' => [91,0], 't' => [91,64], - }}{$1} or internal_error("unknown device $_") }; - $minor += $2 || 0; } elsif (/^ram(.*)/) { $type = c::S_IFBLK(); $major = 1; @@ -132,21 +96,25 @@ sub entry { $type = c::S_IFBLK(); $major = 114; $minor = 16 * $1 + ($2 || 0); - } elsif (/(.*?)(\d+)$/) { - ($type, $major, $minor) = - @{ ${{"fd" => [ c::S_IFBLK(), 2, 0 ], - "hidbp-mse-" => [ c::S_IFCHR(), 10, 32 ], - "lp" => [ c::S_IFCHR(), 6, 0 ], - "usb/lp" => [ c::S_IFCHR(), 180, 0 ], - "input/event" => [ c::S_IFCHR(), 13, 64 ], - "loop" => [ c::S_IFBLK(), 7, 0 ], - "md" => [ c::S_IFBLK(), 9, 0 ], - "nst" => [ c::S_IFCHR(), 9, 128 ], - "sr" => [ c::S_IFBLK(), 11, 0 ], - "ttyS" => [ c::S_IFCHR(), 4, 64 ], - "ubd/" => [ c::S_IFBLK(), 98, 0 ], - }}{$1} }; - $minor += $2; + } elsif (my ($prefix, $nb) = /(.*?)(\d+)$/) { + my $f = ${{"fd" => sub { c::S_IFBLK(), 2, 0 }, + "hidbp-mse-" => sub { c::S_IFCHR(), 10, 32 }, + "lp" => sub { c::S_IFCHR(), 6, 0 }, + "usb/lp" => sub { c::S_IFCHR(), 180, 0 }, + "input/event" => sub { c::S_IFCHR(), 13, 64 }, + "loop" => sub { c::S_IFBLK(), 7, 0 }, + "md" => sub { c::S_IFBLK(), 9, 0 }, + "nst" => sub { c::S_IFCHR(), 9, 128 }, + "sr" => sub { c::S_IFBLK(), 11, 0 }, + "tty" => sub { c::S_IFCHR(), 4, 0 }, + "ttyS" => sub { c::S_IFCHR(), 4, 64 }, + "ubd/" => sub { c::S_IFBLK(), 98, 0 }, + "dm-" => sub { c::S_IFBLK(), get_dynamic_major('device-mapper'), 0 }, + }}{$prefix}; + if ($f) { + ($type, $major, $minor) = $f->(); + $minor += $nb; + } } unless ($type) { ($type, $major, $minor) = @@ -170,13 +138,52 @@ sub entry { "tty" => [ c::S_IFCHR(), 5, 0 ], "input/mice" => [ c::S_IFCHR(), 13, 63 ], - "usbmouse" => [ c::S_IFCHR(), 13, 63 ], #- aka /dev/input/mice "adbmouse" => [ c::S_IFCHR(), 10, 10 ], #- PPC "vcsa" => [ c::S_IFCHR(), 7, 128 ], "zero" => [ c::S_IFCHR(), 1, 5 ], "null" => [ c::S_IFCHR(), 1, 3 ], - }}{$_} or internal_error("unknown device $_") }; + + "initrd" => [ c::S_IFBLK(), 1, 250 ], + "console" => [ c::S_IFCHR(), 5, 1 ], + "systty" => [ c::S_IFCHR(), 4, 0 ], + "lvm" => [ c::S_IFBLK(), 109, 0 ], + }}{$_} || [] }; + } + # Lookup non listed devices in /sys + unless ($type) { + my $sysdev; + if (m!input/(.*)! && -e "/sys/class/input/$1/dev") { + $sysdev = "/sys/class/input/$1/dev"; + $type = c::S_IFCHR(); + } elsif (-e "/sys/block/$_/dev") { + $sysdev = "/sys/block/$_/dev"; + $type = c::S_IFBLK(); + } elsif (/^(.+)(\d+)$/ && -e "/sys/block/$1/$_/dev") { + $sysdev = "/sys/block/$1/$_/dev"; + $type = c::S_IFBLK(); + } + ($major, $minor) = split(':', chomp_(cat_($sysdev))); + } + # Lookup partitions in /proc/partitions in case /sys was not available + unless ($type) { + if (-e "/proc/partitions") { + if (cat_("/proc/partitions") =~ /^\s*(\d+)\s+(\d+)\s+\d+\s+$_$/m) { + ($major, $minor) = ($1, $2); + $type = c::S_IFBLK(); + } + } + } + # Try to access directly the device + # Now device mapper devices are links and do not appear in /proc or /sys + unless ($type) { + if (-e "/dev/$_") { + my (undef, undef, $mode, undef, undef, undef, $rdev, undef) = stat("/dev/$_"); + ($major, $minor) = unmakedev($rdev); + $type = $mode & c::S_IFMT(); + } } + + $type or internal_error("unknown device $_"); ($type, $major, $minor); } @@ -193,77 +200,19 @@ sub make($) { my ($type, $major, $minor) = entry($_); - if ($file =~ m|/dev/| && -e '/dev/.devfsd') { - #- argh, creating devices is no good with devfs... - #- return the file even if the device file does not exist - #- the caller will fail or not, better compatibility than raising an exception here - return $file; - } - #- make a directory for this inode if needed. mkdir_p(dirname($file)); - syscall_('mknod', $file, $type | 0600, makedev($major, $minor)) or die "mknod failed (dev $_): $!"; + syscall_('mknod', $file, $type | 0600, makedev($major, $minor)) or do { + die "mknod failed (dev $_): $!" if ! -e $file; # we may have raced with udev + }; $file; } - -#- only isomorphic entries are allowed, -#- i.e. entries which can go devfs -> normal and normal -> devfs -my %to_devfs = ( - psaux => 'misc/psaux', - usbmouse => 'input/mice', -); -my %to_devfs_prefix = ( - ttyS => 'tts/', -); - -sub to_devfs { - my ($dev) = @_; - if (my $r = $to_devfs{$dev}) { - return $r; - } elsif ($dev =~ /(.*?)(\d+)$/) { - my $r = $to_devfs_prefix{$1}; - return "$r$2" if $r; - } - readlink("/dev/" . $dev); -} - -sub read_proc_partitions_raw() { - my (undef, undef, @all) = cat_("/proc/partitions"); - grep { - $_->{size} != 1 && # skip main extended partition - $_->{size} != 0x3fffffff; # skip cdroms (otherwise stops cd-audios) - } map { - my %l; - @l{qw(major minor size dev)} = split; - \%l; - } @all; -} - -sub from_devfs { - my ($dev) = @_; - my %from_devfs = reverse %to_devfs; - if (my $r = $from_devfs{$dev}) { - return $r; - } elsif ($dev =~ /(.*?)(\d+)$/) { - my %from_devfs_prefix = reverse %to_devfs_prefix; - my $r = $from_devfs_prefix{$1}; - return "$r$2" if $r; - } - $dev = "/dev/" . $dev; - if (-e $dev) { - my ($major, $minor) = unmakedev((stat($dev))[6]); - my $r = find { $_->{major} == $major && $_->{minor} == $minor } read_proc_partitions_raw(); - $r and return $r->{dev}; - } - undef; -} - sub simple_partition_scan { my ($part) = @_; - $part->{device} =~ /([hs]d[a-z])(\d+)$/; + $part->{device} =~ /((?:[hsv]|xv)d[a-z]|mmcblk\d+p)(\d+)$/; } sub part_number { my ($part) = @_; @@ -274,4 +223,26 @@ sub part_prefix { (simple_partition_scan($part))[0]; } +sub prefix_for_dev { + my ($dev) = @_; + $dev . ($dev =~ /\d$/ || $dev =~ m!mapper/! ? 'p' : ''); +} + +sub should_prefer_UUID { + my ($dev) = @_; + $dev =~ /^((?:[hsv]|xv)d)/; +} + +sub symlink_now_and_register { + my ($if_struct, $of) = @_; + my $if = $if_struct->{device}; + + #- add a static udev device node, we can't do it with a udev rule, + #- eg, ttySL0 is a symlink created by a daemon + symlinkf($if, "$::prefix/usr/lib/udev/devices/$of"); + + symlinkf($if, "/dev/$of"); +} + + 1; |
