summaryrefslogtreecommitdiffstats
path: root/lib/libalpm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libalpm')
-rw-r--r--lib/libalpm/be_files.c61
-rw-r--r--lib/libalpm/be_package.c111
-rw-r--r--lib/libalpm/package.c78
3 files changed, 175 insertions, 75 deletions
diff --git a/lib/libalpm/be_files.c b/lib/libalpm/be_files.c
index e8573947..737f22c8 100644
--- a/lib/libalpm/be_files.c
+++ b/lib/libalpm/be_files.c
@@ -230,6 +230,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(alpm_pkg_get_db(pkg)),
+ 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.
@@ -290,6 +347,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,
};
static int checkdbdir(pmdb_t *db)
diff --git a/lib/libalpm/be_package.c b/lib/libalpm/be_package.c
index f581813c..4a8624e5 100644
--- a/lib/libalpm/be_package.c
+++ b/lib/libalpm/be_package.c
@@ -26,6 +26,7 @@
#include <limits.h>
#include <ctype.h>
#include <locale.h> /* setlocale */
+#include <errno.h>
/* libarchive */
#include <archive.h>
@@ -39,6 +40,114 @@
#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)
+{
+ ssize_t sret = archive_read_data((struct archive*)fp, ptr, size);
+ /* Report error (negative values) */
+ if(sret < 0) {
+ pm_errno = PM_ERR_LIBARCHIVE;
+ return(0);
+ } else {
+ return((size_t)sret);
+ }
+}
+
+/*
+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
@@ -236,7 +345,7 @@ static pmpkg_t *pkg_load(const char *pkgfile, int 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 4f7cc2db..2d0ec010 100644
--- a/lib/libalpm/package.c
+++ b/lib/libalpm/package.c
@@ -300,50 +300,7 @@ pmdb_t SYMEXPORT *alpm_pkg_get_db(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;
-
- 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(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);
}
/**
@@ -361,34 +318,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) {
- ssize_t sret = archive_read_data((struct archive*)fp, ptr, size);
- /* Report error (negative values) */
- if(sret < 0) {
- pm_errno = PM_ERR_LIBARCHIVE;
- ret = 0;
- } else {
- ret = (size_t)sret;
- }
- } 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);
}
*/
@@ -402,13 +338,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);
}
int SYMEXPORT alpm_pkg_has_scriptlet(pmpkg_t *pkg)