emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master cb4579ed6b: Allow inserting parts of /dev/urandom with insert-fil


From: Lars Ingebrigtsen
Subject: master cb4579ed6b: Allow inserting parts of /dev/urandom with insert-file-contents
Date: Sat, 11 Jun 2022 08:40:50 -0400 (EDT)

branch: master
commit cb4579ed6ba45c81ee7ec627bf197e1def121f24
Author: Lars Ingebrigtsen <larsi@gnus.org>
Commit: Lars Ingebrigtsen <larsi@gnus.org>

    Allow inserting parts of /dev/urandom with insert-file-contents
    
    * doc/lispref/files.texi (Reading from Files): Document it.
    * src/fileio.c (Finsert_file_contents): Allow specifying END for
    special files (bug#18370).
---
 doc/lispref/files.texi   |  9 ++++++---
 src/fileio.c             | 31 +++++++++++++++++++++----------
 test/src/fileio-tests.el |  7 +++++++
 3 files changed, 34 insertions(+), 13 deletions(-)

diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi
index d473261026..ea8683a6d8 100644
--- a/doc/lispref/files.texi
+++ b/doc/lispref/files.texi
@@ -581,9 +581,12 @@ contents of the file.  This is better than simply deleting 
the buffer
 contents and inserting the whole file, because (1) it preserves some
 marker positions and (2) it puts less data in the undo list.
 
-It is possible to read a special file (such as a FIFO or an I/O device)
-with @code{insert-file-contents}, as long as @var{replace} and
-@var{visit} are @code{nil}.
+It is possible to read a special file (such as a FIFO or an I/O
+device) with @code{insert-file-contents}, as long as @var{replace},
+and @var{visit} and @var{beg} are @code{nil}.  However, you should
+normally use an @var{end} argument for these files to avoid inserting
+(potentially) unlimited data into the buffer (for instance, when
+inserting data from @file{/dev/urandom}).
 @end defun
 
 @defun insert-file-contents-literally filename &optional visit beg end replace
diff --git a/src/fileio.c b/src/fileio.c
index 094516bfef..94cbc14371 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -3898,6 +3898,10 @@ The optional third and fourth arguments BEG and END 
specify what portion
 of the file to insert.  These arguments count bytes in the file, not
 characters in the buffer.  If VISIT is non-nil, BEG and END must be nil.
 
+When inserting data from a special file (e.g., /dev/urandom), you
+can't specify VISIT or BEG, and END should be specified to avoid
+inserting unlimited data into the buffer.
+
 If optional fifth argument REPLACE is non-nil, replace the current
 buffer contents (in the accessible portion) with the file contents.
 This is better than simply deleting and inserting the whole thing
@@ -3925,7 +3929,7 @@ by calling `format-decode', which see.  */)
   Lisp_Object handler, val, insval, orig_filename, old_undo;
   Lisp_Object p;
   ptrdiff_t total = 0;
-  bool not_regular = 0;
+  bool regular = true;
   int save_errno = 0;
   char read_buf[READ_BUF_SIZE];
   struct coding_system coding;
@@ -3948,6 +3952,7 @@ by calling `format-decode', which see.  */)
   /* SAME_AT_END_CHARPOS counts characters, because
      restore_window_points needs the old character count.  */
   ptrdiff_t same_at_end_charpos = ZV;
+  bool seekable = true;
 
   if (current_buffer->base_buffer && ! NILP (visit))
     error ("Cannot do file visiting in an indirect buffer");
@@ -4021,7 +4026,8 @@ by calling `format-decode', which see.  */)
      least signal an error.  */
   if (!S_ISREG (st.st_mode))
     {
-      not_regular = 1;
+      regular = false;
+      seekable = lseek (fd, 0, SEEK_CUR) < 0;
 
       if (! NILP (visit))
         {
@@ -4029,7 +4035,12 @@ by calling `format-decode', which see.  */)
          goto notfound;
         }
 
-      if (! NILP (replace) || ! NILP (beg) || ! NILP (end))
+      if (!NILP (beg) && !seekable)
+       xsignal2 (Qfile_error,
+                 build_string ("trying to use a start positing in a 
non-seekable file"),
+                 orig_filename);
+
+      if (!NILP (replace))
        xsignal2 (Qfile_error,
                  build_string ("not a regular file"), orig_filename);
     }
@@ -4051,7 +4062,7 @@ by calling `format-decode', which see.  */)
     end_offset = file_offset (end);
   else
     {
-      if (not_regular)
+      if (!regular)
        end_offset = TYPE_MAXIMUM (off_t);
       else
        {
@@ -4073,7 +4084,7 @@ by calling `format-decode', which see.  */)
   /* 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)
+  if (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.  */
@@ -4111,7 +4122,7 @@ by calling `format-decode', which see.  */)
        {
          /* Don't try looking inside a file for a coding system
             specification if it is not seekable.  */
-         if (! not_regular && ! NILP (Vset_auto_coding_function))
+         if (regular && !NILP (Vset_auto_coding_function))
            {
              /* Find a coding system specified in the heading two
                 lines or in the tailing several lines of the file.
@@ -4573,7 +4584,7 @@ by calling `format-decode', which see.  */)
       goto handled;
     }
 
-  if (! not_regular)
+  if (seekable || !NILP (end))
     total = end_offset - beg_offset;
   else
     /* For a special file, all we can do is guess.  */
@@ -4619,7 +4630,7 @@ by calling `format-decode', which see.  */)
        ptrdiff_t trytry = min (total - how_much, READ_BUF_SIZE);
        ptrdiff_t this;
 
-       if (not_regular)
+       if (!seekable && NILP (end))
          {
            Lisp_Object nbytes;
 
@@ -4670,7 +4681,7 @@ by calling `format-decode', which see.  */)
           For a special file, where TOTAL is just a buffer size,
           so don't bother counting in HOW_MUCH.
           (INSERTED is where we count the number of characters inserted.)  */
-       if (! not_regular)
+       if (seekable || !NILP (end))
          how_much += this;
        inserted += this;
       }
@@ -4848,7 +4859,7 @@ by calling `format-decode', which see.  */)
            Funlock_file (BVAR (current_buffer, file_truename));
          Funlock_file (filename);
        }
-      if (not_regular)
+      if (!regular)
        xsignal2 (Qfile_error,
                  build_string ("not a regular file"), orig_filename);
     }
diff --git a/test/src/fileio-tests.el b/test/src/fileio-tests.el
index 511490c574..a9a43781d4 100644
--- a/test/src/fileio-tests.el
+++ b/test/src/fileio-tests.el
@@ -193,4 +193,11 @@ Also check that an encoding error can appear in a symlink."
   (should (equal (file-name-concat "" "bar") "bar"))
   (should (equal (file-name-concat "" "") "")))
 
+(defun test-non-regular-insert ()
+  (skip-unless (file-exists-p "/dev/urandom"))
+  (with-temp-buffer
+    (should-error (insert-file-contents "/dev/urandom" nil 5 10))
+    (insert-file-contents "/dev/urandom" nil nil 10)
+    (should (= (point-max) 10))))
+
 ;;; fileio-tests.el ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]