libalpm
Arch Linux Package Manager Library
package.c
Go to the documentation of this file.
00001 /*
00002  *  package.c
00003  *
00004  *  Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
00005  *  Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
00006  *  Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>
00007  *  Copyright (c) 2005, 2006 by Christian Hamar <krics@linuxforum.hu>
00008  *  Copyright (c) 2005, 2006 by Miklos Vajna <vmiklos@frugalware.org>
00009  *
00010  *  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version.
00014  *
00015  *  This program is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  *  GNU General Public License for more details.
00019  *
00020  *  You should have received a copy of the GNU General Public License
00021  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00022  */
00023 
00024 #include <stdlib.h>
00025 #include <string.h>
00026 #include <sys/types.h>
00027 
00028 /* libalpm */
00029 #include "package.h"
00030 #include "alpm_list.h"
00031 #include "log.h"
00032 #include "util.h"
00033 #include "db.h"
00034 #include "delta.h"
00035 #include "handle.h"
00036 #include "deps.h"
00037 
00038 /** \addtogroup alpm_packages Package Functions
00039  * @brief Functions to manipulate libalpm packages
00040  * @{
00041  */
00042 
00043 /** Free a package. */
00044 int SYMEXPORT alpm_pkg_free(alpm_pkg_t *pkg)
00045 {
00046     ASSERT(pkg != NULL, return -1);
00047 
00048     /* Only free packages loaded in user space */
00049     if(pkg->origin == PKG_FROM_FILE) {
00050         _alpm_pkg_free(pkg);
00051     }
00052 
00053     return 0;
00054 }
00055 
00056 /** Check the integrity (with md5) of a package from the sync cache. */
00057 int SYMEXPORT alpm_pkg_checkmd5sum(alpm_pkg_t *pkg)
00058 {
00059     char *fpath;
00060     int retval;
00061 
00062     ASSERT(pkg != NULL, return -1);
00063     pkg->handle->pm_errno = 0;
00064     /* We only inspect packages from sync repositories */
00065     ASSERT(pkg->origin == PKG_FROM_SYNCDB,
00066             RET_ERR(pkg->handle, ALPM_ERR_WRONG_ARGS, -1));
00067 
00068     fpath = _alpm_filecache_find(pkg->handle, pkg->filename);
00069 
00070     retval = _alpm_test_checksum(fpath, pkg->md5sum, ALPM_CSUM_MD5);
00071 
00072     if(retval == 0) {
00073         return 0;
00074     } else if(retval == 1) {
00075         pkg->handle->pm_errno = ALPM_ERR_PKG_INVALID;
00076         retval = -1;
00077     }
00078 
00079     return retval;
00080 }
00081 
00082 /* Default package accessor functions. These will get overridden by any
00083  * backend logic that needs lazy access, such as the local database through
00084  * a lazy-load cache. However, the defaults will work just fine for fully-
00085  * populated package structures. */
00086 static const char *_pkg_get_desc(alpm_pkg_t *pkg)        { return pkg->desc; }
00087 static const char *_pkg_get_url(alpm_pkg_t *pkg)         { return pkg->url; }
00088 static alpm_time_t _pkg_get_builddate(alpm_pkg_t *pkg)   { return pkg->builddate; }
00089 static alpm_time_t _pkg_get_installdate(alpm_pkg_t *pkg) { return pkg->installdate; }
00090 static const char *_pkg_get_packager(alpm_pkg_t *pkg)    { return pkg->packager; }
00091 static const char *_pkg_get_arch(alpm_pkg_t *pkg)        { return pkg->arch; }
00092 static off_t _pkg_get_isize(alpm_pkg_t *pkg)             { return pkg->isize; }
00093 static alpm_pkgreason_t _pkg_get_reason(alpm_pkg_t *pkg) { return pkg->reason; }
00094 static int _pkg_has_scriptlet(alpm_pkg_t *pkg)           { return pkg->scriptlet; }
00095 
00096 static alpm_list_t *_pkg_get_licenses(alpm_pkg_t *pkg)   { return pkg->licenses; }
00097 static alpm_list_t *_pkg_get_groups(alpm_pkg_t *pkg)     { return pkg->groups; }
00098 static alpm_list_t *_pkg_get_depends(alpm_pkg_t *pkg)    { return pkg->depends; }
00099 static alpm_list_t *_pkg_get_optdepends(alpm_pkg_t *pkg) { return pkg->optdepends; }
00100 static alpm_list_t *_pkg_get_conflicts(alpm_pkg_t *pkg)  { return pkg->conflicts; }
00101 static alpm_list_t *_pkg_get_provides(alpm_pkg_t *pkg)   { return pkg->provides; }
00102 static alpm_list_t *_pkg_get_replaces(alpm_pkg_t *pkg)   { return pkg->replaces; }
00103 static alpm_filelist_t *_pkg_get_files(alpm_pkg_t *pkg)  { return &(pkg->files); }
00104 static alpm_list_t *_pkg_get_backup(alpm_pkg_t *pkg)     { return pkg->backup; }
00105 
00106 static void *_pkg_changelog_open(alpm_pkg_t UNUSED *pkg)
00107 {
00108     return NULL;
00109 }
00110 
00111 static size_t _pkg_changelog_read(void UNUSED *ptr, size_t UNUSED size,
00112         const alpm_pkg_t UNUSED *pkg, UNUSED void *fp)
00113 {
00114     return 0;
00115 }
00116 
00117 static int _pkg_changelog_close(const alpm_pkg_t UNUSED *pkg,
00118         void UNUSED *fp)
00119 {
00120     return EOF;
00121 }
00122 
00123 static int _pkg_force_load(alpm_pkg_t UNUSED *pkg) { return 0; }
00124 
00125 /** The standard package operations struct. Get fields directly from the
00126  * struct itself with no abstraction layer or any type of lazy loading.
00127  */
00128 struct pkg_operations default_pkg_ops = {
00129     .get_desc        = _pkg_get_desc,
00130     .get_url         = _pkg_get_url,
00131     .get_builddate   = _pkg_get_builddate,
00132     .get_installdate = _pkg_get_installdate,
00133     .get_packager    = _pkg_get_packager,
00134     .get_arch        = _pkg_get_arch,
00135     .get_isize       = _pkg_get_isize,
00136     .get_reason      = _pkg_get_reason,
00137     .has_scriptlet   = _pkg_has_scriptlet,
00138 
00139     .get_licenses    = _pkg_get_licenses,
00140     .get_groups      = _pkg_get_groups,
00141     .get_depends     = _pkg_get_depends,
00142     .get_optdepends  = _pkg_get_optdepends,
00143     .get_conflicts   = _pkg_get_conflicts,
00144     .get_provides    = _pkg_get_provides,
00145     .get_replaces    = _pkg_get_replaces,
00146     .get_files       = _pkg_get_files,
00147     .get_backup      = _pkg_get_backup,
00148 
00149     .changelog_open  = _pkg_changelog_open,
00150     .changelog_read  = _pkg_changelog_read,
00151     .changelog_close = _pkg_changelog_close,
00152 
00153     .force_load      = _pkg_force_load,
00154 };
00155 
00156 /* Public functions for getting package information. These functions
00157  * delegate the hard work to the function callbacks attached to each
00158  * package, which depend on where the package was loaded from. */
00159 const char SYMEXPORT *alpm_pkg_get_filename(alpm_pkg_t *pkg)
00160 {
00161     ASSERT(pkg != NULL, return NULL);
00162     pkg->handle->pm_errno = 0;
00163     return pkg->filename;
00164 }
00165 
00166 const char SYMEXPORT *alpm_pkg_get_name(alpm_pkg_t *pkg)
00167 {
00168     ASSERT(pkg != NULL, return NULL);
00169     pkg->handle->pm_errno = 0;
00170     return pkg->name;
00171 }
00172 
00173 const char SYMEXPORT *alpm_pkg_get_version(alpm_pkg_t *pkg)
00174 {
00175     ASSERT(pkg != NULL, return NULL);
00176     pkg->handle->pm_errno = 0;
00177     return pkg->version;
00178 }
00179 
00180 alpm_pkgfrom_t SYMEXPORT alpm_pkg_get_origin(alpm_pkg_t *pkg)
00181 {
00182     ASSERT(pkg != NULL, return -1);
00183     pkg->handle->pm_errno = 0;
00184     return pkg->origin;
00185 }
00186 
00187 const char SYMEXPORT *alpm_pkg_get_desc(alpm_pkg_t *pkg)
00188 {
00189     ASSERT(pkg != NULL, return NULL);
00190     pkg->handle->pm_errno = 0;
00191     return pkg->ops->get_desc(pkg);
00192 }
00193 
00194 const char SYMEXPORT *alpm_pkg_get_url(alpm_pkg_t *pkg)
00195 {
00196     ASSERT(pkg != NULL, return NULL);
00197     pkg->handle->pm_errno = 0;
00198     return pkg->ops->get_url(pkg);
00199 }
00200 
00201 alpm_time_t SYMEXPORT alpm_pkg_get_builddate(alpm_pkg_t *pkg)
00202 {
00203     ASSERT(pkg != NULL, return -1);
00204     pkg->handle->pm_errno = 0;
00205     return pkg->ops->get_builddate(pkg);
00206 }
00207 
00208 alpm_time_t SYMEXPORT alpm_pkg_get_installdate(alpm_pkg_t *pkg)
00209 {
00210     ASSERT(pkg != NULL, return -1);
00211     pkg->handle->pm_errno = 0;
00212     return pkg->ops->get_installdate(pkg);
00213 }
00214 
00215 const char SYMEXPORT *alpm_pkg_get_packager(alpm_pkg_t *pkg)
00216 {
00217     ASSERT(pkg != NULL, return NULL);
00218     pkg->handle->pm_errno = 0;
00219     return pkg->ops->get_packager(pkg);
00220 }
00221 
00222 const char SYMEXPORT *alpm_pkg_get_md5sum(alpm_pkg_t *pkg)
00223 {
00224     ASSERT(pkg != NULL, return NULL);
00225     pkg->handle->pm_errno = 0;
00226     return pkg->md5sum;
00227 }
00228 
00229 const char SYMEXPORT *alpm_pkg_get_sha256sum(alpm_pkg_t *pkg)
00230 {
00231     ASSERT(pkg != NULL, return NULL);
00232     pkg->handle->pm_errno = 0;
00233     return pkg->sha256sum;
00234 }
00235 
00236 const char SYMEXPORT *alpm_pkg_get_base64_sig(alpm_pkg_t *pkg)
00237 {
00238     ASSERT(pkg != NULL, return NULL);
00239     pkg->handle->pm_errno = 0;
00240     return pkg->base64_sig;
00241 }
00242 
00243 const char SYMEXPORT *alpm_pkg_get_arch(alpm_pkg_t *pkg)
00244 {
00245     ASSERT(pkg != NULL, return NULL);
00246     pkg->handle->pm_errno = 0;
00247     return pkg->ops->get_arch(pkg);
00248 }
00249 
00250 off_t SYMEXPORT alpm_pkg_get_size(alpm_pkg_t *pkg)
00251 {
00252     ASSERT(pkg != NULL, return -1);
00253     pkg->handle->pm_errno = 0;
00254     return pkg->size;
00255 }
00256 
00257 off_t SYMEXPORT alpm_pkg_get_isize(alpm_pkg_t *pkg)
00258 {
00259     ASSERT(pkg != NULL, return -1);
00260     pkg->handle->pm_errno = 0;
00261     return pkg->ops->get_isize(pkg);
00262 }
00263 
00264 alpm_pkgreason_t SYMEXPORT alpm_pkg_get_reason(alpm_pkg_t *pkg)
00265 {
00266     ASSERT(pkg != NULL, return -1);
00267     pkg->handle->pm_errno = 0;
00268     return pkg->ops->get_reason(pkg);
00269 }
00270 
00271 alpm_list_t SYMEXPORT *alpm_pkg_get_licenses(alpm_pkg_t *pkg)
00272 {
00273     ASSERT(pkg != NULL, return NULL);
00274     pkg->handle->pm_errno = 0;
00275     return pkg->ops->get_licenses(pkg);
00276 }
00277 
00278 alpm_list_t SYMEXPORT *alpm_pkg_get_groups(alpm_pkg_t *pkg)
00279 {
00280     ASSERT(pkg != NULL, return NULL);
00281     pkg->handle->pm_errno = 0;
00282     return pkg->ops->get_groups(pkg);
00283 }
00284 
00285 alpm_list_t SYMEXPORT *alpm_pkg_get_depends(alpm_pkg_t *pkg)
00286 {
00287     ASSERT(pkg != NULL, return NULL);
00288     pkg->handle->pm_errno = 0;
00289     return pkg->ops->get_depends(pkg);
00290 }
00291 
00292 alpm_list_t SYMEXPORT *alpm_pkg_get_optdepends(alpm_pkg_t *pkg)
00293 {
00294     ASSERT(pkg != NULL, return NULL);
00295     pkg->handle->pm_errno = 0;
00296     return pkg->ops->get_optdepends(pkg);
00297 }
00298 
00299 alpm_list_t SYMEXPORT *alpm_pkg_get_conflicts(alpm_pkg_t *pkg)
00300 {
00301     ASSERT(pkg != NULL, return NULL);
00302     pkg->handle->pm_errno = 0;
00303     return pkg->ops->get_conflicts(pkg);
00304 }
00305 
00306 alpm_list_t SYMEXPORT *alpm_pkg_get_provides(alpm_pkg_t *pkg)
00307 {
00308     ASSERT(pkg != NULL, return NULL);
00309     pkg->handle->pm_errno = 0;
00310     return pkg->ops->get_provides(pkg);
00311 }
00312 
00313 alpm_list_t SYMEXPORT *alpm_pkg_get_replaces(alpm_pkg_t *pkg)
00314 {
00315     ASSERT(pkg != NULL, return NULL);
00316     pkg->handle->pm_errno = 0;
00317     return pkg->ops->get_replaces(pkg);
00318 }
00319 
00320 alpm_list_t SYMEXPORT *alpm_pkg_get_deltas(alpm_pkg_t *pkg)
00321 {
00322     ASSERT(pkg != NULL, return NULL);
00323     pkg->handle->pm_errno = 0;
00324     return pkg->deltas;
00325 }
00326 
00327 alpm_filelist_t SYMEXPORT *alpm_pkg_get_files(alpm_pkg_t *pkg)
00328 {
00329     ASSERT(pkg != NULL, return NULL);
00330     pkg->handle->pm_errno = 0;
00331     return pkg->ops->get_files(pkg);
00332 }
00333 
00334 alpm_list_t SYMEXPORT *alpm_pkg_get_backup(alpm_pkg_t *pkg)
00335 {
00336     ASSERT(pkg != NULL, return NULL);
00337     pkg->handle->pm_errno = 0;
00338     return pkg->ops->get_backup(pkg);
00339 }
00340 
00341 alpm_db_t SYMEXPORT *alpm_pkg_get_db(alpm_pkg_t *pkg)
00342 {
00343     /* Sanity checks */
00344     ASSERT(pkg != NULL, return NULL);
00345     ASSERT(pkg->origin != PKG_FROM_FILE, return NULL);
00346     pkg->handle->pm_errno = 0;
00347 
00348     return pkg->origin_data.db;
00349 }
00350 
00351 /** Open a package changelog for reading. */
00352 void SYMEXPORT *alpm_pkg_changelog_open(alpm_pkg_t *pkg)
00353 {
00354     ASSERT(pkg != NULL, return NULL);
00355     pkg->handle->pm_errno = 0;
00356     return pkg->ops->changelog_open(pkg);
00357 }
00358 
00359 /** Read data from an open changelog 'file stream'. */
00360 size_t SYMEXPORT alpm_pkg_changelog_read(void *ptr, size_t size,
00361         const alpm_pkg_t *pkg, void *fp)
00362 {
00363     ASSERT(pkg != NULL, return 0);
00364     pkg->handle->pm_errno = 0;
00365     return pkg->ops->changelog_read(ptr, size, pkg, fp);
00366 }
00367 
00368 /** Close a package changelog for reading. */
00369 int SYMEXPORT alpm_pkg_changelog_close(const alpm_pkg_t *pkg, void *fp)
00370 {
00371     ASSERT(pkg != NULL, return -1);
00372     pkg->handle->pm_errno = 0;
00373     return pkg->ops->changelog_close(pkg, fp);
00374 }
00375 
00376 int SYMEXPORT alpm_pkg_has_scriptlet(alpm_pkg_t *pkg)
00377 {
00378     ASSERT(pkg != NULL, return -1);
00379     pkg->handle->pm_errno = 0;
00380     return pkg->ops->has_scriptlet(pkg);
00381 }
00382 
00383 static void find_requiredby(alpm_pkg_t *pkg, alpm_db_t *db, alpm_list_t **reqs)
00384 {
00385     const alpm_list_t *i;
00386     pkg->handle->pm_errno = 0;
00387 
00388     for(i = _alpm_db_get_pkgcache(db); i; i = i->next) {
00389         alpm_pkg_t *cachepkg = i->data;
00390         alpm_list_t *j;
00391         for(j = alpm_pkg_get_depends(cachepkg); j; j = j->next) {
00392             if(_alpm_depcmp(pkg, j->data)) {
00393                 const char *cachepkgname = cachepkg->name;
00394                 if(alpm_list_find_str(*reqs, cachepkgname) == NULL) {
00395                     *reqs = alpm_list_add(*reqs, strdup(cachepkgname));
00396                 }
00397             }
00398         }
00399     }
00400 }
00401 
00402 /** Compute the packages requiring a given package. */
00403 alpm_list_t SYMEXPORT *alpm_pkg_compute_requiredby(alpm_pkg_t *pkg)
00404 {
00405     const alpm_list_t *i;
00406     alpm_list_t *reqs = NULL;
00407     alpm_db_t *db;
00408 
00409     ASSERT(pkg != NULL, return NULL);
00410     pkg->handle->pm_errno = 0;
00411 
00412     if(pkg->origin == PKG_FROM_FILE) {
00413         /* The sane option; search locally for things that require this. */
00414         find_requiredby(pkg, pkg->handle->db_local, &reqs);
00415     } else {
00416         /* We have a DB package. if it is a local package, then we should
00417          * only search the local DB; else search all known sync databases. */
00418         db = pkg->origin_data.db;
00419         if(db->status & DB_STATUS_LOCAL) {
00420             find_requiredby(pkg, db, &reqs);
00421         } else {
00422             for(i = pkg->handle->dbs_sync; i; i = i->next) {
00423                 db = i->data;
00424                 find_requiredby(pkg, db, &reqs);
00425             }
00426             reqs = alpm_list_msort(reqs, alpm_list_count(reqs), _alpm_str_cmp);
00427         }
00428     }
00429     return reqs;
00430 }
00431 
00432 /** @} */
00433 
00434 alpm_file_t *_alpm_file_copy(alpm_file_t *dest,
00435         const alpm_file_t *src)
00436 {
00437     STRDUP(dest->name, src->name, return NULL);
00438     dest->size = src->size;
00439     dest->mode = src->mode;
00440 
00441     return dest;
00442 }
00443 
00444 /* Helper function for comparing files list entries
00445  */
00446 int _alpm_files_cmp(const void *f1, const void *f2)
00447 {
00448     const alpm_file_t *file1 = f1;
00449     const alpm_file_t *file2 = f2;
00450     return strcmp(file1->name, file2->name);
00451 }
00452 
00453 alpm_pkg_t *_alpm_pkg_new(void)
00454 {
00455     alpm_pkg_t* pkg;
00456 
00457     CALLOC(pkg, 1, sizeof(alpm_pkg_t), return NULL);
00458 
00459     return pkg;
00460 }
00461 
00462 static alpm_list_t *list_depdup(alpm_list_t *old)
00463 {
00464     alpm_list_t *i, *new = NULL;
00465     for(i = old; i; i = i->next) {
00466         new = alpm_list_add(new, _alpm_dep_dup(i->data));
00467     }
00468     return new;
00469 }
00470 
00471 /**
00472  * Duplicate a package data struct.
00473  * @param pkg the package to duplicate
00474  * @param new_ptr location to store duplicated package pointer
00475  * @return 0 on success, -1 on fatal error, 1 on non-fatal error
00476  */
00477 int _alpm_pkg_dup(alpm_pkg_t *pkg, alpm_pkg_t **new_ptr)
00478 {
00479     alpm_pkg_t *newpkg;
00480     alpm_list_t *i;
00481     int ret = 0;
00482 
00483     if(!pkg || !pkg->handle) {
00484         return -1;
00485     }
00486 
00487     if(!new_ptr) {
00488         RET_ERR(pkg->handle, ALPM_ERR_WRONG_ARGS, -1);
00489     }
00490 
00491     if(pkg->ops->force_load(pkg)) {
00492         _alpm_log(pkg->handle, ALPM_LOG_WARNING,
00493                 _("could not fully load metadata for package %s-%s\n"),
00494                 pkg->name, pkg->version);
00495         ret = 1;
00496         pkg->handle->pm_errno = ALPM_ERR_PKG_INVALID;
00497     }
00498 
00499     CALLOC(newpkg, 1, sizeof(alpm_pkg_t), goto cleanup);
00500 
00501     newpkg->name_hash = pkg->name_hash;
00502     STRDUP(newpkg->filename, pkg->filename, goto cleanup);
00503     STRDUP(newpkg->name, pkg->name, goto cleanup);
00504     STRDUP(newpkg->version, pkg->version, goto cleanup);
00505     STRDUP(newpkg->desc, pkg->desc, goto cleanup);
00506     STRDUP(newpkg->url, pkg->url, goto cleanup);
00507     newpkg->builddate = pkg->builddate;
00508     newpkg->installdate = pkg->installdate;
00509     STRDUP(newpkg->packager, pkg->packager, goto cleanup);
00510     STRDUP(newpkg->md5sum, pkg->md5sum, goto cleanup);
00511     STRDUP(newpkg->sha256sum, pkg->md5sum, goto cleanup);
00512     STRDUP(newpkg->arch, pkg->arch, goto cleanup);
00513     newpkg->size = pkg->size;
00514     newpkg->isize = pkg->isize;
00515     newpkg->scriptlet = pkg->scriptlet;
00516     newpkg->reason = pkg->reason;
00517 
00518     newpkg->licenses   = alpm_list_strdup(pkg->licenses);
00519     newpkg->replaces   = list_depdup(pkg->replaces);
00520     newpkg->groups     = alpm_list_strdup(pkg->groups);
00521     for(i = pkg->backup; i; i = i->next) {
00522         newpkg->backup = alpm_list_add(newpkg->backup, _alpm_backup_dup(i->data));
00523     }
00524     newpkg->depends    = list_depdup(pkg->depends);
00525     newpkg->optdepends = alpm_list_strdup(pkg->optdepends);
00526     newpkg->conflicts  = list_depdup(pkg->conflicts);
00527     newpkg->provides   = list_depdup(pkg->provides);
00528     for(i = pkg->deltas; i; i = i->next) {
00529         newpkg->deltas = alpm_list_add(newpkg->deltas, _alpm_delta_dup(i->data));
00530     }
00531 
00532     if(pkg->files.count) {
00533         size_t filenum;
00534         size_t len = sizeof(alpm_file_t) * pkg->files.count;
00535         MALLOC(newpkg->files.files, len, goto cleanup);
00536         for(filenum = 0; filenum < pkg->files.count; filenum++) {
00537             if(!_alpm_file_copy(newpkg->files.files + filenum,
00538                         pkg->files.files + filenum)) {
00539                 goto cleanup;
00540             }
00541         }
00542         newpkg->files.count = pkg->files.count;
00543     }
00544 
00545     /* internal */
00546     newpkg->infolevel = pkg->infolevel;
00547     newpkg->origin = pkg->origin;
00548     if(newpkg->origin == PKG_FROM_FILE) {
00549         newpkg->origin_data.file = strdup(pkg->origin_data.file);
00550     } else {
00551         newpkg->origin_data.db = pkg->origin_data.db;
00552     }
00553     newpkg->ops = pkg->ops;
00554     newpkg->handle = pkg->handle;
00555 
00556     *new_ptr = newpkg;
00557     return ret;
00558 
00559 cleanup:
00560     _alpm_pkg_free(newpkg);
00561     RET_ERR(pkg->handle, ALPM_ERR_MEMORY, -1);
00562 }
00563 
00564 static void free_deplist(alpm_list_t *deps)
00565 {
00566     alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_dep_free);
00567     alpm_list_free(deps);
00568 }
00569 
00570 void _alpm_pkg_free(alpm_pkg_t *pkg)
00571 {
00572     if(pkg == NULL) {
00573         return;
00574     }
00575 
00576     FREE(pkg->filename);
00577     FREE(pkg->name);
00578     FREE(pkg->version);
00579     FREE(pkg->desc);
00580     FREE(pkg->url);
00581     FREE(pkg->packager);
00582     FREE(pkg->md5sum);
00583     FREE(pkg->sha256sum);
00584     FREE(pkg->base64_sig);
00585     FREE(pkg->arch);
00586 
00587     FREELIST(pkg->licenses);
00588     free_deplist(pkg->replaces);
00589     FREELIST(pkg->groups);
00590     if(pkg->files.count) {
00591         size_t i;
00592         for(i = 0; i < pkg->files.count; i++) {
00593             free(pkg->files.files[i].name);
00594         }
00595         free(pkg->files.files);
00596     }
00597     alpm_list_free_inner(pkg->backup, (alpm_list_fn_free)_alpm_backup_free);
00598     alpm_list_free(pkg->backup);
00599     free_deplist(pkg->depends);
00600     FREELIST(pkg->optdepends);
00601     free_deplist(pkg->conflicts);
00602     free_deplist(pkg->provides);
00603     alpm_list_free_inner(pkg->deltas, (alpm_list_fn_free)_alpm_delta_free);
00604     alpm_list_free(pkg->deltas);
00605     alpm_list_free(pkg->delta_path);
00606     alpm_list_free(pkg->removes);
00607 
00608     if(pkg->origin == PKG_FROM_FILE) {
00609         FREE(pkg->origin_data.file);
00610     }
00611     FREE(pkg);
00612 }
00613 
00614 /* This function should be used when removing a target from upgrade/sync target list
00615  * Case 1: If pkg is a loaded package file (PKG_FROM_FILE), it will be freed.
00616  * Case 2: If pkg is a pkgcache entry (PKG_FROM_CACHE), it won't be freed,
00617  *         only the transaction specific fields of pkg will be freed.
00618  */
00619 void _alpm_pkg_free_trans(alpm_pkg_t *pkg)
00620 {
00621     if(pkg == NULL) {
00622         return;
00623     }
00624 
00625     if(pkg->origin == PKG_FROM_FILE) {
00626         _alpm_pkg_free(pkg);
00627         return;
00628     }
00629 
00630     alpm_list_free(pkg->removes);
00631     pkg->removes = NULL;
00632 }
00633 
00634 /* Is spkg an upgrade for localpkg? */
00635 int _alpm_pkg_compare_versions(alpm_pkg_t *spkg, alpm_pkg_t *localpkg)
00636 {
00637     return alpm_pkg_vercmp(spkg->version, localpkg->version);
00638 }
00639 
00640 /* Helper function for comparing packages
00641  */
00642 int _alpm_pkg_cmp(const void *p1, const void *p2)
00643 {
00644     const alpm_pkg_t *pkg1 = p1;
00645     const alpm_pkg_t *pkg2 = p2;
00646     return strcmp(pkg1->name, pkg2->name);
00647 }
00648 
00649 /* Test for existence of a package in a alpm_list_t*
00650  * of alpm_pkg_t*
00651  */
00652 alpm_pkg_t *_alpm_pkg_find(alpm_list_t *haystack, const char *needle)
00653 {
00654     alpm_list_t *lp;
00655     unsigned long needle_hash;
00656 
00657     if(needle == NULL || haystack == NULL) {
00658         return NULL;
00659     }
00660 
00661     needle_hash = _alpm_hash_sdbm(needle);
00662 
00663     for(lp = haystack; lp; lp = lp->next) {
00664         alpm_pkg_t *info = lp->data;
00665 
00666         if(info) {
00667             if(info->name_hash != needle_hash) {
00668                 continue;
00669             }
00670 
00671             /* finally: we had hash match, verify string match */
00672             if(strcmp(info->name, needle) == 0) {
00673                 return info;
00674             }
00675         }
00676     }
00677     return NULL;
00678 }
00679 
00680 /** Test if a package should be ignored.
00681  *
00682  * Checks if the package is ignored via IgnorePkg, or if the package is
00683  * in a group ignored via IgnoreGroup.
00684  *
00685  * @param handle the context handle
00686  * @param pkg the package to test
00687  *
00688  * @return 1 if the package should be ignored, 0 otherwise
00689  */
00690 int _alpm_pkg_should_ignore(alpm_handle_t *handle, alpm_pkg_t *pkg)
00691 {
00692     alpm_list_t *groups = NULL;
00693 
00694     /* first see if the package is ignored */
00695     if(alpm_list_find(handle->ignorepkg, pkg->name, _alpm_fnmatch)) {
00696         return 1;
00697     }
00698 
00699     /* next see if the package is in a group that is ignored */
00700     for(groups = alpm_pkg_get_groups(pkg); groups; groups = groups->next) {
00701         char *grp = groups->data;
00702         if(alpm_list_find(handle->ignoregroup, grp, _alpm_fnmatch)) {
00703             return 1;
00704         }
00705     }
00706 
00707     return 0;
00708 }
00709 
00710 /* vim: set ts=2 sw=2 noet: */