]> code.delx.au - gnu-emacs/blobdiff - src/fileio.c
Merge from trunk.
[gnu-emacs] / src / fileio.c
index 7e6fd8c82a8c2fb6015fe92df92fec9c6dc465ab..110977b3a602f0523ef93c2fdbee884bfab20fa2 100644 (file)
@@ -145,9 +145,9 @@ 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,
+static int a_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t,
                     Lisp_Object *, struct coding_system *);
-static int e_write (int, Lisp_Object, EMACS_INT, EMACS_INT,
+static int e_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t,
                    struct coding_system *);
 
 \f
@@ -257,7 +257,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);
@@ -275,7 +275,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;
 
@@ -440,11 +440,9 @@ get a current directory to run processes in.  */)
 static char *
 file_name_as_directory (char *out, const char *in)
 {
-  int size = strlen (in) - 1;
+  ptrdiff_t len = strlen (in);
 
-  strcpy (out, in);
-
-  if (size < 0)
+  if (len == 0)
     {
       out[0] = '.';
       out[1] = '/';
@@ -452,11 +450,13 @@ file_name_as_directory (char *out, const char *in)
       return out;
     }
 
+  strcpy (out, in);
+
   /* For Unix syntax, Append a slash if necessary */
-  if (!IS_DIRECTORY_SEP (out[size]))
+  if (!IS_DIRECTORY_SEP (out[len - 1]))
     {
-      out[size + 1] = DIRECTORY_SEP;
-      out[size + 2] = '\0';
+      out[len] = DIRECTORY_SEP;
+      out[len + 1] = '\0';
     }
 #ifdef DOS_NT
   dostounix_filename (out);
@@ -503,7 +503,7 @@ For a Unix-syntax file name, just appends a slash.  */)
 static int
 directory_file_name (char *src, char *dst)
 {
-  long slen;
+  ptrdiff_t slen;
 
   slen = strlen (src);
 
@@ -587,9 +587,9 @@ make_temp_name (Lisp_Object prefix, int base64_p)
 {
   Lisp_Object val;
   int len, clen;
-  int pid;
+  printmax_t pid;
   char *p, *data;
-  char pidbuf[20];
+  char pidbuf[INT_BUFSIZE_BOUND (printmax_t)];
   int pidlen;
 
   CHECK_STRING (prefix);
@@ -599,7 +599,7 @@ make_temp_name (Lisp_Object prefix, int base64_p)
      three are incremented if the file already exists.  This ensures
      262144 unique file names per PID per PREFIX.  */
 
-  pid = (int) getpid ();
+  pid = getpid ();
 
   if (base64_p)
     {
@@ -611,8 +611,7 @@ make_temp_name (Lisp_Object prefix, int base64_p)
   else
     {
 #ifdef HAVE_LONG_FILE_NAMES
-      sprintf (pidbuf, "%d", pid);
-      pidlen = strlen (pidbuf);
+      pidlen = sprintf (pidbuf, "%"pMd, pid);
 #else
       pidbuf[0] = make_temp_name_tbl[pid & 63], pid >>= 6;
       pidbuf[1] = make_temp_name_tbl[pid & 63], pid >>= 6;
@@ -643,7 +642,7 @@ make_temp_name (Lisp_Object prefix, int base64_p)
 
   if (!make_temp_name_count_initialized_p)
     {
-      make_temp_name_count = (unsigned) time (NULL);
+      make_temp_name_count = time (NULL);
       make_temp_name_count_initialized_p = 1;
     }
 
@@ -737,14 +736,14 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
   /* This should only point to alloca'd data.  */
   char *target;
 
-  int tlen;
+  ptrdiff_t tlen;
   struct passwd *pw;
 #ifdef DOS_NT
   int drive = 0;
   int collapse_newdir = 1;
   int is_escaped = 0;
 #endif /* DOS_NT */
-  int length;
+  ptrdiff_t length;
   Lisp_Object handler, result;
   int multibyte;
   Lisp_Object hdir;
@@ -1314,7 +1313,7 @@ See also the function `substitute-in-file-name'.")
   unsigned char *nm;
 
   register unsigned char *newdir, *p, *o;
-  int tlen;
+  ptrdiff_t tlen;
   unsigned char *target;
   struct passwd *pw;
   int lose;
@@ -1366,7 +1365,7 @@ See also the function `substitute-in-file-name'.")
        unsigned char *user = nm + 1;
        /* Find end of name. */
        unsigned char *ptr = (unsigned char *) strchr (user, '/');
-       int len = ptr ? ptr - user : strlen (user);
+       ptrdiff_t len = ptr ? ptr - user : strlen (user);
        /* Copy the user name into temp storage. */
        o = (unsigned char *) alloca (len + 1);
        memcpy (o, user, len);
@@ -1473,7 +1472,7 @@ search_embedded_absfilename (char *nm, char *endp)
       if ((0
           || IS_DIRECTORY_SEP (p[-1]))
          && file_name_absolute_p (p)
-#if defined (WINDOWSNT) || defined(CYGWIN)
+#if defined (WINDOWSNT) || defined (CYGWIN)
          /* // at start of file name is meaningful in Apollo,
             WindowsNT and Cygwin systems.  */
          && !(IS_DIRECTORY_SEP (p[0]) && p - 1 == nm)
@@ -1672,7 +1671,7 @@ those `/' is discarded.  */)
        else
          {
            Lisp_Object orig, decoded;
-           int orig_length, decoded_length;
+           ptrdiff_t orig_length, decoded_length;
            orig_length = strlen (o);
            orig = make_unibyte_string (o, orig_length);
            decoded = DECODE_FILE (orig);
@@ -1756,6 +1755,10 @@ barf_or_query_if_file_exists (Lisp_Object absname, const char *querystring,
      regardless of what access permissions it has.  */
   if (lstat (SSDATA (encoded_filename), &statbuf) >= 0)
     {
+      if (S_ISDIR (statbuf.st_mode))
+       xsignal2 (Qfile_error,
+                 build_string ("File is a directory"), absname);
+
       if (! interactive)
        xsignal2 (Qfile_already_exists,
                  build_string ("File already exists"), absname);
@@ -1810,12 +1813,12 @@ 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 ();
+  ptrdiff_t count = SPECPDL_INDEX ();
   int input_file_statable_p;
   Lisp_Object encoded_file, encoded_newname;
 #if HAVE_LIBSELINUX
@@ -1934,10 +1937,19 @@ on the system, we copy the SELinux context of FILE to NEWNAME.  */)
                    | (NILP (ok_if_already_exists) ? O_EXCL : 0),
                    S_IREAD | S_IWRITE);
 #else  /* not MSDOS */
-  ofd = emacs_open (SSDATA (encoded_newname),
-                   O_WRONLY | O_TRUNC | O_CREAT
-                   | (NILP (ok_if_already_exists) ? O_EXCL : 0),
-                   0666);
+  {
+    int new_mask = 0666;
+    if (input_file_statable_p)
+      {
+       if (!NILP (preserve_uid_gid))
+         new_mask = 0600;
+       new_mask &= st.st_mode;
+      }
+    ofd = emacs_open (SSDATA (encoded_newname),
+                     (O_WRONLY | O_TRUNC | O_CREAT
+                      | (NILP (ok_if_already_exists) ? O_EXCL : 0)),
+                     new_mask);
+  }
 #endif /* not MSDOS */
   if (ofd < 0)
     report_file_error ("Opening output file", Fcons (newname, Qnil));
@@ -1956,9 +1968,21 @@ on the system, we copy the SELinux context of FILE to NEWNAME.  */)
      owner and group.  */
   if (input_file_statable_p)
     {
-      if (!NILP (preserve_uid_gid) && fchown (ofd, st.st_uid, st.st_gid) != 0)
-       report_file_error ("Doing chown", Fcons (newname, Qnil));
-      if (fchmod (ofd, st.st_mode & 07777) != 0)
+      int mode_mask = 07777;
+      if (!NILP (preserve_uid_gid))
+       {
+         /* Attempt to change owner and group.  If that doesn't work
+            attempt to change just the group, as that is sometimes allowed.
+            Adjust the mode mask to eliminate setuid or setgid bits
+            that are inappropriate if the owner and group are wrong.  */
+         if (fchown (ofd, st.st_uid, st.st_gid) != 0)
+           {
+             mode_mask &= ~06000;
+             if (fchown (ofd, -1, st.st_gid) == 0)
+               mode_mask |= 02000;
+           }
+       }
+      if (fchmod (ofd, st.st_mode & mode_mask) != 0)
        report_file_error ("Doing chmod", Fcons (newname, Qnil));
     }
 #endif /* not MSDOS */
@@ -2186,7 +2210,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,
@@ -2473,7 +2497,7 @@ See also `file-exists-p' and `file-attributes'.  */)
 
   absname = ENCODE_FILE (absname);
 
-#if defined(DOS_NT) || defined(macintosh)
+#if defined (DOS_NT) || defined (macintosh)
   /* Under MS-DOS, Windows, and Macintosh, open does not work for
      directories.  */
   if (access (SDATA (absname), 0) == 0)
@@ -2758,7 +2782,7 @@ if file does not exist, is not accessible, or SELinux is disabled */)
     }
 #endif
 
-  return Flist (sizeof(values) / sizeof(values[0]), values);
+  return Flist (sizeof (values) / sizeof (values[0]), values);
 }
 \f
 DEFUN ("set-file-selinux-context", Fset_file_selinux_context,
@@ -2829,7 +2853,7 @@ is disabled. */)
          context_free (parsed_con);
        }
       else
