Include <config.h> instead of "config.h".
[bpt/emacs.git] / src / fileio.c
index 01de4f3..347585f 100644 (file)
@@ -1,5 +1,5 @@
 /* File IO for GNU Emacs.
 /* File IO for GNU Emacs.
-   Copyright (C) 1985, 1986, 1987, 1988, 1992 Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 1987, 1988, 1993 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 
 This file is part of GNU Emacs.
 
@@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 along with GNU Emacs; see the file COPYING.  If not, write to
 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
-#include "config.h"
+#include <config.h>
 
 #include <sys/types.h>
 #include <sys/stat.h>
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -35,8 +35,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include <perror.h>
 #include <stddef.h>
 #include <string.h>
 #include <perror.h>
 #include <stddef.h>
 #include <string.h>
-#else
-#include <sys/dir.h>
 #endif
 
 #include <errno.h>
 #endif
 
 #include <errno.h>
@@ -53,7 +51,16 @@ extern int sys_nerr;
 #include <sys/time.h>
 #endif
 
 #include <sys/time.h>
 #endif
 
+#ifndef USG
+#ifndef VMS
+#ifndef BSD4_1
+#define HAVE_FSYNC
+#endif
+#endif
+#endif
+
 #include "lisp.h"
 #include "lisp.h"
+#include "intervals.h"
 #include "buffer.h"
 #include "window.h"
 
 #include "buffer.h"
 #include "window.h"
 
@@ -69,9 +76,11 @@ extern int sys_nerr;
 #ifdef HPUX
 #include <netio.h>
 #ifndef HPUX8
 #ifdef HPUX
 #include <netio.h>
 #ifndef HPUX8
+#ifndef HPUX9
 #include <errnet.h>
 #endif
 #endif
 #include <errnet.h>
 #endif
 #endif
+#endif
 
 #ifndef O_WRONLY
 #define O_WRONLY 1
 
 #ifndef O_WRONLY
 #define O_WRONLY 1
@@ -130,6 +139,12 @@ close_file_unwind (fd)
   close (XFASTINT (fd));
 }
 \f
   close (XFASTINT (fd));
 }
 \f
+Lisp_Object Qexpand_file_name;
+Lisp_Object Qdirectory_file_name;
+Lisp_Object Qfile_name_directory;
+Lisp_Object Qfile_name_nondirectory;
+Lisp_Object Qunhandled_file_name_directory;
+Lisp_Object Qfile_name_as_directory;
 Lisp_Object Qcopy_file;
 Lisp_Object Qmake_directory;
 Lisp_Object Qdelete_directory;
 Lisp_Object Qcopy_file;
 Lisp_Object Qmake_directory;
 Lisp_Object Qdelete_directory;
@@ -150,15 +165,21 @@ Lisp_Object Qfile_newer_than_file_p;
 Lisp_Object Qinsert_file_contents;
 Lisp_Object Qwrite_region;
 Lisp_Object Qverify_visited_file_modtime;
 Lisp_Object Qinsert_file_contents;
 Lisp_Object Qwrite_region;
 Lisp_Object Qverify_visited_file_modtime;
+Lisp_Object Qset_visited_file_modtime;
 
 
-/* If FILENAME is handled specially on account of its syntax,
-   return its handler function.  Otherwise, return nil.  */
-
-Lisp_Object
-find_file_handler (filename)
-     Lisp_Object filename;
+DEFUN ("find-file-name-handler", Ffind_file_name_handler, Sfind_file_name_handler, 1, 1, 0,
+  "Return FILENAME's handler function, if its syntax is handled specially.\n\
+Otherwise, return nil.\n\
+A file name is handled if one of the regular expressions in\n\
+`file-name-handler-alist' matches it.")
+  (filename)
+    Lisp_Object filename;
 {
 {
+  /* This function must not munge the match data.  */
   Lisp_Object chain;
   Lisp_Object chain;
+
+  CHECK_STRING (filename, 0);
+
   for (chain = Vfile_name_handler_alist; XTYPE (chain) == Lisp_Cons;
        chain = XCONS (chain)->cdr)
     {
   for (chain = Vfile_name_handler_alist; XTYPE (chain) == Lisp_Cons;
        chain = XCONS (chain)->cdr)
     {
@@ -169,9 +190,11 @@ find_file_handler (filename)
          Lisp_Object string;
          string = XCONS (elt)->car;
          if (XTYPE (string) == Lisp_String
          Lisp_Object string;
          string = XCONS (elt)->car;
          if (XTYPE (string) == Lisp_String
-             && fast_string_match (string, filename))
+             && fast_string_match (string, filename) >= 0)
            return XCONS (elt)->cdr;
        }
            return XCONS (elt)->cdr;
        }
+
+      QUIT;
     }
   return Qnil;
 }
     }
   return Qnil;
 }
@@ -188,9 +211,16 @@ on VMS, perhaps instead a string ending in `:', `]' or `>'.")
 {
   register unsigned char *beg;
   register unsigned char *p;
 {
   register unsigned char *beg;
   register unsigned char *p;
+  Lisp_Object handler;
 
   CHECK_STRING (file, 0);
 
 
   CHECK_STRING (file, 0);
 
+  /* If the file name has special constructs in it,
+     call the corresponding file handler.  */
+  handler = Ffind_file_name_handler (file);
+  if (!NILP (handler))
+    return call2 (handler, Qfile_name_directory, file);
+
   beg = XSTRING (file)->data;
   p = beg + XSTRING (file)->size;
 
   beg = XSTRING (file)->data;
   p = beg + XSTRING (file)->size;
 
@@ -215,9 +245,16 @@ or the entire name if it contains no slash.")
      Lisp_Object file;
 {
   register unsigned char *beg, *p, *end;
      Lisp_Object file;
 {
   register unsigned char *beg, *p, *end;
+  Lisp_Object handler;
 
   CHECK_STRING (file, 0);
 
 
   CHECK_STRING (file, 0);
 
+  /* If the file name has special constructs in it,
+     call the corresponding file handler.  */
+  handler = Ffind_file_name_handler (file);
+  if (!NILP (handler))
+    return call2 (handler, Qfile_name_nondirectory, file);
+
   beg = XSTRING (file)->data;
   end = p = beg + XSTRING (file)->size;
 
   beg = XSTRING (file)->data;
   end = p = beg + XSTRING (file)->size;
 
@@ -229,6 +266,29 @@ or the entire name if it contains no slash.")
 
   return make_string (p, end - p);
 }
 
   return make_string (p, end - p);
 }
+
+DEFUN ("unhandled-file-name-directory", Funhandled_file_name_directory, Sunhandled_file_name_directory, 1, 1, 0,
+  "Return a directly usable directory name somehow associated with FILENAME.\n\
+A `directly usable' directory name is one that may be used without the\n\
+intervention of any file handler.\n\
+If FILENAME is a directly usable file itself, return\n\
+(file-name-directory FILENAME).\n\
+The `call-process' and `start-process' functions use this function to\n\
+get a current directory to run processes in.")
+  (filename)
+    Lisp_Object filename;
+{
+  Lisp_Object handler;
+
+  /* If the file name has special constructs in it,
+     call the corresponding file handler.  */
+  handler = Ffind_file_name_handler (filename);
+  if (!NILP (handler))
+    return call2 (handler, Qunhandled_file_name_directory, filename);
+
+  return Ffile_name_directory (filename);
+}
+
 \f
 char *
 file_name_as_directory (out, in)
 \f
 char *
 file_name_as_directory (out, in)
@@ -316,10 +376,18 @@ On VMS, converts \"[X]FOO.DIR\" to \"[X.FOO]\", etc.")
      Lisp_Object file;
 {
   char *buf;
      Lisp_Object file;
 {
   char *buf;
+  Lisp_Object handler;
 
   CHECK_STRING (file, 0);
   if (NILP (file))
     return Qnil;
 
   CHECK_STRING (file, 0);
   if (NILP (file))
     return Qnil;
+
+  /* If the file name has special constructs in it,
+     call the corresponding file handler.  */
+  handler = Ffind_file_name_handler (file);
+  if (!NILP (handler))
+    return call2 (handler, Qfile_name_as_directory, file);
+
   buf = (char *) alloca (XSTRING (file)->size + 10);
   return build_string (file_name_as_directory (buf, XSTRING (file)->data));
 }
   buf = (char *) alloca (XSTRING (file)->size + 10);
   return build_string (file_name_as_directory (buf, XSTRING (file)->data));
 }
@@ -442,9 +510,11 @@ directory_file_name (src, dst)
                  && (ptr[rlen] == ']' || ptr[rlen] == '>')
                  && ptr[rlen - 1] == '.')
                {
                  && (ptr[rlen] == ']' || ptr[rlen] == '>')
                  && ptr[rlen - 1] == '.')
                {
-                 ptr[rlen - 1] = ']';
-                 ptr[rlen] = '\0';
-                 return directory_file_name (ptr, dst);
+                 char * buf = (char *) alloca (strlen (ptr) + 1);
+                 strcpy (buf, ptr);
+                 buf[rlen - 1] = ']';
+                 buf[rlen] = '\0';
+                 return directory_file_name (buf, dst);
                }
              else
                dst[slen - 1] = ':';
                }
              else
                dst[slen - 1] = ':';
