diff options
author | Andreas Gruenbacher <agruen@suse.de> | 2009-03-12 15:13:11 +0100 |
---|---|---|
committer | Andreas Gruenbacher <agruen@suse.de> | 2009-03-12 15:13:11 +0100 |
commit | bcce1233902dc7a94623b3a90cd7920c44f22474 (patch) | |
tree | 35098589ae46a13ab212e74fc6b0b710a44bbcb3 /util.c | |
parent | 068f401ee314e2274b58adbc1256286ae7a56f9f (diff) | |
download | patch-2.2.tar.gz |
Import of patch-2.2.tar.gzv2.2
Diffstat (limited to 'util.c')
-rw-r--r-- | util.c | 902 |
1 files changed, 575 insertions, 327 deletions
@@ -1,296 +1,477 @@ -#include "EXTERN.h" -#include "common.h" -#include "INTERN.h" -#include "util.h" -#include "backupfile.h" - -void my_exit(); - -#ifndef HAVE_STRERROR -static char * -private_strerror (errnum) - int errnum; -{ - extern char *sys_errlist[]; - extern int sys_nerr; +/* utility functions for `patch' */ + +/* $Id: util.c,v 1.9 1997/04/14 05:32:30 eggert Exp $ */ + +/* +Copyright 1986 Larry Wall +Copyright 1992, 1993, 1997 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 <version.h> +#undef XTERN +#define XTERN +#include <util.h> + +#include <signal.h> +#if !defined SIGCHLD && defined SIGCLD +#define SIGCHLD SIGCLD +#endif - if (errnum > 0 && errnum <= sys_nerr) - return sys_errlist[errnum]; - return "Unknown system error"; -} -#define strerror private_strerror -#endif /* !HAVE_STRERROR */ +#ifdef __STDC__ +# include <stdarg.h> +# define vararg_start va_start +#else +# define vararg_start(ap,p) va_start (ap) +# if HAVE_VARARGS_H +# include <varargs.h> +# else + typedef char *va_list; +# define va_dcl int va_alist; +# define va_start(ap) ((ap) = (va_list) &va_alist) +# define va_arg(ap, t) (((t *) ((ap) += sizeof (t))) [-1]) +# define va_end(ap) +# endif +#endif /* Rename a file, copying it if necessary. */ -int -move_file(from,to) -char *from, *to; +void +move_file (from, to, backup) + char const *from, *to; + int backup; { - char bakname[512]; - Reg1 char *s; - Reg2 int i; - Reg3 int fromfd; - - /* to stdout? */ - - if (strEQ(to, "-")) { -#ifdef DEBUGGING - if (debug & 4) - say2("Moving %s to stdout.\n", from); -#endif - fromfd = open(from, 0); - if (fromfd < 0) - pfatal2("internal error, can't reopen %s", from); - while ((i=read(fromfd, buf, sizeof buf)) > 0) - if (write(1, buf, i) != 1) - pfatal1("write failed"); - Close(fromfd); - return 0; - } - - if (origprae) { - Strcpy(bakname, origprae); - Strcat(bakname, to); - } else { -#ifndef NODIR - char *backupname = find_backup_file_name(to); - if (backupname == (char *) 0) - fatal1("out of memory\n"); - Strcpy(bakname, backupname); - free(backupname); -#else /* NODIR */ - Strcpy(bakname, to); - Strcat(bakname, simple_backup_suffix); -#endif /* NODIR */ - } - - if (stat(to, &filestat) == 0) { /* output file exists */ - dev_t to_device = filestat.st_dev; - ino_t to_inode = filestat.st_ino; - char *simplename = bakname; - - for (s=bakname; *s; s++) { - if (*s == '/') - simplename = s+1; + register char *s; + register char *bakname; + struct stat tost, bakst; + + if (backup && stat (to, &tost) == 0) + { + char *simplename; + + 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); } - /* Find a backup name that is not the same file. - Change the first lowercase char into uppercase; - if that isn't sufficient, chop off the first char and try again. */ - while (stat(bakname, &filestat) == 0 && - to_device == filestat.st_dev && to_inode == filestat.st_ino) { - /* Skip initial non-lowercase chars. */ - for (s=simplename; *s && !islower(*s); s++) ; - if (*s) - *s = toupper(*s); - else - Strcpy(simplename, simplename+1); + else + { + bakname = find_backup_file_name (to); + if (!bakname) + memory_fatal (); } - while (unlink(bakname) >= 0) ; /* while() is for benefit of Eunice */ -#ifdef DEBUGGING - if (debug & 4) - say3("Moving %s to %s.\n", to, bakname); -#endif - if (rename(to, bakname) < 0) { - say4("Can't backup %s, output is in %s: %s\n", to, from, - strerror(errno)); - return -1; + + simplename = base_name (bakname); + /* Find a backup name that is not the same file. + Change the first lowercase char into uppercase; + if that doesn't suffice, chop off the first char and try again. */ + while (stat (bakname, &bakst) == 0 + && tost.st_dev == bakst.st_dev + && tost.st_ino == bakst.st_ino) + { + /* Skip initial non-lowercase chars. */ + for (s=simplename; *s && !ISLOWER ((unsigned char) *s); s++) + continue; + if (*s) + *s = toupper ((unsigned char) *s); + else + remove_prefix (simplename, 1); } - while (unlink(to) >= 0) ; + if (debug & 4) + say ("Moving %s to %s.\n", to, bakname); + if (rename (to, bakname) != 0) + pfatal ("Can't rename `%s' to `%s'", to, bakname); + free (bakname); } -#ifdef DEBUGGING - if (debug & 4) - say3("Moving %s to %s.\n", from, to); -#endif - if (rename(from, to) < 0) { /* different file system? */ - Reg4 int tofd; - - tofd = creat(to, 0666); - if (tofd < 0) { - say4("Can't create %s, output is in %s: %s\n", - to, from, strerror(errno)); - return -1; + + if (debug & 4) + say ("Moving %s to %s.\n", from, to); + + if (rename (from, to) != 0) + { +#ifdef EXDEV + if (errno == EXDEV) + { + if (! backup && unlink (to) != 0 + && errno != ENOENT && errno != ENOTDIR) + pfatal ("Can't remove `%s'", to); + copy_file (from, to); + if (unlink (from) != 0) + pfatal ("Can't remove `%s'", from); + return; } - fromfd = open(from, 0); - if (fromfd < 0) - pfatal2("internal error, can't reopen %s", from); - while ((i=read(fromfd, buf, sizeof buf)) > 0) - if (write(tofd, buf, i) != i) - pfatal1("write failed"); - Close(fromfd); - Close(tofd); +#endif + pfatal ("Can't rename `%s' to `%s'", from, to); } - Unlink(from); - return 0; } /* Copy a file. */ void copy_file(from,to) -char *from, *to; + char const *from; + char const *to; { - Reg3 int tofd; - Reg2 int fromfd; - Reg1 int i; - - tofd = creat(to, 0666); - if (tofd < 0) - pfatal2("can't create %s", to); - fromfd = open(from, 0); - if (fromfd < 0) - pfatal2("internal error, can't reopen %s", from); - while ((i=read(fromfd, buf, sizeof buf)) > 0) - if (write(tofd, buf, i) != i) - pfatal2("write to %s failed", to); - Close(fromfd); - Close(tofd); + int tofd; + int fromfd = open (from, O_RDONLY); + long i; + + if (fromfd < 0) + pfatal ("can't reopen %s", from); + tofd = creat (to, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); + if (tofd < 0) + pfatal ("can't create %s", to); + while ((i = read (fromfd, buf, bufsize)) > 0) + if (write (tofd, buf, (size_t) i) != i) + write_fatal (); + if (i < 0 || close (fromfd) != 0) + read_fatal (); + if (close (tofd) != 0) + write_fatal (); } /* Allocate a unique area for a string. */ char * -savestr(s) -Reg1 char *s; +savebuf (s, size) + register char const *s; + register size_t size; { - Reg3 char *rv; - Reg2 char *t; - - if (!s) - s = "Oops"; - t = s; - while (*t++); - rv = malloc((MEM) (t - s)); - if (rv == Nullch) { - if (using_plan_a) - out_of_mem = TRUE; - else - fatal1("out of memory\n"); - } - else { - t = rv; - while (*t++ = *s++); + register char *rv; + + assert (s && size); + rv = malloc (size); + + if (! rv) + { + if (! using_plan_a) + memory_fatal (); } - return rv; + else + memcpy (rv, s, size); + + return rv; } -#if defined(lint) && defined(CANVARARG) +char * +savestr(s) + char const *s; +{ + return savebuf (s, strlen (s) + 1); +} -/*VARARGS ARGSUSED*/ -say(pat) char *pat; { ; } -/*VARARGS ARGSUSED*/ -fatal(pat) char *pat; { ; } -/*VARARGS ARGSUSED*/ -pfatal(pat) char *pat; { ; } -/*VARARGS ARGSUSED*/ -ask(pat) char *pat; { ; } +void +remove_prefix (p, prefixlen) + char *p; + size_t prefixlen; +{ + char const *s = p + prefixlen; + while ((*p++ = *s++)) + continue; +} +#if !HAVE_VPRINTF +#define vfprintf my_vfprintf +static int vfprintf PARAMS ((FILE *, char const *, va_list)); +static int +vfprintf (stream, format, args) + 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. */ -/* Vanilla terminal output (buffered). */ +#ifdef __STDC__ +void +fatal (char const *format, ...) +#else +/*VARARGS1*/ void +fatal (format, va_alist) + char const *format; + va_dcl +#endif +{ + va_list args; + fprintf (stderr, "%s: **** ", program_name); + vararg_start (args, format); + vfprintf (stderr, format, args); + va_end (args); + putc ('\n', stderr); + fflush (stderr); + fatal_exit (0); +} void -say(pat,arg1,arg2,arg3) -char *pat; -long arg1,arg2,arg3; +memory_fatal () { - fprintf(stderr, pat, arg1, arg2, arg3); - Fflush(stderr); + fatal ("out of memory"); } -/* Terminal output, pun intended. */ +void +read_fatal () +{ + pfatal ("read error"); +} -void /* very void */ -fatal(pat,arg1,arg2,arg3) -char *pat; -long arg1,arg2,arg3; +void +write_fatal () { - fprintf(stderr, "patch: **** "); - fprintf(stderr, pat, arg1, arg2, arg3); - my_exit(1); + pfatal ("write error"); } /* Say something from patch, something from the system, then silence . . . */ -void /* very void */ -pfatal(pat,arg1,arg2,arg3) -char *pat; -long arg1,arg2,arg3; +#ifdef __STDC__ +void +pfatal (char const *format, ...) +#else +/*VARARGS1*/ void +pfatal (format, va_alist) + char const *format; + va_dcl +#endif { - int errnum = errno; + int errnum = errno; + va_list args; + fprintf (stderr, "%s: **** ", program_name); + vararg_start (args, format); + vfprintf (stderr, format, args); + va_end (args); + fflush (stderr); + errno = errnum; + perror (" "); + fflush (stderr); + fatal_exit (0); +} + +/* Tell the user something. */ - fprintf(stderr, "patch: **** "); - fprintf(stderr, pat, arg1, arg2, arg3); - fprintf(stderr, ": %s\n", strerror(errnum)); - my_exit(1); +#ifdef __STDC__ +void +say (char const *format, ...) +#else +/*VARARGS1*/ void +say (format, va_alist) + char const *format; + va_dcl +#endif +{ + va_list args; + vararg_start (args, format); + vfprintf (stdout, format, args); + va_end (args); + fflush (stdout); } /* Get a response from the user, somehow or other. */ +#ifdef __STDC__ void -ask(pat,arg1,arg2,arg3) -char *pat; -long arg1,arg2,arg3; +ask (char const *format, ...) +#else +/*VARARGS1*/ void +ask (format, va_alist) + char const *format; + va_dcl +#endif { - int ttyfd; - int r; - bool tty2 = isatty(2); - - Sprintf(buf, pat, arg1, arg2, arg3); - Fflush(stderr); - write(2, buf, strlen(buf)); - if (tty2) { /* might be redirected to a file */ - r = read(2, buf, sizeof buf); - } - else if (isatty(1)) { /* this may be new file output */ - Fflush(stdout); - write(1, buf, strlen(buf)); - r = read(1, buf, sizeof buf); - } - else if ((ttyfd = open("/dev/tty", 2)) >= 0 && isatty(ttyfd)) { - /* might be deleted or unwriteable */ - write(ttyfd, buf, strlen(buf)); - r = read(ttyfd, buf, sizeof buf); - Close(ttyfd); + static int ttyfd = -2; + int r; + va_list args; + + vararg_start (args, format); + vfprintf (stdout, format, args); + va_end (args); + fflush (stdout); + + if (ttyfd == -2) + { + ttyfd = open ("/dev/tty", O_RDONLY); + if (ttyfd < 0) + { + close (ttyfd); + for (ttyfd = STDERR_FILENO; 0 <= ttyfd; ttyfd--) + if (isatty (ttyfd)) + break; + } } - else if (isatty(0)) { /* this is probably patch input */ - Fflush(stdin); - write(0, buf, strlen(buf)); - r = read(0, buf, sizeof buf); + + if (ttyfd < 0) + { + /* No terminal at all -- default it. */ + buf[0] = '\n'; + r = 1; } - else { /* no terminal at all--default it */ - buf[0] = '\n'; - r = 1; + else + { + r = read (ttyfd, buf, bufsize - 1); + if (r == 0) + printf ("EOF\n"); + else if (r < 0) + { + close (ttyfd); + ttyfd = -1; + r = 0; + } } - if (r <= 0) - buf[0] = 0; - else - buf[r] = '\0'; - if (!tty2) - say1(buf); + + buf[r] = '\0'; } -#endif /* lint */ /* How to handle certain events when not in a critical region. */ +#define NUM_SIGS (sizeof (sigs) / sizeof (*sigs)) +static int const sigs[] = { +#ifdef SIGHUP + SIGHUP, +#endif +#ifdef SIGTERM + SIGTERM, +#endif +#ifdef SIGXCPU + SIGXCPU, +#endif +#ifdef SIGXFSZ + SIGXFSZ, +#endif + SIGINT, + SIGPIPE +}; + +#if !HAVE_SIGPROCMASK +#define sigset_t int +#define sigemptyset(s) (*(s) = 0) +#ifndef sigmask +#define sigmask(sig) (1 << ((sig) - 1)) +#endif +#define sigaddset(s, sig) (*(s) |= sigmask (sig)) +#define sigismember(s, sig) ((*(s) & sigmask (sig)) != 0) +#ifndef SIG_BLOCK +#define SIG_BLOCK 0 +#endif +#ifndef SIG_UNBLOCK +#define SIG_UNBLOCK (SIG_BLOCK + 1) +#endif +#ifndef SIG_SETMASK +#define SIG_SETMASK (SIG_BLOCK + 2) +#endif +#define sigprocmask(how, n, o) \ + ((how) == SIG_BLOCK \ + ? ((o) ? *(o) = sigblock (*(n)) : sigblock (*(n))) \ + : (how) == SIG_UNBLOCK \ + ? sigsetmask (((o) ? *(o) = sigblock (0) : sigblock (0)) & ~*(n)) \ + : (o ? *(o) = sigsetmask (*(n)) : sigsetmask (*(n)))) +#if !HAVE_SIGSETMASK +#define sigblock(mask) 0 +#define sigsetmask(mask) 0 +#endif +#endif + +static sigset_t initial_signal_mask; +static sigset_t signals_to_block; + +#if ! HAVE_SIGACTION +static RETSIGTYPE fatal_exit_handler PARAMS ((int)) __attribute__ ((noreturn)); +static RETSIGTYPE +fatal_exit_handler (sig) + int sig; +{ + signal (sig, SIG_IGN); + fatal_exit (sig); +} +#endif + void set_signals(reset) int reset; { -#ifndef lint - static RETSIGTYPE (*hupval)(),(*intval)(); - - if (!reset) { - hupval = signal(SIGHUP, SIG_IGN); - if (hupval != SIG_IGN) - hupval = (RETSIGTYPE(*)())my_exit; - intval = signal(SIGINT, SIG_IGN); - if (intval != SIG_IGN) - intval = (RETSIGTYPE(*)())my_exit; + int i; +#if HAVE_SIGACTION + struct sigaction initial_act, fatal_act; + fatal_act.sa_handler = fatal_exit; + sigemptyset (&fatal_act.sa_mask); + fatal_act.sa_flags = 0; +#define setup_handler(sig) sigaction (sig, &fatal_act, (struct sigaction *) 0) +#else +#define setup_handler(sig) signal (sig, fatal_exit_handler) +#endif + + if (!reset) + { +#ifdef SIGCHLD + /* System V fork+wait does not work if SIGCHLD is ignored. */ + signal (SIGCHLD, SIG_DFL); +#endif + sigemptyset (&signals_to_block); + for (i = 0; i < NUM_SIGS; i++) + { + int ignoring_signal; +#if HAVE_SIGACTION + if (sigaction (sigs[i], (struct sigaction *) 0, &initial_act) != 0) + continue; + ignoring_signal = initial_act.sa_handler == SIG_IGN; +#else + ignoring_signal = signal (sigs[i], SIG_IGN) == SIG_IGN; +#endif + if (! ignoring_signal) + { + sigaddset (&signals_to_block, sigs[i]); + setup_handler (sigs[i]); + } + } } - Signal(SIGHUP, hupval); - Signal(SIGINT, intval); + else + { + /* Undo the effect of ignore_signals. */ +#if HAVE_SIGPROCMASK || HAVE_SIGSETMASK + sigprocmask (SIG_SETMASK, &initial_signal_mask, (sigset_t *) 0); +#else + for (i = 0; i < NUM_SIGS; i++) + if (sigismember (&signals_to_block, sigs[i])) + setup_handler (sigs[i]); #endif + } } /* How to handle certain events when in a critical region. */ @@ -298,136 +479,203 @@ int reset; void ignore_signals() { -#ifndef lint - Signal(SIGHUP, SIG_IGN); - Signal(SIGINT, SIG_IGN); +#if HAVE_SIGPROCMASK || HAVE_SIGSETMASK + sigprocmask (SIG_BLOCK, &signals_to_block, &initial_signal_mask); +#else + int i; + for (i = 0; i < NUM_SIGS; i++) + if (sigismember (&signals_to_block, sigs[i])) + signal (sigs[i], SIG_IGN); #endif } +void +exit_with_signal (sig) + int sig; +{ + sigset_t s; + signal (sig, SIG_DFL); + sigemptyset (&s); + sigaddset (&s, sig); + sigprocmask (SIG_UNBLOCK, &s, (sigset_t *) 0); + kill (getpid (), sig); + exit (2); +} + +#if !HAVE_MKDIR +/* This is good enough for `patch'; it's not a general emulator. */ +static int mkdir PARAMS ((char const *, int)); +static int +mkdir (path, mode) + char const *path; + int mode; /* ignored */ +{ + char *cmd = xmalloc (strlen (path) + 9); + int r; + sprintf (cmd, "mkdir '%s'", path); + r = system (cmd); + free (cmd); + return r; +} +#endif + +/* Replace '/' with '\0' in FILENAME if it marks a place that + needs testing for the existence of directory. Return the address + of the last location replaced, or FILENAME if none were replaced. */ +static char *replace_slashes PARAMS ((char *)); +static char * +replace_slashes (filename) + char *filename; +{ + char *f; + for (f = filename; *f == '/'; f++) + continue; + for (; *f; f++) + if (*f == '/') + { + *f = '\0'; + while (f[1] == '/') + f++; + } + while (filename != f && *--f) + continue; + return f; +} + +/* Count the number of path name components in the existing leading prefix + of `filename'. Do not count the last element, or the root dir. */ +int +countdirs (filename) + char *filename; +{ + int count = 0; + + if (*filename) + { + register char *f; + register char *flim = replace_slashes (filename); + + /* Now turn the '\0's back to '/'s, calling stat as we go. */ + for (f = filename; f <= flim; f++) + if (!*f) + { + struct stat sbuf; + if (stat (filename, &sbuf) != 0) + break; + count++; + *f = '/'; + } + + for (; f <= flim; f++) + if (!*f) + *f = '/'; + } + + return count; +} + /* Make sure we'll have the directories to create a file. - If `striplast' is TRUE, ignore the last element of `filename'. */ + Ignore the last element of `filename'. */ void -makedirs(filename,striplast) -Reg1 char *filename; -bool striplast; +makedirs (filename) + register char *filename; { - char tmpbuf[256]; - Reg2 char *s = tmpbuf; - char *dirv[20]; /* Point to the NULs between elements. */ - Reg3 int i; - Reg4 int dirvp = 0; /* Number of finished entries in dirv. */ - - /* Copy `filename' into `tmpbuf' with a NUL instead of a slash - between the directories. */ - while (*filename) { - if (*filename == '/') { - filename++; - dirv[dirvp++] = s; - *s++ = '\0'; - } - else { - *s++ = *filename++; - } - } - *s = '\0'; - dirv[dirvp] = s; - if (striplast) - dirvp--; - if (dirvp < 0) - return; - - strcpy(buf, "mkdir"); - s = buf; - for (i=0; i<=dirvp; i++) { - struct stat sbuf; - - if (stat(tmpbuf, &sbuf) && errno == ENOENT) { - while (*s) s++; - *s++ = ' '; - strcpy(s, tmpbuf); - } - *dirv[i] = '/'; + if (*filename) + { + register char *f; + register char *flim = replace_slashes (filename); + + /* Now turn the NULs back to '/'s; stop when the path doesn't exist. */ + errno = 0; + for (f = filename; f <= flim; f++) + if (!*f) + { + struct stat sbuf; + if (stat (filename, &sbuf) != 0) + break; + *f = '/'; + } + + /* Create the missing directories, replacing NULs by '/'s. */ + if (errno == ENOENT) + for (; f <= flim; f++) + if (!*f) + { + if (mkdir (filename, + S_IRUSR|S_IWUSR|S_IXUSR + |S_IRGRP|S_IWGRP|S_IXGRP + |S_IROTH|S_IWOTH|S_IXOTH) != 0) + break; + *f = '/'; + } + + for (; f <= flim; f++) + if (!*f) + *f = '/'; } - if (s != buf) - system(buf); } /* Make filenames more reasonable. */ char * -fetchname(at,strip_leading,assume_exists) +fetchname (at, strip_leading) char *at; int strip_leading; -int assume_exists; { - char *fullname; char *name; - Reg1 char *t; - char tmpbuf[200]; + register char *t; int sleading = strip_leading; if (!at) - return Nullch; - while (isspace(*at)) + return 0; + while (ISSPACE (*at)) at++; -#ifdef DEBUGGING if (debug & 128) - say4("fetchname %s %d %d\n",at,strip_leading,assume_exists); -#endif - if (strnEQ(at, "/dev/null", 9)) /* so files can be created by diffing */ - return Nullch; /* against /dev/null. */ - name = fullname = t = savestr(at); + say ("fetchname %s %d\n", at, strip_leading); + name = at; /* Strip off up to `sleading' leading slashes and null terminate. */ - for (; *t && !isspace(*t); t++) + for (t = at; *t; t++) if (*t == '/') + { + while (t[1] == '/') + t++; if (--sleading >= 0) name = t+1; - *t = '\0'; - - /* If no -p option was given (957 is the default value!), - we were given a relative pathname, - and the leading directories that we just stripped off all exist, - put them back on. */ - if (strip_leading == 957 && name != fullname && *fullname != '/') { - name[-1] = '\0'; - if (stat(fullname, &filestat) == 0 && S_ISDIR (filestat.st_mode)) { - name[-1] = '/'; - name=fullname; - } - } + } + else if (ISSPACE (*t)) + { + *t = '\0'; + break; + } - name = savestr(name); - free(fullname); - - if (stat(name, &filestat) && !assume_exists) { - char *filebase = basename(name); - int pathlen = filebase - name; - - /* Put any leading path into `tmpbuf'. */ - strncpy(tmpbuf, name, pathlen); - -#define try(f, a1, a2) (Sprintf(tmpbuf + pathlen, f, a1, a2), stat(tmpbuf, &filestat) == 0) - if ( try("RCS/%s%s", filebase, RCSSUFFIX) - || try("RCS/%s" , filebase, 0) - || try( "%s%s", filebase, RCSSUFFIX) - || try("SCCS/%s%s", SCCSPREFIX, filebase) - || try( "%s%s", SCCSPREFIX, filebase)) - return name; - free(name); - name = Nullch; - } + if (!*name) + return 0; + + /* Allow files to be created by diffing against /dev/null. */ + if (strcmp (at, "/dev/null") == 0) + return 0; - return name; + return savestr (name); } -char * +VOID * xmalloc (size) - unsigned size; + size_t size; { - register char *p = (char *) malloc (size); + register VOID *p = malloc (size); if (!p) - fatal("out of memory"); + memory_fatal (); return p; } + +void +Fseek (stream, offset, ptrname) + FILE *stream; + long offset; + int ptrname; +{ + if (fseek (stream, offset, ptrname) != 0) + pfatal ("fseek"); +} |