-       report_file_error("Doing lgetfilecon", Fcons (absname, Qnil));
+       report_file_error ("Doing lgetfilecon", Fcons (absname, Qnil));
 
       if (con)
        freecon (con);
@@ -2888,7 +2912,7 @@ symbolic notation, like the `chmod' command from GNU Coreutils.  */)
 
   encoded_absname = ENCODE_FILE (absname);
 
-  if (chmod (SSDATA (encoded_absname), XINT (mode)) < 0)
+  if (chmod (SSDATA (encoded_absname), XINT (mode) & 07777) < 0)
     report_file_error ("Doing chmod", Fcons (absname, Qnil));
 
   return Qnil;
@@ -3031,6 +3055,8 @@ otherwise, if FILE2 does not exist, the answer is t.  */)
 #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
@@ -3075,8 +3101,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.
@@ -3087,7 +3113,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;
@@ -3109,6 +3135,21 @@ read_non_regular_quit (Lisp_Object ignore)
   return Qnil;
 }
 
+/* Reposition FD to OFFSET, based on WHENCE.  This acts like lseek
+   except that it also tests for OFFSET being out of lseek's range.  */
+static off_t
+emacs_lseek (int fd, EMACS_INT offset, int whence)
+{
+  /* Use "&" rather than "&&" to suppress a bogus GCC warning; see
+     <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43772>.  */
+  if (! ((TYPE_MINIMUM (off_t) <= offset) & (offset <= TYPE_MAXIMUM (off_t))))
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  return lseek (fd, offset, whence);
+}
+
 
 DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents,
        1, 5, 0,
@@ -3137,16 +3178,18 @@ variable `last-coding-system-used' to the coding system actually used.  */)
 {
   struct stat st;
   register int fd;
-  EMACS_INT inserted = 0;
+  ptrdiff_t inserted = 0;
   int nochange = 0;
-  register EMACS_INT how_much;
-  register EMACS_INT unprocessed;
-  int count = SPECPDL_INDEX ();
+  register ptrdiff_t how_much;
+  off_t beg_offset, end_offset;
+  register 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;
+  ptrdiff_t total = 0;
   int not_regular = 0;
+  int save_errno = 0;
   char read_buf[READ_BUF_SIZE];
   struct coding_system coding;
   char buffer[1 << 14];
@@ -3185,7 +3228,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;
     }
