diff options
-rw-r--r-- | lib/libalpm/alpm.h | 5 | ||||
-rw-r--r-- | lib/libalpm/package.c | 109 | ||||
-rw-r--r-- | src/pacman/package.c | 38 | ||||
-rw-r--r-- | src/pacman/package.h | 2 | ||||
-rw-r--r-- | src/pacman/query.c | 9 |
5 files changed, 137 insertions, 26 deletions
diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index 1e18ad95..c98adc5f 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -216,6 +216,11 @@ alpm_list_t *alpm_pkg_get_deltas(pmpkg_t *pkg); alpm_list_t *alpm_pkg_get_replaces(pmpkg_t *pkg); alpm_list_t *alpm_pkg_get_files(pmpkg_t *pkg); alpm_list_t *alpm_pkg_get_backup(pmpkg_t *pkg); +void *alpm_pkg_changelog_open(pmpkg_t *pkg); +size_t alpm_pkg_changelog_read(void *ptr, size_t size, + const pmpkg_t *pkg, const void *fp); +/*int alpm_pkg_changelog_feof(const pmpkg_t *pkg, void *fp);*/ +int alpm_pkg_changelog_close(const pmpkg_t *pkg, void *fp); unsigned short alpm_pkg_has_scriptlet(pmpkg_t *pkg); unsigned long alpm_pkg_download_size(pmpkg_t *newpkg, pmdb_t *db_local); diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c index 172456d6..efb54b02 100644 --- a/lib/libalpm/package.c +++ b/lib/libalpm/package.c @@ -491,6 +491,115 @@ alpm_list_t SYMEXPORT *alpm_pkg_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' could really be from an archive + * as well as from the database. + * @param pkg the package to read the changelog of (either file or db) + * @return a 'file stream' to the package changelog + */ +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_CACHE) { + 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"); + } else 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_ERROR, 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 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_CACHE) { + ret = fread(ptr, 1, size, (FILE*)fp); + } else if(pkg->origin == PKG_FROM_FILE) { + ret = archive_read_data((struct archive*)fp, ptr, size); + } + return(ret); +} + +/* +int SYMEXPORT alpm_pkg_changelog_feof(const pmpkg_t *pkg, void *fp) +{ + int ret = 0; + if(pkg->origin == PKG_FROM_CACHE) { + ret = feof((FILE*)fp); + } else 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); + } + return(ret); +} +*/ + +/** + * Close a package changelog for reading. Similar to fclose in functionality, + * except that the 'file stream' could really be from an archive as well as + * 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 SYMEXPORT alpm_pkg_changelog_close(const pmpkg_t *pkg, void *fp) +{ + int ret = 0; + if(pkg->origin == PKG_FROM_CACHE) { + ret = fclose((FILE*)fp); + } else if(pkg->origin == PKG_FROM_FILE) { + ret = archive_read_finish((struct archive *)fp); + } + return(ret); +} + unsigned short SYMEXPORT alpm_pkg_has_scriptlet(pmpkg_t *pkg) { ALPM_LOG_FUNC; diff --git a/src/pacman/package.c b/src/pacman/package.c index ac3f8207..ba572141 100644 --- a/src/pacman/package.c +++ b/src/pacman/package.c @@ -34,6 +34,8 @@ #include "package.h" #include "util.h" +#define CLBUF_SIZE 4096 + /* Display the content of a package * * level: <0 - sync package [-Si] @@ -232,28 +234,30 @@ void dump_pkg_files(pmpkg_t *pkg) fflush(stdout); } -/* Display the changelog of an installed package +/* Display the changelog of a package */ -void dump_pkg_changelog(char *clfile, const char *pkgname) +void dump_pkg_changelog(pmpkg_t *pkg) { - FILE* fp = NULL; - char line[PATH_MAX+1]; + void *fp = NULL; - if((fp = fopen(clfile, "r")) == NULL) - { - fprintf(stderr, _("error: no changelog available for '%s'.\n"), pkgname); + if((fp = alpm_pkg_changelog_open(pkg)) == NULL) { + /* TODO after string freeze use pm_fprintf */ + fprintf(stderr, _("error: no changelog available for '%s'.\n"), + alpm_pkg_get_name(pkg)); return; - } - else - { - while(!feof(fp)) - { - fgets(line, (int)PATH_MAX, fp); - printf("%s", line); - line[0] = '\0'; + } else { + /* allocate a buffer to get the changelog back in chunks */ + char buf[CLBUF_SIZE]; + int ret = 0; + while((ret = alpm_pkg_changelog_read(buf, CLBUF_SIZE, pkg, fp))) { + if(ret < CLBUF_SIZE) { + /* if we hit the end of the file, we need to add a null terminator */ + *(buf + ret) = '\0'; + } + printf("%s", buf); } - fclose(fp); - return; + alpm_pkg_changelog_close(pkg, fp); + printf("\n"); } } diff --git a/src/pacman/package.h b/src/pacman/package.h index 0e4bb0fa..7dfc0548 100644 --- a/src/pacman/package.h +++ b/src/pacman/package.h @@ -28,7 +28,7 @@ void dump_pkg_sync(pmpkg_t *pkg, const char *treename); void dump_pkg_backups(pmpkg_t *pkg); void dump_pkg_files(pmpkg_t *pkg); -void dump_pkg_changelog(char *clfile, const char *pkgname); +void dump_pkg_changelog(pmpkg_t *pkg); #endif /* _PM_PACKAGE_H */ diff --git a/src/pacman/query.c b/src/pacman/query.c index 8a8765b6..13070772 100644 --- a/src/pacman/query.c +++ b/src/pacman/query.c @@ -312,14 +312,7 @@ static void display(pmpkg_t *pkg) dump_pkg_files(pkg); } if(config->op_q_changelog) { - char changelog[PATH_MAX]; - /* TODO should be done in the backend- no raw DB stuff up front */ - snprintf(changelog, PATH_MAX, "%s/%s/%s-%s/changelog", - alpm_option_get_dbpath(), - alpm_db_get_name(db_local), - alpm_pkg_get_name(pkg), - alpm_pkg_get_version(pkg)); - dump_pkg_changelog(changelog, alpm_pkg_get_name(pkg)); + dump_pkg_changelog(pkg); } if(!config->op_q_info && !config->op_q_list && !config->op_q_changelog) { if (!config->quiet) { |