]> git.ipfire.org Git - pakfire.git/blame - src/libpakfire/package.c
package: Refactor pakfire_package_set_filelist_from_string
[pakfire.git] / src / libpakfire / package.c
CommitLineData
221cc3ce
MT
1/*#############################################################################
2# #
3# Pakfire - The IPFire package management system #
4# Copyright (C) 2013 Pakfire development team #
5# #
6# This program is free software: you can redistribute it and/or modify #
7# it under the terms of the GNU General Public License as published by #
8# the Free Software Foundation, either version 3 of the License, or #
9# (at your option) any later version. #
10# #
11# This program is distributed in the hope that it will be useful, #
12# but WITHOUT ANY WARRANTY; without even the implied warranty of #
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14# GNU General Public License for more details. #
15# #
16# You should have received a copy of the GNU General Public License #
17# along with this program. If not, see <http://www.gnu.org/licenses/>. #
18# #
19#############################################################################*/
20
e42b5960 21#include <errno.h>
4a81ff85 22#include <linux/limits.h>
221cc3ce
MT
23#include <stdlib.h>
24#include <string.h>
25#include <time.h>
57e2cf99 26#include <uuid/uuid.h>
221cc3ce 27
b59c9fa2
MT
28#include <json.h>
29
221cc3ce
MT
30#include <solv/evr.h>
31#include <solv/pool.h>
221cc3ce
MT
32#include <solv/repo.h>
33#include <solv/solvable.h>
34
cbed1552 35#include <pakfire/archive.h>
221cc3ce 36#include <pakfire/constants.h>
2a623cf8 37#include <pakfire/dependencies.h>
c52e0148 38#include <pakfire/digest.h>
221cc3ce 39#include <pakfire/file.h>
5e9463ec 40#include <pakfire/filelist.h>
221cc3ce 41#include <pakfire/i18n.h>
6cdfb9dd 42#include <pakfire/logging.h>
221cc3ce 43#include <pakfire/package.h>
cbed1552 44#include <pakfire/pakfire.h>
9f953e68 45#include <pakfire/private.h>
221cc3ce 46#include <pakfire/repo.h>
d973a13d 47#include <pakfire/string.h>
221cc3ce
MT
48#include <pakfire/util.h>
49
31480bee 50struct pakfire_package {
ac4c607b 51 struct pakfire* pakfire;
7847efcd 52 int nrefs;
e9d9eadc 53
8b088877
MT
54 // Reference to this package in the SOLV pool
55 Id id;
4651122b 56 struct pakfire_repo* repo;
8b088877 57
40fcf5ff 58 char nevra[NAME_MAX];
571539a7 59 char source_nevra[NAME_MAX];
40fcf5ff 60
b12a5d7d
MT
61 char filename[NAME_MAX];
62 char path[PATH_MAX];
7847efcd
MT
63};
64
ac4c607b 65struct pakfire_package* pakfire_package_create_from_solvable(struct pakfire* pakfire, Id id) {
31480bee 66 struct pakfire_package* pkg = calloc(1, sizeof(*pkg));
e9d9eadc
MT
67 if (!pkg)
68 return NULL;
6cdfb9dd 69
e9d9eadc
MT
70 pkg->pakfire = pakfire_ref(pakfire);
71 pkg->id = id;
72
73 // Initialize reference counter
74 pkg->nrefs = 1;
221cc3ce
MT
75
76 return pkg;
77}
78
32136e0c
MT
79PAKFIRE_EXPORT struct pakfire_package* pakfire_package_create(
80 struct pakfire* pakfire, struct pakfire_repo* repo,
81 const char* name, const char* evr, const char* arch) {
82 struct pakfire_package* pkg = NULL;
83 struct pakfire_repo* dummy = NULL;
84
85 // Default to dummy repository
86 if (!repo) {
87 dummy = pakfire_get_repo(pakfire, PAKFIRE_REPO_DUMMY);
88 if (!dummy) {
89 errno = ENOENT;
90 return NULL;
91 }
92
93 repo = dummy;
94 }
95
96 // Allocate a new solvable
e9d9eadc
MT
97 Id id = pakfire_repo_add_solvable(repo);
98 if (!id)
32136e0c 99 goto ERROR;
e9d9eadc 100
32136e0c
MT
101 // Create a new package object
102 pkg = pakfire_package_create_from_solvable(pakfire, id);
e9d9eadc 103 if (!pkg)
32136e0c 104 goto ERROR;
221cc3ce 105
e9d9eadc
MT
106 pkg->repo = pakfire_repo_ref(repo);
107
108 // Set the given attributes
221cc3ce
MT
109 pakfire_package_set_name(pkg, name);
110 pakfire_package_set_evr(pkg, evr);
111 pakfire_package_set_arch(pkg, arch);
112
32136e0c
MT
113ERROR:
114 if (dummy)
115 pakfire_repo_unref(dummy);
116
221cc3ce
MT
117 return pkg;
118}
119
31480bee 120static void pakfire_package_free(struct pakfire_package* pkg) {
e9d9eadc
MT
121 if (pkg->repo)
122 pakfire_repo_unref(pkg->repo);
123
5e9463ec 124 pakfire_unref(pkg->pakfire);
f0d6233d 125 free(pkg);
221cc3ce
MT
126}
127
31480bee 128PAKFIRE_EXPORT struct pakfire_package* pakfire_package_ref(struct pakfire_package* pkg) {
a4e3894f
MT
129 pkg->nrefs++;
130
131 return pkg;
132}
133
31480bee 134PAKFIRE_EXPORT struct pakfire_package* pakfire_package_unref(struct pakfire_package* pkg) {
a4e3894f
MT
135 if (--pkg->nrefs > 0)
136 return pkg;
137
138 pakfire_package_free(pkg);
139 return NULL;
140}
141
ac4c607b 142PAKFIRE_EXPORT struct pakfire* pakfire_package_get_pakfire(struct pakfire_package* pkg) {
178a4506
MT
143 return pakfire_ref(pkg->pakfire);
144}
145
31480bee 146static Solvable* get_solvable(struct pakfire_package* pkg) {
0defa23e 147 Pool* pool = pakfire_get_solv_pool(pkg->pakfire);
221cc3ce 148
f1c7996e 149 return pool_id2solvable(pool, pkg->id);
221cc3ce
MT
150}
151
31480bee 152PAKFIRE_EXPORT int pakfire_package_eq(struct pakfire_package* pkg1, struct pakfire_package* pkg2) {
221cc3ce
MT
153 return pkg1->id == pkg2->id;
154}
155
31480bee 156PAKFIRE_EXPORT int pakfire_package_cmp(struct pakfire_package* pkg1, struct pakfire_package* pkg2) {
0defa23e 157 Pool* pool = pakfire_get_solv_pool(pkg1->pakfire);
221cc3ce
MT
158
159 Solvable* s1 = get_solvable(pkg1);
160 Solvable* s2 = get_solvable(pkg2);
161
162 // Check names
163 const char* str1 = pool_id2str(pool, s1->name);
164 const char* str2 = pool_id2str(pool, s2->name);
165
166 int ret = strcmp(str1, str2);
167 if (ret)
168 return ret;
169
170 // Check the version string
171 ret = pakfire_package_evr_cmp(pkg1, pkg2);
172 if (ret)
173 return ret;
174
175 // Check repositories
4651122b
MT
176 struct pakfire_repo* repo1 = pakfire_package_get_repo(pkg1);
177 struct pakfire_repo* repo2 = pakfire_package_get_repo(pkg2);
221cc3ce
MT
178
179 if (repo1 && repo2) {
180 ret = pakfire_repo_cmp(repo1, repo2);
3ff6aee6 181 }
221cc3ce 182
3ff6aee6
MT
183 pakfire_repo_unref(repo1);
184 pakfire_repo_unref(repo2);
221cc3ce 185
3ff6aee6
MT
186 if (ret)
187 return ret;
221cc3ce
MT
188
189 // Check package architectures
190 str1 = pool_id2str(pool, s1->arch);
191 str2 = pool_id2str(pool, s2->arch);
192
193 return strcmp(str1, str2);
194}
195
31480bee 196PAKFIRE_EXPORT int pakfire_package_evr_cmp(struct pakfire_package* pkg1, struct pakfire_package* pkg2) {
0defa23e 197 Pool* pool = pakfire_get_solv_pool(pkg1->pakfire);
221cc3ce
MT
198
199 Solvable* s1 = get_solvable(pkg1);
200 Solvable* s2 = get_solvable(pkg2);
201
202 return pool_evrcmp(pool, s1->evr, s2->evr, EVRCMP_COMPARE);
203}
204
31480bee 205Id pakfire_package_id(struct pakfire_package* pkg) {
221cc3ce
MT
206 return pkg->id;
207}
208
31480bee 209PAKFIRE_EXPORT const char* pakfire_package_get_nevra(struct pakfire_package* pkg) {
40fcf5ff
MT
210 if (!*pkg->nevra) {
211 Pool* pool = pakfire_get_solv_pool(pkg->pakfire);
212 Solvable* s = get_solvable(pkg);
221cc3ce 213
40fcf5ff
MT
214 pakfire_string_set(pkg->nevra, pool_solvable2str(pool, s));
215 }
221cc3ce 216
40fcf5ff 217 return pkg->nevra;
221cc3ce
MT
218}
219
31480bee 220PAKFIRE_EXPORT const char* pakfire_package_get_name(struct pakfire_package* pkg) {
0defa23e 221 Pool* pool = pakfire_get_solv_pool(pkg->pakfire);
221cc3ce
MT
222 Solvable* s = get_solvable(pkg);
223
224 return pool_id2str(pool, s->name);
225}
226
31480bee 227PAKFIRE_EXPORT void pakfire_package_set_name(struct pakfire_package* pkg, const char* name) {
0defa23e 228 Pool* pool = pakfire_get_solv_pool(pkg->pakfire);
221cc3ce
MT
229 Solvable* s = get_solvable(pkg);
230
231 s->name = pool_str2id(pool, name, 1);
232}
233
31480bee 234PAKFIRE_EXPORT const char* pakfire_package_get_evr(struct pakfire_package* pkg) {
0defa23e 235 Pool* pool = pakfire_get_solv_pool(pkg->pakfire);
221cc3ce
MT
236 Solvable* s = get_solvable(pkg);
237
238 return pool_id2str(pool, s->evr);
239}
240
31480bee 241PAKFIRE_EXPORT void pakfire_package_set_evr(struct pakfire_package* pkg, const char* evr) {
0defa23e 242 Pool* pool = pakfire_get_solv_pool(pkg->pakfire);
221cc3ce
MT
243 Solvable* s = get_solvable(pkg);
244
85b75c7b
MT
245 // Skip empty epoch
246 if (pakfire_string_startswith(evr, "0:"))
247 evr += 2;
248
221cc3ce
MT
249 s->evr = pool_str2id(pool, evr, 1);
250}
251
e42b5960
MT
252char* pakfire_package_join_evr(const char* e, const char* v, const char* r) {
253 char* buffer = NULL;
312fd26f 254
e42b5960
MT
255 // Check for valid input
256 if (!e || !v || !r) {
257 errno = EINVAL;
258 return NULL;
312fd26f
MT
259 }
260
e42b5960
MT
261 // Skip any zeroes in epoch
262 while (*e && *e == '0')
263 e++;
264
265 // Format string with epoch
266 if (*e) {
267 if (asprintf(&buffer, "%s:%s-%s", e, v, r) < 0)
268 return NULL;
269
270 // Or format it without epoch
271 } else {
272 if (asprintf(&buffer, "%s-%s", v, r) < 0)
273 return NULL;
274 }
312fd26f
MT
275
276 return buffer;
277}
278
31480bee 279PAKFIRE_EXPORT const char* pakfire_package_get_arch(struct pakfire_package* pkg) {
0defa23e 280 Pool* pool = pakfire_get_solv_pool(pkg->pakfire);
221cc3ce
MT
281 Solvable* s = get_solvable(pkg);
282
283 return pool_id2str(pool, s->arch);
284}
285
31480bee 286PAKFIRE_EXPORT void pakfire_package_set_arch(struct pakfire_package* pkg, const char* arch) {
0defa23e 287 Pool* pool = pakfire_get_solv_pool(pkg->pakfire);
221cc3ce
MT
288 Solvable* s = get_solvable(pkg);
289
290 s->arch = pool_str2id(pool, arch, 1);
291}
292
31480bee 293int pakfire_package_is_source(struct pakfire_package* pkg) {
af14aefb
MT
294 const char* arch = pakfire_package_get_arch(pkg);
295 if (!arch)
296 return 1;
297
298 return (strcmp(arch, "src") == 0);
299}
300
31480bee 301static void pakfire_package_internalize_repo(struct pakfire_package* pkg) {
4651122b 302 struct pakfire_repo* repo = pakfire_package_get_repo(pkg);
221cc3ce 303 if (repo) {
9eba3d65 304 pakfire_repo_internalize(repo, 0);
3ff6aee6 305 pakfire_repo_unref(repo);
221cc3ce
MT
306 }
307}
308
31480bee 309static unsigned long long pakfire_package_get_num(struct pakfire_package* pkg, Id type) {
ac71886a
MT
310 pakfire_package_internalize_repo(pkg);
311
312 Solvable* s = get_solvable(pkg);
313 return solvable_lookup_num(s, type, 0);
314}
315
31480bee 316static void pakfire_package_set_num(struct pakfire_package* pkg, Id type, unsigned long long value) {
ac71886a
MT
317 Solvable* s = get_solvable(pkg);
318
319 solvable_set_num(s, type, value);
320}
321
8e76ebe1 322static const char* pakfire_package_get_string(struct pakfire_package* pkg, Id key) {
221cc3ce
MT
323 pakfire_package_internalize_repo(pkg);
324
325 Solvable* s = get_solvable(pkg);
221cc3ce 326
8e76ebe1
MT
327 const char* str = solvable_lookup_str(s, key);
328 if (!str || !*str)
221cc3ce
MT
329 return NULL;
330
331 return str;
332}
333
31480bee 334static void pakfire_package_set_string(struct pakfire_package* pkg, int key, const char* value) {
221cc3ce
MT
335 Solvable* s = get_solvable(pkg);
336
51c47a9a
MT
337 // Unset on empty string
338 if (!value || !*value)
339 solvable_unset(s, key);
221cc3ce 340
51c47a9a
MT
341 // Store string
342 solvable_set_str(s, key, value);
7ccc9d74
MT
343}
344
31480bee 345static char** pakfire_package_get_string_array(struct pakfire_package* pkg, Id key) {
1eb7f40b
MT
346 char** strings = NULL;
347
348 Queue ids;
349 queue_init(&ids);
350
0defa23e 351 Pool* pool = pakfire_get_solv_pool(pkg->pakfire);
7ccc9d74 352 Solvable* s = get_solvable(pkg);
1eb7f40b
MT
353 solvable_lookup_idarray(s, key, &ids);
354
355 if (ids.count > 0) {
356 strings = calloc(ids.count + 1, sizeof(*strings));
357 if (!strings) {
358 queue_free(&ids);
359 return NULL;
360 }
361
362 for (int i = 0; i < ids.count; i++) {
363 const char* value = pool_id2str(pool, ids.elements[i]);
364 strings[i] = strdup(value);
365 }
7ccc9d74 366
1eb7f40b
MT
367 strings[ids.count] = NULL;
368 }
369
370 queue_free(&ids);
371
372 return strings;
373}
374
31480bee 375static void pakfire_package_add_string_array(struct pakfire_package* pkg, Id key, const char* value) {
7ccc9d74
MT
376 if (!value)
377 return;
378
1eb7f40b 379 Solvable* s = get_solvable(pkg);
7ccc9d74 380 solvable_add_poolstr_array(s, key, value);
221cc3ce
MT
381}
382
31480bee 383uint64_t pakfire_package_get_dbid(struct pakfire_package* pkg) {
ac71886a
MT
384 return pakfire_package_get_num(pkg, RPM_RPMDBID);
385}
386
31480bee 387void pakfire_package_set_dbid(struct pakfire_package* pkg, uint64_t id) {
ac71886a
MT
388 pakfire_package_set_num(pkg, RPM_RPMDBID, id);
389}
390
31480bee 391PAKFIRE_EXPORT const char* pakfire_package_get_uuid(struct pakfire_package* pkg) {
221cc3ce
MT
392 return pakfire_package_get_string(pkg, SOLVABLE_PKGID);
393}
394
31480bee 395PAKFIRE_EXPORT void pakfire_package_set_uuid(struct pakfire_package* pkg, const char* uuid) {
221cc3ce
MT
396 pakfire_package_set_string(pkg, SOLVABLE_PKGID, uuid);
397}
398
c52e0148 399static enum pakfire_digest_types pakfire_package_id2digest(Id id) {
e61716e4
MT
400 switch (id) {
401 case REPOKEY_TYPE_SHA512:
4500ed0a 402 return PAKFIRE_DIGEST_SHA2_512;
b28af23a 403
e61716e4 404 case REPOKEY_TYPE_SHA256:
4500ed0a 405 return PAKFIRE_DIGEST_SHA2_256;
b28af23a
MT
406 }
407
9802aaf6 408 return 0;
b28af23a
MT
409}
410
411PAKFIRE_EXPORT const unsigned char* pakfire_package_get_digest(
c52e0148 412 struct pakfire_package* pkg, enum pakfire_digest_types* type) {
b28af23a 413 Solvable* s = get_solvable(pkg);
e61716e4 414 Id id;
b28af23a 415
e61716e4 416 const unsigned char* checksum = solvable_lookup_bin_checksum(s, SOLVABLE_CHECKSUM, &id);
b28af23a 417
e61716e4
MT
418 // Convert ID to digest type
419 *type = pakfire_package_id2digest(id);
420 if (!*type) {
421 errno = ENOTSUP;
422 checksum = NULL;
423 }
424
425 return checksum;
b28af23a
MT
426}
427
428PAKFIRE_EXPORT const char* pakfire_package_get_hexdigest(
c52e0148 429 struct pakfire_package* pkg, enum pakfire_digest_types* type) {
b28af23a 430 Solvable* s = get_solvable(pkg);
e61716e4 431 Id id;
b28af23a 432
e61716e4 433 const char* checksum = solvable_lookup_checksum(s, SOLVABLE_CHECKSUM, &id);
b28af23a 434
e61716e4
MT
435 // Convert ID to digest type
436 *type = pakfire_package_id2digest(id);
437 if (!*type) {
438 errno = ENOTSUP;
439 checksum = NULL;
440 }
441
442 return checksum;
b28af23a
MT
443}
444
445PAKFIRE_EXPORT int pakfire_package_set_digest(struct pakfire_package* pkg,
c52e0148 446 enum pakfire_digest_types type, const unsigned char* digest) {
b28af23a
MT
447 Solvable* s = get_solvable(pkg);
448 Pool* pool = s->repo->pool;
e61716e4 449 Id id;
b28af23a
MT
450 int r = 1;
451
e61716e4 452 switch (type) {
4500ed0a 453 case PAKFIRE_DIGEST_SHA2_256:
e61716e4
MT
454 id = REPOKEY_TYPE_SHA256;
455 break;
456
4500ed0a 457 case PAKFIRE_DIGEST_SHA2_512:
e61716e4
MT
458 id = REPOKEY_TYPE_SHA512;
459 break;
460
461 default:
462 errno = ENOTSUP;
463 return 1;
464 }
b28af23a
MT
465
466 struct pakfire_repo* repo = pakfire_package_get_repo(pkg);
467
468 Repodata* data = pakfire_repo_get_repodata(repo);
469 if (!data)
470 goto ERROR;
471
472 repodata_set_bin_checksum(data, s - pool->solvables, SOLVABLE_CHECKSUM, id, digest);
473
474 // Success
475 r = 0;
476
477ERROR:
478 pakfire_repo_unref(repo);
479
480 return r;
481}
482
b28af23a 483PAKFIRE_EXPORT int pakfire_package_set_hexdigest(struct pakfire_package* pkg,
c52e0148 484 enum pakfire_digest_types type, const char* hexdigest) {
7cea394c 485 const size_t digest_length = pakfire_digest_length(type);
b28af23a
MT
486
487 if (!digest_length) {
488 errno = EINVAL;
489 return 1;
490 }
491
492 // Allocate a buffer for the binary representation of the digest
493 unsigned char* digest = alloca(digest_length);
494 if (!digest)
495 return 1;
496
497 // Convert from hex to binary
498 __pakfire_unhexlify(digest, digest_length, hexdigest);
499
500 return pakfire_package_set_digest(pkg, type, digest);
221cc3ce
MT
501}
502
31480bee 503PAKFIRE_EXPORT const char* pakfire_package_get_summary(struct pakfire_package* pkg) {
221cc3ce
MT
504 return pakfire_package_get_string(pkg, SOLVABLE_SUMMARY);
505}
506
31480bee 507PAKFIRE_EXPORT void pakfire_package_set_summary(struct pakfire_package* pkg, const char* summary) {
221cc3ce
MT
508 pakfire_package_set_string(pkg, SOLVABLE_SUMMARY, summary);
509}
510
31480bee 511PAKFIRE_EXPORT const char* pakfire_package_get_description(struct pakfire_package* pkg) {
221cc3ce
MT
512 return pakfire_package_get_string(pkg, SOLVABLE_DESCRIPTION);
513}
514
31480bee 515PAKFIRE_EXPORT void pakfire_package_set_description(struct pakfire_package* pkg, const char* description) {
221cc3ce
MT
516 pakfire_package_set_string(pkg, SOLVABLE_DESCRIPTION, description);
517}
518
31480bee 519PAKFIRE_EXPORT const char* pakfire_package_get_license(struct pakfire_package* pkg) {
221cc3ce
MT
520 return pakfire_package_get_string(pkg, SOLVABLE_LICENSE);
521}
522
31480bee 523PAKFIRE_EXPORT void pakfire_package_set_license(struct pakfire_package* pkg, const char* license) {
221cc3ce
MT
524 pakfire_package_set_string(pkg, SOLVABLE_LICENSE, license);
525}
526
31480bee 527PAKFIRE_EXPORT const char* pakfire_package_get_url(struct pakfire_package* pkg) {
221cc3ce
MT
528 return pakfire_package_get_string(pkg, SOLVABLE_URL);
529}
530
31480bee 531PAKFIRE_EXPORT void pakfire_package_set_url(struct pakfire_package* pkg, const char* url) {
221cc3ce
MT
532 pakfire_package_set_string(pkg, SOLVABLE_URL, url);
533}
534
31480bee 535PAKFIRE_EXPORT char* pakfire_package_get_groups(struct pakfire_package* pkg) {
1eb7f40b
MT
536 char** groups = pakfire_package_get_string_array(pkg, SOLVABLE_GROUP);
537 if (!groups)
538 return NULL;
539
540 char* string = pakfire_string_join(groups, " ");
541
542 // Free array
543 for (char** group = groups; *group; group++)
544 free(*group);
545 free(groups);
546
547 return string;
221cc3ce
MT
548}
549
31480bee 550PAKFIRE_EXPORT void pakfire_package_set_groups(struct pakfire_package* pkg, const char* groups) {
d973a13d 551 char** list = pakfire_string_split(groups, ' ');
1eb7f40b
MT
552 if (!list)
553 return;
221cc3ce 554
1eb7f40b
MT
555 for (char** group = list; *group; group++) {
556 pakfire_package_add_string_array(pkg, SOLVABLE_GROUP, *group);
557 free(*group);
2141b578 558 }
1eb7f40b
MT
559
560 free(list);
8ad0a954
MT
561}
562
31480bee 563PAKFIRE_EXPORT const char* pakfire_package_get_vendor(struct pakfire_package* pkg) {
221cc3ce
MT
564 return pakfire_package_get_string(pkg, SOLVABLE_VENDOR);
565}
566
31480bee 567PAKFIRE_EXPORT void pakfire_package_set_vendor(struct pakfire_package* pkg, const char* vendor) {
221cc3ce
MT
568 pakfire_package_set_string(pkg, SOLVABLE_VENDOR, vendor);
569}
570
ca002cae
MT
571PAKFIRE_EXPORT const char* pakfire_package_get_distribution(struct pakfire_package* pkg) {
572 return pakfire_package_get_string(pkg, SOLVABLE_DISTRIBUTION);
573}
574
575PAKFIRE_EXPORT void pakfire_package_set_distribution(struct pakfire_package* pkg, const char* distribution) {
576 pakfire_package_set_string(pkg, SOLVABLE_DISTRIBUTION, distribution);
577}
578
31480bee 579PAKFIRE_EXPORT const char* pakfire_package_get_maintainer(struct pakfire_package* pkg) {
221cc3ce
MT
580 return pakfire_package_get_string(pkg, SOLVABLE_PACKAGER);
581}
582
31480bee 583PAKFIRE_EXPORT void pakfire_package_set_maintainer(struct pakfire_package* pkg, const char* maintainer) {
221cc3ce
MT
584 pakfire_package_set_string(pkg, SOLVABLE_PACKAGER, maintainer);
585}
586
31480bee 587static int pakfire_package_make_cache_path(struct pakfire_package* pkg) {
b12a5d7d 588 const char* filename = pakfire_package_get_filename(pkg);
b12a5d7d 589
c52e0148 590 enum pakfire_digest_types digest;
e61716e4
MT
591 const char* hexdigest = pakfire_package_get_hexdigest(pkg, &digest);
592
126037d1 593 if (hexdigest && strlen(hexdigest) >= 3)
df1409ef 594 return pakfire_cache_path(pkg->pakfire, pkg->path,
126037d1 595 "%c%c/%s/%s", hexdigest[0], hexdigest[1], hexdigest + 2, filename);
b12a5d7d 596
df1409ef 597 return pakfire_cache_path(pkg->pakfire, pkg->path, "%s", filename);
b12a5d7d
MT
598}
599
31480bee 600PAKFIRE_EXPORT const char* pakfire_package_get_path(struct pakfire_package* pkg) {
b12a5d7d
MT
601 int r;
602
603 if (!*pkg->path) {
604 const char* base = pakfire_package_get_string(pkg, SOLVABLE_MEDIABASE);
605 if (base) {
606 const char* filename = pakfire_package_get_filename(pkg);
607 if (!filename)
608 return NULL;
609
610 pakfire_string_format(pkg->path, "%s/%s", base, filename);
611 } else {
612 r = pakfire_package_make_cache_path(pkg);
613 if (r)
614 return NULL;
615 }
616 }
617
618 return pkg->path;
619}
620
31480bee 621PAKFIRE_EXPORT void pakfire_package_set_path(struct pakfire_package* pkg, const char* path) {
bbbc9842
MT
622 const char* basename = pakfire_basename(path);
623 const char* dirname = pakfire_dirname(path);
b12a5d7d 624
bbbc9842 625 if (basename)
b12a5d7d 626 pakfire_package_set_string(pkg, SOLVABLE_MEDIAFILE, basename);
b12a5d7d 627
bbbc9842 628 if (dirname)
b12a5d7d 629 pakfire_package_set_string(pkg, SOLVABLE_MEDIABASE, dirname);
b12a5d7d
MT
630
631 pakfire_string_set(pkg->path, path);
632}
633
634// Removes epoch
635static const char* evr2vr(const char* evr) {
636 const char* p = evr;
637
638 // Skip any leading digits
639 for (; *p >= '0' && *p <= '9'; p++);
640
641 // If after the leading digits, we found :, we return the rest of the string
642 if (p != evr && *p == ':')
643 return ++p;
644
645 return evr;
646}
647
31480bee 648static const char* pakfire_package_make_filename(struct pakfire_package* pkg) {
b12a5d7d
MT
649 if (!*pkg->filename) {
650 const char* name = pakfire_package_get_name(pkg);
651 const char* evr = pakfire_package_get_evr(pkg);
652 const char* arch = pakfire_package_get_arch(pkg);
653
654 if (!name || !evr || !arch)
655 return NULL;
656
657 const char* vr = evr2vr(evr);
658
659 pakfire_string_format(pkg->filename, "%s-%s.%s.pfm", name, vr, arch);
660 }
661
662 return pkg->filename;
663}
664
31480bee 665PAKFIRE_EXPORT const char* pakfire_package_get_filename(struct pakfire_package* pkg) {
b12a5d7d
MT
666 const char* filename = pakfire_package_get_string(pkg, SOLVABLE_MEDIAFILE);
667
668 // Generate the filename if not set
669 if (!filename)
670 filename = pakfire_package_make_filename(pkg);
671
672 return filename;
221cc3ce
MT
673}
674
31480bee 675PAKFIRE_EXPORT void pakfire_package_set_filename(struct pakfire_package* pkg, const char* filename) {
221cc3ce
MT
676 pakfire_package_set_string(pkg, SOLVABLE_MEDIAFILE, filename);
677}
678
31480bee 679PAKFIRE_EXPORT int pakfire_package_is_installed(struct pakfire_package* pkg) {
0defa23e 680 Pool* pool = pakfire_get_solv_pool(pkg->pakfire);
221cc3ce
MT
681 Solvable* s = get_solvable(pkg);
682
683 return pool->installed == s->repo;
684}
685
27116707 686PAKFIRE_EXPORT size_t pakfire_package_get_downloadsize(struct pakfire_package* pkg) {
221cc3ce
MT
687 return pakfire_package_get_num(pkg, SOLVABLE_DOWNLOADSIZE);
688}
689
27116707 690PAKFIRE_EXPORT void pakfire_package_set_downloadsize(struct pakfire_package* pkg, size_t downloadsize) {
47b7aebd 691 pakfire_package_set_num(pkg, SOLVABLE_DOWNLOADSIZE, downloadsize);
221cc3ce
MT
692}
693
27116707 694PAKFIRE_EXPORT size_t pakfire_package_get_installsize(struct pakfire_package* pkg) {
221cc3ce
MT
695 return pakfire_package_get_num(pkg, SOLVABLE_INSTALLSIZE);
696}
697
27116707 698PAKFIRE_EXPORT void pakfire_package_set_installsize(struct pakfire_package* pkg, size_t installsize) {
47b7aebd 699 pakfire_package_set_num(pkg, SOLVABLE_INSTALLSIZE, installsize);
221cc3ce
MT
700}
701
27116707 702PAKFIRE_EXPORT size_t pakfire_package_get_size(struct pakfire_package* pkg) {
221cc3ce
MT
703 if (pakfire_package_is_installed(pkg))
704 return pakfire_package_get_installsize(pkg);
705
706 return pakfire_package_get_downloadsize(pkg);
707}
708
31480bee 709PAKFIRE_EXPORT const char* pakfire_package_get_build_host(struct pakfire_package* pkg) {
221cc3ce
MT
710 return pakfire_package_get_string(pkg, SOLVABLE_BUILDHOST);
711}
712
31480bee 713PAKFIRE_EXPORT void pakfire_package_set_build_host(struct pakfire_package* pkg, const char* build_host) {
2ffc704d 714 pakfire_package_set_string(pkg, SOLVABLE_BUILDHOST, build_host);
221cc3ce
MT
715}
716
31480bee 717PAKFIRE_EXPORT const char* pakfire_package_get_build_id(struct pakfire_package* pkg) {
7996020a
MT
718 return pakfire_package_get_string(pkg, SOLVABLE_BUILDVERSION);
719}
720
31480bee 721PAKFIRE_EXPORT void pakfire_package_set_build_id(struct pakfire_package* pkg, const char* build_id) {
7996020a
MT
722 pakfire_package_set_string(pkg, SOLVABLE_BUILDVERSION, build_id);
723}
724
57e2cf99
MT
725void pakfire_package_set_build_id_from_uuid(struct pakfire_package* pkg, uuid_t* build_id) {
726 char buffer[UUID_STR_LEN];
727
728 // Convert the UUID to string
729 uuid_unparse_lower(*build_id, buffer);
730
731 pakfire_package_set_build_id(pkg, buffer);
732}
733
31480bee 734PAKFIRE_EXPORT time_t pakfire_package_get_build_time(struct pakfire_package* pkg) {
221cc3ce
MT
735 return pakfire_package_get_num(pkg, SOLVABLE_BUILDTIME);
736}
737
31480bee 738PAKFIRE_EXPORT void pakfire_package_set_build_time(struct pakfire_package* pkg, time_t build_time) {
2ffc704d 739 pakfire_package_set_num(pkg, SOLVABLE_BUILDTIME, build_time);
221cc3ce
MT
740}
741
31480bee 742PAKFIRE_EXPORT time_t pakfire_package_get_install_time(struct pakfire_package* pkg) {
221cc3ce
MT
743 return pakfire_package_get_num(pkg, SOLVABLE_INSTALLTIME);
744}
745
31480bee 746PAKFIRE_EXPORT void pakfire_package_set_install_time(struct pakfire_package* pkg, time_t install_time) {
af647c55
MT
747 pakfire_package_set_num(pkg, SOLVABLE_INSTALLTIME, install_time);
748}
749
571539a7
MT
750PAKFIRE_EXPORT const char* pakfire_package_get_source_package(struct pakfire_package* pkg) {
751 if (!*pkg->source_nevra) {
752 const char* name = pakfire_package_get_source_name(pkg);
753 const char* evr = pakfire_package_get_source_evr(pkg);
754 const char* arch = pakfire_package_get_source_arch(pkg);
755
756 // Return nothing if we don't have all information
757 if (!name || !evr || !arch)
758 return NULL;
759
760 // Format package name
761 pakfire_string_format(pkg->source_nevra, "%s-%s.%s", name, evr, arch);
762 }
763
764 return pkg->source_nevra;
765}
766
767PAKFIRE_EXPORT const char* pakfire_package_get_source_name(struct pakfire_package* pkg) {
768 return pakfire_package_get_string(pkg, SOLVABLE_SOURCENAME);
769}
770
771PAKFIRE_EXPORT void pakfire_package_set_source_name(struct pakfire_package* pkg, const char* name) {
772 pakfire_package_set_string(pkg, SOLVABLE_SOURCENAME, name);
773}
774
775PAKFIRE_EXPORT const char* pakfire_package_get_source_evr(struct pakfire_package* pkg) {
776 return pakfire_package_get_string(pkg, SOLVABLE_SOURCEEVR);
777}
778
779PAKFIRE_EXPORT void pakfire_package_set_source_evr(struct pakfire_package* pkg, const char* evr) {
780 // Skip empty epoch
781 if (pakfire_string_startswith(evr, "0:"))
782 evr += 2;
783
784 pakfire_package_set_string(pkg, SOLVABLE_SOURCEEVR, evr);
785}
786
787PAKFIRE_EXPORT const char* pakfire_package_get_source_arch(struct pakfire_package* pkg) {
788 return pakfire_package_get_string(pkg, SOLVABLE_SOURCEARCH);
789}
790
791PAKFIRE_EXPORT void pakfire_package_set_source_arch(struct pakfire_package* pkg, const char* arch) {
792 pakfire_package_set_string(pkg, SOLVABLE_SOURCEARCH, arch);
793}
794
452d3833 795static char** pakfire_package_get_relationlist(
31480bee 796 struct pakfire_package* pkg, Id type, Id marker) {
452d3833
MT
797 char** array = NULL;
798
221cc3ce
MT
799 Queue q;
800 queue_init(&q);
801
802 Solvable* s = get_solvable(pkg);
452d3833
MT
803
804 // Fetch all deps
a9659851 805 solvable_lookup_deparray(s, type, &q, marker);
221cc3ce 806
452d3833
MT
807 // Nothing to do if the array was empty
808 if (!q.count)
809 goto ERROR;
d6ea32df 810
452d3833
MT
811 // Allocate array
812 array = calloc(q.count + 1, sizeof(*array));
813 if (!array)
814 goto ERROR;
815
816 for (int i = 0; i < q.count; i++) {
b1171f6a 817 const char* dep = pakfire_dep2str(pkg->pakfire, q.elements[i]);
d6ea32df 818
452d3833
MT
819 array[i] = strdup(dep);
820 }
821
822ERROR:
823 queue_free(&q);
824
825 return array;
221cc3ce
MT
826}
827
31480bee 828static void pakfire_package_add_dep(struct pakfire_package* pkg, Id type,
452d3833 829 const char* dep, Id marker) {
221cc3ce
MT
830 Solvable* s = get_solvable(pkg);
831
452d3833 832 // Parse the dependency
4abdf39d 833 Id id = pakfire_str2dep(pkg->pakfire, dep);
452d3833
MT
834 if (!id)
835 return;
836
837 solvable_add_deparray(s, type, id, marker);
221cc3ce
MT
838}
839
31480bee 840PAKFIRE_EXPORT char** pakfire_package_get_provides(struct pakfire_package* pkg) {
063ca10f 841 return pakfire_package_get_relationlist(pkg, SOLVABLE_PROVIDES, -SOLVABLE_FILEMARKER);
221cc3ce
MT
842}
843
31480bee 844void pakfire_package_add_provides(struct pakfire_package* pkg, const char* dep) {
452d3833 845 pakfire_package_add_dep(pkg, SOLVABLE_PROVIDES, dep, -SOLVABLE_FILEMARKER);
221cc3ce
MT
846}
847
31480bee 848PAKFIRE_EXPORT char** pakfire_package_get_prerequires(struct pakfire_package* pkg) {
063ca10f 849 return pakfire_package_get_relationlist(pkg, SOLVABLE_REQUIRES, SOLVABLE_PREREQMARKER);
221cc3ce
MT
850}
851
31480bee 852void pakfire_package_add_prerequires(struct pakfire_package* pkg, const char* dep) {
452d3833
MT
853 pakfire_package_add_dep(pkg, SOLVABLE_REQUIRES, dep, SOLVABLE_PREREQMARKER);
854}
855
31480bee 856PAKFIRE_EXPORT char** pakfire_package_get_requires(struct pakfire_package* pkg) {
063ca10f 857 return pakfire_package_get_relationlist(pkg, SOLVABLE_REQUIRES, -SOLVABLE_PREREQMARKER);
221cc3ce
MT
858}
859
31480bee 860void pakfire_package_add_requires(struct pakfire_package* pkg, const char* dep) {
452d3833 861 pakfire_package_add_dep(pkg, SOLVABLE_REQUIRES, dep, -SOLVABLE_PREREQMARKER);
221cc3ce
MT
862}
863
31480bee 864PAKFIRE_EXPORT char** pakfire_package_get_conflicts(struct pakfire_package* pkg) {
a9659851 865 return pakfire_package_get_relationlist(pkg, SOLVABLE_CONFLICTS, 0);
221cc3ce
MT
866}
867
31480bee 868void pakfire_package_add_conflicts(struct pakfire_package* pkg, const char* dep) {
452d3833 869 pakfire_package_add_dep(pkg, SOLVABLE_CONFLICTS, dep, 0);
221cc3ce
MT
870}
871
31480bee 872PAKFIRE_EXPORT char** pakfire_package_get_obsoletes(struct pakfire_package* pkg) {
a9659851 873 return pakfire_package_get_relationlist(pkg, SOLVABLE_OBSOLETES, 0);
221cc3ce
MT
874}
875
31480bee 876void pakfire_package_add_obsoletes(struct pakfire_package* pkg, const char* dep) {
452d3833 877 pakfire_package_add_dep(pkg, SOLVABLE_OBSOLETES, dep, 0);
221cc3ce
MT
878}
879
31480bee 880PAKFIRE_EXPORT char** pakfire_package_get_recommends(struct pakfire_package* pkg) {
a9659851 881 return pakfire_package_get_relationlist(pkg, SOLVABLE_RECOMMENDS, 0);
221cc3ce
MT
882}
883
31480bee 884void pakfire_package_add_recommends(struct pakfire_package* pkg, const char* dep) {
452d3833 885 pakfire_package_add_dep(pkg, SOLVABLE_RECOMMENDS, dep, 0);
221cc3ce
MT
886}
887
31480bee 888PAKFIRE_EXPORT char** pakfire_package_get_suggests(struct pakfire_package* pkg) {
a9659851 889 return pakfire_package_get_relationlist(pkg, SOLVABLE_SUGGESTS, 0);
221cc3ce
MT
890}
891
31480bee 892void pakfire_package_add_suggests(struct pakfire_package* pkg, const char* dep) {
452d3833 893 pakfire_package_add_dep(pkg, SOLVABLE_SUGGESTS, dep, 0);
221cc3ce
MT
894}
895
31480bee 896PAKFIRE_EXPORT char** pakfire_package_get_supplements(struct pakfire_package* pkg) {
8fe2e4ba
MT
897 return pakfire_package_get_relationlist(pkg, SOLVABLE_SUPPLEMENTS, 0);
898}
899
31480bee 900void pakfire_package_add_supplements(struct pakfire_package* pkg, const char* dep) {
452d3833
MT
901 pakfire_package_add_dep(pkg, SOLVABLE_SUPPLEMENTS, dep, 0);
902}
903
31480bee 904PAKFIRE_EXPORT char** pakfire_package_get_enhances(struct pakfire_package* pkg) {
8fe2e4ba
MT
905 return pakfire_package_get_relationlist(pkg, SOLVABLE_ENHANCES, 0);
906}
907
31480bee 908void pakfire_package_add_enhances(struct pakfire_package* pkg, const char* dep) {
452d3833
MT
909 pakfire_package_add_dep(pkg, SOLVABLE_ENHANCES, dep, 0);
910}
911
31480bee 912PAKFIRE_EXPORT int pakfire_package_get_reverse_requires(struct pakfire_package* pkg,
e1d77c57
MT
913 struct pakfire_packagelist** list) {
914 Queue matches;
915 queue_init(&matches);
916
917 // Reset pointer
918 *list = NULL;
919
920 Pool* pool = pakfire_get_solv_pool(pkg->pakfire);
921
922 // Search for any matches
923 pool_whatmatchessolvable(pool, SOLVABLE_REQUIRES, pkg->id, &matches, 0);
924
925 // Create a new package list
926 int r = pakfire_packagelist_create_from_queue(list, pkg->pakfire, &matches);
927 if (r)
928 goto ERROR;
929
930ERROR:
931 queue_free(&matches);
932
933 return r;
934}
935
555b6dd2
MT
936static int pakfire_package_has_rich_deps_in_deparray(
937 struct pakfire_package* pkg, Id type) {
938 int r = 0;
939
940 Solvable* s = get_solvable(pkg);
941
942 Queue q;
943 queue_init(&q);
944
945 // Fetch all deps
946 solvable_lookup_deparray(s, type, &q, 0);
947
948 // Nothing to do if the array was empty
949 if (!q.count)
950 goto ERROR;
951
952 for (int i = 0; i < q.count; i++) {
953 const char* dep = pakfire_dep2str(pkg->pakfire, q.elements[i]);
954
955 // Is this a rich dependency?
956 if (dep && *dep == '(') {
957 r = 1;
958 break;
959 }
960 }
961
962ERROR:
963 queue_free(&q);
964
965 return r;
966}
967
968int pakfire_package_has_rich_deps(struct pakfire_package* pkg) {
969 static const Id types[] = {
970 // Requires (includes pre-requires)
971 SOLVABLE_REQUIRES,
972 SOLVABLE_PROVIDES,
973 SOLVABLE_CONFLICTS,
974 SOLVABLE_OBSOLETES,
975 SOLVABLE_RECOMMENDS,
976 SOLVABLE_SUGGESTS,
977 SOLVABLE_SUPPLEMENTS,
978 SOLVABLE_ENHANCES,
979 0,
980 };
981
982 for (const Id* type = types; *type; type++) {
983 int r = pakfire_package_has_rich_deps_in_deparray(pkg, *type);
984 if (r)
985 return r;
986 }
987
988 // No match
989 return 0;
990}
991
4651122b 992PAKFIRE_EXPORT struct pakfire_repo* pakfire_package_get_repo(struct pakfire_package* pkg) {
e9d9eadc
MT
993 if (!pkg->repo) {
994 Solvable* s = get_solvable(pkg);
995
996 pkg->repo = pakfire_repo_create_from_repo(pkg->pakfire, s->repo);
997 }
221cc3ce 998
e9d9eadc 999 return pakfire_repo_ref(pkg->repo);
221cc3ce
MT
1000}
1001
221cc3ce
MT
1002static void pakfire_package_dump_add_line(char** str, const char* key, const char* val) {
1003 if (val)
1004 asprintf(str, "%s%-15s: %s\n", *str, key ? key : "", val);
1005}
1006
1007static void pakfire_package_dump_add_lines(char** str, const char* key, const char* val) {
d973a13d 1008 char** lines = pakfire_string_split(val, '\n');
7500066c
MT
1009 if (!lines)
1010 return;
221cc3ce 1011
7500066c
MT
1012 while (*lines) {
1013 pakfire_package_dump_add_line(str, key, *lines);
1014 lines++;
221cc3ce
MT
1015 }
1016}
1017
5cf4a7a1
MT
1018static void pakfire_package_dump_add_line_date(char** str, const char* key, time_t date) {
1019 char buffer[1024];
1020 int r;
221cc3ce 1021
5cf4a7a1
MT
1022 // Format time
1023 r = pakfire_strftime(buffer, "%a, %d %b %Y %T %z", date);
1024 if (r)
1025 return;
221cc3ce 1026
5cf4a7a1 1027 pakfire_package_dump_add_line(str, key, buffer);
221cc3ce
MT
1028}
1029
27116707 1030static void pakfire_package_dump_add_line_size(char** str, const char* key, size_t size) {
cc90545a 1031 char buffer[128];
9b0e3d52
MT
1032
1033 // Format size in human-readable format
1034 int r = pakfire_format_size(buffer, size);
1035 if (r < 0)
1036 return;
221cc3ce 1037
cc90545a 1038 pakfire_package_dump_add_line(str, key, buffer);
221cc3ce
MT
1039}
1040
7db0d073
MT
1041static int pakfire_sort_dependencies(const void* p1, const void* p2) {
1042 const char* dep1 = *(const char**)p1;
1043 const char* dep2 = *(const char**)p2;
1044
1045 return strcmp(dep1, dep2);
1046}
1047
31480bee 1048PAKFIRE_EXPORT char* pakfire_package_dump(struct pakfire_package* pkg, int flags) {
221cc3ce
MT
1049 char* string = "";
1050
1051 // Name
1052 const char* name = pakfire_package_get_name(pkg);
1053 pakfire_package_dump_add_line(&string, _("Name"), name);
1054
6ed66687
MT
1055 // EVR
1056 const char* evr = pakfire_package_get_evr(pkg);
1057 pakfire_package_dump_add_line(&string, _("Version"), evr);
221cc3ce 1058
6ed66687
MT
1059 // Arch
1060 const char* arch = pakfire_package_get_arch(pkg);
1061 pakfire_package_dump_add_line(&string, _("Arch"), arch);
221cc3ce
MT
1062
1063 // Size
27116707 1064 size_t size = pakfire_package_get_size(pkg);
c2737936
MT
1065 if (size)
1066 pakfire_package_dump_add_line_size(&string, _("Size"), size);
221cc3ce 1067
d0f0d507 1068 // Installed Size
221cc3ce 1069 if (pakfire_package_is_installed(pkg)) {
27116707 1070 size_t installsize = pakfire_package_get_installsize(pkg);
d0f0d507
MT
1071 if (installsize)
1072 pakfire_package_dump_add_line_size(&string, _("Installed Size"), installsize);
221cc3ce 1073
d0f0d507 1074 // Download Size
221cc3ce 1075 } else {
27116707 1076 size_t downloadsize = pakfire_package_get_downloadsize(pkg);
d0f0d507
MT
1077 if (downloadsize)
1078 pakfire_package_dump_add_line_size(&string, _("Download Size"), downloadsize);
221cc3ce
MT
1079 }
1080
d0f0d507 1081 // Repository
4651122b 1082 struct pakfire_repo* repo = pakfire_package_get_repo(pkg);
221cc3ce 1083 if (repo) {
866aa605 1084 if (!pakfire_repo_name_equals(repo, PAKFIRE_REPO_DUMMY)) {
a4292569
MT
1085 const char* repo_name = pakfire_repo_get_name(repo);
1086 pakfire_package_dump_add_line(&string, _("Repo"), repo_name);
1087 }
221cc3ce 1088
3ff6aee6 1089 pakfire_repo_unref(repo);
221cc3ce
MT
1090 }
1091
1092 // Summary
1093 const char* summary = pakfire_package_get_summary(pkg);
1094 pakfire_package_dump_add_line(&string, _("Summary"), summary);
1095
1096 // Description
1097 const char* description = pakfire_package_get_description(pkg);
1b99c676
MT
1098 if (description)
1099 pakfire_package_dump_add_lines(&string, _("Description"), description);
221cc3ce
MT
1100
1101 // Groups
7ccc9d74 1102 const char* groups = pakfire_package_get_groups(pkg);
2141b578 1103 if (groups) {
7ccc9d74 1104 pakfire_package_dump_add_lines(&string, _("Groups"), groups);
2141b578 1105 }
221cc3ce
MT
1106
1107 // URL
1108 const char* url = pakfire_package_get_url(pkg);
1109 pakfire_package_dump_add_line(&string, _("URL"), url);
1110
1111 // License
1112 const char* license = pakfire_package_get_license(pkg);
1113 pakfire_package_dump_add_line(&string, _("License"), license);
1114
1115 if (flags & PAKFIRE_PKG_DUMP_LONG) {
af647c55
MT
1116 // Install Time
1117 time_t install_time = pakfire_package_get_install_time(pkg);
1118 if (install_time) {
1119 pakfire_package_dump_add_line_date(&string, _("Install Time"), install_time);
1120 }
1121
221cc3ce
MT
1122 // Maintainer
1123 const char* maintainer = pakfire_package_get_maintainer(pkg);
1124 pakfire_package_dump_add_line(&string, _("Maintainer"), maintainer);
1125
1126 // Vendor
1127 const char* vendor = pakfire_package_get_vendor(pkg);
1128 pakfire_package_dump_add_line(&string, _("Vendor"), vendor);
1129
1130 // UUID
1131 const char* uuid = pakfire_package_get_uuid(pkg);
1132 pakfire_package_dump_add_line(&string, _("UUID"), uuid);
1133
7996020a
MT
1134 // Build ID
1135 const char* build_id = pakfire_package_get_build_id(pkg);
1136 if (build_id)
1137 pakfire_package_dump_add_line(&string, _("Build ID"), build_id);
1138
c52e0148 1139 enum pakfire_digest_types digest = 0;
e61716e4
MT
1140
1141 // Digest
1142 const char* hexdigest = pakfire_package_get_hexdigest(pkg, &digest);
1143 switch (digest) {
4500ed0a 1144 case PAKFIRE_DIGEST_SHA2_512:
e61716e4
MT
1145 pakfire_package_dump_add_line(&string, _("SHA512 Digest"), hexdigest);
1146 break;
b28af23a 1147
4500ed0a 1148 case PAKFIRE_DIGEST_SHA2_256:
e61716e4 1149 pakfire_package_dump_add_line(&string, _("SHA256 Digest"), hexdigest);
5e8dfbeb 1150 break;
2c4b4a02 1151
d98740de
MT
1152 case PAKFIRE_DIGEST_SHA3_512:
1153 case PAKFIRE_DIGEST_SHA3_256:
f1e6c5df
MT
1154 case PAKFIRE_DIGEST_BLAKE2B512:
1155 case PAKFIRE_DIGEST_BLAKE2S256:
2c4b4a02
MT
1156 case PAKFIRE_DIGEST_UNDEFINED:
1157 break;
e61716e4 1158 }
b28af23a 1159
571539a7
MT
1160 // Source package
1161 const char* source_package = pakfire_package_get_source_package(pkg);
1162 if (source_package)
1163 pakfire_package_dump_add_line(&string, _("Source Package"), source_package);
1164
221cc3ce 1165 // Build time
2ffc704d
MT
1166 time_t build_time = pakfire_package_get_build_time(pkg);
1167 pakfire_package_dump_add_line_date(&string, _("Build Time"), build_time);
221cc3ce
MT
1168
1169 // Build host
2ffc704d
MT
1170 const char* build_host = pakfire_package_get_build_host(pkg);
1171 pakfire_package_dump_add_line(&string, _("Build Host"), build_host);
221cc3ce 1172
2f873877
MT
1173 // Dependencies
1174
1175 const struct relation {
1176 const char* name;
31480bee 1177 char** (*get)(struct pakfire_package* pkg);
2f873877
MT
1178 } relations[] = {
1179 { _("Provides"), pakfire_package_get_provides, },
1180 { _("Pre-Requires"), pakfire_package_get_prerequires, },
1181 { _("Requires"), pakfire_package_get_requires, },
1182 { _("Conflicts"), pakfire_package_get_conflicts, },
1183 { _("Obsoletes"), pakfire_package_get_obsoletes, },
1184 { _("Recommends"), pakfire_package_get_recommends, },
1185 { _("Suggests"), pakfire_package_get_suggests, },
8fe2e4ba
MT
1186 { _("Supplements"), pakfire_package_get_supplements, },
1187 { _("Enhances"), pakfire_package_get_enhances, },
2f873877
MT
1188 { NULL, NULL},
1189 };
1190
1191 for (const struct relation* relation = relations; relation->name; relation++) {
7db0d073
MT
1192 char** deps = relation->get(pkg);
1193 if (deps) {
23b93958 1194 name = relation->name;
7db0d073
MT
1195 size_t count = 0;
1196
1197 // Count elements in the list
1198 for (char** dep = deps; *dep; dep++)
1199 count++;
1200
1201 // Sort the list
1202 qsort(deps, count, sizeof(*deps), pakfire_sort_dependencies);
1203
1204 // Write it to the console
1205 for (char** dep = deps; *dep; dep++) {
e650b3ee 1206 pakfire_package_dump_add_line(&string, name, *dep);
452d3833 1207 free(*dep);
e650b3ee
MT
1208
1209 // Clear name after first line
1210 name = NULL;
452d3833 1211 }
7db0d073 1212 free(deps);
2f873877 1213 }
221cc3ce
MT
1214 }
1215 }
1216
1217 if (flags & PAKFIRE_PKG_DUMP_FILELIST) {
1bbbfb9e 1218 struct pakfire_filelist* filelist = pakfire_package_get_filelist(pkg);
5e9463ec
MT
1219
1220 const char* prefix = _("Filelist");
1221
1222 for (unsigned int i = 0; i < pakfire_filelist_size(filelist); i++) {
5803b5f6 1223 struct pakfire_file* file = pakfire_filelist_get(filelist, i);
221cc3ce 1224
32485f6c
MT
1225 const char* path = pakfire_file_get_path(file);
1226 pakfire_package_dump_add_line(&string, prefix, path);
221cc3ce 1227
5e9463ec 1228 pakfire_file_unref(file);
221cc3ce 1229
5e9463ec 1230 // Only prefix the first line
221cc3ce
MT
1231 prefix = NULL;
1232 }
5e9463ec
MT
1233
1234 pakfire_filelist_unref(filelist);
221cc3ce
MT
1235 }
1236
1237 return string;
1238}
1239
900faa2f 1240PAKFIRE_EXPORT struct pakfire_archive* pakfire_package_get_archive(struct pakfire_package* pkg) {
9686a82a 1241 struct pakfire_archive* archive = NULL;
b12a5d7d 1242
cbed1552 1243 // Otherwise open the archive from the cache
b12a5d7d 1244 const char* path = pakfire_package_get_path(pkg);
641cab18
MT
1245 if (!path)
1246 return NULL;
cbed1552 1247
641cab18 1248 // Open archive
cf3e773a 1249 int r = pakfire_archive_open(&archive, pkg->pakfire, path);
9686a82a
MT
1250 if (r)
1251 return NULL;
cbed1552 1252
9686a82a 1253 return archive;
cbed1552
MT
1254}
1255
1bbbfb9e 1256static int pakfire_package_fetch_legacy_filelist(struct pakfire_package* pkg, struct pakfire_filelist* filelist) {
221cc3ce
MT
1257 pakfire_package_internalize_repo(pkg);
1258
4651122b 1259 struct pakfire_repo* repo = pakfire_package_get_repo(pkg);
221cc3ce 1260 Solvable* s = get_solvable(pkg);
23b93958 1261 Repo* _repo = pakfire_repo_get_repo(repo);
5e9463ec 1262 pakfire_repo_unref(repo);
221cc3ce
MT
1263
1264 int found_marker = 0;
1265
1266 Id id, *ids;
23b93958 1267 ids = _repo->idarraydata + s->provides;
221cc3ce 1268 while((id = *ids++) != 0) {
b1171f6a 1269 const char* path = pakfire_dep2str(pkg->pakfire, id);
221cc3ce
MT
1270
1271 if (found_marker) {
5803b5f6 1272 struct pakfire_file* file;
221cc3ce 1273
883b3be9 1274 int r = pakfire_file_create(&file, pkg->pakfire);
5e9463ec
MT
1275 if (r)
1276 return r;
1277
32485f6c
MT
1278 // Set path
1279 pakfire_file_set_path(file, path);
5e9463ec 1280
f4560c3f 1281 r = pakfire_filelist_append(filelist, file);
5e9463ec
MT
1282 if (r)
1283 return r;
1284
1285 pakfire_file_unref(file);
221cc3ce
MT
1286 continue;
1287 }
1288
614a3dc8 1289 if (strcmp(path, "solvable:filemarker") == 0)
221cc3ce
MT
1290 ++found_marker;
1291 }
1292
5e9463ec 1293 return 0;
221cc3ce
MT
1294}
1295
1bbbfb9e 1296static int pakfire_package_fetch_filelist(struct pakfire_package* pkg, struct pakfire_filelist* filelist) {
5e9463ec
MT
1297 int r;
1298
221cc3ce
MT
1299 pakfire_package_internalize_repo(pkg);
1300
96c6c8f6 1301 Solvable* s = get_solvable(pkg);
221cc3ce
MT
1302
1303 Dataiterator di;
96c6c8f6 1304 dataiterator_init(&di, s->repo->pool, s->repo, pkg->id,
221cc3ce 1305 SOLVABLE_FILELIST, NULL, SEARCH_FILES | SEARCH_COMPLETE_FILELIST);
5e9463ec 1306
221cc3ce 1307 while (dataiterator_step(&di)) {
5803b5f6 1308 struct pakfire_file* file;
221cc3ce 1309
883b3be9 1310 r = pakfire_file_create(&file, pkg->pakfire);
5e9463ec
MT
1311 if (r)
1312 return r;
221cc3ce 1313
32485f6c 1314 pakfire_file_set_path(file, di.kv.str);
221cc3ce 1315
5e9463ec 1316 // Append to filelist
f4560c3f 1317 pakfire_filelist_append(filelist, file);
5e9463ec 1318 pakfire_file_unref(file);
221cc3ce 1319 }
5e9463ec 1320 dataiterator_free(&di);
221cc3ce
MT
1321
1322 // If the file list is empty, we fall back to read files
1323 // in the older format.
f4560c3f
MT
1324 if (pakfire_filelist_is_empty(filelist)) {
1325 r = pakfire_package_fetch_legacy_filelist(pkg, filelist);
5e9463ec
MT
1326 if (r)
1327 return r;
1328 }
1329
1330 // Sort the list
f4560c3f 1331 pakfire_filelist_sort(filelist);
221cc3ce 1332
5e9463ec 1333 return 0;
221cc3ce
MT
1334}
1335
1bbbfb9e 1336PAKFIRE_EXPORT struct pakfire_filelist* pakfire_package_get_filelist(struct pakfire_package* pkg) {
f78f6159 1337 struct pakfire_filelist* filelist = NULL;
5e9463ec 1338
f78f6159 1339 // Create a new filelist
883b3be9 1340 int r = pakfire_filelist_create(&filelist, pkg->pakfire);
f4560c3f 1341 if (r)
f78f6159 1342 goto ERROR;
5e9463ec 1343
f78f6159 1344 // Fetch all entries from the repository database
f4560c3f 1345 r = pakfire_package_fetch_filelist(pkg, filelist);
f78f6159
MT
1346 if (r)
1347 goto ERROR;
221cc3ce 1348
f4560c3f 1349 return filelist;
f78f6159
MT
1350
1351ERROR:
1352 if (filelist)
1353 pakfire_filelist_unref(filelist);
1354
1355 return NULL;
221cc3ce
MT
1356}
1357
31480bee 1358static int pakfire_package_append_file(struct pakfire_package* pkg, const char* path) {
5e9463ec 1359 // Fetch repodata
4651122b 1360 struct pakfire_repo* repo = pakfire_package_get_repo(pkg);
3ff6aee6 1361 Repodata* repodata = pakfire_repo_get_repodata(repo);
5e9463ec 1362 pakfire_repo_unref(repo);
221cc3ce 1363
bbbc9842
MT
1364 const char* basename = pakfire_basename(path);
1365 const char* dirname = pakfire_dirname(path);
d995f7fc
MT
1366
1367 // Convert directory into ID
1368 Id did = repodata_str2dir(repodata, dirname, 1);
1369 if (!did)
1370 did = repodata_str2dir(repodata, "/", 1);
1371
1372 // Add data to list
94db84fc 1373 repodata_add_dirstr(repodata, pkg->id,
d995f7fc
MT
1374 SOLVABLE_FILELIST, did, basename);
1375
d995f7fc
MT
1376 return 0;
1377}
1378
30ab941e
MT
1379static int __pakfire_package_set_filelist(struct pakfire* pakfire,
1380 struct pakfire_file* file, void* data) {
1381 struct pakfire_package* pkg = (struct pakfire_package*)data;
221cc3ce 1382
30ab941e
MT
1383 // Fetch the path
1384 const char* path = pakfire_file_get_path(file);
d995f7fc 1385
30ab941e
MT
1386 return pakfire_package_append_file(pkg, path);
1387}
d995f7fc 1388
30ab941e
MT
1389PAKFIRE_EXPORT int pakfire_package_set_filelist(
1390 struct pakfire_package* pkg, struct pakfire_filelist* filelist) {
1391 return pakfire_filelist_walk(filelist, __pakfire_package_set_filelist, pkg);
d995f7fc 1392}
221cc3ce 1393
31480bee 1394int pakfire_package_set_filelist_from_string(struct pakfire_package* pkg, const char* files) {
731f1d42
MT
1395 char* p = NULL;
1396 int r = 0;
d995f7fc 1397
731f1d42
MT
1398 // Copy files
1399 char* buffer = strdup(files);
1400 if (!buffer)
1401 goto ERROR;
d995f7fc 1402
731f1d42
MT
1403 // Walk through all files
1404 char* path = strtok_r(buffer, "\n", &p);
1405 while (path) {
1406 r = pakfire_package_append_file(pkg, path);
d995f7fc 1407 if (r)
731f1d42 1408 goto ERROR;
d995f7fc 1409
731f1d42 1410 path = strtok_r(NULL, "\n", &p);
5e9463ec 1411 }
221cc3ce 1412
731f1d42
MT
1413ERROR:
1414 if (buffer)
1415 free(buffer);
1416
1417 return r;
221cc3ce 1418}
b59c9fa2
MT
1419
1420static int _pakfire_package_add_json_dependencies(
1421 struct pakfire_package* pkg,
1422 struct json_object* json,
1423 const char* name,
1424 char** (*func)(struct pakfire_package* pkg)) {
1425 // Fetch dependencies
1426 char** dependencies = func(pkg);
1427
1428 // Nothing to do if there are no dependencies
1429 if (!dependencies)
1430 return 0;
1431
1432 // Add dependencies
1433 int r = pakfire_json_add_string_array(pkg->pakfire, json, name, dependencies);
1434 if (r)
1435 goto ERROR;
1436
1437ERROR:
1438 if (dependencies) {
1439 for (char** dep = dependencies; *dep; dep++)
1440 free(*dep);
1441 free(dependencies);
1442 }
1443
1444 return r;
1445}
1446
1447static int pakfire_package_add_json_dependencies(
1448 struct pakfire_package* pkg, struct json_object* md) {
1449 int r = 0;
1450
1451 // Create new dependencies object
1452 struct json_object* object = json_object_new_object();
1453 if (!object)
1454 return 1;
1455
1456 // Pre-requires
1457 r = _pakfire_package_add_json_dependencies(pkg, object,
1458 "prerequires", pakfire_package_get_prerequires);
1459 if (r)
1460 goto ERROR;
1461
1462 // Requires
1463 r = _pakfire_package_add_json_dependencies(pkg, object,
1464 "requires", pakfire_package_get_requires);
1465 if (r)
1466 goto ERROR;
1467
1468 // Provides
1469 r = _pakfire_package_add_json_dependencies(pkg, object,
1470 "provides", pakfire_package_get_provides);
1471 if (r)
1472 goto ERROR;
1473
1474 // Conflicts
1475 r = _pakfire_package_add_json_dependencies(pkg, object,
1476 "conflicts", pakfire_package_get_conflicts);
1477 if (r)
1478 goto ERROR;
1479
1480 // Obsoletes
1481 r = _pakfire_package_add_json_dependencies(pkg, object,
1482 "obsoletes", pakfire_package_get_obsoletes);
1483 if (r)
1484 goto ERROR;
1485
1486 // Recommends
1487 r = _pakfire_package_add_json_dependencies(pkg, object,
1488 "recommends", pakfire_package_get_recommends);
1489 if (r)
1490 goto ERROR;
1491
1492 // Suggests
1493 r = _pakfire_package_add_json_dependencies(pkg, object,
1494 "suggests", pakfire_package_get_suggests);
1495 if (r)
1496 goto ERROR;
1497
1498 // Supplements
1499 r = _pakfire_package_add_json_dependencies(pkg, object,
1500 "supplements", pakfire_package_get_supplements);
1501 if (r)
1502 goto ERROR;
1503
1504 // Enhances
1505 r = _pakfire_package_add_json_dependencies(pkg, object,
1506 "enhances", pakfire_package_get_enhances);
1507 if (r)
1508 goto ERROR;
1509
1510 // Add object
1511 r = json_object_object_add(md, "dependencies", object);
1512 if (r)
1513 goto ERROR;
1514
1515ERROR:
1516 if (r)
1517 json_object_put(object);
1518
1519 return r;
1520}
1521
1522static int pakfire_package_add_build_metadata(struct pakfire_package* pkg,
1523 struct json_object* md) {
1524 int r;
1525
1526 // Create a new JSON object
1527 struct json_object* object = json_object_new_object();
1528 if (!object)
1529 return 1;
1530
1531 // Add pakfire version that generated this metadata
1532 r = pakfire_json_add_string(pkg->pakfire, object, "pakfire", PACKAGE_VERSION);
1533 if (r)
1534 goto ERROR;
1535
1536 // Write build host
1537 const char* build_host = pakfire_package_get_build_host(pkg);
1538 if (build_host) {
1539 r = pakfire_json_add_string(pkg->pakfire, object, "host", build_host);
1540 if (r)
1541 goto ERROR;
1542 }
1543
1544 // Write build id
1545 const char* build_id = pakfire_package_get_build_id(pkg);
1546 if (build_id) {
1547 r = pakfire_json_add_string(pkg->pakfire, object, "id", build_id);
1548 if (r)
1549 goto ERROR;
1550 }
1551
1552 // Write build host
1553 time_t build_time = pakfire_package_get_build_time(pkg);
1554 if (build_time) {
1555 r = pakfire_json_add_integer(pkg->pakfire, object, "time", build_time);
1556 if (r)
1557 goto ERROR;
1558 }
1559
571539a7
MT
1560 // Source package name
1561 const char* name = pakfire_package_get_source_name(pkg);
1562 if (name) {
1563 r = pakfire_json_add_string(pkg->pakfire, object, "source-name", name);
1564 if (r)
1565 goto ERROR;
1566 }
1567
1568 // Source package EVR
1569 const char* evr = pakfire_package_get_source_evr(pkg);
1570 if (evr) {
1571 r = pakfire_json_add_string(pkg->pakfire, object, "source-evr", evr);
1572 if (r)
1573 goto ERROR;
1574 }
1575
1576 // Source package arch
1577 const char* arch = pakfire_package_get_source_arch(pkg);
1578 if (arch) {
1579 r = pakfire_json_add_string(pkg->pakfire, object, "source-arch", arch);
1580 if (r)
1581 goto ERROR;
1582 }
1583
b59c9fa2
MT
1584 // Add object
1585 r = json_object_object_add(md, "build", object);
1586 if (r)
1587 goto ERROR;
1588
1589ERROR:
1590 if (r)
1591 json_object_put(object);
1592
1593 return r;
1594}
1595
1596struct json_object* pakfire_package_to_json(struct pakfire_package* pkg) {
1597 struct json_object* md = json_object_new_object();
1598 int r = 0;
1599
1600 // Name
1601 const char* name = pakfire_package_get_name(pkg);
1602 if (name) {
1603 r = pakfire_json_add_string(pkg->pakfire, md, "name", name);
1604 if (r)
1605 goto ERROR;
1606 }
1607
1608 // EVR
1609 const char* evr = pakfire_package_get_evr(pkg);
1610 if (evr) {
1611 r = pakfire_json_add_string(pkg->pakfire, md, "evr", evr);
1612 if (r)
1613 goto ERROR;
1614 }
1615
1616 // Arch
1617 const char* arch = pakfire_package_get_arch(pkg);
1618 if (arch) {
1619 r = pakfire_json_add_string(pkg->pakfire, md, "arch", arch);
1620 if (r)
1621 goto ERROR;
1622 }
1623
d9475a74
MT
1624 // Vendor
1625 const char* vendor = pakfire_package_get_vendor(pkg);
1626 if (vendor) {
1627 r = pakfire_json_add_string(pkg->pakfire, md, "vendor", vendor);
1628 if (r)
1629 goto ERROR;
1630 }
1631
ca002cae
MT
1632 // Distribution
1633 const char* distribution = pakfire_package_get_distribution(pkg);
1634 if (distribution) {
1635 r = pakfire_json_add_string(pkg->pakfire, md, "distribution", distribution);
1636 if (r)
1637 goto ERROR;
1638 }
1639
b59c9fa2
MT
1640 // UUID
1641 const char* uuid = pakfire_package_get_uuid(pkg);
1642 if (uuid) {
1643 r = pakfire_json_add_string(pkg->pakfire, md, "uuid", uuid);
1644 if (r)
1645 goto ERROR;
1646 }
1647
1648 // Groups
1649 char* groups = pakfire_package_get_groups(pkg);
1650 if (groups) {
1651 r = pakfire_json_add_string(pkg->pakfire, md, "groups", groups);
1652 free(groups);
1653 if (r)
1654 goto ERROR;
1655 }
1656
1657 // Maintainer
1658 const char* maintainer = pakfire_package_get_maintainer(pkg);
1659 if (maintainer) {
1660 r = pakfire_json_add_string(pkg->pakfire, md, "maintainer", maintainer);
1661 if (r)
1662 goto ERROR;
1663 }
1664
1665 // URL
1666 const char* url = pakfire_package_get_url(pkg);
1667 if (url) {
1668 r = pakfire_json_add_string(pkg->pakfire, md, "url", url);
1669 if (r)
1670 goto ERROR;
1671 }
1672
1673 // License
1674 const char* license = pakfire_package_get_license(pkg);
1675 if (license) {
1676 r = pakfire_json_add_string(pkg->pakfire, md, "license", license);
1677 if (r)
1678 goto ERROR;
1679 }
1680
1681 // Summary
1682 const char* summary = pakfire_package_get_summary(pkg);
1683 if (summary) {
1684 r = pakfire_json_add_string(pkg->pakfire, md, "summary", summary);
1685 if (r)
1686 goto ERROR;
1687 }
1688
1689 // Description
1690 const char* description = pakfire_package_get_description(pkg);
1691 if (description) {
1692 r = pakfire_json_add_string(pkg->pakfire, md, "description", description);
1693 if (r)
1694 goto ERROR;
1695 }
1696
1697 // Installed package size
1698 size_t installsize = pakfire_package_get_installsize(pkg);
1699 r = pakfire_json_add_integer(pkg->pakfire, md, "size", installsize);
1700 if (r)
1701 goto ERROR;
1702
1703 // Generate dependency metadata
1704 r = pakfire_package_add_json_dependencies(pkg, md);
1705 if (r)
1706 goto ERROR;
1707
1708 // Generate build metadata
1709 r = pakfire_package_add_build_metadata(pkg, md);
1710 if (r)
1711 goto ERROR;
1712
1713ERROR:
1714 if (r)
1715 json_object_put(md);
1716
1717 return md;
1718}