diff --git a/lib/libalpm/be_files.c b/lib/libalpm/be_files.c index c0298049..e8573947 100644 --- a/lib/libalpm/be_files.c +++ b/lib/libalpm/be_files.c @@ -1,8 +1,8 @@ /* * be_files.c * - * Copyright (c) 2006 by Christian Hamar - * Copyright (c) 2006 by Miklos Vajna + * Copyright (c) 2006-2010 Pacman Development Team + * Copyright (c) 2002-2006 by Judd Vinet * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -51,6 +51,247 @@ #include "dload.h" +#define LAZY_LOAD(info, errret) \ + do { \ + ALPM_LOG_FUNC; \ + ASSERT(handle != NULL, return(errret)); \ + ASSERT(pkg != NULL, return(errret)); \ + if(pkg->origin != PKG_FROM_FILE && !(pkg->infolevel & info)) { \ + _alpm_db_read(pkg->origin_data.db, pkg, info); \ + } \ + } while(0) + + +/* Cache-specific accessor functions. These implementations allow for lazy + * loading by the files backend when a data member is actually needed + * rather than loading all pieces of information when the package is first + * initialized. + */ + +const char *_cache_get_filename(pmpkg_t *pkg) +{ + LAZY_LOAD(INFRQ_DESC, NULL); + return pkg->filename; +} + +const char *_cache_get_name(pmpkg_t *pkg) +{ + ASSERT(pkg != NULL, return(NULL)); + return pkg->name; +} + +static const char *_cache_get_version(pmpkg_t *pkg) +{ + ASSERT(pkg != NULL, return(NULL)); + return pkg->version; +} + +static const char *_cache_get_desc(pmpkg_t *pkg) +{ + LAZY_LOAD(INFRQ_DESC, NULL); + return pkg->desc; +} + +const char *_cache_get_url(pmpkg_t *pkg) +{ + LAZY_LOAD(INFRQ_DESC, NULL); + return pkg->url; +} + +time_t _cache_get_builddate(pmpkg_t *pkg) +{ + LAZY_LOAD(INFRQ_DESC, 0); + return pkg->builddate; +} + +time_t _cache_get_installdate(pmpkg_t *pkg) +{ + LAZY_LOAD(INFRQ_DESC, 0); + return pkg->installdate; +} + +const char *_cache_get_packager(pmpkg_t *pkg) +{ + LAZY_LOAD(INFRQ_DESC, NULL); + return pkg->packager; +} + +const char *_cache_get_md5sum(pmpkg_t *pkg) +{ + LAZY_LOAD(INFRQ_DESC, NULL); + return pkg->md5sum; +} + +const char *_cache_get_arch(pmpkg_t *pkg) +{ + LAZY_LOAD(INFRQ_DESC, NULL); + return pkg->arch; +} + +off_t _cache_get_size(pmpkg_t *pkg) +{ + LAZY_LOAD(INFRQ_DESC, -1); + return pkg->size; +} + +off_t _cache_get_isize(pmpkg_t *pkg) +{ + LAZY_LOAD(INFRQ_DESC, -1); + return pkg->isize; +} + +pmpkgreason_t _cache_get_reason(pmpkg_t *pkg) +{ + LAZY_LOAD(INFRQ_DESC, -1); + return pkg->reason; +} + +alpm_list_t *_cache_get_licenses(pmpkg_t *pkg) +{ + LAZY_LOAD(INFRQ_DESC, NULL); + return pkg->licenses; +} + +alpm_list_t *_cache_get_groups(pmpkg_t *pkg) +{ + LAZY_LOAD(INFRQ_DESC, NULL); + return pkg->groups; +} + +int _cache_has_force(pmpkg_t *pkg) +{ + LAZY_LOAD(INFRQ_DESC, -1); + return pkg->force; +} + +alpm_list_t *_cache_get_depends(pmpkg_t *pkg) +{ + LAZY_LOAD(INFRQ_DEPENDS, NULL); + return pkg->depends; +} + +alpm_list_t *_cache_get_optdepends(pmpkg_t *pkg) +{ + LAZY_LOAD(INFRQ_DEPENDS, NULL); + return pkg->optdepends; +} + +alpm_list_t *_cache_get_conflicts(pmpkg_t *pkg) +{ + LAZY_LOAD(INFRQ_DEPENDS, NULL); + return pkg->conflicts; +} + +alpm_list_t *_cache_get_provides(pmpkg_t *pkg) +{ + LAZY_LOAD(INFRQ_DEPENDS, NULL); + return pkg->provides; +} + +alpm_list_t *_cache_get_replaces(pmpkg_t *pkg) +{ + LAZY_LOAD(INFRQ_DESC, NULL); + return pkg->replaces; +} + +alpm_list_t *_cache_get_deltas(pmpkg_t *pkg) +{ + LAZY_LOAD(INFRQ_DELTAS, NULL); + return pkg->deltas; +} + +alpm_list_t *_cache_get_files(pmpkg_t *pkg) +{ + ALPM_LOG_FUNC; + + /* Sanity checks */ + ASSERT(handle != NULL, return(NULL)); + ASSERT(pkg != NULL, return(NULL)); + + if(pkg->origin == PKG_FROM_LOCALDB + && !(pkg->infolevel & INFRQ_FILES)) { + _alpm_db_read(pkg->origin_data.db, pkg, INFRQ_FILES); + } + return pkg->files; +} + +alpm_list_t *_cache_get_backup(pmpkg_t *pkg) +{ + ALPM_LOG_FUNC; + + /* Sanity checks */ + ASSERT(handle != NULL, return(NULL)); + ASSERT(pkg != NULL, return(NULL)); + + if(pkg->origin == PKG_FROM_LOCALDB + && !(pkg->infolevel & INFRQ_FILES)) { + _alpm_db_read(pkg->origin_data.db, pkg, INFRQ_FILES); + } + return pkg->backup; +} + +/** The sync database operations struct. Get package fields through + * lazy accessor methods that handle any backend loading and caching + * logic. + */ +static struct pkg_operations sync_pkg_ops = { + .get_filename = _cache_get_filename, + .get_name = _cache_get_name, + .get_version = _cache_get_version, + .get_desc = _cache_get_desc, + .get_url = _cache_get_url, + .get_builddate = _cache_get_builddate, + .get_installdate = _cache_get_installdate, + .get_packager = _cache_get_packager, + .get_md5sum = _cache_get_md5sum, + .get_arch = _cache_get_arch, + .get_size = _cache_get_size, + .get_isize = _cache_get_isize, + .get_reason = _cache_get_reason, + .has_force = _cache_has_force, + .get_licenses = _cache_get_licenses, + .get_groups = _cache_get_groups, + .get_depends = _cache_get_depends, + .get_optdepends = _cache_get_optdepends, + .get_conflicts = _cache_get_conflicts, + .get_provides = _cache_get_provides, + .get_replaces = _cache_get_replaces, + .get_deltas = _cache_get_deltas, + .get_files = _cache_get_files, + .get_backup = _cache_get_backup, +}; + +/** The local database operations struct. Get package fields through + * lazy accessor methods that handle any backend loading and caching + * logic. + */ +static struct pkg_operations local_pkg_ops = { + .get_filename = _cache_get_filename, + .get_name = _cache_get_name, + .get_version = _cache_get_version, + .get_desc = _cache_get_desc, + .get_url = _cache_get_url, + .get_builddate = _cache_get_builddate, + .get_installdate = _cache_get_installdate, + .get_packager = _cache_get_packager, + .get_md5sum = _cache_get_md5sum, + .get_arch = _cache_get_arch, + .get_size = _cache_get_size, + .get_isize = _cache_get_isize, + .get_reason = _cache_get_reason, + .has_force = _cache_has_force, + .get_licenses = _cache_get_licenses, + .get_groups = _cache_get_groups, + .get_depends = _cache_get_depends, + .get_optdepends = _cache_get_optdepends, + .get_conflicts = _cache_get_conflicts, + .get_provides = _cache_get_provides, + .get_replaces = _cache_get_replaces, + .get_deltas = _cache_get_deltas, + .get_files = _cache_get_files, + .get_backup = _cache_get_backup, +}; + static int checkdbdir(pmdb_t *db) { struct stat buf; @@ -417,8 +658,10 @@ int _alpm_db_populate(pmdb_t *db) } if(db == handle->db_local) { pkg->origin = PKG_FROM_LOCALDB; + pkg->ops = &local_pkg_ops; } else { pkg->origin = PKG_FROM_SYNCDB; + pkg->ops = &sync_pkg_ops; } pkg->origin_data.db = db; /* add to the collection */ diff --git a/lib/libalpm/be_package.c b/lib/libalpm/be_package.c index 3d8c4e38..f581813c 100644 --- a/lib/libalpm/be_package.c +++ b/lib/libalpm/be_package.c @@ -234,7 +234,9 @@ static pmpkg_t *pkg_load(const char *pkgfile, int full) /* internal fields for package struct */ newpkg->origin = PKG_FROM_FILE; + /* TODO eventually kill/move this? */ newpkg->origin_data.file = strdup(pkgfile); + newpkg->ops = &default_pkg_ops; if(full) { /* "checking for conflicts" requires a sorted list, ensure that here */ diff --git a/lib/libalpm/cache.c b/lib/libalpm/cache.c index 5126f3b1..096f59d0 100644 --- a/lib/libalpm/cache.c +++ b/lib/libalpm/cache.c @@ -98,7 +98,7 @@ alpm_list_t *_alpm_db_get_pkgcache(pmdb_t *db) return(db->pkgcache); } -/* "duplicate" pkg with BASE info (to spare some memory) then add it to pkgcache */ +/* "duplicate" pkg then add it to pkgcache */ int _alpm_db_add_pkgincache(pmdb_t *db, pmpkg_t *pkg) { pmpkg_t *newpkg; @@ -109,17 +109,10 @@ int _alpm_db_add_pkgincache(pmdb_t *db, pmpkg_t *pkg) return(-1); } - newpkg = _alpm_pkg_new(); + newpkg = _alpm_pkg_dup(pkg); if(newpkg == NULL) { return(-1); } - newpkg->name = strdup(pkg->name); - newpkg->version = strdup(pkg->version); - if(newpkg->name == NULL || newpkg->version == NULL) { - pm_errno = PM_ERR_MEMORY; - _alpm_pkg_free(newpkg); - return(-1); - } _alpm_log(PM_LOG_DEBUG, "adding entry '%s' in '%s' cache\n", alpm_pkg_get_name(newpkg), db->treename); diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c index d30e6138..4f7cc2db 100644 --- a/lib/libalpm/package.c +++ b/lib/libalpm/package.c @@ -99,176 +99,187 @@ int SYMEXPORT alpm_pkg_checkmd5sum(pmpkg_t *pkg) return(retval); } -#define LAZY_LOAD(info, errret) \ - do { \ - ALPM_LOG_FUNC; \ - ASSERT(handle != NULL, return(errret)); \ - ASSERT(pkg != NULL, return(errret)); \ - if(pkg->origin != PKG_FROM_FILE && !(pkg->infolevel & info)) { \ - _alpm_db_read(pkg->origin_data.db, pkg, info); \ - } \ - } while(0) +/* Default package accessor functions. These will get overridden by any + * backend logic that needs lazy access, such as the local database through + * a lazy-laod cache. However, the defaults will work just fine for fully- + * populated package structures. */ +const char *_pkg_get_filename(pmpkg_t *pkg) { return pkg->filename; } +const char *_pkg_get_name(pmpkg_t *pkg) { return pkg->name; } +const char *_pkg_get_version(pmpkg_t *pkg) { return pkg->version; } +const char *_pkg_get_desc(pmpkg_t *pkg) { return pkg->desc; } +const char *_pkg_get_url(pmpkg_t *pkg) { return pkg->url; } +time_t _pkg_get_builddate(pmpkg_t *pkg) { return pkg->builddate; } +time_t _pkg_get_installdate(pmpkg_t *pkg) { return pkg->installdate; } +const char *_pkg_get_packager(pmpkg_t *pkg) { return pkg->packager; } +const char *_pkg_get_md5sum(pmpkg_t *pkg) { return pkg->md5sum; } +const char *_pkg_get_arch(pmpkg_t *pkg) { return pkg->arch; } +off_t _pkg_get_size(pmpkg_t *pkg) { return pkg->size; } +off_t _pkg_get_isize(pmpkg_t *pkg) { return pkg->isize; } +pmpkgreason_t _pkg_get_reason(pmpkg_t *pkg) { return pkg->reason; } +int _pkg_has_force(pmpkg_t *pkg) { return pkg->force; } +alpm_list_t *_pkg_get_licenses(pmpkg_t *pkg) { return pkg->licenses; } +alpm_list_t *_pkg_get_groups(pmpkg_t *pkg) { return pkg->groups; } +alpm_list_t *_pkg_get_depends(pmpkg_t *pkg) { return pkg->depends; } +alpm_list_t *_pkg_get_optdepends(pmpkg_t *pkg) { return pkg->optdepends; } +alpm_list_t *_pkg_get_conflicts(pmpkg_t *pkg) { return pkg->conflicts; } +alpm_list_t *_pkg_get_provides(pmpkg_t *pkg) { return pkg->provides; } +alpm_list_t *_pkg_get_replaces(pmpkg_t *pkg) { return pkg->replaces; } +alpm_list_t *_pkg_get_deltas(pmpkg_t *pkg) { return pkg->deltas; } +alpm_list_t *_pkg_get_files(pmpkg_t *pkg) { return pkg->files; } +alpm_list_t *_pkg_get_backup(pmpkg_t *pkg) { return pkg->backup; } + +/** The standard package operations struct. Get fields directly from the + * struct itself with no abstraction layer or any type of lazy loading. + */ +struct pkg_operations default_pkg_ops = { + .get_filename = _pkg_get_filename, + .get_name = _pkg_get_name, + .get_version = _pkg_get_version, + .get_desc = _pkg_get_desc, + .get_url = _pkg_get_url, + .get_builddate = _pkg_get_builddate, + .get_installdate = _pkg_get_installdate, + .get_packager = _pkg_get_packager, + .get_md5sum = _pkg_get_md5sum, + .get_arch = _pkg_get_arch, + .get_size = _pkg_get_size, + .get_isize = _pkg_get_isize, + .get_reason = _pkg_get_reason, + .has_force = _pkg_has_force, + .get_licenses = _pkg_get_licenses, + .get_groups = _pkg_get_groups, + .get_depends = _pkg_get_depends, + .get_optdepends = _pkg_get_optdepends, + .get_conflicts = _pkg_get_conflicts, + .get_provides = _pkg_get_provides, + .get_replaces = _pkg_get_replaces, + .get_deltas = _pkg_get_deltas, + .get_files = _pkg_get_files, + .get_backup = _pkg_get_backup, +}; + +/* Public functions for getting package information. These functions + * delegate the hard work to the function callbacks attached to each + * package, which depend on where the package was loaded from. */ const char SYMEXPORT *alpm_pkg_get_filename(pmpkg_t *pkg) { - LAZY_LOAD(INFRQ_DESC, NULL); - return pkg->filename; + return pkg->ops->get_filename(pkg); } const char SYMEXPORT *alpm_pkg_get_name(pmpkg_t *pkg) { - ASSERT(pkg != NULL, return(NULL)); - return pkg->name; + return pkg->ops->get_name(pkg); } const char SYMEXPORT *alpm_pkg_get_version(pmpkg_t *pkg) { - ASSERT(pkg != NULL, return(NULL)); - return pkg->version; + return pkg->ops->get_version(pkg); } const char SYMEXPORT *alpm_pkg_get_desc(pmpkg_t *pkg) { - LAZY_LOAD(INFRQ_DESC, NULL); - return pkg->desc; + return pkg->ops->get_desc(pkg); } const char SYMEXPORT *alpm_pkg_get_url(pmpkg_t *pkg) { - LAZY_LOAD(INFRQ_DESC, NULL); - return pkg->url; + return pkg->ops->get_url(pkg); } time_t SYMEXPORT alpm_pkg_get_builddate(pmpkg_t *pkg) { - LAZY_LOAD(INFRQ_DESC, 0); - return pkg->builddate; + return pkg->ops->get_builddate(pkg); } time_t SYMEXPORT alpm_pkg_get_installdate(pmpkg_t *pkg) { - LAZY_LOAD(INFRQ_DESC, 0); - return pkg->installdate; + return pkg->ops->get_installdate(pkg); } const char SYMEXPORT *alpm_pkg_get_packager(pmpkg_t *pkg) { - LAZY_LOAD(INFRQ_DESC, NULL); - return pkg->packager; + return pkg->ops->get_packager(pkg); } const char SYMEXPORT *alpm_pkg_get_md5sum(pmpkg_t *pkg) { - LAZY_LOAD(INFRQ_DESC, NULL); - return pkg->md5sum; + return pkg->ops->get_md5sum(pkg); } const char SYMEXPORT *alpm_pkg_get_arch(pmpkg_t *pkg) { - LAZY_LOAD(INFRQ_DESC, NULL); - return pkg->arch; + return pkg->ops->get_arch(pkg); } off_t SYMEXPORT alpm_pkg_get_size(pmpkg_t *pkg) { - LAZY_LOAD(INFRQ_DESC, -1); - return pkg->size; + return pkg->ops->get_size(pkg); } off_t SYMEXPORT alpm_pkg_get_isize(pmpkg_t *pkg) { - LAZY_LOAD(INFRQ_DESC, -1); - return pkg->isize; + return pkg->ops->get_isize(pkg); } pmpkgreason_t SYMEXPORT alpm_pkg_get_reason(pmpkg_t *pkg) { - LAZY_LOAD(INFRQ_DESC, -1); - return pkg->reason; -} - -alpm_list_t SYMEXPORT *alpm_pkg_get_licenses(pmpkg_t *pkg) -{ - LAZY_LOAD(INFRQ_DESC, NULL); - return pkg->licenses; -} - -alpm_list_t SYMEXPORT *alpm_pkg_get_groups(pmpkg_t *pkg) -{ - LAZY_LOAD(INFRQ_DESC, NULL); - return pkg->groups; + return pkg->ops->get_reason(pkg); } int SYMEXPORT alpm_pkg_has_force(pmpkg_t *pkg) { - LAZY_LOAD(INFRQ_DESC, -1); - return pkg->force; + return pkg->ops->has_force(pkg); +} + +alpm_list_t SYMEXPORT *alpm_pkg_get_licenses(pmpkg_t *pkg) +{ + return pkg->ops->get_licenses(pkg); +} + +alpm_list_t SYMEXPORT *alpm_pkg_get_groups(pmpkg_t *pkg) +{ + return pkg->ops->get_groups(pkg); } alpm_list_t SYMEXPORT *alpm_pkg_get_depends(pmpkg_t *pkg) { - LAZY_LOAD(INFRQ_DEPENDS, NULL); - return pkg->depends; + return pkg->ops->get_depends(pkg); } alpm_list_t SYMEXPORT *alpm_pkg_get_optdepends(pmpkg_t *pkg) { - LAZY_LOAD(INFRQ_DEPENDS, NULL); - return pkg->optdepends; + return pkg->ops->get_optdepends(pkg); } alpm_list_t SYMEXPORT *alpm_pkg_get_conflicts(pmpkg_t *pkg) { - LAZY_LOAD(INFRQ_DEPENDS, NULL); - return pkg->conflicts; + return pkg->ops->get_conflicts(pkg); } alpm_list_t SYMEXPORT *alpm_pkg_get_provides(pmpkg_t *pkg) { - LAZY_LOAD(INFRQ_DEPENDS, NULL); - return pkg->provides; -} - -alpm_list_t SYMEXPORT *alpm_pkg_get_deltas(pmpkg_t *pkg) -{ - LAZY_LOAD(INFRQ_DELTAS, NULL); - return pkg->deltas; + return pkg->ops->get_provides(pkg); } alpm_list_t SYMEXPORT *alpm_pkg_get_replaces(pmpkg_t *pkg) { - LAZY_LOAD(INFRQ_DESC, NULL); - return pkg->replaces; + return pkg->ops->get_replaces(pkg); +} + +alpm_list_t SYMEXPORT *alpm_pkg_get_deltas(pmpkg_t *pkg) +{ + return pkg->ops->get_deltas(pkg); } alpm_list_t SYMEXPORT *alpm_pkg_get_files(pmpkg_t *pkg) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(pkg != NULL, return(NULL)); - - if(pkg->origin == PKG_FROM_LOCALDB - && !(pkg->infolevel & INFRQ_FILES)) { - _alpm_db_read(pkg->origin_data.db, pkg, INFRQ_FILES); - } - return pkg->files; + return pkg->ops->get_files(pkg); } alpm_list_t SYMEXPORT *alpm_pkg_get_backup(pmpkg_t *pkg) { - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(pkg != NULL, return(NULL)); - - if(pkg->origin == PKG_FROM_LOCALDB - && !(pkg->infolevel & INFRQ_FILES)) { - _alpm_db_read(pkg->origin_data.db, pkg, INFRQ_FILES); - } - return pkg->backup; + return pkg->ops->get_backup(pkg); } pmdb_t SYMEXPORT *alpm_pkg_get_db(pmpkg_t *pkg) @@ -517,6 +528,7 @@ pmpkg_t *_alpm_pkg_dup(pmpkg_t *pkg) /* internal */ newpkg->origin = pkg->origin; + newpkg->ops = pkg->ops; if(newpkg->origin == PKG_FROM_FILE) { newpkg->origin_data.file = strdup(pkg->origin_data.file); } else { diff --git a/lib/libalpm/package.h b/lib/libalpm/package.h index daff9717..5ad553ac 100644 --- a/lib/libalpm/package.h +++ b/lib/libalpm/package.h @@ -36,6 +36,60 @@ typedef enum _pmpkgfrom_t { PKG_FROM_SYNCDB } pmpkgfrom_t; +/** Package operations struct. This struct contains function pointers to + * all methods used to access data in a package to allow for things such + * as lazy package intialization (such as used by the file backend). Each + * backend is free to define a stuct containing pointers to a specific + * implementation of these methods. Some backends may find using the + * defined default_pkg_ops struct to work just fine for their needs. + */ +struct pkg_operations { + const char *(*get_filename) (pmpkg_t *); + const char *(*get_name) (pmpkg_t *); + const char *(*get_version) (pmpkg_t *); + const char *(*get_desc) (pmpkg_t *); + const char *(*get_url) (pmpkg_t *); + time_t (*get_builddate) (pmpkg_t *); + time_t (*get_installdate) (pmpkg_t *); + const char *(*get_packager) (pmpkg_t *); + const char *(*get_md5sum) (pmpkg_t *); + const char *(*get_arch) (pmpkg_t *); + off_t (*get_size) (pmpkg_t *); + off_t (*get_isize) (pmpkg_t *); + pmpkgreason_t (*get_reason) (pmpkg_t *); + int (*has_force) (pmpkg_t *); + + alpm_list_t *(*get_licenses) (pmpkg_t *); + alpm_list_t *(*get_groups) (pmpkg_t *); + alpm_list_t *(*get_depends) (pmpkg_t *); + alpm_list_t *(*get_optdepends) (pmpkg_t *); + alpm_list_t *(*get_conflicts) (pmpkg_t *); + alpm_list_t *(*get_provides) (pmpkg_t *); + alpm_list_t *(*get_replaces) (pmpkg_t *); + alpm_list_t *(*get_deltas) (pmpkg_t *); + alpm_list_t *(*get_files) (pmpkg_t *); + alpm_list_t *(*get_backup) (pmpkg_t *); + + void *(*changelog_open) (pmpkg_t *); + size_t (*changelog_read) (void *, size_t, const pmpkg_t *, const void *); + int (*changelog_close) (const pmpkg_t *, void *); + + /* still to add: + * free() + * dup() + * checkmd5sum() ? + * has_scriptlet() + * compute_requiredby() + */ +}; + +/** The standard package operations struct. get fields directly from the + * struct itself with no abstraction layer or any type of lazy loading. + * The actual definition is in package.c so it can have access to the + * default accessor functions which are defined there. + */ +extern struct pkg_operations default_pkg_ops; + struct __pmpkg_t { char *filename; char *name; @@ -76,6 +130,8 @@ struct __pmpkg_t { char *file; } origin_data; pmdbinfrq_t infolevel; + + struct pkg_operations *ops; }; pmpkg_t* _alpm_pkg_new(void);