]> Dogcows Code - chaz/tar/commitdiff
*** empty log message ***
authorFrançois Pinard <pinard@iro.umontreal.ca>
Wed, 16 Nov 1994 02:43:28 +0000 (02:43 +0000)
committerFrançois Pinard <pinard@iro.umontreal.ca>
Wed, 16 Nov 1994 02:43:28 +0000 (02:43 +0000)
src/create.c
src/port.c [new file with mode: 0644]
src/version.c [new file with mode: 0644]

index 0bf8a70733d483c20d8a593553a2e5038b45dc5f..1bc82beb02be3e0412e9e6b2d9a711707cc91bcd 100644 (file)
@@ -1,5 +1,5 @@
 /* Create a tar archive.
-   Copyright (C) 1985, 1992 Free Software Foundation
+   Copyright (C) 1985, 1992, 1993 Free Software Foundation
 
 This file is part of GNU Tar.
 
@@ -170,10 +170,8 @@ create_archive ()
     }
   else
     {
-      p = name_next (1);
-      do
+      while (p = name_next (1))
        dump_file (p, -1, 1);
-      while (p = name_next (1));
     }
 
   write_eot ();
@@ -345,7 +343,7 @@ dump_file (p, curdev, toplevel)
        }
 
       /* Not found.  Add it to the list of possible links. */
-      lp = (struct link *) malloc ((unsigned) (sizeof (struct link) + strlen (p)));
+      lp = (struct link *) ck_malloc ((unsigned) (sizeof (struct link) + strlen (p)));
       if (!lp)
        {
          if (!nolinks)
@@ -992,7 +990,7 @@ init_sparsearray ()
   /*
         * Make room for our scratch space -- initially is 10 elts long
         */
-  sparsearray = (struct sp_array *) malloc (sp_array_size * sizeof (struct sp_array));
+  sparsearray = (struct sp_array *) ck_malloc (sp_array_size * sizeof (struct sp_array));
   for (i = 0; i < sp_array_size; i++)
     {
       sparsearray[i].offset = 0;
diff --git a/src/port.c b/src/port.c
new file mode 100644 (file)
index 0000000..2f3c282
--- /dev/null
@@ -0,0 +1,1161 @@
+/* Supporting routines which may sometimes be missing.
+   Copyright (C) 1988 Free Software Foundation
+
+This file is part of GNU Tar.
+
+GNU Tar 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.
+
+GNU Tar 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 GNU Tar; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <errno.h>
+#ifndef STDC_HEADERS
+extern int errno;
+#endif
+
+#ifdef BSD42
+#include <sys/file.h>
+#else
+#ifndef V7
+#include <fcntl.h>
+#endif
+#endif
+
+#include "tar.h"
+#include "port.h"
+
+extern long baserec;
+
+/* All machine-dependent #ifdefs should appear here, instead of
+   being scattered through the file.  For UN*X systems, it is better to
+   figure out what is needed in the configure script, for most of the
+   features. */
+
+#ifdef __MSDOS__
+char TTY_NAME[] = "con";
+
+#else /* not __MSDOS__ */
+
+char TTY_NAME[] ="/dev/tty";
+
+#endif /* not __MSDOS__ */
+
+/* End of system-dependent #ifdefs */
+
+
+#ifndef HAVE_VALLOC
+/*
+ * valloc() does a malloc() on a page boundary.  On some systems,
+ * this can make large block I/O more efficient.
+ */
+char *
+valloc (size)
+       unsigned size;
+{
+       return (malloc (size));
+}
+#endif
+
+#ifndef HAVE_MKDIR
+/*
+ * Written by Robert Rother, Mariah Corporation, August 1985. 
+ *
+ * If you want it, it's yours.  All I ask in return is that if you
+ * figure out how to do this in a Bourne Shell script you send me
+ * a copy.
+ *                                     sdcsvax!rmr or rmr@uscd
+ *
+ * Severely hacked over by John Gilmore to make a 4.2BSD compatible
+ * subroutine. 11Mar86; hoptoad!gnu
+ *
+ * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
+ * subroutine didn't return EEXIST.  It does now.
+ */
+
+/*
+ * Make a directory.
+ */
+int
+mkdir(dpath, dmode)
+       char *dpath;
+       int dmode;
+{
+       int cpid, status;
+       struct stat statbuf;
+
+       if (stat(dpath,&statbuf) == 0) {
+               errno = EEXIST;         /* Stat worked, so it already exists */
+               return -1;
+       }
+
+       /* If stat fails for a reason other than non-existence, return error */
+       if (errno != ENOENT) return -1; 
+
+       switch (cpid = fork()) {
+
+       case -1:                        /* Error in fork() */
+               return(-1);             /* Errno is set already */
+
+       case 0:                         /* Child process */
+               /*
+                * Cheap hack to set mode of new directory.  Since this
+                * child process is going away anyway, we zap its umask.
+                * FIXME, this won't suffice to set SUID, SGID, etc. on this
+                * directory.  Does anybody care?
+                */
+               status = umask(0);      /* Get current umask */
+               status = umask(status | (0777 & ~dmode)); /* Set for mkdir */
+               execl("/bin/mkdir", "mkdir", dpath, (char *)0);
+               _exit(-1);              /* Can't exec /bin/mkdir */
+       
+       default:                        /* Parent process */
+               while (cpid != wait(&status)) ; /* Wait for kid to finish */
+       }
+
+       if (WTERMSIG(status) != 0 || WEXITSTATUS(status) != 0) {
+               errno = EIO;            /* We don't know why, but */
+               return -1;              /* /bin/mkdir failed */
+       }
+
+       return 0;
+}
+
+int
+rmdir(dpath)
+       char *dpath;
+{
+       int cpid, status;
+       struct stat statbuf;
+
+       if (stat(dpath,&statbuf) != 0) {
+               /* Stat just set errno.  We don't have to */
+               return -1;
+       }
+
+       switch (cpid = fork()) {
+
+       case -1:                        /* Error in fork() */
+               return(-1);             /* Errno is set already */
+
+       case 0:                         /* Child process */
+               execl("/bin/rmdir", "rmdir", dpath, (char *)0);
+               _exit(-1);              /* Can't exec /bin/mkdir */
+       
+       default:                        /* Parent process */
+               while (cpid != wait(&status)) ; /* Wait for kid to finish */
+       }
+
+       if (WTERMSIG(status) != 0 || WEXITSTATUS(status) != 0) {
+               errno = EIO;            /* We don't know why, but */
+               return -1;              /* /bin/mkdir failed */
+       }
+
+       return 0;
+}
+#endif
+
+#ifndef HAVE_RENAME
+/* Rename file FROM to file TO.
+   Return 0 if successful, -1 if not. */
+
+int
+rename (from, to)
+     char *from;
+     char *to;
+{
+  struct stat from_stats;
+
+  if (stat (from, &from_stats) == 0)
+    {
+      if (unlink (to) && errno != ENOENT)
+       return -1;
+      if (link (from, to) == 0 && (unlink (from) == 0 || errno == ENOENT))
+       return 0;
+    }
+  return -1;
+}
+#endif
+
+#ifndef HAVE_BZERO
+/* Minix has bcopy but not bzero, and no memset.  Thanks, Andy. */
+void
+bzero (s1, n)
+       register char *s1;
+       register int n;
+{
+       while (n--) *s1++ = '\0';
+}
+
+/* It also has no bcmp() */
+int
+bcmp (s1, s2, n) 
+       register char *s1,*s2;
+       register int n;
+{
+       for ( ; n-- ; ++s1, ++s2) {
+               if (*s1 != *s2) return *s1 - *s2;
+       }
+       return 0;
+}
+
+/*
+ * Groan, Minix doesn't have execlp either!
+ *
+ * execlp(file,arg0,arg1...argn,(char *)NULL)
+ * exec a program, automatically searching for the program through
+ * all the directories on the PATH.
+ *
+ * This version is naive about variable argument lists, it assumes
+ * a straightforward C calling sequence.  If your system has odd stacks
+ * *and* doesn't have execlp, YOU get to fix it.
+ */
+int
+execlp(filename, arg0)
+       char *filename, *arg0;
+{
+       register char *p, *path;    
+       register char *fnbuffer;
+       char **argstart = &arg0;
+       struct stat statbuf;
+       extern char **environ;
+
+       if ((p = getenv("PATH")) == NULL) {
+               /* couldn't find path variable -- try to exec given filename */
+               return execve(filename, argstart, environ);
+       }
+
+       /*
+        * make a place to build the filename.  We malloc larger than we
+        * need, but we know it will fit in this.
+        */
+       fnbuffer = malloc( strlen(p) + 1 + strlen(filename) );
+       if (fnbuffer == NULL) {
+               errno = ENOMEM;
+               return -1;
+       }
+
+       /*
+        * try each component of the path to see if the file's there
+        * and executable.
+        */
+       for (path = p ; path ; path = p) {
+               /* construct full path name to try */
+               if ((p = index(path,':')) == NULL) {
+                       strcpy(fnbuffer, path);
+               } else {
+                       strncpy(fnbuffer, path, p-path);
+                       fnbuffer[p-path] = '\0';
+                       p++;            /* Skip : for next time */
+               }
+               if (strlen(fnbuffer) != 0)
+                       strcat(fnbuffer,"/");
+               strcat(fnbuffer,filename);
+
+               /* check to see if file is there and is a normal file */
+               if (stat(fnbuffer, &statbuf) < 0) {
+                       if (errno == ENOENT)
+                               continue; /* file not there,keep on looking */
+                       else
+                               goto fail; /* failed for some reason, return */
+               }
+               if (!S_ISREG(statbuf.st_mode)) continue;
+
+               if (execve(fnbuffer, argstart, environ) < 0
+                   && errno != ENOENT
+                   && errno != ENOEXEC) {
+                       /* failed, for some other reason besides "file
+                        * not found" or "not a.out format"
+                        */
+                       goto fail;
+               }
+
+               /*
+                * If we got error ENOEXEC, the file is executable but is
+                * not an object file.  Try to execute it as a shell script,
+                * returning error if we can't execute /bin/sh.
+                *
+                * FIXME, this code is broken in several ways.  Shell
+                * scripts should not in general be executed by the user's
+                * SHELL variable program.  On more mature systems, the
+                * script can specify with #!/bin/whatever.  Also, this
+                * code clobbers argstart[-1] if the exec of the shell
+                * fails.
+                */
+               if (errno == ENOEXEC) {
+                       char *shell;
+
+                       /* Try to execute command "sh arg0 arg1 ..." */
+                       if ((shell = getenv("SHELL")) == NULL)
+                               shell = "/bin/sh";
+                       argstart[-1] = shell;
+                       argstart[0] = fnbuffer;
+                       execve(shell, &argstart[-1], environ);
+                       goto fail;      /* Exec didn't work */
+               }
+
+               /* 
+                * If we succeeded, the execve() doesn't return, so we
+                * can only be here is if the file hasn't been found yet.
+                * Try the next place on the path.
+                */
+       }
+
+       /* all attempts failed to locate the file.  Give up. */
+       errno = ENOENT;
+
+fail:
+       free(fnbuffer);
+       return -1;
+}
+#endif
+
+
+#ifdef EMUL_OPEN3
+#include "open3.h"
+/*
+ * open3 -- routine to emulate the 3-argument open system
+ * call that is present in most modern Unix systems.
+ * This version attempts to support all the flag bits except for O_NDELAY
+ * and O_APPEND, which are silently ignored.  The emulation is not as efficient
+ * as the real thing (at worst, 4 system calls instead of one), but there's
+ * not much I can do about that.
+ *
+ * Written 6/10/87 by rmtodd@uokmax
+ *
+ * open3(path, flag, mode)
+ * Attempts to open the file specified by
+ * the given pathname.  The following flag bits (#defined in tar.h)
+ * specify options to the routine:
+ *     O_RDONLY        file open for read only
+ *     O_WRONLY        file open for write only
+ *     O_RDWR          file open for both read & write
+ * (Needless to say, you should only specify one of the above).
+ *     O_CREAT         file is created with specified mode if it needs to be.
+ *     O_TRUNC         if file exists, it is truncated to 0 bytes
+ *     O_EXCL          used with O_CREAT--routine returns error if file exists
+ * Function returns file descriptor if successful, -1 and errno if not.
+ */
+
+/*
+ * array to give arguments to access for various modes
+ * FIXME, this table depends on the specific integer values of O_XXX,
+ * and also contains integers (args to 'access') that should be #define's.
+ */
+static int modes[] =
+       {
+               04, /* O_RDONLY */
+               02, /* O_WRONLY */
+               06, /* O_RDWR */
+               06, /* invalid but we'd better cope -- O_WRONLY+O_RDWR */
+       };
+
+/* Shut off the automatic emulation of open(), we'll need it. */
+#undef open
+
+int
+open3(path, flags, mode)
+char *path;
+int flags, mode;
+{
+       int exists = 1;
+       int call_creat = 0;
+       int fd;
+       /*
+        * We actually do the work by calling the open() or creat() system
+        * call, depending on the flags.  Call_creat is true if we will use 
+        * creat(), false if we will use open().
+        */
+
+       /*
+        * See if the file exists and is accessible in the requested mode. 
+        *
+        * Strictly speaking we shouldn't be using access, since access checks
+        * against real uid, and the open call should check against euid.
+        * Most cases real uid == euid, so it won't matter.   FIXME.
+        * FIXME, the construction "flags & 3" and the modes table depends
+        * on the specific integer values of the O_XXX #define's.  Foo!
+        */
+       if (access(path,modes[flags & 3]) < 0) {
+               if (errno == ENOENT) {
+                       /* the file does not exist */
+                       exists = 0;
+               } else {
+                       /* probably permission violation */
+                       if (flags & O_EXCL) {
+                               /* Oops, the file exists, we didn't want it. */
+                               /* No matter what the error, claim EEXIST. */
+                               errno = EEXIST;
+                       }
+                       return -1;
+               }
+       }
+
+       /* if we have the O_CREAT bit set, check for O_EXCL */
+       if (flags & O_CREAT) {
+               if ((flags & O_EXCL) && exists) {
+                       /* Oops, the file exists and we didn't want it to. */
+                       errno = EEXIST;
+                       return -1;
+               }
+               /*
+                * If the file doesn't exist, be sure to call creat() so that
+                * it will be created with the proper mode.
+                */
+               if (!exists) call_creat = 1;
+       } else {
+               /* If O_CREAT isn't set and the file doesn't exist, error. */
+               if (!exists) {
+                       errno = ENOENT;
+                       return -1;
+               }
+       }
+
+       /*
+        * If the O_TRUNC flag is set and the file exists, we want to call
+        * creat() anyway, since creat() guarantees that the file will be
+        * truncated and open()-for-writing doesn't.
+        * (If the file doesn't exist, we're calling creat() anyway and the
+        * file will be created with zero length.)
+        */
+       if ((flags & O_TRUNC) && exists) call_creat = 1;
+       /* actually do the call */
+       if (call_creat) {
+               /*
+                * call creat.  May have to close and reopen the file if we
+                * want O_RDONLY or O_RDWR access -- creat() only gives
+                * O_WRONLY.
+                */
+               fd = creat(path,mode);
+               if (fd < 0 || (flags & O_WRONLY)) return fd;
+               if (close(fd) < 0) return -1;
+               /* Fall out to reopen the file we've created */
+       }
+
+       /*
+        * calling old open, we strip most of the new flags just in case.
+        */
+       return open(path, flags & (O_RDONLY|O_WRONLY|O_RDWR|O_BINARY));
+}
+#endif
+
+#ifndef HAVE_MKNOD
+#ifdef __MSDOS__
+typedef int dev_t;
+#endif
+/* Fake mknod by complaining */
+int
+mknod(path, mode, dev)
+       char            *path;
+       unsigned short  mode;
+       dev_t           dev;
+{
+       int             fd;
+       
+       errno = ENXIO;          /* No such device or address */
+       return -1;              /* Just give an error */
+}
+
+/* Fake links by copying */
+int
+link(path1, path2)
+       char            *path1;
+       char            *path2;
+{
+       char    buf[256];
+       int     ifd, ofd;
+       int     nrbytes;
+       int     nwbytes;
+
+       fprintf(stderr, "%s: %s: cannot link to %s, copying instead\n",
+               tar, path1, path2);
+       if ((ifd = open(path1, O_RDONLY|O_BINARY)) < 0)
+               return -1;
+       if ((ofd = creat(path2, 0666)) < 0)
+               return -1;
+       setmode(ofd, O_BINARY);
+       while ((nrbytes = read(ifd, buf, sizeof(buf))) > 0) {
+               if ((nwbytes = write(ofd, buf, nrbytes)) != nrbytes) {
+                       nrbytes = -1;
+                       break;
+               }
+       }
+       /* Note use of "|" rather than "||" below: we want to close
+        * the files even if an error occurs.
+        */
+       if ((nrbytes < 0) | (0 != close(ifd)) | (0 != close(ofd))) {
+               unlink(path2);
+               return -1;
+       }
+       return 0;
+}
+
+/* everyone owns everything on MS-DOS (or is it no one owns anything?) */
+int
+chown(path, uid, gid)
+       char    *path;
+       int     uid;
+       int     gid;
+{
+       return 0;
+}
+
+int
+geteuid()
+{
+       return 0;
+}
+#endif /* !HAVE_MKNOD */
+
+#ifdef __TURBOC__
+#include <time.h>
+#include <fcntl.h>
+#include <io.h>
+
+struct utimbuf
+{
+  time_t  actime;              /* Access time. */
+  time_t  modtime;             /* Modification time. */
+};
+
+int
+utime (char *filename, struct utimbuf *utb)
+{
+  struct tm *tm;
+  struct ftime filetime;
+  time_t when;
+  int fd;
+  int status;
+
+  if (utb == 0)
+    when = time (0);
+  else
+    when = utb->modtime;
+
+  fd = _open (filename, O_RDWR);
+  if (fd == -1)
+    return -1;
+
+  tm = localtime (&when);
+  if (tm->tm_year < 80)
+    filetime.ft_year = 0;
+  else
+    filetime.ft_year = tm->tm_year - 80;
+  filetime.ft_month = tm->tm_mon + 1;
+  filetime.ft_day = tm->tm_mday;
+  if (tm->tm_hour < 0)
+    filetime.ft_hour = 0;
+  else
+    filetime.ft_hour = tm->tm_hour;
+  filetime.ft_min = tm->tm_min;
+  filetime.ft_tsec = tm->tm_sec / 2;
+
+  status = setftime (fd, &filetime);
+  _close (fd);
+  return status;
+}
+#endif
+
+/* Stash argv[0] here so panic will know what the program is called */
+char *myname = 0;
+
+void
+panic(s)
+char *s;
+{
+       if(myname)
+               fprintf(stderr,"%s:",myname);
+       fprintf(stderr,s);
+       putc('\n',stderr);
+       exit(12);
+}
+
+
+PTR
+ck_malloc(size)
+size_t size;
+{
+       PTR ret;
+
+       if(!size)
+               size++;
+       ret=malloc(size);
+       if(ret==0)
+               panic("Couldn't allocate memory");
+       return ret;
+}
+
+/* Used by alloca.c and bison.simple. */
+char *
+xmalloc(size)
+size_t size;
+{
+       return (char *) ck_malloc(size);
+}
+
+PTR
+ck_realloc(ptr,size)
+PTR ptr;
+size_t size;
+{
+       PTR ret;
+
+       if(!ptr)
+               ret=ck_malloc(size);
+       else
+               ret=realloc(ptr,size);
+       if(ret==0)
+               panic("Couldn't re-allocate memory");
+       return ret;
+}
+
+/* Implement a variable sized buffer of 'stuff'.  We don't know what it is,
+   nor do we care, as long as it doesn't mind being aligned on a char boundry.
+ */
+
+struct buffer {
+       int     allocated;
+       int     length;
+       char    *b;
+};
+
+#define MIN_ALLOCATE 50
+
+char *
+init_buffer()
+{
+       struct buffer *b;
+
+       b=(struct buffer *)ck_malloc(sizeof(struct buffer));
+       b->allocated=MIN_ALLOCATE;
+       b->b=(char *)ck_malloc(MIN_ALLOCATE);
+       b->length=0;
+       return (char *)b;
+}
+
+void
+flush_buffer(bb)
+char *bb;
+{
+       struct buffer *b;
+
+       b=(struct buffer *)bb;
+       free(b->b);
+       b->b=0;
+       b->allocated=0;
+       b->length=0;
+       free((void *)b);
+}
+
+void
+add_buffer(bb,p,n)
+char *bb;
+char *p;
+int n;
+{
+       struct buffer *b;
+
+       b=(struct buffer *)bb;
+       if(b->length+n>b->allocated) {
+               b->allocated=b->length+n+MIN_ALLOCATE;
+               b->b=(char *)ck_realloc(b->b,b->allocated);
+       }
+       bcopy(p,b->b+b->length,n);
+       b->length+=n;
+}
+
+char *
+get_buffer(bb)
+char *bb;
+{
+       struct buffer *b;
+
+       b=(struct buffer *)bb;
+       return b->b;
+}
+
+char *
+merge_sort(list,n,off,cmp)
+char *list;
+int (*cmp)();
+unsigned n;
+int off;
+{
+       char *ret;
+
+       char *alist,*blist;
+       unsigned alength,blength;
+
+       char *tptr;
+       int tmp;
+       char **prev;
+#define NEXTOF(ptr)    (* ((char **)(((char *)(ptr))+off) ) )
+       if(n==1)
+               return list;
+       if(n==2) {
+               if((*cmp)(list,NEXTOF(list))>0) {
+                       ret=NEXTOF(list);
+                       NEXTOF(ret)=list;
+                       NEXTOF(list)=0;
+                       return ret;
+               }
+               return list;
+       }
+       alist=list;
+       alength=(n+1)/2;
+       blength=n/2;
+       for(tptr=list,tmp=(n-1)/2;tmp;tptr=NEXTOF(tptr),tmp--)
+               ;
+       blist=NEXTOF(tptr);
+       NEXTOF(tptr)=0;
+
+       alist=merge_sort(alist,alength,off,cmp);
+       blist=merge_sort(blist,blength,off,cmp);
+       prev = &ret;
+       for(;alist && blist;) {
+               if((*cmp)(alist,blist)<0) {
+                       tptr=NEXTOF(alist);
+                       *prev = alist;
+                       prev = &(NEXTOF(alist));
+                       alist=tptr;
+               } else {
+                       tptr=NEXTOF(blist);
+                       *prev = blist;
+                       prev = &(NEXTOF(blist));
+                       blist=tptr;
+               }
+       }
+       if(alist)
+               *prev = alist;
+       else
+               *prev = blist;
+
+       return ret;
+}
+
+void
+ck_close(fd)
+int fd;
+{
+       if(close(fd)<0) {
+               msg_perror("can't close a file #%d",fd);
+               exit(EX_SYSTEM);
+       }
+}
+
+#include <ctype.h>
+
+/* Quote_copy_string is like quote_string, but instead of modifying the
+   string in place, it malloc-s a copy  of the string, and returns that.
+   If the string does not have to be quoted, it returns the NULL string.
+   The allocated copy can, of course, be freed with free() after the
+   caller is done with it.
+ */
+char *
+quote_copy_string(string)
+char *string;
+{
+       char    *from_here;
+       char    *to_there = 0;
+       char    *copy_buf = 0;
+       int     c;
+       int     copying = 0;
+
+       from_here=string;
+       while(*from_here) {
+               c= *from_here++;
+               if(c=='\\') {
+                       if(!copying) {
+                               int n;
+
+                               n=(from_here-string)-1;
+                               copying++;
+                               copy_buf=(char *)malloc(n+5+strlen(from_here)*4);
+                               if(!copy_buf)
+                                       return 0;
+                               bcopy(string,copy_buf,n);
+                               to_there=copy_buf+n;
+                       }
+                       *to_there++='\\';
+                       *to_there++='\\';
+               } else if(isprint(c)) {
+                       if(copying)
+                               *to_there++= c;
+               } else {
+                       if(!copying) {
+                               int     n;
+
+                               n=(from_here-string)-1;
+                               copying++;
+                               copy_buf=(char *)malloc(n+5+strlen(from_here)*4);
+                               if(!copy_buf)
+                                       return 0;
+                               bcopy(string,copy_buf,n);
+                               to_there=copy_buf+n;
+                       }
+                       *to_there++='\\';
+                       if(c=='\n') *to_there++='n';
+                       else if(c=='\t') *to_there++='t';
+                       else if(c=='\f') *to_there++='f';
+                       else if(c=='\b') *to_there++='b';
+                       else if(c=='\r') *to_there++='r';
+                       else if(c=='\177') *to_there++='?';
+                       else {
+                               to_there[0]=(c>>6)+'0';
+                               to_there[1]=((c>>3)&07)+'0';
+                               to_there[2]=(c&07)+'0';
+                               to_there+=3;
+                       }
+               }
+       }
+       if(copying) {
+               *to_there='\0';
+               return copy_buf;
+       }
+       return (char *)0;
+}
+
+
+/* Un_quote_string takes a quoted c-string (like those produced by
+   quote_string or quote_copy_string and turns it back into the
+   un-quoted original.  This is done in place.
+ */
+
+/* There is no un-quote-copy-string.  Write it yourself */
+
+char *
+un_quote_string(string)
+char *string;
+{
+       char *ret;
+       char *from_here;
+       char *to_there;
+       int     tmp;
+
+       ret=string;
+       to_there=string;
+       from_here=string;
+       while(*from_here) {
+               if(*from_here!='\\') {
+                       if(from_here!=to_there)
+                               *to_there++= *from_here++;
+                       else
+                               from_here++,to_there++;
+                       continue;
+               }
+               switch(*++from_here) {
+               case '\\':
+                       *to_there++= *from_here++;
+                       break;
+               case 'n':
+                       *to_there++= '\n';
+                       from_here++;
+                       break;
+               case 't':
+                       *to_there++= '\t';
+                       from_here++;
+                       break;
+               case 'f':
+                       *to_there++= '\f';
+                       from_here++;
+                       break;
+               case 'b':
+                       *to_there++= '\b';
+                       from_here++;
+                       break;
+               case 'r':
+                       *to_there++= '\r';
+                       from_here++;
+                       break;
+               case '?':
+                       *to_there++= 0177;
+                       from_here++;
+                       break;
+               case '0':
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+                       tmp= *from_here - '0';
+                       from_here++;
+                       if(*from_here<'0' || *from_here>'7') {
+                               *to_there++= tmp;
+                               break;
+                       }
+                       tmp= tmp*8 + *from_here-'0';
+                       from_here++;
+                       if(*from_here<'0' || *from_here>'7') {
+                               *to_there++= tmp;
+                               break;
+                       }
+                       tmp=tmp*8 + *from_here-'0';
+                       from_here++;
+                       *to_there=tmp;
+                       break;
+               default:
+                       ret=0;
+                       *to_there++='\\';
+                       *to_there++= *from_here++;
+                       break;
+               }
+       }
+       if(*to_there)
+               *to_there++='\0';
+       return ret;
+}
+
+void ck_pipe(pipes)
+int *pipes;
+{
+       if(pipe(pipes)<0) {
+               msg_perror("can't open a pipe");
+               exit(EX_SYSTEM);
+       }
+}
+
+
+#ifndef HAVE_STRSTR
+/*
+ * strstr - find first occurrence of wanted in s
+ */
+
+char *                         /* found string, or NULL if none */
+strstr(s, wanted)
+char *s;
+char *wanted;
+{
+       register char *scan;
+       register size_t len;
+       register char firstc;
+
+       if (*wanted == '\0')
+         return (char *)0;
+       /*
+        * The odd placement of the two tests is so "" is findable.
+        * Also, we inline the first char for speed.
+        * The ++ on scan has been moved down for optimization.
+        */
+       firstc = *wanted;
+       len = strlen(wanted);
+       for (scan = s; *scan != firstc || strncmp(scan, wanted, len) != 0; )
+               if (*scan++ == '\0')
+                       return (char *)0;
+       return scan;
+}
+#endif
+
+#infdef HAVE_FTRUNCATE
+
+#ifdef F_CHSIZE
+int
+ftruncate (fd, length)
+     int fd;
+     off_t length;
+{
+  return fcntl (fd, F_CHSIZE, length);
+}
+#else
+#ifdef F_FREESP
+/* code courtesy of William Kucharski, kucharsk@Solbourne.com */
+
+int
+ftruncate(fd, length)
+int fd;                       /* file descriptor */
+off_t length;         /* length to set file to */
+{
+       struct flock fl;
+
+       fl.l_whence = 0;
+       fl.l_len = 0;
+       fl.l_start = length;
+       fl.l_type = F_WRLCK;    /* write lock on file space */
+
+       /*
+        * This relies on the UNDOCUMENTED F_FREESP argument to
+        * fcntl(2), which truncates the file so that it ends at the
+        * position indicated by fl.l_start.
+        *
+        * Will minor miracles never cease?
+        */
+
+       if (fcntl(fd, F_FREESP, &fl) < 0)
+           return -1;
+
+       return 0;
+}
+
+#else
+
+int
+ftruncate(fd, length)
+int fd;
+off_t length;
+{
+       errno = EIO;
+       return -1;
+}
+#endif
+#endif
+#endif
+
+
+extern FILE *msg_file;
+
+#if defined (HAVE_VPRINTF) && __STDC__
+#include <stdarg.h>
+
+void
+msg(char *str,...)
+{
+       va_list args;
+
+       va_start(args,str);
+       fflush(msg_file);
+       fprintf(stderr,"%s: ",tar);
+       if(f_sayblock)
+               fprintf(stderr,"rec %d: ",baserec + (ar_record - ar_block));
+       vfprintf(stderr,str,args);
+       va_end(args);
+       putc('\n',stderr);
+       fflush(stderr);
+}
+
+void
+msg_perror(char *str,...)
+{
+       va_list args;
+       int save_e;
+
+       save_e=errno;
+       fflush(msg_file);
+       fprintf(stderr,"%s: ",tar);
+       if(f_sayblock)
+               fprintf(stderr,"rec %d: ",baserec + (ar_record - ar_block));
+       va_start(args,str);
+       vfprintf(stderr,str,args);
+       va_end(args);
+       errno=save_e;
+       perror(" ");
+       fflush(stderr);
+}
+#endif /* HAVE_VPRINTF and __STDC__ */
+
+#if defined(HAVE_VPRINTF) && !__STDC__
+#include <varargs.h>
+void
+msg(str,va_alist)
+char *str;
+va_dcl
+{
+       va_list args;
+
+       fflush(msg_file);
+       fprintf(stderr,"%s: ",tar);
+       if(f_sayblock)
+               fprintf(stderr,"rec %d: ",baserec + (ar_record - ar_block));
+       va_start(args);
+       vfprintf(stderr,str,args);
+       va_end(args);
+       putc('\n',stderr);
+       fflush(stderr);
+}
+
+void
+msg_perror(str,va_alist)
+char *str;
+va_dcl
+{
+       va_list args;
+       int save_e;
+
+       save_e=errno;
+       fflush(msg_file);
+       fprintf(stderr,"%s: ",tar);
+       if(f_sayblock)
+               fprintf(stderr,"rec %d: ",baserec + (ar_record - ar_block));
+       va_start(args);
+       vfprintf(stderr,str,args);
+       va_end(args);
+       errno=save_e;
+       perror(" ");
+       fflush(stderr);
+}
+#endif /* HAVE_VPRINTF and not __STDC__ */
+
+#if !defined(HAVE_VPRINTF) && defined(HAVE_DOPRNT)
+void
+msg(str,args)
+char *str;
+int args;
+{
+       fflush(msg_file);
+       fprintf(stderr,"%s: ",tar);
+       if(f_sayblock)
+               fprintf(stderr,"rec %d: ",baserec + (ar_record - ar_block));
+       _doprnt(str, &args, stderr);
+       putc('\n',stderr);
+       fflush(stderr);
+}
+
+void
+msg_perror(str,args)
+char *str;
+{
+       int save_e;
+
+       save_e=errno;
+       fflush(msg_file);
+       fprintf(stderr,"%s: ",tar);
+       if(f_sayblock)
+               fprintf(stderr,"rec %d: ",baserec + (ar_record - ar_block));
+       _doprnt(str, &args, stderr);
+       errno=save_e;
+       perror(" ");
+       fflush(stderr);
+}
+#endif /* !HAVE_VPRINTF and HAVE_DOPRNT */
+
+#if !defined(HAVE_VPRINTF) && !defined(HAVE_DOPRNT)
+void msg(str,a1,a2,a3,a4,a5,a6)
+char *str;
+{
+       fflush(msg_file);
+       fprintf(stderr,"%s: ",tar);
+       if(f_sayblock)
+               fprintf(stderr,"rec %d: ",baserec + (ar_record - ar_block));
+       fprintf(stderr,str,a1,a2,a3,a4,a5,a6);
+       putc('\n',stderr);
+       fflush(stderr);
+}
+
+void
+msg_perror(str,a1,a2,a3,a4,a5,a6)
+char *str;
+{
+       int save_e;
+
+       save_e=errno;
+       fflush(msg_file);
+       fprintf(stderr,"%s: ",tar);
+       if(f_sayblock)
+               fprintf(stderr,"rec %d: ",baserec + (ar_record - ar_block));
+       fprintf(stderr,str,a1,a2,a3,a4,a5,a6);
+       fprintf(stderr,": ");
+       errno=save_e;
+       perror(" ");
+}
+#endif /* !HAVE_VPRINTF and !HAVE_DOPRNT */
diff --git a/src/version.c b/src/version.c
new file mode 100644 (file)
index 0000000..eaa5152
--- /dev/null
@@ -0,0 +1,20 @@
+/* Version info for tar.
+   Copyright (C) 1989, Free Software Foundation.
+
+This file is part of GNU Tar.
+
+GNU Tar 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.
+
+GNU Tar 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 GNU Tar; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+   
+char version_string[] = "GNU tar version 1.10.14";
This page took 0.050357 seconds and 4 git commands to generate.