aboutsummaryrefslogtreecommitdiffstats
path: root/src/fileio.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fileio.c')
-rw-r--r--src/fileio.c153
1 files changed, 73 insertions, 80 deletions
diff --git a/src/fileio.c b/src/fileio.c
index 4a14f5a5911..c3566390130 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -20,7 +20,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20#include <config.h> 20#include <config.h>
21#include <limits.h> 21#include <limits.h>
22#include <fcntl.h> 22#include <fcntl.h>
23#include <stdio.h> 23#include "sysstdio.h"
24#include <sys/types.h> 24#include <sys/types.h>
25#include <sys/stat.h> 25#include <sys/stat.h>
26#include <unistd.h> 26#include <unistd.h>
@@ -55,7 +55,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
55#ifdef WINDOWSNT 55#ifdef WINDOWSNT
56#define NOMINMAX 1 56#define NOMINMAX 1
57#include <windows.h> 57#include <windows.h>
58#include <fcntl.h>
59#include <sys/file.h> 58#include <sys/file.h>
60#include "w32.h" 59#include "w32.h"
61#endif /* not WINDOWSNT */ 60#endif /* not WINDOWSNT */
@@ -63,7 +62,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
63#ifdef MSDOS 62#ifdef MSDOS
64#include "msdos.h" 63#include "msdos.h"
65#include <sys/param.h> 64#include <sys/param.h>
66#include <fcntl.h>
67#endif 65#endif
68 66
69#ifdef DOS_NT 67#ifdef DOS_NT
@@ -148,7 +146,7 @@ static Lisp_Object Qdelete_directory;
148#ifdef WINDOWSNT 146#ifdef WINDOWSNT
149#endif 147#endif
150 148
151Lisp_Object Qfile_error; 149Lisp_Object Qfile_error, Qfile_notify_error;
152static Lisp_Object Qfile_already_exists, Qfile_date_error; 150static Lisp_Object Qfile_already_exists, Qfile_date_error;
153static Lisp_Object Qexcl; 151static Lisp_Object Qexcl;
154Lisp_Object Qfile_name_history; 152Lisp_Object Qfile_name_history;
@@ -161,11 +159,13 @@ static bool e_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t,
161 struct coding_system *); 159 struct coding_system *);
162 160
163 161
162/* Signal a file-access failure. STRING describes the failure,
163 DATA the file that was involved, and ERRORNO the errno value. */
164
164void 165void
165report_file_error (const char *string, Lisp_Object data) 166report_file_errno (char const *string, Lisp_Object data, int errorno)
166{ 167{
167 Lisp_Object errstring; 168 Lisp_Object errstring;
168 int errorno = errno;
169 char *str; 169 char *str;
170 170
171 synchronize_system_messages_locale (); 171 synchronize_system_messages_locale ();
@@ -198,6 +198,12 @@ report_file_error (const char *string, Lisp_Object data)
198 } 198 }
199} 199}
200 200
201void
202report_file_error (char const *string, Lisp_Object data)
203{
204 report_file_errno (string, data, errno);
205}
206
201Lisp_Object 207Lisp_Object
202close_file_unwind (Lisp_Object fd) 208close_file_unwind (Lisp_Object fd)
203{ 209{
@@ -2021,11 +2027,8 @@ entries (depending on how Emacs was built). */)
2021 { 2027 {
2022 /* CopyFile doesn't set errno when it fails. By far the most 2028 /* CopyFile doesn't set errno when it fails. By far the most
2023 "popular" reason is that the target is read-only. */ 2029 "popular" reason is that the target is read-only. */
2024 if (GetLastError () == 5) 2030 report_file_errno ("Copying file", Fcons (file, Fcons (newname, Qnil)),
2025 errno = EACCES; 2031 GetLastError () == 5 ? EACCES : EPERM);
2026 else
2027 errno = EPERM;
2028 report_file_error ("Copying file", Fcons (file, Fcons (newname, Qnil)));
2029 } 2032 }
2030 /* CopyFile retains the timestamp by default. */ 2033 /* CopyFile retains the timestamp by default. */
2031 else if (NILP (keep_time)) 2034 else if (NILP (keep_time))
@@ -2086,36 +2089,25 @@ entries (depending on how Emacs was built). */)
2086 2089
2087 if (out_st.st_mode != 0 2090 if (out_st.st_mode != 0
2088 && st.st_dev == out_st.st_dev && st.st_ino == out_st.st_ino) 2091 && st.st_dev == out_st.st_dev && st.st_ino == out_st.st_ino)
2089 { 2092 report_file_errno ("Input and output files are the same",
2090 errno = 0; 2093 Fcons (file, Fcons (newname, Qnil)), 0);
2091 report_file_error ("Input and output files are the same",
2092 Fcons (file, Fcons (newname, Qnil)));
2093 }
2094 2094
2095 /* We can copy only regular files. */ 2095 /* We can copy only regular files. */
2096 if (!S_ISREG (st.st_mode)) 2096 if (!S_ISREG (st.st_mode))
2097 { 2097 report_file_errno ("Non-regular file", Fcons (file, Qnil),
2098 /* Get a better looking error message. */ 2098 S_ISDIR (st.st_mode) ? EISDIR : EINVAL);
2099 errno = S_ISDIR (st.st_mode) ? EISDIR : EINVAL;
2100 report_file_error ("Non-regular file", Fcons (file, Qnil));
2101 }
2102 2099
2103#ifdef MSDOS
2104 /* System's default file type was set to binary by _fmode in emacs.c. */
2105 ofd = emacs_open (SDATA (encoded_newname),
2106 O_WRONLY | O_TRUNC | O_CREAT
2107 | (NILP (ok_if_already_exists) ? O_EXCL : 0),
2108 S_IREAD | S_IWRITE);
2109#else /* not MSDOS */
2110 { 2100 {
2111 mode_t new_mask = !NILP (preserve_uid_gid) ? 0600 : 0666; 2101#ifndef MSDOS
2112 new_mask &= st.st_mode; 2102 int new_mask = st.st_mode & (!NILP (preserve_uid_gid) ? 0600 : 0666);
2103#else
2104 int new_mask = S_IREAD | S_IWRITE;
2105#endif
2113 ofd = emacs_open (SSDATA (encoded_newname), 2106 ofd = emacs_open (SSDATA (encoded_newname),
2114 (O_WRONLY | O_TRUNC | O_CREAT 2107 (O_WRONLY | O_TRUNC | O_CREAT
2115 | (NILP (ok_if_already_exists) ? O_EXCL : 0)), 2108 | (NILP (ok_if_already_exists) ? O_EXCL : 0)),
2116 new_mask); 2109 new_mask);
2117 } 2110 }
2118#endif /* not MSDOS */
2119 if (ofd < 0) 2111 if (ofd < 0)
2120 report_file_error ("Opening output file", Fcons (newname, Qnil)); 2112 report_file_error ("Opening output file", Fcons (newname, Qnil));
2121 2113
@@ -2124,7 +2116,7 @@ entries (depending on how Emacs was built). */)
2124 immediate_quit = 1; 2116 immediate_quit = 1;
2125 QUIT; 2117 QUIT;
2126 while ((n = emacs_read (ifd, buf, sizeof buf)) > 0) 2118 while ((n = emacs_read (ifd, buf, sizeof buf)) > 0)
2127 if (emacs_write (ofd, buf, n) != n) 2119 if (emacs_write_sig (ofd, buf, n) != n)
2128 report_file_error ("I/O error", Fcons (newname, Qnil)); 2120 report_file_error ("I/O error", Fcons (newname, Qnil));
2129 immediate_quit = 0; 2121 immediate_quit = 0;
2130 2122
@@ -2611,7 +2603,11 @@ Use `file-symlink-p' to test for such links. */)
2611 call the corresponding file handler. */ 2603 call the corresponding file handler. */
2612 handler = Ffind_file_name_handler (absname, Qfile_exists_p); 2604 handler = Ffind_file_name_handler (absname, Qfile_exists_p);
2613 if (!NILP (handler)) 2605 if (!NILP (handler))
2614 return call2 (handler, Qfile_exists_p, absname); 2606 {
2607 Lisp_Object result = call2 (handler, Qfile_exists_p, absname);
2608 errno = 0;
2609 return result;
2610 }
2615 2611
2616 absname = ENCODE_FILE (absname); 2612 absname = ENCODE_FILE (absname);
2617 2613
@@ -2708,7 +2704,6 @@ If there is no error, returns nil. */)
2708 (Lisp_Object filename, Lisp_Object string) 2704 (Lisp_Object filename, Lisp_Object string)
2709{ 2705{
2710 Lisp_Object handler, encoded_filename, absname; 2706 Lisp_Object handler, encoded_filename, absname;
2711 int fd;
2712 2707
2713 CHECK_STRING (filename); 2708 CHECK_STRING (filename);
2714 absname = Fexpand_file_name (filename, Qnil); 2709 absname = Fexpand_file_name (filename, Qnil);
@@ -2723,10 +2718,8 @@ If there is no error, returns nil. */)
2723 2718
2724 encoded_filename = ENCODE_FILE (absname); 2719 encoded_filename = ENCODE_FILE (absname);
2725 2720
2726 fd = emacs_open (SSDATA (encoded_filename), O_RDONLY, 0); 2721 if (faccessat (AT_FDCWD, SSDATA (encoded_filename), R_OK, AT_EACCESS) != 0)
2727 if (fd < 0)
2728 report_file_error (SSDATA (string), Fcons (filename, Qnil)); 2722 report_file_error (SSDATA (string), Fcons (filename, Qnil));
2729 emacs_close (fd);
2730 2723
2731 return Qnil; 2724 return Qnil;
2732} 2725}
@@ -2835,7 +2828,11 @@ searchable directory. */)
2835 call the corresponding file handler. */ 2828 call the corresponding file handler. */
2836 handler = Ffind_file_name_handler (absname, Qfile_accessible_directory_p); 2829 handler = Ffind_file_name_handler (absname, Qfile_accessible_directory_p);
2837 if (!NILP (handler)) 2830 if (!NILP (handler))
2838 return call2 (handler, Qfile_accessible_directory_p, absname); 2831 {
2832 Lisp_Object r = call2 (handler, Qfile_accessible_directory_p, absname);
2833 errno = 0;
2834 return r;
2835 }
2839 2836
2840 absname = ENCODE_FILE (absname); 2837 absname = ENCODE_FILE (absname);
2841 return file_accessible_directory_p (SSDATA (absname)) ? Qt : Qnil; 2838 return file_accessible_directory_p (SSDATA (absname)) ? Qt : Qnil;
@@ -3347,7 +3344,7 @@ otherwise, if FILE2 does not exist, the answer is t. */)
3347 if (stat (SSDATA (absname2), &st2) < 0) 3344 if (stat (SSDATA (absname2), &st2) < 0)
3348 return Qt; 3345 return Qt;
3349 3346
3350 return (EMACS_TIME_GT (get_stat_mtime (&st1), get_stat_mtime (&st2)) 3347 return (EMACS_TIME_LT (get_stat_mtime (&st2), get_stat_mtime (&st1))
3351 ? Qt : Qnil); 3348 ? Qt : Qnil);
3352} 3349}
3353 3350
@@ -4577,8 +4574,8 @@ by calling `format-decode', which see. */)
4577 && EMACS_NSECS (current_buffer->modtime) == NONEXISTENT_MODTIME_NSECS) 4574 && EMACS_NSECS (current_buffer->modtime) == NONEXISTENT_MODTIME_NSECS)
4578 { 4575 {
4579 /* If visiting nonexistent file, return nil. */ 4576 /* If visiting nonexistent file, return nil. */
4580 errno = save_errno; 4577 report_file_errno ("Opening input file", Fcons (orig_filename, Qnil),
4581 report_file_error ("Opening input file", Fcons (orig_filename, Qnil)); 4578 save_errno);
4582 } 4579 }
4583 4580
4584 if (read_quit) 4581 if (read_quit)
@@ -4899,13 +4896,13 @@ This calls `write-region-annotate-functions' at the start, and
4899 4896
4900 if (desc < 0) 4897 if (desc < 0)
4901 { 4898 {
4899 int open_errno = errno;
4902#ifdef CLASH_DETECTION 4900#ifdef CLASH_DETECTION
4903 save_errno = errno;
4904 if (!auto_saving) unlock_file (lockname); 4901 if (!auto_saving) unlock_file (lockname);
4905 errno = save_errno;
4906#endif /* CLASH_DETECTION */ 4902#endif /* CLASH_DETECTION */
4907 UNGCPRO; 4903 UNGCPRO;
4908 report_file_error ("Opening output file", Fcons (filename, Qnil)); 4904 report_file_errno ("Opening output file", Fcons (filename, Qnil),
4905 open_errno);
4909 } 4906 }
4910 4907
4911 record_unwind_protect (close_file_unwind, make_number (desc)); 4908 record_unwind_protect (close_file_unwind, make_number (desc));
@@ -4915,13 +4912,13 @@ This calls `write-region-annotate-functions' at the start, and
4915 off_t ret = lseek (desc, offset, SEEK_SET); 4912 off_t ret = lseek (desc, offset, SEEK_SET);
4916 if (ret < 0) 4913 if (ret < 0)
4917 { 4914 {
4915 int lseek_errno = errno;
4918#ifdef CLASH_DETECTION 4916#ifdef CLASH_DETECTION
4919 save_errno = errno;
4920 if (!auto_saving) unlock_file (lockname); 4917 if (!auto_saving) unlock_file (lockname);
4921 errno = save_errno;
4922#endif /* CLASH_DETECTION */ 4918#endif /* CLASH_DETECTION */
4923 UNGCPRO; 4919 UNGCPRO;
4924 report_file_error ("Lseek error", Fcons (filename, Qnil)); 4920 report_file_errno ("Lseek error", Fcons (filename, Qnil),
4921 lseek_errno);
4925 } 4922 }
4926 } 4923 }
4927 4924
@@ -5319,12 +5316,10 @@ e_write (int desc, Lisp_Object string, ptrdiff_t start, ptrdiff_t end,
5319 5316
5320 if (coding->produced > 0) 5317 if (coding->produced > 0)
5321 { 5318 {
5322 coding->produced 5319 char *buf = (STRINGP (coding->dst_object)
5323 -= emacs_write (desc, 5320 ? SSDATA (coding->dst_object)
5324 STRINGP (coding->dst_object) 5321 : (char *) BYTE_POS_ADDR (coding->dst_pos_byte));
5325 ? SSDATA (coding->dst_object) 5322 coding->produced -= emacs_write_sig (desc, buf, coding->produced);
5326 : (char *) BYTE_POS_ADDR (coding->dst_pos_byte),
5327 coding->produced);
5328 5323
5329 if (coding->produced) 5324 if (coding->produced)
5330 return 0; 5325 return 0;
@@ -5379,36 +5374,19 @@ See Info node `(elisp)Modification Time' for more details. */)
5379 return Qnil; 5374 return Qnil;
5380} 5375}
5381 5376
5382DEFUN ("clear-visited-file-modtime", Fclear_visited_file_modtime,
5383 Sclear_visited_file_modtime, 0, 0, 0,
5384 doc: /* Clear out records of last mod time of visited file.
5385Next attempt to save will certainly not complain of a discrepancy. */)
5386 (void)
5387{
5388 current_buffer->modtime = make_emacs_time (0, UNKNOWN_MODTIME_NSECS);
5389 current_buffer->modtime_size = -1;
5390 return Qnil;
5391}
5392
5393DEFUN ("visited-file-modtime", Fvisited_file_modtime, 5377DEFUN ("visited-file-modtime", Fvisited_file_modtime,
5394 Svisited_file_modtime, 0, 0, 0, 5378 Svisited_file_modtime, 0, 0, 0,
5395 doc: /* Return the current buffer's recorded visited file modification time. 5379 doc: /* Return the current buffer's recorded visited file modification time.
5396The value is a list of the form (HIGH LOW USEC PSEC), like the time values that 5380The value is a list of the form (HIGH LOW USEC PSEC), like the time values that
5397`file-attributes' returns. If the current buffer has no recorded file 5381`file-attributes' returns. If the current buffer has no recorded file
5398modification time, this function returns 0. If the visited file 5382modification time, this function returns 0. If the visited file
5399doesn't exist, HIGH will be -1. 5383doesn't exist, return -1.
5400See Info node `(elisp)Modification Time' for more details. */) 5384See Info node `(elisp)Modification Time' for more details. */)
5401 (void) 5385 (void)
5402{ 5386{
5403 if (EMACS_NSECS (current_buffer->modtime) < 0) 5387 int ns = EMACS_NSECS (current_buffer->modtime);
5404 { 5388 if (ns < 0)
5405 if (EMACS_NSECS (current_buffer->modtime) == NONEXISTENT_MODTIME_NSECS) 5389 return make_number (UNKNOWN_MODTIME_NSECS - ns);
5406 {
5407 /* make_lisp_time won't work here if time_t is unsigned. */
5408 return list4i (-1, 65535, 0, 0);
5409 }
5410 return make_number (0);
5411 }
5412 return make_lisp_time (current_buffer->modtime); 5390 return make_lisp_time (current_buffer->modtime);
5413} 5391}
5414 5392
@@ -5419,12 +5397,22 @@ Useful if the buffer was not read from the file normally
5419or if the file itself has been changed for some known benign reason. 5397or if the file itself has been changed for some known benign reason.
5420An argument specifies the modification time value to use 5398An argument specifies the modification time value to use
5421\(instead of that of the visited file), in the form of a list 5399\(instead of that of the visited file), in the form of a list
5422\(HIGH LOW USEC PSEC) as returned by `current-time'. */) 5400\(HIGH LOW USEC PSEC) or an integer flag as returned by
5423 (Lisp_Object time_list) 5401`visited-file-modtime'. */)
5402 (Lisp_Object time_flag)
5424{ 5403{
5425 if (!NILP (time_list)) 5404 if (!NILP (time_flag))
5426 { 5405 {
5427 current_buffer->modtime = lisp_time_argument (time_list); 5406 EMACS_TIME mtime;
5407 if (INTEGERP (time_flag))
5408 {
5409 CHECK_RANGED_INTEGER (time_flag, -1, 0);
5410 mtime = make_emacs_time (0, UNKNOWN_MODTIME_NSECS - XINT (time_flag));
5411 }
5412 else
5413 mtime = lisp_time_argument (time_flag);
5414
5415 current_buffer->modtime = mtime;
5428 current_buffer->modtime_size = -1; 5416 current_buffer->modtime_size = -1;
5429 } 5417 }
5430 else 5418 else
@@ -5620,7 +5608,7 @@ A non-nil CURRENT-ONLY argument means save only current buffer. */)
5620 UNGCPRO; 5608 UNGCPRO;
5621 } 5609 }
5622 5610
5623 stream = fopen (SSDATA (listfile), "w"); 5611 stream = emacs_fopen (SSDATA (listfile), "w");
5624 } 5612 }
5625 5613
5626 record_unwind_protect (do_auto_save_unwind, 5614 record_unwind_protect (do_auto_save_unwind,
@@ -5887,6 +5875,7 @@ syms_of_fileio (void)
5887 DEFSYM (Qfile_error, "file-error"); 5875 DEFSYM (Qfile_error, "file-error");
5888 DEFSYM (Qfile_already_exists, "file-already-exists"); 5876 DEFSYM (Qfile_already_exists, "file-already-exists");
5889 DEFSYM (Qfile_date_error, "file-date-error"); 5877 DEFSYM (Qfile_date_error, "file-date-error");
5878 DEFSYM (Qfile_notify_error, "file-notify-error");
5890 DEFSYM (Qexcl, "excl"); 5879 DEFSYM (Qexcl, "excl");
5891 5880
5892 DEFVAR_LISP ("file-name-coding-system", Vfile_name_coding_system, 5881 DEFVAR_LISP ("file-name-coding-system", Vfile_name_coding_system,
@@ -5925,6 +5914,11 @@ of file names regardless of the current language environment. */);
5925 Fput (Qfile_date_error, Qerror_message, 5914 Fput (Qfile_date_error, Qerror_message,
5926 build_pure_c_string ("Cannot set file date")); 5915 build_pure_c_string ("Cannot set file date"));
5927 5916
5917 Fput (Qfile_notify_error, Qerror_conditions,
5918 Fpurecopy (list3 (Qfile_notify_error, Qfile_error, Qerror)));
5919 Fput (Qfile_notify_error, Qerror_message,
5920 build_pure_c_string ("File notification error"));
5921
5928 DEFVAR_LISP ("file-name-handler-alist", Vfile_name_handler_alist, 5922 DEFVAR_LISP ("file-name-handler-alist", Vfile_name_handler_alist,
5929 doc: /* Alist of elements (REGEXP . HANDLER) for file names handled specially. 5923 doc: /* Alist of elements (REGEXP . HANDLER) for file names handled specially.
5930If a file name matches REGEXP, all I/O on that file is done by calling 5924If a file name matches REGEXP, all I/O on that file is done by calling
@@ -6119,7 +6113,6 @@ This includes interactive calls to `delete-file' and
6119 defsubr (&Swrite_region); 6113 defsubr (&Swrite_region);
6120 defsubr (&Scar_less_than_car); 6114 defsubr (&Scar_less_than_car);
6121 defsubr (&Sverify_visited_file_modtime); 6115 defsubr (&Sverify_visited_file_modtime);
6122 defsubr (&Sclear_visited_file_modtime);
6123 defsubr (&Svisited_file_modtime); 6116 defsubr (&Svisited_file_modtime);
6124 defsubr (&Sset_visited_file_modtime); 6117 defsubr (&Sset_visited_file_modtime);
6125 defsubr (&Sdo_auto_save); 6118 defsubr (&Sdo_auto_save);