# mount-lib.pl
# Functions for handling the /etc/[v]fstab file. Some functions are defined in
# here, and some in OS-specific files named <os_type>-lib.pl

do '../web-lib.pl';
&init_config();
require '../ui-lib.pl';
%access = &get_module_acl();

# get_mount(directory|'swap', device)
# Returns the index of this mount, or -1 if not known
sub get_mount
{
local(@mlist, $p, $d, $i);
@mlist = &list_mounts();
for($i=0; $i<@mlist; $i++) {
	$p = $mlist[$i];
	if ($_[0] eq "*" && $p->[1] eq $_[1]) {
		# found by match on device
		return $i;
		}
	elsif ($_[1] eq "*" && $p->[0] eq $_[0]) {
		# found by match on directory
		return $i;
		}
	elsif ($p->[0] eq $_[0] && $p->[1] eq $_[1]) {
		# found by match on both
		return $i;
		}
	}
return -1;
}


# get_mounted(directory|'swap', device)
# Returns the index of this current mount, or -1 if not known
sub get_mounted
{
local(@mlist, $p, $d, $i);
@mlist = &list_mounted();
for($i=0; $i<@mlist; $i++) {
	$p = $mlist[$i];
	if ($_[0] eq "*" && $p->[1] eq $_[1]) {
		# found by match on device
		return $i;
		}
	elsif ($_[1] eq "*" && $p->[0] eq $_[0]) {
		# found by match on directory
		return $i;
		}
	elsif ($p->[0] eq $_[0] && $p->[1] eq $_[1]) {
		# found by match on both
		return $i;
		}
	}
return -1;
}


# parse_options(type, options)
# Convert an options string for some filesystem into the associative
# array %options
sub parse_options
{
local($_);
undef(%options);
if ($_[1] ne "-") {
	foreach (split(/,/, $_[1])) {
		if (/^([^=]+)=(.*)$/) { $options{$1} = $2; }
		else { $options{$_} = ""; }
		}
	}
}

# join_options(type, [&hash])
# Returns a string constructed from the %options hash
sub join_options
{
local $h = $_[1] || \%options;
local (@rv, $k);
foreach $k (keys %$h) {
	push(@rv, $h->{$k} eq "" ? $k : $k."=".$h->{$k});
	}
return @rv ? join(",", @rv) : "-";
}

# swap_form(path)
# This function should be called by os-specific code to display a form
# asking for the size of a swap file to create. The form will be submitted
# to a creation program, and then redirected back to the original mount cgi
sub swap_form
{
&header("Create Swap File", "");
print "<hr>\n";
print "<form action=create_swap.cgi>\n";
foreach $k (keys %in) {
	print "<input type=hidden name=\"$k\" value=\"$in{$k}\">\n";
	}
print "<input type=hidden name=cswap_file value=\"$_[0]\">\n";
print "The swap file <tt>$_[0]</tt> does not exist.<p>\n";
print "Create and mount a swap file with size <input name=cswap_size size=6>\n";
print "<select name=cswap_units>\n";
print "<option value=k> kB\n";
print "<option value=m> MB\n";
print "</select>\n";
print "<input type=submit value=\"Create\"></form>\n";
print "<hr>\n";
&footer("", "mount list");
exit;
}

# nfs_server_chooser_button(input, [form])
sub nfs_server_chooser_button
{
local($form);
$form = @_ > 1 ? $_[1] : 0;
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";
}

# nfs_export_chooser_button(serverinput, exportinput, [form])
sub nfs_export_chooser_button
{
local($form);
$form = @_ > 2 ? $_[2] : 0;
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";
}

# smb_server_chooser_button(serverinput, [form])
sub smb_server_chooser_button
{
local($form);
$form = @_ > 1 ? $_[1] : 0;
if (&has_command($config{'smbclient_path'})) {
	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";
	}
}

# smb_share_chooser_button(serverinput, shareinput, [form])
sub smb_share_chooser_button
{
local($form);
$form = @_ > 2 ? $_[2] : 0;
if (&has_command($config{'smbclient_path'})) {
	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";
	}
}

# Include the correct OS-specific functions file
if ($gconfig{'os_type'} =~ /^\S+\-linux$/) {
	do "linux-lib.pl";
	}
else {
	do "$gconfig{'os_type'}-lib.pl";
	}

# can_edit_fs(dir, device, type, options)
# Returns 1 if a filesystem can be edited, 0 otherwise
sub can_edit_fs
{
return 1 if (!$access{'fs'});
local @dirs = split(/\s+/, $access{'fs'});
local $d;
foreach $d (@dirs) {
	return 1 if ($d eq "/" || $d eq $_[0] ||
		     substr($_[0], 0, length($d)+1) eq "$d/");
	}
return 0;
}

# compile_program(name, default-arch)
# Ensures that some C program is compiled and copied to /etc/webmin . Uses the
# supplied native versions if possible
sub compile_program
{
return if (-r "$module_config_directory/$_[0]" &&
	   system("$module_config_directory/$_[0] >/dev/null 2>&1 </dev/null")
		== 0);
local $arch = `uname -m`;
$arch =~ s/\r|\n//g;
local $re = $_[1];
if ($re && $arch =~ /^$re$/i && -r "$module_root_directory/$_[0]" &&
    system("$module_root_directory/$_[0] >/dev/null 2>&1 </dev/null") == 0) {
	# Compiled program for this architecture already exists and is working,
	# so can just copy
	system("cp $module_root_directory/$_[0] $module_config_directory/$_[0]");
	}
else {
	# Need to compile
	local ($cc) = (&has_command("gcc") || &has_command("cc"));
	$cc || &error($text{'egcc'});
	local $out = `$cc -o $module_config_directory/$_[0] $module_root_directory/$_[0].c 2>&1`;
	if ($?) {
		&error(&text('ecompile', "<pre>$out</pre>"));
		}
	}
}

1;

