summaryrefslogtreecommitdiffstats
path: root/perl-install/devices.pm
diff options
context:
space:
mode:
Diffstat (limited to 'perl-install/devices.pm')
-rw-r--r--perl-install/devices.pm253
1 files changed, 113 insertions, 140 deletions
diff --git a/perl-install/devices.pm b/perl-install/devices.pm
index 496a593bc..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,63 +8,55 @@ use run_program;
use log;
use c;
-sub size($) {
- local *F;
- sysopen F, $_[0], 0 or log::l("open $_[0]: $!"), 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$_");
- local *F;
- sysopen F, $dev, 2 or next;
- !ioctl(F, c::LOOP_GET_STATUS(), my $tmp) && $! == 6 or next; #- 6 == ENXIO
- close F;
+ sysopen(my $F, $dev, 2) or next;
+ !ioctl($F, c::LOOP_GET_STATUS(), my $_tmp) && $! == 6 or next; #- 6 == ENXIO
return $dev;
}
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");
- local *F;
- open F, "|$cmd";
- print F $encrypt_key;
- close F or die "losetup failed";
+ 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_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 ($_) = @_;
@@ -72,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;
@@ -105,50 +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 ],
- }}{$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 ],
- }}{$_} or die "unknown device $_ (caller is " . join(":", caller()) . ")" };
+ @{ ${{
+ "atibm" => [ c::S_IFCHR(), 10, 3 ],
+ }}{$_} || [] };
+ }
+ # 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);
}
@@ -156,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 dirname($file), 0755;
+ 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/mouse0',
-);
-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;