#! /usr/bin/perl -w

#
# Copyright (c) 2007 Apple Inc. All rights reserved.
#
# @APPLE_LICENSE_HEADER_START@
#
# This file contains Original Code and/or Modifications of Original Code
# as defined in and that are subject to the Apple Public Source License
# Version 2.0 (the 'License'). You may not use this file except in
# compliance with the License. Please obtain a copy of the License at
# http://www.opensource.apple.com/apsl/ and read it before using this
# file.
#
# The Original Code and all software distributed under the License are
# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
# Please see the License for the specific language governing rights and
# limitations under the License.
#
# @APPLE_LICENSE_HEADER_END@
#

use strict;
$0 = 'smb-config-upgrade';

# Standard install script variables:
# $1: Full path to the installation package.
# $2: Full path to the installation destination.
# $3: Installation volume (or mountpoint) to receive the payload.
# $4: The root directory for the system.
# $SCRIPT_NAME: Filename of the operation executable

my $pkg_path = shift || '';
my $install_dest = shift || '';
my $install_volume = shift || '';
my $install_operation = $ENV{SCRIPT_NAME} ? $ENV{SCRIPT_NAME} : 'postupgrade';

my $SMB_CONF = $ENV{SMB_CONF} ? $ENV{SMB_CONF}
			    : "$install_volume/etc/smb.conf";
my $SMB_TEMPLATE = $ENV{SMB_TEMPLATE} ? $ENV{SMB_TEMPLATE}
			    : "$install_volume/etc/smb.conf.template";

# Read the new template file and gather the required section. the required
# section is all the lines between "BEGIN required" and "END required".
sub read_new_template
{
    my $template = shift;
    my $fh;
    my $lines = [];
    my $snarf = 0;

    open ($fh, "< $template")
	or die "$0: unable to read $template: $!";

    while (my $line = <$fh>) {
	if ($line =~ m/BEGIN required/) {
	    $snarf = 1;
	} elsif ($line =~ m/END required/) {
	    push @$lines, ($line);
	    $snarf = 0;
	}

	if ($snarf) {
	    push @$lines, ($line);
	}
    }

    close($fh);
    return $lines;
}

# Read the existing config file and replace the required section with the
# required section taken from the template config file. Pass other lines
# through unmodified.
sub generate_new_config
{
    my $config = shift;
    my $template = shift;

    my $replace = 0;
    my $fh;
    my $lines = [];

    open ($fh, "< $config")
	or die "$0: unable to read $config: $!";

    while (my $line = <$fh>) {
	if ($line =~ m/BEGIN required/) {
	    $replace = 1;
	    push @$lines, @$template;
	    next;
	} elsif ($line =~ m/END required/) {
	    $replace = 0;
	    next;
	}

	unless ($replace) {
	    push @$lines, ($line);
	}
    }

    close($fh);
    return $lines;
}

sub replace_config
{
    require File::Temp;

    my $config = shift;
    my $lines = shift;

    my ($fh, $name) = File::Temp::tempfile(
				TEMPLATE =>'.smb.upgrade.XXXXXXXX',
				UNLINK => 0,
				DIR => "$install_volume/etc");

    map { $fh->write($_); } @$lines;
    $fh->flush();
    $fh->sync();

    rename $name, $config
	or die "$0: unable to replace $config: $!";

    chmod 0644, $config;
    $fh->close();

    return 1;
}

my $template_lines;
my $config_lines;

# Get the new require config section.
unless ($template_lines = read_new_template($SMB_TEMPLATE)) {
    die "$0: smb.conf template is corrupt or missing";
}

# Replace the existing required section with the new one.
unless ($config_lines = generate_new_config($SMB_CONF, $template_lines)) {
    die "$0: smb.conf is corrupt or missing";
}

if (scalar(@$config_lines) == 0) {
    print "$0: empty $SMB_CONF?\n";
    exit 1;
}

# Write out the merged config file.
unless (replace_config($SMB_CONF, $config_lines)) {
    die "$0: unable to replace $SMB_CONF";
}

exit 0;

