diff --git a/src/basic/fileio.c b/src/basic/fileio.c index cd6f2f7a77..16f36359eb 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -404,7 +404,10 @@ int read_virtual_file(const char *filename, size_t max_size, char **ret_contents /* Be prepared for files from /proc which generally report a file size of 0. */ assert_cc(READ_FULL_BYTES_MAX < SSIZE_MAX); - if (st.st_size > 0) { + if (st.st_size > 0 && n_retries > 1) { + /* Let's use the file size if we have more than 1 attempt left. On the last attempt + * we'll ignore the file size */ + if (st.st_size > SSIZE_MAX) { /* Avoid overflow with 32-bit size_t and 64-bit off_t. */ if (max_size == SIZE_MAX) @@ -427,6 +430,7 @@ int read_virtual_file(const char *filename, size_t max_size, char **ret_contents buf = malloc(size + 1); if (!buf) return -ENOMEM; + /* Use a bigger allocation if we got it anyway, but not more than the limit. */ size = MIN3(MALLOC_SIZEOF_SAFE(buf) - 1, max_size, READ_FULL_BYTES_MAX); @@ -457,20 +461,13 @@ int read_virtual_file(const char *filename, size_t max_size, char **ret_contents break; } - /* Hmm... either we read too few bytes from /proc or less likely the content - * of the file might have been changed (and is now bigger) while we were - * processing, let's try again either with a bigger guessed size or the new - * file size. */ + /* We have no further attempts left? Then the file is apparently larger than our limits. Give up. */ + if (n_retries <= 0) + return -EFBIG; - if (n_retries <= 0) { - if (max_size == SIZE_MAX) - return st.st_size > 0 ? -EIO : -EFBIG; - - /* Accept a short read, but truncate it appropropriately. */ - n = MIN(n, max_size); - truncated = true; - break; - } + /* Hmm... either we read too few bytes from /proc or less likely the content of the file + * might have been changed (and is now bigger) while we were processing, let's try again + * either with the new file size. */ if (lseek(fd, 0, SEEK_SET) < 0) return -errno;