@@ -481,11 +551,19 @@ it returns a file name such as \"[X]Y.DIR.1\".")
      Lisp_Object directory;
 {
   char *buf;
      Lisp_Object directory;
 {
   char *buf;
+  Lisp_Object handler;
 
   CHECK_STRING (directory, 0);
 
   if (NILP (directory))
     return Qnil;
 
   CHECK_STRING (directory, 0);
 
   if (NILP (directory))
     return Qnil;
+
+  /* If the file name has special constructs in it,
+     call the corresponding file handler.  */
+  handler = Ffind_file_name_handler (directory);
+  if (!NILP (handler))
+    return call2 (handler, Qdirectory_file_name, directory);
+
 #ifdef VMS
   /* 20 extra chars is insufficient for VMS, since we might perform a
      logical name translation. an equivalence string can be up to 255
 #ifdef VMS
   /* 20 extra chars is insufficient for VMS, since we might perform a
      logical name translation. an equivalence string can be up to 255
@@ -532,7 +610,6 @@ See also the function `substitute-in-file-name'.")
   int tlen;
   unsigned char *target;
   struct passwd *pw;
   int tlen;
   unsigned char *target;
   struct passwd *pw;
-  int lose;
 #ifdef VMS
   unsigned char * colon = 0;
   unsigned char * close = 0;
 #ifdef VMS
   unsigned char * colon = 0;
   unsigned char * close = 0;
@@ -541,9 +618,42 @@ See also the function `substitute-in-file-name'.")
   int lbrack = 0, rbrack = 0;
   int dots = 0;
 #endif /* VMS */
   int lbrack = 0, rbrack = 0;
   int dots = 0;
 #endif /* VMS */
+  Lisp_Object handler;
   
   CHECK_STRING (name, 0);
 
   
   CHECK_STRING (name, 0);
 
+  /* If the file name has special constructs in it,
+     call the corresponding file handler.  */
+  handler = Ffind_file_name_handler (name);
+  if (!NILP (handler))
+    return call3 (handler, Qexpand_file_name, name, defalt);
+
+  /* Use the buffer's default-directory if DEFALT is omitted.  */
+  if (NILP (defalt))
+    defalt = current_buffer->directory;
+  CHECK_STRING (defalt, 1);
+
+  /* Make sure DEFALT is properly expanded.
+     It would be better to do this down below where we actually use
+     defalt.  Unfortunately, calling Fexpand_file_name recursively
+     could invoke GC, and the strings might be relocated.  This would
+     be annoying because we have pointers into strings lying around
+     that would need adjusting, and people would add new pointers to
+     the code and forget to adjust them, resulting in intermittent bugs.
+     Putting this call here avoids all that crud.
+
+     The EQ test avoids infinite recursion.  */
+  if (! NILP (defalt) && !EQ (defalt, name)
+      /* This saves time in a common case.  */
+      && XSTRING (defalt)->data[0] != '/')
+    {
+      struct gcpro gcpro1;
+
+      GCPRO1 (name);
+      defalt = Fexpand_file_name (defalt, Qnil);
+      UNGCPRO;
+    }
+
 #ifdef VMS
   /* Filenames on VMS are always upper case.  */
   name = Fupcase (name);
 #ifdef VMS
   /* Filenames on VMS are always upper case.  */
   name = Fupcase (name);
@@ -560,10 +670,22 @@ See also the function `substitute-in-file-name'.")
 #endif /* VMS */
       )
     {
 #endif /* VMS */
       )
     {
+      /* 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;
+
       p = nm;
       p = nm;
-      lose = 0;
       while (*p)
        {
       while (*p)
        {
+         /* Since we know the path is absolute, we can assume that each
+            element starts with a "/".  */
+
+         /* "//" anywhere isn't necessarily hairy; we just start afresh
+            with the second slash.  */
          if (p[0] == '/' && p[1] == '/'
 #ifdef APOLLO
              /* // at start of filename is meaningful on Apollo system */
          if (p[0] == '/' && p[1] == '/'
 #ifdef APOLLO
              /* // at start of filename is meaningful on Apollo system */
@@ -571,11 +693,18 @@ See also the function `substitute-in-file-name'.")
 #endif /* APOLLO */
              )
            nm = p + 1;
 #endif /* APOLLO */
              )
            nm = p + 1;
+
+         /* "~" is hairy as the start of any path element.  */
          if (p[0] == '/' && p[1] == '~')
            nm = p + 1, lose = 1;
          if (p[0] == '/' && p[1] == '~')
            nm = p + 1, lose = 1;
-         if (p[0] == '/' && p[1] == '.'
-             && (p[2] == '/' || p[2] == 0
-                 || (p[2] == '.' && (p[3] == '/' || p[3] == 0))))
+
+         /* "." and ".." are hairy.  */
+         if (p[0] == '/'
+             && p[1] == '.'
+             && (p[2] == '/'
+                 || p[2] == 0
+                 || (p[2] == '.' && (p[3] == '/'
+                                     || p[3] == 0))))
            lose = 1;
 #ifdef VMS
          if (p[0] == '\\')
            lose = 1;
 #ifdef VMS
          if (p[0] == '\\')
@@ -669,44 +798,46 @@ See also the function `substitute-in-file-name'.")
   newdir = 0;
 
   if (nm[0] == '~')            /* prefix ~ */
   newdir = 0;
 
   if (nm[0] == '~')            /* prefix ~ */
-    if (nm[1] == '/'
+    {
+      if (nm[1] == '/'
 #ifdef VMS
 #ifdef VMS
-       || nm[1] == ':'
-#endif /* VMS */
-       || nm[1] == 0)/* ~ by itself */
-      {
-       if (!(newdir = (unsigned char *) egetenv ("HOME")))
-         newdir = (unsigned char *) "";
-       nm++;
+         || nm[1] == ':'
+#endif                         /* VMS */
+         || nm[1] == 0)        /* ~ by itself */
+       {
+         if (!(newdir = (unsigned char *) egetenv ("HOME")))
+           newdir = (unsigned char *) "";
+         nm++;
 #ifdef VMS
 #ifdef VMS
-       nm++;                   /* Don't leave the slash in nm.  */
-#endif /* VMS */
-      }
-    else                       /* ~user/filename */
-      {
-       for (p = nm; *p && (*p != '/'
+         nm++;                 /* Don't leave the slash in nm.  */
+#endif                         /* VMS */
+       }
+      else                     /* ~user/filename */
+       {
+         for (p = nm; *p && (*p != '/'
 #ifdef VMS
 #ifdef VMS
-                           && *p != ':'
-#endif /* VMS */
-                           ); p++);
-       o = (unsigned char *) alloca (p - nm + 1);
-       bcopy ((char *) nm, o, p - nm);
-       o [p - nm] = 0;
+                             && *p != ':'
+#endif                         /* VMS */
+                             ); p++);
+         o = (unsigned char *) alloca (p - nm + 1);
+         bcopy ((char *) nm, o, p - nm);
+         o [p - nm] = 0;
 
 
-       pw = (struct passwd *) getpwnam (o + 1);
-       if (pw)
-         {
-           newdir = (unsigned char *) pw -> pw_dir;
+         pw = (struct passwd *) getpwnam (o + 1);
+         if (pw)
+           {
+             newdir = (unsigned char *) pw -> pw_dir;
 #ifdef VMS
 #ifdef VMS
-           nm = p + 1;         /* skip the terminator */
+             nm = p + 1;       /* skip the terminator */
 #else
 #else
-           nm = p;
-#endif /* VMS */
-         }
+             nm = p;
+#endif                         /* VMS */
+           }
 
 
-       /* If we don't find a user of that name, leave the name
-          unchanged; don't move nm forward to p.  */
-      }
+         /* If we don't find a user of that name, leave the name
+            unchanged; don't move nm forward to p.  */
+       }
+    }
 
   if (nm[0] != '/'
 #ifdef VMS
 
   if (nm[0] != '/'
 #ifdef VMS
@@ -714,9 +845,6 @@ See also the function `substitute-in-file-name'.")
 #endif /* not VMS */
       && !newdir)
     {
 #endif /* not VMS */
       && !newdir)
     {
-      if (NILP (defalt))
-       defalt = current_buffer->directory;
-      CHECK_STRING (defalt, 1);
       newdir = XSTRING (defalt)->data;
     }
 
       newdir = XSTRING (defalt)->data;
     }
 
