Merge from emacs--rel--22
[bpt/emacs.git] / src / fileio.c
index 4dac185..53cab8c 100644 (file)
@@ -1,6 +1,7 @@
 /* File IO for GNU Emacs.
 /* File IO for GNU Emacs.
-   Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1996, 1997, 1998,
-     1999, 2000, 2001, 2003, 2004, 2005  Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1996,
+                 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+                 2005, 2006, 2007 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 
 This file is part of GNU Emacs.
 
@@ -16,8 +17,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 #include <config.h>
 
 
 #include <config.h>
 
@@ -76,6 +77,7 @@ extern int errno;
 #include "charset.h"
 #include "coding.h"
 #include "window.h"
 #include "charset.h"
 #include "coding.h"
 #include "window.h"
+#include "blockinput.h"
 
 #ifdef WINDOWSNT
 #define NOMINMAX 1
 
 #ifdef WINDOWSNT
 #define NOMINMAX 1
@@ -224,6 +226,11 @@ int vms_stmlf_recfm;
    expanding file names.  This can be bound to / or \. */
 Lisp_Object Vdirectory_sep_char;
 
    expanding file names.  This can be bound to / or \. */
 Lisp_Object Vdirectory_sep_char;
 
+#ifdef HAVE_FSYNC
+/* Nonzero means skip the call to fsync in Fwrite-region.  */
+int write_region_inhibit_fsync;
+#endif
+
 extern Lisp_Object Vuser_login_name;
 
 #ifdef WINDOWSNT
 extern Lisp_Object Vuser_login_name;
 
 #ifdef WINDOWSNT
@@ -273,7 +280,7 @@ report_file_error (string, data)
     switch (errorno)
       {
       case EEXIST:
     switch (errorno)
       {
       case EEXIST:
-       Fsignal (Qfile_already_exists, Fcons (errstring, data));
+       xsignal (Qfile_already_exists, Fcons (errstring, data));
        break;
       default:
        /* System error messages are capitalized.  Downcase the initial
        break;
       default:
        /* System error messages are capitalized.  Downcase the initial
@@ -281,7 +288,7 @@ report_file_error (string, data)
        if (SREF (errstring, 1) != '/')
          SSET (errstring, 0, DOWNCASE (SREF (errstring, 0)));
 
        if (SREF (errstring, 1) != '/')
          SSET (errstring, 0, DOWNCASE (SREF (errstring, 0)));
 
-       Fsignal (Qfile_error,
+       xsignal (Qfile_error,
                 Fcons (build_string (string), Fcons (errstring, data)));
       }
 }
                 Fcons (build_string (string), Fcons (errstring, data)));
       }
 }
@@ -1055,6 +1062,7 @@ See also the function `substitute-in-file-name'.  */)
 #endif /* DOS_NT */
   int length;
   Lisp_Object handler, result;
 #endif /* DOS_NT */
   int length;
   Lisp_Object handler, result;
+  int multibyte;
 
   CHECK_STRING (name);
 
 
   CHECK_STRING (name);
 
@@ -1132,6 +1140,7 @@ See also the function `substitute-in-file-name'.  */)
 
   name = FILE_SYSTEM_CASE (name);
   nm = SDATA (name);
 
   name = FILE_SYSTEM_CASE (name);
   nm = SDATA (name);
+  multibyte = STRING_MULTIBYTE (name);
 
 #ifdef DOS_NT
   /* We will force directory separators to be either all \ or /, so make
 
 #ifdef DOS_NT
   /* We will force directory separators to be either all \ or /, so make
@@ -1239,9 +1248,9 @@ See also the function `substitute-in-file-name'.  */)
              }
            else
 #endif /* NO_HYPHENS_IN_FILENAMES */
              }
            else
 #endif /* NO_HYPHENS_IN_FILENAMES */
-             if (lbrack > rbrack &&
-                 ((p[-1] == '.' || p[-1] == '[' || p[-1] == '<') &&
-                  (p[1] == '.' || p[1] == ']' || p[1] == '>')))
+             if (lbrack > rbrack
+                 && ((p[-1] == '.' || p[-1] == '[' || p[-1] == '<')
+                     && (p[1] == '.' || p[1] == ']' || p[1] == '>')))
                lose = 1;
 #ifdef NO_HYPHENS_IN_FILENAMES
              else
                lose = 1;
 #ifdef NO_HYPHENS_IN_FILENAMES
              else
@@ -1297,8 +1306,7 @@ See also the function `substitute-in-file-name'.  */)
          if (index (nm, '/'))
            {
              nm = sys_translate_unix (nm);
          if (index (nm, '/'))
            {
              nm = sys_translate_unix (nm);
-             return make_specified_string (nm, -1, strlen (nm),
-                                           STRING_MULTIBYTE (name));
+             return make_specified_string (nm, -1, strlen (nm), multibyte);
            }
 #endif /* VMS */
 #ifdef DOS_NT
            }
 #endif /* VMS */
 #ifdef DOS_NT
@@ -1310,8 +1318,7 @@ See also the function `substitute-in-file-name'.  */)
          if (IS_DIRECTORY_SEP (nm[1]))
            {
              if (strcmp (nm, SDATA (name)) != 0)
          if (IS_DIRECTORY_SEP (nm[1]))
            {
              if (strcmp (nm, SDATA (name)) != 0)
-               name = make_specified_string (nm, -1, strlen (nm),
-                                             STRING_MULTIBYTE (name));
+               name = make_specified_string (nm, -1, strlen (nm), multibyte);
            }
          else
 #endif
            }
          else
 #endif
@@ -1320,8 +1327,7 @@ See also the function `substitute-in-file-name'.  */)
            {
              char temp[] = " :";
 
            {
              char temp[] = " :";
 
-             name = make_specified_string (nm, -1, p - nm,
-                                           STRING_MULTIBYTE (name));
+             name = make_specified_string (nm, -1, p - nm, multibyte);
              temp[0] = DRIVE_LETTER (drive);
              name = concat2 (build_string (temp), name);
            }
              temp[0] = DRIVE_LETTER (drive);
              name = concat2 (build_string (temp), name);
            }
@@ -1329,8 +1335,7 @@ See also the function `substitute-in-file-name'.  */)
 #else /* not DOS_NT */
          if (nm == SDATA (name))
            return name;
 #else /* not DOS_NT */
          if (nm == SDATA (name))
            return name;
-         return make_specified_string (nm, -1, strlen (nm),
-                                       STRING_MULTIBYTE (name));
+         return make_specified_string (nm, -1, strlen (nm), multibyte);
 #endif /* not DOS_NT */
        }
     }
 #endif /* not DOS_NT */
        }
     }
