#!/usr/bin/env perl
#
# BEGIN COPYRIGHT BLOCK
# Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
# Copyright (C) 2013 Red Hat, Inc.
# All rights reserved.
#
# License: GPL (version 3 or any later version).
# See LICENSE for details. 
# END COPYRIGHT BLOCK
#

use lib qw(/usr/lib/x86_64-linux-gnu/dirsrv/perl);
use File::Basename;
use DSUtil;

DSUtil::libpath_add("");
DSUtil::libpath_add("/usr/lib");
DSUtil::libpath_add("/usr/lib64");
DSUtil::libpath_add("/usr/lib64");
$ENV{'PATH'} = ":/usr/bin:/usr/lib64/mozldap/";
$ENV{'SHLIB_PATH'} = "$ENV{'LD_LIBRARY_PATH'}";

$dbtype = "ldbm database";
$i = 0;

sub usage {
    print(STDERR "Usage: db2bak.pl [-Z serverID] [-D rootdn] { -w password | -w - | -j filename } [-a backupdir]\n");
    print(STDERR "                 [-t dbtype] [-P protocol] [-h]\n");
    print(STDERR "Options:\n");
    print(STDERR "        -D rootdn     - Directory Manager\n");
    print(STDERR "        -w password   - Directory Manager's password\n");
    print(STDERR "        -w -          - Prompt for Directory Manager's password\n");
    print(STDERR "        -Z serverID   - Server instance identifier\n");
    print(STDERR "        -j filename   - Read Directory Manager's password from file\n");
    print(STDERR "        -A backupdir  - Backup directory symlink(backupdir/ID-<date_time>)\n");
    print(STDERR "        -a backupdir  - Backup directory symlink\n");
    print(STDERR "        -t dbtype     - Database type (default: ldbm database)\n");
    print(STDERR "        -P protocol   - STARTTLS, LDAPS, LDAPI, LDAP (default: uses most secure protocol available)\n");
    print(STDERR "        -h            - Display usage\n");
}

$nestit = 0;
while ($i <= $#ARGV) {
    if ("$ARGV[$i]" eq "-a") {    # backup directory
        $i++; $archivedir = $ARGV[$i];
    } elsif ("$ARGV[$i]" eq "-A") { # backup directory
        $nestit = 1;
        $i++; $archivedir = $ARGV[$i];
    } elsif ("$ARGV[$i]" eq "-D") { # Directory Manager
        $i++; $rootdn = $ARGV[$i];
    } elsif ("$ARGV[$i]" eq "-w") { # Directory Manager's password
        $i++; $passwd = $ARGV[$i];
    } elsif ("$ARGV[$i]" eq "-j") { # Read Directory Manager's password from a file
        $i++; $passwdfile = $ARGV[$i];
    } elsif ("$ARGV[$i]" eq "-t") { # database type
        $i++; $dbtype = $ARGV[$i];
    } elsif ("$ARGV[$i]" eq "-Z") { # Server identifier
        $i++; $servid = $ARGV[$i];    
    } elsif ("$ARGV[$i]" eq "-P") { # protocol preference
        $i++; $protocol = $ARGV[$i];
    } elsif ("$ARGV[$i]" eq "-h") { # help
        &usage; exit(0);
    } else {
        print "ERROR - Unknown option: $ARGV[$i]\n";
        &usage; exit(1);
    }
    $i++;
}

#
# Gather all our config settings
#
($servid, $confdir) = DSUtil::get_server_id($servid, "/etc/default");
%info = DSUtil::get_info($confdir, $host, $port, $rootdn);
$info{rootdnpw} = DSUtil::get_password_from_file($passwd, $passwdfile);
$info{protocol} = $protocol;
$info{args} = "-a";

$mybakdir = "/var/lib/dirsrv/slapd-$servid/bak";

# 
# Construct the task entry
#
($s, $m, $h, $dy, $mn, $yr, $wdy, $ydy, $r) = localtime(time);
$mn++; $yr += 1900;
$taskname = "backup_${yr}_${mn}_${dy}_${h}_${m}_${s}";
$symname = "";
$dirname = "";
if ($archivedir eq "") {
    $archivedir = "${mybakdir}/$servid-${yr}_${mn}_${dy}_${h}_${m}_${s}";
    print("Back up directory: $archivedir\n");
} else {
    if ($nestit == 1) {
        $archivebase = "${servid}-${yr}_${mn}_${dy}_${h}_${m}_${s}";
        $dirname = "${archivedir}";
        $archivedir = "${dirname}/${archivebase}";
    } else {
        my @archivedirs = split(/\//, $archivedir);
        $archivebase = $archivedirs[-1];
        $dirname = dirname(${archivedir});
    }
    if ($mybakdir =~ /^$dirname/) { # $mybakdir is parent; no symlink needed
        $symname = "";
    } else {
        $symname = $archivedir;
    }
    if ($symname eq "") {
        print("Back up directory: $archivedir\n");
    } else {
        print("Back up directory: $archivedir -> $mybakdir/$archivebase\n");
    }

    # If an archive dir is specified, create it as a symlink pointing
    # to the default backup dir not to violate the selinux policy.
    $archivedir = "${mybakdir}/${archivebase}";
}

$dn = "dn: cn=$taskname, cn=backup, cn=tasks, cn=config\n";
$misc = "objectclass: top\nobjectclass: extensibleObject\n";
$cn = "cn: $taskname\n";
$nsarchivedir = "nsArchiveDir: $archivedir\n";
$nsdbtype = "nsDatabaseType: $dbtype\n";
$entry = "${dn}${misc}${cn}${nsarchivedir}${nsdbtype}";

$rc = DSUtil::ldapmod($entry, %info);

$dn =~ s/^dn: //;
$dn =~ s/\n//;
if($rc == 0){
    print "Successfully added task entry \"$dn\"\n";
    if (($symname ne "") && ($dirname ne "")) {
        if (!(-d $dirname)) {
            mkdir ($dirname);
        }
        if (-e $symname) {
            unlink ($symname);
        }
        if (!symlink($archivedir, $symname)) {
            print "Failed to create a symlink from $archivedir to $symname\n";
            exit(1);
        }
    }
} else {
    print "Failed to add task entry \"$dn\" error ($rc)\n";
}

exit($rc);
