⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 patch.c

📁 制作2.6内核的CLFS时 patch包
💻 C
📖 第 1 页 / 共 3 页
字号:
/* patch - a program to apply diffs to original files *//* $Id: patch.c,v 1.44 2003/05/20 13:55:03 eggert Exp $ *//* Copyright (C) 1984, 1985, 1986, 1987, 1988 Larry Wall   Copyright (C) 1989, 1990, 1991, 1992, 1993, 1997, 1998, 1999, 2002,   2003 Free Software Foundation, Inc.   This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2, or (at your option)   any later version.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with this program; see the file COPYING.   If not, write to the Free Software Foundation,   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */#define XTERN#include <common.h>#undef XTERN#define XTERN extern#include <argmatch.h>#include <backupfile.h>#include <getopt.h>#include <inp.h>#include <pch.h>#include <quotearg.h>#include <util.h>#include <version.h>#include <xalloc.h>#if HAVE_UTIME_H# include <utime.h>#endif/* Some nonstandard hosts don't declare this structure even in <utime.h>.  */#if ! HAVE_STRUCT_UTIMBUFstruct utimbuf{  time_t actime;  time_t modtime;};#endif/* Output stream state.  */struct outstate{  FILE *ofp;  bool after_newline;  bool zero_output;};/* procedures */static FILE *create_output_file (char const *, int);static LINENUM locate_hunk (LINENUM);static bool apply_hunk (struct outstate *, LINENUM);static bool copy_till (struct outstate *, LINENUM);static bool patch_match (LINENUM, LINENUM, LINENUM, LINENUM);static bool similar (char const *, size_t, char const *, size_t);static bool spew_output (struct outstate *);static char const *make_temp (char);static int numeric_string (char const *, bool, char const *);static void abort_hunk (void);static void cleanup (void);static void get_some_switches (void);static void init_output (char const *, int, struct outstate *);static void init_reject (void);static void reinitialize_almost_everything (void);static void remove_if_needed (char const *, int volatile *);static void usage (FILE *, int) __attribute__((noreturn));static bool make_backups;static bool backup_if_mismatch;static char const *version_control;static char const *version_control_context;static bool remove_empty_files;/* true if -R was specified on command line.  */static bool reverse_flag_specified;/* how many input lines have been irretractably output */static LINENUM last_frozen_line;static char const *do_defines; /* symbol to patch using ifdef, ifndef, etc. */static char const if_defined[] = "\n#ifdef %s\n";static char const not_defined[] = "\n#ifndef %s\n";static char const else_defined[] = "\n#else\n";static char const end_defined[] = "\n#endif\n";static int Argc;static char * const *Argv;static FILE *rejfp;  /* reject file pointer */static char const *patchname;static char *rejname;static char const * volatile TMPREJNAME;static int volatile TMPREJNAME_needs_removal;static LINENUM last_offset;static LINENUM maxfuzz = 2;static char serrbuf[BUFSIZ];/* Apply a set of diffs as appropriate. */intmain (int argc, char **argv){    char const *val;    bool somefailed = false;    struct outstate outstate;    char numbuf[LINENUM_LENGTH_BOUND + 1];    xalloc_exit_failure = 2;    program_name = argv[0];    init_time ();    setbuf(stderr, serrbuf);    xalloc_fail_func = memory_fatal;    bufsize = 8 * 1024;    buf = xmalloc (bufsize);    strippath = -1;    val = getenv ("QUOTING_STYLE");    {      int i = val ? argmatch (val, quoting_style_args, 0, 0) : -1;      set_quoting_style ((struct quoting_options *) 0,			 i < 0 ? shell_quoting_style : (enum quoting_style) i);    }    posixly_correct = getenv ("POSIXLY_CORRECT") != 0;    backup_if_mismatch = ! posixly_correct;    patch_get = ((val = getenv ("PATCH_GET"))		 ? numeric_string (val, true, "PATCH_GET value")		 : posixly_correct - 1);    val = getenv ("SIMPLE_BACKUP_SUFFIX");    simple_backup_suffix = val && *val ? val : ".orig";    if ((version_control = getenv ("PATCH_VERSION_CONTROL")))      version_control_context = "$PATCH_VERSION_CONTROL";    else if ((version_control = getenv ("VERSION_CONTROL")))      version_control_context = "$VERSION_CONTROL";    /* Cons up the names of the global temporary files.       Do this before `cleanup' can possibly be called (e.g. by `pfatal').  */    TMPOUTNAME = make_temp ('o');    TMPINNAME = make_temp ('i');    TMPREJNAME = make_temp ('r');    TMPPATNAME = make_temp ('p');    /* parse switches */    Argc = argc;    Argv = argv;    get_some_switches();    if (make_backups | backup_if_mismatch)      backup_type = get_version (version_control_context, version_control);    init_output (outfile, 0, &outstate);    /* Make sure we clean up in case of disaster.  */    set_signals (false);    for (	open_patch_file (patchname);	there_is_another_patch();	reinitialize_almost_everything()    ) {					/* for each patch in patch file */      int hunk = 0;      int failed = 0;      bool mismatch = false;      char *outname = outfile ? outfile : inname;      if (!skip_rest_of_patch)	get_input_file (inname, outname);      if (diff_type == ED_DIFF) {	outstate.zero_output = false;	somefailed |= skip_rest_of_patch;	do_ed_script (outstate.ofp);	if (! dry_run && ! outfile && ! skip_rest_of_patch)	  {	    struct stat statbuf;	    if (stat (TMPOUTNAME, &statbuf) != 0)	      pfatal ("%s", TMPOUTNAME);	    outstate.zero_output = statbuf.st_size == 0;	  }      } else {	int got_hunk;	bool apply_anyway = false;	/* initialize the patched file */	if (! skip_rest_of_patch && ! outfile)	  {	    int exclusive = TMPOUTNAME_needs_removal ? 0 : O_EXCL;	    TMPOUTNAME_needs_removal = 1;	    init_output (TMPOUTNAME, exclusive, &outstate);	  }	/* initialize reject file */	init_reject ();	/* find out where all the lines are */	if (!skip_rest_of_patch)	    scan_input (inname);	/* from here on, open no standard i/o files, because malloc */	/* might misfire and we can't catch it easily */	/* apply each hunk of patch */	while (0 < (got_hunk = another_hunk (diff_type, reverse))) {	    LINENUM where = 0; /* Pacify `gcc -Wall'.  */	    LINENUM newwhere;	    LINENUM fuzz = 0;	    LINENUM prefix_context = pch_prefix_context ();	    LINENUM suffix_context = pch_suffix_context ();	    LINENUM context = (prefix_context < suffix_context			       ? suffix_context : prefix_context);	    LINENUM mymaxfuzz = (maxfuzz < context ? maxfuzz : context);	    hunk++;	    if (!skip_rest_of_patch) {		do {		    where = locate_hunk(fuzz);		    if (! where || fuzz || last_offset)		      mismatch = true;		    if (hunk == 1 && ! where && ! (force | apply_anyway)			&& reverse == reverse_flag_specified) {						/* dwim for reversed patch? */			if (!pch_swap()) {			    say ("Not enough memory to try swapped hunk!  Assuming unswapped.\n");			    continue;			}			/* Try again.  */			where = locate_hunk (fuzz);			if (where			    && (ok_to_reverse				("%s patch detected!",				 (reverse				  ? "Unreversed"				  : "Reversed (or previously applied)"))))			  reverse = ! reverse;			else			  {			    /* Put it back to normal.  */			    if (! pch_swap ())			      fatal ("lost hunk on alloc error!");			    if (where)			      {				apply_anyway = true;				fuzz--; /* Undo `++fuzz' below.  */				where = 0;			      }			  }		    }		} while (!skip_rest_of_patch && !where			 && ++fuzz <= mymaxfuzz);		if (skip_rest_of_patch) {		/* just got decided */		  if (outstate.ofp && ! outfile)		    {		      fclose (outstate.ofp);		      outstate.ofp = 0;		    }		}	    }	    newwhere = pch_newfirst() + last_offset;	    if (skip_rest_of_patch) {		abort_hunk();		failed++;		if (verbosity == VERBOSE)		  say ("Hunk #%d ignored at %s.\n", hunk,		       format_linenum (numbuf, newwhere));	    }	    else if (!where		     || (where == 1 && pch_says_nonexistent (reverse) == 2			 && instat.st_size)) {		if (where)		  say ("Patch attempted to create file %s, which already exists.\n",		       quotearg (inname));		abort_hunk();		failed++;		if (verbosity != SILENT)		  say ("Hunk #%d FAILED at %s.\n", hunk,		       format_linenum (numbuf, newwhere));	    }	    else if (! apply_hunk (&outstate, where)) {		abort_hunk ();		failed++;		if (verbosity != SILENT)		  say ("Hunk #%d FAILED at %s.\n", hunk,		       format_linenum (numbuf, newwhere));	    } else {		if (verbosity == VERBOSE		    || (verbosity != SILENT && (fuzz || last_offset))) {		    say ("Hunk #%d succeeded at %s", hunk,			 format_linenum (numbuf, newwhere));		    if (fuzz)		      say (" with fuzz %s", format_linenum (numbuf, fuzz));		    if (last_offset)		      say (" (offset %s line%s)",			   format_linenum (numbuf, last_offset),			   "s" + (last_offset == 1));		    say (".\n");		}	    }	}	if (!skip_rest_of_patch)	  {	    if (got_hunk < 0  &&  using_plan_a)	      {		if (outfile)		  fatal ("out of memory using Plan A");		say ("\n\nRan out of memory using Plan A -- trying again...\n\n");		if (outstate.ofp)		  {		    fclose (outstate.ofp);		    outstate.ofp = 0;		  }		fclose (rejfp);		continue;	      }	    /* Finish spewing out the new file.  */	    assert (hunk);	    if (! spew_output (&outstate))	      {		say ("Skipping patch.\n");		skip_rest_of_patch = true;	      }	  }      }      /* and put the output where desired */      ignore_signals ();      if (! skip_rest_of_patch && ! outfile) {	  if (outstate.zero_output	      && (remove_empty_files		  || (pch_says_nonexistent (! reverse) == 2		      && ! posixly_correct)))	    {	      if (verbosity == VERBOSE)		say ("Removing file %s%s\n", quotearg (outname),		     dry_run ? " and any empty ancestor directories" : "");	      if (! dry_run)		{		  move_file ((char *) 0, (int *) 0, outname, (mode_t) 0,			     (make_backups			      || (backup_if_mismatch && (mismatch | failed))));		  removedirs (outname);		}	    }	  else	    {	      if (! outstate.zero_output		  && pch_says_nonexistent (! reverse))		{		  mismatch = true;		  if (verbosity != SILENT)		    say ("File %s is not empty after patch, as expected\n",			 quotearg (outname));		}	      if (! dry_run)		{		  time_t t;		  move_file (TMPOUTNAME, &TMPOUTNAME_needs_removal,			     outname, instat.st_mode,			     (make_backups			      || (backup_if_mismatch && (mismatch | failed))));		  if ((set_time | set_utc)		      && (t = pch_timestamp (! reverse)) != (time_t) -1)		    {		      struct utimbuf utimbuf;		      utimbuf.actime = utimbuf.modtime = t;		      if (! force && ! inerrno			  && pch_says_nonexistent (reverse) != 2			  && (t = pch_timestamp (reverse)) != (time_t) -1			  && t != instat.st_mtime)			say ("Not setting time of file %s (time mismatch)\n",			     quotearg (outname));		      else if (! force && (mismatch | failed))			say ("Not setting time of file %s (contents mismatch)\n",			     quotearg (outname));		      else if (utime (outname, &utimbuf) != 0)			pfatal ("Can't set timestamp on file %s",				quotearg (outname));		    }		  if (! inerrno && chmod (outname, instat.st_mode) != 0)		    pfatal ("Can't set permissions on file %s",			    quotearg (outname));		}	    }      }      if (diff_type != ED_DIFF) {	if (fclose (rejfp) != 0)	    write_fatal ();	if (failed) {	    somefailed = true;	    say ("%d out of %d hunk%s %s", failed, hunk, "s" + (hunk == 1),		 skip_rest_of_patch ? "ignored" : "FAILED");	    if (outname) {		char *rej = rejname;		if (!rejname) {		    rej = xmalloc (strlen (outname) + 5);		    strcpy (rej, outname);		    addext (rej, ".rej", '#');		}		say (" -- saving rejects to file %s", quotearg (rej));		if (! dry_run)		  {		    move_file (TMPREJNAME, &TMPREJNAME_needs_removal,			       rej, instat.st_mode, false);		    if (! inerrno			&& (chmod (rej, (instat.st_mode					 & ~(S_IXUSR|S_IXGRP|S_IXOTH)))			    != 0))		      pfatal ("can't set permissions on file %s",			      quotearg (rej));		  }		if (!rejname)		    free (rej);	    }	    say ("\n");	}      }      set_signals (true);    }    if (outstate.ofp && (ferror (outstate.ofp) || fclose (outstate.ofp) != 0))      write_fatal ();    cleanup ();    if (somefailed)      exit (1);    return 0;}/* Prepare to find the next patch to do in the patch file. */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -