aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2013-01-19 01:59:51 -0800
committerPaul Eggert2013-01-19 01:59:51 -0800
commitb3fbb3956cda29770670ac02d04804cee0c74f86 (patch)
treee9031a92a7f186ee6c7db5bdab9864697d9e25e1 /src
parent73c1421878b3ce4ac6fdb2b0133fda7522578a29 (diff)
downloademacs-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/ChangeLog9
-rw-r--r--src/fileio.c59
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 @@
12013-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
12013-01-19 Chong Yidong <cyd@gnu.org> 102013-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. */
3448static off_t 3448static off_t
3449emacs_lseek (int fd, EMACS_INT offset, int whence) 3449file_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
4714instead of any buffer contents; END is ignored. 4712instead of any buffer contents; END is ignored.
4715 4713
4716Optional fourth argument APPEND if non-nil means 4714Optional 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.
4719Optional fifth argument VISIT, if t or a string, means 4717Optional 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