@@ -1382,7 +1387,9 @@ See also the function `substitute-in-file-name'.  */)
          bcopy ((char *) nm, o, p - nm);
          o [p - nm] = 0;
 
          bcopy ((char *) nm, o, p - nm);
          o [p - nm] = 0;
 
+         BLOCK_INPUT;
          pw = (struct passwd *) getpwnam (o + 1);
          pw = (struct passwd *) getpwnam (o + 1);
+         UNBLOCK_INPUT;
          if (pw)
            {
              newdir = (unsigned char *) pw -> pw_dir;
          if (pw)
            {
              newdir = (unsigned char *) pw -> pw_dir;
@@ -1442,6 +1449,7 @@ See also the function `substitute-in-file-name'.  */)
       && !newdir)
     {
       newdir = SDATA (default_directory);
       && !newdir)
     {
       newdir = SDATA (default_directory);
+      multibyte |= STRING_MULTIBYTE (default_directory);
 #ifdef DOS_NT
       /* Note if special escape prefix is present, but remove for now.  */
       if (newdir[0] == '/' && newdir[1] == ':')
 #ifdef DOS_NT
       /* Note if special escape prefix is present, but remove for now.  */
       if (newdir[0] == '/' && newdir[1] == ':')
@@ -1611,8 +1619,8 @@ See also the function `substitute-in-file-name'.  */)
          else if (*p == '-' && *o != '.')
            *--p = '.';
        }
          else if (*p == '-' && *o != '.')
            *--p = '.';
        }
-      else if (p[0] == '-' && o[-1] == '.' &&
-              (p[1] == '.' || p[1] == ']' || p[1] == '>'))
+      else if (p[0] == '-' && o[-1] == '.'
+              && (p[1] == '.' || p[1] == ']' || p[1] == '>'))
        /* flush .foo.- ; leave - if stopped by '[' or '<' */
        {
          do
        /* flush .foo.- ; leave - if stopped by '[' or '<' */
        {
          do
@@ -1627,9 +1635,9 @@ See also the function `substitute-in-file-name'.  */)
       else
        {
 #ifdef NO_HYPHENS_IN_FILENAMES
       else
        {
 #ifdef NO_HYPHENS_IN_FILENAMES
-         if (*p == '-' &&
-             o[-1] != '[' && o[-1] != '<' && o[-1] != '.' &&
-             p[1] != ']' && p[1] != '>' && p[1] != '.')
+         if (*p == '-'
+             && o[-1] != '[' && o[-1] != '<' && o[-1] != '.'
+             && p[1] != ']' && p[1] != '>' && p[1] != '.')
            *p = '_';
 #endif /* NO_HYPHENS_IN_FILENAMES */
          *o++ = *p++;
            *p = '_';
 #endif /* NO_HYPHENS_IN_FILENAMES */
          *o++ = *p++;
@@ -1639,8 +1647,7 @@ See also the function `substitute-in-file-name'.  */)
        {
          *o++ = *p++;
        }
        {
          *o++ = *p++;
        }
-      else if (IS_DIRECTORY_SEP (p[0])
-              && p[1] == '.'
+      else if (p[1] == '.'
               && (IS_DIRECTORY_SEP (p[2])
                   || p[2] == 0))
        {
               && (IS_DIRECTORY_SEP (p[2])
                   || p[2] == 0))
        {
@@ -1650,7 +1657,7 @@ See also the function `substitute-in-file-name'.  */)
            *o++ = *p;
          p += 2;
        }
            *o++ = *p;
          p += 2;
        }
-      else if (IS_DIRECTORY_SEP (p[0]) && p[1] == '.' && p[2] == '.'
+      else if (p[1] == '.' && p[2] == '.'
               /* `/../' is the "superroot" on certain file systems.
                  Turned off on DOS_NT systems because they have no
                  "superroot" and because this causes us to produce
               /* `/../' is the "superroot" on certain file systems.
                  Turned off on DOS_NT systems because they have no
                  "superroot" and because this causes us to produce
@@ -1670,14 +1677,9 @@ See also the function `substitute-in-file-name'.  */)
            ++o;
          p += 3;
        }
            ++o;
          p += 3;
        }
-      else if (p > target
-              && IS_DIRECTORY_SEP (p[0]) && IS_DIRECTORY_SEP (p[1]))
-       {
-         /* Collapse multiple `/' in a row.  */
-         *o++ = *p++;
-         while (IS_DIRECTORY_SEP (*p))
-           ++p;
-       }
+      else if (p > target && IS_DIRECTORY_SEP (p[1]))
+       /* Collapse multiple `/' in a row.  */
+       p++;
       else
        {
          *o++ = *p++;
       else
        {
          *o++ = *p++;
@@ -1707,8 +1709,7 @@ See also the function `substitute-in-file-name'.  */)
   CORRECT_DIR_SEPS (target);
 #endif /* DOS_NT */
 
   CORRECT_DIR_SEPS (target);
 #endif /* DOS_NT */
 
-  result = make_specified_string (target, -1, o - target,
-                                  STRING_MULTIBYTE (name));
+  result = make_specified_string (target, -1, o - target, multibyte);
 
   /* Again look to see if the file name has special constructs in it
      and perhaps call the corresponding file handler.  This is needed
 
   /* Again look to see if the file name has special constructs in it
      and perhaps call the corresponding file handler.  This is needed
@@ -1819,9 +1820,9 @@ See also the function `substitute-in-file-name'.")
              }
            else
 #endif /* VMS4_4 */
              }
            else
 #endif /* VMS4_4 */
-             if (lbrack > rbrack &&
-                 ((p[-1] == '.' || p[-1] == '[' || p[-1] == '<') &&
-                  (p[1] == '.' || p[1] == ']' || p[1] == '>')))
+             if (lbrack > rbrack
+                 && ((p[-1] == '.' || p[-1] == '[' || p[-1] == '<')
+                     && (p[1] == '.' || p[1] == ']' || p[1] == '>')))
                lose = 1;
 #ifndef VMS4_4
              else
                lose = 1;
 #ifndef VMS4_4
              else
@@ -1919,7 +1920,9 @@ See also the function `substitute-in-file-name'.")
        o[len] = 0;
 
        /* Look up the user name. */
        o[len] = 0;
 
        /* Look up the user name. */
+       BLOCK_INPUT;
        pw = (struct passwd *) getpwnam (o + 1);
        pw = (struct passwd *) getpwnam (o + 1);
+       UNBLOCK_INPUT;
        if (!pw)
          error ("\"%s\" isn't a registered user", o + 1);
 
        if (!pw)
          error ("\"%s\" isn't a registered user", o + 1);
 
@@ -1988,8 +1991,8 @@ See also the function `substitute-in-file-name'.")
          else if (*p == '-' && *o != '.')
            *--p = '.';
        }
          else if (*p == '-' && *o != '.')
            *--p = '.';
        }
-      else if (p[0] == '-' && o[-1] == '.' &&
-              (p[1] == '.' || p[1] == ']' || p[1] == '>'))
+      else if (p[0] == '-' && o[-1] == '.'
+              && (p[1] == '.' || p[1] == ']' || p[1] == '>'))
        /* flush .foo.- ; leave - if stopped by '[' or '<' */
        {
          do
        /* flush .foo.- ; leave - if stopped by '[' or '<' */
        {
          do
@@ -2004,9 +2007,9 @@ See also the function `substitute-in-file-name'.")
       else
        {
 #ifndef VMS4_4
       else
        {
 #ifndef VMS4_4
-         if (*p == '-' &&
-             o[-1] != '[' && o[-1] != '<' && o[-1] != '.' &&
-             p[1] != ']' && p[1] != '>' && p[1] != '.')
+         if (*p == '-'
+             && o[-1] != '[' && o[-1] != '<' && o[-1] != '.'
+             && p[1] != ']' && p[1] != '>' && p[1] != '.')
            *p = '_';
 #endif /* VMS4_4 */
          *o++ = *p++;
            *p = '_';
 #endif /* VMS4_4 */
          *o++ = *p++;
@@ -2026,8 +2029,8 @@ See also the function `substitute-in-file-name'.")
          o = target;
          p++;
        }
          o = target;
          p++;
        }
