]> git.ipfire.org Git - people/ms/pakfire.git/blame - src/libpakfire/packager.c
packages: Move pakfire_package_{g,s}et_source_* functions
[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
122 pakfire_package_set_build_time(pkg, p->time_created);
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
9ca45f4f
MT
135 if (p->digests & PAKFIRE_DIGEST_SHA3_512)
136 pakfire_package_add_requires(p->pkg, "pakfire(Digest-SHA3-512)");
137 if (p->digests & PAKFIRE_DIGEST_SHA3_256)
138 pakfire_package_add_requires(p->pkg, "pakfire(Digest-SHA3-256)");
139 if (p->digests & PAKFIRE_DIGEST_BLAKE2B512)
140 pakfire_package_add_requires(p->pkg, "pakfire(Digest-BLAKE2b512)");
141 if (p->digests & PAKFIRE_DIGEST_BLAKE2S256)
142 pakfire_package_add_requires(p->pkg, "pakfire(Digest-BLAKE2s256)");
143 if (p->digests & PAKFIRE_DIGEST_SHA2_512)
144 pakfire_package_add_requires(p->pkg, "pakfire(Digest-SHA2-512)");
145 if (p->digests & PAKFIRE_DIGEST_SHA2_256)
146 pakfire_package_add_requires(p->pkg, "pakfire(Digest-SHA2-256)");
6bf9841b 147
6aeb48e6
MT
148 *packager = p;
149
150 return 0;
1ba1869e
MT
151
152ERROR:
153 pakfire_packager_free(p);
154
155 return r;
6aeb48e6
MT
156}
157
22b8e37b 158struct pakfire_packager* pakfire_packager_ref(
6aeb48e6
MT
159 struct pakfire_packager* packager) {
160 ++packager->nrefs;
161
162 return packager;
163}
164
22b8e37b 165struct pakfire_packager* pakfire_packager_unref(
6aeb48e6
MT
166 struct pakfire_packager* packager) {
167 if (--packager->nrefs > 0)
168 return packager;
169
170 pakfire_packager_free(packager);
6aeb48e6
MT
171 return NULL;
172}
da08f989 173
22b8e37b 174const char* pakfire_packager_filename(struct pakfire_packager* packager) {
bb06d548 175 if (!*packager->filename) {
0aade652 176 const char* filename = pakfire_package_get_string(packager->pkg, PAKFIRE_PKG_FILENAME);
bb06d548
MT
177
178 // Add arch
179 if (pakfire_package_is_source(packager->pkg))
180 pakfire_string_set(packager->filename, filename);
181 else {
74468e4f 182 const char* arch = pakfire_package_get_string(packager->pkg, PAKFIRE_PKG_ARCH);
bb06d548
MT
183
184 pakfire_string_format(packager->filename, "%s/%s", arch, filename);
185 }
186 }
187
188 return packager->filename;
96d2c7bc
MT
189}
190
28700a5b 191static struct archive_entry* pakfire_packager_create_file(
95b81a98 192 struct pakfire_packager* packager, const char* filename, size_t size, mode_t mode) {
98e85f1c
MT
193 // Create a new file entry
194 struct archive_entry* entry = archive_entry_new();
195 if (!entry)
28700a5b 196 return NULL;
98e85f1c
MT
197
198 // Set filename
199 archive_entry_set_pathname(entry, filename);
200
201 // This is a regular file
202 archive_entry_set_filetype(entry, AE_IFREG);
95b81a98 203 archive_entry_set_perm(entry, mode);
98e85f1c 204
28700a5b
MT
205 // Set size
206 archive_entry_set_size(entry, size);
207
05cfc2c9
MT
208 // Set ownership
209 archive_entry_set_uname(entry, "root");
210 archive_entry_set_uid(entry, 0);
211 archive_entry_set_gname(entry, "root");
212 archive_entry_set_gid(entry, 0);
213
214 // Set times
215 archive_entry_set_birthtime(entry, packager->time_created, 0);
216 archive_entry_set_ctime(entry, packager->time_created, 0);
217 archive_entry_set_mtime(entry, packager->time_created, 0);
218 archive_entry_set_atime(entry, packager->time_created, 0);
219
28700a5b
MT
220 return entry;
221}
222
223static int pakfire_packager_write_file_from_buffer(struct pakfire_packager* packager,
bfdad796 224 struct archive* a, const char* filename, mode_t mode, const char* buffer) {
28700a5b
MT
225 size_t size = strlen(buffer);
226
227 // Create a new file
7e346194
MT
228 struct archive_entry* entry = pakfire_packager_create_file(packager, filename, size, mode);
229 if (!entry) {
230 ERROR(packager->pakfire, "Could not create file '%s'\n", filename);
28700a5b 231 return 1;
7e346194 232 }
98e85f1c
MT
233
234 // This is the end of the header
235 int r = archive_write_header(a, entry);
236 if (r) {
237 ERROR(packager->pakfire, "Error writing header: %s\n", archive_error_string(a));
265a7974 238 goto ERROR;
98e85f1c
MT
239 }
240
241 // Write content
242 r = archive_write_data(a, buffer, strlen(buffer));
243 if (r < 0) {
244 ERROR(packager->pakfire, "Error writing data: %s\n", archive_error_string(a));
265a7974 245 goto ERROR;
98e85f1c
MT
246 }
247
265a7974
MT
248 // Success
249 r = 0;
250
251ERROR:
98e85f1c
MT
252 archive_entry_free(entry);
253
265a7974 254 return r;
98e85f1c
MT
255}
256
436677a3
MT
257static int pakfire_packager_write_format(struct pakfire_packager* packager,
258 struct archive* a) {
259 const char buffer[] = TO_STRING(PACKAGE_FORMAT) "\n";
260
7e346194
MT
261 DEBUG(packager->pakfire, "Writing package format\n");
262
bfdad796 263 int r = pakfire_packager_write_file_from_buffer(packager, a,
0dbfb5e1 264 "pakfire-format", 0444, buffer);
a6dd151e
MT
265 if (r)
266 return r;
267
268 // Add package format marker
269 pakfire_package_add_requires(packager->pkg,
270 "pakfire(PackageFormat-" TO_STRING(PACKAGE_FORMAT) ")");
271
272 return 0;
436677a3
MT
273}
274
b59c9fa2
MT
275static char* pakfire_packager_make_metadata(struct pakfire_packager* packager) {
276 char* result = NULL;
98e85f1c 277
b59c9fa2
MT
278 // Convert all package metadata to JSON
279 struct json_object* md = pakfire_package_to_json(packager->pkg);
280 if (!md)
98e85f1c
MT
281 goto ERROR;
282
b59c9fa2 283 // Serialize JSON to file
ef4a2e77 284 const char* s = json_object_to_json_string_ext(md, 0);
b59c9fa2 285 if (!s)
98e85f1c
MT
286 goto ERROR;
287
b59c9fa2
MT
288 // Copy result onto heap
289 result = strdup(s);
290 if (!result)
98e85f1c 291 goto ERROR;
98e85f1c
MT
292
293ERROR:
b59c9fa2
MT
294 // Free metadata
295 if (md)
296 json_object_put(md);
98e85f1c 297
b59c9fa2 298 return result;
98e85f1c
MT
299}
300
301static int pakfire_packager_write_metadata(struct pakfire_packager* packager,
bfdad796 302 struct archive* a) {
98e85f1c 303 // Make metadata
b59c9fa2 304 char* buffer = pakfire_packager_make_metadata(packager);
98e85f1c
MT
305 if (!buffer)
306 return 1;
307
b59c9fa2 308 DEBUG(packager->pakfire, "Generated package metadata:\n%s\n", buffer);
98e85f1c
MT
309
310 // Write buffer
bfdad796 311 int r = pakfire_packager_write_file_from_buffer(packager, a,
9f6b177b 312 ".PKGINFO", 0444, buffer);
98e85f1c
MT
313
314 free(buffer);
315
316 return r;
317}
318
106d2edd 319static int pakfire_packager_write_scriptlet(struct pakfire_packager* packager,
bfdad796 320 struct archive* a, struct pakfire_scriptlet* scriptlet) {
106d2edd
MT
321 char filename[PATH_MAX];
322 size_t size;
323 int r;
324
325 // Fetch type
326 const char* type = pakfire_scriptlet_get_type(scriptlet);
327
328 DEBUG(packager->pakfire, "Writing scriptlet '%s' to package\n", type);
329
330 // Make filename
9f6b177b 331 r = pakfire_string_format(filename, ".scriptlets/%s", type);
a60955af 332 if (r)
106d2edd
MT
333 return r;
334
335 // Fetch scriptlet
336 const char* data = pakfire_scriptlet_get_data(scriptlet, &size);
337
338 // Write file
bfdad796 339 return pakfire_packager_write_file_from_buffer(packager, a, filename, 0544, data);
106d2edd
MT
340}
341
436677a3
MT
342/*
343 This function is being called at the end when all data has been added to the package.
344
345 It will create a new archive and write the package to the given file descriptor.
346*/
22b8e37b 347int pakfire_packager_finish(struct pakfire_packager* packager, FILE* f) {
1b4e7c7b 348 struct archive* a = NULL;
96d2c7bc 349 int r = 1;
436677a3 350
74468e4f 351 const char* nevra = pakfire_package_get_string(packager->pkg, PAKFIRE_PKG_NEVRA);
1b4e7c7b 352
555b6dd2
MT
353 // Add requires feature markers
354 if (pakfire_package_has_rich_deps(packager->pkg))
355 pakfire_package_add_requires(packager->pkg, "pakfire(RichDependencies)");
356
9cfb8bb8
MT
357#ifdef ENABLE_DEBUG
358 DEBUG(packager->pakfire, "Filelist:\n");
359
360 // Dump filelist
361 r = pakfire_filelist_dump(packager->filelist, 1);
362 if (r)
363 goto ERROR;
364#endif
365
260006f2
MT
366 // Add filelist
367 r = pakfire_package_set_filelist(packager->pkg, packager->filelist);
368 if (r)
369 goto ERROR;
370
6bf9841b
MT
371 const size_t installsize = pakfire_filelist_total_size(packager->filelist);
372
508e2030 373 // Store total install size
6bf9841b 374 pakfire_package_set_installsize(packager->pkg, installsize);
fafe383d 375
508e2030
MT
376 // Dump package metadata
377 char* dump = pakfire_package_dump(packager->pkg, PAKFIRE_PKG_DUMP_LONG);
378 if (dump) {
379 INFO(packager->pakfire, "%s\n", dump);
380 free(dump);
381 }
382
436677a3 383 // Open a new archive
1b4e7c7b 384 a = archive_write_new();
436677a3
MT
385 if (!a) {
386 ERROR(packager->pakfire, "archive_write_new() failed\n");
260006f2 387 r = 1;
436677a3
MT
388 goto ERROR;
389 }
390
391 // Use the PAX format
96d2c7bc 392 r = archive_write_set_format_pax(a);
436677a3
MT
393 if (r) {
394 ERROR(packager->pakfire, "Could not set format to PAX: %s\n",
395 archive_error_string(a));
396 goto ERROR;
397 }
398
63476763
MT
399 // Store any extended attributes in the SCHILY headers
400 r = archive_write_set_format_option(a, "pax", "xattrheader", "SCHILY");
401 if (r) {
402 ERROR(packager->pakfire, "Could not set xattrheader option: %s\n",
403 archive_error_string(a));
404 return r;
405 }
406
407 // Enable Zstd
408 r = archive_write_add_filter_zstd(a);
409 if (r) {
410 ERROR(packager->pakfire, "Could not enable Zstandard compression: %s\n",
411 archive_error_string(a));
412 return r;
413 }
414
415 // Set compression level to highest
416 r = archive_write_set_filter_option(a, NULL, "compression-level", "22");
417 if (r) {
418 ERROR(packager->pakfire, "Could not set Zstandard compression level: %s\n",
419 archive_error_string(a));
420 return r;
421 }
422
423 // Add feature marker
424 pakfire_package_add_requires(packager->pkg, "pakfire(Compress-Zstandard)");
425
fb74dae4
MT
426 // Store the filelist
427 r = pakfire_package_set_filelist(packager->pkg, packager->filelist);
428 if (r) {
429 ERROR(packager->pakfire, "Could not store filelist: %m\n");
430 return r;
431 }
432
63476763
MT
433 // Do not pad the last block
434 archive_write_set_bytes_in_last_block(a, 1);
435
436677a3
MT
436 // Write archive to f
437 r = archive_write_open_FILE(a, f);
438 if (r) {
439 ERROR(packager->pakfire, "archive_write_open_FILE() failed: %s\n",
440 archive_error_string(a));
441 goto ERROR;
442 }
443
444 // Start with the format file
445 r = pakfire_packager_write_format(packager, a);
265a7974
MT
446 if (r) {
447 ERROR(packager->pakfire, "Could not add format file to archive: %s\n",
448 archive_error_string(a));
436677a3 449 goto ERROR;
265a7974 450 }
436677a3 451
98e85f1c 452 // Write the metadata
bfdad796 453 r = pakfire_packager_write_metadata(packager, a);
265a7974
MT
454 if (r) {
455 ERROR(packager->pakfire, "Could not add metadata file to archive: %s\n",
456 archive_error_string(a));
98e85f1c 457 goto ERROR;
265a7974 458 }
98e85f1c 459
d8856104
MT
460 // Write scriptlets
461 for (unsigned int i = 0; i < packager->num_scriptlets; i++) {
462 r = pakfire_packager_write_scriptlet(packager, a, packager->scriptlets[i]);
463 if (r) {
464 ERROR(packager->pakfire, "Could not add scriptlet to the archive: %m\n");
465 goto ERROR;
466 }
467 }
468
bfdad796 469 // Write the payload
6bf9841b
MT
470 r = pakfire_compress(packager->pakfire, a, packager->filelist, nevra,
471 PAKFIRE_COMPRESS_SHOW_THROUGHPUT, PAKFIRE_PACKAGER_DIGESTS);
131c1449
MT
472 if (r)
473 goto ERROR;
265a7974 474
2013270b
MT
475 // Flush all buffers to disk
476 fflush(f);
477
96d2c7bc
MT
478 // Success
479 r = 0;
436677a3
MT
480
481ERROR:
482 if (a)
265a7974 483 archive_write_free(a);
436677a3 484
96d2c7bc 485 return r;
436677a3
MT
486}
487
22b8e37b 488int pakfire_packager_finish_to_directory(struct pakfire_packager* packager,
45448dbd 489 const char* target, char** result) {
48c6f2e7 490 char path[PATH_MAX];
bb06d548 491 char tmppath[PATH_MAX];
131c1449 492 FILE* f = NULL;
48c6f2e7
MT
493 int r = 1;
494
495 // target cannot be empty
496 if (!target) {
497 errno = EINVAL;
498 return 1;
499 }
500
bb06d548
MT
501 // Get the filename of the package
502 const char* filename = pakfire_packager_filename(packager);
503 if (!filename) {
b1772bfb 504 ERROR(packager->pakfire, "Could not generate filename for package: %m\n");
bb06d548
MT
505 r = 1;
506 goto ERROR;
507 }
508
509 // Make the package path
510 r = pakfire_string_format(path, "%s/%s", target, filename);
a60955af 511 if (r)
bb06d548
MT
512 goto ERROR;
513
514 // Create the parent directory
520ce66c 515 r = pakfire_mkparentdir(path, 0755);
bb06d548
MT
516 if (r)
517 goto ERROR;
518
48c6f2e7 519 // Create a temporary file in the target directory
bb06d548 520 r = pakfire_string_format(tmppath, "%s.XXXXXX", path);
a60955af 521 if (r)
bb06d548 522 goto ERROR;
48c6f2e7
MT
523
524 // Create a temporary result file
131c1449 525 f = pakfire_mktemp(tmppath);
48c6f2e7
MT
526 if (!f)
527 goto ERROR;
528
529 // Write the finished package
530 r = pakfire_packager_finish(packager, f);
531 if (r) {
b1772bfb 532 ERROR(packager->pakfire, "pakfire_packager_finish() failed: %m\n");
48c6f2e7
MT
533 goto ERROR;
534 }
535
48c6f2e7 536 // Move the temporary file to destination
bb06d548
MT
537 r = rename(tmppath, path);
538 if (r) {
b1772bfb 539 ERROR(packager->pakfire, "Could not move %s to %s: %m\n", tmppath, path);
48c6f2e7 540 goto ERROR;
bb06d548 541 }
48c6f2e7 542
bb06d548 543 INFO(packager->pakfire, "Package written to %s\n", path);
48c6f2e7 544
45448dbd
MT
545 // Store result path if requested
546 if (result) {
547 *result = strdup(path);
548 if (!*result) {
549 r = 1;
550 goto ERROR;
551 }
552 }
553
48c6f2e7
MT
554 // Success
555 r = 0;
556
557ERROR:
131c1449
MT
558 if (f)
559 fclose(f);
560
48c6f2e7 561 // Remove temporary file
bb06d548
MT
562 if (r && *tmppath)
563 unlink(tmppath);
48c6f2e7 564
bb06d548 565 return r;
48c6f2e7
MT
566}
567
80a108bf 568int pakfire_packager_add_file(struct pakfire_packager* packager, struct pakfire_file* file) {
85b59296
MT
569 // Check input
570 if (!file) {
255d4488
MT
571 errno = EINVAL;
572 return 1;
573 }
da08f989 574
85b59296
MT
575 // Fetch path
576 const char* path = pakfire_file_get_path(file);
da08f989 577
85b59296
MT
578 // Files cannot have an empty path
579 if (!*path) {
580 ERROR(packager->pakfire, "Cannot add a file with an empty path\n");
581 errno = EPERM;
582 return 1;
da08f989 583
85b59296
MT
584 // Hidden files cannot be added
585 } else if (*path == '.') {
586 ERROR(packager->pakfire, "Hidden files cannot be added to a package: %s\n", path);
587 errno = EPERM;
588 return 1;
738b3582 589 }
da08f989 590
85b59296
MT
591 DEBUG(packager->pakfire, "Adding file to payload: %s\n", path);
592
2ed2b519
MT
593 // Overwrite a couple of things for source archives
594 if (pakfire_package_is_source(packager->pkg)) {
595 // Reset permissions
85b59296 596 pakfire_file_set_perms(file, 0644);
2ed2b519
MT
597
598 // Reset file ownership
302e3253
MT
599 pakfire_file_set_uname(file, "root");
600 pakfire_file_set_gname(file, "root");
2ed2b519
MT
601 }
602
6bf9841b
MT
603 // Append the file to the filelist
604 return pakfire_filelist_append(packager->filelist, file);
da08f989 605}
106d2edd 606
85b59296
MT
607int pakfire_packager_add(struct pakfire_packager* packager,
608 const char* sourcepath, const char* path) {
609 struct pakfire_file* file = NULL;
610 int r = 1;
611
61b0856b
MT
612 // Create file
613 r = pakfire_file_create_from_path(&file, packager->pakfire, sourcepath);
85b59296
MT
614 if (r)
615 goto ERROR;
616
61b0856b
MT
617 // Assign a new path for inside the archive
618 if (path) {
619 r = pakfire_file_set_path(file, path);
620 if (r)
621 goto ERROR;
622 }
623
85b59296
MT
624 // Call the main function
625 r = pakfire_packager_add_file(packager, file);
626
627ERROR:
628 if (file)
629 pakfire_file_unref(file);
630
631 return r;
632}
633
5d5da764
MT
634static int __pakfire_packager_add_files(struct pakfire* pakfire,
635 struct pakfire_file* file, void* p) {
636 struct pakfire_packager* packager = (struct pakfire_packager*)p;
814b7fee 637
5d5da764
MT
638 return pakfire_packager_add_file(packager, file);
639}
814b7fee 640
5d5da764
MT
641int pakfire_packager_add_files(
642 struct pakfire_packager* packager, struct pakfire_filelist* filelist) {
643 // Add all files on the filelist
86bad6b2 644 return pakfire_filelist_walk(filelist, __pakfire_packager_add_files, packager);
814b7fee
MT
645}
646
106d2edd
MT
647int pakfire_packager_add_scriptlet(struct pakfire_packager* packager,
648 struct pakfire_scriptlet* scriptlet) {
649 if (!scriptlet) {
650 errno = EINVAL;
651 return 1;
652 }
653
654 // Extend array
655 packager->scriptlets = reallocarray(packager->scriptlets,
656 packager->num_scriptlets + 1, sizeof(*packager->scriptlets));
657 if (!packager->scriptlets)
658 return 1;
659
660 // Append scriptlet
661 packager->scriptlets[packager->num_scriptlets++] = pakfire_scriptlet_ref(scriptlet);
662
663 return 0;
664}
2a838122
MT
665
666/*
667 Removes all files on the filelist
668*/
669int pakfire_packager_cleanup(struct pakfire_packager* packager) {
670 // Delete all files on the filelist
671 return pakfire_filelist_cleanup(packager->filelist);
672}