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.