vim-patch:9.0.0810: readblob() returns empty when trying to read too much

Problem:    readblob() returns empty when trying to read too much.
Solution:   Return what is available.

5b2a3d77d3

Co-authored-by: Bram Moolenaar <Bram@vim.org>
This commit is contained in:
zeertzjq
2023-02-28 19:29:59 +08:00
parent 4bd0611d7b
commit 7aad75e293
3 changed files with 24 additions and 10 deletions

View File

@@ -6171,8 +6171,10 @@ readblob({fname} [, {offset} [, {size}]]) *readblob()*
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.
When the offset is beyond the end of the file the result is an
empty blob.
When trying to read more bytes than are available the result
is truncated.
Also see |readfile()| and |writefile()|.

View File

@@ -5879,22 +5879,27 @@ int read_blob(FILE *const fd, typval_T *rettv, off_T offset, off_T size_arg)
int whence;
off_T size = size_arg;
const off_T file_size = (off_T)os_fileinfo_size(&file_info);
if (offset >= 0) {
if (size == -1) {
// The size defaults to the whole file. If a size is given it is
// limited to not go past the end of the file.
if (size == -1 || (size > file_size - offset && !S_ISCHR(file_info.stat.st_mode))) {
// size may become negative, checked below
size = (off_T)os_fileinfo_size(&file_info) - offset;
}
whence = SEEK_SET;
} else {
if (size == -1) {
// limit the offset to not go before the start of the file
if (-offset > file_size && !S_ISCHR(file_info.stat.st_mode)) {
offset = -file_size;
}
// Size defaults to reading until the end of the file.
if (size == -1 || size > -offset) {
size = -offset;
}
whence = SEEK_END;
}
// Trying to read bytes that aren't there results in an empty blob, not an
// error.
if (size < 0 || (!S_ISCHR(file_info.stat.st_mode)
&& size > (off_T)os_fileinfo_size(&file_info))) {
if (size <= 0) {
return OK;
}
if (offset != 0 && vim_fseek(fd, offset, whence) != 0) {

View File

@@ -450,10 +450,17 @@ func Test_blob_read_write()
VAR br6 = readblob('Xblob', -3, 2)
call assert_equal(b[-3 : -2], br6)
#" reading past end of file, empty result
VAR br1e = readblob('Xblob', 10000)
call assert_equal(0z, br1e)
VAR br2e = readblob('Xblob', -10000)
call assert_equal(0z, br2e)
#" reading too much, result is truncated
VAR blong = readblob('Xblob', -1000)
call assert_equal(b, blong)
LET blong = readblob('Xblob', -10, 8)
call assert_equal(b, blong)
LET blong = readblob('Xblob', 0, 10)
call assert_equal(b, blong)
call delete('Xblob')
END