1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
package devices;
use diagnostics;
use strict;
use common qw(:system :file);
use run_program;
use log;
use c;
1;
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
my $size = 0;
ioctl(F, c::BLKGETSIZE(), $size) and return unpack("i", $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 make($) {
local $_ = my $file = $_[0];
my ($type, $major, $minor);
my $prefix = '';
if (m,^(.*/(?:dev|tmp))/(.*),) {
$_ = $2;
} else {
$file = "$prefix/dev/$_";
-e $file or $file = "$prefix/tmp/$_";
}
-e $file and return $file; # assume nobody takes fun at creating files named as device
if (/^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],
}}{$1} or die "unknown device $_" };
$minor += $2 || 0;
} elsif (/^ram(.*)/) {
$type = c::S_IFBLK();
$major = 1;
$minor = $1 eq '' ? 1 : $1;
} elsif (m|^rd/c(\d+)d(\d+)(p(\d+))?|) {
# dac 960 "/rd/cXdXXpX"
$type = c::S_IFBLK();
$major = 48 + $1;
$minor = 8 * $2 + $4;
} elsif (m|ida/c(\d+)d(\d+)(p(\d+))?|) {
# Compaq Smart Array "ida/c0d0{p1}"
$type = c::S_IFBLK();
$major = 72 + $1;
$minor = 16 * $2 + ($4 || 0);
} else {
($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 ],
"tty" => [ c::S_IFCHR(), 5, 0 ],
"fd0" => [ c::S_IFBLK(), 2, 0 ],
"fd1" => [ c::S_IFBLK(), 2, 1 ],
"gscd" => [ c::S_IFBLK(), 16, 0 ],
"lp0" => [ c::S_IFCHR(), 6, 0 ],
"lp1" => [ c::S_IFCHR(), 6, 1 ],
"lp2" => [ c::S_IFCHR(), 6, 2 ],
"mcd" => [ c::S_IFBLK(), 23, 0 ],
"mcdx" => [ c::S_IFBLK(), 20, 0 ],
"nst0" => [ c::S_IFCHR(), 9, 128 ],
"optcd" => [ c::S_IFBLK(), 17, 0 ],
"sbpcd" => [ c::S_IFBLK(), 25, 0 ],
"scd0" => [ c::S_IFBLK(), 11, 0 ],
"scd1" => [ c::S_IFBLK(), 11, 1 ],
"sjcd" => [ c::S_IFBLK(), 18, 0 ],
}}{$_} or die "unknown device $_" };
}
# make a directory for this inode if needed.
mkdir dirname($file), 0755;
syscall_('mknod', $file, $type | 0600, makedev($major, $minor)) or die "mknod failed (dev:$_): $!";
$file;
}
|