*** copyout.c~0	Wed Jan 10 16:10:44 1996
--- copyout.c	Sat Oct 25 17:16:00 1997
***************
*** 26,31 ****
--- 26,35 ----
  #include "defer.h"
  #include "rmt.h"
  
+ #ifdef __DJGPP__
+ #include <io.h>
+ #endif
+ 
  static unsigned long read_for_checksum ();
  static void tape_clear_rest_of_block ();
  static void tape_pad_output ();
*************** process_copy_out ()
*** 213,218 ****
--- 217,226 ----
  #ifdef __MSDOS__
    setmode (archive_des, O_BINARY);
  #endif
+ #ifdef __DJGPP__
+   if (!isatty (archive_des))
+     setmode (archive_des, O_BINARY);
+ #endif
    /* Check whether the output file might be a tape.  */
    out_file_des = archive_des;
    if (_isrmt (out_file_des))
*************** process_copy_out ()
*** 232,237 ****
--- 240,252 ----
        output_is_seekable = S_ISREG (file_stat.st_mode);
      }
  
+ #ifdef __DJGPP__
+   /* We might as well give the user an opportunity to recover
+      from "No space on device" even if they are writing to disk
+      files.  It is specifically handy with floppies.  */
+   output_is_special = !isatty (out_file_des);
+ #endif
+ 
    if (append_flag)
      {
        process_copy_in ();
*************** process_copy_out ()
*** 257,262 ****
--- 272,281 ----
  	  file_hdr.c_dev_maj = major (file_stat.st_dev);
  	  file_hdr.c_dev_min = minor (file_stat.st_dev);
  	  file_hdr.c_ino = file_stat.st_ino;
+ #ifdef __DJGPP__
+ 	  /* DJGPP doesn't support st_rdev.  Repair that.  */
+ 	  file_stat.st_rdev = file_stat.st_dev;
+ #endif
  	  /* For POSIX systems that don't define the S_IF macros,
  	     we can't assume that S_ISfoo means the standard Unix
  	     S_IFfoo bit(s) are set.  So do it manually, with a

*** copypass.c~0	Mon Jan  8 21:59:04 1996
--- copypass.c	Sat Oct 25 15:05:10 1997
*************** process_copy_pass ()
*** 86,92 ****
  	}
  
        /* Make the name of the new file.  */
!       for (slash = input_name.ds_string; *slash == '/'; ++slash)
  	;
  #ifdef HPUX_CDF
        /* For CDF's we add a 2nd `/' after all "hidden" directories.
--- 86,97 ----
  	}
  
        /* Make the name of the new file.  */
!       slash = input_name.ds_string; 
! #if defined(__MSDOS__) || defined(__DJGPP__)
!       if (*slash >= 'A' && *slash <= 'z' && slash[1] == ':')
! 	slash += 2;
! #endif
!       for ( ; *slash == '/'; ++slash)
  	;
  #ifdef HPUX_CDF
        /* For CDF's we add a 2nd `/' after all "hidden" directories.
*************** process_copy_pass ()
*** 164,170 ****
  		}
  	      if (out_file_des < 0)
  		{
! 		  error (0, errno, "%s", output_name.ds_string);
  		  close (in_file_des);
  		  continue;
  		}
--- 169,187 ----
  		}
  	      if (out_file_des < 0)
  		{
! 		  /* If we aren't allowed to create intermediate directories,
! 		     make the error message mention the parent directory.  */
! 		  if (!create_dir_flag)
! 		    {
! 		      char *dirpart = dirname (output_name.ds_string);
! 		      struct stat dirpart_stat;
! 
! 		      if (stat (dirpart, &dirpart_stat) < 0)
! 			error (0, errno, "%s", dirpart);
! 		      free (dirpart);
! 		    }
! 		  else
! 		    error (0, errno, "%s", output_name.ds_string);
  		  close (in_file_des);
  		  continue;
  		}
*************** process_copy_pass ()
*** 235,248 ****
  	    }
  	  if (res < 0)
  	    {
  	      /* In some odd cases where the output_name includes `.',
  	         the directory may have actually been created by
  	         create_all_directories(), so the mkdir will fail
  	         because the directory exists.  If that's the case,
  	         don't complain about it.  */
! 	      if ( (errno != EEXIST) ||
!       		   (lstat (output_name.ds_string, &out_file_stat) != 0) ||
! 	           !(S_ISDIR (out_file_stat.st_mode) ) )
  		{
  		  error (0, errno, "%s", output_name.ds_string);
  		  continue;
--- 252,277 ----
  	    }
  	  if (res < 0)
  	    {
+ 	      /* If we aren't allowed to create intermediate directories,
+ 		 make the error message mention the parent directory.  */
+ 	      if (!create_dir_flag)
+ 		{
+ 		  char *dirpart = dirname (output_name.ds_string);
+ 		  struct stat dirpart_stat;
+ 
+ 		  if (stat (dirpart, &dirpart_stat) < 0)
+ 		    error (0, errno, "%s", dirpart);
+ 		  free (dirpart);
+ 		  continue;
+ 		}
  	      /* In some odd cases where the output_name includes `.',
  	         the directory may have actually been created by
  	         create_all_directories(), so the mkdir will fail
  	         because the directory exists.  If that's the case,
  	         don't complain about it.  */
! 	      else if ( (errno != EEXIST) ||
! 			(lstat (output_name.ds_string, &out_file_stat) != 0) ||
! 			!(S_ISDIR (out_file_stat.st_mode) ) )
  		{
  		  error (0, errno, "%s", output_name.ds_string);
  		  continue;
*************** process_copy_pass ()
*** 267,272 ****
--- 296,309 ----
  	    {
  	      times.actime = times.modtime = in_file_stat.st_mtime;
  	      if (utime (output_name.ds_string, &times) < 0)
+ #if defined(__MSDOS__) || defined(__DJGPP__)
+ 		/* MS-DOS/Windows won't let us to set mod times of
+ 		   a directory.  Make the error message explicit.  */
+ 		if (errno == EACCES)
+ 		  error (0, 0, "%s: Cannot set access time of a directory",
+ 			 output_name.ds_string);
+ 		else
+ #endif
  		error (0, errno, "%s", output_name.ds_string);
  	    }
  	}
*************** process_copy_pass ()
*** 305,311 ****
  		}
  	      if (res < 0)
  		{
! 		  error (0, errno, "%s", output_name.ds_string);
  		  continue;
  		}
  	      if (!no_chown_flag)
--- 342,360 ----
  		}
  	      if (res < 0)
  		{
! 		  /* If we aren't allowed to create intermediate directories,
! 		     make the error message mention the parent directory.  */
! 		  if (!create_dir_flag)
! 		    {
! 		      char *dirpart = dirname (output_name.ds_string);
! 		      struct stat dirpart_stat;
! 
! 		      if (stat (dirpart, &dirpart_stat) < 0)
! 			error (0, errno, "%s", dirpart);
! 		      free (dirpart);
! 		    }
! 		  else
! 		    error (0, errno, "%s", output_name.ds_string);
  		  continue;
  		}
  	      if (!no_chown_flag)
*************** process_copy_pass ()
*** 354,360 ****
  	    }
  	  if (res < 0)
  	    {
! 	      error (0, errno, "%s", output_name.ds_string);
  	      free (link_name);
  	      continue;
  	    }
--- 403,421 ----
  	    }
  	  if (res < 0)
  	    {
! 	      /* If we aren't allowed to create intermediate directories,
! 		 make the error message mention the parent directory.  */
! 	      if (!create_dir_flag)
! 		{
! 		  char *dirpart = dirname (output_name.ds_string);
! 		  struct stat dirpart_stat;
! 
! 		  if (stat (dirpart, &dirpart_stat) < 0)
! 		    error (0, errno, "%s", dirpart);
! 		  free (dirpart);
! 		}
! 	      else
! 		error (0, errno, "%s", output_name.ds_string);
  	      free (link_name);
  	      continue;
  	    }

*** dirname.c~0	Fri Oct  7 17:21:30 1994
--- dirname.c	Thu Oct 23 18:38:30 1997
*************** dirname (path)
*** 47,52 ****
--- 47,57 ----
    int length;			/* Length of result, not including NUL.  */
  
    slash = strrchr (path, '/');
+ #ifdef __DJGPP__
+   /* Handle the case of "d:foo".  */
+   if (slash == 0 && path[0] >= 'A' && path[0] <= 'z' && path[1] == ':')
+     slash = path + 1;
+ #endif
    if (slash == 0)
      {
        /* File is in the current directory.  */
*************** dirname (path)
*** 58,63 ****
--- 63,74 ----
        /* Remove any trailing slashes from the result.  */
        while (slash > path && *slash == '/')
  	--slash;
+ 
+ #ifdef __DJGPP__
+       /* Leave alone the last slash in "d:/".  */
+       if (*slash == ':' && slash[1] == '/')
+ 	++slash;
+ #endif
  
        length = slash - path + 1;
      }

