#ifdef DOS_NT
/* On Windows, drive letters must be alphabetic - on DOS, the Netware
- redirector allows the six letters between 'Z' and 'a' as well. */
+ redirector allows the six letters between 'Z' and 'a' as well. */
#ifdef MSDOS
#define IS_DRIVE(x) ((x) >= 'A' && (x) <= 'z')
#endif
#define IS_DRIVE(x) isalpha ((unsigned char) (x))
#endif
/* Need to lower-case the drive letter, or else expanded
- filenames will sometimes compare inequal, because
+ filenames will sometimes compare unequal, because
`expand-file-name' doesn't always down-case the drive letter. */
#define DRIVE_LETTER(x) (tolower ((unsigned char) (x)))
#endif
while (p != beg && !IS_DIRECTORY_SEP (p[-1])
#ifdef DOS_NT
- /* only recognise drive specifier at the beginning */
+ /* only recognize drive specifier at the beginning */
&& !(p[-1] == ':'
/* handle the "/:d:foo" and "/:foo" cases correctly */
&& ((p == beg + 2 && !IS_DIRECTORY_SEP (*beg))
while (p != beg && !IS_DIRECTORY_SEP (p[-1])
#ifdef DOS_NT
- /* only recognise drive specifier at beginning */
+ /* only recognize drive specifier at beginning */
&& !(p[-1] == ':'
/* handle the "/:d:foo" case correctly */
&& (p == beg + 2 || (p == beg + 4 && IS_DIRECTORY_SEP (*beg))))
if ((0
|| IS_DIRECTORY_SEP (p[-1]))
&& file_name_absolute_p (p)
-#if defined (WINDOWSNT) || defined(CYGWIN)
+#if defined (WINDOWSNT) || defined (CYGWIN)
/* // at start of file name is meaningful in Apollo,
WindowsNT and Cygwin systems. */
&& !(IS_DIRECTORY_SEP (p[0]) && p - 1 == nm)
if (p)
/* Start over with the new string, so we check the file-name-handler
again. Important with filenames like "/home/foo//:/hello///there"
- which whould substitute to "/:/hello///there" rather than "/there". */
+ which would substitute to "/:/hello///there" rather than "/there". */
return Fsubstitute_in_file_name
(make_specified_string (p, -1, endp - p, multibyte));
absname = ENCODE_FILE (absname);
-#if defined(DOS_NT) || defined(macintosh)
+#if defined (DOS_NT) || defined (macintosh)
/* Under MS-DOS, Windows, and Macintosh, open does not work for
directories. */
if (access (SDATA (absname), 0) == 0)
}
#endif
- return Flist (sizeof(values) / sizeof(values[0]), values);
+ return Flist (sizeof (values) / sizeof (values[0]), values);
}
\f
DEFUN ("set-file-selinux-context", Fset_file_selinux_context,
context_free (parsed_con);
}
else
- report_file_error("Doing lgetfilecon", Fcons (absname, Qnil));
+ report_file_error ("Doing lgetfilecon", Fcons (absname, Qnil));
if (con)
freecon (con);
EMACS_INT inserted = 0;
int nochange = 0;
register EMACS_INT how_much;
+ off_t beg_offset, end_offset;
register EMACS_INT unprocessed;
int count = SPECPDL_INDEX ();
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
Lisp_Object p;
EMACS_INT total = 0;
int not_regular = 0;
+ int save_errno = 0;
char read_buf[READ_BUF_SIZE];
struct coding_system coding;
char buffer[1 << 14];
#endif /* WINDOWSNT */
{
badopen:
+ save_errno = errno;
if (NILP (visit))
report_file_error ("Opening input file", Fcons (orig_filename, Qnil));
st.st_mtime = -1;
+ st.st_size = -1;
how_much = 0;
if (!NILP (Vcoding_system_for_read))
Fset (Qbuffer_file_coding_system, Vcoding_system_for_read);
record_unwind_protect (close_file_unwind, make_number (fd));
- /* Check whether the size is too large or negative, which can happen on a
- platform that allows file sizes greater than the maximum off_t value. */
- if (! not_regular
- && ! (0 <= st.st_size && st.st_size <= BUF_BYTES_MAX))
- buffer_overflow ();
-
- /* Prevent redisplay optimizations. */
- current_buffer->clip_changed = 1;
-
if (!NILP (visit))
{
if (!NILP (beg) || !NILP (end))
}
if (!NILP (beg))
- CHECK_NUMBER (beg);
+ {
+ if (! (RANGED_INTEGERP (0, beg, TYPE_MAXIMUM (off_t))))
+ wrong_type_argument (intern ("file-offset"), beg);
+ beg_offset = XFASTINT (beg);
+ }
else
- XSETFASTINT (beg, 0);
+ beg_offset = 0;
if (!NILP (end))
- CHECK_NUMBER (end);
+ {
+ if (! (RANGED_INTEGERP (0, end, TYPE_MAXIMUM (off_t))))
+ wrong_type_argument (intern ("file-offset"), end);
+ end_offset = XFASTINT (end);
+ }
else
{
- if (! not_regular)
+ if (not_regular)
+ end_offset = TYPE_MAXIMUM (off_t);
+ else
{
- XSETINT (end, st.st_size);
+ end_offset = st.st_size;
+
+ /* A negative size can happen on a platform that allows file
+ sizes greater than the maximum off_t value. */
+ if (end_offset < 0)
+ buffer_overflow ();
/* The file size returned from stat may be zero, but data
may be readable nonetheless, for example when this is a
file in the /proc filesystem. */
- if (st.st_size == 0)
- XSETINT (end, READ_BUF_SIZE);
+ if (end_offset == 0)
+ end_offset = READ_BUF_SIZE;
+ }
+ }
+
+ /* Check now whether the buffer will become too large,
+ in the likely case where the file's length is not changing.
+ This saves a lot of needless work before a buffer overflow. */
+ if (! not_regular)
+ {
+ /* The likely offset where we will stop reading. We could read
+ more (or less), if the file grows (or shrinks) as we read it. */
+ off_t likely_end = min (end_offset, st.st_size);
+
+ if (beg_offset < likely_end)
+ {
+ ptrdiff_t buf_bytes =
+ Z_BYTE - (!NILP (replace) ? ZV_BYTE - BEGV_BYTE : 0);
+ ptrdiff_t buf_growth_max = BUF_BYTES_MAX - buf_bytes;
+ off_t likely_growth = likely_end - beg_offset;
+ if (buf_growth_max < likely_growth)
+ buffer_overflow ();
}
}
+ /* Prevent redisplay optimizations. */
+ current_buffer->clip_changed = 1;
+
if (EQ (Vcoding_system_for_read, Qauto_save_coding))
{
coding_system = coding_inherit_eol_type (Qutf_8_emacs, Qunix);
give up on handling REPLACE in the optimized way. */
int giveup_match_end = 0;
- if (XINT (beg) != 0)
+ if (beg_offset != 0)
{
- if (emacs_lseek (fd, XINT (beg), SEEK_SET) < 0)
+ if (lseek (fd, beg_offset, SEEK_SET) < 0)
report_file_error ("Setting file position",
Fcons (orig_filename, Qnil));
}
immediate_quit = 0;
/* If the file matches the buffer completely,
there's no need to replace anything. */
- if (same_at_start - BEGV_BYTE == XINT (end))
+ if (same_at_start - BEGV_BYTE == end_offset - beg_offset)
{
emacs_close (fd);
specpdl_ptr--;
already found that decoding is necessary, don't waste time. */
while (!giveup_match_end)
{
- EMACS_INT total_read, nread, bufpos, curpos, trial;
+ int total_read, nread, bufpos, trial;
+ off_t curpos;
/* At what file position are we now scanning? */
- curpos = XINT (end) - (ZV_BYTE - same_at_end);
+ curpos = end_offset - (ZV_BYTE - same_at_end);
/* If the entire file matches the buffer tail, stop the scan. */
if (curpos == 0)
break;
/* How much can we scan in the next step? */
trial = min (curpos, sizeof buffer);
- if (emacs_lseek (fd, curpos - trial, SEEK_SET) < 0)
+ if (lseek (fd, curpos - trial, SEEK_SET) < 0)
report_file_error ("Setting file position",
Fcons (orig_filename, Qnil));
/* Don't try to reuse the same piece of text twice. */
overlap = (same_at_start - BEGV_BYTE
- - (same_at_end + st.st_size - ZV));
+ - (same_at_end
+ + (! NILP (end) ? end_offset : st.st_size) - ZV_BYTE));
if (overlap > 0)
same_at_end += overlap;
/* Arrange to read only the nonmatching middle part of the file. */
- XSETFASTINT (beg, XINT (beg) + (same_at_start - BEGV_BYTE));
- XSETFASTINT (end, XINT (end) - (ZV_BYTE - same_at_end));
+ beg_offset += same_at_start - BEGV_BYTE;
+ end_offset -= ZV_BYTE - same_at_end;
del_range_byte (same_at_start, same_at_end, 0);
/* Insert from the file at the proper position. */
int this_count = SPECPDL_INDEX ();
int multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters));
Lisp_Object conversion_buffer;
+ struct gcpro gcpro1;
conversion_buffer = code_conversion_save (1, multibyte);
/* First read the whole file, performing code conversion into
CONVERSION_BUFFER. */
- if (emacs_lseek (fd, XINT (beg), SEEK_SET) < 0)
+ if (lseek (fd, beg_offset, SEEK_SET) < 0)
report_file_error ("Setting file position",
Fcons (orig_filename, Qnil));
{
/* We read one bunch by one (READ_BUF_SIZE bytes) to allow
quitting while reading a huge while. */
- /* try is reserved in some compilers (Microsoft C) */
+ /* `try'' is reserved in some compilers (Microsoft C). */
EMACS_INT trytry = min (total - how_much,
READ_BUF_SIZE - unprocessed);
}
if (! not_regular)
- total = XINT (end) - XINT (beg);
+ total = end_offset - beg_offset;
else
/* For a special file, all we can do is guess. */
total = READ_BUF_SIZE;
if (GAP_SIZE < total)
make_gap (total - GAP_SIZE);
- if (XINT (beg) != 0 || !NILP (replace))
+ if (beg_offset != 0 || !NILP (replace))
{
- if (emacs_lseek (fd, XINT (beg), SEEK_SET) < 0)
+ if (lseek (fd, beg_offset, SEEK_SET) < 0)
report_file_error ("Setting file position",
Fcons (orig_filename, Qnil));
}
&& current_buffer->modtime == -1)
{
/* If visiting nonexistent file, return nil. */
+ errno = save_errno;
report_file_error ("Opening input file", Fcons (orig_filename, Qnil));
}
if (!NILP (append) && !NILP (Ffile_regular_p (filename)))
{
- long ret;
+ off_t ret;
if (NUMBERP (append))
ret = emacs_lseek (desc, XINT (append), SEEK_CUR);
if (ret < 0)
{
#ifdef CLASH_DETECTION
+ save_errno = errno;
if (!auto_saving) unlock_file (lockname);
+ errno = save_errno;
#endif /* CLASH_DETECTION */
UNGCPRO;
report_file_error ("Lseek error", Fcons (filename, Qnil));
DEFUN ("visited-file-modtime", Fvisited_file_modtime,
Svisited_file_modtime, 0, 0, 0,
doc: /* Return the current buffer's recorded visited file modification time.
-The value is a list of the form (HIGH LOW), like the time values
-that `file-attributes' returns. If the current buffer has no recorded
-file modification time, this function returns 0.
+The value is a list of the form (HIGH LOW), like the time values that
+`file-attributes' returns. If the current buffer has no recorded file
+modification time, this function returns 0. If the visited file
+doesn't exist, HIGH will be -1.
See Info node `(elisp)Modification Time' for more details. */)
(void)
{
EMACS_GET_TIME (before_time);
/* If we had a failure, don't try again for 20 minutes. */
- if (b->auto_save_failure_time >= 0
+ if (b->auto_save_failure_time > 0
&& EMACS_SECS (before_time) - b->auto_save_failure_time < 1200)
continue;
they're not autosaved. */
BUF_AUTOSAVE_MODIFF (current_buffer) = MODIFF;
XSETFASTINT (BVAR (current_buffer, save_length), Z - BEG);
- current_buffer->auto_save_failure_time = -1;
+ current_buffer->auto_save_failure_time = 0;
return Qnil;
}
doc: /* Clear any record of a recent auto-save failure in the current buffer. */)
(void)
{
- current_buffer->auto_save_failure_time = -1;
+ current_buffer->auto_save_failure_time = 0;
return Qnil;
}