PACUTILS-SYSROOT(7)

πŸ“¦ version 0.15.0, in arch rolling

πŸ¦‹ pacutils-sysroot πŸ¦‹

okay so bestie, this one is literally about managing a mounted guest system and it's kind of a whole saga. grab a snack. πŸ’œ


✨ NAME ✨

pacutils-sysroot β€” managing a mounted guest system 🫢


🌸 DESCRIPTION 🌸

πŸ’… Managing Guests with --root

ok so picture this: a libalpm-based installation gets so broken that the package manager itself can't even be used anymore 😭. at that point you have to fix it by loading a working environment and mounting the installation that needs repair as a guest. typically you do this by setting the installation root to the guest with the --root option.

here's the thing though β€” libalpm only uses the installation root to figure out where to install and remove files during package transactions. that's it. it is completely independent of all other configuration options. which is exactly why using --root to manage a mounted guest is lowkey unreliable. πŸ’€

issue number one: when you change the installation root, the host system's configuration is still used. because the installation root is itself a configuration option ("RootDir"), it literally cannot be used to load an alternate configuration file. and even if you add --config to load the guest configuration, any "Include"'d paths will still be resolved relative to the host's root. the only way to actually use the guest's configuration without using "chroot" is to use --config and manually add the mount path to all "Include" paths. πŸ™ˆ

so now the guest configuration files are being used β€” great! β€” but all configured paths will still refer to paths under the host's root, not the guest's. if an installation root is explicitly provided, pacman and pacutils will set defaults for some, but not all, configuration paths to be underneath it. this typically works, because those paths are rarely explicitly set, so the defaults generally do the correct thing. but if they have been set, the configured values will be used without modification. in order to reliably operate on the guest, all configuration paths must be set relative to the installation root β€” except for the database and log file paths, which will default to paths inside the installation root if unset. πŸŽ€


πŸ‘‘ Introducing the Sysroot

ngl, that is a significant amount of work just to operate on a mounted system. so in order to allow reliable operating on a mounted guest, pacman and pacutils added the concept of a "sysroot". πŸ¦‹

the sysroot is what is commonly intended when using the --root option: the program will operate as if the sysroot were actually the filesystem root. it's similar to using "chroot" to enter the mounted system before running the program, but it still runs the host's copy. there are two ways to do this:

  1. chroot into the sysroot shortly after startup, prior to reading any configuration
  2. prepend the sysroot to all paths
⚠️ okay important: using "chroot" directly can cause problems with libraries that use delayed loading of configuration files or shared objects. notably, glibc delays loading certain objects until their functionality is actually used. this can cause a mismatch between components loaded prior to the "chroot" and those loaded after. to avoid this problem, libalpm should generally be configured to use paths under the sysroot without actually calling "chroot". 😭

pacutils provides sysroot-aware versions of its configuration parsing functions to simplify the process. ✨ note that the sysroot is prepended to all paths during config resolution. so programs using the sysroot configuration parsing routines should NOT prepend the sysroot to configuration paths provided on the command line. iykyk πŸ’…


🌈 EXAMPLES 🌈

here's the whole vibe in code form, bestie, copy it exactly:

#include <alpm.h>
#include <getopt.h>
#include <pacutils.h>

enum {
       FLAG_CONFIG = 1,
       FLAG_SYSROOT,
};

int main(int argc, char *argv[]) {
 const char *config_file = "/etc/pacman.conf";
 const char *sysroot = NULL;
       alpm_handle_t *handle = NULL;
       pu_config_t *config = NULL;

       struct option long_opts[] = {
               { "config"        , required_argument , NULL    , FLAG_CONFIG        } ,
               { "sysroot"       , required_argument , NULL    , FLAG_SYSROOT       } ,
               { 0, 0, 0, 0 },
       };
       while((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
               switch(c) {
                       case FLAG_CONFIG: config_file = optarg; break;
                       case FLAG_SYSROOT: sysroot = optarg; break;
                       case '?': return 1; /* getopt_long already printed an error message */
               }
       }
       if((config = pu_ui_config_load_sysroot(NULL, config_file, sysroot)) == NULL)
               { return 1; } /* load_sysroot already printed an error message */

       if(!(handle = pu_initialize_handle_from_config(config))) {
               fprintf(stderr, "error: failed to initialize alpm.\n");
               return 1;
       }

       puts(alpm_option_get_root(handle));

       pu_config_free(config);
       alpm_release(handle);

       return 0;
}

ok that's the whole page bestie, go fix that guest system, you got this πŸ’–βœ¨

this was pacutils, dated 2025-12-04 β€” main character energy, no cap πŸ‘‘πŸŒΈ

πŸ“¦ where this page comes from