[pacman-dev] [PATCH] Move changelog functions to callback struct

Dan McGee dan at archlinux.org
Sun May 11 21:29:00 EDT 2008


Signed-off-by: Dan McGee <dan at archlinux.org>
---
 lib/libalpm/be_files.c   |   61 +++++++++++++++++++++++++++
 lib/libalpm/be_package.c |  104 +++++++++++++++++++++++++++++++++++++++++++++-
 lib/libalpm/package.c    |   71 ++-----------------------------
 3 files changed, 168 insertions(+), 68 deletions(-)

diff --git a/lib/libalpm/be_files.c b/lib/libalpm/be_files.c
index c9e708d..485d960 100644
--- a/lib/libalpm/be_files.c
+++ b/lib/libalpm/be_files.c
@@ -364,6 +364,63 @@ alpm_list_t *_cache_get_backup(pmpkg_t *pkg)
 	return pkg->backup;
 }
 
+/**
+ * Open a package changelog for reading. Similar to fopen in functionality,
+ * except that the returned 'file stream' is from the database.
+ * @param pkg the package (from db) to read the changelog
+ * @return a 'file stream' to the package changelog
+ */
+void *_cache_changelog_open(pmpkg_t *pkg)
+{
+	ALPM_LOG_FUNC;
+
+	/* Sanity checks */
+	ASSERT(handle != NULL, return(NULL));
+	ASSERT(pkg != NULL, return(NULL));
+
+	char clfile[PATH_MAX];
+	snprintf(clfile, PATH_MAX, "%s/%s/%s-%s/changelog",
+			alpm_option_get_dbpath(),
+			alpm_db_get_name(handle->db_local),
+			alpm_pkg_get_name(pkg),
+			alpm_pkg_get_version(pkg));
+	return fopen(clfile, "r");
+}
+
+/**
+ * Read data from an open changelog 'file stream'. Similar to fread in
+ * functionality, this function takes a buffer and amount of data to read.
+ * @param ptr a buffer to fill with raw changelog data
+ * @param size the size of the buffer
+ * @param pkg the package that the changelog is being read from
+ * @param fp a 'file stream' to the package changelog
+ * @return the number of characters read, or 0 if there is no more data
+ */
+size_t _cache_changelog_read(void *ptr, size_t size,
+		const pmpkg_t *pkg, const void *fp)
+{
+	return ( fread(ptr, 1, size, (FILE*)fp) );
+}
+
+/*
+int _cache_changelog_feof(const pmpkg_t *pkg, void *fp)
+{
+	return( feof((FILE*)fp) );
+}
+*/
+
+/**
+ * Close a package changelog for reading. Similar to fclose in functionality,
+ * except that the 'file stream' is from the database.
+ * @param pkg the package that the changelog was read from
+ * @param fp a 'file stream' to the package changelog
+ * @return whether closing the package changelog stream was successful
+ */
+int _cache_changelog_close(const pmpkg_t *pkg, void *fp)
+{
+	return( fclose((FILE*)fp) );
+}
+
 /** The sync database operations struct. Get package fields through
  * lazy accessor methods that handle any backend loading and caching
  * logic.
@@ -422,6 +479,10 @@ static struct pkg_operations local_pkg_ops = {
 	.get_deltas      = _cache_get_deltas,
 	.get_files       = _cache_get_files,
 	.get_backup      = _cache_get_backup,
+
+	.changelog_open  = _cache_changelog_open,
+	.changelog_read  = _cache_changelog_read,
+	.changelog_close = _cache_changelog_close,
 };
 
 /*
diff --git a/lib/libalpm/be_package.c b/lib/libalpm/be_package.c
index 93965db..0c8291a 100644
--- a/lib/libalpm/be_package.c
+++ b/lib/libalpm/be_package.c
@@ -25,6 +25,7 @@
 #include <limits.h>
 #include <ctype.h>
 #include <locale.h> /* setlocale */
+#include <errno.h>
 
 /* libarchive */
 #include <archive.h>
