]> code.delx.au - gnu-emacs/blobdiff - src/fileio.c
Fix an error in Tramp for rsync
[gnu-emacs] / src / fileio.c
index a36dfbcfa364b78a0546b04ec823bbc8bad3669d..b1f9d3cf73aaf6216802eeec6bd9e746412fa620 100644 (file)
@@ -1,13 +1,13 @@
 /* File IO for GNU Emacs.
 
-Copyright (C) 1985-1988, 1993-2015 Free Software Foundation, Inc.
+Copyright (C) 1985-1988, 1993-2016 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 GNU Emacs is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+the Free Software Foundation, either version 3 of the License, or (at
+your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -36,14 +36,14 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <selinux/context.h>
 #endif
 
-#ifdef HAVE_ACL_SET_FILE
+#if USE_ACL && defined HAVE_ACL_SET_FILE
 #include <sys/acl.h>
 #endif
 
 #include <c-ctype.h>
 
 #include "lisp.h"
-#include "intervals.h"
+#include "composite.h"
 #include "character.h"
 #include "buffer.h"
 #include "coding.h"
@@ -51,7 +51,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "blockinput.h"
 #include "region-cache.h"
 #include "frame.h"
-#include "dispextern.h"
 
 #ifdef WINDOWSNT
 #define NOMINMAX 1
@@ -186,11 +185,10 @@ void
 report_file_errno (char const *string, Lisp_Object name, int errorno)
 {
   Lisp_Object data = CONSP (name) || NILP (name) ? name : list1 (name);
-  synchronize_system_messages_locale ();
-  char *str = strerror (errorno);
+  char *str = emacs_strerror (errorno);
+  AUTO_STRING (unibyte_str, str);
   Lisp_Object errstring
-    = code_convert_string_norecord (build_unibyte_string (str),
-                                   Vlocale_coding_system, 0);
+    = code_convert_string_norecord (unibyte_str, Vlocale_coding_system, 0);
   Lisp_Object errdata = Fcons (errstring, data);
 
   if (errorno == EEXIST)
@@ -210,6 +208,21 @@ report_file_error (char const *string, Lisp_Object name)
   report_file_errno (string, name, errno);
 }
 
+/* Like report_file_error, but reports a file-notify-error instead.  */
+
+void
+report_file_notify_error (const char *string, Lisp_Object name)
+{
+  char *str = emacs_strerror (errno);
+  AUTO_STRING (unibyte_str, str);
+  Lisp_Object errstring
+    = code_convert_string_norecord (unibyte_str, Vlocale_coding_system, 0);
+  Lisp_Object data = CONSP (name) || NILP (name) ? name : list1 (name);
+  Lisp_Object errdata = Fcons (errstring, data);
+
+  xsignal (Qfile_notify_error, Fcons (build_string (string), errdata));
+}
+
 void
 close_file_unwind (int fd)
 {
@@ -435,7 +448,7 @@ DEFUN ("unhandled-file-name-directory", Funhandled_file_name_directory,
 A `directly usable' directory name is one that may be used without the
 intervention of any file handler.
 If FILENAME is a directly usable file itself, return
-\(file-name-directory FILENAME).
+\(file-name-as-directory FILENAME).
 If FILENAME refers to a file which is not accessible from a local process,
 then this should return nil.
 The `call-process' and `start-process' functions use this function to
@@ -454,7 +467,7 @@ get a current directory to run processes in.  */)
       return STRINGP (handled_name) ? handled_name : Qnil;
     }
 
-  return Ffile_name_directory (filename);
+  return Ffile_name_as_directory (filename);
 }
 
 /* Maximum number of bytes that DST will be longer than SRC
@@ -1000,11 +1013,9 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
          /* Drive must be set, so this is okay.  */
          if (strcmp (nm - 2, SSDATA (name)) != 0)
            {
-             char temp[] = " :";
-
              name = make_specified_string (nm, -1, p - nm, multibyte);
-             temp[0] = DRIVE_LETTER (drive);
-             AUTO_STRING (drive_prefix, temp);
+             char temp[] = { DRIVE_LETTER (drive), ':', 0 };
+             AUTO_STRING_WITH_LEN (drive_prefix, temp, 2);
              name = concat2 (drive_prefix, name);
            }
 #ifdef WINDOWSNT
