struct coding_system *);
\f
+/* Signal a file-access failure. STRING describes the failure,
+ NAME the file involved, and ERRORNO the errno value.
+
+ If NAME is neither null nor a pair, package it up as a singleton
+ list before reporting it; this saves report_file_errno's caller the
+ trouble of preserving errno before calling list1. */
+
void
-report_file_error (const char *string, Lisp_Object data)
+report_file_errno (char const *string, Lisp_Object name, int errorno)
{
+ Lisp_Object data = CONSP (name) || NILP (name) ? name : list1 (name);
Lisp_Object errstring;
- int errorno = errno;
char *str;
synchronize_system_messages_locale ();
}
}
-Lisp_Object
-close_file_unwind (Lisp_Object fd)
+/* Signal a file-access failure that set errno. STRING describes the
+ failure, NAME the file involved. */
+
+void
+report_file_error (char const *string, Lisp_Object name)
{
- emacs_close (XFASTINT (fd));
- return Qnil;
+ report_file_errno (string, name, errno);
+}
+
+void
+close_file_unwind (int fd)
+{
+ emacs_close (fd);
}
/* Restore point, having saved it as a marker. */
-Lisp_Object
+void
restore_point_unwind (Lisp_Object location)
{
Fgoto_char (location);
Fset_marker (location, Qnil, Qnil);
- return Qnil;
}
\f
dog-slow, but also useless since eventually nil would
have to be returned anyway. */
report_file_error ("Cannot create temporary name for prefix",
- Fcons (prefix, Qnil));
+ prefix);
/* not reached */
}
}
{
acl = acl_get_file (SDATA (encoded_file), ACL_TYPE_ACCESS);
if (acl == NULL && acl_errno_valid (errno))
- report_file_error ("Getting ACL", Fcons (file, Qnil));
+ report_file_error ("Getting ACL", file);
}
if (!CopyFile (SDATA (encoded_file),
SDATA (encoded_newname),
{
/* CopyFile doesn't set errno when it fails. By far the most
"popular" reason is that the target is read-only. */
- if (GetLastError () == 5)
- errno = EACCES;
- else
- errno = EPERM;
- report_file_error ("Copying file", Fcons (file, Fcons (newname, Qnil)));
+ report_file_errno ("Copying file", list2 (file, newname),
+ GetLastError () == 5 ? EACCES : EPERM);
}
/* CopyFile retains the timestamp by default. */
else if (NILP (keep_time))
bool fail =
acl_set_file (SDATA (encoded_newname), ACL_TYPE_ACCESS, acl) != 0;
if (fail && acl_errno_valid (errno))
- report_file_error ("Setting ACL", Fcons (newname, Qnil));
+ report_file_error ("Setting ACL", newname);
acl_free (acl);
}
immediate_quit = 0;
if (ifd < 0)
- report_file_error ("Opening input file", Fcons (file, Qnil));
+ report_file_error ("Opening input file", file);
- record_unwind_protect (close_file_unwind, make_number (ifd));
+ record_unwind_protect_int (close_file_unwind, ifd);
if (fstat (ifd, &st) != 0)
- report_file_error ("Input file status", Fcons (file, Qnil));
+ report_file_error ("Input file status", file);
if (!NILP (preserve_extended_attributes))
{
{
conlength = fgetfilecon (ifd, &con);
if (conlength == -1)
- report_file_error ("Doing fgetfilecon", Fcons (file, Qnil));
+ report_file_error ("Doing fgetfilecon", file);
}
#endif
}
if (out_st.st_mode != 0
&& st.st_dev == out_st.st_dev && st.st_ino == out_st.st_ino)
- {
- errno = 0;
- report_file_error ("Input and output files are the same",
- Fcons (file, Fcons (newname, Qnil)));
- }
+ report_file_errno ("Input and output files are the same",
+ list2 (file, newname), 0);
/* We can copy only regular files. */
if (!S_ISREG (st.st_mode))
- {
- /* Get a better looking error message. */
- errno = S_ISDIR (st.st_mode) ? EISDIR : EINVAL;
- report_file_error ("Non-regular file", Fcons (file, Qnil));
- }
+ report_file_errno ("Non-regular file", file,
+ S_ISDIR (st.st_mode) ? EISDIR : EINVAL);
-#ifdef MSDOS
- /* System's default file type was set to binary by _fmode in emacs.c. */
- ofd = emacs_open (SDATA (encoded_newname),
- O_WRONLY | O_TRUNC | O_CREAT
- | (NILP (ok_if_already_exists) ? O_EXCL : 0),
- S_IREAD | S_IWRITE);
-#else /* not MSDOS */
{
- mode_t new_mask = !NILP (preserve_uid_gid) ? 0600 : 0666;
- new_mask &= st.st_mode;
+#ifndef MSDOS
+ int new_mask = st.st_mode & (!NILP (preserve_uid_gid) ? 0600 : 0666);
+#else
+ int new_mask = S_IREAD | S_IWRITE;
+#endif
ofd = emacs_open (SSDATA (encoded_newname),
(O_WRONLY | O_TRUNC | O_CREAT
| (NILP (ok_if_already_exists) ? O_EXCL : 0)),
new_mask);
}
-#endif /* not MSDOS */
if (ofd < 0)
- report_file_error ("Opening output file", Fcons (newname, Qnil));
+ report_file_error ("Opening output file", newname);
- record_unwind_protect (close_file_unwind, make_number (ofd));
+ record_unwind_protect_int (close_file_unwind, ofd);
immediate_quit = 1;
QUIT;
while ((n = emacs_read (ifd, buf, sizeof buf)) > 0)
- if (emacs_write (ofd, buf, n) != n)
- report_file_error ("I/O error", Fcons (newname, Qnil));
+ if (emacs_write_sig (ofd, buf, n) != n)
+ report_file_error ("Write error", newname);
immediate_quit = 0;
#ifndef MSDOS
st.st_mode & mode_mask)
: fchmod (ofd, st.st_mode & mode_mask))
{
- case -2: report_file_error ("Copying permissions from", list1 (file));
- case -1: report_file_error ("Copying permissions to", list1 (newname));
+ case -2: report_file_error ("Copying permissions from", file);
+ case -1: report_file_error ("Copying permissions to", newname);
}
}
#endif /* not MSDOS */
bool fail = fsetfilecon (ofd, con) != 0;
/* See http://debbugs.gnu.org/11245 for ENOTSUP. */
if (fail && errno != ENOTSUP)
- report_file_error ("Doing fsetfilecon", Fcons (newname, Qnil));
+ report_file_error ("Doing fsetfilecon", newname);
freecon (con);
}
}
if (emacs_close (ofd) < 0)
- report_file_error ("I/O error", Fcons (newname, Qnil));
+ report_file_error ("Write error", newname);
emacs_close (ifd);
#else
if (mkdir (dir, 0777 & ~auto_saving_dir_umask) != 0)
#endif
- report_file_error ("Creating directory", list1 (directory));
+ report_file_error ("Creating directory", directory);
return Qnil;
}
dir = SSDATA (encoded_dir);
if (rmdir (dir) != 0)
- report_file_error ("Removing directory", list1 (directory));
+ report_file_error ("Removing directory", directory);
return Qnil;
}
encoded_file = ENCODE_FILE (filename);
if (unlink (SSDATA (encoded_file)) < 0)
- report_file_error ("Removing old name", list1 (filename));
+ report_file_error ("Removing old name", filename);
return Qnil;
}
call the corresponding file handler. */
handler = Ffind_file_name_handler (absname, Qfile_exists_p);
if (!NILP (handler))
- return call2 (handler, Qfile_exists_p, absname);
+ {
+ Lisp_Object result = call2 (handler, Qfile_exists_p, absname);
+ errno = 0;
+ return result;
+ }
absname = ENCODE_FILE (absname);
(Lisp_Object filename, Lisp_Object string)
{
Lisp_Object handler, encoded_filename, absname;
- int fd;
CHECK_STRING (filename);
absname = Fexpand_file_name (filename, Qnil);
encoded_filename = ENCODE_FILE (absname);
- fd = emacs_open (SSDATA (encoded_filename), O_RDONLY, 0);
- if (fd < 0)
- report_file_error (SSDATA (string), Fcons (filename, Qnil));
- emacs_close (fd);
+ if (faccessat (AT_FDCWD, SSDATA (encoded_filename), R_OK, AT_EACCESS) != 0)
+ report_file_error (SSDATA (string), filename);
return Qnil;
}
call the corresponding file handler. */
handler = Ffind_file_name_handler (absname, Qfile_accessible_directory_p);
if (!NILP (handler))
- return call2 (handler, Qfile_accessible_directory_p, absname);
+ {
+ Lisp_Object r = call2 (handler, Qfile_accessible_directory_p, absname);
+ errno = 0;
+ return r;
+ }
absname = ENCODE_FILE (absname);
return file_accessible_directory_p (SSDATA (absname)) ? Qt : Qnil;
!= 0);
/* See http://debbugs.gnu.org/11245 for ENOTSUP. */
if (fail && errno != ENOTSUP)
- report_file_error ("Doing lsetfilecon", Fcons (absname, Qnil));
+ report_file_error ("Doing lsetfilecon", absname);
context_free (parsed_con);
freecon (con);
return fail ? Qnil : Qt;
}
else
- report_file_error ("Doing lgetfilecon", Fcons (absname, Qnil));
+ report_file_error ("Doing lgetfilecon", absname);
}
#endif
acl = acl_from_text (SSDATA (acl_string));
if (acl == NULL)
{
- report_file_error ("Converting ACL", Fcons (absname, Qnil));
+ report_file_error ("Converting ACL", absname);
return Qnil;
}
acl)
!= 0);
if (fail && acl_errno_valid (errno))
- report_file_error ("Setting ACL", Fcons (absname, Qnil));
+ report_file_error ("Setting ACL", absname);
acl_free (acl);
return fail ? Qnil : Qt;
encoded_absname = ENCODE_FILE (absname);
if (chmod (SSDATA (encoded_absname), XINT (mode) & 07777) < 0)
- report_file_error ("Doing chmod", Fcons (absname, Qnil));
+ report_file_error ("Doing chmod", absname);
return Qnil;
}
if (file_directory_p (SSDATA (encoded_absname)))
return Qnil;
#endif
- report_file_error ("Setting file times", Fcons (absname, Qnil));
+ report_file_error ("Setting file times", absname);
}
}
if (stat (SSDATA (absname2), &st2) < 0)
return Qt;
- return (EMACS_TIME_GT (get_stat_mtime (&st1), get_stat_mtime (&st2))
+ return (EMACS_TIME_LT (get_stat_mtime (&st2), get_stat_mtime (&st1))
? Qt : Qnil);
}
\f
o remove all text properties.
o set back the buffer multibyteness. */
-static Lisp_Object
+static void
decide_coding_unwind (Lisp_Object unwind_data)
{
Lisp_Object multibyte, undo_list, buffer;
/* Now we are safe to change the buffer's multibyteness directly. */
bset_enable_multibyte_characters (current_buffer, multibyte);
bset_undo_list (current_buffer, undo_list);
-
- return Qnil;
}
/* Read from a non-regular file. STATE is a Lisp_Save_Value
{
save_errno = errno;
if (NILP (visit))
- report_file_error ("Opening input file", Fcons (orig_filename, Qnil));
+ report_file_error ("Opening input file", orig_filename);
mtime = time_error_value (save_errno);
st.st_size = -1;
if (!NILP (Vcoding_system_for_read))
if (!NILP (replace))
record_unwind_protect (restore_point_unwind, Fpoint_marker ());
- record_unwind_protect (close_file_unwind, make_number (fd));
+ record_unwind_protect_int (close_file_unwind, fd);
if (fstat (fd, &st) != 0)
- report_file_error ("Input file status", Fcons (orig_filename, Qnil));
+ report_file_error ("Input file status", orig_filename);
mtime = get_stat_mtime (&st);
/* This code will need to be changed in order to work on named
int ntail;
if (lseek (fd, - (1024 * 3), SEEK_END) < 0)
report_file_error ("Setting file position",
- Fcons (orig_filename, Qnil));
+ orig_filename);
ntail = emacs_read (fd, read_buf + nread, 1024 * 3);
nread = ntail < 0 ? ntail : nread + ntail;
}
}
if (nread < 0)
- error ("IO error reading %s: %s",
- SDATA (orig_filename), emacs_strerror (errno));
+ report_file_error ("Read error", orig_filename);
else if (nread > 0)
{
struct buffer *prev = current_buffer;
/* Rewind the file for the actual read done later. */
if (lseek (fd, 0, SEEK_SET) < 0)
- report_file_error ("Setting file position",
- Fcons (orig_filename, Qnil));
+ report_file_error ("Setting file position", orig_filename);
}
}
if (beg_offset != 0)
{
if (lseek (fd, beg_offset, SEEK_SET) < 0)
- report_file_error ("Setting file position",
- Fcons (orig_filename, Qnil));
+ report_file_error ("Setting file position", orig_filename);
}
immediate_quit = 1;
nread = emacs_read (fd, read_buf, sizeof read_buf);
if (nread < 0)
- error ("IO error reading %s: %s",
- SSDATA (orig_filename), emacs_strerror (errno));
+ report_file_error ("Read error", orig_filename);
else if (nread == 0)
break;
/* How much can we scan in the next step? */
trial = min (curpos, sizeof read_buf);
if (lseek (fd, curpos - trial, SEEK_SET) < 0)
- report_file_error ("Setting file position",
- Fcons (orig_filename, Qnil));
+ report_file_error ("Setting file position", orig_filename);
total_read = nread = 0;
while (total_read < trial)
{
nread = emacs_read (fd, read_buf + total_read, trial - total_read);
if (nread < 0)
- error ("IO error reading %s: %s",
- SDATA (orig_filename), emacs_strerror (errno));
+ report_file_error ("Read error", orig_filename);
else if (nread == 0)
break;
total_read += nread;
CONVERSION_BUFFER. */
if (lseek (fd, beg_offset, SEEK_SET) < 0)
- report_file_error ("Setting file position",
- Fcons (orig_filename, Qnil));
+ report_file_error ("Setting file position", orig_filename);
inserted = 0; /* Bytes put into CONVERSION_BUFFER so far. */
unprocessed = 0; /* Bytes not processed in previous loop. */
deferred_remove_unwind_protect = 1;
if (this < 0)
- error ("IO error reading %s: %s",
- SDATA (orig_filename), emacs_strerror (errno));
+ report_file_error ("Read error", orig_filename);
if (unprocessed > 0)
{
if (beg_offset != 0 || !NILP (replace))
{
if (lseek (fd, beg_offset, SEEK_SET) < 0)
- report_file_error ("Setting file position",
- Fcons (orig_filename, Qnil));
+ report_file_error ("Setting file position", orig_filename);
}
/* In the following loop, HOW_MUCH contains the total bytes read so
specpdl_ptr--;
if (how_much < 0)
- error ("IO error reading %s: %s",
- SDATA (orig_filename), emacs_strerror (errno));
+ report_file_error ("Read error", orig_filename);
/* Make the text read part of the buffer. */
GAP_SIZE -= inserted;
&& EMACS_NSECS (current_buffer->modtime) == NONEXISTENT_MODTIME_NSECS)
{
/* If visiting nonexistent file, return nil. */
- errno = save_errno;
- report_file_error ("Opening input file", Fcons (orig_filename, Qnil));
+ report_file_errno ("Opening input file", orig_filename, save_errno);
}
if (read_quit)
\f
static Lisp_Object build_annotations (Lisp_Object, Lisp_Object);
-static Lisp_Object
+static void
build_annotations_unwind (Lisp_Object arg)
{
Vwrite_region_annotation_buffers = arg;
- return Qnil;
}
/* Decide the coding-system to encode the data with. */
&& !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, Fcons (Qt, Fcons (val, Qnil)),
+ start, end, list2 (Qt, val),
Qnil, filename);
}
else
record_unwind_protect (build_annotations_unwind,
Vwrite_region_annotation_buffers);
- Vwrite_region_annotation_buffers = Fcons (Fcurrent_buffer (), Qnil);
+ Vwrite_region_annotation_buffers = list1 (Fcurrent_buffer ());
count1 = SPECPDL_INDEX ();
given_buffer = current_buffer;
if (desc < 0)
{
+ int open_errno = errno;
#ifdef CLASH_DETECTION
- save_errno = errno;
if (!auto_saving) unlock_file (lockname);
- errno = save_errno;
#endif /* CLASH_DETECTION */
UNGCPRO;
- report_file_error ("Opening output file", Fcons (filename, Qnil));
+ report_file_errno ("Opening output file", filename, open_errno);
}
- record_unwind_protect (close_file_unwind, make_number (desc));
+ record_unwind_protect_int (close_file_unwind, desc);
if (NUMBERP (append))
{
off_t ret = lseek (desc, offset, SEEK_SET);
if (ret < 0)
{
+ int lseek_errno = errno;
#ifdef CLASH_DETECTION
- save_errno = errno;
if (!auto_saving) unlock_file (lockname);
- errno = save_errno;
#endif /* CLASH_DETECTION */
UNGCPRO;
- report_file_error ("Lseek error", Fcons (filename, Qnil));
+ report_file_errno ("Lseek error", filename, lseek_errno);
}
}
}
if (! ok)
- error ("IO error writing %s: %s", SDATA (filename),
- emacs_strerror (save_errno));
+ report_file_errno ("Write error", filename, save_errno);
if (visiting)
{
if (coding->produced > 0)
{
- coding->produced
- -= emacs_write (desc,
- STRINGP (coding->dst_object)
- ? SSDATA (coding->dst_object)
- : (char *) BYTE_POS_ADDR (coding->dst_pos_byte),
- coding->produced);
+ char *buf = (STRINGP (coding->dst_object)
+ ? SSDATA (coding->dst_object)
+ : (char *) BYTE_POS_ADDR (coding->dst_pos_byte));
+ coding->produced -= emacs_write_sig (desc, buf, coding->produced);
if (coding->produced)
return 0;
return Qnil;
}
-DEFUN ("clear-visited-file-modtime", Fclear_visited_file_modtime,
- Sclear_visited_file_modtime, 0, 0, 0,
- doc: /* Clear out records of last mod time of visited file.
-Next attempt to save will certainly not complain of a discrepancy. */)
- (void)
-{
- current_buffer->modtime = make_emacs_time (0, UNKNOWN_MODTIME_NSECS);
- current_buffer->modtime_size = -1;
- return Qnil;
-}
-
DEFUN ("visited-file-modtime", Fvisited_file_modtime,
Svisited_file_modtime, 0, 0, 0,
doc: /* Return the current buffer's recorded visited file modification time.
The value is a list of the form (HIGH LOW USEC PSEC), like the time values that
`file-attributes' returns. If the current buffer has no recorded file
modification time, this function returns 0. If the visited file
-doesn't exist, HIGH will be -1.
+doesn't exist, return -1.
See Info node `(elisp)Modification Time' for more details. */)
(void)
{
- if (EMACS_NSECS (current_buffer->modtime) < 0)
- {
- if (EMACS_NSECS (current_buffer->modtime) == NONEXISTENT_MODTIME_NSECS)
- {
- /* make_lisp_time won't work here if time_t is unsigned. */
- return list4i (-1, 65535, 0, 0);
- }
- return make_number (0);
- }
+ int ns = EMACS_NSECS (current_buffer->modtime);
+ if (ns < 0)
+ return make_number (UNKNOWN_MODTIME_NSECS - ns);
return make_lisp_time (current_buffer->modtime);
}
or if the file itself has been changed for some known benign reason.
An argument specifies the modification time value to use
\(instead of that of the visited file), in the form of a list
-\(HIGH LOW USEC PSEC) as returned by `current-time'. */)
- (Lisp_Object time_list)
+\(HIGH LOW USEC PSEC) or an integer flag as returned by
+`visited-file-modtime'. */)
+ (Lisp_Object time_flag)
{
- if (!NILP (time_list))
+ if (!NILP (time_flag))
{
- current_buffer->modtime = lisp_time_argument (time_list);
+ EMACS_TIME mtime;
+ if (INTEGERP (time_flag))
+ {
+ CHECK_RANGED_INTEGER (time_flag, -1, 0);
+ mtime = make_emacs_time (0, UNKNOWN_MODTIME_NSECS - XINT (time_flag));
+ }
+ else
+ mtime = lisp_time_argument (time_flag);
+
+ current_buffer->modtime = mtime;
current_buffer->modtime_size = -1;
}
else
Qnil, Qnil);
}
-static Lisp_Object
-do_auto_save_unwind (Lisp_Object arg) /* used as unwind-protect function */
+struct auto_save_unwind
+{
+ FILE *stream;
+ bool auto_raise;
+};
+static void
+do_auto_save_unwind (void *arg)
{
- FILE *stream = XSAVE_POINTER (arg, 0);
+ struct auto_save_unwind *p = arg;
+ FILE *stream = p->stream;
+ minibuffer_auto_raise = p->auto_raise;
auto_saving = 0;
if (stream != NULL)
{
fclose (stream);
unblock_input ();
}
- return Qnil;
-}
-
-static Lisp_Object
-do_auto_save_unwind_1 (Lisp_Object value) /* used as unwind-protect function */
-
-{
- minibuffer_auto_raise = XINT (value);
- return Qnil;
}
static Lisp_Object
ptrdiff_t count = SPECPDL_INDEX ();
bool orig_minibuffer_auto_raise = minibuffer_auto_raise;
bool old_message_p = 0;
+ struct auto_save_unwind auto_save_unwind;
struct gcpro gcpro1, gcpro2;
if (max_specpdl_size < specpdl_size + 40)
if (NILP (no_message))
{
old_message_p = push_message ();
- record_unwind_protect (pop_message_unwind, Qnil);
+ record_unwind_protect_void (pop_message_unwind);
}
/* Ordinarily don't quit within this function,
stream = emacs_fopen (SSDATA (listfile), "w");
}
- record_unwind_protect (do_auto_save_unwind,
- make_save_pointer (stream));
- record_unwind_protect (do_auto_save_unwind_1,
- make_number (minibuffer_auto_raise));
+ auto_save_unwind.stream = stream;
+ auto_save_unwind.auto_raise = minibuffer_auto_raise;
+ record_unwind_protect_ptr (do_auto_save_unwind, &auto_save_unwind);
minibuffer_auto_raise = 0;
auto_saving = 1;
auto_save_error_occurred = 0;
defsubr (&Swrite_region);
defsubr (&Scar_less_than_car);
defsubr (&Sverify_visited_file_modtime);
- defsubr (&Sclear_visited_file_modtime);
defsubr (&Svisited_file_modtime);
defsubr (&Sset_visited_file_modtime);
defsubr (&Sdo_auto_save);