@@ -724,6 +852,9 @@ See also the function `substitute-in-file-name'.")
     {
       /* Get rid of any slash at the end of newdir.  */
       int length = strlen (newdir);
     {
       /* Get rid of any slash at the end of newdir.  */
       int length = strlen (newdir);
+      /* Adding `length > 1 &&' makes ~ expand into / when homedir
+        is the root dir.  People disagree about whether that is right.
+        Anyway, we can't take the risk of this change now.  */
       if (newdir[length - 1] == '/')
        {
          unsigned char *temp = (unsigned char *) alloca (length);
       if (newdir[length - 1] == '/')
        {
          unsigned char *temp = (unsigned char *) alloca (length);
@@ -748,7 +879,7 @@ See also the function `substitute-in-file-name'.")
        strcpy (target, newdir);
       else
 #endif
        strcpy (target, newdir);
       else
 #endif
-      file_name_as_directory (target, newdir);
+       file_name_as_directory (target, newdir);
     }
 
   strcat (target, nm);
     }
 
   strcat (target, nm);
@@ -757,7 +888,7 @@ See also the function `substitute-in-file-name'.")
     strcpy (target, sys_translate_unix (target));
 #endif /* VMS */
 
     strcpy (target, sys_translate_unix (target));
 #endif /* VMS */
 
-  /* Now canonicalize by removing /. and /foo/.. if they appear */
+  /* Now canonicalize by removing /. and /foo/.. if they appear */
 
   p = target;
   o = target;
 
   p = target;
   o = target;
@@ -820,9 +951,17 @@ See also the function `substitute-in-file-name'.")
          o = target;
          p++;
        }
          o = target;
          p++;
        }
-      else if (p[0] == '/' && p[1] == '.' &&
-              (p[2] == '/' || p[2] == 0))
-       p += 2;
+      else if (p[0] == '/'
+              && p[1] == '.'
+              && (p[2] == '/'
+                  || p[2] == 0))
+       {
+         /* If "/." is the entire filename, keep the "/".  Otherwise,
+            just delete the whole "/.".  */
+         if (o == target && p[2] == '\0')
+           *o++ = *p;
+         p += 2;
+       }
       else if (!strncmp (p, "/..", 3)
               /* `/../' is the "superroot" on certain file systems.  */
               && o != target
       else if (!strncmp (p, "/..", 3)
               /* `/../' is the "superroot" on certain file systems.  */
               && o != target
@@ -1367,11 +1506,7 @@ duplicates what `expand-file-name' does.")
 }
 \f
 /* A slightly faster and more convenient way to get
 }
 \f
 /* A slightly faster and more convenient way to get
-   (directory-file-name (expand-file-name FOO)).  The return value may
-   have had its last character zapped with a '\0' character, meaning
-   that it is acceptable to system calls, but not to other lisp
-   functions.  Callers should make sure that the return value doesn't
-   escape.  */
+   (directory-file-name (expand-file-name FOO)).  */
 
 Lisp_Object
 expand_and_dir_to_file (filename, defdir)
 
 Lisp_Object
 expand_and_dir_to_file (filename, defdir)
@@ -1391,11 +1526,8 @@ expand_and_dir_to_file (filename, defdir)
      stat behaves differently depending!  */
   if (XSTRING (abspath)->size > 1
       && XSTRING (abspath)->data[XSTRING (abspath)->size - 1] == '/')
      stat behaves differently depending!  */
   if (XSTRING (abspath)->size > 1
       && XSTRING (abspath)->data[XSTRING (abspath)->size - 1] == '/')
-    {
-      if (EQ (abspath, filename))
-       abspath = Fcopy_sequence (abspath);
-      XSTRING (abspath)->data[XSTRING (abspath)->size - 1] = 0;
-    }
+    /* We cannot take shortcuts; they might be wrong for magic file names.  */
+    abspath = Fdirectory_file_name (abspath);
 #endif
   return abspath;
 }
 #endif
   return abspath;
 }
@@ -1445,6 +1577,7 @@ A prefix arg makes KEEP-TIME non-nil.")
   Lisp_Object handler;
   struct gcpro gcpro1, gcpro2;
   int count = specpdl_ptr - specpdl;
   Lisp_Object handler;
   struct gcpro gcpro1, gcpro2;
   int count = specpdl_ptr - specpdl;
+  Lisp_Object args[6];
 
   GCPRO2 (filename, newname);
   CHECK_STRING (filename, 0);
 
   GCPRO2 (filename, newname);
   CHECK_STRING (filename, 0);
@@ -1452,11 +1585,15 @@ A prefix arg makes KEEP-TIME non-nil.")
   filename = Fexpand_file_name (filename, Qnil);
   newname = Fexpand_file_name (newname, Qnil);
 
   filename = Fexpand_file_name (filename, Qnil);
   newname = Fexpand_file_name (newname, Qnil);
 
-  /* If the file name has special constructs in it,
+  /* If the input file name has special constructs in it,
      call the corresponding file handler.  */
      call the corresponding file handler.  */
-  handler = find_file_handler (filename);
+  handler = Ffind_file_name_handler (filename);
+  /* Likewise for output file name.  */
+  if (NILP (handler))
+    handler = Ffind_file_name_handler (newname);
   if (!NILP (handler))
   if (!NILP (handler))
-    return call3 (handler, Qcopy_file, filename, newname);
+    return call5 (handler, Qcopy_file, filename, newname,
+                 ok_if_already_exists, keep_date);
 
   if (NILP (ok_if_already_exists)
       || XTYPE (ok_if_already_exists) == Lisp_Int)
 
   if (NILP (ok_if_already_exists)
       || XTYPE (ok_if_already_exists) == Lisp_Int)
@@ -1513,7 +1650,8 @@ A prefix arg makes KEEP-TIME non-nil.")
   return Qnil;
 }
 
   return Qnil;
 }
 
-DEFUN ("make-directory", Fmake_directory, Smake_directory, 1, 1, "FMake directory: ",
+DEFUN ("make-directory-internal", Fmake_directory_internal,
+       Smake_directory_internal, 1, 1, 0,
   "Create a directory.  One argument, a file name string.")
   (dirname)
      Lisp_Object dirname;
   "Create a directory.  One argument, a file name string.")
   (dirname)
      Lisp_Object dirname;
@@ -1524,10 +1662,10 @@ DEFUN ("make-directory", Fmake_directory, Smake_directory, 1, 1, "FMake director
   CHECK_STRING (dirname, 0);
   dirname = Fexpand_file_name (dirname, Qnil);
 
   CHECK_STRING (dirname, 0);
   dirname = Fexpand_file_name (dirname, Qnil);
 
-  handler = find_file_handler (dirname);
+  handler = Ffind_file_name_handler (dirname);
   if (!NILP (handler))
   if (!NILP (handler))
-    return call2 (handler, Qmake_directory, dirname);
+    return call3 (handler, Qmake_directory, dirname, Qnil);
+
   dir = XSTRING (dirname)->data;
 
   if (mkdir (dir, 0777) != 0)
   dir = XSTRING (dirname)->data;
 
   if (mkdir (dir, 0777) != 0)
@@ -1548,7 +1686,7 @@ DEFUN ("delete-directory", Fdelete_directory, Sdelete_directory, 1, 1, "FDelete
   dirname = Fexpand_file_name (dirname, Qnil);
   dir = XSTRING (dirname)->data;
 
   dirname = Fexpand_file_name (dirname, Qnil);
   dir = XSTRING (dirname)->data;
 
-  handler = find_file_handler (dirname);
+  handler = Ffind_file_name_handler (dirname);
   if (!NILP (handler))
     return call2 (handler, Qdelete_directory, dirname);
 
   if (!NILP (handler))
     return call2 (handler, Qdelete_directory, dirname);
 
@@ -1568,7 +1706,7 @@ If file has multiple names, it continues to exist with the other names.")
   CHECK_STRING (filename, 0);
   filename = Fexpand_file_name (filename, Qnil);
 
   CHECK_STRING (filename, 0);
   filename = Fexpand_file_name (filename, Qnil);
 
-  handler = find_file_handler (filename);
+  handler = Ffind_file_name_handler (filename);
   if (!NILP (handler))
     return call2 (handler, Qdelete_file, filename);
 
   if (!NILP (handler))
     return call2 (handler, Qdelete_file, filename);
 
@@ -1602,9 +1740,12 @@ This is what happens in interactive use with M-x.")
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
-  handler = find_file_handler (filename);
+  handler = Ffind_file_name_handler (filename);
+  if (NILP (handler))
+    handler = Ffind_file_name_handler (newname);
   if (!NILP (handler))
   if (!NILP (handler))
-    return call3 (handler, Qrename_file, filename, newname);
+    return call4 (handler, Qrename_file,
+                 filename, newname, ok_if_already_exists);
 
   if (NILP (ok_if_already_exists)
       || XTYPE (ok_if_already_exists) == Lisp_Int)
 
   if (NILP (ok_if_already_exists)
       || XTYPE (ok_if_already_exists) == Lisp_Int)
@@ -1619,7 +1760,10 @@ This is what happens in interactive use with M-x.")
     {
       if (errno == EXDEV)
        {
     {
       if (errno == EXDEV)
        {
-         Fcopy_file (filename, newname, ok_if_already_exists, Qt);
+         Fcopy_file (filename, newname,
+                     /* We have already prompted if it was an integer,
+                        so don't have copy-file prompt again.  */
+                     NILP (ok_if_already_exists) ? Qnil : Qt, Qt);
          Fdelete_file (filename);
        }
       else
          Fdelete_file (filename);
        }
       else
@@ -1661,9 +1805,10 @@ This is what happens in interactive use with M-x.")
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
-  handler = find_file_handler (filename);
+  handler = Ffind_file_name_handler (filename);
   if (!NILP (handler))
   if (!NILP (handler))
-    return call3 (handler, Qadd_name_to_file, filename, newname);
+    return call4 (handler, Qadd_name_to_file, filename, newname,
+                 ok_if_already_exists);
 
   if (NILP (ok_if_already_exists)
       || XTYPE (ok_if_already_exists) == Lisp_Int)
 
   if (NILP (ok_if_already_exists)
       || XTYPE (ok_if_already_exists) == Lisp_Int)
@@ -1712,9 +1857,10 @@ This happens for interactive use with M-x.")
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
-  handler = find_file_handler (filename);
+  handler = Ffind_file_name_handler (filename);
   if (!NILP (handler))
   if (!NILP (handler))
-    return call3 (handler, Qmake_symbolic_link, filename, linkname);
+    return call4 (handler, Qmake_symbolic_link, filename, linkname,
+                 ok_if_already_exists);
 
   if (NILP (ok_if_already_exists)
       || XTYPE (ok_if_already_exists) == Lisp_Int)
 
   if (NILP (ok_if_already_exists)
       || XTYPE (ok_if_already_exists) == Lisp_Int)
@@ -1725,7 +1871,7 @@ This happens for interactive use with M-x.")
       /* If we didn't complain already, silently delete existing file.  */
       if (errno == EEXIST)
        {
       /* If we didn't complain already, silently delete existing file.  */
       if (errno == EEXIST)
        {
-         unlink (XSTRING (filename)->data);
+         unlink (XSTRING (linkname)->data);
          if (0 <= symlink (XSTRING (filename)->data, XSTRING (linkname)->data))
            return Qnil;
        }
          if (0 <= symlink (XSTRING (filename)->data, XSTRING (linkname)->data))
            return Qnil;
        }
@@ -1829,16 +1975,16 @@ See also `file-readable-p' and `file-attributes'.")
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
-  handler = find_file_handler (filename);
+  handler = Ffind_file_name_handler (abspath);
   if (!NILP (handler))
   if (!NILP (handler))
-    return call2 (handler, Qfile_exists_p, filename);
+    return call2 (handler, Qfile_exists_p, abspath);
 
   return (access (XSTRING (abspath)->data, 0) >= 0) ? Qt : Qnil;
 }
 
 DEFUN ("file-executable-p", Ffile_executable_p, Sfile_executable_p, 1, 1, 0,
   "Return t if FILENAME can be executed by you.\n\
 
   return (access (XSTRING (abspath)->data, 0) >= 0) ? Qt : Qnil;
 }
 
 DEFUN ("file-executable-p", Ffile_executable_p, Sfile_executable_p, 1, 1, 0,
   "Return t if FILENAME can be executed by you.\n\
-For directories this means you can change to that directory.")
+For a directory, this means you can access files in that directory.")
   (filename)
     Lisp_Object filename;
 
   (filename)
     Lisp_Object filename;
 
@@ -1851,9 +1997,9 @@ For directories this means you can change to that directory.")
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
-  handler = find_file_handler (filename);
+  handler = Ffind_file_name_handler (abspath);
   if (!NILP (handler))
   if (!NILP (handler))
-    return call2 (handler, Qfile_executable_p, filename);
+    return call2 (handler, Qfile_executable_p, abspath);
 
   return (access (XSTRING (abspath)->data, 1) >= 0) ? Qt : Qnil;
 }
 
   return (access (XSTRING (abspath)->data, 1) >= 0) ? Qt : Qnil;
 }
