]> code.delx.au - gnu-emacs/blobdiff - src/fileio.c
Merge from emacs-24; up to 2012-05-07T14:57:18Z!michael.albinus@gmx.de
[gnu-emacs] / src / fileio.c
index 3a74672b9a64251796ca6b6ce022f076eace6ebd..6c4e34d7312dd4f1bfce437cfdefb0f96a82818d 100644 (file)
@@ -1,6 +1,6 @@
 /* File IO for GNU Emacs.
 
-Copyright (C) 1985-1988, 1993-2012  Free Software Foundation, Inc.
+Copyright (C) 1985-1988, 1993-2012 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -23,14 +23,12 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <stdio.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <setjmp.h>
 #include <unistd.h>
 
 #ifdef HAVE_PWD_H
 #include <pwd.h>
 #endif
 
-#include <ctype.h>
 #include <errno.h>
 
 #ifdef HAVE_LIBSELINUX
@@ -38,10 +36,12 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <selinux/context.h>
 #endif
 
+#include <c-ctype.h>
+
 #include "lisp.h"
 #include "intervals.h"
-#include "buffer.h"
 #include "character.h"
+#include "buffer.h"
 #include "coding.h"
 #include "window.h"
 #include "blockinput.h"
@@ -67,15 +67,16 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #define IS_DRIVE(x) ((x) >= 'A' && (x) <= 'z')
 #endif
 #ifdef WINDOWSNT
-#define IS_DRIVE(x) isalpha ((unsigned char) (x))
+#define IS_DRIVE(x) c_isalpha (x)
 #endif
 /* Need to lower-case the drive letter, or else expanded
    filenames will sometimes compare unequal, because
    `expand-file-name' doesn't always down-case the drive letter.  */
-#define DRIVE_LETTER(x) (tolower ((unsigned char) (x)))
+#define DRIVE_LETTER(x) c_tolower (x)
 #endif
 
 #include "systime.h"
+#include <stat-time.h>
 
 #ifdef HPUX
 #include <netio.h>
@@ -83,22 +84,18 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "commands.h"
 
-#ifndef FILE_SYSTEM_CASE
-#define FILE_SYSTEM_CASE(filename)  (filename)
-#endif
-
-/* Nonzero during writing of auto-save files */
-static int auto_saving;
+/* True during writing of auto-save files.  */
+static bool auto_saving;
 
-/* Nonzero umask during creation of auto-save directories */
-static int auto_saving_dir_umask;
+/* Nonzero umask during creation of auto-save directories */
+static mode_t auto_saving_dir_umask;
 
 /* Set by auto_save_1 to mode of original file so Fwrite_region will create
-   a new file with the same mode as the original */
-static int auto_save_mode_bits;
+   a new file with the same mode as the original */
+static mode_t auto_save_mode_bits;
 
-/* Set by auto_save_1 if an error occurred during the last auto-save. */
-static int auto_save_error_occurred;
+/* Set by auto_save_1 if an error occurred during the last auto-save.  */
+static bool auto_save_error_occurred;
 
 /* The symbol bound to coding-system-for-read when
    insert-file-contents is called for recovering a file.  This is not
@@ -111,7 +108,7 @@ static Lisp_Object Qauto_save_coding;
    which gives a list of operations it handles..  */
 static Lisp_Object Qoperations;
 
-/* Lisp functions for translating file formats */
+/* Lisp functions for translating file formats */
 static Lisp_Object Qformat_decode, Qformat_annotate_function;
 
 /* Lisp function for setting buffer-file-coding-system and the
@@ -147,11 +144,10 @@ Lisp_Object Qfile_name_history;
 
 static Lisp_Object Qcar_less_than_car;
 
-static Lisp_Object Fmake_symbolic_link (Lisp_Object, Lisp_Object, Lisp_Object);
-static int a_write (int, Lisp_Object, EMACS_INT, EMACS_INT,
-                    Lisp_Object *, struct coding_system *);
-static int e_write (int, Lisp_Object, EMACS_INT, EMACS_INT,
-                   struct coding_system *);
+static bool a_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t,
+                    Lisp_Object *, struct coding_system *);
+static bool e_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t,
+                    struct coding_system *);
 
 \f
 void
@@ -163,8 +159,7 @@ report_file_error (const char *string, Lisp_Object data)
 
   synchronize_system_messages_locale ();
   str = strerror (errorno);
-  errstring = code_convert_string_norecord (make_unibyte_string (str,
-                                                                strlen (str)),
+  errstring = code_convert_string_norecord (build_unibyte_string (str),
                                            Vlocale_coding_system, 0);
 
   while (1)
@@ -260,7 +255,7 @@ use the standard functions without calling themselves recursively.  */)
 {
   /* This function must not munge the match data.  */
   Lisp_Object chain, inhibited_handlers, result;
-  int pos = -1;
+  ptrdiff_t pos = -1;
 
   result = Qnil;
   CHECK_STRING (filename);
@@ -278,7 +273,7 @@ use the standard functions without calling themselves recursively.  */)
       if (CONSP (elt))
        {
          Lisp_Object string = XCAR (elt);
-         EMACS_INT match_pos;
+         ptrdiff_t match_pos;
          Lisp_Object handler = XCDR (elt);
          Lisp_Object operations = Qnil;
 
@@ -334,9 +329,8 @@ Given a Unix syntax file name, returns a string ending in slash.  */)
       return STRINGP (handled_name) ? handled_name : Qnil;
     }
 
-  filename = FILE_SYSTEM_CASE (filename);
 #ifdef DOS_NT
-  beg = (char *) alloca (SBYTES (filename) + 1);
+  beg = alloca (SBYTES (filename) + 1);
   memcpy (beg, SSDATA (filename), SBYTES (filename) + 1);
 #else
   beg = SSDATA (filename);
@@ -365,12 +359,12 @@ Given a Unix syntax file name, returns a string ending in slash.  */)
 
       if (p == beg + 4 && IS_DIRECTORY_SEP (*beg) && beg[1] == ':')
        {
-         strncpy (res, beg, 2);
+         memcpy (res, beg, 2);
          beg += 2;
          r += 2;
        }
 
-      if (getdefdir (toupper ((unsigned char) *beg) - 'A' + 1, r))
+      if (getdefdir (c_toupper (*beg) - 'A' + 1, r))
        {
          if (!IS_DIRECTORY_SEP (res[strlen (res) - 1]))
            strcat (res, "/");
@@ -453,32 +447,33 @@ get a current directory to run processes in.  */)
   return Ffile_name_directory (filename);
 }
 
-\f
-static char *
-file_name_as_directory (char *out, const char *in)
-{
-  ptrdiff_t len = strlen (in);
+/* Convert from file name SRC of length SRCLEN to directory name
+   in DST.  On UNIX, just make sure there is a terminating /.
+   Return the length of DST.  */
 
-  if (len == 0)
+static ptrdiff_t
+file_name_as_directory (char *dst, const char *src, ptrdiff_t srclen)
+{
+  if (srclen == 0)
     {
-      out[0] = '.';
-      out[1] = '/';
-      out[2] = 0;
-      return out;
+      dst[0] = '.';
+      dst[1] = '/';
+      dst[2] = '\0';
+      return 2;
     }
 
-  strcpy (out, in);
+  strcpy (dst, src);
 
-  /* For Unix syntax, Append a slash if necessary */
-  if (!IS_DIRECTORY_SEP (out[len - 1]))
+  if (!IS_DIRECTORY_SEP (dst[srclen - 1]))
     {
-      out[len] = DIRECTORY_SEP;
-      out[len + 1] = '\0';
+      dst[srclen] = DIRECTORY_SEP;
+      dst[srclen + 1] = '\0';
+      srclen++;
     }
 #ifdef DOS_NT
-  dostounix_filename (out);
+  dostounix_filename (dst);
 #endif
-  return out;
+  return srclen;
 }
 
 DEFUN ("file-name-as-directory", Ffile_name_as_directory,
@@ -492,6 +487,7 @@ For a Unix-syntax file name, just appends a slash.  */)
   (Lisp_Object file)
 {
   char *buf;
+  ptrdiff_t length;
   Lisp_Object handler;
 
   CHECK_STRING (file);
@@ -510,40 +506,35 @@ For a Unix-syntax file name, just appends a slash.  */)
       error ("Invalid handler in `file-name-handler-alist'");
     }
 
-  buf = (char *) alloca (SBYTES (file) + 10);
-  file_name_as_directory (buf, SSDATA (file));
-  return make_specified_string (buf, -1, strlen (buf),
-                               STRING_MULTIBYTE (file));
+  buf = alloca (SBYTES (file) + 10);
+  length = file_name_as_directory (buf, SSDATA (file), SBYTES (file));
+  return make_specified_string (buf, -1, length, STRING_MULTIBYTE (file));
 }
 \f
-/*
- * Convert from directory name to filename.
* On UNIX, it's simple: just make sure there isn't a terminating /
+/* Convert from directory name SRC of length SRCLEN to
+   file name in DST.  On UNIX, just make sure there isn't
  a terminating /.  Return the length of DST.  */
 
- * Value is nonzero if the string output is different from the input.
- */
-
-static int
-directory_file_name (char *src, char *dst)
+static ptrdiff_t
+directory_file_name (char *dst, char *src, ptrdiff_t srclen)
 {
-  ptrdiff_t slen;
-
-  slen = strlen (src);
-
   /* Process as Unix format: just remove any final slash.
      But leave "/" unchanged; do not change it to "".  */
   strcpy (dst, src);
-  if (slen > 1
-      && IS_DIRECTORY_SEP (dst[slen - 1])
+  if (srclen > 1
+      && IS_DIRECTORY_SEP (dst[srclen - 1])
 #ifdef DOS_NT
-      && !IS_ANY_SEP (dst[slen - 2])
+      && !IS_ANY_SEP (dst[srclen - 2])
 #endif
       )
-    dst[slen - 1] = 0;
+    {
+      dst[srclen - 1] = 0;
+      srclen--;
+    }
 #ifdef DOS_NT
   dostounix_filename (dst);
 #endif
-  return 1;
+  return srclen;
 }
 
 DEFUN ("directory-file-name", Fdirectory_file_name, Sdirectory_file_name,
@@ -556,6 +547,7 @@ In Unix-syntax, this function just removes the final slash.  */)
   (Lisp_Object directory)
 {
   char *buf;
+  ptrdiff_t length;
   Lisp_Object handler;
 
   CHECK_STRING (directory);
@@ -575,10 +567,9 @@ In Unix-syntax, this function just removes the final slash.  */)
       error ("Invalid handler in `file-name-handler-alist'");
     }
 
