diff options
Diffstat (limited to 'contrib/patch/util.c')
-rw-r--r-- | contrib/patch/util.c | 1079 |
1 files changed, 0 insertions, 1079 deletions
diff --git a/contrib/patch/util.c b/contrib/patch/util.c deleted file mode 100644 index 03a8e16..0000000 --- a/contrib/patch/util.c +++ /dev/null @@ -1,1079 +0,0 @@ -/* utility functions for `patch' */ - -/* $Id: util.c,v 1.24 1997/07/10 08:16:12 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 <quotearg.h> -#include <version.h> -#undef XTERN -#define XTERN -#include <util.h> - -#include <maketime.h> -#include <partime.h> - -#include <signal.h> -#if !defined SIGCHLD && defined SIGCLD -#define SIGCHLD SIGCLD -#endif -#if ! HAVE_RAISE -# define raise(sig) kill (getpid (), sig) -#endif - -#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 - -static void makedirs PARAMS ((char *)); - -/* Move a file FROM 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). - Back up TO if BACKUP is nonzero. */ - -#ifdef __STDC__ -/* If mode_t doesn't promote to itself, we can't use old-style definition. */ -void -move_file (char const *from, char *to, mode_t mode, int backup) -#else -void -move_file (from, to, mode, backup) - char const *from; - char *to; - mode_t mode; - int backup; -#endif -{ - 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); - if (!bakname) - memory_fatal (); - } - - if (to_errno) - { - int fd; - if (debug & 4) - say ("creating empty unreadable file `%s'\n", bakname); - try_makedirs_errno = ENOENT; - unlink (bakname); - while ((fd = creat (bakname, 0)) < 0) - { - if (errno != try_makedirs_errno) - pfatal ("can't create file `%s'", bakname); - makedirs (bakname); - try_makedirs_errno = 0; - } - if (close (fd) != 0) - pfatal ("can't close `%s'", bakname); - } - else - { - if (debug & 4) - say ("renaming `%s' to `%s'\n", to, bakname); - while (rename (to, bakname) != 0) - { - if (errno != try_makedirs_errno) - pfatal ("can't rename `%s' to `%s'", to, bakname); - makedirs (bakname); - try_makedirs_errno = 0; - } - } - - free (bakname); - } - - if (from) - { - if (debug & 4) - say ("renaming `%s' to `%s'\n", from, to); - - if (rename (from, to) != 0) - { - int to_dir_known_to_exist = 0; - - if (errno == ENOENT - && (to_errno == -1 || to_errno == ENOENT)) - { - makedirs (to); - to_dir_known_to_exist = 1; - if (rename (from, to) == 0) - return; - } - - if (errno == EXDEV) - { - if (! backup) - { - if (unlink (to) == 0) - to_dir_known_to_exist = 1; - else if (errno != ENOENT) - pfatal ("can't remove `%s'", to); - } - if (! to_dir_known_to_exist) - makedirs (to); - copy_file (from, to, mode); - return; - } - - pfatal ("can't rename `%s' to `%s'", from, to); - } - } - else if (! backup) - { - if (debug & 4) - say ("removing `%s'\n", to); - if (unlink (to) != 0) - pfatal ("can't remove `%s'", 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. */ -#ifdef __STDC__ -/* If mode_t doesn't promote to itself, we can't use old-style definition. */ -int -create_file (char const *file, int open_flags, mode_t mode) -#else -int -create_file (file, open_flags, mode) - char const *file; - int open_flags; - mode_t mode; -#endif -{ - 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 `%s'", file); - return fd; -} - -/* Copy a file. */ - -#ifdef __STDC__ -/* If mode_t doesn't promote to itself, we can't use old-style definition. */ -void -copy_file (char const *from, char const *to, mode_t mode) -#else -void -copy_file (from, to, mode) - char const *from; - char const *to; - mode_t mode; -#endif -{ - int tofd; - int fromfd; - size_t i; - - if ((fromfd = open (from, O_RDONLY | O_BINARY)) < 0) - pfatal ("can't reopen `%s'", from); - tofd = create_file (to, O_WRONLY | O_BINARY, mode); - while ((i = read (fromfd, buf, bufsize)) != 0) - { - if (i == -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 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 RCSSUFFIX[] = ",v"; -static char const CHECKOUT[] = "co %s"; -static char const CHECKOUT_LOCKED[] = "co -l %s"; -static char const RCSDIFF1[] = "rcsdiff %s"; - -/* Return "RCS" if FILENAME is controlled by RCS, - "SCCS" if it is controlled by SCCS, and 0 otherwise. - READONLY is nonzero 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. - *GETBUF and *DIFFBUF must be freed by the caller. */ -char const * -version_controller (filename, readonly, filestat, getbuf, diffbuf) - char const *filename; - int readonly; - struct stat const *filestat; - char **getbuf; - char **diffbuf; -{ - struct stat cstat; - char const *filebase = base_name (filename); - char const *dotslash = *filename == '-' ? "./" : ""; - size_t dir_len = 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 GET_LOCKED + 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 + dir_len, f, a1), stat (trybuf, &cstat) == 0) -#define try2(f,a1,a2) (sprintf (trybuf + dir_len, 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"; - } - - free (trybuf); - return r; -} - -/* Get FILENAME from version control system CS. The file already exists if - EXISTS is nonzero. Only readonly access is needed if READONLY is nonzero. - Use the command GETBUF to actually get the named file. - Store the resulting file status into *FILESTAT. - Return nonzero if successful. */ -int -version_get (filename, cs, exists, readonly, getbuf, filestat) - char const *filename; - char const *cs; - int exists; - int readonly; - char const *getbuf; - struct stat *filestat; -{ - if (patch_get < 0) - { - ask ("Get file `%s' from %s%s? [y] ", 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", - filename, getbuf); - } - else - { - if (verbosity == VERBOSE) - say ("Getting file `%s' from %s%s...\n", filename, - cs, readonly ? "" : " with lock"); - if (systemic (getbuf) != 0) - fatal ("can't get file `%s' from %s", filename, cs); - if (stat (filename, filestat) != 0) - pfatal ("%s", filename); - } - - return 1; -} - -/* Allocate a unique area for a string. */ - -char * -savebuf (s, size) - 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(s) - char const *s; -{ - return savebuf (s, strlen (s) + 1); -} - -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. */ - -#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 -memory_fatal () -{ - fatal ("out of memory"); -} - -void -read_fatal () -{ - pfatal ("read error"); -} - -void -write_fatal () -{ - pfatal ("write error"); -} - -/* Say something from patch, something from the system, then silence . . . */ - -#ifdef __STDC__ -void -pfatal (char const *format, ...) -#else -/*VARARGS1*/ void -pfatal (format, va_alist) - char const *format; - va_dcl -#endif -{ - int errnum = errno; - va_list args; - fprintf (stderr, "%s: **** ", program_name); - vararg_start (args, format); - vfprintf (stderr, format, args); - va_end (args); - fflush (stderr); /* perror bypasses stdio on some hosts. */ - errno = errnum; - perror (" "); - fflush (stderr); - fatal_exit (0); -} - -/* Tell the user something. */ - -#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 (char const *format, ...) -#else -/*VARARGS1*/ void -ask (format, va_alist) - char const *format; - va_dcl -#endif -{ - 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) - { - /* If standard output is not a tty, don't bother opening /dev/tty, - since it's unlikely that stdout will be seen by the tty user. - The isatty test also works around a bug in GNU Emacs 19.34 under Linux - which makes a call-process `patch' hang when it reads from /dev/tty. - POSIX.2 requires that we read /dev/tty, though. */ - ttyfd = (posixly_correct || isatty (STDOUT_FILENO) - ? open (TTY_DEVICE, O_RDONLY) - : -1); - } - - if (ttyfd < 0) - { - /* No terminal at all -- default it. */ - printf ("\n"); - buf[0] = '\n'; - buf[1] = '\0'; - } - else - { - size_t s = 0; - while ((r = read (ttyfd, buf + s, bufsize - 1 - s)) == bufsize - 1 - s - && buf[bufsize - 2] != '\n') - { - s = bufsize - 1; - bufsize *= 2; - buf = realloc (buf, bufsize); - if (!buf) - memory_fatal (); - } - if (r == 0) - printf ("EOF\n"); - else if (r < 0) - { - perror ("tty read"); - fflush (stderr); - close (ttyfd); - ttyfd = -1; - r = 0; - } - buf[s + r] = '\0'; - } -} - -/* Return nonzero if it OK to reverse a patch. */ - -#ifdef __STDC__ -int -ok_to_reverse (char const *format, ...) -#else -ok_to_reverse (format, va_alist) - char const *format; - va_dcl -#endif -{ - int r = 0; - - if (noreverse || ! (force && verbosity == SILENT)) - { - va_list args; - vararg_start (args, format); - vfprintf (stdout, format, args); - va_end (args); - } - - if (noreverse) - { - printf (" Skipping patch.\n"); - skip_rest_of_patch = TRUE; - r = 0; - } - else if (force) - { - if (verbosity != SILENT) - printf (" Applying it anyway.\n"); - r = 0; - } - else if (batch) - { - say (reverse ? " Ignoring -R.\n" : " Assuming -R.\n"); - r = 1; - } - else - { - ask (reverse ? " Ignore -R? [n] " : " Assume -R? [n] "); - r = *buf == 'y'; - if (! r) - { - ask ("Apply anyway? [n] "); - if (*buf != 'y') - { - if (verbosity != SILENT) - say ("Skipping patch.\n"); - skip_rest_of_patch = TRUE; - } - } - } - - return r; -} - -/* 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 SIGPIPE - SIGPIPE, -#endif -#ifdef SIGTERM - SIGTERM, -#endif -#ifdef SIGXCPU - SIGXCPU, -#endif -#ifdef SIGXFSZ - SIGXFSZ, -#endif - SIGINT -}; - -#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; -{ - 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]); - } - } - } - 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. */ - -void -ignore_signals() -{ -#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); - raise (sig); - exit (2); -} - -int -systemic (command) - char const *command; -{ - if (debug & 8) - say ("+ %s\n", command); - fflush (stdout); - return system (command); -} - -#if !HAVE_MKDIR -/* These mkdir and rmdir substitutes are good enough for `patch'; - they are not general emulators. */ - -static int doprogram PARAMS ((char const *, char const *)); -static int mkdir PARAMS ((char const *, mode_t)); -static int rmdir PARAMS ((char const *)); - -static int -doprogram (program, arg) - char const *program; - char const *arg; -{ - int result; - static char const DISCARD_OUTPUT[] = " 2>/dev/null"; - size_t program_len = strlen (program); - char *cmd = xmalloc (program_len + 1 + quote_system_arg (0, arg) - + sizeof DISCARD_OUTPUT); - char *p = cmd; - strcpy (p, program); - p += program_len; - *p++ = ' '; - p += quote_system_arg (p, arg); - strcpy (p, DISCARD_OUTPUT); - result = systemic (cmd); - free (cmd); - return result; -} - -#ifdef __STDC__ -/* If mode_t doesn't promote to itself, we can't use old-style definition. */ -static int -mkdir (char const *path, mode_t mode) -#else -static int -mkdir (path, mode) - char const *path; - mode_t mode; /* ignored */ -#endif -{ - return doprogram ("mkdir", path); -} - -static int -rmdir (path) - char const *path; -{ - int result = doprogram ("rmdir", path); - errno = EEXIST; - return result; -} -#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 0 if none were replaced. */ -static char *replace_slashes PARAMS ((char *)); -static char * -replace_slashes (filename) - char *filename; -{ - char *f; - char *last_location_replaced = 0; - char const *component_start; - - for (f = filename + FILESYSTEM_PREFIX_LEN (filename); ISSLASH (*f); f++) - continue; - - component_start = f; - - for (; *f; f++) - if (ISSLASH (*f)) - { - char *slash = f; - - /* Treat multiple slashes as if they were one slash. */ - while (ISSLASH (f[1])) - f++; - - /* Ignore slashes at the end of the path. */ - if (! f[1]) - break; - - /* "." and ".." need not be tested. */ - if (! (slash - component_start <= 2 - && component_start[0] == '.' && slash[-1] == '.')) - { - *slash = '\0'; - last_location_replaced = slash; - } - - component_start = f + 1; - } - - return last_location_replaced; -} - -/* Make sure we'll have the directories to create a file. - Ignore the last element of `filename'. */ - -static void -makedirs (filename) - register char *filename; -{ - register char *f; - register char *flim = replace_slashes (filename); - - if (flim) - { - /* Create any missing directories, replacing NULs by '/'s. - Ignore errors. We may have to keep going even after an EEXIST, - since the path may contain ".."s; and when there is an EEXIST - failure the system may return some other error number. - Any problems will eventually be reported when we create the file. */ - for (f = filename; f <= flim; f++) - if (!*f) - { - mkdir (filename, - S_IRUSR|S_IWUSR|S_IXUSR - |S_IRGRP|S_IWGRP|S_IXGRP - |S_IROTH|S_IWOTH|S_IXOTH); - *f = '/'; - } - } -} - -/* Remove empty ancestor directories of FILENAME. - Ignore errors, since the path may contain ".."s, and when there - is an EEXIST failure the system may return some other error number. */ -void -removedirs (filename) - char *filename; -{ - size_t i; - - for (i = strlen (filename); i != 0; i--) - if (ISSLASH (filename[i]) - && ! (ISSLASH (filename[i - 1]) - || (filename[i - 1] == '.' - && (i == 1 - || ISSLASH (filename[i - 2]) - || (filename[i - 2] == '.' - && (i == 2 - || ISSLASH (filename[i - 3]))))))) - { - filename[i] = '\0'; - if (rmdir (filename) == 0 && verbosity == VERBOSE) - say ("Removed empty directory `%s'.\n", filename); - filename[i] = '/'; - } -} - -static time_t initial_time; - -void -init_time () -{ - time (&initial_time); -} - -/* Make filenames more reasonable. */ - -char * -fetchname (at, strip_leading, pstamp) -char *at; -int strip_leading; -time_t *pstamp; -{ - char *name; - register char *t; - int sleading = strip_leading; - time_t stamp = (time_t) -1; - - while (ISSPACE ((unsigned char) *at)) - at++; - if (debug & 128) - say ("fetchname %s %d\n", at, strip_leading); - - name = at; - /* Strip off up to `sleading' leading slashes and null terminate. */ - for (t = at; *t; t++) - { - if (ISSLASH (*t)) - { - while (ISSLASH (t[1])) - t++; - if (--sleading >= 0) - name = t+1; - } - else if (ISSPACE ((unsigned char) *t)) - { - if (set_time | set_utc) - stamp = str2time (t, initial_time, set_utc ? 0L : TM_LOCAL_ZONE); - else - { - /* The head says the file is nonexistent if the timestamp - is the epoch; but the listed time is local time, not UTC, - and POSIX.1 allows local time to be 24 hours away from UTC. - So match any time within 24 hours of the epoch. - Use a default time zone 24 hours behind UTC so that any - non-zoned time within 24 hours of the epoch is valid. */ - stamp = str2time (t, initial_time, -24L * 60 * 60); - if (0 <= stamp && stamp <= 2 * 24L * 60 * 60) - stamp = 0; - } - - *t = '\0'; - break; - } - } - - if (!*name) - return 0; - - /* Allow files to be created by diffing against /dev/null. */ - if (strcmp (at, "/dev/null") == 0) - { - if (pstamp) - *pstamp = 0; - return 0; - } - - if (pstamp) - *pstamp = stamp; - - return savestr (name); -} - -GENERIC_OBJECT * -xmalloc (size) - size_t size; -{ - register GENERIC_OBJECT *p = malloc (size); - if (!p) - memory_fatal (); - return p; -} - -void -Fseek (stream, offset, ptrname) - FILE *stream; - file_offset offset; - int ptrname; -{ - if (file_seek (stream, offset, ptrname) != 0) - pfatal ("fseek"); -} |