\d+)/) {
return ("$+{total}", "$+{free}", "$+{used}", "$+{percent}");
}
else {
return ( );
}
}
# list_fstypes()
# Returns an array of all the supported filesystem types. If a filesystem is
# found that is not one of the supported types, generate_location() and
# generate_options() will not be called for it.
sub list_fstypes
{
local @rv = ("ufs", "nfs", "cd9660", "msdos", "swap");
push(@rv, "ext2fs") if (&has_command("mount_ext2fs"));
push(@rv, "ntfs") if (&has_command("mount_ntfs"));
push(@rv, "smbfs") if ($smbfs_support);
return @rv;
}
# fstype_name(type)
# Given a short filesystem type, return a human-readable name for it
sub fstype_name
{
local(%fsmap);
%fsmap = ("ufs", "FreeBSD Unix Filesystem",
"nfs", "Network Filesystem",
"cd9660", "ISO9660 CD-ROM",
"msdos", "MS-DOS Filesystem",
"ext2fs", "Linux Filesystem",
"ntfs", "Windows NT Filesystem",
"swap", "Virtual Memory",
"proc", "Process Image Filesystem",
"smbfs", "Windows Networking Filesystem");
return $config{long_fstypes} && $fsmap{$_[0]} ? $fsmap{$_[0]} : uc($_[0]);
}
# multiple_mount(type)
# Returns 1 if filesystems of this type can be mounted multiple times, 0 if not
sub multiple_mount
{
return $_[0] eq "nfs" || $_[0] eq "smbfs";
}
# generate_location(type, location)
# Output HTML for editing the mount location of some filesystem.
sub generate_location
{
local ($type, $loc) = @_;
if ($type eq "nfs") {
# NFS mount from some host and directory
local ($host, $dir) = $loc =~ /^([^:]+):(.*)$/ ? ( $1, $2 ) : ( );
print &ui_table_row(&hlink($text{'linux_nfshost'}, "nfshost"),
&ui_textbox("nfs_host", $host, 30).
&nfs_server_chooser_button("nfs_host").
" ".
"".&hlink($text{'linux_nfsdir'}, "nfsdir")." ".
&ui_textbox("nfs_dir",
($type eq "nfs4") && ($dir eq "") ? "/" : $dir, 30).
&nfs_export_chooser_button("nfs_host", "nfs_dir"));
}
elsif ($type eq "smbfs") {
# SMB mount from some server and share
local ($server, $share) = $loc =~ /^\\\\([^\\]*)\\(.*)$/ ?
($1, $2) : ( );
print &ui_table_row($text{'linux_smbserver'},
&ui_textbox("smbfs_server", $server, 30)." ".
&smb_server_chooser_button("smbfs_server")." ".
" ".
"$text{'linux_smbshare'} ".
&ui_textbox("smbfs_share", $share, 30)." ".
&smb_share_chooser_button("smbfs_server", "smbfs_share"));
}
else {
local $msg;
if ($type eq "swap") {
# Swap file or device
$msg = $text{'linux_swapfile'};
}
else {
# Disk-based filesystem
$msg = &fstype_name($type);
}
# Generate disk selection options
my @opts;
my $found;
my $sel = &bsdfdisk::partition_select(
"disk_select", $loc, 3, \$found);
push(@opts, [ 0, $text{'freebsd_select'}, $sel ]);
push(@opts, [ 1, $text{'freebsd_other'},
&ui_textbox("dev_path", $found ? "" : $loc, 40).
" ".&file_chooser_button("dev_path", 0) ]);
print &ui_table_row($msg,
&ui_radio_table("disk_dev", $found ? 0 : 1, \@opts));
}
}
# generate_options(type, newmount)
# Output HTML for editing mount options for a particular filesystem
# under this OS
sub generate_options
{
if ($_[0] ne "swap") {
# These options are common to all filesystems
print " | Read-only? | \n";
printf " Yes\n",
defined($options{"rdonly"}) || defined($options{"ro"})
? "checked" : "";
printf " No | \n",
defined($options{"rdonly"}) || defined($options{"ro"})
? "" : "checked";
print "Buffer writes to filesystem? | \n";
printf" Yes\n",
defined($options{"sync"}) ? "" : "checked";
printf " No |
\n",
defined($options{"sync"}) ? "checked" : "";
print " | Allow device files? | \n";
printf " Yes\n",
defined($options{"nodev"}) ? "" : "checked";
printf " No | \n",
defined($options{"nodev"}) ? "checked" : "";
print "Allow execution of binaries? | \n";
printf" Yes\n",
defined($options{"noexec"}) ? "" : "checked";
printf " No |
\n",
defined($options{"noexec"}) ? "checked" : "";
print " | Disallow setuid programs? | \n";
printf " Yes\n",
defined($options{"nosuid"}) ? "checked" : "";
printf " No | \n",
defined($options{"nosuid"}) ? "" : "checked";
print "Update access times? | \n";
printf" Yes\n",
defined($options{"noatime"}) ? "" : "checked";
printf " No |
\n",
defined($options{"noatime"}) ? "checked" : "";
if ($uname_release =~ /^[34]\./) {
# FreeBSD 3.x has some more options
print " | Follow symbolic links? | \n";
printf " Yes\n",
defined($options{"nosymfollow"}) ? "" : "checked";
printf " No | \n",
defined($options{"nosymfollow"}) ? "checked" : "";
print "Files inherit group from SUID directories? | \n";
printf" Yes\n",
defined($options{"suiddir"}) ? "checked" : "";
printf " No |
\n",
defined($options{"suiddir"}) ? "" : "checked";
}
}
if ($_[0] eq "ufs") {
# UFS filesystems support quotas
print " | User quotas at boot | \n";
printf " Disabled\n",
defined($options{'userquota'}) ? "" : "checked";
printf " Enabled\n",
defined($options{'userquota'}) && $options{'userquota'} eq ""
? "checked" : "";
printf "\n",
$options{'userquota'} ? "checked" : "";
print "Enabled, use file\n";
printf "\n",
$options{'userquota'};
print " |
\n";
print " | Group quotas at boot | \n";
printf " Disabled\n",
defined($options{'groupquota'}) ? "" : "checked";
printf " Enabled\n",
defined($options{'groupquota'}) && $options{'groupquota'} eq ""
? "checked" : "";
printf "\n",
$options{'groupquota'} ? "checked" : "";
print "Enabled, use file\n";
printf "\n",
$options{'groupquota'};
print " |
\n";
}
elsif ($_[0] eq "nfs") {
# NFS filesystems have lots more options
print " | Retry mounts in background? | \n";
printf " Yes\n",
defined($options{"-b"}) ? "checked" : "";
printf " No | \n",
defined($options{"-b"}) ? "" : "checked";
print "Return error on timeouts? | \n";
printf " Yes\n",
defined($options{"-s"}) ? "checked" : "";
printf " No |
\n",
defined($options{"-s"}) ? "" : "checked";
print " | Timeout | \n";
printf " Default\n",
defined($options{"-t"}) ? "" : "checked";
printf "\n",
defined($options{"-t"}) ? "checked" : "";
printf " | \n";
print "Number of Retransmissions | \n";
printf " Default\n",
defined($options{"-x"}) ? "" : "checked";
printf "\n",
defined($options{"-x"}) ? "checked" : "";
print " |
\n";
print " | NFS version | \n";
local $v = defined($options{"-2"}) ? 2 :
defined($options{"-3"}) ? 3 : 0;
printf " Auto\n",
$v ? "" : "checked";
printf " V2\n",
$v == 2 ? "checked" : "";
printf " V3 | \n",
$v == 3 ? "checked" : "";
print "Mount retries | \n";
printf " Default\n",
defined($options{"-R"}) ? "" : "checked";
printf "\n",
defined($options{"-R"}) ? "checked" : "";
print " |
\n";
print " | Read-ahead blocks | \n";
printf " Default\n",
defined($options{"-a"}) ? "" : "checked";
printf "\n",
defined($options{"-a"}) ? "checked" : "";
print " | \n";
print "RPC Protocol | \n";
printf " TCP\n",
defined($options{"-T"}) ? "checked" : "";
printf " UDP |
\n",
defined($options{"-T"}) ? "" : "checked";
}
elsif ($_[0] eq "msdos"){
# MS-DOS filesystems options deal with filling in
# missing unix functionality
print " | User files are owned by | \n";
printf "\n",
defined($options{"-u"}) ? getpwuid($options{"-u"}) : "";
print &user_chooser_button("msdos_u", 0)," | \n";
print "Group files are owned by | \n";
printf "\n",
defined($options{"-g"}) ? getgrgid($options{"-g"}) : "";
print &group_chooser_button("msdos_g", 0)," | \n";
print "
| File permissions mask | \n";
printf " Default\n",
defined($options{"-m"}) ? "" : "checked";
printf "\n",
defined($options{"-m"}) ? "checked" : "";
print " | \n";
}
elsif ($_[0] eq "cd9660") {
# CDROM filesystem
print "
| Ignore Unix Attributes? | \n";
printf " Yes\n",
defined($options{"-r"}) ? "checked" : "";
printf " No | \n",
defined($options{"-r"}) ? "" : "checked";
print "Show version numbers? | \n";
printf " Yes\n",
defined($options{"-g"}) ? "checked" : "";
printf " No |
\n",
defined($options{"-g"}) ? "" : "checked";
print " | Use extended attributes? | \n";
printf " Yes\n",
defined($options{"-e"}) ? "checked" : "";
printf " No |
\n",
defined($options{"-e"}) ? "" : "checked";
}
elsif ($_[0] eq "ntfs") {
# Windows NT filesystem
print " | Display MSDOS 8.3 filenames? | \n";
printf " Yes\n",
defined($options{"-a"}) ? "checked" : "";
printf " No | \n",
defined($options{"-a"}) ? "" : "checked";
print "Case sensitive filenames? | \n";
printf " Yes\n",
defined($options{"-i"}) ? "" : "checked";
printf " No |
\n",
defined($options{"-i"}) ? "checked" : "";
print " | User files are owned by | \n";
printf " Default\n",
defined($options{"-u"}) ? "" : "checked";
printf "\n",
defined($options{"-u"}) ? "checked" : "";
printf " %s | \n",
defined($options{"-u"}) ? scalar(getpwuid($options{"-u"})) : "",
&user_chooser_button("ntfs_u");
print "Group files are owned by | \n";
printf " Default\n",
defined($options{"-u"}) ? "" : "checked";
printf "\n",
defined($options{"-u"}) ? "checked" : "";
printf " %s |
\n",
defined($options{"-g"}) ? scalar(getgrgid($options{"-g"})) : "",
&group_chooser_button("ntfs_g");
}
elsif ($_[0] eq "swap") {
# Swap has no options..
print " | No Options Available |
\n";
}
elsif ($_[0] eq "smbfs") {
# SMBFS has some special options
print " | $text{'linux_username'} | \n";
printf " | \n",
$options{"user"};
print "$text{'linux_password'} | \n";
printf " |
\n",
$options{"nsmb_password"};
print " | $text{'linux_wg'} | \n";
printf " $text{'linux_auto'}\n",
defined($options{"nsmb_workgroup"}) ? "" : "checked";
printf "\n",
defined($options{"nsmb_workgroup"}) ? "checked" : "";
print " |
\n";
print " | $text{'linux_mname'} | \n";
printf " %s\n",
defined($options{"nsmb_addr"}) ? "" : "checked", $text{'linux_auto'};
printf "\n",
defined($options{"nsmb_addr"}) ? "checked" : "";
print " |
\n";
}
}
# check_location(type)
# Parse and check inputs from %in, calling &error() if something is wrong.
# Returns the location string for storing in the fstab file
sub check_location
{
if ($_[0] eq "nfs") {
local($out, $temp, $mout, $dirlist);
if ($config{'nfs_check'}) {
# Use ping and showmount to see if the host exists and is up
if ($in{nfs_host} !~ /^\S+$/) {
&error("'$in{nfs_host}' is not a valid hostname");
}
&execute_command("ping -c 1 '$in{nfs_host}'", undef, \$out, \$out);
if ($out =~ /unknown host/i) {
&error("The host '$in{nfs_host}' does not exist");
}
elsif ($out =~ /100\% packet loss/) {
&error("The host '$in{nfs_host}' is down");
}
&execute_command("showmount -e '$in{nfs_host}'", undef, \$out, \$out);
if ($out =~ /Unable to receive/) {
&error("The host '$in{nfs_host}' does not support NFS");
}
elsif ($?) {
&error("Failed to get mount list : $out");
}
}
# Validate directory name
foreach (split(/\n/, $out)) {
if (/^(\/\S+)/) { $dirlist .= "$1\n"; }
}
if ($in{nfs_dir} !~ /^\/\S+$/) {
&error("'$in{nfs_dir}' is not a valid directory name. The ".
"available directories on $in{nfs_host} are:".
"$dirlist
");
}
# Try a test mount to see if filesystem is available
$temp = &transname();
&make_dir($temp, 0755);
&execute_command("mount $in{nfs_host}:$in{nfs_dir} $temp",
undef, \$mout, \$mout);
if ($mout =~ /No such file or directory/) {
&error("The directory '$in{nfs_dir}' does not exist on the ".
"host $in{nfs_host}. The available directories are:".
"$dirlist
");
}
elsif ($mout =~ /Permission denied/) {
&error("This host is not allowed to mount the directory ".
"$in{nfs_dir} from $in{nfs_host}");
}
elsif ($?) {
&error("NFS Error - $mout");
}
# It worked! unmount
&execute_command("umount $temp");
&unlink_file($temp);
return "$in{nfs_host}:$in{nfs_dir}";
}
elsif ($_[0] eq "smbfs") {
# A windows server filesystem .. check the server and share
$in{'smbfs_server'} =~ /\S/ || &error($text{'linux_eserver'});
$in{'smbfs_share'} =~ /\S/ || &error($text{'linux_eshare'});
return "\\\\".lc($in{'smbfs_server'})."\\".lc($in{'smbfs_share'});
}
else {
# This is some kind of disk-based filesystem.. get the device name
if ($in{'disk_dev'} == 0) {
# From menu
$dv = $in{'disk_select'};
}
else {
# Manually entered
$dv = $in{'dev_path'};
$dv =~ /^\// || &error($text{'freebsd_edevpath'});
}
# If the device entered is a symlink, follow it
if ($dvlink = readlink($dv)) {
if ($dvlink =~ /^\//) { $dv = $dvlink; }
else { $dv =~ /^(.*\/)[^\/]+$/;
$dv = $1.$dvlink;
}
}
# Check if the device actually exists and uses the right filesystem
(-r $dv) || &error(&text('freebsd_edevfile', $dv));
return $dv;
}
}
# check_options(type, device, directory)
# Read options for some filesystem from %in, and use them to update the
# %options array. Options handled by the user interface will be set or
# removed, while unknown options will be left untouched.
sub check_options
{
local($k, @rv);
# Parse the common options first..
if ($_[0] ne "swap") {
delete($options{"ro"}); delete($options{"rw"});
delete($options{"rdonly"});
if ($in{'bsd_ro'}) { $options{'ro'} = ''; }
else { $options{'rw'} = ""; }
delete($options{"sync"}); delete($options{"async"});
if ($in{'bsd_sync'}) { $options{'sync'} = ''; }
delete($options{'nodev'});
if ($in{'bsd_nodev'}) { $options{'nodev'} = ''; }
delete($options{'noexec'});
if ($in{'bsd_noexec'}) { $options{'noexec'} = ''; }
delete($options{'nosuid'});
if ($in{'bsd_nosuid'}) { $options{'nosuid'} = ''; }
delete($options{'noatime'});
if ($in{'bsd_noatime'}) { $options{'noatime'} = ''; }
if ($uname_release =~ /^[34]\./) {
delete($options{'nosymfollow'});
$options{'nosymfollow'} = '' if ($in{'bsd_nosymfollow'});
delete($options{'suiddir'});
$options{'suiddir'} = '' if ($in{'bsd_suiddir'});
}
}
else {
# Swap always has the sw option
$options{'sw'} = "";
}
if ($_[0] eq "ufs") {
# Parse UFS quota options
delete($options{'userquota'}) if ($in{'ufs_userquota'} == 0);
$options{'userquota'} = "" if ($in{'ufs_userquota'} == 1);
$options{'userquota'} = $in{'ufs_groupquota_file'}
if ($in{'ufs_userquota'} == 2);
delete($options{'groupquota'}) if ($in{'ufs_groupquota'} == 0);
$options{'groupquota'} = "" if ($in{'ufs_groupquota'} == 1);
$options{'groupquota'} = $in{'ufs_groupquota_file'}
if ($in{'ufs_groupquota'} == 2);
}
elsif ($_[0] eq "nfs") {
# NFS has a few specific options..
delete($options{'-b'});
$options{'-b'} = "" if ($in{'nfs_b'});
delete($options{'-s'});
$options{'-s'} = "" if ($in{'nfs_s'});
delete($options{'-t'});
$options{'-t'} = $in{'nfs_t'} if (!$in{'nfs_t_def'});
delete($options{'-x'});
$options{'-x'} = $in{'nfs_x'} if (!$in{'nfs_x_def'});
delete($options{'-2'}); delete($options{'-3'});
$options{'-2'} = "" if ($in{'nfs_ver'} == 2);
$options{'-3'} = "" if ($in{'nfs_ver'} == 3);
delete($options{'-R'});
$options{'-R'} = $in{'nfs_r'} if (!$in{'nfs_r_def'});
delete($options{'-a'});
$options{'-a'} = $in{'nfs_a'} if (!$in{'nfs_a_def'});
delete($options{'-T'});
$options{'-T'} = "" if ($in{'nfs_t2'});
}
elsif ($_[0] eq "msdos") {
# MSDOS options for file ownership/perms
delete($options{"-u"}); delete($options{"-g"});
if ($in{'msdos_u'} ne "") { $options{'-u'} = getpwnam($in{'msdos_u'}); }
if ($in{'msdos_g'} ne "") { $options{'-g'} = getgrnam($in{'msdos_g'}); }
delete($options{"-m"});
if (!$in{'msdos_m_def'}) {
$in{'msdos_m'} =~ /^[0-7]{3}$/ ||
&error("'$in{'msdos_m'}' is not a valid octal mask");
$options{'-m'} = $in{'msdos_m'};
}
}
elsif ($_[0] eq "cd9660") {
# Options for iso9660 cd-roms
delete($options{'-r'});
$options{'-r'} = "" if ($in{'cd9660_r'});
delete($options{'-g'});
$options{'-g'} = "" if ($in{'cd9660_g'});
delete($options{'-e'});
$options{'-e'} = "" if ($in{'cd9660_e'});
}
elsif ($_[0] eq "ntfs") {
delete($options{"-u"}); delete($options{"-g"});
if ($in{'ntfs_u'} ne "") { $options{'-u'} = getpwnam($in{'ntfs_u'}); }
if ($in{'ntfs_g'} ne "") { $options{'-g'} = getgrnam($in{'ntfs_g'}); }
delete($options{"-a"});
$options{"-a"} = '' if ($in{'ntfs_a'});
delete($options{"-i"});
$options{"-i"} = '' if ($in{'ntfs_i'});
}
elsif ($_[0] eq "smbfs") {
# Parse SMBFS options
delete($options{'user'});
$options{'user'} = $in{'smbfs_user'} if ($in{'smbfs_user'});
delete($options{'nsmb_password'});
$options{'nsmb_password'} = $in{'smbfs_password'}
if ($in{'smbfs_password'});
delete($options{'nsmb_addr'});
if (!$in{"smbfs_addr_def"}) {
&check_ipaddress($in{"smbfs_addr"}) ||
&error($text{'freebsd_eaddr'});
$options{'nsmb_addr'} = $in{"smbfs_addr"};
}
delete($options{'nsmb_workgroup'});
if (!$in{"smbfs_workgroup_def"}) {
$in{"smbfs_workgroup"} =~ /^\S+$/ ||
&error($text{'freebsd_eworkgroup'});
$options{'nsmb_workgroup'} = $in{"smbfs_workgroup"};
}
}
# Return options string
return &join_options();
}
# create_swap(file, size, units)
# Calls dd and mkswap to setup a swap file
sub create_swap
{
local($out, $bl);
$bl = $_[1] * ($_[2] eq "t" ? 1024*1024*1024 :
$_[2] eq "g" ? 1024*1024 :
$_[2] eq "m" ? 1024 : 1);
$out = &backquote_logged("dd if=/dev/zero of=$_[0] bs=1024 count=$bl 2>&1");
if ($?) { return "dd failed : $out"; }
$out = &backquote_logged("mkswap $_[0] $bl 2>&1");
if ($?) { return "mkswap failed : $out"; }
&system_logged("sync >/dev/null 2>&1");
return 0;
}
# exports_list(host, dirarray, clientarray)
# Fills the directory and client array references with exports from some
# host. Returns an error string if something went wrong
sub exports_list
{
local($dref, $cref, $out, $_);
$dref = $_[1]; $cref = $_[2];
&execute_command("showmount -e ".quotemeta($_[0]), undef, \$out, \$out, 0, 1);
if ($?) { return $out; }
foreach (split(/\n/, $out)) {
if (/^(\/\S*)\s+(.*)$/) {
push(@$dref, $1); push(@$cref, $2);
}
}
return undef;
}
# broadcast_addr()
# Returns a useable broadcast address for finding NFS servers
sub broadcast_addr
{
local($out);
&execute_command("ifconfig -a", undef, \$out, \$out, 0, 1);
if ($out =~ /broadcast\s+(\S+)\s+/) { return $1; }
return "255.255.255.255";
}
sub device_name
{
my ($dev) = @_;
return &bsdfdisk::partition_description($dev);
}
sub files_to_lock
{
return ( $config{'fstab_file'}, $nsmb_conf );
}
# get_nsmb_conf(server, share, user)
# Finds a single nsmb.conf section
sub get_nsmb_conf
{
local $conf;
local $insection = 0;
local $lnum = 0;
open(CONF, "<".$nsmb_conf);
while() {
s/\r|\n//g;
s/^\s*#.*$//;
if (/^\s*\[([^:]+):([^:]+):([^:]+)\]/ &&
lc($1) eq lc($_[0]) && lc($2) eq lc($_[2]) && lc($3) eq lc($_[1])) {
# Start of section
$insection = 1;
$conf = { 'line' => $lnum,
'eline' => $lnum,
'server' => lc($_[0]),
'user' => lc($_[2]),
'share' => lc($_[1]) };
}
elsif (/^\s*\[.*\]/) {
# Start of another section
$insection = 0;
}
elsif (/^\s*(\S+)\s*=\s*(\S+)/ && $insection) {
$conf->{'values'}->{lc($1)} = $2;
$conf->{'eline'} = $lnum;
}
$lnum++;
}
close(CONF);
return $conf;
}
# save_nsmb_conf(&conf)
# Updates or creates a single nsmb.conf section
sub save_nsmb_conf
{
local $lref = &read_file_lines($nsmb_conf);
local @lines = ( "[$_[0]->{'server'}:$_[0]->{'user'}:$_[0]->{'share'}]" );
foreach $k (keys %{$_[0]->{'values'}}) {
push(@lines, $k."=".$_[0]->{'values'}->{$k});
}
if (defined($_[0]->{'line'})) {
# Modifying
splice(@$lref, $_[0]->{'line'}, $_[0]->{'eline'} - $_[0]->{'line'} + 1,
@lines);
}
else {
# Adding
push(@$lref, @lines);
}
&flush_file_lines();
}
# update_nsmb(share, &options)
sub update_nsmb
{
local ($server, $share, $user);
if ($_[0] =~ /^[\\\/]{2}(\S+)\@(\S+)[\\\/](\S+)$/) {
($user, $server, $share) = ($1, $2, $3);
}
elsif ($_[0] =~ /^[\\\/]{2}(\S+)[\\\/](\S+)$/) {
($user, $server, $share) = ("root", $1, $2);
}
else {
&error("Invalid share $_[0]");
}
local $conf = &get_nsmb_conf($server, $share, $user);
$conf ||= { "server" => $server,
"share" => $share,
"user" => $user };
$conf->{'values'} = { };
local %others;
foreach $k (keys %{$_[1]}) {
if ($k =~ /^nsmb_(.*)$/) {
$conf->{'values'}->{$1} = $_[1]->{$k};
}
else {
$others{$k} = $_[1]->{$k};
}
}
&save_nsmb_conf($conf);
return \%others;
}
# read_nsmb(share)
# Returns a hash reference containing options for some share
sub read_nsmb
{
local ($server, $share, $user);
if ($_[0] =~ /^[\\\/]{2}(\S+)\@(\S+)[\\\/](\S+)$/) {
($user, $server, $share) = ($1, $2, $3);
}
elsif ($_[0] =~ /^[\\\/]{2}(\S+)[\\\/](\S+)$/) {
($user, $server, $share) = ("root", $1, $2);
}
else {
&error("Invalid share $_[0]");
}
local $conf = &get_nsmb_conf($server, $share, $user);
if ($conf) {
local (%rv, $k);
foreach $k (keys %{$conf->{'values'}}) {
$rv{"nsmb_".$k} = $conf->{'values'}->{$k};
}
return \%rv;
}
return undef;
}
1;