@@ -1872,9 +2018,9 @@ See also `file-exists-p' and `file-attributes'.")
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
-  handler = find_file_handler (filename);
+  handler = Ffind_file_name_handler (abspath);
   if (!NILP (handler))
   if (!NILP (handler))
-    return call2 (handler, Qfile_readable_p, filename);
+    return call2 (handler, Qfile_readable_p, abspath);
 
   return (access (XSTRING (abspath)->data, 4) >= 0) ? Qt : Qnil;
 }
 
   return (access (XSTRING (abspath)->data, 4) >= 0) ? Qt : Qnil;
 }
@@ -1898,7 +2044,7 @@ Otherwise returns NIL.")
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
-  handler = find_file_handler (filename);
+  handler = Ffind_file_name_handler (filename);
   if (!NILP (handler))
     return call2 (handler, Qfile_symlink_p, filename);
 
   if (!NILP (handler))
     return call2 (handler, Qfile_symlink_p, filename);
 
@@ -1910,22 +2056,46 @@ Otherwise returns NIL.")
       valsize = readlink (XSTRING (filename)->data, buf, bufsize);
       if (valsize < bufsize) break;
       /* Buffer was not long enough */
       valsize = readlink (XSTRING (filename)->data, buf, bufsize);
       if (valsize < bufsize) break;
       /* Buffer was not long enough */
-      free (buf);
+      xfree (buf);
       bufsize *= 2;
     }
   if (valsize == -1)
     {
       bufsize *= 2;
     }
   if (valsize == -1)
     {
-      free (buf);
+      xfree (buf);
       return Qnil;
     }
   val = make_string (buf, valsize);
       return Qnil;
     }
   val = make_string (buf, valsize);
-  free (buf);
+  xfree (buf);
   return val;
 #else /* not S_IFLNK */
   return Qnil;
 #endif /* not S_IFLNK */
 }
 
   return val;
 #else /* not S_IFLNK */
   return Qnil;
 #endif /* not S_IFLNK */
 }
 
+#ifdef SOLARIS_BROKEN_ACCESS
+/* In Solaris 2.1, the readonly-ness of the filesystem is not
+   considered by the access system call.  This is Sun's bug, but we
+   still have to make Emacs work.  */
+
+#include <sys/statvfs.h>
+
+static int
+ro_fsys (path)
+    char *path;
+{
+    struct statvfs statvfsb;
+
+    if (statvfs(path, &statvfsb))
+      return 1;  /* error from statvfs, be conservative and say not wrtable */
+    else
+      /* Otherwise, fsys is ro if bit is set.  */
+      return statvfsb.f_flag & ST_RDONLY;
+}
+#else
+/* But on every other os, access has already done the right thing.  */
+#define ro_fsys(path) 0
+#endif
+
 /* Having this before file-symlink-p mysteriously caused it to be forgotten
    on the RT/PC.  */
 DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
 /* Having this before file-symlink-p mysteriously caused it to be forgotten
    on the RT/PC.  */
 DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
@@ -1941,18 +2111,21 @@ DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
-  handler = find_file_handler (filename);
+  handler = Ffind_file_name_handler (abspath);
   if (!NILP (handler))
   if (!NILP (handler))
-    return call2 (handler, Qfile_writable_p, filename);
+    return call2 (handler, Qfile_writable_p, abspath);
 
   if (access (XSTRING (abspath)->data, 0) >= 0)
 
   if (access (XSTRING (abspath)->data, 0) >= 0)
-    return (access (XSTRING (abspath)->data, 2) >= 0) ? Qt : Qnil;
+    return ((access (XSTRING (abspath)->data, 2) >= 0
+            && ! ro_fsys ((char *) XSTRING (abspath)->data))
+           ? Qt : Qnil);
   dir = Ffile_name_directory (abspath);
 #ifdef VMS
   if (!NILP (dir))
     dir = Fdirectory_file_name (dir);
 #endif /* VMS */
   dir = Ffile_name_directory (abspath);
 #ifdef VMS
   if (!NILP (dir))
     dir = Fdirectory_file_name (dir);
 #endif /* VMS */
-  return (access (!NILP (dir) ? (char *) XSTRING (dir)->data : "", 2) >= 0
+  return ((access (!NILP (dir) ? (char *) XSTRING (dir)->data : "", 2) >= 0
+          && ! ro_fsys ((char *) XSTRING (dir)->data))
          ? Qt : Qnil);
 }
 
          ? Qt : Qnil);
 }
 
@@ -1971,9 +2144,9 @@ if the directory so specified exists and really is a directory.")
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
-  handler = find_file_handler (filename);
+  handler = Ffind_file_name_handler (abspath);
   if (!NILP (handler))
   if (!NILP (handler))
-    return call2 (handler, Qfile_directory_p, filename);
+    return call2 (handler, Qfile_directory_p, abspath);
 
   if (stat (XSTRING (abspath)->data, &st) < 0)
     return Qnil;
 
   if (stat (XSTRING (abspath)->data, &st) < 0)
     return Qnil;
@@ -1994,7 +2167,7 @@ searchable directory.")
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
-  handler = find_file_handler (filename);
+  handler = Ffind_file_name_handler (filename);
   if (!NILP (handler))
     return call2 (handler, Qfile_accessible_directory_p, filename);
 
   if (!NILP (handler))
     return call2 (handler, Qfile_accessible_directory_p, filename);
 
@@ -2018,9 +2191,9 @@ DEFUN ("file-modes", Ffile_modes, Sfile_modes, 1, 1, 0,
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
-  handler = find_file_handler (filename);
+  handler = Ffind_file_name_handler (abspath);
   if (!NILP (handler))
   if (!NILP (handler))
-    return call2 (handler, Qfile_modes, filename);
+    return call2 (handler, Qfile_modes, abspath);
 
   if (stat (XSTRING (abspath)->data, &st) < 0)
     return Qnil;
 
   if (stat (XSTRING (abspath)->data, &st) < 0)
     return Qnil;
@@ -2041,9 +2214,9 @@ Only the 12 low bits of MODE are used.")
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
-  handler = find_file_handler (filename);
+  handler = Ffind_file_name_handler (abspath);
   if (!NILP (handler))
   if (!NILP (handler))
-    return call3 (handler, Qset_file_modes, filename, mode);
+    return call3 (handler, Qset_file_modes, abspath, mode);
 
 #ifndef APOLLO
   if (chmod (XSTRING (abspath)->data, XINT (mode)) < 0)
 
 #ifndef APOLLO
   if (chmod (XSTRING (abspath)->data, XINT (mode)) < 0)
@@ -2079,35 +2252,33 @@ Only the 12 low bits of MODE are used.")
   return Qnil;
 }
 
   return Qnil;
 }
 
