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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
package urpm::sys;
use strict;
#- find used mount point from a pathname, use a optional mode to allow
#- filtering according the next operation (mount or umount).
sub find_mntpoints {
my ($dir, $infos) = @_;
my (%fstab, @mntpoints);
local ($_);
#- read /etc/fstab and check for existing mount point.
open my $f, "/etc/fstab" or return ();
while (<$f>) {
next if /^\s*#/;
my ($device, $mntpoint, $fstype, $options) = m!^\s*(\S+)\s+(/\S+)\s+(\S+)\s+(\S+)!
or next;
$mntpoint =~ s,/+,/,g; $mntpoint =~ s,/$,,;
$fstab{$mntpoint} = 0;
if (ref($infos)) {
if ($fstype eq 'supermount') {
$options =~ /^(?:.*[\s,])?dev=([^\s,]+)/ and $infos->{$mntpoint} = {
mounted => 0,
device => $1,
fs => $fstype,
supermount => 1,
};
} else {
$infos->{$mntpoint} = { mounted => 0, device => $device, fs => $fstype };
}
}
}
close $f;
open $f, "/etc/mtab" or return ();
while (<$f>) {
my ($device, $mntpoint, $fstype, $options) = m!^\s*(\S+)\s+(/\S+)\s+(\S+)\s+(\S+)!
or next;
$mntpoint =~ s,/+,/,g; $mntpoint =~ s,/$,,;
$fstab{$mntpoint} = 1;
if (ref($infos)) {
if ($fstype eq 'supermount') {
$options =~ /^(?:.*[\s,])?dev=([^\s,]+)/ and $infos->{$mntpoint} = {
mounted => 1,
device => $1,
fs => $fstype,
supermount => 1,
};
} else {
$infos->{$mntpoint} = { mounted => 1, device => $device, fs => $fstype };
}
}
}
close $f;
#- try to follow symlink, too complex symlink graph may not be seen.
#- check the possible mount point.
my @paths = split '/', $dir;
my $pdir = '';
while (defined ($_ = shift @paths)) {
length($_) or next;
$pdir .= "/$_";
$pdir =~ s,/+,/,g; $pdir =~ s,/$,,;
if (exists($fstab{$pdir})) {
ref($infos) and push @mntpoints, $pdir;
$infos eq 'mount' && ! $fstab{$pdir} and push @mntpoints, $pdir;
$infos eq 'umount' && $fstab{$pdir} and unshift @mntpoints, $pdir;
#- following symlinks may be useless or dangerous for supermounted devices.
#- this means it is assumed no symlink inside a removable device
#- will go outside the device itself (or at least will go into
#- regular already mounted device like /).
#- for simplification we refuse also any other device and stop here.
last;
} elsif (-l $pdir) {
while (my $v = readlink $pdir) {
if ($pdir =~ m|^/|) {
$pdir = $v;
} else {
while ($v =~ m|^\.\./(.*)|) {
$v = $1;
$pdir =~ s|^(.*)/[^/]+/*|$1|;
}
$pdir .= "/$v";
}
}
unshift @paths, split '/', $pdir;
$pdir = '';
}
}
@mntpoints;
}
#- returns the first unused loop device, or an empty string if none is found.
sub first_free_loopdev () {
open my $mounts, '/proc/mounts' or do { warn "Can't read /proc/mounts: $!\n"; return 1 };
my %loopdevs = map { $_ => 1 } grep { ! -d $_ } glob('/dev/loop*');
local *_;
while (<$mounts>) {
(our $dev) = split ' ';
delete $loopdevs{$dev} if $dev =~ m!^/dev/loop!;
}
close $mounts;
my @l = keys %loopdevs;
@l ? $l[0] : '';
}
sub trim_until_d {
my ($dir) = @_;
open my $mounts, '/proc/mounts' or do { warn "Can't read /proc/mounts: $!\n"; return $dir };
local *_;
while (<$mounts>) {
#- fail if an iso is already mounted
m!^/dev/loop! and return $dir;
}
while ($dir && !-d $dir) { $dir =~ s,/[^/]*$,, }
$dir;
}
#- checks if the main filesystems are writeable for urpmi to install files in
sub check_fs_writable () {
open my $mounts, '/proc/mounts' or do { warn "Can't read /proc/mounts: $!\n"; return 1 };
local *_;
while (<$mounts>) {
(undef, our $mountpoint, undef, my $opts) = split ' ';
if ($opts =~ /\bro\b/ && $mountpoint =~ m!^(/|/usr|/s?bin)$!) {
return 0;
}
}
1;
}
1;
|