[pacman-dev] [PATCH] Add functions for reading mtree file from local db

Dan McGee dpmcgee at gmail.com
Tue May 1 08:18:47 EDT 2012


On Tue, May 1, 2012 at 3:17 AM, Allan McRae <allan at archlinux.org> wrote:
> Signed-off-by: Allan McRae <allan at archlinux.org>
> ---
>
> I have not tested this actually reads the mtree file correctly yet...
> but I would like some feedback if people think that this is the right approach
> to take before I spend more time on it.
>
>  lib/libalpm/be_local.c |   60 ++++++++++++++++++++++++++++++++++++++++++++++++
>  lib/libalpm/package.c  |   21 +++++++++++++++++
>  lib/libalpm/package.h  |    8 +++++++
>  3 files changed, 89 insertions(+)
>
> diff --git a/lib/libalpm/be_local.c b/lib/libalpm/be_local.c
> index aab6718..dbd8138 100644
> --- a/lib/libalpm/be_local.c
> +++ b/lib/libalpm/be_local.c
> @@ -28,6 +28,10 @@
>  #include <dirent.h>
>  #include <limits.h> /* PATH_MAX */
>
> +/* libarchive */
> +#include <archive.h>
> +#include <archive_entry.h>
> +
>  /* libalpm */
>  #include "db.h"
>  #include "alpm_list.h"
> @@ -210,6 +214,58 @@ static int _cache_changelog_close(const alpm_pkg_t UNUSED *pkg, void *fp)
>        return fclose((FILE *)fp);
>  }
>
> +static void *_cache_mtree_open(alpm_pkg_t *pkg)
> +{
> +       int r;
> +       struct archive *mtree;
> +
> +       pkg->handle->pm_errno = 0;
> +
> +       alpm_db_t *db = alpm_pkg_get_db(pkg);
> +       char *mtfile = _alpm_local_db_pkgpath(db, pkg, "mtree");
> +
> +       if(access(mtfile, F_OK) != 0) {
> +               /* there is no mtree file for this package */
> +               return NULL;
> +       }
> +
> +       if((mtree = archive_read_new()) == NULL) {
> +               pkg->handle->pm_errno = ALPM_ERR_LIBARCHIVE;
free(mtfile);
> +               return NULL;
> +       }
> +
> +       archive_read_support_filter_gzip(mtree);
Any reason to restrict the filter support here, other than you knew
you chose gzip? Might as well remain flexible.
> +       archive_read_support_format_mtree(mtree);
> +
> +       if((r = archive_read_open_file(mtree, mtfile, ALPM_BUFFER_SIZE))) {
> +               _alpm_log(pkg->handle, ALPM_LOG_ERROR, _("error while reading file %s: %s\n"),
> +                                       mtfile, archive_error_string(mtree));
> +               pkg->handle->pm_errno = ALPM_ERR_LIBARCHIVE;
> +               archive_read_finish(mtree);
free(mtfile);
This never frees itself.
> +               return NULL;
> +       }
> +
> +       return mtree;
> +}
> +
> +static int _cache_mtree_read(void *entry, const alpm_pkg_t UNUSED *pkg,
> +               void *archive)
> +{
> +       int ret;
> +       struct archive *mtree = archive;
> +       struct archive_entry *details = entry;
> +
> +       ret = archive_read_next_header(mtree, &details);
> +
> +       return ret;
> +}
> +
> +static void _cache_mtree_close(const alpm_pkg_t UNUSED *pkg, void *archive)
> +{
> +       struct archive *mtree = archive;
> +       archive_read_free(mtree);
> +}
> +
>  static int _cache_force_load(alpm_pkg_t *pkg)
>  {
>        return local_db_read(pkg, INFRQ_ALL);
> @@ -245,6 +301,10 @@ static struct pkg_operations local_pkg_ops = {
>        .changelog_read  = _cache_changelog_read,
>        .changelog_close = _cache_changelog_close,
>
> +       .mtree_open  = _cache_mtree_open,
> +       .mtree_read  = _cache_mtree_read,
> +       .mtree_close = _cache_mtree_close,
> +
>        .force_load      = _cache_force_load,
>  };
>
> diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c
> index 46d1473..0f446d3 100644
> --- a/lib/libalpm/package.c
> +++ b/lib/libalpm/package.c
> @@ -121,6 +121,23 @@ static int _pkg_changelog_close(const alpm_pkg_t UNUSED *pkg,
>        return EOF;
>  }
>
> +static void *_pkg_mtree_open(alpm_pkg_t UNUSED *pkg)
> +{
> +       return NULL;
> +}
> +
> +static int _pkg_mtree_read(void UNUSED *entry, const alpm_pkg_t UNUSED *pkg,
> +               void UNUSED *archive)
> +{
> +       return 0;
> +}
> +
> +static void _pkg_mtree_close(const alpm_pkg_t UNUSED *pkg,
> +               void UNUSED *archive)
> +{
> +       return;
> +}
> +
>  static int _pkg_force_load(alpm_pkg_t UNUSED *pkg) { return 0; }
>
>  /** The standard package operations struct. Get fields directly from the
> @@ -152,6 +169,10 @@ struct pkg_operations default_pkg_ops = {
>        .changelog_read  = _pkg_changelog_read,
>        .changelog_close = _pkg_changelog_close,
>
> +       .mtree_open      = _pkg_mtree_open,
> +       .mtree_read      = _pkg_mtree_read,
> +       .mtree_close     = _pkg_mtree_close,
> +

Since we are including this file in the package itself, in the long
run, we can have an implementation in the be_package.c backend too.
But don't worry about that now since I have no idea how or why one
would use that yet.

>        .force_load      = _pkg_force_load,
>  };
>
> diff --git a/lib/libalpm/package.h b/lib/libalpm/package.h
> index c473549..aff9075 100644
> --- a/lib/libalpm/package.h
> +++ b/lib/libalpm/package.h
> @@ -26,6 +26,10 @@
>
>  #include <sys/types.h> /* off_t */
>
> +/* libarchive */
> +#include <archive.h>
> +#include <archive_entry.h>
> +
>  #include "alpm.h"
>  #include "backup.h"
>  #include "db.h"
> @@ -64,6 +68,10 @@ struct pkg_operations {
>        size_t (*changelog_read) (void *, size_t, const alpm_pkg_t *, void *);
>        int (*changelog_close) (const alpm_pkg_t *, void *);
>
> +       void *(*mtree_open) (alpm_pkg_t *);
> +       int (*mtree_read) (void *, const alpm_pkg_t *, void *);
> +       void (*mtree_close) (const alpm_pkg_t *, void *);
> +
>        int (*force_load) (alpm_pkg_t *);
>  };
>
> --

As to your original question- yes, this approach seems reasonable and
the right way to go about it. One issue here is you didn't actually
return the "details" object from _cache_mtree_read() here. In any
case, we can probably tailor this API to both receive and return (in a
pointer argument) libarchive stuff directly, as we can just designate
that as our public mtree interface.

-Dan


More information about the pacman-dev mailing list