2 # Functions for handling the /etc/[v]fstab file. Some functions are defined in
3 # here, and some in OS-specific files named <os_type>-lib.pl
5 BEGIN { push(@INC, ".."); };
8 %access = &get_module_acl();
9 $filesystem_users_file = "$module_config_directory/filesystem-users";
10 @access_fs = split(/\s+/, $access{'fs'});
12 # get_mount(directory|'swap', device)
13 # Returns the index of this mount, or -1 if not known
16 local(@mlist, $p, $d, $i);
17 @mlist = &list_mounts();
18 for($i=0; $i<@mlist; $i++) {
20 if ($_[0] eq "*" && $p->[1] eq $_[1]) {
21 # found by match on device
24 elsif ($_[1] eq "*" && $p->[0] eq $_[0]) {
25 # found by match on directory
28 elsif ($p->[0] eq $_[0] && $p->[1] eq $_[1]) {
29 # found by match on both
37 # get_mounted(directory|'swap', device)
38 # Returns the index of this current mount, or -1 if not known
41 local(@mlist, $p, $d, $i);
42 @mlist = &list_mounted();
43 for($i=0; $i<@mlist; $i++) {
45 if ($_[0] eq "*" && $p->[1] eq $_[1]) {
46 # found by match on device
49 elsif ($_[1] eq "*" && $p->[0] eq $_[0]) {
50 # found by match on directory
53 elsif ($p->[0] eq $_[0] && $p->[1] eq $_[1]) {
54 # found by match on both
62 # parse_options(type, options)
63 # Convert an options string for some filesystem into the associative
70 foreach (split(/,/, $_[1])) {
71 if (/^([^=]+)=(.*)$/) { $options{$1} = $2; }
72 else { $options{$_} = ""; }
78 # join_options(type, [&hash])
79 # Returns a string constructed from the %options hash
82 local $h = $_[1] || \%options;
84 foreach $k (keys %$h) {
85 push(@rv, $h->{$k} eq "" ? $k : $k."=".$h->{$k});
87 return @rv ? join(",", @rv) : "-";
91 # This function should be called by os-specific code to display a form
92 # asking for the size of a swap file to create. The form will be submitted
93 # to a creation program, and then redirected back to the original mount cgi
96 &ui_print_header(undef, "Create Swap File", "");
97 print "<form action=create_swap.cgi>\n";
98 foreach $k (keys %in) {
99 print "<input type=hidden name=\"$k\" value=\"$in{$k}\">\n";
101 print "<input type=hidden name=cswap_file value=\"$_[0]\">\n";
102 print "The swap file <tt>$_[0]</tt> does not exist.<p>\n";
103 print "Create and mount a swap file with size <input name=cswap_size size=6>\n";
104 print "<select name=cswap_units>\n";
105 print "<option value=k> kB\n";
106 print "<option value=m selected> MB\n";
107 print "<option value=g> GB\n";
109 print "<input type=submit value=\"Create\"></form>\n";
110 &ui_print_footer("", "mount list");
114 # nfs_server_chooser_button(input, [form])
115 sub nfs_server_chooser_button
118 $form = @_ > 1 ? $_[1] : 0;
119 if ($access{'browse'}) {
120 print "<input type=button onClick='ifield = document.forms[$form].$_[0]; nfs_server = window.open(\"../$module_name/nfs_server.cgi\", \"nfs_server\", \"toolbar=no,menubar=no,scrollbars=yes,width=400,height=300\"); nfs_server.ifield = ifield; window.ifield = ifield' value=\"...\">\n";
124 # nfs_export_chooser_button(serverinput, exportinput, [form])
125 sub nfs_export_chooser_button
128 $form = @_ > 2 ? $_[2] : 0;
129 if ($access{'browse'}) {
130 print "<input type=button onClick='if (document.forms[$form].$_[0].value != \"\") { ifield = document.forms[$form].$_[1]; nfs_export = window.open(\"../$module_name/nfs_export.cgi?server=\"+document.forms[$form].$_[0].value, \"nfs_export\", \"toolbar=no,menubar=no,scrollbars=yes,width=500,height=200\"); nfs_export.ifield = ifield; window.ifield = ifield }' value=\"...\">\n";
134 # smb_server_chooser_button(serverinput, [form])
135 sub smb_server_chooser_button
138 $form = @_ > 1 ? $_[1] : 0;
139 if (&has_command($config{'smbclient_path'}) && $access{'browse'}) {
140 print "<input type=button onClick='ifield = document.forms[$form].$_[0]; smb_server = window.open(\"../$module_name/smb_server.cgi\", \"smb_server\", \"toolbar=no,menubar=no,scrollbars=yes,width=400,height=300\"); smb_server.ifield = ifield; window.ifield = ifield' value=\"...\">\n";
144 # smb_share_chooser_button(serverinput, shareinput, [form])
145 sub smb_share_chooser_button
148 $form = @_ > 2 ? $_[2] : 0;
149 if (&has_command($config{'smbclient_path'}) && $access{'browse'}) {
150 print "<input type=button onClick='if (document.forms[$form].$_[0].value != \"\") { ifield = document.forms[$form].$_[1]; smb_share = window.open(\"../$module_name/smb_share.cgi?server=\"+document.forms[$form].$_[0].value, \"smb_share\", \"toolbar=no,menubar=no,scrollbars=yes,width=400,height=300\"); smb_share.ifield = ifield; window.ifield = ifield }' value=\"...\">\n";
154 # Include the correct OS-specific functions file
155 if ($gconfig{'os_type'} =~ /^\S+\-linux$/) {
159 do "$gconfig{'os_type'}-lib.pl";
162 # can_edit_fs(dir, device, type, options, [is-new])
163 # Returns 1 if a filesystem can be edited, 0 otherwise
169 foreach $d (@access_fs) {
170 $ok = 0 if (!&is_under_directory($d, $_[0]));
173 $ok = 0 if (!&can_fstype($_[2]));
174 if ($access{'user'} && !$_[4]) {
175 local $users = &get_filesystem_users();
176 $ok = 0 if ($users->{$_[0]} ne $remote_user);
184 return 1 if (!$access{'types'});
185 local @types = split(/\s+/, $access{'types'});
186 return &indexof($_[0], @types) >= 0;
189 # compile_program(name, default-arch)
190 # Ensures that some C program is compiled and copied to /etc/webmin . Uses the
191 # supplied native versions if possible
194 return if (-r "$module_config_directory/$_[0]" &&
195 &execute_command("$module_config_directory/$_[0]", undef, undef, undef, 0, 1) == 0);
196 local $arch = &backquote_command("uname -m");
199 if ($re && $arch =~ /^$re$/i && -r "$module_root_directory/$_[0]" &&
200 &execute_command("$module_root_directory/$_[0]", undef, undef, undef, 0, 1) == 0) {
201 # Compiled program for this architecture already exists and is working,
203 &execute_command("cp $module_root_directory/$_[0] $module_config_directory/$_[0]");
207 local ($cc) = (&has_command("gcc") || &has_command("cc") ||
208 &has_command("gcc-4.0") || &has_command("gcc-3.3"));
209 $cc || &error($text{'egcc'});
210 local $out = &backquote_logged("$cc -o $module_config_directory/$_[0] $module_root_directory/$_[0].c 2>&1");
212 &error(&text('ecompile', "<pre>$out</pre>"));
215 &set_ownership_permissions(undef, undef, 0755,"$module_config_directory/$_[0]");
218 # get_filesystem_users()
219 # Returns a mapping between filesystems and their owners
220 sub get_filesystem_users
223 &read_file($filesystem_users_file, \%users);
227 # save_filesystem_users(&usermap)
228 # Saves the filesystem owner mapping
229 sub save_filesystem_users
231 &write_file($filesystem_users_file, $_[0]);
234 # can_delete_directory(mount-point)
235 # Returns 1 if some directory should be deleted when un-mounting
236 sub can_delete_directory
238 local @dirs = split(/\s+/, $config{'delete_under'});
239 return 0 if (!@dirs);
240 return 0 if ($_[0] eq "swap");
243 return 1 if (&is_under_directory($d, $_[0]));
248 # delete_unmounted(dir, device)
249 # If some directory is no longer in the permanent mount list, delete it if it
250 # is under the list of dirs to auto-delete
253 if (&can_delete_directory($_[0]) &&
254 &get_mount($_[0], $_[1]) < 0) {
255 &system_logged("rmdir ".quotemeta($_[0]));
259 # remount_dir(directory, device, type, options)
260 # Adjusts the options for some mounted filesystem
263 if (defined(&os_remount_dir)) {
264 return &os_remount_dir(@_);
267 local $err = &unmount_dir(@_);
268 return $err if ($err);
269 return &mount_dir(@_);
273 # filesystem_for_dir(dir)
274 # Give a directory, returns the details filesystem it is on (dir, device,
276 sub filesystem_for_dir
278 local @stdir = stat($_[0]);
279 foreach my $m (&list_mounted()) {
280 local @stm = stat($m->[0]);
281 if ($stm[0] == $stdir[0]) {
282 # Save device number!
289 # local_disk_space([&always-count])
290 # Returns the total local and free disk space on the system.
294 my ($total, $free) = (0, 0);
295 my @mounted = &mount::list_mounted();
298 foreach $m (@mounted) {
299 if ($m->[2] =~ /^ext/ ||
300 $m->[2] eq "reiserfs" || $m->[2] eq "ufs" ||
301 $m->[2] eq "zfs" || $m->[2] eq "simfs" || $m->[2] eq "vzfs" ||
302 $m->[2] eq "xfs" || $m->[2] eq "jfs" ||
303 $m->[1] =~ /^\/dev\// ||
304 &indexof($m->[1], @$always) >= 0) {
305 if ($m->[1] =~ /^zones\/([^\/]+)/ &&
306 $m->[2] eq "zfs" && $donezone{$1}++) {
307 # Don't double-count zones
310 my ($t, $f) = &mount::disk_space($m->[2], $m->[0]);
311 if (($m->[2] eq "simfs" || $m->[2] eq "vzfs" ||
312 $m->[0] eq "/dev/vzfs") &&
313 $donevzfs{$t,$f}++) {
314 # Don't double-count VPS filesystems
321 return ($total, $free);