]> git.ipfire.org Git - pakfire.git/blame - src/libpakfire/package.c
logging: Make the legacy logger configurable
[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
517708c8
MT
35// Enable legacy logging
36#define PAKFIRE_LEGACY_LOGGING
37
cbed1552 38#include <pakfire/archive.h>
221cc3ce 39#include <pakfire/constants.h>
484b2077 40#include <pakfire/ctx.h>
2a623cf8 41#include <pakfire/dependencies.h>
c52e0148 42#include <pakfire/digest.h>
221cc3ce 43#include <pakfire/file.h>
5e9463ec 44#include <pakfire/filelist.h>
221cc3ce 45#include <pakfire/i18n.h>
6cdfb9dd 46#include <pakfire/logging.h>
221cc3ce 47#include <pakfire/package.h>
cbed1552 48#include <pakfire/pakfire.h>
b4ae14b2 49#include <pakfire/path.h>
9f953e68 50#include <pakfire/private.h>
221cc3ce 51#include <pakfire/repo.h>
d973a13d 52#include <pakfire/string.h>
2f269d34 53#include <pakfire/transaction.h>
221cc3ce
MT
54#include <pakfire/util.h>
55
31480bee 56struct pakfire_package {
484b2077 57 struct pakfire_ctx* ctx;
ac4c607b 58 struct pakfire* pakfire;
7847efcd 59 int nrefs;
e9d9eadc 60
8b088877
MT
61 // Reference to this package in the SOLV pool
62 Id id;
4651122b 63 struct pakfire_repo* repo;
8b088877 64
40fcf5ff 65 char nevra[NAME_MAX];
571539a7 66 char source_nevra[NAME_MAX];
40fcf5ff 67
b12a5d7d
MT
68 char filename[NAME_MAX];
69 char path[PATH_MAX];
6c0217d3 70 char cache_path[PATH_MAX];
7847efcd
MT
71};
72
39d1a3d3
MT
73static Solvable* get_solvable(struct pakfire_package* pkg) {
74 Pool* pool = pakfire_get_solv_pool(pkg->pakfire);
75
76 return pool_id2solvable(pool, pkg->id);
77}
78
79static int pakfire_package_dep2id(const enum pakfire_package_key key,
80 Id* id, Id* marker) {
81 switch (key) {
82 case PAKFIRE_PKG_PROVIDES:
83 *id = SOLVABLE_PROVIDES;
84 *marker = -SOLVABLE_FILEMARKER;
85 break;
86
87 case PAKFIRE_PKG_PREREQUIRES:
88 *id = SOLVABLE_REQUIRES;
89 *marker = SOLVABLE_PREREQMARKER;
90 break;
91
92 case PAKFIRE_PKG_REQUIRES:
93 *id = SOLVABLE_REQUIRES;
94 *marker = -SOLVABLE_PREREQMARKER;
95 break;
96
97 case PAKFIRE_PKG_CONFLICTS:
98 *id = SOLVABLE_CONFLICTS;
99 break;
100
101 case PAKFIRE_PKG_OBSOLETES:
102 *id = SOLVABLE_OBSOLETES;
103 break;
104
105 case PAKFIRE_PKG_RECOMMENDS:
106 *id = SOLVABLE_RECOMMENDS;
107 break;
108
109 case PAKFIRE_PKG_SUGGESTS:
110 *id = SOLVABLE_SUGGESTS;
111 break;
112
113 case PAKFIRE_PKG_SUPPLEMENTS:
114 *id = SOLVABLE_SUPPLEMENTS;
115 break;
116
117 case PAKFIRE_PKG_ENHANCES:
118 *id = SOLVABLE_ENHANCES;
119 break;
120
121 // This operation is not possible for any other types
122 default:
123 errno = EINVAL;
124 return 1;
125 }
126
127 return 0;
128}
129
130static int pakfire_package_add_depid(struct pakfire_package* pkg,
131 const enum pakfire_package_key key, Id dep) {
132 Solvable* s = get_solvable(pkg);
6a648bd4
MT
133 int r;
134
39d1a3d3
MT
135 Id id = ID_NULL;
136 Id marker = ID_NULL;
137
138 // Translate the dependency type
139 r = pakfire_package_dep2id(key, &id, &marker);
140 if (r)
6a648bd4
MT
141 return r;
142
39d1a3d3
MT
143 // Append to the dependency array
144 solvable_add_deparray(s, id, dep, marker);
6a648bd4 145
39d1a3d3
MT
146 return 0;
147}
6a648bd4 148
39d1a3d3
MT
149static int pakfire_package_add_self_provides(struct pakfire_package* pkg) {
150 // Fetch the solvable
151 Solvable* s = get_solvable(pkg);
152 if (!s)
153 return 1;
154
155 // Get the self-provides ID
156 Id dep = solvable_selfprovidedep(s);
157
158 // Add it to the package
159 return pakfire_package_add_depid(pkg, PAKFIRE_PKG_PROVIDES, dep);
6a648bd4
MT
160}
161
33ad2a01
MT
162int pakfire_package_create_from_solvable(struct pakfire_package** package,
163 struct pakfire* pakfire, Id id) {
31480bee 164 struct pakfire_package* pkg = calloc(1, sizeof(*pkg));
e9d9eadc 165 if (!pkg)
33ad2a01 166 return 1;
6cdfb9dd 167
484b2077
MT
168 // Store a reference to the context
169 pkg->ctx = pakfire_ctx(pakfire);
170
e9d9eadc 171 pkg->pakfire = pakfire_ref(pakfire);
e9d9eadc 172 pkg->nrefs = 1;
221cc3ce 173
33ad2a01
MT
174 // Store the ID
175 pkg->id = id;
176
177 // Success
178 *package = pkg;
179 return 0;
221cc3ce
MT
180}
181
33ad2a01 182PAKFIRE_EXPORT int pakfire_package_create(struct pakfire_package** package,
32136e0c
MT
183 struct pakfire* pakfire, struct pakfire_repo* repo,
184 const char* name, const char* evr, const char* arch) {
32136e0c 185 struct pakfire_repo* dummy = NULL;
33ad2a01
MT
186 int r;
187
188 // Check for some valid input
189 if (!name || !evr || !arch) {
190 errno = EINVAL;
191 return 1;
192 }
32136e0c
MT
193
194 // Default to dummy repository
195 if (!repo) {
196 dummy = pakfire_get_repo(pakfire, PAKFIRE_REPO_DUMMY);
197 if (!dummy) {
198 errno = ENOENT;
33ad2a01 199 return 1;
32136e0c
MT
200 }
201
202 repo = dummy;
203 }
204
205 // Allocate a new solvable
e9d9eadc 206 Id id = pakfire_repo_add_solvable(repo);
33ad2a01
MT
207 if (!id) {
208 ERROR(pakfire, "Could not allocate a solvable: %m\n");
209 r = 1;
32136e0c 210 goto ERROR;
33ad2a01 211 }
e9d9eadc 212
32136e0c 213 // Create a new package object
33ad2a01
MT
214 r = pakfire_package_create_from_solvable(package, pakfire, id);
215 if (r)
32136e0c 216 goto ERROR;
221cc3ce 217
33ad2a01
MT
218 // Reference the repository
219 (*package)->repo = pakfire_repo_ref(repo);
e9d9eadc 220
33ad2a01
MT
221 // Set the name
222 r = pakfire_package_set_string(*package, PAKFIRE_PKG_NAME, name);
223 if (r) {
224 ERROR(pakfire, "Could not set package name '%s': %m\n", name);
225 goto ERROR;
226 }
227
228 // Set EVR
229 r = pakfire_package_set_string(*package, PAKFIRE_PKG_EVR, evr);
230 if (r) {
231 ERROR(pakfire, "Could not set package EVR '%s': %m\n", evr);
232 goto ERROR;
233 }
234
235 // Set arch
236 r = pakfire_package_set_string(*package, PAKFIRE_PKG_ARCH, arch);
237 if (r) {
238 ERROR(pakfire, "Could not set package arch '%s': %m\n", arch);
239 goto ERROR;
240 }
221cc3ce 241
6a648bd4 242 // Add self-provides
39d1a3d3 243 r = pakfire_package_add_self_provides(*package);
6a648bd4
MT
244 if (r) {
245 ERROR(pakfire, "Could not create self-provides: %m\n");
246 goto ERROR;
247 }
248
32136e0c
MT
249ERROR:
250 if (dummy)
251 pakfire_repo_unref(dummy);
252
33ad2a01 253 return r;
221cc3ce
MT
254}
255
31480bee 256static void pakfire_package_free(struct pakfire_package* pkg) {
e9d9eadc
MT
257 if (pkg->repo)
258 pakfire_repo_unref(pkg->repo);
484b2077
MT
259 if (pkg->pakfire)
260 pakfire_unref(pkg->pakfire);
261 if (pkg->ctx)
262 pakfire_ctx_unref(pkg->ctx);
f0d6233d 263 free(pkg);
221cc3ce
MT
264}
265
31480bee 266PAKFIRE_EXPORT struct pakfire_package* pakfire_package_ref(struct pakfire_package* pkg) {
a4e3894f
MT
267 pkg->nrefs++;
268
269 return pkg;
270}
271
31480bee 272PAKFIRE_EXPORT struct pakfire_package* pakfire_package_unref(struct pakfire_package* pkg) {
a4e3894f
MT
273 if (--pkg->nrefs > 0)
274 return pkg;
275
276 pakfire_package_free(pkg);
277 return NULL;
278}
279
ac4c607b 280PAKFIRE_EXPORT struct pakfire* pakfire_package_get_pakfire(struct pakfire_package* pkg) {
178a4506
MT
281 return pakfire_ref(pkg->pakfire);
282}
283
31480bee 284PAKFIRE_EXPORT int pakfire_package_eq(struct pakfire_package* pkg1, struct pakfire_package* pkg2) {
221cc3ce
MT
285 return pkg1->id == pkg2->id;
286}
287
31480bee 288PAKFIRE_EXPORT int pakfire_package_cmp(struct pakfire_package* pkg1, struct pakfire_package* pkg2) {
0defa23e 289 Pool* pool = pakfire_get_solv_pool(pkg1->pakfire);
221cc3ce
MT
290
291 Solvable* s1 = get_solvable(pkg1);
292 Solvable* s2 = get_solvable(pkg2);
293
294 // Check names
295 const char* str1 = pool_id2str(pool, s1->name);
296 const char* str2 = pool_id2str(pool, s2->name);
297
298 int ret = strcmp(str1, str2);
299 if (ret)
300 return ret;
301
302 // Check the version string
303 ret = pakfire_package_evr_cmp(pkg1, pkg2);
304 if (ret)
305 return ret;
306
307 // Check repositories
4651122b
MT
308 struct pakfire_repo* repo1 = pakfire_package_get_repo(pkg1);
309 struct pakfire_repo* repo2 = pakfire_package_get_repo(pkg2);
221cc3ce
MT
310
311 if (repo1 && repo2) {
312 ret = pakfire_repo_cmp(repo1, repo2);
3ff6aee6 313 }
221cc3ce 314
3ff6aee6
MT
315 pakfire_repo_unref(repo1);
316 pakfire_repo_unref(repo2);
221cc3ce 317
3ff6aee6
MT
318 if (ret)
319 return ret;
221cc3ce
MT
320
321 // Check package architectures
322 str1 = pool_id2str(pool, s1->arch);
323 str2 = pool_id2str(pool, s2->arch);
324
325 return strcmp(str1, str2);
326}
327
31480bee 328PAKFIRE_EXPORT int pakfire_package_evr_cmp(struct pakfire_package* pkg1, struct pakfire_package* pkg2) {
0defa23e 329 Pool* pool = pakfire_get_solv_pool(pkg1->pakfire);
221cc3ce
MT
330
331 Solvable* s1 = get_solvable(pkg1);
332 Solvable* s2 = get_solvable(pkg2);
333
334 return pool_evrcmp(pool, s1->evr, s2->evr, EVRCMP_COMPARE);
335}
336
d99f530b 337PAKFIRE_EXPORT unsigned int pakfire_package_id(struct pakfire_package* pkg) {
221cc3ce
MT
338 return pkg->id;
339}
340
e42b5960
MT
341char* pakfire_package_join_evr(const char* e, const char* v, const char* r) {
342 char* buffer = NULL;
312fd26f 343
e42b5960
MT
344 // Check for valid input
345 if (!e || !v || !r) {
346 errno = EINVAL;
347 return NULL;
312fd26f
MT
348 }
349
e42b5960
MT
350 // Skip any zeroes in epoch
351 while (*e && *e == '0')
352 e++;
353
354 // Format string with epoch
355 if (*e) {
356 if (asprintf(&buffer, "%s:%s-%s", e, v, r) < 0)
357 return NULL;
358
359 // Or format it without epoch
360 } else {
361 if (asprintf(&buffer, "%s-%s", v, r) < 0)
362 return NULL;
363 }
312fd26f
MT
364
365 return buffer;
366}
367
31480bee 368int pakfire_package_is_source(struct pakfire_package* pkg) {
74468e4f 369 const char* arch = pakfire_package_get_string(pkg, PAKFIRE_PKG_ARCH);
af14aefb
MT
370 if (!arch)
371 return 1;
372
373 return (strcmp(arch, "src") == 0);
374}
375
31480bee 376static void pakfire_package_internalize_repo(struct pakfire_package* pkg) {
4651122b 377 struct pakfire_repo* repo = pakfire_package_get_repo(pkg);
221cc3ce 378 if (repo) {
9eba3d65 379 pakfire_repo_internalize(repo, 0);
3ff6aee6 380 pakfire_repo_unref(repo);
221cc3ce 381 }
becf17ca 382}
221cc3ce 383
becf17ca
MT
384static void pakfire_package_has_changed(struct pakfire_package* pkg) {
385 struct pakfire_repo* repo = pakfire_package_get_repo(pkg);
386 if (repo) {
387 pakfire_repo_has_changed(repo);
388 pakfire_repo_unref(repo);
389 }
7fbede3a
MT
390}
391
0aade652
MT
392// Removes epoch
393static const char* evr2vr(const char* evr) {
394 const char* p = evr;
395
396 // Skip any leading digits
397 for (; *p >= '0' && *p <= '9'; p++);
398
399 // If after the leading digits, we found :, we return the rest of the string
400 if (p != evr && *p == ':')
401 return ++p;
402
403 return evr;
404}
405
406static const char* pakfire_package_make_filename(struct pakfire_package* pkg) {
407 int r;
408
409 if (!*pkg->filename) {
410 const char* name = pakfire_package_get_string(pkg, PAKFIRE_PKG_NAME);
411 const char* evr = pakfire_package_get_string(pkg, PAKFIRE_PKG_EVR);
412 const char* arch = pakfire_package_get_string(pkg, PAKFIRE_PKG_ARCH);
413
414 if (!name || !evr || !arch)
415 return NULL;
416
417 const char* vr = evr2vr(evr);
418 if (!vr)
419 return NULL;
420
421 r = pakfire_string_format(pkg->filename, "%s-%s.%s.pfm", name, vr, arch);
422 if (r)
423 return NULL;
424 }
425
426 return pkg->filename;
427}
428
b1743459 429static int pakfire_package_make_cache_path(struct pakfire_package* pkg) {
6c0217d3 430 const char* nevra = pakfire_package_get_string(pkg, PAKFIRE_PKG_NEVRA);
b1743459 431
6c0217d3
MT
432 // Fetch the filename
433 const char* filename = pakfire_package_get_string(pkg, PAKFIRE_PKG_FILENAME);
434 if (!filename) {
435 ERROR(pkg->pakfire, "Could not fetch filename for %s: %m\n", nevra);
436 return 1;
437 }
b1743459 438
6c0217d3
MT
439 // Fetch UUID
440 const char* uuid = pakfire_package_get_string(pkg, PAKFIRE_PKG_UUID);
441 if (!uuid) {
442 ERROR(pkg->pakfire, "Could not fetch UUID for %s: %m\n", nevra);
443 return 1;
444 }
b1743459 445
5f4d8a0b 446 return pakfire_cache_path(pkg->pakfire, pkg->cache_path, "%s/%s", uuid, filename);
b1743459
MT
447}
448
314e2310
MT
449PAKFIRE_EXPORT void pakfire_package_unset(struct pakfire_package* pkg,
450 const enum pakfire_package_key key) {
451 Id id = ID_NULL;
452
453 Solvable* s = get_solvable(pkg);
454
455 switch (key) {
456 // Some keys cannot be unset
457 case PAKFIRE_PKG_NAME:
458 case PAKFIRE_PKG_EVR:
459 case PAKFIRE_PKG_ARCH:
460 return;
461
462 case PAKFIRE_PKG_NEVRA:
463 break;
464
465 case PAKFIRE_PKG_UUID:
466 id = SOLVABLE_PKGID;
467 break;
468
469 case PAKFIRE_PKG_SUMMARY:
470 id = SOLVABLE_SUMMARY;
471 break;
472
473 case PAKFIRE_PKG_DESCRIPTION:
474 id = SOLVABLE_DESCRIPTION;
475 break;
476
477 case PAKFIRE_PKG_LICENSE:
478 id = SOLVABLE_LICENSE;
479 break;
480
481 case PAKFIRE_PKG_URL:
482 id = SOLVABLE_URL;
483 break;
484
485 case PAKFIRE_PKG_GROUPS:
486 id = SOLVABLE_GROUP;
487 break;
488
489 case PAKFIRE_PKG_VENDOR:
490 id = SOLVABLE_VENDOR;
491 break;
492
493 case PAKFIRE_PKG_DISTRO:
494 id = SOLVABLE_DISTRIBUTION;
495 break;
496
497 case PAKFIRE_PKG_PACKAGER:
498 id = SOLVABLE_PACKAGER;
499 break;
500
501 case PAKFIRE_PKG_PATH:
502 id = SOLVABLE_MEDIADIR;
503
504 // Unset the filename, too
505 pakfire_package_unset(pkg, PAKFIRE_PKG_FILENAME);
506
507 // Invalidate the cache
508 *pkg->path = '\0';
509 break;
510
511 case PAKFIRE_PKG_FILENAME:
512 id = SOLVABLE_MEDIAFILE;
513 break;
514
515 case PAKFIRE_PKG_CACHE_PATH:
516 *pkg->cache_path = '\0';
517 break;
518
519 case PAKFIRE_PKG_BUILD_HOST:
520 id = SOLVABLE_BUILDHOST;
521 break;
522
523 case PAKFIRE_PKG_BUILD_ID:
524 id = SOLVABLE_BUILDVERSION;
525 break;
526
527 case PAKFIRE_PKG_BUILD_TIME:
528 id = SOLVABLE_BUILDTIME;
529 break;
530
531 case PAKFIRE_PKG_BUILD_ARCHES:
532 id = SOLVABLE_BUILDFLAVOR;
533 break;
534
535 case PAKFIRE_PKG_SOURCE_PKG:
536 pakfire_package_unset(pkg, PAKFIRE_PKG_SOURCE_NAME);
537 pakfire_package_unset(pkg, PAKFIRE_PKG_SOURCE_EVR);
538 pakfire_package_unset(pkg, PAKFIRE_PKG_SOURCE_ARCH);
539
540 // Invalidate cache
541 *pkg->source_nevra = '\0';
542 break;
543
544 case PAKFIRE_PKG_SOURCE_NAME:
545 id = SOLVABLE_SOURCENAME;
546 break;
547
548 case PAKFIRE_PKG_SOURCE_EVR:
549 id = SOLVABLE_SOURCEEVR;
550 break;
551
552 case PAKFIRE_PKG_SOURCE_ARCH:
553 id = SOLVABLE_SOURCEARCH;
554 break;
555
556 case PAKFIRE_PKG_DOWNLOADSIZE:
557 id = SOLVABLE_DOWNLOADSIZE;
558 break;
559
560 case PAKFIRE_PKG_INSTALLSIZE:
561 id = SOLVABLE_INSTALLSIZE;
562 break;
563
564 case PAKFIRE_PKG_INSTALLTIME:
565 id = SOLVABLE_INSTALLTIME;
566 break;
567
568 // Cannot unset dependencies here
569 case PAKFIRE_PKG_PROVIDES:
570 case PAKFIRE_PKG_PREREQUIRES:
571 case PAKFIRE_PKG_REQUIRES:
572 case PAKFIRE_PKG_CONFLICTS:
573 case PAKFIRE_PKG_OBSOLETES:
574 case PAKFIRE_PKG_RECOMMENDS:
575 case PAKFIRE_PKG_SUGGESTS:
576 case PAKFIRE_PKG_SUPPLEMENTS:
577 case PAKFIRE_PKG_ENHANCES:
578 return;
579
580 case PAKFIRE_PKG_DBID:
581 return;
582 }
583
584 // Unset any values
585 solvable_unset(s, id);
586}
587
10211c67 588PAKFIRE_EXPORT char** pakfire_package_get_strings(
314e2310 589 struct pakfire_package* pkg, const enum pakfire_package_key key) {
10211c67
MT
590 char** ret = NULL;
591 const char* str = NULL;
314e2310
MT
592 Queue strings;
593 Id id = ID_NULL;
594
595 pakfire_package_internalize_repo(pkg);
596
597 Pool* pool = pakfire_get_solv_pool(pkg->pakfire);
598 Solvable* s = get_solvable(pkg);
599
600 switch (key) {
d333480c
MT
601 case PAKFIRE_PKG_GROUPS:
602 id = SOLVABLE_GROUP;
603 break;
604
314e2310
MT
605 case PAKFIRE_PKG_BUILD_ARCHES:
606 id = SOLVABLE_BUILDFLAVOR;
607 break;
608
609 default:
610 errno = EINVAL;
611 return NULL;
612 }
613
614 // Setup a queue
615 queue_init(&strings);
616
617 // Fetch the strings
618 solvable_lookup_idarray(s, id, &strings);
619
620 if (strings.count) {
621 // Allocate an array
622 ret = calloc(strings.count + 1, sizeof(*ret));
623 if (!ret)
624 goto ERROR;
625
626 // Fetch the strings
10211c67
MT
627 for (int i = 0; i < strings.count; i++) {
628 str = pool_id2str(pool, strings.elements[i]);
629 if (!str)
630 goto ERROR;
631
632 // Copy string to heap
633 ret[i] = strdup(str);
634 }
314e2310
MT
635 }
636
637ERROR:
638 // Free the queue
639 queue_free(&strings);
640
641 return ret;
642}
643
644PAKFIRE_EXPORT int pakfire_package_set_strings(struct pakfire_package* pkg,
645 const enum pakfire_package_key key, const char** values) {
646 int r;
647
648 // Drop any previous values
649 pakfire_package_unset(pkg, key);
650
651 // End without error if values is empty
652 if (!values)
653 return 0;
654
655 // Add all new values
656 for (const char** value = values; *value; value++) {
657 r = pakfire_package_add_string(pkg, key, *value);
658 if (r)
659 return r;
660 }
661
662 return 0;
663}
664
665int pakfire_package_set_strings_from_string(struct pakfire_package* pkg,
666 const enum pakfire_package_key key, const char* value) {
667 char* buffer = NULL;
668 char* p = NULL;
669 int r;
670
671 // Drop any previous values
672 pakfire_package_unset(pkg, key);
673
674 // End without error if value is empty
675 if (!value || !*value)
676 return 0;
677
678 // Copy the string to the heap to change it
679 buffer = strdup(value);
680 if (!buffer) {
681 r = -errno;
682 goto ERROR;
683 }
684
685 // Split the string
686 char* s = strtok_r(buffer, " ", &p);
687
688 // Add each part individually
689 while (s) {
690 r = pakfire_package_add_string(pkg, key, s);
691 if (r)
692 goto ERROR;
693
694 // Move on to the next part
695 s = strtok_r(NULL, " ", &p);
696 }
697
698ERROR:
699 if (buffer)
700 free(buffer);
701
702 return r;
703}
704
7fbede3a
MT
705PAKFIRE_EXPORT const char* pakfire_package_get_string(
706 struct pakfire_package* pkg, const enum pakfire_package_key key) {
707 const char* ret = NULL;
708 int r;
709
ac71886a
MT
710 pakfire_package_internalize_repo(pkg);
711
7fbede3a 712 Pool* pool = pakfire_get_solv_pool(pkg->pakfire);
ac71886a 713 Solvable* s = get_solvable(pkg);
ac71886a 714
7fbede3a
MT
715 switch (key) {
716 case PAKFIRE_PKG_NAME:
717 return pool_id2str(pool, s->name);
ac71886a 718
7fbede3a
MT
719 case PAKFIRE_PKG_EVR:
720 return pool_id2str(pool, s->evr);
ac71886a 721
7fbede3a
MT
722 case PAKFIRE_PKG_ARCH:
723 return pool_id2str(pool, s->arch);
221cc3ce 724
7fbede3a 725 case PAKFIRE_PKG_NEVRA:
064b177e 726 if (!*pkg->nevra) {
7fbede3a
MT
727 r = pakfire_string_set(pkg->nevra, pool_solvable2str(pool, s));
728 if (r)
729 return NULL;
730 }
221cc3ce 731
7fbede3a
MT
732 return pkg->nevra;
733
734 case PAKFIRE_PKG_UUID:
735 ret = solvable_lookup_str(s, SOLVABLE_PKGID);
8ceacfa4
MT
736 if (!ret)
737 return NULL;
7189e532
MT
738
739 // Validate the UUID
740 if (!pakfire_uuid_is_valid(ret)) {
741 errno = EINVAL;
742 return NULL;
743 }
744
7fbede3a
MT
745 break;
746
747 case PAKFIRE_PKG_SUMMARY:
748 ret = solvable_lookup_str(s, SOLVABLE_SUMMARY);
749 break;
750
751 case PAKFIRE_PKG_DESCRIPTION:
752 ret = solvable_lookup_str(s, SOLVABLE_DESCRIPTION);
753 break;
754
755 case PAKFIRE_PKG_LICENSE:
756 ret = solvable_lookup_str(s, SOLVABLE_LICENSE);
757 break;
758
759 case PAKFIRE_PKG_URL:
760 ret = solvable_lookup_str(s, SOLVABLE_URL);
761 break;
762
7fbede3a
MT
763 case PAKFIRE_PKG_VENDOR:
764 ret = solvable_lookup_str(s, SOLVABLE_VENDOR);
765 break;
221cc3ce 766
7fbede3a
MT
767 case PAKFIRE_PKG_DISTRO:
768 ret = solvable_lookup_str(s, SOLVABLE_DISTRIBUTION);
769 break;
770
145d0efe 771 case PAKFIRE_PKG_PACKAGER:
7fbede3a
MT
772 ret = solvable_lookup_str(s, SOLVABLE_PACKAGER);
773 break;
0aade652 774
b1743459
MT
775 case PAKFIRE_PKG_PATH:
776 if (!*pkg->path) {
6c0217d3
MT
777 const char* filename = pakfire_package_get_string(pkg, PAKFIRE_PKG_FILENAME);
778 if (!filename)
779 return NULL;
b1743459 780
a98600fb 781 const char* dir = solvable_lookup_str(s, SOLVABLE_MEDIADIR);
6c0217d3
MT
782 if (dir) {
783 r = pakfire_string_format(pkg->path, "%s/%s", dir, filename);
784 if (r)
785 return NULL;
b1743459 786 } else {
6c0217d3 787 r = pakfire_string_set(pkg->path, filename);
b1743459
MT
788 if (r)
789 return NULL;
790 }
791 }
792
793 return pkg->path;
794
0aade652
MT
795 case PAKFIRE_PKG_FILENAME:
796 ret = solvable_lookup_str(s, SOLVABLE_MEDIAFILE);
797
798 // Generate the filename if not set
799 if (!ret)
800 ret = pakfire_package_make_filename(pkg);
801 break;
1f669e88 802
6c0217d3
MT
803 case PAKFIRE_PKG_CACHE_PATH:
804 if (!*pkg->cache_path) {
805 r = pakfire_package_make_cache_path(pkg);
806 if (r)
807 return NULL;
808 }
809
810 return pkg->cache_path;
811
1f669e88
MT
812 case PAKFIRE_PKG_BUILD_HOST:
813 ret = solvable_lookup_str(s, SOLVABLE_BUILDHOST);
814 break;
70f6900d
MT
815
816 case PAKFIRE_PKG_BUILD_ID:
817 ret = solvable_lookup_str(s, SOLVABLE_BUILDVERSION);
818 break;
73ff505b
MT
819
820 case PAKFIRE_PKG_SOURCE_PKG:
821 if (!*pkg->source_nevra) {
988ce1bc
MT
822 const char* name = pakfire_package_get_string(pkg, PAKFIRE_PKG_SOURCE_NAME);
823 const char* evr = pakfire_package_get_string(pkg, PAKFIRE_PKG_SOURCE_EVR);
824 const char* arch = pakfire_package_get_string(pkg, PAKFIRE_PKG_SOURCE_ARCH);
73ff505b
MT
825
826 // Return nothing if we don't have all information
827 if (!name || !evr || !arch)
828 return NULL;
829
830 // Format package name
831 r = pakfire_string_format(pkg->source_nevra, "%s-%s.%s", name, evr, arch);
832 if (r)
833 return NULL;
834 }
835
836 return pkg->source_nevra;
988ce1bc
MT
837
838 case PAKFIRE_PKG_SOURCE_NAME:
839 ret = solvable_lookup_str(s, SOLVABLE_SOURCENAME);
840 break;
841
842 case PAKFIRE_PKG_SOURCE_EVR:
843 ret = solvable_lookup_str(s, SOLVABLE_SOURCEEVR);
844 break;
845
846 case PAKFIRE_PKG_SOURCE_ARCH:
847 ret = solvable_lookup_str(s, SOLVABLE_SOURCEARCH);
848 break;
3f327c3c
MT
849
850 default:
851 break;
7fbede3a
MT
852 }
853
854 return ret;
221cc3ce
MT
855}
856
74468e4f 857PAKFIRE_EXPORT int pakfire_package_set_string(
7fbede3a 858 struct pakfire_package* pkg, const enum pakfire_package_key key, const char* value) {
f54eb6e7
MT
859 char basename[PATH_MAX];
860 char dirname[PATH_MAX];
7fbede3a 861 Id id = ID_NULL;
f54eb6e7 862 int r;
7fbede3a 863
74468e4f
MT
864 Pool* pool = pakfire_get_solv_pool(pkg->pakfire);
865 Solvable* s = get_solvable(pkg);
866
7fbede3a
MT
867 switch (key) {
868 // Do not allow to change name, evr, or arch
869 case PAKFIRE_PKG_NAME:
74468e4f
MT
870 // Reset nevra & filename
871 *pkg->nevra = *pkg->filename = '\0';
872
873 s->name = pool_str2id(pool, value, 1);
874 return 0;
875
7fbede3a 876 case PAKFIRE_PKG_EVR:
74468e4f
MT
877 // Reset nevra & filename
878 *pkg->nevra = *pkg->filename = '\0';
879
880 // Skip empty epoch
881 if (pakfire_string_startswith(value, "0:"))
882 value += 2;
883
884 s->evr = pool_str2id(pool, value, 1);
885 return 0;
886
7fbede3a 887 case PAKFIRE_PKG_ARCH:
74468e4f
MT
888 // Reset nevra & filename
889 *pkg->nevra = *pkg->filename = '\0';
890
891 s->arch = pool_str2id(pool, value, 1);
892 return 0;
893
7fbede3a
MT
894 case PAKFIRE_PKG_NEVRA:
895 errno = EINVAL;
896 return 1;
897
898 case PAKFIRE_PKG_UUID:
899 id = SOLVABLE_PKGID;
7189e532
MT
900
901 // Validate the UUID
902 if (!pakfire_uuid_is_valid(value))
903 return -EINVAL;
904
7fbede3a
MT
905 break;
906
907 case PAKFIRE_PKG_SUMMARY:
908 id = SOLVABLE_SUMMARY;
909 break;
910
911 case PAKFIRE_PKG_DESCRIPTION:
912 id = SOLVABLE_DESCRIPTION;
913 break;
914
915 case PAKFIRE_PKG_LICENSE:
916 id = SOLVABLE_LICENSE;
917 break;
918
919 case PAKFIRE_PKG_URL:
920 id = SOLVABLE_URL;
921 break;
922
7fbede3a
MT
923 case PAKFIRE_PKG_VENDOR:
924 id = SOLVABLE_VENDOR;
925 break;
926
927 case PAKFIRE_PKG_DISTRO:
928 id = SOLVABLE_DISTRIBUTION;
929 break;
930
145d0efe 931 case PAKFIRE_PKG_PACKAGER:
7fbede3a
MT
932 id = SOLVABLE_PACKAGER;
933 break;
0aade652 934
b1743459
MT
935 case PAKFIRE_PKG_PATH:
936 if (value) {
67497686 937 r = pakfire_path_basename(basename, value);
f54eb6e7
MT
938 if (r)
939 return r;
940
b4ae14b2 941 r = pakfire_path_dirname(dirname, value);
f54eb6e7
MT
942 if (r)
943 return r;
b1743459
MT
944 }
945
f54eb6e7 946 if (*basename)
b1743459
MT
947 solvable_set_str(s, SOLVABLE_MEDIAFILE, basename);
948 else
949 solvable_unset(s, SOLVABLE_MEDIAFILE);
950
f54eb6e7 951 if (*dirname)
a98600fb 952 solvable_set_str(s, SOLVABLE_MEDIADIR, dirname);
b1743459 953 else
a98600fb 954 solvable_unset(s, SOLVABLE_MEDIADIR);
b1743459
MT
955
956 // Cache the path
957 pakfire_string_set(pkg->path, value);
958
959 // Mark the package as changed
960 pakfire_package_has_changed(pkg);
961
962 return 0;
963
0aade652
MT
964 case PAKFIRE_PKG_FILENAME:
965 id = SOLVABLE_MEDIAFILE;
966 break;
1f669e88 967
6c0217d3
MT
968 case PAKFIRE_PKG_CACHE_PATH:
969 return pakfire_string_set(pkg->cache_path, value);
970
1f669e88
MT
971 case PAKFIRE_PKG_BUILD_HOST:
972 id = SOLVABLE_BUILDHOST;
973 break;
70f6900d
MT
974
975 case PAKFIRE_PKG_BUILD_ID:
976 id = SOLVABLE_BUILDVERSION;
977 break;
73ff505b
MT
978
979 case PAKFIRE_PKG_SOURCE_PKG:
980 // The source package name cannot be set
981 break;
988ce1bc
MT
982
983 case PAKFIRE_PKG_SOURCE_NAME:
984 id = SOLVABLE_SOURCENAME;
985 break;
986
987 case PAKFIRE_PKG_SOURCE_EVR:
988 // Skip empty epoch
989 if (pakfire_string_startswith(value, "0:"))
990 value += 2;
991
992 id = SOLVABLE_SOURCEEVR;
993 break;
994
995 case PAKFIRE_PKG_SOURCE_ARCH:
996 id = SOLVABLE_SOURCEARCH;
997 break;
3f327c3c 998
314e2310
MT
999 // Compat which splits a string and stores it as an array
1000 case PAKFIRE_PKG_BUILD_ARCHES:
d333480c 1001 case PAKFIRE_PKG_GROUPS:
314e2310
MT
1002 return pakfire_package_set_strings_from_string(pkg, key, value);
1003
3f327c3c
MT
1004 default:
1005 break;
7fbede3a
MT
1006 }
1007
1008 // Check if we have found a valid ID
1009 if (id == ID_NULL) {
1010 errno = EINVAL;
1011 return 1;
1012 }
1013
51c47a9a 1014 // Unset on empty string
ba1229cc 1015 if (!value)
7fbede3a 1016 solvable_unset(s, id);
221cc3ce 1017
51c47a9a 1018 // Store string
ba1229cc
MT
1019 else
1020 solvable_set_str(s, id, value);
7fbede3a
MT
1021
1022 // Mark the package as changed
1023 pakfire_package_has_changed(pkg);
1024
1025 return 0;
1026}
1027
314e2310
MT
1028PAKFIRE_EXPORT int pakfire_package_add_string(struct pakfire_package* pkg,
1029 const enum pakfire_package_key key, const char* value) {
1030 Id key_id = ID_NULL;
1031 Id value_id = ID_NULL;
1032
1033 Pool* pool = pakfire_get_solv_pool(pkg->pakfire);
1034 Solvable* s = get_solvable(pkg);
1035
1036 switch (key) {
d333480c
MT
1037 case PAKFIRE_PKG_GROUPS:
1038 key_id = SOLVABLE_GROUP;
1039 break;
1040
314e2310
MT
1041 case PAKFIRE_PKG_BUILD_ARCHES:
1042 key_id = SOLVABLE_BUILDFLAVOR;
314e2310
MT
1043 break;
1044
1045 default:
1046 errno = EINVAL;
1047 return 1;
1048 }
1049
d333480c
MT
1050 // Convert value
1051 value_id = pool_str2id(pool, value, 1);
1052
314e2310
MT
1053 // Append the string to the ID array
1054 solvable_add_idarray(s, key_id, value_id);
1055
1056 // Mark the package as changed
1057 pakfire_package_has_changed(pkg);
1058
1059 return 0;
1060}
1061
3bea955d
MT
1062PAKFIRE_EXPORT int pakfire_package_get_uuid(struct pakfire_package* pkg,
1063 const enum pakfire_package_key key, uuid_t uuid) {
1064 const char* buffer = NULL;
1065 int r;
1066
1067 switch (key) {
1068 case PAKFIRE_PKG_UUID:
1069 case PAKFIRE_PKG_BUILD_ID:
1070 // Clear the UUID
1071 uuid_clear(uuid);
1072
1073 // Fetch the value
1074 buffer = pakfire_package_get_string(pkg, key);
1075 if (!buffer)
1076 return 1;
1077
1078 // Read buffer into the output
1079 r = uuid_parse(buffer, uuid);
1080 if (r)
1081 return r;
1082
1083 return 0;
1084
1085 default:
1086 errno = EINVAL;
1087 return 1;
1088 }
1089}
1090
1091PAKFIRE_EXPORT int pakfire_package_set_uuid(struct pakfire_package* pkg,
1092 const enum pakfire_package_key key, const uuid_t uuid) {
1093 char buffer[UUID_STR_LEN];
1094
1095 switch (key) {
1096 case PAKFIRE_PKG_UUID:
1097 case PAKFIRE_PKG_BUILD_ID:
1098 // Convert the UUID to string
1099 uuid_unparse_lower(uuid, buffer);
1100
1101 // Store the UUID as string
1102 return pakfire_package_set_string(pkg, key, buffer);
1103
1104 default:
1105 errno = EINVAL;
1106 return 1;
1107 }
1108}
1109
3f327c3c
MT
1110PAKFIRE_EXPORT unsigned long long pakfire_package_get_num(struct pakfire_package* pkg,
1111 const enum pakfire_package_key key, unsigned long long notfound) {
1112 Id id = ID_NULL;
7fbede3a 1113
3f327c3c 1114 switch (key) {
20b898e3
MT
1115 case PAKFIRE_PKG_DBID:
1116 id = RPM_RPMDBID;
1117 break;
1118
3f327c3c
MT
1119 case PAKFIRE_PKG_DOWNLOADSIZE:
1120 id = SOLVABLE_DOWNLOADSIZE;
1121 break;
1122
1123 case PAKFIRE_PKG_INSTALLSIZE:
1124 id = SOLVABLE_INSTALLSIZE;
1125 break;
1126
1127 case PAKFIRE_PKG_BUILD_TIME:
1128 id = SOLVABLE_BUILDTIME;
1129 break;
1130
1131 case PAKFIRE_PKG_INSTALLTIME:
1132 id = SOLVABLE_INSTALLTIME;
1133 break;
1134
1135 // Return zero for all unhandled keys
1136 default:
1137 errno = EINVAL;
1138 return 1;
1139 }
7fbede3a 1140
7fbede3a
MT
1141 Solvable* s = get_solvable(pkg);
1142
4ab9fd79
MT
1143 pakfire_package_internalize_repo(pkg);
1144
3f327c3c 1145 return solvable_lookup_num(s, id, notfound);
7ccc9d74
MT
1146}
1147
3f327c3c
MT
1148PAKFIRE_EXPORT int pakfire_package_set_num(struct pakfire_package* pkg,
1149 const enum pakfire_package_key key, unsigned long long num) {
1150 Id id = ID_NULL;
1151
1152 switch (key) {
20b898e3
MT
1153 case PAKFIRE_PKG_DBID:
1154 id = RPM_RPMDBID;
1155 break;
1156
3f327c3c
MT
1157 case PAKFIRE_PKG_DOWNLOADSIZE:
1158 id = SOLVABLE_DOWNLOADSIZE;
1159 break;
ac71886a 1160
3f327c3c
MT
1161 case PAKFIRE_PKG_INSTALLSIZE:
1162 id = SOLVABLE_INSTALLSIZE;
1163 break;
1164
1165 case PAKFIRE_PKG_BUILD_TIME:
1166 id = SOLVABLE_BUILDTIME;
1167 break;
1168
1169 case PAKFIRE_PKG_INSTALLTIME:
1170 id = SOLVABLE_INSTALLTIME;
1171 break;
1172
1173 // Return zero for all unhandled keys
1174 default:
1175 errno = EINVAL;
1176 return 1;
1177 }
1178
1179 Solvable* s = get_solvable(pkg);
1180
4ab9fd79 1181 // Store the number
3f327c3c
MT
1182 solvable_set_num(s, id, num);
1183
4ab9fd79
MT
1184 // Mark the package as changed
1185 pakfire_package_has_changed(pkg);
1186
3f327c3c 1187 return 0;
ac71886a
MT
1188}
1189
c52e0148 1190static enum pakfire_digest_types pakfire_package_id2digest(Id id) {
e61716e4
MT
1191 switch (id) {
1192 case REPOKEY_TYPE_SHA512:
4500ed0a 1193 return PAKFIRE_DIGEST_SHA2_512;
b28af23a 1194
e61716e4 1195 case REPOKEY_TYPE_SHA256:
4500ed0a 1196 return PAKFIRE_DIGEST_SHA2_256;
b28af23a
MT
1197 }
1198
9802aaf6 1199 return 0;
b28af23a
MT
1200}
1201
1202PAKFIRE_EXPORT const unsigned char* pakfire_package_get_digest(
e082fb85 1203 struct pakfire_package* pkg, enum pakfire_digest_types* type, size_t* length) {
b28af23a 1204 Solvable* s = get_solvable(pkg);
e082fb85 1205 Id id = 0;
b28af23a 1206
e61716e4 1207 const unsigned char* checksum = solvable_lookup_bin_checksum(s, SOLVABLE_CHECKSUM, &id);
b28af23a 1208
e61716e4
MT
1209 // Convert ID to digest type
1210 *type = pakfire_package_id2digest(id);
1211 if (!*type) {
1212 errno = ENOTSUP;
1213 checksum = NULL;
1214 }
1215
e082fb85
MT
1216 // Store the length (if requested)
1217 if (length)
1218 *length = pakfire_digest_length(*type);
e61716e4
MT
1219
1220 return checksum;
b28af23a
MT
1221}
1222
1223PAKFIRE_EXPORT int pakfire_package_set_digest(struct pakfire_package* pkg,
e082fb85 1224 enum pakfire_digest_types type, const unsigned char* digest, const size_t length) {
b28af23a
MT
1225 Solvable* s = get_solvable(pkg);
1226 Pool* pool = s->repo->pool;
e61716e4 1227 Id id;
b28af23a
MT
1228 int r = 1;
1229
e61716e4 1230 switch (type) {
4500ed0a 1231 case PAKFIRE_DIGEST_SHA2_256:
e61716e4
MT
1232 id = REPOKEY_TYPE_SHA256;
1233 break;
1234
4500ed0a 1235 case PAKFIRE_DIGEST_SHA2_512:
e61716e4
MT
1236 id = REPOKEY_TYPE_SHA512;
1237 break;
1238
1239 default:
1240 errno = ENOTSUP;
1241 return 1;
1242 }
b28af23a 1243
e082fb85
MT
1244 // Check if the digest length matches
1245 if (pakfire_digest_length(type) != length) {
1246 errno = EINVAL;
1247 return 1;
1248 }
1249
b28af23a
MT
1250 struct pakfire_repo* repo = pakfire_package_get_repo(pkg);
1251
1252 Repodata* data = pakfire_repo_get_repodata(repo);
1253 if (!data)
1254 goto ERROR;
1255
1256 repodata_set_bin_checksum(data, s - pool->solvables, SOLVABLE_CHECKSUM, id, digest);
1257
1258 // Success
1259 r = 0;
1260
1261ERROR:
1262 pakfire_repo_unref(repo);
1263
1264 return r;
1265}
1266
f3320724 1267int pakfire_package_is_installed(struct pakfire_package* pkg) {
0defa23e 1268 Pool* pool = pakfire_get_solv_pool(pkg->pakfire);
221cc3ce
MT
1269 Solvable* s = get_solvable(pkg);
1270
1271 return pool->installed == s->repo;
1272}
1273
27116707 1274PAKFIRE_EXPORT size_t pakfire_package_get_size(struct pakfire_package* pkg) {
221cc3ce 1275 if (pakfire_package_is_installed(pkg))
3f327c3c 1276 return pakfire_package_get_num(pkg, PAKFIRE_PKG_INSTALLSIZE, 0);
221cc3ce 1277
3f327c3c 1278 return pakfire_package_get_num(pkg, PAKFIRE_PKG_DOWNLOADSIZE, 0);
af647c55
MT
1279}
1280
be3f4199
MT
1281// Build
1282
1283int pakfire_package_supports_build_arch(struct pakfire_package* pkg, const char* arch) {
1284 int r;
1285
1286 char** supported_arches = pakfire_package_get_strings(pkg, PAKFIRE_PKG_BUILD_ARCHES);
1287
1288 // If no build arches are configured, this package supports all arches
1289 if (!supported_arches)
1290 return 1;
1291
1292 for (char** supported_arch = supported_arches; *supported_arch; supported_arch++) {
1293 if (strcmp(arch, *supported_arch) == 0) {
1294 r = 1;
1295 goto END;
1296 }
1297 }
1298
1299 // No match found
1300 r = 0;
1301
1302END:
1303 // Cleanup
1304 if (supported_arches)
1305 pakfire_strings_free(supported_arches);
1306
1307 return r;
1308}
1309
6f3fad3b 1310// Dependencies
452d3833 1311
6f3fad3b
MT
1312PAKFIRE_EXPORT char** pakfire_package_get_deps(struct pakfire_package* pkg,
1313 const enum pakfire_package_key key) {
1314 Solvable* s = get_solvable(pkg);
1315 char** ret = NULL;
1316 int r;
221cc3ce 1317
6f3fad3b
MT
1318 Queue q;
1319 Id id = ID_NULL;
1320 Id marker = ID_NULL;
1321 const char* dep = NULL;
221cc3ce 1322
6f3fad3b
MT
1323 r = pakfire_package_dep2id(key, &id, &marker);
1324 if (r)
1325 return NULL;
221cc3ce 1326
6f3fad3b
MT
1327 // Initialize the output queue
1328 queue_init(&q);
452d3833 1329
6f3fad3b
MT
1330 // Fetch all deps
1331 solvable_lookup_deparray(s, id, &q, marker);
221cc3ce 1332
6f3fad3b
MT
1333 // Allocate array
1334 ret = calloc(q.count + 1, sizeof(*ret));
1335 if (!ret)
1336 goto ERROR;
221cc3ce 1337
6f3fad3b
MT
1338 for (int i = 0; i < q.count; i++) {
1339 dep = pakfire_dep2str(pkg->pakfire, q.elements[i]);
1340 if (!dep)
1341 goto ERROR;
221cc3ce 1342
6f3fad3b
MT
1343 ret[i] = strdup(dep);
1344 if (!ret[i])
1345 goto ERROR;
1346 }
221cc3ce 1347
6f3fad3b
MT
1348 // All good!
1349 goto SUCCESS;
221cc3ce 1350
6f3fad3b
MT
1351ERROR:
1352 if (ret) {
15360ad7 1353 pakfire_strings_free(ret);
6f3fad3b
MT
1354 ret = NULL;
1355 }
221cc3ce 1356
6f3fad3b
MT
1357SUCCESS:
1358 queue_free(&q);
221cc3ce 1359
6f3fad3b 1360 return ret;
221cc3ce
MT
1361}
1362
6f3fad3b
MT
1363int pakfire_package_add_dep(struct pakfire_package* pkg,
1364 const enum pakfire_package_key key, const char* dep) {
6f3fad3b 1365 // Parse the dependency
39d1a3d3 1366 Id id = pakfire_str2dep(pkg->pakfire, dep);
ca66e095
MT
1367
1368 // Silently ignore any invalid dependencies
39d1a3d3 1369 if (!id)
ca66e095 1370 return 0;
8fe2e4ba 1371
39d1a3d3 1372 return pakfire_package_add_depid(pkg, key, id);
452d3833
MT
1373}
1374
31480bee 1375PAKFIRE_EXPORT int pakfire_package_get_reverse_requires(struct pakfire_package* pkg,
4a25eca3 1376 struct pakfire_packagelist* list) {
e1d77c57
MT
1377 Queue matches;
1378 queue_init(&matches);
1379
4a25eca3
MT
1380 // Get the pool ready
1381 pakfire_pool_internalize(pkg->pakfire);
e1d77c57
MT
1382
1383 Pool* pool = pakfire_get_solv_pool(pkg->pakfire);
1384
1385 // Search for any matches
1386 pool_whatmatchessolvable(pool, SOLVABLE_REQUIRES, pkg->id, &matches, 0);
1387
4a25eca3 1388 // Import the result to the package list
460ce205 1389 int r = pakfire_packagelist_import_solvables(list, pkg->pakfire, &matches);
e1d77c57
MT
1390 if (r)
1391 goto ERROR;
1392
1393ERROR:
1394 queue_free(&matches);
1395
1396 return r;
1397}
1398
555b6dd2
MT
1399static int pakfire_package_has_rich_deps_in_deparray(
1400 struct pakfire_package* pkg, Id type) {
1401 int r = 0;
1402
1403 Solvable* s = get_solvable(pkg);
1404
1405 Queue q;
1406 queue_init(&q);
1407
1408 // Fetch all deps
1409 solvable_lookup_deparray(s, type, &q, 0);
1410
1411 // Nothing to do if the array was empty
1412 if (!q.count)
1413 goto ERROR;
1414
1415 for (int i = 0; i < q.count; i++) {
1416 const char* dep = pakfire_dep2str(pkg->pakfire, q.elements[i]);
1417
1418 // Is this a rich dependency?
1419 if (dep && *dep == '(') {
1420 r = 1;
1421 break;
1422 }
1423 }
1424
1425ERROR:
1426 queue_free(&q);
1427
1428 return r;
1429}
1430
1431int pakfire_package_has_rich_deps(struct pakfire_package* pkg) {
3bf61f1d 1432 const Id types[] = {
555b6dd2
MT
1433 // Requires (includes pre-requires)
1434 SOLVABLE_REQUIRES,
1435 SOLVABLE_PROVIDES,
1436 SOLVABLE_CONFLICTS,
1437 SOLVABLE_OBSOLETES,
1438 SOLVABLE_RECOMMENDS,
1439 SOLVABLE_SUGGESTS,
1440 SOLVABLE_SUPPLEMENTS,
1441 SOLVABLE_ENHANCES,
1442 0,
1443 };
1444
1445 for (const Id* type = types; *type; type++) {
1446 int r = pakfire_package_has_rich_deps_in_deparray(pkg, *type);
1447 if (r)
1448 return r;
1449 }
1450
1451 // No match
1452 return 0;
1453}
1454
f35eadab
MT
1455int pakfire_package_matches_dep(struct pakfire_package* pkg,
1456 const enum pakfire_package_key key, const char* dep) {
1457 int r;
1458
1459 Id id = ID_NULL;
1460 int marker = 0;
1461
1462 // Translate the dependency type
1463 r = pakfire_package_dep2id(key, &id, &marker);
1464 if (r)
1465 return r;
1466
1467 // Get the dependency
1468 Id depid = pakfire_str2dep(pkg->pakfire, dep);
1469 if (!depid)
56281312 1470 return -1;
f35eadab
MT
1471
1472 // Fetch the solvable
1473 Solvable* s = get_solvable(pkg);
1474
1475 // Check whether this solvable matches the requested dependency
061bcc69 1476 return solvable_matchesdep(s, id, depid, marker);
f35eadab
MT
1477}
1478
4651122b 1479PAKFIRE_EXPORT struct pakfire_repo* pakfire_package_get_repo(struct pakfire_package* pkg) {
e9d9eadc
MT
1480 if (!pkg->repo) {
1481 Solvable* s = get_solvable(pkg);
1482
1483 pkg->repo = pakfire_repo_create_from_repo(pkg->pakfire, s->repo);
1484 }
221cc3ce 1485
e9d9eadc 1486 return pakfire_repo_ref(pkg->repo);
221cc3ce
MT
1487}
1488
221cc3ce
MT
1489static void pakfire_package_dump_add_line(char** str, const char* key, const char* val) {
1490 if (val)
2932624b 1491 asprintf(str, "%s%-15s: %s\n", (*str) ? *str : "", key ? key : "", val);
221cc3ce
MT
1492}
1493
d333480c
MT
1494static void pakfire_package_dump_add_lines(char** str, const char* key, char** lines) {
1495 for (; *lines; lines++) {
1496 pakfire_package_dump_add_line(str, key, *lines);
1497
1498 // Reset the key after the first line
1499 key = NULL;
1500 }
1501}
1502
1503static void pakfire_package_dump_add_long_line(char** str, const char* key, const char* val) {
45f9e649
MT
1504 char* p = NULL;
1505
1506 // Copy the string onto the heap
1507 char* buffer = strdupa(val);
1508 if (!buffer)
7500066c 1509 return;
221cc3ce 1510
45f9e649
MT
1511 const char* line = strtok_r(buffer, "\n", &p);
1512
1513 while (line) {
1514 pakfire_package_dump_add_line(str, key, line);
1515
1516 // Reset the key
1517 key = NULL;
1518
1519 // Go to the next line
1520 line = strtok_r(NULL, "\n", &p);
1521 }
221cc3ce
MT
1522}
1523
5cf4a7a1
MT
1524static void pakfire_package_dump_add_line_date(char** str, const char* key, time_t date) {
1525 char buffer[1024];
1526 int r;
221cc3ce 1527
5cf4a7a1
MT
1528 // Format time
1529 r = pakfire_strftime(buffer, "%a, %d %b %Y %T %z", date);
1530 if (r)
1531 return;
221cc3ce 1532
5cf4a7a1 1533 pakfire_package_dump_add_line(str, key, buffer);
221cc3ce
MT
1534}
1535
e0b28592
MT
1536static void pakfire_package_dump_add_line_hex(char** str,
1537 const char* key, const unsigned char* buffer, const size_t length) {
1538 char* hex = __pakfire_hexlify(buffer, length);
1539 if (!hex)
1540 return;
1541
1542 pakfire_package_dump_add_line(str, key, hex);
1543 free(hex);
1544}
1545
27116707 1546static void pakfire_package_dump_add_line_size(char** str, const char* key, size_t size) {
cc90545a 1547 char buffer[128];
9b0e3d52
MT
1548
1549 // Format size in human-readable format
1550 int r = pakfire_format_size(buffer, size);
1551 if (r < 0)
1552 return;
221cc3ce 1553
cc90545a 1554 pakfire_package_dump_add_line(str, key, buffer);
221cc3ce
MT
1555}
1556
7db0d073
MT
1557static int pakfire_sort_dependencies(const void* p1, const void* p2) {
1558 const char* dep1 = *(const char**)p1;
1559 const char* dep2 = *(const char**)p2;
1560
1561 return strcmp(dep1, dep2);
1562}
1563
31480bee 1564PAKFIRE_EXPORT char* pakfire_package_dump(struct pakfire_package* pkg, int flags) {
2932624b 1565 char* string = NULL;
221cc3ce
MT
1566
1567 // Name
74468e4f
MT
1568 const char* name = pakfire_package_get_string(pkg, PAKFIRE_PKG_NAME);
1569 if (name)
1570 pakfire_package_dump_add_line(&string, _("Name"), name);
221cc3ce 1571
6ed66687 1572 // EVR
74468e4f
MT
1573 const char* evr = pakfire_package_get_string(pkg, PAKFIRE_PKG_EVR);
1574 if (evr)
1575 pakfire_package_dump_add_line(&string, _("Version"), evr);
221cc3ce 1576
6ed66687 1577 // Arch
74468e4f
MT
1578 const char* arch = pakfire_package_get_string(pkg, PAKFIRE_PKG_ARCH);
1579 if (arch)
1580 pakfire_package_dump_add_line(&string, _("Arch"), arch);
221cc3ce
MT
1581
1582 // Size
27116707 1583 size_t size = pakfire_package_get_size(pkg);
c2737936
MT
1584 if (size)
1585 pakfire_package_dump_add_line_size(&string, _("Size"), size);
221cc3ce 1586
d0f0d507 1587 // Installed Size
221cc3ce 1588 if (pakfire_package_is_installed(pkg)) {
8fde67b2 1589 unsigned long long installsize = pakfire_package_get_num(pkg, PAKFIRE_PKG_INSTALLSIZE, 0);
d0f0d507
MT
1590 if (installsize)
1591 pakfire_package_dump_add_line_size(&string, _("Installed Size"), installsize);
221cc3ce 1592
d0f0d507 1593 // Download Size
221cc3ce 1594 } else {
3f327c3c 1595 size_t downloadsize = pakfire_package_get_num(pkg, PAKFIRE_PKG_DOWNLOADSIZE, 0);
d0f0d507
MT
1596 if (downloadsize)
1597 pakfire_package_dump_add_line_size(&string, _("Download Size"), downloadsize);
221cc3ce
MT
1598 }
1599
d0f0d507 1600 // Repository
4651122b 1601 struct pakfire_repo* repo = pakfire_package_get_repo(pkg);
221cc3ce 1602 if (repo) {
866aa605 1603 if (!pakfire_repo_name_equals(repo, PAKFIRE_REPO_DUMMY)) {
a4292569
MT
1604 const char* repo_name = pakfire_repo_get_name(repo);
1605 pakfire_package_dump_add_line(&string, _("Repo"), repo_name);
1606 }
221cc3ce 1607
3ff6aee6 1608 pakfire_repo_unref(repo);
221cc3ce
MT
1609 }
1610
1611 // Summary
74468e4f
MT
1612 const char* summary = pakfire_package_get_string(pkg, PAKFIRE_PKG_SUMMARY);
1613 if (summary)
1614 pakfire_package_dump_add_line(&string, _("Summary"), summary);
221cc3ce
MT
1615
1616 // Description
74468e4f 1617 const char* description = pakfire_package_get_string(pkg, PAKFIRE_PKG_DESCRIPTION);
1b99c676 1618 if (description)
d333480c 1619 pakfire_package_dump_add_long_line(&string, _("Description"), description);
221cc3ce
MT
1620
1621 // Groups
d333480c
MT
1622 char** groups = pakfire_package_get_strings(pkg, PAKFIRE_PKG_GROUPS);
1623 if (groups) {
7ccc9d74 1624 pakfire_package_dump_add_lines(&string, _("Groups"), groups);
d333480c
MT
1625 pakfire_strings_free(groups);
1626 }
221cc3ce
MT
1627
1628 // URL
74468e4f
MT
1629 const char* url = pakfire_package_get_string(pkg, PAKFIRE_PKG_URL);
1630 if (url)
1631 pakfire_package_dump_add_line(&string, _("URL"), url);
221cc3ce
MT
1632
1633 // License
74468e4f
MT
1634 const char* license = pakfire_package_get_string(pkg, PAKFIRE_PKG_LICENSE);
1635 if (license)
1636 pakfire_package_dump_add_line(&string, _("License"), license);
221cc3ce
MT
1637
1638 if (flags & PAKFIRE_PKG_DUMP_LONG) {
af647c55 1639 // Install Time
3f327c3c
MT
1640 time_t install_time = pakfire_package_get_num(pkg, PAKFIRE_PKG_INSTALLTIME, 0);
1641 if (install_time)
af647c55 1642 pakfire_package_dump_add_line_date(&string, _("Install Time"), install_time);
af647c55 1643
cb9b4eba 1644 // Distribution
74468e4f 1645 const char* distro = pakfire_package_get_string(pkg, PAKFIRE_PKG_DISTRO);
cb9b4eba
MT
1646 if (distro)
1647 pakfire_package_dump_add_line(&string, _("Distribution"), distro);
1648
145d0efe
MT
1649 // Packager
1650 const char* packager = pakfire_package_get_string(pkg, PAKFIRE_PKG_PACKAGER);
1651 if (packager)
1652 pakfire_package_dump_add_line(&string, _("Packager"), packager);
221cc3ce
MT
1653
1654 // Vendor
74468e4f
MT
1655 const char* vendor = pakfire_package_get_string(pkg, PAKFIRE_PKG_VENDOR);
1656 if (vendor)
1657 pakfire_package_dump_add_line(&string, _("Vendor"), vendor);
221cc3ce
MT
1658
1659 // UUID
74468e4f
MT
1660 const char* uuid = pakfire_package_get_string(pkg, PAKFIRE_PKG_UUID);
1661 if (uuid)
1662 pakfire_package_dump_add_line(&string, _("UUID"), uuid);
221cc3ce 1663
7996020a 1664 // Build ID
70f6900d 1665 const char* build_id = pakfire_package_get_string(pkg, PAKFIRE_PKG_BUILD_ID);
7996020a
MT
1666 if (build_id)
1667 pakfire_package_dump_add_line(&string, _("Build ID"), build_id);
1668
314e2310 1669 // Build Arches
10211c67 1670 char** build_arches = pakfire_package_get_strings(pkg, PAKFIRE_PKG_BUILD_ARCHES);
314e2310 1671 if (build_arches) {
d333480c 1672 pakfire_package_dump_add_lines(&string, _("Build Arch"), build_arches);
15360ad7 1673 pakfire_strings_free(build_arches);
314e2310
MT
1674 }
1675
e0b28592
MT
1676 enum pakfire_digest_types digest_type = PAKFIRE_DIGEST_UNDEFINED;
1677 size_t digest_length = 0;
e61716e4
MT
1678
1679 // Digest
e0b28592
MT
1680 const unsigned char* digest = pakfire_package_get_digest(pkg,
1681 &digest_type, &digest_length);
1682 if (digest) {
1683 switch (digest_type) {
1684 case PAKFIRE_DIGEST_SHA2_512:
1685 pakfire_package_dump_add_line_hex(&string,
1686 _("SHA2-512 Digest"), digest, digest_length);
1687 break;
1688
1689 case PAKFIRE_DIGEST_SHA2_256:
1690 pakfire_package_dump_add_line_hex(&string,
1691 _("SHA2-256 Digest"), digest, digest_length);
1692 break;
1693
1694 case PAKFIRE_DIGEST_SHA3_512:
1695 case PAKFIRE_DIGEST_SHA3_256:
1696 case PAKFIRE_DIGEST_BLAKE2B512:
1697 case PAKFIRE_DIGEST_BLAKE2S256:
1698 case PAKFIRE_DIGEST_UNDEFINED:
1699 break;
1700 }
e61716e4 1701 }
b28af23a 1702
571539a7 1703 // Source package
73ff505b 1704 const char* source_package = pakfire_package_get_string(pkg, PAKFIRE_PKG_SOURCE_PKG);
571539a7
MT
1705 if (source_package)
1706 pakfire_package_dump_add_line(&string, _("Source Package"), source_package);
1707
221cc3ce 1708 // Build time
3f327c3c
MT
1709 time_t build_time = pakfire_package_get_num(pkg, PAKFIRE_PKG_BUILD_TIME, 0);
1710 if (build_time)
1711 pakfire_package_dump_add_line_date(&string, _("Build Time"), build_time);
221cc3ce
MT
1712
1713 // Build host
1f669e88
MT
1714 const char* build_host = pakfire_package_get_string(pkg, PAKFIRE_PKG_BUILD_HOST);
1715 if (build_host)
1716 pakfire_package_dump_add_line(&string, _("Build Host"), build_host);
221cc3ce 1717
2f873877 1718 // Dependencies
6f3fad3b
MT
1719 for (const struct pakfire_dep* dep = pakfire_deps; dep->key; dep++) {
1720 char** deps = pakfire_package_get_deps(pkg, dep->key);
7db0d073
MT
1721 if (deps) {
1722 size_t count = 0;
1723
1724 // Count elements in the list
6f3fad3b 1725 for (char** d = deps; *d; d++)
7db0d073
MT
1726 count++;
1727
1728 // Sort the list
1729 qsort(deps, count, sizeof(*deps), pakfire_sort_dependencies);
1730
6f3fad3b
MT
1731 switch (dep->key) {
1732 case PAKFIRE_PKG_PROVIDES:
1733 name = _("Provides");
1734 break;
1735
1736 case PAKFIRE_PKG_PREREQUIRES:
1737 name = _("Pre-Requires");
1738 break;
1739
1740 case PAKFIRE_PKG_REQUIRES:
1741 name = _("Requires");
1742 break;
1743
1744 case PAKFIRE_PKG_CONFLICTS:
1745 name = _("Conflicts");
1746 break;
1747
1748 case PAKFIRE_PKG_OBSOLETES:
1749 name = _("Obsoletes");
1750 break;
1751
1752 case PAKFIRE_PKG_RECOMMENDS:
1753 name = _("Recommends");
1754 break;
1755
1756 case PAKFIRE_PKG_SUGGESTS:
1757 name = _("Suggests");
1758 break;
1759
1760 case PAKFIRE_PKG_SUPPLEMENTS:
1761 name = _("Supplements");
1762 break;
1763
1764 case PAKFIRE_PKG_ENHANCES:
1765 name = _("Enhances");
1766 break;
1767
1768 default:
1769 name = NULL;
1770 break;
1771 }
1772
7db0d073 1773 // Write it to the console
e3a6f5d2
MT
1774 pakfire_package_dump_add_lines(&string, name, deps);
1775 pakfire_strings_free(deps);
2f873877 1776 }
221cc3ce
MT
1777 }
1778 }
1779
1780 if (flags & PAKFIRE_PKG_DUMP_FILELIST) {
1bbbfb9e 1781 struct pakfire_filelist* filelist = pakfire_package_get_filelist(pkg);
5e9463ec
MT
1782
1783 const char* prefix = _("Filelist");
1784
94ff3014 1785 for (unsigned int i = 0; i < pakfire_filelist_length(filelist); i++) {
5803b5f6 1786 struct pakfire_file* file = pakfire_filelist_get(filelist, i);
221cc3ce 1787
32485f6c
MT
1788 const char* path = pakfire_file_get_path(file);
1789 pakfire_package_dump_add_line(&string, prefix, path);
221cc3ce 1790
5e9463ec 1791 pakfire_file_unref(file);
221cc3ce 1792
5e9463ec 1793 // Only prefix the first line
221cc3ce
MT
1794 prefix = NULL;
1795 }
5e9463ec
MT
1796
1797 pakfire_filelist_unref(filelist);
221cc3ce
MT
1798 }
1799
1800 return string;
1801}
1802
900faa2f 1803PAKFIRE_EXPORT struct pakfire_archive* pakfire_package_get_archive(struct pakfire_package* pkg) {
9686a82a 1804 struct pakfire_archive* archive = NULL;
6c0217d3
MT
1805 struct pakfire_repo* repo = NULL;
1806 const char* path = NULL;
1807 int r;
1808
1809 // Fetch the repository
1810 repo = pakfire_package_get_repo(pkg);
1811 if (repo) {
1812 if (pakfire_repo_is_local(repo)) {
1813 path = pakfire_package_get_string(pkg, PAKFIRE_PKG_PATH);
1814 if (!path)
1815 goto ERROR;
1816 }
1817 }
b12a5d7d 1818
cbed1552 1819 // Otherwise open the archive from the cache
641cab18 1820 if (!path)
6c0217d3 1821 path = pakfire_package_get_string(pkg, PAKFIRE_PKG_CACHE_PATH);
cbed1552 1822
641cab18 1823 // Open archive
6c0217d3
MT
1824 r = pakfire_archive_open(&archive, pkg->pakfire, path);
1825 if (r) {
1826 ERROR(pkg->pakfire, "Could not open archive for %s (at %s): %m\n",
1827 pakfire_package_get_string(pkg, PAKFIRE_PKG_NEVRA), path);
1828 goto ERROR;
1829 }
1830
1831ERROR:
1832 if (repo)
1833 pakfire_repo_unref(repo);
cbed1552 1834
9686a82a 1835 return archive;
cbed1552
MT
1836}
1837
843fa803
MT
1838struct pakfire_package_filelist_search {
1839 struct pakfire* pakfire;
1840 struct pakfire_filelist* filelist;
1841 int r;
1842};
1843
1844static int __pakfire_package_fetch_filelist(void* data, Solvable* s, Repodata* repodata,
1845 Repokey* key, struct s_KeyValue* kv) {
1846 struct pakfire_package_filelist_search* search = (struct pakfire_package_filelist_search*)data;
1847
a83d9e9f 1848 struct pakfire_file* file = NULL;
843fa803 1849 int r;
5e9463ec 1850
843fa803
MT
1851 // Skip any results of the wrong type
1852 if (key->type != REPOKEY_TYPE_DIRSTRARRAY)
1853 return 0;
221cc3ce 1854
843fa803
MT
1855 // Fetch the path
1856 const char* path = repodata_dir2str(repodata, kv->id, kv->str);
1857 if (!path) {
1858 r = 1;
1859 goto ERROR;
1860 }
221cc3ce 1861
843fa803
MT
1862 // Create a new file entry
1863 r = pakfire_file_create(&file, search->pakfire);
1864 if (r)
1865 goto ERROR;
5e9463ec 1866
843fa803
MT
1867 // Set path
1868 r = pakfire_file_set_path(file, path);
1869 if (r)
1870 goto ERROR;
221cc3ce 1871
843fa803 1872 // Append the file to the filelist
2f88682d 1873 r = pakfire_filelist_add(search->filelist, file);
843fa803
MT
1874 if (r)
1875 goto ERROR;
1876
1877ERROR:
1878 // Store the error code
1879 search->r = r;
221cc3ce 1880
843fa803 1881 if (file)
5e9463ec 1882 pakfire_file_unref(file);
221cc3ce 1883
843fa803
MT
1884 return r;
1885}
1886
1887static int pakfire_package_fetch_filelist(struct pakfire_package* pkg, struct pakfire_filelist* filelist) {
1888 struct pakfire_package_filelist_search search = {
1889 .pakfire = pkg->pakfire,
1890 .filelist = filelist,
1891 .r = 0,
1892 };
5e9463ec 1893
843fa803
MT
1894 pakfire_package_internalize_repo(pkg);
1895
1896 Solvable* s = get_solvable(pkg);
1897
1898 Repodata* repodata = repo_last_repodata(s->repo);
1899
1900 // Search for all files
1901 repodata_search(repodata, pkg->id, SOLVABLE_FILELIST, SEARCH_FILES,
1902 __pakfire_package_fetch_filelist, &search);
1903
1904 // Break on any error
1905 if (search.r)
1906 return search.r;
1907
843fa803 1908 return search.r;
221cc3ce
MT
1909}
1910
1bbbfb9e 1911PAKFIRE_EXPORT struct pakfire_filelist* pakfire_package_get_filelist(struct pakfire_package* pkg) {
f78f6159 1912 struct pakfire_filelist* filelist = NULL;
5e9463ec 1913
f78f6159 1914 // Create a new filelist
883b3be9 1915 int r = pakfire_filelist_create(&filelist, pkg->pakfire);
f4560c3f 1916 if (r)
f78f6159 1917 goto ERROR;
5e9463ec 1918
f78f6159 1919 // Fetch all entries from the repository database
f4560c3f 1920 r = pakfire_package_fetch_filelist(pkg, filelist);
f78f6159
MT
1921 if (r)
1922 goto ERROR;
221cc3ce 1923
f4560c3f 1924 return filelist;
f78f6159
MT
1925
1926ERROR:
1927 if (filelist)
1928 pakfire_filelist_unref(filelist);
1929
1930 return NULL;
221cc3ce
MT
1931}
1932
9da8ddfc 1933int pakfire_package_append_file(struct pakfire_package* pkg, const char* path) {
f54eb6e7
MT
1934 char basename[PATH_MAX];
1935 char dirname[PATH_MAX];
1936 int r;
1937
5e9463ec 1938 // Fetch repodata
4651122b 1939 struct pakfire_repo* repo = pakfire_package_get_repo(pkg);
0384da25
MT
1940 if (!repo) {
1941 ERROR(pkg->pakfire, "Could not find repository for %s: %m\n",
74468e4f 1942 pakfire_package_get_string(pkg, PAKFIRE_PKG_NEVRA));
0384da25
MT
1943 return 1;
1944 }
1945
3ff6aee6 1946 Repodata* repodata = pakfire_repo_get_repodata(repo);
221cc3ce 1947
f54eb6e7 1948 // Get filename part
67497686 1949 r = pakfire_path_basename(basename, path);
f54eb6e7
MT
1950 if (r)
1951 return r;
1952
1953 // Get directory part
b4ae14b2 1954 r = pakfire_path_dirname(dirname, path);
f54eb6e7
MT
1955 if (r)
1956 return r;
d995f7fc
MT
1957
1958 // Convert directory into ID
1959 Id did = repodata_str2dir(repodata, dirname, 1);
1960 if (!did)
1961 did = repodata_str2dir(repodata, "/", 1);
1962
1963 // Add data to list
94db84fc 1964 repodata_add_dirstr(repodata, pkg->id,
d995f7fc
MT
1965 SOLVABLE_FILELIST, did, basename);
1966
0384da25
MT
1967 pakfire_repo_unref(repo);
1968
843fa803
MT
1969 // This package has changed
1970 pakfire_package_has_changed(pkg);
1971
d995f7fc
MT
1972 return 0;
1973}
1974
30ab941e
MT
1975static int __pakfire_package_set_filelist(struct pakfire* pakfire,
1976 struct pakfire_file* file, void* data) {
1977 struct pakfire_package* pkg = (struct pakfire_package*)data;
221cc3ce 1978
30ab941e
MT
1979 // Fetch the path
1980 const char* path = pakfire_file_get_path(file);
d995f7fc 1981
30ab941e
MT
1982 return pakfire_package_append_file(pkg, path);
1983}
d995f7fc 1984
30ab941e
MT
1985PAKFIRE_EXPORT int pakfire_package_set_filelist(
1986 struct pakfire_package* pkg, struct pakfire_filelist* filelist) {
a3f3c077 1987 return pakfire_filelist_walk(filelist, __pakfire_package_set_filelist, pkg, 0);
d995f7fc 1988}
221cc3ce 1989
31480bee 1990int pakfire_package_set_filelist_from_string(struct pakfire_package* pkg, const char* files) {
731f1d42
MT
1991 char* p = NULL;
1992 int r = 0;
d995f7fc 1993
731f1d42
MT
1994 // Copy files
1995 char* buffer = strdup(files);
1996 if (!buffer)
1997 goto ERROR;
d995f7fc 1998
731f1d42
MT
1999 // Walk through all files
2000 char* path = strtok_r(buffer, "\n", &p);
2001 while (path) {
2002 r = pakfire_package_append_file(pkg, path);
d995f7fc 2003 if (r)
731f1d42 2004 goto ERROR;
d995f7fc 2005
731f1d42 2006 path = strtok_r(NULL, "\n", &p);
5e9463ec 2007 }
221cc3ce 2008
731f1d42
MT
2009ERROR:
2010 if (buffer)
2011 free(buffer);
2012
2013 return r;
221cc3ce 2014}
b59c9fa2
MT
2015
2016static int _pakfire_package_add_json_dependencies(
2017 struct pakfire_package* pkg,
2018 struct json_object* json,
2019 const char* name,
6f3fad3b 2020 const enum pakfire_package_key key) {
b59c9fa2 2021 // Fetch dependencies
6f3fad3b 2022 char** dependencies = pakfire_package_get_deps(pkg, key);
b59c9fa2 2023 if (!dependencies)
6f3fad3b 2024 return 1;
b59c9fa2
MT
2025
2026 // Add dependencies
10211c67 2027 int r = pakfire_json_add_string_array(pkg->pakfire, json, name, dependencies);
b59c9fa2
MT
2028 if (r)
2029 goto ERROR;
2030
2031ERROR:
15360ad7
MT
2032 if (dependencies)
2033 pakfire_strings_free(dependencies);
b59c9fa2
MT
2034
2035 return r;
2036}
2037
2038static int pakfire_package_add_json_dependencies(
2039 struct pakfire_package* pkg, struct json_object* md) {
2040 int r = 0;
2041
2042 // Create new dependencies object
2043 struct json_object* object = json_object_new_object();
2044 if (!object)
2045 return 1;
2046
2047 // Pre-requires
2048 r = _pakfire_package_add_json_dependencies(pkg, object,
6f3fad3b 2049 "prerequires", PAKFIRE_PKG_PREREQUIRES);
b59c9fa2
MT
2050 if (r)
2051 goto ERROR;
2052
2053 // Requires
2054 r = _pakfire_package_add_json_dependencies(pkg, object,
6f3fad3b 2055 "requires", PAKFIRE_PKG_REQUIRES);
b59c9fa2
MT
2056 if (r)
2057 goto ERROR;
2058
2059 // Provides
2060 r = _pakfire_package_add_json_dependencies(pkg, object,
6f3fad3b 2061 "provides", PAKFIRE_PKG_PROVIDES);
b59c9fa2
MT
2062 if (r)
2063 goto ERROR;
2064
2065 // Conflicts
2066 r = _pakfire_package_add_json_dependencies(pkg, object,
6f3fad3b 2067 "conflicts", PAKFIRE_PKG_CONFLICTS);
b59c9fa2
MT
2068 if (r)
2069 goto ERROR;
2070
2071 // Obsoletes
2072 r = _pakfire_package_add_json_dependencies(pkg, object,
6f3fad3b 2073 "obsoletes", PAKFIRE_PKG_OBSOLETES);
b59c9fa2
MT
2074 if (r)
2075 goto ERROR;
2076
2077 // Recommends
2078 r = _pakfire_package_add_json_dependencies(pkg, object,
6f3fad3b 2079 "recommends", PAKFIRE_PKG_RECOMMENDS);
b59c9fa2
MT
2080 if (r)
2081 goto ERROR;
2082
2083 // Suggests
2084 r = _pakfire_package_add_json_dependencies(pkg, object,
6f3fad3b 2085 "suggests", PAKFIRE_PKG_SUGGESTS);
b59c9fa2
MT
2086 if (r)
2087 goto ERROR;
2088
2089 // Supplements
2090 r = _pakfire_package_add_json_dependencies(pkg, object,
6f3fad3b 2091 "supplements", PAKFIRE_PKG_SUPPLEMENTS);
b59c9fa2
MT
2092 if (r)
2093 goto ERROR;
2094
2095 // Enhances
2096 r = _pakfire_package_add_json_dependencies(pkg, object,
6f3fad3b 2097 "enhances", PAKFIRE_PKG_ENHANCES);
b59c9fa2
MT
2098 if (r)
2099 goto ERROR;
2100
2101 // Add object
2102 r = json_object_object_add(md, "dependencies", object);
2103 if (r)
2104 goto ERROR;
2105
2106ERROR:
2107 if (r)
2108 json_object_put(object);
2109
2110 return r;
2111}
2112
ee292522
MT
2113static int __pakfire_package_add_json_filelist(struct pakfire* pakfire,
2114 struct pakfire_file* file, void* data) {
2115 struct json_object* filelist = (struct json_object*)data;
2116 int r = 1;
2117
2118 // Fetch the file path
2119 const char* path = pakfire_file_get_path(file);
2120
2121 // Create a new JSON string
2122 struct json_object* object = json_object_new_string(path);
2123 if (!object)
2124 goto ERROR;
2125
2126 // Append the string
2127 r = json_object_array_add(filelist, object);
2128 if (r)
2129 goto ERROR;
2130
2131 return 0;
2132
2133ERROR:
2134 // Free JSON string
2135 if (object)
2136 json_object_put(object);
2137
2138 return r;
2139}
2140
2141static int pakfire_package_add_json_filelist(
2142 struct pakfire_package* pkg, struct json_object* md) {
2143 struct pakfire_filelist* filelist = NULL;
2144 struct json_object* object = NULL;
2145 int r;
2146
2147 // Fetch the filelist
2148 filelist = pakfire_package_get_filelist(pkg);
2149 if (!filelist) {
2150 ERROR(pkg->pakfire, "Could not fetch package filelist\n");
2151 r = 1;
2152 goto ERROR;
2153 }
2154
2155 // Create a new JSON array
2156 object = json_object_new_array();
2157 if (!object) {
2158 ERROR(pkg->pakfire, "Could not create a JSON array\n");
2159 r = 1;
2160 goto ERROR;
2161 }
2162
2163 // Walk through the filelist
a3f3c077 2164 r = pakfire_filelist_walk(filelist, __pakfire_package_add_json_filelist, object, 0);
ee292522
MT
2165 if (r)
2166 goto ERROR;
2167
2168 // Add object
2169 r = json_object_object_add(md, "filelist", object);
2170 if (r)
2171 goto ERROR;
2172
2173ERROR:
2174 // Free JSON object on error
2175 if (r)
2176 json_object_put(object);
2177 if (filelist)
2178 pakfire_filelist_unref(filelist);
2179
2180 return r;
2181}
2182
460ce205 2183static int __pakfire_package_add_build_packages(struct pakfire_ctx* ctx,
1cb9c3bf
MT
2184 struct pakfire_package* pkg, void* p) {
2185 struct json_object* object = (struct json_object*)p;
2186 int r;
2187
2188 const char* name = pakfire_package_get_string(pkg, PAKFIRE_PKG_NAME);
2189 const char* evr = pakfire_package_get_string(pkg, PAKFIRE_PKG_EVR);
2190
2191 if (!name || !evr) {
460ce205 2192 CTX_ERROR(ctx, "Could not fetch package information: %m\n");
1cb9c3bf
MT
2193 return 1;
2194 }
2195
2196 // Add package information to the list
460ce205 2197 r = pakfire_json_add_string(pkg->pakfire, object, name, evr);
1cb9c3bf 2198 if (r) {
460ce205 2199 CTX_ERROR(ctx, "Could not add package to packages list: %m\n");
1cb9c3bf
MT
2200 return r;
2201 }
2202
2203 return 0;
2204}
2205
2206static int pakfire_package_add_build_packages(struct pakfire_package* pkg,
2207 struct json_object* md) {
2208 struct pakfire_repo* repo = NULL;
2209 struct pakfire_packagelist* packages = NULL;
2210 struct json_object* object = NULL;
2211 int r;
2212
2213 // Create a new JSON array
2214 object = json_object_new_object();
2215 if (!object) {
2216 ERROR(pkg->pakfire, "Could not create a new JSON object: %m\n");
2217 r = 1;
2218 goto ERROR;
2219 }
2220
2221 // Fetch the installed repository
2222 repo = pakfire_get_installed_repo(pkg->pakfire);
2223 if (!repo) {
2224 ERROR(pkg->pakfire, "Could not fetch the installed repository: %m\n");
2225 r = 1;
2226 goto ERROR;
2227 }
2228
d789a72a 2229 // Create a new list
460ce205 2230 r = pakfire_packagelist_create(&packages, pkg->ctx);
d789a72a
MT
2231 if (r)
2232 goto ERROR;
2233
1cb9c3bf 2234 // Fetch all installed packages
d789a72a 2235 r = pakfire_repo_to_packagelist(repo, packages);
1cb9c3bf
MT
2236 if (r) {
2237 ERROR(pkg->pakfire, "Could not fetch packages from installed repository: %m\n");
2238 goto ERROR;
2239 }
2240
2241 // Add all packages to the array
2242 r = pakfire_packagelist_walk(packages, __pakfire_package_add_build_packages, object);
2243 if (r)
2244 goto ERROR;
2245
2246 // Add object
2247 r = json_object_object_add(md, "packages", json_object_get(object));
2248 if (r)
2249 goto ERROR;
2250
2251ERROR:
2252 if (packages)
2253 pakfire_packagelist_unref(packages);
2254 if (repo)
2255 pakfire_repo_unref(repo);
2256 if (object)
2257 json_object_put(object);
2258
2259 return r;
2260}
2261
b59c9fa2
MT
2262static int pakfire_package_add_build_metadata(struct pakfire_package* pkg,
2263 struct json_object* md) {
2264 int r;
2265
2266 // Create a new JSON object
2267 struct json_object* object = json_object_new_object();
2268 if (!object)
2269 return 1;
2270
2271 // Add pakfire version that generated this metadata
2272 r = pakfire_json_add_string(pkg->pakfire, object, "pakfire", PACKAGE_VERSION);
2273 if (r)
2274 goto ERROR;
2275
2276 // Write build host
1f669e88 2277 const char* build_host = pakfire_package_get_string(pkg, PAKFIRE_PKG_BUILD_HOST);
b59c9fa2
MT
2278 if (build_host) {
2279 r = pakfire_json_add_string(pkg->pakfire, object, "host", build_host);
2280 if (r)
2281 goto ERROR;
2282 }
2283
2284 // Write build id
70f6900d 2285 const char* build_id = pakfire_package_get_string(pkg, PAKFIRE_PKG_BUILD_ID);
b59c9fa2
MT
2286 if (build_id) {
2287 r = pakfire_json_add_string(pkg->pakfire, object, "id", build_id);
2288 if (r)
2289 goto ERROR;
2290 }
2291
2292 // Write build host
3f327c3c 2293 time_t build_time = pakfire_package_get_num(pkg, PAKFIRE_PKG_BUILD_TIME, 0);
b59c9fa2
MT
2294 if (build_time) {
2295 r = pakfire_json_add_integer(pkg->pakfire, object, "time", build_time);
2296 if (r)
2297 goto ERROR;
2298 }
2299
314e2310 2300 // Write build arches
10211c67 2301 char** build_arches = pakfire_package_get_strings(pkg, PAKFIRE_PKG_BUILD_ARCHES);
314e2310
MT
2302 if (build_arches) {
2303 r = pakfire_json_add_string_array(pkg->pakfire, object, "arches", build_arches);
10211c67
MT
2304
2305 // Cleanup
15360ad7 2306 pakfire_strings_free(build_arches);
314e2310
MT
2307
2308 if (r)
2309 goto ERROR;
2310 }
2311
571539a7 2312 // Source package name
988ce1bc 2313 const char* name = pakfire_package_get_string(pkg, PAKFIRE_PKG_SOURCE_NAME);
571539a7
MT
2314 if (name) {
2315 r = pakfire_json_add_string(pkg->pakfire, object, "source-name", name);
2316 if (r)
2317 goto ERROR;
2318 }
2319
2320 // Source package EVR
988ce1bc 2321 const char* evr = pakfire_package_get_string(pkg, PAKFIRE_PKG_SOURCE_EVR);
571539a7
MT
2322 if (evr) {
2323 r = pakfire_json_add_string(pkg->pakfire, object, "source-evr", evr);
2324 if (r)
2325 goto ERROR;
2326 }
2327
2328 // Source package arch
988ce1bc 2329 const char* arch = pakfire_package_get_string(pkg, PAKFIRE_PKG_SOURCE_ARCH);
571539a7
MT
2330 if (arch) {
2331 r = pakfire_json_add_string(pkg->pakfire, object, "source-arch", arch);
2332 if (r)
2333 goto ERROR;
2334 }
2335
1cb9c3bf
MT
2336 // Build Packages
2337 if (!pakfire_package_is_source(pkg)) {
2338 r = pakfire_package_add_build_packages(pkg, object);
2339 if (r)
2340 goto ERROR;
2341 }
2342
b59c9fa2
MT
2343 // Add object
2344 r = json_object_object_add(md, "build", object);
2345 if (r)
2346 goto ERROR;
2347
2348ERROR:
2349 if (r)
2350 json_object_put(object);
2351
2352 return r;
2353}
2354
2355struct json_object* pakfire_package_to_json(struct pakfire_package* pkg) {
2356 struct json_object* md = json_object_new_object();
2357 int r = 0;
2358
2359 // Name
74468e4f 2360 const char* name = pakfire_package_get_string(pkg, PAKFIRE_PKG_NAME);
b59c9fa2
MT
2361 if (name) {
2362 r = pakfire_json_add_string(pkg->pakfire, md, "name", name);
2363 if (r)
2364 goto ERROR;
2365 }
2366
2367 // EVR
74468e4f 2368 const char* evr = pakfire_package_get_string(pkg, PAKFIRE_PKG_EVR);
b59c9fa2
MT
2369 if (evr) {
2370 r = pakfire_json_add_string(pkg->pakfire, md, "evr", evr);
2371 if (r)
2372 goto ERROR;
2373 }
2374
2375 // Arch
74468e4f 2376 const char* arch = pakfire_package_get_string(pkg, PAKFIRE_PKG_ARCH);
b59c9fa2
MT
2377 if (arch) {
2378 r = pakfire_json_add_string(pkg->pakfire, md, "arch", arch);
2379 if (r)
2380 goto ERROR;
2381 }
2382
d9475a74 2383 // Vendor
74468e4f 2384 const char* vendor = pakfire_package_get_string(pkg, PAKFIRE_PKG_VENDOR);
d9475a74
MT
2385 if (vendor) {
2386 r = pakfire_json_add_string(pkg->pakfire, md, "vendor", vendor);
2387 if (r)
2388 goto ERROR;
2389 }
2390
ca002cae 2391 // Distribution
74468e4f 2392 const char* distribution = pakfire_package_get_string(pkg, PAKFIRE_PKG_DISTRO);
ca002cae
MT
2393 if (distribution) {
2394 r = pakfire_json_add_string(pkg->pakfire, md, "distribution", distribution);
2395 if (r)
2396 goto ERROR;
2397 }
2398
b59c9fa2 2399 // UUID
74468e4f 2400 const char* uuid = pakfire_package_get_string(pkg, PAKFIRE_PKG_UUID);
b59c9fa2
MT
2401 if (uuid) {
2402 r = pakfire_json_add_string(pkg->pakfire, md, "uuid", uuid);
2403 if (r)
2404 goto ERROR;
2405 }
2406
2407 // Groups
d333480c 2408 char** groups = pakfire_package_get_strings(pkg, PAKFIRE_PKG_GROUPS);
b59c9fa2 2409 if (groups) {
d333480c
MT
2410 r = pakfire_json_add_string_array(pkg->pakfire, md, "groups", groups);
2411
2412 // Cleanup
2413 pakfire_strings_free(groups);
2414
cb9b4eba
MT
2415 if (r)
2416 goto ERROR;
2417 }
2418
145d0efe
MT
2419 // Packager
2420 const char* packager = pakfire_package_get_string(pkg, PAKFIRE_PKG_PACKAGER);
2421 if (packager) {
2422 r = pakfire_json_add_string(pkg->pakfire, md, "packager", packager);
b59c9fa2
MT
2423 if (r)
2424 goto ERROR;
2425 }
2426
2427 // URL
74468e4f 2428 const char* url = pakfire_package_get_string(pkg, PAKFIRE_PKG_URL);
b59c9fa2
MT
2429 if (url) {
2430 r = pakfire_json_add_string(pkg->pakfire, md, "url", url);
2431 if (r)
2432 goto ERROR;
2433 }
2434
2435 // License
74468e4f 2436 const char* license = pakfire_package_get_string(pkg, PAKFIRE_PKG_LICENSE);
b59c9fa2
MT
2437 if (license) {
2438 r = pakfire_json_add_string(pkg->pakfire, md, "license", license);
2439 if (r)
2440 goto ERROR;
2441 }
2442
2443 // Summary
74468e4f 2444 const char* summary = pakfire_package_get_string(pkg, PAKFIRE_PKG_SUMMARY);
b59c9fa2
MT
2445 if (summary) {
2446 r = pakfire_json_add_string(pkg->pakfire, md, "summary", summary);
2447 if (r)
2448 goto ERROR;
2449 }
2450
2451 // Description
74468e4f 2452 const char* description = pakfire_package_get_string(pkg, PAKFIRE_PKG_DESCRIPTION);
b59c9fa2
MT
2453 if (description) {
2454 r = pakfire_json_add_string(pkg->pakfire, md, "description", description);
2455 if (r)
2456 goto ERROR;
2457 }
2458
2459 // Installed package size
8fde67b2 2460 unsigned long long installsize = pakfire_package_get_num(pkg, PAKFIRE_PKG_INSTALLSIZE, 0);
3f327c3c 2461
8fde67b2 2462 r = pakfire_json_add_integer(pkg->pakfire, md, "size", (uint64_t)installsize);
b59c9fa2
MT
2463 if (r)
2464 goto ERROR;
2465
2466 // Generate dependency metadata
2467 r = pakfire_package_add_json_dependencies(pkg, md);
2468 if (r)
2469 goto ERROR;
2470
ee292522
MT
2471 // Generate filelist
2472 r = pakfire_package_add_json_filelist(pkg, md);
2473 if (r)
2474 goto ERROR;
2475
b59c9fa2
MT
2476 // Generate build metadata
2477 r = pakfire_package_add_build_metadata(pkg, md);
2478 if (r)
2479 goto ERROR;
2480
2481ERROR:
2482 if (r)
2483 json_object_put(md);
2484
2485 return md;
2486}
4df7e8d8 2487
2f269d34
MT
2488PAKFIRE_EXPORT int pakfire_package_installcheck(struct pakfire_package* pkg,
2489 char** problem, int flags) {
2490 struct pakfire_transaction* transaction = NULL;
2491 char* p = NULL;
4df7e8d8
MT
2492 int r;
2493
2494 const char* nevra = pakfire_package_get_string(pkg, PAKFIRE_PKG_NEVRA);
2495
2f269d34
MT
2496 // Create a new transaction
2497 r = pakfire_transaction_create(&transaction, pkg->pakfire, flags);
4df7e8d8
MT
2498 if (r)
2499 goto ERROR;
2500
2501 // Install the package
2f269d34
MT
2502 r = pakfire_transaction_request_package(transaction,
2503 PAKFIRE_JOB_INSTALL, pkg, PAKFIRE_JOB_ESSENTIAL);
4df7e8d8
MT
2504 if (r) {
2505 ERROR(pkg->pakfire, "Could not add package %s to the request\n", nevra);
2506 goto ERROR;
2507 }
2508
2f269d34 2509 // Solve the transaction
94427e38 2510 r = pakfire_transaction_solve(transaction, PAKFIRE_TRANSACTION_WITHOUT_RECOMMENDED, &p);
4df7e8d8 2511 if (r) {
2f269d34 2512 DEBUG(pkg->pakfire, "Could not install %s:\n%s\n", nevra, p);
4df7e8d8 2513
2f269d34
MT
2514 // Copy the problem string
2515 if (p)
2516 *problem = strdup(p);
4df7e8d8
MT
2517 }
2518
2519ERROR:
2f269d34
MT
2520 if (p)
2521 free(p);
2522 if (transaction)
2523 pakfire_transaction_unref(transaction);
4df7e8d8
MT
2524
2525 return r;
2526}