*** dstring.c~0	Tue Nov 24 13:40:34 1992
--- dstring.c	Thu Oct 23 17:20:20 1997
*************** ds_fgetstr (f, s, eos)
*** 81,86 ****
--- 81,94 ----
    next_ch = getc (f);
    while (next_ch != eos && next_ch != EOF)
      {
+ #ifdef __DJGPP__
+       /* This is really a kludge.
+ 	 Only file names are read through this function, and it is very
+ 	 convenient to convert DOS-style backslashes (which the rest of
+ 	 the code cannot grok) into Unix-style forward slashes right here.  */
+       if (next_ch == '\\')
+ 	next_ch = '/';
+ #endif
        if (insize >= strsize - 1)
  	{
  	  ds_resize (s, strsize * 2 + 2);

*** error.c~0	Tue Dec  5 23:39:52 1995
--- error.c	Sat Oct 25 18:52:34 1997
*************** void (*error_print_progname) () = NULL;
*** 59,64 ****
--- 59,66 ----
     name of the executing program.  */
  extern char *program_name;
  
+ extern int dot_flag;
+ 
  #if HAVE_STRERROR || _LIBC
  # ifndef strerror		/* On some systems, strerror is a macro */
  char *strerror ();
*************** error (status, errnum, message, va_alist
*** 104,109 ****
--- 106,113 ----
    else
      {
        fflush (stdout);
+       if (dot_flag)
+ 	fputc ('\n', stderr);
        fprintf (stderr, "%s: ", program_name);
      }
  

*** filemode.c~0	Fri Nov  4 16:48:14 1994
--- filemode.c	Sat Oct 25 12:52:42 1997
*************** setst (bits, chars)
*** 253,255 ****
--- 253,326 ----
      }
  #endif
  }
+ 
+ #ifdef __DJGPP__
+ 
+ #include "filetype.h"
+ 
+ static char cpio_ftypelet (long);
+ 
+ /* Like mode_string, but uses cpio_ftypelet.  */
+ 
+ void
+ cpio_mode_string (mode, str)
+      unsigned short mode;
+      char *str;
+ {
+   str[0] = cpio_ftypelet ((long) mode);
+   rwx ((mode & 0700) << 0, &str[1]);
+   rwx ((mode & 0070) << 3, &str[4]);
+   rwx ((mode & 0007) << 6, &str[7]);
+   setst (mode, str);
+ }
+ 
+ /* Return a character indicating the type of file described by
+    cpio mode BITS:
+    'd' for directories
+    'b' for block special files
+    'c' for character special files
+    'm' for multiplexor files
+    'l' for symbolic links
+    's' for sockets
+    'p' for fifos
+    '-' for regular files
+    '?' for any other file type.  */
+ 
+ static char
+ cpio_ftypelet (bits)
+      long bits;
+ {
+ #ifdef CP_IFBLK
+   if ((bits & CP_IFMT) == CP_IFBLK)
+     return 'b';
+ #endif
+   if ((bits & CP_IFMT) == CP_IFCHR)
+     return 'c';
+   if ((bits & CP_IFMT) == CP_IFDIR)
+     return 'd';
+   if ((bits & CP_IFMT) == CP_IFREG)
+     return '-';
+ #ifdef CP_IFIFO
+   if ((bits & CP_IFMT) == CP_IFIFO)
+     return 'p';
+ #endif
+ #ifdef CP_IFLNK
+   if ((bits & CP_IFMT) == CP_IFLNK)
+     return 'l';
+ #endif
+ #ifdef CP_IFSOCK
+   if ((bits & CP_IFMT) == CP_IFSOCK)
+     return 's';
+ #endif
+ #ifdef CP_IFMPC
+   if ((bits & CP_IFMT) == CP_IFMPC)
+     return 'm';
+ #endif
+ #ifdef CP_IFNWK
+   if ((bits & CP_IFMT) == CP_IFNWK)
+     return 'n';
+ #endif
+   return '?';
+ }
+ 
+ #endif /* __DJGPP__ */

*** filetype.h~0	Sun Jul 19 05:53:46 1992
--- filetype.h	Thu Oct 23 16:13:38 1997
***************
*** 82,84 ****
--- 82,91 ----
  #endif
  int lstat ();
  int stat ();
+ 
+ /* Even though MS-DOS/MS-Windows don't support links, it makes
+    sense to have CP_IFLNK defined, so we could copy-in archives
+    created on systems which do support them.  */
+ #ifdef __DJGPP__
+ #define CP_IFLNK 0120000
+ #endif

*** idcache.c~0	Sat Jun 24 03:57:24 1995
--- idcache.c	Thu Oct 23 19:55:52 1997
*************** static struct userid *user_alist;
*** 59,64 ****
--- 59,71 ----
  /* The members of this list have names not in the local passwd file.  */
  static struct userid *nouser_alist;
  
+ #ifdef __DJGPP__
+ /* A faked passwd/group entries which we create on-the-fly when
+    they need to give away files to users/groups we don't know about.  */
+ static struct passwd dos_pwent = {"dos-user", 42, 42, "/", "/bin/sh"};
+ static struct group  dos_grent = {42, 0, "dos-users"};
+ #endif
+ 
  /* Translate UID to a login name or a stringified number,
     with cache.  */
  
*************** getuidbyname (user)
*** 118,123 ****
--- 125,139 ----
    tail = (struct userid *) xmalloc (sizeof (struct userid));
    tail->name = xstrdup (user);
  
+ #ifdef __DJGPP__
+   /* Let them give away files to anybody.  */
+   if (!pwent)
+     {
+       dos_pwent.pw_uid++;
+       pwent = &dos_pwent;
+     }
+ #endif
+ 
    /* Add to the head of the list, so most recently used is first.  */
    if (pwent)
      {
*************** getgidbyname (group)
*** 194,199 ****
--- 210,224 ----
  
    tail = (struct userid *) xmalloc (sizeof (struct userid));
    tail->name = xstrdup (group);
+ 
+ #ifdef __DJGPP__
+   /* Let them give away files to any group.  */
+   if (!grent)
+     {
+       dos_grent.gr_gid++;
+       grent = &dos_grent;
+     }
+ #endif
  
    /* Add to the head of the list, so most recently used is first.  */
    if (grent)

*** main.c~0	Thu Dec  1 00:24:20 1994
--- main.c	Sat Oct 25 14:31:20 1997
*************** main (argc, argv)
*** 498,503 ****
--- 498,522 ----
       char *argv[];
  {
    program_name = argv[0];
+ #if defined(__MSDOS__) || defined(__DJGPP__)
+   /* Drop the full path and .exe suffix.  */
+   {
+     char *p = program_name + strlen (program_name) - 4;
+ 
+     if (p > program_name
+ 	&& (strcmp (p, ".exe") == 0 || strcmp (p, ".EXE") == 0))
+       *p-- = '\0';
+     else
+       p += 3;
+ 
+     for ( ; p > program_name; p--)
+       if (*p == '/' || *p == '\\' || *p == ':')
+ 	{
+ 	  program_name = p + 1;
+ 	  break;
+ 	}
+   }
+ #endif
    umask (0);
  
  #ifdef __TURBOC__

*** makepath.c~0	Wed Nov 30 22:50:10 1994
--- makepath.c	Fri Oct 24 19:39:18 1997
*************** make_path (argpath, mode, parent_mode, o
*** 130,135 ****
--- 130,141 ----
  	}
  
        slash = dirpath;
+ #if defined(__MSDOS__) || defined(__DJGPP__)
+       /* Get past the drive letter, if any, so we don't try to remake
+ 	 root directories or current directories on other drives.  */
+       if (*slash >= 'A' && *slash <= 'z' && slash[1] == ':')
+ 	slash += 2;
+ #endif
        while (*slash == '/')
  	slash++;
        while ((slash = index (slash, '/')))
*** README.~0	Mon Jul  5 18:41:50 1993
--- README	Thu Oct 23 14:15:16 1997
*************** See the file INSTALL for compilation and
*** 11,16 ****
--- 11,18 ----
  
  For non-Unix systems:
  
+ To build cpio with DJGPP tools, see README.djgpp.
+ 
  makefile.pc is a makefile for Turbo C or C++ or Borland C++ on MS-DOS.
  
  makefile.os2 is a makefile for MS C and GNU C (emx/gcc) on OS/2.

*** stripslash.c~0	Mon Sep 26 21:42:18 1994
--- stripslash.c	Fri Oct 24 19:50:24 1997
*************** strip_trailing_slashes (path)
*** 38,43 ****
--- 38,51 ----
    int last;
  
    last = strlen (path) - 1;
+ 
+ #if defined(__MSDOS__) || defined(__DJGPP__)
+   /* Leave alone the trailing slash is DOS-style root directory "d:/".  */
+   if (last == 2 && path[2] == '/'
+       && path[1] == ':' && *path >= 'A' && *path <= 'z')
+     return;
+ #endif
+ 
    while (last > 0 && path[last] == '/')
      path[last--] = '\0';
  }

*** system.h~0	Wed Nov 30 22:50:00 1994
--- system.h	Fri Oct 24 22:04:34 1997
*************** extern int errno;
*** 95,100 ****
--- 95,104 ----
  #define EPERM EACCES
  #define ENXIO EIO
  #endif
+ #ifdef __DJGPP__
+ #undef  EPERM
+ #define EPERM EACCES
+ #endif
  
  #ifdef HAVE_UTIME_H
  #include <utime.h>
*************** typedef int gid_t;
*** 135,141 ****
     symlink(). */
  
  #ifndef SYMLINK_USES_UMASK
! #define UMASKED_SYMLINK(name1,name2,mode)    symlink(name1,name2)
  #else
  #define UMASKED_SYMLINK(name1,name2,mode)    umasked_symlink(name1,name2,mode)
  #endif /* SYMLINK_USES_UMASK */
--- 139,149 ----
     symlink(). */
  
  #ifndef SYMLINK_USES_UMASK
! # ifdef __DJGPP__
! #  define UMASKED_SYMLINK(name1,name2,mode)    link(name1,name2)
! # else
! #  define UMASKED_SYMLINK(name1,name2,mode)    symlink(name1,name2)
! # endif
  #else
  #define UMASKED_SYMLINK(name1,name2,mode)    umasked_symlink(name1,name2,mode)
  #endif /* SYMLINK_USES_UMASK */

*** userspec.c~0	Mon Sep 26 21:42:08 1994
--- userspec.c	Fri Oct 24 21:20:38 1997
*************** parse_user_spec (spec_arg, uid, gid, use
*** 153,158 ****
--- 153,172 ----
    if (u != NULL)
      {
        pwd = getpwnam (u);
+ #ifdef __DJGPP__
+       /* This all owner stuff is really a no-op, since in the end
+ 	 we will call `chown' which does nothing.  So just substitute
+ 	 the unknown user with a fake passwd entry, which will let
+ 	 them give any non-numeric username as an argument and be happy.  */
+       if (pwd == NULL && !isnumber (u))
+ 	{
+ 	  static struct passwd fake_pwent = {
+ 	    "dos-user", 42, 42, "/", "/bin/sh"
+ 	  };
+ 
+ 	  pwd = &fake_pwent;
+ 	}
+ #endif
        if (pwd == NULL)
  	{
  
*************** parse_user_spec (spec_arg, uid, gid, use
*** 200,205 ****
--- 214,230 ----
      {
        /* Explicit group.  */
        grp = getgrnam (g);
+ #ifdef __DJGPP__
+       /* See the commentary above.  */
+       if (grp == NULL && !isnumber (g))
+ 	{
+ 	  static struct group fake_grent = {
+ 	    42, 0, "dos-users"
+ 	  };
+ 
+ 	  grp = &fake_grent;
+ 	}
+ #endif
        if (grp == NULL)
  	{
  	  if (!isnumber (g))

*** cpio.t~0	Wed Dec 20 16:29:34 1995
--- cpio.texi	Sat Oct 25 18:36:34 1997
***************
*** 82,88 ****
  GNU cpio is a tool for creating and extracting archives, or copying
  files from one place to another.  It handles a number of cpio formats as
  well as reading and writing tar files.  This is the first edition of the 
! GNU cpio documentation and is consistant with @value{VERSION}.
  
  @menu
  * Introduction::                
--- 82,88 ----
  GNU cpio is a tool for creating and extracting archives, or copying
  files from one place to another.  It handles a number of cpio formats as
  well as reading and writing tar files.  This is the first edition of the 
! GNU cpio documentation and is consistent with @value{VERSION}.
  
  @menu
  * Introduction::                
***************
*** 107,122 ****
  @comment  node-name,  next,  previous,  up
  @chapter Introduction
  
! GNU cpio copies files into or out of a cpio or tar archive, The archive
! can be another file on the disk, a magnetic tape, or a pipe.
  
! GNU cpio supports the following archive formats: binary, old ASCII, new
! ASCII, crc, HPUX binary, HPUX old ASCII, old tar, and POSIX.1 tar.  The
! tar format is provided for compatability with the tar program. By
! default, cpio creates binary format archives, for compatibility with
! older cpio programs.  When extracting from archives, cpio automatically
! recognizes which kind of archive it is reading and can read archives
! created on machines with a different byte-order.
  
  @node Tutorial, Invoking `cpio', Introduction, Top
  @comment  node-name,  next,  previous,  up
--- 107,123 ----
  @comment  node-name,  next,  previous,  up
  @chapter Introduction
  
! GNU @code{cpio} copies files into or out of a cpio or tar archive, The
! archive can be another file on the disk, a magnetic tape, or a pipe.
  
! GNU @code{cpio} supports the following archive formats: binary, old
! ASCII, new ASCII, crc, HPUX binary, HPUX old ASCII, old tar, and POSIX.1
! tar.  The tar format is provided for compatability with the @code{tar}
! program. By default, @code{cpio} creates binary format archives, for
! compatibility with older @code{cpio} programs.  When extracting from
! archives, @code{cpio} automatically recognizes which kind of archive it
! is reading and can read archives created on machines with a different
! byte-order.
  
  @node Tutorial, Invoking `cpio', Introduction, Top
  @comment  node-name,  next,  previous,  up
***************
*** 127,143 ****
  @cindex passing directory structures
  
  
! GNU cpio performs three primary functions.  Copying files to an
  archive, Extracting files from an archive, and passing files to another
  directory tree.  An archive can be a file on disk, one or more floppy
  disks, or one or more tapes.
  
! When creating an archive, cpio takes the list of files to be processed
! from the standard input, and then sends the archive to the standard
! output, or to the device defined by the @samp{-F} option.
! @xref{Copy-out mode}.  Usually find or ls is used to provide this list
! to the standard input.  In the following example you can see the
! possibilities for archiving the contents of a single directory.
  
  
  @example
--- 128,145 ----
  @cindex passing directory structures
  
  
! GNU @code{cpio} performs three primary functions.  Copying files to an
  archive, Extracting files from an archive, and passing files to another
  directory tree.  An archive can be a file on disk, one or more floppy
  disks, or one or more tapes.
  
! When creating an archive, @code{cpio} takes the list of files to be
! processed from the standard input, and then sends the archive to the
! standard output, or to the device defined by the @samp{-F} option.
! @xref{Copy-out mode}.  Usually, @code{find} or @code{ls} is used to
! provide this list to the standard input.  In the following example you
! can see the possibilities for archiving the contents of a single
! directory.
  
  
  @example
***************
*** 149,160 ****
  The @samp{-o} option creates the archive, and the @samp{-v} option
  prints the names of the files archived as they are added.  Notice that
  the options can be put together after a single @samp{-} or can be placed
! separately on the command line.  The @samp{>} redirects the cpio output
! to the file @samp{directory.cpio}.
  
  
! If you wanted to archive an entire directory tree, the find command can
! provide the file list to cpio:
  
  
  @example
--- 151,162 ----
  The @samp{-o} option creates the archive, and the @samp{-v} option
  prints the names of the files archived as they are added.  Notice that
  the options can be put together after a single @samp{-} or can be placed
! separately on the command line.  The @samp{>} redirects the @code{cpio}
! output to the file @file{directory.cpio}.
  
  
! If you wanted to archive an entire directory tree, the @code{find}
! command can provide the file list to @code{cpio}:
  
  
  @example
***************
*** 164,186 ****
  @end example
  
  
! This will take all the files in the current directory, the directories
! below and place them in the archive tree.cpio.  Again the @samp{-o}
! creates an archive, and the @samp{-v} option shows you the name of the
! files as they are archived.  @xref{Copy-out mode}.  Using the `.' in the
! find statement will give you more flexibility when doing restores, as it
! will save file names with a relative path vice a hard wired, absolute
! path.  The @samp{-depth} option forces @samp{find} to print of the
! entries in a directory before printing the directory itself.  This
! limits the effects of restrictive directory permissions by printing the
! directory entries in a directory before the directory name itself.
! 
! 
! 
! 
! Extracting an archive requires a bit more thought because cpio will not
! create directories by default.  Another characteristic, is it will not
! overwrite existing files unless you tell it to.
  
  
  @example
--- 166,187 ----
  @end example
  
  
! This will take all the files in the current directory and its
! sub-directories, and place them in the archive @file{tree.cpio}.  Again
! the @samp{-o} creates an archive, and the @samp{-v} option shows you the
! name of the files as they are archived.  @xref{Copy-out mode}.  Using
! the @samp{.} argument to @code{find} will give you more flexibility when
! doing restores, as it will save file names with a relative path instead
! of a hard-wired, absolute path.  The @samp{-depth} option forces
! @samp{find} to print all the entries in a directory before printing the
! directory itself.  This limits the effects of restrictive directory
! permissions by putting the directory entries into the aarchive before the
! directory name itself.
! 
! 
! Extracting an archive requires a bit more thought because @code{cpio}
! will not create directories by default.  Also, it will not overwrite
! existing files unless you tell it to.
  
  
  @example
***************
*** 189,199 ****
  @end cartouche
  @end example
  
! This will retrieve the files archived in the file directory.cpio and
! place them in the present directory.  The @samp{-i} option extracts the
! archive and the @samp{-v} shows the file names as they are extracted.
! If you are dealing with an archived directory tree, you need to use the
! @samp{-d} option to create directories as necessary, something like:
  
  @example
  @cartouche
--- 190,201 ----
  @end cartouche
  @end example
  
! This will retrieve the files archived in the file @file{directory.cpio}
! and place them in the present directory.  The @samp{-i} option extracts
! the archive and the @samp{-v} shows the file names as they are
! extracted.  If you are dealing with an archived directory tree, you need
! to use the @samp{-d} option to create directories as necessary,
! something like:
  
  @example
  @cartouche
***************
*** 201,218 ****
  @end cartouche
  @end example
  
! This will take the contents of the archive tree.cpio and extract it to
! the current directory.  If you try to extract the files on top of files
! of the same name that already exist (and have the same or later
! modification time) cpio will not extract the file unless told to do so
! by the -u option.  @xref{Copy-in mode}.
  
  
! In copy-pass mode, cpio copies files from one directory tree to another,
! combining the copy-out and copy-in steps without actually using an
! archive.  It reads the list of files to copy from the standard input;
! the directory into which it will copy them is given as a non-option
! argument.  @xref{Copy-pass mode}.
  
  @example
  @cartouche
--- 203,220 ----
  @end cartouche
  @end example
  
! This will take the contents of the archive @file{tree.cpio} and extract
! it into the current directory.  If you try to extract the files on top of
! files of the same name that already exist (and have the same or later
! modification time), @code{cpio} will not extract the files unless told to
! do so by the @samp{-u} option.  @xref{Copy-in mode}.
  
  
! In copy-pass mode, @code{cpio} copies files from one directory tree to
! another, combining the copy-out and copy-in steps without actually
! creating an archive.  It reads the list of files to copy from the
! standard input; the directory into which it will copy them is given as a
! non-option argument.  @xref{Copy-pass mode}.
  
  @example
  @cartouche
***************
*** 221,233 ****
  @end example
  
  
! The example shows copying the files of the present directory, and
! sub-directories to a new directory called new-dir.  Some new options are
! the @samp{-print0} available with GNU find, combined with the
! @samp{--null} option of cpio.  These two options act together to send
! file names between find and cpio, even if special characters are
! embedded in the file names.  Another is @samp{-p}, which tells cpio to
! pass the files it finds to the directory @samp{new-dir}.
  
  @node Invoking `cpio', Media, Tutorial, Top
  @comment  node-name,  next,  previous,  up
--- 223,236 ----
  @end example
  
  
! This example shows copying the files of the present directory, and
! sub-directories to a new directory called @file{new-dir}.  Some new
! options are the @samp{-print0} available with GNU @code{find}, combined
! with the @samp{--null} option of @code{cpio}.  These two options act
! together to send file names between @code{find} and @code{cpio}, even if
! special characters are embedded in the file names.  The @samp{-p} option
! tells @code{cpio} to @emph{pass} the files it finds to the directory
! @samp{new-dir}.
  
  @node Invoking `cpio', Media, Tutorial, Top
  @comment  node-name,  next,  previous,  up
***************
*** 246,258 ****
  @comment  node-name,  next,  previous,  up
  @section Copy-out mode
  
! In copy-out mode, cpio copies files into an archive.  It reads a list
! of filenames, one per line, on the standard input, and writes the
! archive onto the standard output.  A typical way to generate the list
! of filenames is with the find command; you should give find the -depth
! option to minimize problems with permissions on directories that are
! unreadable.
! @xref{Options}.
  
  @example
  cpio @{-o|--create@} [-0acvABLV] [-C bytes] [-H format]
--- 249,260 ----
  @comment  node-name,  next,  previous,  up
  @section Copy-out mode
  
! In copy-out mode, @code{cpio} copies files into an archive.  It reads a
! list of filenames, one per line, on the standard input, and writes the
! archive onto the standard output.  A typical way to generate the list of
! filenames is with the @code{find} command; you should give find the
! @samp{-depth} option to minimize problems with permissions on
! directories that are unreadable.  @xref{Options}.
  
  @example
  cpio @{-o|--create@} [-0acvABLV] [-C bytes] [-H format]
***************
*** 267,280 ****
  @comment  node-name,  next,  previous,  up
  @section Copy-in mode
  
! In copy-in mode, cpio copies files out of an archive or lists the
  archive contents.  It reads the archive from the standard input.  Any
  non-option command line arguments are shell globbing patterns; only
  files in the archive whose names match one or more of those patterns are
! copied from the archive.  Unlike in the shell, an initial `.' in a
! filename does match a wildcard at the start of a pattern, and a `/' in a
! filename can match wildcards.  If no patterns are given, all files are
! extracted.  @xref{Options}.
  
  @example
  cpio @{-i|--extract@} [-bcdfmnrtsuvBSV] [-C bytes] [-E file]
--- 269,282 ----
  @comment  node-name,  next,  previous,  up
  @section Copy-in mode
  
! In copy-in mode, @code{cpio} copies files out of an archive or lists the
  archive contents.  It reads the archive from the standard input.  Any
  non-option command line arguments are shell globbing patterns; only
  files in the archive whose names match one or more of those patterns are
! copied from the archive.  Unlike in the shell, an initial @file{.} in a
! filename does match a wildcard at the start of a pattern, and a @file{/}
! in a filename can match wildcards.  If no patterns are given, all files
! are extracted.  @xref{Options}.
  
  @example
  cpio @{-i|--extract@} [-bcdfmnrtsuvBSV] [-C bytes] [-E file]
***************
*** 295,303 ****
  @comment  node-name,  next,  previous,  up
  @section Copy-pass mode
  
! In copy-pass mode, cpio copies files from one directory tree to
  another, combining the copy-out and copy-in steps without actually
! using an archive.  It reads the list of files to copy from the
  standard input; the directory into which it will copy them is given as
  a non-option argument.
  @xref{Options}.
--- 297,305 ----
  @comment  node-name,  next,  previous,  up
  @section Copy-pass mode
  
! In copy-pass mode, @code{cpio} copies files from one directory tree to
  another, combining the copy-out and copy-in steps without actually
! creating an archive.  It reads the list of files to copy from the
  standard input; the directory into which it will copy them is given as
  a non-option argument.
  @xref{Options}.
***************
*** 324,335 ****
  @item -0, --null
  Read a list of filenames terminated by a null character, instead of a
  newline, so that files whose names contain newlines can be archived.
! GNU find is one way to produce a list of null-terminated filenames.
! This option may be used in copy-out and copy-pass modes.
  
  @item -a, --reset-access-time
  Reset the access times of files after reading them, so
! that it does not look like they have just been read.
  
  @item -A, --append
  Append to an existing archive.  Only works in copy-out
--- 326,339 ----
  @item -0, --null
  Read a list of filenames terminated by a null character, instead of a
  newline, so that files whose names contain newlines can be archived.
! GNU @code{find} is one way to produce a list of null-terminated
! filenames.  This option may be used in copy-out and copy-pass modes.
  
  @item -a, --reset-access-time
  Reset the access times of files after reading them, so
! that it does not look like they have just been read.  (This option has
! no effect on plain DOS, since DOS filesystem only stores a single time
! stamp per file.  It does work on Windows 9X.)
  
  @item -A, --append
  Append to an existing archive.  Only works in copy-out
***************
*** 346,373 ****
  Set the I/O block size to 5120 bytes.  Initially the
  block size is 512 bytes.
  
! @item --block-size=BLOCK-SIZE
! Set the I/O block size to BLOCK-SIZE * 512 bytes.
  
  @item -c
  Use the old portable (ASCII) archive format.
  
! @item -C IO-SIZE, --io-size=IO-SIZE
! Set the I/O block size to IO-SIZE bytes.
  
  @item -d, --make-directories
  Create leading directories where needed.
  
! @item -E FILE, --pattern-file=FILE
  Read additional patterns specifying filenames to extract or list from
! FILE.  The lines of FILE are treated as if they had been non-option
! arguments to cpio.  This option is used in copy-in mode,
  
  @item -f, --nonmatching
  Only copy files that do not match any of the given
  patterns.
  
! @item -F, --file=archive
  Archive filename to use instead of standard input or output.  To use a
  tape drive on another machine as the archive, use a filename that starts
  with `HOSTNAME:'.  The hostname can be preceded by a username and an
--- 350,378 ----
  Set the I/O block size to 5120 bytes.  Initially the
  block size is 512 bytes.
  
! @item --block-size=@var{block-size}
! Set the I/O block size to @var{block-size} * 512 bytes.
  
  @item -c
  Use the old portable (ASCII) archive format.
  
! @item -C @var{io-size}, --io-size=@var{io-size}
! Set the I/O block size to @var{io-size} bytes.
  
  @item -d, --make-directories
  Create leading directories where needed.
  
! @item -E @var{file}, --pattern-file=@var{file}
  Read additional patterns specifying filenames to extract or list from
! @var{file}.  The lines of @var{file} are treated as if they had been
! non-option arguments to @code{cpio}.  This option is used in copy-in
! mode,
  
  @item -f, --nonmatching
  Only copy files that do not match any of the given
  patterns.
  
! @item -F, --file=@var{archive}
  Archive filename to use instead of standard input or output.  To use a
  tape drive on another machine as the archive, use a filename that starts
  with `HOSTNAME:'.  The hostname can be preceded by a username and an
***************
*** 375,390 ****
  permission to do so (typically an entry in that user's `~/.rhosts'
  file).
  
  @item --force-local
  With -F, -I, or -O, take the archive file name to be a
  local file even if it contains a colon, which would
  ordinarily indicate a remote host name.
  
! @item -H FORMAT, --format=FORMAT
! Use archive format FORMAT.  The valid formats are listed below; the same
! names are also recognized in all-caps.  The default in copy-in mode is
! to automatically detect the archive format, and in copy-out mode is
! @samp{bin}.
  
  @table @samp
  @item bin  
--- 380,397 ----
  permission to do so (typically an entry in that user's `~/.rhosts'
  file).
  
+ Remote archives are not supported on MS-DOS and MS-Windows.
+ 
  @item --force-local
  With -F, -I, or -O, take the archive file name to be a
  local file even if it contains a colon, which would
  ordinarily indicate a remote host name.
  
! @item -H @var{format}, --format=@var{format}
! Use archive format @var{format}.  The valid formats are listed below;
! the same names are also recognized in all-capital letters.  The default
! in copy-in mode is to automatically detect the archive format, and in
! copy-out mode is @samp{bin}.
  
  @table @samp
  @item bin  
***************
*** 408,418 ****
  similar but not identical.
  
  @item hpbin
! The obsolete binary format used by HPUX's cpio (which stores device
  files differently).
  
  @item hpodc
! The portable format used by HPUX's cpio (which stores device files
  differently).
  @end table
  
--- 415,425 ----
  similar but not identical.
  
  @item hpbin
! The obsolete binary format used by HPUX's @code{cpio} (which stores device
  files differently).
  
  @item hpodc
! The portable format used by HPUX's @code{cpio} (which stores device files
  differently).
  @end table
  
***************
*** 420,434 ****
  Run in copy-in mode.
  @xref{Copy-in mode}.
  
! @item -I archive
  Archive filename to use instead of standard input.  To use a tape drive
  on another machine as the archive, use a filename that starts with
  `HOSTNAME:'.  The hostname can be preceded by a username and an `@@' to
  access the remote tape drive as that user, if you have permission to do
  so (typically an entry in that user's `~/.rhosts' file).
  
  @item -k
! Ignored; for compatibility with other versions of cpio.
  
  @item -l, --link
  Link files instead of copying them, when possible.
--- 427,443 ----
  Run in copy-in mode.
  @xref{Copy-in mode}.
  
! @item -I @var{archive}
  Archive filename to use instead of standard input.  To use a tape drive
  on another machine as the archive, use a filename that starts with
  `HOSTNAME:'.  The hostname can be preceded by a username and an `@@' to
  access the remote tape drive as that user, if you have permission to do
  so (typically an entry in that user's `~/.rhosts' file).
  
+ Remote archives are not supported on MS-DOS and MS-Windows.
+ 
  @item -k
! Ignored; for compatibility with other versions of @code{cpio}.
  
  @item -l, --link
  Link files instead of copying them, when possible.
***************
*** 440,454 ****
  @item -m, --preserve-modification-time
  Retain previous file modification times when creating files.
  
! @item -M MESSAGE, --message=MESSAGE
! Print MESSAGE when the end of a volume of the backup media (such as a
! tape or a floppy disk) is reached, to prompt the user to insert a new
! volume.  If MESSAGE contains the string "%d", it is replaced by the
! current volume number (starting at 1).
  
  @item -n, --numeric-uid-gid
! Show numeric UID and GID instead of translating them into names when using the
! @samp{--verbose option}.
  
  @item --no-absolute-filenames
  Create all files relative to the current directory in copy-in mode, even
--- 449,463 ----
  @item -m, --preserve-modification-time
  Retain previous file modification times when creating files.
  
! @item -M @var{message}, --message=@var{message}
! Print @var{message} when the end of a volume of the backup media (such
! as a tape or a floppy disk) is reached, to prompt the user to insert a
! new volume.  If @var{message} contains the string "%d", it is replaced
! by the current volume number (starting at 1).
  
  @item -n, --numeric-uid-gid
! Show numeric UID and GID instead of translating them into names when
! using the @samp{--verbose option}.
  
  @item --no-absolute-filenames
  Create all files relative to the current directory in copy-in mode, even
***************
*** 464,476 ****
  Run in copy-out mode.
  @xref{Copy-out mode}.
  
! @item -O archive
  Archive filename to use instead of standard output.  To use a tape drive
  on another machine as the archive, use a filename that starts with
  `HOSTNAME:'.  The hostname can be preceded by a username and an `@@' to
  access the remote tape drive as that user, if you have permission to do
  so (typically an entry in that user's `~/.rhosts' file).
  
  @item --only-verify-crc
  Verify the CRC's of each file in the archive, when reading a CRC format
  archive. Don't actually extract the files.
--- 473,487 ----
  Run in copy-out mode.
  @xref{Copy-out mode}.
  
! @item -O @var{archive}
  Archive filename to use instead of standard output.  To use a tape drive
  on another machine as the archive, use a filename that starts with
  `HOSTNAME:'.  The hostname can be preceded by a username and an `@@' to
  access the remote tape drive as that user, if you have permission to do
  so (typically an entry in that user's `~/.rhosts' file).
  
+ Remote archives are not supported on MS-DOS and MS-Windows.
+ 
  @item --only-verify-crc
  Verify the CRC's of each file in the archive, when reading a CRC format
  archive. Don't actually extract the files.
***************
*** 483,497 ****
  Do not print the number of blocks copied.
  
  @item -r, --rename
! Interactively rename files.
  
  @item -R [user][:.][group], --owner [user][:.][group]
  Set the ownership of all files created to the specified user and/or
! group in copy-out and copy-pass modes.  Either the user, the group, or
  both, must be present.  If the group is omitted but the ":" or "."
  separator is given, use the given user's login group.  Only the
  super-user can change files' ownership.
  
  @item -s, --swap-bytes
  Swap the bytes of each halfword (pair of bytes) in the files.This option
  can be used in copy-in mode.
--- 494,519 ----
  Do not print the number of blocks copied.
  
  @item -r, --rename
! Interactively rename files.  For each file in the archive, @code{cpio}
! will print its name and wait for the user to type a new name.  An empty
! name (produced by pressing @kbd{RET}) means skip the file.
! 
! @item --rename-batch-file=@var{rename-file}
! Non-interactively rename files.  For each file in the archive,
! @code{cpio} will read a replacement name from the named
! @var{rename-file}.  In that file, file names should be separated by
! newlines.  An empty line causes @code{cpio} to skip the file.
  
  @item -R [user][:.][group], --owner [user][:.][group]
  Set the ownership of all files created to the specified user and/or
! group in copy-in and copy-pass modes.  Either the user, the group, or
  both, must be present.  If the group is omitted but the ":" or "."
  separator is given, use the given user's login group.  Only the
  super-user can change files' ownership.
  
+ (On MS-DOS and MS-Windows, any user can use this option, since changing
+ ownership is a no-op on these systems.)
+ 
  @item -s, --swap-bytes
  Swap the bytes of each halfword (pair of bytes) in the files.This option
  can be used in copy-in mode.
***************
*** 522,528 ****
  Print a @kbd{.} for each file processed.
  
  @item --version
! Print the cpio program version number and exit.
  @end table
  
  
--- 544,550 ----
  Print a @kbd{.} for each file processed.
  
  @item --version
! Print the @code{cpio} program version number and exit.
  @end table
  
  
***************
*** 534,548 ****
  Archives are usually written on removable media--tape cartridges, mag
  tapes, or floppy disks.
  
! The amount of data a tape or disk holds depends not only on its size,
  but also on how it is formatted.  A 2400 foot long reel of mag tape
  holds 40 megabytes of data when formated at 1600 bits per inch.  The
  physically smaller EXABYTE tape cartridge holds 2.3 gigabytes.
  
  Magnetic media are re-usable--once the archive on a tape is no longer
! needed, the archive can be erased and the tape or disk used over. Media
  quality does deteriorate with use, however.  Most tapes or disks should
! be disgarded when they begin to produce data errors.
  
  Magnetic media are written and erased using magnetic fields, and should
  be protected from such fields to avoid damage to stored data.  Sticking
--- 556,570 ----
  Archives are usually written on removable media--tape cartridges, mag
  tapes, or floppy disks.
  
! The amount of data a tape or disk can hold depends not only on its size,
  but also on how it is formatted.  A 2400 foot long reel of mag tape
  holds 40 megabytes of data when formated at 1600 bits per inch.  The
  physically smaller EXABYTE tape cartridge holds 2.3 gigabytes.
  
  Magnetic media are re-usable--once the archive on a tape is no longer
! needed, the archive can be erased and the tape or disk used over.  Media
  quality does deteriorate with use, however.  Most tapes or disks should
! be discarded when they begin to produce data errors.
  
  Magnetic media are written and erased using magnetic fields, and should
  be protected from such fields to avoid damage to stored data.  Sticking

*** tar.c~0	Fri Feb 25 19:25:32 1994
--- tar.c	Sat Nov  1 12:29:12 1997
*************** read_in_tar_header (file_hdr, in_des)
*** 277,282 ****
--- 277,288 ----
  	otoa (tar_hdr->gid, &file_hdr->c_gid);
        otoa (tar_hdr->size, &file_hdr->c_filesize);
        otoa (tar_hdr->mtime, &file_hdr->c_mtime);
+ #if defined(__MSDOS__) || defined(__DJGPP__)
+       /* DOS truncates times down to the nearest even second.  Truncate
+ 	 the time of the file ahead of DOS, so -m option works correctly.  */
+       file_hdr->c_mtime += 1;
+       file_hdr->c_mtime &= 0xfffffff0LU;
+ #endif
        otoa (tar_hdr->devmajor, (unsigned long *) &file_hdr->c_rdev_maj);
        otoa (tar_hdr->devminor, (unsigned long *) &file_hdr->c_rdev_min);
        file_hdr->c_tar_linkname = NULL;

*** util.c~0	Tue Jan 16 21:40:14 1996
--- util.c	Sat Nov  1 12:08:08 1997
*************** write_nuls_to_file (num_bytes, out_des)
*** 1341,1343 ****
--- 1341,1501 ----
  	error (1, errno, "error writing NUL's");
      }
  }
+ 
+ #ifdef __DJGPP__
+ 
+ #include <errno.h>
+ #include <limits.h>
+ #include <sys/stat.h>
+ 
+ /* A dummy version of `readlink' which just fails.
+    FIXME: it might be nice to support ``symlinks'' to executable programs.  */
+ int readlink (const char *path, char *linkname, int name_buf_size)
+ {
+   errno = ENOSYS;
+   return -1;
+ }
+ 
+ /* If the original file name includes characters illegal for MS-DOS and
+    MS-Windows, massage it to make it suitable and return a pointer to
+    static storage with a new name.  If the original name is legit,
+    return it instead.  Return NULL if the rename failed (shouldn't happen).
+ 
+    The file name changes are: (1) any name that is reserved by a DOS
+    device driver (such as `prn.txt' or `aux.c') is prepended with a `_';
+    and (2) illegal characters are replaced with `_' or `-' (well, almost;
+    look at the code below for details).  */
+    
+ char * maybe_rename_file (char *original_name)
+ {
+   static char dosified_name[PATH_MAX];
+   static char illegal_chars_dos[] = ".+, ;=[]|<>\\\":?*";
+   static char *illegal_chars_w95 = &illegal_chars_dos[8];
+   int idx, dot_idx;
+   char *s = original_name, *d = dosified_name;
+   char *illegal_aliens = illegal_chars_dos;
+   size_t len = sizeof (illegal_chars_dos) - 1;
+   int windows9x = _use_lfn (original_name);
+ 
+   /* Support for Windows 9X VFAT systems, when available.  */
+   if (windows9x)
+     {
+       illegal_aliens = illegal_chars_w95;
+       len -= (illegal_chars_w95 - illegal_chars_dos);
+     }
+ 
+   /* Get past the drive letter, if any. */
+   if (s[0] >= 'A' && s[0] <= 'z' && s[1] == ':')
+     {
+       *d++ = *s++;
+       *d++ = *s++;
+     }
+ 
+   for (idx = 0, dot_idx = -1; *s; s++, d++)
+     {
+       if (memchr (illegal_aliens, *s, len))
+ 	{
+ 	  /* Dots are special on DOS: it doesn't allow them as the leading
+ 	     character, and a file name cannot have more than a single dot.
+ 	     We leave the first non-leading dot alone, unless it comes too
+ 	     close to the beginning of the name: we want sh.lex.c to become
+ 	     sh_lex.c, not sh.lex-c.  */
+ 	  if (*s == '.')
+ 	    {
+ 	      if (idx == 0
+ 		  && (s[1] == '/' || s[1] == '\0'
+ 		      || (s[1] == '.' && (s[2] == '/' || s[2] == '\0'))))
+ 		{
+ 		  /* Copy "./" and "../" verbatim.  */
+ 		  *d++ = *s++;
+ 		  if (*s == '.')
+ 		    *d++ = *s++;
+ 		  *d = *s;
+ 		}
+ 	      else if (idx == 0)
+ 		*d = '_';
+ 	      else if (dot_idx >= 0)
+ 		{
+ 		  if (dot_idx < 5) /* 5 is merely a heuristic ad-hoc'ery */
+ 		    {
+ 		      d[dot_idx - idx] = '_'; /* replace previous dot */
+ 		      *d = '.';
+ 		    }
+ 		  else
+ 		    *d = '-';
+ 		}
+ 	      else
+ 		*d = '.';
+ 
+ 	      if (*s == '.')
+ 		dot_idx = idx;
+ 	    }
+ 	  else if (*s == '+' && s[1] == '+')
+ 	    {
+ 	      if (idx - 2 == dot_idx) /* .c++, .h++ etc. */
+ 		{
+ 		  *d++ = 'x';
+ 		  *d   = 'x';
+ 		}
+ 	      else
+ 		{
+ 		  /* libg++ etc.  */
+ 		  memcpy (d, "plus", 4);
+ 		  d += 3;
+ 		}
+ 	      s++;
+ 	      idx++;
+ 	    }
+ 	  else
+ 	    *d = '_';
+ 	}
+       else
+ 	*d = *s;
+       if (*s == '/')
+ 	{
+ 	  idx = 0;
+ 	  dot_idx = -1;
+ 	}
+       else
+ 	idx++;
+     }
+ 
+   *d = '\0';
+ 
+   /* We could have a file in an archive whose name is reserved
+      on MS-DOS by a device driver.  Trying to extract such a
+      file would fail at best and wedge us at worst.  We need to
+      rename such files.  */
+ 
+   if (idx > 0)
+     {
+       struct stat st_buf;
+       char *base = d - idx;
+       int i = 0;
+ 
+       /* The list of character devices is not constant: it depends on
+ 	 what device drivers did they install in their CONFIG.SYS.
+ 	 `stat' will tell us if the basename of the file name is a
+ 	 characer device.  */
+       while (stat (base, &st_buf) == 0 && S_ISCHR (st_buf.st_mode))
+ 	{
+ 	  size_t blen = strlen (base);
+ 
+ 	  /* I don't believe any DOS character device names begin with a
+ 	     `_'.  But in case they invent such a device, let us try twice.  */
+ 	  if (++i > 2)
+ 	    return (char *)0;
+ 
+ 	  /* Prepend a '_'.  */
+ 	  memmove (base + 1, base, blen + 1);
+ 	  base[0] = '_';
+ 	}
+     }
+ 
+   if (strcmp (original_name, dosified_name))
+     return dosified_name;
+   return original_name;
+ }
+ 
+ 
+ #endif /* __DJGPP__ */

*** copyin.c~0	Wed Nov 30 22:49:06 1994
--- copyin.c	Sat Nov  1 12:24:50 1997
***************
*** 29,34 ****
--- 29,38 ----
  #include <fnmatch.h>
  #endif
  
+ #ifdef __DJGPP__
+ #include <io.h>
+ #endif
+ 
  #ifndef HAVE_LCHOWN
  #define lchown chown
  #endif
*************** read_in_old_ascii (file_hdr, in_des)
*** 178,183 ****
--- 182,193 ----
    file_hdr->c_dev_min = minor (dev);
    file_hdr->c_rdev_maj = major (rdev);
    file_hdr->c_rdev_min = minor (rdev);
+ #if defined(__MSDOS__) || defined(__DJGPP__)
+   /* DOS truncates times down to the nearest even second.  Truncate
+      the time of the file ahead of DOS, so -m option works correctly.  */
+   file_hdr->c_mtime += 1;
+   file_hdr->c_mtime &= 0xfffffff0LU;
+ #endif
  
    /* Read file name from input.  */
    if (file_hdr->c_name != NULL)
*************** read_in_new_ascii (file_hdr, in_des)
*** 236,241 ****
--- 246,258 ----
  	  &file_hdr->c_filesize, &file_hdr->c_dev_maj, &file_hdr->c_dev_min,
  	&file_hdr->c_rdev_maj, &file_hdr->c_rdev_min, &file_hdr->c_namesize,
  	  &file_hdr->c_chksum);
