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>
30 #include <sys/mount.h>
32 #include <sys/utsname.h>
33 #include <sys/types.h>
38 #include <archive_entry.h>
41 #include <solv/pool.h>
42 #include <solv/poolarch.h>
43 #include <solv/queue.h>
45 #include <pakfire/arch.h>
46 #include <pakfire/build.h>
47 #include <pakfire/config.h>
48 #include <pakfire/constants.h>
49 #include <pakfire/ctx.h>
50 #include <pakfire/db.h>
51 #include <pakfire/dependencies.h>
52 #include <pakfire/dist.h>
53 #include <pakfire/logging.h>
54 #include <pakfire/mount.h>
55 #include <pakfire/os.h>
56 #include <pakfire/package.h>
57 #include <pakfire/packagelist.h>
58 #include <pakfire/pakfire.h>
59 #include <pakfire/parser.h>
60 #include <pakfire/path.h>
61 #include <pakfire/private.h>
62 #include <pakfire/pwd.h>
63 #include <pakfire/repo.h>
64 #include <pakfire/string.h>
65 #include <pakfire/transaction.h>
66 #include <pakfire/util.h>
68 #define LOCK_PATH PAKFIRE_PRIVATE_DIR "/.lock"
71 struct pakfire_ctx
* ctx
;
75 char lock_path
[PATH_MAX
];
76 char cache_path
[PATH_MAX
];
78 struct pakfire_arches
{
79 char nominal
[ARCH_MAX
];
80 const char* effective
;
88 // UID/GID of running user
93 struct pakfire_subid subuids
;
96 struct pakfire_group
{
99 struct pakfire_subid subgids
;
105 struct pakfire_config
* config
;
108 struct pakfire_distro distro
;
114 unsigned int destroy_on_free
:1;
115 unsigned int pool_ready
:1;
116 unsigned int in_free
:1;
120 This is a list of all features that are supported by this version of Pakfire
122 static const struct pakfire_feature
{
125 { "RichDependencies" },
128 { "PackageFormat-6" },
129 { "PackageFormat-5" },
133 { "Compress-Zstandard" },
136 { "Digest-BLAKE2b512" },
137 { "Digest-BLAKE2s256" },
138 { "Digest-SHA3-512" },
139 { "Digest-SHA3-256" },
140 { "Digest-SHA2-512" },
141 { "Digest-SHA2-256" },
144 { "systemd-sysusers" },
145 { "systemd-tmpfiles" },
151 int pakfire_on_root(struct pakfire
* pakfire
) {
152 return (strcmp(pakfire
->path
, "/") == 0);
155 uid_t
pakfire_uid(struct pakfire
* pakfire
) {
156 return pakfire
->user
.uid
;
159 gid_t
pakfire_gid(struct pakfire
* pakfire
) {
160 return pakfire
->group
.gid
;
163 const struct pakfire_subid
* pakfire_subuid(struct pakfire
* pakfire
) {
164 return &pakfire
->user
.subuids
;
167 const struct pakfire_subid
* pakfire_subgid(struct pakfire
* pakfire
) {
168 return &pakfire
->group
.subgids
;
172 Maps any UID/GIDs to the SUBUID/SUBGIDs so that we can transparently
173 copy files in and out of the jail environment.
175 static unsigned int pakfire_map_id(struct pakfire
* pakfire
,
176 const struct pakfire_subid
* subid
, const unsigned int id
) {
177 // Nothing to do if we are running on root
178 if (pakfire_on_root(pakfire
))
182 unsigned int mapped_id
= subid
->id
+ id
;
184 // Check if the ID is in range
185 if (id
> subid
->length
) {
186 ERROR(pakfire
, "Mapped ID is out of range. Setting to %u\n", subid
->id
);
187 mapped_id
= subid
->id
;
193 static unsigned int pakfire_unmap_id(struct pakfire
* pakfire
,
194 const struct pakfire_subid
* subid
, const unsigned int id
) {
195 // Nothing to do if we are running on root
196 if (pakfire_on_root(pakfire
))
200 int unmapped_id
= id
- subid
->id
;
202 // Check if the ID is in range
203 if (unmapped_id
< 0) {
204 ERROR(pakfire
, "Mapped ID is out of range. Setting to %u\n", subid
->id
);
205 unmapped_id
= subid
->id
;
211 static void pool_log(Pool
* pool
, void* data
, int type
, const char* s
) {
212 struct pakfire
* pakfire
= (struct pakfire
*)data
;
214 DEBUG(pakfire
, "pool: %s", s
);
217 static Id
pakfire_handle_ns_pakfire(struct pakfire
* pakfire
, const char* name
) {
218 // Find all supported features
219 for (const struct pakfire_feature
* feature
= features
; feature
->name
; feature
++) {
220 if (strcmp(feature
->name
, name
) == 0)
228 static Id
pakfire_handle_ns_arch(struct pakfire
* pakfire
, const char* name
) {
229 const char* arch
= pakfire_get_arch(pakfire
);
231 return strcmp(arch
, name
) == 0;
234 static Id
pakfire_namespace_callback(Pool
* pool
, void* data
, Id ns
, Id id
) {
235 struct pakfire
* pakfire
= (struct pakfire
*)data
;
237 const char* namespace = pool_id2str(pool
, ns
);
238 const char* name
= pakfire_dep2str(pakfire
, id
);
240 DEBUG(pakfire
, "Namespace callback called for %s(%s)\n", namespace, name
);
242 // Handle the pakfire() namespace
243 if (strcmp(namespace, "pakfire") == 0)
244 return pakfire_handle_ns_pakfire(pakfire
, name
);
246 // Handle the arch() namespace
247 else if (strcmp(namespace, "arch") == 0)
248 return pakfire_handle_ns_arch(pakfire
, name
);
255 static int pakfire_lock_running_kernel(struct pakfire
* pakfire
) {
256 struct utsname utsname
;
257 char buffer
[NAME_MAX
];
260 int r
= uname(&utsname
);
262 ERROR(pakfire
, "uname() failed: %m\n");
266 DEBUG(pakfire
, "Locking running kernel %s\n", utsname
.release
);
268 r
= pakfire_string_format(buffer
, "kernel(%s)", utsname
.release
);
272 // Add a locking pool job
273 Id id
= pool_str2id(pakfire
->pool
, buffer
, 1);
275 queue_push2(&pakfire
->pool
->pooljobs
, SOLVER_LOCK
|SOLVER_SOLVABLE_PROVIDES
, id
);
280 static int pakfire_populate_pool(struct pakfire
* pakfire
) {
281 struct pakfire_db
* db
= NULL
;
282 struct pakfire_repo
* commandline
= NULL
;
283 struct pakfire_repo
* dummy
= NULL
;
284 struct pakfire_repo
* system
= NULL
;
287 const char* arch
= pakfire_get_effective_arch(pakfire
);
289 // Initialize the pool
290 Pool
* pool
= pakfire
->pool
= pool_create();
291 pool_setdisttype(pool
, DISTTYPE_RPM
);
294 // Enable debug output
295 pool_setdebuglevel(pool
, 3);
298 // Set architecture of the pool
299 pool_setarch(pool
, arch
);
302 pool_set_rootdir(pool
, pakfire
->path
);
304 // Set debug callback
305 pool_setdebugcallback(pool
, pool_log
, pakfire
);
307 // Install namespace callback
308 pool_setnamespacecallback(pool
, pakfire_namespace_callback
, pakfire
);
310 // These packages can be installed multiple times simultaneously
311 static const char* pakfire_multiinstall_packages
[] = {
317 for (const char** package
= pakfire_multiinstall_packages
; *package
; package
++) {
318 Id id
= pakfire_str2dep(pakfire
, *package
);
322 queue_push2(&pool
->pooljobs
, SOLVER_SOLVABLE_PROVIDES
|SOLVER_MULTIVERSION
, id
);
325 // Open database in read-only mode and try to load all installed packages
326 r
= pakfire_db_open(&db
, pakfire
, PAKFIRE_DB_READWRITE
);
330 // Create a dummy repository
331 r
= pakfire_repo_create(&dummy
, pakfire
, PAKFIRE_REPO_DUMMY
);
335 // Disable the repository
336 pakfire_repo_set_enabled(dummy
, 0);
338 // Create the system repository
339 r
= pakfire_repo_create(&system
, pakfire
, PAKFIRE_REPO_SYSTEM
);
343 // Set this repository as the installed one
344 pool_set_installed(pool
, pakfire_repo_get_repo(system
));
346 // Create the command line repo
347 r
= pakfire_repo_create(&commandline
, pakfire
, PAKFIRE_REPO_COMMANDLINE
);
351 // Load database content
352 r
= pakfire_db_load(db
, system
);
356 // Lock the running kernel
357 if (pakfire_on_root(pakfire
)) {
358 r
= pakfire_lock_running_kernel(pakfire
);
365 pakfire_db_unref(db
);
367 pakfire_repo_unref(commandline
);
369 pakfire_repo_unref(dummy
);
371 pakfire_repo_unref(system
);
376 static void pakfire_free(struct pakfire
* pakfire
) {
377 struct pakfire_repo
* repo
= NULL
;
380 // Avoid recursive free
381 if (pakfire
->in_free
)
384 pakfire
->in_free
= 1;
386 // Destroy the commandline repository
387 repo
= pakfire_get_repo(pakfire
, PAKFIRE_REPO_COMMANDLINE
);
389 r
= pakfire_repo_clean(repo
, PAKFIRE_REPO_CLEAN_FLAGS_DESTROY
);
391 ERROR(pakfire
, "Could not cleanup %s repository: %m\n", PAKFIRE_REPO_COMMANDLINE
);
393 pakfire_repo_unref(repo
);
396 // Release Magic Context
398 magic_close(pakfire
->magic
);
400 // Release lock (if not already done so)
401 pakfire_release_lock(pakfire
);
403 if (pakfire
->destroy_on_free
&& *pakfire
->path
) {
404 DEBUG(pakfire
, "Destroying %s\n", pakfire
->path
);
406 // Umount the ramdisk
407 r
= umount2(pakfire
->path
, MNT_DETACH
);
409 ERROR(pakfire
, "Could not umount ramdisk at %s: %m\n", pakfire
->path
);
411 // Destroy the temporary directory
412 pakfire_rmtree(pakfire
->path
, 0);
415 pakfire_repo_free_all(pakfire
);
418 pool_free(pakfire
->pool
);
421 pakfire_config_unref(pakfire
->config
);
424 pakfire_ctx_unref(pakfire
->ctx
);
429 // Safety check in case this is being launched on the host system
430 static int pakfire_safety_checks(struct pakfire
* pakfire
) {
431 // Nothing to do if we are not working on root
432 if (!pakfire_on_root(pakfire
))
435 // We must be root in order to operate in /
436 if (pakfire
->user
.uid
) {
437 ERROR(pakfire
, "Must be running as root on /\n");
442 if (strcmp(pakfire
->distro
.id
, "ipfire") != 0) {
443 ERROR(pakfire
, "Not an IPFire system\n");
451 static int pakfire_read_one_repo_config(struct pakfire
* pakfire
, DIR* dir
, const char* path
) {
457 fd
= openat(dirfd(dir
), path
, O_CLOEXEC
);
461 // Re-open as file handle
466 // Read the configuration
467 r
= pakfire_config_read(pakfire
->config
, f
);
475 static int pakfire_read_repo_config(struct pakfire
* pakfire
) {
476 struct dirent
* entry
= NULL
;
480 // Make path absolute
481 r
= pakfire_path(pakfire
, path
, "%s", PAKFIRE_CONFIG_DIR
"/repos");
485 DEBUG(pakfire
, "Reading repository configuration from %s\n", path
);
488 DIR* dir
= opendir(path
);
495 ERROR(pakfire
, "Could not open %s: %m\n", path
);
501 entry
= readdir(dir
);
505 // Skip anything that isn't a regular file
506 if (entry
->d_type
!= DT_REG
)
509 // Skip any files that don't end on .repo
510 if (!pakfire_path_match("*.repo", entry
->d_name
))
513 // Read the configuration
514 r
= pakfire_read_one_repo_config(pakfire
, dir
, entry
->d_name
);
529 const char* pakfire_get_distro_name(struct pakfire
* pakfire
) {
530 if (*pakfire
->distro
.name
)
531 return pakfire
->distro
.name
;
536 const char* pakfire_get_distro_id(struct pakfire
* pakfire
) {
537 if (*pakfire
->distro
.id
)
538 return pakfire
->distro
.id
;
543 const char* pakfire_get_distro_vendor(struct pakfire
* pakfire
) {
544 if (*pakfire
->distro
.vendor
)
545 return pakfire
->distro
.vendor
;
550 const char* pakfire_get_distro_version(struct pakfire
* pakfire
) {
551 if (*pakfire
->distro
.version
)
552 return pakfire
->distro
.version
;
557 const char* pakfire_get_distro_version_id(struct pakfire
* pakfire
) {
558 if (*pakfire
->distro
.version_id
)
559 return pakfire
->distro
.version_id
;
564 const char* pakfire_get_distro_tag(struct pakfire
* pakfire
) {
567 if (*pakfire
->distro
.tag
)
568 return pakfire
->distro
.tag
;
570 const char* id
= pakfire_get_distro_id(pakfire
);
571 const char* version_id
= pakfire_get_distro_version_id(pakfire
);
573 // Break if the configuration is incomplete
574 if (!id
|| !version_id
) {
580 r
= pakfire_string_format(pakfire
->distro
.tag
, "%s%s", id
, version_id
);
585 return pakfire
->distro
.tag
;
588 static int pakfire_config_import_distro(struct pakfire
* pakfire
) {
589 // Nothing to do if there is no distro section
590 if (!pakfire_config_has_section(pakfire
->config
, "distro"))
594 const char* name
= pakfire_config_get(pakfire
->config
, "distro", "name", NULL
);
596 pakfire_string_set(pakfire
->distro
.name
, name
);
599 const char* id
= pakfire_config_get(pakfire
->config
, "distro", "id", NULL
);
601 pakfire_string_set(pakfire
->distro
.id
, id
);
604 const char* version_id
= pakfire_config_get(pakfire
->config
, "distro", "version_id", NULL
);
606 pakfire_string_set(pakfire
->distro
.version_id
, version_id
);
609 const char* codename
= pakfire_config_get(pakfire
->config
, "distro", "codename", NULL
);
611 pakfire_string_set(pakfire
->distro
.version_codename
, codename
);
614 if (*pakfire
->distro
.version_codename
)
615 pakfire_string_format(pakfire
->distro
.version
, "%s (%s)",
616 pakfire
->distro
.version_id
, pakfire
->distro
.version_codename
);
618 pakfire_string_set(pakfire
->distro
.version
, pakfire
->distro
.version_id
);
620 // Fill in pretty name
621 pakfire_string_format(pakfire
->distro
.pretty_name
, "%s %s",
622 pakfire
->distro
.name
, pakfire
->distro
.version
);
625 const char* vendor
= pakfire_config_get(pakfire
->config
, "distro", "vendor", NULL
);
627 pakfire_string_set(pakfire
->distro
.vendor
, vendor
);
630 const char* slogan
= pakfire_config_get(pakfire
->config
, "distro", "slogan", NULL
);
632 pakfire_string_set(pakfire
->distro
.slogan
, slogan
);
637 static int pakfire_read_config(struct pakfire
* pakfire
, FILE* f
) {
640 DEBUG(pakfire
, "Reading configuration\n");
642 // Read configuration from file
644 r
= pakfire_config_read(pakfire
->config
, f
);
646 ERROR(pakfire
, "Could not parse configuration: %m\n");
651 // Import distro configuration
652 r
= pakfire_config_import_distro(pakfire
);
656 // Read repository configuration
657 r
= pakfire_read_repo_config(pakfire
);
664 static int pakfire_read_os_release(struct pakfire
* pakfire
) {
669 r
= pakfire_path(pakfire
, path
, "%s", "/etc/os-release");
673 return pakfire_distro(&pakfire
->distro
, path
);
676 static int pakfire_set_cache_path(struct pakfire
* pakfire
) {
677 const char* cache_path
= pakfire_ctx_get_cache_path(pakfire
->ctx
);
678 const char* arch
= pakfire_get_effective_arch(pakfire
);
680 // Format the final path
681 return pakfire_string_format(pakfire
->cache_path
, "%s/%s/%s/%s",
682 cache_path
, pakfire
->distro
.id
, pakfire
->distro
.version_id
, arch
);
685 static int pakfire_setup_user(struct pakfire
* pakfire
) {
687 struct passwd
* u
= NULL
;
689 struct group
* g
= NULL
;
693 // Fetch the UID/GID we are running as
694 const uid_t uid
= geteuid();
695 const gid_t gid
= getegid();
697 // Fetch all user information
698 r
= getpwuid_r(uid
, &user
, buffer
, sizeof(buffer
), &u
);
703 pakfire
->user
.uid
= pakfire
->user
.subuids
.id
= uid
;
706 r
= pakfire_string_set(pakfire
->user
.name
, user
.pw_name
);
710 // Store home directory
711 r
= pakfire_string_set(pakfire
->user
.home
, user
.pw_dir
);
715 // Fetch all group information
716 r
= getgrgid_r(gid
, &group
, buffer
, sizeof(buffer
), &g
);
721 pakfire
->group
.gid
= pakfire
->group
.subgids
.id
= gid
;
724 r
= pakfire_string_set(pakfire
->group
.name
, group
.gr_name
);
729 Set default ranges for SUBUID/SUBGID
731 For root, we set the entire range, but for unprivileged users,
732 we can only map our own UID/GID. This may later be overwritten
733 from /etc/sub{u,g}id.
736 pakfire
->user
.subuids
.length
= pakfire
->group
.subgids
.length
= 0xffffffff - 1;
738 pakfire
->user
.subuids
.length
= pakfire
->group
.subgids
.length
= 1;
740 // Read SUBUID/SUBGIDs from file
741 if (!pakfire_on_root(pakfire
)) {
743 r
= pakfire_getsubuid(pakfire
, pakfire
->user
.name
, &pakfire
->user
.subuids
);
754 r
= pakfire_getsubgid(pakfire
, pakfire
->user
.name
, &pakfire
->group
.subgids
);
772 PAKFIRE_EXPORT
int pakfire_create(struct pakfire
** pakfire
, struct pakfire_ctx
* ctx
,
773 const char* path
, const char* arch
, FILE* conf
, int flags
) {
774 char tempdir
[PATH_MAX
] = PAKFIRE_TMP_DIR
"/pakfire-root-XXXXXX";
775 char private_dir
[PATH_MAX
];
778 // Reset pakfire pointer
781 // Default to the native architecture
783 arch
= pakfire_arch_native();
785 struct pakfire
* p
= calloc(1, sizeof(*p
));
789 // Reference the context
790 p
->ctx
= pakfire_ctx_ref(ctx
);
795 // Store the nominal architecture
796 r
= pakfire_string_set(p
->arches
.nominal
, arch
);
800 // Determine the effective architecture
801 p
->arches
.effective
= pakfire_arch_is_supported_by_host(arch
);
802 if (!p
->arches
.effective
) {
803 ERROR(p
, "Unsupported architecture: %s\n", arch
);
808 // Path must be absolute
809 if (path
&& !pakfire_string_startswith(path
, "/")) {
810 ERROR(p
, "Invalid path: %s\n", path
);
815 // Create a ramdisk if no path was given
817 r
= pakfire_make_ramdisk(p
, tempdir
, NULL
);
821 // Use the ramdisk as path
824 // Destroy everything when done
825 p
->destroy_on_free
= 1;
829 pakfire_string_set(p
->path
, path
);
832 r
= pakfire_setup_user(p
);
836 // Initialise configuration
837 r
= pakfire_config_create(&p
->config
);
841 // Read /etc/os-release
842 r
= pakfire_read_os_release(p
);
843 if (r
&& errno
!= ENOENT
)
846 // Bump RLIMIT_NOFILE to maximum
847 r
= pakfire_rlimit_set(p
, PAKFIRE_RLIMIT_NOFILE_MAX
);
851 DEBUG(p
, "Pakfire initialized at %p\n", p
);
852 DEBUG(p
, " user = %s (%u)\n", p
->user
.name
, p
->user
.uid
);
853 DEBUG(p
, " group = %s (%u)\n", p
->group
.name
, p
->group
.gid
);
854 DEBUG(p
, " arch = %s (%s)\n", pakfire_get_arch(p
), pakfire_get_effective_arch(p
));
855 DEBUG(p
, " path = %s\n", pakfire_get_path(p
));
856 if (p
->user
.subuids
.id
)
857 DEBUG(p
, " subuid = %u (%zu)\n", p
->user
.subuids
.id
, p
->user
.subuids
.length
);
858 if (p
->group
.subgids
.id
)
859 DEBUG(p
, " subgid = %u (%zu)\n", p
->group
.subgids
.id
, p
->group
.subgids
.length
);
861 // Perform some safety checks
862 r
= pakfire_safety_checks(p
);
866 // Read configuration file
867 r
= pakfire_read_config(p
, conf
);
871 // Dump distribution configuration
872 DEBUG(p
, " Distribution: %s\n", p
->distro
.pretty_name
);
873 DEBUG(p
, " name = %s\n", p
->distro
.name
);
874 DEBUG(p
, " id = %s\n", p
->distro
.id
);
875 DEBUG(p
, " version = %s\n", p
->distro
.version
);
876 DEBUG(p
, " version_id = %s\n", p
->distro
.version_id
);
877 if (*p
->distro
.version_codename
)
878 DEBUG(p
, " codename = %s\n", p
->distro
.version_codename
);
879 if (*p
->distro
.vendor
)
880 DEBUG(p
, " vendor = %s\n", p
->distro
.vendor
);
881 if (*p
->distro
.slogan
)
882 DEBUG(p
, " slogan = %s\n", p
->distro
.slogan
);
885 r
= pakfire_path(p
, p
->lock_path
, "%s", LOCK_PATH
);
887 ERROR(p
, "Could not set lock path: %m\n");
892 r
= pakfire_set_cache_path(p
);
894 ERROR(p
, "Could not set cache path: %m\n");
898 // Make path for private files
899 r
= pakfire_path(p
, private_dir
, "%s", PAKFIRE_PRIVATE_DIR
);
903 // Make sure that our private directory exists
904 r
= pakfire_mkdir(private_dir
, 0755);
906 ERROR(p
, "Could not create private directory %s: %m\n", private_dir
);
911 r
= pakfire_populate_pool(p
);
915 // Create repositories
916 r
= pakfire_repo_import(p
, p
->config
);
930 PAKFIRE_EXPORT
struct pakfire
* pakfire_ref(struct pakfire
* pakfire
) {
936 PAKFIRE_EXPORT
struct pakfire
* pakfire_unref(struct pakfire
* pakfire
) {
937 if (--pakfire
->nrefs
> 0)
940 pakfire_free(pakfire
);
945 struct pakfire_ctx
* pakfire_ctx(struct pakfire
* pakfire
) {
946 return pakfire_ctx_ref(pakfire
->ctx
);
949 PAKFIRE_EXPORT
int pakfire_has_flag(struct pakfire
* pakfire
, const int flag
) {
950 return pakfire
->flags
& flag
;
953 struct pakfire_config
* pakfire_get_config(struct pakfire
* pakfire
) {
954 if (!pakfire
->config
)
957 return pakfire_config_ref(pakfire
->config
);
960 PAKFIRE_EXPORT
const char* pakfire_get_path(struct pakfire
* pakfire
) {
961 return pakfire
->path
;
964 int pakfire_acquire_lock(struct pakfire
* pakfire
) {
967 // Check if the lock is already held
969 ERROR(pakfire
, "Lock is already been acquired by this process\n");
973 DEBUG(pakfire
, "Acquire lock...\n");
975 // Ensure the parent directory exists
976 pakfire_mkparentdir(pakfire
->lock_path
, 0755);
978 // Open the lock file
979 pakfire
->lock
= fopen(pakfire
->lock_path
, "w");
980 if (!pakfire
->lock
) {
981 ERROR(pakfire
, "Could not open lock file %s: %m\n", pakfire
->lock_path
);
985 // Attempt to lock the file exclusively
987 r
= flock(fileno(pakfire
->lock
), LOCK_EX
|LOCK_NB
);
993 DEBUG(pakfire
, "Could not acquire lock %s: %m\n", pakfire
->lock_path
);
995 // Wait 500ms until the next attempt
1000 DEBUG(pakfire
, "Lock acquired\n");
1005 void pakfire_release_lock(struct pakfire
* pakfire
) {
1009 DEBUG(pakfire
, "Releasing lock\n");
1011 fclose(pakfire
->lock
);
1012 pakfire
->lock
= NULL
;
1014 // Attempt to unlink the lock file
1015 unlink(pakfire
->lock_path
);
1018 int __pakfire_path(struct pakfire
* pakfire
, char* path
, const size_t length
,
1019 const char* format
, ...) {
1020 char buffer
[PATH_MAX
];
1024 // Format input into buffer
1025 va_start(args
, format
);
1026 r
= __pakfire_string_vformat(buffer
, sizeof(buffer
), format
, args
);
1029 // Break on any errors
1033 // Join paths together
1034 return __pakfire_path_append(path
, length
, pakfire
->path
, buffer
);
1037 const char* pakfire_relpath(struct pakfire
* pakfire
, const char* path
) {
1038 return pakfire_path_relpath(pakfire
->path
, path
);
1041 int __pakfire_cache_path(struct pakfire
* pakfire
, char* path
, size_t length
,
1042 const char* format
, ...) {
1043 char buffer
[PATH_MAX
];
1047 // Format input into buffer
1048 va_start(args
, format
);
1049 r
= __pakfire_string_vformat(buffer
, sizeof(buffer
), format
, args
);
1052 // Break on any errors
1056 // Join paths together
1057 return __pakfire_path_append(path
, length
, pakfire
->cache_path
, buffer
);
1060 magic_t
pakfire_get_magic(struct pakfire
* pakfire
) {
1063 // Initialize the context if not already done
1064 if (!pakfire
->magic
) {
1065 // Allocate a new context
1066 pakfire
->magic
= magic_open(MAGIC_MIME_TYPE
| MAGIC_ERROR
| MAGIC_NO_CHECK_TOKENS
);
1067 if (!pakfire
->magic
) {
1068 ERROR(pakfire
, "Could not allocate magic context: %m\n");
1072 // Load the database
1073 r
= magic_load(pakfire
->magic
, NULL
);
1075 ERROR(pakfire
, "Could not open the magic database: %s\n",
1076 magic_error(pakfire
->magic
));
1081 return pakfire
->magic
;
1085 magic_close(pakfire
->magic
);
1087 // Reset the pointer
1088 pakfire
->magic
= NULL
;
1093 int pakfire_repo_walk(struct pakfire
* pakfire
,
1094 pakfire_repo_walk_callback callback
, void* p
) {
1095 struct pakfire_repo
* repo
= NULL
;
1096 Repo
* solv_repo
= NULL
;
1100 Pool
* pool
= pakfire
->pool
;
1102 // Run func for every repository
1103 FOR_REPOS(i
, solv_repo
) {
1104 repo
= pakfire_repo_create_from_repo(pakfire
, solv_repo
);
1109 r
= callback(pakfire
, repo
, p
);
1110 pakfire_repo_unref(repo
);
1120 static int __pakfire_repo_clean(struct pakfire
* pakfire
, struct pakfire_repo
* repo
,
1122 int flags
= *(int*)p
;
1124 return pakfire_repo_clean(repo
, flags
);
1127 PAKFIRE_EXPORT
int pakfire_clean(struct pakfire
* pakfire
, int flags
) {
1130 // Clean all repositories
1131 r
= pakfire_repo_walk(pakfire
, __pakfire_repo_clean
, &flags
);
1135 // Clean build environments
1136 r
= pakfire_build_clean(pakfire
, flags
);
1141 return pakfire_rmtree(PAKFIRE_CACHE_DIR
, 0);
1144 static int __pakfire_repo_refresh(struct pakfire
* pakfire
, struct pakfire_repo
* repo
,
1146 int flags
= *(int*)p
;
1148 return pakfire_repo_refresh(repo
, flags
);
1151 PAKFIRE_EXPORT
int pakfire_refresh(struct pakfire
* pakfire
, int flags
) {
1152 return pakfire_repo_walk(pakfire
, __pakfire_repo_refresh
, &flags
);
1155 PAKFIRE_EXPORT
const char* pakfire_get_arch(struct pakfire
* pakfire
) {
1156 return pakfire
->arches
.nominal
;
1159 const char* pakfire_get_effective_arch(struct pakfire
* pakfire
) {
1160 return pakfire
->arches
.effective
;
1163 PAKFIRE_EXPORT
int pakfire_version_compare(struct pakfire
* pakfire
, const char* evr1
, const char* evr2
) {
1164 return pool_evrcmp_str(pakfire
->pool
, evr1
, evr2
, EVRCMP_COMPARE
);
1167 Pool
* pakfire_get_solv_pool(struct pakfire
* pakfire
) {
1168 return pakfire
->pool
;
1171 void pakfire_pool_has_changed(struct pakfire
* pakfire
) {
1172 pakfire
->pool_ready
= 0;
1175 static int __pakfire_repo_internalize(struct pakfire
* pakfire
, struct pakfire_repo
* repo
,
1177 int flags
= *(int*)p
;
1179 return pakfire_repo_internalize(repo
, flags
);
1182 void pakfire_pool_internalize(struct pakfire
* pakfire
) {
1185 // Nothing to do if the pool is ready
1186 if (pakfire
->pool_ready
)
1189 // Internalize all repositories
1190 pakfire_repo_walk(pakfire
, __pakfire_repo_internalize
, &flags
);
1192 // Create fileprovides
1193 pool_addfileprovides(pakfire
->pool
);
1195 // Create whatprovides index
1196 pool_createwhatprovides(pakfire
->pool
);
1198 // Mark the pool as ready
1199 pakfire
->pool_ready
= 1;
1202 PAKFIRE_EXPORT
struct pakfire_repolist
* pakfire_get_repos(struct pakfire
* pakfire
) {
1203 struct pakfire_repolist
* list
;
1205 int r
= pakfire_repolist_create(&list
);
1209 Pool
* pool
= pakfire_get_solv_pool(pakfire
);
1213 FOR_REPOS(i
, solv_repo
) {
1214 // Skip the dummy repository
1215 if (strcmp(solv_repo
->name
, PAKFIRE_REPO_DUMMY
) == 0)
1218 struct pakfire_repo
* repo
= pakfire_repo_create_from_repo(pakfire
, solv_repo
);
1224 r
= pakfire_repolist_append(list
, repo
);
1226 pakfire_repo_unref(repo
);
1230 pakfire_repo_unref(repo
);
1236 pakfire_repolist_unref(list
);
1240 PAKFIRE_EXPORT
struct pakfire_repo
* pakfire_get_repo(struct pakfire
* pakfire
, const char* name
) {
1241 Pool
* pool
= pakfire_get_solv_pool(pakfire
);
1248 FOR_REPOS(i
, repo
) {
1249 if (strcmp(repo
->name
, name
) == 0)
1250 return pakfire_repo_create_from_repo(pakfire
, repo
);
1257 struct pakfire_repo
* pakfire_get_installed_repo(struct pakfire
* pakfire
) {
1258 if (!pakfire
->pool
->installed
)
1261 return pakfire_repo_create_from_repo(pakfire
, pakfire
->pool
->installed
);
1265 Convenience function to dist() a package on the fly
1267 static int pakfire_commandline_dist(struct pakfire
* pakfire
, struct pakfire_repo
* repo
,
1268 const char* path
, struct pakfire_package
** package
) {
1269 char* result
= NULL
;
1272 // XXX result is not unique!
1275 r
= pakfire_dist(pakfire
, path
, PAKFIRE_TMP_DIR
, &result
);
1279 // Try to add the package to the repository
1280 r
= pakfire_repo_add(repo
, result
, package
);
1290 Convenience function to add a package to the @commandline repository
1292 int pakfire_commandline_add(struct pakfire
* pakfire
, const char* path
,
1293 struct pakfire_package
** package
) {
1294 struct pakfire_repo
* repo
= NULL
;
1297 // Find the commandline repository
1298 repo
= pakfire_get_repo(pakfire
, PAKFIRE_REPO_COMMANDLINE
);
1300 ERROR(pakfire
, "Could not find the commandline repository: %m\n");
1305 r
= pakfire_repo_add(repo
, path
, package
);
1308 r
= pakfire_commandline_dist(pakfire
, repo
, path
, package
);
1317 pakfire_repo_unref(repo
);
1322 static int __pakfire_search(struct pakfire
* pakfire
, struct pakfire_packagelist
* list
,
1323 const Id
* keys
, const char* what
, int flags
) {
1328 // Get the pool ready
1329 pakfire_pool_internalize(pakfire
);
1331 // Initialize the result queue
1332 queue_init(&matches
);
1334 // Setup the data interator
1335 dataiterator_init(&di
, pakfire
->pool
, 0, 0, 0, what
, flags
);
1337 // Search through these keys and add matches to the queue
1338 for (const Id
* key
= keys
; *key
; key
++) {
1339 dataiterator_set_keyname(&di
, *key
);
1340 dataiterator_set_search(&di
, 0, 0);
1342 while (dataiterator_step(&di
))
1343 queue_pushunique(&matches
, di
.solvid
);
1346 // Import matches into the package list
1347 r
= pakfire_packagelist_import_solvables(list
, pakfire
, &matches
);
1352 dataiterator_free(&di
);
1353 queue_free(&matches
);
1358 static int pakfire_search_filelist(struct pakfire
* pakfire
, const char* what
, int flags
,
1359 struct pakfire_packagelist
* list
) {
1365 return __pakfire_search(pakfire
, list
, keys
, what
, SEARCH_FILES
|SEARCH_GLOB
);
1368 static int pakfire_search_dep(struct pakfire
* pakfire
, Id type
, const char* what
, int flags
,
1369 struct pakfire_packagelist
* list
) {
1372 // Get the pool ready
1373 pakfire_pool_internalize(pakfire
);
1375 // Translate dependency to ID
1376 Id dep
= pakfire_str2dep(pakfire
, what
);
1383 queue_init(&matches
);
1385 // Search for anything that matches
1386 pool_whatmatchesdep(pakfire
->pool
, type
, dep
, &matches
, 0);
1388 // Add the result to the packagelist
1389 r
= pakfire_packagelist_import_solvables(list
, pakfire
, &matches
);
1394 queue_free(&matches
);
1399 PAKFIRE_EXPORT
int pakfire_whatprovides(struct pakfire
* pakfire
, const char* what
, int flags
,
1400 struct pakfire_packagelist
* list
) {
1403 // Check for valid input
1404 if (!what
|| !list
) {
1409 // Search for all packages that match this dependency
1410 r
= pakfire_search_dep(pakfire
, SOLVABLE_PROVIDES
, what
, flags
, list
);
1414 // Search the filelist
1416 r
= pakfire_search_filelist(pakfire
, what
, flags
, list
);
1424 static int __pakfire_whatrequires(struct pakfire_ctx
* ctx
, struct pakfire_package
* pkg
, void* data
) {
1425 struct pakfire_packagelist
* list
= (struct pakfire_packagelist
*)data
;
1427 return pakfire_package_get_reverse_requires(pkg
, list
);
1430 PAKFIRE_EXPORT
int pakfire_whatrequires(struct pakfire
* pakfire
, const char* what
, int flags
,
1431 struct pakfire_packagelist
* list
) {
1432 struct pakfire_packagelist
* packages
= NULL
;
1440 // Create a new package list
1441 r
= pakfire_packagelist_create(&packages
, pakfire
->ctx
);
1445 // Find any packages that match the name
1446 r
= __pakfire_search(pakfire
, packages
, keys
, what
, SEARCH_STRING
);
1450 // Find everything for all packages
1451 r
= pakfire_packagelist_walk(packages
, __pakfire_whatrequires
, list
);
1455 // Append any simple dependencies
1456 r
= pakfire_search_dep(pakfire
, SOLVABLE_REQUIRES
, what
, flags
, list
);
1462 pakfire_packagelist_unref(packages
);
1467 PAKFIRE_EXPORT
int pakfire_search(struct pakfire
* pakfire
, const char* what
, int flags
,
1468 struct pakfire_packagelist
* list
) {
1472 SOLVABLE_DESCRIPTION
,
1476 const Id keys_name_only
[] = {
1481 return __pakfire_search(pakfire
,
1483 (flags
& PAKFIRE_SEARCH_NAME_ONLY
) ? keys_name_only
: keys
,
1485 SEARCH_SUBSTRING
|SEARCH_NOCASE
);
1490 // XXX This function is deprecated and needs to be removed
1491 void pakfire_log(struct pakfire
* pakfire
, int priority
, int r
,
1492 const char* file
, int line
, const char* fn
, const char* format
, ...) {
1493 char* buffer
= NULL
;
1497 int saved_errno
= errno
;
1501 va_start(args
, format
);
1502 r
= vasprintf(&buffer
, format
, args
);
1506 errno
= saved_errno
;
1511 // Pass on to the context logger
1512 pakfire_ctx_log(pakfire
->ctx
, priority
, file
, line
, fn
, "%s", buffer
);
1515 static const char* pakfire_user_lookup(void* data
, la_int64_t uid
) {
1516 struct pakfire
* pakfire
= (struct pakfire
*)data
;
1518 // Unmap the UID first
1519 uid
= pakfire_unmap_id(pakfire
, &pakfire
->user
.subuids
, uid
);
1521 // Fast path for "root"
1525 DEBUG(pakfire
, "Looking up name for UID %ld\n", uid
);
1527 // Find a matching entry in /etc/passwd
1528 struct passwd
* entry
= pakfire_getpwuid(pakfire
, uid
);
1530 ERROR(pakfire
, "Could not retrieve uname for %ld: %m\n", uid
);
1534 DEBUG(pakfire
, "Mapping UID %ld to %s\n", uid
, entry
->pw_name
);
1536 return entry
->pw_name
;
1539 static const char* pakfire_group_lookup(void* data
, la_int64_t gid
) {
1540 struct pakfire
* pakfire
= (struct pakfire
*)data
;
1542 // Unmap the GID first
1543 gid
= pakfire_unmap_id(pakfire
, &pakfire
->group
.subgids
, gid
);
1545 // Fast path for "root"
1549 DEBUG(pakfire
, "Looking up name for GID %ld\n", gid
);
1551 // Find a matching entry in /etc/group
1552 struct group
* entry
= pakfire_getgrgid(pakfire
, gid
);
1554 ERROR(pakfire
, "Could not retrieve gname for %ld: %m\n", gid
);
1558 DEBUG(pakfire
, "Mapping GID %ld to %s\n", gid
, entry
->gr_name
);
1560 return entry
->gr_name
;
1563 struct archive
* pakfire_make_archive_disk_reader(struct pakfire
* pakfire
, int internal
) {
1564 struct archive
* archive
= archive_read_disk_new();
1568 // Do not read fflags
1569 int r
= archive_read_disk_set_behavior(archive
, ARCHIVE_READDISK_NO_FFLAGS
);
1571 ERROR(pakfire
, "Could not change behavior of reader: %s\n",
1572 archive_error_string(archive
));
1573 archive_read_free(archive
);
1577 // Install user/group lookups
1579 archive_read_disk_set_uname_lookup(archive
, pakfire
, pakfire_user_lookup
, NULL
);
1580 archive_read_disk_set_gname_lookup(archive
, pakfire
, pakfire_group_lookup
, NULL
);
1582 archive_read_disk_set_standard_lookup(archive
);
1588 static la_int64_t
pakfire_uid_lookup(void* data
, const char* name
, la_int64_t uid
) {
1589 struct pakfire
* pakfire
= (struct pakfire
*)data
;
1591 // Fast path for "root"
1592 if (strcmp(name
, "root") == 0)
1593 return pakfire_map_id(pakfire
, &pakfire
->user
.subuids
, 0);
1595 DEBUG(pakfire
, "Looking up UID for '%s' (%ld)\n", name
, uid
);
1597 // Find a matching entry in /etc/passwd
1598 struct passwd
* entry
= pakfire_getpwnam(pakfire
, name
);
1600 ERROR(pakfire
, "Could not retrieve UID for '%s': %m\n", name
);
1601 return pakfire_map_id(pakfire
, &pakfire
->user
.subuids
, 0);
1604 DEBUG(pakfire
, "Mapping %s to UID %u\n", name
, entry
->pw_uid
);
1606 return pakfire_map_id(pakfire
, &pakfire
->user
.subuids
, entry
->pw_uid
);
1609 static la_int64_t
pakfire_gid_lookup(void* data
, const char* name
, la_int64_t gid
) {
1610 struct pakfire
* pakfire
= (struct pakfire
*)data
;
1612 // Fast path for "root"
1613 if (strcmp(name
, "root") == 0)
1614 return pakfire_map_id(pakfire
, &pakfire
->group
.subgids
, 0);
1616 DEBUG(pakfire
, "Looking up GID for '%s' (%ld)\n", name
, gid
);
1618 // Find a matching entry in /etc/group
1619 struct group
* entry
= pakfire_getgrnam(pakfire
, name
);
1621 ERROR(pakfire
, "Could not retrieve GID for '%s': %m\n", name
);
1622 return pakfire_map_id(pakfire
, &pakfire
->group
.subgids
, 0);
1625 DEBUG(pakfire
, "Mapping %s to GID %u\n", name
, entry
->gr_gid
);
1627 return pakfire_map_id(pakfire
, &pakfire
->group
.subgids
, entry
->gr_gid
);
1630 struct archive
* pakfire_make_archive_disk_writer(struct pakfire
* pakfire
, int internal
) {
1631 struct archive
* archive
= archive_write_disk_new();
1635 // Set flags for extracting files
1637 ARCHIVE_EXTRACT_ACL
|
1638 ARCHIVE_EXTRACT_OWNER
|
1639 ARCHIVE_EXTRACT_PERM
|
1640 ARCHIVE_EXTRACT_TIME
|
1641 ARCHIVE_EXTRACT_UNLINK
|
1642 ARCHIVE_EXTRACT_XATTR
;
1644 archive_write_disk_set_options(archive
, flags
);
1646 // Install our own routine for user/group lookups
1648 archive_write_disk_set_user_lookup(archive
, pakfire
, pakfire_uid_lookup
, NULL
);
1649 archive_write_disk_set_group_lookup(archive
, pakfire
, pakfire_gid_lookup
, NULL
);
1651 archive_write_disk_set_standard_lookup(archive
);
1657 // Convenience functions to install/erase/update packages
1659 static int pakfire_verify(struct pakfire
* pakfire
, int *changed
) {
1661 return pakfire_perform_transaction_simple(pakfire
, 0, PAKFIRE_JOB_VERIFY
,
1662 0, changed
, NULL
, NULL
);
1668 static int pakfire_check_files(struct pakfire
* pakfire
,
1669 struct pakfire_db
* db
, struct pakfire_filelist
* errors
) {
1670 struct pakfire_filelist
* filelist
= NULL
;
1673 // Fetch the filelist
1674 r
= pakfire_db_filelist(db
, &filelist
);
1678 // Verify the filelist
1679 r
= pakfire_filelist_verify(filelist
, errors
);
1683 pakfire_filelist_unref(filelist
);
1688 PAKFIRE_EXPORT
int pakfire_check(struct pakfire
* pakfire
, struct pakfire_filelist
* errors
) {
1689 struct pakfire_db
* db
= NULL
;
1692 // Open database in read-only mode and try to load all installed packages
1693 r
= pakfire_db_open(&db
, pakfire
, PAKFIRE_DB_READWRITE
);
1697 // Perform a database integrity check
1698 r
= pakfire_db_check(db
);
1702 // Check if all dependencies are intact
1703 r
= pakfire_verify(pakfire
, NULL
);
1708 r
= pakfire_check_files(pakfire
, db
, errors
);
1714 pakfire_db_unref(db
);