Signed-off-by: Dan McGee <[EMAIL PROTECTED]>
---
 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


_______________________________________________
pacman-dev mailing list
[email protected]
http://archlinux.org/mailman/listinfo/pacman-dev

Reply via email to