@@ -2529,7 +2540,7 @@ DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
   /* The read-only attribute of the parent directory doesn't affect
      whether a file or directory can be created within it.  Some day we
      should check ACLs though, which do affect this.  */
-  return file_directory_p (SDATA (dir)) ? Qt : Qnil;
+  return file_directory_p (SSDATA (dir)) ? Qt : Qnil;
 #else
   return check_writable (SSDATA (dir), W_OK | X_OK) ? Qt : Qnil;
 #endif
@@ -2649,13 +2660,13 @@ file_directory_p (char const *file)
 
 DEFUN ("file-accessible-directory-p", Ffile_accessible_directory_p,
        Sfile_accessible_directory_p, 1, 1, 0,
-       doc: /* Return t if file FILENAME names a directory you can open.
-For the value to be t, FILENAME must specify the name of a directory as a file,
-and the directory must allow you to open files in it.  In order to use a
-directory as a buffer's current directory, this predicate must return true.
-A directory name spec may be given instead; then the value is t
-if the directory so specified exists and really is a readable and
-searchable directory.  */)
+       doc: /* Return t if FILENAME names a directory you can open.
+For the value to be t, FILENAME must specify the name of a directory
+as a file, and the directory must allow you to open files in it.  In
+order to use a directory as a buffer's current directory, this
+predicate must return true.  A directory name spec may be given
+instead; then the value is t if the directory so specified exists and
+really is a readable and searchable directory.  */)
   (Lisp_Object filename)
 {
   Lisp_Object absname;
@@ -2760,7 +2771,7 @@ See `file-symlink-p' to distinguish symlinks.  */)
 
     /* Tell stat to use expensive method to get accurate info.  */
     Vw32_get_true_file_attributes = Qt;
-    result = stat (SDATA (absname), &st);
+    result = stat (SSDATA (absname), &st);
     Vw32_get_true_file_attributes = tem;
 
     if (result < 0)
@@ -2922,16 +2933,17 @@ Return nil if file does not exist or is not accessible, or if Emacs
 was unable to determine the ACL entries.  */)
   (Lisp_Object filename)
 {
+#if USE_ACL
   Lisp_Object absname;
   Lisp_Object handler;
-#ifdef HAVE_ACL_SET_FILE
+# ifdef HAVE_ACL_SET_FILE
   acl_t acl;
   Lisp_Object acl_string;
   char *str;
-# ifndef HAVE_ACL_TYPE_EXTENDED
+#  ifndef HAVE_ACL_TYPE_EXTENDED
   acl_type_t ACL_TYPE_EXTENDED = ACL_TYPE_ACCESS;
+#  endif
 # endif
-#endif
 
   absname = expand_and_dir_to_file (filename,
                                    BVAR (current_buffer, directory));
@@ -2942,7 +2954,7 @@ was unable to determine the ACL entries.  */)
   if (!NILP (handler))
     return call2 (handler, Qfile_acl, absname);
 
-#ifdef HAVE_ACL_SET_FILE
+# ifdef HAVE_ACL_SET_FILE
   absname = ENCODE_FILE (absname);
 
   acl = acl_get_file (SSDATA (absname), ACL_TYPE_EXTENDED);
@@ -2961,6 +2973,7 @@ was unable to determine the ACL entries.  */)
   acl_free (acl);
 
   return acl_string;
+# endif
 #endif
 
   return Qnil;
@@ -2978,13 +2991,14 @@ Setting ACL for local files requires Emacs to be built with ACL
 support.  */)
   (Lisp_Object filename, Lisp_Object acl_string)
 {
+#if USE_ACL
   Lisp_Object absname;
   Lisp_Object handler;
-#ifdef HAVE_ACL_SET_FILE
+# ifdef HAVE_ACL_SET_FILE
   Lisp_Object encoded_absname;
   acl_t acl;
   bool fail;
-#endif
+# endif
 
   absname = Fexpand_file_name (filename, BVAR (current_buffer, directory));
 
@@ -2994,7 +3008,7 @@ support.  */)
   if (!NILP (handler))
     return call3 (handler, Qset_file_acl, absname, acl_string);
 
-#ifdef HAVE_ACL_SET_FILE
+# ifdef HAVE_ACL_SET_FILE
   if (STRINGP (acl_string))
     {
       acl = acl_from_text (SSDATA (acl_string));
@@ -3015,6 +3029,7 @@ support.  */)
       acl_free (acl);
       return fail ? Qnil : Qt;
     }
+# endif
 #endif
 
   return Qnil;
@@ -3344,6 +3359,21 @@ restore_window_points (Lisp_Object window_markers, ptrdiff_t inserted,
       }
 }
 
+/* Make sure the gap is at Z_BYTE.  This is required to treat buffer
+   text as a linear C char array.  */
+static void
+maybe_move_gap (struct buffer *b)
+{
+  if (BUF_GPT_BYTE (b) != BUF_Z_BYTE (b))
+    {
+      struct buffer *cb = current_buffer;
+
+      set_buffer_internal (b);
+      move_gap_both (Z, Z_BYTE);
+      set_buffer_internal (cb);
+    }
+}
+
 /* FIXME: insert-file-contents should be split with the top-level moved to
    Elisp and only the core kept in C.  */
 
@@ -3454,7 +3484,11 @@ by calling `format-decode', which see.  */)
       mtime = time_error_value (save_errno);
       st.st_size = -1;
       if (!NILP (Vcoding_system_for_read))
-       Fset (Qbuffer_file_coding_system, Vcoding_system_for_read);
+       {
+         /* Don't let invalid values into buffer-file-coding-system.  */
+         CHECK_CODING_SYSTEM (Vcoding_system_for_read);
+         Fset (Qbuffer_file_coding_system, Vcoding_system_for_read);
+       }
       goto notfound;
     }
 
