use Getopt::Std;
$g_my_name = "patch_jabberd.pl";
$g_default_log_dir = "/tmp";
$g_default_logfile = "$g_default_log_dir/$g_my_name.log";
$g_default_tmp = "/tmp";
$g_default_source_dir = "./jabberd2";
$g_default_patch_dir = "./apple_patch/pre_configure/jabberd2";
$g_tmp = $g_default_tmp;
$g_logfile = $g_default_logfile;
$g_update_patches = 0;
$DEBUG = 0;
$SILENT = 0;
$LOGGING = 1;
$PATCHFILE_EXT = ".patch";
$JABBERD_DIST_DIR = "jabberd-2.1.24.1";
sub _usage() {
print "$g_my_name: Tool for applying or creating patch files for jabberd source\n";
print "Usage:\n\n";
print "== Patch Creation ==\n";
print "Creates a set of patches for a jabberd2 source tree, comparing the original jabberd distribution\n";
print "with a modified source tree.\n\n";
print "$g_my_name -c [options]\n";
print "Required Options:\n";
print " -n PATH: Path to the modified Apple source code to create patches from (Default: \"$g_default_source_dir\")\n";
print " -f FILE: jabberd bzip'd tarfile to use for reference\n";
print " -p PATH: Path to Apple patch directory (new patch files will be created here) (Default: \"$g_default_patch_dir\")\n";
print "\n\n";
print "== Patch Application ==\n";
print "Extracts the jabberd2 source from an archive and applies a set of patches to the source, leaving the patched\n";
print "source available for building or modification.\n\n";
print "$g_my_name -a [options]\n";
print "Required Options:\n";
print " -n PATH: Path to place the newly patched source code (Default: \"$g_default_source_dir\")\n";
print " -f FILE: jabberd bzip'd tarfile to use for reference\n";
print " -p PATH: Path to Apple patch directory (patches here will be applied to the original source) (Default: \"$g_default_patch_dir\")\n";
print "Other options:\n";
print " -d : debug mode\n";
print " -l FILE: Set log file location. Default: $g_default_logfile\n";
print " -t PATH: Set temp directory. Default: $g_default_tmp\n";
print " -s : Silent mode\n";
print "\n";
print "Examples:\n";
print "$g_my_name -c -n $g_default_source_dir -f ./opensource_pkgs/jabberd-2.1.24.1.tar.bz2 -p $g_default_patch_dir\n";
print "$g_my_name -a -n $g_default_source_dir -f ./opensource_pkgs/jabberd-2.1.24.1.tar.bz2 -p $g_default_patch_dir\n";
print "\n";
}
sub _timestamp()
{
my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) =
localtime(time);
$year += 1900;
$mon += 1;
if ( $hour =~ /^\d$/ ) { $hour = "0" . $hour; }
if ( $min =~ /^\d$/ ) { $min = "0" . $min; }
if ( $sec =~ /^\d$/ ) { $sec = "0" . $sec; }
my $ret = $year."-".$mon."-".$mday."-$hour:$min:$sec";
return $ret;
}
sub _log() {
my $t = &_timestamp;
if ($LOGGING) {
open(LOG, ">>$g_logfile") || die "ERROR: could not open log file at $g_logfile: $!";
print LOG "$t: $_[0]\n";
}
if (! $SILENT) { print "$t: $_[0]\n"; }
}
sub _bail() {
&_log($_[0]);
exit 1;
}
sub create_patch {
my $path1 = shift;
my $path2 = shift;
my $patch_path = shift;
my $created_directory = 0;
my $created_new_file = 0;
if (-f $patch_path) {
&_bail("Exiting, patch already exists: $patch_path");
}
my $patch_dir = $patch_path;
$patch_dir =~ s/(.*[\/\\]).*/$1/;
if (! -d $patch_dir) {
my $ret = `mkdir -p "$patch_dir"`;
$created_directory = 1;
}
$patch_path .= $PATCHFILE_EXT;
if (! -e $patch_path) {
$created_new_file = 1;
}
if ((! $created_new_file) && ($g_update_patches)) {
system("cp \"$patch_path\" \"$patch_path.orig\"");
}
my $cmd = "diff -bwpduN \"$path1\" \"$path2\" > \"$patch_path\"";
&_log("Executing: $cmd");
$ret = `$cmd`;
if ($ret ne "") {
&_bail("diff appears to have failed with error: $ret");
}
if ((! $created_new_file) && ($g_update_patches)) {
$cmd = "diff \"$patch_path.orig\" \"$patch_path\"";
my @ret_lines = `$cmd`;
if (($ ($ret_lines[1] =~ /\d\d\d\d-\d\d-\d\d\s\d\d:\d\d:\d\d/) &&
($ret_lines[3] =~ /\d\d\d\d-\d\d-\d\d\s\d\d:\d\d:\d\d/)) {
system("mv -f \"$patch_path.orig\" \"$patch_path\"");
} else {
unlink("$patch_path.orig");
}
}
if (! -s $patch_path) {
unlink($patch_path);
if ($created_directory) {
rmdir($patch_dir);
}
} else {
if ($g_update_patches) {
if ($created_directory) {
&_log("NOTICE: Added new directory: $patch_dir");
}
if ($created_new_file) {
&_log("NOTICE: Added new patch: $patch_path");
}
} else {
&_log("Created patchfile: $patch_path");
}
}
return 0;
}
sub create_patches {
my $base_apple_source_dir = shift; my $jabberd_dist_dir = shift; my $patch_dir = shift; my $appended_apple_source_dir = shift;
if ($DEBUG) {
print "DEBUG: create_patches($base_apple_source_dir, $jabberd_dist_dir, $patch_dir, $appended_apple_source_dir)\n";
}
if ($appended_apple_source_dir eq "") {
if ($g_update_patches) {
&_log("NOTICE: Updating existing patches in: $patch_dir");
}
}
opendir(D, $base_apple_source_dir.$appended_apple_source_dir) ||
&_bail("can't open dir $base_apple_source_dir$appended_apple_source_dir");
my @files = readdir(D);
closedir(D);
foreach my $file (@files) {
if ($file eq "." || $file eq ".." || $file eq ".svn" || $file eq "CVS") {
next;
}
my $full_filename = "$base_apple_source_dir$appended_apple_source_dir/$file";
if (-d $full_filename) {
&create_patches($base_apple_source_dir, $jabberd_dist_dir, $patch_dir, $appended_apple_source_dir."/$file");
} else {
&create_patch($jabberd_dist_dir.$appended_apple_source_dir."/$file", $full_filename,
"$patch_dir/$appended_apple_source_dir/$file");
}
}
return 0;
}
sub apply_patches {
my $patch_dir = shift; my $jabberd_dist_dir = shift; my $appended_apple_patch_dir = shift;
opendir(D, $patch_dir.$appended_apple_patch_dir) ||
&_bail("can't open dir $patch_dir$appended_apple_patch_dir");
my @files = readdir(D);
closedir(D);
foreach my $file (@files) {
if ($file eq "." || $file eq ".." || $file eq ".svn" || $file eq "CVS") {
next;
}
my $full_filename = "$patch_dir$appended_apple_patch_dir/$file";
if (-d $full_filename) {
&apply_patches($patch_dir, $jabberd_dist_dir, $appended_apple_patch_dir."/$file");
} else {
my $patch_target = $file;
$patch_target =~ s/$PATCHFILE_EXT$//;
$cmd = "patch -l \"$jabberd_dist_dir$appended_apple_patch_dir/$patch_target\" \"$full_filename\"";
if ($DEBUG) {
print "DEBUG: $cmd\n";
}
system($cmd);
}
}
return 0;
}
umask(077);
my $source_dir = $g_default_source_dir;
my $jabberd_tarball = "";
my $patch_dir = $g_default_patch_dir;
getopts('n:f:p:l:t:p:ac?hvds', \%opts);
if (defined $opts{'d'}) {
$DEBUG = 1;
}
if (defined $opts{'s'}) {
$SILENT = 1;
}
if (defined $opts{'l'}) {
$g_logfile = $opts{'l'};
}
if (defined $opts{'?'} || defined $opts{'h'} || defined $opts{'v'}) {
&_usage;
exit 0;
}
if (defined $opts{'n'}) {
$source_dir = $opts{'n'};
}
if (defined $opts{'f'}) {
$jabberd_tarball = $opts{'f'};
} else {
&_bail("You must specify an archive file using the -f flag.\n");
}
if (defined $opts{'p'}) {
$patch_dir = $opts{'p'};
}
if (defined $opts{'l'}) {
$LOGGING = 1;
$g_logfile = $opts{'l'};
}
if (defined $opts{'t'}) {
$g_tmp = $opts{'t'};
}
if (defined $opts{'c'}) {
&_log("################ CREATING PATCH FILES ################");
if (!(defined $source_dir) && (defined $jabberd_tarball) && (defined $patch_dir)) {
&_bail("Some required arguments are not defined.");
}
if (! -e $jabberd_tarball) {
&_bail("Could not find file: $jabberd_tarball");
}
if (! -e $source_dir) {
&_bail("Could not find source directory: $source_dir");
}
if (-e $patch_dir) {
$g_update_patches = 1;
}
`tar -C $g_tmp -xjvf $jabberd_tarball`;
my $jabberd_dist_dir = $g_tmp."/".$JABBERD_DIST_DIR;
&create_patches($source_dir, $jabberd_dist_dir, $patch_dir, "");
if ($jabberd_dist_dir ne "") {
&_log("Removing temporary source dir: $jabberd_dist_dir");
system("rm -Rf $jabberd_dist_dir");
}
&_log("Finished creating patch files.");
} elsif (defined $opts{'a'}) {
&_log("################ APPLYING PATCH FILES ################");
if (!(defined $source_dir) && (defined $jabberd_tarball) && (defined $patch_dir)) {
&_bail("Some required arguments are not defined.");
}
if (! -e $jabberd_tarball) {
&_bail("Could not find file: $jabberd_tarball");
}
if (! -d $patch_dir) {
&_bail("Cannot find patch dir: $patch_dir");
}
if (-e $source_dir) {
&_bail("Target directory already exists: $source_dir");
}
`tar -C $g_tmp -xjvf $jabberd_tarball`;
my $jabberd_dist_dir = $g_tmp."/".$JABBERD_DIST_DIR;
&apply_patches($patch_dir, $jabberd_dist_dir, "");
system("cp -R \"$jabberd_dist_dir\" \"$source_dir\"");
if ($jabberd_dist_dir ne "") {
&_log("Removing temporary source dir: $jabberd_dist_dir");
system("rm -Rf $jabberd_dist_dir");
}
&_log("Finished applying patch files. Final source is available in: $source_dir");
} else {
print "You did not specify an operation to perform.\n";
&_usage;
}