summaryrefslogtreecommitdiff
path: root/src/basic/fileio.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2021-05-21 17:40:19 +0200
committerLennart Poettering <lennart@poettering.net>2021-05-21 21:54:44 +0200
commitb2d0b90f5405370ad35dca6fd6851c737f14a732 (patch)
treed94a37c554416812d20cbb75c67affded3c388c4 /src/basic/fileio.c
parenteff722c693d3011ec0217e7a4a7a6fb9f689778b (diff)
downloadsystemd-b2d0b90f5405370ad35dca6fd6851c737f14a732.tar.gz
fileio: read_virtual_file(): on last attempt ignore file size
Apparently the reported file size was misleading on this file, hence ignore it on our last loop attempt and just pretend it wasn't reported at all.
Diffstat (limited to 'src/basic/fileio.c')
-rw-r--r--src/basic/fileio.c25
1 files changed, 11 insertions, 14 deletions
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. */
-
- if (n_retries <= 0) {
- if (max_size == SIZE_MAX)
- return st.st_size > 0 ? -EIO : -EFBIG;
+ /* We have no further attempts left? Then the file is apparently larger than our limits. Give up. */
+ if (n_retries <= 0)
+ return -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;