From f8c737d3b6b28373a69d5979a4ba2e31b77baa62 Mon Sep 17 00:00:00 2001
From: Dan McGee <dan@archlinux.org>
Date: Tue, 25 Mar 2008 21:23:14 -0500
Subject: [PATCH] Add an archive_fgets() function

This crude function allows reading from an archive on a line-by-line basis
similar to the familiar fgets() call on a FILE stream. This is the first
step in being able to read DB entries straight from an archive.

Signed-off-by: Dan McGee <dan@archlinux.org>
---
 lib/libalpm/util.c | 29 +++++++++++++++++++++++++++++
 lib/libalpm/util.h |  2 ++
 2 files changed, 31 insertions(+)

diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c
index 806f601c..7de5b069 100644
--- a/lib/libalpm/util.c
+++ b/lib/libalpm/util.c
@@ -673,4 +673,33 @@ int _alpm_test_md5sum(const char *filepath, const char *md5sum)
 	return(ret);
 }
 
+char *_alpm_archive_fgets(char *line, size_t size, struct archive *a)
+{
+	/* for now, just read one char at a time until we get to a
+	 * '\n' char. we can optimize this later with an internal
+	 * buffer. */
+	/* leave room for zero terminator */
+	char *last = line + size - 1;
+	char *i;
+
+	for(i = line; i < last; i++) {
+		int ret = archive_read_data(a, i, 1);
+		/* special check for first read- if null, return null,
+		 * this indicates EOF */
+		if(i == line && (ret <= 0 || *i == '\0')) {
+			return(NULL);
+		}
+		/* check if read value was null or newline */
+		if(ret <= 0 || *i == '\0' || *i == '\n') {
+			last = i + 1;
+			break;
+		}
+	}
+
+	/* always null terminate the buffer */
+	*last = '\0';
+
+	return(line);
+}
+
 /* vim: set ts=2 sw=2 noet: */
diff --git a/lib/libalpm/util.h b/lib/libalpm/util.h
index 6849fa19..0bf122cd 100644
--- a/lib/libalpm/util.h
+++ b/lib/libalpm/util.h
@@ -30,6 +30,7 @@
 #include <stdarg.h>
 #include <time.h>
 #include <sys/stat.h> /* struct stat */
+#include <archive.h> /* struct archive */
 
 #ifdef ENABLE_NLS
 #include <libintl.h> /* here so it doesn't need to be included elsewhere */
@@ -66,6 +67,7 @@ char *_alpm_filecache_find(const char *filename);
 const char *_alpm_filecache_setup(void);
 int _alpm_lstat(const char *path, struct stat *buf);
 int _alpm_test_md5sum(const char *filepath, const char *md5sum);
+char *_alpm_archive_fgets(char *line, size_t size, struct archive *a);
 
 #ifndef HAVE_STRVERSCMP
 int strverscmp(const char *, const char *);