@@ -3923,6 +3957,7 @@ by calling `format-decode', which see.  */)
 
       coding_system = CODING_ID_NAME (coding.id);
       set_coding_system = true;
+      maybe_move_gap (XBUFFER (conversion_buffer));
       decoded = BUF_BEG_ADDR (XBUFFER (conversion_buffer));
       inserted = (BUF_Z_BYTE (XBUFFER (conversion_buffer))
                  - BUF_BEG_BYTE (XBUFFER (conversion_buffer)));
@@ -4244,9 +4279,14 @@ by calling `format-decode', which see.  */)
       if (CODING_FOR_UNIBYTE (&coding)
          /* Can't do this if part of the buffer might be preserved.  */
          && NILP (replace))
-       /* Visiting a file with these coding system makes the buffer
-          unibyte.  */
-       bset_enable_multibyte_characters (current_buffer, Qnil);
+       {
+         /* Visiting a file with these coding system makes the buffer
+            unibyte.  */
+         if (inserted > 0)
+           bset_enable_multibyte_characters (current_buffer, Qnil);
+         else
+           Fset_buffer_multibyte (Qnil);
+       }
     }
 
   coding.dst_multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters));
@@ -4553,7 +4593,7 @@ choose_write_coding_system (Lisp_Object start, Lisp_Object end, Lisp_Object file
       if (NILP (val))
        {
          /* If we still have not decided a coding system, use the
-            default value of buffer-file-coding-system.  */
+            current buffer's value of buffer-file-coding-system.  */
          val = BVAR (current_buffer, buffer_file_coding_system);
          using_default_coding = 1;
        }
@@ -4562,6 +4602,7 @@ choose_write_coding_system (Lisp_Object start, Lisp_Object end, Lisp_Object file
        {
          Lisp_Object spec, attrs;
 
+         CHECK_CODING_SYSTEM (val);
          CHECK_CODING_SYSTEM_GET_SPEC (val, spec);
          attrs = AREF (spec, 0);
          if (EQ (CODING_ATTR_TYPE (attrs), Qraw_text))
@@ -4570,17 +4611,27 @@ choose_write_coding_system (Lisp_Object start, Lisp_Object end, Lisp_Object file
 
       if (!force_raw_text
          && !NILP (Ffboundp (Vselect_safe_coding_system_function)))
-       /* Confirm that VAL can surely encode the current region.  */
-       val = call5 (Vselect_safe_coding_system_function,
-                    start, end, val, Qnil, filename);
+       {
+         /* Confirm that VAL can surely encode the current region.  */
+         val = call5 (Vselect_safe_coding_system_function,
+                      start, end, val, Qnil, filename);
+         /* As the function specified by select-safe-coding-system-function
+            is out of our control, make sure we are not fed by bogus
+            values.  */
+         if (!NILP (val))
+           CHECK_CODING_SYSTEM (val);
+       }
 
       /* If the decided coding-system doesn't specify end-of-line
         format, we use that of
         `default-buffer-file-coding-system'.  */
-      if (! using_default_coding
-         && ! NILP (BVAR (&buffer_defaults, buffer_file_coding_system)))
-       val = (coding_inherit_eol_type
-              (val, BVAR (&buffer_defaults, buffer_file_coding_system)));
+      if (! using_default_coding)
+       {
+         Lisp_Object dflt = BVAR (&buffer_defaults, buffer_file_coding_system);
+
+         if (! NILP (dflt))
+           val = coding_inherit_eol_type (val, dflt);
+       }
 
       /* If we decide not to encode text, use `raw-text' or one of its
         subsidiaries.  */
@@ -4650,7 +4701,7 @@ write_region (Lisp_Object start, Lisp_Object end, Lisp_Object filename,
 {
   int open_flags;
   int mode;
-  off_t offset IF_LINT (= 0);
+  off_t offset UNINIT;
   bool open_and_close_file = desc < 0;
   bool ok;
   int save_errno = 0;
@@ -4658,7 +4709,7 @@ write_region (Lisp_Object start, Lisp_Object end, Lisp_Object filename,
   struct stat st;
   struct timespec modtime;
   ptrdiff_t count = SPECPDL_INDEX ();
-  ptrdiff_t count1 IF_LINT (= 0);
+  ptrdiff_t count1 UNINIT;
   Lisp_Object handler;
   Lisp_Object visit_file;
   Lisp_Object annotations;
@@ -4767,7 +4818,7 @@ write_region (Lisp_Object start, Lisp_Object end, Lisp_Object filename,
 
   encoded_filename = ENCODE_FILE (filename);
   fn = SSDATA (encoded_filename);
-  open_flags = O_WRONLY | O_BINARY | O_CREAT;
+  open_flags = O_WRONLY | O_CREAT;
   open_flags |= EQ (mustbenew, Qexcl) ? O_EXCL : !NILP (append) ? 0 : O_TRUNC;
   if (NUMBERP (append))
     offset = file_offset (append);
@@ -4886,7 +4937,7 @@ write_region (Lisp_Object start, Lisp_Object end, Lisp_Object filename,
   if (timespec_valid_p (modtime)
       && ! (valid_timestamp_file_system && st.st_dev == timestamp_file_system))
     {
-      int desc1 = emacs_open (fn, O_WRONLY | O_BINARY, 0);
+      int desc1 = emacs_open (fn, O_WRONLY, 0);
       if (desc1 >= 0)
        {
          struct stat st1;
@@ -5339,25 +5390,15 @@ An argument specifies the modification time value to use
 static Lisp_Object
 auto_save_error (Lisp_Object error_val)
 {
-  Lisp_Object msg;
-  int i;
-
   auto_save_error_occurred = 1;
 
   ring_bell (XFRAME (selected_frame));
 
   AUTO_STRING (format, "Auto-saving %s: %s");
-  msg = CALLN (Fformat, format, BVAR (current_buffer, name),
-              Ferror_message_string (error_val));
-
-  for (i = 0; i < 3; ++i)
-    {
-      if (i == 0)
-       message3 (msg);
-      else
-       message3_nolog (msg);
-      Fsleep_for (make_number (1), Qnil);
-    }
+  Lisp_Object msg = CALLN (Fformat, format, BVAR (current_buffer, name),
+                          Ferror_message_string (error_val));
+  call3 (intern ("display-warning"),
+         intern ("auto-save"), msg, intern ("error"));
 
   return Qnil;
 }
@@ -5878,7 +5919,7 @@ the arguments that were passed to that primitive.  For example, if you
 do (file-exists-p FILENAME) and FILENAME is handled by HANDLER, then
 HANDLER is called like this:
 
-  (funcall HANDLER 'file-exists-p FILENAME)
+  (funcall HANDLER \\='file-exists-p FILENAME)
 
 Note that HANDLER must be able to handle all I/O primitives; if it has
 nothing special to do for a primitive, it should reinvoke the