summaryrefslogtreecommitdiff
path: root/src/backend/storage/file/buffile.c
diff options
context:
space:
mode:
authorPeter Eisentraut <peter@eisentraut.org>2023-01-16 09:20:44 +0100
committerPeter Eisentraut <peter@eisentraut.org>2023-01-16 11:01:31 +0100
commit20428d344a2964de6aaef9984fcd472f3c65d115 (patch)
tree12ec494bd3dd561e56417915bcf97da45eb1cb17 /src/backend/storage/file/buffile.c
parent1561612e3bf3264c31618b9455d0c1003b9271ec (diff)
Add BufFileRead variants with short read and EOF detection
Most callers of BufFileRead() want to check whether they read the full specified length. Checking this at every call site is very tedious. This patch provides additional variants BufFileReadExact() and BufFileReadMaybeEOF() that include the length checks. I considered changing BufFileRead() itself, but this function is also used in extensions, and so changing the behavior like this would create a lot of problems there. The new names are analogous to the existing LogicalTapeReadExact(). Reviewed-by: Amit Kapila <amit.kapila16@gmail.com> Discussion: https://www.postgresql.org/message-id/flat/f3501945-c591-8cc3-5ef0-b72a2e0eaa9c@enterprisedb.com
Diffstat (limited to 'src/backend/storage/file/buffile.c')
-rw-r--r--src/backend/storage/file/buffile.c50
1 files changed, 47 insertions, 3 deletions
diff --git a/src/backend/storage/file/buffile.c b/src/backend/storage/file/buffile.c
index 4a5bd0e224d..c5464b6aa62 100644
--- a/src/backend/storage/file/buffile.c
+++ b/src/backend/storage/file/buffile.c
@@ -573,14 +573,19 @@ BufFileDumpBuffer(BufFile *file)
}
/*
- * BufFileRead
+ * BufFileRead variants
*
* Like fread() except we assume 1-byte element size and report I/O errors via
* ereport().
+ *
+ * If 'exact' is true, then an error is also raised if the number of bytes
+ * read is not exactly 'size' (no short reads). If 'exact' and 'eofOK' are
+ * true, then reading zero bytes is ok.
*/
-size_t
-BufFileRead(BufFile *file, void *ptr, size_t size)
+static size_t
+BufFileReadCommon(BufFile *file, void *ptr, size_t size, bool exact, bool eofOK)
{
+ size_t start_size = size;
size_t nread = 0;
size_t nthistime;
@@ -612,10 +617,49 @@ BufFileRead(BufFile *file, void *ptr, size_t size)
nread += nthistime;
}
+ if (exact &&
+ (nread != start_size && !(nread == 0 && eofOK)))
+ ereport(ERROR,
+ errcode_for_file_access(),
+ file->name ?
+ errmsg("could not read from file set \"%s\": read only %zu of %zu bytes",
+ file->name, nread, start_size) :
+ errmsg("could not read from temporary file: read only %zu of %zu bytes",
+ nread, start_size));
+
return nread;
}
/*
+ * Legacy interface where the caller needs to check for end of file or short
+ * reads.
+ */
+size_t
+BufFileRead(BufFile *file, void *ptr, size_t size)
+{
+ return BufFileReadCommon(file, ptr, size, false, false);
+}
+
+/*
+ * Require read of exactly the specified size.
+ */
+void
+BufFileReadExact(BufFile *file, void *ptr, size_t size)
+{
+ BufFileReadCommon(file, ptr, size, true, false);
+}
+
+/*
+ * Require read of exactly the specified size, but optionally allow end of
+ * file (in which case 0 is returned).
+ */
+size_t
+BufFileReadMaybeEOF(BufFile *file, void *ptr, size_t size, bool eofOK)
+{
+ return BufFileReadCommon(file, ptr, size, true, eofOK);
+}
+
+/*
* BufFileWrite
*
* Like fwrite() except we assume 1-byte element size and report errors via