diff options
| author | Paul Eggert | 2023-02-13 12:32:11 -0800 |
|---|---|---|
| committer | Paul Eggert | 2023-02-13 12:32:59 -0800 |
| commit | b950b46f514989442fdd9937a0e96d53a3affa88 (patch) | |
| tree | cf02f481ec03906bdc17caa5baea265eeee28280 /src | |
| parent | bae5fa5d9a8ef8c41fbb3408eea441a2ee14d1db (diff) | |
| download | emacs-b950b46f514989442fdd9937a0e96d53a3affa88.tar.gz emacs-b950b46f514989442fdd9937a0e96d53a3affa88.zip | |
Fix insert-file-contents on /proc files
This should fix Bug#9800 (2011-10-19).
* src/fileio.c (Finsert_file_contents):
Do not trust st_size even on regular files, as the file might
be a Linux /proc file, or it might be growing.
Instead, always read to EOF when END is nil.
Diffstat (limited to 'src')
| -rw-r--r-- | src/fileio.c | 57 |
1 files changed, 25 insertions, 32 deletions
diff --git a/src/fileio.c b/src/fileio.c index ee30db8b49b..b80f8d61de4 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -3907,7 +3907,6 @@ by calling `format-decode', which see. */) | |||
| 3907 | struct timespec mtime; | 3907 | struct timespec mtime; |
| 3908 | int fd; | 3908 | int fd; |
| 3909 | ptrdiff_t inserted = 0; | 3909 | ptrdiff_t inserted = 0; |
| 3910 | ptrdiff_t how_much; | ||
| 3911 | int unprocessed; | 3910 | int unprocessed; |
| 3912 | specpdl_ref count = SPECPDL_INDEX (); | 3911 | specpdl_ref count = SPECPDL_INDEX (); |
| 3913 | Lisp_Object handler, val, insval, orig_filename, old_undo; | 3912 | Lisp_Object handler, val, insval, orig_filename, old_undo; |
| @@ -3920,7 +3919,8 @@ by calling `format-decode', which see. */) | |||
| 3920 | bool replace_handled = false; | 3919 | bool replace_handled = false; |
| 3921 | bool set_coding_system = false; | 3920 | bool set_coding_system = false; |
| 3922 | Lisp_Object coding_system; | 3921 | Lisp_Object coding_system; |
| 3923 | bool read_quit = false; | 3922 | /* Negative if read error, 0 if OK so far, positive if quit. */ |
| 3923 | ptrdiff_t read_quit = 0; | ||
| 3924 | /* If the undo log only contains the insertion, there's no point | 3924 | /* If the undo log only contains the insertion, there's no point |
| 3925 | keeping it. It's typically when we first fill a file-buffer. */ | 3925 | keeping it. It's typically when we first fill a file-buffer. */ |
| 3926 | bool empty_undo_list_p | 3926 | bool empty_undo_list_p |
| @@ -4404,7 +4404,7 @@ by calling `format-decode', which see. */) | |||
| 4404 | ptrdiff_t bufpos; | 4404 | ptrdiff_t bufpos; |
| 4405 | unsigned char *decoded; | 4405 | unsigned char *decoded; |
| 4406 | ptrdiff_t temp; | 4406 | ptrdiff_t temp; |
| 4407 | ptrdiff_t this = 0; | 4407 | ptrdiff_t this; |
| 4408 | specpdl_ref this_count = SPECPDL_INDEX (); | 4408 | specpdl_ref this_count = SPECPDL_INDEX (); |
| 4409 | bool multibyte | 4409 | bool multibyte |
| 4410 | = ! NILP (BVAR (current_buffer, enable_multibyte_characters)); | 4410 | = ! NILP (BVAR (current_buffer, enable_multibyte_characters)); |
| @@ -4580,8 +4580,12 @@ by calling `format-decode', which see. */) | |||
| 4580 | } | 4580 | } |
| 4581 | 4581 | ||
| 4582 | move_gap_both (PT, PT_BYTE); | 4582 | move_gap_both (PT, PT_BYTE); |
| 4583 | if (GAP_SIZE < total) | 4583 | |
| 4584 | make_gap (total - GAP_SIZE); | 4584 | /* Ensure the gap is at least one byte larger than needed for the |
| 4585 | estimated file size, so that in the usual case we read to EOF | ||
| 4586 | without reallocating. */ | ||
| 4587 | if (GAP_SIZE <= total) | ||
| 4588 | make_gap (total - GAP_SIZE + 1); | ||
| 4585 | 4589 | ||
| 4586 | if (beg_offset != 0 || !NILP (replace)) | 4590 | if (beg_offset != 0 || !NILP (replace)) |
| 4587 | { | 4591 | { |
| @@ -4589,12 +4593,6 @@ by calling `format-decode', which see. */) | |||
| 4589 | report_file_error ("Setting file position", orig_filename); | 4593 | report_file_error ("Setting file position", orig_filename); |
| 4590 | } | 4594 | } |
| 4591 | 4595 | ||
| 4592 | /* In the following loop, HOW_MUCH contains the total bytes read so | ||
| 4593 | far for a regular file, and not changed for a special file. But, | ||
| 4594 | before exiting the loop, it is set to a negative value if I/O | ||
| 4595 | error occurs. */ | ||
| 4596 | how_much = 0; | ||
| 4597 | |||
| 4598 | /* Total bytes inserted. */ | 4596 | /* Total bytes inserted. */ |
| 4599 | inserted = 0; | 4597 | inserted = 0; |
| 4600 | 4598 | ||
| @@ -4603,23 +4601,26 @@ by calling `format-decode', which see. */) | |||
| 4603 | { | 4601 | { |
| 4604 | ptrdiff_t gap_size = GAP_SIZE; | 4602 | ptrdiff_t gap_size = GAP_SIZE; |
| 4605 | 4603 | ||
| 4606 | while (how_much < total) | 4604 | while (NILP (end) || inserted < total) |
| 4607 | { | 4605 | { |
| 4608 | /* `try' is reserved in some compilers (Microsoft C). */ | ||
| 4609 | ptrdiff_t trytry = min (total - how_much, READ_BUF_SIZE); | ||
| 4610 | ptrdiff_t this; | 4606 | ptrdiff_t this; |
| 4611 | 4607 | ||
| 4608 | if (gap_size == 0) | ||
| 4609 | { | ||
| 4610 | /* The size estimate was wrong. Make the gap 50% larger. */ | ||
| 4611 | make_gap (GAP_SIZE >> 1); | ||
| 4612 | gap_size = GAP_SIZE - inserted; | ||
| 4613 | } | ||
| 4614 | |||
| 4615 | /* 'try' is reserved in some compilers (Microsoft C). */ | ||
| 4616 | ptrdiff_t trytry = min (gap_size, READ_BUF_SIZE); | ||
| 4617 | if (!NILP (end)) | ||
| 4618 | trytry = min (trytry, total - inserted); | ||
| 4619 | |||
| 4612 | if (!seekable && NILP (end)) | 4620 | if (!seekable && NILP (end)) |
| 4613 | { | 4621 | { |
| 4614 | Lisp_Object nbytes; | 4622 | Lisp_Object nbytes; |
| 4615 | 4623 | ||
| 4616 | /* Maybe make more room. */ | ||
| 4617 | if (gap_size < trytry) | ||
| 4618 | { | ||
| 4619 | make_gap (trytry - gap_size); | ||
| 4620 | gap_size = GAP_SIZE - inserted; | ||
| 4621 | } | ||
| 4622 | |||
| 4623 | /* Read from the file, capturing `quit'. When an | 4624 | /* Read from the file, capturing `quit'. When an |
| 4624 | error occurs, end the loop, and arrange for a quit | 4625 | error occurs, end the loop, and arrange for a quit |
| 4625 | to be signaled after decoding the text we read. */ | 4626 | to be signaled after decoding the text we read. */ |
| @@ -4630,7 +4631,7 @@ by calling `format-decode', which see. */) | |||
| 4630 | 4631 | ||
| 4631 | if (NILP (nbytes)) | 4632 | if (NILP (nbytes)) |
| 4632 | { | 4633 | { |
| 4633 | read_quit = true; | 4634 | read_quit = 1; |
| 4634 | break; | 4635 | break; |
| 4635 | } | 4636 | } |
| 4636 | 4637 | ||
| @@ -4649,19 +4650,11 @@ by calling `format-decode', which see. */) | |||
| 4649 | 4650 | ||
| 4650 | if (this <= 0) | 4651 | if (this <= 0) |
| 4651 | { | 4652 | { |
| 4652 | how_much = this; | 4653 | read_quit = this; |
| 4653 | break; | 4654 | break; |
| 4654 | } | 4655 | } |
| 4655 | 4656 | ||
| 4656 | gap_size -= this; | 4657 | gap_size -= this; |
| 4657 | |||
| 4658 | /* For a regular file, where TOTAL is the real size, | ||
| 4659 | count HOW_MUCH to compare with it. | ||
| 4660 | For a special file, where TOTAL is just a buffer size, | ||
| 4661 | so don't bother counting in HOW_MUCH. | ||
| 4662 | (INSERTED is where we count the number of characters inserted.) */ | ||
| 4663 | if (seekable || !NILP (end)) | ||
| 4664 | how_much += this; | ||
| 4665 | inserted += this; | 4658 | inserted += this; |
| 4666 | } | 4659 | } |
| 4667 | } | 4660 | } |
| @@ -4682,7 +4675,7 @@ by calling `format-decode', which see. */) | |||
| 4682 | emacs_close (fd); | 4675 | emacs_close (fd); |
| 4683 | clear_unwind_protect (fd_index); | 4676 | clear_unwind_protect (fd_index); |
| 4684 | 4677 | ||
| 4685 | if (how_much < 0) | 4678 | if (read_quit < 0) |
| 4686 | report_file_error ("Read error", orig_filename); | 4679 | report_file_error ("Read error", orig_filename); |
| 4687 | 4680 | ||
| 4688 | notfound: | 4681 | notfound: |