-DEFUN ("set-umask", Fset_umask, Sset_umask, 1, 1, 0,
-    "Select which permission bits to disable in newly created files.\n\
-MASK should be an integer; if a permission's bit in MASK is 1,\n\
-subsequently created files will not have that permission enabled.\n\
-Only the low 9 bits are used.\n\
+DEFUN ("set-default-file-modes", Fset_default_file_modes, Sset_default_file_modes, 1, 1, 0,
+    "Set the file permission bits for newly created files.\n\
+The argument MODE should be an integer; only the low 9 bits are used.\n\
 This setting is inherited by subprocesses.")
 This setting is inherited by subprocesses.")
-  (mask)
-     Lisp_Object mask;
+  (mode)
+     Lisp_Object mode;
 {
 {
-  CHECK_NUMBER (mask, 0);
+  CHECK_NUMBER (mode, 0);
   
   
-  umask (XINT (mask) & 0777);
+  umask ((~ XINT (mode)) & 0777);
 
   return Qnil;
 }
 
 
   return Qnil;
 }
 
-DEFUN ("umask", Fumask, Sumask, 0, 0, 0,
-    "Return the current umask value.\n\
-The umask value determines which permissions are enabled in newly\n\
-created files.  If a permission's bit in the umask is 1, subsequently\n\
-created files will not have that permission enabled.")
+DEFUN ("default-file-modes", Fdefault_file_modes, Sdefault_file_modes, 0, 0, 0,
+    "Return the default file protection for created files.\n\
+The value is an integer.")
   ()
 {
   ()
 {
-  Lisp_Object mask;
+  int realmask;
+  Lisp_Object value;
 
 
-  XSET (mask, Lisp_Int, umask (0));
-  umask (XINT (mask));
+  realmask = umask (0);
+  umask (realmask);
 
 
-  return mask;
+  XSET (value, Lisp_Int, (~ realmask) & 0777);
+  return value;
 }
 
 #ifdef unix
 }
 
 #ifdef unix
@@ -2133,16 +2304,22 @@ otherwise, if FILE2 does not exist, the answer is t.")
   struct stat st;
   int mtime1;
   Lisp_Object handler;
   struct stat st;
   int mtime1;
   Lisp_Object handler;
+  struct gcpro gcpro1, gcpro2;
 
   CHECK_STRING (file1, 0);
   CHECK_STRING (file2, 0);
 
 
   CHECK_STRING (file1, 0);
   CHECK_STRING (file2, 0);
 
+  abspath1 = Qnil;
+  GCPRO2 (abspath1, file2);
   abspath1 = expand_and_dir_to_file (file1, current_buffer->directory);
   abspath2 = expand_and_dir_to_file (file2, current_buffer->directory);
   abspath1 = expand_and_dir_to_file (file1, current_buffer->directory);
   abspath2 = expand_and_dir_to_file (file2, current_buffer->directory);
+  UNGCPRO;
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
-  handler = find_file_handler (abspath1);
+  handler = Ffind_file_name_handler (abspath1);
+  if (NILP (handler))
+    handler = Ffind_file_name_handler (abspath2);
   if (!NILP (handler))
     return call3 (handler, Qfile_newer_than_file_p, abspath1, abspath2);
 
   if (!NILP (handler))
     return call3 (handler, Qfile_newer_than_file_p, abspath1, abspath2);
 
@@ -2158,15 +2335,18 @@ otherwise, if FILE2 does not exist, the answer is t.")
 }
 \f
 DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents,
 }
 \f
 DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents,
-  1, 2, 0,
+  1, 4, 0,
   "Insert contents of file FILENAME after point.\n\
   "Insert contents of file FILENAME after point.\n\
-Returns list of absolute pathname and length of data inserted.\n\
+Returns list of absolute file name and length of data inserted.\n\
 If second argument VISIT is non-nil, the buffer's visited filename\n\
 and last save file modtime are set, and it is marked unmodified.\n\
 If visiting and the file does not exist, visiting is completed\n\
 If second argument VISIT is non-nil, the buffer's visited filename\n\
 and last save file modtime are set, and it is marked unmodified.\n\
 If visiting and the file does not exist, visiting is completed\n\
-before the error is signaled.")
-  (filename, visit)
-     Lisp_Object filename, visit;
+before the error is signaled.\n\n\
+The optional third and fourth arguments BEG and END\n\
+specify what portion of the file to insert.\n\
+If VISIT is non-nil, BEG and END must be nil.")
+  (filename, visit, beg, end)
+     Lisp_Object filename, visit, beg, end;
 {
   struct stat st;
   register int fd;
 {
   struct stat st;
   register int fd;
@@ -2175,6 +2355,7 @@ before the error is signaled.")
   int count = specpdl_ptr - specpdl;
   struct gcpro gcpro1;
   Lisp_Object handler, val;
   int count = specpdl_ptr - specpdl;
   struct gcpro gcpro1;
   Lisp_Object handler, val;
+  int total;
 
   val = Qnil;
 
 
   val = Qnil;
 
@@ -2187,10 +2368,10 @@ before the error is signaled.")
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
-  handler = find_file_handler (filename);
+  handler = Ffind_file_name_handler (filename);
   if (!NILP (handler))
     {
   if (!NILP (handler))
     {
-      val = call3 (handler, Qinsert_file_contents, filename, visit);
+      val = call5 (handler, Qinsert_file_contents, filename, visit, beg, end);
       st.st_mtime = 0;
       goto handled;
     }
       st.st_mtime = 0;
       goto handled;
     }
@@ -2229,25 +2410,51 @@ before the error is signaled.")
   if (st.st_size < 0)
     error ("File size is negative");
 
   if (st.st_size < 0)
     error ("File size is negative");
 
+  if (!NILP (beg) || !NILP (end))
+    if (!NILP (visit))
+      error ("Attempt to visit less than an entire file");
+
+  if (!NILP (beg))
+    CHECK_NUMBER (beg, 0);
+  else
+    XFASTINT (beg) = 0;
+
+  if (!NILP (end))
+    CHECK_NUMBER (end, 0);
+  else
+    {
+      XSETINT (end, st.st_size);
+      if (XINT (end) != st.st_size)
+       error ("maximum buffer size exceeded");
+    }
+
+  total = XINT (end) - XINT (beg);
+
   {
     register Lisp_Object temp;
 
     /* Make sure point-max won't overflow after this insertion.  */
   {
     register Lisp_Object temp;
 
     /* Make sure point-max won't overflow after this insertion.  */
-    XSET (temp, Lisp_Int, st.st_size + Z);
-    if (st.st_size + Z != XINT (temp))
+    XSET (temp, Lisp_Int, total);
+    if (total != XINT (temp))
       error ("maximum buffer size exceeded");
   }
 
       error ("maximum buffer size exceeded");
   }
 
-  if (NILP (visit))
+  if (NILP (visit) && total > 0)
     prepare_to_modify_buffer (point, point);
 
   move_gap (point);
     prepare_to_modify_buffer (point, point);
 
   move_gap (point);
-  if (GAP_SIZE < st.st_size)
-    make_gap (st.st_size - GAP_SIZE);
-    
+  if (GAP_SIZE < total)
+    make_gap (total - GAP_SIZE);
+
+  if (XINT (beg) != 0)
+    {
+      if (lseek (fd, XINT (beg), 0) < 0)
+       report_file_error ("Setting file position", Fcons (filename, Qnil));
+    }
+
   while (1)
     {
   while (1)
     {
-      int try = min (st.st_size - inserted, 64 << 10);
+      int try = min (total - inserted, 64 << 10);
       int this;
 
       /* Allow quitting out of the actual I/O.  */
       int this;
 
       /* Allow quitting out of the actual I/O.  */
@@ -2270,8 +2477,13 @@ before the error is signaled.")
     }
 
   if (inserted > 0)
     }
 
   if (inserted > 0)
-    MODIFF++;
-  record_insert (point, inserted);
+    {
+      record_insert (point, inserted);
+
+      /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
+      offset_intervals (current_buffer, point, inserted);
+      MODIFF++;
+    }
 
   close (fd);
 
 
   close (fd);
 
@@ -2317,7 +2529,7 @@ before the error is signaled.")
                         Fcons (make_number (inserted),
                                Qnil)));
 }
                         Fcons (make_number (inserted),
                                Qnil)));
 }
-
+\f
 DEFUN ("write-region", Fwrite_region, Swrite_region, 3, 5,
   "r\nFWrite region to file: ",
   "Write current region into specified file.\n\
 DEFUN ("write-region", Fwrite_region, Swrite_region, 3, 5,
   "r\nFWrite region to file: ",
   "Write current region into specified file.\n\
@@ -2328,8 +2540,11 @@ Optional fourth argument APPEND if non-nil means\n\
 Optional fifth argument VISIT if t means\n\
   set the last-save-file-modtime of buffer to this file's modtime\n\
   and mark buffer not modified.\n\
 Optional fifth argument VISIT if t means\n\
   set the last-save-file-modtime of buffer to this file's modtime\n\
   and mark buffer not modified.\n\
-If VISIT is neither t nor nil, it means do not print\n\
-  the \"Wrote file\" message.\n\
+If VISIT is a string, it is a second file name;\n\
+  the output goes to FILENAME, but the buffer is marked as visiting VISIT.\n\
+  VISIT is also the file name to lock and unlock for clash detection.\n\
+If VISIT is neither t nor nil nor a string,\n\
+  that means do not print the \"Wrote file\" message.\n\
 Kludgy feature: if START is a string, then that string is written\n\
 to the file, instead of any buffer contents, and END is ignored.")
   (start, end, filename, append, visit)
 Kludgy feature: if START is a string, then that string is written\n\
 to the file, instead of any buffer contents, and END is ignored.")
   (start, end, filename, append, visit)