-      else if (p[0] == '/' && p[1] == '.' &&
-              (p[2] == '/' || p[2] == 0))
+      else if (p[0] == '/' && p[1] == '.'
+              && (p[2] == '/' || p[2] == 0))
        p += 2;
       else if (!strncmp (p, "/..", 3)
               /* `/../' is the "superroot" on certain file systems.  */
        p += 2;
       else if (!strncmp (p, "/..", 3)
               /* `/../' is the "superroot" on certain file systems.  */
@@ -2113,10 +2116,11 @@ search_embedded_absfilename (nm, endp)
              /* If we have ~user and `user' exists, discard
                 everything up to ~.  But if `user' does not exist, leave
                 ~user alone, it might be a literal file name.  */
              /* If we have ~user and `user' exists, discard
                 everything up to ~.  But if `user' does not exist, leave
                 ~user alone, it might be a literal file name.  */
-             if ((pw = getpwnam (o + 1)))
+             BLOCK_INPUT;
+             pw = getpwnam (o + 1);
+             UNBLOCK_INPUT;
+             if (pw)
                return p;
                return p;
-             else
-               xfree (pw);
            }
          else
            return p;
            }
          else
            return p;
@@ -2380,9 +2384,8 @@ barf_or_query_if_file_exists (absname, querystring, interactive, statptr, quick)
   if (lstat (SDATA (encoded_filename), &statbuf) >= 0)
     {
       if (! interactive)
   if (lstat (SDATA (encoded_filename), &statbuf) >= 0)
     {
       if (! interactive)
-       Fsignal (Qfile_already_exists,
-                Fcons (build_string ("File already exists"),
-                       Fcons (absname, Qnil)));
+       xsignal2 (Qfile_already_exists,
+                 build_string ("File already exists"), absname);
       GCPRO1 (absname);
       tem = format2 ("File %s already exists; %s anyway? ",
                     absname, build_string (querystring));
       GCPRO1 (absname);
       tem = format2 ("File %s already exists; %s anyway? ",
                     absname, build_string (querystring));
@@ -2392,9 +2395,8 @@ barf_or_query_if_file_exists (absname, querystring, interactive, statptr, quick)
        tem = do_yes_or_no_p (tem);
       UNGCPRO;
       if (NILP (tem))
        tem = do_yes_or_no_p (tem);
       UNGCPRO;
       if (NILP (tem))
-       Fsignal (Qfile_already_exists,
-                Fcons (build_string ("File already exists"),
-                       Fcons (absname, Qnil)));
+       xsignal2 (Qfile_already_exists,
+                 build_string ("File already exists"), absname);
       if (statptr)
        *statptr = statbuf;
     }
       if (statptr)
        *statptr = statbuf;
     }
@@ -2410,25 +2412,28 @@ DEFUN ("copy-file", Fcopy_file, Scopy_file, 2, 5,
        "fCopy file: \nGCopy %s to file: \np\nP",
        doc: /* Copy FILE to NEWNAME.  Both args must be strings.
 If NEWNAME names a directory, copy FILE there.
        "fCopy file: \nGCopy %s to file: \np\nP",
        doc: /* Copy FILE to NEWNAME.  Both args must be strings.
 If NEWNAME names a directory, copy FILE there.
-Signals a `file-already-exists' error if file NEWNAME already exists,
-unless a third argument OK-IF-ALREADY-EXISTS is supplied and non-nil.
-A number as third arg means request confirmation if NEWNAME already exists.
-This is what happens in interactive use with M-x.
-Always sets the file modes of the output file to match the input file.
+
+This function always sets the file modes of the output file to match
+the input file.
+
+The optional third argument OK-IF-ALREADY-EXISTS specifies what to do
+if file NEWNAME already exists.  If OK-IF-ALREADY-EXISTS is nil, we
+signal a `file-already-exists' error without overwriting.  If
+OK-IF-ALREADY-EXISTS is a number, we request confirmation from the user
+about overwriting; this is what happens in interactive use with M-x.
+Any other value for OK-IF-ALREADY-EXISTS means to overwrite the
+existing file.
 
 Fourth arg KEEP-TIME non-nil means give the output file the same
 last-modified time as the old one.  (This works on only some systems.)
 
 A prefix arg makes KEEP-TIME non-nil.
 
 
 Fourth arg KEEP-TIME non-nil means give the output file the same
 last-modified time as the old one.  (This works on only some systems.)
 
 A prefix arg makes KEEP-TIME non-nil.
 
-The optional fifth arg MUSTBENEW, if non-nil, insists on a check
-for an existing file with the same name.  If MUSTBENEW is `excl',
-that means to get an error if the file already exists; never overwrite.
-If MUSTBENEW is neither nil nor `excl', that means ask for
-confirmation before overwriting, but do go ahead and overwrite the file
-if the user confirms.  */)
-  (file, newname, ok_if_already_exists, keep_time, mustbenew)
-     Lisp_Object file, newname, ok_if_already_exists, keep_time, mustbenew;
+If PRESERVE-UID-GID is non-nil, we try to transfer the
+uid and gid of FILE to NEWNAME.  */)
+  (file, newname, ok_if_already_exists, keep_time, preserve_uid_gid)
+     Lisp_Object file, newname, ok_if_already_exists, keep_time;
+     Lisp_Object preserve_uid_gid;
 {
   int ifd, ofd, n;
   char buf[16 * 1024];
 {
   int ifd, ofd, n;
   char buf[16 * 1024];
@@ -2444,9 +2449,6 @@ if the user confirms.  */)
   CHECK_STRING (file);
   CHECK_STRING (newname);
 
   CHECK_STRING (file);
   CHECK_STRING (newname);
 
-  if (!NILP (mustbenew) && !EQ (mustbenew, Qexcl))
-    barf_or_query_if_file_exists (newname, "overwrite", 1, 0, 1);
-
   if (!NILP (Ffile_directory_p (newname)))
     newname = Fexpand_file_name (Ffile_name_nondirectory (file), newname);
   else
   if (!NILP (Ffile_directory_p (newname)))
     newname = Fexpand_file_name (Ffile_name_nondirectory (file), newname);
   else
@@ -2469,7 +2471,7 @@ if the user confirms.  */)
 
   if (NILP (ok_if_already_exists)
       || INTEGERP (ok_if_already_exists))
 
   if (NILP (ok_if_already_exists)
       || INTEGERP (ok_if_already_exists))
-    barf_or_query_if_file_exists (encoded_newname, "copy to it",
+    barf_or_query_if_file_exists (newname, "copy to it",
                                  INTEGERP (ok_if_already_exists), &out_st, 0);
   else if (stat (SDATA (encoded_newname), &out_st) < 0)
     out_st.st_mode = 0;
                                  INTEGERP (ok_if_already_exists), &out_st, 0);
   else if (stat (SDATA (encoded_newname), &out_st) < 0)
     out_st.st_mode = 0;
@@ -2496,9 +2498,8 @@ if the user confirms.  */)
        {
          /* Restore original attributes.  */
          SetFileAttributes (filename, attributes);
        {
          /* Restore original attributes.  */
          SetFileAttributes (filename, attributes);
-         Fsignal (Qfile_date_error,
-                  Fcons (build_string ("Cannot set file date"),
-                         Fcons (newname, Qnil)));
+         xsignal2 (Qfile_date_error,
+                   build_string ("Cannot set file date"), newname);
        }
       /* Restore original attributes.  */
       SetFileAttributes (filename, attributes);
        }
       /* Restore original attributes.  */
       SetFileAttributes (filename, attributes);
