4 * Copyright (c) 2002-2007 by Judd Vinet <jvinet@zeroflux.org>
5 * Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>
6 * Copyright (c) 2005, 2006 by Christian Hamar <krics@linuxforum.hu>
7 * Copyright (c) 2005, 2006 by Miklos Vajna <vmiklos@frugalware.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
31 #include <sys/types.h>
37 #include <archive_entry.h>
41 #include "alpm_list.h"
50 /** \addtogroup alpm_packages Package Functions
51 * @brief Functions to manipulate libalpm packages
56 * @param pkg package pointer to free
57 * @return 0 on success, -1 on error (pm_errno is set accordingly)
59 int SYMEXPORT
alpm_pkg_free(pmpkg_t
*pkg
)
63 ASSERT(pkg
!= NULL
, RET_ERR(PM_ERR_WRONG_ARGS
, -1));
65 /* Only free packages loaded in user space */
66 if(pkg
->origin
!= PKG_FROM_CACHE
) {
73 /** Check the integrity (with md5) of a package from the sync cache.
74 * @param pkg package pointer
75 * @return 0 on success, -1 on error (pm_errno is set accordingly)
77 int SYMEXPORT
alpm_pkg_checkmd5sum(pmpkg_t
*pkg
)
84 ASSERT(pkg
!= NULL
, RET_ERR(PM_ERR_WRONG_ARGS
, -1));
85 /* We only inspect packages from sync repositories */
86 ASSERT(pkg
->origin
== PKG_FROM_CACHE
, RET_ERR(PM_ERR_PKG_INVALID
, -1));
87 ASSERT(pkg
->origin_data
.db
!= handle
->db_local
, RET_ERR(PM_ERR_PKG_INVALID
, -1));
89 fpath
= _alpm_filecache_find(alpm_pkg_get_filename(pkg
));
91 retval
= _alpm_test_md5sum(fpath
, alpm_pkg_get_md5sum(pkg
));
95 } else if (retval
== 1) {
96 pm_errno
= PM_ERR_PKG_INVALID
;
103 /** Compare versions.
104 * @param ver1 first version
105 * @param ver2 secont version
106 * @return postive, 0 or negative if ver1 is less, equal or more
107 * than ver2, respectively.
109 int SYMEXPORT
alpm_pkg_vercmp(const char *ver1
, const char *ver2
)
113 return(_alpm_versioncmp(ver1
, ver2
));
116 const char SYMEXPORT
*alpm_pkg_get_filename(pmpkg_t
*pkg
)
121 ASSERT(handle
!= NULL
, return(NULL
));
122 ASSERT(pkg
!= NULL
, return(NULL
));
124 if(pkg
->origin
== PKG_FROM_CACHE
&& !(pkg
->infolevel
& INFRQ_DESC
)) {
125 _alpm_db_read(pkg
->origin_data
.db
, pkg
, INFRQ_DESC
);
128 return pkg
->filename
;
131 const char SYMEXPORT
*alpm_pkg_get_name(pmpkg_t
*pkg
)
136 ASSERT(handle
!= NULL
, return(NULL
));
137 ASSERT(pkg
!= NULL
, return(NULL
));
139 if(pkg
->origin
== PKG_FROM_CACHE
&& !(pkg
->infolevel
& INFRQ_BASE
)) {
140 _alpm_db_read(pkg
->origin_data
.db
, pkg
, INFRQ_BASE
);
145 const char SYMEXPORT
*alpm_pkg_get_version(pmpkg_t
*pkg
)
150 ASSERT(handle
!= NULL
, return(NULL
));
151 ASSERT(pkg
!= NULL
, return(NULL
));
153 if(pkg
->origin
== PKG_FROM_CACHE
&& !(pkg
->infolevel
& INFRQ_BASE
)) {
154 _alpm_db_read(pkg
->origin_data
.db
, pkg
, INFRQ_BASE
);
159 const char SYMEXPORT
*alpm_pkg_get_desc(pmpkg_t
*pkg
)
164 ASSERT(handle
!= NULL
, return(NULL
));
165 ASSERT(pkg
!= NULL
, return(NULL
));
167 if(pkg
->origin
== PKG_FROM_CACHE
&& !(pkg
->infolevel
& INFRQ_DESC
)) {
168 _alpm_db_read(pkg
->origin_data
.db
, pkg
, INFRQ_DESC
);
173 const char SYMEXPORT
*alpm_pkg_get_url(pmpkg_t
*pkg
)
178 ASSERT(handle
!= NULL
, return(NULL
));
179 ASSERT(pkg
!= NULL
, return(NULL
));
181 if(pkg
->origin
== PKG_FROM_CACHE
&& !(pkg
->infolevel
& INFRQ_DESC
)) {
182 _alpm_db_read(pkg
->origin_data
.db
, pkg
, INFRQ_DESC
);
187 time_t SYMEXPORT
alpm_pkg_get_builddate(pmpkg_t
*pkg
)
192 ASSERT(handle
!= NULL
, return(0));
193 ASSERT(pkg
!= NULL
, return(0));
195 if(pkg
->origin
== PKG_FROM_CACHE
&& !(pkg
->infolevel
& INFRQ_DESC
)) {
196 _alpm_db_read(pkg
->origin_data
.db
, pkg
, INFRQ_DESC
);
198 return pkg
->builddate
;
201 time_t SYMEXPORT
alpm_pkg_get_installdate(pmpkg_t
*pkg
)
206 ASSERT(handle
!= NULL
, return(0));
207 ASSERT(pkg
!= NULL
, return(0));
209 if(pkg
->origin
== PKG_FROM_CACHE
&& !(pkg
->infolevel
& INFRQ_DESC
)) {
210 _alpm_db_read(pkg
->origin_data
.db
, pkg
, INFRQ_DESC
);
212 return pkg
->installdate
;
215 const char SYMEXPORT
*alpm_pkg_get_packager(pmpkg_t
*pkg
)
220 ASSERT(handle
!= NULL
, return(NULL
));
221 ASSERT(pkg
!= NULL
, return(NULL
));
223 if(pkg
->origin
== PKG_FROM_CACHE
&& !(pkg
->infolevel
& INFRQ_DESC
)) {
224 _alpm_db_read(pkg
->origin_data
.db
, pkg
, INFRQ_DESC
);
226 return pkg
->packager
;
229 const char SYMEXPORT
*alpm_pkg_get_md5sum(pmpkg_t
*pkg
)
234 ASSERT(handle
!= NULL
, return(NULL
));
235 ASSERT(pkg
!= NULL
, return(NULL
));
237 if(pkg
->origin
== PKG_FROM_CACHE
&& !(pkg
->infolevel
& INFRQ_DESC
)) {
238 _alpm_db_read(pkg
->origin_data
.db
, pkg
, INFRQ_DESC
);
243 const char SYMEXPORT
*alpm_pkg_get_arch(pmpkg_t
*pkg
)
248 ASSERT(handle
!= NULL
, return(NULL
));
249 ASSERT(pkg
!= NULL
, return(NULL
));
251 if(pkg
->origin
== PKG_FROM_CACHE
&& !(pkg
->infolevel
& INFRQ_DESC
)) {
252 _alpm_db_read(pkg
->origin_data
.db
, pkg
, INFRQ_DESC
);
257 unsigned long SYMEXPORT
alpm_pkg_get_size(pmpkg_t
*pkg
)
262 ASSERT(handle
!= NULL
, return(-1));
263 ASSERT(pkg
!= NULL
, return(-1));
265 if(pkg
->origin
== PKG_FROM_CACHE
&& !(pkg
->infolevel
& INFRQ_DESC
)) {
266 _alpm_db_read(pkg
->origin_data
.db
, pkg
, INFRQ_DESC
);
271 unsigned long SYMEXPORT
alpm_pkg_get_isize(pmpkg_t
*pkg
)
276 ASSERT(handle
!= NULL
, return(-1));
277 ASSERT(pkg
!= NULL
, return(-1));
279 if(pkg
->origin
== PKG_FROM_CACHE
&& !(pkg
->infolevel
& INFRQ_DESC
)) {
280 _alpm_db_read(pkg
->origin_data
.db
, pkg
, INFRQ_DESC
);
285 pmpkgreason_t SYMEXPORT
alpm_pkg_get_reason(pmpkg_t
*pkg
)
290 ASSERT(handle
!= NULL
, return(-1));
291 ASSERT(pkg
!= NULL
, return(-1));
293 if(pkg
->origin
== PKG_FROM_CACHE
&& !(pkg
->infolevel
& INFRQ_DESC
)) {
294 _alpm_db_read(pkg
->origin_data
.db
, pkg
, INFRQ_DESC
);
299 alpm_list_t SYMEXPORT
*alpm_pkg_get_licenses(pmpkg_t
*pkg
)
304 ASSERT(handle
!= NULL
, return(NULL
));
305 ASSERT(pkg
!= NULL
, return(NULL
));
307 if(pkg
->origin
== PKG_FROM_CACHE
&& !(pkg
->infolevel
& INFRQ_DESC
)) {
308 _alpm_db_read(pkg
->origin_data
.db
, pkg
, INFRQ_DESC
);
310 return pkg
->licenses
;
313 alpm_list_t SYMEXPORT
*alpm_pkg_get_groups(pmpkg_t
*pkg
)
318 ASSERT(handle
!= NULL
, return(NULL
));
319 ASSERT(pkg
!= NULL
, return(NULL
));
321 if(pkg
->origin
== PKG_FROM_CACHE
&& !(pkg
->infolevel
& INFRQ_DESC
)) {
322 _alpm_db_read(pkg
->origin_data
.db
, pkg
, INFRQ_DESC
);
327 alpm_list_t SYMEXPORT
*alpm_pkg_get_depends(pmpkg_t
*pkg
)
332 ASSERT(handle
!= NULL
, return(NULL
));
333 ASSERT(pkg
!= NULL
, return(NULL
));
335 if(pkg
->origin
== PKG_FROM_CACHE
&& !(pkg
->infolevel
& INFRQ_DEPENDS
)) {
336 _alpm_db_read(pkg
->origin_data
.db
, pkg
, INFRQ_DEPENDS
);
341 alpm_list_t SYMEXPORT
*alpm_pkg_get_optdepends(pmpkg_t
*pkg
)
346 ASSERT(handle
!= NULL
, return(NULL
));
347 ASSERT(pkg
!= NULL
, return(NULL
));
349 if(pkg
->origin
== PKG_FROM_CACHE
&& !(pkg
->infolevel
& INFRQ_DEPENDS
)) {
350 _alpm_db_read(pkg
->origin_data
.db
, pkg
, INFRQ_DEPENDS
);
352 return pkg
->optdepends
;
355 alpm_list_t SYMEXPORT
*alpm_pkg_get_conflicts(pmpkg_t
*pkg
)
360 ASSERT(handle
!= NULL
, return(NULL
));
361 ASSERT(pkg
!= NULL
, return(NULL
));
363 if(pkg
->origin
== PKG_FROM_CACHE
&& !(pkg
->infolevel
& INFRQ_DEPENDS
)) {
364 _alpm_db_read(pkg
->origin_data
.db
, pkg
, INFRQ_DEPENDS
);
366 return pkg
->conflicts
;
369 alpm_list_t SYMEXPORT
*alpm_pkg_get_provides(pmpkg_t
*pkg
)
374 ASSERT(handle
!= NULL
, return(NULL
));
375 ASSERT(pkg
!= NULL
, return(NULL
));
377 if(pkg
->origin
== PKG_FROM_CACHE
&& !(pkg
->infolevel
& INFRQ_DEPENDS
)) {
378 _alpm_db_read(pkg
->origin_data
.db
, pkg
, INFRQ_DEPENDS
);
380 return pkg
->provides
;
383 alpm_list_t SYMEXPORT
*alpm_pkg_get_deltas(pmpkg_t
*pkg
)
388 ASSERT(handle
!= NULL
, return(NULL
));
389 ASSERT(pkg
!= NULL
, return(NULL
));
391 if(pkg
->origin
== PKG_FROM_CACHE
&& !(pkg
->infolevel
& INFRQ_DELTAS
)) {
392 _alpm_db_read(pkg
->origin_data
.db
, pkg
, INFRQ_DELTAS
);
397 alpm_list_t SYMEXPORT
*alpm_pkg_get_replaces(pmpkg_t
*pkg
)
402 ASSERT(handle
!= NULL
, return(NULL
));
403 ASSERT(pkg
!= NULL
, return(NULL
));
405 if(pkg
->origin
== PKG_FROM_CACHE
&& !(pkg
->infolevel
& INFRQ_DESC
)) {
406 _alpm_db_read(pkg
->origin_data
.db
, pkg
, INFRQ_DESC
);
408 return pkg
->replaces
;
411 alpm_list_t SYMEXPORT
*alpm_pkg_get_files(pmpkg_t
*pkg
)
416 ASSERT(handle
!= NULL
, return(NULL
));
417 ASSERT(pkg
!= NULL
, return(NULL
));
419 if(pkg
->origin
== PKG_FROM_CACHE
&& pkg
->origin_data
.db
== handle
->db_local
420 && !(pkg
->infolevel
& INFRQ_FILES
)) {
421 _alpm_db_read(pkg
->origin_data
.db
, pkg
, INFRQ_FILES
);
426 alpm_list_t SYMEXPORT
*alpm_pkg_get_backup(pmpkg_t
*pkg
)
431 ASSERT(handle
!= NULL
, return(NULL
));
432 ASSERT(pkg
!= NULL
, return(NULL
));
434 if(pkg
->origin
== PKG_FROM_CACHE
&& pkg
->origin_data
.db
== handle
->db_local
435 && !(pkg
->infolevel
& INFRQ_FILES
)) {
436 _alpm_db_read(pkg
->origin_data
.db
, pkg
, INFRQ_FILES
);
442 * Open a package changelog for reading. Similar to fopen in functionality,
443 * except that the returned 'file stream' could really be from an archive
444 * as well as from the database.
445 * @param pkg the package to read the changelog of (either file or db)
446 * @return a 'file stream' to the package changelog
448 void SYMEXPORT
*alpm_pkg_changelog_open(pmpkg_t
*pkg
)
453 ASSERT(handle
!= NULL
, return(NULL
));
454 ASSERT(pkg
!= NULL
, return(NULL
));
456 if(pkg
->origin
== PKG_FROM_CACHE
) {
457 char clfile
[PATH_MAX
];
458 snprintf(clfile
, PATH_MAX
, "%s/%s/%s-%s/changelog",
459 alpm_option_get_dbpath(),
460 alpm_db_get_name(handle
->db_local
),
461 alpm_pkg_get_name(pkg
),
462 alpm_pkg_get_version(pkg
));
463 return fopen(clfile
, "r");
464 } else if(pkg
->origin
== PKG_FROM_FILE
) {
465 struct archive
*archive
= NULL
;
466 struct archive_entry
*entry
;
467 const char *pkgfile
= pkg
->origin_data
.file
;
468 int ret
= ARCHIVE_OK
;
470 if((archive
= archive_read_new()) == NULL
) {
471 RET_ERR(PM_ERR_LIBARCHIVE
, NULL
);
474 archive_read_support_compression_all(archive
);
475 archive_read_support_format_all(archive
);
477 if (archive_read_open_filename(archive
, pkgfile
,
478 ARCHIVE_DEFAULT_BYTES_PER_BLOCK
) != ARCHIVE_OK
) {
479 RET_ERR(PM_ERR_PKG_OPEN
, NULL
);
482 while((ret
= archive_read_next_header(archive
, &entry
)) == ARCHIVE_OK
) {
483 const char *entry_name
= archive_entry_pathname(entry
);
485 if(strcmp(entry_name
, ".CHANGELOG") == 0) {
489 /* we didn't find a changelog */
490 archive_read_finish(archive
);
497 * Read data from an open changelog 'file stream'. Similar to fread in
498 * functionality, this function takes a buffer and amount of data to read.
499 * @param ptr a buffer to fill with raw changelog data
500 * @param size the size of the buffer
501 * @param pkg the package that the changelog is being read from
502 * @param fp a 'file stream' to the package changelog
503 * @return the number of characters read, or 0 if there is no more data
505 size_t SYMEXPORT
alpm_pkg_changelog_read(void *ptr
, size_t size
,
506 const pmpkg_t
*pkg
, const void *fp
)
509 if(pkg
->origin
== PKG_FROM_CACHE
) {
510 ret
= fread(ptr
, 1, size
, (FILE*)fp
);
511 } else if(pkg
->origin
== PKG_FROM_FILE
) {
512 ret
= archive_read_data((struct archive
*)fp
, ptr
, size
);
518 int SYMEXPORT alpm_pkg_changelog_feof(const pmpkg_t *pkg, void *fp)
521 if(pkg->origin == PKG_FROM_CACHE) {
522 ret = feof((FILE*)fp);
523 } else if(pkg->origin == PKG_FROM_FILE) {
524 // note: this doesn't quite work, no feof in libarchive
525 ret = archive_read_data((struct archive*)fp, NULL, 0);
532 * Close a package changelog for reading. Similar to fclose in functionality,
533 * except that the 'file stream' could really be from an archive as well as
535 * @param pkg the package that the changelog was read from
536 * @param fp a 'file stream' to the package changelog
537 * @return whether closing the package changelog stream was successful
539 int SYMEXPORT
alpm_pkg_changelog_close(const pmpkg_t
*pkg
, void *fp
)
542 if(pkg
->origin
== PKG_FROM_CACHE
) {
543 ret
= fclose((FILE*)fp
);
544 } else if(pkg
->origin
== PKG_FROM_FILE
) {
545 ret
= archive_read_finish((struct archive
*)fp
);
550 unsigned short SYMEXPORT
alpm_pkg_has_scriptlet(pmpkg_t
*pkg
)
555 ASSERT(handle
!= NULL
, return(-1));
556 ASSERT(pkg
!= NULL
, return(-1));
558 if(pkg
->origin
== PKG_FROM_CACHE
&& pkg
->origin_data
.db
== handle
->db_local
559 && !(pkg
->infolevel
& INFRQ_SCRIPTLET
)) {
560 _alpm_db_read(pkg
->origin_data
.db
, pkg
, INFRQ_SCRIPTLET
);
562 return pkg
->scriptlet
;
566 * @brief Compute the packages requiring a given package.
567 * @param pkg a package
568 * @return the list of packages requiring pkg
570 * A depends on B through n depends <=> A listed in B's requiredby n times
571 * n == 0 or 1 in almost all cases */
572 alpm_list_t SYMEXPORT
*alpm_pkg_compute_requiredby(pmpkg_t
*pkg
)
574 const alpm_list_t
*i
, *j
;
575 alpm_list_t
*reqs
= NULL
;
577 pmdb_t
*localdb
= alpm_option_get_localdb();
578 for(i
= _alpm_db_get_pkgcache(localdb
); i
; i
= i
->next
) {
582 pmpkg_t
*cachepkg
= i
->data
;
583 const char *cachepkgname
= alpm_pkg_get_name(cachepkg
);
585 for(j
= alpm_pkg_get_depends(cachepkg
); j
; j
= j
->next
) {
586 pmdepend_t
*dep
= j
->data
;
588 if(alpm_depcmp(pkg
, dep
)) {
589 _alpm_log(PM_LOG_DEBUG
, "adding '%s' in requiredby field for '%s'\n",
590 cachepkgname
, pkg
->name
);
591 reqs
= alpm_list_add(reqs
, strdup(cachepkgname
));
600 /* this function was taken from rpm 4.0.4 and rewritten */
601 int _alpm_versioncmp(const char *a
, const char *b
)
603 char str1
[64], str2
[64];
606 char *rel1
= NULL
, *rel2
= NULL
;
617 strncpy(str1
, a
, 64);
619 strncpy(str2
, b
, 64);
622 /* lose the release number */
623 for(one
= str1
; *one
&& *one
!= '-'; one
++);
628 for(two
= str2
; *two
&& *two
!= '-'; two
++);
637 while(*one
|| *two
) {
638 while(*one
&& !isalnum((int)*one
)) one
++;
639 while(*two
&& !isalnum((int)*two
)) two
++;
644 /* find the next segment for each string */
645 if(isdigit((int)*ptr1
)) {
647 while(*ptr1
&& isdigit((int)*ptr1
)) ptr1
++;
650 while(*ptr1
&& isalpha((int)*ptr1
)) ptr1
++;
652 if(isdigit((int)*ptr2
)) {
654 while(*ptr2
&& isdigit((int)*ptr2
)) ptr2
++;
657 while(*ptr2
&& isalpha((int)*ptr2
)) ptr2
++;
665 /* see if we ran out of segments on one string */
666 if(one
== ptr1
&& two
!= ptr2
) {
667 return(is2num
? -1 : 1);
669 if(one
!= ptr1
&& two
== ptr2
) {
670 return(is1num
? 1 : -1);
673 /* see if we have a type mismatch (ie, one is alpha and one is digits) */
674 if(is1num
&& !is2num
) return(1);
675 if(!is1num
&& is2num
) return(-1);
677 if(is1num
) while(*one
== '0') one
++;
678 if(is2num
) while(*two
== '0') two
++;
680 rc
= strverscmp(one
, two
);
689 if((!*one
) && (!*two
)) {
690 /* compare release numbers */
691 if(rel1
&& rel2
&& strlen(rel1
) && strlen(rel2
)) return(_alpm_versioncmp(rel1
, rel2
));
695 return(*one
? 1 : -1);
699 pmpkg_t
*_alpm_pkg_new(const char *name
, const char *version
)
705 CALLOC(pkg
, 1, sizeof(pmpkg_t
), RET_ERR(PM_ERR_MEMORY
, NULL
));
708 STRDUP(pkg
->name
, name
, RET_ERR(PM_ERR_MEMORY
, pkg
));
712 STRDUP(pkg
->version
, version
, RET_ERR(PM_ERR_MEMORY
, pkg
));
718 pmpkg_t
*_alpm_pkg_dup(pmpkg_t
*pkg
)
725 CALLOC(newpkg
, 1, sizeof(pmpkg_t
), RET_ERR(PM_ERR_MEMORY
, NULL
));
727 STRDUP(newpkg
->filename
, pkg
->filename
, RET_ERR(PM_ERR_MEMORY
, newpkg
));
728 STRDUP(newpkg
->name
, pkg
->name
, RET_ERR(PM_ERR_MEMORY
, newpkg
));
729 STRDUP(newpkg
->version
, pkg
->version
, RET_ERR(PM_ERR_MEMORY
, newpkg
));
730 STRDUP(newpkg
->desc
, pkg
->desc
, RET_ERR(PM_ERR_MEMORY
, newpkg
));
731 STRDUP(newpkg
->url
, pkg
->url
, RET_ERR(PM_ERR_MEMORY
, newpkg
));
732 newpkg
->builddate
= pkg
->builddate
;
733 newpkg
->installdate
= pkg
->installdate
;
734 STRDUP(newpkg
->packager
, pkg
->packager
, RET_ERR(PM_ERR_MEMORY
, newpkg
));
735 STRDUP(newpkg
->md5sum
, pkg
->md5sum
, RET_ERR(PM_ERR_MEMORY
, newpkg
));
736 STRDUP(newpkg
->arch
, pkg
->arch
, RET_ERR(PM_ERR_MEMORY
, newpkg
));
737 newpkg
->size
= pkg
->size
;
738 newpkg
->isize
= pkg
->isize
;
739 newpkg
->scriptlet
= pkg
->scriptlet
;
740 newpkg
->force
= pkg
->force
;
741 newpkg
->reason
= pkg
->reason
;
743 newpkg
->licenses
= alpm_list_strdup(alpm_pkg_get_licenses(pkg
));
744 newpkg
->replaces
= alpm_list_strdup(alpm_pkg_get_replaces(pkg
));
745 newpkg
->groups
= alpm_list_strdup(alpm_pkg_get_groups(pkg
));
746 newpkg
->files
= alpm_list_strdup(alpm_pkg_get_files(pkg
));
747 newpkg
->backup
= alpm_list_strdup(alpm_pkg_get_backup(pkg
));
748 for(i
= alpm_pkg_get_depends(pkg
); i
; i
= alpm_list_next(i
)) {
749 newpkg
->depends
= alpm_list_add(newpkg
->depends
, _alpm_dep_dup(i
->data
));
751 newpkg
->optdepends
= alpm_list_strdup(alpm_pkg_get_optdepends(pkg
));
752 newpkg
->conflicts
= alpm_list_strdup(alpm_pkg_get_conflicts(pkg
));
753 newpkg
->provides
= alpm_list_strdup(alpm_pkg_get_provides(pkg
));
754 newpkg
->deltas
= alpm_list_copy_data(alpm_pkg_get_deltas(pkg
),
758 newpkg
->origin
= pkg
->origin
;
759 if(newpkg
->origin
== PKG_FROM_FILE
) {
760 newpkg
->origin_data
.file
= strdup(pkg
->origin_data
.file
);
762 newpkg
->origin_data
.db
= pkg
->origin_data
.db
;
764 newpkg
->infolevel
= pkg
->infolevel
;
769 void _alpm_pkg_free(pmpkg_t
*pkg
)
785 FREELIST(pkg
->licenses
);
786 FREELIST(pkg
->replaces
);
787 FREELIST(pkg
->groups
);
788 FREELIST(pkg
->files
);
789 FREELIST(pkg
->backup
);
790 alpm_list_free_inner(pkg
->depends
, (alpm_list_fn_free
)_alpm_dep_free
);
791 alpm_list_free(pkg
->depends
);
792 FREELIST(pkg
->optdepends
);
793 FREELIST(pkg
->conflicts
);
794 FREELIST(pkg
->provides
);
795 alpm_list_free_inner(pkg
->deltas
, (alpm_list_fn_free
)_alpm_delta_free
);
796 alpm_list_free(pkg
->deltas
);
797 alpm_list_free(pkg
->delta_path
);
799 if(pkg
->origin
== PKG_FROM_FILE
) {
800 FREE(pkg
->origin_data
.file
);
805 /* Is pkgB an upgrade for pkgA ? */
806 int _alpm_pkg_compare_versions(pmpkg_t
*local_pkg
, pmpkg_t
*pkg
)
812 if(pkg
->origin
== PKG_FROM_CACHE
) {
813 /* ensure we have the /desc file, which contains the 'force' option */
814 _alpm_db_read(pkg
->origin_data
.db
, pkg
, INFRQ_DESC
);
817 /* compare versions and see if we need to upgrade */
818 cmp
= _alpm_versioncmp(alpm_pkg_get_version(pkg
), alpm_pkg_get_version(local_pkg
));
820 if(cmp
!= 0 && pkg
->force
) {
822 _alpm_log(PM_LOG_WARNING
, _("%s: forcing upgrade to version %s\n"),
823 alpm_pkg_get_name(pkg
), alpm_pkg_get_version(pkg
));
825 /* local version is newer */
826 pmdb_t
*db
= pkg
->origin_data
.db
;
827 _alpm_log(PM_LOG_WARNING
, _("%s: local (%s) is newer than %s (%s)\n"),
828 alpm_pkg_get_name(local_pkg
), alpm_pkg_get_version(local_pkg
),
829 alpm_db_get_name(db
), alpm_pkg_get_version(pkg
));
836 /* Helper function for comparing packages
838 int _alpm_pkg_cmp(const void *p1
, const void *p2
)
840 pmpkg_t
*pk1
= (pmpkg_t
*)p1
;
841 pmpkg_t
*pk2
= (pmpkg_t
*)p2
;
843 return(strcmp(alpm_pkg_get_name(pk1
), alpm_pkg_get_name(pk2
)));
846 int _alpm_pkgname_pkg_cmp(const void *pkgname
, const void *package
)
848 return(strcmp(alpm_pkg_get_name((pmpkg_t
*) package
), (char *) pkgname
));
851 /* Test for existence of a package in a alpm_list_t*
854 pmpkg_t
*_alpm_pkg_find(const char *needle
, alpm_list_t
*haystack
)
860 if(needle
== NULL
|| haystack
== NULL
) {
864 for(lp
= haystack
; lp
; lp
= lp
->next
) {
865 pmpkg_t
*info
= lp
->data
;
867 if(info
&& strcmp(alpm_pkg_get_name(info
), needle
) == 0) {
874 /** Test if a package should be ignored.
876 * Checks if the package is ignored via IgnorePkg, or if the package is
877 * in a group ignored via IgnoreGrp.
879 * @param pkg the package to test
881 * @return 1 if the package should be ignored, 0 otherwise
883 int _alpm_pkg_should_ignore(pmpkg_t
*pkg
)
885 alpm_list_t
*groups
= NULL
;
887 /* first see if the package is ignored */
888 if(alpm_list_find_str(handle
->ignorepkg
, alpm_pkg_get_name(pkg
))) {
892 /* next see if the package is in a group that is ignored */
893 for(groups
= handle
->ignoregrp
; groups
; groups
= alpm_list_next(groups
)) {
894 char *grp
= (char *)alpm_list_getdata(groups
);
895 if(alpm_list_find_str(alpm_pkg_get_groups(pkg
), grp
)) {
903 /* vim: set ts=2 sw=2 noet: */