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