ACC SHELL
#! /usr/bin/perl
# File: modules/SambaConfig.pm
# Package: Configuration of samba-server
# Summary: Manage samba configuration data (smb.conf).
# Authors: Martin Lazar <mlazar@suse.cz>
#
# $Id: SambaConfig.pm 60974 2010-02-23 10:41:10Z jsuchome $
#
# Functions for acess to samba configuration file. It provide
# unified acces to configuration keys including aliases and other
# difficulty.
#
package SambaConfig;
use strict;
use Data::Dumper;
use YaST::YCP qw(:DATA :LOGGING);
use YaPI;
textdomain "samba-client";
our %TYPEINFO;
YaST::YCP::Import("FileUtils");
YaST::YCP::Import("Mode");
YaST::YCP::Import("SCR");
YaST::YCP::Import("PackageSystem");
###########################################################################
# variables
my %Config; # configuration hash
my %WinbindConfig; # configuration hash for /etc/security/pam_winbind.conf
my %OriginalKeys; # saving original names of smb.conf keys
###########################################################################
# global (static) variables (constants)
# synonyms hash
my %Synonyms = (
"timestamp logs" => "debug timestamp",
"default" => "default service",
"winbind gid" => "idmap gid",
"winbind uid" => "idmap uid",
"lock dir" => "lock directory",
"debuglevel" => "log level",
"protocol" => "max protocol",
"min password len" => "min password length",
"prefered master" => "preferred master",
"auto services" => "preload",
"root" => "root directory",
"root dir" => "root directory",
"browsable" => "browseable",
"casesignames" => "case sensitive",
"create mode" => "create mask",
"directory mode" => "directory mask",
"group" => "force group",
"public" => "guest ok",
"only guest" => "guest only",
"allow hosts" => "hosts allow",
"deny hosts" => "hosts deny",
"directory" => "path",
"exec" => "preexec",
"print ok" => "printable",
"printcap" => "printcap name",
"printer" => "printer name",
"user" => "username",
"users" => "username",
"vfs object" => "vfs objects",
"writable" => "writeable",
);
# inverted synonyms hash
my %InvertedSynonyms = (
"writeable" => "read only",
"writable" => "read only",
);
# keys in /etc/security/pam_winbind.conf
my %winbind_params = (
"cached_login" => 1,
"krb5_auth" => 1,
"krb5_ccache_type" => 1,
"require_membership_of" => 1
);
###########################################################################
# helper functions
# nomralize boolean value
sub toboolean {
my $val = shift;
return undef unless defined $val;
return 0 if $val =~ /^\s*(no|false|disable|0+)\s*$/i;
return 0 unless $val;
return 1;
}
###########################################################################
# public methods
# return modified status
BEGIN{ $TYPEINFO{GetModified} = ["function", "boolean"]; }
sub GetModified {
my ($self) = @_;
foreach (keys %Config) {
return 1 if (defined $Config{$_} && $Config{$_}{_modified});
}
foreach (keys %WinbindConfig) {
return 1 if (defined $WinbindConfig{$_} && $WinbindConfig{$_}{_modified});
}
return 0;
}
# set modified status
BEGIN{ $TYPEINFO{SetModified} = ["function", "boolean"]; }
sub SetModified {
my ($self) = @_;
$Config{"global"}{_modified} = 1;
$WinbindConfig{"global"}{_modified} = 1;
return 1;
}
# unset modified status
BEGIN{ $TYPEINFO{UnsetModified} = ["function", "void"]; }
sub UnsetModified {
my ($self) = @_;
foreach (keys %Config) {
delete $Config{$_}{_modified};
}
foreach (keys %WinbindConfig) {
delete $WinbindConfig{$_}{_modified};
}
}
# dump configuration to STDOUT (for debugging)
BEGIN{ $TYPEINFO{Dump} = ["function", "void", "string"]; }
sub Dump {
my ($self,$preffix) = @_;
$preffix = "SambaConfig: " unless $preffix;
my @out = ();
foreach my $share (sort keys %Config) {
my $out = "$preffix\[$share\]\n";
foreach my $key (sort keys %{$Config{$share}}) {
$out .= "$preffix$key = ".($Config{$share}{$key}||"<undefined>")."\n";
}
push @out, $out;
}
print join("$preffix\n", @out);
print "\n";
}
# read configuration from files:
# /etc/samba/smb.conf, /etc/security/pam_winbind.conf
BEGIN{ $TYPEINFO{Read} = ["function", "boolean", "boolean"]; }
sub Read {
my ($self, $forceReRead) = @_;
if (!PackageSystem->Installed("samba-client")) {
y2error("package samba-client not installed");
return 0;
}
# configuraton already read
return 1 if not $forceReRead and %Config;
# forget previous configuration
%Config = ();
%OriginalKeys = ();
# read the complete global section
my $AllAtOnce = SCR->Read(".etc.smb.all");
# convert .ini agent all-at-once map to %Config
foreach my $section (@{$AllAtOnce->{value}}) {
next if $section->{kind} ne "section";
my $share = $section->{name};
# disabled (comment-out) share
$Config{$share}{_disabled} = 1 if $section->{type};
my $comment = $section->{comment};
$comment =~ s/^[ \t]*[;#]+[ \t]*//gm if $comment;
$comment =~ s/^Share disabled by YaST$//mgi if $comment;
$comment =~ s/^\n*// if $comment;
$comment =~ s/\n*$// if $comment;
$Config{$share}{_comment} = $comment if $comment;
foreach my $line (@{$section->{value}}) {
next if $line->{kind} ne "value";
next if $line->{type} and not $section->{type}; # commented line
my $key = $line->{name};
if ($key ne lc ($key)) {
# we are lowercasing keys later for simpler comparing, now save those
# which were not in lower case before
$OriginalKeys{$share} = {} if !defined $OriginalKeys{$share};
$OriginalKeys{$share}{lc ($key)} = $key;
y2debug ("key $key not in lowercase");
}
if (defined $Config{$share}{$key}) {
$self->ShareAddStr($share, $key, $line->{value});
}
else {
$self->ShareSetStr($share, $key, $line->{value});
}
}
}
$self->UnsetModified();
y2debug ("Read config: ".Dumper(\%Config));
y2debug ("original keys: ".Dumper(\%OriginalKeys));
# configuraton already read
return 1 if not $forceReRead and %WinbindConfig;
%WinbindConfig = ();
# read the complete global section
$AllAtOnce = {};
if (FileUtils->Exists ("/etc/security/pam_winbind.conf")) {
$AllAtOnce = SCR->Read(".etc.security_winbind.all");
}
# convert .ini agent all-at-once map to %WinbindConfig
foreach my $section (@{$AllAtOnce->{value}}) {
next if $section->{kind} ne "section";
my $share = $section->{name};
# disabled (comment-out) share
$WinbindConfig{$share}{_disabled} = 1 if $section->{type};
my $comment = $section->{comment};
$comment =~ s/^[ \t]*[;#]+[ \t]*//gm if $comment;
$comment =~ s/^Share disabled by YaST$//mgi if $comment;
$comment =~ s/^\n*// if $comment;
$comment =~ s/\n*$// if $comment;
$WinbindConfig{$share}{_comment} = $comment if $comment;
foreach my $line (@{$section->{value}}) {
next if $line->{kind} ne "value";
next if $line->{type} and not $section->{type}; # commented line
if (defined $WinbindConfig{$share}{$line->{name}}) {
$self->WinbindShareAddStr($share, $line->{name},$line->{value});
}
else {
$self->WinbindShareSetStr($share, $line->{name},$line->{value});
}
}
}
$self->UnsetModified();
y2debug ("Read config: ".Dumper(\%WinbindConfig));
return 1;
}
# write /etc/security/pam_winbind.conf.
BEGIN{ $TYPEINFO{WriteWinbind} = ["function", "boolean", "boolean"]; }
sub WriteWinbind {
my ($self, $forceWrite) = @_;
y2debug("modified flag is ".($self->GetModified()?"set":"not set"));
return 1 unless $forceWrite or $self->GetModified();
# first, write the global settings complete
if ($forceWrite or $WinbindConfig{global}{_modified}) {
foreach my $key (sort keys %{$WinbindConfig{global}}) {
next if $key =~ /^_/; # skip internal keys
my $val = $WinbindConfig{global}{$key};
if (!defined $val) {
SCR->Write(".etc.security_winbind.value.global.$key", undef);
} else {
if (ref ($val) ne "ARRAY") {
$val = [ String($val) ];
}
SCR->Write(".etc.security_winbind.value.global.$key", $val);
# ensure option is not commented
SCR->Write(".etc.security_winbind.value_type.global.$key", [Integer(0)]);
}
}
# ensure global section is not commented
SCR->Write(".etc.security_winbind.section_type.global", [Integer(0)]);
# remove modified flag
$WinbindConfig{global}{_modified} = undef;
}
# remove removed shares first
foreach my $share (sort grep {!$WinbindConfig{$_}} keys %WinbindConfig) {
SCR->Write(".etc.security_winbind.section.$share", undef);
};
$WinbindConfig{_removed} = undef; # remove modified flag
# write shares
foreach my $share (sort keys %WinbindConfig) {
next unless $WinbindConfig{$share}; # skip removed shares
next if $share eq "global"; # skip global section
next if $share =~ /^_/; # skip internal shares
next unless $forceWrite || $WinbindConfig{$share}{_modified};
# prepare the right type for writing out the value
my $commentout = $WinbindConfig{$share}{_disabled} ? 1 : 0;
# write all the options
foreach my $key (sort keys %{$WinbindConfig{$share}}) {
next if $key =~ /^_/; # skip our internal options
my $val = $WinbindConfig{$share}{$key};
if (!defined $val) {
SCR->Write(".etc.security_winbind.value.$share.$key", undef);
} else {
if (ref ($val) ne "ARRAY") {
$val = [ String($val) ];
}
my $ret1 = SCR->Write(".etc.security_winbind.value.$share.$key", $val);
my $ret = SCR->Write(".etc.security_winbind.value_type.$share.$key", [ Integer($commentout)]);
}
};
# write the type and comment of the section
SCR->Write(".etc.security_winbind.section_type.$share", [Integer($commentout)]);
my $comment = $WinbindConfig{$share}{_comment} || "";
$comment =~ s/\n*$//;
$comment =~ s/^\n*//;
if ($commentout && $comment !~ /.*Share.*Disabled.*/i) {
$comment = ($comment?"$comment\n":"") . "## Share disabled by YaST";
}
$comment =~ s/^(?![#;])/; /mg if $comment;
$comment .= "\n" if $comment;
SCR->Write(".etc.security_winbind.section_comment.$share", [String("\n$comment")]);
# remove modified flag
$WinbindConfig{$share}{_modified} = undef;
};
# commit the changes
if (!SCR->Write(".etc.security_winbind", undef)) {
y2error("Cannot write settings to /etc/security/winbind.conf");
return 0;
}
return 1;
}
# write configuration to file
# TODO: use all-at-once write
BEGIN{ $TYPEINFO{Write} = ["function", "boolean", "boolean"]; }
sub Write {
my ($self, $forceWrite) = @_;
y2debug("modified flag is ".($self->GetModified()?"set":"not set"));
return 1 unless $forceWrite or $self->GetModified();
# first, write the global settings complete
if ($forceWrite or $Config{global}{_modified}) {
foreach my $key (sort keys %{$Config{global}}) {
next if $key =~ /^_/; # skip internal keys
my $val = $Config{global}{$key};
if (!defined $val) {
SCR->Write(".etc.smb.value.global.$key", undef);
} else {
if (ref ($val) ne "ARRAY") {
$val = [ String($val) ];
}
# check if key was not changed on read
my $saved_key = $key;
$saved_key = $OriginalKeys{global}{$key} if defined $OriginalKeys{global}{$key};
SCR->Write(".etc.smb.value.global.$saved_key", $val);
# ensure option is not commented
SCR->Write(".etc.smb.value_type.global.$saved_key", [Integer(0)]);
}
}
# ensure global section is not commented
SCR->Write(".etc.smb.section_type.global", [Integer(0)]);
# remove modified flag
$Config{global}{_modified} = undef;
}
# remove removed shares first
foreach my $share (sort grep {!$Config{$_}} keys %Config) {
SCR->Write(".etc.smb.section.$share", undef);
};
$Config{_removed} = undef; # remove modified flag
# write shares
foreach my $share (sort keys %Config) {
next unless $Config{$share}; # skip removed shares
next if $share eq "global"; # skip global section
next if $share =~ /^_/; # skip internal shares
next unless $forceWrite || $Config{$share}{_modified};
# prepare the right type for writing out the value
my $commentout = $Config{$share}{_disabled} ? 1 : 0;
# write all the options
foreach my $key (sort keys %{$Config{$share}}) {
next if $key =~ /^_/; # skip our internal options
my $val = $Config{$share}{$key};
if (!defined $val) {
SCR->Write(".etc.smb.value.$share.$key", undef);
} else {
if (ref ($val) ne "ARRAY") {
$val = [ String($val) ];
}
# check if key was not changed on read
my $saved_key = $key;
$saved_key = $OriginalKeys{$share}{$key} if defined $OriginalKeys{$share}{$key};
my $ret1 = SCR->Write(".etc.smb.value.$share.$saved_key", $val);
my $ret = SCR->Write(".etc.smb.value_type.$share.$saved_key", [ Integer($commentout)]);
}
};
# write the type and comment of the section
SCR->Write(".etc.smb.section_type.$share", [Integer($commentout)]);
my $comment = $Config{$share}{_comment} || "";
$comment =~ s/\n*$//;
$comment =~ s/^\n*//;
if ($commentout && $comment !~ /.*Share.*Disabled.*/i) {
$comment = ($comment?"$comment\n":"") . "## Share disabled by YaST";
}
$comment =~ s/^(?![#;])/; /mg if $comment;
$comment .= "\n" if $comment;
SCR->Write(".etc.smb.section_comment.$share", [String("\n$comment")]);
# remove modified flag
$Config{$share}{_modified} = undef;
};
# commit the changes
if (!SCR->Write(".etc.smb", undef)) {
y2error("Cannot write settings to /etc/samba/smb.conf");
return 0;
}
return $self->WriteWinbind ($forceWrite);
}
# return list of shares
BEGIN{ $TYPEINFO{GetShares} = ["function", ["list", "string"]]; }
sub GetShares {
my ($self) = @_;
return [ grep {!/^(_.*|global)$/ and defined $Config{$_}} keys %Config ];
}
# return true if configured
BEGIN{ $TYPEINFO{Configured} = ["function", "boolean"]; }
sub Configured {
my ($self) = @_;
return keys %Config ? 1 : 0;
}
# export configuration
BEGIN{ $TYPEINFO{Export} = ["function", "any"]; }
sub Export {
my ($self) = @_;
# remove modified flags and internal shares from config
my @myconfig;
foreach my $share (keys %Config) {
next unless $Config{$share}; # skip removed shares
next if $share =~ /^_/; # skip internal shares
my %section;
$section{name} = $share;
$section{comment} = $Config{$share}{_comment} if $Config{$share}{_comment};
$section{disabled} = Boolean(1) if $Config{$share}{_disabled};
while(my ($key, $val) = each %{$Config{$share}}) {
next unless defined $val; # skip undefined values
next if $key =~ /^_/; # skip internal keys
$key =~ tr/a-zA-Z0-9/_/cs;
$section{parameters}{lc $key} = $val; # TODO check for ARRAY?
}
if (defined $WinbindConfig{$share}) {
while(my ($key, $val) = each %{$WinbindConfig{$share}}) {
next unless defined $val; # skip undefined values
next if $key =~ /^_/; # skip internal keys
$key =~ tr/a-zA-Z0-9/_/cs;
$section{parameters}{lc $key} = $val;
}
}
push @myconfig, \%section;
}
return \@myconfig;
}
# import configuration
BEGIN{$TYPEINFO{Import} = ["function", "void", "any"]}
sub Import {
my ($self, $config) = @_;
%Config = ();
%WinbindConfig = ();
if ($config && ref $config eq "ARRAY") { # normal import
foreach my $section (@$config) {
my $name = $section->{name};
next unless $name;
$self->ShareSetComment($name, $section->{comment}) if $section->{comment};
$self->ShareDisable($name) if $section->{disabled};
while(my ($key, $val) = each %{$section->{parameters}}) {
if (exists $winbind_params{$key}) {
$self->WinbindShareSetStr($name, $key, $val);
}
else {
$key =~ tr/_/ /;
$self->ShareSetStr($name, $key, $val);
}
}
}
$self->UnsetModified();
} elsif ($config && ref $config eq "HASH") { # for testing
%Config = %$config;
}
y2debug("Imported config: ".Dumper(\%Config));
}
###########################################################################
# general shares
# remove share
BEGIN{ $TYPEINFO{ShareRemove} = ["function", "boolean", "string"]; }
sub ShareRemove {
my ($self, $share) = @_;
if (not defined $share) {
y2error("undefned share");
return undef;
}
return 0 unless defined $Config{$share};
$Config{$share} = undef;
$self->ShareSetModified("_removed");
y2debug("ShareRemove($share)");
return 1;
}
# return true if share exists
BEGIN{ $TYPEINFO{ShareExists} = ["function", "boolean", "string"]; }
sub ShareExists {
my ($self, $share) = @_;
if (not defined $share) {
y2error("undefned share");
return undef;
}
return defined $Config{$share};
}
# get share keys
BEGIN{ $TYPEINFO{ShareKeys} = ["function", ["list", "string"], "string"]; }
sub ShareKeys {
my ($self, $share) = @_;
if (not defined $share) {
y2error("undefned share");
return undef;
}
return [] unless defined $Config{$share};
return [ grep {$_!~/^_/ and defined $Config{$share}{$_}} keys %{${Config{$share}}} ];
}
# get share key value
BEGIN{ $TYPEINFO{ShareGetStr} = ["function", "string", "string", "string", "string"]; }
sub ShareGetStr {
my ($self, $share, $key, $default) = @_;
if (not defined $share) {
y2error("undefned share");
return undef;
}
if (not defined $key) {
y2error("undefned key");
return undef;
}
$key = lc($key);
$key = $Synonyms{$key} if exists $Synonyms{$key};
if (exists $InvertedSynonyms{$key}) {
$key = $InvertedSynonyms{$key};
my $val = $Config{$share}{$key};
if (ref $val eq "ARRAY") {
$val= $Config{$share}{$key}[0];
}
$val = toboolean($val);
return defined $val ? ($val ? "No" : "Yes") : $default;
}
if (defined $Config{$share} && $Config{$share}{$key}) {
if (ref $Config{$share}{$key} eq "ARRAY") {
return $Config{$share}{$key}[0];
}
return $Config{$share}{$key};
}
return $default;
}
# get share key values (return a list of values for given key)
BEGIN{ $TYPEINFO{ShareGetList} = ["function", ["list", "string"], "string", "string", ["list", "string"]]; }
sub ShareGetList {
my ($self, $share, $key, $default) = @_;
if (not defined $share) {
y2error("undefned share");
return undef;
}
if (not defined $key) {
y2error("undefned key");
return undef;
}
$key = lc($key);
$key = $Synonyms{$key} if exists $Synonyms{$key};
if (exists $InvertedSynonyms{$key}) {
$key = $InvertedSynonyms{$key};
if (defined $Config{$share}{$key}) {
my $val = $Config{$share}{$key};
if (ref $val eq "ARRAY") {
return $val;
}
return [$val];
}
}
if (defined $Config{$share} && $Config{$share}{$key}) {
if (ref $Config{$share}{$key} eq "ARRAY") {
return $Config{$share}{$key};
}
else {
return [$Config{$share}{$key}];
}
}
return $default;
}
# set share key values
# (no check for InvertedSynonyms)
BEGIN{ $TYPEINFO{ShareSetList} = ["function", "boolean", "string", "string", ["list", "string"]]; }
sub ShareSetList {
my ($self, $share, $key, $val) = @_;
if (not defined $share) {
y2error("undefned share");
return undef;
}
if (not defined $key) {
y2error("undefned key");
return undef;
}
my $modified = 0;
$key = lc($key);
$key = $Synonyms{$key} if exists $Synonyms{$key};
my $old = $Config{$share}{$key};
if (defined $val) {
if (defined $old && ref ($old) eq "ARRAY" && ref ($val) eq "ARRAY") {
return 0 if @$old eq @$val;
}
$modified = 1;
$Config{$share}{$key} = $val;
} else {
$modified = 1 if defined $old;
$Config{$share}{$key} = undef;
}
$self->ShareSetModified($share) if $modified;
y2debug ("ShareSetList($share, $key, ".($val||"<undef>").")") if $modified;
return $modified;
}
# add share key value: used when some key is used multiple times
# no checks for InvertedSynonyms, no checking for changes
BEGIN{ $TYPEINFO{ShareAddStr} = ["function", "boolean", "string", "string", "string"]; }
sub ShareAddStr {
my ($self, $share, $key, $val) = @_;
if (not defined $share) {
y2error("undefned share");
return undef;
}
if (not defined $key) {
y2error("undefned key");
return undef;
}
$key = lc($key);
$key = $Synonyms{$key} if exists $Synonyms{$key};
my $old = $Config{$share}{$key};
if (ref ($old) ne "ARRAY") {
$Config{$share}{$key} = [];
if (defined $old) {
push @{$Config{$share}{$key}}, $old;
}
}
push @{$Config{$share}{$key}}, $val;
$self->ShareSetModified($share);
return 1; # allways modified, since we're always adding
}
# set share key value, return modified boolean
BEGIN{ $TYPEINFO{ShareSetStr} = ["function", "boolean", "string", "string", "string"]; }
sub ShareSetStr {
my ($self, $share, $key, $val) = @_;
if (not defined $share) {
y2error("undefned share");
return undef;
}
if (not defined $key) {
y2error("undefned key");
return undef;
}
my $modified = 0;
$key = lc($key);
$key = $Synonyms{$key} if exists $Synonyms{$key};
if (exists $InvertedSynonyms{$key}) {
$key = $InvertedSynonyms{$key};
my $old = toboolean($Config{$share}{$key});
if (defined $val) {
$val = 1-toboolean($val);
$modified = 1 unless defined $old and $old == $val;
$Config{$share}{$key} = $val ? "Yes" : "No";
} else {
$modified = 1 if defined $old;
# delete $Config{$share}{$key};
$Config{$share}{$key} = undef;
}
} else {
my $old = $Config{$share}{$key};
if (defined $val) {
$modified = 1 unless defined $old and $old eq $val;
$Config{$share}{$key} = $val;
} else {
$modified = 1 if defined $old;
# delete $Config{$share}{$key};
$Config{$share}{$key} = undef;
}
}
$self->ShareSetModified($share) if $modified;
y2debug("ShareSetStr($share, $key, ".($val||"<undef>").")") if $modified;
return $modified;
}
# get share key value as boolean
BEGIN{ $TYPEINFO{ShareGetTruth} = ["function", "boolean", "string", "string", "boolean"]; }
sub ShareGetTruth {
my ($self, $share, $key, $default) = @_;
return toboolean($self->ShareGetStr($share, $key, defined $default ? ($default ? "Yes" : "No") : undef));
}
# get share key value as integer
BEGIN{ $TYPEINFO{ShareGetInteger} = ["function", "integer", "string", "string", "integer"]; }
sub ShareGetInteger {
my ($self, $share, $key, $default) = @_;
return $self->ShareGetStr($share, $key, $default);
}
# set share key value as boolean
BEGIN{ $TYPEINFO{ShareSetTruth} = ["function", "boolean", "string", "string", "boolean"]; }
sub ShareSetTruth {
my ($self, $share, $key, $val) = @_;
return $self->ShareSetStr($share, $key, (defined $val ? ($val ? "Yes" : "No") : undef));
}
# get share key value as integer
BEGIN{ $TYPEINFO{ShareSetInteger} = ["function", "boolean", "string", "string", "integer"]; }
sub ShareSetInteger {
my ($self, $share, $key, $val) = @_;
return $self->ShareSetStr($share, $key, $val);
}
# enable share
BEGIN{ $TYPEINFO{ShareEnable} = ["function", "boolean", "string"]; }
sub ShareEnable {
my ($self, $share) = @_;
if (not defined $share) {
y2error("undefned share");
return undef;
}
return undef unless $self->ShareExists($share);
if ($Config{$share}{_disabled}) {
delete $Config{$share}{_disabled};
y2debug("ShareEnable($share)");
return 1;
}
return 0;
}
# enable share
BEGIN{ $TYPEINFO{ShareDisable} = ["function", "boolean", "string"]; }
sub ShareDisable {
my ($self, $share) = @_;
if (not defined $share) {
y2error("undefned share");
return undef;
}
return undef unless $self->ShareExists($share);
unless ($Config{$share}{_disabled}) {
$Config{$share}{_disabled} = 1;
y2debug("ShareDisable($share)");
return 1;
}
return 0;
}
# enable/disable share
BEGIN{ $TYPEINFO{ShareAdjust} = ["function", "boolean", "string", "boolean"]; }
sub ShareAdjust {
my ($self, $share, $adjust) = @_;
$self->ShareSetModified($share);
return $adjust ? $self->ShareEnable($share) : $self->ShareDisable($share);
}
# is share enabled
BEGIN{ $TYPEINFO{ShareEnabled} = ["function", "boolean", "string"]; }
sub ShareEnabled {
my ($self, $share) = @_;
if (not defined $share) {
y2error("undefned share");
return undef;
}
return undef unless $self->ShareExists($share);
return $Config{$share}{_disabled}?0:1;
}
# return share
BEGIN{ $TYPEINFO{ShareGetMap} = ["function", ["map", "string", "string"], "string"]; }
sub ShareGetMap {
my ($self, $share) = @_;
if (not defined $share) {
y2error("undefned share");
return undef;
}
my %ret;
my $keys = $self->ShareKeys($share);
foreach(@$keys) {
$ret{$_} = (ref $Config{$share}{$_} ne "ARRAY") ? $Config{$share}{$_} :
$Config{$share}{$_}[0];
}
return \%ret;
}
# set share
BEGIN{ $TYPEINFO{ShareSetMap} = ["function", "boolean", "string", ["map", "string", "string"]]; }
sub ShareSetMap {
my ($self, $share, $map) = @_;
if (not defined $share) {
y2error("undefned share");
return undef;
}
my $modified = 0;
foreach(keys %$map) {
$modified |= $self->ShareSetStr($share, $_, $map->{$_});
}
return $modified;
}
# update share
BEGIN{ $TYPEINFO{ShareUpdateMap} = ["function", "boolean", "string", ["map", "string", "string"]]; }
sub ShareUpdateMap {
my ($self, $share, $map) = @_;
if (not defined $share) {
y2error("undefned share");
return undef;
}
my $modified = 0;
foreach(keys %$map) {
$modified |= $self->ShareSetStr($share, $_, $map->{$_})
unless defined $self->ShareGetStr($share, $_, undef);
}
return $modified;
}
# set share modified
BEGIN{ $TYPEINFO{ShareSetModified} = ["function", "boolean", "string"]; }
sub ShareSetModified {
my ($self, $share) = @_;
if (not defined $share) {
y2error("undefned share");
return undef;
}
return 0 if $Config{$share}{_modified};
$Config{$share}{_modified} = 1;
return 1;
}
# get share modified
BEGIN{ $TYPEINFO{ShareGetModified} = ["function", "boolean", "string"]; }
sub ShareGetModified {
my ($self, $share) = @_;
if (not defined $share) {
y2error("undefned share");
return undef;
}
return $Config{$share}{_modified} ? 1 : 0;
}
# get share comment
BEGIN{ $TYPEINFO{ShareGetComment} = ["function", "string", "string"]; }
sub ShareGetComment {
my ($self, $share) = @_;
return $self->ShareGetStr($share, "_comment", undef);
}
# get share comment
BEGIN{ $TYPEINFO{ShareSetComment} = ["function", "void", "string", "string"]; }
sub ShareSetComment {
my ($self, $share, $comment) = @_;
return $self->ShareSetStr($share, "_comment", $comment);
}
###########################################################################
# Homes
BEGIN{ $TYPEINFO{HomesRemove} = ["function", "boolean"]; }
sub HomesRemove { return ShareRemove(shift, "homes"); }
BEGIN{ $TYPEINFO{HomesExists} = ["function", "boolean"]; }
sub HomesExists { return ShareExists(shift, "homes"); }
BEGIN{ $TYPEINFO{HomesKeys} = ["function", ["list", "string"]]; }
sub HomesKeys { return ShareKeys(shift, "homes"); }
BEGIN{ $TYPEINFO{HomesGetStr} = ["function", "string", "string", "string"]; }
sub HomesGetStr { return ShareGetStr(shift, "homes", @_); }
BEGIN{ $TYPEINFO{HomesSetStr} = ["function", "boolean", "string", "string"]; }
sub HomesSetStr { return ShareSetStr(shift, "homes", @_); }
BEGIN{ $TYPEINFO{HomesGetTruth} = ["function", "boolean", "string", "boolean"]; }
sub HomesGetTruth { return ShareGetTruth(shift, "homes", @_); }
BEGIN{ $TYPEINFO{HomesSetTruth} = ["function", "boolean", "string", "boolean"]; }
sub HomesSetTruth { return ShareSetTruth(shift, "homes", @_); }
BEGIN{ $TYPEINFO{HomesGetInteger} = ["function", "integer", "string", "integer"]; }
sub HomesGetInteger { return ShareGetInteger(shift, "homes", @_); }
BEGIN{ $TYPEINFO{HomesSetInteger} = ["function", "boolean", "string", "integer"]; }
sub HomesSetInteger { return ShareSetInteger(shift, "homes", @_); }
BEGIN{ $TYPEINFO{HomesEnable} = ["function", "boolean"]; }
sub HomesEnable { return ShareEnable(shift, "homes", @_); }
BEGIN{ $TYPEINFO{HomesDisable} = ["function", "boolean"]; }
sub HomesDisable { return ShareDisable(shift, "homes", @_); }
BEGIN{ $TYPEINFO{HomesAdjust} = ["function", "boolean", "boolean"]; }
sub HomesAdjust { return ShareAdjust(shift, "homes", @_); }
BEGIN{ $TYPEINFO{HomesEnabled} = ["function", "boolean"]; }
sub HomesEnabled { return ShareEnabled(shift, "homes", @_); }
BEGIN{ $TYPEINFO{HomesSetMap} = ["function", "boolean", ["map", "string", "string"]]; }
sub HomesSetMap { return ShareSetMap(shift, "homes", @_); }
BEGIN{ $TYPEINFO{HomesUpdateMap} = ["function", "boolean", ["map", "string", "string"]]; }
sub HomesUpdateMap { return ShareUpdateMap(shift, "homes", @_); }
BEGIN{ $TYPEINFO{HomesGetMap} = ["function", ["map", "string", "string"]]; }
sub HomesGetMap { return ShareGetMap(shift, "homes", @_); }
BEGIN{ $TYPEINFO{HomesSetModified} = ["function", "void"]; }
sub HomesSetModified { return ShareSetModified(shift, "homes", @_); }
BEGIN{ $TYPEINFO{HomesGetModified} = ["function", "boolean"]; }
sub HomesGetModified { return ShareGetModified(shift, "homes", @_); }
###########################################################################
# Global
BEGIN{ $TYPEINFO{GlobalRemove} = ["function", "boolean"]; }
sub GlobalRemove { return ShareRemove(shift, "global"); }
BEGIN{ $TYPEINFO{GlobalExists} = ["function", "boolean"]; }
sub GlobalExists { return ShareExists(shift, "global"); }
BEGIN{ $TYPEINFO{GlobalKeys} = ["function", ["list", "string"]]; }
sub GlobalKeys { return ShareKeys(shift, "global"); }
BEGIN{ $TYPEINFO{GlobalGetStr} = ["function", "string", "string", "string"]; }
sub GlobalGetStr { return ShareGetStr(shift, "global", @_); }
BEGIN{ $TYPEINFO{GlobalSetStr} = ["function", "boolean", "string", "string"]; }
sub GlobalSetStr { return ShareSetStr(shift, "global", @_); }
BEGIN{ $TYPEINFO{GlobalGetTruth} = ["function", "boolean", "string", "boolean"]; }
sub GlobalGetTruth { return ShareGetTruth(shift, "global", @_); }
BEGIN{ $TYPEINFO{GlobalSetTruth} = ["function", "boolean", "string", "boolean"]; }
sub GlobalSetTruth { return ShareSetTruth(shift, "global", @_); }
BEGIN{ $TYPEINFO{GlobalGetInteger} = ["function", "integer", "string", "integer"]; }
sub GlobalGetInteger { return ShareGetInteger(shift, "global", @_); }
BEGIN{ $TYPEINFO{GlobalSetInteger} = ["function", "boolean", "string", "integer"]; }
sub GlobalSetInteger { return ShareSetInteger(shift, "global", @_); }
BEGIN{ $TYPEINFO{GlobalGetList} = ["function", ["list", "string"], "string", ["list", "string"]]; }
sub GlobalGetList { return ShareGetList(shift, "global", @_); }
BEGIN{ $TYPEINFO{GlobalSetList} = ["function", "boolean", "string", ["list", "string"]]; }
sub GlobalSetList { return ShareSetList(shift, "global", @_); }
BEGIN{ $TYPEINFO{GlobalEnable} = ["function", "boolean"]; }
sub GlobalEnable { ShareEnable(shift, "global", @_); }
BEGIN{ $TYPEINFO{GlobalDisable} = ["function", "boolean"]; }
sub GlobalDisable { return ShareDisable(shift, "global", @_); }
BEGIN{ $TYPEINFO{GlobalAdjust} = ["function", "boolean", "boolean"]; }
sub GlobalAdjust { return ShareAdjust(shift, "global", @_); }
BEGIN{ $TYPEINFO{GlobalEnabled} = ["function", "boolean"]; }
sub GlobalEnabled { return ShareEnabled(shift, "global", @_); }
BEGIN{ $TYPEINFO{GlobalSetMap} = ["function", "boolean", ["map", "string", "string"]]; }
sub GlobalSetMap { return ShareSetMap(shift, "global", @_); }
BEGIN{ $TYPEINFO{GlobalUpdateMap} = ["function", "boolean", ["map", "string", "string"]]; }
sub GlobalUpdateMap { return ShareUpdateMap(shift, "global", @_); }
BEGIN{ $TYPEINFO{GlobalGetMap} = ["function", ["map", "string", "string"]]; }
sub GlobalGetMap { return ShareGetMap(shift, "global", @_); }
BEGIN{ $TYPEINFO{GlobalSetModified} = ["function", "void"]; }
sub GlobalSetModified { return ShareSetModified(shift, "global", @_); }
BEGIN{ $TYPEINFO{GlobalGetModified} = ["function", "boolean"]; }
sub GlobalGetModified { return ShareGetModified(shift, "global", @_); }
##############################################################################
####### functions related to /etc/security/pam_winbind.conf
# set share modified
BEGIN{ $TYPEINFO{WinbindShareSetModified} = ["function", "boolean", "string"]; }
sub WinbindShareSetModified {
my ($self, $share) = @_;
if (not defined $share) {
y2error("undefned share");
return undef;
}
return 0 if $WinbindConfig{$share}{_modified};
$WinbindConfig{$share}{_modified} = 1;
return 1;
}
# get share modified
BEGIN{ $TYPEINFO{WinbindShareGetModified} = ["function", "boolean", "string"]; }
sub WinbindShareGetModified {
my ($self, $share) = @_;
if (not defined $share) {
y2error("undefned share");
return undef;
}
return $WinbindConfig{$share}{_modified} ? 1 : 0;
}
# get share key value from /etc/security/pam_winbind.conf
BEGIN{ $TYPEINFO{WinbindShareGetStr} = ["function", "string", "string", "string", "string"]; }
sub WinbindShareGetStr {
my ($self, $share, $key, $default) = @_;
if (not defined $share) {
y2error("undefned share");
return undef;
}
if (not defined $key) {
y2error("undefned key");
return undef;
}
$key = lc($key);
$key = $Synonyms{$key} if exists $Synonyms{$key};
if (defined $WinbindConfig{$share} && defined $WinbindConfig{$share}{$key})
{
if (ref $WinbindConfig{$share}{$key} eq "ARRAY") {
return $WinbindConfig{$share}{$key}[0];
}
return $WinbindConfig{$share}{$key};
}
return $default;
}
# add share key value: used when some key is used multiple times
BEGIN{ $TYPEINFO{WinbindShareAddStr} = ["function", "boolean", "string", "string", "string"]; }
sub WinbindShareAddStr {
my ($self, $share, $key, $val) = @_;
if (not defined $share) {
y2error("undefned share");
return undef;
}
if (not defined $key) {
y2error("undefned key");
return undef;
}
$key = lc($key);
$key = $Synonyms{$key} if exists $Synonyms{$key};
my $old = $WinbindConfig{$share}{$key};
if (ref ($old) ne "ARRAY") {
$WinbindConfig{$share}{$key} = [];
if (defined $old) {
push @{$WinbindConfig{$share}{$key}}, $old;
}
}
push @{$WinbindConfig{$share}{$key}}, $val;
return 1;
}
# set share key value, return old value
BEGIN{ $TYPEINFO{WinbindShareSetStr} = ["function", "boolean", "string", "string", "string"]; }
sub WinbindShareSetStr {
my ($self, $share, $key, $val) = @_;
if (not defined $share) {
y2error("undefned share");
return undef;
}
if (not defined $key) {
y2error("undefned key");
return undef;
}
my $modified = 0;
$key = lc($key);
$key = $Synonyms{$key} if exists $Synonyms{$key};
my $old = $WinbindConfig{$share}{$key};
if (defined $val) {
$modified = 1 unless defined $old and $old eq $val;
$WinbindConfig{$share}{$key} = $val;
} else {
$modified = 1 if defined $old;
$WinbindConfig{$share}{$key} = undef;
}
$self->WinbindShareSetModified($share) if $modified;
y2debug("WinbindShareSetStr($share, $key, ".($val||"<undef>").")") if $modified;
return $modified;
}
# set share for /etc/security/pam_winbind.conf.
BEGIN{ $TYPEINFO{WinbindShareSetMap} = ["function", "boolean", "string", ["map", "string", "string"]]; }
sub WinbindShareSetMap {
my ($self, $share, $map) = @_;
if (not defined $share) {
y2error("undefned share");
return undef;
}
my $modified = 0;
foreach(keys %$map) {
$modified |= $self->WinbindShareSetStr($share, $_, $map->{$_});
}
return $modified;
}
BEGIN{ $TYPEINFO{WinbindGlobalGetStr} = ["function", "string", "string", "string"]; }
sub WinbindGlobalGetStr { return WinbindShareGetStr(shift, "global", @_); }
BEGIN{ $TYPEINFO{WinbindGlobalSetStr} = ["function", "boolean", "string", "string"]; }
sub WinbindGlobalSetStr { return WinbindShareSetStr(shift, "global", @_); }
BEGIN{ $TYPEINFO{WinbindGlobalSetMap} = ["function", "boolean", ["map", "string", "string"]]; }
sub WinbindGlobalSetMap { return WinbindShareSetMap(shift, "global", @_); }
1;
ACC SHELL 2018