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.
This commit is contained in:
Paul Eggert 2013-01-19 01:59:51 -08:00
parent 73c1421878
commit b3fbb3956c
4 changed files with 47 additions and 37 deletions

View file

@ -1,3 +1,9 @@
2013-01-19 Paul Eggert <eggert@cs.ucla.edu>
Allow floating-point file offsets.
* files.texi (Reading from Files, Writing to Files):
Say that file offsets can be numbers, not just integers.
2013-01-09 Glenn Morris <rgm@gnu.org>
* commands.texi (Interactive Codes):

View file

@ -533,9 +533,9 @@ is visiting the file @var{filename}: these include the buffer's visited
file name and its last save file modtime. This feature is used by
@code{find-file-noselect} and you probably should not use it yourself.
If @var{beg} and @var{end} are non-@code{nil}, they should be integers
specifying the portion of the file to insert. In this case, @var{visit}
must be @code{nil}. For example,
If @var{beg} and @var{end} are non-@code{nil}, they should be numbers
that are byte offsets specifying the portion of the file to insert.
In this case, @var{visit} must be @code{nil}. For example,
@example
(insert-file-contents filename nil 0 500)
@ -605,8 +605,8 @@ that string, rather than text from the buffer. @var{end} is ignored in
this case.
If @var{append} is non-@code{nil}, then the specified text is appended
to the existing file contents (if any). If @var{append} is an
integer, @code{write-region} seeks to that byte offset from the start
to the existing file contents (if any). If @var{append} is a
number, @code{write-region} seeks to that byte offset from the start
of the file and writes the data from there.
If @var{mustbenew} is non-@code{nil}, then @code{write-region} asks

View file

@ -1,3 +1,12 @@
2013-01-19 Paul Eggert <eggert@cs.ucla.edu>
Allow floating-point file offsets.
Problem reported by Vitalie Spinu in
<http://lists.gnu.org/archive/html/emacs-devel/2013-01/msg00411.html>.
* fileio.c (emacs_lseek): Remove.
(file_offset): New function.
(Finsert_file_contents, Fwrite_region): Use it.
2013-01-19 Chong Yidong <cyd@gnu.org>
* emacs.c (Fkill_emacs): Set waiting_for_input to 0 to avoid

View file

@ -3443,19 +3443,25 @@ read_contents_quit (Lisp_Object ignore)
return Qnil;
}
/* Reposition FD to OFFSET, based on WHENCE. This acts like lseek
except that it also tests for OFFSET being out of lseek's range. */
/* Return the file offset that VAL represents, checking for type
errors and overflow. */
static off_t
emacs_lseek (int fd, EMACS_INT offset, int whence)
file_offset (Lisp_Object val)
{
/* Use "&" rather than "&&" to suppress a bogus GCC warning; see
<http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43772>. */
if (! ((offset >= TYPE_MINIMUM (off_t)) & (offset <= TYPE_MAXIMUM (off_t))))
if (RANGED_INTEGERP (0, val, TYPE_MAXIMUM (off_t)))
return XINT (val);
if (FLOATP (val))
{
errno = EINVAL;
return -1;
double v = XFLOAT_DATA (val);
if (0 <= v
&& (sizeof (off_t) < sizeof v
? v <= TYPE_MAXIMUM (off_t)
: v < TYPE_MAXIMUM (off_t)))
return v;
}
return lseek (fd, offset, whence);
wrong_type_argument (intern ("file-offset"), val);
}
/* Return a special time value indicating the error number ERRNUM. */
@ -3606,20 +3612,12 @@ by calling `format-decode', which see. */)
}
if (!NILP (beg))
{
if (! RANGED_INTEGERP (0, beg, TYPE_MAXIMUM (off_t)))
wrong_type_argument (intern ("file-offset"), beg);
beg_offset = XFASTINT (beg);
}
beg_offset = file_offset (beg);
else
beg_offset = 0;
if (!NILP (end))
{
if (! RANGED_INTEGERP (0, end, TYPE_MAXIMUM (off_t)))
wrong_type_argument (intern ("file-offset"), end);
end_offset = XFASTINT (end);
}
end_offset = file_offset (end);
else
{
if (not_regular)
@ -4714,7 +4712,7 @@ If START is a string, then output that string to the file
instead of any buffer contents; END is ignored.
Optional fourth argument APPEND if non-nil means
append to existing file contents (if any). If it is an integer,
append to existing file contents (if any). If it is a number,
seek to that offset in the file before writing.
Optional fifth argument VISIT, if t or a string, means
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
(Lisp_Object start, Lisp_Object end, Lisp_Object filename, Lisp_Object append, Lisp_Object visit, Lisp_Object lockname, Lisp_Object mustbenew)
{
int desc;
off_t offset;
bool ok;
int save_errno = 0;
const char *fn;
@ -4864,13 +4863,14 @@ This calls `write-region-annotate-functions' at the start, and
encoded_filename = ENCODE_FILE (filename);
fn = SSDATA (encoded_filename);
offset = 0;
desc = -1;
if (!NILP (append))
#ifdef DOS_NT
desc = emacs_open (fn, O_WRONLY | O_BINARY, 0);
#else /* not DOS_NT */
desc = emacs_open (fn, O_WRONLY, 0);
#endif /* not DOS_NT */
{
if (NUMBERP (append))
offset = file_offset (append);
desc = emacs_open (fn, O_WRONLY | O_BINARY, 0);
}
if (desc < 0 && (NILP (append) || errno == ENOENT))
#ifdef DOS_NT
@ -4897,14 +4897,9 @@ This calls `write-region-annotate-functions' at the start, and
record_unwind_protect (close_file_unwind, make_number (desc));
if (!NILP (append) && !NILP (Ffile_regular_p (filename)))
if (!NILP (append))
{
off_t ret;
if (NUMBERP (append))
ret = emacs_lseek (desc, XINT (append), SEEK_CUR);
else
ret = lseek (desc, 0, SEEK_END);
off_t ret = lseek (desc, offset, NUMBERP (append) ? SEEK_SET : SEEK_END);
if (ret < 0)
{
#ifdef CLASH_DETECTION