Browse Source

faux.base: faux_read_whole_file()

Serj Kalichev 3 years ago
parent
commit
88dbab2ccf
2 changed files with 105 additions and 0 deletions
  1. 104 0
      faux/base/io.c
  2. 1 0
      faux/faux.h

+ 104 - 0
faux/base/io.c

@@ -10,7 +10,10 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/uio.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 
+#include "faux/faux.h"
 
 /** @brief Writes data to file.
  *
@@ -145,3 +148,104 @@ size_t faux_read_block(int fd, void *buf, size_t n)
 
 	return total_readed;
 }
+
+
+/** @brief Reads whole file to buffer.
+ *
+ * Allocates buffer and read whole file to it.
+ *
+ * @param [in] path File name.
+ * @param [out] buf Output buffer with file content.
+ * @warn Buffer must be freed with faux_free().
+ * @return Number of bytes readed.
+ * = n Empty file. The data param will be set to NULL.
+ * < 0 Error.
+ */
+ssize_t faux_read_whole_file(const char *path, void **data)
+{
+	ssize_t expected_size = 0;
+	struct stat statbuf = {};
+	char *buf = NULL;
+	size_t buf_full_size = 0;
+	ssize_t bytes_readed = 0;
+	size_t total_readed = 0;
+	int fd = -1;
+
+	assert(path);
+	assert(data);
+	if (!path || !data)
+		return -1;
+
+	if (stat(path, &statbuf) < 0)
+		return -1;
+
+	// Regular file?
+	if (!S_ISREG(statbuf.st_mode))
+		return -1;
+
+	// Get expected file size
+	expected_size = faux_filesize(path);
+	if (expected_size < 0)
+		return -1;
+	// Add some extra space to buffer. Because actual filesize can
+	// differ while reading. Try to read more data than expected.
+	expected_size++;
+
+	// Open file
+	fd = open(path, O_RDONLY);
+	if (fd < 0)
+		return -1;
+
+	// Allocate buffer
+	buf_full_size = expected_size;
+	buf = faux_zmalloc(buf_full_size);
+	if (!buf) {
+		close(fd);
+		return -1;
+	}
+
+	while ((bytes_readed = faux_read(fd, buf + total_readed,
+		buf_full_size - total_readed)) > 0) {
+		total_readed += bytes_readed;
+		// Enlarge buffer if needed
+		if (total_readed == buf_full_size) {
+			char *p = NULL;
+			buf_full_size = buf_full_size * 2;
+			p = realloc(buf, buf_full_size);
+			if (!p) {
+				free(buf);
+				close(fd);
+				return -1;
+			}
+			buf = p;
+		}
+	}
+	close(fd);
+
+	// Something went wrong
+	if (bytes_readed < 0) {
+		free(buf);
+		return -1;
+	}
+
+	// Empty file
+	if (0 == total_readed) {
+		free(buf);
+		*data = NULL;
+		return 0;
+	}
+
+	// Shrink buffer to actual data size
+	if (total_readed < buf_full_size) {
+		char *p = NULL;
+		p = realloc(buf, total_readed);
+		if (!p) {
+			free(buf);
+			return -1;
+		}
+		buf = p;
+	}
+	*data = buf;
+
+	return total_readed;
+}

+ 1 - 0
faux/faux.h

@@ -83,6 +83,7 @@ ssize_t faux_write(int fd, const void *buf, size_t n);
 ssize_t faux_read(int fd, void *buf, size_t n);
 ssize_t faux_write_block(int fd, const void *buf, size_t n);
 size_t faux_read_block(int fd, void *buf, size_t n);
+ssize_t faux_read_whole_file(const char *path, void **data);
 
 // Filesystem
 ssize_t faux_filesize(const char *path);