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