@@ -2517,7 +2518,7 @@ if the user confirms.  */)
      copyable by us. */
   input_file_statable_p = (fstat (ifd, &st) >= 0);
 
      copyable by us. */
   input_file_statable_p = (fstat (ifd, &st) >= 0);
 
-#if !defined (DOS_NT) || __DJGPP__ > 1
+#if !defined (MSDOS) || __DJGPP__ > 1
   if (out_st.st_mode != 0
       && st.st_dev == out_st.st_dev && st.st_ino == out_st.st_ino)
     {
   if (out_st.st_mode != 0
       && st.st_dev == out_st.st_dev && st.st_ino == out_st.st_ino)
     {
@@ -2549,12 +2550,12 @@ if the user confirms.  */)
   /* System's default file type was set to binary by _fmode in emacs.c.  */
   ofd = emacs_open (SDATA (encoded_newname),
                    O_WRONLY | O_TRUNC | O_CREAT
   /* System's default file type was set to binary by _fmode in emacs.c.  */
   ofd = emacs_open (SDATA (encoded_newname),
                    O_WRONLY | O_TRUNC | O_CREAT
-                   | (EQ (mustbenew, Qexcl) ? O_EXCL : 0),
+                   | (NILP (ok_if_already_exists) ? O_EXCL : 0),
                    S_IREAD | S_IWRITE);
 #else  /* not MSDOS */
   ofd = emacs_open (SDATA (encoded_newname),
                    O_WRONLY | O_TRUNC | O_CREAT
                    S_IREAD | S_IWRITE);
 #else  /* not MSDOS */
   ofd = emacs_open (SDATA (encoded_newname),
                    O_WRONLY | O_TRUNC | O_CREAT
-                   | (EQ (mustbenew, Qexcl) ? O_EXCL : 0),
+                   | (NILP (ok_if_already_exists) ? O_EXCL : 0),
                    0666);
 #endif /* not MSDOS */
 #endif /* VMS */
                    0666);
 #endif /* not MSDOS */
 #endif /* VMS */
@@ -2570,6 +2571,17 @@ if the user confirms.  */)
       report_file_error ("I/O error", Fcons (newname, Qnil));
   immediate_quit = 0;
 
       report_file_error ("I/O error", Fcons (newname, Qnil));
   immediate_quit = 0;
 
+#ifndef MSDOS
+  /* Preserve the original file modes, and if requested, also its
+     owner and group.  */
+  if (input_file_statable_p)
+    {
+      if (! NILP (preserve_uid_gid))
+       fchown (ofd, st.st_uid, st.st_gid);
+      fchmod (ofd, st.st_mode & 07777);
+    }
+#endif /* not MSDOS */
+
   /* Closing the output clobbers the file times on some systems.  */
   if (emacs_close (ofd) < 0)
     report_file_error ("I/O error", Fcons (newname, Qnil));
   /* Closing the output clobbers the file times on some systems.  */
   if (emacs_close (ofd) < 0)
     report_file_error ("I/O error", Fcons (newname, Qnil));
@@ -2583,26 +2595,25 @@ if the user confirms.  */)
          EMACS_SET_SECS_USECS (mtime, st.st_mtime, 0);
          if (set_file_times (SDATA (encoded_newname),
                              atime, mtime))
          EMACS_SET_SECS_USECS (mtime, st.st_mtime, 0);
          if (set_file_times (SDATA (encoded_newname),
                              atime, mtime))
-           Fsignal (Qfile_date_error,
-                    Fcons (build_string ("Cannot set file date"),
-                           Fcons (newname, Qnil)));
+           xsignal2 (Qfile_date_error,
+                     build_string ("Cannot set file date"), newname);
        }
        }
-#ifndef MSDOS
-      chmod (SDATA (encoded_newname), st.st_mode & 07777);
-#else /* MSDOS */
+    }
+
+  emacs_close (ifd);
+
 #if defined (__DJGPP__) && __DJGPP__ > 1
 #if defined (__DJGPP__) && __DJGPP__ > 1
+  if (input_file_statable_p)
+    {
       /* In DJGPP v2.0 and later, fstat usually returns true file mode bits,
          and if it can't, it tells so.  Otherwise, under MSDOS we usually
          get only the READ bit, which will make the copied file read-only,
          so it's better not to chmod at all.  */
       if ((_djstat_flags & _STFAIL_WRITEBIT) == 0)
        chmod (SDATA (encoded_newname), st.st_mode & 07777);
       /* In DJGPP v2.0 and later, fstat usually returns true file mode bits,
          and if it can't, it tells so.  Otherwise, under MSDOS we usually
          get only the READ bit, which will make the copied file read-only,
          so it's better not to chmod at all.  */
       if ((_djstat_flags & _STFAIL_WRITEBIT) == 0)
        chmod (SDATA (encoded_newname), st.st_mode & 07777);
-#endif /* DJGPP version 2 or newer */
-#endif /* MSDOS */
     }
     }
-
-  emacs_close (ifd);
-#endif /* WINDOWSNT */
+#endif /* DJGPP version 2 or newer */
+#endif /* not WINDOWSNT */
 
   /* Discard the unwind protects.  */
   specpdl_ptr = specpdl + count;
 
   /* Discard the unwind protects.  */
   specpdl_ptr = specpdl + count;
@@ -2637,7 +2648,7 @@ DEFUN ("make-directory-internal", Fmake_directory_internal,
 #else
   if (mkdir (dir, 0777) != 0)
 #endif
 #else
   if (mkdir (dir, 0777) != 0)
 #endif
-    report_file_error ("Creating directory", Flist (1, &directory));
+    report_file_error ("Creating directory", list1 (directory));
 
   return Qnil;
 }
 
   return Qnil;
 }
@@ -2663,7 +2674,7 @@ DEFUN ("delete-directory", Fdelete_directory, Sdelete_directory, 1, 1, "FDelete
   dir = SDATA (encoded_dir);
 
   if (rmdir (dir) != 0)
   dir = SDATA (encoded_dir);
 
   if (rmdir (dir) != 0)
-    report_file_error ("Removing directory", Flist (1, &directory));
+    report_file_error ("Removing directory", list1 (directory));
 
   return Qnil;
 }
 
   return Qnil;
 }
@@ -2681,9 +2692,9 @@ If file has multiple names, it continues to exist with the other names.  */)
   GCPRO1 (filename);
   if (!NILP (Ffile_directory_p (filename))
       && NILP (Ffile_symlink_p (filename)))
   GCPRO1 (filename);
   if (!NILP (Ffile_directory_p (filename))
       && NILP (Ffile_symlink_p (filename)))
-    Fsignal (Qfile_error,
-            Fcons (build_string ("Removing old name: is a directory"),
-                   Fcons (filename, Qnil)));
+    xsignal2 (Qfile_error,
+             build_string ("Removing old name: is a directory"),
+             filename);
   UNGCPRO;
   filename = Fexpand_file_name (filename, Qnil);
 
   UNGCPRO;
   filename = Fexpand_file_name (filename, Qnil);
 
@@ -2694,7 +2705,7 @@ If file has multiple names, it continues to exist with the other names.  */)
   encoded_file = ENCODE_FILE (filename);
 
   if (0 > unlink (SDATA (encoded_file)))
   encoded_file = ENCODE_FILE (filename);
 
   if (0 > unlink (SDATA (encoded_file)))
-    report_file_error ("Removing old name", Flist (1, &filename));
+    report_file_error ("Removing old name", list1 (filename));
   return Qnil;
 }
 
   return Qnil;
 }
 
