2015-12-24  Juan Manuel Guerrero  <juan.guerrero@gmx.de>

	* lib/rename.c (rpl_rename): For DJGPP use wrapper function for rename.


2015-12-23  Juan Manuel Guerrero  <juan.guerrero@gmx.de>

	* lib/backupfile.c (check_extension) [HAVE_DOS_FILE_NAMES]: Support
	for numbered backups for SFN systems like DOS.
	(numbered_backup): Support for numbered backups for SFN systems like
	DOS.
	(numbered_backup) [HAVE_DOS_FILE_NAMES]: If no LFN support is available,
	create a valid short file name from the backup file name before checking
	if it is a valid file name in the directory by calling check_extension.

	* lib/quotearg.c: New macros defined.  DJGPP specific definitions are
	provided by config.h.  If not defined DEFAULT_OS_QUOTING_STYLE defaults
	to "shell_quoting_style" and DEFAULT_OS_QUOTING_STYLE_DCL to empty.
	Add "dos-shell" and "nt-shell" to quoting_style_args.
	(set_quoting_style): Set quoting style to DEFAULT_OS_QUOTING_STYLE.
	(quotearg_buffer_restyled): Quote DJGPP and DOS specific characters
	"'", "." and "%".

	* lib/quotearg.h: Add default_quoting_style, dos_shell_quoting_style
	and nt_shell_quoting_style to quoting_style.
	[DEFAULT_QUOTING_STYLE]: If not defined define DEFAULT_QUOTING_STYLE
	to default_quoting_style.

	* lib/unlink.c (rpl_unlink): For DJGPP use wrapper function for unlink.

	* pc/pc_quote.c: DJGPP/DOS specific file handling the quoting flavor of
	the different kind of supported shells.  These are ndos.com, 4dos.com,
	cmd.exe, command.com and bash.exe.

	* pc/pc_inode.c (create_inode): New function.  Creates an entry for a
	given file name in the inode_table array storing the file name and is
	currently associated file descriptor.  The array index is used as the
	unique st_ino value for this file during runtime.  An array entry is
	never deleted during runtime, so its index can be used as a unique and
	persistent st_ino value.
	(get_inode): New function.  If it finds an entry for the given file
	descriptor in the inode_table array, it returns the array index as
	inode number else -1.
	(reset_descriptor): New function.  If it finds the file descriptor in
	the inode_table array, its set the corresponding file descriptor entry
	to -1.
	(open_wrapper):  New function.  Calls libc open() function and creates
	an entry in inode_table for the given file name and descriptor calling
	create_node.  If an entry already exists for the file name only the
	descriptor is stored.
	(close_wrapper):  New function.  Calls libc close() function and resets
	the descriptor value for the file name entry in inode_tabler calling
	reset_descriptor.
	(stat_wrapper):  New function.  Calls libc stat() function and creates
	an entry in inode_table for the given file name calling create_node.
	If an entry already exists for the file name only the descriptor is
	reset to -1.
	(fstat_wrapper):  New function.  Calls libc fstat() function and sets
	the inode number for that file descriptor calling get_inode.  If no
	inode number is returned by get_inode, the original is left unaltered.
	(lstat_wrapper):  New function.  Calls libc lstat() function and creates
	an entry in inode_table for the given file name calling create_node.
	If an entry already exists for the file name only the descriptor is
	reset to -1.
	(resolve_symlink): New function.  For DJGPP 2.04 this function resolves
	the symlink name to its real file name.  To this file name, later the
	unique st_ino and file descriptor is assigned.
	(djgpp_wrapper_stat): Use resolve_symlink to get real file name from
	link file before creating the unique st_ino and file descriptor for
	the file.
	(djgpp_wrapper_lstat): Ditto.
	(djgpp_wrapper_open): Ditto.
	(djgpp_wrapper_fopen): Ditto.
	New macro MAP_S_IFREG.  It maps the S_IFREG value from 0x0000 to 0x6000.
	This is necessary so the file mode becomes different from zero for
	regular files.
	(djgpp_wrapper_stat): Use MAP_S_IFREG to adjust S_IFREG if necessary.
	(djgpp_wrapper_fstat): Ditto.
	(djgpp_wrapper_lstat): Ditto.
	(replace_inode): Removes the destination inode table entry and replaces
	it with the source inode table entry.  This entry gets assigned the file
	name of the destination inode table entry.
	(djgpp_wrapper_rename): New function.  Calls libc rename() function,
	removes the destination inode table entry by the source one and assigns
	it the destination file name.
	(remove_inode): Removes the inode table entry corresponding to the
	file name.
	(djgpp_wrapper_unlink): New function.  Calls libc unlink() function
	and removes the inode table entry corresponding to the file name.

	* src/common.h [HAVE_SETMODE_DOS]: Include io.h to provide the function
	prototype of setmode.
	[DJGPP]: New macros HAVE_LFN_SUPPORT, CANONICALIZE_PATH, MAP_FILE_TYPE,
	IS_SLASH and STRIP_EXTENSION defined.  For all other systems these are
	no-ops.
	[DJGPP]: Move HAVE_LFN_SUPPORT macro to config.h.  For all other systems
	the macro definition remains here.

	* src/patch.c (main): Use STRIP_EXTENSION to strip the extension from
	argv[0].
	(main): Use macro DEFAULT_QUOTING_STYLE instead of default UNIX shell
	quoting style.

	* src/pch.c (fetchmode): Use MAP_FILE_TYPE to map linux file modes
	to DJGPP file modes.  This is necessary to identify symlinks in git
	style patches.

	* src/util.c [FILESYSTEM_BACKSLASH_IS_FILE_NAME_SEPARATOR]: If defined
	use P_tmpdir as TMPDIR value, if not default to "c:".
	[__DJGPP__]: New macro DIR_EXISTS.
	(make_tempfile): Check that tmpdir exists before using it.
	(set_file_attributes) [HAVE_RAW_DECL_LCHOWN]: Use lchown only if
	HAVE_RAW_DECL_LCHOWN is defined.
	(stat_file): For DJGPP use wrapper functions for stat and lstat.
	(make_tempfile): Make temp file name dependent from result of HAVE_LFN_SUPPORT.








