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/dependencies.h>
39 #include <pakfire/digest.h>
40 #include <pakfire/file.h>
41 #include <pakfire/filelist.h>
42 #include <pakfire/i18n.h>
43 #include <pakfire/jail.h>
44 #include <pakfire/logging.h>
45 #include <pakfire/package.h>
46 #include <pakfire/pakfire.h>
47 #include <pakfire/private.h>
48 #include <pakfire/repo.h>
49 #include <pakfire/scriptlet.h>
50 #include <pakfire/string.h>
51 #include <pakfire/util.h>
53 #define MAX_SCRIPTLETS 9
55 struct pakfire_archive
{
56 struct pakfire
* pakfire
;
63 struct pakfire_package
* package
;
67 struct json_object
* metadata
;
69 struct pakfire_filelist
* filelist
;
72 struct pakfire_scriptlet
* scriptlets
[MAX_SCRIPTLETS
];
73 unsigned int num_scriptlets
;
76 struct pakfire_digests digests
;
82 static FILE* pakfire_archive_clone_file(struct pakfire_archive
* archive
) {
83 int fd
= fileno(archive
->f
);
85 ERROR(archive
->pakfire
, "Could not fetch the archive's file descriptor: %m\n");
89 // Duplicate the file descriptor
92 ERROR(archive
->pakfire
, "Could not duplicate the file descriptor: %m\n");
96 // Re-open a file handle
97 return fdopen(fd
, "r");
100 static int pakfire_archive_compute_digests(struct pakfire_archive
* archive
) {
103 // Start reading at the beginning
107 r
= pakfire_digests_compute_from_file(archive
->pakfire
, &archive
->digests
,
108 PAKFIRE_ARCHIVE_CHECKSUM
, archive
->f
);
110 ERROR(archive
->pakfire
, "Could not calculate digest of %s: %m\n", archive
->path
);
116 A helper function to close the archive and reset our data structures
118 static void close_archive(struct pakfire_archive
* archive
, struct archive
* a
) {
120 archive_read_free(a
);
124 A helper function that opens the archive for reading
126 static struct archive
* open_archive(struct pakfire_archive
* archive
, FILE* f
) {
127 // If no special file descriptor has been given we use the open one
131 // Create a new archive object
132 struct archive
* a
= archive_read_new();
136 // Archives must be uncompressed tarballs
137 archive_read_support_format_tar(a
);
139 // Archives are compressed using Zstandard
140 archive_read_support_filter_zstd(a
);
142 // Start reading from the beginning
145 // Try opening the archive file
146 int r
= archive_read_open_FILE(a
, f
);
148 ERROR(archive
->pakfire
, "Could not open archive %s: %s\n",
149 archive
->path
, archive_error_string(a
));
157 close_archive(archive
, a
);
162 static int pakfire_archive_walk(struct pakfire_archive
* archive
,
163 pakfire_walk_callback callback
, pakfire_walk_filter_callback filter_callback
, void* data
) {
166 // Open the archive file
167 struct archive
* a
= open_archive(archive
, NULL
);
171 // Walk through the archive
172 r
= pakfire_walk(archive
->pakfire
, a
, callback
, filter_callback
, data
);
176 close_archive(archive
, a
);
181 static void pakfire_archive_free(struct pakfire_archive
* archive
) {
187 for (unsigned int i
= 0; i
< archive
->num_scriptlets
; i
++)
188 pakfire_scriptlet_unref(archive
->scriptlets
[i
]);
190 if (archive
->filelist
)
191 pakfire_filelist_unref(archive
->filelist
);
192 if (archive
->package
)
193 pakfire_package_unref(archive
->package
);
194 if (archive
->metadata
)
195 json_object_put(archive
->metadata
);
196 pakfire_unref(archive
->pakfire
);
200 static int pakfire_archive_create(struct pakfire_archive
** archive
, struct pakfire
* pakfire
) {
201 struct pakfire_archive
* a
= calloc(1, sizeof(*a
));
205 a
->pakfire
= pakfire_ref(pakfire
);
212 PAKFIRE_EXPORT
struct pakfire_archive
* pakfire_archive_ref(struct pakfire_archive
* archive
) {
218 PAKFIRE_EXPORT
struct pakfire_archive
* pakfire_archive_unref(struct pakfire_archive
* archive
) {
219 if (--archive
->nrefs
> 0)
222 pakfire_archive_free(archive
);
227 static struct pakfire_package
* pakfire_archive_get_package(struct pakfire_archive
* archive
) {
228 if (!archive
->package
) {
229 int r
= pakfire_archive_make_package(archive
, NULL
, &archive
->package
);
234 return pakfire_package_ref(archive
->package
);
239 static int pakfire_archive_parse_json_metadata(struct pakfire_archive
* archive
,
240 const char* data
, const size_t length
) {
244 struct json_tokener
* tokener
= json_tokener_new();
246 ERROR(archive
->pakfire
, "Could not allocate JSON tokener: %m\n");
250 // Parse JSON from buffer
251 archive
->metadata
= json_tokener_parse_ex(tokener
, data
, length
);
252 if (!archive
->metadata
) {
253 enum json_tokener_error error
= json_tokener_get_error(tokener
);
255 ERROR(archive
->pakfire
, "JSON parsing error: %s\n",
256 json_tokener_error_desc(error
));
260 DEBUG(archive
->pakfire
, "Successfully parsed package metadata:\n%s\n",
261 json_object_to_json_string_ext(archive
->metadata
,
262 JSON_C_TO_STRING_PRETTY
|JSON_C_TO_STRING_PRETTY_TAB
));
269 json_tokener_free(tokener
);
274 static int pakfire_archive_parse_format(struct pakfire_archive
* archive
,
275 const char* data
, const size_t length
) {
276 // Check if format has already been set
277 if (archive
->format
) {
278 ERROR(archive
->pakfire
, "Archive format has already been parsed\n");
284 archive
->format
= strtoul(data
, NULL
, 10);
286 switch (archive
->format
) {
287 // Handle all supported formats
291 // Break on anything else
293 ERROR(archive
->pakfire
, "This version of Pakfire does not support "
294 "archive format %d\n", archive
->format
);
299 DEBUG(archive
->pakfire
, "Archive format is %d\n", archive
->format
);
304 static int pakfire_archive_parse_scriptlet(struct pakfire_archive
* archive
,
305 const char* path
, const char* data
, const size_t length
) {
306 struct pakfire_scriptlet
* scriptlet
= NULL
;
307 const char* type
= NULL
;
310 // Check for any available space
311 if (archive
->num_scriptlets
>= MAX_SCRIPTLETS
) {
312 ERROR(archive
->pakfire
, "Too many scriptlets\n");
318 type
= pakfire_path_relpath(".scriptlets/", path
);
320 ERROR(archive
->pakfire
, "Could not determine the scriptlet type from '%s'\n", path
);
325 // Allocate a scriptlet
326 r
= pakfire_scriptlet_create(&scriptlet
, archive
->pakfire
, type
, data
, length
);
331 archive
->scriptlets
[archive
->num_scriptlets
++] = scriptlet
;
336 static int __pakfire_archive_read_metadata(struct pakfire
* pakfire
, struct archive
* a
,
337 struct archive_entry
* entry
, void* p
) {
338 struct pakfire_archive
* archive
= (struct pakfire_archive
*)p
;
344 const char* path
= archive_entry_pathname(entry
);
346 DEBUG(pakfire
, "Reading metadata file: %s\n", path
);
348 // Load the file into memory
349 r
= pakfire_archive_copy_data_to_buffer(archive
->pakfire
, a
, entry
, &data
, &length
);
351 ERROR(archive
->pakfire
, "Could not read data from archive: %s\n",
352 archive_error_string(a
));
357 if (archive
->format
>= 6) {
359 if (strcmp(path
, ".PKGINFO") == 0) {
360 r
= pakfire_archive_parse_json_metadata(archive
, data
, length
);
365 } else if (pakfire_string_startswith(path
, ".scriptlets/")) {
366 r
= pakfire_archive_parse_scriptlet(archive
, path
, data
, length
);
372 } else if (strcmp(path
, "pakfire-format") == 0) {
373 r
= pakfire_archive_parse_format(archive
, data
, length
);
385 static int __pakfire_archive_filter_metadata(struct pakfire
* pakfire
,
386 struct archive
* a
, struct archive_entry
* entry
, void* p
) {
387 struct pakfire_archive
* archive
= (struct pakfire_archive
*)p
;
389 const char* path
= archive_entry_pathname(entry
);
392 if (archive
->format
>= 6) {
393 // Anything that starts with "." is a metadata file
395 return PAKFIRE_WALK_OK
;
397 // Otherwise, the payload begins
398 return PAKFIRE_WALK_END
;
400 // The pakfire-format file is part of the metadata
401 } else if (strcmp(path
, "pakfire-format") == 0) {
402 return PAKFIRE_WALK_OK
;
406 return PAKFIRE_WALK_ERROR
;
409 static int pakfire_archive_read_metadata(struct pakfire_archive
* archive
) {
412 // Check if the archive file actually has any contect
413 if (!archive
->stat
.st_size
) {
414 ERROR(archive
->pakfire
, "Trying to open an empty archive file\n");
419 DEBUG(archive
->pakfire
, "Reading archive metadata...\n");
421 // Walk through the archive
422 r
= pakfire_archive_walk(archive
, __pakfire_archive_read_metadata
,
423 __pakfire_archive_filter_metadata
, archive
);
427 // Check if we could successfully read something
428 if (!archive
->format
) {
429 ERROR(archive
->pakfire
, "Archive has an unknown format\n");
434 // Check if we have read some metadata
435 if (!archive
->metadata
) {
436 ERROR(archive
->pakfire
, "Archive has no metadata\n");
444 static int pakfire_archive_try_open(struct pakfire_archive
* archive
, const char* path
) {
452 DEBUG(archive
->pakfire
, "Opening archive %s\n", path
);
455 pakfire_string_set(archive
->path
, path
);
457 // Open the file (and keep the file descriptor open)
458 archive
->f
= fopen(archive
->path
, "r");
462 // Let the kernel know, that we will read the file sequentially
463 r
= posix_fadvise(fileno(archive
->f
), 0, 0, POSIX_FADV_SEQUENTIAL
);
465 ERROR(archive
->pakfire
, "posix_fadvise() failed: %m\n");
470 r
= fstat(fileno(archive
->f
), &archive
->stat
);
472 ERROR(archive
->pakfire
, "Could not stat archive: %m\n");
476 // Read all package metadata
477 r
= pakfire_archive_read_metadata(archive
);
479 ERROR(archive
->pakfire
, "Could not open archive: %m\n");
487 PAKFIRE_EXPORT
int pakfire_archive_open(struct pakfire_archive
** archive
, struct pakfire
* pakfire
, const char* path
) {
488 int r
= pakfire_archive_create(archive
, pakfire
);
492 r
= pakfire_archive_try_open(*archive
, path
);
499 pakfire_archive_unref(*archive
);
505 static struct json_object
* pakfire_archive_metadata_get_object(
506 struct pakfire_archive
* archive
, const char* key1
, const char* key2
) {
507 struct json_object
* object
= archive
->metadata
;
510 const char* keys
[] = {
516 // Walk through all keys
517 for (const char** key
= keys
; *key
; key
++) {
518 // Try finding a matching JSON object
519 r
= json_object_object_get_ex(object
, *key
, &object
);
521 DEBUG(archive
->pakfire
, "Could not find JSON object at '%s': %m\n", *key
);
529 static const char* pakfire_archive_metadata_get(
530 struct pakfire_archive
* archive
, const char* key1
, const char* key2
) {
531 // Try finding an object
532 struct json_object
* object
= pakfire_archive_metadata_get_object(archive
, key1
, key2
);
536 // Return the object as string
537 return json_object_get_string(object
);
540 static int64_t pakfire_archive_metadata_get_int64(
541 struct pakfire_archive
* archive
, const char* key1
, const char* key2
) {
542 // Try finding an object
543 struct json_object
* object
= pakfire_archive_metadata_get_object(archive
, key1
, key2
);
547 // Return the object as integer
548 return json_object_get_int64(object
);
551 static int __pakfire_archive_filter_payload(struct pakfire
* pakfire
,
552 struct archive
* a
, struct archive_entry
* entry
, void* p
) {
553 const char* path
= archive_entry_pathname(entry
);
555 return PAKFIRE_WALK_ERROR
;
559 if (strcmp(path
, "pakfire-format") == 0)
560 return PAKFIRE_WALK_SKIP
;
565 return PAKFIRE_WALK_SKIP
;
567 // The first file that isn't metadata, so we are done calling the filter callback
569 return PAKFIRE_WALK_DONE
;
574 Read files from the archive
576 struct pakfire_archive_read_cookie
{
577 // A reference to the archive
578 struct pakfire_archive
* archive
;
580 // A copy of the underlying file descriptor
583 // The opened archive
587 static ssize_t
__pakfire_archive_cookie_read(void* c
, char* buffer
, size_t size
) {
588 struct pakfire_archive_read_cookie
* cookie
= (struct pakfire_archive_read_cookie
*)c
;
590 // Read the data directly from the archive
591 return archive_read_data(cookie
->a
, buffer
, size
);
594 static int __pakfire_archive_cookie_close(void* c
) {
595 struct pakfire_archive_read_cookie
* cookie
= (struct pakfire_archive_read_cookie
*)c
;
598 pakfire_archive_unref(cookie
->archive
);
600 archive_read_free(cookie
->a
);
610 static cookie_io_functions_t pakfire_archive_read_functions
= {
611 .read
= __pakfire_archive_cookie_read
,
612 .close
= __pakfire_archive_cookie_close
,
615 PAKFIRE_EXPORT
FILE* pakfire_archive_read(struct pakfire_archive
* archive
, const char* path
) {
616 struct pakfire_archive_read_cookie
* cookie
= NULL
;
620 // Check if path is absolute
621 if (!path
|| *path
!= '/') {
626 // Strip leading / from filenames, because tarballs don't use any leading slashes
627 path
= pakfire_path_relpath("/", path
);
632 cookie
= calloc(1, sizeof(*cookie
));
634 ERROR(archive
->pakfire
, "Could not allocate a cookie: %m\n");
638 // Store a reference to the archive
639 cookie
->archive
= pakfire_archive_ref(archive
);
641 // Clone the archive file descriptor to read the file independently
642 cookie
->f
= pakfire_archive_clone_file(archive
);
644 ERROR(archive
->pakfire
, "Could not duplicate file descriptor for %s: %m\n",
650 cookie
->a
= open_archive(archive
, cookie
->f
);
654 // Tries to find a matching file in the archive
655 int __pakfire_archive_read_filter(struct pakfire
* pakfire
, struct archive
* a
,
656 struct archive_entry
* e
, void* data
) {
657 // Stop reading the archive after we have found our file
659 return PAKFIRE_WALK_END
;
662 const char* p
= archive_entry_pathname(e
);
664 return PAKFIRE_WALK_ERROR
;
667 if (strcmp(path
, p
) == 0)
668 return PAKFIRE_WALK_OK
;
670 // Otherwise we skip the file
671 return PAKFIRE_WALK_SKIP
;
674 // Reads a matching file into memory
675 int __pakfire_archive_read(struct pakfire
* pakfire
, struct archive
* a
,
676 struct archive_entry
* e
, void* data
) {
677 // Create a file descriptor
678 f
= fopencookie(cookie
, "r", pakfire_archive_read_functions
);
680 ERROR(pakfire
, "Could not open /%s: %m\n", path
);
681 return PAKFIRE_WALK_ERROR
;
684 return PAKFIRE_WALK_DONE
;
687 // Walk through the archive
688 r
= pakfire_walk(archive
->pakfire
, cookie
->a
,
689 __pakfire_archive_read
, __pakfire_archive_read_filter
, NULL
);
695 ERROR(archive
->pakfire
, "Could not find /%s\n", path
);
697 // No such file or directory
706 __pakfire_archive_cookie_close(cookie
);
711 int pakfire_archive_copy(struct pakfire_archive
* archive
, const char* path
) {
717 // Determine the file size
718 ssize_t size
= pakfire_archive_get_size(archive
);
722 DEBUG(archive
->pakfire
, "Copying %s to %s...\n", archive
->path
, path
);
724 // Ensure we copy from the very beginning
727 // Ensure the parent directory exists
728 pakfire_mkparentdir(path
, 0755);
730 // Open destination file
731 FILE* f
= fopen(path
, "w");
738 ssize_t bytes_written
= sendfile(fileno(f
), fileno(archive
->f
), NULL
, size
);
739 if (bytes_written
< size
) {
740 ERROR(archive
->pakfire
, "Could not copy archive (%zu byte(s) written): %m\n",
751 // Delete the file on error
758 static int pakfire_archive_link(struct pakfire_archive
* archive
, const char* path
) {
761 // Check if path is set
767 DEBUG(archive
->pakfire
, "Linking %s to %s...\n", archive
->path
, path
);
769 // Delete the destination file (if it exists)
772 // Create the new link
773 r
= link(archive
->path
, path
);
775 DEBUG(archive
->pakfire
, "Could not create hardlink %s: %m\n", path
);
782 int pakfire_archive_link_or_copy(struct pakfire_archive
* archive
, const char* path
) {
785 // Try to create a hardlink
786 r
= pakfire_archive_link(archive
, path
);
789 // Try to copy the file if we could not create a hardlink
791 r
= pakfire_archive_copy(archive
, path
);
801 static int __pakfire_archive_extract(struct pakfire_archive
* archive
, int flags
) {
802 struct pakfire_filelist
* filelist
= NULL
;
803 struct pakfire_package
* pkg
= NULL
;
804 struct archive
* a
= NULL
;
805 char prefix
[PATH_MAX
] = "";
809 pkg
= pakfire_archive_get_package(archive
);
814 const char* nevra
= pakfire_package_get_string(pkg
, PAKFIRE_PKG_NEVRA
);
816 DEBUG(archive
->pakfire
, "Extracting %s\n", archive
->path
);
818 // Set prefix for source packages
819 if (pakfire_package_is_source(pkg
)) {
820 r
= pakfire_string_format(prefix
, "/usr/src/packages/%s", nevra
);
825 // Load the filelist (if not done already)
826 if (!archive
->filelist
) {
827 r
= pakfire_filelist_create(&filelist
, archive
->pakfire
);
833 a
= open_archive(archive
, NULL
);
840 r
= pakfire_extract(archive
->pakfire
, a
, archive
->stat
.st_size
,
841 filelist
, prefix
, nevra
, __pakfire_archive_filter_payload
, flags
);
845 // Store the filelist permanently
846 if (!archive
->filelist
)
847 archive
->filelist
= pakfire_filelist_ref(filelist
);
851 pakfire_filelist_unref(filelist
);
853 pakfire_package_unref(pkg
);
855 close_archive(archive
, a
);
860 PAKFIRE_EXPORT
int pakfire_archive_extract(struct pakfire_archive
* archive
) {
861 return __pakfire_archive_extract(archive
, 0);
864 PAKFIRE_EXPORT
const char* pakfire_archive_get_path(struct pakfire_archive
* archive
) {
865 return archive
->path
;
868 PAKFIRE_EXPORT
unsigned int pakfire_archive_get_format(struct pakfire_archive
* archive
) {
869 return archive
->format
;
872 static int pakfire_archive_load_filelist(struct pakfire_archive
* archive
) {
873 // Perform a dry-run extraction
874 return __pakfire_archive_extract(archive
,
875 PAKFIRE_EXTRACT_DRY_RUN
|PAKFIRE_EXTRACT_NO_PROGRESS
);
878 PAKFIRE_EXPORT
struct pakfire_filelist
* pakfire_archive_get_filelist(struct pakfire_archive
* archive
) {
879 if (!archive
->filelist
) {
880 int r
= pakfire_archive_load_filelist(archive
);
885 if (!archive
->filelist
)
888 return pakfire_filelist_ref(archive
->filelist
);
891 PAKFIRE_EXPORT
int pakfire_archive_verify(struct pakfire_archive
* archive
, int* status
) {
892 // XXX currently not implemented
896 PAKFIRE_EXPORT ssize_t
pakfire_archive_get_size(struct pakfire_archive
* archive
) {
897 return archive
->stat
.st_size
;
900 int pakfire_archive_check_digest(struct pakfire_archive
* archive
,
901 const enum pakfire_digest_types type
, const unsigned char* digest
, const size_t length
) {
902 size_t computed_length
= 0;
905 // Compute the digest
906 r
= pakfire_archive_compute_digests(archive
);
910 // Compare computed with expected digest
911 r
= pakfire_digests_compare_one(archive
->pakfire
, &archive
->digests
,
912 type
, digest
, length
);
914 const unsigned char* computed_digest
= pakfire_digest_get(
915 &archive
->digests
, type
, &computed_length
);
917 char* expected_hexdigest
= __pakfire_hexlify(digest
, length
);
918 char* computed_hexdigest
= __pakfire_hexlify(computed_digest
, computed_length
);
920 ERROR(archive
->pakfire
, "Archive digest does not match for %s:\n", archive
->path
);
921 ERROR(archive
->pakfire
, " Expected: %s\n", expected_hexdigest
);
922 ERROR(archive
->pakfire
, " Computed: %s\n", computed_hexdigest
);
924 if (expected_hexdigest
)
925 free(expected_hexdigest
);
926 if (computed_hexdigest
)
927 free(computed_hexdigest
);
935 static int pakfire_archive_import_filelist_from_json(
936 struct pakfire_archive
* archive
, struct pakfire_package
* package
) {
937 struct json_object
* array
= NULL
;
940 // Fetch the array with the filelist
941 array
= pakfire_archive_metadata_get_object(archive
, "filelist", NULL
);
943 ERROR(archive
->pakfire
, "Archive has no filelist: %m\n");
947 // Determine the length of the array
948 const size_t length
= json_object_array_length(array
);
950 // End here if the array is empty
954 // Walk through all items in this array
955 for (unsigned int i
= 0; i
< length
; i
++) {
956 struct json_object
* item
= json_object_array_get_idx(array
, i
);
960 // Extract the path value
961 const char* path
= json_object_get_string(item
);
965 // Append the file to the package
966 r
= pakfire_package_append_file(package
, path
);
974 static int pakfire_archive_make_package_from_json(struct pakfire_archive
* archive
,
975 struct pakfire_repo
* repo
, struct pakfire_package
** package
) {
976 struct pakfire_package
* pkg
= NULL
;
980 r
= pakfire_archive_compute_digests(archive
);
984 // Fetch the most basic package information
985 const char* name
= pakfire_archive_metadata_get(archive
, "name", NULL
);
986 const char* evr
= pakfire_archive_metadata_get(archive
, "evr", NULL
);
987 const char* arch
= pakfire_archive_metadata_get(archive
, "arch", NULL
);
989 // Create a new package object
990 r
= pakfire_package_create(&pkg
, archive
->pakfire
, repo
, name
, evr
, arch
);
995 const char* nevra
= pakfire_package_get_string(pkg
, PAKFIRE_PKG_NEVRA
);
997 DEBUG(archive
->pakfire
, "Created package %s (%p) from archive %p\n",
998 nevra
, pkg
, archive
);
1002 pakfire_package_set_string(pkg
, PAKFIRE_PKG_PATH
, archive
->path
);
1005 switch (PAKFIRE_ARCHIVE_CHECKSUM
) {
1006 case PAKFIRE_DIGEST_SHA2_512
:
1007 pakfire_package_set_digest(pkg
, PAKFIRE_ARCHIVE_CHECKSUM
,
1008 archive
->digests
.sha2_512
, sizeof(archive
->digests
.sha2_512
));
1011 case PAKFIRE_DIGEST_SHA2_256
:
1012 pakfire_package_set_digest(pkg
, PAKFIRE_ARCHIVE_CHECKSUM
,
1013 archive
->digests
.sha2_256
, sizeof(archive
->digests
.sha2_256
));
1016 case PAKFIRE_DIGEST_UNDEFINED
:
1022 const char* vendor
= pakfire_archive_metadata_get(archive
, "vendor", NULL
);
1024 r
= pakfire_package_set_string(pkg
, PAKFIRE_PKG_VENDOR
, vendor
);
1030 const char* uuid
= pakfire_archive_metadata_get(archive
, "uuid", NULL
);
1032 r
= pakfire_package_set_string(pkg
, PAKFIRE_PKG_UUID
, uuid
);
1038 const char* groups
= pakfire_archive_metadata_get(archive
, "groups", NULL
);
1040 r
= pakfire_package_set_string(pkg
, PAKFIRE_PKG_GROUPS
, groups
);
1046 const char* distro
= pakfire_archive_metadata_get(archive
, "distribution", NULL
);
1048 r
= pakfire_package_set_string(pkg
, PAKFIRE_PKG_DISTRO
, distro
);
1054 const char* packager
= pakfire_archive_metadata_get(archive
, "packager", NULL
);
1056 r
= pakfire_package_set_string(pkg
, PAKFIRE_PKG_PACKAGER
, packager
);
1062 const char* url
= pakfire_archive_metadata_get(archive
, "url", NULL
);
1064 r
= pakfire_package_set_string(pkg
, PAKFIRE_PKG_URL
, url
);
1070 const char* license
= pakfire_archive_metadata_get(archive
, "license", NULL
);
1072 r
= pakfire_package_set_string(pkg
, PAKFIRE_PKG_LICENSE
, license
);
1078 const char* summary
= pakfire_archive_metadata_get(archive
, "summary", NULL
);
1080 r
= pakfire_package_set_string(pkg
, PAKFIRE_PKG_SUMMARY
, summary
);
1086 const char* description
= pakfire_archive_metadata_get(archive
, "description", NULL
);
1088 r
= pakfire_package_set_string(pkg
, PAKFIRE_PKG_DESCRIPTION
, description
);
1093 // Installed package size
1094 size_t installsize
= pakfire_archive_metadata_get_int64(archive
, "size", NULL
);
1096 r
= pakfire_package_set_num(pkg
, PAKFIRE_PKG_INSTALLSIZE
, installsize
);
1102 r
= pakfire_package_set_num(pkg
,
1103 PAKFIRE_PKG_DOWNLOADSIZE
, pakfire_archive_get_size(archive
));
1108 const char* build_host
= pakfire_archive_metadata_get(archive
, "build", "host");
1110 r
= pakfire_package_set_string(pkg
, PAKFIRE_PKG_BUILD_HOST
, build_host
);
1116 const char* build_id
= pakfire_archive_metadata_get(archive
, "build", "id");
1118 r
= pakfire_package_set_string(pkg
, PAKFIRE_PKG_BUILD_ID
, build_id
);
1124 time_t build_time
= pakfire_archive_metadata_get_int64(archive
, "build", "time");
1126 r
= pakfire_package_set_num(pkg
, PAKFIRE_PKG_BUILD_TIME
, build_time
);
1132 const char* source_name
= pakfire_archive_metadata_get(archive
, "build", "source-name");
1134 r
= pakfire_package_set_string(pkg
, PAKFIRE_PKG_SOURCE_NAME
, source_name
);
1140 const char* source_evr
= pakfire_archive_metadata_get(archive
, "build", "source-evr");
1142 r
= pakfire_package_set_string(pkg
, PAKFIRE_PKG_SOURCE_EVR
, source_evr
);
1148 const char* source_arch
= pakfire_archive_metadata_get(archive
, "build", "source-arch");
1150 r
= pakfire_package_set_string(pkg
, PAKFIRE_PKG_SOURCE_ARCH
, source_arch
);
1156 for (const struct pakfire_dep
* dep
= pakfire_deps
; dep
->key
; dep
++) {
1157 struct json_object
* array
= pakfire_archive_metadata_get_object(
1158 archive
, "dependencies", dep
->name
);
1162 // Determine the length of the array
1163 const size_t length
= json_object_array_length(array
);
1167 // Walk through all items in this array
1168 for (unsigned int i
= 0; i
< length
; i
++) {
1169 struct json_object
* item
= json_object_array_get_idx(array
, i
);
1173 // Extract the string value
1174 const char* string
= json_object_get_string(item
);
1178 // Add the dependency to the package
1179 r
= pakfire_package_add_dep(pkg
, dep
->key
, string
);
1185 // Import the filelist
1186 r
= pakfire_archive_import_filelist_from_json(archive
, pkg
);
1199 Copy all metadata from this archive to the package object
1201 PAKFIRE_EXPORT
int pakfire_archive_make_package(struct pakfire_archive
* archive
,
1202 struct pakfire_repo
* repo
, struct pakfire_package
** package
) {
1203 struct pakfire_repo
* dummy
= NULL
;
1206 // Use dummy repo if no repository was passed
1208 dummy
= pakfire_get_repo(archive
->pakfire
, PAKFIRE_REPO_DUMMY
);
1215 // Make package from JSON metadata
1216 r
= pakfire_archive_make_package_from_json(archive
, repo
, package
);
1218 // Free dummy repository
1220 pakfire_repo_unref(dummy
);
1225 struct pakfire_scriptlet
* pakfire_archive_get_scriptlet(
1226 struct pakfire_archive
* archive
, const char* type
) {
1227 struct pakfire_scriptlet
* scriptlet
= NULL
;
1229 for (unsigned int i
= 0; i
< archive
->num_scriptlets
; i
++) {
1230 scriptlet
= archive
->scriptlets
[i
];
1233 const char* t
= pakfire_scriptlet_get_type(scriptlet
);
1236 if (strcmp(t
, type
) == 0)
1237 return pakfire_scriptlet_ref(scriptlet
);
1246 static int __pakfire_archive_filter_systemd_sysusers(struct pakfire
* pakfire
,
1247 struct archive
* a
, struct archive_entry
* e
, void* data
) {
1248 const char* path
= archive_entry_pathname(e
);
1250 if (!pakfire_path_match("/usr/lib/sysusers.d/*.conf", path
))
1251 return PAKFIRE_WALK_SKIP
;
1253 return PAKFIRE_WALK_OK
;
1256 static int pakfire_archive_stream_payload(struct pakfire
* pakfire
, void* data
, int fd
) {
1259 struct archive
* a
= (struct archive
*)data
;
1261 // Read a block from the input archive
1262 ssize_t bytes_read
= archive_read_data(a
, buffer
, sizeof(buffer
));
1263 if (bytes_read
< 0) {
1264 ERROR(pakfire
, "Could not read from archive: %s\n", archive_error_string(a
));
1268 // We have consumed everything
1269 if (bytes_read
== 0)
1272 // Write the data to the output file descriptor
1273 ssize_t bytes_written
= write(fd
, buffer
, bytes_read
);
1274 if (bytes_written
< 0) {
1275 ERROR(pakfire
, "Could not stream output: %m\n");
1282 static int __pakfire_archive_handle_systemd_sysusers(struct pakfire
* pakfire
,
1283 struct archive
* a
, struct archive_entry
* e
, void* data
) {
1284 struct pakfire_jail
* jail
= NULL
;
1285 char replace
[PATH_MAX
];
1289 const char* path
= archive_entry_pathname(e
);
1292 r
= pakfire_string_format(replace
, "--replace=/%s", path
);
1296 const char* argv
[] = { "/usr/bin/systemd-sysusers", replace
, "-", NULL
};
1298 // Create a new jail
1299 r
= pakfire_jail_create(&jail
, pakfire
);
1303 r
= pakfire_jail_exec(jail
, argv
, pakfire_archive_stream_payload
, NULL
, a
,
1304 PAKFIRE_JAIL_NOENT_OK
);
1308 pakfire_jail_unref(jail
);
1313 int pakfire_archive_apply_systemd_sysusers(struct pakfire_archive
* archive
) {
1314 pakfire_archive_walk(archive
,
1315 __pakfire_archive_filter_systemd_sysusers
, __pakfire_archive_handle_systemd_sysusers
, NULL
);