@@ -3210,9 +3254,11 @@ variable `last-coding-system-used' to the coding system actually used.  */)
 #endif /* WINDOWSNT */
     {
     badopen:
+      save_errno = errno;
       if (NILP (visit))
        report_file_error ("Opening input file", Fcons (orig_filename, Qnil));
       st.st_mtime = -1;
+      st.st_size = -1;
       how_much = 0;
       if (!NILP (Vcoding_system_for_read))
        Fset (Qbuffer_file_coding_system, Vcoding_system_for_read);
@@ -3245,15 +3291,6 @@ variable `last-coding-system-used' to the coding system actually used.  */)
   record_unwind_protect (close_file_unwind, make_number (fd));
 
 
-  /* Check whether the size is too large or negative, which can happen on a
-     platform that allows file sizes greater than the maximum off_t value.  */
-  if (! not_regular
-      && ! (0 <= st.st_size && st.st_size <= MOST_POSITIVE_FIXNUM))
-    error ("Maximum buffer size exceeded");
-
-  /* Prevent redisplay optimizations.  */
-  current_buffer->clip_changed = 1;
-
   if (!NILP (visit))
     {
       if (!NILP (beg) || !NILP (end))
@@ -3263,26 +3300,64 @@ variable `last-coding-system-used' to the coding system actually used.  */)
     }
 
   if (!NILP (beg))
-    CHECK_NUMBER (beg);
+    {
+      if (! (RANGED_INTEGERP (0, beg, TYPE_MAXIMUM (off_t))))
+       wrong_type_argument (intern ("file-offset"), beg);
+      beg_offset = XFASTINT (beg);
+    }
   else
-    XSETFASTINT (beg, 0);
+    beg_offset = 0;
 
   if (!NILP (end))
-    CHECK_NUMBER (end);
+    {
+      if (! (RANGED_INTEGERP (0, end, TYPE_MAXIMUM (off_t))))
+       wrong_type_argument (intern ("file-offset"), end);
+      end_offset = XFASTINT (end);
+    }
   else
     {
-      if (! not_regular)
+      if (not_regular)
+       end_offset = TYPE_MAXIMUM (off_t);
+      else
        {
-         XSETINT (end, st.st_size);
+         end_offset = st.st_size;
+
+         /* A negative size can happen on a platform that allows file
+            sizes greater than the maximum off_t value.  */
+         if (end_offset < 0)
+           buffer_overflow ();
 
          /* The file size returned from stat may be zero, but data
             may be readable nonetheless, for example when this is a
             file in the /proc filesystem.  */
-         if (st.st_size == 0)
-           XSETINT (end, READ_BUF_SIZE);
+         if (end_offset == 0)
+           end_offset = READ_BUF_SIZE;
        }
     }
 
+  /* Check now whether the buffer will become too large,
+     in the likely case where the file's length is not changing.
+     This saves a lot of needless work before a buffer overflow.  */
+  if (! not_regular)
+    {
+      /* The likely offset where we will stop reading.  We could read
+        more (or less), if the file grows (or shrinks) as we read it.  */
+      off_t likely_end = min (end_offset, st.st_size);
+
+      if (beg_offset < likely_end)
+       {
+         ptrdiff_t buf_bytes =
+           Z_BYTE - (!NILP (replace) ? ZV_BYTE - BEGV_BYTE  : 0);
+         ptrdiff_t buf_growth_max = BUF_BYTES_MAX - buf_bytes;
+         off_t likely_growth = likely_end - beg_offset;
+         if (buf_growth_max < likely_growth)
+           buffer_overflow ();
+       }
+    }
+
+  /* Prevent redisplay optimizations.  */
+  current_buffer->clip_changed = 1;
+
   if (EQ (Vcoding_system_for_read, Qauto_save_coding))
     {
       coding_system = coding_inherit_eol_type (Qutf_8_emacs, Qunix);
@@ -3308,7 +3383,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);
@@ -3317,7 +3392,7 @@ variable `last-coding-system-used' to the coding system actually used.  */)
                  nread = emacs_read (fd, read_buf, 1024);
                  if (nread >= 0)
                    {
-                     if (lseek (fd, st.st_size - (1024 * 3), 0) < 0)
+                     if (lseek (fd, st.st_size - (1024 * 3), SEEK_SET) < 0)
                        report_file_error ("Setting file position",
                                           Fcons (orig_filename, Qnil));
                      nread += emacs_read (fd, read_buf + nread, 1024 * 3);
@@ -3361,7 +3436,7 @@ variable `last-coding-system-used' to the coding system actually used.  */)
                  specpdl_ptr--;
 
                  /* Rewind the file for the actual read done later.  */
-                 if (lseek (fd, 0, 0) < 0)
+                 if (lseek (fd, 0, SEEK_SET) < 0)
                    report_file_error ("Setting file position",
                                       Fcons (orig_filename, Qnil));
                }
@@ -3418,17 +3493,17 @@ 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
         give up on handling REPLACE in the optimized way.  */
       int giveup_match_end = 0;
 
-      if (XINT (beg) != 0)
+      if (beg_offset != 0)
        {
-         if (lseek (fd, XINT (beg), 0) < 0)
+         if (lseek (fd, beg_offset, SEEK_SET) < 0)
            report_file_error ("Setting file position",
                               Fcons (orig_filename, Qnil));
        }
@@ -3439,7 +3514,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)
@@ -3476,7 +3551,7 @@ variable `last-coding-system-used' to the coding system actually used.  */)
       immediate_quit = 0;
       /* If the file matches the buffer completely,
         there's no need to replace anything.  */
-      if (same_at_start - BEGV_BYTE == XINT (end))
+      if (same_at_start - BEGV_BYTE == end_offset - beg_offset)
        {
          emacs_close (fd);
          specpdl_ptr--;
@@ -3491,16 +3566,17 @@ variable `last-coding-system-used' to the coding system actually used.  */)
         already found that decoding is necessary, don't waste time.  */
       while (!giveup_match_end)
        {
-         EMACS_INT total_read, nread, bufpos, curpos, trial;
+         int total_read, nread, bufpos, trial;
+         off_t curpos;
 
          /* At what file position are we now scanning?  */
-         curpos = XINT (end) - (ZV_BYTE - same_at_end);
+         curpos = end_offset - (ZV_BYTE - same_at_end);
          /* If the entire file matches the buffer tail, stop the scan.  */
          if (curpos == 0)
            break;
          /* How much can we scan in the next step?  */
          trial = min (curpos, sizeof buffer);
-         if (lseek (fd, curpos - trial, 0) < 0)
+         if (lseek (fd, curpos - trial, SEEK_SET) < 0)
            report_file_error ("Setting file position",
                               Fcons (orig_filename, Qnil));
 
@@ -3547,7 +3623,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.  */
 
@@ -3567,13 +3643,14 @@ variable `last-coding-system-used' to the coding system actually used.  */)
 
          /* Don't try to reuse the same piece of text twice.  */
          overlap = (same_at_start - BEGV_BYTE
-                    - (same_at_end + st.st_size - ZV));
+                    - (same_at_end
+                       + (! NILP (end) ? end_offset : st.st_size) - ZV_BYTE));
          if (overlap > 0)
            same_at_end += overlap;
 
          /* Arrange to read only the nonmatching middle part of the file.  */
-         XSETFASTINT (beg, XINT (beg) + (same_at_start - BEGV_BYTE));
-         XSETFASTINT (end, XINT (end) - (ZV_BYTE - same_at_end));
+         beg_offset += same_at_start - BEGV_BYTE;
+         end_offset -= ZV_BYTE - same_at_end;
 
          del_range_byte (same_at_start, same_at_end, 0);
          /* Insert from the file at the proper position.  */
@@ -3600,16 +3677,16 @@ 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 ();
+      ptrdiff_t temp;
+      ptrdiff_t this = 0;
+      ptrdiff_t this_count = SPECPDL_INDEX ();
       int multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters));
       Lisp_Object conversion_buffer;
 