@@ -2711,8 +2722,10 @@ int
 internal_delete_file (filename)
      Lisp_Object filename;
 {
 internal_delete_file (filename)
      Lisp_Object filename;
 {
-  return NILP (internal_condition_case_1 (Fdelete_file, filename,
-                                         Qt, internal_delete_file_1));
+  Lisp_Object tem;
+  tem = internal_condition_case_1 (Fdelete_file, filename,
+                                  Qt, internal_delete_file_1);
+  return NILP (tem);
 }
 \f
 DEFUN ("rename-file", Frename_file, Srename_file, 2, 3,
 }
 \f
 DEFUN ("rename-file", Frename_file, Srename_file, 2, 3,
@@ -2726,9 +2739,6 @@ This is what happens in interactive use with M-x.  */)
      (file, newname, ok_if_already_exists)
      Lisp_Object file, newname, ok_if_already_exists;
 {
      (file, newname, ok_if_already_exists)
      Lisp_Object file, newname, ok_if_already_exists;
 {
-#ifdef NO_ARG_ARRAY
-  Lisp_Object args[2];
-#endif
   Lisp_Object handler;
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
   Lisp_Object encoded_file, encoded_newname, symlink_target;
   Lisp_Object handler;
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
   Lisp_Object encoded_file, encoded_newname, symlink_target;
@@ -2739,7 +2749,13 @@ This is what happens in interactive use with M-x.  */)
   CHECK_STRING (newname);
   file = Fexpand_file_name (file, Qnil);
 
   CHECK_STRING (newname);
   file = Fexpand_file_name (file, Qnil);
 
-  if (!NILP (Ffile_directory_p (newname)))
+  if ((!NILP (Ffile_directory_p (newname)))
+#ifdef DOS_NT
+      /* If the file names are identical but for the case,
+        don't attempt to move directory to itself. */
+      && (NILP (Fstring_equal (Fdowncase (file), Fdowncase (newname))))
+#endif
+      )
     newname = Fexpand_file_name (Ffile_name_nondirectory (file), newname);
   else
     newname = Fexpand_file_name (newname, Qnil);
     newname = Fexpand_file_name (Ffile_name_nondirectory (file), newname);
   else
     newname = Fexpand_file_name (newname, Qnil);
@@ -2764,7 +2780,7 @@ This is what happens in interactive use with M-x.  */)
 #endif
   if (NILP (ok_if_already_exists)
       || INTEGERP (ok_if_already_exists))
 #endif
   if (NILP (ok_if_already_exists)
       || INTEGERP (ok_if_already_exists))
-    barf_or_query_if_file_exists (encoded_newname, "rename to it",
+    barf_or_query_if_file_exists (newname, "rename to it",
                                  INTEGERP (ok_if_already_exists), 0, 0);
 #ifndef BSD4_1
   if (0 > rename (SDATA (encoded_file), SDATA (encoded_newname)))
                                  INTEGERP (ok_if_already_exists), 0, 0);
 #ifndef BSD4_1
   if (0 > rename (SDATA (encoded_file), SDATA (encoded_newname)))
@@ -2782,23 +2798,16 @@ This is what happens in interactive use with M-x.  */)
                                  NILP (ok_if_already_exists) ? Qnil : Qt);
           else
 #endif
                                  NILP (ok_if_already_exists) ? Qnil : Qt);
           else
 #endif
-            Fcopy_file (file, newname,
-                        /* We have already prompted if it was an integer,
-                           so don't have copy-file prompt again.  */
-                        NILP (ok_if_already_exists) ? Qnil : Qt,
-                       Qt, Qnil);
+           Fcopy_file (file, newname,
+                       /* We have already prompted if it was an integer,
+                          so don't have copy-file prompt again.  */
+                       NILP (ok_if_already_exists) ? Qnil : Qt,
+                       Qt, Qt);
+
          Fdelete_file (file);
        }
       else
          Fdelete_file (file);
        }
       else
-#ifdef NO_ARG_ARRAY
-       {
-         args[0] = file;
-         args[1] = newname;
-         report_file_error ("Renaming", Flist (2, args));
-       }
-#else
-       report_file_error ("Renaming", Flist (2, &file));
-#endif
+       report_file_error ("Renaming", list2 (file, newname));
     }
   UNGCPRO;
   return Qnil;
     }
   UNGCPRO;
   return Qnil;
@@ -2814,9 +2823,6 @@ This is what happens in interactive use with M-x.  */)
      (file, newname, ok_if_already_exists)
      Lisp_Object file, newname, ok_if_already_exists;
 {
      (file, newname, ok_if_already_exists)
      Lisp_Object file, newname, ok_if_already_exists;
 {
-#ifdef NO_ARG_ARRAY
-  Lisp_Object args[2];
-#endif
   Lisp_Object handler;
   Lisp_Object encoded_file, encoded_newname;
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
   Lisp_Object handler;
   Lisp_Object encoded_file, encoded_newname;
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
@@ -2851,20 +2857,12 @@ This is what happens in interactive use with M-x.  */)
 
   if (NILP (ok_if_already_exists)
       || INTEGERP (ok_if_already_exists))
 
   if (NILP (ok_if_already_exists)
       || INTEGERP (ok_if_already_exists))
-    barf_or_query_if_file_exists (encoded_newname, "make it a new name",
+    barf_or_query_if_file_exists (newname, "make it a new name",
                                  INTEGERP (ok_if_already_exists), 0, 0);
 
   unlink (SDATA (newname));
   if (0 > link (SDATA (encoded_file), SDATA (encoded_newname)))
                                  INTEGERP (ok_if_already_exists), 0, 0);
 
   unlink (SDATA (newname));
   if (0 > link (SDATA (encoded_file), SDATA (encoded_newname)))
-    {
-#ifdef NO_ARG_ARRAY
-      args[0] = file;
-      args[1] = newname;
-      report_file_error ("Adding new name", Flist (2, args));
-#else
-      report_file_error ("Adding new name", Flist (2, &file));
-#endif
-    }
+    report_file_error ("Adding new name", list2 (file, newname));
 
   UNGCPRO;
   return Qnil;
 
   UNGCPRO;
   return Qnil;
@@ -2882,9 +2880,6 @@ This happens for interactive use with M-x.  */)
      (filename, linkname, ok_if_already_exists)
      Lisp_Object filename, linkname, ok_if_already_exists;
 {
      (filename, linkname, ok_if_already_exists)
      Lisp_Object filename, linkname, ok_if_already_exists;
 {
-#ifdef NO_ARG_ARRAY
-  Lisp_Object args[2];
-#endif
   Lisp_Object handler;
   Lisp_Object encoded_filename, encoded_linkname;
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
   Lisp_Object handler;
   Lisp_Object encoded_filename, encoded_linkname;
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
@@ -2923,7 +2918,7 @@ This happens for interactive use with M-x.  */)
 
   if (NILP (ok_if_already_exists)
       || INTEGERP (ok_if_already_exists))
 
   if (NILP (ok_if_already_exists)
       || INTEGERP (ok_if_already_exists))
-    barf_or_query_if_file_exists (encoded_linkname, "make it a link",
+    barf_or_query_if_file_exists (linkname, "make it a link",
                                  INTEGERP (ok_if_already_exists), 0, 0);
   if (0 > symlink (SDATA (encoded_filename),
                   SDATA (encoded_linkname)))
                                  INTEGERP (ok_if_already_exists), 0, 0);
   if (0 > symlink (SDATA (encoded_filename),
                   SDATA (encoded_linkname)))
@@ -2940,13 +2935,7 @@ This happens for interactive use with M-x.  */)
            }
        }
 
            }
        }
 
