changeset 30938:84f6f91ca02a v9.0.0803

patch 9.0.0803: readblob() cannot read from character device Commit: https://github.com/vim/vim/commit/43625762a9751cc6e6e4d8f54fbc8b82d98fb20d Author: K.Takata <kentkt@csc.jp> Date: Thu Oct 20 13:28:51 2022 +0100 patch 9.0.0803: readblob() cannot read from character device Problem: readblob() cannot read from character device. Solution: Use S_ISCHR() to not check the size. (Ken Takata, closes https://github.com/vim/vim/issues/11407)
author Bram Moolenaar <Bram@vim.org>
date Thu, 20 Oct 2022 14:30:13 +0200
parents d192688c8bab
children 0c6fe9b4ecd1
files runtime/doc/builtin.txt src/blob.c src/proto/blob.pro src/testdir/test_blob.vim src/version.c
diffstat 5 files changed, 20 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -6859,7 +6859,12 @@ readblob({fname} [, {offset} [, {size}]]
 			readblob('file.bin', 0, 100)
 <		If {size} is -1 or omitted, the whole data starting from
 		{offset} will be read.
-		When the file can't be opened an error message is given and
+		This can be also used to read the data from a character device
+		on Unix when {size} is explicitly set.  Only if the device
+		supports seeking {offset} can be used.  Otherwise it should be
+		zero.  E.g. to read 10 bytes from a serial console: >
+			readblob('/dev/ttyS0', 0, 10)
+<		When the file can't be opened an error message is given and
 		the result is an empty |Blob|.
 		When trying to read bytes beyond the end of the file the
 		result is an empty blob.
--- a/src/blob.c
+++ b/src/blob.c
@@ -212,9 +212,13 @@ read_blob(FILE *fd, typval_T *rettv, off
     }
     // Trying to read bytes that aren't there results in an empty blob, not an
     // error.
-    if (size < 0 || size > st.st_size)
+    if (size <= 0 || (
+#ifdef S_ISCHR
+		!S_ISCHR(st.st_mode) &&
+#endif
+		size > st.st_size))
 	return OK;
-    if (vim_fseek(fd, offset, whence) != 0)
+    if (offset != 0 && vim_fseek(fd, offset, whence) != 0)
 	return OK;
 
     if (ga_grow(&blob->bv_ga, (int)size) == FAIL)
--- a/src/proto/blob.pro
+++ b/src/proto/blob.pro
@@ -10,7 +10,7 @@ int blob_get(blob_T *b, int idx);
 void blob_set(blob_T *blob, int idx, int byte);
 void blob_set_append(blob_T *blob, int idx, int byte);
 int blob_equal(blob_T *b1, blob_T *b2);
-int read_blob(FILE *fd, typval_T *rettv, off_T offset, off_T size);
+int read_blob(FILE *fd, typval_T *rettv, off_T offset, off_T size_arg);
 int write_blob(FILE *fd, blob_T *blob);
 char_u *blob2string(blob_T *blob, char_u **tofree, char_u *numbuf);
 blob_T *string2blob(char_u *str);
--- a/src/testdir/test_blob.vim
+++ b/src/testdir/test_blob.vim
@@ -508,6 +508,11 @@ func Test_blob_read_write()
   END
   call v9.CheckLegacyAndVim9Success(lines)
 
+  if filereadable('/dev/random')
+    let b = readblob('/dev/random', 0, 10)
+    call assert_equal(10, len(b))
+  endif
+
   call assert_fails("call readblob('notexist')", 'E484:')
   " TODO: How do we test for the E485 error?
 
--- a/src/version.c
+++ b/src/version.c
@@ -696,6 +696,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    803,
+/**/
     802,
 /**/
     801,