Fix documentation syntax and typo
[pacman-ng.git] / lib / libalpm / package.c
blob682ff90c9d5e3db17bc53913eeeacc8c67274d23
1 /*
2 * package.c
4 * Copyright (c) 2006-2010 Pacman Development Team <pacman-dev@archlinux.org>
5 * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
6 * Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>
7 * Copyright (c) 2005, 2006 by Christian Hamar <krics@linuxforum.hu>
8 * Copyright (c) 2005, 2006 by Miklos Vajna <vmiklos@frugalware.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "config.h"
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <limits.h>
29 #include <string.h>
30 #include <ctype.h>
31 #include <errno.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
35 /* libarchive */
36 #include <archive.h>
37 #include <archive_entry.h>
39 /* libalpm */
40 #include "package.h"
41 #include "alpm_list.h"
42 #include "log.h"
43 #include "util.h"
44 #include "db.h"
45 #include "delta.h"
46 #include "handle.h"
47 #include "deps.h"
49 /** \addtogroup alpm_packages Package Functions
50 * @brief Functions to manipulate libalpm packages
51 * @{
54 /** Free a package.
55 * @param pkg package pointer to free
56 * @return 0 on success, -1 on error (pm_errno is set accordingly)
58 int SYMEXPORT alpm_pkg_free(pmpkg_t *pkg)
60 ALPM_LOG_FUNC;
62 ASSERT(pkg != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1));
64 /* Only free packages loaded in user space */
65 if(pkg->origin == PKG_FROM_FILE) {
66 _alpm_pkg_free(pkg);
69 return(0);
72 /** Check the integrity (with md5) of a package from the sync cache.
73 * @param pkg package pointer
74 * @return 0 on success, -1 on error (pm_errno is set accordingly)
76 int SYMEXPORT alpm_pkg_checkmd5sum(pmpkg_t *pkg)
78 char *fpath;
79 int retval;
81 ALPM_LOG_FUNC;
83 ASSERT(pkg != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1));
84 /* We only inspect packages from sync repositories */
85 ASSERT(pkg->origin == PKG_FROM_SYNCDB, RET_ERR(PM_ERR_PKG_INVALID, -1));
87 fpath = _alpm_filecache_find(alpm_pkg_get_filename(pkg));
89 retval = _alpm_test_md5sum(fpath, alpm_pkg_get_md5sum(pkg));
91 if(retval == 0) {
92 return(0);
93 } else if (retval == 1) {
94 pm_errno = PM_ERR_PKG_INVALID;
95 retval = -1;
98 return(retval);
101 /* Default package accessor functions. These will get overridden by any
102 * backend logic that needs lazy access, such as the local database through
103 * a lazy-load cache. However, the defaults will work just fine for fully-
104 * populated package structures. */
105 const char *_pkg_get_filename(pmpkg_t *pkg) { return pkg->filename; }
106 const char *_pkg_get_name(pmpkg_t *pkg) { return pkg->name; }
107 const char *_pkg_get_version(pmpkg_t *pkg) { return pkg->version; }
108 const char *_pkg_get_desc(pmpkg_t *pkg) { return pkg->desc; }
109 const char *_pkg_get_url(pmpkg_t *pkg) { return pkg->url; }
110 time_t _pkg_get_builddate(pmpkg_t *pkg) { return pkg->builddate; }
111 time_t _pkg_get_installdate(pmpkg_t *pkg) { return pkg->installdate; }
112 const char *_pkg_get_packager(pmpkg_t *pkg) { return pkg->packager; }
113 const char *_pkg_get_md5sum(pmpkg_t *pkg) { return pkg->md5sum; }
114 const char *_pkg_get_arch(pmpkg_t *pkg) { return pkg->arch; }
115 off_t _pkg_get_size(pmpkg_t *pkg) { return pkg->size; }
116 off_t _pkg_get_isize(pmpkg_t *pkg) { return pkg->isize; }
117 pmpkgreason_t _pkg_get_reason(pmpkg_t *pkg) { return pkg->reason; }
118 int _pkg_has_force(pmpkg_t *pkg) { return pkg->force; }
120 alpm_list_t *_pkg_get_licenses(pmpkg_t *pkg) { return pkg->licenses; }
121 alpm_list_t *_pkg_get_groups(pmpkg_t *pkg) { return pkg->groups; }
122 alpm_list_t *_pkg_get_depends(pmpkg_t *pkg) { return pkg->depends; }
123 alpm_list_t *_pkg_get_optdepends(pmpkg_t *pkg) { return pkg->optdepends; }
124 alpm_list_t *_pkg_get_conflicts(pmpkg_t *pkg) { return pkg->conflicts; }
125 alpm_list_t *_pkg_get_provides(pmpkg_t *pkg) { return pkg->provides; }
126 alpm_list_t *_pkg_get_replaces(pmpkg_t *pkg) { return pkg->replaces; }
127 alpm_list_t *_pkg_get_deltas(pmpkg_t *pkg) { return pkg->deltas; }
128 alpm_list_t *_pkg_get_files(pmpkg_t *pkg) { return pkg->files; }
129 alpm_list_t *_pkg_get_backup(pmpkg_t *pkg) { return pkg->backup; }
131 /** The standard package operations struct. Get fields directly from the
132 * struct itself with no abstraction layer or any type of lazy loading.
134 struct pkg_operations default_pkg_ops = {
135 .get_filename = _pkg_get_filename,
136 .get_name = _pkg_get_name,
137 .get_version = _pkg_get_version,
138 .get_desc = _pkg_get_desc,
139 .get_url = _pkg_get_url,
140 .get_builddate = _pkg_get_builddate,
141 .get_installdate = _pkg_get_installdate,
142 .get_packager = _pkg_get_packager,
143 .get_md5sum = _pkg_get_md5sum,
144 .get_arch = _pkg_get_arch,
145 .get_size = _pkg_get_size,
146 .get_isize = _pkg_get_isize,
147 .get_reason = _pkg_get_reason,
148 .has_force = _pkg_has_force,
149 .get_licenses = _pkg_get_licenses,
150 .get_groups = _pkg_get_groups,
151 .get_depends = _pkg_get_depends,
152 .get_optdepends = _pkg_get_optdepends,
153 .get_conflicts = _pkg_get_conflicts,
154 .get_provides = _pkg_get_provides,
155 .get_replaces = _pkg_get_replaces,
156 .get_deltas = _pkg_get_deltas,
157 .get_files = _pkg_get_files,
158 .get_backup = _pkg_get_backup,
161 /* Public functions for getting package information. These functions
162 * delegate the hard work to the function callbacks attached to each
163 * package, which depend on where the package was loaded from. */
164 const char SYMEXPORT *alpm_pkg_get_filename(pmpkg_t *pkg)
166 return pkg->ops->get_filename(pkg);
169 const char SYMEXPORT *alpm_pkg_get_name(pmpkg_t *pkg)
171 return pkg->ops->get_name(pkg);
174 const char SYMEXPORT *alpm_pkg_get_version(pmpkg_t *pkg)
176 return pkg->ops->get_version(pkg);
179 const char SYMEXPORT *alpm_pkg_get_desc(pmpkg_t *pkg)
181 return pkg->ops->get_desc(pkg);
184 const char SYMEXPORT *alpm_pkg_get_url(pmpkg_t *pkg)
186 return pkg->ops->get_url(pkg);
189 time_t SYMEXPORT alpm_pkg_get_builddate(pmpkg_t *pkg)
191 return pkg->ops->get_builddate(pkg);
194 time_t SYMEXPORT alpm_pkg_get_installdate(pmpkg_t *pkg)
196 return pkg->ops->get_installdate(pkg);
199 const char SYMEXPORT *alpm_pkg_get_packager(pmpkg_t *pkg)
201 return pkg->ops->get_packager(pkg);
204 const char SYMEXPORT *alpm_pkg_get_md5sum(pmpkg_t *pkg)
206 return pkg->ops->get_md5sum(pkg);
209 const char SYMEXPORT *alpm_pkg_get_arch(pmpkg_t *pkg)
211 return pkg->ops->get_arch(pkg);
214 off_t SYMEXPORT alpm_pkg_get_size(pmpkg_t *pkg)
216 return pkg->ops->get_size(pkg);
219 off_t SYMEXPORT alpm_pkg_get_isize(pmpkg_t *pkg)
221 return pkg->ops->get_isize(pkg);
224 pmpkgreason_t SYMEXPORT alpm_pkg_get_reason(pmpkg_t *pkg)
226 return pkg->ops->get_reason(pkg);
229 int SYMEXPORT alpm_pkg_has_force(pmpkg_t *pkg)
231 return pkg->ops->has_force(pkg);
234 alpm_list_t SYMEXPORT *alpm_pkg_get_licenses(pmpkg_t *pkg)
236 return pkg->ops->get_licenses(pkg);
239 alpm_list_t SYMEXPORT *alpm_pkg_get_groups(pmpkg_t *pkg)
241 return pkg->ops->get_groups(pkg);
244 alpm_list_t SYMEXPORT *alpm_pkg_get_depends(pmpkg_t *pkg)
246 return pkg->ops->get_depends(pkg);
249 alpm_list_t SYMEXPORT *alpm_pkg_get_optdepends(pmpkg_t *pkg)
251 return pkg->ops->get_optdepends(pkg);
254 alpm_list_t SYMEXPORT *alpm_pkg_get_conflicts(pmpkg_t *pkg)
256 return pkg->ops->get_conflicts(pkg);
259 alpm_list_t SYMEXPORT *alpm_pkg_get_provides(pmpkg_t *pkg)
261 return pkg->ops->get_provides(pkg);
264 alpm_list_t SYMEXPORT *alpm_pkg_get_replaces(pmpkg_t *pkg)
266 return pkg->ops->get_replaces(pkg);
269 alpm_list_t SYMEXPORT *alpm_pkg_get_deltas(pmpkg_t *pkg)
271 return pkg->ops->get_deltas(pkg);
274 alpm_list_t SYMEXPORT *alpm_pkg_get_files(pmpkg_t *pkg)
276 return pkg->ops->get_files(pkg);
279 alpm_list_t SYMEXPORT *alpm_pkg_get_backup(pmpkg_t *pkg)
281 return pkg->ops->get_backup(pkg);
284 pmdb_t SYMEXPORT *alpm_pkg_get_db(pmpkg_t *pkg)
286 /* Sanity checks */
287 ASSERT(pkg != NULL, return(NULL));
288 ASSERT(pkg->origin != PKG_FROM_FILE, return(NULL));
290 return(pkg->origin_data.db);
294 * Open a package changelog for reading. Similar to fopen in functionality,
295 * except that the returned 'file stream' could really be from an archive
296 * as well as from the database.
297 * @param pkg the package to read the changelog of (either file or db)
298 * @return a 'file stream' to the package changelog
300 void SYMEXPORT *alpm_pkg_changelog_open(pmpkg_t *pkg)
302 return pkg->ops->changelog_open(pkg);
306 * Read data from an open changelog 'file stream'. Similar to fread in
307 * functionality, this function takes a buffer and amount of data to read. If an
308 * error occurs pm_errno will be set.
310 * @param ptr a buffer to fill with raw changelog data
311 * @param size the size of the buffer
312 * @param pkg the package that the changelog is being read from
313 * @param fp a 'file stream' to the package changelog
314 * @return the number of characters read, or 0 if there is no more data or an
315 * error occurred.
317 size_t SYMEXPORT alpm_pkg_changelog_read(void *ptr, size_t size,
318 const pmpkg_t *pkg, const void *fp)
320 return pkg->ops->changelog_read(ptr, size, pkg, fp);
324 int SYMEXPORT alpm_pkg_changelog_feof(const pmpkg_t *pkg, void *fp)
326 return pkg->ops->changelog_feof(pkg, fp);
331 * Close a package changelog for reading. Similar to fclose in functionality,
332 * except that the 'file stream' could really be from an archive as well as
333 * from the database.
334 * @param pkg the package that the changelog was read from
335 * @param fp a 'file stream' to the package changelog
336 * @return whether closing the package changelog stream was successful
338 int SYMEXPORT alpm_pkg_changelog_close(const pmpkg_t *pkg, void *fp)
340 return pkg->ops->changelog_close(pkg, fp);
343 int SYMEXPORT alpm_pkg_has_scriptlet(pmpkg_t *pkg)
345 ALPM_LOG_FUNC;
347 /* Sanity checks */
348 ASSERT(handle != NULL, return(-1));
349 ASSERT(pkg != NULL, return(-1));
351 if(pkg->origin == PKG_FROM_LOCALDB
352 && !(pkg->infolevel & INFRQ_SCRIPTLET)) {
353 _alpm_db_read(pkg->origin_data.db, pkg, INFRQ_SCRIPTLET);
355 return pkg->scriptlet;
358 static void find_requiredby(pmpkg_t *pkg, pmdb_t *db, alpm_list_t **reqs)
360 const alpm_list_t *i;
361 for(i = _alpm_db_get_pkgcache(db); i; i = i->next) {
362 if(!i->data) {
363 continue;
365 pmpkg_t *cachepkg = i->data;
366 if(_alpm_dep_edge(cachepkg, pkg)) {
367 const char *cachepkgname = cachepkg->name;
368 if(alpm_list_find_str(*reqs, cachepkgname) == 0) {
369 *reqs = alpm_list_add(*reqs, strdup(cachepkgname));
376 * @brief Compute the packages requiring a given package.
377 * @param pkg a package
378 * @return the list of packages requiring pkg
380 alpm_list_t SYMEXPORT *alpm_pkg_compute_requiredby(pmpkg_t *pkg)
382 const alpm_list_t *i;
383 alpm_list_t *reqs = NULL;
384 pmdb_t *db;
386 if(pkg->origin == PKG_FROM_FILE) {
387 /* The sane option; search locally for things that require this. */
388 db = alpm_option_get_localdb();
389 find_requiredby(pkg, db, &reqs);
390 } else {
391 /* We have a DB package. if it is a local package, then we should
392 * only search the local DB; else search all known sync databases. */
393 db = pkg->origin_data.db;
394 if(db->is_local) {
395 find_requiredby(pkg, db, &reqs);
396 } else {
397 for(i = handle->dbs_sync; i; i = i->next) {
398 db = i->data;
399 find_requiredby(pkg, db, &reqs);
400 reqs = alpm_list_msort(reqs, alpm_list_count(reqs), _alpm_str_cmp);
404 return(reqs);
407 /** @} */
409 pmpkg_t *_alpm_pkg_new(void)
411 pmpkg_t* pkg;
413 ALPM_LOG_FUNC;
415 CALLOC(pkg, 1, sizeof(pmpkg_t), RET_ERR(PM_ERR_MEMORY, NULL));
417 return(pkg);
420 pmpkg_t *_alpm_pkg_dup(pmpkg_t *pkg)
422 pmpkg_t *newpkg;
423 alpm_list_t *i;
425 ALPM_LOG_FUNC;
427 CALLOC(newpkg, 1, sizeof(pmpkg_t), RET_ERR(PM_ERR_MEMORY, NULL));
429 STRDUP(newpkg->filename, pkg->filename, RET_ERR(PM_ERR_MEMORY, newpkg));
430 STRDUP(newpkg->name, pkg->name, RET_ERR(PM_ERR_MEMORY, newpkg));
431 STRDUP(newpkg->version, pkg->version, RET_ERR(PM_ERR_MEMORY, newpkg));
432 STRDUP(newpkg->desc, pkg->desc, RET_ERR(PM_ERR_MEMORY, newpkg));
433 STRDUP(newpkg->url, pkg->url, RET_ERR(PM_ERR_MEMORY, newpkg));
434 newpkg->builddate = pkg->builddate;
435 newpkg->installdate = pkg->installdate;
436 STRDUP(newpkg->packager, pkg->packager, RET_ERR(PM_ERR_MEMORY, newpkg));
437 STRDUP(newpkg->md5sum, pkg->md5sum, RET_ERR(PM_ERR_MEMORY, newpkg));
438 STRDUP(newpkg->arch, pkg->arch, RET_ERR(PM_ERR_MEMORY, newpkg));
439 newpkg->size = pkg->size;
440 newpkg->isize = pkg->isize;
441 newpkg->scriptlet = pkg->scriptlet;
442 newpkg->force = pkg->force;
443 newpkg->reason = pkg->reason;
445 newpkg->licenses = alpm_list_strdup(pkg->licenses);
446 newpkg->replaces = alpm_list_strdup(pkg->replaces);
447 newpkg->groups = alpm_list_strdup(pkg->groups);
448 newpkg->files = alpm_list_strdup(pkg->files);
449 newpkg->backup = alpm_list_strdup(pkg->backup);
450 for(i = pkg->depends; i; i = alpm_list_next(i)) {
451 newpkg->depends = alpm_list_add(newpkg->depends, _alpm_dep_dup(i->data));
453 newpkg->optdepends = alpm_list_strdup(pkg->optdepends);
454 newpkg->conflicts = alpm_list_strdup(pkg->conflicts);
455 newpkg->provides = alpm_list_strdup(pkg->provides);
456 newpkg->deltas = alpm_list_copy_data(pkg->deltas, sizeof(pmdelta_t));
458 /* internal */
459 newpkg->origin = pkg->origin;
460 newpkg->ops = pkg->ops;
461 if(newpkg->origin == PKG_FROM_FILE) {
462 newpkg->origin_data.file = strdup(pkg->origin_data.file);
463 } else {
464 newpkg->origin_data.db = pkg->origin_data.db;
466 newpkg->infolevel = pkg->infolevel;
468 return(newpkg);
471 void _alpm_pkg_free(pmpkg_t *pkg)
473 ALPM_LOG_FUNC;
475 if(pkg == NULL) {
476 return;
479 FREE(pkg->filename);
480 FREE(pkg->name);
481 FREE(pkg->version);
482 FREE(pkg->desc);
483 FREE(pkg->url);
484 FREE(pkg->packager);
485 FREE(pkg->md5sum);
486 FREE(pkg->arch);
487 FREELIST(pkg->licenses);
488 FREELIST(pkg->replaces);
489 FREELIST(pkg->groups);
490 FREELIST(pkg->files);
491 FREELIST(pkg->backup);
492 alpm_list_free_inner(pkg->depends, (alpm_list_fn_free)_alpm_dep_free);
493 alpm_list_free(pkg->depends);
494 FREELIST(pkg->optdepends);
495 FREELIST(pkg->conflicts);
496 FREELIST(pkg->provides);
497 alpm_list_free_inner(pkg->deltas, (alpm_list_fn_free)_alpm_delta_free);
498 alpm_list_free(pkg->deltas);
499 alpm_list_free(pkg->delta_path);
500 alpm_list_free(pkg->removes);
502 if(pkg->origin == PKG_FROM_FILE) {
503 FREE(pkg->origin_data.file);
505 FREE(pkg);
508 /* This function should be used when removing a target from upgrade/sync target list
509 * Case 1: If pkg is a loaded package file (PKG_FROM_FILE), it will be freed.
510 * Case 2: If pkg is a pkgcache entry (PKG_FROM_CACHE), it won't be freed,
511 * only the transaction specific fields of pkg will be freed.
513 void _alpm_pkg_free_trans(pmpkg_t *pkg)
515 ALPM_LOG_FUNC;
517 if(pkg == NULL) {
518 return;
521 if(pkg->origin == PKG_FROM_FILE) {
522 _alpm_pkg_free(pkg);
523 return;
526 alpm_list_free(pkg->removes);
527 pkg->removes = NULL;
530 /* Is spkg an upgrade for locapkg? */
531 int _alpm_pkg_compare_versions(pmpkg_t *spkg, pmpkg_t *localpkg)
533 int cmp = 0;
535 ALPM_LOG_FUNC;
537 cmp = alpm_pkg_vercmp(alpm_pkg_get_version(spkg),
538 alpm_pkg_get_version(localpkg));
540 if(cmp < 0 && alpm_pkg_has_force(spkg)) {
541 cmp = 1;
544 return(cmp);
547 /* Helper function for comparing packages
549 int _alpm_pkg_cmp(const void *p1, const void *p2)
551 pmpkg_t *pkg1 = (pmpkg_t *)p1;
552 pmpkg_t *pkg2 = (pmpkg_t *)p2;
553 return(strcoll(pkg1->name, pkg2->name));
556 /* Test for existence of a package in a alpm_list_t*
557 * of pmpkg_t*
559 pmpkg_t *_alpm_pkg_find(alpm_list_t *haystack, const char *needle)
561 alpm_list_t *lp;
563 ALPM_LOG_FUNC;
565 if(needle == NULL || haystack == NULL) {
566 return(NULL);
569 for(lp = haystack; lp; lp = lp->next) {
570 pmpkg_t *info = lp->data;
572 if(info && strcmp(info->name, needle) == 0) {
573 return(info);
576 return(NULL);
579 /** Test if a package should be ignored.
581 * Checks if the package is ignored via IgnorePkg, or if the package is
582 * in a group ignored via IgnoreGrp.
584 * @param pkg the package to test
586 * @return 1 if the package should be ignored, 0 otherwise
588 int _alpm_pkg_should_ignore(pmpkg_t *pkg)
590 alpm_list_t *groups = NULL;
592 /* first see if the package is ignored */
593 if(alpm_list_find_str(handle->ignorepkg, alpm_pkg_get_name(pkg))) {
594 return(1);
597 /* next see if the package is in a group that is ignored */
598 for(groups = handle->ignoregrp; groups; groups = alpm_list_next(groups)) {
599 char *grp = (char *)alpm_list_getdata(groups);
600 if(alpm_list_find_str(alpm_pkg_get_groups(pkg), grp)) {
601 return(1);
605 return(0);
608 /* vim: set ts=2 sw=2 noet: */