1 /*
2  *  package.c
3  *
4  *  Copyright (c) 2006-2018 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>
9  *
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.
14  *
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.
19  *
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/>.
22  */
23 
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/types.h>
27 
28 /* libalpm */
29 #include "package.h"
30 #include "alpm_list.h"
31 #include "log.h"
32 #include "util.h"
33 #include "db.h"
34 #include "delta.h"
35 #include "handle.h"
36 #include "deps.h"
37 
38 /** \addtogroup alpm_packages Package Functions
39  * @brief Functions to manipulate libalpm packages
40  * @{
41  */
42 
43 /** Free a package. */
alpm_pkg_free(alpm_pkg_t * pkg)44 int SYMEXPORT alpm_pkg_free(alpm_pkg_t *pkg)
45 {
46 	ASSERT(pkg != NULL, return -1);
47 
48 	/* Only free packages loaded in user space */
49 	if(pkg->origin == ALPM_PKG_FROM_FILE) {
50 		_alpm_pkg_free(pkg);
51 	}
52 
53 	return 0;
54 }
55 
56 /** Check the integrity (with md5) of a package from the sync cache. */
alpm_pkg_checkmd5sum(alpm_pkg_t * pkg)57 int SYMEXPORT alpm_pkg_checkmd5sum(alpm_pkg_t *pkg)
58 {
59 	char *fpath;
60 	int retval;
61 
62 	ASSERT(pkg != NULL, return -1);
63 	pkg->handle->pm_errno = ALPM_ERR_OK;
64 	/* We only inspect packages from sync repositories */
65 	ASSERT(pkg->origin == ALPM_PKG_FROM_SYNCDB,
66 			RET_ERR(pkg->handle, ALPM_ERR_WRONG_ARGS, -1));
67 
68 	fpath = _alpm_filecache_find(pkg->handle, pkg->filename);
69 
70 	retval = _alpm_test_checksum(fpath, pkg->md5sum, ALPM_PKG_VALIDATION_MD5SUM);
71 
72 	FREE(fpath);
73 
74 	if(retval == 1) {
75 		pkg->handle->pm_errno = ALPM_ERR_PKG_INVALID;
76 		retval = -1;
77 	}
78 
79 	return retval;
80 }
81 
82 /* Default package accessor functions. These will get overridden by any
83  * backend logic that needs lazy access, such as the local database through
84  * a lazy-load cache. However, the defaults will work just fine for fully-
85  * populated package structures. */
_pkg_get_base(alpm_pkg_t * pkg)86 static const char *_pkg_get_base(alpm_pkg_t *pkg)        { return pkg->base; }
_pkg_get_desc(alpm_pkg_t * pkg)87 static const char *_pkg_get_desc(alpm_pkg_t *pkg)        { return pkg->desc; }
_pkg_get_url(alpm_pkg_t * pkg)88 static const char *_pkg_get_url(alpm_pkg_t *pkg)         { return pkg->url; }
_pkg_get_builddate(alpm_pkg_t * pkg)89 static alpm_time_t _pkg_get_builddate(alpm_pkg_t *pkg)   { return pkg->builddate; }
_pkg_get_installdate(alpm_pkg_t * pkg)90 static alpm_time_t _pkg_get_installdate(alpm_pkg_t *pkg) { return pkg->installdate; }
_pkg_get_packager(alpm_pkg_t * pkg)91 static const char *_pkg_get_packager(alpm_pkg_t *pkg)    { return pkg->packager; }
_pkg_get_arch(alpm_pkg_t * pkg)92 static const char *_pkg_get_arch(alpm_pkg_t *pkg)        { return pkg->arch; }
_pkg_get_isize(alpm_pkg_t * pkg)93 static off_t _pkg_get_isize(alpm_pkg_t *pkg)             { return pkg->isize; }
_pkg_get_reason(alpm_pkg_t * pkg)94 static alpm_pkgreason_t _pkg_get_reason(alpm_pkg_t *pkg) { return pkg->reason; }
_pkg_get_validation(alpm_pkg_t * pkg)95 static int _pkg_get_validation(alpm_pkg_t *pkg) { return pkg->validation; }
_pkg_has_scriptlet(alpm_pkg_t * pkg)96 static int _pkg_has_scriptlet(alpm_pkg_t *pkg)           { return pkg->scriptlet; }
97 
_pkg_get_licenses(alpm_pkg_t * pkg)98 static alpm_list_t *_pkg_get_licenses(alpm_pkg_t *pkg)   { return pkg->licenses; }
_pkg_get_groups(alpm_pkg_t * pkg)99 static alpm_list_t *_pkg_get_groups(alpm_pkg_t *pkg)     { return pkg->groups; }
_pkg_get_depends(alpm_pkg_t * pkg)100 static alpm_list_t *_pkg_get_depends(alpm_pkg_t *pkg)    { return pkg->depends; }
_pkg_get_optdepends(alpm_pkg_t * pkg)101 static alpm_list_t *_pkg_get_optdepends(alpm_pkg_t *pkg) { return pkg->optdepends; }
_pkg_get_checkdepends(alpm_pkg_t * pkg)102 static alpm_list_t *_pkg_get_checkdepends(alpm_pkg_t *pkg) { return pkg->checkdepends; }
_pkg_get_makedepends(alpm_pkg_t * pkg)103 static alpm_list_t *_pkg_get_makedepends(alpm_pkg_t *pkg) { return pkg->makedepends; }
_pkg_get_conflicts(alpm_pkg_t * pkg)104 static alpm_list_t *_pkg_get_conflicts(alpm_pkg_t *pkg)  { return pkg->conflicts; }
_pkg_get_provides(alpm_pkg_t * pkg)105 static alpm_list_t *_pkg_get_provides(alpm_pkg_t *pkg)   { return pkg->provides; }
_pkg_get_replaces(alpm_pkg_t * pkg)106 static alpm_list_t *_pkg_get_replaces(alpm_pkg_t *pkg)   { return pkg->replaces; }
_pkg_get_files(alpm_pkg_t * pkg)107 static alpm_filelist_t *_pkg_get_files(alpm_pkg_t *pkg)  { return &(pkg->files); }
_pkg_get_backup(alpm_pkg_t * pkg)108 static alpm_list_t *_pkg_get_backup(alpm_pkg_t *pkg)     { return pkg->backup; }
109 
_pkg_changelog_open(alpm_pkg_t UNUSED * pkg)110 static void *_pkg_changelog_open(alpm_pkg_t UNUSED *pkg)
111 {
112 	return NULL;
113 }
114 
_pkg_changelog_read(void UNUSED * ptr,size_t UNUSED size,const alpm_pkg_t UNUSED * pkg,UNUSED void * fp)115 static size_t _pkg_changelog_read(void UNUSED *ptr, size_t UNUSED size,
116 		const alpm_pkg_t UNUSED *pkg, UNUSED void *fp)
117 {
118 	return 0;
119 }
120 
_pkg_changelog_close(const alpm_pkg_t UNUSED * pkg,void UNUSED * fp)121 static int _pkg_changelog_close(const alpm_pkg_t UNUSED *pkg,
122 		void UNUSED *fp)
123 {
124 	return EOF;
125 }
126 
_pkg_mtree_open(alpm_pkg_t UNUSED * pkg)127 static struct archive *_pkg_mtree_open(alpm_pkg_t UNUSED *pkg)
128 {
129 	return NULL;
130 }
131 
_pkg_mtree_next(const alpm_pkg_t UNUSED * pkg,struct archive UNUSED * archive,struct archive_entry UNUSED ** entry)132 static int _pkg_mtree_next(const alpm_pkg_t UNUSED *pkg,
133 		struct archive UNUSED *archive, struct archive_entry UNUSED **entry)
134 {
135 	return -1;
136 }
137 
_pkg_mtree_close(const alpm_pkg_t UNUSED * pkg,struct archive UNUSED * archive)138 static int _pkg_mtree_close(const alpm_pkg_t UNUSED *pkg,
139 		struct archive UNUSED *archive)
140 {
141 	return -1;
142 }
143 
_pkg_force_load(alpm_pkg_t UNUSED * pkg)144 static int _pkg_force_load(alpm_pkg_t UNUSED *pkg) { return 0; }
145 
146 /** The standard package operations struct. Get fields directly from the
147  * struct itself with no abstraction layer or any type of lazy loading.
148  */
149 struct pkg_operations default_pkg_ops = {
150 	.get_base        = _pkg_get_base,
151 	.get_desc        = _pkg_get_desc,
152 	.get_url         = _pkg_get_url,
153 	.get_builddate   = _pkg_get_builddate,
154 	.get_installdate = _pkg_get_installdate,
155 	.get_packager    = _pkg_get_packager,
156 	.get_arch        = _pkg_get_arch,
157 	.get_isize       = _pkg_get_isize,
158 	.get_reason      = _pkg_get_reason,
159 	.get_validation  = _pkg_get_validation,
160 	.has_scriptlet   = _pkg_has_scriptlet,
161 
162 	.get_licenses    = _pkg_get_licenses,
163 	.get_groups      = _pkg_get_groups,
164 	.get_depends     = _pkg_get_depends,
165 	.get_optdepends  = _pkg_get_optdepends,
166 	.get_checkdepends = _pkg_get_checkdepends,
167 	.get_makedepends = _pkg_get_makedepends,
168 	.get_conflicts   = _pkg_get_conflicts,
169 	.get_provides    = _pkg_get_provides,
170 	.get_replaces    = _pkg_get_replaces,
171 	.get_files       = _pkg_get_files,
172 	.get_backup      = _pkg_get_backup,
173 
174 	.changelog_open  = _pkg_changelog_open,
175 	.changelog_read  = _pkg_changelog_read,
176 	.changelog_close = _pkg_changelog_close,
177 
178 	.mtree_open      = _pkg_mtree_open,
179 	.mtree_next      = _pkg_mtree_next,
180 	.mtree_close     = _pkg_mtree_close,
181 
182 	.force_load      = _pkg_force_load,
183 };
184 
185 /* Public functions for getting package information. These functions
186  * delegate the hard work to the function callbacks attached to each
187  * package, which depend on where the package was loaded from. */
alpm_pkg_get_filename(alpm_pkg_t * pkg)188 const char SYMEXPORT *alpm_pkg_get_filename(alpm_pkg_t *pkg)
189 {
190 	ASSERT(pkg != NULL, return NULL);
191 	pkg->handle->pm_errno = ALPM_ERR_OK;
192 	return pkg->filename;
193 }
194 
alpm_pkg_get_base(alpm_pkg_t * pkg)195 const char SYMEXPORT *alpm_pkg_get_base(alpm_pkg_t *pkg)
196 {
197 	ASSERT(pkg != NULL, return NULL);
198 	pkg->handle->pm_errno = ALPM_ERR_OK;
199 	return pkg->ops->get_base(pkg);
200 }
201 
alpm_pkg_get_name(alpm_pkg_t * pkg)202 const char SYMEXPORT *alpm_pkg_get_name(alpm_pkg_t *pkg)
203 {
204 	ASSERT(pkg != NULL, return NULL);
205 	pkg->handle->pm_errno = ALPM_ERR_OK;
206 	return pkg->name;
207 }
208 
alpm_pkg_get_version(alpm_pkg_t * pkg)209 const char SYMEXPORT *alpm_pkg_get_version(alpm_pkg_t *pkg)
210 {
211 	ASSERT(pkg != NULL, return NULL);
212 	pkg->handle->pm_errno = ALPM_ERR_OK;
213 	return pkg->version;
214 }
215 
alpm_pkg_get_origin(alpm_pkg_t * pkg)216 alpm_pkgfrom_t SYMEXPORT alpm_pkg_get_origin(alpm_pkg_t *pkg)
217 {
218 	ASSERT(pkg != NULL, return -1);
219 	pkg->handle->pm_errno = ALPM_ERR_OK;
220 	return pkg->origin;
221 }
222 
alpm_pkg_get_desc(alpm_pkg_t * pkg)223 const char SYMEXPORT *alpm_pkg_get_desc(alpm_pkg_t *pkg)
224 {
225 	ASSERT(pkg != NULL, return NULL);
226 	pkg->handle->pm_errno = ALPM_ERR_OK;
227 	return pkg->ops->get_desc(pkg);
228 }
229 
alpm_pkg_get_url(alpm_pkg_t * pkg)230 const char SYMEXPORT *alpm_pkg_get_url(alpm_pkg_t *pkg)
231 {
232 	ASSERT(pkg != NULL, return NULL);
233 	pkg->handle->pm_errno = ALPM_ERR_OK;
234 	return pkg->ops->get_url(pkg);
235 }
236 
alpm_pkg_get_builddate(alpm_pkg_t * pkg)237 alpm_time_t SYMEXPORT alpm_pkg_get_builddate(alpm_pkg_t *pkg)
238 {
239 	ASSERT(pkg != NULL, return -1);
240 	pkg->handle->pm_errno = ALPM_ERR_OK;
241 	return pkg->ops->get_builddate(pkg);
242 }
243 
alpm_pkg_get_installdate(alpm_pkg_t * pkg)244 alpm_time_t SYMEXPORT alpm_pkg_get_installdate(alpm_pkg_t *pkg)
245 {
246 	ASSERT(pkg != NULL, return -1);
247 	pkg->handle->pm_errno = ALPM_ERR_OK;
248 	return pkg->ops->get_installdate(pkg);
249 }
250 
alpm_pkg_get_packager(alpm_pkg_t * pkg)251 const char SYMEXPORT *alpm_pkg_get_packager(alpm_pkg_t *pkg)
252 {
253 	ASSERT(pkg != NULL, return NULL);
254 	pkg->handle->pm_errno = ALPM_ERR_OK;
255 	return pkg->ops->get_packager(pkg);
256 }
257 
alpm_pkg_get_md5sum(alpm_pkg_t * pkg)258 const char SYMEXPORT *alpm_pkg_get_md5sum(alpm_pkg_t *pkg)
259 {
260 	ASSERT(pkg != NULL, return NULL);
261 	pkg->handle->pm_errno = ALPM_ERR_OK;
262 	return pkg->md5sum;
263 }
264 
alpm_pkg_get_sha256sum(alpm_pkg_t * pkg)265 const char SYMEXPORT *alpm_pkg_get_sha256sum(alpm_pkg_t *pkg)
266 {
267 	ASSERT(pkg != NULL, return NULL);
268 	pkg->handle->pm_errno = ALPM_ERR_OK;
269 	return pkg->sha256sum;
270 }
271 
alpm_pkg_get_base64_sig(alpm_pkg_t * pkg)272 const char SYMEXPORT *alpm_pkg_get_base64_sig(alpm_pkg_t *pkg)
273 {
274 	ASSERT(pkg != NULL, return NULL);
275 	pkg->handle->pm_errno = ALPM_ERR_OK;
276 	return pkg->base64_sig;
277 }
278 
alpm_pkg_get_arch(alpm_pkg_t * pkg)279 const char SYMEXPORT *alpm_pkg_get_arch(alpm_pkg_t *pkg)
280 {
281 	ASSERT(pkg != NULL, return NULL);
282 	pkg->handle->pm_errno = ALPM_ERR_OK;
283 	return pkg->ops->get_arch(pkg);
284 }
285 
alpm_pkg_get_size(alpm_pkg_t * pkg)286 off_t SYMEXPORT alpm_pkg_get_size(alpm_pkg_t *pkg)
287 {
288 	ASSERT(pkg != NULL, return -1);
289 	pkg->handle->pm_errno = ALPM_ERR_OK;
290 	return pkg->size;
291 }
292 
alpm_pkg_get_isize(alpm_pkg_t * pkg)293 off_t SYMEXPORT alpm_pkg_get_isize(alpm_pkg_t *pkg)
294 {
295 	ASSERT(pkg != NULL, return -1);
296 	pkg->handle->pm_errno = ALPM_ERR_OK;
297 	return pkg->ops->get_isize(pkg);
298 }
299 
alpm_pkg_get_reason(alpm_pkg_t * pkg)300 alpm_pkgreason_t SYMEXPORT alpm_pkg_get_reason(alpm_pkg_t *pkg)
301 {
302 	ASSERT(pkg != NULL, return -1);
303 	pkg->handle->pm_errno = ALPM_ERR_OK;
304 	return pkg->ops->get_reason(pkg);
305 }
306 
alpm_pkg_get_validation(alpm_pkg_t * pkg)307 int SYMEXPORT alpm_pkg_get_validation(alpm_pkg_t *pkg)
308 {
309 	ASSERT(pkg != NULL, return -1);
310 	pkg->handle->pm_errno = ALPM_ERR_OK;
311 	return pkg->ops->get_validation(pkg);
312 }
313 
alpm_pkg_get_licenses(alpm_pkg_t * pkg)314 alpm_list_t SYMEXPORT *alpm_pkg_get_licenses(alpm_pkg_t *pkg)
315 {
316 	ASSERT(pkg != NULL, return NULL);
317 	pkg->handle->pm_errno = ALPM_ERR_OK;
318 	return pkg->ops->get_licenses(pkg);
319 }
320 
alpm_pkg_get_groups(alpm_pkg_t * pkg)321 alpm_list_t SYMEXPORT *alpm_pkg_get_groups(alpm_pkg_t *pkg)
322 {
323 	ASSERT(pkg != NULL, return NULL);
324 	pkg->handle->pm_errno = ALPM_ERR_OK;
325 	return pkg->ops->get_groups(pkg);
326 }
327 
alpm_pkg_get_depends(alpm_pkg_t * pkg)328 alpm_list_t SYMEXPORT *alpm_pkg_get_depends(alpm_pkg_t *pkg)
329 {
330 	ASSERT(pkg != NULL, return NULL);
331 	pkg->handle->pm_errno = ALPM_ERR_OK;
332 	return pkg->ops->get_depends(pkg);
333 }
334 
alpm_pkg_get_optdepends(alpm_pkg_t * pkg)335 alpm_list_t SYMEXPORT *alpm_pkg_get_optdepends(alpm_pkg_t *pkg)
336 {
337 	ASSERT(pkg != NULL, return NULL);
338 	pkg->handle->pm_errno = ALPM_ERR_OK;
339 	return pkg->ops->get_optdepends(pkg);
340 }
341 
alpm_pkg_get_checkdepends(alpm_pkg_t * pkg)342 alpm_list_t SYMEXPORT *alpm_pkg_get_checkdepends(alpm_pkg_t *pkg)
343 {
344 	ASSERT(pkg != NULL, return NULL);
345 	pkg->handle->pm_errno = ALPM_ERR_OK;
346 	return pkg->ops->get_checkdepends(pkg);
347 }
348 
alpm_pkg_get_makedepends(alpm_pkg_t * pkg)349 alpm_list_t SYMEXPORT *alpm_pkg_get_makedepends(alpm_pkg_t *pkg)
350 {
351 	ASSERT(pkg != NULL, return NULL);
352 	pkg->handle->pm_errno = ALPM_ERR_OK;
353 	return pkg->ops->get_makedepends(pkg);
354 }
355 
alpm_pkg_get_conflicts(alpm_pkg_t * pkg)356 alpm_list_t SYMEXPORT *alpm_pkg_get_conflicts(alpm_pkg_t *pkg)
357 {
358 	ASSERT(pkg != NULL, return NULL);
359 	pkg->handle->pm_errno = ALPM_ERR_OK;
360 	return pkg->ops->get_conflicts(pkg);
361 }
362 
alpm_pkg_get_provides(alpm_pkg_t * pkg)363 alpm_list_t SYMEXPORT *alpm_pkg_get_provides(alpm_pkg_t *pkg)
364 {
365 	ASSERT(pkg != NULL, return NULL);
366 	pkg->handle->pm_errno = ALPM_ERR_OK;
367 	return pkg->ops->get_provides(pkg);
368 }
369 
alpm_pkg_get_replaces(alpm_pkg_t * pkg)370 alpm_list_t SYMEXPORT *alpm_pkg_get_replaces(alpm_pkg_t *pkg)
371 {
372 	ASSERT(pkg != NULL, return NULL);
373 	pkg->handle->pm_errno = ALPM_ERR_OK;
374 	return pkg->ops->get_replaces(pkg);
375 }
376 
alpm_pkg_get_deltas(alpm_pkg_t * pkg)377 alpm_list_t SYMEXPORT *alpm_pkg_get_deltas(alpm_pkg_t *pkg)
378 {
379 	ASSERT(pkg != NULL, return NULL);
380 	pkg->handle->pm_errno = ALPM_ERR_OK;
381 	return pkg->deltas;
382 }
383 
alpm_pkg_get_files(alpm_pkg_t * pkg)384 alpm_filelist_t SYMEXPORT *alpm_pkg_get_files(alpm_pkg_t *pkg)
385 {
386 	ASSERT(pkg != NULL, return NULL);
387 	pkg->handle->pm_errno = ALPM_ERR_OK;
388 	return pkg->ops->get_files(pkg);
389 }
390 
alpm_pkg_get_backup(alpm_pkg_t * pkg)391 alpm_list_t SYMEXPORT *alpm_pkg_get_backup(alpm_pkg_t *pkg)
392 {
393 	ASSERT(pkg != NULL, return NULL);
394 	pkg->handle->pm_errno = ALPM_ERR_OK;
395 	return pkg->ops->get_backup(pkg);
396 }
397 
alpm_pkg_get_db(alpm_pkg_t * pkg)398 alpm_db_t SYMEXPORT *alpm_pkg_get_db(alpm_pkg_t *pkg)
399 {
400 	/* Sanity checks */
401 	ASSERT(pkg != NULL, return NULL);
402 	ASSERT(pkg->origin != ALPM_PKG_FROM_FILE, return NULL);
403 	pkg->handle->pm_errno = ALPM_ERR_OK;
404 
405 	return pkg->origin_data.db;
406 }
407 
408 /** Open a package changelog for reading. */
alpm_pkg_changelog_open(alpm_pkg_t * pkg)409 void SYMEXPORT *alpm_pkg_changelog_open(alpm_pkg_t *pkg)
410 {
411 	ASSERT(pkg != NULL, return NULL);
412 	pkg->handle->pm_errno = ALPM_ERR_OK;
413 	return pkg->ops->changelog_open(pkg);
414 }
415 
416 /** Read data from an open changelog 'file stream'. */
alpm_pkg_changelog_read(void * ptr,size_t size,const alpm_pkg_t * pkg,void * fp)417 size_t SYMEXPORT alpm_pkg_changelog_read(void *ptr, size_t size,
418 		const alpm_pkg_t *pkg, void *fp)
419 {
420 	ASSERT(pkg != NULL, return 0);
421 	pkg->handle->pm_errno = ALPM_ERR_OK;
422 	return pkg->ops->changelog_read(ptr, size, pkg, fp);
423 }
424 
425 /** Close a package changelog for reading. */
alpm_pkg_changelog_close(const alpm_pkg_t * pkg,void * fp)426 int SYMEXPORT alpm_pkg_changelog_close(const alpm_pkg_t *pkg, void *fp)
427 {
428 	ASSERT(pkg != NULL, return -1);
429 	pkg->handle->pm_errno = ALPM_ERR_OK;
430 	return pkg->ops->changelog_close(pkg, fp);
431 }
432 
433 /** Open a package mtree file for reading. */
alpm_pkg_mtree_open(alpm_pkg_t * pkg)434 struct archive SYMEXPORT *alpm_pkg_mtree_open(alpm_pkg_t * pkg)
435 {
436 	ASSERT(pkg != NULL, return NULL);
437 	pkg->handle->pm_errno = ALPM_ERR_OK;
438 	return pkg->ops->mtree_open(pkg);
439 }
440 
441 /** Read entry from an open mtree file. */
alpm_pkg_mtree_next(const alpm_pkg_t * pkg,struct archive * archive,struct archive_entry ** entry)442 int SYMEXPORT alpm_pkg_mtree_next(const alpm_pkg_t * pkg, struct archive *archive,
443 	struct archive_entry **entry)
444 {
445 	ASSERT(pkg != NULL, return -1);
446 	pkg->handle->pm_errno = ALPM_ERR_OK;
447 	return pkg->ops->mtree_next(pkg, archive, entry);
448 }
449 
450 /** Close a package mtree file for reading. */
alpm_pkg_mtree_close(const alpm_pkg_t * pkg,struct archive * archive)451 int SYMEXPORT alpm_pkg_mtree_close(const alpm_pkg_t * pkg, struct archive *archive)
452 {
453 	ASSERT(pkg != NULL, return -1);
454 	pkg->handle->pm_errno = ALPM_ERR_OK;
455 	return pkg->ops->mtree_close(pkg, archive);
456 }
457 
alpm_pkg_has_scriptlet(alpm_pkg_t * pkg)458 int SYMEXPORT alpm_pkg_has_scriptlet(alpm_pkg_t *pkg)
459 {
460 	ASSERT(pkg != NULL, return -1);
461 	pkg->handle->pm_errno = ALPM_ERR_OK;
462 	return pkg->ops->has_scriptlet(pkg);
463 }
464 
find_requiredby(alpm_pkg_t * pkg,alpm_db_t * db,alpm_list_t ** reqs,int optional)465 static void find_requiredby(alpm_pkg_t *pkg, alpm_db_t *db, alpm_list_t **reqs,
466 		int optional)
467 {
468 	const alpm_list_t *i;
469 	pkg->handle->pm_errno = ALPM_ERR_OK;
470 
471 	for(i = _alpm_db_get_pkgcache(db); i; i = i->next) {
472 		alpm_pkg_t *cachepkg = i->data;
473 		alpm_list_t *j;
474 
475 		if(optional == 0) {
476 			j = alpm_pkg_get_depends(cachepkg);
477 		} else {
478 			j = alpm_pkg_get_optdepends(cachepkg);
479 		}
480 
481 		for(; j; j = j->next) {
482 			if(_alpm_depcmp(pkg, j->data)) {
483 				const char *cachepkgname = cachepkg->name;
484 				if(alpm_list_find_str(*reqs, cachepkgname) == NULL) {
485 					*reqs = alpm_list_add(*reqs, strdup(cachepkgname));
486 				}
487 			}
488 		}
489 	}
490 }
491 
compute_requiredby(alpm_pkg_t * pkg,int optional)492 static alpm_list_t *compute_requiredby(alpm_pkg_t *pkg, int optional)
493 {
494 	const alpm_list_t *i;
495 	alpm_list_t *reqs = NULL;
496 	alpm_db_t *db;
497 
498 	ASSERT(pkg != NULL, return NULL);
499 	pkg->handle->pm_errno = ALPM_ERR_OK;
500 
501 	if(pkg->origin == ALPM_PKG_FROM_FILE) {
502 		/* The sane option; search locally for things that require this. */
503 		find_requiredby(pkg, pkg->handle->db_local, &reqs, optional);
504 	} else {
505 		/* We have a DB package. if it is a local package, then we should
506 		 * only search the local DB; else search all known sync databases. */
507 		db = pkg->origin_data.db;
508 		if(db->status & DB_STATUS_LOCAL) {
509 			find_requiredby(pkg, db, &reqs, optional);
510 		} else {
511 			for(i = pkg->handle->dbs_sync; i; i = i->next) {
512 				db = i->data;
513 				find_requiredby(pkg, db, &reqs, optional);
514 			}
515 			reqs = alpm_list_msort(reqs, alpm_list_count(reqs), _alpm_str_cmp);
516 		}
517 	}
518 	return reqs;
519 }
520 
521 /** Compute the packages requiring a given package. */
alpm_pkg_compute_requiredby(alpm_pkg_t * pkg)522 alpm_list_t SYMEXPORT *alpm_pkg_compute_requiredby(alpm_pkg_t *pkg)
523 {
524 	return compute_requiredby(pkg, 0);
525 }
526 
527 /** Compute the packages optionally requiring a given package. */
alpm_pkg_compute_optionalfor(alpm_pkg_t * pkg)528 alpm_list_t SYMEXPORT *alpm_pkg_compute_optionalfor(alpm_pkg_t *pkg)
529 {
530 	return compute_requiredby(pkg, 1);
531 }
532 
533 
534 /** @} */
535 
_alpm_file_copy(alpm_file_t * dest,const alpm_file_t * src)536 alpm_file_t *_alpm_file_copy(alpm_file_t *dest,
537 		const alpm_file_t *src)
538 {
539 	STRDUP(dest->name, src->name, return NULL);
540 	dest->size = src->size;
541 	dest->mode = src->mode;
542 
543 	return dest;
544 }
545 
_alpm_pkg_new(void)546 alpm_pkg_t *_alpm_pkg_new(void)
547 {
548 	alpm_pkg_t *pkg;
549 
550 	CALLOC(pkg, 1, sizeof(alpm_pkg_t), return NULL);
551 
552 	return pkg;
553 }
554 
list_depdup(alpm_list_t * old)555 static alpm_list_t *list_depdup(alpm_list_t *old)
556 {
557 	alpm_list_t *i, *new = NULL;
558 	for(i = old; i; i = i->next) {
559 		new = alpm_list_add(new, _alpm_dep_dup(i->data));
560 	}
561 	return new;
562 }
563 
564 /**
565  * Duplicate a package data struct.
566  * @param pkg the package to duplicate
567  * @param new_ptr location to store duplicated package pointer
568  * @return 0 on success, -1 on fatal error, 1 on non-fatal error
569  */
_alpm_pkg_dup(alpm_pkg_t * pkg,alpm_pkg_t ** new_ptr)570 int _alpm_pkg_dup(alpm_pkg_t *pkg, alpm_pkg_t **new_ptr)
571 {
572 	alpm_pkg_t *newpkg;
573 	alpm_list_t *i;
574 	int ret = 0;
575 
576 	if(!pkg || !pkg->handle) {
577 		return -1;
578 	}
579 
580 	if(!new_ptr) {
581 		RET_ERR(pkg->handle, ALPM_ERR_WRONG_ARGS, -1);
582 	}
583 
584 	if(pkg->ops->force_load(pkg)) {
585 		_alpm_log(pkg->handle, ALPM_LOG_WARNING,
586 				_("could not fully load metadata for package %s-%s\n"),
587 				pkg->name, pkg->version);
588 		ret = 1;
589 		pkg->handle->pm_errno = ALPM_ERR_PKG_INVALID;
590 	}
591 
592 	CALLOC(newpkg, 1, sizeof(alpm_pkg_t), goto cleanup);
593 
594 	newpkg->name_hash = pkg->name_hash;
595 	STRDUP(newpkg->filename, pkg->filename, goto cleanup);
596 	STRDUP(newpkg->base, pkg->base, goto cleanup);
597 	STRDUP(newpkg->name, pkg->name, goto cleanup);
598 	STRDUP(newpkg->version, pkg->version, goto cleanup);
599 	STRDUP(newpkg->desc, pkg->desc, goto cleanup);
600 	STRDUP(newpkg->url, pkg->url, goto cleanup);
601 	newpkg->builddate = pkg->builddate;
602 	newpkg->installdate = pkg->installdate;
603 	STRDUP(newpkg->packager, pkg->packager, goto cleanup);
604 	STRDUP(newpkg->md5sum, pkg->md5sum, goto cleanup);
605 	STRDUP(newpkg->sha256sum, pkg->sha256sum, goto cleanup);
606 	STRDUP(newpkg->arch, pkg->arch, goto cleanup);
607 	newpkg->size = pkg->size;
608 	newpkg->isize = pkg->isize;
609 	newpkg->scriptlet = pkg->scriptlet;
610 	newpkg->reason = pkg->reason;
611 	newpkg->validation = pkg->validation;
612 
613 	newpkg->licenses   = alpm_list_strdup(pkg->licenses);
614 	newpkg->replaces   = list_depdup(pkg->replaces);
615 	newpkg->groups     = alpm_list_strdup(pkg->groups);
616 	for(i = pkg->backup; i; i = i->next) {
617 		newpkg->backup = alpm_list_add(newpkg->backup, _alpm_backup_dup(i->data));
618 	}
619 	newpkg->depends    = list_depdup(pkg->depends);
620 	newpkg->optdepends = list_depdup(pkg->optdepends);
621 	newpkg->conflicts  = list_depdup(pkg->conflicts);
622 	newpkg->provides   = list_depdup(pkg->provides);
623 	for(i = pkg->deltas; i; i = i->next) {
624 		newpkg->deltas = alpm_list_add(newpkg->deltas, _alpm_delta_dup(i->data));
625 	}
626 
627 	if(pkg->files.count) {
628 		size_t filenum;
629 		size_t len = sizeof(alpm_file_t) * pkg->files.count;
630 		MALLOC(newpkg->files.files, len, goto cleanup);
631 		for(filenum = 0; filenum < pkg->files.count; filenum++) {
632 			if(!_alpm_file_copy(newpkg->files.files + filenum,
633 						pkg->files.files + filenum)) {
634 				goto cleanup;
635 			}
636 		}
637 		newpkg->files.count = pkg->files.count;
638 	}
639 
640 	/* internal */
641 	newpkg->infolevel = pkg->infolevel;
642 	newpkg->origin = pkg->origin;
643 	if(newpkg->origin == ALPM_PKG_FROM_FILE) {
644 		STRDUP(newpkg->origin_data.file, pkg->origin_data.file, goto cleanup);
645 	} else {
646 		newpkg->origin_data.db = pkg->origin_data.db;
647 	}
648 	newpkg->ops = pkg->ops;
649 	newpkg->handle = pkg->handle;
650 
651 	*new_ptr = newpkg;
652 	return ret;
653 
654 cleanup:
655 	_alpm_pkg_free(newpkg);
656 	RET_ERR(pkg->handle, ALPM_ERR_MEMORY, -1);
657 }
658 
free_deplist(alpm_list_t * deps)659 static void free_deplist(alpm_list_t *deps)
660 {
661 	alpm_list_free_inner(deps, (alpm_list_fn_free)alpm_dep_free);
662 	alpm_list_free(deps);
663 }
664 
_alpm_pkg_free(alpm_pkg_t * pkg)665 void _alpm_pkg_free(alpm_pkg_t *pkg)
666 {
667 	if(pkg == NULL) {
668 		return;
669 	}
670 
671 	FREE(pkg->filename);
672 	FREE(pkg->base);
673 	FREE(pkg->name);
674 	FREE(pkg->version);
675 	FREE(pkg->desc);
676 	FREE(pkg->url);
677 	FREE(pkg->packager);
678 	FREE(pkg->md5sum);
679 	FREE(pkg->sha256sum);
680 	FREE(pkg->base64_sig);
681 	FREE(pkg->arch);
682 
683 	FREELIST(pkg->licenses);
684 	free_deplist(pkg->replaces);
685 	FREELIST(pkg->groups);
686 	if(pkg->files.count) {
687 		size_t i;
688 		for(i = 0; i < pkg->files.count; i++) {
689 			FREE(pkg->files.files[i].name);
690 		}
691 		free(pkg->files.files);
692 	}
693 	alpm_list_free_inner(pkg->backup, (alpm_list_fn_free)_alpm_backup_free);
694 	alpm_list_free(pkg->backup);
695 	free_deplist(pkg->depends);
696 	free_deplist(pkg->optdepends);
697 	free_deplist(pkg->conflicts);
698 	free_deplist(pkg->provides);
699 	alpm_list_free_inner(pkg->deltas, (alpm_list_fn_free)_alpm_delta_free);
700 	alpm_list_free(pkg->deltas);
701 	alpm_list_free(pkg->delta_path);
702 	alpm_list_free(pkg->removes);
703 	_alpm_pkg_free(pkg->oldpkg);
704 
705 	if(pkg->origin == ALPM_PKG_FROM_FILE) {
706 		FREE(pkg->origin_data.file);
707 	}
708 	FREE(pkg);
709 }
710 
711 /* This function should be used when removing a target from upgrade/sync target list
712  * Case 1: If pkg is a loaded package file (ALPM_PKG_FROM_FILE), it will be freed.
713  * Case 2: If pkg is a pkgcache entry (ALPM_PKG_FROM_CACHE), it won't be freed,
714  *         only the transaction specific fields of pkg will be freed.
715  */
_alpm_pkg_free_trans(alpm_pkg_t * pkg)716 void _alpm_pkg_free_trans(alpm_pkg_t *pkg)
717 {
718 	if(pkg == NULL) {
719 		return;
720 	}
721 
722 	if(pkg->origin == ALPM_PKG_FROM_FILE) {
723 		_alpm_pkg_free(pkg);
724 		return;
725 	}
726 
727 	alpm_list_free(pkg->removes);
728 	pkg->removes = NULL;
729 	_alpm_pkg_free(pkg->oldpkg);
730 	pkg->oldpkg = NULL;
731 }
732 
733 /* Is spkg an upgrade for localpkg? */
_alpm_pkg_compare_versions(alpm_pkg_t * spkg,alpm_pkg_t * localpkg)734 int _alpm_pkg_compare_versions(alpm_pkg_t *spkg, alpm_pkg_t *localpkg)
735 {
736 	return alpm_pkg_vercmp(spkg->version, localpkg->version);
737 }
738 
739 /* Helper function for comparing packages
740  */
_alpm_pkg_cmp(const void * p1,const void * p2)741 int _alpm_pkg_cmp(const void *p1, const void *p2)
742 {
743 	const alpm_pkg_t *pkg1 = p1;
744 	const alpm_pkg_t *pkg2 = p2;
745 	return strcmp(pkg1->name, pkg2->name);
746 }
747 
748 /* Test for existence of a package in a alpm_list_t*
749  * of alpm_pkg_t*
750  */
alpm_pkg_find(alpm_list_t * haystack,const char * needle)751 alpm_pkg_t SYMEXPORT *alpm_pkg_find(alpm_list_t *haystack, const char *needle)
752 {
753 	alpm_list_t *lp;
754 	unsigned long needle_hash;
755 
756 	if(needle == NULL || haystack == NULL) {
757 		return NULL;
758 	}
759 
760 	needle_hash = _alpm_hash_sdbm(needle);
761 
762 	for(lp = haystack; lp; lp = lp->next) {
763 		alpm_pkg_t *info = lp->data;
764 
765 		if(info) {
766 			if(info->name_hash != needle_hash) {
767 				continue;
768 			}
769 
770 			/* finally: we had hash match, verify string match */
771 			if(strcmp(info->name, needle) == 0) {
772 				return info;
773 			}
774 		}
775 	}
776 	return NULL;
777 }
778 
779 /** Test if a package should be ignored.
780  *
781  * Checks if the package is ignored via IgnorePkg, or if the package is
782  * in a group ignored via IgnoreGroup.
783  *
784  * @param handle the context handle
785  * @param pkg the package to test
786  *
787  * @return 1 if the package should be ignored, 0 otherwise
788  */
alpm_pkg_should_ignore(alpm_handle_t * handle,alpm_pkg_t * pkg)789 int SYMEXPORT alpm_pkg_should_ignore(alpm_handle_t *handle, alpm_pkg_t *pkg)
790 {
791 	alpm_list_t *groups = NULL;
792 
793 	/* first see if the package is ignored */
794 	if(alpm_list_find(handle->ignorepkg, pkg->name, _alpm_fnmatch)) {
795 		return 1;
796 	}
797 
798 	/* next see if the package is in a group that is ignored */
799 	for(groups = alpm_pkg_get_groups(pkg); groups; groups = groups->next) {
800 		char *grp = groups->data;
801 		if(alpm_list_find(handle->ignoregroup, grp, _alpm_fnmatch)) {
802 			return 1;
803 		}
804 	}
805 
806 	return 0;
807 }
808