aboutsummaryrefslogtreecommitdiffstats
path: root/src/fileio.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fileio.c')
-rw-r--r--src/fileio.c264
1 files changed, 142 insertions, 122 deletions
diff --git a/src/fileio.c b/src/fileio.c
index 59e84053773..0e6113f349d 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -233,7 +233,7 @@ void
233restore_point_unwind (Lisp_Object location) 233restore_point_unwind (Lisp_Object location)
234{ 234{
235 Fgoto_char (location); 235 Fgoto_char (location);
236 Fset_marker (location, Qnil, Qnil); 236 unchain_marker (XMARKER (location));
237} 237}
238 238
239 239
@@ -366,8 +366,7 @@ Given a Unix syntax file name, returns a string ending in slash. */)
366 } 366 }
367 367
368#ifdef DOS_NT 368#ifdef DOS_NT
369 beg = alloca (SBYTES (filename) + 1); 369 beg = xlispstrdupa (filename);
370 memcpy (beg, SSDATA (filename), SBYTES (filename) + 1);
371#else 370#else
372 beg = SSDATA (filename); 371 beg = SSDATA (filename);
373#endif 372#endif
@@ -505,6 +504,10 @@ get a current directory to run processes in. */)
505 return Ffile_name_directory (filename); 504 return Ffile_name_directory (filename);
506} 505}
507 506
507/* Maximum number of bytes that DST will be longer than SRC
508 in file_name_as_directory. This occurs when SRCLEN == 0. */
509enum { file_name_as_directory_slop = 2 };
510
508/* Convert from file name SRC of length SRCLEN to directory name in 511/* Convert from file name SRC of length SRCLEN to directory name in
509 DST. MULTIBYTE non-zero means the file name in SRC is a multibyte 512 DST. MULTIBYTE non-zero means the file name in SRC is a multibyte
510 string. On UNIX, just make sure there is a terminating /. Return 513 string. On UNIX, just make sure there is a terminating /. Return
@@ -522,14 +525,10 @@ file_name_as_directory (char *dst, const char *src, ptrdiff_t srclen,
522 return 2; 525 return 2;
523 } 526 }
524 527
525 strcpy (dst, src); 528 memcpy (dst, src, srclen);
526
527 if (!IS_DIRECTORY_SEP (dst[srclen - 1])) 529 if (!IS_DIRECTORY_SEP (dst[srclen - 1]))
528 { 530 dst[srclen++] = DIRECTORY_SEP;
529 dst[srclen] = DIRECTORY_SEP; 531 dst[srclen] = 0;
530 dst[srclen + 1] = '\0';
531 srclen++;
532 }
533#ifdef DOS_NT 532#ifdef DOS_NT
534 dostounix_filename (dst, multibyte); 533 dostounix_filename (dst, multibyte);
535#endif 534#endif
@@ -548,7 +547,8 @@ For a Unix-syntax file name, just appends a slash. */)
548{ 547{
549 char *buf; 548 char *buf;
550 ptrdiff_t length; 549 ptrdiff_t length;
551 Lisp_Object handler; 550 Lisp_Object handler, val;
551 USE_SAFE_ALLOCA;
552 552
553 CHECK_STRING (file); 553 CHECK_STRING (file);
554 if (NILP (file)) 554 if (NILP (file))
@@ -570,10 +570,12 @@ For a Unix-syntax file name, just appends a slash. */)
570 if (!NILP (Vw32_downcase_file_names)) 570 if (!NILP (Vw32_downcase_file_names))
571 file = Fdowncase (file); 571 file = Fdowncase (file);
572#endif 572#endif
573 buf = alloca (SBYTES (file) + 10); 573 buf = SAFE_ALLOCA (SBYTES (file) + file_name_as_directory_slop + 1);
574 length = file_name_as_directory (buf, SSDATA (file), SBYTES (file), 574 length = file_name_as_directory (buf, SSDATA (file), SBYTES (file),
575 STRING_MULTIBYTE (file)); 575 STRING_MULTIBYTE (file));
576 return make_specified_string (buf, -1, length, STRING_MULTIBYTE (file)); 576 val = make_specified_string (buf, -1, length, STRING_MULTIBYTE (file));
577 SAFE_FREE ();
578 return val;
577} 579}
578 580
579/* Convert from directory name SRC of length SRCLEN to file name in 581/* Convert from directory name SRC of length SRCLEN to file name in
@@ -585,18 +587,17 @@ static ptrdiff_t
585directory_file_name (char *dst, char *src, ptrdiff_t srclen, bool multibyte) 587directory_file_name (char *dst, char *src, ptrdiff_t srclen, bool multibyte)
586{ 588{
587 /* Process as Unix format: just remove any final slash. 589 /* Process as Unix format: just remove any final slash.
588 But leave "/" unchanged; do not change it to "". */ 590 But leave "/" and "//" unchanged. */
589 strcpy (dst, src); 591 while (srclen > 1
590 if (srclen > 1
591 && IS_DIRECTORY_SEP (dst[srclen - 1])
592#ifdef DOS_NT 592#ifdef DOS_NT
593 && !IS_ANY_SEP (dst[srclen - 2]) 593 && !IS_ANY_SEP (src[srclen - 2])
594#endif 594#endif
595 ) 595 && IS_DIRECTORY_SEP (src[srclen - 1])
596 { 596 && ! (srclen == 2 && IS_DIRECTORY_SEP (src[0])))
597 dst[srclen - 1] = 0; 597 srclen--;
598 srclen--; 598
599 } 599 memcpy (dst, src, srclen);
600 dst[srclen] = 0;
600#ifdef DOS_NT 601#ifdef DOS_NT
601 dostounix_filename (dst, multibyte); 602 dostounix_filename (dst, multibyte);
602#endif 603#endif
@@ -614,7 +615,8 @@ In Unix-syntax, this function just removes the final slash. */)
614{ 615{
615 char *buf; 616 char *buf;
616 ptrdiff_t length; 617 ptrdiff_t length;
617 Lisp_Object handler; 618 Lisp_Object handler, val;
619 USE_SAFE_ALLOCA;
618 620
619 CHECK_STRING (directory); 621 CHECK_STRING (directory);
620 622
@@ -637,10 +639,12 @@ In Unix-syntax, this function just removes the final slash. */)
637 if (!NILP (Vw32_downcase_file_names)) 639 if (!NILP (Vw32_downcase_file_names))
638 directory = Fdowncase (directory); 640 directory = Fdowncase (directory);
639#endif 641#endif
640 buf = alloca (SBYTES (directory) + 20); 642 buf = SAFE_ALLOCA (SBYTES (directory) + 1);
641 length = directory_file_name (buf, SSDATA (directory), SBYTES (directory), 643 length = directory_file_name (buf, SSDATA (directory), SBYTES (directory),
642 STRING_MULTIBYTE (directory)); 644 STRING_MULTIBYTE (directory));
643 return make_specified_string (buf, -1, length, STRING_MULTIBYTE (directory)); 645 val = make_specified_string (buf, -1, length, STRING_MULTIBYTE (directory));
646 SAFE_FREE ();
647 return val;
644} 648}
645 649
646static const char make_temp_name_tbl[64] = 650static const char make_temp_name_tbl[64] =
@@ -838,6 +842,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
838 Lisp_Object handler, result, handled_name; 842 Lisp_Object handler, result, handled_name;
839 bool multibyte; 843 bool multibyte;
840 Lisp_Object hdir; 844 Lisp_Object hdir;
845 USE_SAFE_ALLOCA;
841 846
842 CHECK_STRING (name); 847 CHECK_STRING (name);
843 848
@@ -944,8 +949,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
944#endif 949#endif
945 950
946 /* Make a local copy of nm[] to protect it from GC in DECODE_FILE below. */ 951 /* Make a local copy of nm[] to protect it from GC in DECODE_FILE below. */
947 nm = alloca (SBYTES (name) + 1); 952 nm = xlispstrdupa (name);
948 memcpy (nm, SSDATA (name), SBYTES (name) + 1);
949 953
950#ifdef DOS_NT 954#ifdef DOS_NT
951 /* Note if special escape prefix is present, but remove for now. */ 955 /* Note if special escape prefix is present, but remove for now. */
@@ -1013,11 +1017,11 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1013 || (p[2] == '.' && (IS_DIRECTORY_SEP (p[3]) 1017 || (p[2] == '.' && (IS_DIRECTORY_SEP (p[3])
1014 || p[3] == 0)))) 1018 || p[3] == 0))))
1015 lose = 1; 1019 lose = 1;
1016 /* We want to replace multiple `/' in a row with a single 1020 /* Replace multiple slashes with a single one, except
1017 slash. */ 1021 leave leading "//" alone. */
1018 else if (p > nm 1022 else if (IS_DIRECTORY_SEP (p[0])
1019 && IS_DIRECTORY_SEP (p[0]) 1023 && IS_DIRECTORY_SEP (p[1])
1020 && IS_DIRECTORY_SEP (p[1])) 1024 && (p != nm || IS_DIRECTORY_SEP (p[2])))
1021 lose = 1; 1025 lose = 1;
1022 p++; 1026 p++;
1023 } 1027 }
@@ -1100,10 +1104,11 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1100 else /* ~user/filename */ 1104 else /* ~user/filename */
1101 { 1105 {
1102 char *o, *p; 1106 char *o, *p;
1103 for (p = nm; *p && (!IS_DIRECTORY_SEP (*p)); p++); 1107 for (p = nm; *p && !IS_DIRECTORY_SEP (*p); p++)
1104 o = alloca (p - nm + 1); 1108 continue;
1109 o = SAFE_ALLOCA (p - nm + 1);
1105 memcpy (o, nm, p - nm); 1110 memcpy (o, nm, p - nm);
1106 o [p - nm] = 0; 1111 o[p - nm] = 0;
1107 1112
1108 block_input (); 1113 block_input ();
1109 pw = getpwnam (o + 1); 1114 pw = getpwnam (o + 1);
@@ -1219,7 +1224,8 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1219 if (!IS_DIRECTORY_SEP (nm[0])) 1224 if (!IS_DIRECTORY_SEP (nm[0]))
1220 { 1225 {
1221 ptrdiff_t newlen = strlen (newdir); 1226 ptrdiff_t newlen = strlen (newdir);
1222 char *tmp = alloca (newlen + strlen (nm) + 2); 1227 char *tmp = alloca (newlen + file_name_as_directory_slop
1228 + strlen (nm) + 1);
1223 file_name_as_directory (tmp, newdir, newlen, multibyte); 1229 file_name_as_directory (tmp, newdir, newlen, multibyte);
1224 strcat (tmp, nm); 1230 strcat (tmp, nm);
1225 nm = tmp; 1231 nm = tmp;
@@ -1273,31 +1279,18 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1273 1279
1274 if (newdir) 1280 if (newdir)
1275 { 1281 {
1276 /* Get rid of any slash at the end of newdir, unless newdir is 1282 /* Ignore any slash at the end of newdir, unless newdir is
1277 just / or // (an incomplete UNC name). */ 1283 just "/" or "//". */
1278 length = strlen (newdir); 1284 length = strlen (newdir);
1279 tlen = length + 1; 1285 while (length > 1 && IS_DIRECTORY_SEP (newdir[length - 1])
1280 if (length > 1 && IS_DIRECTORY_SEP (newdir[length - 1]) 1286 && ! (length == 2 && IS_DIRECTORY_SEP (newdir[0])))
1281#ifdef WINDOWSNT 1287 length--;
1282 && !(length == 2 && IS_DIRECTORY_SEP (newdir[0]))
1283#endif
1284 )
1285 {
1286 char *temp = alloca (length);
1287 memcpy (temp, newdir, length - 1);
1288 temp[length - 1] = 0;
1289 length--;
1290 newdir = temp;
1291 }
1292 } 1288 }
1293 else 1289 else
1294 { 1290 length = 0;
1295 length = 0;
1296 tlen = 0;
1297 }
1298 1291
1299 /* Now concatenate the directory and name to new space in the stack frame. */ 1292 /* Now concatenate the directory and name to new space in the stack frame. */
1300 tlen += strlen (nm) + 1; 1293 tlen = length + file_name_as_directory_slop + strlen (nm) + 1;
1301#ifdef DOS_NT 1294#ifdef DOS_NT
1302 /* Reserve space for drive specifier and escape prefix, since either 1295 /* Reserve space for drive specifier and escape prefix, since either
1303 or both may need to be inserted. (The Microsoft x86 compiler 1296 or both may need to be inserted. (The Microsoft x86 compiler
@@ -1305,7 +1298,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1305 target = alloca (tlen + 4); 1298 target = alloca (tlen + 4);
1306 target += 4; 1299 target += 4;
1307#else /* not DOS_NT */ 1300#else /* not DOS_NT */
1308 target = alloca (tlen); 1301 target = SAFE_ALLOCA (tlen);
1309#endif /* not DOS_NT */ 1302#endif /* not DOS_NT */
1310 *target = 0; 1303 *target = 0;
1311 1304
@@ -1322,7 +1315,10 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1322 if (!(drive && nm[0] && IS_DIRECTORY_SEP (newdir[0]) 1315 if (!(drive && nm[0] && IS_DIRECTORY_SEP (newdir[0])
1323 && newdir[1] == '\0')) 1316 && newdir[1] == '\0'))
1324#endif 1317#endif
1325 strcpy (target, newdir); 1318 {
1319 memcpy (target, newdir, length);
1320 target[length] = 0;
1321 }
1326 } 1322 }
1327 else 1323 else
1328 file_name_as_directory (target, newdir, length, multibyte); 1324 file_name_as_directory (target, newdir, length, multibyte);
@@ -1382,8 +1378,9 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1382 ++o; 1378 ++o;
1383 p += 3; 1379 p += 3;
1384 } 1380 }
1385 else if (p > target && IS_DIRECTORY_SEP (p[1])) 1381 else if (IS_DIRECTORY_SEP (p[1])
1386 /* Collapse multiple `/' in a row. */ 1382 && (p != target || IS_DIRECTORY_SEP (p[2])))
1383 /* Collapse multiple "/", except leave leading "//" alone. */
1387 p++; 1384 p++;
1388 else 1385 else
1389 { 1386 {
@@ -1431,11 +1428,12 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1431 { 1428 {
1432 handled_name = call3 (handler, Qexpand_file_name, 1429 handled_name = call3 (handler, Qexpand_file_name,
1433 result, default_directory); 1430 result, default_directory);
1434 if (STRINGP (handled_name)) 1431 if (! STRINGP (handled_name))
1435 return handled_name; 1432 error ("Invalid handler in `file-name-handler-alist'");
1436 error ("Invalid handler in `file-name-handler-alist'"); 1433 result = handled_name;
1437 } 1434 }
1438 1435
1436 SAFE_FREE ();
1439 return result; 1437 return result;
1440} 1438}
1441 1439
@@ -1693,8 +1691,7 @@ those `/' is discarded. */)
1693 /* Always work on a copy of the string, in case GC happens during 1691 /* Always work on a copy of the string, in case GC happens during
1694 decode of environment variables, causing the original Lisp_String 1692 decode of environment variables, causing the original Lisp_String
1695 data to be relocated. */ 1693 data to be relocated. */
1696 nm = alloca (SBYTES (filename) + 1); 1694 nm = xlispstrdupa (filename);
1697 memcpy (nm, SDATA (filename), SBYTES (filename) + 1);
1698 1695
1699#ifdef DOS_NT 1696#ifdef DOS_NT
1700 dostounix_filename (nm, multibyte); 1697 dostounix_filename (nm, multibyte);
@@ -2048,7 +2045,7 @@ entries (depending on how Emacs was built). */)
2048 /* CopyFile retains the timestamp by default. */ 2045 /* CopyFile retains the timestamp by default. */
2049 else if (NILP (keep_time)) 2046 else if (NILP (keep_time))
2050 { 2047 {
2051 EMACS_TIME now; 2048 struct timespec now;
2052 DWORD attributes; 2049 DWORD attributes;
2053 char * filename; 2050 char * filename;
2054 2051
@@ -2057,7 +2054,7 @@ entries (depending on how Emacs was built). */)
2057 /* Ensure file is writable while its modified time is set. */ 2054 /* Ensure file is writable while its modified time is set. */
2058 attributes = GetFileAttributes (filename); 2055 attributes = GetFileAttributes (filename);
2059 SetFileAttributes (filename, attributes & ~FILE_ATTRIBUTE_READONLY); 2056 SetFileAttributes (filename, attributes & ~FILE_ATTRIBUTE_READONLY);
2060 now = current_emacs_time (); 2057 now = current_timespec ();
2061 if (set_file_times (-1, filename, now, now)) 2058 if (set_file_times (-1, filename, now, now))
2062 { 2059 {
2063 /* Restore original attributes. */ 2060 /* Restore original attributes. */
@@ -2181,8 +2178,8 @@ entries (depending on how Emacs was built). */)
2181 2178
2182 if (!NILP (keep_time)) 2179 if (!NILP (keep_time))
2183 { 2180 {
2184 EMACS_TIME atime = get_stat_atime (&st); 2181 struct timespec atime = get_stat_atime (&st);
2185 EMACS_TIME mtime = get_stat_mtime (&st); 2182 struct timespec mtime = get_stat_mtime (&st);
2186 if (set_file_times (ofd, SSDATA (encoded_newname), atime, mtime)) 2183 if (set_file_times (ofd, SSDATA (encoded_newname), atime, mtime))
2187 xsignal2 (Qfile_date_error, 2184 xsignal2 (Qfile_date_error,
2188 build_string ("Cannot set file date"), newname); 2185 build_string ("Cannot set file date"), newname);
@@ -3289,7 +3286,7 @@ Use the current time if TIMESTAMP is nil. TIMESTAMP is in the format of
3289{ 3286{
3290 Lisp_Object absname, encoded_absname; 3287 Lisp_Object absname, encoded_absname;
3291 Lisp_Object handler; 3288 Lisp_Object handler;
3292 EMACS_TIME t = lisp_time_argument (timestamp); 3289 struct timespec t = lisp_time_argument (timestamp);
3293 3290
3294 absname = Fexpand_file_name (filename, BVAR (current_buffer, directory)); 3291 absname = Fexpand_file_name (filename, BVAR (current_buffer, directory));
3295 3292
@@ -3366,7 +3363,7 @@ otherwise, if FILE2 does not exist, the answer is t. */)
3366 if (stat (SSDATA (absname2), &st2) < 0) 3363 if (stat (SSDATA (absname2), &st2) < 0)
3367 return Qt; 3364 return Qt;
3368 3365
3369 return (EMACS_TIME_LT (get_stat_mtime (&st2), get_stat_mtime (&st1)) 3366 return (timespec_cmp (get_stat_mtime (&st2), get_stat_mtime (&st1)) < 0
3370 ? Qt : Qnil); 3367 ? Qt : Qnil);
3371} 3368}
3372 3369
@@ -3466,13 +3463,13 @@ file_offset (Lisp_Object val)
3466} 3463}
3467 3464
3468/* Return a special time value indicating the error number ERRNUM. */ 3465/* Return a special time value indicating the error number ERRNUM. */
3469static EMACS_TIME 3466static struct timespec
3470time_error_value (int errnum) 3467time_error_value (int errnum)
3471{ 3468{
3472 int ns = (errnum == ENOENT || errnum == EACCES || errnum == ENOTDIR 3469 int ns = (errnum == ENOENT || errnum == EACCES || errnum == ENOTDIR
3473 ? NONEXISTENT_MODTIME_NSECS 3470 ? NONEXISTENT_MODTIME_NSECS
3474 : UNKNOWN_MODTIME_NSECS); 3471 : UNKNOWN_MODTIME_NSECS);
3475 return make_emacs_time (0, ns); 3472 return make_timespec (0, ns);
3476} 3473}
3477 3474
3478DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents, 3475DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents,
@@ -3504,7 +3501,7 @@ by calling `format-decode', which see. */)
3504 (Lisp_Object filename, Lisp_Object visit, Lisp_Object beg, Lisp_Object end, Lisp_Object replace) 3501 (Lisp_Object filename, Lisp_Object visit, Lisp_Object beg, Lisp_Object end, Lisp_Object replace)
3505{ 3502{
3506 struct stat st; 3503 struct stat st;
3507 EMACS_TIME mtime; 3504 struct timespec mtime;
3508 int fd; 3505 int fd;
3509 ptrdiff_t inserted = 0; 3506 ptrdiff_t inserted = 0;
3510 ptrdiff_t how_much; 3507 ptrdiff_t how_much;
@@ -4570,7 +4567,7 @@ by calling `format-decode', which see. */)
4570 } 4567 }
4571 4568
4572 if (!NILP (visit) 4569 if (!NILP (visit)
4573 && EMACS_NSECS (current_buffer->modtime) == NONEXISTENT_MODTIME_NSECS) 4570 && current_buffer->modtime.tv_nsec == NONEXISTENT_MODTIME_NSECS)
4574 { 4571 {
4575 /* If visiting nonexistent file, return nil. */ 4572 /* If visiting nonexistent file, return nil. */
4576 report_file_errno ("Opening input file", orig_filename, save_errno); 4573 report_file_errno ("Opening input file", orig_filename, save_errno);
@@ -4746,25 +4743,39 @@ This does code conversion according to the value of
4746 4743
4747This calls `write-region-annotate-functions' at the start, and 4744This calls `write-region-annotate-functions' at the start, and
4748`write-region-post-annotation-function' at the end. */) 4745`write-region-post-annotation-function' at the end. */)
4749 (Lisp_Object start, Lisp_Object end, Lisp_Object filename, Lisp_Object append, Lisp_Object visit, Lisp_Object lockname, Lisp_Object mustbenew) 4746 (Lisp_Object start, Lisp_Object end, Lisp_Object filename, Lisp_Object append,
4747 Lisp_Object visit, Lisp_Object lockname, Lisp_Object mustbenew)
4748{
4749 return write_region (start, end, filename, append, visit, lockname, mustbenew,
4750 -1);
4751}
4752
4753/* Like Fwrite_region, except that if DESC is nonnegative, it is a file
4754 descriptor for FILENAME, so do not open or close FILENAME. */
4755
4756Lisp_Object
4757write_region (Lisp_Object start, Lisp_Object end, Lisp_Object filename,
4758 Lisp_Object append, Lisp_Object visit, Lisp_Object lockname,
4759 Lisp_Object mustbenew, int desc)
4750{ 4760{
4751 int desc;
4752 int open_flags; 4761 int open_flags;
4753 int mode; 4762 int mode;
4754 off_t offset IF_LINT (= 0); 4763 off_t offset IF_LINT (= 0);
4764 bool open_and_close_file = desc < 0;
4755 bool ok; 4765 bool ok;
4756 int save_errno = 0; 4766 int save_errno = 0;
4757 const char *fn; 4767 const char *fn;
4758 struct stat st; 4768 struct stat st;
4759 EMACS_TIME modtime; 4769 struct timespec modtime;
4760 ptrdiff_t count = SPECPDL_INDEX (); 4770 ptrdiff_t count = SPECPDL_INDEX ();
4761 ptrdiff_t count1; 4771 ptrdiff_t count1 IF_LINT (= 0);
4762 Lisp_Object handler; 4772 Lisp_Object handler;
4763 Lisp_Object visit_file; 4773 Lisp_Object visit_file;
4764 Lisp_Object annotations; 4774 Lisp_Object annotations;
4765 Lisp_Object encoded_filename; 4775 Lisp_Object encoded_filename;
4766 bool visiting = (EQ (visit, Qt) || STRINGP (visit)); 4776 bool visiting = (EQ (visit, Qt) || STRINGP (visit));
4767 bool quietly = !NILP (visit); 4777 bool quietly = !NILP (visit);
4778 bool file_locked = 0;
4768 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; 4779 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
4769 struct buffer *given_buffer; 4780 struct buffer *given_buffer;
4770 struct coding_system coding; 4781 struct coding_system coding;
@@ -4832,7 +4843,6 @@ This calls `write-region-annotate-functions' at the start, and
4832 record_unwind_protect (build_annotations_unwind, 4843 record_unwind_protect (build_annotations_unwind,
4833 Vwrite_region_annotation_buffers); 4844 Vwrite_region_annotation_buffers);
4834 Vwrite_region_annotation_buffers = list1 (Fcurrent_buffer ()); 4845 Vwrite_region_annotation_buffers = list1 (Fcurrent_buffer ());
4835 count1 = SPECPDL_INDEX ();
4836 4846
4837 given_buffer = current_buffer; 4847 given_buffer = current_buffer;
4838 4848
@@ -4871,8 +4881,11 @@ This calls `write-region-annotate-functions' at the start, and
4871 coding.mode |= CODING_MODE_SELECTIVE_DISPLAY; 4881 coding.mode |= CODING_MODE_SELECTIVE_DISPLAY;
4872 4882
4873#ifdef CLASH_DETECTION 4883#ifdef CLASH_DETECTION
4874 if (!auto_saving) 4884 if (open_and_close_file && !auto_saving)
4875 lock_file (lockname); 4885 {
4886 lock_file (lockname);
4887 file_locked = 1;
4888 }
4876#endif /* CLASH_DETECTION */ 4889#endif /* CLASH_DETECTION */
4877 4890
4878 encoded_filename = ENCODE_FILE (filename); 4891 encoded_filename = ENCODE_FILE (filename);
@@ -4889,19 +4902,23 @@ This calls `write-region-annotate-functions' at the start, and
4889 mode = auto_saving ? auto_save_mode_bits : 0666; 4902 mode = auto_saving ? auto_save_mode_bits : 0666;
4890#endif 4903#endif
4891 4904
4892 desc = emacs_open (fn, open_flags, mode); 4905 if (open_and_close_file)
4893
4894 if (desc < 0)
4895 { 4906 {
4896 int open_errno = errno; 4907 desc = emacs_open (fn, open_flags, mode);
4908 if (desc < 0)
4909 {
4910 int open_errno = errno;
4897#ifdef CLASH_DETECTION 4911#ifdef CLASH_DETECTION
4898 if (!auto_saving) unlock_file (lockname); 4912 if (file_locked)
4913 unlock_file (lockname);
4899#endif /* CLASH_DETECTION */ 4914#endif /* CLASH_DETECTION */
4900 UNGCPRO; 4915 UNGCPRO;
4901 report_file_errno ("Opening output file", filename, open_errno); 4916 report_file_errno ("Opening output file", filename, open_errno);
4902 } 4917 }
4903 4918
4904 record_unwind_protect_int (close_file_unwind, desc); 4919 count1 = SPECPDL_INDEX ();
4920 record_unwind_protect_int (close_file_unwind, desc);
4921 }
4905 4922
4906 if (NUMBERP (append)) 4923 if (NUMBERP (append))
4907 { 4924 {
@@ -4910,7 +4927,8 @@ This calls `write-region-annotate-functions' at the start, and
4910 { 4927 {
4911 int lseek_errno = errno; 4928 int lseek_errno = errno;
4912#ifdef CLASH_DETECTION 4929#ifdef CLASH_DETECTION
4913 if (!auto_saving) unlock_file (lockname); 4930 if (file_locked)
4931 unlock_file (lockname);
4914#endif /* CLASH_DETECTION */ 4932#endif /* CLASH_DETECTION */
4915 UNGCPRO; 4933 UNGCPRO;
4916 report_file_errno ("Lseek error", filename, lseek_errno); 4934 report_file_errno ("Lseek error", filename, lseek_errno);
@@ -4945,9 +4963,9 @@ This calls `write-region-annotate-functions' at the start, and
4945 4963
4946 immediate_quit = 0; 4964 immediate_quit = 0;
4947 4965
4948 /* fsync is not crucial for auto-save files, since they might lose 4966 /* fsync is not crucial for temporary files. Nor for auto-save
4949 some work anyway. */ 4967 files, since they might lose some work anyway. */
4950 if (!auto_saving && !write_region_inhibit_fsync) 4968 if (open_and_close_file && !auto_saving && !write_region_inhibit_fsync)
4951 { 4969 {
4952 /* Transfer data and metadata to disk, retrying if interrupted. 4970 /* Transfer data and metadata to disk, retrying if interrupted.
4953 fsync can report a write failure here, e.g., due to disk full 4971 fsync can report a write failure here, e.g., due to disk full
@@ -4962,7 +4980,7 @@ This calls `write-region-annotate-functions' at the start, and
4962 } 4980 }
4963 } 4981 }
4964 4982
4965 modtime = invalid_emacs_time (); 4983 modtime = invalid_timespec ();
4966 if (visiting) 4984 if (visiting)
4967 { 4985 {
4968 if (fstat (desc, &st) == 0) 4986 if (fstat (desc, &st) == 0)
@@ -4971,12 +4989,15 @@ This calls `write-region-annotate-functions' at the start, and
4971 ok = 0, save_errno = errno; 4989 ok = 0, save_errno = errno;
4972 } 4990 }
4973 4991
4974 /* NFS can report a write failure now. */ 4992 if (open_and_close_file)
4975 if (emacs_close (desc) < 0) 4993 {
4976 ok = 0, save_errno = errno; 4994 /* NFS can report a write failure now. */
4995 if (emacs_close (desc) < 0)
4996 ok = 0, save_errno = errno;
4977 4997
4978 /* Discard the unwind protect for close_file_unwind. */ 4998 /* Discard the unwind protect for close_file_unwind. */
4979 specpdl_ptr = specpdl + count1; 4999 specpdl_ptr = specpdl + count1;
5000 }
4980 5001
4981 /* Some file systems have a bug where st_mtime is not updated 5002 /* Some file systems have a bug where st_mtime is not updated
4982 properly after a write. For example, CIFS might not see the 5003 properly after a write. For example, CIFS might not see the
@@ -4993,7 +5014,7 @@ This calls `write-region-annotate-functions' at the start, and
4993 unlikely and a similar race between the last write and the fstat 5014 unlikely and a similar race between the last write and the fstat
4994 above cannot possibly be closed anyway. */ 5015 above cannot possibly be closed anyway. */
4995 5016
4996 if (EMACS_TIME_VALID_P (modtime) 5017 if (timespec_valid_p (modtime)
4997 && ! (valid_timestamp_file_system && st.st_dev == timestamp_file_system)) 5018 && ! (valid_timestamp_file_system && st.st_dev == timestamp_file_system))
4998 { 5019 {
4999 int desc1 = emacs_open (fn, O_WRONLY | O_BINARY, 0); 5020 int desc1 = emacs_open (fn, O_WRONLY | O_BINARY, 0);
@@ -5015,11 +5036,11 @@ This calls `write-region-annotate-functions' at the start, and
5015 bool use_heuristic 5036 bool use_heuristic
5016 = ((open_flags & (O_EXCL | O_TRUNC)) != 0 5037 = ((open_flags & (O_EXCL | O_TRUNC)) != 0
5017 && st.st_size != 0 5038 && st.st_size != 0
5018 && EMACS_NSECS (modtime) % 100 != 0); 5039 && modtime.tv_nsec % 100 != 0);
5019 5040
5020 EMACS_TIME modtime1 = get_stat_mtime (&st1); 5041 struct timespec modtime1 = get_stat_mtime (&st1);
5021 if (use_heuristic 5042 if (use_heuristic
5022 && EMACS_TIME_EQ (modtime, modtime1) 5043 && timespec_cmp (modtime, modtime1) == 0
5023 && st.st_size == st1.st_size) 5044 && st.st_size == st1.st_size)
5024 { 5045 {
5025 timestamp_file_system = st.st_dev; 5046 timestamp_file_system = st.st_dev;
@@ -5052,14 +5073,14 @@ This calls `write-region-annotate-functions' at the start, and
5052 unbind_to (count, Qnil); 5073 unbind_to (count, Qnil);
5053 5074
5054#ifdef CLASH_DETECTION 5075#ifdef CLASH_DETECTION
5055 if (!auto_saving) 5076 if (file_locked)
5056 unlock_file (lockname); 5077 unlock_file (lockname);
5057#endif /* CLASH_DETECTION */ 5078#endif /* CLASH_DETECTION */
5058 5079
5059 /* Do this before reporting IO error 5080 /* Do this before reporting IO error
5060 to avoid a "file has changed on disk" warning on 5081 to avoid a "file has changed on disk" warning on
5061 next attempt to save. */ 5082 next attempt to save. */
5062 if (EMACS_TIME_VALID_P (modtime)) 5083 if (timespec_valid_p (modtime))
5063 { 5084 {
5064 current_buffer->modtime = modtime; 5085 current_buffer->modtime = modtime;
5065 current_buffer->modtime_size = st.st_size; 5086 current_buffer->modtime_size = st.st_size;
@@ -5334,7 +5355,7 @@ See Info node `(elisp)Modification Time' for more details. */)
5334 struct stat st; 5355 struct stat st;
5335 Lisp_Object handler; 5356 Lisp_Object handler;
5336 Lisp_Object filename; 5357 Lisp_Object filename;
5337 EMACS_TIME mtime; 5358 struct timespec mtime;
5338 5359
5339 if (NILP (buf)) 5360 if (NILP (buf))
5340 b = current_buffer; 5361 b = current_buffer;
@@ -5345,7 +5366,7 @@ See Info node `(elisp)Modification Time' for more details. */)
5345 } 5366 }
5346 5367
5347 if (!STRINGP (BVAR (b, filename))) return Qt; 5368 if (!STRINGP (BVAR (b, filename))) return Qt;
5348 if (EMACS_NSECS (b->modtime) == UNKNOWN_MODTIME_NSECS) return Qt; 5369 if (b->modtime.tv_nsec == UNKNOWN_MODTIME_NSECS) return Qt;
5349 5370
5350 /* If the file name has special constructs in it, 5371 /* If the file name has special constructs in it,
5351 call the corresponding file handler. */ 5372 call the corresponding file handler. */
@@ -5359,7 +5380,7 @@ See Info node `(elisp)Modification Time' for more details. */)
5359 mtime = (stat (SSDATA (filename), &st) == 0 5380 mtime = (stat (SSDATA (filename), &st) == 0
5360 ? get_stat_mtime (&st) 5381 ? get_stat_mtime (&st)
5361 : time_error_value (errno)); 5382 : time_error_value (errno));
5362 if (EMACS_TIME_EQ (mtime, b->modtime) 5383 if (timespec_cmp (mtime, b->modtime) == 0
5363 && (b->modtime_size < 0 5384 && (b->modtime_size < 0
5364 || st.st_size == b->modtime_size)) 5385 || st.st_size == b->modtime_size))
5365 return Qt; 5386 return Qt;
@@ -5376,7 +5397,7 @@ doesn't exist, return -1.
5376See Info node `(elisp)Modification Time' for more details. */) 5397See Info node `(elisp)Modification Time' for more details. */)
5377 (void) 5398 (void)
5378{ 5399{
5379 int ns = EMACS_NSECS (current_buffer->modtime); 5400 int ns = current_buffer->modtime.tv_nsec;
5380 if (ns < 0) 5401 if (ns < 0)
5381 return make_number (UNKNOWN_MODTIME_NSECS - ns); 5402 return make_number (UNKNOWN_MODTIME_NSECS - ns);
5382 return make_lisp_time (current_buffer->modtime); 5403 return make_lisp_time (current_buffer->modtime);
@@ -5395,11 +5416,11 @@ An argument specifies the modification time value to use
5395{ 5416{
5396 if (!NILP (time_flag)) 5417 if (!NILP (time_flag))
5397 { 5418 {
5398 EMACS_TIME mtime; 5419 struct timespec mtime;
5399 if (INTEGERP (time_flag)) 5420 if (INTEGERP (time_flag))
5400 { 5421 {
5401 CHECK_RANGED_INTEGER (time_flag, -1, 0); 5422 CHECK_RANGED_INTEGER (time_flag, -1, 0);
5402 mtime = make_emacs_time (0, UNKNOWN_MODTIME_NSECS - XINT (time_flag)); 5423 mtime = make_timespec (0, UNKNOWN_MODTIME_NSECS - XINT (time_flag));
5403 } 5424 }
5404 else 5425 else
5405 mtime = lisp_time_argument (time_flag); 5426 mtime = lisp_time_argument (time_flag);
@@ -5618,9 +5639,8 @@ A non-nil CURRENT-ONLY argument means save only current buffer. */)
5618 couldn't handle some ange-ftp'd file. */ 5639 couldn't handle some ange-ftp'd file. */
5619 5640
5620 for (do_handled_files = 0; do_handled_files < 2; do_handled_files++) 5641 for (do_handled_files = 0; do_handled_files < 2; do_handled_files++)
5621 for (tail = Vbuffer_alist; CONSP (tail); tail = XCDR (tail)) 5642 FOR_EACH_LIVE_BUFFER (tail, buf)
5622 { 5643 {
5623 buf = XCDR (XCAR (tail));
5624 b = XBUFFER (buf); 5644 b = XBUFFER (buf);
5625 5645
5626 /* Record all the buffers that have auto save mode 5646 /* Record all the buffers that have auto save mode
@@ -5663,12 +5683,12 @@ A non-nil CURRENT-ONLY argument means save only current buffer. */)
5663 || NILP (Ffind_file_name_handler (BVAR (b, auto_save_file_name), 5683 || NILP (Ffind_file_name_handler (BVAR (b, auto_save_file_name),
5664 Qwrite_region)))) 5684 Qwrite_region))))
5665 { 5685 {
5666 EMACS_TIME before_time = current_emacs_time (); 5686 struct timespec before_time = current_timespec ();
5667 EMACS_TIME after_time; 5687 struct timespec after_time;
5668 5688
5669 /* If we had a failure, don't try again for 20 minutes. */ 5689 /* If we had a failure, don't try again for 20 minutes. */
5670 if (b->auto_save_failure_time > 0 5690 if (b->auto_save_failure_time > 0
5671 && EMACS_SECS (before_time) - b->auto_save_failure_time < 1200) 5691 && before_time.tv_sec - b->auto_save_failure_time < 1200)
5672 continue; 5692 continue;
5673 5693
5674 set_buffer_internal (b); 5694 set_buffer_internal (b);
@@ -5701,12 +5721,12 @@ A non-nil CURRENT-ONLY argument means save only current buffer. */)
5701 XSETFASTINT (BVAR (current_buffer, save_length), Z - BEG); 5721 XSETFASTINT (BVAR (current_buffer, save_length), Z - BEG);
5702 set_buffer_internal (old); 5722 set_buffer_internal (old);
5703 5723
5704 after_time = current_emacs_time (); 5724 after_time = current_timespec ();
5705 5725
5706 /* If auto-save took more than 60 seconds, 5726 /* If auto-save took more than 60 seconds,
5707 assume it was an NFS failure that got a timeout. */ 5727 assume it was an NFS failure that got a timeout. */
5708 if (EMACS_SECS (after_time) - EMACS_SECS (before_time) > 60) 5728 if (after_time.tv_sec - before_time.tv_sec > 60)
5709 b->auto_save_failure_time = EMACS_SECS (after_time); 5729 b->auto_save_failure_time = after_time.tv_sec;
5710 } 5730 }
5711 } 5731 }
5712 5732