@@ -3618,7 +3695,7 @@ variable `last-coding-system-used' to the coding system actually used.  */)
       /* First read the whole file, performing code conversion into
         CONVERSION_BUFFER.  */
 
-      if (lseek (fd, XINT (beg), 0) < 0)
+      if (lseek (fd, beg_offset, SEEK_SET) < 0)
        report_file_error ("Setting file position",
                           Fcons (orig_filename, Qnil));
 
@@ -3633,8 +3710,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;
@@ -3785,16 +3861,7 @@ variable `last-coding-system-used' to the coding system actually used.  */)
     }
 
   if (! not_regular)
-    {
-      register Lisp_Object temp;
-
-      total = XINT (end) - XINT (beg);
-
-      /* Make sure point-max won't overflow after this insertion.  */
-      XSETINT (temp, total);
-      if (total != XINT (temp))
-       error ("Maximum buffer size exceeded");
-    }
+    total = end_offset - beg_offset;
   else
     /* For a special file, all we can do is guess.  */
     total = READ_BUF_SIZE;
@@ -3815,9 +3882,9 @@ variable `last-coding-system-used' to the coding system actually used.  */)
   if (GAP_SIZE < total)
     make_gap (total - GAP_SIZE);
 
-  if (XINT (beg) != 0 || !NILP (replace))
+  if (beg_offset != 0 || !NILP (replace))
     {
-      if (lseek (fd, XINT (beg), 0) < 0)
+      if (lseek (fd, beg_offset, SEEK_SET) < 0)
        report_file_error ("Setting file position",
                           Fcons (orig_filename, Qnil));
     }
@@ -3834,13 +3901,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)
          {
@@ -3959,7 +4026,7 @@ 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),
@@ -4080,7 +4147,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);
        }
     }
@@ -4089,8 +4157,8 @@ 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);
 
@@ -4102,7 +4170,8 @@ variable `last-coding-system-used' to the coding system actually used.  */)
        {
          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
@@ -4116,15 +4185,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
@@ -4146,7 +4216,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);
                }
            }
