3 use if $ENV{DEBUG} ~~ /ptable|all/ => qw(Smart::Comments); |
3 use if $ENV{DEBUG} ~~ /ptable|all/ => qw(Smart::Comments); |
4 |
4 |
5 use strict; |
5 use strict; |
6 use warnings; |
6 use warnings; |
7 use File::Find; |
7 use File::Find; |
|
8 use File::Basename; |
8 use IO::File; |
9 use IO::File; |
9 |
|
10 |
10 |
11 use SI::tools; |
11 use SI::tools; |
12 $ENV{LC_ALL} = "C"; |
12 $ENV{LC_ALL} = "C"; |
13 |
13 |
14 sub volumes($\%) { |
14 sub volumes($\%) { |
15 my ($file, $devs) = @_; |
15 my ($file, $devs) = @_; |
16 |
16 |
17 # find the non-removable devices |
17 # find the partition tables of all |
|
18 # non-removable block devices (this may include |
|
19 # LVs (used as disk itself) too) |
|
20 foreach (glob("/sys/block/*")) { |
|
21 my $name = basename($_); |
|
22 verbose("device $name"); |
18 |
23 |
19 my ($current, $of); |
24 if (!-e "$_/device") { |
20 foreach (`sfdisk -d 2>/dev/null`) { |
25 verbose("skipping (non-dev)\n"); |
21 chomp; |
26 next; |
22 |
27 } |
23 # new entry, new disk |
|
24 if (my ($device, $name) = /^# partition table .*?(\/\S+\/(\S+))/) { |
|
25 verbose("scanning device $device"); |
|
26 |
|
27 if ((grep { /ATTR{removable}/ } `udevadm info --attribute-walk --name $name`)[0] !~ /==.0./) { |
28 if ((grep { /ATTR{removable}/ } `udevadm info --attribute-walk --name $name`)[0] !~ /==.0./) { |
28 $current = undef; |
|
29 verbose("skipping (removable)\n"); |
29 verbose("skipping (removable)\n"); |
30 next; |
30 next; |
31 } |
31 } |
|
32 verbose("\n"); |
32 |
33 |
33 # if it looks like a device mapper, we'll have to remember |
34 die "ERR: /dev/$name does not exist. (should not happen)" |
34 # this |
35 if !-e "/dev/$name"; |
35 if ($device =~ /\/dev\/dm-/) { |
36 |
36 if (my $alias = find_by_devid("/dev/mapper", (stat $device)[6])) { |
37 # now the physical disk -- let's ask for the partition table |
37 verbose("(alias $device)"); |
38 |
38 $devs->{disk}{$alias}{dm} = $device; |
39 my @sfdisk = `sfdisk -d /dev/$name 2>/dev/null`; |
39 $device = $alias; |
40 |
40 } |
41 my $of = sprintf $file, $name; |
|
42 my $oh = new IO::File ">$of" or die "Can't open >$of: $!\n"; |
|
43 print $oh @sfdisk; |
|
44 |
|
45 $devs->{disk}{"/dev/$name"} = { |
|
46 pt => \@sfdisk |
|
47 }; |
|
48 |
|
49 push @{$devs->{known}}, "/dev/$name"; |
|
50 |
|
51 # and let's prepare the volume entries |
|
52 foreach (@sfdisk) { |
|
53 /^(\S+)\s*:.*Id=\s*(\d+)/ or next; |
|
54 $devs->{volume}{$1} = { |
|
55 origin => "ptable", |
|
56 ptable_type => $2, |
|
57 }; |
|
58 push @{$devs->{known}}, $1; |
41 } |
59 } |
42 |
|
43 # save in our data structure |
|
44 verbose("\n"); |
|
45 $current = $device; |
|
46 push @{$devs->{disk}{$current}{pt}}, $_; |
|
47 |
|
48 # and open the outfile |
|
49 my $f = sprintf ">$file", $name; |
|
50 $of = new IO::File $f or die "ERR: Can't open $f: $!\n"; |
|
51 print $of "$_\n"; |
|
52 |
|
53 next; |
|
54 } |
|
55 |
|
56 next if not $current; |
|
57 |
|
58 push @{$devs->{disk}{$current}{pt}}, $_; |
|
59 print $of "$_\n"; |
|
60 |
|
61 # if it looks like a partition (volume), then |
|
62 # save it |
|
63 if (my ($dev, $id) = /^(\/dev\/\S+)\s*:.*\sId=\s*(\d+)/) { |
|
64 if (my $dm = $devs->{disk}{$current}{dm}) { |
|
65 $dev =~ s/$dm/$current/; |
|
66 } |
|
67 $devs->{volume}{$dev}{fstype} = $id; |
|
68 } |
|
69 |
|
70 } |
60 } |
71 |
61 |
72 return; |
62 return; |
73 } |
63 } |
74 1; |
64 1; |