1 /*#############################################################################
3 # Pakfire - The IPFire package management system #
4 # Copyright (C) 2017 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 #############################################################################*/
24 #include <linux/limits.h>
29 #include <sys/mount.h>
31 #include <sys/types.h>
36 #include <archive_entry.h>
40 #include <solv/pool.h>
41 #include <solv/poolarch.h>
42 #include <solv/queue.h>
44 #include <pakfire/arch.h>
45 #include <pakfire/build.h>
46 #include <pakfire/config.h>
47 #include <pakfire/constants.h>
48 #include <pakfire/db.h>
49 #include <pakfire/dependencies.h>
50 #include <pakfire/keystore.h>
51 #include <pakfire/logging.h>
52 #include <pakfire/mount.h>
53 #include <pakfire/package.h>
54 #include <pakfire/packagelist.h>
55 #include <pakfire/pakfire.h>
56 #include <pakfire/parser.h>
57 #include <pakfire/private.h>
58 #include <pakfire/pwd.h>
59 #include <pakfire/repo.h>
60 #include <pakfire/request.h>
61 #include <pakfire/string.h>
62 #include <pakfire/transaction.h>
63 #include <pakfire/ui.h>
64 #include <pakfire/util.h>
66 #define KEYSTORE_DIR "/etc/pakfire/trusted.keys.d"
67 #define LOCK_PATH PAKFIRE_PRIVATE_DIR "/.lock"
73 char lock_path
[PATH_MAX
];
74 char cache_path
[PATH_MAX
];
76 char keystore_path
[PATH_MAX
];
83 // UID/GID of running user
88 struct pakfire_subid subuid
;
89 struct pakfire_subid subgid
;
95 struct pakfire_callbacks
{
97 pakfire_log_callback log
;
101 pakfire_confirm_callback confirm
;
108 struct pakfire_config
* config
;
110 struct pakfire_distro
{
111 char pretty_name
[256];
117 char version_codename
[32];
129 int destroy_on_free
:1;
135 This is a list of all features that are supported by this version of Pakfire
137 static const struct pakfire_feature
{
140 { "RichDependencies" },
143 { "PackageFormat-6" },
144 { "PackageFormat-5" },
148 { "Compress-Zstandard" },
151 { "Digest-BLAKE2b512" },
152 { "Digest-BLAKE2s256" },
153 { "Digest-SHA3-512" },
154 { "Digest-SHA3-256" },
155 { "Digest-SHA2-512" },
156 { "Digest-SHA2-256" },
162 int pakfire_on_root(struct pakfire
* pakfire
) {
163 return (strcmp(pakfire
->path
, "/") == 0);
166 uid_t
pakfire_uid(struct pakfire
* pakfire
) {
170 gid_t
pakfire_gid(struct pakfire
* pakfire
) {
174 const struct pakfire_subid
* pakfire_subuid(struct pakfire
* pakfire
) {
175 return &pakfire
->subuid
;
178 const struct pakfire_subid
* pakfire_subgid(struct pakfire
* pakfire
) {
179 return &pakfire
->subgid
;
183 Maps any UID/GIDs to the SUBUID/SUBGIDs so that we can transparently
184 copy files in and out of the jail environment.
186 static unsigned int pakfire_map_id(struct pakfire
* pakfire
,
187 const struct pakfire_subid
* subid
, const unsigned int id
) {
188 // Nothing to do if we are running on root
189 if (pakfire_on_root(pakfire
))
193 unsigned int mapped_id
= subid
->id
+ id
;
195 // Check if the ID is in range
196 if (id
> subid
->length
) {
197 ERROR(pakfire
, "Mapped ID is out of range. Setting to %u\n", subid
->id
);
198 mapped_id
= subid
->id
;
201 DEBUG(pakfire
, "Mapping UID/GID %u to %u\n", id
, mapped_id
);
206 static unsigned int pakfire_unmap_id(struct pakfire
* pakfire
,
207 const struct pakfire_subid
* subid
, const unsigned int id
) {
208 // Nothing to do if we are running on root
209 if (pakfire_on_root(pakfire
))
213 int unmapped_id
= id
- subid
->id
;
215 // Check if the ID is in range
216 if (unmapped_id
< 0) {
217 ERROR(pakfire
, "Mapped ID is out of range. Setting to %d\n", subid
->id
);
218 unmapped_id
= subid
->id
;
221 DEBUG(pakfire
, "Mapping UID/GID %d from %d\n", unmapped_id
, id
);
226 static int log_priority(const char* priority
) {
229 int prio
= strtol(priority
, &end
, 10);
230 if (*end
== '\0' || isspace(*end
))
233 if (strncmp(priority
, "error", strlen("error")) == 0)
236 if (strncmp(priority
, "info", strlen("info")) == 0)
239 if (strncmp(priority
, "debug", strlen("debug")) == 0)
245 static void pool_log(Pool
* pool
, void* data
, int type
, const char* s
) {
246 struct pakfire
* pakfire
= (struct pakfire
*)data
;
248 DEBUG(pakfire
, "pool: %s", s
);
251 static Id
pakfire_handle_ns_pakfire(struct pakfire
* pakfire
, const char* name
) {
252 // Find all supported features
253 for (const struct pakfire_feature
* feature
= features
; feature
->name
; feature
++) {
254 if (strcmp(feature
->name
, name
) == 0)
262 static Id
pakfire_handle_ns_arch(struct pakfire
* pakfire
, const char* name
) {
263 const char* arch
= pakfire_get_arch(pakfire
);
265 return strcmp(arch
, name
) == 0;
268 static Id
pakfire_namespace_callback(Pool
* pool
, void* data
, Id ns
, Id id
) {
269 struct pakfire
* pakfire
= (struct pakfire
*)data
;
271 const char* namespace = pool_id2str(pool
, ns
);
272 const char* name
= pakfire_dep2str(pakfire
, id
);
274 DEBUG(pakfire
, "Namespace callback called for %s(%s)\n", namespace, name
);
276 // Handle the pakfire() namespace
277 if (strcmp(namespace, "pakfire") == 0)
278 return pakfire_handle_ns_pakfire(pakfire
, name
);
280 // Handle the arch() namespace
281 else if (strcmp(namespace, "arch") == 0)
282 return pakfire_handle_ns_arch(pakfire
, name
);
289 static int pakfire_populate_pool(struct pakfire
* pakfire
) {
290 struct pakfire_db
* db
= NULL
;
291 struct pakfire_repo
* commandline
= NULL
;
292 struct pakfire_repo
* dummy
= NULL
;
293 struct pakfire_repo
* system
= NULL
;
296 // Initialize the pool
297 Pool
* pool
= pakfire
->pool
= pool_create();
298 pool_setdisttype(pool
, DISTTYPE_RPM
);
301 // Enable debug output
302 pool_setdebuglevel(pool
, 3);
305 // Set architecture of the pool
306 pool_setarch(pool
, pakfire
->arch
);
309 pool_set_rootdir(pool
, pakfire
->path
);
311 // Set debug callback
312 pool_setdebugcallback(pool
, pool_log
, pakfire
);
314 // Install namespace callback
315 pool_setnamespacecallback(pool
, pakfire_namespace_callback
, pakfire
);
317 // Open database in read-only mode and try to load all installed packages
318 r
= pakfire_db_open(&db
, pakfire
, PAKFIRE_DB_READWRITE
);
322 // Create a dummy repository
323 r
= pakfire_repo_create(&dummy
, pakfire
, PAKFIRE_REPO_DUMMY
);
327 // Disable the repository
328 pakfire_repo_set_enabled(dummy
, 0);
330 // Create the system repository
331 r
= pakfire_repo_create(&system
, pakfire
, PAKFIRE_REPO_SYSTEM
);
335 // Set this repository as the installed one
336 pool_set_installed(pool
, pakfire_repo_get_repo(system
));
338 // Create the command line repo
339 r
= pakfire_repo_create(&commandline
, pakfire
, PAKFIRE_REPO_COMMANDLINE
);
343 // Load database content
344 r
= pakfire_db_load(db
, system
);
350 pakfire_db_unref(db
);
352 pakfire_repo_unref(commandline
);
354 pakfire_repo_unref(dummy
);
356 pakfire_repo_unref(system
);
361 static void pakfire_free(struct pakfire
* pakfire
) {
362 struct pakfire_repo
* repo
= NULL
;
365 // Avoid recursive free
366 if (pakfire
->in_free
++)
369 // Destroy the commandline repository
370 repo
= pakfire_get_repo(pakfire
, PAKFIRE_REPO_COMMANDLINE
);
372 r
= pakfire_repo_clean(repo
, PAKFIRE_REPO_CLEAN_FLAGS_DESTROY
);
374 ERROR(pakfire
, "Could not cleanup %s repository: %m\n", PAKFIRE_REPO_COMMANDLINE
);
376 pakfire_repo_unref(repo
);
379 // Release Magic Context
381 magic_close(pakfire
->magic
);
383 // Release GPGME context
385 pakfire_keystore_destroy(pakfire
, &pakfire
->gpgctx
);
387 // Release lock (if not already done so)
388 pakfire_release_lock(pakfire
);
390 if (pakfire
->destroy_on_free
&& *pakfire
->path
) {
391 DEBUG(pakfire
, "Destroying %s\n", pakfire
->path
);
393 // Destroy the temporary directory
394 pakfire_rmtree(pakfire
->path
, 0);
397 pakfire_repo_free_all(pakfire
);
400 pool_free(pakfire
->pool
);
403 pakfire_config_unref(pakfire
->config
);
408 // Safety check in case this is being launched on the host system
409 static int pakfire_safety_checks(struct pakfire
* pakfire
) {
410 // Nothing to do if we are not working on root
411 if (!pakfire_on_root(pakfire
))
414 // We must be root in order to operate in /
416 ERROR(pakfire
, "Must be running as root on /\n");
421 if (strcmp(pakfire
->distro
.id
, "ipfire") != 0) {
422 ERROR(pakfire
, "Not an IPFire system\n");
430 static int pakfire_read_repo_config(struct pakfire
* pakfire
) {
434 // Make path absolute
435 r
= pakfire_path(pakfire
, path
, "%s", PAKFIRE_CONFIG_DIR
"/repos");
439 DEBUG(pakfire
, "Reading repository configuration from %s\n", path
);
446 FTS
* d
= fts_open(paths
, FTS_NOCHDIR
|FTS_NOSTAT
, NULL
);
451 FTSENT
* fent
= fts_read(d
);
456 if (fent
->fts_info
& FTS_F
) {
457 // Skip everything that doesn't end in .repo
458 if (!pakfire_string_endswith(fent
->fts_name
, ".repo"))
461 DEBUG(pakfire
, "Reading %s\n", fent
->fts_path
);
463 FILE* f
= fopen(fent
->fts_path
, "r");
467 // Parse the configuration file
468 r
= pakfire_config_read(pakfire
->config
, f
);
486 const char* pakfire_get_distro_name(struct pakfire
* pakfire
) {
487 if (*pakfire
->distro
.name
)
488 return pakfire
->distro
.name
;
493 const char* pakfire_get_distro_id(struct pakfire
* pakfire
) {
494 if (*pakfire
->distro
.id
)
495 return pakfire
->distro
.id
;
500 const char* pakfire_get_distro_vendor(struct pakfire
* pakfire
) {
501 if (*pakfire
->distro
.vendor
)
502 return pakfire
->distro
.vendor
;
507 const char* pakfire_get_distro_version(struct pakfire
* pakfire
) {
508 if (*pakfire
->distro
.version
)
509 return pakfire
->distro
.version
;
514 const char* pakfire_get_distro_version_id(struct pakfire
* pakfire
) {
515 if (*pakfire
->distro
.version_id
)
516 return pakfire
->distro
.version_id
;
521 const char* pakfire_get_distro_tag(struct pakfire
* pakfire
) {
524 if (*pakfire
->distro
.tag
)
525 return pakfire
->distro
.tag
;
527 const char* id
= pakfire_get_distro_id(pakfire
);
528 const char* version_id
= pakfire_get_distro_version_id(pakfire
);
530 // Break if the configuration is incomplete
531 if (!id
|| !version_id
) {
537 r
= pakfire_string_format(pakfire
->distro
.tag
, "%s%s", id
, version_id
);
542 return pakfire
->distro
.tag
;
545 static int pakfire_config_import_distro(struct pakfire
* pakfire
) {
546 // Nothing to do if there is no distro section
547 if (!pakfire_config_has_section(pakfire
->config
, "distro"))
551 const char* name
= pakfire_config_get(pakfire
->config
, "distro", "name", NULL
);
553 pakfire_string_set(pakfire
->distro
.name
, name
);
556 const char* id
= pakfire_config_get(pakfire
->config
, "distro", "id", NULL
);
558 pakfire_string_set(pakfire
->distro
.id
, id
);
561 const char* version_id
= pakfire_config_get(pakfire
->config
, "distro", "version_id", NULL
);
563 pakfire_string_set(pakfire
->distro
.version_id
, version_id
);
566 const char* codename
= pakfire_config_get(pakfire
->config
, "distro", "codename", NULL
);
568 pakfire_string_set(pakfire
->distro
.version_codename
, codename
);
571 if (*pakfire
->distro
.version_codename
)
572 pakfire_string_format(pakfire
->distro
.version
, "%s (%s)",
573 pakfire
->distro
.version_id
, pakfire
->distro
.version_codename
);
575 pakfire_string_set(pakfire
->distro
.version
, pakfire
->distro
.version_id
);
577 // Fill in pretty name
578 pakfire_string_format(pakfire
->distro
.pretty_name
, "%s %s",
579 pakfire
->distro
.name
, pakfire
->distro
.version
);
582 const char* vendor
= pakfire_config_get(pakfire
->config
, "distro", "vendor", NULL
);
584 pakfire_string_set(pakfire
->distro
.vendor
, vendor
);
587 const char* slogan
= pakfire_config_get(pakfire
->config
, "distro", "slogan", NULL
);
589 pakfire_string_set(pakfire
->distro
.slogan
, slogan
);
594 static int pakfire_read_config(struct pakfire
* pakfire
, const char* path
) {
595 char default_path
[PATH_MAX
];
598 // Use default path if none set
600 r
= pakfire_path(pakfire
, default_path
, "%s", PAKFIRE_CONFIG_DIR
"/general.conf");
607 DEBUG(pakfire
, "Reading configuration from %s\n", path
);
609 FILE* f
= fopen(path
, "r");
611 // Silently ignore when there is no default configuration file
612 if (*default_path
&& errno
== ENOENT
)
615 ERROR(pakfire
, "Could not open configuration file %s: %m\n", path
);
619 // Read configuration from file
620 r
= pakfire_config_read(pakfire
->config
, f
);
622 ERROR(pakfire
, "Could not parse configuration file %s: %m\n", path
);
626 // Import distro configuration
627 r
= pakfire_config_import_distro(pakfire
);
631 // Read repository configuration
632 r
= pakfire_read_repo_config(pakfire
);
642 static int pakfire_read_os_release(struct pakfire
* pakfire
) {
647 int r
= pakfire_path(pakfire
, path
, "%s", "/etc/os-release");
653 FILE* f
= fopen(path
, "r");
655 // Ignore when the file does not exist
656 if (errno
== ENOENT
) {
661 ERROR(pakfire
, "Could not open %s: %m\n", path
);
666 ssize_t bytes_read
= getline(&line
, &l
, f
);
670 // Remove trailing newline
671 pakfire_remove_trailing_newline(line
);
674 char* delim
= strchr(line
, '=');
681 // Set key and val to the start of the strings
683 char* val
= delim
+ 1;
686 val
= pakfire_unquote_in_place(val
);
688 if (strcmp(key
, "PRETTY_NAME") == 0)
689 r
= pakfire_string_set(pakfire
->distro
.pretty_name
, val
);
690 else if (strcmp(key
, "NAME") == 0)
691 r
= pakfire_string_set(pakfire
->distro
.name
, val
);
692 else if (strcmp(key
, "ID") == 0)
693 r
= pakfire_string_set(pakfire
->distro
.id
, val
);
694 else if (strcmp(key
, "VERSION") == 0)
695 r
= pakfire_string_set(pakfire
->distro
.version
, val
);
696 else if (strcmp(key
, "VERSION_CODENAME") == 0)
697 r
= pakfire_string_set(pakfire
->distro
.version_codename
, val
);
698 else if (strcmp(key
, "VERSION_ID") == 0)
699 r
= pakfire_string_set(pakfire
->distro
.version_id
, val
);
720 PAKFIRE_EXPORT
int pakfire_create(struct pakfire
** pakfire
, const char* path
,
721 const char* arch
, const char* conf
, int flags
,
722 int loglevel
, pakfire_log_callback log_callback
, void* log_data
) {
723 char tempdir
[PATH_MAX
] = PAKFIRE_TMP_DIR
"/pakfire-root-XXXXXX";
724 char private_dir
[PATH_MAX
];
727 // Reset pakfire pointer
730 // Default to the native architecture
732 arch
= pakfire_arch_native();
734 // Check if the architecture is supported
735 if (!pakfire_arch_supported(arch
)) {
740 // Path must be absolute
741 if (path
&& !pakfire_string_startswith(path
, "/")) {
746 struct pakfire
* p
= calloc(1, sizeof(*p
));
753 // Store the UID/GID we are running as
758 pakfire_string_set(p
->arch
, arch
);
762 pakfire_set_log_callback(p
, log_callback
, log_data
);
764 pakfire_set_log_callback(p
, pakfire_log_syslog
, NULL
);
768 pakfire_log_set_priority(p
, loglevel
);
770 const char* env
= secure_getenv("PAKFIRE_LOG");
772 pakfire_log_set_priority(p
, log_priority(env
));
775 // Initialise configuration
776 r
= pakfire_config_create(&p
->config
);
780 // Generate a random path if none is set
782 path
= pakfire_mkdtemp(tempdir
);
788 // Destroy everything when done
789 p
->destroy_on_free
= 1;
793 pakfire_string_set(p
->path
, path
);
795 // Read /etc/os-release
796 r
= pakfire_read_os_release(p
);
797 if (r
&& errno
!= ENOENT
)
800 // Bump RLIMIT_NOFILE to maximum
801 r
= pakfire_rlimit_set(p
, PAKFIRE_RLIMIT_NOFILE_MAX
);
805 DEBUG(p
, "Pakfire initialized at %p\n", p
);
806 DEBUG(p
, " arch = %s\n", pakfire_get_arch(p
));
807 DEBUG(p
, " path = %s\n", pakfire_get_path(p
));
809 // Fetch sub UID/GIDs
810 if (!pakfire_on_root(p
)) {
812 r
= pakfire_getsubid(p
, "/etc/subuid", p
->uid
, &p
->subuid
);
814 ERROR(p
, "Could not fetch subuid: %m\n");
819 r
= pakfire_getsubid(p
, "/etc/subgid", p
->uid
, &p
->subgid
);
821 ERROR(p
, "Could not fetch subgid: %m\n");
826 DEBUG(p
, " subuid = %u - %zu\n", p
->subuid
.id
, p
->subuid
.id
+ p
->subuid
.length
);
827 DEBUG(p
, " subgid = %u - %zu\n", p
->subgid
.id
, p
->subgid
.id
+ p
->subgid
.length
);
830 // Perform some safety checks
831 r
= pakfire_safety_checks(p
);
835 // Read configuration file
836 r
= pakfire_read_config(p
, conf
);
840 // Dump distribution configuration
841 DEBUG(p
, " Distribution: %s\n", p
->distro
.pretty_name
);
842 DEBUG(p
, " name = %s\n", p
->distro
.name
);
843 DEBUG(p
, " id = %s\n", p
->distro
.id
);
844 DEBUG(p
, " version = %s\n", p
->distro
.version
);
845 DEBUG(p
, " version_id = %s\n", p
->distro
.version_id
);
846 if (*p
->distro
.version_codename
)
847 DEBUG(p
, " codename = %s\n", p
->distro
.version_codename
);
848 if (*p
->distro
.vendor
)
849 DEBUG(p
, " vendor = %s\n", p
->distro
.vendor
);
850 if (*p
->distro
.slogan
)
851 DEBUG(p
, " slogan = %s\n", p
->distro
.slogan
);
854 r
= pakfire_path(p
, p
->lock_path
, "%s", LOCK_PATH
);
856 ERROR(p
, "Could not set lock path: %m\n");
862 const char* home
= pakfire_get_home(p
, p
->uid
);
864 ERROR(p
, "Could not find home directory\n");
869 pakfire_string_format(p
->cache_path
, "%s/.pakfire/cache/%s/%s/%s",
870 home
, p
->distro
.id
, p
->distro
.version_id
, p
->arch
);
872 pakfire_string_format(p
->cache_path
, "%s/%s/%s/%s",
873 PAKFIRE_CACHE_DIR
, p
->distro
.id
, p
->distro
.version_id
, p
->arch
);
877 r
= pakfire_path(p
, p
->keystore_path
, "%s", KEYSTORE_DIR
);
879 ERROR(p
, "Could not set keystore path: %m\n");
883 // Make path for private files
884 r
= pakfire_path(p
, private_dir
, "%s", PAKFIRE_PRIVATE_DIR
);
888 // Make sure that our private directory exists
889 r
= pakfire_mkdir(private_dir
, 0755);
891 ERROR(p
, "Could not create private directory %s: %m\n", private_dir
);
895 // Initialize keystore
896 r
= pakfire_keystore_init(p
, &p
->gpgctx
);
901 r
= pakfire_populate_pool(p
);
905 // Create repositories
906 r
= pakfire_repo_import(p
, p
->config
);
920 PAKFIRE_EXPORT
struct pakfire
* pakfire_ref(struct pakfire
* pakfire
) {
926 PAKFIRE_EXPORT
struct pakfire
* pakfire_unref(struct pakfire
* pakfire
) {
927 if (--pakfire
->nrefs
> 0)
930 pakfire_free(pakfire
);
935 int pakfire_has_flag(struct pakfire
* pakfire
, int flag
) {
936 return pakfire
->flags
& flag
;
939 struct pakfire_config
* pakfire_get_config(struct pakfire
* pakfire
) {
940 if (!pakfire
->config
)
943 return pakfire_config_ref(pakfire
->config
);
946 PAKFIRE_EXPORT
const char* pakfire_get_path(struct pakfire
* pakfire
) {
947 return pakfire
->path
;
950 int pakfire_acquire_lock(struct pakfire
* pakfire
) {
953 // Check if the lock is already held
955 ERROR(pakfire
, "Lock is already been acquired by this process\n");
960 DEBUG(pakfire
, "Acquire lock...\n");
962 // Ensure the parent directory exists
963 pakfire_mkparentdir(pakfire
->lock_path
, 0755);
965 // Open the lock file
966 pakfire
->lock
= fopen(pakfire
->lock_path
, "w");
967 if (!pakfire
->lock
) {
968 ERROR(pakfire
, "Could not open lock file %s: %m\n", pakfire
->lock_path
);
972 // Attempt to lock the file exclusively
974 r
= flock(fileno(pakfire
->lock
), LOCK_EX
|LOCK_NB
);
980 DEBUG(pakfire
, "Could not acquire lock %s: %m\n", pakfire
->lock_path
);
982 // Wait 500ms until the next attempt
987 DEBUG(pakfire
, "Lock acquired\n");
992 void pakfire_release_lock(struct pakfire
* pakfire
) {
996 DEBUG(pakfire
, "Releasing lock\n");
998 fclose(pakfire
->lock
);
999 pakfire
->lock
= NULL
;
1001 // Attempt to unlink the lock file
1002 unlink(pakfire
->lock_path
);
1005 const char* pakfire_get_keystore_path(struct pakfire
* pakfire
) {
1006 return pakfire
->keystore_path
;
1009 int __pakfire_path(struct pakfire
* pakfire
, char* path
, const size_t length
,
1010 const char* format
, ...) {
1011 char buffer
[PATH_MAX
];
1015 // Format input into buffer
1016 va_start(args
, format
);
1017 r
= __pakfire_string_vformat(buffer
, sizeof(buffer
), format
, args
);
1020 // Break on any errors
1024 // Join paths together
1025 return __pakfire_path_join(path
, length
, pakfire
->path
, buffer
);
1028 const char* pakfire_relpath(struct pakfire
* pakfire
, const char* path
) {
1029 return pakfire_path_relpath(pakfire
->path
, path
);
1032 int __pakfire_cache_path(struct pakfire
* pakfire
, char* path
, size_t length
,
1033 const char* format
, ...) {
1034 char buffer
[PATH_MAX
];
1038 // Format input into buffer
1039 va_start(args
, format
);
1040 r
= __pakfire_string_vformat(buffer
, sizeof(buffer
), format
, args
);
1043 // Break on any errors
1047 // Join paths together
1048 return __pakfire_path_join(path
, length
, pakfire
->cache_path
, buffer
);
1051 gpgme_ctx_t
pakfire_get_gpgctx(struct pakfire
* pakfire
) {
1052 return pakfire
->gpgctx
;
1055 magic_t
pakfire_get_magic(struct pakfire
* pakfire
) {
1058 // Initialize the context if not already done
1059 if (!pakfire
->magic
) {
1060 // Allocate a new context
1061 pakfire
->magic
= magic_open(MAGIC_MIME_TYPE
| MAGIC_ERROR
| MAGIC_NO_CHECK_TOKENS
);
1062 if (!pakfire
->magic
) {
1063 ERROR(pakfire
, "Could not allocate magic context: %m\n");
1067 // Load the database
1068 r
= magic_load(pakfire
->magic
, NULL
);
1070 ERROR(pakfire
, "Could not open the magic database: %s\n",
1071 magic_error(pakfire
->magic
));
1076 return pakfire
->magic
;
1080 magic_close(pakfire
->magic
);
1082 // Reset the pointer
1083 pakfire
->magic
= NULL
;
1088 PAKFIRE_EXPORT
int pakfire_list_keys(struct pakfire
* pakfire
, struct pakfire_key
*** keys
) {
1092 // Fetch GPGME context
1093 gpgme_ctx_t gpgctx
= pakfire_get_gpgctx(pakfire
);
1097 struct pakfire_key
* key
= NULL
;
1098 gpgme_key_t gpgkey
= NULL
;
1102 // Iterate over all keys and import them to the list
1103 gpgme_error_t e
= gpgme_op_keylist_start(gpgctx
, NULL
, 0);
1108 e
= gpgme_op_keylist_next(gpgctx
, &gpgkey
);
1113 r
= pakfire_key_create(&key
, pakfire
, gpgkey
);
1114 gpgme_key_unref(gpgkey
);
1119 *keys
= reallocarray(*keys
, length
+ 2, sizeof(**keys
));
1125 // Store key in array
1126 (*keys
)[length
++] = key
;
1128 // Terminate the array
1129 (*keys
)[length
] = NULL
;
1137 for (struct pakfire_key
** _key
= *keys
; *_key
; _key
++)
1138 pakfire_key_unref(*_key
);
1146 int pakfire_repo_walk(struct pakfire
* pakfire
,
1147 pakfire_repo_walk_callback callback
, void* p
) {
1148 struct pakfire_repo
* repo
= NULL
;
1149 Repo
* solv_repo
= NULL
;
1153 Pool
* pool
= pakfire
->pool
;
1155 // Run func for every repository
1156 FOR_REPOS(i
, solv_repo
) {
1157 repo
= pakfire_repo_create_from_repo(pakfire
, solv_repo
);
1162 r
= callback(pakfire
, repo
, p
);
1163 pakfire_repo_unref(repo
);
1173 static int __pakfire_repo_clean(struct pakfire
* pakfire
, struct pakfire_repo
* repo
,
1175 int flags
= *(int*)p
;
1177 return pakfire_repo_clean(repo
, flags
);
1180 PAKFIRE_EXPORT
int pakfire_clean(struct pakfire
* pakfire
, int flags
) {
1183 // Clean all repositories
1184 r
= pakfire_repo_walk(pakfire
, __pakfire_repo_clean
, &flags
);
1188 // Clean build environments
1189 r
= pakfire_build_clean(pakfire
, flags
);
1194 return pakfire_rmtree(PAKFIRE_CACHE_DIR
, 0);
1197 static int __pakfire_repo_refresh(struct pakfire
* pakfire
, struct pakfire_repo
* repo
,
1199 int flags
= *(int*)p
;
1201 return pakfire_repo_refresh(repo
, flags
);
1204 PAKFIRE_EXPORT
int pakfire_refresh(struct pakfire
* pakfire
, int flags
) {
1205 return pakfire_repo_walk(pakfire
, __pakfire_repo_refresh
, &flags
);
1208 enum pakfire_copy_direction
{
1213 static int pakfire_copy(struct pakfire
* pakfire
, const char* src
, const char* dst
,
1214 enum pakfire_copy_direction direction
) {
1215 struct archive
* reader
= NULL
;
1216 struct archive
* writer
= NULL
;
1217 struct archive_entry
* entry
= NULL
;
1221 DEBUG(pakfire
, "Copying %s to %s\n", src
, dst
);
1223 // Open the source file
1224 f
= fopen(src
, "r");
1226 ERROR(pakfire
, "Could not open %s: %m\n", src
);
1231 reader
= pakfire_make_archive_disk_reader(pakfire
, (direction
== PAKFIRE_COPY_OUT
));
1236 writer
= pakfire_make_archive_disk_writer(pakfire
, (direction
== PAKFIRE_COPY_IN
));
1240 // Create a new entry
1241 entry
= archive_entry_new();
1245 // Set the source path
1246 archive_entry_copy_sourcepath(entry
, src
);
1248 // Set the destination path
1249 archive_entry_set_pathname(entry
, dst
);
1251 // Read everything from source file
1252 r
= archive_read_disk_entry_from_file(reader
, entry
, fileno(f
), NULL
);
1254 ERROR(pakfire
, "Could not read from %s: %m\n", src
);
1258 // Write file to destination
1259 r
= archive_write_header(writer
, entry
);
1261 ERROR(pakfire
, "Could not write %s: %m\n", dst
);
1266 if (archive_entry_filetype(entry
) == AE_IFREG
) {
1267 r
= pakfire_archive_copy_data_from_file(pakfire
, writer
, f
);
1276 archive_entry_free(entry
);
1278 archive_read_free(reader
);
1280 archive_write_free(writer
);
1285 PAKFIRE_EXPORT
int pakfire_copy_in(struct pakfire
* pakfire
, const char* src
, const char* dst
) {
1286 char path
[PATH_MAX
];
1289 if (pakfire_on_root(pakfire
)) {
1294 r
= pakfire_path(pakfire
, path
, "%s", dst
);
1298 return pakfire_copy(pakfire
, src
, path
, PAKFIRE_COPY_IN
);
1301 PAKFIRE_EXPORT
int pakfire_copy_out(struct pakfire
* pakfire
, const char* src
, const char* dst
) {
1302 char path
[PATH_MAX
];
1305 if (pakfire_on_root(pakfire
)) {
1310 r
= pakfire_path(pakfire
, path
, "%s", src
);
1314 return pakfire_copy(pakfire
, path
, dst
, PAKFIRE_COPY_OUT
);
1317 PAKFIRE_EXPORT
const char* pakfire_get_arch(struct pakfire
* pakfire
) {
1318 return pakfire
->arch
;
1321 PAKFIRE_EXPORT
int pakfire_version_compare(struct pakfire
* pakfire
, const char* evr1
, const char* evr2
) {
1322 return pool_evrcmp_str(pakfire
->pool
, evr1
, evr2
, EVRCMP_COMPARE
);
1325 Pool
* pakfire_get_solv_pool(struct pakfire
* pakfire
) {
1326 return pakfire
->pool
;
1329 void pakfire_pool_has_changed(struct pakfire
* pakfire
) {
1330 pakfire
->pool_ready
= 0;
1333 static int __pakfire_repo_internalize(struct pakfire
* pakfire
, struct pakfire_repo
* repo
,
1335 int flags
= *(int*)p
;
1337 return pakfire_repo_internalize(repo
, flags
);
1340 void pakfire_pool_internalize(struct pakfire
* pakfire
) {
1343 // Nothing to do if the pool is ready
1344 if (pakfire
->pool_ready
)
1347 // Internalize all repositories
1348 pakfire_repo_walk(pakfire
, __pakfire_repo_internalize
, &flags
);
1350 // Create fileprovides
1351 pool_addfileprovides(pakfire
->pool
);
1353 // Create whatprovides index
1354 pool_createwhatprovides(pakfire
->pool
);
1356 // Mark the pool as ready
1357 pakfire
->pool_ready
= 1;
1360 PAKFIRE_EXPORT
struct pakfire_repolist
* pakfire_get_repos(struct pakfire
* pakfire
) {
1361 struct pakfire_repolist
* list
;
1363 int r
= pakfire_repolist_create(&list
);
1367 Pool
* pool
= pakfire_get_solv_pool(pakfire
);
1371 FOR_REPOS(i
, solv_repo
) {
1372 // Skip the dummy repository
1373 if (strcmp(solv_repo
->name
, PAKFIRE_REPO_DUMMY
) == 0)
1376 struct pakfire_repo
* repo
= pakfire_repo_create_from_repo(pakfire
, solv_repo
);
1382 r
= pakfire_repolist_append(list
, repo
);
1384 pakfire_repo_unref(repo
);
1388 pakfire_repo_unref(repo
);
1394 pakfire_repolist_unref(list
);
1398 PAKFIRE_EXPORT
struct pakfire_repo
* pakfire_get_repo(struct pakfire
* pakfire
, const char* name
) {
1399 Pool
* pool
= pakfire_get_solv_pool(pakfire
);
1406 FOR_REPOS(i
, repo
) {
1407 if (strcmp(repo
->name
, name
) == 0)
1408 return pakfire_repo_create_from_repo(pakfire
, repo
);
1415 struct pakfire_repo
* pakfire_get_installed_repo(struct pakfire
* pakfire
) {
1416 if (!pakfire
->pool
->installed
)
1419 return pakfire_repo_create_from_repo(pakfire
, pakfire
->pool
->installed
);
1423 Convenience function to add a package to the @commandline repository
1425 int pakfire_commandline_add(struct pakfire
* pakfire
, const char* path
,
1426 struct pakfire_package
** package
) {
1427 struct pakfire_repo
* repo
= NULL
;
1430 // Find the commandline repository
1431 repo
= pakfire_get_repo(pakfire
, PAKFIRE_REPO_COMMANDLINE
);
1433 ERROR(pakfire
, "Could not find the commandline repository: %m\n");
1438 r
= pakfire_repo_add(repo
, path
, package
);
1444 pakfire_repo_unref(repo
);
1449 static int pakfire_search_dep(struct pakfire
* pakfire
, Id type
, const char* what
, int flags
,
1450 struct pakfire_packagelist
** list
) {
1453 // Get the pool ready
1454 pakfire_pool_internalize(pakfire
);
1456 // Translate dependency to ID
1457 Id dep
= pakfire_str2dep(pakfire
, what
);
1467 queue_init(&matches
);
1469 // Search for anything that matches
1470 pool_whatmatchesdep(pakfire
->pool
, type
, dep
, &matches
, 0);
1472 // Create a packagelist
1473 r
= pakfire_packagelist_create_from_queue(list
, pakfire
, &matches
);
1478 pakfire_packagelist_sort(*list
);
1481 queue_free(&matches
);
1486 PAKFIRE_EXPORT
int pakfire_whatprovides(struct pakfire
* pakfire
, const char* what
, int flags
,
1487 struct pakfire_packagelist
** list
) {
1488 return pakfire_search_dep(pakfire
, SOLVABLE_PROVIDES
, what
, flags
, list
);
1491 PAKFIRE_EXPORT
int pakfire_whatrequires(struct pakfire
* pakfire
, const char* what
, int flags
,
1492 struct pakfire_packagelist
** list
) {
1493 return pakfire_search_dep(pakfire
, SOLVABLE_REQUIRES
, what
, flags
, list
);
1496 PAKFIRE_EXPORT
int pakfire_search(struct pakfire
* pakfire
, const char* what
, int flags
,
1497 struct pakfire_packagelist
** list
) {
1502 // Get the pool ready
1503 pakfire_pool_internalize(pakfire
);
1505 // Initialize the result queue
1506 queue_init(&matches
);
1508 // Setup the data interator
1509 dataiterator_init(&di
, pakfire
->pool
, 0, 0, 0, what
, SEARCH_SUBSTRING
|SEARCH_NOCASE
);
1514 SOLVABLE_DESCRIPTION
,
1518 // Search through these keys and add matches to the queue
1519 for (const Id
* key
= keys
; *key
; key
++) {
1520 dataiterator_set_keyname(&di
, *key
);
1521 dataiterator_set_search(&di
, 0, 0);
1523 while (dataiterator_step(&di
))
1524 queue_pushunique(&matches
, di
.solvid
);
1527 if (flags
& PAKFIRE_SEARCH_NAME_ONLY
)
1531 // Convert matches to package list
1532 r
= pakfire_packagelist_create_from_queue(list
, pakfire
, &matches
);
1537 pakfire_packagelist_sort(*list
);
1540 dataiterator_free(&di
);
1541 queue_free(&matches
);
1548 PAKFIRE_EXPORT
int pakfire_log_get_priority(struct pakfire
* pakfire
) {
1549 return pakfire
->log_priority
;
1552 PAKFIRE_EXPORT
void pakfire_log_set_priority(struct pakfire
* pakfire
, int priority
) {
1553 pakfire
->log_priority
= priority
;
1556 PAKFIRE_EXPORT
void pakfire_set_log_callback(struct pakfire
* pakfire
,
1557 pakfire_log_callback callback
, void* data
) {
1558 pakfire
->callbacks
.log
= callback
;
1559 pakfire
->callbacks
.log_data
= data
;
1562 void pakfire_log(struct pakfire
* pakfire
, int priority
, const char* file
, int line
,
1563 const char* fn
, const char* format
, ...) {
1566 // Do not do anything if callback isn't set
1567 if (!pakfire
->callbacks
.log
)
1571 int saved_errno
= errno
;
1573 va_start(args
, format
);
1574 pakfire
->callbacks
.log(pakfire
->callbacks
.log_data
,
1575 priority
, file
, line
, fn
, format
, args
);
1579 errno
= saved_errno
;
1584 PAKFIRE_EXPORT
void pakfire_set_confirm_callback(struct pakfire
* pakfire
,
1585 pakfire_confirm_callback callback
, void* data
) {
1586 pakfire
->callbacks
.confirm
= callback
;
1587 pakfire
->callbacks
.confirm_data
= data
;
1590 int pakfire_confirm(struct pakfire
* pakfire
, const char* message
, const char* question
) {
1592 if (pakfire
->callbacks
.confirm
)
1593 return pakfire
->callbacks
.confirm(
1594 pakfire
, pakfire
->callbacks
.confirm_data
, message
, question
);
1596 // If no callback is set, we just log the message
1597 INFO(pakfire
, "%s\n", message
);
1602 static const char* pakfire_user_lookup(void* data
, la_int64_t uid
) {
1603 struct pakfire
* pakfire
= (struct pakfire
*)data
;
1605 DEBUG(pakfire
, "Looking up name for UID %ld\n", uid
);
1607 // Unmap the UID first
1608 uid
= pakfire_unmap_id(pakfire
, &pakfire
->subuid
, uid
);
1610 // Fast path for "root"
1614 // Find a matching entry in /etc/passwd
1615 struct passwd
* entry
= pakfire_getpwuid(pakfire
, uid
);
1617 ERROR(pakfire
, "Could not retrieve uname for %ld: %m\n", uid
);
1621 DEBUG(pakfire
, "Mapping UID %ld to %s\n", uid
, entry
->pw_name
);
1623 return entry
->pw_name
;
1626 static const char* pakfire_group_lookup(void* data
, la_int64_t gid
) {
1627 struct pakfire
* pakfire
= (struct pakfire
*)data
;
1629 DEBUG(pakfire
, "Looking up name for GID %ld\n", gid
);
1631 // Unmap the GID first
1632 gid
= pakfire_unmap_id(pakfire
, &pakfire
->subgid
, gid
);
1634 // Fast path for "root"
1638 // Find a matching entry in /etc/group
1639 struct group
* entry
= pakfire_getgrgid(pakfire
, gid
);
1641 ERROR(pakfire
, "Could not retrieve gname for %ld: %m\n", gid
);
1645 DEBUG(pakfire
, "Mapping GID %ld to %s\n", gid
, entry
->gr_name
);
1647 return entry
->gr_name
;
1650 struct archive
* pakfire_make_archive_disk_reader(struct pakfire
* pakfire
, int internal
) {
1651 struct archive
* archive
= archive_read_disk_new();
1655 // Do not read fflags
1656 int r
= archive_read_disk_set_behavior(archive
, ARCHIVE_READDISK_NO_FFLAGS
);
1658 ERROR(pakfire
, "Could not change behavior of reader: %s\n",
1659 archive_error_string(archive
));
1660 archive_read_free(archive
);
1664 // Install user/group lookups
1666 archive_read_disk_set_uname_lookup(archive
, pakfire
, pakfire_user_lookup
, NULL
);
1667 archive_read_disk_set_gname_lookup(archive
, pakfire
, pakfire_group_lookup
, NULL
);
1669 archive_read_disk_set_standard_lookup(archive
);
1675 static la_int64_t
pakfire_uid_lookup(void* data
, const char* name
, la_int64_t uid
) {
1676 struct pakfire
* pakfire
= (struct pakfire
*)data
;
1678 DEBUG(pakfire
, "Looking up UID for '%s' (%ld)\n", name
, uid
);
1680 // Fast path for "root"
1681 if (strcmp(name
, "root") == 0)
1682 return pakfire_map_id(pakfire
, &pakfire
->subuid
, 0);
1684 // Find a matching entry in /etc/passwd
1685 struct passwd
* entry
= pakfire_getpwnam(pakfire
, name
);
1687 ERROR(pakfire
, "Could not retrieve UID for '%s': %m\n", name
);
1688 return pakfire_map_id(pakfire
, &pakfire
->subuid
, 0);
1691 DEBUG(pakfire
, "Mapping %s to UID %d\n", name
, entry
->pw_uid
);
1693 return pakfire_map_id(pakfire
, &pakfire
->subuid
, entry
->pw_uid
);
1696 static la_int64_t
pakfire_gid_lookup(void* data
, const char* name
, la_int64_t gid
) {
1697 struct pakfire
* pakfire
= (struct pakfire
*)data
;
1699 DEBUG(pakfire
, "Looking up GID for '%s' (%ld)\n", name
, gid
);
1701 // Fast path for "root"
1702 if (strcmp(name
, "root") == 0)
1703 return pakfire_map_id(pakfire
, &pakfire
->subgid
, 0);
1705 // Find a matching entry in /etc/group
1706 struct group
* entry
= pakfire_getgrnam(pakfire
, name
);
1708 ERROR(pakfire
, "Could not retrieve GID for '%s': %m\n", name
);
1709 return pakfire_map_id(pakfire
, &pakfire
->subgid
, 0);
1712 DEBUG(pakfire
, "Mapping %s to GID %d\n", name
, entry
->gr_gid
);
1714 return pakfire_map_id(pakfire
, &pakfire
->subgid
, entry
->gr_gid
);
1717 struct archive
* pakfire_make_archive_disk_writer(struct pakfire
* pakfire
, int internal
) {
1718 struct archive
* archive
= archive_write_disk_new();
1722 // Set flags for extracting files
1724 ARCHIVE_EXTRACT_ACL
|
1725 ARCHIVE_EXTRACT_OWNER
|
1726 ARCHIVE_EXTRACT_PERM
|
1727 ARCHIVE_EXTRACT_TIME
|
1728 ARCHIVE_EXTRACT_UNLINK
|
1729 ARCHIVE_EXTRACT_XATTR
;
1731 archive_write_disk_set_options(archive
, flags
);
1733 // Install our own routine for user/group lookups
1735 archive_write_disk_set_user_lookup(archive
, pakfire
, pakfire_uid_lookup
, NULL
);
1736 archive_write_disk_set_group_lookup(archive
, pakfire
, pakfire_gid_lookup
, NULL
);
1738 archive_write_disk_set_standard_lookup(archive
);
1744 // Convenience functions to install/erase/update packages
1746 static int pakfire_perform_transaction(
1747 struct pakfire
* pakfire
,
1748 int transaction_flags
,
1750 const enum pakfire_request_action action
,
1751 const char** packages
,
1755 pakfire_status_callback status_callback
,
1756 void* status_callback_data
) {
1757 struct pakfire_request
* request
= NULL
;
1758 struct pakfire_transaction
* transaction
= NULL
;
1761 // Packages cannot be NULL
1768 r
= pakfire_acquire_lock(pakfire
);
1772 // Create a new request
1773 r
= pakfire_request_create(&request
, pakfire
, solver_flags
);
1777 // Lock anything that should be locked
1779 for (const char** lock
= locks
; *lock
; lock
++) {
1780 r
= pakfire_request_add(request
, PAKFIRE_REQ_LOCK
, *lock
, 0);
1782 ERROR(pakfire
, "Could not lock '%s': %m\n", *lock
);
1788 // Perform action on all packages
1789 for (const char** package
= packages
; *package
; package
++) {
1790 r
= pakfire_request_add(request
, action
, *package
, job_flags
);
1792 ERROR(pakfire
, "Could not find '%s': %m\n", *package
);
1797 // Solve the request
1798 r
= pakfire_request_solve(request
);
1802 // Fetch the transaction
1803 r
= pakfire_request_get_transaction(request
, &transaction
);
1807 // Set how many packages have been changed
1809 *changed
= pakfire_transaction_count(transaction
);
1811 // Set status callback
1812 if (status_callback
)
1813 pakfire_transaction_set_status_callback(
1814 transaction
, status_callback
, status_callback_data
);
1816 // Run the transaction
1817 r
= pakfire_transaction_run(transaction
, transaction_flags
);
1826 pakfire_release_lock(pakfire
);
1829 pakfire_transaction_unref(transaction
);
1831 pakfire_request_unref(request
);
1836 PAKFIRE_EXPORT
int pakfire_install(
1837 struct pakfire
* pakfire
,
1838 int transaction_flags
,
1840 const char** packages
,
1844 pakfire_status_callback status_callback
,
1845 void* status_callback_data
) {
1846 return pakfire_perform_transaction(
1850 PAKFIRE_REQ_INSTALL
,
1856 status_callback_data
);
1859 PAKFIRE_EXPORT
int pakfire_erase(
1860 struct pakfire
* pakfire
,
1861 int transaction_flags
,
1863 const char** packages
,
1867 pakfire_status_callback status_callback
,
1868 void* status_callback_data
) {
1869 return pakfire_perform_transaction(
1879 status_callback_data
);
1882 static int pakfire_perform_transaction_simple(struct pakfire
* pakfire
, int solver_flags
,
1883 const enum pakfire_request_action action
, int job_flags
, int* changed
,
1884 pakfire_status_callback status_callback
, void* status_callback_data
) {
1885 struct pakfire_request
* request
= NULL
;
1886 struct pakfire_transaction
* transaction
= NULL
;
1890 r
= pakfire_acquire_lock(pakfire
);
1894 // Create a new request
1895 r
= pakfire_request_create(&request
, pakfire
, solver_flags
);
1900 r
= pakfire_request_add(request
, action
, NULL
, job_flags
);
1904 // Solve the request
1905 r
= pakfire_request_solve(request
);
1909 // Fetch the transaction
1910 r
= pakfire_request_get_transaction(request
, &transaction
);
1914 // Set how many packages have been changed
1916 *changed
= pakfire_transaction_count(transaction
);
1918 // Set status callback
1919 if (status_callback
)
1920 pakfire_transaction_set_status_callback(
1921 transaction
, status_callback
, status_callback_data
);
1923 // Run the transaction
1924 r
= pakfire_transaction_run(transaction
, 0);
1933 pakfire_release_lock(pakfire
);
1936 pakfire_transaction_unref(transaction
);
1938 pakfire_request_unref(request
);
1943 PAKFIRE_EXPORT
int pakfire_update(
1944 struct pakfire
* pakfire
,
1945 int transaction_flags
,
1947 const char** packages
,
1951 pakfire_status_callback status_callback
,
1952 void* status_callback_data
) {
1953 // If no packages are being passed, we will try to update everything
1956 return pakfire_perform_transaction_simple(
1957 pakfire
, solver_flags
, PAKFIRE_REQ_UPDATE_ALL
, flags
, changed
,
1958 status_callback
, status_callback_data
);
1960 return pakfire_perform_transaction(pakfire
, transaction_flags
, solver_flags
,
1961 PAKFIRE_REQ_UPDATE
, packages
, locks
, flags
, changed
,
1962 status_callback
, status_callback_data
);
1965 static int pakfire_verify(struct pakfire
* pakfire
, int *changed
) {
1966 return pakfire_perform_transaction_simple(pakfire
, 0, PAKFIRE_REQ_VERIFY
,
1967 0, changed
, NULL
, NULL
);
1970 static int pakfire_check_files(struct pakfire
* pakfire
,
1971 struct pakfire_db
* db
, struct pakfire_filelist
* errors
) {
1972 struct pakfire_filelist
* filelist
= NULL
;
1975 // Fetch the filelist
1976 r
= pakfire_db_filelist(db
, &filelist
);
1980 // Verify the filelist
1981 r
= pakfire_filelist_verify(filelist
, errors
);
1985 pakfire_filelist_unref(filelist
);
1990 PAKFIRE_EXPORT
int pakfire_check(struct pakfire
* pakfire
, struct pakfire_filelist
* errors
) {
1991 struct pakfire_db
* db
= NULL
;
1994 // Open database in read-only mode and try to load all installed packages
1995 r
= pakfire_db_open(&db
, pakfire
, PAKFIRE_DB_READWRITE
);
1999 // Perform a database integrity check
2000 r
= pakfire_db_check(db
);
2004 // Check if all dependencies are intact
2005 r
= pakfire_verify(pakfire
, NULL
);
2010 r
= pakfire_check_files(pakfire
, db
, errors
);
2016 pakfire_db_unref(db
);
2021 PAKFIRE_EXPORT
int pakfire_sync(struct pakfire
* pakfire
, int solver_flags
, int flags
,
2022 int* changed
, pakfire_status_callback status_callback
, void* status_callback_data
) {
2023 return pakfire_perform_transaction_simple(pakfire
, solver_flags
,
2024 PAKFIRE_REQ_SYNC
, flags
, changed
, status_callback
, status_callback_data
);