summaryrefslogtreecommitdiffstats
path: root/ldap/admin/src/migrateTo4
diff options
context:
space:
mode:
Diffstat (limited to 'ldap/admin/src/migrateTo4')
-rw-r--r--ldap/admin/src/migrateTo41581
1 files changed, 1581 insertions, 0 deletions
diff --git a/ldap/admin/src/migrateTo4 b/ldap/admin/src/migrateTo4
new file mode 100644
index 00000000..862bfff2
--- /dev/null
+++ b/ldap/admin/src/migrateTo4
@@ -0,0 +1,1581 @@
+#!perl
+#
+# BEGIN COPYRIGHT BLOCK
+# Copyright 2001 Sun Microsystems, Inc.
+# Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+# All rights reserved.
+# END COPYRIGHT BLOCK
+#
+
+BEGIN {
+ require 'uname.lib';
+ $isNT = -d '\\';
+ @INC = ( '.', '../../../admin/admin/bin' );
+ grep { s@/@\\@g } @INC if $isNT;
+ $PATHSEP = $isNT ? '\\' : '/';
+ # NT needs quotes around some things unix doesn't
+ $quote = $isNT ? "\"" : "";
+
+ # If this variable is set, all file/directory creation will make sure the mode
+ # and ownership of the destination is the same as the source
+ $PRESERVE = 1 if (!$isNT);
+ $script_suffix = $isNT ? ".bat" : "";
+ $exe_suffix = $isNT ? ".exe" : "";
+ if ($isNT) {
+ $os = "WINNT";
+ } else {
+ $os = &uname("-s");
+ }
+
+ if ($isNT) {
+ # we have to pass batch files directly to the NT command interpreter
+ $com_spec = $ENV{ComSpec};
+ if (!$com_spec) {
+ $com_spec = $ENV{COMSPEC};
+ }
+ if (!$com_spec || ! -f $com_spec) {
+ # find the first available command interpreter
+ foreach $drive (c..z) {
+ $com_spec = "$drive:\\winnt\\system32\\cmd.exe";
+ last if (-f $com_spec);
+ $com_spec = undef;
+ }
+ if (! $com_spec) {
+ # punt and pray
+ $com_spec = 'c:\winnt\system32\cmd.exe';
+ }
+ }
+ }
+
+ # dll suffix for shared libraries in old instance; note that the dll suffix
+ # may have changed for the new instance e.g. AIX now uses .so
+ if ( $os eq "AIX" ) {
+ $dll_suffix = "_shr.a";
+ }
+ elsif ( $os eq "HP-UX" ) {
+ $dll_suffix = ".sl";
+ }
+ elsif ( $os eq "WINNT" ) {
+ $dll_suffix = ".dll";
+ }
+ else {
+ $dll_suffix = ".so";
+ }
+ $slapdExecName = $isNT ? 'slapd.exe' : 'ns-slapd';
+ # if this flag is set, we will migrate the 3.0 and 3.1 databases
+ # by doing a db2ldif -> ldif2db; if this is not set, we will just
+ # copy the directories; right now, we cannot copy the directories,
+ # because the database format has changed for 4.0, and the new
+ # code does not recognize the old db format. It is hoped that it
+ # will by RTM . . .
+ $convertToLDIF = 1;
+ select STDERR;
+ $| = 1;
+ select STDOUT;
+ $| = 1;
+
+ # if the old value for dbcachesize is less than this, make it this
+ $MIN_DBCACHESIZE = '500000';
+}
+
+sub getCwd {
+ my $command = $isNT ? "cd" : "/bin/pwd";
+ open(PWDCMD, "$command 2>&1 |") or
+ die "Error: could not execute $command: $!";
+ # without the following sleep, reading from the pipe will
+ # return nothing; I guess it gives the pwd command time
+ # to get some data to read . . .
+ sleep(1);
+ my $curdir;
+ while (<PWDCMD>) {
+ if (!$curdir) {
+ chomp($curdir = $_);
+ }
+ }
+ my $code = close(PWDCMD);
+# if ($code || $?) {
+# print "$command returned code=$code status=$? dir=$curdir\n";
+# }
+# print "getCwd curdir=\[$curdir\]\n";
+ return $curdir;
+}
+
+sub fixBinaryAttr {
+ my $foo = shift;
+ $foo =~ s/;binary//ig;
+ return $foo;
+}
+
+$type = "slapd";
+$root = $ARGV[0];
+$oldDir = $ARGV[1];
+$newname = $ARGV[2];
+$oldname = $ARGV[3];
+$savedMDLdif = $ARGV[4];
+$savedLdif = $ARGV[5];
+$sieName = $ARGV[6];
+$secPwd = $ARGV[7];
+
+if (($root =~ m#/$#) || ($root =~ m#\\$#)) {
+ chop $root;
+}
+
+if (($oldDir =~ m#/$#) || ($oldDir =~ m#\\$#)) {
+ chop $oldDir;
+}
+
+sub basename {
+ my @list = split(/[\\\/]/, $_[0]);
+ return $list[@list - 1];
+}
+
+# this is used to strip html formatting from output to user
+sub localprint {
+ # arg 1 is string to print
+ # arg 2 is beginning html directive
+ # arg 3 is closing html directive
+ my ($str, $begin, $end) = @_;
+ print $str;
+}
+
+# this is used to run the system() call, capture exit and signal codes,
+# and die() upon badness; the first argument is a directory to change
+# dir to, if any, and the rest are passed to system()
+sub mySystem {
+ my $rc = &mySystemNoDie(@_);
+ my ($dir, @args) = @_;
+ if ($rc == 0) {
+# success
+ } elsif ($rc == 0xff00) {
+ die "Error executing @args: error code $rc: $!";
+ } elsif ($rc > 0x80) {
+ $rc >>= 8;
+ die "Error executing @args: error code $rc: $!";
+ } else {
+ if ($rc & 0x80) {
+ $rc &= ~0x80;
+ }
+ die "Error executing @args: received signal $rc: $!";
+ }
+
+ # usually won't get return value
+ return $rc;
+}
+
+# This version does not die but just returns the error code
+sub mySystemNoDie {
+ my ($dir, @args) = @_;
+ if ($dir && ($dir ne "")) {
+ chdir($dir) or die "Could not change directory to $dir: $!";
+ }
+ my $cmd = $args[0];
+ # the system {$cmd} avoids some NT shell quoting problems if the $cmd
+ # needs to be quoted e.g. contains spaces; the map puts double quotes
+ # around the arguments on NT which are stripped by the command
+ # interpreter cmd.exe; but don't quote things which are already quoted
+ my @fixargs = map { /^[\"].*[\"]$/ ? $_ : $quote . $_ . $quote } @args;
+ my $rc = 0;
+ if ($cmd =~ /[.](bat|cmd)$/) {
+ # we have to pass batch files directly to the NT command interpreter
+ $cmd = $com_spec;
+# print "system $cmd /c \"@fixargs\"\n";
+ $rc = 0xffff & system {$cmd} '/c', "\"@fixargs\"";
+ } else {
+# print "system $cmd @fixargs\n";
+ $rc = 0xffff & system {$cmd} @fixargs;
+ }
+ return $rc;
+}
+
+$serverHome = "$root${PATHSEP}$type-$newname";
+
+$oldHome = "$oldDir${PATHSEP}slapd-$oldname";
+
+# these are the default values used by the 4.0 installer
+$DEFAULT_CHANGELOG_DIR = $serverHome . $PATHSEP . 'logs' . $PATHSEP . 'changelogdb';
+$DEFAULT_CHANGELOG_SUFFIX = "cn=changelog";
+
+# get some information from the new slapd.conf file
+open(INPUT, "$serverHome${PATHSEP}config${PATHSEP}slapd.conf") or
+ die "Could not open file $serverHome${PATHSEP}config${PATHSEP}slapd.conf";
+while (<INPUT>) {
+ if (/^port\s+/i) { chomp($newport = $'); }
+ elsif (/^localhost\s+/i) { chomp($newlocalhost = $'); }
+ elsif (/^localuser\s+/i) { chomp($newuser = $'); }
+}
+close INPUT;
+
+# get some information from the new slapd.ldbm.conf file
+open(INPUT, "$serverHome${PATHSEP}config${PATHSEP}slapd.ldbm.conf") or
+ die "Could not open file $serverHome${PATHSEP}config${PATHSEP}slapd.ldbm.conf";
+while (<INPUT>) {
+ if (/^directory\s+[\"]?(.*?)[\"]?\s*$/i) {
+ # "
+ $newDbDir = $1;
+ # paths are stored in unix format in the config files . . .
+ $newDbDir =~ s#/#\\#g if ($isNT);
+ }
+}
+close INPUT;
+
+# get some information from the old slapd.conf file
+open(INPUT, "$oldHome${PATHSEP}config${PATHSEP}slapd.conf") or
+ die "Could not open file $oldHome${PATHSEP}config${PATHSEP}slapd.conf";
+while (<INPUT>) {
+ if (/^changelogdir\s+[\"]?(.*?)[\"]?\s*$/i) {
+ # "
+ $oldChangeLogDir = $1;
+ # paths are stored in unix format in the config files . . .
+ $oldChangeLogDir =~ s#/#\\#g if ($isNT);
+ }
+ elsif (/^changelogsuffix\s+[\"]?(.*?)[\"]?\s*$/i) {
+ # "
+ $oldChangeLogSuffix = $1;
+ }
+ elsif (/^directory\s+[\"]?(.*?)[\"]?\s*$/i) {
+ # "
+ $oldDbDir = $1;
+ # paths are stored in unix format in the config files . . .
+ $oldDbDir =~ s#/#\\#g if ($isNT);
+ }
+ elsif (/^localuser\s+/i) { chomp($olduser = $'); }
+ elsif (/^encryption-alias\s+/i) { chomp($encryption_alias = $'); }
+ # the user may have given us a network mounted old home directory, but in the
+ # old instance's config files, the root directory referred to is usually
+ # a local directory. For example, suppose there is an automounter map for
+ # hosts which maps onto /h e.g. /h/oldhost would contain all directories
+ # exported via NFS. Similarly, for NT, you could do \\oldhost\c to look
+ # at the C: drive on the old host. Or the user may have network mounted
+ # the old server root some other way. Anyway, we need to determine what
+ # the old server root was local to the original host because that is what
+ # will be referred to it the old config files. So, we look at the errorlog
+ # directive in slapd.conf and use whatever comes before the slapd-oldname
+ elsif (/^errorlog\s+[\"]?(.*)$type-$oldname/i) {
+ # there may be leading "
+ chop($realOldDir = $1);
+ }
+}
+close INPUT;
+
+if (! $realOldDir) {
+ $realOldDir = $oldDir;
+}
+
+$realOldHome = $realOldDir . $PATHSEP . $type . '-' . $oldname;
+
+# the oldDbDir is stored as a local dir, but we may need a network dir
+($networkDbDir = $oldDbDir) =~ s/^$realOldDir/$oldDir/ig;
+
+# list of standard plugins configured out of the box in version 3
+# all of these paths are in unix format . . .
+$oldLibDir = lc("$realOldDir/lib/");
+$oldConfDir = lc("$realOldHome/config/");
+$oldLogsDir = lc("$realOldHome/logs/");
+$oldLibDir =~ s#\\#/#g if ($isNT);
+$oldConfDir =~ s#\\#/#g if ($isNT);
+$oldLogsDir =~ s#\\#/#g if ($isNT);
+
+# note that all of these should be lower case, since NT does not distinguish case
+# and we don't really care about case for plugin directives anyway . . .
+%stdPlugins = (
+ "plugin syntax \"${oldLibDir}syntax-plugin${dll_suffix}\" cis_init", "\n",
+ "plugin syntax \"${oldLibDir}syntax-plugin${dll_suffix}\" ces_init", "\n",
+ "plugin syntax \"${oldLibDir}syntax-plugin${dll_suffix}\" bin_init", "\n",
+ "plugin syntax \"${oldLibDir}syntax-plugin${dll_suffix}\" tel_init", "\n",
+ "plugin syntax \"${oldLibDir}syntax-plugin${dll_suffix}\" int_init", "\n",
+ "plugin syntax \"${oldLibDir}syntax-plugin${dll_suffix}\" dn_init", "\n",
+ "plugin matchingrule \"${oldLibDir}liblcoll${dll_suffix}\" orderingrule_init ${quote}${oldConfDir}slapd-collations.conf$quote", "\n",
+ "plugin database \"${oldLibDir}libback-ldbm${dll_suffix}\" ldbm_back_init", "\n",
+ "plugin postoperation ${quote}${oldLibDir}referint-plugin${dll_suffix}${quote} referint_postop_init 0 ${quote}${oldLogsDir}referint${quote} member uniquemember owner seealso", "\n",
+ "plugin postoperation ${quote}${oldLibDir}referint-plugin${dll_suffix}${quote} referint_postop_init 0 ${quote}${oldLogsDir}referint${quote} 0 member uniquemember owner seealso", "\n",
+ "plugin preoperation ${quote}${oldLibDir}libntsynch${dll_suffix}${quote} libntsynch_plugin_preop_init", "\n",
+ "plugin postoperation ${quote}${oldLibDir}libntsynch${dll_suffix}${quote} libntsynch_plugin_postop_init", "\n"
+);
+
+# list of standard indexes configured out of the box in version 3
+%stdIndex = (
+ 'index aci pres', "\n",
+ 'index cn pres,eq,sub', "\n",
+ 'index sn pres,eq,sub', "\n",
+ 'index givenName pres,eq,sub', "\n",
+ 'index mail pres,eq,sub', "\n",
+ 'index telephoneNumber pres,eq,sub', "\n",
+ 'index ntUserDomainId pres,eq,sub', "\n",
+ 'index uid eq', "\n",
+ 'index changenumber eq', "\n",
+ 'index uniquemember eq', "\n",
+ 'index member eq', "\n",
+ 'index owner eq', "\n",
+ 'index seeAlso eq', "\n"
+);
+
+# These are files included into slapd.conf, slapd.dynamic-ldbm.conf and
+# slapd.ldbm.conf by default in earlier releases. We use this hash to
+# determine if there are user defined files which have been included
+# into the slapd.conf e.g. for user defined attributes, object classes,
+# indexes, etc.
+%stdIncludes = (
+ "${oldConfDir}slapd.at.conf", "\n",
+ "${oldConfDir}slapd.oc.conf", "\n",
+ "${oldConfDir}ns-schema.conf", "\n",
+ "${oldConfDir}ns-globopt.conf", "\n",
+);
+
+
+# list of parameters that we don't care about; these are usually just parameters
+# which hold paths relative to this instance and server root, which change anyway
+%oldParametersToSkip = (
+ 'userat', "\n", # use the new one
+ 'useroc', "\n", # use the new one
+ 'instancedir', "\n", # must be the new one
+ 'dynamicconf', "\n", # use the new one
+ 'directory', "\n", # use the new one
+ 'access', "\n", # obsolete
+ 'defaultaccess', "\n", # obsolete
+ 'security-path', "\n", # obsolete
+ 'localuser', "\n", # use the newly configured suitespot user
+ 'port', "\n", # the new port must already be set either as determined from
+ # the old config or because we are migrating into the MC
+ # instance and cannot change the port number
+ 'rootdn', "\n", # the new rootdn must already be set either as determined from
+ # the old config or because we are migrating into the MC
+ # instance and cannot change it
+ 'rootpw', "\n", # the new rootpw must already be set either as determined from
+ # the old config or because we are migrating into the MC
+ # instance and cannot change it
+);
+
+# list of old ldbm specific parameters. These parameters may be present in the
+# old slapd.conf, but have been moved to the new slapd.ldbm.conf
+%oldLdbmParameters = (
+ 'database', "\n",
+ 'lookthroughlimit', "\n",
+ 'mode', "\n",
+ 'cachesize', "\n",
+ 'dbcachesize', "\n",
+ 'allidsthreshold', "\n",
+ 'parentcheck', "\n",
+);
+
+# list of old slapd.conf parameters which have been moved to the new dse.ldif
+%oldDSEParameters = (
+ 'encryption-alias', "\n",
+ 'sslclientauth', "\n"
+);
+
+($oldversion,$oldminor) = &getVersion($oldDir);
+($newversion,$newminor) = &getVersion($root);
+
+# if there was no old user specified
+if (! $isNT && ! $olduser) {
+ # get the olduid and oldgid from doing a stat of the db directory
+ ($olduid, $oldgid) = (stat($networkDbDir))[4..5];
+}
+# convert the user names to numeric uids
+if ($PRESERVE) {
+ if (! $olduid && $olduser) {
+ ($login,$pass,$olduid,$oldgid) = getpwnam($olduser);
+ }
+ ($login,$pass,$newuid,$newgid) = getpwnam($newuser);
+}
+
+# copy the old config files
+&copyDir("$oldHome${PATHSEP}config", "$serverHome${PATHSEP}migrate_config");
+
+print "Migrating log files . . .\n";
+# copy the log files
+$srcdir = "$oldHome${PATHSEP}logs";
+opendir(LOGDIR, $srcdir) or
+ die "Error: could not open log file dir $srcdir : $!";
+foreach (readdir(LOGDIR)) {
+ if (! /[.][.]?/ && -f "$srcdir${PATHSEP}$_") {
+ &copyBinFile("$srcdir${PATHSEP}$_",
+ "$serverHome${PATHSEP}logs${PATHSEP}${_}.migrate");
+ }
+}
+closedir(LOGDIR);
+
+# copy the ssl directory
+&copyDir("$oldHome${PATHSEP}ssl", "$serverHome${PATHSEP}ssl");
+
+# copy the cert db and key files
+if ( -d "$oldDir${PATHSEP}alias" && $encryption_alias ) {
+ $aliasDir = "$root${PATHSEP}alias";
+ if (! -d $aliasDir) {
+ mkdir($aliasDir, 0750);
+ }
+ $adminDir = $root . $PATHSEP . 'bin' . $PATHSEP . 'admin' . $PATHSEP .
+ 'admin' . $PATHSEP . 'bin';
+ print "Migrating the key and certificate databases . . .\n";
+ mySystem($adminDir, $adminDir . $PATHSEP . 'sec-migrate',
+ $oldDir, $encryption_alias, $root, $sieName, $secPwd);
+ # copy the old password file
+ if (-f "$oldDir${PATHSEP}alias${PATHSEP}$encryption_alias-password.txt") {
+ &copyBinFile(
+ "$oldDir${PATHSEP}alias${PATHSEP}$encryption_alias-password.txt",
+ "$aliasDir${PATHSEP}$type-$newname-password.txt"
+ );
+ if ($newversion >= 4 && $newminor >= 1) {
+ # need to convert the old format to new pin format
+ print "Converting password file to new pin format . . .\n";
+ $script = "$root${PATHSEP}bin${PATHSEP}slapd${PATHSEP}admin${PATHSEP}bin${PATHSEP}migratePwdFile";
+ mySystem($aliasDir, $, $script, $root, "$type-$newname");
+ }
+ }
+
+ # get the new key/cert db filenames
+ opendir(CERTDIR, $aliasDir) or
+ die "Error: could not open cert dir $aliasDir: $!";
+ foreach (readdir(CERTDIR)) {
+ if (/^$sieName/i) {
+ if (/[-]cert/) {
+ $newcertdb = $_;
+ } elsif (/[-]key/) {
+ $newkeydb = $_;
+ }
+ }
+ }
+ closedir(CERTDIR);
+}
+
+$needAclUpg = 0;
+if ($oldversion == 1) {
+ $needAclUpg = 1;
+ $convertToLDIF = 1; # always need this for conversion from 1.X db
+}
+
+# Copy/Convert ldif files in ldif/
+print "Migrating old LDIF files . . .\n";
+&copyLdif;
+
+if ($convertToLDIF) {
+ # Converting database
+ print "Migrating database to LDIF . . .\n";
+ $oldLdif = "$oldHome${PATHSEP}ldif${PATHSEP}old.ldif";
+ &db2ldif($networkDbDir, $oldLdif);
+ if ($needAclUpg) {
+ print "Converting ACLs in old data . . .\n";
+ &mySystem("$root${PATHSEP}bin${PATHSEP}slapd${PATHSEP}server",
+ "$root${PATHSEP}bin${PATHSEP}slapd${PATHSEP}server${PATHSEP}" .
+ "aclupg$exe_suffix", '-d', '-i',
+ $oldLdif, '-o',
+ "$oldHome${PATHSEP}ldif${PATHSEP}aclupg.ldif");
+ unlink($oldLdif);
+ rename("$oldHome${PATHSEP}ldif${PATHSEP}aclupg.ldif", $oldLdif);
+ }
+ chown $newuid, $newgid, $oldLdif if (!$isNT);
+# copy the changelogdb directory
+# how to handle a 1.0 change log?
+# &copyDir($changelogdir, "$serverHome${PATHSEP}changelogdb") if ($changelogdir);
+}
+
+# Compare each configuration file against its default version. If it has changed,
+# notify the user that the file has changed and will need to be checked by the
+# user. This should be safe to do because there should be no path information
+# stored in these conf files, which are just schema stuff.
+print "Migrating configuration files . . .\n";
+$origFilePath = "$root${PATHSEP}bin${PATHSEP}slapd${PATHSEP}install${PATHSEP}version${oldversion}";
+$srcdir = "$serverHome${PATHSEP}migrate_config";
+opendir(CONFDIR, $srcdir) or
+ die "Error: could not open migrated config dir $srcdir: $!";
+foreach $file (readdir(CONFDIR)) {
+ $origFile = $origFilePath . $file;
+ if (-f $origFile) {
+ $diffs = &diff("$srcdir${PATHSEP}$file", $origFile);
+ if ($diffs) {
+ print "File $srcdir${PATHSEP}$file could not be migrated\n";
+ print "because it is different than\n";
+ print "the standard installed version. You will need to check this\n";
+ print "file and make sure its changes are compatible with the new\n";
+ print "directory server. Here are the differences:\n";
+ print $diffs, "\n";
+ } else {
+# print "No changes to old config file $srcdir${PATHSEP}$file\n";
+ }
+ }
+}
+closedir(CONFDIR);
+
+# make a backup of the current user_at and user_oc files, and copy the old ones
+# into the config directory
+
+&copyBinFile("$serverHome${PATHSEP}config${PATHSEP}slapd.user_at.conf",
+ "$serverHome${PATHSEP}config${PATHSEP}slapd.user_at.conf.bak");
+&copyBinFile("$serverHome${PATHSEP}config${PATHSEP}slapd.user_oc.conf",
+ "$serverHome${PATHSEP}config${PATHSEP}slapd.user_oc.conf.bak");
+
+if (-f "$serverHome${PATHSEP}migrate_config${PATHSEP}slapd.user_at.conf") {
+ &copyAndEditTextFile(
+ "$serverHome${PATHSEP}migrate_config${PATHSEP}slapd.user_at.conf",
+ "$serverHome${PATHSEP}config${PATHSEP}slapd.user_at.conf",
+ \&fixBinaryAttr);
+}
+
+if (-f "$serverHome${PATHSEP}migrate_config${PATHSEP}slapd.user_oc.conf") {
+ &copyAndEditTextFile(
+ "$serverHome${PATHSEP}migrate_config${PATHSEP}slapd.user_oc.conf",
+ "$serverHome${PATHSEP}config${PATHSEP}slapd.user_oc.conf",
+ \&fixBinaryAttr);
+}
+
+# parse the parameters from the old configuration files and put them into
+# the new configuration files
+&fixConf("$serverHome${PATHSEP}migrate_config${PATHSEP}slapd.conf",
+ "$serverHome${PATHSEP}migrate_config${PATHSEP}slapd.dynamic_ldbm.conf",
+ "$serverHome${PATHSEP}migrate_config${PATHSEP}dse.ldif",
+ "$serverHome${PATHSEP}config${PATHSEP}slapd.conf",
+ "$serverHome${PATHSEP}config${PATHSEP}slapd.ldbm.conf",
+ "$serverHome${PATHSEP}config${PATHSEP}dse.ldif");
+
+# copy in old data and any data we wanted to save
+if ($convertToLDIF) {
+ print "Migrating old database to new database . . .\n";
+ &manyLdif2db($savedMDLdif, $oldLdif, $savedLdif);
+ unlink $savedMDLdif, $savedLdif;
+}
+
+if ($oldChangeLogDir && -e $oldChangeLogDir) {
+ print "Migrating changelog database . . .\n";
+ my $realDir = $oldChangeLogDir;
+ $realDir =~ s/^$realOldDir/$oldDir/ig;
+ if ($convertToLDIF) {
+ $srcDir = $realDir;
+ $destDir = $DEFAULT_CHANGELOG_DIR;
+ $srcLDIF = "$oldHome${PATHSEP}ldif${PATHSEP}changelog.ldif";
+ $destLDIF = "$serverHome${PATHSEP}ldif${PATHSEP}changelog.ldif";
+ mkdir( $destDir , 0755 ) if !( -e $destDir);
+ # Converting database
+ if ( !$isNT && $newuser ) {
+ chown($newuid, $newgid, $destDir);
+ }
+ &other_db2ldif($srcDir, $srcLDIF);
+ if ($needAclUpg) {
+ &mySystem("$root${PATHSEP}bin${PATHSEP}slapd${PATHSEP}server",
+ "$root${PATHSEP}bin${PATHSEP}slapd${PATHSEP}server" .
+ "${PATHSEP}aclupg$exe_suffix", '-d', '-i',
+ $srcLDIF, '-o', $destLDIF);
+ } else {
+ &copyBinFile($srcLDIF, $destLDIF);
+ }
+ &other_ldif2db($destLDIF, $destDir, 'slapd.ldbm.conf',
+ "suffix \"$oldChangeLogSuffix\"");
+ } else {
+ # the dir is stored as a local dir, but we may need a network dir here
+ &copyDir($realDir, $DEFAULT_CHANGELOG_DIR, '\.share$');
+ }
+}
+
+if ($convertToLDIF) {
+ # Convert the db backup, bak/
+ print "Migrating database backups . . .\n";
+ &copyBak;
+} else {
+ # just copy the directories over
+ &copyDir($networkDbDir, "$serverHome${PATHSEP}db", '\.share$');
+ &copyDir("$oldHome${PATHSEP}bak", "$serverHome${PATHSEP}bak", '\.share$');
+}
+
+if (-f $oldLdif) {
+ unlink($oldLdif);
+}
+
+exit(0);
+
+############# END OF PROCESSING; SUBROUTINES FOLLOW
+
+# This subroutine merges the old and new source files into the new destination file
+sub fixConf {
+ my $oldsrc = shift;
+ my $oldldbmsrc = shift;
+ my $olddseldif = shift;
+ my $newsrc = shift;
+ my $newldbmsrc = shift;
+ my $newdseldif = shift;
+
+ # read the old conf file into a hash table
+ open( OLDSRC, $oldsrc ) ||
+ die "Can't open $oldsrc: $!: ";
+ LINE: while ( <OLDSRC> ) {
+ if (/^\s*#/) { # skip comments
+ next LINE;
+ }
+ if (/^\s*$/) { # skip blank lines
+ next LINE;
+ } elsif (/^plugin/i) {
+ chomp($_);
+ if (! &isAStandardPlugin($_)) {
+ push @badPlugins, $_;
+ }
+ } elsif (/^index/i) {
+ chomp($_);
+ if (! &isAStandardIndex($_)) {
+ push @newIndex, $_;
+ }
+ } elsif (/^include\s+[\"]?(.*?)[\"]?\s*$/i) {
+ # strip leading and trailing "
+ if (! &isAStandardInclude($1)) {
+ push @newInclude, $1;
+ }
+ } elsif (/^dbcachesize\s+[\"]?(.*?)[\"]?\s*$/i) {
+ # strip leading and trailing "
+ $param = 'dbcachesize';
+ $value = $1;
+ if ($value < $MIN_DBCACHESIZE) {
+ $value = $MIN_DBCACHESIZE;
+ }
+
+ if ($oldLdbmParameters{lc($param)}) {
+ $oldldbmhash{lc($param)} = $value;
+ } else {
+ $oldhash{lc($param)} = $value;
+
+ }
+ } elsif (/^errorlog/i) {
+ $oldhash{'errorlog-logging-enabled'} = "on";
+ } elsif (/^accesslog/i) {
+ $oldhash{'accesslog-logging-enabled'} = "on";
+ } elsif (/^auditlog/i) {
+ $oldhash{'auditlog-logging-enabled'} = "on";
+ } elsif (/^replogfile/i) {
+ # replogfile was only used in 1.X, and it had no suffix
+ $oldhash{'changelogdir'} = $DEFAULT_CHANGELOG_DIR;
+ $oldhash{'changelogsuffix'} = $DEFAULT_CHANGELOG_SUFFIX;
+ } elsif (/^changelogdir/i) {
+ # force use of default
+ $oldhash{'changelogdir'} = $DEFAULT_CHANGELOG_DIR;
+ } elsif (/^\s*(\S+)\s+[\"]?(.*?)[\"]?\s*$/i) {
+ # strip leading and trailing "
+ $param = $1;
+ $value = $2;
+ if ($oldParametersToSkip{lc($param)}) {
+ next LINE;
+ } elsif (lc($param) eq 'suffix') {
+ if (lc($value) cmp 'cn=schema') {
+ $oldsuffix{lc($value)} = $value;
+ }
+ } else {
+ if ($oldLdbmParameters{lc($param)}) {
+ $oldldbmhash{lc($param)} = $value;
+ } elsif ($oldDSEParameters{lc($param)}) {
+ if (lc($param) eq 'encryption-alias') {
+ if ($newcertdb) {
+ $olddsehash{'nscertfile'} = "alias/$newcertdb";
+ } else {
+ $olddsehash{'nscertfile'} = "alias/$type-$newname-cert.db";
+ }
+ if ($newkeydb) {
+ $olddsehash{'nskeyfile'} = "alias/$newkeydb";
+ } else {
+ $olddsehash{'nskeyfile'} = "alias/$type-$newname-key.db";
+ }
+ } elsif (lc($param) eq 'sslclientauth') {
+ $olddsehash{'nssslclientauth'} = $value;
+ } else {
+ $olddsehash{lc($param)} = $value;
+ }
+ } elsif (($param eq 'passwdhash') &&
+ ((! $value) || ($value eq ""))) {
+ # 3.X used "" as an alias for "clear"
+ $oldhash{lc($param)} = 'clear';
+ } else {
+ $oldhash{lc($param)} = $value;
+ }
+ }
+ }
+ }
+ close(OLDSRC);
+
+ $oldhash{'errorlog-logging-enabled'} = "off"
+ if (! $oldhash{'errorlog-logging-enabled'});
+ $oldhash{'accesslog-logging-enabled'} = "off"
+ if (! $oldhash{'accesslog-logging-enabled'});
+ $oldhash{'auditlog-logging-enabled'} = "off"
+ if (! $oldhash{'auditlog-logging-enabled'});
+
+ # read the old ldbm conf file into a hash table; note that there may not be
+ # one, so don't complain
+ open( OLDSRC, $oldldbmsrc );
+ LINE2: while ( <OLDSRC> ) {
+ if (/^\s*#/) { # skip comments
+ next LINE2;
+ }
+ if (/^\s*$/) { # skip blank lines
+ next LINE2;
+ }
+ if (/^index/i) {
+ chomp($_);
+ if (! &isAStandardIndex($_)) {
+ push @newIndex, $_;
+ }
+ next LINE2;
+ }
+ if (/^plugin/i) {
+ chomp($_);
+ if (! &isAStandardPlugin($_)) {
+ push @badLdbmPlugins, $_;
+ }
+ next LINE2;
+ }
+ if (/^include\s+/i) {
+ chomp($inc = $');
+ $inc =~ s/\"//g;
+ # strip " characters
+ if (! &isAStandardInclude($inc)) {
+ push @newLdbmInclude, $inc;
+ }
+ next LINE2;
+ }
+ if (/^dbcachesize\s+[\"]?(.*?)[\"]?\s*$/i) {
+ # strip leading and trailing "
+ $param = 'dbcachesize';
+ $value = $1;
+ if ($value < $MIN_DBCACHESIZE) {
+ $value = $MIN_DBCACHESIZE;
+ }
+
+ $oldldbmhash{lc($param)} = $value;
+ next LINE2;
+ }
+
+ if (/^\s*(\S+)\s+[\"]?(.*?)[\"]?\s*$/) {
+ # strip leading and trailing "
+ $param = $1;
+ $value = $2;
+ if ($oldParametersToSkip{lc($param)}) {
+ next LINE2;
+ } elsif (lc($param) eq 'suffix') {
+ if (lc($value) cmp 'cn=schema') {
+ $oldsuffix{lc($value)} = $value;
+ }
+ } else {
+ $oldldbmhash{lc($param)} = $value;
+ }
+ }
+ }
+ close(OLDSRC);
+
+ # read the old dse.ldif file into a hash table; note that there may not be
+ # one, so don't complain
+ open(OLDSRC, $olddseldif);
+ while ( <OLDSRC> ) {
+ chomp($_);
+ if ( /^passwordchange:\s*/i ) {
+ if ($' eq "must") {
+ $oldhash{'pw_change'} = "on";
+ $oldhash{'pw_must_change'} = "on";
+ } elsif ($' eq "may") {
+ $oldhash{'pw_change'} = "on";
+ $oldhash{'pw_must_change'} = "off";
+ } else {
+ $oldhash{'pw_change'} = "off";
+ $oldhash{'pw_must_change'} = "off";
+ }
+ } elsif ( /^passwordchecksyntax:\s*/i ) {
+ if ($' > 0) {
+ $oldhash{'pw_syntax'} = "on";
+ } else {
+ $oldhash{'pw_syntax'} = "off";
+ }
+ } elsif ( /^passwordminlength:\s*/i ) {
+ $oldhash{'pw_minlength'} = $';
+ } elsif ( /^passwordexp:\s*/i ) {
+ if ($' > 0) {
+ $oldhash{'pw_exp'} = "on";
+ } else {
+ $oldhash{'pw_exp'} = "off";
+ }
+ } elsif ( /^passwordmaxage:\s*/i ) {
+ $oldhash{'pw_maxage'} = $';
+ } elsif ( /^passwordwarning:\s*/i ) {
+ $oldhash{'pw_warning'} = $';
+ } elsif ( /^passwordkeephistory:\s*/i ) {
+ if ($' > 0) {
+ $oldhash{'pw_history'} = "on";
+ } else {
+ $oldhash{'pw_history'} = "off";
+ }
+ } elsif ( /^passwordinhistory:\s*/i ) {
+ $oldhash{'pw_inhistory'} = $';
+ } elsif ( /^passwordlockoutduration:\s*/i ) {
+ $oldhash{'pw_lockduration'} = $';
+ } elsif ( /^passwordlockout:\s*/i ) {
+ if ($' > 0) {
+ $oldhash{'pw_lockout'} = "on";
+ } else {
+ $oldhash{'pw_lockout'} = "off";
+ }
+ } elsif ( /^passwordmaxfailure:\s*/i ) {
+ $oldhash{'pw_maxfailure'} = $';
+ } elsif ( /^passwordunlock:\s*/i ) {
+ if ($' > 0) {
+ $oldhash{'pw_unlock'} = "on";
+ } else {
+ $oldhash{'pw_unlock'} = "off";
+ }
+ } elsif ( /^passwordresetduration:\s*/i ) {
+ $oldhash{'pw_resetfailurecount'} = $';
+ }
+ }
+ close(OLDSRC);
+
+ open(NEWSRC, $newsrc ) || die "Can't open $newsrc: $!: ";
+ open(NEWDEST, ">$newsrc.tmp" ) || die "Can't create $newsrc.tmp: $!: ";
+ while ( <NEWSRC> ) {
+ # make sure the dynamicconf parameter is the last one in the file
+ if (/^dynamicconf/i) {
+ # print the parameters which exist in the old file but do not
+ # exist in the new file; these are the parameters we have not
+ # deleted from oldhash
+ print NEWDEST "#These additional parameters have been migrated\n";
+ foreach $param (sort keys %oldhash) {
+ if (lc($param) eq 'passwdhash') {
+ $pwhash = $oldhash{lc($param)};
+ # if the old value was not set, don't set the new value either
+ # just have the server use the default value
+ if ($pwhash && $pwhash ne "" && $pwhash ne '""') {
+ print NEWDEST 'pw_storagescheme', "\t", $pwhash, "\n";
+ }
+ } elsif (lc($param) eq 'ntsynchusessl') {
+ print NEWDEST 'NTSynchUseSSL', "\t", $oldhash{lc($param)}, "\n";
+ } else {
+ print NEWDEST $param, "\t", "\"$oldhash{lc($param)}\"",
+ "\n";
+ }
+ }
+ print NEWDEST "#End of additional migrated parameters\n\n";
+ # use the temp one for now until we have the real one in place, then
+ # we will change this back
+ print NEWDEST "dynamicconf\t\"$newldbmsrc.tmp\"\n";
+ } elsif (/^\s*#/) {
+ print NEWDEST $_;
+ } elsif (/^include/ && @newInclude) {
+ my $newConfDir = $serverHome . '/' . 'config' . '/';
+ $newConfDir =~ s#\\#/#g if ($isNT);
+ print NEWDEST "# These non standard includes were migrated:\n";
+ print "These non standard includes were migrated:\n";
+ while (@newInclude) {
+ my $oldPath = shift @newInclude;
+ # oldPath is a local path; we need a network path here because
+ # we will be copying the file
+ $oldPath =~ s/^$realOldDir/$oldDir/ig;
+ my $base = &basename($oldPath);
+ my $newone = $newConfDir . $base;
+ # convert to new path
+ print NEWDEST "include ", $quote, $newone, $quote, "\n";
+ print $newone, "\n";
+ # now, change path separators back to the correct ones for
+ # the os
+ $oldPath =~ s#/#\\#g if ($isNT);
+ $newone =~ s#/#\\#g if ($isNT);
+ &copyAndEditTextFile($oldPath, $newone, \&fixBinaryAttr);
+ }
+ print NEWDEST "# end of migrated includes\n";
+ print "Be sure to check the new slapd.conf file to make sure the order\n";
+ print "is correct and there are no conflicts with new config files,\n";
+ print "object classes, attributes, etc.\n";
+ print NEWDEST $_;
+ } elsif (/^\s*(\S+)\s+[\"]?(.*?)[\"]?\s*$/) {
+ $param = $1;
+ $value = $2;
+ # see if the parameter is set in the old config file
+ if ($oldhash{lc($param)}) {
+ # only set the parameter if the old value is different than
+ # the new value
+ if ($value cmp $oldhash{lc($param)}) {
+ print NEWDEST "#This parameter was migrated: the original value was $value\n";
+ print NEWDEST $param, "\t", "\"$oldhash{lc($param)}\"", "\n";
+ } else {
+ print NEWDEST $_;
+ }
+ delete $oldhash{lc($param)};
+ } else {
+ # just print the parameter
+ print NEWDEST $_;
+ }
+ } else {
+ print NEWDEST $_;
+ }
+ }
+ close (NEWSRC);
+
+ # print the bad plugins, commented out, at the end of the file
+ if (@badPlugins) {
+ print NEWDEST "#The following non standard plugins were detected:\n";
+ print "The following non standard plugins were detected:\n";
+ foreach (@badPlugins) {
+ print NEWDEST "#", $_, "\n";
+ print $_, "\n";
+ }
+ print NEWDEST "#These plugins will probably need to be recompiled for this release\n";
+ print "These plugins will probably need to be recompiled for this release\n";
+ print NEWDEST "#of directory server, or at the very least, reconfigured.\n";
+ print "of directory server, or at the very least, reconfigured.\n";
+ }
+
+ close( NEWDEST );
+
+ open(NEWSRC, $newldbmsrc ) || die "Can't open $newldbmsrc: $!: ";
+ open(NEWDEST, ">$newldbmsrc.tmp" ) || die "Can't create $newldbmsrc.tmp: $!: ";
+ while ( <NEWSRC> ) {
+ if (/^\s*#/) {
+ print NEWDEST $_;
+ } elsif (/^include/ && @newLdbmInclude) {
+ my $newConfDir = $serverHome . '/' . 'config' . '/';
+ $newConfDir =~ s#\\#/#g if ($isNT);
+ print NEWDEST "# These non standard ldbm includes were migrated:\n";
+ print "These non standard includes were migrated:\n";
+ while (@newLdbmInclude) {
+ my $oldPath = shift @newInclude;
+ # oldPath is a local path; we need a network path here because
+ # we will be copying the file
+ $oldPath =~ s/^$realOldDir/$oldDir/ig;
+ my $base = &basename($oldPath);
+ my $newone = $newConfDir . $base;
+ # convert to new path
+ print NEWDEST "include ", $quote, $newone, $quote, "\n";
+ print $newone, "\n";
+ # now, change path separators back to the correct ones for
+ # the os
+ $oldPath =~ s#/#\\#g if ($isNT);
+ $newone =~ s#/#\\#g if ($isNT);
+ &copyBinFile($oldPath, $newone);
+ }
+ print NEWDEST "# end of migrated includes\n";
+ print "Be sure to check the new slapd.ldbm.conf file to make sure the order\n";
+ print "is correct and there are no conflicts with new config files,\n";
+ print "object classes, attributes, etc.\n";
+ print NEWDEST $_;
+ } elsif (/^\s*(\S+)\s+[\"]?(.*?)[\"]?\s*$/) {
+ # strip " characters
+ $param = $1;
+ $value = $2;
+ if (lc($param) eq 'suffix') {
+ if ($oldsuffix{lc($value)}) {
+ delete $oldsuffix{lc($value)};
+ }
+ print NEWDEST $_;
+ } elsif ($oldhash{lc($param)}) {
+ # only set the parameter if the old value is different than
+ # the new value
+ if ($value cmp $oldhash{lc($param)}) {
+ print NEWDEST "#This parameter was migrated: the original value was $value\n";
+ print NEWDEST $param, "\t", "\"$oldhash{lc($param)}\"", "\n";
+ } else {
+ print NEWDEST $_;
+ }
+ delete $oldhash{lc($param)};
+ } elsif ($oldldbmhash{lc($param)}) {
+ # only set the parameter if the old value is different than
+ # the new value
+ if ($value cmp $oldldbmhash{lc($param)}) {
+ print NEWDEST "#This parameter was migrated: the original value was $value\n";
+ print NEWDEST $param, "\t", "\"$oldldbmhash{lc($param)}\"", "\n";
+ } else {
+ print NEWDEST $_;
+ }
+ delete $oldldbmhash{lc($param)};
+ } else {
+ # just print the parameter
+ print NEWDEST $_;
+ }
+ } else {
+ print NEWDEST $_;
+ }
+ }
+ close (NEWSRC);
+
+ # add the suffixes we didn't already have
+ if (%oldsuffix) {
+ print NEWDEST "#These suffixes were migrated\n";
+ foreach (values %oldsuffix) {
+ print NEWDEST 'suffix', "\t", "\"$_\"", "\n";
+ }
+ }
+
+ # add the user defined indexes
+ if (@newIndex) {
+ print NEWDEST "#These indexes were migrated\n";
+ while (@newIndex) {
+ print NEWDEST shift(@newIndex), "\n";
+ }
+ }
+
+ # print the bad plugins, commented out, at the end of the file
+ if (@badLdbmPlugins) {
+ print NEWDEST "#The following non standard plugins were detected:\n";
+ print "The following non standard ldbm plugins were detected:\n";
+ foreach (@badLdbmPlugins) {
+ print NEWDEST "#", $_, "\n";
+ print $_, "\n";
+ }
+ print NEWDEST "#These plugins will probably need to be recompiled for this release\n";
+ print "These plugins will probably need to be recompiled for this release\n";
+ print NEWDEST "#of directory server, or at the very least, reconfigured.\n";
+ print "of directory server, or at the very least, reconfigured.\n";
+ }
+
+ close( NEWDEST );
+
+ open(NEWSRC, $newdseldif ) || die "Can't open $newdseldif: $!: ";
+ open(NEWDEST, ">$newdseldif.tmp" ) || die "Can't create $newdseldif.tmp: $!: ";
+ $inEncryptionConfig = 0;
+ while ( <NEWSRC> ) {
+ if (/^\s*#/) {
+ print NEWDEST $_;
+ } elsif (/^\s*$/) {
+ if ($inEncryptionConfig) { # end of entry
+ $inEncryptionConfig = 0;
+ # if attributes were present in the old config but not
+ # in the new one, add them to the end of the entry
+ foreach $key (keys %olddsehash) {
+ print NEWDEST $key, ': ', $olddsehash{$key}, "\n";
+ }
+ }
+ print NEWDEST $_;
+ } elsif (/cn=encryption\s*,\s*cn=config/) {
+ $inEncryptionConfig = 1;
+ print NEWDEST $_;
+ } elsif (/^\s*(\S+):\s*(.*)$/) {
+ $param = $1;
+ $value = $2;
+ if ($olddsehash{lc($param)}) {
+ # only set the parameter if the old value is different than
+ # the new value
+ if ($value cmp $olddsehash{lc($param)}) {
+ print NEWDEST $param, "\t", $olddsehash{lc($param)}, "\n";
+ } else {
+ print NEWDEST $_;
+ }
+ delete $olddsehash{lc($param)};
+ } else {
+ # just print the parameter
+ print NEWDEST $_;
+ }
+ } else {
+ print NEWDEST $_;
+ }
+ }
+ close (NEWSRC);
+ close( NEWDEST );
+
+ # final step: use the slapd_config program to check the new config file
+ my $rc = &mySystemNoDie("$root${PATHSEP}bin${PATHSEP}slapd${PATHSEP}server",
+ "$root${PATHSEP}bin${PATHSEP}slapd${PATHSEP}server" .
+ "${PATHSEP}slapd_config${exe_suffix}",
+ '-c', '-f', "$newsrc.tmp");
+
+ # if the check failed, run slapd_config again in verbose mode to provide
+ # more information to the user; this will die and abort processing
+ if ($rc) {
+ print "The following problems were found with the new configuration:\n";
+ &mySystem("$root${PATHSEP}bin${PATHSEP}slapd${PATHSEP}server",
+ "$root${PATHSEP}bin${PATHSEP}slapd${PATHSEP}server" .
+ "${PATHSEP}slapd_config${exe_suffix}",
+ '-f', "$newsrc.tmp");
+ }
+
+ # if we got here, the files were good
+ # save a copy of the old config files
+ &copyBinFile("$newsrc", "$newsrc.save");
+ &copyBinFile("$newldbmsrc", "$newldbmsrc.save");
+
+ # replace the temporary dynamicconf directive with the real one
+ open(NEWSRC, "$newsrc.tmp") or die "Could not open file $newsrc.tmp: $!";
+ open(NEWDEST, ">$newsrc") or die "Could not write file $newsrc: $!";
+ while(<NEWSRC>) {
+ if (/^dynamicconf/i) {
+ print NEWDEST "dynamicconf\t\"$newldbmsrc\"\n";
+ } else {
+ print NEWDEST;
+ }
+ }
+ close NEWSRC;
+ close NEWDEST;
+
+ &copyBinFile("$newldbmsrc.tmp", "$newldbmsrc");
+ &copyBinFile("$newdseldif.tmp", "$newdseldif");
+}
+
+sub copyDir {
+ my $src = shift;
+ my $dest = shift;
+ my $exclude = shift;
+
+ opendir( SRC, $src ) or die "Can't open directory $src: $!: ";
+ my $mode;
+ my $uid;
+ my $gid;
+ mkdir ( $dest , 0755 ) if !( -e $dest );
+ if ($PRESERVE) {
+ $mode = (stat($src))[2];
+ ($uid, $gid) = (stat(_))[4..5];
+ # Make sure files owned by the old user are owned by the
+ # new user
+ if ($uid == $olduid) {
+ $uid = $newuid;
+ $gid = $newgid;
+ }
+ chown $uid, $gid, $dest;
+ chmod $mode, $dest;
+ }
+ local ( @files ) = readdir ( SRC );
+ closedir( SRC );
+ for ( @files ) {
+ if ( $_ eq "." || $_ eq ".." ) {
+ next;
+ } elsif ( $exclude && /$exclude/ ) {
+ next;
+ } elsif( -d "$src${PATHSEP}$_") {
+ &copyDir ( "$src${PATHSEP}$_", "$dest${PATHSEP}$_" );
+ } else {
+ &copyBinFile ( "$src${PATHSEP}$_", "$dest${PATHSEP}$_");
+ }
+ }
+}
+
+sub copyBinFile {
+ my $src = shift;
+ my $dest = shift;
+ my $buf = "";
+ my $bufsize = 8192;
+
+ open( SRC, $src ) || die "Can't open $src: $!\n";
+ # if we are given a directory destination instead of a file, extract the
+ # filename portion of the source to use as the destination filename
+ if (-d $dest) {
+ $dest = $dest . $PATHSEP . &basename($src);
+ }
+ open( DEST, ">$dest" ) || die "Can't create $dest: $!\n";
+ binmode SRC;
+ binmode DEST;
+ if ($PRESERVE) {
+ $mode = (stat($src))[2];
+ ($uid, $gid) = (stat(_))[4..5];
+ # Make sure files owned by the old user are owned by the
+ # new user
+ if ($uid == $olduid) {
+ $uid = $newuid;
+ $gid = $newgid;
+ }
+ chown $uid, $gid, $dest;
+ chmod $mode, $dest;
+ }
+ while (read(SRC, $buf, $bufsize)) {
+ print DEST $buf;
+ }
+ close( SRC );
+ close( DEST );
+}
+
+sub isAStandardPlugin {
+ my $line = shift;
+
+ chomp($line);
+ return $stdPlugins{lc($line)};
+}
+
+sub isAStandardIndex {
+ my $line = shift;
+
+ chomp($line);
+ return $stdIndex{$line};
+}
+
+sub isAStandardInclude {
+ my $line = shift;
+
+ chomp($line);
+ return $stdIncludes{lc($line)};
+}
+
+# Do a file copy, but convert path names as the file gets copied
+# Don't convert paths that don't point anywere, except for log files
+# push non-converted paths to the results list
+# If you are xlating paths that contain one another, the long paths must come
+# first
+sub xlatePath {
+ my $src = shift;
+ my $dest = shift;
+
+ open( SRC, $src ) || die "Can't open $src: $!: ";
+ open( DEST, ">$dest" ) || die "Can't create $dest: $!: ";
+ if ($PRESERVE) {
+ $mode = (stat($src))[2];
+ ($uid, $gid) = (stat(_))[4..5];
+ # Make sure files owned by the old user are owned by the
+ # new user
+ if ($uid == $olduid) {
+ $uid = $newuid;
+ $gid = $newgid;
+ }
+ chown $uid, $gid, $dest;
+ chmod $mode, $dest;
+ }
+ while ( <SRC> ) {
+ print DEST &xlatePaths( $_, @_ );
+ }
+ close( SRC );
+ close( DEST );
+}
+
+# translate paths in the string
+sub xlatePaths {
+ my $line = shift;
+ my @otherParams = @_;
+ my $numXs = shift;
+ my @srcPaths = splice( @_, 0, $numXs );
+ my @destPaths = splice( @_, 0, $numXs );
+ my @allowedEmpty = @_;
+ my @pathLengths = map { length( $_ ) } @srcPaths;
+ my $i;
+ my $pre;
+ my $post;
+ my $allowed;
+ my $path;
+ my $destPath;
+
+ # replace the src paths with the dest paths
+ # NOTE: this algorithm will only work if the longest paths
+ # are replaced first e.g. strlen(srcPath[N]) > strlen(srcPath[N+1])
+ # and none of the destpaths match any of the srcpaths
+ for ( $i = 0 ; $i < $numXs ; ++$i ) {
+ if ($srcPaths[$i] ne $destPaths[$i]) {
+ $line =~ s/$srcPaths[$i]/$destPaths[$i]/g;
+ }
+ }
+
+ return $line;
+}
+
+sub copyBak {
+ opendir( OLDBAK, "$oldHome${PATHSEP}bak" ) ||
+ die "Can't open directory $oldHome${PATHSEP}bak: $!: ";
+ local ( @dirs ) = readdir( OLDBAK );
+ closedir ( OLDBAK );
+ for ( @dirs ) {
+ if ( $_ eq "." || $_ eq ".." ) {
+ next;
+ } elsif ( -d "$oldHome${PATHSEP}bak${PATHSEP}$_" ) {
+ $srcDir = "$oldHome${PATHSEP}bak${PATHSEP}$_";
+ $destDir = "$serverHome${PATHSEP}bak${PATHSEP}$_";
+ $srcLDIF = "$oldHome${PATHSEP}ldif${PATHSEP}bak.ldif";
+ $destLDIF = "$serverHome${PATHSEP}ldif${PATHSEP}bak.ldif";
+ mkdir( $destDir , 0755 ) if !( -e $destDir);
+ # Converting database
+ if ( !$isNT && $newuser ) {
+ chown($newuid, $newgid,
+ "$serverHome${PATHSEP}bak", $destDir);
+ }
+ &other_db2ldif($srcDir, $srcLDIF);
+ if ($needAclUpg) {
+ &mySystem("$root${PATHSEP}bin${PATHSEP}slapd${PATHSEP}server",
+ "$root${PATHSEP}bin${PATHSEP}slapd${PATHSEP}server" .
+ "${PATHSEP}aclupg$exe_suffix", '-d', '-i',
+ $srcLDIF, '-o', $destLDIF);
+ } else {
+ &copyBinFile($srcLDIF, $destLDIF);
+ }
+ &other_ldif2db($destLDIF, $destDir);
+ }
+ }
+}
+
+sub other_db2ldif {
+ my $srcDbDir = shift;
+ my $ldif = shift;
+
+ if ($oldversion == 1) {
+ &db2ldif($srcDbDir, $ldif);
+ } else {
+ # make a dummy version of the current slapd.conf and tell it that
+ # the db directory is really the back up directory so that we can
+ # trick ns-slapd db2ldif to do the right thing; Oh how I wish there
+ # were a simple ldbmcat utility for 3.X and 4.0 . . .
+ &xlatePath("$oldHome${PATHSEP}config${PATHSEP}slapd.conf",
+ "$oldHome${PATHSEP}config${PATHSEP}slapd.conf.bak",
+ 3,
+ "$realOldHome",
+ "$oldDbDir",
+ "slapd.dynamic_ldbm.conf",
+ "$oldHome",
+ "$srcDbDir",
+ "slapd.dynamic_ldbm.conf.bak",
+ '/logs/');
+ &xlatePath("$oldHome${PATHSEP}config${PATHSEP}slapd.dynamic_ldbm.conf",
+ "$oldHome${PATHSEP}config${PATHSEP}slapd.dynamic_ldbm.conf.bak",
+ 2,
+ "$realOldHome",
+ "$oldDbDir",
+ "$oldHome",
+ "$srcDbDir",
+ '/logs/');
+ # now do the ldif2db with our munged conf files . . .
+ &db2ldif($srcDbDir, $ldif,
+ "$oldHome${PATHSEP}config${PATHSEP}slapd.conf.bak");
+ unlink("$oldHome${PATHSEP}config${PATHSEP}slapd.conf.bak");
+ unlink("$oldHome${PATHSEP}config${PATHSEP}slapd.dynamic_ldbm.conf.bak");
+ }
+}
+
+sub other_ldif2db {
+ my $ldif = shift;
+ my $destDbDir = shift;
+ my $confFile = shift;
+ my $directiveToAdd = shift;
+
+ # make a dummy version of the current slapd.conf and slapd.ldbm.conf
+ # to point to the database directory we want to populate instead of
+ # the standard
+ &xlatePath("$serverHome${PATHSEP}config${PATHSEP}slapd.conf",
+ "$serverHome${PATHSEP}config${PATHSEP}slapd.conf.bak",
+ 3,
+ "$newDbDir",
+ "slapd.ldbm.conf",
+ "slapd.dynamic_ldbm.conf",
+ "$destDbDir",
+ "slapd.ldbm.conf.bak",
+ "slapd.ldbm.conf.bak",
+ '/logs/');
+ &xlatePath("$serverHome${PATHSEP}config${PATHSEP}slapd.ldbm.conf",
+ "$serverHome${PATHSEP}config${PATHSEP}slapd.ldbm.conf.bak",
+ 1,
+ "$newDbDir",
+ "$destDbDir",
+ '/logs/');
+
+ # we may need to add something to a config file e.g. when migrating the change
+ # log, we need to add suffix $changeLogSuffix to slapd.ldbm.conf in order to
+ # ldif2db it without error
+ if ($confFile && $directiveToAdd) {
+ open(CONFADD, ">>$serverHome${PATHSEP}config${PATHSEP}${confFile}.bak") or
+ die "Could not append to $serverHome${PATHSEP}config${PATHSEP}${confFile}.bak: $!";
+ print CONFADD $directiveToAdd, "\n";
+ close(CONFADD);
+ }
+
+ &mySystem("$root${PATHSEP}bin${PATHSEP}slapd${PATHSEP}server",
+ "$root${PATHSEP}bin${PATHSEP}slapd${PATHSEP}server" .
+ "${PATHSEP}$slapdExecName",
+ "ldif2db", '-C', '-f',
+ "$serverHome${PATHSEP}config${PATHSEP}slapd.conf.bak", '-i',
+ "$ldif");
+ unlink("$serverHome${PATHSEP}config${PATHSEP}slapd.conf.bak");
+ unlink("$serverHome${PATHSEP}config${PATHSEP}slapd.ldbm.conf.bak");
+ unlink($ldif);
+}
+
+sub manyLdif2db {
+ my @args = ();
+ while (@_) {
+ push @args, '-i', shift(@_);
+ }
+ &mySystem("$root${PATHSEP}bin${PATHSEP}slapd${PATHSEP}server",
+ "$root${PATHSEP}bin${PATHSEP}slapd${PATHSEP}server" .
+ "${PATHSEP}$slapdExecName", "ldif2db", '-C', '-f',
+ "$serverHome${PATHSEP}config${PATHSEP}slapd.conf", @args);
+}
+
+sub copyLdif {
+ opendir (LDIFDIR, "$oldHome${PATHSEP}ldif" );
+ local ( @files ) = readdir ( LDIFDIR );
+ closedir(LDIFDIR);
+ for ( @files ) {
+ if ( $_ eq "." || $_ eq ".." || $_ eq "demo.ldif" ) {
+ next;
+ }
+
+ if ($needAclUpg) {
+ &mySystem("$root${PATHSEP}bin${PATHSEP}slapd${PATHSEP}server",
+ "$root${PATHSEP}bin${PATHSEP}slapd${PATHSEP}server${PATHSEP}" .
+ "aclupg$exe_suffix", '-d', '-i',
+ "$oldHome${PATHSEP}ldif${PATHSEP}$_", '-o',
+ "$serverHome${PATHSEP}ldif${PATHSEP}$_");
+ } else {
+ &copyBinFile("$oldHome${PATHSEP}ldif${PATHSEP}$_",
+ "$serverHome${PATHSEP}ldif${PATHSEP}$_");
+ }
+ }
+}
+
+sub genAcl {
+ my $filename = "$root${PATHSEP}httpacl${PATHSEP}generated.$type-$newname.acl";
+
+ open( S, ">$filename" ) || die "Can't create file $filename: $!: ";
+ print S "version $newversion.0;\n";
+ print S "acl agents;\n";
+ print S "authenticate (user, group) {\n";
+ print S " prompt = \"Agent Service\";\n";
+ print S "};\n";
+ print S "deny absolute (all) (user != all);\n";
+ print S "allow absolute (all) (user = all);\n";
+ print S "\n";
+ print S "acl \"default\";\n";
+ print S "allow (read, list, execute,info) user = \"anyone\";\n";
+ print S "allow (write, delete) user = \"all\";\n";
+ close( S );
+}
+
+sub getVersion {
+ my $rootDir = shift;
+ my $version = 0;
+ my $minor = 0;
+ my $progDir = "${PATHSEP}bin${PATHSEP}slapd${PATHSEP}server${PATHSEP}";
+ my $progDir2 = "${PATHSEP}bin${PATHSEP}slapd${PATHSEP}";
+ # get the current directory so we can go back to it
+ my $curdir = &getCwd;
+
+ # find the slapd executable
+ $prog = $rootDir . $progDir . $slapdExecName;
+ if (! -f $prog) {
+ $prog = $rootDir . $progDir2 . $slapdExecName;
+ if (-f $prog && $isNT) {
+ # if slapd is in bin/slapd and we're on NT, just assume version 1;
+ # apparently, slapd.exe doesn't like the -v argument . . .
+ return ( '1', $minor );
+ }
+ }
+
+ # read the old version from the old slapd program
+ chdir($rootDir . $progDir) or
+ die "Could not chdir to $rootDir${progDir}: $!: ";
+ open(F, "${quote}${quote}$prog${quote} -v${quote} 2>&1 |") or
+ die "Could not run slapd program $prog: $!";
+ sleep(1); # allow some data to accumulate in the pipe
+# print "Output from $prog -v:\n";
+ while (<F>) {
+# print;
+ if (/^Netscape-Directory\/(\d+)\.(\d+)/) {
+ $version = $1;
+ $minor = $2;
+ last;
+ }
+ }
+ $code = close(F);
+# print "$prog returned code=$code status=$?\n";
+
+ # done determining versions; go back to orig directory
+ chdir($curdir) or die "Could not chdir to $curdir: $!: ";
+
+ $version == 0 and
+ die "Could not determine version of the directory server in $rootDir: ";
+
+ return ( $version, $minor );
+}
+
+# this subroutine implements a very stupid version of diff
+sub diff {
+ my $f1 = shift;
+ my $f2 = shift;
+ my $retval = "";
+
+ open(F1, "$f1") or die "Could not open file $f1";
+ open(F2, "$f2") or close(F1), die "Could not open file $f2";
+
+ while (defined($l1 = <F1>) && defined($l2 = <F2>)) {
+ if (!($l1 eq $l2)) {
+ # ignore comments
+ if (($l1 =~ /^#/) && ($l2 =~ /^#/)) {
+ next;
+ }
+ # ignore whitespace
+ $l1 =~ s/\s//g;
+ $l2 =~ s/\s//g;
+
+ if (!($l1 eq $l2)) {
+ $retval .= "< ${l1}> $l2";
+ }
+ }
+ }
+
+ close(F1);
+ close(F2);
+
+ if ($retval eq "") {
+ return undef;
+ }
+
+ return $retval;
+}
+
+# unfortunately, we can't use the shell script/batch file because it may
+# not have been updated if the user changed the database directory
+sub db2ldif {
+ my ($srcDbDir, $ldif, $conf) = @_;
+
+ if ($oldversion == 1) {
+ my $dir = "$oldDir${PATHSEP}bin${PATHSEP}slapd${PATHSEP}server";
+ chdir($dir) or die "Error: could not change directory to $dir: $!";
+ my @cmd = ("${quote}$dir${PATHSEP}ldbmcat${exe_suffix}${quote}", '-n',
+ "${quote}$srcDbDir${PATHSEP}id2entry.dbb${quote}");
+ open(LDBMCAT, "${quote}@cmd${quote}|") or
+ die "Error: could not execute @cmd: $!";
+ open(OUTLDIF, "> $ldif") or
+ die "Error: could not write to $ldif: $!";
+ sleep(1); # allow pipe to fill with data
+ $ii = 0; # counter
+ while (<LDBMCAT>) {
+ print OUTLDIF;
+ ++$ii;
+ if (($ii % 250) == 0) {
+ print " Processed ", $ii, " lines\n";
+ }
+ }
+ close(LDBMCAT);
+ close(OUTLDIF);
+ } else {
+ if (!$conf) {
+ $conf = "$oldHome${PATHSEP}config${PATHSEP}slapd.conf";
+ }
+ my $baseldif = &basename($ldif);
+ if ($baseldif eq $ldif) {
+ $ldif = "$oldHome${PATHSEP}ldif${PATHSEP}$ldif";
+ }
+ my $dir = "$oldDir${PATHSEP}bin${PATHSEP}slapd${PATHSEP}server";
+ chdir($dir) or
+ die "Error: could not change directory to $dir: $!";
+
+ my @cmd =
+ ( "${quote}$oldDir${PATHSEP}bin${PATHSEP}slapd${PATHSEP}server" .
+ "${PATHSEP}$slapdExecName${quote}", "db2ldif", '-n', '-f',
+ "${quote}$conf${quote}", '-a', "${quote}$ldif${quote}",
+ '-d', '1' );
+ open(DB2LDIF, "${quote}@cmd${quote} 2>&1|") or
+ die "Error: could not execute @cmd: $!";
+ sleep(1); # allow pipe to fill with data
+ $ii = 0; # counter
+ while (<DB2LDIF>) {
+ ++$ii;
+ if (($ii % 250) == 0) {
+ print " Processing...\n";
+ }
+ }
+ close(DB2LDIF);
+ }
+ print " Done.\n";
+}
+
+# this subroutine works like sed in that it will create another version
+# of the input file with some editing done
+# the file should be a text file
+sub copyAndEditTextFile {
+ my $srcFile = shift;
+ my $destFile = shift;
+ my $sub = shift;
+
+ open(SRCFILE, "$srcFile") or die "Error: could not open file $srcFile: $!";
+ open(DESTFILE, ">$destFile") or die "Error: could not write file $destFile:
+$!";
+
+ while (<SRCFILE>) {
+ my $newline = &$sub($_);
+ if ($newline cmp $_) {
+ print "The line: $_";
+ print "Was converted to: $newline";
+ print "File: $srcFile\n";
+ }
+ print DESTFILE $newline;
+ }
+
+ close(SRCFILE);
+ close(DESTFILE);
+}