1 /*#############################################################################
3 # Pakfire - The IPFire package management system #
4 # Copyright (C) 2014 Pakfire development team #
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. #
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. #
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/>. #
19 #############################################################################*/
25 #include <sys/types.h>
26 #include <sys/sendfile.h>
31 #include <archive_entry.h>
36 #include <pakfire/archive.h>
37 #include <pakfire/compress.h>
38 #include <pakfire/ctx.h>
39 #include <pakfire/dependencies.h>
40 #include <pakfire/digest.h>
41 #include <pakfire/file.h>
42 #include <pakfire/filelist.h>
43 #include <pakfire/i18n.h>
44 #include <pakfire/jail.h>
45 #include <pakfire/logging.h>
46 #include <pakfire/package.h>
47 #include <pakfire/pakfire.h>
48 #include <pakfire/path.h>
49 #include <pakfire/private.h>
50 #include <pakfire/repo.h>
51 #include <pakfire/scriptlet.h>
52 #include <pakfire/string.h>
53 #include <pakfire/util.h>
55 #define MAX_SCRIPTLETS 9
57 // The maximum number of symlinks to follow when reading a file from an archive
58 #define MAX_FOLLOW_SYMLINKS 10
60 struct pakfire_archive
{
61 struct pakfire_ctx
* ctx
;
62 struct pakfire
* pakfire
;
69 struct pakfire_package
* package
;
73 struct json_object
* metadata
;
75 struct pakfire_filelist
* filelist
;
78 struct pakfire_scriptlet
* scriptlets
[MAX_SCRIPTLETS
];
79 unsigned int num_scriptlets
;
82 struct pakfire_digests digests
;
88 static FILE* pakfire_archive_clone_file(struct pakfire_archive
* archive
) {
89 int fd
= fileno(archive
->f
);
91 CTX_ERROR(archive
->ctx
, "Could not fetch the archive's file descriptor: %m\n");
95 // Duplicate the file descriptor
98 CTX_ERROR(archive
->ctx
, "Could not duplicate the file descriptor: %m\n");
102 // Re-open a file handle
103 return fdopen(fd
, "r");
106 static int pakfire_archive_compute_digests(struct pakfire_archive
* archive
) {
109 // Start reading at the beginning
113 r
= pakfire_digests_compute_from_file(archive
->ctx
, &archive
->digests
,
114 PAKFIRE_ARCHIVE_CHECKSUM
, archive
->f
);
116 CTX_ERROR(archive
->ctx
, "Could not calculate digest of %s: %m\n", archive
->path
);
122 A helper function to close the archive and reset our data structures
124 static void close_archive(struct pakfire_archive
* archive
, struct archive
* a
) {
126 archive_read_free(a
);
130 A helper function that opens the archive for reading
132 static struct archive
* open_archive(struct pakfire_archive
* archive
, FILE* f
) {
133 // If no special file descriptor has been given we use the open one
137 // Create a new archive object
138 struct archive
* a
= archive_read_new();
142 // Archives must be uncompressed tarballs
143 archive_read_support_format_tar(a
);
145 // Archives are compressed using Zstandard
146 archive_read_support_filter_zstd(a
);
148 // Start reading from the beginning
151 // Try opening the archive file
152 int r
= archive_read_open_FILE(a
, f
);
154 CTX_ERROR(archive
->ctx
, "Could not open archive %s: %s\n",
155 archive
->path
, archive_error_string(a
));
163 close_archive(archive
, a
);
168 static int pakfire_archive_walk(struct pakfire_archive
* archive
,
169 pakfire_walk_callback callback
, pakfire_walk_filter_callback filter_callback
, void* data
) {
172 // Open the archive file
173 struct archive
* a
= open_archive(archive
, NULL
);
177 // Walk through the archive
178 r
= pakfire_walk(archive
->ctx
, a
, callback
, filter_callback
, data
);
182 close_archive(archive
, a
);
187 static void pakfire_archive_free(struct pakfire_archive
* archive
) {
193 for (unsigned int i
= 0; i
< archive
->num_scriptlets
; i
++)
194 pakfire_scriptlet_unref(archive
->scriptlets
[i
]);
196 if (archive
->filelist
)
197 pakfire_filelist_unref(archive
->filelist
);
198 if (archive
->package
)
199 pakfire_package_unref(archive
->package
);
200 if (archive
->metadata
)
201 json_object_put(archive
->metadata
);
202 if (archive
->pakfire
)
203 pakfire_unref(archive
->pakfire
);
205 pakfire_ctx_unref(archive
->ctx
);
209 static int pakfire_archive_create(struct pakfire_archive
** archive
, struct pakfire
* pakfire
) {
210 struct pakfire_archive
* a
= calloc(1, sizeof(*a
));
214 // Store a reference to the context
215 a
->ctx
= pakfire_ctx(pakfire
);
217 a
->pakfire
= pakfire_ref(pakfire
);
224 PAKFIRE_EXPORT
struct pakfire_archive
* pakfire_archive_ref(struct pakfire_archive
* archive
) {
230 PAKFIRE_EXPORT
struct pakfire_archive
* pakfire_archive_unref(struct pakfire_archive
* archive
) {
231 if (--archive
->nrefs
> 0)
234 pakfire_archive_free(archive
);
239 static struct pakfire_package
* pakfire_archive_get_package(struct pakfire_archive
* archive
) {
240 if (!archive
->package
) {
241 int r
= pakfire_archive_make_package(archive
, NULL
, &archive
->package
);
246 return pakfire_package_ref(archive
->package
);
251 static int pakfire_archive_parse_json_metadata(struct pakfire_archive
* archive
,
252 const char* data
, const size_t length
) {
256 struct json_tokener
* tokener
= json_tokener_new();
258 CTX_ERROR(archive
->ctx
, "Could not allocate JSON tokener: %m\n");
262 // Parse JSON from buffer
263 archive
->metadata
= json_tokener_parse_ex(tokener
, data
, length
);
264 if (!archive
->metadata
) {
265 enum json_tokener_error error
= json_tokener_get_error(tokener
);
267 CTX_ERROR(archive
->ctx
, "JSON parsing error: %s\n",
268 json_tokener_error_desc(error
));
272 CTX_DEBUG(archive
->ctx
, "Successfully parsed package metadata:\n%s\n",
273 json_object_to_json_string_ext(archive
->metadata
,
274 JSON_C_TO_STRING_PRETTY
|JSON_C_TO_STRING_PRETTY_TAB
));
281 json_tokener_free(tokener
);
286 static int pakfire_archive_parse_format(struct pakfire_archive
* archive
,
287 const char* data
, const size_t length
) {
288 // Check if format has already been set
289 if (archive
->format
) {
290 CTX_ERROR(archive
->ctx
, "Archive format has already been parsed\n");
295 archive
->format
= strtoul(data
, NULL
, 10);
297 switch (archive
->format
) {
298 // Handle all supported formats
302 // Break on anything else
304 CTX_ERROR(archive
->ctx
, "This version of Pakfire does not support "
305 "archive format %u\n", archive
->format
);
309 CTX_DEBUG(archive
->ctx
, "Archive format is %u\n", archive
->format
);
314 static int pakfire_archive_parse_scriptlet(struct pakfire_archive
* archive
,
315 const char* path
, const char* data
, const size_t length
) {
316 struct pakfire_scriptlet
* scriptlet
= NULL
;
317 const char* type
= NULL
;
320 // Check for any available space
321 if (archive
->num_scriptlets
>= MAX_SCRIPTLETS
) {
322 CTX_ERROR(archive
->ctx
, "Too many scriptlets\n");
327 type
= pakfire_path_relpath(".scriptlets/", path
);
329 CTX_ERROR(archive
->ctx
, "Could not determine the scriptlet type from '%s'\n", path
);
333 // Allocate a scriptlet
334 r
= pakfire_scriptlet_create(&scriptlet
, archive
->ctx
, type
, data
, length
);
339 archive
->scriptlets
[archive
->num_scriptlets
++] = scriptlet
;
344 static int pakfire_archive_copy_data_to_buffer(struct pakfire_archive
* archive
,
345 struct archive
* a
, struct archive_entry
* entry
, char** data
, size_t* length
) {
346 size_t bytes_read
= 0;
350 // Fetch how large the buffer needs to be
351 size_t required_size
= archive_entry_size(entry
);
355 // Allocate a block of the required size
356 buffer
= calloc(1, required_size
+ 1);
360 // Read the data into the buffer
361 bytes_read
= archive_read_data(a
, buffer
, required_size
);
362 if (bytes_read
< required_size
) {
363 CTX_ERROR(archive
->ctx
, "Could not read from archive: %s\n", archive_error_string(a
));
370 *length
= bytes_read
;
381 static int __pakfire_archive_read_metadata(struct pakfire_ctx
* ctx
, struct archive
* a
,
382 struct archive_entry
* entry
, void* p
) {
383 struct pakfire_archive
* archive
= (struct pakfire_archive
*)p
;
389 const char* path
= archive_entry_pathname(entry
);
391 CTX_DEBUG(ctx
, "Reading metadata file: %s\n", path
);
393 // Load the file into memory
394 r
= pakfire_archive_copy_data_to_buffer(archive
, a
, entry
, &data
, &length
);
396 CTX_ERROR(archive
->ctx
, "Could not read data from archive: %s\n",
397 archive_error_string(a
));
402 if (archive
->format
>= 6) {
404 if (strcmp(path
, ".PKGINFO") == 0) {
405 r
= pakfire_archive_parse_json_metadata(archive
, data
, length
);
410 } else if (pakfire_string_startswith(path
, ".scriptlets/")) {
411 r
= pakfire_archive_parse_scriptlet(archive
, path
, data
, length
);
417 } else if (strcmp(path
, "pakfire-format") == 0) {
418 r
= pakfire_archive_parse_format(archive
, data
, length
);
430 static int __pakfire_archive_filter_metadata(struct pakfire_ctx
* ctx
,
431 struct archive
* a
, struct archive_entry
* entry
, void* p
) {
432 struct pakfire_archive
* archive
= (struct pakfire_archive
*)p
;
434 const char* path
= archive_entry_pathname(entry
);
437 if (archive
->format
>= 6) {
438 // Anything that starts with "." is a metadata file
440 return PAKFIRE_WALK_OK
;
442 // Otherwise, the payload begins
443 return PAKFIRE_WALK_END
;
445 // The pakfire-format file is part of the metadata
446 } else if (strcmp(path
, "pakfire-format") == 0) {
447 return PAKFIRE_WALK_OK
;
451 return PAKFIRE_WALK_ERROR
;
454 static int pakfire_archive_read_metadata(struct pakfire_archive
* archive
) {
457 // Check if the archive file actually has any contect
458 if (!archive
->stat
.st_size
) {
459 CTX_ERROR(archive
->ctx
, "Trying to open an empty archive file\n");
463 CTX_DEBUG(archive
->ctx
, "Reading archive metadata...\n");
465 // Walk through the archive
466 r
= pakfire_archive_walk(archive
, __pakfire_archive_read_metadata
,
467 __pakfire_archive_filter_metadata
, archive
);
471 // Check if we could successfully read something
472 if (!archive
->format
) {
473 CTX_ERROR(archive
->ctx
, "Archive has an unknown format\n");
477 // Check if we have read some metadata
478 if (!archive
->metadata
) {
479 CTX_ERROR(archive
->ctx
, "Archive has no metadata\n");
486 static int pakfire_archive_try_open(struct pakfire_archive
* archive
, const char* path
) {
493 CTX_DEBUG(archive
->ctx
, "Opening archive %s\n", path
);
496 pakfire_string_set(archive
->path
, path
);
498 // Open the file (and keep the file descriptor open)
499 archive
->f
= fopen(archive
->path
, "r");
503 // Let the kernel know, that we will read the file sequentially
504 r
= posix_fadvise(fileno(archive
->f
), 0, 0, POSIX_FADV_SEQUENTIAL
);
506 CTX_ERROR(archive
->ctx
, "posix_fadvise() failed: %m\n");
511 r
= fstat(fileno(archive
->f
), &archive
->stat
);
513 CTX_ERROR(archive
->ctx
, "Could not stat archive: %m\n");
517 // Read all package metadata
518 r
= pakfire_archive_read_metadata(archive
);
520 CTX_ERROR(archive
->ctx
, "Could not open archive: %s\n", strerror(-r
));
528 PAKFIRE_EXPORT
int pakfire_archive_open(struct pakfire_archive
** archive
, struct pakfire
* pakfire
, const char* path
) {
529 int r
= pakfire_archive_create(archive
, pakfire
);
533 r
= pakfire_archive_try_open(*archive
, path
);
540 pakfire_archive_unref(*archive
);
546 static struct json_object
* pakfire_archive_metadata_get_object(
547 struct pakfire_archive
* archive
, const char* key1
, const char* key2
) {
548 struct json_object
* object
= archive
->metadata
;
551 const char* keys
[] = {
557 // Walk through all keys
558 for (const char** key
= keys
; *key
; key
++) {
559 // Try finding a matching JSON object
560 r
= json_object_object_get_ex(object
, *key
, &object
);
562 CTX_DEBUG(archive
->ctx
, "Could not find JSON object at '%s': %m\n", *key
);
570 static const char* pakfire_archive_metadata_get(
571 struct pakfire_archive
* archive
, const char* key1
, const char* key2
) {
572 // Try finding an object
573 struct json_object
* object
= pakfire_archive_metadata_get_object(archive
, key1
, key2
);
577 // Return the object as string
578 return json_object_get_string(object
);
581 static int64_t pakfire_archive_metadata_get_int64(
582 struct pakfire_archive
* archive
, const char* key1
, const char* key2
) {
583 // Try finding an object
584 struct json_object
* object
= pakfire_archive_metadata_get_object(archive
, key1
, key2
);
588 // Return the object as integer
589 return json_object_get_int64(object
);
592 static int __pakfire_archive_filter_payload(struct pakfire_ctx
* ctx
,
593 struct archive
* a
, struct archive_entry
* entry
, void* p
) {
594 const char* path
= archive_entry_pathname(entry
);
596 return PAKFIRE_WALK_ERROR
;
600 if (strcmp(path
, "pakfire-format") == 0)
601 return PAKFIRE_WALK_SKIP
;
605 return PAKFIRE_WALK_SKIP
;
611 // The first file that isn't metadata, so we are done calling the filter callback
612 return PAKFIRE_WALK_DONE
;
616 Read files from the archive
618 struct pakfire_archive_read_cookie
{
619 // A reference to the archive
620 struct pakfire_archive
* archive
;
622 // The path we are reading
625 // A copy of the underlying file descriptor
628 // The opened archive
631 // File handle opened by the cookie
637 // Count how many symlinks we have followed
638 unsigned int followed_symlinks
;
641 static ssize_t
__pakfire_archive_cookie_read(void* c
, char* buffer
, size_t size
) {
642 struct pakfire_archive_read_cookie
* cookie
= (struct pakfire_archive_read_cookie
*)c
;
644 // Read the data directly from the archive
645 return archive_read_data(cookie
->a
, buffer
, size
);
648 static int __pakfire_archive_cookie_close(void* c
) {
649 struct pakfire_archive_read_cookie
* cookie
= (struct pakfire_archive_read_cookie
*)c
;
652 pakfire_archive_unref(cookie
->archive
);
654 archive_read_free(cookie
->a
);
664 static cookie_io_functions_t pakfire_archive_read_functions
= {
665 .read
= __pakfire_archive_cookie_read
,
666 .close
= __pakfire_archive_cookie_close
,
669 // Tries to find a matching file in the archive
670 static int __pakfire_archive_read_filter(struct pakfire_ctx
* ctx
, struct archive
* a
,
671 struct archive_entry
* e
, void* data
) {
672 struct pakfire_archive_read_cookie
* cookie
= data
;
673 const char* symlink
= NULL
;
677 const char* p
= archive_entry_pathname(e
);
679 return PAKFIRE_WALK_ERROR
;
682 if (strcmp(cookie
->path
+ 1, p
) == 0) {
683 if (cookie
->flags
& PAKFIRE_ARCHIVE_READ_FOLLOW_SYMLINKS
) {
684 switch (archive_entry_filetype(e
)) {
689 return PAKFIRE_WALK_DONE
;
692 // Resolve the destination of the symlink
693 symlink
= archive_entry_symlink(e
);
695 return PAKFIRE_WALK_ERROR
;
698 r
= pakfire_path_merge(cookie
->path
, cookie
->path
, symlink
);
700 return PAKFIRE_WALK_ERROR
;
703 if (++cookie
->followed_symlinks
>= MAX_FOLLOW_SYMLINKS
) {
704 CTX_ERROR(ctx
, "Reached maximum number of symlinks to follow\n");
705 return PAKFIRE_WALK_ERROR
;
708 return PAKFIRE_WALK_AGAIN
;
711 return PAKFIRE_WALK_DONE
;
714 // Otherwise we skip the file
715 return PAKFIRE_WALK_SKIP
;
718 // Reads a matching file into memory
719 static int __pakfire_archive_read(struct pakfire_ctx
* ctx
, struct archive
* a
,
720 struct archive_entry
* e
, void* data
) {
721 struct pakfire_archive_read_cookie
* cookie
= data
;
723 // Create a file descriptor
724 cookie
->__f
= fopencookie(cookie
, "r", pakfire_archive_read_functions
);
726 CTX_ERROR(ctx
, "Could not open /%s: %m\n", cookie
->path
);
727 return PAKFIRE_WALK_ERROR
;
730 return PAKFIRE_WALK_DONE
;
733 PAKFIRE_EXPORT
FILE* pakfire_archive_read(struct pakfire_archive
* archive
, const char* path
, int flags
) {
734 struct pakfire_archive_read_cookie
* cookie
= NULL
;
737 // Check if path is absolute
738 if (!path
|| *path
!= '/') {
744 cookie
= calloc(1, sizeof(*cookie
));
746 CTX_ERROR(archive
->ctx
, "Could not allocate a cookie: %m\n");
750 // Store a reference to the archive
751 cookie
->archive
= pakfire_archive_ref(archive
);
754 cookie
->flags
= flags
;
757 r
= pakfire_string_set(cookie
->path
, path
);
759 CTX_ERROR(archive
->ctx
, "Could not set path: %m\n");
763 // Clone the archive file descriptor to read the file independently
764 cookie
->f
= pakfire_archive_clone_file(archive
);
766 CTX_ERROR(archive
->ctx
, "Could not duplicate file descriptor for %s: %m\n",
773 cookie
->a
= open_archive(archive
, cookie
->f
);
777 // Walk through the archive
778 r
= pakfire_walk(archive
->ctx
, cookie
->a
, __pakfire_archive_read
,
779 __pakfire_archive_read_filter
, cookie
);
784 archive_read_free(cookie
->a
);
796 CTX_ERROR(archive
->ctx
, "Could not find /%s\n", path
);
798 // No such file or directory
807 __pakfire_archive_cookie_close(cookie
);
812 int pakfire_archive_copy(struct pakfire_archive
* archive
, const char* path
) {
816 // Determine the file size
817 ssize_t size
= pakfire_archive_get_size(archive
);
821 CTX_DEBUG(archive
->ctx
, "Copying %s to %s...\n", archive
->path
, path
);
823 // Ensure we copy from the very beginning
826 // Ensure the parent directory exists
827 pakfire_mkparentdir(path
, 0755);
829 // Open destination file
830 FILE* f
= fopen(path
, "w");
837 ssize_t bytes_written
= sendfile(fileno(f
), fileno(archive
->f
), NULL
, size
);
838 if (bytes_written
< size
) {
839 CTX_ERROR(archive
->ctx
, "Could not copy archive (%zd byte(s) written): %m\n",
850 // Delete the file on error
857 static int pakfire_archive_link(struct pakfire_archive
* archive
, const char* path
) {
860 // Check if path is set
864 CTX_DEBUG(archive
->ctx
, "Linking %s to %s...\n", archive
->path
, path
);
866 // Delete the destination file (if it exists)
869 // Create the new link
870 r
= link(archive
->path
, path
);
872 CTX_DEBUG(archive
->ctx
, "Could not create hardlink %s: %m\n", path
);
879 int pakfire_archive_link_or_copy(struct pakfire_archive
* archive
, const char* path
) {
882 // Make sure the parent directory exists
883 r
= pakfire_mkparentdir(path
, 0755);
887 // Try to create a hardlink
888 r
= pakfire_archive_link(archive
, path
);
890 // Try to copy the file if we could not create a hardlink
892 r
= pakfire_archive_copy(archive
, path
);
901 static int __pakfire_archive_extract(struct pakfire_archive
* archive
,
902 const char* path
, int flags
) {
903 struct pakfire_filelist
* filelist
= NULL
;
904 struct pakfire_package
* pkg
= NULL
;
905 struct archive
* a
= NULL
;
906 char prefix
[PATH_MAX
] = "";
910 pkg
= pakfire_archive_get_package(archive
);
915 const char* nevra
= pakfire_package_get_string(pkg
, PAKFIRE_PKG_NEVRA
);
917 CTX_DEBUG(archive
->ctx
, "Extracting %s\n", archive
->path
);
919 // Copy everything to path if set
921 r
= pakfire_string_set(prefix
, path
);
925 // Set prefix for source packages
926 } else if (pakfire_package_is_source(pkg
)) {
927 r
= pakfire_path(archive
->pakfire
, prefix
, "/usr/src/packages/%s", nevra
);
931 // Otherwise extract relative to the pakfire root
933 r
= pakfire_path(archive
->pakfire
, prefix
, "%s", "/");
938 // Load the filelist (if not done already)
939 if (!archive
->filelist
) {
940 r
= pakfire_filelist_create(&filelist
, archive
->pakfire
);
946 a
= open_archive(archive
, NULL
);
953 r
= pakfire_extract(archive
->pakfire
, a
, archive
->stat
.st_size
,
954 filelist
, prefix
, nevra
, __pakfire_archive_filter_payload
, flags
);
958 // Store the filelist permanently
959 if (!archive
->filelist
)
960 archive
->filelist
= pakfire_filelist_ref(filelist
);
964 pakfire_filelist_unref(filelist
);
966 pakfire_package_unref(pkg
);
968 close_archive(archive
, a
);
973 PAKFIRE_EXPORT
int pakfire_archive_extract(struct pakfire_archive
* archive
,
974 const char* path
, const int flags
) {
975 return __pakfire_archive_extract(archive
, path
, flags
);
978 PAKFIRE_EXPORT
const char* pakfire_archive_get_path(struct pakfire_archive
* archive
) {
979 return archive
->path
;
982 PAKFIRE_EXPORT
unsigned int pakfire_archive_get_format(struct pakfire_archive
* archive
) {
983 return archive
->format
;
986 static int pakfire_archive_load_filelist(struct pakfire_archive
* archive
) {
987 // Perform a dry-run extraction
988 return __pakfire_archive_extract(archive
, NULL
,
989 PAKFIRE_EXTRACT_DRY_RUN
|PAKFIRE_EXTRACT_NO_PROGRESS
);
992 PAKFIRE_EXPORT
struct pakfire_filelist
* pakfire_archive_get_filelist(struct pakfire_archive
* archive
) {
993 if (!archive
->filelist
) {
994 int r
= pakfire_archive_load_filelist(archive
);
999 if (!archive
->filelist
)
1002 return pakfire_filelist_ref(archive
->filelist
);
1005 PAKFIRE_EXPORT
int pakfire_archive_verify(struct pakfire_archive
* archive
, int* status
) {
1006 // XXX currently not implemented
1010 PAKFIRE_EXPORT ssize_t
pakfire_archive_get_size(struct pakfire_archive
* archive
) {
1011 return archive
->stat
.st_size
;
1014 int pakfire_archive_check_digest(struct pakfire_archive
* archive
,
1015 const enum pakfire_digest_types type
, const unsigned char* digest
, const size_t length
) {
1016 size_t computed_length
= 0;
1019 // Compute the digest
1020 r
= pakfire_archive_compute_digests(archive
);
1024 // Compare computed with expected digest
1025 r
= pakfire_digests_compare_one(archive
->ctx
, &archive
->digests
, type
, digest
, length
);
1027 const unsigned char* computed_digest
= pakfire_digest_get(
1028 &archive
->digests
, type
, &computed_length
);
1030 char* expected_hexdigest
= __pakfire_hexlify(digest
, length
);
1031 char* computed_hexdigest
= __pakfire_hexlify(computed_digest
, computed_length
);
1033 CTX_ERROR(archive
->ctx
, "Archive digest does not match for %s:\n", archive
->path
);
1034 CTX_ERROR(archive
->ctx
, " Expected: %s\n", expected_hexdigest
);
1035 CTX_ERROR(archive
->ctx
, " Computed: %s\n", computed_hexdigest
);
1037 if (expected_hexdigest
)
1038 free(expected_hexdigest
);
1039 if (computed_hexdigest
)
1040 free(computed_hexdigest
);
1048 static int pakfire_archive_import_filelist_from_json(
1049 struct pakfire_archive
* archive
, struct pakfire_package
* package
) {
1050 struct json_object
* array
= NULL
;
1053 // Fetch the array with the filelist
1054 array
= pakfire_archive_metadata_get_object(archive
, "filelist", NULL
);
1056 CTX_ERROR(archive
->ctx
, "Archive has no filelist: %m\n");
1060 // Determine the length of the array
1061 const size_t length
= json_object_array_length(array
);
1063 // End here if the array is empty
1067 // Walk through all items in this array
1068 for (unsigned int i
= 0; i
< length
; i
++) {
1069 struct json_object
* item
= json_object_array_get_idx(array
, i
);
1073 // Extract the path value
1074 const char* path
= json_object_get_string(item
);
1078 // Append the file to the package
1079 r
= pakfire_package_append_file(package
, path
);
1087 static int pakfire_archive_make_package_from_json(struct pakfire_archive
* archive
,
1088 struct pakfire_repo
* repo
, struct pakfire_package
** package
) {
1089 struct pakfire_package
* pkg
= NULL
;
1093 r
= pakfire_archive_compute_digests(archive
);
1097 // Fetch the most basic package information
1098 const char* name
= pakfire_archive_metadata_get(archive
, "name", NULL
);
1099 const char* evr
= pakfire_archive_metadata_get(archive
, "evr", NULL
);
1100 const char* arch
= pakfire_archive_metadata_get(archive
, "arch", NULL
);
1102 // Create a new package object
1103 r
= pakfire_package_create(&pkg
, archive
->pakfire
, repo
, name
, evr
, arch
);
1108 const char* nevra
= pakfire_package_get_string(pkg
, PAKFIRE_PKG_NEVRA
);
1110 CTX_DEBUG(archive
->ctx
, "Created package %s (%p) from archive %p\n",
1111 nevra
, pkg
, archive
);
1115 pakfire_package_set_string(pkg
, PAKFIRE_PKG_PATH
, archive
->path
);
1118 switch (PAKFIRE_ARCHIVE_CHECKSUM
) {
1119 case PAKFIRE_DIGEST_SHA2_512
:
1120 pakfire_package_set_digest(pkg
, PAKFIRE_ARCHIVE_CHECKSUM
,
1121 archive
->digests
.sha2_512
, sizeof(archive
->digests
.sha2_512
));
1124 case PAKFIRE_DIGEST_SHA2_256
:
1125 pakfire_package_set_digest(pkg
, PAKFIRE_ARCHIVE_CHECKSUM
,
1126 archive
->digests
.sha2_256
, sizeof(archive
->digests
.sha2_256
));
1129 case PAKFIRE_DIGEST_UNDEFINED
:
1135 const char* vendor
= pakfire_archive_metadata_get(archive
, "vendor", NULL
);
1137 r
= pakfire_package_set_string(pkg
, PAKFIRE_PKG_VENDOR
, vendor
);
1143 const char* uuid
= pakfire_archive_metadata_get(archive
, "uuid", NULL
);
1145 r
= pakfire_package_set_string(pkg
, PAKFIRE_PKG_UUID
, uuid
);
1151 struct json_object
* groups
= pakfire_archive_metadata_get_object(archive
, "groups", NULL
);
1152 if (groups
&& json_object_is_type(groups
, json_type_array
)) {
1153 const size_t length
= json_object_array_length(groups
);
1155 for (unsigned int i
= 0; i
< length
; i
++) {
1156 struct json_object
* item
= json_object_array_get_idx(groups
, i
);
1160 const char* group
= json_object_get_string(item
);
1164 r
= pakfire_package_add_string(pkg
, PAKFIRE_PKG_GROUPS
, group
);
1171 const char* distro
= pakfire_archive_metadata_get(archive
, "distribution", NULL
);
1173 r
= pakfire_package_set_string(pkg
, PAKFIRE_PKG_DISTRO
, distro
);
1179 const char* packager
= pakfire_archive_metadata_get(archive
, "packager", NULL
);
1181 r
= pakfire_package_set_string(pkg
, PAKFIRE_PKG_PACKAGER
, packager
);
1187 const char* url
= pakfire_archive_metadata_get(archive
, "url", NULL
);
1189 r
= pakfire_package_set_string(pkg
, PAKFIRE_PKG_URL
, url
);
1195 const char* license
= pakfire_archive_metadata_get(archive
, "license", NULL
);
1197 r
= pakfire_package_set_string(pkg
, PAKFIRE_PKG_LICENSE
, license
);
1203 const char* summary
= pakfire_archive_metadata_get(archive
, "summary", NULL
);
1205 r
= pakfire_package_set_string(pkg
, PAKFIRE_PKG_SUMMARY
, summary
);
1211 const char* description
= pakfire_archive_metadata_get(archive
, "description", NULL
);
1213 r
= pakfire_package_set_string(pkg
, PAKFIRE_PKG_DESCRIPTION
, description
);
1218 // Installed package size
1219 size_t installsize
= pakfire_archive_metadata_get_int64(archive
, "size", NULL
);
1221 r
= pakfire_package_set_num(pkg
, PAKFIRE_PKG_INSTALLSIZE
, installsize
);
1227 r
= pakfire_package_set_num(pkg
,
1228 PAKFIRE_PKG_DOWNLOADSIZE
, pakfire_archive_get_size(archive
));
1233 const char* build_host
= pakfire_archive_metadata_get(archive
, "build", "host");
1235 r
= pakfire_package_set_string(pkg
, PAKFIRE_PKG_BUILD_HOST
, build_host
);
1241 const char* build_id
= pakfire_archive_metadata_get(archive
, "build", "id");
1243 r
= pakfire_package_set_string(pkg
, PAKFIRE_PKG_BUILD_ID
, build_id
);
1249 time_t build_time
= pakfire_archive_metadata_get_int64(archive
, "build", "time");
1251 r
= pakfire_package_set_num(pkg
, PAKFIRE_PKG_BUILD_TIME
, build_time
);
1257 struct json_object
* build_arches
= pakfire_archive_metadata_get_object(archive
, "build", "arches");
1258 if (build_arches
&& json_object_is_type(build_arches
, json_type_array
)) {
1259 const size_t length
= json_object_array_length(build_arches
);
1261 for (unsigned int i
= 0; i
< length
; i
++) {
1262 struct json_object
* item
= json_object_array_get_idx(build_arches
, i
);
1266 const char* build_arch
= json_object_get_string(item
);
1270 r
= pakfire_package_add_string(pkg
, PAKFIRE_PKG_BUILD_ARCHES
, build_arch
);
1277 const char* source_name
= pakfire_archive_metadata_get(archive
, "build", "source-name");
1279 r
= pakfire_package_set_string(pkg
, PAKFIRE_PKG_SOURCE_NAME
, source_name
);
1285 const char* source_evr
= pakfire_archive_metadata_get(archive
, "build", "source-evr");
1287 r
= pakfire_package_set_string(pkg
, PAKFIRE_PKG_SOURCE_EVR
, source_evr
);
1293 const char* source_arch
= pakfire_archive_metadata_get(archive
, "build", "source-arch");
1295 r
= pakfire_package_set_string(pkg
, PAKFIRE_PKG_SOURCE_ARCH
, source_arch
);
1301 for (const struct pakfire_dep
* dep
= pakfire_deps
; dep
->key
; dep
++) {
1302 struct json_object
* array
= pakfire_archive_metadata_get_object(
1303 archive
, "dependencies", dep
->name
);
1307 // Determine the length of the array
1308 const size_t length
= json_object_array_length(array
);
1312 // Walk through all items in this array
1313 for (unsigned int i
= 0; i
< length
; i
++) {
1314 struct json_object
* item
= json_object_array_get_idx(array
, i
);
1318 // Extract the string value
1319 const char* string
= json_object_get_string(item
);
1323 // Add the dependency to the package
1324 r
= pakfire_package_add_dep(pkg
, dep
->key
, string
);
1330 // Import the filelist
1331 r
= pakfire_archive_import_filelist_from_json(archive
, pkg
);
1344 Copy all metadata from this archive to the package object
1346 PAKFIRE_EXPORT
int pakfire_archive_make_package(struct pakfire_archive
* archive
,
1347 struct pakfire_repo
* repo
, struct pakfire_package
** package
) {
1348 struct pakfire_repo
* dummy
= NULL
;
1351 // Use dummy repo if no repository was passed
1353 dummy
= pakfire_get_repo(archive
->pakfire
, PAKFIRE_REPO_DUMMY
);
1360 // Make package from JSON metadata
1361 r
= pakfire_archive_make_package_from_json(archive
, repo
, package
);
1363 // Free dummy repository
1365 pakfire_repo_unref(dummy
);
1370 struct pakfire_scriptlet
* pakfire_archive_get_scriptlet(
1371 struct pakfire_archive
* archive
, const char* type
) {
1372 struct pakfire_scriptlet
* scriptlet
= NULL
;
1374 for (unsigned int i
= 0; i
< archive
->num_scriptlets
; i
++) {
1375 scriptlet
= archive
->scriptlets
[i
];
1378 const char* t
= pakfire_scriptlet_get_type(scriptlet
);
1381 if (strcmp(t
, type
) == 0)
1382 return pakfire_scriptlet_ref(scriptlet
);
1391 static int __pakfire_archive_filter_systemd_sysusers(struct pakfire_ctx
* ctx
,
1392 struct archive
* a
, struct archive_entry
* e
, void* data
) {
1393 const char* path
= archive_entry_pathname(e
);
1395 if (!pakfire_path_match("usr/lib/sysusers.d/*.conf", path
))
1396 return PAKFIRE_WALK_SKIP
;
1398 return PAKFIRE_WALK_OK
;
1401 static int pakfire_archive_stream_payload(struct pakfire
* pakfire
, void* data
, int fd
) {
1404 struct archive
* a
= (struct archive
*)data
;
1406 // Read a block from the input archive
1407 ssize_t bytes_read
= archive_read_data(a
, buffer
, sizeof(buffer
));
1408 if (bytes_read
< 0) {
1409 ERROR(pakfire
, "Could not read from archive: %s\n", archive_error_string(a
));
1413 // We have consumed everything
1414 if (bytes_read
== 0)
1417 // Write the data to the output file descriptor
1418 ssize_t bytes_written
= write(fd
, buffer
, bytes_read
);
1419 if (bytes_written
< 0) {
1420 ERROR(pakfire
, "Could not stream output: %m\n");
1427 static int __pakfire_archive_handle_systemd_sysusers(struct pakfire_ctx
* ctx
,
1428 struct archive
* a
, struct archive_entry
* e
, void* data
) {
1429 struct pakfire_jail
* jail
= NULL
;
1430 char replace
[PATH_MAX
];
1433 struct pakfire
* pakfire
= data
;
1436 const char* path
= archive_entry_pathname(e
);
1439 r
= pakfire_string_format(replace
, "--replace=/%s", path
);
1443 const char* argv
[] = { "/usr/bin/systemd-sysusers", replace
, "-", NULL
};
1445 // Create a new jail
1446 r
= pakfire_jail_create(&jail
, pakfire
);
1450 r
= pakfire_jail_exec(jail
, argv
, pakfire_archive_stream_payload
, NULL
, a
,
1451 PAKFIRE_JAIL_NOENT_OK
);
1455 pakfire_jail_unref(jail
);
1460 int pakfire_archive_apply_systemd_sysusers(struct pakfire_archive
* archive
) {
1461 pakfire_archive_walk(archive
,
1462 __pakfire_archive_handle_systemd_sysusers
,
1463 __pakfire_archive_filter_systemd_sysusers
,