From bfa0bc7df0ca527fcec49dbd2055f1bac438663e Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 19:04:32 +0800 Subject: vim-patch:9.0.0795: readblob() always reads the whole file Problem: readblob() always reads the whole file. Solution: Add arguments to read part of the file. (Ken Takata, closes vim/vim#11402) https://github.com/vim/vim/commit/11df3aeee548b959ccd4b9a4d3c44651eab6b3ce Remove trailing whitespace in test as done in patch 9.0.1257. Move the help for rand() before range(). Co-authored-by: K.Takata --- src/nvim/eval.c | 50 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 10 deletions(-) (limited to 'src/nvim/eval.c') diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 698172442e..c2f84735b2 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -5859,27 +5859,57 @@ write_blob_error: return false; } -/// Read a blob from a file `fd`. +/// Read blob from file "fd". +/// Caller has allocated a blob in "rettv". /// /// @param[in] fd File to read from. -/// @param[in,out] blob Blob to write to. +/// @param[in,out] rettv Blob to write to. +/// @param[in] offset Read the file from the specified offset. +/// @param[in] size Read the specified size, or -1 if no limit. /// -/// @return true on success, or false on failure. -bool read_blob(FILE *const fd, blob_T *const blob) +/// @return OK on success, or FAIL on failure. +int read_blob(FILE *const fd, typval_T *rettv, off_T offset, off_T size_arg) FUNC_ATTR_NONNULL_ALL { + blob_T *const blob = rettv->vval.v_blob; FileInfo file_info; if (!os_fileinfo_fd(fileno(fd), &file_info)) { - return false; + return FAIL; // can't read the file, error + } + + int whence; + off_T size = size_arg; + if (offset >= 0) { + if (size == -1) { + // size may become negative, checked below + size = (off_T)os_fileinfo_size(&file_info) - offset; + } + whence = SEEK_SET; + } else { + if (size == -1) { + size = -offset; + } + whence = SEEK_END; + } + // Trying to read bytes that aren't there results in an empty blob, not an + // error. + if (size < 0 || size > (off_T)os_fileinfo_size(&file_info)) { + return OK; + } + if (vim_fseek(fd, offset, whence) != 0) { + return OK; } - const int size = (int)os_fileinfo_size(&file_info); - ga_grow(&blob->bv_ga, size); - blob->bv_ga.ga_len = size; + + ga_grow(&blob->bv_ga, (int)size); + blob->bv_ga.ga_len = (int)size; if (fread(blob->bv_ga.ga_data, 1, (size_t)blob->bv_ga.ga_len, fd) < (size_t)blob->bv_ga.ga_len) { - return false; + // An empty blob is returned on error. + tv_blob_free(rettv->vval.v_blob); + rettv->vval.v_blob = NULL; + return FAIL; } - return true; + return OK; } /// Saves a typval_T as a string. -- cgit From 4bd0611d7b07b56fc5a9e121669a313166ba540f Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 19:23:28 +0800 Subject: vim-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 vim/vim#11407) https://github.com/vim/vim/commit/43625762a9751cc6e6e4d8f54fbc8b82d98fb20d S_ISCHR is always defined in Nvim. Co-authored-by: K.Takata --- src/nvim/eval.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval.c') diff --git a/src/nvim/eval.c b/src/nvim/eval.c index c2f84735b2..92fd8a8de3 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -5893,10 +5893,11 @@ int read_blob(FILE *const fd, typval_T *rettv, off_T offset, off_T size_arg) } // Trying to read bytes that aren't there results in an empty blob, not an // error. - if (size < 0 || size > (off_T)os_fileinfo_size(&file_info)) { + if (size < 0 || (!S_ISCHR(file_info.stat.st_mode) + && size > (off_T)os_fileinfo_size(&file_info))) { return OK; } - if (vim_fseek(fd, offset, whence) != 0) { + if (offset != 0 && vim_fseek(fd, offset, whence) != 0) { return OK; } -- cgit From 7aad75e293e3a01e292308ca2058e35083b83280 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 19:29:59 +0800 Subject: 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. https://github.com/vim/vim/commit/5b2a3d77d320d76f12b1666938a9d58c2a848205 Co-authored-by: Bram Moolenaar --- src/nvim/eval.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'src/nvim/eval.c') diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 92fd8a8de3..b81384266c 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -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) { -- cgit