-#ifdef NO_ARG_ARRAY
-      args[0] = filename;
-      args[1] = linkname;
-      report_file_error ("Making symbolic link", Flist (2, args));
-#else
-      report_file_error ("Making symbolic link", Flist (2, &filename));
-#endif
+      report_file_error ("Making symbolic link", list2 (filename, linkname));
     }
   UNGCPRO;
   return Qnil;
     }
   UNGCPRO;
   return Qnil;
@@ -3372,8 +3361,10 @@ searchable directory.  */)
 }
 
 DEFUN ("file-regular-p", Ffile_regular_p, Sfile_regular_p, 1, 1, 0,
 }
 
 DEFUN ("file-regular-p", Ffile_regular_p, Sfile_regular_p, 1, 1, 0,
-       doc: /* Return t if file FILENAME is the name of a regular file.
-This is the sort of file that holds an ordinary stream of data bytes.  */)
+       doc: /* Return t if FILENAME names a regular file.
+This is the sort of file that holds an ordinary stream of data bytes.
+Symbolic links to regular files count as regular files.
+See `file-symlink-p' to distinguish symlinks.  */)
      (filename)
      Lisp_Object filename;
 {
      (filename)
      Lisp_Object filename;
 {
@@ -3550,11 +3541,7 @@ Use the current time if TIME is nil.  TIME is in the format of
   return Qt;
 }
 \f
   return Qt;
 }
 \f
-#ifdef __NetBSD__
-#define unix 42
-#endif
-
-#ifdef unix
+#ifdef HAVE_SYNC
 DEFUN ("unix-sync", Funix_sync, Sunix_sync, 0, 0, "",
        doc: /* Tell Unix to finish all pending disk updates.  */)
      ()
 DEFUN ("unix-sync", Funix_sync, Sunix_sync, 0, 0, "",
        doc: /* Tell Unix to finish all pending disk updates.  */)
      ()
@@ -3563,7 +3550,7 @@ DEFUN ("unix-sync", Funix_sync, Sunix_sync, 0, 0, "",
   return Qnil;
 }
 
   return Qnil;
 }
 
-#endif /* unix */
+#endif /* HAVE_SYNC */
 
 DEFUN ("file-newer-than-file-p", Ffile_newer_than_file_p, Sfile_newer_than_file_p, 2, 2, 0,
        doc: /* Return t if file FILE1 is newer than file FILE2.
 
 DEFUN ("file-newer-than-file-p", Ffile_newer_than_file_p, Sfile_newer_than_file_p, 2, 2, 0,
        doc: /* Return t if file FILE1 is newer than file FILE2.
@@ -3745,7 +3732,7 @@ actually used.  */)
   int set_coding_system = 0;
   int coding_system_decided = 0;
   int read_quit = 0;
   int set_coding_system = 0;
   int coding_system_decided = 0;
   int read_quit = 0;
-  int old_Vdeactivate_mark = Vdeactivate_mark;
+  Lisp_Object old_Vdeactivate_mark = Vdeactivate_mark;
   int we_locked_file = 0;
 
   if (current_buffer->base_buffer && ! NILP (visit))
   int we_locked_file = 0;
 
   if (current_buffer->base_buffer && ! NILP (visit))
@@ -3822,9 +3809,8 @@ actually used.  */)
        goto notfound;
 
       if (! NILP (replace) || ! NILP (beg) || ! NILP (end))
        goto notfound;
 
       if (! NILP (replace) || ! NILP (beg) || ! NILP (end))
-       Fsignal (Qfile_error,
-                Fcons (build_string ("not a regular file"),
-                       Fcons (orig_filename, Qnil)));
+       xsignal2 (Qfile_error,
+                 build_string ("not a regular file"), orig_filename);
     }
 #endif
 
     }
 #endif
 
@@ -4307,11 +4293,8 @@ actually used.  */)
        {
          xfree (conversion_buffer);
          coding_free_composition_data (&coding);
        {
          xfree (conversion_buffer);
          coding_free_composition_data (&coding);
-         if (how_much == -1)
-           error ("IO error reading %s: %s",
-                  SDATA (orig_filename), emacs_strerror (errno));
-         else if (how_much == -2)
-           error ("maximum buffer size exceeded");
+         error ("IO error reading %s: %s",
+                SDATA (orig_filename), emacs_strerror (errno));
        }
 
       /* Compare the beginning of the converted file
        }
 
       /* Compare the beginning of the converted file
@@ -4396,6 +4379,8 @@ actually used.  */)
 
       /* Set `inserted' to the number of inserted characters.  */
       inserted = PT - temp;
 
       /* Set `inserted' to the number of inserted characters.  */
       inserted = PT - temp;
+      /* Set point before the inserted characters.  */
+      SET_PT_BOTH (temp, same_at_start);
 
       xfree (conversion_buffer);
       emacs_close (fd);
 
       xfree (conversion_buffer);
       emacs_close (fd);
@@ -4530,6 +4515,8 @@ actually used.  */)
 #endif
       Vdeactivate_mark = old_Vdeactivate_mark;
     }
 #endif
       Vdeactivate_mark = old_Vdeactivate_mark;
     }
+  else
+    Vdeactivate_mark = Qt;
 
   /* Make the text read part of the buffer.  */
   GAP_SIZE -= inserted;
 
   /* Make the text read part of the buffer.  */
   GAP_SIZE -= inserted;
@@ -4696,9 +4683,8 @@ actually used.  */)
        }
 #endif /* CLASH_DETECTION */
       if (not_regular)
        }
 #endif /* CLASH_DETECTION */
       if (not_regular)
-       Fsignal (Qfile_error,
-                Fcons (build_string ("not a regular file"),
-                       Fcons (orig_filename, Qnil)));
+       xsignal2 (Qfile_error,
+                 build_string ("not a regular file"), orig_filename);
     }
 
   if (set_coding_system)
     }
 
   if (set_coding_system)
@@ -4824,6 +4810,8 @@ choose_write_coding_system (start, end, filename,
       /* ... but with the special flag to indicate not to strip off
         leading code of eight-bit-control chars.  */
       coding->flags = 1;
       /* ... but with the special flag to indicate not to strip off
         leading code of eight-bit-control chars.  */
       coding->flags = 1;
+      /* We force LF for end-of-line because that is faster.  */
+      coding->eol_type = CODING_EOL_LF;
       goto done_setup_coding;
     }
   else if (!NILP (Vcoding_system_for_write))
       goto done_setup_coding;
     }
   else if (!NILP (Vcoding_system_for_write))
@@ -4916,6 +4904,8 @@ choose_write_coding_system (start, end, filename,
   setup_coding_system (Fcheck_coding_system (val), coding);
 
  done_setup_coding:
   setup_coding_system (Fcheck_coding_system (val), coding);
 
  done_setup_coding:
+  if (coding->eol_type == CODING_EOL_UNDECIDED)
+    coding->eol_type = system_eol_type;
   if (!STRINGP (start) && !NILP (current_buffer->selective_display))
     coding->mode |= CODING_MODE_SELECTIVE_DISPLAY;
 }
   if (!STRINGP (start) && !NILP (current_buffer->selective_display))
     coding->mode |= CODING_MODE_SELECTIVE_DISPLAY;
 }
