/* 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
#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"
#include "blockinput.h"
#include "region-cache.h"
#include "frame.h"
-#include "dispextern.h"
#ifdef WINDOWSNT
#define NOMINMAX 1
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)
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)
{
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
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
/* 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
/* 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
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;
/* 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)
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));
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);
acl_free (acl);
return acl_string;
+# endif
#endif
return Qnil;
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));
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));
acl_free (acl);
return fail ? Qnil : Qt;
}
+# endif
#endif
return Qnil;
}
}
+/* 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. */
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;
}
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)));
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));
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;
}
{
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))
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. */
{
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;
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;
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);
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;
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;
}
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