]> git.ipfire.org Git - pakfire.git/blob - src/libpakfire/package.c
libpakfire: Use internal access function to check if a file exists
[pakfire.git] / src / libpakfire / package.c
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
21 #include <assert.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <time.h>
25
26 #include <solv/evr.h>
27 #include <solv/pool.h>
28 #include <solv/pooltypes.h>
29 #include <solv/repo.h>
30 #include <solv/solvable.h>
31
32 #include <pakfire/archive.h>
33 #include <pakfire/constants.h>
34 #include <pakfire/file.h>
35 #include <pakfire/i18n.h>
36 #include <pakfire/logging.h>
37 #include <pakfire/package.h>
38 #include <pakfire/pakfire.h>
39 #include <pakfire/private.h>
40 #include <pakfire/relation.h>
41 #include <pakfire/relationlist.h>
42 #include <pakfire/repo.h>
43 #include <pakfire/util.h>
44
45 struct _PakfirePackage {
46 Pakfire pakfire;
47 Id id;
48 PakfireFile filelist;
49 PakfireArchive archive;
50 int nrefs;
51 };
52
53 static Pool* pakfire_package_get_solv_pool(PakfirePackage pkg) {
54 return pakfire_get_solv_pool(pkg->pakfire);
55 }
56
57 static void pakfire_package_add_self_provides(Pakfire pakfire, PakfirePackage pkg, const char* name, const char* evr) {
58 PakfireRelation relation = pakfire_relation_create(pakfire, name, PAKFIRE_EQ, evr);
59
60 pakfire_package_add_provides(pkg, relation);
61
62 pakfire_relation_unref(relation);
63 }
64
65 PAKFIRE_EXPORT PakfirePackage pakfire_package_create(Pakfire pakfire, Id id) {
66 PakfirePackage pkg = pakfire_calloc(1, sizeof(*pkg));
67 if (pkg) {
68 DEBUG("Allocated Package at %p\n", pkg);
69
70 pkg->pakfire = pakfire_ref(pakfire);
71 pkg->id = id;
72
73 // Initialize reference counter
74 pkg->nrefs = 1;
75 }
76
77 return pkg;
78 }
79
80 PAKFIRE_EXPORT PakfirePackage pakfire_package_create2(Pakfire pakfire, PakfireRepo repo, const char* name, const char* evr, const char* arch) {
81 PakfirePackage pkg = pakfire_repo_add_package(repo);
82
83 pakfire_package_set_name(pkg, name);
84 pakfire_package_set_evr(pkg, evr);
85 pakfire_package_set_arch(pkg, arch);
86
87 pakfire_package_add_self_provides(pakfire, pkg, name, evr);
88
89 return pkg;
90 }
91
92 static void pakfire_package_free(PakfirePackage pkg) {
93 pakfire_archive_unref(pkg->archive);
94 pakfire_package_filelist_remove(pkg);
95 pakfire_unref(pkg->pakfire);
96 pakfire_free(pkg);
97
98 DEBUG("Released Package at %p\n", pkg);
99 }
100
101 PAKFIRE_EXPORT PakfirePackage pakfire_package_ref(PakfirePackage pkg) {
102 pkg->nrefs++;
103
104 return pkg;
105 }
106
107 PAKFIRE_EXPORT PakfirePackage pakfire_package_unref(PakfirePackage pkg) {
108 if (!pkg)
109 return NULL;
110
111 if (--pkg->nrefs > 0)
112 return pkg;
113
114 pakfire_package_free(pkg);
115 return NULL;
116 }
117
118 static Solvable* get_solvable(PakfirePackage pkg) {
119 Pool* pool = pakfire_package_get_solv_pool(pkg);
120
121 return pool_id2solvable(pool, pkg->id);
122 }
123
124 static Repo* pakfire_package_solv_repo(PakfirePackage pkg) {
125 Solvable* s = get_solvable(pkg);
126
127 return s->repo;
128 }
129
130 static Id pakfire_package_get_handle(PakfirePackage pkg) {
131 Pool* pool = pakfire_package_get_solv_pool(pkg);
132 Solvable* s = get_solvable(pkg);
133
134 return s - pool->solvables;
135 }
136
137 PAKFIRE_EXPORT int pakfire_package_identical(PakfirePackage pkg1, PakfirePackage pkg2) {
138 return pkg1->id == pkg2->id;
139 }
140
141 PAKFIRE_EXPORT int pakfire_package_cmp(PakfirePackage pkg1, PakfirePackage pkg2) {
142 Pool* pool = pakfire_package_get_solv_pool(pkg1);
143
144 Solvable* s1 = get_solvable(pkg1);
145 Solvable* s2 = get_solvable(pkg2);
146
147 // Check names
148 const char* str1 = pool_id2str(pool, s1->name);
149 const char* str2 = pool_id2str(pool, s2->name);
150
151 int ret = strcmp(str1, str2);
152 if (ret)
153 return ret;
154
155 // Check the version string
156 ret = pakfire_package_evr_cmp(pkg1, pkg2);
157 if (ret)
158 return ret;
159
160 // Check repositories
161 PakfireRepo repo1 = pakfire_package_get_repo(pkg1);
162 PakfireRepo repo2 = pakfire_package_get_repo(pkg2);
163
164 if (repo1 && repo2) {
165 ret = pakfire_repo_cmp(repo1, repo2);
166 }
167
168 pakfire_repo_unref(repo1);
169 pakfire_repo_unref(repo2);
170
171 if (ret)
172 return ret;
173
174 // Check package architectures
175 str1 = pool_id2str(pool, s1->arch);
176 str2 = pool_id2str(pool, s2->arch);
177
178 return strcmp(str1, str2);
179 }
180
181 PAKFIRE_EXPORT int pakfire_package_evr_cmp(PakfirePackage pkg1, PakfirePackage pkg2) {
182 Pool* pool = pakfire_package_get_solv_pool(pkg1);
183
184 Solvable* s1 = get_solvable(pkg1);
185 Solvable* s2 = get_solvable(pkg2);
186
187 return pool_evrcmp(pool, s1->evr, s2->evr, EVRCMP_COMPARE);
188 }
189
190 PAKFIRE_EXPORT Id pakfire_package_id(PakfirePackage pkg) {
191 return pkg->id;
192 }
193
194 PAKFIRE_EXPORT char* pakfire_package_get_nevra(PakfirePackage pkg) {
195 Pool* pool = pakfire_package_get_solv_pool(pkg);
196 Solvable* s = get_solvable(pkg);
197
198 const char* nevra = pool_solvable2str(pool, s);
199
200 return pakfire_strdup(nevra);
201 }
202
203 PAKFIRE_EXPORT const char* pakfire_package_get_name(PakfirePackage pkg) {
204 Pool* pool = pakfire_package_get_solv_pool(pkg);
205 Solvable* s = get_solvable(pkg);
206
207 return pool_id2str(pool, s->name);
208 }
209
210 PAKFIRE_EXPORT void pakfire_package_set_name(PakfirePackage pkg, const char* name) {
211 Pool* pool = pakfire_package_get_solv_pool(pkg);
212 Solvable* s = get_solvable(pkg);
213
214 s->name = pool_str2id(pool, name, 1);
215 }
216
217 PAKFIRE_EXPORT const char* pakfire_package_get_evr(PakfirePackage pkg) {
218 Pool* pool = pakfire_package_get_solv_pool(pkg);
219 Solvable* s = get_solvable(pkg);
220
221 return pool_id2str(pool, s->evr);
222 }
223
224 PAKFIRE_EXPORT void pakfire_package_set_evr(PakfirePackage pkg, const char* evr) {
225 Pool* pool = pakfire_package_get_solv_pool(pkg);
226 Solvable* s = get_solvable(pkg);
227
228 s->evr = pool_str2id(pool, evr, 1);
229 }
230
231 static void split_evr(Pool* pool, const char* evr_c, char** epoch, char** version, char** release) {
232 char *e, *v, *r;
233
234 char* evr = pool_alloctmpspace(pool, strlen(evr_c) + 1);
235 strcpy(evr, evr_c);
236
237 for (e = evr + 1; *e != ':' && *e != '-'; ++e)
238 ;
239
240 if (*e == '-') {
241 *e = '\0';
242 v = evr;
243 r = e + 1;
244 e = NULL;
245 } else { /* *e == ':' */
246 *e = '\0';
247 v = e + 1;
248 e = evr;
249 for (r = v + 1; *r != '-'; ++r)
250 ;
251 *r = '\0';
252 r++;
253 }
254
255 *epoch = e;
256 *version = v;
257 *release = r;
258 }
259
260 PAKFIRE_EXPORT unsigned long pakfire_package_get_epoch(PakfirePackage pkg) {
261 Pool* pool = pakfire_package_get_solv_pool(pkg);
262 char *e, *v, *r, *endptr;
263
264 unsigned long epoch = 0;
265
266 split_evr(pool, pakfire_package_get_evr(pkg), &e, &v, &r);
267
268 if (e) {
269 long int converted = strtol(e, &endptr, 10);
270 assert(converted > 0);
271 assert(*endptr == '\0');
272 epoch = converted;
273 }
274
275 return epoch;
276 }
277
278 PAKFIRE_EXPORT const char* pakfire_package_get_version(PakfirePackage pkg) {
279 Pool* pool = pakfire_package_get_solv_pool(pkg);
280 char *e, *v, *r;
281
282 split_evr(pool, pakfire_package_get_evr(pkg), &e, &v, &r);
283 return pakfire_strdup(v);
284 }
285
286 PAKFIRE_EXPORT const char* pakfire_package_get_release(PakfirePackage pkg) {
287 Pool* pool = pakfire_package_get_solv_pool(pkg);
288 char *e, *v, *r;
289
290 split_evr(pool, pakfire_package_get_evr(pkg), &e, &v, &r);
291 return pakfire_strdup(r);
292 }
293
294 PAKFIRE_EXPORT const char* pakfire_package_get_arch(PakfirePackage pkg) {
295 Pool* pool = pakfire_package_get_solv_pool(pkg);
296 Solvable* s = get_solvable(pkg);
297
298 return pool_id2str(pool, s->arch);
299 }
300
301 PAKFIRE_EXPORT void pakfire_package_set_arch(PakfirePackage pkg, const char* arch) {
302 Pool* pool = pakfire_package_get_solv_pool(pkg);
303 Solvable* s = get_solvable(pkg);
304
305 s->arch = pool_str2id(pool, arch, 1);
306 }
307
308 static void pakfire_package_internalize_repo(PakfirePackage pkg) {
309 PakfireRepo repo = pakfire_package_get_repo(pkg);
310 if (repo) {
311 pakfire_repo_internalize(repo);
312 pakfire_repo_unref(repo);
313 }
314 }
315
316 static const char* pakfire_package_get_string(PakfirePackage pkg, int key) {
317 pakfire_package_internalize_repo(pkg);
318
319 Solvable* s = get_solvable(pkg);
320 const char* str = solvable_lookup_str(s, key);
321
322 if (!str)
323 return NULL;
324
325 if (strlen(str) == 0)
326 return NULL;
327
328 return str;
329 }
330
331 static void pakfire_package_set_string(PakfirePackage pkg, int key, const char* value) {
332 Solvable* s = get_solvable(pkg);
333
334 if (!value)
335 value = "";
336
337 solvable_set_str(s, key, value);
338 }
339
340 PAKFIRE_EXPORT const char* pakfire_package_get_uuid(PakfirePackage pkg) {
341 return pakfire_package_get_string(pkg, SOLVABLE_PKGID);
342 }
343
344 PAKFIRE_EXPORT void pakfire_package_set_uuid(PakfirePackage pkg, const char* uuid) {
345 pakfire_package_set_string(pkg, SOLVABLE_PKGID, uuid);
346 }
347
348 PAKFIRE_EXPORT const char* pakfire_package_get_checksum(PakfirePackage pkg) {
349 return pakfire_package_get_string(pkg, SOLVABLE_CHECKSUM);
350 }
351
352 PAKFIRE_EXPORT void pakfire_package_set_checksum(PakfirePackage pkg, const char* checksum) {
353 pakfire_package_set_string(pkg, SOLVABLE_CHECKSUM, checksum);
354 }
355
356 PAKFIRE_EXPORT const char* pakfire_package_get_summary(PakfirePackage pkg) {
357 return pakfire_package_get_string(pkg, SOLVABLE_SUMMARY);
358 }
359
360 PAKFIRE_EXPORT void pakfire_package_set_summary(PakfirePackage pkg, const char* summary) {
361 pakfire_package_set_string(pkg, SOLVABLE_SUMMARY, summary);
362 }
363
364 PAKFIRE_EXPORT const char* pakfire_package_get_description(PakfirePackage pkg) {
365 return pakfire_package_get_string(pkg, SOLVABLE_DESCRIPTION);
366 }
367
368 PAKFIRE_EXPORT void pakfire_package_set_description(PakfirePackage pkg, const char* description) {
369 pakfire_package_set_string(pkg, SOLVABLE_DESCRIPTION, description);
370 }
371
372 PAKFIRE_EXPORT const char* pakfire_package_get_license(PakfirePackage pkg) {
373 return pakfire_package_get_string(pkg, SOLVABLE_LICENSE);
374 }
375
376 PAKFIRE_EXPORT void pakfire_package_set_license(PakfirePackage pkg, const char* license) {
377 pakfire_package_set_string(pkg, SOLVABLE_LICENSE, license);
378 }
379
380 PAKFIRE_EXPORT const char* pakfire_package_get_url(PakfirePackage pkg) {
381 return pakfire_package_get_string(pkg, SOLVABLE_URL);
382 }
383
384 PAKFIRE_EXPORT void pakfire_package_set_url(PakfirePackage pkg, const char* url) {
385 pakfire_package_set_string(pkg, SOLVABLE_URL, url);
386 }
387
388 #warning the groups functions need to be refactored
389
390 PAKFIRE_EXPORT const char** pakfire_package_get_groups(PakfirePackage pkg) {
391 const char* groups = pakfire_package_get_string(pkg, SOLVABLE_GROUP);
392
393 const char** grouplist = NULL;
394 char* group = strtok((char *)groups, " ");
395
396 int i = 0;
397 while (group != NULL) {
398 grouplist = realloc(grouplist, sizeof(char *) * ++i);
399 assert(grouplist);
400 grouplist[i - 1] = group;
401
402 group = strtok(NULL, " ");
403 }
404 grouplist[i] = NULL;
405
406 return grouplist;
407 }
408
409 PAKFIRE_EXPORT void pakfire_package_set_groups(PakfirePackage pkg, const char** grouplist) {
410 char groups[2048] = "";
411
412 if (grouplist) {
413 const char* group;
414 while ((group = *grouplist++) != NULL) {
415 if (groups[0])
416 strcat(groups, " ");
417
418 strcat(groups, group);
419 }
420 groups[sizeof(groups) - 1] = '\0';
421 } else
422 groups[0] = '\0';
423
424 pakfire_package_set_string(pkg, SOLVABLE_GROUP, (const char *)&groups);
425 }
426
427 PAKFIRE_EXPORT const char* pakfire_package_get_vendor(PakfirePackage pkg) {
428 return pakfire_package_get_string(pkg, SOLVABLE_VENDOR);
429 }
430
431 PAKFIRE_EXPORT void pakfire_package_set_vendor(PakfirePackage pkg, const char* vendor) {
432 pakfire_package_set_string(pkg, SOLVABLE_VENDOR, vendor);
433 }
434
435 PAKFIRE_EXPORT const char* pakfire_package_get_maintainer(PakfirePackage pkg) {
436 return pakfire_package_get_string(pkg, SOLVABLE_PACKAGER);
437 }
438
439 PAKFIRE_EXPORT void pakfire_package_set_maintainer(PakfirePackage pkg, const char* maintainer) {
440 pakfire_package_set_string(pkg, SOLVABLE_PACKAGER, maintainer);
441 }
442
443 PAKFIRE_EXPORT const char* pakfire_package_get_filename(PakfirePackage pkg) {
444 return pakfire_package_get_string(pkg, SOLVABLE_MEDIAFILE);
445 }
446
447 PAKFIRE_EXPORT void pakfire_package_set_filename(PakfirePackage pkg, const char* filename) {
448 pakfire_package_set_string(pkg, SOLVABLE_MEDIAFILE, filename);
449 }
450
451 PAKFIRE_EXPORT int pakfire_package_is_installed(PakfirePackage pkg) {
452 Pool* pool = pakfire_package_get_solv_pool(pkg);
453 Solvable* s = get_solvable(pkg);
454
455 return pool->installed == s->repo;
456 }
457
458 static unsigned long long pakfire_package_get_num(PakfirePackage pkg, Id type) {
459 pakfire_package_internalize_repo(pkg);
460
461 Solvable* s = get_solvable(pkg);
462 return solvable_lookup_num(s, type, 0);
463 }
464
465 static void pakfire_package_set_num(PakfirePackage pkg, Id type, unsigned long long value) {
466 Solvable* s = get_solvable(pkg);
467
468 solvable_set_num(s, type, value);
469 }
470
471 PAKFIRE_EXPORT unsigned long long pakfire_package_get_downloadsize(PakfirePackage pkg) {
472 return pakfire_package_get_num(pkg, SOLVABLE_DOWNLOADSIZE);
473 }
474
475 PAKFIRE_EXPORT void pakfire_package_set_downloadsize(PakfirePackage pkg, unsigned long long downloadsize) {
476 return pakfire_package_set_num(pkg, SOLVABLE_DOWNLOADSIZE, downloadsize);
477 }
478
479 PAKFIRE_EXPORT unsigned long long pakfire_package_get_installsize(PakfirePackage pkg) {
480 return pakfire_package_get_num(pkg, SOLVABLE_INSTALLSIZE);
481 }
482
483 PAKFIRE_EXPORT void pakfire_package_set_installsize(PakfirePackage pkg, unsigned long long installsize) {
484 return pakfire_package_set_num(pkg, SOLVABLE_INSTALLSIZE, installsize);
485 }
486
487 PAKFIRE_EXPORT unsigned long long pakfire_package_get_size(PakfirePackage pkg) {
488 if (pakfire_package_is_installed(pkg))
489 return pakfire_package_get_installsize(pkg);
490
491 return pakfire_package_get_downloadsize(pkg);
492 }
493
494 PAKFIRE_EXPORT const char* pakfire_package_get_buildhost(PakfirePackage pkg) {
495 return pakfire_package_get_string(pkg, SOLVABLE_BUILDHOST);
496 }
497
498 PAKFIRE_EXPORT void pakfire_package_set_buildhost(PakfirePackage pkg, const char* buildhost) {
499 pakfire_package_set_string(pkg, SOLVABLE_BUILDHOST, buildhost);
500 }
501
502 PAKFIRE_EXPORT unsigned long long pakfire_package_get_buildtime(PakfirePackage pkg) {
503 return pakfire_package_get_num(pkg, SOLVABLE_BUILDTIME);
504 }
505
506 PAKFIRE_EXPORT void pakfire_package_set_buildtime(PakfirePackage pkg, unsigned long long buildtime) {
507 pakfire_package_set_num(pkg, SOLVABLE_BUILDTIME, buildtime);
508 }
509
510 PAKFIRE_EXPORT unsigned long long pakfire_package_get_installtime(PakfirePackage pkg) {
511 return pakfire_package_get_num(pkg, SOLVABLE_INSTALLTIME);
512 }
513
514 static PakfireRelationList pakfire_package_get_relationlist(PakfirePackage pkg, Id type) {
515 Queue q;
516 queue_init(&q);
517
518 Solvable* s = get_solvable(pkg);
519 solvable_lookup_idarray(s, type, &q);
520
521 PakfireRelationList relationlist = pakfire_relationlist_from_queue(pkg->pakfire, q);
522 queue_free(&q);
523
524 return relationlist;
525 }
526
527 static void pakfire_package_set_relationlist(PakfirePackage pkg, Id type, PakfireRelationList relationlist) {
528 #if 0
529 // This implemention should be the fastest, but unfortunately does not work.
530 Queue q;
531 pakfire_relationlist_clone_to_queue(relationlist, &q);
532
533 Solvable* s = get_solvable(pkg);
534 solvable_set_idarray(s, type, &q);
535
536 queue_free(&q);
537 #endif
538
539 Solvable* s = get_solvable(pkg);
540 solvable_unset(s, type);
541
542 int count = pakfire_relationlist_count(relationlist);
543 for (int i = 0; i < count; i++) {
544 PakfireRelation relation = pakfire_relationlist_get_clone(relationlist, i);
545 solvable_add_idarray(s, type, pakfire_relation_get_id(relation));
546
547 pakfire_relation_unref(relation);
548 }
549 }
550
551 static void pakfire_package_add_relation(PakfirePackage pkg, Id type, PakfireRelation relation) {
552 Solvable* s = get_solvable(pkg);
553
554 solvable_add_idarray(s, type, pakfire_relation_get_id(relation));
555 }
556
557 PAKFIRE_EXPORT PakfireRelationList pakfire_package_get_provides(PakfirePackage pkg) {
558 return pakfire_package_get_relationlist(pkg, SOLVABLE_PROVIDES);
559 }
560
561 PAKFIRE_EXPORT void pakfire_package_set_provides(PakfirePackage pkg, PakfireRelationList relationlist) {
562 pakfire_package_set_relationlist(pkg, SOLVABLE_PROVIDES, relationlist);
563 }
564
565 PAKFIRE_EXPORT void pakfire_package_add_provides(PakfirePackage pkg, PakfireRelation relation) {
566 pakfire_package_add_relation(pkg, SOLVABLE_PROVIDES, relation);
567 }
568
569 PAKFIRE_EXPORT PakfireRelationList pakfire_package_get_prerequires(PakfirePackage pkg) {
570 #warning TODO
571 return NULL;
572 }
573
574 PAKFIRE_EXPORT PakfireRelationList pakfire_package_get_requires(PakfirePackage pkg) {
575 return pakfire_package_get_relationlist(pkg, SOLVABLE_REQUIRES);
576 }
577
578 PAKFIRE_EXPORT void pakfire_package_set_requires(PakfirePackage pkg, PakfireRelationList relationlist) {
579 pakfire_package_set_relationlist(pkg, SOLVABLE_REQUIRES, relationlist);
580 }
581
582 PAKFIRE_EXPORT void pakfire_package_add_requires(PakfirePackage pkg, PakfireRelation relation) {
583 pakfire_package_add_relation(pkg, SOLVABLE_REQUIRES, relation);
584 }
585
586 PAKFIRE_EXPORT PakfireRelationList pakfire_package_get_conflicts(PakfirePackage pkg) {
587 return pakfire_package_get_relationlist(pkg, SOLVABLE_CONFLICTS);
588 }
589
590 PAKFIRE_EXPORT void pakfire_package_set_conflicts(PakfirePackage pkg, PakfireRelationList relationlist) {
591 pakfire_package_set_relationlist(pkg, SOLVABLE_CONFLICTS, relationlist);
592 }
593
594 PAKFIRE_EXPORT void pakfire_package_add_conflicts(PakfirePackage pkg, PakfireRelation relation) {
595 pakfire_package_add_relation(pkg, SOLVABLE_CONFLICTS, relation);
596 }
597
598 PAKFIRE_EXPORT PakfireRelationList pakfire_package_get_obsoletes(PakfirePackage pkg) {
599 return pakfire_package_get_relationlist(pkg, SOLVABLE_OBSOLETES);
600 }
601
602 PAKFIRE_EXPORT void pakfire_package_set_obsoletes(PakfirePackage pkg, PakfireRelationList relationlist) {
603 pakfire_package_set_relationlist(pkg, SOLVABLE_OBSOLETES, relationlist);
604 }
605
606 PAKFIRE_EXPORT void pakfire_package_add_obsoletes(PakfirePackage pkg, PakfireRelation relation) {
607 pakfire_package_add_relation(pkg, SOLVABLE_OBSOLETES, relation);
608 }
609
610 PAKFIRE_EXPORT PakfireRelationList pakfire_package_get_recommends(PakfirePackage pkg) {
611 return pakfire_package_get_relationlist(pkg, SOLVABLE_RECOMMENDS);
612 }
613
614 PAKFIRE_EXPORT void pakfire_package_set_recommends(PakfirePackage pkg, PakfireRelationList relationlist) {
615 pakfire_package_set_relationlist(pkg, SOLVABLE_RECOMMENDS, relationlist);
616 }
617
618 PAKFIRE_EXPORT void pakfire_package_add_recommends(PakfirePackage pkg, PakfireRelation relation) {
619 pakfire_package_add_relation(pkg, SOLVABLE_RECOMMENDS, relation);
620 }
621
622 PAKFIRE_EXPORT PakfireRelationList pakfire_package_get_suggests(PakfirePackage pkg) {
623 return pakfire_package_get_relationlist(pkg, SOLVABLE_SUGGESTS);
624 }
625
626 PAKFIRE_EXPORT void pakfire_package_set_suggests(PakfirePackage pkg, PakfireRelationList relationlist) {
627 pakfire_package_set_relationlist(pkg, SOLVABLE_SUGGESTS, relationlist);
628 }
629
630 PAKFIRE_EXPORT void pakfire_package_add_suggests(PakfirePackage pkg, PakfireRelation relation) {
631 pakfire_package_add_relation(pkg, SOLVABLE_SUGGESTS, relation);
632 }
633
634 PAKFIRE_EXPORT PakfireRepo pakfire_package_get_repo(PakfirePackage pkg) {
635 Solvable* s = get_solvable(pkg);
636
637 return pakfire_repo_create_from_repo(pkg->pakfire, s->repo);
638 }
639
640 PAKFIRE_EXPORT void pakfire_package_set_repo(PakfirePackage pkg, PakfireRepo repo) {
641 Solvable* s = get_solvable(pkg);
642
643 s->repo = pakfire_repo_get_repo(repo);
644 }
645
646 PAKFIRE_EXPORT char* pakfire_package_get_location(PakfirePackage pkg) {
647 pakfire_package_internalize_repo(pkg);
648
649 Solvable* s = get_solvable(pkg);
650
651 const char* location = solvable_get_location(s, NULL);
652 return pakfire_strdup(location);
653 }
654
655 static void pakfire_package_dump_add_line(char** str, const char* key, const char* val) {
656 if (val)
657 asprintf(str, "%s%-15s: %s\n", *str, key ? key : "", val);
658 }
659
660 static void pakfire_package_dump_add_lines(char** str, const char* key, const char* val) {
661 const char* string = val;
662
663 while (*string) {
664 char line[STRING_SIZE];
665 int counter = 0;
666
667 while (*string) {
668 if (*string == '\n') {
669 string++;
670 break;
671 }
672
673 line[counter++] = *string++;
674 }
675 line[counter] = '\0';
676
677 if (*line) {
678 pakfire_package_dump_add_line(str, key, line);
679 key = NULL;
680 }
681 }
682 }
683
684 static void pakfire_package_dump_add_line_date(char** str, const char* key, unsigned long long date) {
685 // Convert from integer to tm struct.
686 struct tm* timer = gmtime((time_t *)&date);
687
688 char val[STRING_SIZE];
689 strftime(val, STRING_SIZE, "%a, %d %b %Y %T %z", timer);
690
691 pakfire_package_dump_add_line(str, key, val);
692 }
693
694 static void pakfire_package_dump_add_line_relations(char** str, const char* key, PakfireRelationList deps) {
695 int count = pakfire_relationlist_count(deps);
696 for (int i = 0; i < count; i++) {
697 PakfireRelation relation = pakfire_relationlist_get_clone(deps, i);
698
699 if (relation) {
700 char* dep = pakfire_relation_str(relation);
701 pakfire_relation_unref(relation);
702
703 // Stop here and don't list any files.
704 if (strcmp(PAKFIRE_SOLVABLE_FILEMARKER, dep) == 0)
705 break;
706
707 if (dep) {
708 pakfire_package_dump_add_line(str, (i == 0) ? key : "", dep);
709 pakfire_free(dep);
710 }
711 }
712 }
713 }
714
715 static void pakfire_package_dump_add_line_size(char** str, const char* key, unsigned long long size) {
716 char* val = pakfire_format_size(size);
717
718 if (val) {
719 pakfire_package_dump_add_line(str, key, val);
720 pakfire_free(val);
721 }
722 }
723
724 PAKFIRE_EXPORT char* pakfire_package_dump(PakfirePackage pkg, int flags) {
725 char* string = "";
726
727 // Name
728 const char* name = pakfire_package_get_name(pkg);
729 pakfire_package_dump_add_line(&string, _("Name"), name);
730
731 // Version
732 const char* version = pakfire_package_get_version(pkg);
733 pakfire_package_dump_add_line(&string, _("Version"), version);
734
735 // Release
736 const char* release = pakfire_package_get_release(pkg);
737 pakfire_package_dump_add_line(&string, _("Release"), release);
738
739 // Size
740 unsigned long long size = pakfire_package_get_size(pkg);
741 pakfire_package_dump_add_line_size(&string, _("Size"), size);
742
743 // Installed size
744 if (pakfire_package_is_installed(pkg)) {
745 unsigned long long installsize = pakfire_package_get_installsize(pkg);
746 pakfire_package_dump_add_line_size(&string, _("Installed size"), installsize);
747
748 // Downloadsize
749 } else {
750 unsigned long long downloadsize = pakfire_package_get_downloadsize(pkg);
751 pakfire_package_dump_add_line_size(&string, _("Download size"), downloadsize);
752 }
753
754 PakfireRepo repo = pakfire_package_get_repo(pkg);
755 if (repo) {
756 const char* repo_name = pakfire_repo_get_name(repo);
757 pakfire_package_dump_add_line(&string, _("Repo"), repo_name);
758
759 pakfire_repo_unref(repo);
760 }
761
762 // Summary
763 const char* summary = pakfire_package_get_summary(pkg);
764 pakfire_package_dump_add_line(&string, _("Summary"), summary);
765
766 // Description
767 const char* description = pakfire_package_get_description(pkg);
768 pakfire_package_dump_add_lines(&string, _("Description"), description);
769
770 // Groups
771 #warning TODO groups
772
773 // URL
774 const char* url = pakfire_package_get_url(pkg);
775 pakfire_package_dump_add_line(&string, _("URL"), url);
776
777 // License
778 const char* license = pakfire_package_get_license(pkg);
779 pakfire_package_dump_add_line(&string, _("License"), license);
780
781 if (flags & PAKFIRE_PKG_DUMP_LONG) {
782 // Maintainer
783 const char* maintainer = pakfire_package_get_maintainer(pkg);
784 pakfire_package_dump_add_line(&string, _("Maintainer"), maintainer);
785
786 // Vendor
787 const char* vendor = pakfire_package_get_vendor(pkg);
788 pakfire_package_dump_add_line(&string, _("Vendor"), vendor);
789
790 // UUID
791 const char* uuid = pakfire_package_get_uuid(pkg);
792 pakfire_package_dump_add_line(&string, _("UUID"), uuid);
793
794 // Build time
795 unsigned long long buildtime = pakfire_package_get_buildtime(pkg);
796 pakfire_package_dump_add_line_date(&string, _("Build date"), buildtime);
797
798 // Build host
799 const char* buildhost = pakfire_package_get_buildhost(pkg);
800 pakfire_package_dump_add_line(&string, _("Build host"), buildhost);
801
802 PakfireRelationList provides = pakfire_package_get_provides(pkg);
803 if (provides) {
804 pakfire_package_dump_add_line_relations(&string, _("Provides"), provides);
805 pakfire_relationlist_unref(provides);
806 }
807
808 PakfireRelationList requires = pakfire_package_get_requires(pkg);
809 if (requires) {
810 pakfire_package_dump_add_line_relations(&string, _("Requires"), requires);
811 pakfire_relationlist_unref(requires);
812 }
813
814 PakfireRelationList conflicts = pakfire_package_get_conflicts(pkg);
815 if (conflicts) {
816 pakfire_package_dump_add_line_relations(&string, _("Conflicts"), conflicts);
817 pakfire_relationlist_unref(conflicts);
818 }
819
820 PakfireRelationList obsoletes = pakfire_package_get_obsoletes(pkg);
821 if (obsoletes) {
822 pakfire_package_dump_add_line_relations(&string, _("Obsoletes"), obsoletes);
823 pakfire_relationlist_unref(obsoletes);
824 }
825
826 PakfireRelationList recommends = pakfire_package_get_recommends(pkg);
827 if (recommends) {
828 pakfire_package_dump_add_line_relations(&string, _("Recommends"), recommends);
829 pakfire_relationlist_unref(recommends);
830 }
831
832 PakfireRelationList suggests = pakfire_package_get_suggests(pkg);
833 if (suggests) {
834 pakfire_package_dump_add_line_relations(&string, _("Suggests"), suggests);
835 pakfire_relationlist_unref(suggests);
836 }
837 }
838
839 if (flags & PAKFIRE_PKG_DUMP_FILELIST) {
840 PakfireFile file = pakfire_package_get_filelist(pkg);
841
842 char* prefix = _("Filelist");
843 while (file) {
844 const char* name = pakfire_file_get_name(file);
845 pakfire_package_dump_add_line(&string, prefix, name);
846
847 file = pakfire_file_get_next(file);
848
849 // Only prefix the first line.
850 prefix = NULL;
851 }
852 }
853
854 return string;
855 }
856
857 PAKFIRE_EXPORT int pakfire_package_is_cached(PakfirePackage pkg) {
858 char* path = pakfire_package_get_cache_path(pkg);
859
860 // Check if the file is readable
861 int r = pakfire_access(path, NULL, R_OK);
862 pakfire_free(path);
863
864 return r;
865 }
866
867 PAKFIRE_EXPORT char* pakfire_package_get_cache_path(PakfirePackage pkg) {
868 char buffer[STRING_SIZE] = "";
869
870 const char* filename = pakfire_package_get_filename(pkg);
871 const char* checksum = pakfire_package_get_checksum(pkg);
872
873 if (strlen(checksum) < 3)
874 return NULL;
875
876 snprintf(buffer, sizeof(buffer), "%c%c/%s/%s", checksum[0], checksum[1],
877 checksum + 2, filename);
878
879 return pakfire_get_cache_path(pkg->pakfire, buffer);
880 }
881
882 PAKFIRE_EXPORT PakfireArchive pakfire_package_get_archive(PakfirePackage pkg) {
883 // Return the package if it has already been opened
884 if (pkg->archive)
885 return pakfire_archive_ref(pkg->archive);
886
887 // Otherwise open the archive from the cache
888 char* path = pakfire_package_get_cache_path(pkg);
889 PakfireArchive archive = pakfire_archive_open(pkg->pakfire, path);
890
891 // Free resources
892 pakfire_free(path);
893
894 return archive;
895 }
896
897 static PakfireFile pakfire_package_fetch_legacy_filelist(PakfirePackage pkg) {
898 pakfire_package_internalize_repo(pkg);
899
900 PakfireFile file = NULL;
901 PakfireRepo repo = pakfire_package_get_repo(pkg);
902 Solvable* s = get_solvable(pkg);
903 Pool* p = pakfire_package_get_solv_pool(pkg);
904 Repo* r = pakfire_repo_get_repo(repo);
905
906 int found_marker = 0;
907
908 Id id, *ids;
909 ids = r->idarraydata + s->provides;
910 while((id = *ids++) != 0) {
911 const char* filename = pool_dep2str(p, id);
912
913 if (found_marker) {
914 if (file) {
915 file = pakfire_file_append(file);
916 } else {
917 file = pakfire_file_create();
918 }
919
920 pakfire_file_set_name(file, filename);
921 continue;
922 }
923
924 if (strcmp(filename, PAKFIRE_SOLVABLE_FILEMARKER) == 0)
925 ++found_marker;
926 }
927
928 if (file) {
929 file = pakfire_file_get_first(file);
930
931 // Sort the output
932 file = pakfire_file_sort(file);
933 }
934
935 pakfire_repo_unref(repo);
936
937 return file;
938 }
939
940 static PakfireFile pakfire_package_fetch_filelist(PakfirePackage pkg) {
941 pakfire_package_internalize_repo(pkg);
942
943 PakfireFile file = NULL;
944 Pool* pool = pakfire_package_get_solv_pool(pkg);
945 Repo* repo = pakfire_package_solv_repo(pkg);
946 Id handle = pakfire_package_get_handle(pkg);
947
948 Dataiterator di;
949 dataiterator_init(&di, pool, repo, handle,
950 SOLVABLE_FILELIST, NULL, SEARCH_FILES | SEARCH_COMPLETE_FILELIST);
951 while (dataiterator_step(&di)) {
952 if (file) {
953 file = pakfire_file_append(file);
954 } else {
955 file = pakfire_file_create();
956 }
957
958 pakfire_file_set_name(file, di.kv.str);
959 }
960 dataiterator_free(&di);
961
962 if (file) {
963 file = pakfire_file_get_first(file);
964
965 // Sort the result.
966 file = pakfire_file_sort(file);
967 }
968
969 // If the file list is empty, we fall back to read files
970 // in the older format.
971 if (!file)
972 file = pakfire_package_fetch_legacy_filelist(pkg);
973
974 return file;
975 }
976
977 PAKFIRE_EXPORT PakfireFile pakfire_package_get_filelist(PakfirePackage pkg) {
978 if (!pkg->filelist) {
979 pkg->filelist = pakfire_package_fetch_filelist(pkg);
980 }
981
982 return pkg->filelist;
983 }
984
985 PAKFIRE_EXPORT PakfireFile pakfire_package_filelist_append(PakfirePackage pkg, const char* filename) {
986 PakfireRepo repo = pakfire_package_get_repo(pkg);
987 Repodata* repodata = pakfire_repo_get_repodata(repo);
988
989 Id handle = pakfire_package_get_handle(pkg);
990
991 char* dirname = pakfire_dirname(filename);
992 char* basename = pakfire_basename(filename);
993
994 Id did = repodata_str2dir(repodata, dirname, 1);
995 if (!did)
996 did = repodata_str2dir(repodata, "/", 1);
997
998 repodata_add_dirstr(repodata, handle,
999 SOLVABLE_FILELIST, did, basename);
1000
1001 pakfire_repo_unref(repo);
1002
1003 return NULL;
1004 }
1005
1006 #if 0
1007 PakfireFile pakfire_package_filelist_append(PakfirePackage pkg) {
1008 if (pkg->filelist) {
1009 return pakfire_file_append(pkg->filelist);
1010 }
1011
1012 PakfireFile file = pakfire_file_create();
1013 pkg->filelist = file;
1014
1015 return file;
1016 }
1017 #endif
1018
1019 PAKFIRE_EXPORT void pakfire_package_filelist_remove(PakfirePackage pkg) {
1020 if (pkg->filelist)
1021 pakfire_file_free_all(pkg->filelist);
1022 }