]> git.ipfire.org Git - people/ms/pakfire.git/blame - src/libpakfire/packager.c
python: Drop performance_index function
[people/ms/pakfire.git] / src / libpakfire / packager.c
CommitLineData
6aeb48e6
MT
1/*#############################################################################
2# #
3# Pakfire - The IPFire package management system #
4# Copyright (C) 2021 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 <errno.h>
1ea1f35b
MT
22#include <fcntl.h>
23#include <linux/limits.h>
6aeb48e6 24#include <stdlib.h>
da08f989
MT
25#include <sys/stat.h>
26#include <sys/types.h>
05cfc2c9 27#include <time.h>
da08f989 28#include <unistd.h>
6aeb48e6 29
1ea1f35b 30#include <archive.h>
da08f989 31#include <archive_entry.h>
1ea1f35b 32
b59c9fa2
MT
33#include <json.h>
34
2adc4a4a 35#include <pakfire/archive.h>
6bf9841b 36#include <pakfire/compress.h>
436677a3 37#include <pakfire/constants.h>
1ea1f35b 38#include <pakfire/logging.h>
6aeb48e6
MT
39#include <pakfire/package.h>
40#include <pakfire/packager.h>
41#include <pakfire/pakfire.h>
677e9e5b 42#include <pakfire/pwd.h>
d973a13d 43#include <pakfire/string.h>
f57ad279 44#include <pakfire/util.h>
6aeb48e6
MT
45
46struct pakfire_packager {
ac4c607b 47 struct pakfire* pakfire;
6aeb48e6 48 int nrefs;
05cfc2c9 49 time_t time_created;
6aeb48e6 50
31480bee 51 struct pakfire_package* pkg;
bb06d548 52 char filename[PATH_MAX];
1ea1f35b 53
738b3582
MT
54 // Reader
55 struct archive* reader;
56
57 // Payload
6bf9841b 58 struct pakfire_filelist* filelist;
106d2edd 59
9ca45f4f 60 // Scriptlets
106d2edd
MT
61 struct pakfire_scriptlet** scriptlets;
62 unsigned int num_scriptlets;
9ca45f4f
MT
63
64 // Digests
65 unsigned int digests;
6aeb48e6
MT
66};
67
1ea1f35b 68static void pakfire_packager_free(struct pakfire_packager* packager) {
106d2edd
MT
69 // Scriptlets
70 if (packager->scriptlets) {
71 for (unsigned int i = 0; i < packager->num_scriptlets; i++)
9dd7b1aa 72 pakfire_scriptlet_unref(packager->scriptlets[i]);
106d2edd
MT
73 free(packager->scriptlets);
74 }
75
738b3582 76 if (packager->reader)
66817062 77 archive_read_free(packager->reader);
738b3582 78
6bf9841b
MT
79 if (packager->filelist)
80 pakfire_filelist_unref(packager->filelist);
1ea1f35b
MT
81 pakfire_package_unref(packager->pkg);
82 pakfire_unref(packager->pakfire);
51105783 83 free(packager);
1ea1f35b
MT
84}
85
22b8e37b 86int pakfire_packager_create(struct pakfire_packager** packager,
5d7a93ec 87 struct pakfire* pakfire, struct pakfire_package* pkg) {
6aeb48e6
MT
88 struct pakfire_packager* p = calloc(1, sizeof(*p));
89 if (!p)
90 return ENOMEM;
91
e282863a
MT
92 int r = 1;
93
05cfc2c9
MT
94 // Save creation time
95 p->time_created = time(NULL);
96
6aeb48e6
MT
97 // Initialize reference counting
98 p->nrefs = 1;
99
100 // Store a reference to Pakfire
5d7a93ec 101 p->pakfire = pakfire_ref(pakfire);
6aeb48e6
MT
102
103 // Store a reference to the package
104 p->pkg = pakfire_package_ref(pkg);
105
9ca45f4f
MT
106 // Use the default digests
107 p->digests = PAKFIRE_PACKAGER_DIGESTS;
108
cb9b4eba
MT
109 // Set distribution
110 const char* tag = pakfire_get_distro_tag(p->pakfire);
111 if (!tag) {
112 ERROR(p->pakfire, "Distribution tag is not configured: %m\n");
113 goto ERROR;
114 }
115
74468e4f 116 pakfire_package_set_string(pkg, PAKFIRE_PKG_DISTRO, tag);
cb9b4eba 117
cd2c2cfb 118 // Set build host
1f669e88 119 pakfire_package_set_string(pkg, PAKFIRE_PKG_BUILD_HOST, pakfire_hostname());
cd2c2cfb
MT
120
121 // Set build time
3f327c3c 122 pakfire_package_set_num(pkg, PAKFIRE_PKG_BUILD_TIME, p->time_created);
cd2c2cfb 123
0682aeb3 124 // Create reader
66817062
MT
125 p->reader = pakfire_make_archive_disk_reader(p->pakfire, 1);
126 if (!p->reader)
1ba1869e 127 goto ERROR;
1ea1f35b 128
6bf9841b
MT
129 // Create filelist
130 r = pakfire_filelist_create(&p->filelist, p->pakfire);
0682aeb3 131 if (r)
738b3582 132 goto ERROR;
738b3582 133
6bf9841b 134 // Add a requirement for the cryptographic algorithms we are using
6f3fad3b
MT
135 if (p->digests & PAKFIRE_DIGEST_SHA3_512) {
136 r = pakfire_package_add_dep(p->pkg,
137 PAKFIRE_PKG_REQUIRES, "pakfire(Digest-SHA3-512)");
138 if (r)
139 goto ERROR;
140 }
141 if (p->digests & PAKFIRE_DIGEST_SHA3_256) {
142 r = pakfire_package_add_dep(p->pkg,
143 PAKFIRE_PKG_REQUIRES, "pakfire(Digest-SHA3-256)");
144 if (r)
145 goto ERROR;
146 }
147 if (p->digests & PAKFIRE_DIGEST_BLAKE2B512) {
148 r = pakfire_package_add_dep(p->pkg,
149 PAKFIRE_PKG_REQUIRES, "pakfire(Digest-BLAKE2b512)");
150 if (r)
151 goto ERROR;
152 }
153 if (p->digests & PAKFIRE_DIGEST_BLAKE2S256) {
154 r = pakfire_package_add_dep(p->pkg,
155 PAKFIRE_PKG_REQUIRES, "pakfire(Digest-BLAKE2s256)");
156 if (r)
157 goto ERROR;
158 }
159 if (p->digests & PAKFIRE_DIGEST_SHA2_512) {
160 r = pakfire_package_add_dep(p->pkg,
161 PAKFIRE_PKG_REQUIRES, "pakfire(Digest-SHA2-512)");
162 if (r)
163 goto ERROR;
164 }
165 if (p->digests & PAKFIRE_DIGEST_SHA2_256) {
166 r = pakfire_package_add_dep(p->pkg,
167 PAKFIRE_PKG_REQUIRES, "pakfire(Digest-SHA2-256)");
168 if (r)
169 goto ERROR;
170 }
6bf9841b 171
6aeb48e6
MT
172 *packager = p;
173
174 return 0;
1ba1869e
MT
175
176ERROR:
177 pakfire_packager_free(p);
178
179 return r;
6aeb48e6
MT
180}
181
22b8e37b 182struct pakfire_packager* pakfire_packager_ref(
6aeb48e6
MT
183 struct pakfire_packager* packager) {
184 ++packager->nrefs;
185
186 return packager;
187}
188
22b8e37b 189struct pakfire_packager* pakfire_packager_unref(
6aeb48e6
MT
190 struct pakfire_packager* packager) {
191 if (--packager->nrefs > 0)
192 return packager;
193
194 pakfire_packager_free(packager);
6aeb48e6
MT
195 return NULL;
196}
da08f989 197
22b8e37b 198const char* pakfire_packager_filename(struct pakfire_packager* packager) {
bb06d548 199 if (!*packager->filename) {
0aade652 200 const char* filename = pakfire_package_get_string(packager->pkg, PAKFIRE_PKG_FILENAME);
bb06d548
MT
201
202 // Add arch
203 if (pakfire_package_is_source(packager->pkg))
204 pakfire_string_set(packager->filename, filename);
205 else {
74468e4f 206 const char* arch = pakfire_package_get_string(packager->pkg, PAKFIRE_PKG_ARCH);
bb06d548
MT
207
208 pakfire_string_format(packager->filename, "%s/%s", arch, filename);
209 }
210 }
211
212 return packager->filename;
96d2c7bc
MT
213}
214
28700a5b 215static struct archive_entry* pakfire_packager_create_file(
95b81a98 216 struct pakfire_packager* packager, const char* filename, size_t size, mode_t mode) {
98e85f1c
MT
217 // Create a new file entry
218 struct archive_entry* entry = archive_entry_new();
219 if (!entry)
28700a5b 220 return NULL;
98e85f1c
MT
221
222 // Set filename
223 archive_entry_set_pathname(entry, filename);
224
225 // This is a regular file
226 archive_entry_set_filetype(entry, AE_IFREG);
95b81a98 227 archive_entry_set_perm(entry, mode);
98e85f1c 228
28700a5b
MT
229 // Set size
230 archive_entry_set_size(entry, size);
231
05cfc2c9
MT
232 // Set ownership
233 archive_entry_set_uname(entry, "root");
234 archive_entry_set_uid(entry, 0);
235 archive_entry_set_gname(entry, "root");
236 archive_entry_set_gid(entry, 0);
237
238 // Set times
239 archive_entry_set_birthtime(entry, packager->time_created, 0);
240 archive_entry_set_ctime(entry, packager->time_created, 0);
241 archive_entry_set_mtime(entry, packager->time_created, 0);
242 archive_entry_set_atime(entry, packager->time_created, 0);
243
28700a5b
MT
244 return entry;
245}
246
247static int pakfire_packager_write_file_from_buffer(struct pakfire_packager* packager,
bfdad796 248 struct archive* a, const char* filename, mode_t mode, const char* buffer) {
28700a5b
MT
249 size_t size = strlen(buffer);
250
251 // Create a new file
7e346194
MT
252 struct archive_entry* entry = pakfire_packager_create_file(packager, filename, size, mode);
253 if (!entry) {
254 ERROR(packager->pakfire, "Could not create file '%s'\n", filename);
28700a5b 255 return 1;
7e346194 256 }
98e85f1c
MT
257
258 // This is the end of the header
259 int r = archive_write_header(a, entry);
260 if (r) {
261 ERROR(packager->pakfire, "Error writing header: %s\n", archive_error_string(a));
265a7974 262 goto ERROR;
98e85f1c
MT
263 }
264
265 // Write content
266 r = archive_write_data(a, buffer, strlen(buffer));
267 if (r < 0) {
268 ERROR(packager->pakfire, "Error writing data: %s\n", archive_error_string(a));
265a7974 269 goto ERROR;
98e85f1c
MT
270 }
271
265a7974
MT
272 // Success
273 r = 0;
274
275ERROR:
98e85f1c
MT
276 archive_entry_free(entry);
277
265a7974 278 return r;
98e85f1c
MT
279}
280
436677a3
MT
281static int pakfire_packager_write_format(struct pakfire_packager* packager,
282 struct archive* a) {
283 const char buffer[] = TO_STRING(PACKAGE_FORMAT) "\n";
284
7e346194
MT
285 DEBUG(packager->pakfire, "Writing package format\n");
286
bfdad796 287 int r = pakfire_packager_write_file_from_buffer(packager, a,
0dbfb5e1 288 "pakfire-format", 0444, buffer);
a6dd151e
MT
289 if (r)
290 return r;
291
292 // Add package format marker
6f3fad3b 293 r = pakfire_package_add_dep(packager->pkg, PAKFIRE_PKG_REQUIRES,
a6dd151e 294 "pakfire(PackageFormat-" TO_STRING(PACKAGE_FORMAT) ")");
6f3fad3b
MT
295 if (r)
296 return r;
a6dd151e
MT
297
298 return 0;
436677a3
MT
299}
300
b59c9fa2
MT
301static char* pakfire_packager_make_metadata(struct pakfire_packager* packager) {
302 char* result = NULL;
98e85f1c 303
b59c9fa2
MT
304 // Convert all package metadata to JSON
305 struct json_object* md = pakfire_package_to_json(packager->pkg);
306 if (!md)
98e85f1c
MT
307 goto ERROR;
308
b59c9fa2 309 // Serialize JSON to file
ef4a2e77 310 const char* s = json_object_to_json_string_ext(md, 0);
b59c9fa2 311 if (!s)
98e85f1c
MT
312 goto ERROR;
313
b59c9fa2
MT
314 // Copy result onto heap
315 result = strdup(s);
316 if (!result)
98e85f1c 317 goto ERROR;
98e85f1c
MT
318
319ERROR:
b59c9fa2
MT
320 // Free metadata
321 if (md)
322 json_object_put(md);
98e85f1c 323
b59c9fa2 324 return result;
98e85f1c
MT
325}
326
327static int pakfire_packager_write_metadata(struct pakfire_packager* packager,
bfdad796 328 struct archive* a) {
98e85f1c 329 // Make metadata
b59c9fa2 330 char* buffer = pakfire_packager_make_metadata(packager);
98e85f1c
MT
331 if (!buffer)
332 return 1;
333
b59c9fa2 334 DEBUG(packager->pakfire, "Generated package metadata:\n%s\n", buffer);
98e85f1c
MT
335
336 // Write buffer
bfdad796 337 int r = pakfire_packager_write_file_from_buffer(packager, a,
9f6b177b 338 ".PKGINFO", 0444, buffer);
98e85f1c
MT
339
340 free(buffer);
341
342 return r;
343}
344
106d2edd 345static int pakfire_packager_write_scriptlet(struct pakfire_packager* packager,
bfdad796 346 struct archive* a, struct pakfire_scriptlet* scriptlet) {
106d2edd
MT
347 char filename[PATH_MAX];
348 size_t size;
349 int r;
350
351 // Fetch type
352 const char* type = pakfire_scriptlet_get_type(scriptlet);
353
354 DEBUG(packager->pakfire, "Writing scriptlet '%s' to package\n", type);
355
356 // Make filename
9f6b177b 357 r = pakfire_string_format(filename, ".scriptlets/%s", type);
a60955af 358 if (r)
106d2edd
MT
359 return r;
360
361 // Fetch scriptlet
362 const char* data = pakfire_scriptlet_get_data(scriptlet, &size);
363
364 // Write file
bfdad796 365 return pakfire_packager_write_file_from_buffer(packager, a, filename, 0544, data);
106d2edd
MT
366}
367
436677a3
MT
368/*
369 This function is being called at the end when all data has been added to the package.
370
371 It will create a new archive and write the package to the given file descriptor.
372*/
22b8e37b 373int pakfire_packager_finish(struct pakfire_packager* packager, FILE* f) {
1b4e7c7b 374 struct archive* a = NULL;
a3151996 375 const char* comp_level = NULL;
96d2c7bc 376 int r = 1;
436677a3 377
74468e4f 378 const char* nevra = pakfire_package_get_string(packager->pkg, PAKFIRE_PKG_NEVRA);
1b4e7c7b 379
555b6dd2 380 // Add requires feature markers
6f3fad3b
MT
381 if (pakfire_package_has_rich_deps(packager->pkg)) {
382 r = pakfire_package_add_dep(packager->pkg,
383 PAKFIRE_PKG_REQUIRES, "pakfire(RichDependencies)");
384 if (r)
385 goto ERROR;
386 }
555b6dd2 387
9cfb8bb8
MT
388#ifdef ENABLE_DEBUG
389 DEBUG(packager->pakfire, "Filelist:\n");
390
391 // Dump filelist
392 r = pakfire_filelist_dump(packager->filelist, 1);
393 if (r)
394 goto ERROR;
395#endif
396
260006f2
MT
397 // Add filelist
398 r = pakfire_package_set_filelist(packager->pkg, packager->filelist);
399 if (r)
400 goto ERROR;
401
6bf9841b
MT
402 const size_t installsize = pakfire_filelist_total_size(packager->filelist);
403
508e2030 404 // Store total install size
3f327c3c
MT
405 r = pakfire_package_set_num(packager->pkg, PAKFIRE_PKG_INSTALLSIZE, installsize);
406 if (r)
407 goto ERROR;
fafe383d 408
436677a3 409 // Open a new archive
1b4e7c7b 410 a = archive_write_new();
436677a3
MT
411 if (!a) {
412 ERROR(packager->pakfire, "archive_write_new() failed\n");
260006f2 413 r = 1;
436677a3
MT
414 goto ERROR;
415 }
416
417 // Use the PAX format
96d2c7bc 418 r = archive_write_set_format_pax(a);
436677a3
MT
419 if (r) {
420 ERROR(packager->pakfire, "Could not set format to PAX: %s\n",
421 archive_error_string(a));
422 goto ERROR;
423 }
424
63476763
MT
425 // Store any extended attributes in the SCHILY headers
426 r = archive_write_set_format_option(a, "pax", "xattrheader", "SCHILY");
427 if (r) {
428 ERROR(packager->pakfire, "Could not set xattrheader option: %s\n",
429 archive_error_string(a));
430 return r;
431 }
432
433 // Enable Zstd
434 r = archive_write_add_filter_zstd(a);
435 if (r) {
436 ERROR(packager->pakfire, "Could not enable Zstandard compression: %s\n",
437 archive_error_string(a));
438 return r;
439 }
440
a3151996
MT
441 // Select compression level
442 if (pakfire_package_is_source(packager->pkg))
443 comp_level = "1";
444 else
445 comp_level = "22";
446
63476763 447 // Set compression level to highest
a3151996 448 r = archive_write_set_filter_option(a, NULL, "compression-level", comp_level);
63476763
MT
449 if (r) {
450 ERROR(packager->pakfire, "Could not set Zstandard compression level: %s\n",
451 archive_error_string(a));
452 return r;
453 }
454
455 // Add feature marker
6f3fad3b
MT
456 pakfire_package_add_dep(packager->pkg,
457 PAKFIRE_PKG_REQUIRES, "pakfire(Compress-Zstandard)");
63476763
MT
458
459 // Do not pad the last block
460 archive_write_set_bytes_in_last_block(a, 1);
461
436677a3
MT
462 // Write archive to f
463 r = archive_write_open_FILE(a, f);
464 if (r) {
465 ERROR(packager->pakfire, "archive_write_open_FILE() failed: %s\n",
466 archive_error_string(a));
467 goto ERROR;
468 }
469
470 // Start with the format file
471 r = pakfire_packager_write_format(packager, a);
265a7974
MT
472 if (r) {
473 ERROR(packager->pakfire, "Could not add format file to archive: %s\n",
474 archive_error_string(a));
436677a3 475 goto ERROR;
265a7974 476 }
436677a3 477
98e85f1c 478 // Write the metadata
bfdad796 479 r = pakfire_packager_write_metadata(packager, a);
265a7974
MT
480 if (r) {
481 ERROR(packager->pakfire, "Could not add metadata file to archive: %s\n",
482 archive_error_string(a));
98e85f1c 483 goto ERROR;
265a7974 484 }
98e85f1c 485
d8856104
MT
486 // Write scriptlets
487 for (unsigned int i = 0; i < packager->num_scriptlets; i++) {
488 r = pakfire_packager_write_scriptlet(packager, a, packager->scriptlets[i]);
489 if (r) {
490 ERROR(packager->pakfire, "Could not add scriptlet to the archive: %m\n");
491 goto ERROR;
492 }
493 }
494
bfdad796 495 // Write the payload
6bf9841b
MT
496 r = pakfire_compress(packager->pakfire, a, packager->filelist, nevra,
497 PAKFIRE_COMPRESS_SHOW_THROUGHPUT, PAKFIRE_PACKAGER_DIGESTS);
131c1449
MT
498 if (r)
499 goto ERROR;
265a7974 500
2013270b
MT
501 // Flush all buffers to disk
502 fflush(f);
503
96d2c7bc
MT
504 // Success
505 r = 0;
436677a3
MT
506
507ERROR:
508 if (a)
265a7974 509 archive_write_free(a);
436677a3 510
96d2c7bc 511 return r;
436677a3
MT
512}
513
22b8e37b 514int pakfire_packager_finish_to_directory(struct pakfire_packager* packager,
45448dbd 515 const char* target, char** result) {
48c6f2e7 516 char path[PATH_MAX];
bb06d548 517 char tmppath[PATH_MAX];
131c1449 518 FILE* f = NULL;
48c6f2e7
MT
519 int r = 1;
520
521 // target cannot be empty
522 if (!target) {
523 errno = EINVAL;
524 return 1;
525 }
526
bb06d548
MT
527 // Get the filename of the package
528 const char* filename = pakfire_packager_filename(packager);
529 if (!filename) {
b1772bfb 530 ERROR(packager->pakfire, "Could not generate filename for package: %m\n");
bb06d548
MT
531 r = 1;
532 goto ERROR;
533 }
534
535 // Make the package path
536 r = pakfire_string_format(path, "%s/%s", target, filename);
a60955af 537 if (r)
bb06d548
MT
538 goto ERROR;
539
540 // Create the parent directory
520ce66c 541 r = pakfire_mkparentdir(path, 0755);
bb06d548
MT
542 if (r)
543 goto ERROR;
544
48c6f2e7 545 // Create a temporary file in the target directory
bb06d548 546 r = pakfire_string_format(tmppath, "%s.XXXXXX", path);
a60955af 547 if (r)
bb06d548 548 goto ERROR;
48c6f2e7
MT
549
550 // Create a temporary result file
a87004ed 551 f = pakfire_mktemp(tmppath, 0);
48c6f2e7
MT
552 if (!f)
553 goto ERROR;
554
555 // Write the finished package
556 r = pakfire_packager_finish(packager, f);
557 if (r) {
b1772bfb 558 ERROR(packager->pakfire, "pakfire_packager_finish() failed: %m\n");
48c6f2e7
MT
559 goto ERROR;
560 }
561
48c6f2e7 562 // Move the temporary file to destination
bb06d548
MT
563 r = rename(tmppath, path);
564 if (r) {
b1772bfb 565 ERROR(packager->pakfire, "Could not move %s to %s: %m\n", tmppath, path);
48c6f2e7 566 goto ERROR;
bb06d548 567 }
48c6f2e7 568
3ddc473d 569 DEBUG(packager->pakfire, "Package written to %s\n", path);
48c6f2e7 570
45448dbd
MT
571 // Store result path if requested
572 if (result) {
573 *result = strdup(path);
574 if (!*result) {
575 r = 1;
576 goto ERROR;
577 }
578 }
579
48c6f2e7
MT
580 // Success
581 r = 0;
582
583ERROR:
131c1449
MT
584 if (f)
585 fclose(f);
586
48c6f2e7 587 // Remove temporary file
bb06d548
MT
588 if (r && *tmppath)
589 unlink(tmppath);
48c6f2e7 590
bb06d548 591 return r;
48c6f2e7
MT
592}
593
80a108bf 594int pakfire_packager_add_file(struct pakfire_packager* packager, struct pakfire_file* file) {
85b59296
MT
595 // Check input
596 if (!file) {
255d4488
MT
597 errno = EINVAL;
598 return 1;
599 }
da08f989 600
85b59296
MT
601 // Fetch path
602 const char* path = pakfire_file_get_path(file);
da08f989 603
85b59296
MT
604 // Files cannot have an empty path
605 if (!*path) {
606 ERROR(packager->pakfire, "Cannot add a file with an empty path\n");
607 errno = EPERM;
608 return 1;
da08f989 609
85b59296
MT
610 // Hidden files cannot be added
611 } else if (*path == '.') {
612 ERROR(packager->pakfire, "Hidden files cannot be added to a package: %s\n", path);
613 errno = EPERM;
614 return 1;
738b3582 615 }
da08f989 616
85b59296
MT
617 DEBUG(packager->pakfire, "Adding file to payload: %s\n", path);
618
2ed2b519
MT
619 // Overwrite a couple of things for source archives
620 if (pakfire_package_is_source(packager->pkg)) {
621 // Reset permissions
85b59296 622 pakfire_file_set_perms(file, 0644);
2ed2b519
MT
623
624 // Reset file ownership
302e3253
MT
625 pakfire_file_set_uname(file, "root");
626 pakfire_file_set_gname(file, "root");
2ed2b519
MT
627 }
628
6bf9841b
MT
629 // Append the file to the filelist
630 return pakfire_filelist_append(packager->filelist, file);
da08f989 631}
106d2edd 632
85b59296
MT
633int pakfire_packager_add(struct pakfire_packager* packager,
634 const char* sourcepath, const char* path) {
635 struct pakfire_file* file = NULL;
636 int r = 1;
637
61b0856b
MT
638 // Create file
639 r = pakfire_file_create_from_path(&file, packager->pakfire, sourcepath);
85b59296
MT
640 if (r)
641 goto ERROR;
642
61b0856b
MT
643 // Assign a new path for inside the archive
644 if (path) {
645 r = pakfire_file_set_path(file, path);
646 if (r)
647 goto ERROR;
648 }
649
85b59296
MT
650 // Call the main function
651 r = pakfire_packager_add_file(packager, file);
652
653ERROR:
654 if (file)
655 pakfire_file_unref(file);
656
657 return r;
658}
659
5d5da764
MT
660static int __pakfire_packager_add_files(struct pakfire* pakfire,
661 struct pakfire_file* file, void* p) {
662 struct pakfire_packager* packager = (struct pakfire_packager*)p;
814b7fee 663
5d5da764
MT
664 return pakfire_packager_add_file(packager, file);
665}
814b7fee 666
5d5da764
MT
667int pakfire_packager_add_files(
668 struct pakfire_packager* packager, struct pakfire_filelist* filelist) {
669 // Add all files on the filelist
48ff07ff 670 return pakfire_filelist_walk(filelist, __pakfire_packager_add_files, packager);
814b7fee
MT
671}
672
106d2edd
MT
673int pakfire_packager_add_scriptlet(struct pakfire_packager* packager,
674 struct pakfire_scriptlet* scriptlet) {
675 if (!scriptlet) {
676 errno = EINVAL;
677 return 1;
678 }
679
680 // Extend array
681 packager->scriptlets = reallocarray(packager->scriptlets,
682 packager->num_scriptlets + 1, sizeof(*packager->scriptlets));
683 if (!packager->scriptlets)
684 return 1;
685
686 // Append scriptlet
687 packager->scriptlets[packager->num_scriptlets++] = pakfire_scriptlet_ref(scriptlet);
688
689 return 0;
690}
2a838122
MT
691
692/*
693 Removes all files on the filelist
694*/
695int pakfire_packager_cleanup(struct pakfire_packager* packager) {
696 // Delete all files on the filelist
697 return pakfire_filelist_cleanup(packager->filelist);
698}