diff -aprNU5 patch-2.7.5.orig/lib/backupfile.c patch-2.7.5/lib/backupfile.c
--- patch-2.7.5.orig/lib/backupfile.c	2015-01-29 19:19:26 +0100
+++ patch-2.7.5/lib/backupfile.c	2015-12-24 13:26:38 +0100
@@ -117,11 +117,85 @@ check_extension (char *file, size_t file
     }
 
   if (HAVE_DOS_FILE_NAMES && baselen_max <= 12)
     {
       /* Live within DOS's 8.3 limit.  */
-      char *dot = strchr (base, '.');
+      char *dot, *ext = base + filelen;
+      size_t extlen = baselen - filelen;  /* Including leading dot and discarding terminating zero.  */
+
+      for (dot = ext - 1; *dot != '.' && dot > base; dot--)
+        ;
+
+      if (dot > base)
+      {
+#define EXT_PART_PART_LEN  3
+
+        /* DOS doesn't allow more than a single dot.  */
+        ext++;
+        extlen--;
+
+        /* If EXT is "~N~" and there's not enough space to append it,
+           lose the leading `~' so that we could salvage more of the
+           original name ("foo.c" + ".~9~" -> "foo.c9~" or
+           "bar.txt" + ".~12~" -> "bar.12~").  */
+        if (*ext == '~')
+        {
+          ext++;
+          extlen--;
+        }
+
+        if (extlen < EXT_PART_PART_LEN + 2)
+        {
+          memcpy(dot + 1 + EXT_PART_PART_LEN - extlen, ext, extlen + 1);
+          return;
+        }
+
+#undef EXT_PART_PART_LEN
+      }
+      else
+      {
+#define BASE_PART_LEN  8
+
+        if (ext[1] == '~')
+        {
+          ext++;
+          extlen--;
+        }
+
+        if (extlen < 5)
+        {
+          /* If the file has no extension and the back up extension,
+             after removing the leading tilde, fits in the 3 characters
+             long extension append it to the base part of the file name.
+             E.g.:  "foobar" + "~12~" -> "foobar.12~".  */
+
+          memcpy(ext, ext + 1, extlen);
+          return;
+        }
+
+        if (extlen > 4 && BASE_PART_LEN - (extlen - 1) > 0)
+        {
+          /* If the file has no extension and the back up extension
+             is larger than 3 characters, use the base part of the
+             file name.  The first file name character is always retained.
+             If this is not possible give up.
+             E.g.:  "foobar" + "~123456~" -> "f123456~".  */
+
+          size_t base_offset, diff = filelen + extlen - 1 - BASE_PART_LEN;  /*  one more for the terminating zero.  */
+
+          if (*ext == '~')
+            ext++;
+          base_offset = diff > 0 ? filelen - diff : filelen;
+          memcpy(base + base_offset, ext, extlen);
+          return;
+        }
+
+        dot = NULL;
+
+#undef  BASE_PART_LEN
+      }
+
       if (!dot)
         baselen_max = 8;
       else
         {
           char const *second_dot = strchr (dot + 1, '.');
@@ -190,25 +264,67 @@ numbered_backup (char **buffer, size_t b
   strcpy (base + baselen, ".~1~");
 
   if (!dirp)
     return result;
 
+#if HAVE_DOS_FILE_NAMES
+  /*
+   *  Under DOS 8+3 file name limitations,
+   *  multiple dots in file name are not allowed
+   *  and the backup extensions may consume
+   *  part of the original name.  It is necessary
+   *  to adjust the backup file name to this
+   *  limitations before testing if the backup
+   *  file name is valid.
+   */
+  if (!HAVE_LFN_SUPPORT(base))
+    check_extension (base, baselen, '~');
+#endif /*  HAVE_DOS_FILE_NAMES  */
+
   while ((dp = readdir (dirp)) != NULL)
     {
       char const *p;
       char *q;
-      bool all_9s;
+      bool all_9s, names_are_different;
       size_t versionlen;
       size_t new_buflen;
+      size_t i;
 
-      if (! REAL_DIR_ENTRY (dp) || _D_EXACT_NAMLEN (dp) < baselen + 4)
+      if (! REAL_DIR_ENTRY (dp)
+	  /* Under DOS 8+3 file name limits, backup extensions
+	     may consume part of the original name.  */
+	  || (! HAVE_DOS_FILE_NAMES && _D_EXACT_NAMLEN (dp) < baselen + 4)
+	  || _D_EXACT_NAMLEN (dp) < baselen)
         continue;
 
+#if HAVE_DOS_FILE_NAMES
+      q = buf + base_offset;
+      for (names_are_different = false, i = 0; i < baselen; i++)
+        if (!filename_char_eq(q[i], dp->d_name[i]))
+        {
+          names_are_different = true;
+          break;
+        }
+      if (names_are_different)
+        continue;
+
+      /* The case "foobar.txt" vs "foobar.12~".  */
+      if (q[i] == '.' && dp->d_name[i] == '.')
+      {
+        if (i++, q[i] == '~' && dp->d_name[i] == '~')
+          p = dp->d_name + baselen + 2;
+        else
+          p = dp->d_name + baselen + 1;
+      }
+      else
+        continue;
+#else  /*  !HAVE_DOS_FILE_NAMES  */
       if (memcmp (buf + base_offset, dp->d_name, baselen + 2) != 0)
         continue;
 
       p = dp->d_name + baselen + 2;
+#endif /*  !HAVE_DOS_FILE_NAMES  */
 
       /* Check whether this file has a version number and if so,
          whether it is larger.  Use string operations rather than
          integer arithmetic, to avoid problems with integer overflow.  */
 
diff -aprNU5 patch-2.7.5.orig/lib/quotearg.c patch-2.7.5/lib/quotearg.c
--- patch-2.7.5.orig/lib/quotearg.c	2015-01-29 19:19:26 +0100
+++ patch-2.7.5/lib/quotearg.c	2015-12-24 13:26:38 +0100
@@ -40,10 +40,18 @@
 #include <stdlib.h>
 #include <string.h>
 #include <wchar.h>
 #include <wctype.h>
 
+#ifndef DEFAULT_OS_QUOTING_STYLE
+# define DEFAULT_OS_QUOTING_STYLE shell_quoting_style
+#endif
+
+#ifdef DEFAULT_OS_QUOTING_STYLE_DCL
+ DEFAULT_OS_QUOTING_STYLE_DCL
+#endif
+
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
 #define N_(msgid) msgid
 
 #ifndef SIZE_MAX
@@ -80,10 +88,12 @@ char const *const quoting_style_args[] =
   "c",
   "c-maybe",
   "escape",
   "locale",
   "clocale",
+  "dos-shell",
+  "nt-shell",
   0
 };
 
 /* Correspondences to quoting style names.  */
 enum quoting_style const quoting_style_vals[] =
@@ -124,10 +134,12 @@ get_quoting_style (struct quoting_option
 /* In O (or in the default if O is null),
    set the value of the quoting style to S.  */
 void
 set_quoting_style (struct quoting_options *o, enum quoting_style s)
 {
+  if (s == default_quoting_style)
+    s = DEFAULT_OS_QUOTING_STYLE;
   (o ? o : &default_quoting_options)->style = s;
 }
 
 /* In O (or in the default if O is null),
    set the value of the quoting options for character C to I.
@@ -334,10 +346,14 @@ quotearg_buffer_restyled (char *buffer,
 
     case literal_quoting_style:
       elide_outer_quotes = false;
       break;
 
+    case dos_shell_quoting_style:
+    case nt_shell_quoting_style:
+      break;
+
     default:
       abort ();
     }
 
   for (i = 0;  ! (argsize == SIZE_MAX ? arg[i] == '\0' : i == argsize);  i++)
@@ -487,10 +503,13 @@ quotearg_buffer_restyled (char *buffer,
                 goto force_outer_quoting_style;
               STORE ('\'');
               STORE ('\\');
               STORE ('\'');
             }
+	  else if ((quoting_style == dos_shell_quoting_style) ||
+	           (quoting_style == nt_shell_quoting_style))
+		goto force_outer_quoting_style;
           break;
 
         case '%': case '+': case ',': case '-': case '.': case '/':
         case '0': case '1': case '2': case '3': case '4': case '5':
         case '6': case '7': case '8': case '9': case ':':
@@ -511,10 +530,23 @@ quotearg_buffer_restyled (char *buffer,
              imagine any locale that would use digits or letters as
              quotes, and set_custom_quoting is documented not to accept
              them.  Also, a digit or a special letter would cause
              trouble if it appeared in quote_these_too, but that's also
              documented as not accepting them.  */
+	  switch (c)
+	    {
+	    case '.': /* `...': special in DJGPP wildcard expansion */
+	      if (quoting_style != shell_quoting_style
+	          && arg[i + 1] == '.' && arg[i + 2] == '.'
+	          && strchr ("\\/", arg[i + 3]))
+	        goto force_outer_quoting_style;
+	      break;
+	    case '%':
+	      if (quoting_style == dos_shell_quoting_style)  /* need to double it under DOS shells */
+	        STORE (c);
+	      break;
+	    }
           break;
 
         default:
           /* If we have a multibyte sequence, copy it until we reach
              its end, find an error, or come back to the initial shift
diff -aprNU5 patch-2.7.5.orig/lib/quotearg.h patch-2.7.5/lib/quotearg.h
--- patch-2.7.5.orig/lib/quotearg.h	2015-01-29 19:19:26 +0100
+++ patch-2.7.5/lib/quotearg.h	2015-12-24 13:26:38 +0100
@@ -29,10 +29,12 @@
    style and the default flags and quoted characters.  Note that the
    examples are shown here as valid C strings rather than what
    displays on a terminal (with "??/" as a trigraph for "\\").  */
 enum quoting_style
   {
+    default_quoting_style,	/* --quoting-style=default */
+
     /* Output names as-is (ls --quoting-style=literal).  Can result in
        embedded null bytes if QA_ELIDE_NULL_BYTES is not in
        effect.
 
        quotearg_buffer:
@@ -110,10 +112,14 @@ enum quoting_style
        quotearg_colon:
        "simple", "\\0 \\t\\n'\"\\033??/\\\\", "a\\:b"
     */
     escape_quoting_style,
 
+    dos_shell_quoting_style,	/* --quoting-style=dos-shell */
+
+    nt_shell_quoting_style,	/* --quoting-style=nt-shell */
+
     /* Like clocale_quoting_style, but use single quotes in the
        default C locale or if the program does not use gettext
        (ls --quoting-style=locale).  For UTF-8 locales, quote
        characters will use Unicode.
 
@@ -227,11 +233,11 @@ enum quoting_flags
     QA_SPLIT_TRIGRAPHS = 0x04
   };
 
 /* For now, --quoting-style=literal is the default, but this may change.  */
 # ifndef DEFAULT_QUOTING_STYLE
-#  define DEFAULT_QUOTING_STYLE literal_quoting_style
+#  define DEFAULT_QUOTING_STYLE default_quoting_style
 # endif
 
 /* Names of quoting styles and their corresponding values.  */
 extern char const *const quoting_style_args[];
 extern enum quoting_style const quoting_style_vals[];
diff -aprNU5 patch-2.7.5.orig/lib/rename.c patch-2.7.5/lib/rename.c
--- patch-2.7.5.orig/lib/rename.c	2015-01-29 19:19:26 +0100
+++ patch-2.7.5/lib/rename.c	2015-12-24 13:34:12 +0100
@@ -325,11 +325,15 @@ rpl_rename (char const *src, char const
 # if !RENAME_HARD_LINK_BUG && !RENAME_DEST_EXISTS_BUG
   /* If there are no trailing slashes, then trust the native
      implementation unless we also suspect issues with hard link
      detection or file/directory conflicts.  */
   if (!src_slash && !dst_slash)
+#ifdef __DJGPP__
+    return djgpp_wrapper_rename (src, dst);
+#else
     return rename (src, dst);
+#endif
 # endif /* !RENAME_HARD_LINK_BUG && !RENAME_DEST_EXISTS_BUG */
 
   /* Presence of a trailing slash requires directory semantics.  If
      the source does not exist, or if the destination cannot be turned
      into a directory, give up now.  Otherwise, strip trailing slashes
@@ -458,11 +462,15 @@ rpl_rename (char const *src, char const
           goto out;
         }
     }
 # endif /* RENAME_DEST_EXISTS_BUG */
 
+#ifdef __DJGPP__
+  ret_val = djgpp_wrapper_rename (src_temp, dst_temp);
+#else
   ret_val = rename (src_temp, dst_temp);
+#endif
   rename_errno = errno;
 
  out: _GL_UNUSED_LABEL;
 
   if (src_temp != src)
diff -aprNU5 patch-2.7.5.orig/lib/unlink.c patch-2.7.5/lib/unlink.c
--- patch-2.7.5.orig/lib/unlink.c	2015-01-29 19:19:26 +0100
+++ patch-2.7.5/lib/unlink.c	2015-12-24 13:26:38 +0100
@@ -89,9 +89,13 @@ rpl_unlink (char const *name)
         {
           errno = EISDIR; /* could also use EPERM */
           return -1;
         }
 #endif
+#ifdef __DJGPP__
+      result = djgpp_wrapper_unlink (name);
+#else
       result = unlink (name);
+#endif
     }
   return result;
 }
diff -aprNU5 patch-2.7.5.orig/pc/pc_inode.c patch-2.7.5/pc/pc_inode.c
--- patch-2.7.5.orig/pc/pc_inode.c	1970-01-01 01:00:00 +0100
+++ patch-2.7.5/pc/pc_inode.c	2015-12-24 15:22:56 +0100
@@ -0,0 +1,462 @@
+/* pc_inode.c - assign the same unique st_ino to a file name
+   and its file descriptor.
+   If the file is a symlink, it is resolved and the unique st_ino and fd
+   is always assigned to the real file name only.
+   Copyright (C) 2010-2013 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+/* Written by Juan M. Guerrero <juan.guerrero@gmx.de>,  2010-05-08.  */
+
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#if __DJGPP__ == 2 && __DJGPP_MINOR__ > 3
+# include <libc/symlink.h>
+#endif
+
+
+#if defined (__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8))
+# define __gnuc_extension__  __extension__
+#else
+# define __gnuc_extension__
+#endif
+
+#define MAP_S_IFREG(file_type)               \
+ (__gnuc_extension__                         \
+   ({                                        \
+      if (((file_type) & S_IFMT) == 0x0000)  \
+        (file_type) |= S_IFREG;              \
+      (file_type);                           \
+   })                                        \
+ )
+
+
+void *xmalloc(size_t size);
+void *xfree(void *pointer);
+
+typedef struct inode_table_entry_tag *entry_ptr;
+typedef struct inode_table_entry_tag {
+  ino_t      inode_number;
+  int        fd;
+  char      *file_name;
+  entry_ptr  next_inode;
+} inode_table_entry;
+
+static entry_ptr first_inode = NULL;
+
+
+const char *resolve_symlink(const char *link_name)
+{
+#if __DJGPP__ == 2 && __DJGPP_MINOR__ > 3
+  char *name = xmalloc(FILENAME_MAX * sizeof(char));
+  const char *file_name = link_name;
+  const int previous_errno = errno;
+
+
+  if (__solve_symlinks(link_name, name))
+    file_name = name;
+  else
+    xfree(name);
+  errno = previous_errno;
+
+  return file_name;
+#else
+  return link_name;
+#endif
+}
+
+
+ino_t create_inode(const char *file_name, const int fd)
+{
+  int length;
+  bool file_name_found;
+  entry_ptr last_inode, inode;
+
+
+  if (!first_inode)
+  {
+    first_inode = xmalloc(sizeof(inode_table_entry));
+    first_inode->inode_number = 0;
+    first_inode->fd = -1;
+    first_inode->file_name = NULL;
+    first_inode->next_inode = NULL;
+  }
+  inode = first_inode;
+
+
+  /*
+   *  Check if file name has already been registred.
+   */
+  for (file_name_found = true, last_inode = inode; inode && inode->file_name; last_inode = inode, inode = inode->next_inode, file_name_found = true)
+  {
+    int i;
+
+    for (i = 0; inode->file_name[i] && file_name[i]; i++)
+      if (!filename_char_eq(inode->file_name[i], file_name[i]))
+      {
+        file_name_found = false;
+        break;
+      }
+
+    if (file_name_found && inode->file_name[i] == file_name[i])
+    {
+      if (inode->fd == -1)
+        inode->fd = fd;
+      return inode->inode_number;
+    }
+  }
+
+
+  /*
+   *  File name has not already been registered
+   *  so allocate a new entry in the list and
+   *  return the list index as inode number.
+   */
+  for (length = 0; file_name[length]; length++)
+    ;
+  length++;
+
+  if (!inode)
+  {
+    inode = xmalloc(sizeof(inode_table_entry));
+    last_inode->next_inode = inode;
+  }
+  inode->next_inode = NULL;
+  inode->inode_number = last_inode->inode_number + 1;
+  inode->fd = fd;
+  inode->file_name = xmalloc(length * sizeof(char));
+  memcpy(inode->file_name, file_name, length);
+ 
+  return inode->inode_number;
+}
+
+
+ino_t get_inode(const int fd)
+{
+  entry_ptr inode;
+
+
+  for (inode = first_inode; inode; inode = inode->next_inode)
+    if (inode->fd == fd)
+      return inode->inode_number;
+
+  return (ino_t)(-1);
+}
+
+
+void replace_inode(const char *old_name, const char *new_name)
+{
+  int length;
+  char *name = NULL;
+  bool file_name_found;
+  entry_ptr last_inode, inode;
+
+
+  /*
+   *  If new name has been registred, delete its inode entry from the table.
+   */
+  for (last_inode = inode = first_inode; inode && inode->file_name; last_inode = inode, inode = inode->next_inode)
+  {
+    int i;
+
+    for (file_name_found = true, i = 0; inode->file_name[i] && new_name[i]; i++)
+      if (!filename_char_eq(inode->file_name[i], new_name[i]))
+      {
+        file_name_found = false;
+        break;
+      }
+
+    if (file_name_found && inode->file_name[i] == new_name[i])
+    {
+      if (last_inode == inode)
+        first_inode = inode->next_inode;
+      else
+        last_inode->next_inode = inode->next_inode;
+      name = inode->file_name;
+      xfree(inode);
+      break;
+    }
+  }
+
+
+  /*
+   *  If old name has been registred, rename it to new name.
+   */
+  for (file_name_found = true, last_inode = inode = first_inode; inode && inode->file_name; last_inode = inode, inode = inode->next_inode, file_name_found = true)
+  {
+    int i;
+
+    for (i = 0; inode->file_name[i] && old_name[i]; i++)
+      if (!filename_char_eq(inode->file_name[i], old_name[i]))
+      {
+        file_name_found = false;
+        break;
+      }
+
+    if (file_name_found && inode->file_name[i] == old_name[i])
+    {
+      xfree(inode->file_name);
+
+      if (name)
+        inode->file_name = name;
+      else
+      {
+        int length;
+
+        for (length = 0; new_name[length]; length++)
+         ;
+        length++;
+
+        inode->file_name = xmalloc(length * sizeof(char));
+        memcpy(inode->file_name, new_name, length);
+      }
+
+      return;
+    }
+  }
+
+  /*
+   *  New name has not already been registered
+   *  so allocate a new entry in the list for it.
+   */
+  for (length = 0; new_name[length]; length++)
+    ;
+  length++;
+
+  inode = xmalloc(sizeof(inode_table_entry));
+  inode->next_inode = NULL;
+  inode->inode_number = last_inode->inode_number + 1;
+  inode->fd = -1;
+  inode->file_name = xmalloc(length * sizeof(char));
+  memcpy(inode->file_name, new_name, length);
+
+  last_inode->next_inode = inode;
+}
+
+
+void remove_inode(const char *file_name)
+{
+  bool file_name_found;
+  entry_ptr last_inode, inode;
+
+
+  for (last_inode = inode = first_inode; inode && inode->file_name; last_inode = inode, inode = inode->next_inode)
+  {
+    int i;
+
+    for (file_name_found = true, i = 0; inode->file_name[i] && file_name[i]; i++)
+      if (!filename_char_eq(inode->file_name[i], file_name[i]))
+      {
+        file_name_found = false;
+        break;
+      }
+
+    if (file_name_found && inode->file_name[i] == file_name[i])
+    {
+      if (last_inode == inode)
+        first_inode = inode->next_inode;
+      else
+        last_inode->next_inode = inode->next_inode;
+      xfree(inode->file_name);
+      xfree(inode);
+      break;
+    }
+  }
+}
+
+
+void reset_descriptor(int fd)
+{
+  entry_ptr inode;
+
+
+  for (inode = first_inode; inode; inode = inode->next_inode)
+    if (inode->fd == fd)
+    {
+      inode->fd = -1;
+      return;
+    }
+}
+
+
+
+
+/*  Use DJGPP's stat function in stat_wrapper.  */
+#undef stat
+
+int djgpp_wrapper_stat(const char *file_name, struct stat *stat_buf)
+{
+  int status;
+
+
+  status = stat(file_name, stat_buf);
+  stat_buf->st_ino = create_inode(resolve_symlink(file_name), -1);
+  stat_buf->st_mode = MAP_S_IFREG(stat_buf->st_mode);
+
+  return status;
+}
+
+
+#if __DJGPP__ == 2 && __DJGPP_MINOR__ > 3
+/*  Use DJGPP's lstat function in stat_wrapper.  */
+#undef lstat
+
+int djgpp_wrapper_lstat(const char *file_name, struct stat *stat_buf)
+{
+  int status;
+
+
+  status = lstat(file_name, stat_buf);
+  stat_buf->st_ino = create_inode(resolve_symlink(file_name), -1);
+  stat_buf->st_mode = MAP_S_IFREG(stat_buf->st_mode);
+
+  return status;
+}
+#endif
+
+
+/*  Use DJGPP's fstat function in fstat_wrapper.  */
+#undef fstat
+
+int djgpp_wrapper_fstat(int fd, struct stat *stat_buf)
+{
+  int status;
+  ino_t inode_number;
+
+
+  status = fstat(fd, stat_buf);
+  if (isatty(fd))
+    return status;
+
+  if ((inode_number = get_inode(fd)) != (ino_t)(-1))
+    stat_buf->st_ino = inode_number;
+  stat_buf->st_mode = MAP_S_IFREG(stat_buf->st_mode);
+
+  return status;
+}
+
+
+/*  Use DJGPP's open function in open_wrapper.  */
+#undef open
+int open(const char *_path, int _oflag, ...);
+
+int djgpp_wrapper_open(const char *file_name, int mode, ...)
+{
+  int fd, permissions = *(&mode + 1);
+  const char *real_name = resolve_symlink(file_name);
+
+
+  fd = open(real_name, mode, permissions);
+  create_inode(real_name, fd);
+
+  return fd;
+}
+
+
+/*  Use DJGPP's close function in close_wrapper.  */
+#undef close
+int close(int _fildes);
+
+int djgpp_wrapper_close(int fd)
+{
+  int status;
+
+
+  status = close(fd);
+  reset_descriptor(fd);
+
+  return status;
+}
+
+
+/*  Use DJGPP's fopen function in fopen_wrapper.  */
+#undef fopen
+
+FILE *djgpp_wrapper_fopen(const char *file_name, const char *mode)
+{
+  FILE *fp;
+  const char *real_name = resolve_symlink(file_name);
+
+
+  fp = fopen(real_name, mode);
+  if (fp)
+    create_inode(real_name, fileno(fp));
+
+  return fp;
+}
+
+
+/*  Use DJGPP's fclose function in fclose_wrapper.  */
+#undef fclose
+
+int djgpp_wrapper_fclose(FILE *fp)
+{
+  int fd, status;
+
+
+  fd = fileno(fp);
+  status = fclose(fp);
+  reset_descriptor(fd);
+
+  return status;
+}
+
+
+/*  Use DJGPP's rename function in rename_wrapper.  */
+#undef rename
+
+int djgpp_wrapper_rename(const char *old_name, const char *new_name)
+{
+  int status;
+  const int previous_errno = errno;
+
+
+  status = rename(old_name, new_name);
+  if (!status)
+    replace_inode(old_name, new_name);
+
+  return status;
+}
+
+
+/*  Use DJGPP's unlink function in unlink_wrapper.  */
+#undef unlink
+int unlink(const char *_path);
+
+int djgpp_wrapper_unlink(const char *file_name)
+{
+  int status;
+  const int previous_errno = errno;
+
+
+  status = unlink(file_name);
+  if (!status)
+    remove_inode(file_name);
+
+  return status;
+}
diff -aprNU5 patch-2.7.5.orig/pc/pc_quote.c patch-2.7.5/pc/pc_quote.c
--- patch-2.7.5.orig/pc/pc_quote.c	1970-01-01 01:00:00 +0100
+++ patch-2.7.5/pc/pc_quote.c	2015-12-24 13:26:38 +0100
@@ -0,0 +1,105 @@
+/* pc_quote.c - quoting functions specific to PC environments
+   Copyright (C) 1998 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if HAVE_STDLIB_H
+# include <stdlib.h>
+#else
+extern char *getenv();
+#endif
+
+#if HAVE_STRING_H
+# include <string.h>
+#endif
+
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifndef F_OK
+# define F_OK 0
+#endif
+
+#include <ctype.h>
+
+#include <quotearg.h>
+#include <backupfile.h>
+#include <dirname.h>
+
+struct shell_spec {
+  const char *name;
+  const size_t name_len;
+  const enum quoting_style style;
+};
+
+#include <stdio.h>
+
+/* Determine the default quoting style suitable for the user's shell.  */
+enum quoting_style
+dos_nt_quoting (void)
+{
+  /* Environment variables used to specify the user shell.  */
+  static char const *const shell_denominators[] = {
+    "BASH", "SHELL", "COMSPEC", "ComSpec", 0
+  };
+
+  /* List of shells which don't support Unix-style shell_quoting_style.  */
+  static char const command_com[] = "COMMAND.COM";
+  static char const fordos_com[] = "4DOS.COM";
+  static char const ndos_com[] = "NDOS.COM";
+  static char const cmd_exe[] = "CMD.EXE";
+
+  static struct shell_spec const dos_nt_shells[] = {
+    {command_com, sizeof(command_com) - 1, dos_shell_quoting_style},
+    {fordos_com, sizeof(fordos_com) - 1, dos_shell_quoting_style},
+    {ndos_com, sizeof(ndos_com) - 1, dos_shell_quoting_style},
+    {cmd_exe, sizeof(cmd_exe) - 1, nt_shell_quoting_style},
+    {0, 0, 0}
+  };
+
+  const char *const *shell_to_try = shell_denominators;
+  char *shell = NULL;
+
+  while (*shell_to_try
+	 && ((shell = getenv (*shell_to_try)) == NULL
+	     /* Make sure it is indeed a name of an existing file.  */
+	     || access (shell, F_OK) == -1))
+    shell_to_try++;
+
+  if (shell)
+    {
+      char *shell_base = base_name (shell);
+      size_t shell_base_len = strlen (shell_base);
+      const struct shell_spec *try_shell;
+
+      for (try_shell = dos_nt_shells; try_shell->name; try_shell++)
+	if (shell_base_len == try_shell->name_len)
+	  {
+	    const char *s = shell_base, *p = try_shell->name;
+
+	    for ( ; *s && *p && filename_char_eq (*s, *p); s++, p++)
+	      ;
+	    if (*s == '\0' && *p == '\0')
+	      return try_shell->style;
+	  }
+    }
+
+  /* All other shells are assumed to be Unix-like.  */
+  return shell_quoting_style;
+}
diff -aprNU5 patch-2.7.5.orig/src/common.h patch-2.7.5/src/common.h
--- patch-2.7.5.orig/src/common.h	2015-02-28 17:02:30 +0100
+++ patch-2.7.5/src/common.h	2015-12-24 13:26:38 +0100
@@ -174,10 +174,11 @@ extern int errno;
 #endif
 
 #include <fcntl.h>
 
 #ifdef HAVE_SETMODE_DOS
+# include <io.h>		/* Function prototype of setmode */
   XTERN int binary_transput;	/* O_BINARY if binary i/o is desired */
 #else
 # define binary_transput 0
 #endif
 
@@ -216,5 +217,73 @@ XTERN enum conflict_style conflict_style
 
 bool merge_hunk (int hunk, struct outstate *, lin where, bool *);
 #else
 # define merge_hunk(hunk, outstate, where, somefailed) false
 #endif
+
+#ifdef __DJGPP__
+# if defined (__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8))
+#  define __gnuc_extension__  __extension__
+# else
+#  define __gnuc_extension__
+# endif
+
+# undef  IS_DIR_SEPARATOR
+# define IS_DIR_SEPARATOR(c)  ((c) == '/' || (c) == '\\' || (c) == ':')
+# include <libc/unconst.h>
+# define STRIP_EXTENSION(filename)                           \
+  (__gnuc_extension__                                        \
+    ({                                                       \
+       char *_begin, *_end;                                  \
+       _begin = _end = unconst((filename), char *);          \
+       while (*_end++)                                       \
+         ;                                                   \
+       while ((_end - _begin) && (*--_end != '.'))           \
+         ;                                                   \
+       if (*_end == '.')                                     \
+         *_end = '\0';                                       \
+       (filename);                                           \
+    })                                                       \
+  )
+# define CANONICALIZE_PATH(path)                             \
+  (__gnuc_extension__                                        \
+    ({                                                       \
+       if ((path))                                           \
+       {                                                     \
+         char *_p = unconst((path), char *);                 \
+         for (; *_p; _p++)                                   \
+           if (*_p == '\\')                                  \
+             *_p = '/';                                      \
+       }                                                     \
+       (path);                                               \
+    })                                                       \
+  )
+
+/* Map linux file type to DJGPP file type.  */
+# define MAP_FILE_TYPE(type)                                 \
+  (__gnuc_extension__                                        \
+    ({                                                       \
+       __typeof__(type) linux_type = (type);                 \
+       __typeof__(type) djgpp_type = (type);                 \
+                                                             \
+       if (linux_type & __S_IFMT)                            \
+       {                                                     \
+         djgpp_type &= 0777U;                                \
+         if (___S_ISUID(linux_type)) djgpp_type |= S_ISUID;  \
+         if (___S_ISGID(linux_type)) djgpp_type |= S_ISGID;  \
+                                                             \
+         if (__S_ISBLK(linux_type))  djgpp_type |= S_IFBLK;  \
+         if (__S_ISCHR(linux_type))  djgpp_type |= S_IFCHR;  \
+         if (__S_ISDIR(linux_type))  djgpp_type |= S_IFDIR;  \
+         if (__S_ISIFO(linux_type))  djgpp_type |= S_IFIFO;  \
+         if (__S_ISREG(linux_type))  djgpp_type |= S_IFREG;  \
+         if (__S_ISLNK(linux_type))  djgpp_type |= S_IFLNK;  \
+       }                                                     \
+       djgpp_type;                                           \
+    })                                                       \
+  )
+#else
+# define STRIP_EXTENSION(filename)  (filename)
+# define CANONICALIZE_PATH(path)    (path)
+# define HAVE_LFN_SUPPORT(name)     (1)
+# define MAP_FILE_TYPE(type)        (type)
+#endif
diff -aprNU5 patch-2.7.5.orig/src/patch.c patch-2.7.5/src/patch.c
--- patch-2.7.5.orig/src/patch.c	2015-03-07 01:34:20 +0100
+++ patch-2.7.5/src/patch.c	2015-12-24 13:26:38 +0100
@@ -120,11 +120,11 @@ main (int argc, char **argv)
     mode_t file_type;
     int outfd = -1;
     bool have_git_diff = false;
 
     exit_failure = 2;
-    set_program_name (argv[0]);
+    program_name = STRIP_EXTENSION(argv[0]);
     init_time ();
 
     setbuf(stderr, serrbuf);
 
     bufsize = 8 * 1024;
@@ -134,11 +134,11 @@ main (int argc, char **argv)
 
     val = getenv ("QUOTING_STYLE");
     {
       int i = val ? argmatch (val, quoting_style_args, 0, 0) : -1;
       set_quoting_style ((struct quoting_options *) 0,
-			 i < 0 ? shell_quoting_style : (enum quoting_style) i);
+			 i < 0 ? DEFAULT_QUOTING_STYLE : (enum quoting_style) i);
     }
 
     posixly_correct = getenv ("POSIXLY_CORRECT") != 0;
     backup_if_mismatch = ! posixly_correct;
     patch_get = ((val = getenv ("PATCH_GET"))
diff -aprNU5 patch-2.7.5.orig/src/pch.c patch-2.7.5/src/pch.c
--- patch-2.7.5.orig/src/pch.c	2015-03-07 01:34:20 +0100
+++ patch-2.7.5/src/pch.c	2015-12-24 13:26:38 +0100
@@ -346,11 +346,11 @@ fetchmode (char const *str)
 
     /* NOTE: The "diff --git" format always sets the file mode permission
        bits of symlinks to 0.  (On Linux, symlinks actually always have
        0777 permissions, so this is not even consistent.)  */
 
-   return mode;
+   return MAP_FILE_TYPE(mode);
 }
 
 static void
 get_sha1(char **sha1, char const *start, char const *end)
 {
diff -aprNU5 patch-2.7.5.orig/src/util.c patch-2.7.5/src/util.c
--- patch-2.7.5.orig/src/util.c	2015-03-07 01:34:20 +0100
+++ patch-2.7.5/src/util.c	2015-12-24 13:26:38 +0100
@@ -270,14 +270,18 @@ set_file_attributes (char const *to, enu
       gid = (egid == st->st_gid) ? -1 : st->st_gid;
 
       /* May fail if we are not privileged to set the file owner, or we are
          not in group instat.st_gid.  Ignore those errors.  */
       if ((uid != -1 || gid != -1)
+#if HAVE_RAW_DECL_LCHOWN
 	  && safe_lchown (to, uid, gid) != 0
+#endif
 	  && (errno != EPERM
 	      || (uid != -1
+#if HAVE_RAW_DECL_LCHOWN
 		  && safe_lchown (to, (uid = -1), gid) != 0
+#endif
 		  && errno != EPERM)))
 	pfatal ("Failed to set the %s of %s %s",
 		(uid == -1) ? "owner" : "owning group",
 		S_ISLNK (mode) ? "symbolic link" : "file",
 		quotearg (to));
@@ -1593,11 +1597,25 @@ Fseek (FILE *stream, file_offset offset,
   if (file_seek (stream, offset, ptrname) != 0)
     pfatal ("fseek");
 }
 
 #ifndef TMPDIR
-#define TMPDIR "/tmp"
+# if FILESYSTEM_BACKSLASH_IS_FILE_NAME_SEPARATOR
+#  ifdef P_tmpdir
+#   define TMPDIR P_tmpdir
+#  else
+#   define TMPDIR "c:"
+#  endif
+# else /* POSIX systems */
+#  define TMPDIR "/tmp"
+# endif
+#endif
+
+#ifdef __DJGPP__
+# define DIR_EXISTS(path)   (access((path), D_OK) == 0)
+#else
+# define DIR_EXISTS(path)   (1)
 #endif
 
 struct try_safe_open_args
   {
     int flags;
@@ -1630,11 +1648,11 @@ make_tempfile (char const **name, char l
     .flags = flags,
     .mode = mode,
   };
   int fd;
 
-  if (real_name && ! dry_run)
+  if (real_name && HAVE_LFN_SUPPORT(real_name) && ! dry_run)
     {
       char *dirname, *basename;
 
       dirname = dir_name (real_name);
       basename = base_name (real_name);
@@ -1647,15 +1665,15 @@ make_tempfile (char const **name, char l
   else
     {
       char const *tmpdir;
 
       tmpdir = getenv ("TMPDIR");  /* Unix tradition */
-      if (! tmpdir)
+      if (! tmpdir || *tmpdir == '\0' || !DIR_EXISTS(tmpdir))
 	tmpdir = getenv ("TMP");  /* DOS tradition */
-      if (! tmpdir)
+      if (! tmpdir || *tmpdir == '\0' || !DIR_EXISTS(tmpdir))
 	tmpdir = getenv ("TEMP");  /* another DOS tradition */
-      if (! tmpdir)
+      if (! tmpdir || *tmpdir == '\0' || !DIR_EXISTS(tmpdir))
 	tmpdir = TMPDIR;
 
       template = xmalloc (strlen (tmpdir) + 10);
       sprintf (template, "%s/p%cXXXXXX", tmpdir, letter);
     }
@@ -1665,11 +1683,15 @@ make_tempfile (char const **name, char l
 }
 
 int stat_file (char const *filename, struct stat *st)
 {
   int (*xstat)(char const *, struct stat *) =
+#if defined(__DJGPP__) && __DJGPP__ == 2 && __DJGPP_MINOR__ > 3
+    follow_symlinks ? djgpp_wrapper_stat : djgpp_wrapper_lstat;
+#else
     follow_symlinks ? safe_stat : safe_lstat;
+#endif
 
   return xstat (filename, st) == 0 ? 0 : errno;
 }
 
 /* Check if a filename is relative and free of ".." components.



2016-07-25  Juan Manuel Guerrero  <juan.guerrero@gmx.de>

	* pc/chdirsaf.c: In case that chdir is defined as macro undefine it so
	that both functions restore_wd and chdir_safer does call DJGPP's chdir.








diff -aprNU5 patch-2.7.5.orig/pc/chdirsaf.c patch-2.7.5/pc/chdirsaf.c
--- patch-2.7.5.orig/pc/chdirsaf.c	2014-11-26 13:17:48 -0511
+++ patch-2.7.5/pc/chdirsaf.c	2016-07-25 00:50:24 -0511
@@ -1,9 +1,12 @@
 /* A safer version of chdir, which returns back to the
    initial working directory when the program exits.  */
 
 #include <config.h>
+/*  Use DJGPP's chdir in restore_wd and chdir_safer.  */
+#undef chdir
+
 #include <errno.h>
 #include <stdlib.h>
 #include <unistd.h>
 
 static char *initial_wd;



2016-07-26  Juan Manuel Guerrero  <juan.guerrero@gmx.de>

	* pc/pc_inode.c (djgpp_wrapper_rename, djgpp_wrapper_unlink):  Unused
	variables removed.









diff -aprNU5 patch-2.7.5.orig/pc/pc_inode.c patch-2.7.5/pc/pc_inode.c
--- patch-2.7.5.orig/pc/pc_inode.c	2016-07-26 21:57:14 -0511
+++ patch-2.7.5/pc/pc_inode.c	2016-07-26 22:03:54 -0511
@@ -431,11 +431,10 @@ int djgpp_wrapper_fclose(FILE *fp)
 #undef rename
 
 int djgpp_wrapper_rename(const char *old_name, const char *new_name)
 {
   int status;
-  const int previous_errno = errno;
 
 
   status = rename(old_name, new_name);
   if (!status)
     replace_inode(old_name, new_name);
@@ -449,11 +448,10 @@ int djgpp_wrapper_rename(const char *old
 int unlink(const char *_path);
 
 int djgpp_wrapper_unlink(const char *file_name)
 {
   int status;
-  const int previous_errno = errno;
 
 
   status = unlink(file_name);
   if (!status)
     remove_inode(file_name);



2016-07-27  Juan Manuel Guerrero  <juan.guerrero@gmx.de>

	* src/common.h [__DJGP__]:  Define macro RESTORE_WD.  Calls function
	that restores original working directory in case that program was
        interrupted by SIGINT.  NO-OP for all other OS.

	* src/patch.c (fatal_exit):  Call RESTORE_WD.

	* pc/chdirsaf.c:  Static qualifier removed from restore_wd definition.







diff -aprNU5 patch-2.7.5.orig/pc/chdirsaf.c patch-2.7.5/pc/chdirsaf.c
--- patch-2.7.5.orig/pc/chdirsaf.c	2016-07-27 22:25:42 -0511
+++ patch-2.7.5/pc/chdirsaf.c	2016-07-27 22:29:06 -0511
@@ -9,11 +9,11 @@
 #include <stdlib.h>
 #include <unistd.h>
 
 static char *initial_wd;
 
-static void
+void
 restore_wd (void)
 {
   chdir (initial_wd);
 }
 
diff -aprNU5 patch-2.7.5.orig/src/common.h patch-2.7.5/src/common.h
--- patch-2.7.5.orig/src/common.h	2016-07-27 22:25:42 -0511
+++ patch-2.7.5/src/common.h	2016-07-27 22:26:56 -0511
@@ -279,11 +279,17 @@ bool merge_hunk (int hunk, struct outsta
          if (__S_ISLNK(linux_type))  djgpp_type |= S_IFLNK;  \
        }                                                     \
        djgpp_type;                                           \
     })                                                       \
   )
+
+/* On MS-DOS, CWD is global, so we must remember where we were before
+   changing dirs, and return there if the program is interrupted by SIGINT.  */
+void restore_wd(void);
+# define RESTORE_WD()               restore_wd()
 #else
 # define STRIP_EXTENSION(filename)  (filename)
 # define CANONICALIZE_PATH(path)    (path)
 # define HAVE_LFN_SUPPORT(name)     (1)
 # define MAP_FILE_TYPE(type)        (type)
+# define RESTORE_WD()               /* void */
 #endif
diff -aprNU5 patch-2.7.5.orig/src/patch.c patch-2.7.5/src/patch.c
--- patch-2.7.5.orig/src/patch.c	2016-07-27 22:25:42 -0511
+++ patch-2.7.5/src/patch.c	2016-07-27 22:26:56 -0511
@@ -1980,10 +1980,11 @@ forget_output_files (void)
 
 void
 fatal_exit (int sig)
 {
   cleanup ();
+  RESTORE_WD();
 
   if (sig)
     exit_with_signal (sig);
 
   exit (2);