@@ -2346,6 +2561,8 @@ to the file, instead of any buffer contents, and END is ignored.")
   unsigned char *fname = 0;    /* If non-0, original filename (must rename) */
 #endif /* VMS */
   Lisp_Object handler;
   unsigned char *fname = 0;    /* If non-0, original filename (must rename) */
 #endif /* VMS */
   Lisp_Object handler;
+  Lisp_Object visit_file;
+  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
 
   /* Special kludge to simplify auto-saving */
   if (NILP (start))
 
   /* Special kludge to simplify auto-saving */
   if (NILP (start))
@@ -2357,43 +2574,43 @@ to the file, instead of any buffer contents, and END is ignored.")
     validate_region (&start, &end);
 
   filename = Fexpand_file_name (filename, Qnil);
     validate_region (&start, &end);
 
   filename = Fexpand_file_name (filename, Qnil);
-  fn = XSTRING (filename)->data;
+  if (XTYPE (visit) == Lisp_String)
+    visit_file = Fexpand_file_name (visit, Qnil);
+  else
+    visit_file = filename;
+
+  GCPRO4 (start, filename, visit, visit_file);
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
-  handler = find_file_handler (filename);
+  handler = Ffind_file_name_handler (filename);
 
   if (!NILP (handler))
     {
 
   if (!NILP (handler))
     {
-      Lisp_Object args[7];
       Lisp_Object val;
       Lisp_Object val;
-      args[0] = handler;
-      args[1] = Qwrite_region;
-      args[2] = start;
-      args[3] = end;
-      args[4] = filename;
-      args[5] = append;
-      args[6] = visit;
-      val = Ffuncall (7, args);
+      val = call6 (handler, Qwrite_region, start, end,
+                  filename, append, visit);
 
       /* Do this before reporting IO error
         to avoid a "file has changed on disk" warning on
         next attempt to save.  */
 
       /* Do this before reporting IO error
         to avoid a "file has changed on disk" warning on
         next attempt to save.  */
-      if (EQ (visit, Qt))
+      if (EQ (visit, Qt) || XTYPE (visit) == Lisp_String)
        {
          current_buffer->modtime = 0;
          current_buffer->save_modified = MODIFF;
          XFASTINT (current_buffer->save_length) = Z - BEG;
        {
          current_buffer->modtime = 0;
          current_buffer->save_modified = MODIFF;
          XFASTINT (current_buffer->save_length) = Z - BEG;
-         current_buffer->filename = filename;
+         current_buffer->filename = visit_file;
        }
        }
+      UNGCPRO;
       return val;
     }
 
 #ifdef CLASH_DETECTION
   if (!auto_saving)
       return val;
     }
 
 #ifdef CLASH_DETECTION
   if (!auto_saving)
-    lock_file (filename);
+    lock_file (visit_file);
 #endif /* CLASH_DETECTION */
 
 #endif /* CLASH_DETECTION */
 
+  fn = XSTRING (filename)->data;
   desc = -1;
   if (!NILP (append))
     desc = open (fn, O_WRONLY);
   desc = -1;
   if (!NILP (append))
     desc = open (fn, O_WRONLY);
@@ -2448,11 +2665,13 @@ to the file, instead of any buffer contents, and END is ignored.")
   desc = creat (fn, auto_saving ? auto_save_mode_bits : 0666);
 #endif /* not VMS */
 
   desc = creat (fn, auto_saving ? auto_save_mode_bits : 0666);
 #endif /* not VMS */
 
+  UNGCPRO;
+
   if (desc < 0)
     {
 #ifdef CLASH_DETECTION
       save_errno = errno;
   if (desc < 0)
     {
 #ifdef CLASH_DETECTION
       save_errno = errno;
-      if (!auto_saving) unlock_file (filename);
+      if (!auto_saving) unlock_file (visit_file);
       errno = save_errno;
 #endif /* CLASH_DETECTION */
       report_file_error ("Opening output file", Fcons (filename, Qnil));
       errno = save_errno;
 #endif /* CLASH_DETECTION */
       report_file_error ("Opening output file", Fcons (filename, Qnil));
@@ -2464,7 +2683,7 @@ to the file, instead of any buffer contents, and END is ignored.")
     if (lseek (desc, 0, 2) < 0)
       {
 #ifdef CLASH_DETECTION
     if (lseek (desc, 0, 2) < 0)
       {
 #ifdef CLASH_DETECTION
-       if (!auto_saving) unlock_file (filename);
+       if (!auto_saving) unlock_file (visit_file);
 #endif /* CLASH_DETECTION */
        report_file_error ("Lseek error", Fcons (filename, Qnil));
       }
 #endif /* CLASH_DETECTION */
        report_file_error ("Lseek error", Fcons (filename, Qnil));
       }
@@ -2520,15 +2739,13 @@ to the file, instead of any buffer contents, and END is ignored.")
 
   immediate_quit = 0;
 
 
   immediate_quit = 0;
 
-#ifndef USG
-#ifndef VMS
-#ifndef BSD4_1
+#ifdef HAVE_FSYNC
   /* Note fsync appears to change the modtime on BSD4.2 (both vax and sun).
      Disk full in NFS may be reported here.  */
   /* Note fsync appears to change the modtime on BSD4.2 (both vax and sun).
      Disk full in NFS may be reported here.  */
-  if (fsync (desc) < 0)
+  /* mib says that closing the file will try to write as fast as NFS can do
+     it, and that means the fsync here is not crucial for autosave files.  */
+  if (!auto_saving && fsync (desc) < 0)
     failure = 1, save_errno = errno;
     failure = 1, save_errno = errno;
-#endif
-#endif
 #endif
 
   /* Spurious "file has changed on disk" warnings have been 
 #endif
 
   /* Spurious "file has changed on disk" warnings have been 
@@ -2572,29 +2789,29 @@ to the file, instead of any buffer contents, and END is ignored.")
 
 #ifdef CLASH_DETECTION
   if (!auto_saving)
 
 #ifdef CLASH_DETECTION
   if (!auto_saving)
-    unlock_file (filename);
+    unlock_file (visit_file);
 #endif /* CLASH_DETECTION */
 
   /* Do this before reporting IO error
      to avoid a "file has changed on disk" warning on
      next attempt to save.  */
 #endif /* CLASH_DETECTION */
 
   /* Do this before reporting IO error
      to avoid a "file has changed on disk" warning on
      next attempt to save.  */
-  if (EQ (visit, Qt))
+  if (EQ (visit, Qt) || XTYPE (visit) == Lisp_String)
     current_buffer->modtime = st.st_mtime;
 
   if (failure)
     error ("IO error writing %s: %s", fn, err_str (save_errno));
 
     current_buffer->modtime = st.st_mtime;
 
   if (failure)
     error ("IO error writing %s: %s", fn, err_str (save_errno));
 
-  if (EQ (visit, Qt))
+  if (EQ (visit, Qt) || XTYPE (visit) == Lisp_String)
     {
       current_buffer->save_modified = MODIFF;
       XFASTINT (current_buffer->save_length) = Z - BEG;
     {
       current_buffer->save_modified = MODIFF;
       XFASTINT (current_buffer->save_length) = Z - BEG;
-      current_buffer->filename = filename;
+      current_buffer->filename = visit_file;
     }
   else if (!NILP (visit))
     return Qnil;
 
   if (!auto_saving)
     }
   else if (!NILP (visit))
     return Qnil;
 
   if (!auto_saving)
-    message ("Wrote %s", fn);
+    message ("Wrote %s", XSTRING (visit_file)->data);
 
   return Qnil;
 }
 
   return Qnil;
 }
@@ -2652,9 +2869,9 @@ This means that the file has not been changed since it was visited or saved.")
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
 
   /* If the file name has special constructs in it,
      call the corresponding file handler.  */
-  handler = find_file_handler (b->filename);
+  handler = Ffind_file_name_handler (b->filename);
   if (!NILP (handler))
   if (!NILP (handler))
-    return call2 (handler, Qverify_visited_file_modtime, b->filename);
+    return call2 (handler, Qverify_visited_file_modtime, buf);
 
   if (stat (XSTRING (b->filename)->data, &st) < 0)
     {
 
   if (stat (XSTRING (b->filename)->data, &st) < 0)
     {
@@ -2684,27 +2901,46 @@ Next attempt to save will certainly not complain of a discrepancy.")
   return Qnil;
 }
 
   return Qnil;
 }
 
