This is binpatch.c in view mode; [Download] [Up]
/*
* binpatch.c - apply output of "cmp -l" to patch a binary file
*
* This simple program takes the output from "cmp -l" and applies it as a set
* of patches to a given input file. The input file itself is modified and no
* backup file is created. Thus if a backup of the original is desired (highly
* recommended), create it before using binpatch. An example of its use
* follows:
*
* Assume that you have the file "lpd.diff" that resulted from:
* % cmp -l lpd.broken lpd.fixed > lpd.diff
*
* Now do the following to apply the patch:
* % cp -p lpd lpd.broken
* % binpatch -f lpd.diff lpd
*
* lpd will now be identical to lpd.fixed. This is of course useful when you
* have only the original and the diff file and wish to recreate the patched
* version.
*
* Compile using: cc -O -Wall -o binpatch binpatch.c
*
* Copyright (C) 1991 by Marc Ullman
* All Rights Reserved
* December 16, 1991
*/
static char rcsid[] = "$Header: /local/src/tools/binpatch/RCS/binpatch.c,v 1.1
91/12/16 12:05:50 marc Exp $";
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#define ARGUMENTS "-f diff_file input_file\n" \
" The diff_file is created by \"cmp -l orig.file
modified.file > diff.file\""
static char *program_name = NULL;
static char *input_file_name = NULL;
static char *diff_file_name = NULL;
/* Print error message while exiting due to unrecoverable error */
/* Use variable argument list to support multiple arguments to printf */
static void Error_Exit(char *error_msg, ...)
{
va_list ap;
va_start(ap, error_msg);
fprintf(stderr, "%s: ", program_name);
vfprintf(stderr, error_msg, ap);
va_end(ap);
exit(1);
}
static void Usage()
{
fprintf(stderr, "Usage: %s %s\n", program_name, ARGUMENTS);
exit(1);
}
static void Process_Arguments(int argc, char *argv[])
{
int i;
for (i = 1; i <= (argc - 1); i++) {
if (*argv[i] == '-') {
switch (*(argv[i]+1)) {
case 'f' : /* diff_file */
if (i < (argc - 1)) {
diff_file_name = argv[++i];
} else {
Usage();
}
break;
default :
Error_Exit("invalid option '-%c'\n", *(argv[i]+1));
break;
}
} else {
input_file_name = argv[i];
}
}
/* Check that we got diff_file and input file */
if ((input_file_name == NULL) || (diff_file_name == NULL)) {
Usage();
}
}
void error_exit(FILE *diff_file, FILE *input_file)
{
fclose(diff_file);
fclose(input_file);
exit(EXIT_FAILURE);
}
void main(int argc, char *argv[])
{
FILE *diff_file;
FILE *input_file;
int count = 0;
unsigned long offset;
unsigned int c1, c2, c;
program_name = argv[0];
Process_Arguments(argc, argv);
if ((diff_file = fopen(diff_file_name, "r")) == NULL) {
Error_Exit("can't read %s\n", diff_file_name);
}
if ((input_file = fopen(input_file_name, "r+")) == NULL) {
Error_Exit("can't read %s\n", input_file_name);
}
do {
count = fscanf(diff_file, "%lu %o %o", &offset, &c1, &c2);
if (count == EOF) {
break;
} else if (count != 3) {
printf("Error reading %s\n", diff_file_name);
error_exit(diff_file, input_file);
}
offset--; /* cmp -l returns base 1 offsets */
#ifdef DEBUG
printf("%.8x %.2x %.2x\n", offset, c1, c2);
#endif
if (fseek(input_file, offset, SEEK_SET) != 0) {
printf("Error seeking in %s\n", input_file_name);
error_exit(diff_file, input_file);
}
c = fgetc(input_file);
if (c1 != c) {
printf("Patch file differs from input file at offset %.8x: %.2x %.2x\n",
offset, c, c1);
} else {
fseek(input_file, offset, SEEK_SET);
fputc(c2, input_file);
}
} while (feof(diff_file) == 0);
fclose(diff_file);
fclose(input_file);
exit(EXIT_SUCCESS);
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.