#!@PERL_PATH@ -w ###################################################################### # # EPrints 2 installer : Handles upgrading, simple command detection, # and the creation of the SystemSettings.pm file. This doesn't do the # mySQL install, etc. - you'll need the SuperInstaller for that. # ###################################################################### # __LICENSE__ ###################################################################### my %from_configure; $from_configure{"dist_path"}="@DIST_PATH@"; $from_configure{"perl"}="@PERL_PATH@"; $from_configure{"prefix"}="@PREFIX@"; $from_configure{"user"}="@INSTALL_USER@"; $from_configure{"group"}="@INSTALL_GROUP@"; $from_configure{"disable_df"}=@DISABLE_DF@; $from_configure{"virtualhost"}="@VIRTUALHOST@"; $from_configure{"unzip"}="@UNZIP_PATH@"; $from_configure{"tar"}="@TAR_PATH@"; $from_configure{"gunzip"}="@GUNZIP_PATH@"; $from_configure{"wget"}="@WGET_PATH@"; $from_configure{"sendmail"}="@SENDMAIL_PATH@"; $from_configure{"smtp_server"}="@SMTP_SERVER@"; $from_configure{"latex"}="@LATEX_PATH@"; $from_configure{"dvips"}="@DVIPS_PATH@"; $from_configure{"convert"}="@CONVERT_PATH@"; $from_configure{"enable_gdome"}="@ENABLE_GDOME@"; $from_configure{"apache"}="@APACHE@"; $from_configure{"platform"}="@PLATFORM@"; # hard wired for now. $from_configure{"cp"}="/bin/cp"; $from_configure{"rm"}="/bin/rm"; ###################################################################### if( $from_configure{"apache"} ne "" && $from_configure{"apache"} ne "1" && $from_configure{"apache"} ne "2" ) { print "Apache version must be '1' or '2'.\n"; print "re-run configure with new options.\n"; exit 1; } ###################################################################### if( defined $ARGV[0] ) { print "Destination directory overridden to: $ARGV[0]\n"; } use strict; use Cwd; use Digest::MD5; use Data::Dumper; # # Set the umask so nothing goes odd on systems which # change it. # umask( 0022 ); # # Grab version id number from VERSION file. # my( $version_id, $version ) = read_version( $from_configure{"dist_path"}."/VERSION" ); ### Trim perfix if needed if( $from_configure{"prefix"} =~ s#/$## ) { print "Removing trailing slash from prefix.\n"; } ### Print out some key information, which is bound to ### cause problems if incorrect. # shorter variables for clarity later my $from_path = $from_configure{dist_path}; my $to_path = $from_configure{prefix}; # Implement DESTDIR support for GNU compatibility. # If an argument is specified install there instead. if( defined $ARGV[0] ) { $to_path = $ARGV[0]; } print "Installing from: $from_path\n"; my $system_settings_file = "$to_path/perl_lib/EPrints/SystemSettings.pm"; my $upgrade = 0; if( -e $system_settings_file ) { $upgrade = 1; print "Previous install detected at install location.\n"; print "Upgrading to: $to_path\n"; } else { print "Installing to: $to_path\n"; print "Installing as user: ".$from_configure{"user"}."\n"; print "Installing as group: ".$from_configure{"group"}."\n"; } my $systemsettings = {}; $systemsettings->{"platform"} = $from_configure{"platform"}; $systemsettings->{"version_history"} = [ $version_id ]; # # Set up some default settings. # $systemsettings->{"invocation"} = { zip => '$(unzip) 1>/dev/null 2>&1 -qq -o -d $(DIR) $(ARC)', targz => '$(gunzip) -c < $(ARC) 2>/dev/null | $(tar) xf - -C $(DIR) >/dev/null 2>&1', wget => '$(wget) -r -L -q -m -nH -np --execute="robots=off" --cut-dirs=$(CUTDIRS) $(URL)', sendmail => '$(sendmail) -oi -t -odb --', latex => '$(latex) \'$(SOURCE)\'', dvips => '$(dvips) \'$(SOURCE)\' -o \'$(TARGET)\'', convert_crop_white => '$(convert) -crop 0x0 -bordercolor white -border 4x4 \'$(SOURCE)\' \'$(TARGET)\'', cpall => '$(cp) -pR \'$(SOURCE)\'/* \'$(TARGET)\'', rmall => '$(rm) -rf \'$(TARGET)\'/*', }; $systemsettings->{"archive_extensions"} = {}; $systemsettings->{"archive_formats"} = []; if( $from_configure{"unzip"} ne "" ) { $systemsettings->{"archive_extensions"}->{"zip"} = ".zip" ; push @{$systemsettings->{"archive_formats"}},"zip"; } if( $from_configure{"tar"} ne "" && $from_configure{"gunzip"} ne "" ) { $systemsettings->{"archive_extensions"}->{"targz"} = ".tar.gz" ; push @{$systemsettings->{"archive_formats"}},"targz"; } $systemsettings->{"executables"} = {}; foreach( "perl", "unzip", "tar", "gunzip", "wget", "sendmail", "latex", "dvips", "convert", "cp", "rm", ) { next unless( defined $from_configure{$_} ); $systemsettings->{"executables"}->{$_} = $from_configure{$_}; } $systemsettings->{"file_perms"} = 0664 unless defined $systemsettings->{"file_perms"}; $systemsettings->{"dir_perms"} = 02775 unless defined $systemsettings->{"dir_perms"}; $systemsettings->{"disable_df"} = $from_configure{"disable_df"}; $systemsettings->{"virtualhost"} = $from_configure{"virtualhost"}; if( $upgrade ) { unless( require $system_settings_file ) { print <{"version_id"}."\n"; # create a minimal version history if there was not one already if( !defined $EPrints::SystemSettings::conf->{"version_history"} ) { $EPrints::SystemSettings::conf->{"version_history"} = [ $EPrints::SystemSettings::conf->{"version_id"} ]; } # Current values take precedence. foreach( keys %$EPrints::SystemSettings::conf ) { if( defined $systemsettings->{$_} ) { $systemsettings->{$_} = merge_fields( $EPrints::SystemSettings::conf->{$_}, $systemsettings->{$_} ); } else { $systemsettings->{$_} = $EPrints::SystemSettings::conf->{$_}; } } $systemsettings->{"user"} = $EPrints::SystemSettings::conf->{"user"}; $systemsettings->{"group"} = $EPrints::SystemSettings::conf->{"group"}; print "Upgrading as user: ".$systemsettings->{"user"}."\n"; print "Upgrading as group: ".$systemsettings->{"group"}."\n"; $upgrade = 1; } else { $systemsettings->{"user"} = $from_configure{"user"}; $systemsettings->{"group"} = $from_configure{"group"}; $systemsettings->{"base_path"} = $from_configure{"prefix"}; } $systemsettings->{"version_id"} = $version_id; $systemsettings->{"version"} = $version; set( 'smtp_server', \%from_configure, $systemsettings, '' ); set( 'enable_gdome', \%from_configure, $systemsettings, 0 ); set( 'show_ids_in_log', \%from_configure, $systemsettings, 0 ); set( 'apache', \%from_configure, $systemsettings, "2" ); # Check the user exists unless( getpwnam($systemsettings->{"user"}) ) { print "User ".$from_configure{"user"}." does not exist. Aborting.\n"; exit 1; } # Check the group exists unless( getgrnam($systemsettings->{"group"}) ) { print "Group ".$from_configure{"group"}." does not exist. Aborting.\n"; exit 1; } my(undef,undef,$uid) = getpwnam($systemsettings->{"user"}); my(undef,undef,$gid) = getgrnam($systemsettings->{"group"}); my %oldhashes = (); # If we are upgrading and have a digest file, read the digests into a hash # to check them against the files in place to see if they've changed. if( $upgrade ) { my $sigfile = "$to_path/SIGNATURES"; if (-e $sigfile ) { print "Loading SIGNATURES...\n"; open(SIGS, $sigfile ) || die "Can't open $sigfile"; binmode(SIGS); foreach() { chomp; my( $file, $digest ) = split( " ", $_); $oldhashes{$file} = $digest; } close(SIGS); } else { print "Upgrading, but could not find an old SIGNATURES file.\n"; } } # # Actual install starts here. # ensure_dir( $to_path, $uid, $gid, 02775 ); ensure_dir( "$to_path/testdata", $uid, $gid, 02775 ); my $newsighash = {}; my @normal_dirs = ( "defaultcfg", "cfg", "perl_lib", "lib", "testdata/data", "var" ); my @executable_dirs = ( "bin", "cgi", "testdata/bin" ); my @base_files = ( "VERSION", "CHANGELOG", "COPYING", "NEWS", "AUTHORS", "README" ); foreach my $dir (@normal_dirs) { install_dir($from_path, $dir, 0664, $uid, $gid, $to_path, \%oldhashes, $newsighash); } foreach my $dir (@executable_dirs) { install_dir($from_path, $dir, 0775, $uid, $gid, $to_path, \%oldhashes, $newsighash); } foreach my $file (@base_files) { install_file($from_path, $file, undef, 0664, $uid, $gid, $to_path, \%oldhashes, $newsighash ); } ensure_dir( "$to_path/archives", $uid, $gid, 02775 ); foreach my $oldfile ( keys %oldhashes ) { next if defined $newsighash->{$oldfile}; my $filepath = "$to_path/$oldfile"; next if( !-e $filepath ); my $repl_digest = get_digest( $filepath ); if( $repl_digest ne $oldhashes{$oldfile} ) { move_out_of_harms_way( $filepath ); } else { print "Removing $filepath\n"; unlink( $filepath ); } } write_sigs( $to_path, $newsighash, $uid, $gid ); save_settings( $system_settings_file, $systemsettings, $systemsettings->{user}, $systemsettings->{group} ); # Warnings! if( $upgrade ) { print "Upgraded eprints at: $to_path\n"; } else { print "Installed EPrints to: $to_path\n"; } my $soapdir = "$to_path/cgi/soap"; if( -d $soapdir ) { print <{smtp_server} eq "" && !$upgrade ) { print <{$param} && $from_configure->{$param} ne '' ) { # a setting has actually been configured by configure $systemsettings->{$param} = $from_configure->{$param}; return; } if( !defined $systemsettings->{$param} ) { # no setting is defined at all, not even "" # so use the default $systemsettings->{$param} = $default; return; } return; } sub save_settings { my( $sysfile, $syshash, $user, $group ) = @_; my(undef,undef,$uid,$gid) = getpwnam($user); my $dumper = Data::Dumper->new( [ $syshash ] , [ 'EPrints::SystemSettings::conf' ] ); print "Writing $sysfile\n"; unless( open(FILEOUT, ">".$sysfile) ) { print "Failed to write $sysfile\n"; exit 1; } binmode(FILEOUT); print FILEOUT <Dump(); print FILEOUT "\n1;"; close(FILEOUT); if( $from_configure{"platform"} eq "unix" ) { chmod( 0664, $sysfile ); chown($uid, $gid, $sysfile ); } } sub merge_fields { my($ref1, $ref2) = @_; my %outref; my $type = ref $ref1; if($type eq "HASH") { # $ref1 takes precedence foreach(keys %$ref1) { $outref{$_} = $ref1->{$_}; } foreach(keys %$ref2) { $outref{$_} = $ref2->{$_} unless defined $outref{$_}; } return \%outref; } elsif($type eq "ARRAY") { my $out = []; my $done = {}; if (defined $ref1) { foreach(@$ref1) { $done->{$_} = 1; push @{$out}, $_; } } if (defined $ref2) { foreach(@$ref2) { next if( $done->{$_} ); push @{$out}, $_; } } return $out; } else { return $ref1; } } ####################################### sub detect_df { my $dir = "/"; my ($fmt, $res); # try with statvfs.. eval { { package main; require "sys/syscall.ph"; } $fmt = "\0" x 512; $res = syscall (&main::SYS_statvfs, $dir, $fmt) ; $res == 0; } # try with statfs.. || eval { { package main; require "sys/syscall.ph"; } $fmt = "\0" x 512; $res = syscall (&main::SYS_statfs, $dir, $fmt); $res == 0; } } # Post installation bits sub write_sigs { my( $dir, $sigs, $uid, $gid ) = @_; my $sigfile = $dir.'/SIGNATURES'; # Dump out signature file unless( open (SIGOUT, ">".$sigfile ) ) { print "Unable to write $sigfile: $!\n"; exit 1; } binmode(SIGOUT); foreach( sort keys %{$sigs} ) { print SIGOUT $_." ".$sigs->{$_}."\n"; } close(SIGOUT); if( $from_configure{"platform"} eq "unix" ) { chown($uid, $gid, $sigfile ); chmod( 0664, $sigfile ); } } # Calculate the MD5 digest of a file. sub get_digest { my($file) = @_; unless( open(FILE, $file) ) { print "Can't open '$file': $!\n"; exit 1; } binmode(FILE); my $outdigest = new Digest::MD5; foreach() { $outdigest->add($_); } close(FILE); return $outdigest->hexdigest; } # Install $file from directory $dir into $dest. The permissions # from $perms are set, and the group and user are set from $group # and $user. The %hash is used for MD5 comparisions - currently # not doing anything active, but checking is enabled. sub install_file { my($distdir, $file, $dir, $perms, $uid, $gid, $dest, $sighash, $newsighash ) = @_; my $relpath = $file; if( defined $dir ) { $relpath = "$dir/$file"; } if( !defined $dir ) { $dir = ""; } return unless (-e $distdir."/$relpath"); my @linesout = (); my $linecopy = 0; if($dir eq "bin" || $dir eq "testdata/bin") { $linecopy = 1; } if( $linecopy ) { my $currline = ""; my $outdigest = Digest::MD5->new; open(INFILE, $distdir."/$relpath"); binmode(INFILE); if ($file eq "startup.pl") { # NJS 2007-05-22: Changed $dest to $from_configure{"prefix"} so # that we don't end up with the wrong invocation paths when building # the Debian package with pbuilder. $currline = "use lib '".$from_configure{"prefix"}."/perl_lib';\n"; $outdigest->add($currline); } # NJS 2007-05-29: Added check for new eprints_maintenance and # eprints_alerts scripts, which are shell scripts rather than Perl. elsif (($file eq "eprints_maintenance") || ($file eq "eprints_alerts")) { $currline = "#!/bin/sh\n"; $outdigest->add($currline); } else { # NJS 2007-05-22: Changed $dest to $from_configure{"prefix"} so # that we don't end up with the wrong invocation paths when building # the Debian package with pbuilder. $currline = "#!".$from_configure{perl}." -w -I".$from_configure{"prefix"}."/perl_lib\n"; $outdigest->add($currline); } push @linesout, $currline; my $skipme = ; while(my $line=) { chomp $line; $currline = "$line\n"; $outdigest->add($currline); push @linesout, $currline; } close(INFILE); $newsighash->{$relpath} = $outdigest->hexdigest; } else { $newsighash->{$relpath} = get_digest("$distdir/$relpath"); } if ($sighash->{"$relpath"} && -e "$dest/$relpath") { my $repl_digest = get_digest("$dest/$relpath"); if ($repl_digest ne $sighash->{"$relpath"}) { move_out_of_harms_way( "$dest/$relpath" ); } } if( $linecopy ) { unless( open(OUTFILE, ">$dest/$relpath") ) { print "\nCan't write to $dest/$relpath : $!\n"; exit 1; } binmode(OUTFILE); print OUTFILE join( "", @linesout ); close(OUTFILE); } else { my $cmd = "cp $distdir/$relpath $dest/$relpath "; system( $cmd ); } if( $from_configure{"platform"} eq "unix" ) { unless( chmod($perms, "$dest/$relpath") ) { print "\nUnable to chmod $dest/$relpath : $!\n"; exit 1; } unless( chown($uid, $gid, "$dest/$relpath") ) { print "\nUnable to chown $dest/$relpath : $!\n"; exit 1; } } } sub install_dir { my( $distdir, $dir, $perms, $uid, $gid, $dest, $sighash, $newsighash ) = @_; unless( opendir(INDIR, $dir) ) { print "Unable to open package directory: $dir. $!\n"; exit 1; } my @dirs = (); my @files = (); ensure_dir("$dest/$dir", $uid, $gid, 02775); if( $from_configure{"platform"} eq "unix" ) { unless( chown($uid, $gid, "$dest/$dir") ) { print "\nUnable to chown $dest/$dir : $!\n"; exit 1; } } while(my $item = readdir(INDIR)) { next if( $item eq "." || $item eq ".." ); if( -d $distdir."/$dir/$item" ) { push(@dirs, $item); } else { push(@files, $item); } } closedir(INDIR); foreach(@files) { install_file($distdir, $_, $dir, $perms, $uid, $gid, $dest, $sighash, $newsighash ); } foreach(@dirs) { install_dir($distdir, "$dir/".$_, $perms, $uid, $gid, $dest, $sighash, $newsighash ); } } ############################################################## sub upgrade { my( $base_path, $dist_path, $user, $group ) = @_; my(undef,undef,$uid,$gid) = getpwnam($user); print "Upgrading files : ["; print <' line with User $user o Replace the 'Group ' line with Group $group - su to $user - Move into $base_path and run: bin/configure_archive Good Luck! - To find and share ideas and problems try the EPrints technical mailing list and wiki at http://eprints.org/software/ ====================================================================== HOORAY } sub move_out_of_harms_way { my( $file ) = @_; my @date = localtime; my $safename = sprintf( "%s.backup.%04d-%02d-%02d", $file, $date[5]+1900, $date[4]+1, $date[3] ); my $n = 0; while( -e $safename ) { ++$n; $safename = sprintf( "%s.backup.%04d-%02d-%02d.%d", $file, $date[5]+1900, $date[4]+1, $date[3], $n ); } rename $file, $safename; print "\n$file has been modified.\nSaving old version as $safename\n"; } sub read_version { my( $vfile ) = @_; unless( open(VERSIONIN, $from_configure{"dist_path"}."/VERSION") ) { print "No VERSION file in distribution - invalid distribution?\n"; exit 1; } binmode(VERSIONIN); my $version_id = ; unless( defined($version_id) ) { print "Undefined version number.\n"; exit 1; } chomp($version_id); my $version = ; unless( defined($version) ) { print "Undefined version description.\n"; exit 1; } chomp($version); close(VERSIONIN); return( $version_id, $version ); } sub ensure_dir { my( $dir, $uid, $gid, $mode ) = @_; if( !-d $dir ) { if( !mkdir($dir) ) { print "Unable to make dir: $dir.\n"; print "Aborting!\n"; exit 1; } } unless( chown($uid, $gid, $dir) ) { print "Unable to chown ".$dir." : $!\n"; print "Aborting!\n"; exit 1; } unless( chmod($mode, $dir) ) { print "Unable to chmod ".$dir." : $!\n"; print "Aborting!\n"; exit 1; } return; }