+DEFUN ("visited-file-modtime", Fvisited_file_modtime,
+  Svisited_file_modtime, 0, 0, 0,
+  "Return the current buffer's recorded visited file modification time.\n\
+The value is a list of the form (HIGH . LOW), like the time values\n\
+that `file-attributes' returns.")
+  ()
+{
+  return long_to_cons (current_buffer->modtime);
+}
+
 DEFUN ("set-visited-file-modtime", Fset_visited_file_modtime,
 DEFUN ("set-visited-file-modtime", Fset_visited_file_modtime,
-  Sset_visited_file_modtime, 0, 0, 0,
+  Sset_visited_file_modtime, 0, 1, 0,
   "Update buffer's recorded modification time from the visited file's time.\n\
 Useful if the buffer was not read from the file normally\n\
   "Update buffer's recorded modification time from the visited file's time.\n\
 Useful if the buffer was not read from the file normally\n\
-or if the file itself has been changed for some known benign reason.")
-  ()
+or if the file itself has been changed for some known benign reason.\n\
+An argument specifies the modification time value to use\n\
+\(instead of that of the visited file), in the form of a list\n\
+\(HIGH . LOW) or (HIGH LOW).")
+  (time_list)
+     Lisp_Object time_list;
 {
 {
-  register Lisp_Object filename;
-  struct stat st;
-  Lisp_Object handler;
-
-  filename = Fexpand_file_name (current_buffer->filename, Qnil);
-
-  /* If the file name has special constructs in it,
-     call the corresponding file handler.  */
-  handler = find_file_handler (filename);
-  if (!NILP (handler))
-    current_buffer->modtime = 0;
-  
-  else if (stat (XSTRING (filename)->data, &st) >= 0)
-    current_buffer->modtime = st.st_mtime;
+  if (!NILP (time_list))
+    current_buffer->modtime = cons_to_long (time_list);
+  else
+    {
+      register Lisp_Object filename;
+      struct stat st;
+      Lisp_Object handler;
+
+      filename = Fexpand_file_name (current_buffer->filename, Qnil);
+
+      /* If the file name has special constructs in it,
+        call the corresponding file handler.  */
+      handler = Ffind_file_name_handler (filename);
+      if (!NILP (handler))
+       /* The handler can find the file name the same way we did.  */
+       return call2 (handler, Qset_visited_file_modtime, Qnil);
+      else if (stat (XSTRING (filename)->data, &st) >= 0)
+       current_buffer->modtime = st.st_mtime;
+    }
 
   return Qnil;
 }
 
   return Qnil;
 }
@@ -2752,74 +2988,97 @@ so that your editing is not lost if the system crashes.\n\
 This file is not the file you visited; that changes only when you save.\n\n\
 Non-nil first argument means do not print any message if successful.\n\
 Non-nil second argument means save only current buffer.")
 This file is not the file you visited; that changes only when you save.\n\n\
 Non-nil first argument means do not print any message if successful.\n\
 Non-nil second argument means save only current buffer.")
-  (nomsg)
-     Lisp_Object nomsg;
+  (no_message, current_only)
+     Lisp_Object no_message, current_only;
 {
   struct buffer *old = current_buffer, *b;
   Lisp_Object tail, buf;
   int auto_saved = 0;
   char *omessage = echo_area_glyphs;
 {
   struct buffer *old = current_buffer, *b;
   Lisp_Object tail, buf;
   int auto_saved = 0;
   char *omessage = echo_area_glyphs;
-  extern minibuf_level;
+  extern int minibuf_level;
+  int do_handled_files;
+  Lisp_Object oquit;
+
+  /* Ordinarily don't quit within this function,
+     but don't make it impossible to quit (in case we get hung in I/O).  */
+  oquit = Vquit_flag;
+  Vquit_flag = Qnil;
 
   /* No GCPRO needed, because (when it matters) all Lisp_Object variables
      point to non-strings reached from Vbuffer_alist.  */
 
   auto_saving = 1;
   if (minibuf_level)
 
   /* No GCPRO needed, because (when it matters) all Lisp_Object variables
      point to non-strings reached from Vbuffer_alist.  */
 
   auto_saving = 1;
   if (minibuf_level)
-    nomsg = Qt;
+    no_message = Qt;
 
   /* Vrun_hooks is nil before emacs is dumped, and inc-vers.el will
      eventually call do-auto-save, so don't err here in that case. */
   if (!NILP (Vrun_hooks))
     call1 (Vrun_hooks, intern ("auto-save-hook"));
 
 
   /* Vrun_hooks is nil before emacs is dumped, and inc-vers.el will
      eventually call do-auto-save, so don't err here in that case. */
   if (!NILP (Vrun_hooks))
     call1 (Vrun_hooks, intern ("auto-save-hook"));
 
-  for (tail = Vbuffer_alist; XGCTYPE (tail) == Lisp_Cons;
-       tail = XCONS (tail)->cdr)
-    {
-      buf = XCONS (XCONS (tail)->car)->cdr;
-      b = XBUFFER (buf);
-      /* Check for auto save enabled
-        and file changed since last auto save
-        and file changed since last real save.  */
-      if (XTYPE (b->auto_save_file_name) == Lisp_String
-         && b->save_modified < BUF_MODIFF (b)
-         && b->auto_save_modified < BUF_MODIFF (b))
-       {
-         if ((XFASTINT (b->save_length) * 10
-              > (BUF_Z (b) - BUF_BEG (b)) * 13)
-             /* A short file is likely to change a large fraction;
-                spare the user annoying messages.  */
-             && XFASTINT (b->save_length) > 5000
-             /* These messages are frequent and annoying for `*mail*'.  */
-             && !EQ (b->filename, Qnil))
-           {
-             /* It has shrunk too much; turn off auto-saving here.  */
-             message ("Buffer %s has shrunk a lot; auto save turned off there",
-                      XSTRING (b->name)->data);
-             /* User can reenable saving with M-x auto-save.  */
-             b->auto_save_file_name = Qnil;
-             /* Prevent warning from repeating if user does so.  */
-             XFASTINT (b->save_length) = 0;
-             Fsleep_for (make_number (1), Qnil);
-             continue;
-           }
-         set_buffer_internal (b);
-         if (!auto_saved && NILP (nomsg))
-           message1 ("Auto-saving...");
-         internal_condition_case (auto_save_1, Qt, auto_save_error);
-         auto_saved++;
-         b->auto_save_modified = BUF_MODIFF (b);
-         XFASTINT (current_buffer->save_length) = Z - BEG;
-         set_buffer_internal (old);
-       }
-    }
+  /* First, save all files which don't have handlers.  If Emacs is
+     crashing, the handlers may tweak what is causing Emacs to crash
+     in the first place, and it would be a shame if Emacs failed to
+     autosave perfectly ordinary files because it couldn't handle some
+     ange-ftp'd file.  */
+  for (do_handled_files = 0; do_handled_files < 2; do_handled_files++)
+    for (tail = Vbuffer_alist; XGCTYPE (tail) == Lisp_Cons;
+        tail = XCONS (tail)->cdr)
+      {
+       buf = XCONS (XCONS (tail)->car)->cdr;
+       b = XBUFFER (buf);
+
+       if (!NILP (current_only)
+           && b != current_buffer)
+         continue;
+      
+       /* Check for auto save enabled
+          and file changed since last auto save
+          and file changed since last real save.  */
+       if (XTYPE (b->auto_save_file_name) == Lisp_String
+           && b->save_modified < BUF_MODIFF (b)
+           && b->auto_save_modified < BUF_MODIFF (b)
+           && (do_handled_files
+               || NILP (Ffind_file_name_handler (b->auto_save_file_name))))
+         {
+           if ((XFASTINT (b->save_length) * 10
+                > (BUF_Z (b) - BUF_BEG (b)) * 13)
+               /* A short file is likely to change a large fraction;
+                  spare the user annoying messages.  */
+               && XFASTINT (b->save_length) > 5000
+               /* These messages are frequent and annoying for `*mail*'.  */
+               && !EQ (b->filename, Qnil)
+               && NILP (no_message))
+             {
+               /* It has shrunk too much; turn off auto-saving here.  */
+               message ("Buffer %s has shrunk a lot; auto save turned off there",
+                        XSTRING (b->name)->data);
+               /* User can reenable saving with M-x auto-save.  */
+               b->auto_save_file_name = Qnil;
+               /* Prevent warning from repeating if user does so.  */
+               XFASTINT (b->save_length) = 0;
+               Fsleep_for (make_number (1), Qnil);
+               continue;
+             }
+           set_buffer_internal (b);
+           if (!auto_saved && NILP (no_message))
+             message1 ("Auto-saving...");
+           internal_condition_case (auto_save_1, Qt, auto_save_error);
+           auto_saved++;
+           b->auto_save_modified = BUF_MODIFF (b);
+           XFASTINT (current_buffer->save_length) = Z - BEG;
+           set_buffer_internal (old);
+         }
+      }
 
   /* Prevent another auto save till enough input events come in.  */
   record_auto_save ();
 
 
   /* Prevent another auto save till enough input events come in.  */
   record_auto_save ();
 
-  if (auto_saved && NILP (nomsg))
+  if (auto_saved && NILP (no_message))
     message1 (omessage ? omessage : "Auto-saving...done");
 
     message1 (omessage ? omessage : "Auto-saving...done");
 
+  Vquit_flag = oquit;
+
   auto_saving = 0;
   return Qnil;
 }
   auto_saving = 0;
   return Qnil;
 }
@@ -2855,36 +3114,46 @@ DEFUN ("read-file-name-internal", Fread_file_name_internal, Sread_file_name_inte
      lambda for verify final value */
 {
   Lisp_Object name, specdir, realdir, val, orig_string;
      lambda for verify final value */
 {
   Lisp_Object name, specdir, realdir, val, orig_string;
+  int changed;
+  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
+
+  realdir = dir;
+  name = string;
+  orig_string = Qnil;
+  specdir = Qnil;
+  changed = 0;
+  /* No need to protect ACTION--we only compare it with t and nil.  */
+  GCPRO4 (string, realdir, name, specdir);
 
   if (XSTRING (string)->size == 0)
     {
 
   if (XSTRING (string)->size == 0)
     {
-      orig_string = Qnil; 
-      name = string;
-      realdir = dir;
       if (EQ (action, Qlambda))
       if (EQ (action, Qlambda))
-       return Qnil;
+       {
+         UNGCPRO;
+         return Qnil;
+       }
     }
   else
     {
       orig_string = string;
       string = Fsubstitute_in_file_name (string);
     }
   else
     {
       orig_string = string;
       string = Fsubstitute_in_file_name (string);
+      changed = NILP (Fstring_equal (string, orig_string));
       name = Ffile_name_nondirectory (string);
       name = Ffile_name_nondirectory (string);
-      realdir = Ffile_name_directory (string);
-      if (NILP (realdir))
-       realdir = dir;
-      else
-       realdir = Fexpand_file_name (realdir, dir);
+      val = Ffile_name_directory (string);
+      if (! NILP (val))
+       realdir = Fexpand_file_name (val, realdir);
     }
 
   if (NILP (action))
     {
       specdir = Ffile_name_directory (string);
       val = Ffile_name_completion (name, realdir);
     }
 
   if (NILP (action))
     {
       specdir = Ffile_name_directory (string);
       val = Ffile_name_completion (name, realdir);
+      UNGCPRO;
       if (XTYPE (val) != Lisp_String)
        {
       if (XTYPE (val) != Lisp_String)
        {
-         if (NILP (Fstring_equal (string, orig_string)))
+         if (changed)
            return string;
            return string;
-         return (val);
+         return val;
        }
 
       if (!NILP (specdir))
        }
 
       if (!NILP (specdir))
@@ -2916,8 +3185,9 @@ DEFUN ("read-file-name-internal", Fread_file_name_internal, Sread_file_name_inte
          }
       }
 #endif /* Not VMS */
          }
       }
 #endif /* Not VMS */
-      return (val);
+      return val;
     }
     }
+  UNGCPRO;
 
   if (EQ (action, Qt))
     return Ffile_name_all_completions (name, realdir);
 
   if (EQ (action, Qt))
     return Ffile_name_all_completions (name, realdir);
@@ -3003,6 +3273,8 @@ DIR defaults to current buffer's directory default.")
   tem = Fstring_equal (val, insdef);
   if (!NILP (tem) && !NILP (defalt))
     return defalt;
   tem = Fstring_equal (val, insdef);
   if (!NILP (tem) && !NILP (defalt))
     return defalt;
+  if (XSTRING (val)->size == 0 && NILP (insdef))
+    return defalt;
   return Fsubstitute_in_file_name (val);
 }
 
   return Fsubstitute_in_file_name (val);
 }
 
