# export-lib.pl
# Common functions for the linux exports file

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

# list_exports()
# Returns a list of all exports
sub list_exports
{
local (@rv, $pos, $lnum, $h, $o, $line);
return @list_exports_cache if (@list_exports_cache);
open(EXP, $config{'exports_file'});
$lnum = 0;
while($line = <EXP>) {
	local $slnum = $lnum;
	$line =~ s/\s+$//g;
	while($line =~ /\\$/) {
		# continuation character!
		$line =~ s/\\$//;
		$line .= <EXP>;
		$line =~ s/\s+$//g;
		$lnum++;
		}
	if ($line =~ /^(#*)\s*(\/\S*)\s+(.*)$/) {
		local $active = !$1;
		local $dir = $2;
		local $rest = $3;
		next if ($dir =~ /^$config{'exports_file'}/);
		$pos = 0;
		while($rest =~ /^([^\s+\(\)]*)\(([^\)]*)\)\s*(.*)$/ ||
		      $rest =~ /^([^\s+\(\)]+)\s*()(.*)$/) {
			local %exp;
			$exp{'active'} = $active;
			$exp{'dir'} = $dir;
			$exp{'host'} = $1;
			local $ostr = $2;
			$rest = $3;
			while($ostr =~ /^([a-z_]+)=([0-9,\-]+)\s*,\s*(.*)$/ ||
			      $ostr =~ /^([a-z_]+)=([0-9,\-]+)(.*)$/ ||
			      $ostr =~ /^([a-z_]+)=([^,\s]+),(.*)$/ ||
			      $ostr =~ /^([a-z_]+)=([^,\s]+)(.*)$/ ||
			      $ostr =~ /^([a-z_]+)()\s*,\s*(.*)$/ ||
			      $ostr =~ /^([a-z_]+)()(.*)$/) {
				if ($2 ne "") { $exp{'options'}->{$1} = $2; }
				else { $exp{'options'}->{$1} = ""; }
				$ostr = $3;
				}
			$exp{'line'} = $slnum;
			$exp{'eline'} = $lnum;
			$exp{'pos'} = $pos++;
			$exp{'index'} = scalar(@rv);
			push(@rv, \%exp);
			}
		}
	$lnum++;
	}
close(EXP);
@list_exports_cache = @rv;
return @list_exports_cache;
}

# delete_export(&export)
# Delete an existing export
sub delete_export
{
local @exps = &list_exports();
local @same = grep { $_ ne $_[0] && $_->{'line'} eq $_[0]->{'line'} } @exps;
local $lref = &read_file_lines($config{'exports_file'});
if (@same) {
	# other exports on the same line.. cannot totally delete
	splice(@$lref, $_[0]->{'line'}, $_[0]->{'eline'}-$_[0]->{'line'}+1,
	       &make_exports_line(@same));
	map { $_->{'line'} = $_->{'eline'} = $_[0]->{'line'} } @same;
	}
else {
	# remove export line
	splice(@$lref, $_[0]->{'line'}, $_[0]->{'eline'}-$_[0]->{'line'}+1);
	}
@list_exports_cache = grep { $_ ne $_[0] } @list_exports_cache;
&flush_file_lines();
}

# create_export(&export)
sub create_export
{
open(EXP, ">>$config{'exports_file'}");
print EXP &make_exports_line($_[0]),"\n";
close(EXP);
}

# modify_export(&export, &old)
sub modify_export
{
local @exps = &list_exports();
local @same = grep { $_->{'line'} eq $_[1]->{'line'} } @exps;
local $lref = &read_file_lines($config{'exports_file'});
if ($_[0]->{'dir'} eq $_[1]->{'dir'} &&
    $_[0]->{'active'} == $_[1]->{'active'} || @same == 1) {
	# directory not changed, or on a line of it's own
	splice(@same, &indexof($_[1],@same), 1, $_[0]);
	splice(@$lref, $_[1]->{'line'}, $_[1]->{'eline'}-$_[1]->{'line'}+1,
	       &make_exports_line(@same));
	}
else {
	# move to a line of it's own
	splice(@same, &indexof($_[1],@same), 1);
	splice(@$lref, $_[1]->{'line'}, $_[1]->{'eline'}-$_[1]->{'line'}+1,
	       &make_exports_line(@same));
	push(@$lref, &make_exports_line($_[0]));
	}
&flush_file_lines();
}

# make_exports_line([&export]+)
sub make_exports_line
{
local ($e, @htxt);
foreach $e (@_) {
	local %opts = %{$e->{'options'}};
	if (%opts || !$e->{'host'}) {
		push(@htxt, $e->{'host'}."(".
			    join(",", map { $opts{$_} eq "" ? $_
							    : "$_=$opts{$_}" }
			    (keys %opts)).")");
		}
	else { push(@htxt, $e->{'host'}); }
	}
return ($_[0]->{'active'} ? "" : "#").
       $_[0]->{'dir'}."\t".join(" ", @htxt);
}

# describe_host(host)
# Given a host, regexp or netgroup return a human-readable version
sub describe_host
{
local $h = &html_escape($_[0]);
if ($h eq "=public") { return $text{'exports_webnfs'}; }
elsif ($h =~ /^\@(.*)/) { return &text('exports_ngroup', "<i>$1</i>"); }
elsif ($h =~ /^(\S+)\/(\S+)$/) {
	return &text('exports_net', "<i>$1/$2</i>"); }
elsif ($h eq "" || $h eq "*") { return $text{'exports_all'}; }
elsif ($h =~ /\*/) { return &text('exports_hosts', "<i>$h</i>"); }
else { return &text('exports_host', "<i>$h</i>"); }
}

1;

