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

📄 util.c

📁 制作2.6内核的CLFS时 patch包
💻 C
📖 第 1 页 / 共 2 页
字号:
/* utility functions for `patch' *//* $Id: util.c,v 1.36 2003/05/20 14:04:53 eggert Exp $ *//* Copyright (C) 1986 Larry Wall   Copyright (C) 1992, 1993, 1997, 1998, 1999, 2001, 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 extern#include <common.h>#include <backupfile.h>#include <dirname.h>#include <quotearg.h>#include <quotesys.h>#include <version.h>#undef XTERN#define XTERN#include <util.h>#include <xalloc.h>#include <maketime.h>#include <partime.h>#include <signal.h>#if !defined SIGCHLD && defined SIGCLD#define SIGCHLD SIGCLD#endif#if ! HAVE_RAISE && ! defined raise# define raise(sig) kill (getpid (), sig)#endif#include <stdarg.h>static void makedirs (char *);/* Move a file FROM (where *FROM_NEEDS_REMOVAL is nonzero if FROM   needs removal when cleaning up at the end of execution)   to TO, renaming it if possible and copying it if necessary.   If we must create TO, use MODE to create it.   If FROM is null, remove TO (ignoring FROMSTAT).   FROM_NEEDS_REMOVAL must be nonnull if FROM is nonnull.   Back up TO if BACKUP is true.  */voidmove_file (char const *from, int volatile *from_needs_removal,	   char *to, mode_t mode, bool backup){  struct stat to_st;  int to_errno = ! backup ? -1 : stat (to, &to_st) == 0 ? 0 : errno;  if (backup)    {      int try_makedirs_errno = 0;      char *bakname;      if (origprae || origbase)	{	  char const *p = origprae ? origprae : "";	  char const *b = origbase ? origbase : "";	  char const *o = base_name (to);	  size_t plen = strlen (p);	  size_t tlen = o - to;	  size_t blen = strlen (b);	  size_t osize = strlen (o) + 1;	  bakname = xmalloc (plen + tlen + blen + osize);	  memcpy (bakname, p, plen);	  memcpy (bakname + plen, to, tlen);	  memcpy (bakname + plen + tlen, b, blen);	  memcpy (bakname + plen + tlen + blen, o, osize);	  for (p += FILESYSTEM_PREFIX_LEN (p);  *p;  p++)	    if (ISSLASH (*p))	      {		try_makedirs_errno = ENOENT;		break;	      }	}      else	{	  bakname = find_backup_file_name (to, backup_type);	  if (!bakname)	    memory_fatal ();	}      if (to_errno)	{	  int fd;	  if (debug & 4)	    say ("Creating empty unreadable file %s\n", quotearg (bakname));	  try_makedirs_errno = ENOENT;	  unlink (bakname);	  while ((fd = creat (bakname, 0)) < 0)	    {	      if (errno != try_makedirs_errno)		pfatal ("Can't create file %s", quotearg (bakname));	      makedirs (bakname);	      try_makedirs_errno = 0;	    }	  if (close (fd) != 0)	    pfatal ("Can't close file %s", quotearg (bakname));	}      else	{	  if (debug & 4)	    say ("Renaming file %s to %s\n",		 quotearg_n (0, to), quotearg_n (1, bakname));	  while (rename (to, bakname) != 0)	    {	      if (errno != try_makedirs_errno)		pfatal ("Can't rename file %s to %s",			quotearg_n (0, to), quotearg_n (1, bakname));	      makedirs (bakname);	      try_makedirs_errno = 0;	    }	}      free (bakname);    }  if (from)    {      if (debug & 4)	say ("Renaming file %s to %s\n",	     quotearg_n (0, from), quotearg_n (1, to));      if (rename (from, to) != 0)	{	  bool to_dir_known_to_exist = false;	  if (errno == ENOENT	      && (to_errno == -1 || to_errno == ENOENT))	    {	      makedirs (to);	      to_dir_known_to_exist = 1;	      if (rename (from, to) == 0)		goto rename_succeeded;	    }	  if (errno == EXDEV)	    {	      if (! backup)		{		  if (unlink (to) == 0)		    to_dir_known_to_exist = true;		  else if (errno != ENOENT)		    pfatal ("Can't remove file %s", quotearg (to));		}	      if (! to_dir_known_to_exist)		makedirs (to);	      copy_file (from, to, 0, mode);	      return;	    }	  pfatal ("Can't rename file %s to %s",		  quotearg_n (0, from), quotearg_n (1, to));	}    rename_succeeded:      /* Do not clear *FROM_NEEDS_REMOVAL if it's possible that the	 rename returned zero because FROM and TO are hard links to	 the same file.  */      if (0 < to_errno	  || (to_errno == 0 && to_st.st_nlink <= 1))	*from_needs_removal = 0;    }  else if (! backup)    {      if (debug & 4)	say ("Removing file %s\n", quotearg (to));      if (unlink (to) != 0)	pfatal ("Can't remove file %s", quotearg (to));    }}/* Create FILE with OPEN_FLAGS, and with MODE adjusted so that   we can read and write the file and that the file is not executable.   Return the file descriptor.  */intcreate_file (char const *file, int open_flags, mode_t mode){  int fd;  mode |= S_IRUSR | S_IWUSR;  mode &= ~ (S_IXUSR | S_IXGRP | S_IXOTH);  if (! (O_CREAT && O_TRUNC))    close (creat (file, mode));  fd = open (file, O_CREAT | O_TRUNC | open_flags, mode);  if (fd < 0)    pfatal ("Can't create file %s", quotearg (file));  return fd;}/* Copy a file. */voidcopy_file (char const *from, char const *to, int to_flags, mode_t mode){  int tofd;  int fromfd;  size_t i;  if ((fromfd = open (from, O_RDONLY | O_BINARY)) < 0)    pfatal ("Can't reopen file %s", quotearg (from));  tofd = create_file (to, O_WRONLY | O_BINARY | to_flags, mode);  while ((i = read (fromfd, buf, bufsize)) != 0)    {      if (i == (size_t) -1)	read_fatal ();      if (write (tofd, buf, i) != i)	write_fatal ();    }  if (close (fromfd) != 0)    read_fatal ();  if (close (tofd) != 0)    write_fatal ();}static char const DEV_NULL[] = NULL_DEVICE;static char const RCSSUFFIX[] = ",v";static char const CHECKOUT[] = "co %s";static char const CHECKOUT_LOCKED[] = "co -l %s";static char const RCSDIFF1[] = "rcsdiff %s";static char const SCCSPREFIX[] = "s.";static char const GET[] = "get ";static char const GET_LOCKED[] = "get -e ";static char const SCCSDIFF1[] = "get -p ";static char const SCCSDIFF2[] = "|diff - %s";static char const CLEARTOOL_CO[] = "cleartool co -unr -nc ";static char const PERFORCE_CO[] = "p4 edit ";/* Return "RCS" if FILENAME is controlled by RCS,   "SCCS" if it is controlled by SCCS,   "ClearCase" if it is controlled by Clearcase,   "Perforce" if it is controlled by Perforce,   and 0 otherwise.   READONLY is true if we desire only readonly access to FILENAME.   FILESTAT describes FILENAME's status or is 0 if FILENAME does not exist.   If successful and if GETBUF is nonzero, set *GETBUF to a command   that gets the file; similarly for DIFFBUF and a command to diff the file   (but set *DIFFBUF to 0 if the diff operation is meaningless).   *GETBUF and *DIFFBUF must be freed by the caller.  */char const *version_controller (char const *filename, bool readonly,		    struct stat const *filestat, char **getbuf, char **diffbuf){  struct stat cstat;  char const *filebase = base_name (filename);  char const *dotslash = *filename == '-' ? "./" : "";  size_t dirlen = filebase - filename;  size_t filenamelen = strlen (filename);  size_t maxfixlen = sizeof "SCCS/" - 1 + sizeof SCCSPREFIX - 1;  size_t maxtrysize = filenamelen + maxfixlen + 1;  size_t quotelen = quote_system_arg (0, filename);  size_t maxgetsize = sizeof CLEARTOOL_CO + quotelen + maxfixlen;  size_t maxdiffsize =    (sizeof SCCSDIFF1 + sizeof SCCSDIFF2 + sizeof DEV_NULL - 1     + 2 * quotelen + maxfixlen);  char *trybuf = xmalloc (maxtrysize);  char const *r = 0;  strcpy (trybuf, filename);#define try1(f,a1)    (sprintf (trybuf + dirlen, f, a1),    stat (trybuf, &cstat) == 0)#define try2(f,a1,a2) (sprintf (trybuf + dirlen, f, a1,a2), stat (trybuf, &cstat) == 0)  /* Check that RCS file is not working file.     Some hosts don't report file name length errors.  */  if ((try2 ("RCS/%s%s", filebase, RCSSUFFIX)       || try1 ("RCS/%s", filebase)       || try2 ("%s%s", filebase, RCSSUFFIX))      && ! (filestat	    && filestat->st_dev == cstat.st_dev	    && filestat->st_ino == cstat.st_ino))    {      if (getbuf)	{	  char *p = *getbuf = xmalloc (maxgetsize);	  sprintf (p, readonly ? CHECKOUT : CHECKOUT_LOCKED, dotslash);	  p += strlen (p);	  p += quote_system_arg (p, filename);	  *p = '\0';	}      if (diffbuf)	{	  char *p = *diffbuf = xmalloc (maxdiffsize);	  sprintf (p, RCSDIFF1, dotslash);	  p += strlen (p);	  p += quote_system_arg (p, filename);	  *p++ = '>';	  strcpy (p, DEV_NULL);	}      r = "RCS";    }  else if (try2 ("SCCS/%s%s", SCCSPREFIX, filebase)	   || try2 ("%s%s", SCCSPREFIX, filebase))    {      if (getbuf)	{	  char *p = *getbuf = xmalloc (maxgetsize);	  sprintf (p, readonly ? GET : GET_LOCKED);	  p += strlen (p);	  p += quote_system_arg (p, trybuf);	  *p = '\0';	}      if (diffbuf)	{	  char *p = *diffbuf = xmalloc (maxdiffsize);	  strcpy (p, SCCSDIFF1);	  p += sizeof SCCSDIFF1 - 1;	  p += quote_system_arg (p, trybuf);	  sprintf (p, SCCSDIFF2, dotslash);	  p += strlen (p);	  p += quote_system_arg (p, filename);	  *p++ = '>';	  strcpy (p, DEV_NULL);	}      r = "SCCS";    }  else if (!readonly && filestat	   && try1 ("%s@@", filebase) && S_ISDIR (cstat.st_mode))    {      if (getbuf)	{	  char *p = *getbuf = xmalloc (maxgetsize);	  strcpy (p, CLEARTOOL_CO);	  p += sizeof CLEARTOOL_CO - 1;	  p += quote_system_arg (p, filename);	  *p = '\0';	}      if (diffbuf)	*diffbuf = 0;      r = "ClearCase";     }  else if (!readonly && filestat &&           (getenv("P4PORT") || getenv("P4USER") || getenv("P4CONFIG")))    {      if (getbuf)	{	  char *p = *getbuf = xmalloc (maxgetsize);	  strcpy (p, PERFORCE_CO);	  p += sizeof PERFORCE_CO - 1;	  p += quote_system_arg (p, filename);	  *p = '\0';	}      if (diffbuf)	*diffbuf = 0;      r = "Perforce";    }  free (trybuf);  return r;}/* Get FILENAME from version control system CS.  The file already exists if   EXISTS.  Only readonly access is needed if READONLY.   Use the command GETBUF to actually get the named file.   Store the resulting file status into *FILESTAT.   Return true if successful.  */boolversion_get (char const *filename, char const *cs, bool exists, bool readonly,	     char const *getbuf, struct stat *filestat){  if (patch_get < 0)    {      ask ("Get file %s from %s%s? [y] ",	   quotearg (filename), cs, readonly ? "" : " with lock");      if (*buf == 'n')	return 0;    }  if (dry_run)    {      if (! exists)	fatal ("can't do dry run on nonexistent version-controlled file %s; invoke `%s' and try again",	       quotearg (filename), getbuf);    }  else    {      if (verbosity == VERBOSE)	say ("Getting file %s from %s%s...\n", quotearg (filename),	     cs, readonly ? "" : " with lock");      if (systemic (getbuf) != 0)	fatal ("Can't get file %s from %s", quotearg (filename), cs);      if (stat (filename, filestat) != 0)	pfatal ("%s", quotearg (filename));    }  return 1;}/* Allocate a unique area for a string. */char *savebuf (register char const *s, register size_t size){  register char *rv;  assert (s && size);  rv = malloc (size);  if (! rv)    {      if (! using_plan_a)	memory_fatal ();    }  else    memcpy (rv, s, size);  return rv;}char *savestr (char const *s){  return savebuf (s, strlen (s) + 1);}voidremove_prefix (char *p, size_t prefixlen){  char const *s = p + prefixlen;  while ((*p++ = *s++))    continue;}char *format_linenum (char numbuf[LINENUM_LENGTH_BOUND + 1], LINENUM n){  char *p = numbuf + LINENUM_LENGTH_BOUND;  *p = '\0';  if (n < 0)    {      do	*--p = '0' - (int) (n % 10);      while ((n /= 10) != 0);      *--p = '-';    }  else    {      do	*--p = '0' + (int) (n % 10);      while ((n /= 10) != 0);    }  return p;}#if !HAVE_VPRINTF#define vfprintf my_vfprintfstatic intvfprintf (FILE *stream, char const *format, va_list args){#if !HAVE_DOPRNT && HAVE__DOPRINTF# define _doprnt _doprintf#endif#if HAVE_DOPRNT || HAVE__DOPRINTF  _doprnt (format, args, stream);  return ferror (stream) ? -1 : 0;#else  int *a = (int *) args;  return fprintf (stream, format,		  a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9]);#endif}#endif /* !HAVE_VPRINTF *//* Terminal output, pun intended. */voidfatal (char const *format, ...){  va_list args;  fprintf (stderr, "%s: **** ", program_name);  va_start (args, format);  vfprintf (stderr, format, args);  va_end (args);

⌨️ 快捷键说明

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