@@ -3075,6 +3347,12 @@ DIR defaults to current buffer's directory default.")
 \f
 syms_of_fileio ()
 {
 \f
 syms_of_fileio ()
 {
+  Qexpand_file_name = intern ("expand-file-name");
+  Qdirectory_file_name = intern ("directory-file-name");
+  Qfile_name_directory = intern ("file-name-directory");
+  Qfile_name_nondirectory = intern ("file-name-nondirectory");
+  Qunhandled_file_name_directory = intern ("unhandled-file-name-directory");
+  Qfile_name_as_directory = intern ("file-name-as-directory");
   Qcopy_file = intern ("copy-file");
   Qmake_directory = intern ("make-directory");
   Qdelete_directory = intern ("delete-directory");
   Qcopy_file = intern ("copy-file");
   Qmake_directory = intern ("make-directory");
   Qdelete_directory = intern ("delete-directory");
@@ -3095,10 +3373,14 @@ syms_of_fileio ()
   Qinsert_file_contents = intern ("insert-file-contents");
   Qwrite_region = intern ("write-region");
   Qverify_visited_file_modtime = intern ("verify-visited-file-modtime");
   Qinsert_file_contents = intern ("insert-file-contents");
   Qwrite_region = intern ("write-region");
   Qverify_visited_file_modtime = intern ("verify-visited-file-modtime");
-
-  Qfile_name_history = intern ("file-name-history");
-  Fset (Qfile_name_history, Qnil);
-
+  Qset_visited_file_modtime = intern ("set-visited-file-modtime");
+
+  staticpro (&Qexpand_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);
   staticpro (&Qdelete_directory);
   staticpro (&Qcopy_file);
   staticpro (&Qmake_directory);
   staticpro (&Qdelete_directory);
@@ -3119,6 +3401,9 @@ syms_of_fileio ()
   staticpro (&Qinsert_file_contents);
   staticpro (&Qwrite_region);
   staticpro (&Qverify_visited_file_modtime);
   staticpro (&Qinsert_file_contents);
   staticpro (&Qwrite_region);
   staticpro (&Qverify_visited_file_modtime);
+
+  Qfile_name_history = intern ("file-name-history");
+  Fset (Qfile_name_history, Qnil);
   staticpro (&Qfile_name_history);
 
   Qfile_error = intern ("file-error");
   staticpro (&Qfile_name_history);
 
   Qfile_error = intern ("file-error");
@@ -3156,16 +3441,22 @@ to be handled; the remaining arguments are the arguments that were\n\
 passed to that primitive.  For example, if you do\n\
     (file-exists-p FILENAME)\n\
 and FILENAME is handled by HANDLER, then HANDLER is called like this:\n\
 passed to that primitive.  For example, if you do\n\
     (file-exists-p FILENAME)\n\
 and FILENAME is handled by HANDLER, then HANDLER is called like this:\n\
-    (funcall HANDLER FILENAME)");
+    (funcall HANDLER 'file-exists-p FILENAME)\n\
+The function `find-file-name-handler' checks this list for a handler\n\
+for its argument.");
+  Vfile_name_handler_alist = Qnil;
+
+  defsubr (&Sfind_file_name_handler);
   defsubr (&Sfile_name_directory);
   defsubr (&Sfile_name_nondirectory);
   defsubr (&Sfile_name_directory);
   defsubr (&Sfile_name_nondirectory);
+  defsubr (&Sunhandled_file_name_directory);
   defsubr (&Sfile_name_as_directory);
   defsubr (&Sdirectory_file_name);
   defsubr (&Smake_temp_name);
   defsubr (&Sexpand_file_name);
   defsubr (&Ssubstitute_in_file_name);
   defsubr (&Scopy_file);
   defsubr (&Sfile_name_as_directory);
   defsubr (&Sdirectory_file_name);
   defsubr (&Smake_temp_name);
   defsubr (&Sexpand_file_name);
   defsubr (&Ssubstitute_in_file_name);
   defsubr (&Scopy_file);
-  defsubr (&Smake_directory);
+  defsubr (&Smake_directory_internal);
   defsubr (&Sdelete_directory);
   defsubr (&Sdelete_file);
   defsubr (&Srename_file);
   defsubr (&Sdelete_directory);
   defsubr (&Sdelete_file);
   defsubr (&Srename_file);
@@ -3189,13 +3480,14 @@ and FILENAME is handled by HANDLER, then HANDLER is called like this:\n\
   defsubr (&Sfile_accessible_directory_p);
   defsubr (&Sfile_modes);
   defsubr (&Sset_file_modes);
   defsubr (&Sfile_accessible_directory_p);
   defsubr (&Sfile_modes);
   defsubr (&Sset_file_modes);
-  defsubr (&Sset_umask);
-  defsubr (&Sumask);
+  defsubr (&Sset_default_file_modes);
+  defsubr (&Sdefault_file_modes);
   defsubr (&Sfile_newer_than_file_p);
   defsubr (&Sinsert_file_contents);
   defsubr (&Swrite_region);
   defsubr (&Sverify_visited_file_modtime);
   defsubr (&Sclear_visited_file_modtime);
   defsubr (&Sfile_newer_than_file_p);
   defsubr (&Sinsert_file_contents);
   defsubr (&Swrite_region);
   defsubr (&Sverify_visited_file_modtime);
   defsubr (&Sclear_visited_file_modtime);
+  defsubr (&Svisited_file_modtime);
   defsubr (&Sset_visited_file_modtime);
   defsubr (&Sdo_auto_save);
   defsubr (&Sset_buffer_auto_saved);
   defsubr (&Sset_visited_file_modtime);
   defsubr (&Sdo_auto_save);
   defsubr (&Sset_buffer_auto_saved);
@@ -3204,5 +3496,7 @@ and FILENAME is handled by HANDLER, then HANDLER is called like this:\n\
   defsubr (&Sread_file_name_internal);
   defsubr (&Sread_file_name);
 
   defsubr (&Sread_file_name_internal);
   defsubr (&Sread_file_name);
 
+#ifdef unix
   defsubr (&Sunix_sync);
   defsubr (&Sunix_sync);
+#endif
 }
 }