diff options
Diffstat (limited to 'perl-install/devices.pm')
| -rw-r--r-- | perl-install/devices.pm | 240 | 
1 files changed, 107 insertions, 133 deletions
| diff --git a/perl-install/devices.pm b/perl-install/devices.pm index f6a22c5f1..7ac79dcce 100644 --- a/perl-install/devices.pm +++ b/perl-install/devices.pm @@ -1,4 +1,4 @@ -package devices; # $Id$ +package devices;  use diagnostics;  use strict; @@ -8,37 +8,12 @@ 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 didn't 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);  } -sub find_free_loop { -    foreach (0..7) { +sub find_free_loop() { +    foreach (0..255) {  	my $dev = make("loop$_");  	sysopen(my $F, $dev, 2) or next;  	!ioctl($F, c::LOOP_GET_STATUS(), my $_tmp) && $! == 6 or next; #- 6 == ENXIO @@ -47,21 +22,41 @@ sub find_free_loop {      die "no free loop found";  }  sub set_loop { -    my ($file, $encrypt_key, $encryption) = @_; +    my ($file, $o_encrypt_key, $o_encryption) = @_; +    require modules; +    eval { modules::load('loop') };      my $dev = find_free_loop(); -    if ($encrypt_key && $encryption) { -	my $cmd = "losetup -p 0 -e $encryption $dev $file"; +    if ($o_encrypt_key && $o_encryption) { +	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 $encrypt_key; +	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_compressed_image { +    my ($name) = @_; +    foreach (0..255) { +	my $dev = make("loop$_"); +	my ($file) = `losetup $dev 2>/dev/null` =~ m!\((.*?)\)! or return; +	$file =~ s!^/sysroot/!/!; +	basename($file) eq $name and return $dev, $file; +    } +    undef; +} + +sub init_device_mapper() { +    require modules; +    eval { modules::load('dm-mod') }; +} +  sub entry {      my ($type, $major, $minor);      local ($_) = @_; @@ -69,25 +64,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 die "unknown device $_" }; -	$minor += $2 || 0;      } elsif (/^ram(.*)/) {  	$type = c::S_IFBLK();  	$major = 1; @@ -102,52 +78,57 @@ sub entry {  	$type = c::S_IFBLK();  	$major = ($1 eq 'ida' ? 72 : 104) + $2;  	$minor = 16 * $3 + ($4 || 0); -    } elsif (m,(ataraid)/d(\d+)(?:p(\d+))?,) { -	# ATA raid "ataraid/d0{p1}" -	$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 ], -		   "scd"         => [ 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 = ${{ +		   "md"          => sub { c::S_IFBLK(), 9,  0  }, +		   "ubd/"        => sub { c::S_IFBLK(), 98, 0  }, +	       }}{$prefix}; +	if ($f) { +	    ($type, $major, $minor) = $f->(); +	    $minor += $nb; +        }      }      unless ($type) {  	($type, $major, $minor) = -	     @{ ${{"aztcd"    => [ c::S_IFBLK(), 29, 0  ], -		   "bpcd"     => [ c::S_IFBLK(), 41, 0  ], -		   "cdu31a"   => [ c::S_IFBLK(), 15, 0  ], -		   "cdu535"   => [ c::S_IFBLK(), 24, 0  ], -		   "cm206cd"  => [ c::S_IFBLK(), 32, 0  ], -		   "gscd"     => [ c::S_IFBLK(), 16, 0  ], -		   "mcd"      => [ c::S_IFBLK(), 23, 0  ], -		   "mcdx"     => [ c::S_IFBLK(), 20, 0  ], -		   "mem"      => [ c::S_IFCHR(), 1,  1  ], -		   "optcd"    => [ c::S_IFBLK(), 17, 0  ], -		   "kbd"      => [ c::S_IFCHR(), 11, 0  ], -		   "psaux"    => [ c::S_IFCHR(), 10, 1  ], +	     @{ ${{  		   "atibm"    => [ c::S_IFCHR(), 10, 3  ], -		   "random"   => [ c::S_IFCHR(), 1,  8  ], -		   "sbpcd"    => [ c::S_IFBLK(), 25, 0  ], -		   "sjcd"     => [ c::S_IFBLK(), 18, 0  ], -		   "tty"      => [ c::S_IFCHR(),  5, 0  ], -		   "usbmouse" => [ c::S_IFCHR(), 13, 63 ], #- aka /dev/input/mice -		   "adbmouse" => [ c::S_IFCHR(), 10, 10 ], #- PPC -		   "zero"     => [ c::S_IFCHR(), 1,  5  ],		      -		   "null"     => [ c::S_IFCHR(), 1,  3  ],		      -	       }}{$_} or die "unknown device $_ (caller is " . join(":", caller()) . ")" }; +	       }}{$_} || [] }; +    } +    # 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);  } @@ -155,65 +136,58 @@ sub entry {  sub make($) {      local $_ = my $file = $_[0]; -    if (m,^(.*/(?:dev|tmp))/(.*),) { +    if (m!^(.*/dev)/(.*)!) {  	$_ = $2;      } else { -	$file =~ m|^/| && -e $file or $file = "/tmp/$_";  	$file =~ m|^/| && -e $file or $file = "/dev/$_";      }      -e $file and return $file; #- assume nobody takes fun at creating files named as device -    my ($type, $major, $minor) = eval { entry($_) }; -    $@ and die "unknown device $_ (caller is " . join(":", caller()) . ")"; - -    if ($file =~ m|/dev/| && -e '/dev/.devfsd') { -	#- argh, creating devices is no good with devfs... -	#- return the file even if the device file doesn't exist -	#- the caller will fail or not, better compatibility than raising an exception here -	return $file; -    } +    my ($type, $major, $minor) = entry($_);      #- 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;  } +sub simple_partition_scan { +    my ($part) = @_; +    $part->{device} =~ /((?:[hsv]|xv)d[a-z]|mmcblk|(nvme\d+n)\d+p)(\d+)$/; +} +sub part_number { +    my ($part) = @_; +    (simple_partition_scan($part))[1]; +} +sub part_prefix { +    my ($part) = @_; +    (simple_partition_scan($part))[0]; +} -#- 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 { +sub prefix_for_dev {      my ($dev) = @_; -    if (my $r = $to_devfs{$dev}) {  -	return $r; -    } elsif ($dev =~ /(.*?)(\d+)$/) { -	my $r = $to_devfs_prefix{$1}; -	return "$r$2" if $r; -    } -    undef; +    $dev . ($dev =~ /\d$/ ? 'p' : '');  } -sub from_devfs { +sub should_prefer_UUID {      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; -    } -    undef; +    $dev =~ /^((?:[hsv]|xv)d|mmcblk|nvme)/;  } +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; | 
