On Tue, May 1, 2012 at 3:17 AM, Allan McRae <al...@archlinux.org> wrote: > Signed-off-by: Allan McRae <al...@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