ftp.nice.ch/pub/next/unix/hack/binpatch.N.bs.tar.gz#/binpatch/binpatch.c

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.