@@ -4987,6 +4977,7 @@ This does code conversion according to the value of
   if (!NILP (start) && !STRINGP (start))
     validate_region (&start, &end);
 
   if (!NILP (start) && !STRINGP (start))
     validate_region (&start, &end);
 
+  visit_file = Qnil;
   GCPRO5 (start, filename, visit, visit_file, lockname);
 
   filename = Fexpand_file_name (filename, Qnil);
   GCPRO5 (start, filename, visit, visit_file, lockname);
 
   filename = Fexpand_file_name (filename, Qnil);
@@ -5281,7 +5272,7 @@ This does code conversion according to the value of
      Disk full in NFS may be reported here.  */
   /* mib says that closing the file will try to write as fast as NFS can do
      it, and that means the fsync here is not crucial for autosave files.  */
      Disk full in NFS may be reported here.  */
   /* mib says that closing the file will try to write as fast as NFS can do
      it, and that means the fsync here is not crucial for autosave files.  */
-  if (!auto_saving && fsync (desc) < 0)
+  if (!auto_saving && !write_region_inhibit_fsync && fsync (desc) < 0)
     {
       /* If fsync fails with EINTR, don't treat that as serious.  */
       if (errno != EINTR)
     {
       /* If fsync fails with EINTR, don't treat that as serious.  */
       if (errno != EINTR)
@@ -5752,6 +5743,8 @@ auto_save_error (error)
   Lisp_Object args[3], msg;
   int i, nbytes;
   struct gcpro gcpro1;
   Lisp_Object args[3], msg;
   int i, nbytes;
   struct gcpro gcpro1;
+  char *msgbuf;
+  USE_SAFE_ALLOCA;
 
   ring_bell ();
 
 
   ring_bell ();
 
@@ -5761,16 +5754,19 @@ auto_save_error (error)
   msg = Fformat (3, args);
   GCPRO1 (msg);
   nbytes = SBYTES (msg);
   msg = Fformat (3, args);
   GCPRO1 (msg);
   nbytes = SBYTES (msg);
+  SAFE_ALLOCA (msgbuf, char *, nbytes);
+  bcopy (SDATA (msg), msgbuf, nbytes);
 
   for (i = 0; i < 3; ++i)
     {
       if (i == 0)
 
   for (i = 0; i < 3; ++i)
     {
       if (i == 0)
-       message2 (SDATA (msg), nbytes, STRING_MULTIBYTE (msg));
+       message2 (msgbuf, nbytes, STRING_MULTIBYTE (msg));
       else
       else
-       message2_nolog (SDATA (msg), nbytes, STRING_MULTIBYTE (msg));
+       message2_nolog (msgbuf, nbytes, STRING_MULTIBYTE (msg));
       Fsleep_for (make_number (1), Qnil);
     }
 
       Fsleep_for (make_number (1), Qnil);
     }
 
+  SAFE_FREE ();
   UNGCPRO;
   return Qnil;
 }
   UNGCPRO;
   return Qnil;
 }
@@ -5802,13 +5798,17 @@ auto_save_1 ()
 }
 
 static Lisp_Object
 }
 
 static Lisp_Object
-do_auto_save_unwind (stream)  /* used as unwind-protect function */
-     Lisp_Object stream;
+do_auto_save_unwind (arg)  /* used as unwind-protect function */
+     Lisp_Object arg;
 {
 {
+  FILE *stream = (FILE *) XSAVE_VALUE (arg)->pointer;
   auto_saving = 0;
   auto_saving = 0;
-  if (!NILP (stream))
-    fclose ((FILE *) (XFASTINT (XCAR (stream)) << 16
-                     | XFASTINT (XCDR (stream))));
+  if (stream != NULL)
+    {
+      BLOCK_INPUT;
+      fclose (stream);
+      UNBLOCK_INPUT;
+    }
   return Qnil;
 }
 
   return Qnil;
 }
 
@@ -5824,7 +5824,11 @@ static Lisp_Object
 do_auto_save_make_dir (dir)
      Lisp_Object dir;
 {
 do_auto_save_make_dir (dir)
      Lisp_Object dir;
 {
-  return call2 (Qmake_directory, dir, Qt);
+  Lisp_Object mode;
+
+  call2 (Qmake_directory, dir, Qt);
+  XSETFASTINT (mode, 0700);
+  return Fset_file_modes (dir, mode);
 }
 
 static Lisp_Object
 }
 
 static Lisp_Object
@@ -5853,8 +5857,7 @@ A non-nil CURRENT-ONLY argument means save only current buffer.  */)
   int auto_saved = 0;
   int do_handled_files;
   Lisp_Object oquit;
   int auto_saved = 0;
   int do_handled_files;
   Lisp_Object oquit;
-  FILE *stream;
-  Lisp_Object lispstream;
+  FILE *stream = NULL;
   int count = SPECPDL_INDEX ();
   int orig_minibuffer_auto_raise = minibuffer_auto_raise;
   int old_message_p = 0;
   int count = SPECPDL_INDEX ();
   int orig_minibuffer_auto_raise = minibuffer_auto_raise;
   int old_message_p = 0;
@@ -5906,24 +5909,10 @@ A non-nil CURRENT-ONLY argument means save only current buffer.  */)
        }
 
       stream = fopen (SDATA (listfile), "w");
        }
 
       stream = fopen (SDATA (listfile), "w");
-      if (stream != NULL)
-       {
-         /* Arrange to close that file whether or not we get an error.
-            Also reset auto_saving to 0.  */
-         lispstream = Fcons (Qnil, Qnil);
-         XSETCARFASTINT (lispstream, (EMACS_UINT)stream >> 16);
-         XSETCDRFASTINT (lispstream, (EMACS_UINT)stream & 0xffff);
-       }
-      else
-       lispstream = Qnil;
-    }
-  else
-    {
-      stream = NULL;
-      lispstream = Qnil;
     }
 
     }
 
-  record_unwind_protect (do_auto_save_unwind, lispstream);
+  record_unwind_protect (do_auto_save_unwind,
+                        make_save_value (stream, 0));
   record_unwind_protect (do_auto_save_unwind_1,
                         make_number (minibuffer_auto_raise));
   minibuffer_auto_raise = 0;
   record_unwind_protect (do_auto_save_unwind_1,
                         make_number (minibuffer_auto_raise));
   minibuffer_auto_raise = 0;
