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 urpm::sys;
use strict;
#- check if supermount is used.
sub is_using_supermount {
my ($device_mntpoint) = @_;
local $_;
#- read /etc/fstab and check for existing mount point.
open my $f, "/etc/fstab" or die "Can't read fstab: $!\n";
while (<$f>) {
next if /^\s*#/;
my ($mntpoint, $fstype, $options) = m!^\s*\S+\s+(/\S+)\s+(\S+)\s+(\S+)!
or next;
$mntpoint =~ s,/+,/,g; $mntpoint =~ s,/$,,;
if ($fstype eq 'supermount') {
return 1 if $device_mntpoint eq $mntpoint;
$options =~ /^(?:.*[\s,])?dev=([^\s,]+)/ && $device_mntpoint eq $1
and return 1;
}
}
return 0;
}
#- 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 die "Can't read fstab: $!\n";
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 die "Can't read mtab: $!\n";
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;
while (defined ($_ = shift @paths)) {
length($_) or next;
my $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;
}
1;
|