-  buf = (char *) alloca (SBYTES (directory) + 20);
-  directory_file_name (SSDATA (directory), buf);
-  return make_specified_string (buf, -1, strlen (buf),
-                               STRING_MULTIBYTE (directory));
+  buf = alloca (SBYTES (directory) + 20);
+  length = directory_file_name (buf, SSDATA (directory), SBYTES (directory));
+  return make_specified_string (buf, -1, length, STRING_MULTIBYTE (directory));
 }
 
 static const char make_temp_name_tbl[64] =
@@ -603,7 +594,7 @@ static unsigned make_temp_name_count, make_temp_name_count_initialized_p;
    which has no existing file.  To make this work, PREFIX should be
    an absolute file name.
 
-   BASE64_P non-zero means add the pid as 3 characters in base64
+   BASE64_P means add the pid as 3 characters in base64
    encoding.  In this case, 6 characters will be added to PREFIX to
    form the file name.  Otherwise, if Emacs is running on a system
    with long file names, add the pid as a decimal number.
@@ -612,7 +603,7 @@ static unsigned make_temp_name_count, make_temp_name_count_initialized_p;
    generated.  */
 
 Lisp_Object
-make_temp_name (Lisp_Object prefix, int base64_p)
+make_temp_name (Lisp_Object prefix, bool base64_p)
 {
   Lisp_Object val;
   int len, clen;
@@ -769,12 +760,12 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
   struct passwd *pw;
 #ifdef DOS_NT
   int drive = 0;
-  int collapse_newdir = 1;
-  int is_escaped = 0;
+  bool collapse_newdir = 1;
+  bool is_escaped = 0;
 #endif /* DOS_NT */
   ptrdiff_t length;
   Lisp_Object handler, result, handled_name;
-  int multibyte;
+  bool multibyte;
   Lisp_Object hdir;
 
   CHECK_STRING (name);
@@ -864,7 +855,6 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
        UNGCPRO;
       }
   }
-  name = FILE_SYSTEM_CASE (name);
   multibyte = STRING_MULTIBYTE (name);
   if (multibyte != STRING_MULTIBYTE (default_directory))
     {
@@ -877,8 +867,8 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
        }
     }
 
-  /* Make a local copy of nm[] to protect it from GC in DECODE_FILE below. */
-  nm = (char *) alloca (SBYTES (name) + 1);
+  /* Make a local copy of nm[] to protect it from GC in DECODE_FILE below.  */
+  nm = alloca (SBYTES (name) + 1);
   memcpy (nm, SSDATA (name), SBYTES (name) + 1);
 
 #ifdef DOS_NT
@@ -905,7 +895,7 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
   if (drive && IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1]))
     nm++;
 
-  /* Discard any previous drive specifier if nm is now in UNC format. */
+  /* Discard any previous drive specifier if nm is now in UNC format.  */
   if (IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1]))
     {
       drive = 0;
@@ -929,10 +919,9 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
       /* If it turns out that the filename we want to return is just a
         suffix of FILENAME, we don't need to go through and edit
         things; we just need to construct a new string using data
-        starting at the middle of FILENAME.  If we set lose to a
-        non-zero value, that means we've discovered that we can't do
-        that cool trick.  */
-      int lose = 0;
+        starting at the middle of FILENAME.  If we set LOSE, that
+        means we've discovered that we can't do that cool trick.  */
+      bool lose = 0;
       char *p = nm;
 
       while (*p)
@@ -970,7 +959,7 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
            }
          else
 #endif
