Commit e7be6b76b68ca34a207b3d816546817cb2459615

Edward Thomson 2021-11-29T12:04:06

futils: provide an option to read a whole file by fd

diff --git a/src/util/futils.c b/src/util/futils.c
index 2b0dbf3..9b8d468 100644
--- a/src/util/futils.c
+++ b/src/util/futils.c
@@ -179,6 +179,42 @@ int git_futils_readbuffer_fd(git_str *buf, git_file fd, size_t len)
 	return 0;
 }
 
+int git_futils_readbuffer_fd_full(git_str *buf, git_file fd)
+{
+	static size_t blocksize = 10240;
+	size_t alloc_len = 0, total_size = 0;
+	ssize_t read_size = 0;
+
+	git_str_clear(buf);
+
+	while (true) {
+		GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, blocksize);
+
+		if (git_str_grow(buf, alloc_len) < 0)
+			return -1;
+
+		/* p_read loops internally to read blocksize bytes */
+		read_size = p_read(fd, buf->ptr, blocksize);
+
+		if (read_size < 0) {
+			git_error_set(GIT_ERROR_OS, "failed to read descriptor");
+			git_str_dispose(buf);
+			return -1;
+		}
+
+		total_size += read_size;
+
+		if ((size_t)read_size < blocksize) {
+			break;
+		}
+	}
+
+	buf->ptr[total_size] = '\0';
+	buf->size = total_size;
+
+	return 0;
+}
+
 int git_futils_readbuffer_updated(
 	git_str *out,
 	const char *path,
diff --git a/src/util/futils.h b/src/util/futils.h
index fb1afcb..3f207af 100644
--- a/src/util/futils.h
+++ b/src/util/futils.h
@@ -27,6 +27,7 @@ extern int git_futils_readbuffer_updated(
 	const char *path,
 	unsigned char checksum[GIT_HASH_SHA1_SIZE],
 	int *updated);
+extern int git_futils_readbuffer_fd_full(git_str *obj, git_file fd);
 extern int git_futils_readbuffer_fd(git_str *obj, git_file fd, size_t len);
 
 /* Additional constants for `git_futils_writebuffer`'s `open_flags`.  We