@@ -5949,6 +5938,7 @@ A non-nil CURRENT-ONLY argument means save only current buffer.  */)
        if (STRINGP (b->auto_save_file_name)
            && stream != NULL && do_handled_files == 0)
          {
        if (STRINGP (b->auto_save_file_name)
            && stream != NULL && do_handled_files == 0)
          {
+           BLOCK_INPUT;
            if (!NILP (b->filename))
              {
                fwrite (SDATA (b->filename), 1,
            if (!NILP (b->filename))
              {
                fwrite (SDATA (b->filename), 1,
@@ -5958,6 +5948,7 @@ A non-nil CURRENT-ONLY argument means save only current buffer.  */)
            fwrite (SDATA (b->auto_save_file_name), 1,
                    SBYTES (b->auto_save_file_name), stream);
            putc ('\n', stream);
            fwrite (SDATA (b->auto_save_file_name), 1,
                    SBYTES (b->auto_save_file_name), stream);
            putc ('\n', stream);
+           UNBLOCK_INPUT;
          }
 
        if (!NILP (current_only)
          }
 
        if (!NILP (current_only)
@@ -6037,7 +6028,7 @@ A non-nil CURRENT-ONLY argument means save only current buffer.  */)
        {
          /* If we are going to restore an old message,
             give time to read ours.  */
        {
          /* If we are going to restore an old message,
             give time to read ours.  */
-         sit_for (1, 0, 0, 0, 0);
+         sit_for (make_number (1), 0, 0);
          restore_message ();
        }
       else
          restore_message ();
        }
       else
@@ -6174,7 +6165,7 @@ DEFUN ("read-file-name-internal", Fread_file_name_internal, Sread_file_name_inte
   if (NILP (action))
     {
       specdir = Ffile_name_directory (string);
   if (NILP (action))
     {
       specdir = Ffile_name_directory (string);
-      val = Ffile_name_completion (name, realdir);
+      val = Ffile_name_completion (name, realdir, Vread_file_name_predicate);
       UNGCPRO;
       if (!STRINGP (val))
        {
       UNGCPRO;
       if (!STRINGP (val))
        {
@@ -6212,9 +6203,9 @@ DEFUN ("read-file-name-internal", Fread_file_name_internal, Sread_file_name_inte
            {
              Lisp_Object tem = XCAR (all);
              int len;
            {
              Lisp_Object tem = XCAR (all);
              int len;
-             if (STRINGP (tem) &&
-                 (len = SCHARS (tem), len > 0) &&
-                 IS_DIRECTORY_SEP (SREF (tem, len-1)))
+             if (STRINGP (tem)
+                 && (len = SBYTES (tem), len > 0)
+                 && IS_DIRECTORY_SEP (SREF (tem, len-1)))
                comp = Fcons (tem, comp);
            }
        }
                comp = Fcons (tem, comp);
            }
        }
@@ -6222,13 +6213,17 @@ DEFUN ("read-file-name-internal", Fread_file_name_internal, Sread_file_name_inte
 #endif
        {
          /* Must do it the hard (and slow) way.  */
 #endif
        {
          /* Must do it the hard (and slow) way.  */
+         Lisp_Object tem;
          GCPRO3 (all, comp, specdir);
          count = SPECPDL_INDEX ();
          record_unwind_protect (read_file_name_cleanup, current_buffer->directory);
          current_buffer->directory = realdir;
          for (comp = Qnil; CONSP (all); all = XCDR (all))
          GCPRO3 (all, comp, specdir);
          count = SPECPDL_INDEX ();
          record_unwind_protect (read_file_name_cleanup, current_buffer->directory);
          current_buffer->directory = realdir;
          for (comp = Qnil; CONSP (all); all = XCDR (all))
-           if (!NILP (call1 (Vread_file_name_predicate, XCAR (all))))
-             comp = Fcons (XCAR (all), comp);
+           {
+             tem = call1 (Vread_file_name_predicate, XCAR (all));
+             if (!NILP (tem))
+               comp = Fcons (XCAR (all), comp);
+           }
          unbind_to (count, Qnil);
          UNGCPRO;
        }
          unbind_to (count, Qnil);
          UNGCPRO;
        }
@@ -6435,7 +6430,7 @@ and `read-file-name-function'.  */)
       if (! replace_in_history)
        add_to_history = 1;
 
       if (! replace_in_history)
        add_to_history = 1;
 
-      val = empty_string;
+      val = empty_unibyte_string;
     }
 
   unbind_to (count, Qnil);
     }
 
   unbind_to (count, Qnil);
@@ -6602,19 +6597,17 @@ of file names regardless of the current language environment.  */);
   staticpro (&Qcar_less_than_car);
 
   Fput (Qfile_error, Qerror_conditions,
   staticpro (&Qcar_less_than_car);
 
   Fput (Qfile_error, Qerror_conditions,
-       Fcons (Qfile_error, Fcons (Qerror, Qnil)));
+       list2 (Qfile_error, Qerror));
   Fput (Qfile_error, Qerror_message,
        build_string ("File error"));
 
   Fput (Qfile_already_exists, Qerror_conditions,
   Fput (Qfile_error, Qerror_message,
        build_string ("File error"));
 
   Fput (Qfile_already_exists, Qerror_conditions,
-       Fcons (Qfile_already_exists,
-              Fcons (Qfile_error, Fcons (Qerror, Qnil))));
+       list3 (Qfile_already_exists, Qfile_error, Qerror));
   Fput (Qfile_already_exists, Qerror_message,
        build_string ("File already exists"));
 
   Fput (Qfile_date_error, Qerror_conditions,
   Fput (Qfile_already_exists, Qerror_message,
        build_string ("File already exists"));
 
   Fput (Qfile_date_error, Qerror_conditions,
-       Fcons (Qfile_date_error,
-              Fcons (Qfile_error, Fcons (Qerror, Qnil))));
+       list3 (Qfile_date_error, Qfile_error, Qerror));
   Fput (Qfile_date_error, Qerror_message,
        build_string ("Cannot set file date"));
 
   Fput (Qfile_date_error, Qerror_message,
        build_string ("Cannot set file date"));
 
@@ -6690,8 +6683,9 @@ or local variable spec of the tailing lines with `coding:' tag.  */);
 
   DEFVAR_LISP ("after-insert-file-functions", &Vafter_insert_file_functions,
               doc: /* A list of functions to be called at the end of `insert-file-contents'.
 
   DEFVAR_LISP ("after-insert-file-functions", &Vafter_insert_file_functions,
               doc: /* A list of functions to be called at the end of `insert-file-contents'.
-Each is passed one argument, the number of characters inserted.
-It should return the new character count, and leave point the same.
+Each is passed one argument, the number of characters inserted,
+with point at the start of the inserted text.  Each function
+should leave point the same, and return the new character count.
 If `insert-file-contents' is intercepted by a handler from
 `file-name-handler-alist', that handler is responsible for calling the
 functions in `after-insert-file-functions' if appropriate.  */);
 If `insert-file-contents' is intercepted by a handler from
 `file-name-handler-alist', that handler is responsible for calling the
 functions in `after-insert-file-functions' if appropriate.  */);
@@ -6738,6 +6732,14 @@ shortly after Emacs reads your `.emacs' file, if you have not yet given it
 a non-nil value.  */);
   Vauto_save_list_file_name = Qnil;
 
 a non-nil value.  */);
   Vauto_save_list_file_name = Qnil;
 
+#ifdef HAVE_FSYNC
+  DEFVAR_BOOL ("write-region-inhibit-fsync", &write_region_inhibit_fsync,
+              doc: /* *Non-nil means don't call fsync in `write-region'.
+This variable affects calls to `write-region' as well as save commands.
+A non-nil value may result in data loss!  */);
+  write_region_inhibit_fsync = 0;
+#endif
+
   defsubr (&Sfind_file_name_handler);
   defsubr (&Sfile_name_directory);
   defsubr (&Sfile_name_nondirectory);
   defsubr (&Sfind_file_name_handler);
   defsubr (&Sfile_name_directory);
   defsubr (&Sfile_name_nondirectory);
@@ -6794,7 +6796,7 @@ a non-nil value.  */);
   defsubr (&Sread_file_name);
   defsubr (&Snext_read_file_uses_dialog_p);
 
   defsubr (&Sread_file_name);
   defsubr (&Snext_read_file_uses_dialog_p);
 
-#ifdef unix
+#ifdef HAVE_SYNC
   defsubr (&Sunix_sync);
 #endif
 }
   defsubr (&Sunix_sync);
 #endif
 }