-         /* drive must be set, so this is okay */
+         /* Drive must be set, so this is okay.  */
          if (strcmp (nm - 2, SSDATA (name)) != 0)
            {
              char temp[] = " :";
@@ -1016,7 +1005,7 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
          if (!(newdir = egetenv ("HOME")))
            newdir = "";
          nm++;
-         /* egetenv may return a unibyte string, which will bite us since
+         /* `egetenv' may return a unibyte string, which will bite us since
             we expect the directory to be multibyte.  */
          tem = build_string (newdir);
          if (!STRING_MULTIBYTE (tem))
@@ -1058,17 +1047,17 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
      use the drive's current directory as the prefix if needed.  */
   if (!newdir && drive)
     {
-      /* Get default directory if needed to make nm absolute. */
+      /* Get default directory if needed to make nm absolute.  */
       char *adir = NULL;
       if (!IS_DIRECTORY_SEP (nm[0]))
        {
          adir = alloca (MAXPATHLEN + 1);
-         if (!getdefdir (toupper (drive) - 'A' + 1, adir))
+         if (!getdefdir (c_toupper (drive) - 'A' + 1, adir))
            adir = NULL;
        }
       if (!adir)
        {
-         /* Either nm starts with /, or drive isn't mounted. */
+         /* Either nm starts with /, or drive isn't mounted.  */
          adir = alloca (4);
          adir[0] = DRIVE_LETTER (drive);
          adir[1] = ':';
@@ -1080,11 +1069,11 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
 #endif /* DOS_NT */
 
   /* Finally, if no prefix has been specified and nm is not absolute,
-     then it must be expanded relative to default_directory. */
+     then it must be expanded relative to default_directory.  */
 
   if (1
 #ifndef DOS_NT
-      /* /... alone is not absolute on DOS and Windows. */
+      /* /... alone is not absolute on DOS and Windows.  */
       && !IS_DIRECTORY_SEP (nm[0])
 #endif
 #ifdef WINDOWSNT
@@ -1106,7 +1095,7 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
 #ifdef DOS_NT
   if (newdir)
     {
-      /* First ensure newdir is an absolute name. */
+      /* First ensure newdir is an absolute name.  */
       if (
          /* Detect MSDOS file names with drive specifiers.  */
          ! (IS_DRIVE (newdir[0])
@@ -1121,7 +1110,7 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
             Because of the admonition against calling expand-file-name
             when we have pointers into lisp strings, we accomplish this
             indirectly by prepending newdir to nm if necessary, and using
-            cwd (or the wd of newdir's drive) as the new newdir. */
+            cwd (or the wd of newdir's drive) as the new newdir.  */
          char *adir;
          if (IS_DRIVE (newdir[0]) && IS_DEVICE_SEP (newdir[1]))
            {
@@ -1130,15 +1119,16 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
            }
          if (!IS_DIRECTORY_SEP (nm[0]))
            {
-             char * tmp = alloca (strlen (newdir) + strlen (nm) + 2);
-             file_name_as_directory (tmp, newdir);
+             ptrdiff_t newlen = strlen (newdir);
+             char *tmp = alloca (newlen + strlen (nm) + 2);
+             file_name_as_directory (tmp, newdir, newlen);
              strcat (tmp, nm);
              nm = tmp;
            }
          adir = alloca (MAXPATHLEN + 1);
          if (drive)
            {
-             if (!getdefdir (toupper (drive) - 'A' + 1, adir))
+             if (!getdefdir (c_toupper (drive) - 'A' + 1, adir))
                newdir = "/";
            }
          else
@@ -1146,7 +1136,7 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
          newdir = adir;
        }
 
-      /* Strip off drive name from prefix, if present. */
+      /* Strip off drive name from prefix, if present.  */
       if (IS_DRIVE (newdir[0]) && IS_DEVICE_SEP (newdir[1]))
        {
          drive = newdir[0];
@@ -1180,32 +1170,36 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
       /* Get rid of any slash at the end of newdir, unless newdir is
         just / or // (an incomplete UNC name).  */
       length = strlen (newdir);
+      tlen = length + 1;
       if (length > 1 && IS_DIRECTORY_SEP (newdir[length - 1])
 #ifdef WINDOWSNT
          && !(length == 2 && IS_DIRECTORY_SEP (newdir[0]))
 #endif
          )
        {
-         char *temp = (char *) alloca (length);
+         char *temp = alloca (length);
          memcpy (temp, newdir, length - 1);
          temp[length - 1] = 0;
+         length--;
          newdir = temp;
        }
-      tlen = length + 1;
     }
   else
-    tlen = 0;
+    {
+      length = 0;
+      tlen = 0;
+    }
 
-  /* Now concatenate the directory and name to new space in the stack frame */
+  /* Now concatenate the directory and name to new space in the stack frame */
   tlen += strlen (nm) + 1;
 #ifdef DOS_NT
   /* Reserve space for drive specifier and escape prefix, since either
      or both may need to be inserted.  (The Microsoft x86 compiler
      produces incorrect code if the following two lines are combined.)  */
-  target = (char *) alloca (tlen + 4);
+  target = alloca (tlen + 4);
   target += 4;
 #else  /* not DOS_NT */
-  target = (char *) alloca (tlen);
+  target = alloca (tlen);
 #endif /* not DOS_NT */
   *target = 0;
 
@@ -1225,7 +1219,7 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
            strcpy (target, newdir);
        }
       else
-       file_name_as_directory (target, newdir);
+       file_name_as_directory (target, newdir, length);
     }
 
   strcat (target, nm);
@@ -1292,13 +1286,13 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
       }
 
 #ifdef DOS_NT
-    /* At last, set drive name. */
+    /* At last, set drive name.  */
 #ifdef WINDOWSNT
     /* Except for network file name.  */
     if (!(IS_DIRECTORY_SEP (target[0]) && IS_DIRECTORY_SEP (target[1])))
 #endif /* WINDOWSNT */
       {
-       if (!drive) abort ();
+       if (!drive) emacs_abort ();
        target -= 2;
        target[0] = DRIVE_LETTER (drive);
        target[1] = ':';
@@ -1320,7 +1314,7 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
      and perhaps call the corresponding file handler.  This is needed
      for filenames such as "/foo/../user@host:/bar/../baz".  Expanding
      the ".." component gives us "/user@host:/bar/../baz" which needs
-     to be expanded again. */
+     to be expanded again.  */
   handler = Ffind_file_name_handler (result, Qexpand_file_name);
   if (!NILP (handler))
     {
@@ -1364,7 +1358,6 @@ See also the function `substitute-in-file-name'.")
   ptrdiff_t tlen;
   unsigned char *target;
   struct passwd *pw;
-  int lose;
 
   CHECK_STRING (name);
   nm = SDATA (name);
@@ -1373,8 +1366,8 @@ See also the function `substitute-in-file-name'.")
      If no /./ or /../ we can return right away.  */
   if (nm[0] == '/')
     {
+      bool lose = 0;
       p = nm;
-      lose = 0;
       while (*p)
        {
          if (p[0] == '/' && p[1] == '/'
@@ -1396,7 +1389,7 @@ See also the function `substitute-in-file-name'.")
        }
     }
 
-  /* Now determine directory to start with and put it in NEWDIR */
+  /* Now determine directory to start with and put it in NEWDIR */
 
   newdir = 0;
 
@@ -1409,17 +1402,17 @@ See also the function `substitute-in-file-name'.")
       }
     else  /* ~user/filename */
       {
-       /* Get past ~ to user */
+       /* Get past ~ to user */
        unsigned char *user = nm + 1;
-       /* Find end of name. */
+       /* Find end of name.  */
        unsigned char *ptr = (unsigned char *) strchr (user, '/');
        ptrdiff_t len = ptr ? ptr - user : strlen (user);
-       /* Copy the user name into temp storage. */
-       o = (unsigned char *) alloca (len + 1);
+       /* Copy the user name into temp storage.  */
+       o = alloca (len + 1);
        memcpy (o, user, len);
        o[len] = 0;
 
-       /* Look up the user name. */
+       /* Look up the user name.  */
        BLOCK_INPUT;
        pw = (struct passwd *) getpwnam (o + 1);
        UNBLOCK_INPUT;
@@ -1440,10 +1433,10 @@ See also the function `substitute-in-file-name'.")
       newdir = SDATA (defalt);
     }
 
-  /* Now concatenate the directory and name to new space in the stack frame */
+  /* Now concatenate the directory and name to new space in the stack frame */
 
   tlen = (newdir ? strlen (newdir) + 1 : 0) + strlen (nm) + 1;
-  target = (unsigned char *) alloca (tlen);
+  target = alloca (tlen);
   *target = 0;
 
   if (newdir)
@@ -1456,7 +1449,7 @@ See also the function `substitute-in-file-name'.")
 
   strcat (target, nm);
 
-  /* Now canonicalize by removing /. and /foo/.. if they appear */
+  /* Now canonicalize by removing /. and /foo/.. if they appear */
 
   p = target;
   o = target;
@@ -1498,7 +1491,7 @@ See also the function `substitute-in-file-name'.")
 #endif
 \f
 /* If /~ or // appears, discard everything through first slash.  */
-static int
+static bool
 file_name_absolute_p (const char *filename)
 {
   return
@@ -1528,7 +1521,7 @@ search_embedded_absfilename (char *nm, char *endp)
              )
        {
          for (s = p; *s && (!IS_DIRECTORY_SEP (*s)); s++);
-         if (p[0] == '~' && s > p + 1) /* we've got "/~something/" */
+         if (p[0] == '~' && s > p + 1) /* We've got "/~something/".  */
            {
              char *o = alloca (s - p + 1);
              struct passwd *pw;
@@ -1564,13 +1557,11 @@ If `//' appears, everything up to and including the first of
 those `/' is discarded.  */)
   (Lisp_Object filename)
 {
-  char *nm;
-
-  register char *s, *p, *o, *x, *endp;
+  char *nm, *s, *p, *o, *x, *endp;
   char *target = NULL;
   int total = 0;
-  int substituted = 0;
-  int multibyte;
+  bool substituted = 0;
+  bool multibyte;
   char *xnm;
   Lisp_Object handler;
 
@@ -1593,7 +1584,7 @@ those `/' is discarded.  */)
   /* Always work on a copy of the string, in case GC happens during
      decode of environment variables, causing the original Lisp_String
      data to be relocated.  */
-  nm = (char *) alloca (SBYTES (filename) + 1);
+  nm = alloca (SBYTES (filename) + 1);
   memcpy (nm, SDATA (filename), SBYTES (filename) + 1);
 
 #ifdef DOS_NT
@@ -1612,7 +1603,7 @@ those `/' is discarded.  */)
       (make_specified_string (p, -1, endp - p, multibyte));
 
   /* See if any variables are substituted into the string
-     and find the total length of their values in `total' */
+     and find the total length of their values in `total' */
 
   for (p = nm; p != endp;)
     if (*p != '$')
@@ -1624,7 +1615,7 @@ those `/' is discarded.  */)
          goto badsubst;
        else if (*p == '$')
          {
-           /* "$$" means a single "$" */
+           /* "$$" means a single "$" */
            p++;
            total -= 1;
            substituted = 1;
@@ -1640,19 +1631,19 @@ those `/' is discarded.  */)
        else
          {
            o = p;
-           while (p != endp && (isalnum (*p) || *p == '_')) p++;
+           while (p != endp && (c_isalnum (*p) || *p == '_')) p++;
            s = p;
          }
 
-       /* Copy out the variable name */
-       target = (char *) alloca (s - o + 1);
-       strncpy (target, o, s - o);
+       /* Copy out the variable name */
+       target = alloca (s - o + 1);
+       memcpy (target, o, s - o);
        target[s - o] = 0;
 #ifdef DOS_NT
        strupr (target); /* $home == $HOME etc.  */
 #endif /* DOS_NT */
 
-       /* Get variable value */
+       /* Get variable value */
        o = egetenv (target);
        if (o)
          {
@@ -1662,7 +1653,7 @@ those `/' is discarded.  */)
               env variables twice should be acceptable. Note that
               decoding may cause a garbage collect.  */
            Lisp_Object orig, decoded;
-           orig = make_unibyte_string (o, strlen (o));
+           orig = build_unibyte_string (o);
            decoded = DECODE_FILE (orig);
            total += SBYTES (decoded);
            substituted = 1;
@@ -1674,12 +1665,12 @@ those `/' is discarded.  */)
   if (!substituted)
     return filename;
 
-  /* If substitution required, recopy the string and do it */
-  /* Make space in stack frame for the new copy */
-  xnm = (char *) alloca (SBYTES (filename) + total + 1);
+  /* If substitution required, recopy the string and do it */
+  /* Make space in stack frame for the new copy */
+  xnm = alloca (SBYTES (filename) + total + 1);
   x = xnm;
 
-  /* Copy the rest of the name through, replacing $ constructs with values */
+  /* Copy the rest of the name through, replacing $ constructs with values */
   for (p = nm; *p;)
     if (*p != '$')
       *x++ = *p++;
@@ -1703,19 +1694,19 @@ those `/' is discarded.  */)
        else
          {
            o = p;
-           while (p != endp && (isalnum (*p) || *p == '_')) p++;
+           while (p != endp && (c_isalnum (*p) || *p == '_')) p++;
            s = p;
          }
 
-       /* Copy out the variable name */
-       target = (char *) alloca (s - o + 1);
-       strncpy (target, o, s - o);
+       /* Copy out the variable name */
+       target = alloca (s - o + 1);
+       memcpy (target, o, s - o);
        target[s - o] = 0;
 #ifdef DOS_NT
        strupr (target); /* $home == $HOME etc.  */
 #endif /* DOS_NT */
 
-       /* Get variable value */
+       /* Get variable value */
        o = egetenv (target);
        if (!o)
          {
@@ -1730,13 +1721,13 @@ those `/' is discarded.  */)
            orig = make_unibyte_string (o, orig_length);
            decoded = DECODE_FILE (orig);
            decoded_length = SBYTES (decoded);
-           strncpy (x, SSDATA (decoded), decoded_length);
+           memcpy (x, SDATA (decoded), decoded_length);
            x += decoded_length;
 
            /* If environment variable needed decoding, return value
               needs to be multibyte.  */
            if (decoded_length != orig_length
-               || strncmp (SSDATA (decoded), o, orig_length))
+               || memcmp (SDATA (decoded), o, orig_length))
              multibyte = 1;
          }
       }
@@ -1777,14 +1768,14 @@ expand_and_dir_to_file (Lisp_Object filename, Lisp_Object defdir)
      stat behaves differently depending!  */
   if (SCHARS (absname) > 1
       && IS_DIRECTORY_SEP (SREF (absname, SBYTES (absname) - 1))
-      && !IS_DEVICE_SEP (SREF (absname, SBYTES (absname)-2)))
+      && !IS_DEVICE_SEP (SREF (absname, SBYTES (absname) - 2)))
     /* We cannot take shortcuts; they might be wrong for magic file names.  */
     absname = Fdirectory_file_name (absname);
   return absname;
 }
 \f
 /* Signal an error if the file ABSNAME already exists.
-   If INTERACTIVE is nonzero, ask the user whether to proceed,
+   If INTERACTIVE, ask the user whether to proceed,
    and bypass the error if the user says to go ahead.
    QUERYSTRING is a name for the action that is being considered
    to alter the file.
@@ -1793,19 +1784,20 @@ expand_and_dir_to_file (Lisp_Object filename, Lisp_Object defdir)
    If the file does not exist, STATPTR->st_mode is set to 0.
    If STATPTR is null, we don't store into it.
 
-   If QUICK is nonzero, we ask for y or n, not yes or no.  */
+   If QUICK, ask for y or n, not yes or no.  */
 
 static void
 barf_or_query_if_file_exists (Lisp_Object absname, const char *querystring,
-                             int interactive, struct stat *statptr, int quick)
+                             bool interactive, struct stat *statptr,
+                             bool quick)
 {
-  register Lisp_Object tem, encoded_filename;
+  Lisp_Object tem, encoded_filename;
   struct stat statbuf;
   struct gcpro gcpro1;
 
   encoded_filename = ENCODE_FILE (absname);
 
-  /* stat is a good way to tell whether the file exists,
+  /* `stat' is a good way to tell whether the file exists,
      regardless of what access permissions it has.  */
   if (lstat (SSDATA (encoded_filename), &statbuf) >= 0)
     {
@@ -1867,17 +1859,17 @@ on the system, we copy the SELinux context of FILE to NEWNAME.  */)
   (Lisp_Object file, Lisp_Object newname, Lisp_Object ok_if_already_exists, Lisp_Object keep_time, Lisp_Object preserve_uid_gid, Lisp_Object preserve_selinux_context)
 {
   int ifd, ofd;
-  EMACS_INT n;
+  int n;
   char buf[16 * 1024];
   struct stat st, out_st;
   Lisp_Object handler;
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
-  int count = SPECPDL_INDEX ();
-  int input_file_statable_p;
+  ptrdiff_t count = SPECPDL_INDEX ();
+  bool input_file_statable_p;
   Lisp_Object encoded_file, encoded_newname;
 #if HAVE_LIBSELINUX
   security_context_t con;
-  int fail, conlength = 0;
+  int conlength = 0;
 #endif
 
   encoded_file = encoded_newname = Qnil;
@@ -1925,13 +1917,13 @@ on the system, we copy the SELinux context of FILE to NEWNAME.  */)
       DWORD attributes;
       char * filename;
 
-      EMACS_GET_TIME (now);
       filename = SDATA (encoded_newname);
 
       /* Ensure file is writable while its modified time is set.  */
       attributes = GetFileAttributes (filename);
       SetFileAttributes (filename, attributes & ~FILE_ATTRIBUTE_READONLY);
-      if (set_file_times (filename, now, now))
+      now = current_emacs_time ();
+      if (set_file_times (-1, filename, now, now))
        {
          /* Restore original attributes.  */
          SetFileAttributes (filename, attributes);
@@ -1992,7 +1984,7 @@ on the system, we copy the SELinux context of FILE to NEWNAME.  */)
                    S_IREAD | S_IWRITE);
 #else  /* not MSDOS */
   {
-    int new_mask = 0666;
+    mode_t new_mask = 0666;
     if (input_file_statable_p)
       {
        if (!NILP (preserve_uid_gid))
@@ -2022,7 +2014,7 @@ on the system, we copy the SELinux context of FILE to NEWNAME.  */)
      owner and group.  */
   if (input_file_statable_p)
     {
-      int mode_mask = 07777;
+      mode_t mode_mask = 07777;
       if (!NILP (preserve_uid_gid))
        {
          /* Attempt to change owner and group.  If that doesn't work
@@ -2044,33 +2036,31 @@ on the system, we copy the SELinux context of FILE to NEWNAME.  */)
 #if HAVE_LIBSELINUX
   if (conlength > 0)
     {
-      /* Set the modified context back to the file. */
-      fail = fsetfilecon (ofd, con);
-      if (fail)
+      /* Set the modified context back to the file.  */
+      bool fail = fsetfilecon (ofd, con) != 0;
+      /* See http://debbugs.gnu.org/11245 for ENOTSUP.  */
+      if (fail && errno != ENOTSUP)
        report_file_error ("Doing fsetfilecon", Fcons (newname, Qnil));
 
       freecon (con);
     }
 #endif
 
-  /* Closing the output clobbers the file times on some systems.  */
-  if (emacs_close (ofd) < 0)
-    report_file_error ("I/O error", Fcons (newname, Qnil));
-
   if (input_file_statable_p)
     {
       if (!NILP (keep_time))
        {
-         EMACS_TIME atime, mtime;
-         EMACS_SET_SECS_USECS (atime, st.st_atime, 0);
-         EMACS_SET_SECS_USECS (mtime, st.st_mtime, 0);
-         if (set_file_times (SSDATA (encoded_newname),
-                             atime, mtime))
+         EMACS_TIME atime = get_stat_atime (&st);
+         EMACS_TIME mtime = get_stat_mtime (&st);
+         if (set_file_times (ofd, SSDATA (encoded_newname), atime, mtime))
            xsignal2 (Qfile_date_error,
                      build_string ("Cannot set file date"), newname);
        }
     }
 
+  if (emacs_close (ofd) < 0)
+    report_file_error ("I/O error", Fcons (newname, Qnil));
+
   emacs_close (ifd);
 
 #ifdef MSDOS
@@ -2190,17 +2180,14 @@ internal_delete_file_1 (Lisp_Object ignore)
   return Qt;
 }
 
-/* Delete file FILENAME, returning 1 if successful and 0 if failed.
+/* Delete file FILENAME.
    This ignores `delete-by-moving-to-trash'.  */
 
-int
+void
 internal_delete_file (Lisp_Object filename)
 {
-  Lisp_Object tem;
-
-  tem = internal_condition_case_2 (Fdelete_file, filename, Qnil,
-                                  Qt, internal_delete_file_1);
-  return NILP (tem);
+  internal_condition_case_2 (Fdelete_file, filename, Qnil,
+                            Qt, internal_delete_file_1);
 }
 \f
 DEFUN ("rename-file", Frename_file, Srename_file, 2, 3,
@@ -2264,7 +2251,7 @@ This is what happens in interactive use with M-x.  */)
     {
       if (errno == EXDEV)
        {
-          int count;
+          ptrdiff_t count;
           symlink_target = Ffile_symlink_p (file);
           if (! NILP (symlink_target))
             Fmake_symbolic_link (symlink_target, newname,
@@ -2436,9 +2423,9 @@ On Unix, this is a name starting with a `/' or a `~'.  */)
   return file_name_absolute_p (SSDATA (filename)) ? Qt : Qnil;
 }
 \f
-/* Return nonzero if file FILENAME exists and can be executed.  */
+/* Return true if file FILENAME exists and can be executed.  */
 
-static int
+static bool
 check_executable (char *filename)
 {
 #ifdef DOS_NT
@@ -2458,9 +2445,9 @@ check_executable (char *filename)
 #endif /* not DOS_NT */
 }
 
-/* Return nonzero if file FILENAME exists and can be written.  */
+/* Return true if file FILENAME exists and can be written.  */
 
-static int
+static bool
 check_writable (const char *filename)
 {
 #ifdef MSDOS
@@ -2470,7 +2457,7 @@ check_writable (const char *filename)
   return (st.st_mode & S_IWRITE || S_ISDIR (st.st_mode));
 #else /* not MSDOS */
 #ifdef HAVE_EUIDACCESS
-  int res = (euidaccess (filename, 2) >= 0);
+  bool res = (euidaccess (filename, 2) >= 0);
 #ifdef CYGWIN
   /* euidaccess may have returned failure because Cygwin couldn't
      determine the file's UID or GID; if so, we return success. */
@@ -2738,7 +2725,7 @@ searchable directory.  */)
   (Lisp_Object filename)
 {
   Lisp_Object handler;
-  int tem;
+  bool tem;
   struct gcpro gcpro1;
 
   /* If the file name has special constructs in it,
@@ -2846,9 +2833,8 @@ or if SELinux is disabled, or if Emacs lacks SELinux support.  */)
          if (context_range_get (context))
            values[3] = build_string (context_range_get (context));
          context_free (context);
+         freecon (con);
        }
-      if (con)
-       freecon (con);
     }
 #endif
 
@@ -2874,7 +2860,8 @@ compiled with SELinux support.  */)
   Lisp_Object type = CAR_SAFE (CDR_SAFE (CDR_SAFE (context)));
   Lisp_Object range = CAR_SAFE (CDR_SAFE (CDR_SAFE (CDR_SAFE (context))));
   security_context_t con;
-  int fail, conlength;
+  bool fail;
+  int conlength;
   context_t parsed_con;
 #endif
 
@@ -2917,19 +2904,19 @@ compiled with SELinux support.  */)
                error ("Doing context_range_set");
            }
 
-         /* Set the modified context back to the file. */
-         fail = lsetfilecon (SSDATA (encoded_absname),
-                             context_str (parsed_con));
-         if (fail)
+         /* Set the modified context back to the file.  */
+         fail = (lsetfilecon (SSDATA (encoded_absname),
+                              context_str (parsed_con))
+                 != 0);
+          /* See http://debbugs.gnu.org/11245 for ENOTSUP.  */
+         if (fail && errno != ENOTSUP)
            report_file_error ("Doing lsetfilecon", Fcons (absname, Qnil));
 
          context_free (parsed_con);
+         freecon (con);
        }
       else
        report_file_error ("Doing lgetfilecon", Fcons (absname, Qnil));
-
-      if (con)
-       freecon (con);
     }
 #endif
 
@@ -3009,11 +2996,13 @@ DEFUN ("default-file-modes", Fdefault_file_modes, Sdefault_file_modes, 0, 0, 0,
 The value is an integer.  */)
   (void)
 {
-  int realmask;
+  mode_t realmask;
   Lisp_Object value;
 
+  BLOCK_INPUT;
   realmask = umask (0);
   umask (realmask);
+  UNBLOCK_INPUT;
 
   XSETINT (value, (~ realmask) & 0777);
   return value;
@@ -3030,11 +3019,7 @@ Use the current time if TIMESTAMP is nil.  TIMESTAMP is in the format of
 {
   Lisp_Object absname, encoded_absname;
   Lisp_Object handler;
-  time_t sec;
-  int usec;
-
-  if (! lisp_time_argument (timestamp, &sec, &usec))
-    error ("Invalid time specification");
+  EMACS_TIME t = lisp_time_argument (timestamp);
 
   absname = Fexpand_file_name (filename, BVAR (current_buffer, directory));
 
@@ -3047,12 +3032,7 @@ Use the current time if TIMESTAMP is nil.  TIMESTAMP is in the format of
   encoded_absname = ENCODE_FILE (absname);
 
   {
-    EMACS_TIME t;
-
-    EMACS_SET_SECS (t, sec);
-    EMACS_SET_USECS (t, usec);
-
-    if (set_file_times (SSDATA (encoded_absname), t, t))
+    if (set_file_times (-1, SSDATA (encoded_absname), t, t))
       {
 #ifdef DOS_NT
         struct stat st;
@@ -3087,8 +3067,7 @@ otherwise, if FILE2 does not exist, the answer is t.  */)
   (Lisp_Object file1, Lisp_Object file2)
 {
   Lisp_Object absname1, absname2;
-  struct stat st;
-  int mtime1;
+  struct stat st1, st2;
   Lisp_Object handler;
   struct gcpro gcpro1, gcpro2;
 
@@ -3114,20 +3093,21 @@ otherwise, if FILE2 does not exist, the answer is t.  */)
   absname2 = ENCODE_FILE (absname2);
   UNGCPRO;
 
-  if (stat (SSDATA (absname1), &st) < 0)
+  if (stat (SSDATA (absname1), &st1) < 0)
     return Qnil;
 
-  mtime1 = st.st_mtime;
-
-  if (stat (SSDATA (absname2), &st) < 0)
+  if (stat (SSDATA (absname2), &st2) < 0)
     return Qt;
 
-  return (mtime1 > st.st_mtime) ? Qt : Qnil;
+  return (EMACS_TIME_GT (get_stat_mtime (&st1), get_stat_mtime (&st2))
+         ? Qt : Qnil);
 }
 \f
 #ifndef READ_BUF_SIZE
 #define READ_BUF_SIZE (64 << 10)
 #endif
+/* Some buffer offsets are stored in 'int' variables.  */
+verify (READ_BUF_SIZE <= INT_MAX);
 
 /* This function is called after Lisp functions to decide a coding
    system are called, or when they cause an error.  Before they are
@@ -3154,16 +3134,15 @@ decide_coding_unwind (Lisp_Object unwind_data)
   undo_list = XCAR (unwind_data);
   buffer = XCDR (unwind_data);
 
-  if (current_buffer != XBUFFER (buffer))
-    set_buffer_internal (XBUFFER (buffer));
+  set_buffer_internal (XBUFFER (buffer));
   adjust_markers_for_delete (BEG, BEG_BYTE, Z, Z_BYTE);
   adjust_overlays_for_delete (BEG, Z - BEG);
-  BUF_INTERVALS (current_buffer) = 0;
+  set_buffer_intervals (current_buffer, NULL);
   TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
 
   /* Now we are safe to change the buffer's multibyteness directly.  */
-  BVAR (current_buffer, enable_multibyte_characters) = multibyte;
-  BVAR (current_buffer, undo_list) = undo_list;
+  bset_enable_multibyte_characters (current_buffer, multibyte);
+  bset_undo_list (current_buffer, undo_list);
 
   return Qnil;
 }
@@ -3172,8 +3151,8 @@ decide_coding_unwind (Lisp_Object unwind_data)
 /* Used to pass values from insert-file-contents to read_non_regular.  */
 
 static int non_regular_fd;
-static EMACS_INT non_regular_inserted;
-static EMACS_INT non_regular_nbytes;
+static ptrdiff_t non_regular_inserted;
+static int non_regular_nbytes;
 
 
 /* Read from a non-regular file.
@@ -3184,7 +3163,7 @@ static EMACS_INT non_regular_nbytes;
 static Lisp_Object
 read_non_regular (Lisp_Object ignore)
 {
-  EMACS_INT nbytes;
+  int nbytes;
 
   immediate_quit = 1;
   QUIT;
@@ -3221,6 +3200,15 @@ emacs_lseek (int fd, EMACS_INT offset, int whence)
   return lseek (fd, offset, whence);
 }
 
+/* Return a special time value indicating the error number ERRNUM.  */
+static EMACS_TIME
+time_error_value (int errnum)
+{
+  int ns = (errnum == ENOENT || errnum == EACCES || errnum == ENOTDIR
+           ? NONEXISTENT_MODTIME_NSECS
+           : UNKNOWN_MODTIME_NSECS);
+  return make_emacs_time (0, ns);
+}
 
 DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents,
        1, 5, 0,
@@ -3248,29 +3236,31 @@ variable `last-coding-system-used' to the coding system actually used.  */)
   (Lisp_Object filename, Lisp_Object visit, Lisp_Object beg, Lisp_Object end, Lisp_Object replace)
 {
   struct stat st;
-  register int fd;
-  EMACS_INT inserted = 0;
-  int nochange = 0;
-  register EMACS_INT how_much;
+  int file_status;
+  EMACS_TIME mtime;
+  int fd;
+  ptrdiff_t inserted = 0;
+  bool nochange = 0;
+  ptrdiff_t how_much;
   off_t beg_offset, end_offset;
-  register EMACS_INT unprocessed;
-  int count = SPECPDL_INDEX ();
+  int unprocessed;
+  ptrdiff_t count = SPECPDL_INDEX ();
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
   Lisp_Object handler, val, insval, orig_filename, old_undo;
   Lisp_Object p;
-  EMACS_INT total = 0;
-  int not_regular = 0;
+  ptrdiff_t total = 0;
+  bool not_regular = 0;
   int save_errno = 0;
   char read_buf[READ_BUF_SIZE];
   struct coding_system coding;
   char buffer[1 << 14];
-  int replace_handled = 0;
-  int set_coding_system = 0;
+  bool replace_handled = 0;
+  bool set_coding_system = 0;
   Lisp_Object coding_system;
-  int read_quit = 0;
+  bool read_quit = 0;
   Lisp_Object old_Vdeactivate_mark = Vdeactivate_mark;
-  int we_locked_file = 0;
-  int deferred_remove_unwind_protect = 0;
+  bool we_locked_file = 0;
+  bool deferred_remove_unwind_protect = 0;
 
   if (current_buffer->base_buffer && ! NILP (visit))
     error ("Cannot do file visiting in an indirect buffer");
@@ -3299,7 +3289,8 @@ variable `last-coding-system-used' to the coding system actually used.  */)
     {
       val = call6 (handler, Qinsert_file_contents, filename,
                   visit, beg, end, replace);
-      if (CONSP (val) && CONSP (XCDR (val)))
+      if (CONSP (val) && CONSP (XCDR (val))
+         && RANGED_INTEGERP (0, XCAR (XCDR (val)), ZV - PT))
        inserted = XINT (XCAR (XCDR (val)));
       goto handled;
     }
@@ -3315,19 +3306,22 @@ variable `last-coding-system-used' to the coding system actually used.  */)
 
     /* Tell stat to use expensive method to get accurate info.  */
     Vw32_get_true_file_attributes = Qt;
-    total = stat (SSDATA (filename), &st);
+    file_status = stat (SSDATA (filename), &st);
     Vw32_get_true_file_attributes = tem;
   }
-  if (total < 0)
 #else
-  if (stat (SSDATA (filename), &st) < 0)
+  file_status = stat (SSDATA (filename), &st);
 #endif /* WINDOWSNT */
+
+  if (file_status == 0)
+    mtime = get_stat_mtime (&st);
+  else
     {
     badopen:
       save_errno = errno;
       if (NILP (visit))
        report_file_error ("Opening input file", Fcons (orig_filename, Qnil));
-      st.st_mtime = -1;
+      mtime = time_error_value (save_errno);
       st.st_size = -1;
       how_much = 0;
       if (!NILP (Vcoding_system_for_read))
@@ -3453,7 +3447,7 @@ variable `last-coding-system-used' to the coding system actually used.  */)
                 We assume that the 1K-byte and 3K-byte for heading
                 and tailing respectively are sufficient for this
                 purpose.  */
-             EMACS_INT nread;
+             int nread;
 
              if (st.st_size <= (1024 * 4))
                nread = emacs_read (fd, read_buf, 1024 * 4);
@@ -3478,22 +3472,22 @@ variable `last-coding-system-used' to the coding system actually used.  */)
                  Lisp_Object workbuf;
                  struct buffer *buf;
 
-                 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
+                 record_unwind_current_buffer ();
 
                  workbuf = Fget_buffer_create (build_string (" *code-converting-work*"));
                  buf = XBUFFER (workbuf);
 
                  delete_all_overlays (buf);
-                 BVAR (buf, directory) = BVAR (current_buffer, directory);
-                 BVAR (buf, read_only) = Qnil;
-                 BVAR (buf, filename) = Qnil;
-                 BVAR (buf, undo_list) = Qt;
+                 bset_directory (buf, BVAR (current_buffer, directory));
+                 bset_read_only (buf, Qnil);
+                 bset_filename (buf, Qnil);
+                 bset_undo_list (buf, Qt);
                  eassert (buf->overlays_before == NULL);
                  eassert (buf->overlays_after == NULL);
 
                  set_buffer_internal (buf);
                  Ferase_buffer ();
-                 BVAR (buf, enable_multibyte_characters) = Qnil;
+                 bset_enable_multibyte_characters (buf, Qnil);
 
                  insert_1_both ((char *) read_buf, nread, nread, 0, 0, 0);
                  TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
@@ -3563,13 +3557,13 @@ variable `last-coding-system-used' to the coding system actually used.  */)
       /* same_at_start and same_at_end count bytes,
         because file access counts bytes
         and BEG and END count bytes.  */
-      EMACS_INT same_at_start = BEGV_BYTE;
-      EMACS_INT same_at_end = ZV_BYTE;
-      EMACS_INT overlap;
+      ptrdiff_t same_at_start = BEGV_BYTE;
+      ptrdiff_t same_at_end = ZV_BYTE;
+      ptrdiff_t overlap;
       /* There is still a possibility we will find the need to do code
-        conversion.  If that happens, we set this variable to 1 to
+        conversion.  If that happens, set this variable to
         give up on handling REPLACE in the optimized way.  */
-      int giveup_match_end = 0;
+      bool giveup_match_end = 0;
 
       if (beg_offset != 0)
        {
@@ -3584,7 +3578,7 @@ variable `last-coding-system-used' to the coding system actually used.  */)
         match the text at the beginning of the buffer.  */
       while (1)
        {
-         EMACS_INT nread, bufpos;
+         int nread, bufpos;
 
          nread = emacs_read (fd, buffer, sizeof buffer);
          if (nread < 0)
@@ -3693,7 +3687,7 @@ variable `last-coding-system-used' to the coding system actually used.  */)
 
       if (! giveup_match_end)
        {
-         EMACS_INT temp;
+         ptrdiff_t temp;
 
          /* We win!  We can handle REPLACE the optimized way.  */
 
@@ -3730,7 +3724,7 @@ variable `last-coding-system-used' to the coding system actually used.  */)
          /* If display currently starts at beginning of line,
             keep it that way.  */
          if (XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
-           XWINDOW (selected_window)->start_at_line_beg = Fbolp ();
+           XWINDOW (selected_window)->start_at_line_beg = !NILP (Fbolp ());
 
          replace_handled = 1;
        }
@@ -3747,17 +3741,18 @@ variable `last-coding-system-used' to the coding system actually used.  */)
      in a more optimized way.  */
   if (!NILP (replace) && ! replace_handled && BEGV < ZV)
     {
-      EMACS_INT same_at_start = BEGV_BYTE;
-      EMACS_INT same_at_end = ZV_BYTE;
-      EMACS_INT same_at_start_charpos;
-      EMACS_INT inserted_chars;
-      EMACS_INT overlap;
-      EMACS_INT bufpos;
+      ptrdiff_t same_at_start = BEGV_BYTE;
+      ptrdiff_t same_at_end = ZV_BYTE;
+      ptrdiff_t same_at_start_charpos;
+      ptrdiff_t inserted_chars;
+      ptrdiff_t overlap;
+      ptrdiff_t bufpos;
       unsigned char *decoded;
-      EMACS_INT temp;
-      EMACS_INT this = 0;
-      int this_count = SPECPDL_INDEX ();
-      int multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters));
+      ptrdiff_t temp;
+      ptrdiff_t this = 0;
+      ptrdiff_t this_count = SPECPDL_INDEX ();
+      bool multibyte
+       = ! NILP (BVAR (current_buffer, enable_multibyte_characters));
       Lisp_Object conversion_buffer;
       struct gcpro gcpro1;
 
@@ -3781,8 +3776,7 @@ variable `last-coding-system-used' to the coding system actually used.  */)
          /* We read one bunch by one (READ_BUF_SIZE bytes) to allow
             quitting while reading a huge while.  */
          /* `try'' is reserved in some compilers (Microsoft C).  */
-         EMACS_INT trytry = min (total - how_much,
-                                 READ_BUF_SIZE - unprocessed);
+         int trytry = min (total - how_much, READ_BUF_SIZE - unprocessed);
 
          /* Allow quitting out of the actual I/O.  */
          immediate_quit = 1;
@@ -3888,7 +3882,7 @@ variable `last-coding-system-used' to the coding system actually used.  */)
       /* If display currently starts at beginning of line,
         keep it that way.  */
       if (XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
-       XWINDOW (selected_window)->start_at_line_beg = Fbolp ();
+       XWINDOW (selected_window)->start_at_line_beg = !NILP (Fbolp ());
 
       /* Replace the chars that we need to replace,
         and update INSERTED to equal the number of bytes
@@ -3973,13 +3967,13 @@ variable `last-coding-system-used' to the coding system actually used.  */)
   /* Here, we don't do code conversion in the loop.  It is done by
      decode_coding_gap after all data are read into the buffer.  */
   {
-    EMACS_INT gap_size = GAP_SIZE;
+    ptrdiff_t gap_size = GAP_SIZE;
 
     while (how_much < total)
       {
        /* try is reserved in some compilers (Microsoft C) */
-       EMACS_INT trytry = min (total - how_much, READ_BUF_SIZE);
-       EMACS_INT this;
+       int trytry = min (total - how_much, READ_BUF_SIZE);
+       ptrdiff_t this;
 
        if (not_regular)
          {
@@ -4098,13 +4092,13 @@ variable `last-coding-system-used' to the coding system actually used.  */)
             care of marker adjustment.  By this way, we can run Lisp
             program safely before decoding the inserted text.  */
          Lisp_Object unwind_data;
-         int count1 = SPECPDL_INDEX ();
+         ptrdiff_t count1 = SPECPDL_INDEX ();
 
          unwind_data = Fcons (BVAR (current_buffer, enable_multibyte_characters),
                               Fcons (BVAR (current_buffer, undo_list),
                                      Fcurrent_buffer ()));
-         BVAR (current_buffer, enable_multibyte_characters) = Qnil;
-         BVAR (current_buffer, undo_list) = Qt;
+         bset_enable_multibyte_characters (current_buffer, Qnil);
+         bset_undo_list (current_buffer, Qt);
          record_unwind_protect (decide_coding_unwind, unwind_data);
 
          if (inserted > 0 && ! NILP (Vset_auto_coding_function))
@@ -4152,7 +4146,7 @@ variable `last-coding-system-used' to the coding system actually used.  */)
          && NILP (replace))
        /* Visiting a file with these coding system makes the buffer
           unibyte. */
-       BVAR (current_buffer, enable_multibyte_characters) = Qnil;
+       bset_enable_multibyte_characters (current_buffer, Qnil);
     }
 
   coding.dst_multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters));
@@ -4195,13 +4189,13 @@ variable `last-coding-system-used' to the coding system actually used.  */)
   if (!NILP (visit))
     {
       if (!EQ (BVAR (current_buffer, undo_list), Qt) && !nochange)
-       BVAR (current_buffer, undo_list) = Qnil;
+       bset_undo_list (current_buffer, Qnil);
 
       if (NILP (handler))
        {
-         current_buffer->modtime = st.st_mtime;
+         current_buffer->modtime = mtime;
          current_buffer->modtime_size = st.st_size;
-         BVAR (current_buffer, filename) = orig_filename;
+         bset_filename (current_buffer, orig_filename);
        }
 
       SAVE_MODIFF = MODIFF;
@@ -4229,7 +4223,8 @@ variable `last-coding-system-used' to the coding system actually used.  */)
                      visit);
       if (! NILP (insval))
        {
-         CHECK_NUMBER (insval);
+         if (! RANGED_INTEGERP (0, insval, ZV - PT))
+           wrong_type_argument (intern ("inserted-chars"), insval);
          inserted = XFASTINT (insval);
        }
     }
@@ -4238,20 +4233,21 @@ variable `last-coding-system-used' to the coding system actually used.  */)
   if (inserted > 0)
     {
       /* Don't run point motion or modification hooks when decoding.  */
-      int count1 = SPECPDL_INDEX ();
-      EMACS_INT old_inserted = inserted;
+      ptrdiff_t count1 = SPECPDL_INDEX ();
+      ptrdiff_t old_inserted = inserted;
       specbind (Qinhibit_point_motion_hooks, Qt);
       specbind (Qinhibit_modification_hooks, Qt);
 
       /* Save old undo list and don't record undo for decoding.  */
       old_undo = BVAR (current_buffer, undo_list);
-      BVAR (current_buffer, undo_list) = Qt;
+      bset_undo_list (current_buffer, Qt);
 
       if (NILP (replace))
        {
          insval = call3 (Qformat_decode,
                          Qnil, make_number (inserted), visit);
-         CHECK_NUMBER (insval);
+         if (! RANGED_INTEGERP (0, insval, ZV - PT))
+           wrong_type_argument (intern ("inserted-chars"), insval);
          inserted = XFASTINT (insval);
        }
       else
@@ -4265,15 +4261,16 @@ variable `last-coding-system-used' to the coding system actually used.  */)
             Hence we temporarily save `point' and `inserted' here and
             restore `point' iff format-decode did not insert or delete
             any text.  Otherwise we leave `point' at point-min.  */
-         EMACS_INT opoint = PT;
-         EMACS_INT opoint_byte = PT_BYTE;
-         EMACS_INT oinserted = ZV - BEGV;
-         int ochars_modiff = CHARS_MODIFF;
+         ptrdiff_t opoint = PT;
+         ptrdiff_t opoint_byte = PT_BYTE;
+         ptrdiff_t oinserted = ZV - BEGV;
+         EMACS_INT ochars_modiff = CHARS_MODIFF;
 
          TEMP_SET_PT_BOTH (BEGV, BEGV_BYTE);
          insval = call3 (Qformat_decode,
                          Qnil, make_number (oinserted), visit);
-         CHECK_NUMBER (insval);
+         if (! RANGED_INTEGERP (0, insval, ZV - PT))
+           wrong_type_argument (intern ("inserted-chars"), insval);
          if (ochars_modiff == CHARS_MODIFF)
            /* format_decode didn't modify buffer's characters => move
               point back to position before inserted text and leave
@@ -4295,7 +4292,8 @@ variable `last-coding-system-used' to the coding system actually used.  */)
              insval = call1 (XCAR (p), make_number (inserted));
              if (!NILP (insval))
                {
-                 CHECK_NUMBER (insval);
+                 if (! RANGED_INTEGERP (0, insval, ZV - PT))
+                   wrong_type_argument (intern ("inserted-chars"), insval);
                  inserted = XFASTINT (insval);
                }
            }
@@ -4303,16 +4301,17 @@ variable `last-coding-system-used' to the coding system actually used.  */)
            {
              /* For the rationale of this see the comment on
                 format-decode above.  */
-             EMACS_INT opoint = PT;
-             EMACS_INT opoint_byte = PT_BYTE;
-             EMACS_INT oinserted = ZV - BEGV;
-             int ochars_modiff = CHARS_MODIFF;
+             ptrdiff_t opoint = PT;
+             ptrdiff_t opoint_byte = PT_BYTE;
+             ptrdiff_t oinserted = ZV - BEGV;
+             EMACS_INT ochars_modiff = CHARS_MODIFF;
 
              TEMP_SET_PT_BOTH (BEGV, BEGV_BYTE);
              insval = call1 (XCAR (p), make_number (oinserted));
              if (!NILP (insval))
                {
-                 CHECK_NUMBER (insval);
+                 if (! RANGED_INTEGERP (0, insval, ZV - PT))
+                   wrong_type_argument (intern ("inserted-chars"), insval);
                  if (ochars_modiff == CHARS_MODIFF)
                    /* after_insert_file_functions didn't modify
                       buffer's characters => move point back to
@@ -4333,7 +4332,7 @@ variable `last-coding-system-used' to the coding system actually used.  */)
 
       if (NILP (visit))
        {
-         BVAR (current_buffer, undo_list) = old_undo;
+         bset_undo_list (current_buffer, old_undo);
          if (CONSP (old_undo) && inserted != old_inserted)
            {
              /* Adjust the last undo record for the size change during
@@ -4348,13 +4347,13 @@ variable `last-coding-system-used' to the coding system actually used.  */)
       else
        /* If undo_list was Qt before, keep it that way.
           Otherwise start with an empty undo_list.  */
-       BVAR (current_buffer, undo_list) = EQ (old_undo, Qt) ? Qt : Qnil;
+       bset_undo_list (current_buffer, EQ (old_undo, Qt) ? Qt : Qnil);
 
       unbind_to (count1, Qnil);
     }
 
   if (!NILP (visit)
-      && current_buffer->modtime == -1)
+      && EMACS_NSECS (current_buffer->modtime) == NONEXISTENT_MODTIME_NSECS)
     {
       /* If visiting nonexistent file, return nil.  */
       errno = save_errno;
@@ -4420,8 +4419,8 @@ choose_write_coding_system (Lisp_Object start, Lisp_Object end, Lisp_Object file
         If it is not set locally, we anyway have to convert EOL
         format if the default value of `buffer-file-coding-system'
         tells that it is not Unix-like (LF only) format.  */
-      int using_default_coding = 0;
-      int force_raw_text = 0;
+      bool using_default_coding = 0;
+      bool force_raw_text = 0;
 
       val = BVAR (current_buffer, buffer_file_coding_system);
       if (NILP (val)
@@ -4530,19 +4529,19 @@ This calls `write-region-annotate-functions' at the start, and
 `write-region-post-annotation-function' at the end.  */)
   (Lisp_Object start, Lisp_Object end, Lisp_Object filename, Lisp_Object append, Lisp_Object visit, Lisp_Object lockname, Lisp_Object mustbenew)
 {
-  register int desc;
-  int failure;
+  int desc;
+  bool ok;
   int save_errno = 0;
   const char *fn;
   struct stat st;
-  int count = SPECPDL_INDEX ();
+  ptrdiff_t count = SPECPDL_INDEX ();
   int count1;
   Lisp_Object handler;
   Lisp_Object visit_file;
   Lisp_Object annotations;
   Lisp_Object encoded_filename;
-  int visiting = (EQ (visit, Qt) || STRINGP (visit));
-  int quietly = !NILP (visit);
+  bool visiting = (EQ (visit, Qt) || STRINGP (visit));
+  bool quietly = !NILP (visit);
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
   struct buffer *given_buffer;
   struct coding_system coding;
@@ -4588,7 +4587,7 @@ This calls `write-region-annotate-functions' at the start, and
        {
          SAVE_MODIFF = MODIFF;
          XSETFASTINT (BVAR (current_buffer, save_length), Z - BEG);
-         BVAR (current_buffer, filename) = visit_file;
+         bset_filename (current_buffer, visit_file);
        }
       UNGCPRO;
       return val;
@@ -4706,37 +4705,27 @@ This calls `write-region-annotate-functions' at the start, and
 
   UNGCPRO;
 
-  failure = 0;
   immediate_quit = 1;
 
   if (STRINGP (start))
-    {
-      failure = 0 > a_write (desc, start, 0, SCHARS (start),
-                            &annotations, &coding);
-      save_errno = errno;
-    }
+    ok = a_write (desc, start, 0, SCHARS (start), &annotations, &coding);
   else if (XINT (start) != XINT (end))
-    {
-      failure = 0 > a_write (desc, Qnil,
-                            XINT (start), XINT (end) - XINT (start),
-                            &annotations, &coding);
-      save_errno = errno;
-    }
+    ok = a_write (desc, Qnil, XINT (start), XINT (end) - XINT (start),
+                 &annotations, &coding);
   else
     {
-      /* If file was empty, still need to write the annotations */
+      /* If file was empty, still need to write the annotations */
       coding.mode |= CODING_MODE_LAST_BLOCK;
-      failure = 0 > a_write (desc, Qnil, XINT (end), 0, &annotations, &coding);
-      save_errno = errno;
+      ok = a_write (desc, Qnil, XINT (end), 0, &annotations, &coding);
     }
+  save_errno = errno;
 
-  if (CODING_REQUIRE_FLUSHING (&coding)
-      && !(coding.mode & CODING_MODE_LAST_BLOCK)
-      && ! failure)
+  if (ok && CODING_REQUIRE_FLUSHING (&coding)
+      && !(coding.mode & CODING_MODE_LAST_BLOCK))
     {
       /* We have to flush out a data. */
       coding.mode |= CODING_MODE_LAST_BLOCK;
-      failure = 0 > e_write (desc, Qnil, 1, 1, &coding);
+      ok = e_write (desc, Qnil, 1, 1, &coding);
       save_errno = errno;
     }
 
@@ -4753,13 +4742,13 @@ This calls `write-region-annotate-functions' at the start, and
         ignore EINVAL which happens when fsync is not supported on this
         file.  */
       if (errno != EINTR && errno != EINVAL)
-       failure = 1, save_errno = errno;
+       ok = 0, save_errno = errno;
     }
 #endif
 
   /* NFS can report a write failure now.  */
   if (emacs_close (desc) < 0)
-    failure = 1, save_errno = errno;
+    ok = 0, save_errno = errno;
 
   stat (fn, &st);
 
@@ -4792,11 +4781,11 @@ This calls `write-region-annotate-functions' at the start, and
      next attempt to save.  */
   if (visiting)
     {
-      current_buffer->modtime = st.st_mtime;
+      current_buffer->modtime = get_stat_mtime (&st);
       current_buffer->modtime_size = st.st_size;
     }
 
-  if (failure)
+  if (! ok)
     error ("IO error writing %s: %s", SDATA (filename),
           emacs_strerror (save_errno));
 
@@ -4804,7 +4793,7 @@ This calls `write-region-annotate-functions' at the start, and
     {
       SAVE_MODIFF = MODIFF;
       XSETFASTINT (BVAR (current_buffer, save_length), Z - BEG);
-      BVAR (current_buffer, filename) = visit_file;
+      bset_filename (current_buffer, visit_file);
       update_mode_lines++;
     }
   else if (quietly)
@@ -4852,7 +4841,8 @@ build_annotations (Lisp_Object start, Lisp_Object end)
   Lisp_Object p, res;
   struct gcpro gcpro1, gcpro2;
   Lisp_Object original_buffer;
-  int i, used_global = 0;
+  int i;
+  bool used_global = 0;
 
   XSETBUFFER (original_buffer, current_buffer);
 
@@ -4932,16 +4922,16 @@ build_annotations (Lisp_Object start, Lisp_Object end)
 
    We modify *ANNOT by discarding elements as we use them up.
 
-   The return value is negative in case of system call failure.  */
+   Return true if successful.  */
 
-static int
-a_write (int desc, Lisp_Object string, EMACS_INT pos,
-        register EMACS_INT nchars, Lisp_Object *annot,
+static bool
+a_write (int desc, Lisp_Object string, ptrdiff_t pos,
+        ptrdiff_t nchars, Lisp_Object *annot,
         struct coding_system *coding)
 {
   Lisp_Object tem;
-  EMACS_INT nextpos;
-  EMACS_INT lastpos = pos + nchars;
+  ptrdiff_t nextpos;
+  ptrdiff_t lastpos = pos + nchars;
 
   while (NILP (*annot) || CONSP (*annot))
     {
@@ -4958,30 +4948,30 @@ a_write (int desc, Lisp_Object string, EMACS_INT pos,
       /* Output buffer text up to the next annotation's position.  */
       if (nextpos > pos)
        {
-         if (0 > e_write (desc, string, pos, nextpos, coding))
-           return -1;
+         if (!e_write (desc, string, pos, nextpos, coding))
+           return 0;
          pos = nextpos;
        }
       /* Output the annotation.  */
       tem = Fcdr (Fcar (*annot));
       if (STRINGP (tem))
        {
-         if (0 > e_write (desc, tem, 0, SCHARS (tem), coding))
-           return -1;
+         if (!e_write (desc, tem, 0, SCHARS (tem), coding))
+           return 0;
        }
       *annot = Fcdr (*annot);
     }
-  return 0;
+  return 1;
 }
 
 
 /* Write text in the range START and END into descriptor DESC,
    encoding them with coding system CODING.  If STRING is nil, START
    and END are character positions of the current buffer, else they
-   are indexes to the string STRING.  */
+   are indexes to the string STRING.  Return true if successful.  */
 
-static int
-e_write (int desc, Lisp_Object string, EMACS_INT start, EMACS_INT end,
+static bool
+e_write (int desc, Lisp_Object string, ptrdiff_t start, ptrdiff_t end,
         struct coding_system *coding)
 {
   if (STRINGP (string))
@@ -5013,8 +5003,8 @@ e_write (int desc, Lisp_Object string, EMACS_INT start, EMACS_INT end,
        }
       else
        {
-         EMACS_INT start_byte = CHAR_TO_BYTE (start);
-         EMACS_INT end_byte = CHAR_TO_BYTE (end);
+         ptrdiff_t start_byte = CHAR_TO_BYTE (start);
+         ptrdiff_t end_byte = CHAR_TO_BYTE (end);
 
          coding->src_multibyte = (end - start) < (end_byte - start_byte);
          if (CODING_REQUIRE_ENCODING (coding))
@@ -5049,12 +5039,12 @@ e_write (int desc, Lisp_Object string, EMACS_INT start, EMACS_INT end,
                         coding->produced);
 
          if (coding->produced)
-           return -1;
+           return 0;
        }
       start += coding->consumed_char;
     }
 
-  return 0;
+  return 1;
 }
 \f
 DEFUN ("verify-visited-file-modtime", Fverify_visited_file_modtime,
@@ -5069,6 +5059,7 @@ See Info node `(elisp)Modification Time' for more details.  */)
   struct stat st;
   Lisp_Object handler;
   Lisp_Object filename;
+  EMACS_TIME mtime, diff;
 
   if (NILP (buf))
     b = current_buffer;
@@ -5079,7 +5070,7 @@ See Info node `(elisp)Modification Time' for more details.  */)
     }
 
   if (!STRINGP (BVAR (b, filename))) return Qt;
-  if (b->modtime == 0) return Qt;
+  if (EMACS_NSECS (b->modtime) == UNKNOWN_MODTIME_NSECS) return Qt;
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
@@ -5090,20 +5081,16 @@ See Info node `(elisp)Modification Time' for more details.  */)
 
   filename = ENCODE_FILE (BVAR (b, filename));
 
-  if (stat (SSDATA (filename), &st) < 0)
-    {
-      /* If the file doesn't exist now and didn't exist before,
-        we say that it isn't modified, provided the error is a tame one.  */
-      if (errno == ENOENT || errno == EACCES || errno == ENOTDIR)
-       st.st_mtime = -1;
-      else
-       st.st_mtime = 0;
-    }
-  if ((st.st_mtime == b->modtime
-       /* If both are positive, accept them if they are off by one second.  */
-       || (st.st_mtime > 0 && b->modtime > 0
-          && (st.st_mtime - 1 == b->modtime
-              || st.st_mtime == b->modtime - 1)))
+  mtime = (stat (SSDATA (filename), &st) == 0
+          ? get_stat_mtime (&st)
+          : time_error_value (errno));
+  if ((EMACS_TIME_EQ (mtime, b->modtime)
+       /* If both exist, accept them if they are off by one second.  */
+       || (EMACS_TIME_VALID_P (mtime) && EMACS_TIME_VALID_P (b->modtime)
+          && ((diff = (EMACS_TIME_LT (mtime, b->modtime)
+                       ? sub_emacs_time (b->modtime, mtime)
+                       : sub_emacs_time (mtime, b->modtime))),
+              EMACS_TIME_LE (diff, make_emacs_time (1, 0)))))
       && (st.st_size == b->modtime_size
           || b->modtime_size < 0))
     return Qt;
@@ -5116,7 +5103,7 @@ DEFUN ("clear-visited-file-modtime", Fclear_visited_file_modtime,
 Next attempt to save will certainly not complain of a discrepancy.  */)
   (void)
 {
-  current_buffer->modtime = 0;
+  current_buffer->modtime = make_emacs_time (0, UNKNOWN_MODTIME_NSECS);
   current_buffer->modtime_size = -1;
   return Qnil;
 }
@@ -5124,16 +5111,16 @@ Next attempt to save will certainly not complain of a discrepancy.  */)
 DEFUN ("visited-file-modtime", Fvisited_file_modtime,
        Svisited_file_modtime, 0, 0, 0,
        doc: /* Return the current buffer's recorded visited file modification time.
-The value is a list of the form (HIGH LOW), like the time values that
+The value is a list of the form (HIGH LOW USEC PSEC), like the time values that
 `file-attributes' returns.  If the current buffer has no recorded file
 modification time, this function returns 0.  If the visited file
 doesn't exist, HIGH will be -1.
 See Info node `(elisp)Modification Time' for more details.  */)
   (void)
 {
-  if (! current_buffer->modtime)
+  if (EMACS_NSECS (current_buffer->modtime) < 0)
     return make_number (0);
-  return make_time (current_buffer->modtime);
+  return make_lisp_time (current_buffer->modtime);
 }
 
 DEFUN ("set-visited-file-modtime", Fset_visited_file_modtime,
@@ -5143,12 +5130,12 @@ Useful if the buffer was not read from the file normally
 or if the file itself has been changed for some known benign reason.
 An argument specifies the modification time value to use
 \(instead of that of the visited file), in the form of a list
-\(HIGH . LOW) or (HIGH LOW).  */)
+\(HIGH LOW USEC PSEC) as returned by `current-time'.  */)
   (Lisp_Object time_list)
 {
   if (!NILP (time_list))
     {
-      CONS_TO_INTEGER (time_list, time_t, current_buffer->modtime);
+      current_buffer->modtime = lisp_time_argument (time_list);
       current_buffer->modtime_size = -1;
     }
   else
@@ -5170,7 +5157,7 @@ An argument specifies the modification time value to use
 
       if (stat (SSDATA (filename), &st) >= 0)
         {
-         current_buffer->modtime = st.st_mtime;
+         current_buffer->modtime = get_stat_mtime (&st);
           current_buffer->modtime_size = st.st_size;
         }
     }
@@ -5197,7 +5184,7 @@ auto_save_error (Lisp_Object error_val)
   msg = Fformat (3, args);
   GCPRO1 (msg);
   nbytes = SBYTES (msg);
-  SAFE_ALLOCA (msgbuf, char *, nbytes);
+  msgbuf = SAFE_ALLOCA (nbytes);
   memcpy (msgbuf, SDATA (msg), nbytes);
 
   for (i = 0; i < 3; ++i)
@@ -5296,13 +5283,13 @@ A non-nil CURRENT-ONLY argument means save only current buffer.  */)
 {
   struct buffer *old = current_buffer, *b;
   Lisp_Object tail, buf, hook;
-  int auto_saved = 0;
+  bool auto_saved = 0;
   int do_handled_files;
   Lisp_Object oquit;
   FILE *stream = NULL;
-  int count = SPECPDL_INDEX ();
-  int orig_minibuffer_auto_raise = minibuffer_auto_raise;
-  int old_message_p = 0;
+  ptrdiff_t count = SPECPDL_INDEX ();
+  bool orig_minibuffer_auto_raise = minibuffer_auto_raise;
+  bool old_message_p = 0;
   struct gcpro gcpro1, gcpro2;
 
   if (max_specpdl_size < specpdl_size + 40)
@@ -5415,9 +5402,8 @@ A non-nil CURRENT-ONLY argument means save only current buffer.  */)
                || NILP (Ffind_file_name_handler (BVAR (b, auto_save_file_name),
                                                  Qwrite_region))))
          {
-           EMACS_TIME before_time, after_time;
-
-           EMACS_GET_TIME (before_time);
+           EMACS_TIME before_time = current_emacs_time ();
+           EMACS_TIME after_time;
 
            /* If we had a failure, don't try again for 20 minutes.  */
            if (b->auto_save_failure_time > 0
@@ -5449,12 +5435,12 @@ A non-nil CURRENT-ONLY argument means save only current buffer.  */)
            if (!auto_saved && NILP (no_message))
              message1 ("Auto-saving...");
            internal_condition_case (auto_save_1, Qt, auto_save_error);
-           auto_saved++;
+           auto_saved = 1;
            BUF_AUTOSAVE_MODIFF (b) = BUF_MODIFF (b);
            XSETFASTINT (BVAR (current_buffer, save_length), Z - BEG);
            set_buffer_internal (old);
 
-           EMACS_GET_TIME (after_time);
+           after_time = current_emacs_time ();
 
            /* If auto-save took more than 60 seconds,
               assume it was an NFS failure that got a timeout.  */
@@ -5634,17 +5620,17 @@ of file names regardless of the current language environment.  */);
   Fput (Qfile_error, Qerror_conditions,
        Fpurecopy (list2 (Qfile_error, Qerror)));
   Fput (Qfile_error, Qerror_message,
-       make_pure_c_string ("File error"));
+       build_pure_c_string ("File error"));
 
   Fput (Qfile_already_exists, Qerror_conditions,
        Fpurecopy (list3 (Qfile_already_exists, Qfile_error, Qerror)));
   Fput (Qfile_already_exists, Qerror_message,
-       make_pure_c_string ("File already exists"));
+       build_pure_c_string ("File already exists"));
 
   Fput (Qfile_date_error, Qerror_conditions,
        Fpurecopy (list3 (Qfile_date_error, Qfile_error, Qerror)));
   Fput (Qfile_date_error, Qerror_message,
-       make_pure_c_string ("Cannot set file date"));
+       build_pure_c_string ("Cannot set file date"));
 
   DEFVAR_LISP ("file-name-handler-alist", Vfile_name_handler_alist,
               doc: /* Alist of elements (REGEXP . HANDLER) for file names handled specially.