diff options
| author | Paul Eggert | 2013-01-19 01:59:51 -0800 |
|---|---|---|
| committer | Paul Eggert | 2013-01-19 01:59:51 -0800 |
| commit | b3fbb3956cda29770670ac02d04804cee0c74f86 (patch) | |
| tree | e9031a92a7f186ee6c7db5bdab9864697d9e25e1 /src | |
| parent | 73c1421878b3ce4ac6fdb2b0133fda7522578a29 (diff) | |
| download | emacs-b3fbb3956cda29770670ac02d04804cee0c74f86.tar.gz emacs-b3fbb3956cda29770670ac02d04804cee0c74f86.zip | |
Allow floating-point file offsets.
Problem reported by Vitalie Spinu in
<http://lists.gnu.org/archive/html/emacs-devel/2013-01/msg00411.html>.
* doc/lispref/files.texi (Reading from Files, Writing to Files):
Say that file offsets can be numbers, not just integers.
* src/fileio.c (emacs_lseek): Remove.
(file_offset): New function.
(Finsert_file_contents, Fwrite_region): Use it.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 9 | ||||
| -rw-r--r-- | src/fileio.c | 59 |
2 files changed, 36 insertions, 32 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 4bee4fc5ed7..c6bd70e2a04 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,12 @@ | |||
| 1 | 2013-01-19 Paul Eggert <eggert@cs.ucla.edu> | ||
| 2 | |||
| 3 | Allow floating-point file offsets. | ||
| 4 | Problem reported by Vitalie Spinu in | ||
| 5 | <http://lists.gnu.org/archive/html/emacs-devel/2013-01/msg00411.html>. | ||
| 6 | * fileio.c (emacs_lseek): Remove. | ||
| 7 | (file_offset): New function. | ||
| 8 | (Finsert_file_contents, Fwrite_region): Use it. | ||
| 9 | |||
| 1 | 2013-01-19 Chong Yidong <cyd@gnu.org> | 10 | 2013-01-19 Chong Yidong <cyd@gnu.org> |
| 2 | 11 | ||
| 3 | * emacs.c (Fkill_emacs): Set waiting_for_input to 0 to avoid | 12 | * emacs.c (Fkill_emacs): Set waiting_for_input to 0 to avoid |
diff --git a/src/fileio.c b/src/fileio.c index 616f1c50f91..ab37bf2bd8f 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -3443,19 +3443,25 @@ read_contents_quit (Lisp_Object ignore) | |||
| 3443 | return Qnil; | 3443 | return Qnil; |
| 3444 | } | 3444 | } |
| 3445 | 3445 | ||
| 3446 | /* Reposition FD to OFFSET, based on WHENCE. This acts like lseek | 3446 | /* Return the file offset that VAL represents, checking for type |
| 3447 | except that it also tests for OFFSET being out of lseek's range. */ | 3447 | errors and overflow. */ |
| 3448 | static off_t | 3448 | static off_t |
| 3449 | emacs_lseek (int fd, EMACS_INT offset, int whence) | 3449 | file_offset (Lisp_Object val) |
| 3450 | { | 3450 | { |
| 3451 | /* Use "&" rather than "&&" to suppress a bogus GCC warning; see | 3451 | if (RANGED_INTEGERP (0, val, TYPE_MAXIMUM (off_t))) |
| 3452 | <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43772>. */ | 3452 | return XINT (val); |
| 3453 | if (! ((offset >= TYPE_MINIMUM (off_t)) & (offset <= TYPE_MAXIMUM (off_t)))) | 3453 | |
| 3454 | if (FLOATP (val)) | ||
| 3454 | { | 3455 | { |
| 3455 | errno = EINVAL; | 3456 | double v = XFLOAT_DATA (val); |
| 3456 | return -1; | 3457 | if (0 <= v |
| 3458 | && (sizeof (off_t) < sizeof v | ||
| 3459 | ? v <= TYPE_MAXIMUM (off_t) | ||
| 3460 | : v < TYPE_MAXIMUM (off_t))) | ||
| 3461 | return v; | ||
| 3457 | } | 3462 | } |
| 3458 | return lseek (fd, offset, whence); | 3463 | |
| 3464 | wrong_type_argument (intern ("file-offset"), val); | ||
| 3459 | } | 3465 | } |
| 3460 | 3466 | ||
| 3461 | /* Return a special time value indicating the error number ERRNUM. */ | 3467 | /* Return a special time value indicating the error number ERRNUM. */ |
| @@ -3606,20 +3612,12 @@ by calling `format-decode', which see. */) | |||
| 3606 | } | 3612 | } |
| 3607 | 3613 | ||
| 3608 | if (!NILP (beg)) | 3614 | if (!NILP (beg)) |
| 3609 | { | 3615 | beg_offset = file_offset (beg); |
| 3610 | if (! RANGED_INTEGERP (0, beg, TYPE_MAXIMUM (off_t))) | ||
| 3611 | wrong_type_argument (intern ("file-offset"), beg); | ||
| 3612 | beg_offset = XFASTINT (beg); | ||
| 3613 | } | ||
| 3614 | else | 3616 | else |
| 3615 | beg_offset = 0; | 3617 | beg_offset = 0; |
| 3616 | 3618 | ||
| 3617 | if (!NILP (end)) | 3619 | if (!NILP (end)) |
| 3618 | { | 3620 | end_offset = file_offset (end); |
| 3619 | if (! RANGED_INTEGERP (0, end, TYPE_MAXIMUM (off_t))) | ||
| 3620 | wrong_type_argument (intern ("file-offset"), end); | ||
| 3621 | end_offset = XFASTINT (end); | ||
| 3622 | } | ||
| 3623 | else | 3621 | else |
| 3624 | { | 3622 | { |
| 3625 | if (not_regular) | 3623 | if (not_regular) |
| @@ -4714,7 +4712,7 @@ If START is a string, then output that string to the file | |||
| 4714 | instead of any buffer contents; END is ignored. | 4712 | instead of any buffer contents; END is ignored. |
| 4715 | 4713 | ||
| 4716 | Optional fourth argument APPEND if non-nil means | 4714 | Optional fourth argument APPEND if non-nil means |
| 4717 | append to existing file contents (if any). If it is an integer, | 4715 | append to existing file contents (if any). If it is a number, |
| 4718 | seek to that offset in the file before writing. | 4716 | seek to that offset in the file before writing. |
| 4719 | Optional fifth argument VISIT, if t or a string, means | 4717 | Optional fifth argument VISIT, if t or a string, means |
| 4720 | set the last-save-file-modtime of buffer to this file's modtime | 4718 | set the last-save-file-modtime of buffer to this file's modtime |
| @@ -4743,6 +4741,7 @@ This calls `write-region-annotate-functions' at the start, and | |||
| 4743 | (Lisp_Object start, Lisp_Object end, Lisp_Object filename, Lisp_Object append, Lisp_Object visit, Lisp_Object lockname, Lisp_Object mustbenew) | 4741 | (Lisp_Object start, Lisp_Object end, Lisp_Object filename, Lisp_Object append, Lisp_Object visit, Lisp_Object lockname, Lisp_Object mustbenew) |
| 4744 | { | 4742 | { |
| 4745 | int desc; | 4743 | int desc; |
| 4744 | off_t offset; | ||
| 4746 | bool ok; | 4745 | bool ok; |
| 4747 | int save_errno = 0; | 4746 | int save_errno = 0; |
| 4748 | const char *fn; | 4747 | const char *fn; |
| @@ -4864,13 +4863,14 @@ This calls `write-region-annotate-functions' at the start, and | |||
| 4864 | encoded_filename = ENCODE_FILE (filename); | 4863 | encoded_filename = ENCODE_FILE (filename); |
| 4865 | 4864 | ||
| 4866 | fn = SSDATA (encoded_filename); | 4865 | fn = SSDATA (encoded_filename); |
| 4866 | offset = 0; | ||
| 4867 | desc = -1; | 4867 | desc = -1; |
| 4868 | if (!NILP (append)) | 4868 | if (!NILP (append)) |
| 4869 | #ifdef DOS_NT | 4869 | { |
| 4870 | desc = emacs_open (fn, O_WRONLY | O_BINARY, 0); | 4870 | if (NUMBERP (append)) |
| 4871 | #else /* not DOS_NT */ | 4871 | offset = file_offset (append); |
| 4872 | desc = emacs_open (fn, O_WRONLY, 0); | 4872 | desc = emacs_open (fn, O_WRONLY | O_BINARY, 0); |
| 4873 | #endif /* not DOS_NT */ | 4873 | } |
| 4874 | 4874 | ||
| 4875 | if (desc < 0 && (NILP (append) || errno == ENOENT)) | 4875 | if (desc < 0 && (NILP (append) || errno == ENOENT)) |
| 4876 | #ifdef DOS_NT | 4876 | #ifdef DOS_NT |
| @@ -4897,14 +4897,9 @@ This calls `write-region-annotate-functions' at the start, and | |||
| 4897 | 4897 | ||
| 4898 | record_unwind_protect (close_file_unwind, make_number (desc)); | 4898 | record_unwind_protect (close_file_unwind, make_number (desc)); |
| 4899 | 4899 | ||
| 4900 | if (!NILP (append) && !NILP (Ffile_regular_p (filename))) | 4900 | if (!NILP (append)) |
| 4901 | { | 4901 | { |
| 4902 | off_t ret; | 4902 | off_t ret = lseek (desc, offset, NUMBERP (append) ? SEEK_SET : SEEK_END); |
| 4903 | |||
| 4904 | if (NUMBERP (append)) | ||
| 4905 | ret = emacs_lseek (desc, XINT (append), SEEK_CUR); | ||
| 4906 | else | ||
| 4907 | ret = lseek (desc, 0, SEEK_END); | ||
| 4908 | if (ret < 0) | 4903 | if (ret < 0) |
| 4909 | { | 4904 | { |
| 4910 | #ifdef CLASH_DETECTION | 4905 | #ifdef CLASH_DETECTION |