aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2025-07-12 14:31:18 -0700
committerPaul Eggert2025-07-13 21:09:39 -0700
commitaee9b598312e282700c4eedf02b174b908479ce7 (patch)
tree87c8cd0c1d8c34944f17624007856b4d82251c28 /src
parent56091b6d5cccecf320796bd62e36adc64f45b614 (diff)
downloademacs-aee9b598312e282700c4eedf02b174b908479ce7.tar.gz
emacs-aee9b598312e282700c4eedf02b174b908479ce7.zip
insert-file-contents file end EOF fixes
* src/fileio.c (Finsert_file_contents): When counting bytes at file end, don’t trust lseek to seek to the end of the file. Instead, read a bit after lseeking, to make sure we get to the end, give up if we don’t get to EOF. This works around problems on /proc filesystems where lseek pretends the file is empty. Update file_size_hint when reaching EOF.
Diffstat (limited to 'src')
-rw-r--r--src/fileio.c38
1 files changed, 33 insertions, 5 deletions
diff --git a/src/fileio.c b/src/fileio.c
index 3c371dea98d..b7b4320d73e 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -4488,13 +4488,39 @@ by calling `format-decode', which see. */)
4488 /* Count how many chars at the end of the file 4488 /* Count how many chars at the end of the file
4489 match the text at the end of the buffer. But, if we have 4489 match the text at the end of the buffer. But, if we have
4490 already found that decoding is necessary, don't waste time. */ 4490 already found that decoding is necessary, don't waste time. */
4491
4492 off_t endpos;
4493 if (!giveup_match_end)
4494 {
4495 endpos = end_offset;
4496 if (endpos == TYPE_MAXIMUM (off_t))
4497 {
4498 endpos = emacs_fd_lseek (fd, 0, SEEK_END);
4499 giveup_match_end = endpos < 0;
4500 if (giveup_match_end)
4501 seekable = false;
4502 else
4503 {
4504 /* Check that read reports EOF soon, to catch platforms
4505 where SEEK_END can report wildly small offsets. */
4506 ptrdiff_t n = emacs_fd_read (fd, read_buf, sizeof read_buf);
4507 if (n < 0)
4508 report_file_error ("Read error", orig_filename);
4509 endpos += n;
4510 giveup_match_end = 0 < n;
4511 if (!giveup_match_end)
4512 file_size_hint = endpos;
4513 }
4514 }
4515 }
4516
4491 while (!giveup_match_end) 4517 while (!giveup_match_end)
4492 { 4518 {
4493 int total_read, nread, bufpos, trial; 4519 int total_read, nread, bufpos, trial;
4494 off_t curpos; 4520 off_t curpos;
4495 4521
4496 /* At what file position are we now scanning? */ 4522 /* At what file position are we now scanning? */
4497 curpos = end_offset - (ZV_BYTE - same_at_end); 4523 curpos = endpos - (ZV_BYTE - same_at_end);
4498 /* If the entire file matches the buffer tail, stop the scan. */ 4524 /* If the entire file matches the buffer tail, stop the scan. */
4499 if (curpos == 0) 4525 if (curpos == 0)
4500 break; 4526 break;
@@ -4511,7 +4537,10 @@ by calling `format-decode', which see. */)
4511 if (nread < 0) 4537 if (nread < 0)
4512 report_file_error ("Read error", orig_filename); 4538 report_file_error ("Read error", orig_filename);
4513 else if (nread == 0) 4539 else if (nread == 0)
4514 break; 4540 {
4541 file_size_hint = curpos - trial + total_read;
4542 break;
4543 }
4515 total_read += nread; 4544 total_read += nread;
4516 } 4545 }
4517 4546
@@ -4567,15 +4596,14 @@ by calling `format-decode', which see. */)
4567 /* Don't try to reuse the same piece of text twice. */ 4596 /* Don't try to reuse the same piece of text twice. */
4568 overlap = (same_at_start - BEGV_BYTE 4597 overlap = (same_at_start - BEGV_BYTE
4569 - (same_at_end - ZV_BYTE 4598 - (same_at_end - ZV_BYTE
4570 + (end_offset < TYPE_MAXIMUM (off_t) 4599 + endpos));
4571 ? end_offset : file_size_hint)));
4572 if (overlap > 0) 4600 if (overlap > 0)
4573 same_at_end += overlap; 4601 same_at_end += overlap;
4574 same_at_end_charpos = BYTE_TO_CHAR (same_at_end); 4602 same_at_end_charpos = BYTE_TO_CHAR (same_at_end);
4575 4603
4576 /* Arrange to read only the nonmatching middle part of the file. */ 4604 /* Arrange to read only the nonmatching middle part of the file. */
4577 beg_offset += same_at_start - BEGV_BYTE; 4605 beg_offset += same_at_start - BEGV_BYTE;
4578 end_offset -= ZV_BYTE - same_at_end; 4606 end_offset = endpos - (ZV_BYTE - same_at_end);
4579 4607
4580 if (!NILP (visit) && BEG == BEGV && Z == ZV) 4608 if (!NILP (visit) && BEG == BEGV && Z == ZV)
4581 /* This binding is to avoid ask-user-about-supersession-threat 4609 /* This binding is to avoid ask-user-about-supersession-threat