@@ -39,6 +40,107 @@
 #include "deps.h" /* _alpm_splitdep */
 
 /**
+ * Open a package changelog for reading. Similar to fopen in functionality,
+ * except that the returned 'file stream' is from an archive.
+ * @param pkg the package (file) to read the changelog
+ * @return a 'file stream' to the package changelog
+ */
+void *_package_changelog_open(pmpkg_t *pkg)
+{
+	ALPM_LOG_FUNC;
+
+	ASSERT(pkg != NULL, return(NULL));
+
+	struct archive *archive = NULL;
+	struct archive_entry *entry;
+	const char *pkgfile = pkg->origin_data.file;
+	int ret = ARCHIVE_OK;
+
+	if((archive = archive_read_new()) == NULL) {
+		RET_ERR(PM_ERR_LIBARCHIVE, NULL);
+	}
+
+	archive_read_support_compression_all(archive);
+	archive_read_support_format_all(archive);
+
+	if (archive_read_open_filename(archive, pkgfile,
+				ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) {
+		RET_ERR(PM_ERR_PKG_OPEN, NULL);
+	}
+
+	while((ret = archive_read_next_header(archive, &entry)) == ARCHIVE_OK) {
+		const char *entry_name = archive_entry_pathname(entry);
+
+		if(strcmp(entry_name, ".CHANGELOG") == 0) {
+			return(archive);
+		}
+	}
+	/* we didn't find a changelog */
+	archive_read_finish(archive);
+	errno = ENOENT;
+
+	return(NULL);
+}
+
+/**
+ * Read data from an open changelog 'file stream'. Similar to fread in
+ * functionality, this function takes a buffer and amount of data to read.
+ * @param ptr a buffer to fill with raw changelog data
+ * @param size the size of the buffer
+ * @param pkg the package that the changelog is being read from
+ * @param fp a 'file stream' to the package changelog
+ * @return the number of characters read, or 0 if there is no more data
+ */
+size_t _package_changelog_read(void *ptr, size_t size,
+		const pmpkg_t *pkg, const void *fp)
+{
+	return( archive_read_data((struct archive*)fp, ptr, size) );
+}
+
+/*
+int _package_changelog_feof(const pmpkg_t *pkg, void *fp)
+{
+	// note: this doesn't quite work, no feof in libarchive
+	return( archive_read_data((struct archive*)fp, NULL, 0) );
+}
+*/
+
+/**
+ * Close a package changelog for reading. Similar to fclose in functionality,
+ * except that the 'file stream' is from an archive.
+ * @param pkg the package (file) that the changelog was read from
+ * @param fp a 'file stream' to the package changelog
+ * @return whether closing the package changelog stream was successful
+ */
+int _package_changelog_close(const pmpkg_t *pkg, void *fp)
+{
+	return( archive_read_finish((struct archive *)fp) );
+}
+
+
+/** Package file operations struct accessor. We implement this as a method
+ * rather than a static struct as in be_files because we want to reuse the
+ * majority of the default_pkg_ops struct and add only a few operations of
+ * our own on top. The static file_pkg_ops variable inside this function
+ * lets us only initialize an operations struct once which can always be
+ * accessed by this method.
+ */
+static struct pkg_operations *get_file_pkg_ops()
+{
+	static struct pkg_operations *file_pkg_ops = NULL;
+	/* determine whether our static file_pkg_ops struct has been initialized */
+	if(!file_pkg_ops) {
+		MALLOC(file_pkg_ops, sizeof(struct pkg_operations),
+				RET_ERR(PM_ERR_MEMORY, NULL));
+		memcpy(file_pkg_ops, &default_pkg_ops, sizeof(struct pkg_operations));
+		file_pkg_ops->changelog_open  = _package_changelog_open;
+		file_pkg_ops->changelog_read  = _package_changelog_read;
+		file_pkg_ops->changelog_close = _package_changelog_close;
+	}
+	return(file_pkg_ops);
+}
+
+/**
  * Parses the package description file for a package into a pmpkg_t struct.
  * @param archive the archive to read from, pointed at the .PKGINFO entry
  * @param newpkg an empty pmpkg_t struct to fill with package info
@@ -231,7 +333,7 @@ static pmpkg_t *pkg_load(const char *pkgfile, unsigned short full)
 	newpkg->origin = PKG_FROM_FILE;
 	/* TODO eventually kill/move this? */
 	newpkg->origin_data.file = strdup(pkgfile);
-	newpkg->ops = &default_pkg_ops;
+	newpkg->ops = get_file_pkg_ops();
 
 	if(full) {
 		/* "checking for conflicts" requires a sorted list, ensure that here */
diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c
index c226a64..1dec422 100644
--- a/lib/libalpm/package.c
+++ b/lib/libalpm/package.c
@@ -294,51 +294,7 @@ alpm_list_t SYMEXPORT *alpm_pkg_get_backup(pmpkg_t *pkg)
  */
 void SYMEXPORT *alpm_pkg_changelog_open(pmpkg_t *pkg)
 {
-	ALPM_LOG_FUNC;
-
-	/* Sanity checks */
-	ASSERT(handle != NULL, return(NULL));
-	ASSERT(pkg != NULL, return(NULL));
-
-	if(pkg->origin == PKG_FROM_FILE) {
-		struct archive *archive = NULL;
-		struct archive_entry *entry;
-		const char *pkgfile = pkg->origin_data.file;
-		int ret = ARCHIVE_OK;
-
-		if((archive = archive_read_new()) == NULL) {
-			RET_ERR(PM_ERR_LIBARCHIVE, NULL);
-		}
-
-		archive_read_support_compression_all(archive);
-		archive_read_support_format_all(archive);
-
-		if (archive_read_open_filename(archive, pkgfile,
-					ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) {
-			RET_ERR(PM_ERR_PKG_OPEN, NULL);
-		}
-
-		while((ret = archive_read_next_header(archive, &entry)) == ARCHIVE_OK) {
-			const char *entry_name = archive_entry_pathname(entry);
-
-			if(strcmp(entry_name, ".CHANGELOG") == 0) {
-				return(archive);
-			}
-		}
-		/* we didn't find a changelog */
-		archive_read_finish(archive);
-		errno = ENOENT;
-	} else {
-		char clfile[PATH_MAX];
-		snprintf(clfile, PATH_MAX, "%s/%s/%s-%s/changelog",
-				alpm_option_get_dbpath(),
-				alpm_db_get_name(handle->db_local),
-				alpm_pkg_get_name(pkg),
-				alpm_pkg_get_version(pkg));
-		return fopen(clfile, "r");
-	}
-
-	return(NULL);
+	return pkg->ops->changelog_open(pkg);
 }
 
 /**
@@ -353,26 +309,13 @@ void SYMEXPORT *alpm_pkg_changelog_open(pmpkg_t *pkg)
 size_t SYMEXPORT alpm_pkg_changelog_read(void *ptr, size_t size,
 		const pmpkg_t *pkg, const void *fp)
 {
-	size_t ret = 0;
-	if(pkg->origin == PKG_FROM_FILE) {
-		ret = archive_read_data((struct archive*)fp, ptr, size);
-	} else {
-		ret = fread(ptr, 1, size, (FILE*)fp);
-	}
-	return(ret);
+	return pkg->ops->changelog_read(ptr, size, pkg, fp);
 }
 
 /*
 int SYMEXPORT alpm_pkg_changelog_feof(const pmpkg_t *pkg, void *fp)
 {
-	int ret = 0;
-	if(pkg->origin == PKG_FROM_FILE) {
-		// note: this doesn't quite work, no feof in libarchive
-		ret = archive_read_data((struct archive*)fp, NULL, 0);
-	} else {
-		ret = feof((FILE*)fp);
-	}
-	return(ret);
+	return pkg->ops->changelog_feof(pkg, fp);
 }
 */
 
@@ -386,13 +329,7 @@ int SYMEXPORT alpm_pkg_changelog_feof(const pmpkg_t *pkg, void *fp)
  */
 int SYMEXPORT alpm_pkg_changelog_close(const pmpkg_t *pkg, void *fp)
 {
-	int ret = 0;
-	if(pkg->origin == PKG_FROM_FILE) {
-		ret = archive_read_finish((struct archive *)fp);
-	} else {
-		ret = fclose((FILE*)fp);
-	}
-	return(ret);
+	return pkg->ops->changelog_close(pkg, fp);
 }
 
 unsigned short SYMEXPORT alpm_pkg_has_scriptlet(pmpkg_t *pkg)
-- 
1.5.5.1





More information about the pacman-dev mailing list