+ #if defined(__MSDOS__) || defined(__DJGPP__)
+   /* DOS truncates times down to the nearest even second.  Truncate
+      the time of the file ahead of DOS, so -m option works correctly.  */
+   file_hdr->c_mtime += 1;
+   file_hdr->c_mtime &= 0xfffffff0LU;
+ #endif
+ 
    /* Read file name from input.  */
    if (file_hdr->c_name != NULL)
      free (file_hdr->c_name);
*************** read_in_binary (file_hdr, in_des)
*** 291,296 ****
--- 308,319 ----
    file_hdr->c_rdev_min = minor (short_hdr.c_rdev);
    file_hdr->c_mtime = (unsigned long) short_hdr.c_mtimes[0] << 16
      | short_hdr.c_mtimes[1];
+ #if defined(__MSDOS__) || defined(__DJGPP__)
+   /* DOS truncates times down to the nearest even second.  Truncate
+      the time of the file ahead of DOS, so -m option works correctly.  */
+   file_hdr->c_mtime += 1;
+   file_hdr->c_mtime &= 0xfffffff0LU;
+ #endif
  
    file_hdr->c_namesize = short_hdr.c_namesize;
    file_hdr->c_filesize = (unsigned long) short_hdr.c_filesizes[0] << 16
*************** process_copy_in ()
*** 422,427 ****
--- 445,454 ----
  #ifdef __MSDOS__
    setmode (archive_des, O_BINARY);
  #endif