@@ -4154,16 +4225,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
@@ -4218,6 +4290,7 @@ variable `last-coding-system-used' to the coding system actually used.  */)
       && current_buffer->modtime == -1)
     {
       /* If visiting nonexistent file, return nil.  */
+      errno = save_errno;
       report_file_error ("Opening input file", Fcons (orig_filename, Qnil));
     }
 
@@ -4395,7 +4468,7 @@ This calls `write-region-annotate-functions' at the start, and
   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;
@@ -4546,16 +4619,18 @@ This calls `write-region-annotate-functions' at the start, and
 
   if (!NILP (append) && !NILP (Ffile_regular_p (filename)))
     {
-      long ret;
+      off_t ret;
 
       if (NUMBERP (append))
-       ret = lseek (desc, XINT (append), 1);
+       ret = emacs_lseek (desc, XINT (append), SEEK_CUR);
       else
-       ret = lseek (desc, 0, 2);
+       ret = lseek (desc, 0, SEEK_END);
       if (ret < 0)
        {
 #ifdef CLASH_DETECTION
+         save_errno = errno;
          if (!auto_saving) unlock_file (lockname);
+         errno = save_errno;
 #endif /* CLASH_DETECTION */
          UNGCPRO;
          report_file_error ("Lseek error", Fcons (filename, Qnil));
@@ -4793,13 +4868,13 @@ build_annotations (Lisp_Object start, Lisp_Object end)
    The return value is negative in case of system call failure.  */
 
 static int
-a_write (int desc, Lisp_Object string, EMACS_INT pos,
-        register EMACS_INT nchars, Lisp_Object *annot,
+a_write (int desc, Lisp_Object string, ptrdiff_t pos,
+        register 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))
     {
@@ -4839,7 +4914,7 @@ a_write (int desc, Lisp_Object string, EMACS_INT pos,
    are indexes to the string STRING.  */
 
 static int
-e_write (int desc, Lisp_Object string, EMACS_INT start, EMACS_INT end,
+e_write (int desc, Lisp_Object string, ptrdiff_t start, ptrdiff_t end,
         struct coding_system *coding)
 {
   if (STRINGP (string))
@@ -4871,8 +4946,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))
@@ -4960,7 +5035,7 @@ See Info node `(elisp)Modification Time' for more details.  */)
   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 == b->modtime + 1
