]> git.ipfire.org Git - people/ms/pakfire.git/blame - src/libpakfire/packager.c
archive: Store MIME type of files
[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
260006f2
MT
388 // Add filelist
389 r = pakfire_package_set_filelist(packager->pkg, packager->filelist);
390 if (r)
391 goto ERROR;
392
6bf9841b
MT
393 const size_t installsize = pakfire_filelist_total_size(packager->filelist);
394
508e2030 395 // Store total install size
3f327c3c
MT
396 r = pakfire_package_set_num(packager->pkg, PAKFIRE_PKG_INSTALLSIZE, installsize);
397 if (r)
398 goto ERROR;
fafe383d 399
436677a3 400 // Open a new archive
1b4e7c7b 401 a = archive_write_new();
436677a3
MT
402 if (!a) {
403 ERROR(packager->pakfire, "archive_write_new() failed\n");
260006f2 404 r = 1;
436677a3
MT
405 goto ERROR;
406 }
407
408 // Use the PAX format
96d2c7bc 409 r = archive_write_set_format_pax(a);
436677a3
MT
410 if (r) {
411 ERROR(packager->pakfire, "Could not set format to PAX: %s\n",
412 archive_error_string(a));
413 goto ERROR;
414 }
415
63476763
MT
416 // Store any extended attributes in the SCHILY headers
417 r = archive_write_set_format_option(a, "pax", "xattrheader", "SCHILY");
418 if (r) {
419 ERROR(packager->pakfire, "Could not set xattrheader option: %s\n",
420 archive_error_string(a));
421 return r;
422 }
423
424 // Enable Zstd
425 r = archive_write_add_filter_zstd(a);
426 if (r) {
427 ERROR(packager->pakfire, "Could not enable Zstandard compression: %s\n",
428 archive_error_string(a));
429 return r;
430 }
431
a3151996
MT
432 // Select compression level
433 if (pakfire_package_is_source(packager->pkg))
434 comp_level = "1";
435 else
436 comp_level = "22";
437
63476763 438 // Set compression level to highest
a3151996 439 r = archive_write_set_filter_option(a, NULL, "compression-level", comp_level);
63476763
MT
440 if (r) {
441 ERROR(packager->pakfire, "Could not set Zstandard compression level: %s\n",
442 archive_error_string(a));
443 return r;
444 }
445
446 // Add feature marker
6f3fad3b
MT
447 pakfire_package_add_dep(packager->pkg,
448 PAKFIRE_PKG_REQUIRES, "pakfire(Compress-Zstandard)");
63476763
MT
449
450 // Do not pad the last block
451 archive_write_set_bytes_in_last_block(a, 1);
452
436677a3
MT
453 // Write archive to f
454 r = archive_write_open_FILE(a, f);
455 if (r) {
456 ERROR(packager->pakfire, "archive_write_open_FILE() failed: %s\n",
457 archive_error_string(a));
458 goto ERROR;
459 }
460
461 // Start with the format file
462 r = pakfire_packager_write_format(packager, a);
265a7974
MT
463 if (r) {
464 ERROR(packager->pakfire, "Could not add format file to archive: %s\n",
465 archive_error_string(a));
436677a3 466 goto ERROR;
265a7974 467 }
436677a3 468
98e85f1c 469 // Write the metadata
bfdad796 470 r = pakfire_packager_write_metadata(packager, a);
265a7974
MT
471 if (r) {
472 ERROR(packager->pakfire, "Could not add metadata file to archive: %s\n",
473 archive_error_string(a));
98e85f1c 474 goto ERROR;
265a7974 475 }
98e85f1c 476
d8856104
MT
477 // Write scriptlets
478 for (unsigned int i = 0; i < packager->num_scriptlets; i++) {
479 r = pakfire_packager_write_scriptlet(packager, a, packager->scriptlets[i]);
480 if (r) {
481 ERROR(packager->pakfire, "Could not add scriptlet to the archive: %m\n");
482 goto ERROR;
483 }
484 }
485
bfdad796 486 // Write the payload
6bf9841b
MT
487 r = pakfire_compress(packager->pakfire, a, packager->filelist, nevra,
488 PAKFIRE_COMPRESS_SHOW_THROUGHPUT, PAKFIRE_PACKAGER_DIGESTS);
131c1449
MT
489 if (r)
490 goto ERROR;
265a7974 491
2013270b
MT
492 // Flush all buffers to disk
493 fflush(f);
494
96d2c7bc
MT
495 // Success
496 r = 0;
436677a3
MT
497
498ERROR:
499 if (a)
265a7974 500 archive_write_free(a);
436677a3 501
96d2c7bc 502 return r;
436677a3
MT
503}
504
22b8e37b 505int pakfire_packager_finish_to_directory(struct pakfire_packager* packager,
45448dbd 506 const char* target, char** result) {
48c6f2e7 507 char path[PATH_MAX];
bb06d548 508 char tmppath[PATH_MAX];
131c1449 509 FILE* f = NULL;
48c6f2e7
MT
510 int r = 1;
511
512 // target cannot be empty
513 if (!target) {
514 errno = EINVAL;
515 return 1;
516 }
517
bb06d548
MT
518 // Get the filename of the package
519 const char* filename = pakfire_packager_filename(packager);
520 if (!filename) {
b1772bfb 521 ERROR(packager->pakfire, "Could not generate filename for package: %m\n");
bb06d548
MT
522 r = 1;
523 goto ERROR;
524 }
525
526 // Make the package path
527 r = pakfire_string_format(path, "%s/%s", target, filename);
a60955af 528 if (r)
bb06d548
MT
529 goto ERROR;
530
531 // Create the parent directory
520ce66c 532 r = pakfire_mkparentdir(path, 0755);
bb06d548
MT
533 if (r)
534 goto ERROR;
535
48c6f2e7 536 // Create a temporary file in the target directory
bb06d548 537 r = pakfire_string_format(tmppath, "%s.XXXXXX", path);
a60955af 538 if (r)
bb06d548 539 goto ERROR;
48c6f2e7
MT
540
541 // Create a temporary result file
a87004ed 542 f = pakfire_mktemp(tmppath, 0);
48c6f2e7
MT
543 if (!f)
544 goto ERROR;
545
546 // Write the finished package
547 r = pakfire_packager_finish(packager, f);
548 if (r) {
b1772bfb 549 ERROR(packager->pakfire, "pakfire_packager_finish() failed: %m\n");
48c6f2e7
MT
550 goto ERROR;
551 }
552
48c6f2e7 553 // Move the temporary file to destination
bb06d548
MT
554 r = rename(tmppath, path);
555 if (r) {
b1772bfb 556 ERROR(packager->pakfire, "Could not move %s to %s: %m\n", tmppath, path);
48c6f2e7 557 goto ERROR;
bb06d548 558 }
48c6f2e7 559
3ddc473d 560 DEBUG(packager->pakfire, "Package written to %s\n", path);
48c6f2e7 561
45448dbd
MT
562 // Store result path if requested
563 if (result) {
564 *result = strdup(path);
565 if (!*result) {
566 r = 1;
567 goto ERROR;
568 }
569 }
570
48c6f2e7
MT
571 // Success
572 r = 0;
573
574ERROR:
131c1449
MT
575 if (f)
576 fclose(f);
577
48c6f2e7 578 // Remove temporary file
bb06d548
MT
579 if (r && *tmppath)
580 unlink(tmppath);
48c6f2e7 581
bb06d548 582 return r;
48c6f2e7
MT
583}
584
80a108bf 585int pakfire_packager_add_file(struct pakfire_packager* packager, struct pakfire_file* file) {
210aabe9
MT
586 int r;
587
85b59296
MT
588 // Check input
589 if (!file) {
255d4488
MT
590 errno = EINVAL;
591 return 1;
592 }
da08f989 593
85b59296
MT
594 // Fetch path
595 const char* path = pakfire_file_get_path(file);
da08f989 596
85b59296
MT
597 // Files cannot have an empty path
598 if (!*path) {
599 ERROR(packager->pakfire, "Cannot add a file with an empty path\n");
600 errno = EPERM;
601 return 1;
da08f989 602
85b59296
MT
603 // Hidden files cannot be added
604 } else if (*path == '.') {
605 ERROR(packager->pakfire, "Hidden files cannot be added to a package: %s\n", path);
606 errno = EPERM;
607 return 1;
738b3582 608 }
da08f989 609
85b59296
MT
610 DEBUG(packager->pakfire, "Adding file to payload: %s\n", path);
611
210aabe9
MT
612 // Detect the MIME type
613 r = pakfire_file_detect_mimetype(file);
614 if (r)
615 return r;
616
2ed2b519
MT
617 // Overwrite a couple of things for source archives
618 if (pakfire_package_is_source(packager->pkg)) {
619 // Reset permissions
85b59296 620 pakfire_file_set_perms(file, 0644);
2ed2b519
MT
621
622 // Reset file ownership
302e3253
MT
623 pakfire_file_set_uname(file, "root");
624 pakfire_file_set_gname(file, "root");
2ed2b519
MT
625 }
626
6bf9841b 627 // Append the file to the filelist
2f88682d 628 return pakfire_filelist_add(packager->filelist, file);
da08f989 629}
106d2edd 630
85b59296
MT
631int pakfire_packager_add(struct pakfire_packager* packager,
632 const char* sourcepath, const char* path) {
633 struct pakfire_file* file = NULL;
634 int r = 1;
635
61b0856b
MT
636 // Create file
637 r = pakfire_file_create_from_path(&file, packager->pakfire, sourcepath);
85b59296
MT
638 if (r)
639 goto ERROR;
640
61b0856b
MT
641 // Assign a new path for inside the archive
642 if (path) {
643 r = pakfire_file_set_path(file, path);
644 if (r)
645 goto ERROR;
646 }
647
85b59296
MT
648 // Call the main function
649 r = pakfire_packager_add_file(packager, file);
650
651ERROR:
652 if (file)
653 pakfire_file_unref(file);
654
655 return r;
656}
657
5d5da764
MT
658static int __pakfire_packager_add_files(struct pakfire* pakfire,
659 struct pakfire_file* file, void* p) {
660 struct pakfire_packager* packager = (struct pakfire_packager*)p;
814b7fee 661
5d5da764
MT
662 return pakfire_packager_add_file(packager, file);
663}
814b7fee 664
5d5da764
MT
665int pakfire_packager_add_files(
666 struct pakfire_packager* packager, struct pakfire_filelist* filelist) {
667 // Add all files on the filelist
48ff07ff 668 return pakfire_filelist_walk(filelist, __pakfire_packager_add_files, packager);
814b7fee
MT
669}
670
106d2edd
MT
671int pakfire_packager_add_scriptlet(struct pakfire_packager* packager,
672 struct pakfire_scriptlet* scriptlet) {
673 if (!scriptlet) {
674 errno = EINVAL;
675 return 1;
676 }
677
678 // Extend array
679 packager->scriptlets = reallocarray(packager->scriptlets,
680 packager->num_scriptlets + 1, sizeof(*packager->scriptlets));
681 if (!packager->scriptlets)
682 return 1;
683
684 // Append scriptlet
685 packager->scriptlets[packager->num_scriptlets++] = pakfire_scriptlet_ref(scriptlet);
686
687 return 0;
688}
2a838122
MT
689
690/*
691 Removes all files on the filelist
692*/
693int pakfire_packager_cleanup(struct pakfire_packager* packager) {
694 // Delete all files on the filelist
695 return pakfire_filelist_cleanup(packager->filelist);
696}