+ #ifdef __DJGPP__
+   if (!isatty (archive_des))
+     setmode (archive_des, O_BINARY);
+ #endif
    /* Check whether the input file might be a tape.  */
    in_file_des = archive_des;
    if (_isrmt (in_file_des))
*************** process_copy_in ()
*** 440,445 ****
--- 467,480 ----
  	S_ISCHR (file_stat.st_mode);
        input_is_seekable = S_ISREG (file_stat.st_mode);
      }
+ 
+ #ifdef __DJGPP__
+   /* We might as well give the user an opportunity to recover
+      from premature end of input even if they are reading from
+      a disk file.  It is specifically handy with floppies.  */
+   input_is_special = !isatty (in_file_des);
+ #endif
+ 
    output_is_seekable = TRUE;
  
    /* While there is more input in the collection, process the input.  */
*************** process_copy_in ()
*** 481,486 ****
--- 516,530 ----
  
        /* Do we have to ignore absolute paths, and if so, does the filename
           have an absolute path?  */
+ #if defined (__MSDOS__) || defined (__DJGPP__)
+       /* On MS-DOS and MS-Windows, absolute pathnames might include drive
+ 	 letters.  Remove them, if absolute paths are to be ignored.  */
+       if (no_abs_paths_flag && file_hdr.c_name
+ 	  && file_hdr.c_name [0] >= 'A' && file_hdr.c_name [0] <= 'z'
+ 	  && file_hdr.c_name [1] == ':')
+ 	memmove (file_hdr.c_name, file_hdr.c_name + 2,
+ 		 strlen (file_hdr.c_name) - 1);
+ #endif
        if (no_abs_paths_flag && file_hdr.c_name && file_hdr.c_name [0] == '/')
  	{
  	  char *p;
*************** process_copy_in ()
*** 596,601 ****
--- 640,664 ----
  	  /* Copy the input file into the directory structure.  */
  
  	  /* Do we need to rename the file? */
+ #ifdef __DJGPP__
+ 	  /* Rename file names which cannot be used on MS-DOS/MS-Windows.  */
+ 	  extern char * maybe_rename_file (char *);
+ 	  char *renamed = maybe_rename_file (file_hdr.c_name);
+ 
+ 	  if (renamed == 0)	/* paranoia: this should never happen */
+ 	    {
+ 	      error (0, EACCES, "%s: Could not create file", file_hdr.c_name);
+ 	      tape_toss_input (in_file_des, file_hdr.c_filesize);
+ 	      tape_skip_padding (in_file_des, file_hdr.c_filesize);
+ 	    }
+ 	  else if (renamed != file_hdr.c_name)
+ 	    {
+ 	      if (verbose_flag)
+ 		printf ("rename %s -> %s\n", file_hdr.c_name, renamed);
+ 	      free (file_hdr.c_name);
+ 	      file_hdr.c_name = xstrdup (renamed);
+ 	    }
+ #endif
  	  if (rename_flag || rename_batch_file)
  	    {
  	      if (rename_flag)
*************** process_copy_in ()
*** 687,693 ****
  		     still have to check for links here (and also in case
  		     the archive was created and later appeneded to). */
  		  link_res = link_to_maj_min_ino (file_hdr.c_name, 
! 				file_hdr.c_dev_maj, file_hdr.c_dev_maj,
  				file_hdr.c_ino);
  		  if (link_res == 0)
  		    {
--- 750,756 ----
  		     still have to check for links here (and also in case
  		     the archive was created and later appeneded to). */
  		  link_res = link_to_maj_min_ino (file_hdr.c_name, 
! 				file_hdr.c_dev_maj, file_hdr.c_dev_min,
  				file_hdr.c_ino);
  		  if (link_res == 0)
  		    {
*************** process_copy_in ()
*** 701,707 ****
  		{
  		  int link_res;
  		  link_res = link_to_maj_min_ino (file_hdr.c_name, 
! 				file_hdr.c_dev_maj, file_hdr.c_dev_maj,
  				file_hdr.c_ino);
  		  if (link_res == 0)
  		    {
--- 764,770 ----
  		{
  		  int link_res;
  		  link_res = link_to_maj_min_ino (file_hdr.c_name, 
! 				file_hdr.c_dev_maj, file_hdr.c_dev_min,
  				file_hdr.c_ino);
  		  if (link_res == 0)
  		    {
*************** process_copy_in ()
*** 740,746 ****
  		    }
  		  if (out_file_des < 0)
  		    {
! 		      error (0, errno, "%s", file_hdr.c_name);
  		      tape_toss_input (in_file_des, file_hdr.c_filesize);
  		      tape_skip_padding (in_file_des, file_hdr.c_filesize);
  		      continue;
--- 803,821 ----
  		    }
  		  if (out_file_des < 0)
  		    {
! 		      /* If we cannot copy because -d wasn't given, make the
! 			 error message mention the directory part of name.  */
! 		      if (!create_dir_flag)
! 			{
! 			  char *dirpart = dirname (file_hdr.c_name);
! 			  struct stat dirpart_stat;
! 
! 			  if (stat (dirpart, &dirpart_stat) < 0)
! 			    error (0, errno, "%s", dirpart);
! 			  free (dirpart);
! 			}
! 		      else
! 			error (0, errno, "%s", file_hdr.c_name);
  		      tape_toss_input (in_file_des, file_hdr.c_filesize);
  		      tape_skip_padding (in_file_des, file_hdr.c_filesize);
  		      continue;
*************** process_copy_in ()
*** 845,858 ****
  		}
  	      if (res < 0)
  		{
  		  /* In some odd cases where the file_hdr.c_name includes `.',
  		     the directory may have actually been created by
  		     create_all_directories(), so the mkdir will fail
  		     because the directory exists.  If that's the case,
  		     don't complain about it.  */
! 		  if ( (errno != EEXIST) ||
! 		       (lstat (file_hdr.c_name, &file_stat) != 0) ||
! 		       !(S_ISDIR (file_stat.st_mode) ) )
  		    {
  		      error (0, errno, "%s", file_hdr.c_name);
  		      continue;
--- 920,945 ----
  		}
  	      if (res < 0)
  		{
+ 		  /* If we aren't allowed to create intermediate directories,
+ 		     make the error message mention the parent directory.  */
+ 		  if (!create_dir_flag)
+ 		    {
+ 		      char *dirpart = dirname (file_hdr.c_name);
+ 		      struct stat dirpart_stat;
+ 
+ 		      if (stat (dirpart, &dirpart_stat) < 0)
+ 			error (0, errno, "%s", dirpart);
+ 		      free (dirpart);
+ 		      continue;
+ 		    }
  		  /* In some odd cases where the file_hdr.c_name includes `.',
  		     the directory may have actually been created by
  		     create_all_directories(), so the mkdir will fail
  		     because the directory exists.  If that's the case,
  		     don't complain about it.  */
! 		  else if ( (errno != EEXIST) ||
! 			    (lstat (file_hdr.c_name, &file_stat) != 0) ||
! 			    !(S_ISDIR (file_stat.st_mode) ) )
  		    {
  		      error (0, errno, "%s", file_hdr.c_name);
  		      continue;
*************** process_copy_in ()
*** 877,882 ****
--- 964,977 ----
  		{
  		  times.actime = times.modtime = file_hdr.c_mtime;
  		  if (utime (file_hdr.c_name, &times) < 0)
+ #if defined(__MSDOS__) || defined(__DJGPP__)
+ 		    /* MS-DOS/Windows won't let us to set mod times of
+ 		       a directory.  Make the error message explicit.  */
+ 		    if (errno == EACCES)
+ 		      error (0, 0, "%s: Cannot set access time of a directory",
+ 			     file_hdr.c_name);
+ 		    else
+ #endif
  		    error (0, errno, "%s", file_hdr.c_name);
  		}
  	      break;
*************** process_copy_in ()
*** 895,901 ****
  		{
  		  int link_res;
  		  link_res = link_to_maj_min_ino (file_hdr.c_name, 
! 				file_hdr.c_dev_maj, file_hdr.c_dev_maj,
  				file_hdr.c_ino);
  		  if (link_res == 0)
  		    break;
--- 990,996 ----
  		{
  		  int link_res;
  		  link_res = link_to_maj_min_ino (file_hdr.c_name, 
! 				file_hdr.c_dev_maj, file_hdr.c_dev_min,
  				file_hdr.c_ino);
  		  if (link_res == 0)
  		    break;
*************** process_copy_in ()
*** 931,937 ****
  		}
  	      if (res < 0)
  		{
! 		  error (0, errno, "%s", file_hdr.c_name);
  		  continue;
  		}
  	      if (!no_chown_flag)
--- 1026,1044 ----
  		}
  	      if (res < 0)
  		{
! 		  /* If we aren't allowed to create intermediate directories,
! 		     make the error message mention the parent directory.  */
! 		  if (!create_dir_flag)
! 		    {
! 		      char *dirpart = dirname (file_hdr.c_name);
! 		      struct stat dirpart_stat;
! 
! 		      if (stat (dirpart, &dirpart_stat) < 0)
! 			error (0, errno, "%s", dirpart);
! 		      free (dirpart);
! 		    }
! 		  else
! 		    error (0, errno, "%s", file_hdr.c_name);
  		  continue;
  		}
  	      if (!no_chown_flag)
*************** process_copy_in ()
*** 977,983 ****
  		  }
  		if (res < 0)
  		  {
! 		    error (0, errno, "%s", file_hdr.c_name);
  		    free (link_name);
  		    link_name = NULL;
  		    continue;
--- 1084,1102 ----
  		  }
  		if (res < 0)
  		  {
! 		    /* If we aren't allowed to create intermediate directories,
! 		       make the error message mention the parent directory.  */
! 		    if (!create_dir_flag)
! 		      {
! 			char *dirpart = dirname (file_hdr.c_name);
! 			struct stat dirpart_stat;
! 
! 			if (stat (dirpart, &dirpart_stat) < 0)
! 			  error (0, errno, "%s", dirpart);
! 			free (dirpart);
! 		      }
! 		    else
! 		      error (0, errno, "%s", file_hdr.c_name);
  		    free (link_name);
  		    link_name = NULL;
  		    continue;
*************** process_copy_in ()
*** 995,1001 ****
  #endif
  
  	    default:
! 	      error (0, 0, "%s: unknown file type", file_hdr.c_name);
  	      tape_toss_input (in_file_des, file_hdr.c_filesize);
  	      tape_skip_padding (in_file_des, file_hdr.c_filesize);
  	    }
--- 1114,1120 ----
  #endif
  
  	    default:
! 	      error (0, 0, "%s: unsupported file type", file_hdr.c_name);
  	      tape_toss_input (in_file_des, file_hdr.c_filesize);
  	      tape_skip_padding (in_file_des, file_hdr.c_filesize);
  	    }
*************** long_format (file_hdr, link_name)
*** 1038,1044 ****
--- 1157,1168 ----
    char tbuf[40];
    time_t when;
  
+ #ifdef __DJGPP__
+   /* The S_IFfoo bits are different from the corresponding CP_IFfoo.  */
+   cpio_mode_string (file_hdr->c_mode, mbuf);
+ #else
    mode_string (file_hdr->c_mode, mbuf);
+ #endif
    mbuf[10] = '\0';
  
    /* Get time values ready to print.  */
*************** create_final_defers ()
*** 1306,1314 ****
    
    for (d = deferments; d != NULL; d = d->next)
      {
-       d = deferments;
        link_res = link_to_maj_min_ino (d->header.c_name, 
! 		    d->header.c_dev_maj, d->header.c_dev_maj,
  		    d->header.c_ino);
        if (link_res == 0)
  	{
--- 1430,1437 ----
    
    for (d = deferments; d != NULL; d = d->next)
      {
        link_res = link_to_maj_min_ino (d->header.c_name, 
! 		    d->header.c_dev_maj, d->header.c_dev_min,
  		    d->header.c_ino);
        if (link_res == 0)
  	{

*** /dev/null	Sat Nov  1 13:22:14 1997
--- configdj.sed	Sat Oct 25 19:17:14 1997
***************
*** 0 ****
--- 1,40 ----
+ s%@CFLAGS@%-O2 -g%g
+ s%@CPPFLAGS@%%g
+ s%@CXXFLAGS@%%g
+ s%@DEFS@%-imacros ${srcdir}/configdj.inc%g
+ s%@LDFLAGS@%%g
+ s%@LIBS@%%g
+ s%@prefix@%${DJDIR}%g
+ s%@exec_prefix@%${prefix}%g
+ s%@program_transform_name@%s,x,x,%g
+ s%@bindir@%${exec_prefix}/bin%g
+ s%@libexecdir@%${exec_prefix}/libexec%g
+ s%@sysconfdir@%${prefix}/etc%g
+ s%@sharedstatedir@%${prefix}/com%g
+ s%@localstatedir@%${prefix}/var%g
+ s%@libdir@%${exec_prefix}/lib%g
+ s%@includedir@%${prefix}/include%g
+ s%@oldincludedir@%/usr/include%g
+ s%@infodir@%${prefix}/info%g
+ s%@mandir@%${prefix}/info%g
+ s%@PROGS@%cpio%g
+ s%@CC@%gcc%g
+ s%@CPP@%gcc -E%g
+ s%@INSTALL@%${DJDIR}/bin/ginstall -c%g
+ s%@INSTALL_PROGRAM@%${INSTALL}%g
+ s%@INSTALL_DATA@%${INSTALL} -m 644%g
+ s%@RTAPELIB@%%g
+ s%@LIBOBJS@%%g
+ s%@FNMATCH@%%g
+ s%@ALLOCA@%%g
+ /^	$(SHELL) config.status/d
+ /^Makefile: Makefile.in config.status/a\
+ 	command.com /c configdj.bat\
+ 
+ /^config.status: /a\
+ 	touch $@\
+ 
+ /^config.status: configure/c\
+ config.status: configdj.bat configdj.sed configdj.inc
+ /^	TEXINPUTS=$(srcdir):/s,:,;,
+ /^mandir *=/s,/man1,,

*** /dev/null	Sat Nov  1 13:22:20 1997
--- configdj.bat	Sat Oct 25 19:08:52 1997
***************
*** 0 ****
--- 1,47 ----
+ @echo off
+ 
+ Rem Batch file to configure GNU cpio for DJGPP v2.
+ echo Configuring GNU cpio for DJGPP v2...
+ 
+ Rem Find out where our sources are
+ set XSRC=.
+ if not "%XSRC%" == "." Goto SmallEnv
+ if "%1" == "" Goto FoundSrc
+ set XSRC=%1
+ if not "%XSRC%" == "%1" Goto SmallEnv
+ 
+ :FoundSrc
+ Rem Make sure they have something similar to DJGPP port of Sed installed
+ echo Checking for working Sed...
+ sed -n -e 's,Rem ,Rem ,w foo.txt' %XSRC%/configdj.bat
+ if not exist foo.txt Goto NoSed
+ del foo.txt
+ echo config.status > config.status
+ 
+ Rem Do not do this in one pipe since XSRC might be long enough to
+ Rem overflow the 126-character limit of DOS command line
+ echo Creating Makefile...
+ echo # Generated automatically from Makefile.in by configdj.bat > Makefile.tmp
+ sed -e 's,@srcdir@,%XSRC%,g' %XSRC%/Makefile.in >> Makefile.tmp
+ sed -f %XSRC%/configdj.sed Makefile.tmp > Makefile
+ if exist Makefile.tmp del Makefile.tmp
+ 
+ Rem install-sh looks like install-info under 8+3 DOS namespace,
+ Rem and INSTALL looks like install because of case-insensitivity
+ Rem This will bite them if they say "make install" or "make install-info"
+ Rem because Make will think these targets are up to date.
+ if exist install ren INSTALL INSTALL.txt
+ if exist install-info ren install-sh install-sh.sh
+ 
+ Rem We are done
+ echo Done.
+ Goto Exit
+ 
+ :NoSed
+ echo You need GNU Sed to configure cpio for DJGPP.
+ Goto Exit
+ 
+ :SmallEnv
+ echo Your environment size is too small.  Enlarge it and run me again.
+ 
+ :Exit

*** /dev/null	Sat Oct 25 19:01:57 1997
--- configdj.inc	Fri Oct 24 22:28:38 1997
***************
*** 0 ****
--- 1,21 ----
+ /* -*- C -*-
+ 
+  This file is included when CPIO is compiled with DJGPP v2,
+  which makes the command lines shorter and easier to read.
+  (Most of things are defined on a system header anyway.)  */
+ 
+ #include <sys/config.h>
+ 
+ /* We don't suppor remote tapes (yet).  */
+ #define NO_REMOTE 1
+ 
+ /* cpio will use `chown' which we have  */
+ #undef HAVE_LCHOWN
+ 
+ /* __MSDOS__ is used throughout the sources to disable too much
+    of the functionality, probably because of the old 16-bit compilers
+    used to port CPIO.  We don't need to be that conservative with
+    DJGPP v2, but I cannot be bothered to change too much of the
+    official source code, or to make DJGPP-specific changes (marked by
+    #ifdef __DJGPP__) work with all other DOS compilers.  */
+ #undef __MSDOS__

*** /dev/null	Sat Nov  1 15:05:34 1997
--- README.djgpp	Sat Nov  1 15:00:24 1997
***************
*** 0 ****
--- 1,132 ----
+ 		 GNU `cpio' v2.4.2 ported to DJGPP v2
+ 		 ------------------------------------
+ 
+ A.  Installation of the binary distribution
+     ---------------------------------------
+ 
+     1. Unzip the distribution preserving the directory structure (-d
+        switch if you use PKUNZIP).  On Windows 9X use an unzip program
+        which supports long file names.
+ 
+     2. Edit your info/dir file and add this line to the main menu:
+ 
+        * cpio: (cpio).                 Making tape (or disk) archives.
+ 
+        Note that there should be no whitespace between the `*' and the
+        left margin of the file `dir'.  It is present above only to
+        align it with the text of this README file.
+ 
+     3. If you are familiar with `cpio', either on Unix or previous
+        ports on DOS, I suggest you read the ``Features'' section
+        below.
+ 
+ 
+ B.  Building `cpio' from sources
+     ----------------------------
+ 
+     1. Apart of the standard DJGPP development environment, you will
+        need the following tools:
+ 
+ 	   - GNU Make 3.75 or later (I used Make 3.76.1);
+ 	   - `touch' from GNU Fileutils.
+ 
+        If you need to reconfigure the package (see below), you will
+        need a port of GNU Sed (I used Sed 1.18).
+ 
+        The `install:' target requires a Unix-style shell (use the
+        DJGPP port of Bash) and `ginstall' from GNU Fileutils.
+        Installation is easy, so you might as well do it by hand if
+        your system doesn't have Bash.
+ 
+        All of the above tools should be available from the usual DJGPP
+        archives.
+ 
+     2. Unzip the source distribution from the top of your DJGPP
+        installation tree.  Make sure to preserve the directory
+        structure (-d switch if you use PKUNZIP).  On Windows 9X use an
+        unzip program which supports long file names.
+ 
+     3. The package comes already configured for DJGPP v2.01, so to
+        compile it from the `cpio' source directory, you need only to
+        run Make.  Change to the directory gnu/cpio-2.4-2, and type
+        "make [Enter]".  This will build `cpio.exe' (`mt' and `rmt' are
+        not ported, so they are not built).
+ 
+     4. If you need to build `cpio' from another directory, or with
+        another DJGPP version, you will need to reconfigure the package
+        before compiling it.  To this end, you will have to run the
+        configdj.bat batch file.  (If the reason for reconfiguration is
+        something other than building `cpio' from another directory,
+        you might also need to edit `configdj.sed' script and
+        configdj.inc include file.)  configdj.bat needs the `cpio'
+        source directory as its single argument, like this:
+ 
+ 	      e:\gnu\cpio-2.4-2\configdj e:/gnu/cpio-2.4-2
+ 
+        Note the forward slashes in the argument: you MUST use them.
+ 
+        If you are configuring from the `cpio' source directory, you
+        can omit the argument and run the batch file simply like this:
+ 
+ 	      configdj
+ 
+     5. After this, run Make as above.
+ 
+ 
+ C.  Features
+     --------
+ 
+     I believe this port supports all the features of the original GNU
+     package that can at all be supported on DOS.  The single most
+     important feature that is NOT supported is remote archives.
+ 
+     Here's the list of improvements and bugfixes in this port:
+ 
+     1.  DOS absolute pathnames in cpio archives are fully supported.
+ 
+     2.  Automatic renaming of illegal names and names reserved by DOS
+ 	character devices.  Files like `.emacs', `foo.bar.baz' etc.
+ 	are now automatically renamed to names that DOS allows.  File
+ 	names that are reserved by DOS character device drivers, such
+ 	as `prn.txt' and `aux.c' are renamed by prepending an
+ 	underscore.  Under verbose operation (-v option), `cpio' will
+ 	print a message when it renames these files.
+ 
+     3.  Support for links in archives created on systems which have
+         them.  Both hard and symbolic links are extracted by copying
+         the file they are linked to (if it exists).
+ 
+     4.  When -m is used and cpio creates a directory, the error
+ 	message now explicitly tells that directory time cannot be
+ 	set, instead of the confusing ``Access denied''.
+ 
+     5.  When cpio is not allowed to create directories, the error
+ 	message now mentions the parent directory, not the file
+ 	itself.  Saying ``foo: No such file or directory'' when trying
+ 	to extract `foo' is confusing, since the user knows the file
+ 	doesn't exist.
+ 
+     6.	Support for multi-volume archives on regular files (full
+ 	floppy).  The original code only supported this for archives
+ 	written directly to devices, which is disabled in the DOS
+ 	port.
+ 
+     7.  File times comparisons work correctly when times are truncated
+ 	by DOS to the nearest even second.  The original code would
+ 	sometimes extract files even though they were already
+ 	extracted from the same archive.
+ 
+     8.	Documentation updated with DOS-specific info, and several
+ 	errors and typos in the docs were corrected.
+ 
+     9.  Numeric UIDs and GIDs are now supported.  The -n option now
+         prints the numeric IDs with -t, and -R option is now accepted
+         and silently ignored under copy-in and copy-pass operations.
+         -t option now will print the user and group names, instead of
+         always printing their numeric IDs.
+ 
+     10. Backslashes in file names are supported (but converted to
+         forward slashes before writing the archive).  As a result,
+         archives created on Unix with files which use backslashes to
+         quote special characters will be extracted correctly.
+ 