+          && (st.st_mtime - 1 == b->modtime
               || st.st_mtime == b->modtime - 1)))
       && (st.st_size == b->modtime_size
           || b->modtime_size < 0))
@@ -4982,15 +5057,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 `file-attributes' returns.  If the current buffer has no recorded
-file modification time, this function returns 0.
+The value is a list of the form (HIGH LOW), 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)
     return make_number (0);
-  return make_time ((time_t) current_buffer->modtime);
+  return make_time (current_buffer->modtime);
 }
 
 DEFUN ("set-visited-file-modtime", Fset_visited_file_modtime,
@@ -5005,7 +5081,7 @@ An argument specifies the modification time value to use
 {
   if (!NILP (time_list))
     {
-      current_buffer->modtime = cons_to_long (time_list);
+      CONS_TO_INTEGER (time_list, time_t, current_buffer->modtime);
       current_buffer->modtime_size = -1;
     }
   else
@@ -5084,11 +5160,11 @@ auto_save_1 (void)
     {
       if (stat (SSDATA (BVAR (current_buffer, filename)), &st) >= 0)
        /* But make sure we can overwrite it later!  */
-       auto_save_mode_bits = st.st_mode | 0600;
+       auto_save_mode_bits = (st.st_mode | 0600) & 0777;
       else if ((modes = Ffile_modes (BVAR (current_buffer, filename)),
                INTEGERP (modes)))
        /* Remote files don't cooperate with stat.  */
-       auto_save_mode_bits = XINT (modes) | 0600;
+       auto_save_mode_bits = (XINT (modes) | 0600) & 0777;
     }
 
   return
@@ -5155,7 +5231,7 @@ A non-nil CURRENT-ONLY argument means save only current buffer.  */)
   int do_handled_files;
   Lisp_Object oquit;
   FILE *stream = NULL;
-  int count = SPECPDL_INDEX ();
+  ptrdiff_t count = SPECPDL_INDEX ();
   int orig_minibuffer_auto_raise = minibuffer_auto_raise;
   int old_message_p = 0;
   struct gcpro gcpro1, gcpro2;
@@ -5275,7 +5351,7 @@ A non-nil CURRENT-ONLY argument means save only current buffer.  */)
            EMACS_GET_TIME (before_time);
 
            /* If we had a failure, don't try again for 20 minutes.  */
-           if (b->auto_save_failure_time >= 0
+           if (b->auto_save_failure_time > 0
                && EMACS_SECS (before_time) - b->auto_save_failure_time < 1200)
              continue;
 
@@ -5354,7 +5430,7 @@ No auto-save file will be written until the buffer changes again.  */)
      they're not autosaved.  */
   BUF_AUTOSAVE_MODIFF (current_buffer) = MODIFF;
   XSETFASTINT (BVAR (current_buffer, save_length), Z - BEG);
-  current_buffer->auto_save_failure_time = -1;
+  current_buffer->auto_save_failure_time = 0;
   return Qnil;
 }
 
@@ -5363,7 +5439,7 @@ DEFUN ("clear-buffer-auto-save-failure", Fclear_buffer_auto_save_failure,
        doc: /* Clear any record of a recent auto-save failure in the current buffer.  */)
   (void)
 {
-  current_buffer->auto_save_failure_time = -1;
+  current_buffer->auto_save_failure_time = 0;
   return Qnil;
 }
 
@@ -5420,92 +5496,50 @@ Fread_file_name (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filena
 void
 syms_of_fileio (void)
 {
-  Qoperations = intern_c_string ("operations");
-  Qexpand_file_name = intern_c_string ("expand-file-name");
-  Qsubstitute_in_file_name = intern_c_string ("substitute-in-file-name");
-  Qdirectory_file_name = intern_c_string ("directory-file-name");
-  Qfile_name_directory = intern_c_string ("file-name-directory");
-  Qfile_name_nondirectory = intern_c_string ("file-name-nondirectory");
-  Qunhandled_file_name_directory = intern_c_string ("unhandled-file-name-directory");
-  Qfile_name_as_directory = intern_c_string ("file-name-as-directory");
-  Qcopy_file = intern_c_string ("copy-file");
-  Qmake_directory_internal = intern_c_string ("make-directory-internal");
-  Qmake_directory = intern_c_string ("make-directory");
-  Qdelete_directory_internal = intern_c_string ("delete-directory-internal");
-  Qdelete_file = intern_c_string ("delete-file");
-  Qrename_file = intern_c_string ("rename-file");
-  Qadd_name_to_file = intern_c_string ("add-name-to-file");
-  Qmake_symbolic_link = intern_c_string ("make-symbolic-link");
-  Qfile_exists_p = intern_c_string ("file-exists-p");
-  Qfile_executable_p = intern_c_string ("file-executable-p");
-  Qfile_readable_p = intern_c_string ("file-readable-p");
-  Qfile_writable_p = intern_c_string ("file-writable-p");
-  Qfile_symlink_p = intern_c_string ("file-symlink-p");
-  Qaccess_file = intern_c_string ("access-file");
-  Qfile_directory_p = intern_c_string ("file-directory-p");
-  Qfile_regular_p = intern_c_string ("file-regular-p");
-  Qfile_accessible_directory_p = intern_c_string ("file-accessible-directory-p");
-  Qfile_modes = intern_c_string ("file-modes");
-  Qset_file_modes = intern_c_string ("set-file-modes");
-  Qset_file_times = intern_c_string ("set-file-times");
-  Qfile_selinux_context = intern_c_string("file-selinux-context");
-  Qset_file_selinux_context = intern_c_string("set-file-selinux-context");
-  Qfile_newer_than_file_p = intern_c_string ("file-newer-than-file-p");
-  Qinsert_file_contents = intern_c_string ("insert-file-contents");
-  Qwrite_region = intern_c_string ("write-region");
-  Qverify_visited_file_modtime = intern_c_string ("verify-visited-file-modtime");
-  Qset_visited_file_modtime = intern_c_string ("set-visited-file-modtime");
-  Qauto_save_coding = intern_c_string ("auto-save-coding");
-
-  staticpro (&Qoperations);
-  staticpro (&Qexpand_file_name);
-  staticpro (&Qsubstitute_in_file_name);
-  staticpro (&Qdirectory_file_name);
-  staticpro (&Qfile_name_directory);
-  staticpro (&Qfile_name_nondirectory);
-  staticpro (&Qunhandled_file_name_directory);
-  staticpro (&Qfile_name_as_directory);
-  staticpro (&Qcopy_file);
-  staticpro (&Qmake_directory_internal);
-  staticpro (&Qmake_directory);
-  staticpro (&Qdelete_directory_internal);
-  staticpro (&Qdelete_file);
-  staticpro (&Qrename_file);
-  staticpro (&Qadd_name_to_file);
-  staticpro (&Qmake_symbolic_link);
-  staticpro (&Qfile_exists_p);
-  staticpro (&Qfile_executable_p);
-  staticpro (&Qfile_readable_p);
-  staticpro (&Qfile_writable_p);
-  staticpro (&Qaccess_file);
-  staticpro (&Qfile_symlink_p);
-  staticpro (&Qfile_directory_p);
-  staticpro (&Qfile_regular_p);
-  staticpro (&Qfile_accessible_directory_p);
-  staticpro (&Qfile_modes);
-  staticpro (&Qset_file_modes);
-  staticpro (&Qset_file_times);
-  staticpro (&Qfile_selinux_context);
-  staticpro (&Qset_file_selinux_context);
-  staticpro (&Qfile_newer_than_file_p);
-  staticpro (&Qinsert_file_contents);
-  staticpro (&Qwrite_region);
-  staticpro (&Qverify_visited_file_modtime);
-  staticpro (&Qset_visited_file_modtime);
-  staticpro (&Qauto_save_coding);
-
-  Qfile_name_history = intern_c_string ("file-name-history");
+  DEFSYM (Qoperations, "operations");
+  DEFSYM (Qexpand_file_name, "expand-file-name");
+  DEFSYM (Qsubstitute_in_file_name, "substitute-in-file-name");
+  DEFSYM (Qdirectory_file_name, "directory-file-name");
+  DEFSYM (Qfile_name_directory, "file-name-directory");
+  DEFSYM (Qfile_name_nondirectory, "file-name-nondirectory");
+  DEFSYM (Qunhandled_file_name_directory, "unhandled-file-name-directory");
+  DEFSYM (Qfile_name_as_directory, "file-name-as-directory");
+  DEFSYM (Qcopy_file, "copy-file");
+  DEFSYM (Qmake_directory_internal, "make-directory-internal");
+  DEFSYM (Qmake_directory, "make-directory");
+  DEFSYM (Qdelete_directory_internal, "delete-directory-internal");
+  DEFSYM (Qdelete_file, "delete-file");
+  DEFSYM (Qrename_file, "rename-file");
+  DEFSYM (Qadd_name_to_file, "add-name-to-file");
+  DEFSYM (Qmake_symbolic_link, "make-symbolic-link");
+  DEFSYM (Qfile_exists_p, "file-exists-p");
+  DEFSYM (Qfile_executable_p, "file-executable-p");
+  DEFSYM (Qfile_readable_p, "file-readable-p");
+  DEFSYM (Qfile_writable_p, "file-writable-p");
+  DEFSYM (Qfile_symlink_p, "file-symlink-p");
+  DEFSYM (Qaccess_file, "access-file");
+  DEFSYM (Qfile_directory_p, "file-directory-p");
+  DEFSYM (Qfile_regular_p, "file-regular-p");
+  DEFSYM (Qfile_accessible_directory_p, "file-accessible-directory-p");
+  DEFSYM (Qfile_modes, "file-modes");
+  DEFSYM (Qset_file_modes, "set-file-modes");
+  DEFSYM (Qset_file_times, "set-file-times");
+  DEFSYM (Qfile_selinux_context, "file-selinux-context");
+  DEFSYM (Qset_file_selinux_context, "set-file-selinux-context");
+  DEFSYM (Qfile_newer_than_file_p, "file-newer-than-file-p");
+  DEFSYM (Qinsert_file_contents, "insert-file-contents");
+  DEFSYM (Qwrite_region, "write-region");
+  DEFSYM (Qverify_visited_file_modtime, "verify-visited-file-modtime");
+  DEFSYM (Qset_visited_file_modtime, "set-visited-file-modtime");
+  DEFSYM (Qauto_save_coding, "auto-save-coding");
+
+  DEFSYM (Qfile_name_history, "file-name-history");
   Fset (Qfile_name_history, Qnil);
-  staticpro (&Qfile_name_history);
 
-  Qfile_error = intern_c_string ("file-error");
-  staticpro (&Qfile_error);
-  Qfile_already_exists = intern_c_string ("file-already-exists");
-  staticpro (&Qfile_already_exists);
-  Qfile_date_error = intern_c_string ("file-date-error");
-  staticpro (&Qfile_date_error);
-  Qexcl = intern_c_string ("excl");
-  staticpro (&Qexcl);
+  DEFSYM (Qfile_error, "file-error");
+  DEFSYM (Qfile_already_exists, "file-already-exists");
+  DEFSYM (Qfile_date_error, "file-date-error");
+  DEFSYM (Qexcl, "excl");
 
   DEFVAR_LISP ("file-name-coding-system", Vfile_name_coding_system,
               doc: /* *Coding system for encoding file names.
@@ -5523,15 +5557,10 @@ instead use `file-name-coding-system' to get a constant encoding
 of file names regardless of the current language environment.  */);
   Vdefault_file_name_coding_system = Qnil;
 
