line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# Copyright (c) 2014, cPanel, Inc. |
2
|
|
|
|
|
|
|
# All rights reserved. |
3
|
|
|
|
|
|
|
# http://cpanel.net/ |
4
|
|
|
|
|
|
|
# |
5
|
|
|
|
|
|
|
# This is free software; you can redistribute it and/or modify it under the same |
6
|
|
|
|
|
|
|
# terms as Perl itself. See the LICENSE file for further details. |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
package Filesys::POSIX::Mount; |
9
|
|
|
|
|
|
|
|
10
|
25
|
|
|
25
|
|
85
|
use strict; |
|
25
|
|
|
|
|
23
|
|
|
25
|
|
|
|
|
536
|
|
11
|
25
|
|
|
25
|
|
74
|
use warnings; |
|
25
|
|
|
|
|
26
|
|
|
25
|
|
|
|
|
440
|
|
12
|
|
|
|
|
|
|
|
13
|
25
|
|
|
25
|
|
77
|
use Filesys::POSIX::Bits; |
|
25
|
|
|
|
|
19
|
|
|
25
|
|
|
|
|
5681
|
|
14
|
25
|
|
|
25
|
|
104
|
use Filesys::POSIX::Module (); |
|
25
|
|
|
|
|
28
|
|
|
25
|
|
|
|
|
288
|
|
15
|
25
|
|
|
25
|
|
77
|
use Filesys::POSIX::Path (); |
|
25
|
|
|
|
|
23
|
|
|
25
|
|
|
|
|
383
|
|
16
|
|
|
|
|
|
|
|
17
|
25
|
|
|
25
|
|
76
|
use Filesys::POSIX::Error qw(throw); |
|
25
|
|
|
|
|
23
|
|
|
25
|
|
|
|
|
883
|
|
18
|
|
|
|
|
|
|
|
19
|
25
|
|
|
25
|
|
82
|
use Carp qw(confess); |
|
25
|
|
|
|
|
32
|
|
|
25
|
|
|
|
|
8329
|
|
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
my @METHODS = qw(mount unmount statfs fstatfs mountlist); |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
Filesys::POSIX::Module->export_methods( __PACKAGE__, @METHODS ); |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
=head1 NAME |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
Filesys::POSIX::Mount - Exposes VFS mounting functionality to L |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
=head1 DESCRIPTION |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
C is a mixin module imported into the L |
32
|
|
|
|
|
|
|
namespace by said module that provides a frontend to the internal VFS. Rather |
33
|
|
|
|
|
|
|
than dealing in terms of mount point vnodes as L does, the |
34
|
|
|
|
|
|
|
system calls provided in this module deal in terms of pathnames. |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
=head1 SYSTEM CALLS |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
=over |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
=item C<$fs-Emount($dev, $path, %opts)> |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
Attach the filesystem device, C<$dev>, to the directory inode specified by |
43
|
|
|
|
|
|
|
C<$path>. The C<%opts> hash can be used to pass mount options to the |
44
|
|
|
|
|
|
|
initialization routines for the device object to be mounted; these options are |
45
|
|
|
|
|
|
|
passed to the C<$dev-Einit()> routine that said filesystem device |
46
|
|
|
|
|
|
|
implements. |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
The filesystem mount record is kept in an ordered list by the VFS, and can be |
49
|
|
|
|
|
|
|
retrieved later using the C<$fs-Estatfs>, or C<$fs-Emountlist> system |
50
|
|
|
|
|
|
|
calls. |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
=cut |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
sub mount { |
55
|
14
|
|
|
14
|
1
|
1546
|
my ( $self, $dev, $path, %opts ) = @_; |
56
|
14
|
|
|
|
|
38
|
my $mountpoint = $self->stat($path); |
57
|
14
|
|
|
|
|
35
|
my $realpath = $self->_find_inode_path($mountpoint); |
58
|
|
|
|
|
|
|
|
59
|
14
|
|
33
|
|
|
48
|
$opts{'fs'} ||= $self; |
60
|
|
|
|
|
|
|
|
61
|
14
|
|
|
|
|
41
|
$dev->init(%opts); |
62
|
|
|
|
|
|
|
|
63
|
12
|
|
|
|
|
35
|
$self->{'vfs'}->mount( $dev, $realpath, $mountpoint, %opts ); |
64
|
|
|
|
|
|
|
} |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
=item C<$fs-Eunmount($path)> |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
Attempts to unmount a filesystem mounted at the directory pointed to by |
69
|
|
|
|
|
|
|
C<$path>, performing a number of sanity checks to ensure the safety of the |
70
|
|
|
|
|
|
|
current operation. The following checks are made: |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
=over |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
=item The directory inode is retrieved using C<$fs-Estat>. |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
=item Using Cstatfs>, with the directory inode passed, |
77
|
|
|
|
|
|
|
the VFS is queried to determine if the location given has a filesystem mounted |
78
|
|
|
|
|
|
|
at all. If so, the mount record is kept for reference for the next series of |
79
|
|
|
|
|
|
|
checks. |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
=item The file descriptor table is scanned for open files whose inodes exist on |
82
|
|
|
|
|
|
|
the device found for the mount record queried in the previous step by the VFS. |
83
|
|
|
|
|
|
|
An EBUSY exception is thrown when matching file descriptors are found. |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
=item The current working directory is checked to ensure it is not a reference |
86
|
|
|
|
|
|
|
to a directory inode associated with the mounted device. An EBUSY exception is |
87
|
|
|
|
|
|
|
thrown if the current directory is on the same device that is to be unmounted. |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
=back |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
=cut |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
sub unmount { |
94
|
6
|
|
|
6
|
1
|
407
|
my ( $self, $path ) = @_; |
95
|
6
|
|
|
|
|
12
|
my $mountpoint = $self->stat($path); |
96
|
6
|
|
|
|
|
15
|
my $mount = $self->{'vfs'}->statfs( $mountpoint, 'exact' => 1 ); |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
# |
99
|
|
|
|
|
|
|
# First, check for open file descriptors held on the desired device. |
100
|
|
|
|
|
|
|
# |
101
|
6
|
|
|
|
|
15
|
foreach ( $self->{'fds'}->list ) { |
102
|
3
|
|
|
|
|
8
|
my $inode = $self->{'fds'}->lookup($_)->{'inode'}; |
103
|
|
|
|
|
|
|
|
104
|
3
|
100
|
|
|
|
16
|
throw &Errno::EBUSY if $mount->{'dev'} eq $inode->{'dev'}; |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
# |
108
|
|
|
|
|
|
|
# Next, check to see if the current working directory's device inode |
109
|
|
|
|
|
|
|
# is the same device as the one being requested for unmounting. |
110
|
|
|
|
|
|
|
# |
111
|
5
|
100
|
|
|
|
14
|
throw &Errno::EBUSY if $mount->{'dev'} eq $self->{'cwd'}->{'dev'}; |
112
|
|
|
|
|
|
|
|
113
|
4
|
|
|
|
|
9
|
$self->{'vfs'}->unmount($mount); |
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
=item C<$fs-Estatfs($path)> |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
Returns the mount record for the device associated with the inode specified by |
119
|
|
|
|
|
|
|
$path. The inode is found using C<$fs-Estat>, then queried for by |
120
|
|
|
|
|
|
|
Cstatfs>. |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
=cut |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
sub statfs { |
125
|
3
|
|
|
3
|
1
|
874
|
my ( $self, $path ) = @_; |
126
|
3
|
|
|
|
|
7
|
my $inode = $self->stat($path); |
127
|
|
|
|
|
|
|
|
128
|
3
|
|
|
|
|
7
|
return $self->{'vfs'}->statfs($inode); |
129
|
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
=item C<$fs-Efstatfs($fd)> |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
Returns the mount record for the device associated with the inode referenced by |
134
|
|
|
|
|
|
|
the open file descriptor, C<$fd>. The inode is found using C<$fs-Efstat>, |
135
|
|
|
|
|
|
|
then queried for by Cstatfs>. |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
=cut |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
sub fstatfs { |
140
|
3
|
|
|
3
|
1
|
1683
|
my ( $self, $fd ) = @_; |
141
|
3
|
|
|
|
|
8
|
my $inode = $self->fstat($fd); |
142
|
|
|
|
|
|
|
|
143
|
3
|
|
|
|
|
9
|
return $self->{'vfs'}->statfs($inode); |
144
|
|
|
|
|
|
|
} |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
=item C<$fs-Emountlist> |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
Returns a list of records for each filesystem currently mounted, in the order |
149
|
|
|
|
|
|
|
in which they were mounted. |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
=cut |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
sub mountlist { |
154
|
1
|
|
|
1
|
1
|
8
|
shift->{'vfs'}->mountlist; |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
=back |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
=head1 ANATOMY OF A MOUNT RECORD |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
Mount records are created internally by Cmount>, and |
162
|
|
|
|
|
|
|
are stored as anonymous HASHes. They contain the following attributes: |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
=over |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
=item C |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
Reference to the directory inode (or vnode in the case of multiple filesystems |
169
|
|
|
|
|
|
|
mounted in the same logical location) the filesystem is mounted to. |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
=item C |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
Reference to the mounted filesystem's root directory inode. This is never a |
174
|
|
|
|
|
|
|
vnode. |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
=item C |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
The value of the C flag specified in a call to C<$fs-Emount>. When |
179
|
|
|
|
|
|
|
no value is specified, the value stored is equal to C[. ] |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
=item C |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
A reference to the filesystem device object that was mounted by |
184
|
|
|
|
|
|
|
C<$fs-Emount>. |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
=item C |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
A lowercase string formed by chopping all but the last item in a Perl fully |
189
|
|
|
|
|
|
|
qualified package name corresponding to the type of the device mounted. For |
190
|
|
|
|
|
|
|
instance, an instance of L mounted will result in a value |
191
|
|
|
|
|
|
|
of C<'mem'>. |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
=item C |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
The true, original, and sanitized path of the mount point specified by |
196
|
|
|
|
|
|
|
C<$fs-Emount>. |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
=item C |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
A VFS inode created by Cnew>, containing most |
201
|
|
|
|
|
|
|
attributes of the mounted device's root inode, but with a parent pointing to |
202
|
|
|
|
|
|
|
the mount point inode's parent. |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
=item C |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
A copy of the options passed to C<$fs-Emount>, minus the C option. |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
=back |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
=cut |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
1; |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
__END__ |