diff options
Diffstat (limited to 'ldap/admin/src/migrateTo4')
-rw-r--r-- | ldap/admin/src/migrateTo4 | 1581 |
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 +©Dir("$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}$_") { + ©BinFile("$srcdir${PATHSEP}$_", + "$serverHome${PATHSEP}logs${PATHSEP}${_}.migrate"); + } +} +closedir(LOGDIR); + +# copy the ssl directory +©Dir("$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") { + ©BinFile( + "$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"; +©Ldif; + +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? +# ©Dir($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 + +©BinFile("$serverHome${PATHSEP}config${PATHSEP}slapd.user_at.conf", + "$serverHome${PATHSEP}config${PATHSEP}slapd.user_at.conf.bak"); +©BinFile("$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") { + ©AndEditTextFile( + "$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") { + ©AndEditTextFile( + "$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 { + ©BinFile($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 + ©Dir($realDir, $DEFAULT_CHANGELOG_DIR, '\.share$'); + } +} + +if ($convertToLDIF) { + # Convert the db backup, bak/ + print "Migrating database backups . . .\n"; + ©Bak; +} else { + # just copy the directories over + ©Dir($networkDbDir, "$serverHome${PATHSEP}db", '\.share$'); + ©Dir("$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); + ©AndEditTextFile($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); + ©BinFile($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 + ©BinFile("$newsrc", "$newsrc.save"); + ©BinFile("$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; + + ©BinFile("$newldbmsrc.tmp", "$newldbmsrc"); + ©BinFile("$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}$_") { + ©Dir ( "$src${PATHSEP}$_", "$dest${PATHSEP}$_" ); + } else { + ©BinFile ( "$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 { + ©BinFile($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 { + ©BinFile("$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); +} |