-  Qformat_decode = intern_c_string ("format-decode");
-  staticpro (&Qformat_decode);
-  Qformat_annotate_function = intern_c_string ("format-annotate-function");
-  staticpro (&Qformat_annotate_function);
-  Qafter_insert_file_set_coding = intern_c_string ("after-insert-file-set-coding");
-  staticpro (&Qafter_insert_file_set_coding);
-
-  Qcar_less_than_car = intern_c_string ("car-less-than-car");
-  staticpro (&Qcar_less_than_car);
+  DEFSYM (Qformat_decode, "format-decode");
+  DEFSYM (Qformat_annotate_function, "format-annotate-function");
+  DEFSYM (Qafter_insert_file_set_coding, "after-insert-file-set-coding");
+  DEFSYM (Qcar_less_than_car, "car-less-than-car");
 
   Fput (Qfile_error, Qerror_conditions,
        Fpurecopy (list2 (Qfile_error, Qerror)));
@@ -5610,9 +5639,7 @@ After `write-region' completes, Emacs calls the function stored in
 current when building the annotations (i.e., at least once), with that
 buffer current.  */);
   Vwrite_region_annotate_functions = Qnil;
-  staticpro (&Qwrite_region_annotate_functions);
-  Qwrite_region_annotate_functions
-    = intern_c_string ("write-region-annotate-functions");
+  DEFSYM (Qwrite_region_annotate_functions, "write-region-annotate-functions");
 
   DEFVAR_LISP ("write-region-post-annotation-function",
               Vwrite_region_post_annotation_function,
@@ -5676,12 +5703,10 @@ This includes interactive calls to `delete-file' and
 `delete-directory' and the Dired deletion commands.  */);
   delete_by_moving_to_trash = 0;
   Qdelete_by_moving_to_trash = intern_c_string ("delete-by-moving-to-trash");
-  Qmove_file_to_trash = intern_c_string ("move-file-to-trash");
-  staticpro (&Qmove_file_to_trash);
-  Qcopy_directory = intern_c_string ("copy-directory");
-  staticpro (&Qcopy_directory);
-  Qdelete_directory = intern_c_string ("delete-directory");
-  staticpro (&Qdelete_directory);
+
+  DEFSYM (Qmove_file_to_trash, "move-file-to-trash");
+  DEFSYM (Qcopy_directory, "copy-directory");
+  DEFSYM (Qdelete_directory, "delete-directory");
 
   defsubr (&Sfind_file_name_handler);
   defsubr (&Sfile_name_directory);