pam_mount/convert_pam_mount_conf.pl

442 lines
8.7 KiB
Perl

#!/usr/bin/perl -w
#
# convert tool for pam_mount.conf
#
# Copyright (c) 2007 SUSE LINUX Products GmbH, Nuernberg, Germany.
# This file is under the same license as pam_mount itself.
#
# Please submit bugfixes or comments via http://bugs.opensuse.org/
#
use Data::Dumper;
use Getopt::Long;
use IO::File;
use XML::Writer;
use strict;
my $OLD_CONF = "-";
my $NEW_CONF = "-";
my $debug = 0;
Getopt::Long::Configure(qw(bundling));
GetOptions(
"i=s" => \$OLD_CONF,
"o=s" => \$NEW_CONF,
"d" => \$debug,
);
my %callbacks = (
"debug" => \&callback_debug,
"logout" => \&callback_logout,
"mkmountpoint" => \&callback_mkmountpoint,
"fsckloop" => \&callback_fsckloop,
"luserconf" => \&callback_luserconf,
"options_allow" => \&callback_options_allow,
"options_deny" => \&callback_options_deny,
"options_require" => \&callback_options_require,
"lsof" => \&callback_lsof,
"fsck" => \&callback_fsck,
"losetup" => \&callback_losetup,
"unlosetup" => \&callback_unlosetup,
"cifsmount" => \&callback_cifsmount,
"smbmount" => \&callback_smbmount,
"ncpmount" => \&callback_ncpmount,
"smbumount" => \&callback_smbumount,
"ncpumount" => \&callback_ncpumount,
"fusemount" => \&callback_fusemount,
"fuseumount" => \&callback_fuseumount,
"umount" => \&callback_umount,
"lclmount" => \&callback_lclmount,
"cryptmount" => \&callback_cryptmount,
"nfsmount" => \&callback_nfsmount,
"mntagain" => \&callback_mntagain,
"mntcheck" => \&callback_mntcheck,
"pmvarrun" => \&callback_pmvarrun,
"volume" => \&callback_volume,
);
my $output = new IO::File("> $NEW_CONF");
my $writer = new XML::Writer(OUTPUT => $output, UNSAFE => 1);
$writer->xmlDecl("UTF-8");
$writer->startTag("pam_mount");
$writer->raw("\n\n");
sub callback_debug
{
my @fields = @_;
$writer->emptyTag("debug", "enable" => $fields[1]);
}
sub callback_logout
{
my @fields = @_;
# we create a default entry here, fields are not evaluated
$writer->emptyTag("logout", "wait" => "2000", "hup" => "0", "term" => "1", "kill" => "1");
}
sub callback_mkmountpoint
{
my @fields = @_;
$writer->emptyTag("mkmountpoint", "enable" => $fields[1]);
}
sub callback_fsckloop
{
my @fields = @_;
$writer->emptyTag("fsckloop", "device" => $fields[1]);
}
sub callback_luserconf
{
my @fields = @_;
$writer->emptyTag("luserconf", "name" => $fields[1].".xml");
print STDERR "Please note that you will also probably have to convert",
$fields[1], "\n";
}
sub callback_options_allow
{
my @fields = @_;
$writer->emptyTag("mntoptions", "allow" => $fields[1]);
}
sub callback_options_deny
{
my @fields = @_;
$writer->emptyTag("mntoptions", "deny" => $fields[1]);
}
sub callback_options_require
{
my @fields = @_;
$writer->emptyTag("mntoptions", "require" => $fields[1]);
}
sub callback_fsck
{
my @fields = @_;
shift @fields;
$writer->startTag("fsck");
$writer->characters(join(" ", @fields));
$writer->endTag("fsck");
}
sub callback_losetup
{
my @fields = @_;
shift @fields;
$writer->startTag("losetup");
$writer->characters(join(" ", @fields));
$writer->endTag("losetup");
}
sub callback_unlosetup
{
my @fields = @_;
shift @fields;
$writer->startTag("unlosetup");
$writer->characters(join(" ", @fields));
$writer->endTag("unlosetup");
}
sub callback_cifsmount
{
my @fields = @_;
shift @fields;
$writer->startTag("cifsmount");
$writer->characters(join(" ", @fields));
$writer->endTag("cifsmount");
}
sub callback_smbmount
{
my @fields = @_;
shift @fields;
$writer->startTag("smbmount");
$writer->characters(join(" ", @fields));
$writer->endTag("smbmount");
}
sub callback_ncpmount
{
my @fields = @_;
shift @fields;
$writer->startTag("ncpmount");
$writer->characters(join(" ", @fields));
$writer->endTag("ncpmount");
}
sub callback_smbumount
{
my @fields = @_;
shift @fields;
$writer->startTag("smbumount");
$writer->characters(join(" ", @fields));
$writer->endTag("smbumount");
}
sub callback_ncpumount
{
my @fields = @_;
shift @fields;
$writer->startTag("ncpumount");
$writer->characters(join(" ", @fields));
$writer->endTag("ncpumount");
}
sub callback_fusemount
{
my @fields = @_;
shift @fields;
$writer->startTag("fusemount");
$writer->characters(join(" ", @fields));
$writer->endTag("fusemount");
}
sub callback_fuseumount
{
my @fields = @_;
shift @fields;
$writer->startTag("fuseumount");
$writer->characters(join(" ", @fields));
$writer->endTag("fuseumount");
}
sub callback_umount
{
my @fields = @_;
shift @fields;
$writer->startTag("umount");
$writer->characters(join(" ", @fields));
$writer->endTag("umount");
}
sub callback_lclmount
{
my @fields = @_;
shift @fields;
$writer->startTag("lclmount");
$writer->characters(join(" ", @fields));
$writer->endTag("lclmount");
}
sub callback_cryptmount
{
my @fields = @_;
shift @fields;
$writer->startTag("cryptmount");
$writer->characters(join(" ", @fields));
$writer->endTag("cryptmount");
}
sub callback_nfsmount
{
my @fields = @_;
shift @fields;
$writer->startTag("nfsmount");
$writer->characters(join(" ", @fields));
$writer->endTag("nfsmount");
}
sub callback_mntagain
{
# not translated - removed in pam_mount 0.32
}
sub callback_lsof
{
# not translated - removed
}
sub callback_mntcheck
{
my @fields = @_;
shift @fields;
$writer->startTag("mntcheck");
$writer->characters(join(" ", @fields));
$writer->endTag("mntcheck");
}
sub callback_pmvarrun
{
my @fields = @_;
shift @fields;
$writer->startTag("pmvarrun");
$writer->characters(join(" ", @fields));
$writer->endTag("pmvarrun");
}
sub callback_volume
{
my @fields = @_;
shift @fields;
my %attr = (
"fstype" => "auto",
);
# search for wrong splits
# happens at 'a value' or "a value"
# and remove quotes around a single value. "value" or 'value'
my @new_fields;
my($nf, $char);
foreach my $f (@fields) {
if (!defined($nf) && $f =~ /^'(.+)'$/) {
push(@new_fields, $1);
} elsif (!defined($nf) && $f =~ /^"(.+)"$/) {
push(@new_fields, $1);
} elsif (!defined($nf) && $f =~ /^'([^']+)$/) {
$nf = $1;
$char = "'";
} elsif (!defined($nf) && $f =~ /^"([^"]+)$/) {
$nf = $1;
$char = "\"";
} elsif (defined($nf) && $f =~ /^([^$char]+)$char$/) {
$nf .= " $1";
push(@new_fields, $nf);
$nf = undef;
$char = undef;
} elsif(defined($nf)) {
$nf .= " $f";
} else {
push(@new_fields, $f);
}
}
@fields = @new_fields;
if ($debug) {
print STDERR Data::Dumper->Dump([@new_fields])
}
foreach my $i (2..7) {
$fields[$i] =~ s/&/\%(USER)/g;
$fields[$i] =~ s/\\\s/ /g;
}
if ($fields[0] =~ /^\@\@(.*)/) {
$attr{sgrp} = "$1";
} elsif ($fields[0] =~ /^\@(.*)/) {
$attr{pgrp} = "$1";
} else {
$attr{user} = "$fields[0]";
}
if (defined($fields[1]) && $fields[1] ne "local") {
$attr{fstype} = $fields[1];
}
if (defined($fields[2]) && $fields[2] ne "-") {
$attr{server} = $fields[2];
}
if (defined($fields[3])) {
$attr{path} = $fields[3];
}
if (defined($fields[4]) && $fields[4] ne "-") {
$attr{mountpoint} = $fields[4];
}
if (defined($fields[5]) && $fields[5] ne "-") {
$attr{options} = $fields[5];
}
if (defined($fields[6]) && $fields[6] ne "-") {
$attr{fskeycipher}= $fields[6];
}
if (defined($fields[7]) && $fields[7] ne "-") {
$attr{fskeypath} = $fields[7];
}
$writer->emptyTag("volume", %attr );
}
sub parse_conf
{
my @file;
open(OUT, "< $OLD_CONF") || die "Cannot open $OLD_CONF: $!\n";
@file = <OUT>;
close OUT;
foreach my $line (@file) {
++$.;
chomp $line;
$line =~ s/^\s+//s;
if (length($line) == 0 || substr($line, 0, 1) eq "#") {
next;
}
my @fields = split(/(?<!\\)\s+/, $line);
for (my $i = 0; $i <= $#fields; ++$i) {
if ($fields[$i] eq "#") {
#
# Old-style config file had this oddity in
# one spot, so need to trim it.
#
splice(@fields, $i);
last;
}
}
if (exists $callbacks{$fields[0]}) {
if ($debug) {
print STDERR "callback_$fields[0] called: ",
join(" ", @fields), "\n";
}
$callbacks{$fields[0]}->(@fields);
$writer->raw("\n\n");
} else {
print STDERR "-" x 40, "\n",
"Unknown command: \"$fields[0]\" near ",
"line $.:\n",
$line, "\n",
"-" x 40, "\n";
return 1;
}
# insert new <logout> field after debug
if( $fields[0] eq "debug" )
{
if ($debug) {
print STDERR "callback_logout called: (default)\n";
}
$callbacks{"logout"}->();
$writer->raw("\n\n");
}
}
return 0;
}
my $ret = parse_conf();
$writer->endTag("pam_mount");
$writer->end();
$output->close();
exit $ret;