diff options
Diffstat (limited to 'src/chroot-tools/librechroot')
-rwxr-xr-x | src/chroot-tools/librechroot | 128 |
1 files changed, 86 insertions, 42 deletions
diff --git a/src/chroot-tools/librechroot b/src/chroot-tools/librechroot index e82b18c..e5ca1f7 100755 --- a/src/chroot-tools/librechroot +++ b/src/chroot-tools/librechroot @@ -25,18 +25,26 @@ # - the commands=() array # - the case statement in main() -. $(librelib conf.sh) +. $(librelib conf) load_files chroot . libremessages -. $(librelib makechrootpkg) + +shopt -s nullglob +umask 0022 + +readonly _arch_nspawn=$(librelib chroot/arch-nspawn) +readonly _mkarchroot=$(librelib chroot/mkarchroot) +readonly _makechrootpkg=$(librelib chroot/makechrootpkg.sh) # Because the makechrootpkg.sh library functions don't work with -euE -normshell() ( +_makechrootpkg() ( set +euE + . "$_makechrootpkg" "$@" ) +# Usage: make_empty_repo $copydir make_empty_repo() { local copydir=$1 mkdir -p "${copydir}/repo" @@ -44,8 +52,21 @@ make_empty_repo() { ln -s "repo.db.tar.gz" "${copydir}/repo/repo.db" } +# Usage: chroot_add_to_local_repo $copydir $pkgfiles... +chroot_add_to_local_repo() { + local copydir=$1; shift + mkdir -p "$copydir/repo" + local pkgfile + for pkgfile in "$@"; do + cp "$pkgfile" "$copydir/repo" + pushd "$copydir/repo" >/dev/null + repo-add repo.db.tar.gz "${pkgfile##*/}" + popd >/dev/null + done +} + usage() { - calculate_directories + eval "$(calculate_directories)" print "Usage: %s [OPTIONS] COMMAND [ARGS...]" "${0##*/}" print 'Interacts with an archroot (arch chroot).' echo @@ -99,6 +120,8 @@ usage() { flag '-N' 'Disable networking in the chroot' flag "-C <$(_ FILE)>" 'Copy this file to `$copydir/etc/pacman.conf`' flag "-M <$(_ FILE)>" 'Copy this file to `$copydir/etc/makepkg.conf`' + flag "-w <$(_ 'PATH[:PATH]')>" 'Bind mount a file or directory, read/write' + flag "-r <$(_ 'PATH[:PATH]')>" 'Bind mount a file or directory, read-only' echo print 'Commands:' print ' Create/copy/delete:' @@ -120,7 +143,7 @@ usage() { flag 'clean-repo' 'Clean /repo in the chroot copy' flag 'help' 'Show this message' } -commands=( +readonly commands=( noop make sync delete install-file install-name update clean-pkgs run enter clean-repo help @@ -130,6 +153,7 @@ commands=( calculate_directories() { # Don't assume that CHROOTDIR or CHROOT are set, # but assume that COPY is set. + local rootdir copydir if [[ -n ${CHROOTDIR:-} ]] && [[ -n ${CHROOT:-} ]]; then rootdir="${CHROOTDIR}/${CHROOT}/root" @@ -144,6 +168,18 @@ calculate_directories() { else copydir='' fi + + declare -p rootdir + declare -p copydir +} + +arch_nspawn_flags=() +sysd_nspawn_flags=() +arch-nspawn() { + local copydir=$1; shift + set +u # if an array is empty, it counts as unbound + "$_arch_nspawn" "${arch_nspawn_flags[@]}" "$copydir" "${sysd_nspawn_flags[@]}" -- "$@" + set -u } # Globals: $CHROOTDIR, $CHROOT, $COPY, $rootdir and $copydir @@ -152,19 +188,14 @@ main() { [[ $COPY != root ]] || COPY=copy local mode=enter - local archroot_args=() - while getopts 'n:l:NC:M:' arg; do - case $arg in + while getopts 'n:l:NC:M:w:r:' opt; do + case $opt in n) CHROOT=$OPTARG;; l) COPY=$OPTARG;; - N) - # We do this so that it carries through to - # chroot_* functions - archroot() { - $(which archroot) -N "$@" - } - ;; - C|M) archroot_args+=(-$arg "$OPTARG");; + N) sysd_nspawn_flags+=(--private-network);; + C|M) arch_nspawn_flags+=(-$opt "$OPTARG");; + w) sysd_nspawn_flags+=("--bind=$OPTARG");; + r) sysd_nspawn_flags+=("--bind-ro=$OPTARG");; *) usage >/dev/stderr; return 1;; esac done @@ -188,7 +219,12 @@ main() { fi check_vars chroot CHROOTDIR CHROOT - calculate_directories + eval "$(calculate_directories)" + + readonly LIBREUSER LIBREHOME + readonly CHROOTDIR CHROOT COPY + readonly rootdir copydir + readonly mode ######################################################################## @@ -200,29 +236,27 @@ main() { umask 0022 # Keep this lock as long as we are running - # Note that '9' is the same FD number as in (mk)archroot - lock_open_write 9 "$copydir" \ + # Note that '9' is the same FD number as in mkarchroot et al. + lock 9 "$copydir.lock" \ "Waiting for existing lock on chroot copy to be released: [%s]" "$COPY" if [[ ! -d $rootdir ]]; then msg "Creating 'root' copy for chroot [%s]" "$CHROOT" - set +u # if archroot_args is empty, it counts as unbound - archroot "${archroot_args[@]}" -m "$rootdir" base-devel + set +u # if an array is empty, it counts as unbound + "$_mkarchroot" "${arch_nspawn_flags[@]}" "$rootdir" base-devel set -u make_empty_repo "$rootdir" fi if [[ ! -d $copydir ]] || [[ $mode == sync ]]; then msg "Syncing copy [%s] with root copy" "$COPY" - normshell chroot_sync "$CHROOTDIR/$CHROOT" "$COPY" + _makechrootpkg sync_chroot "$CHROOTDIR/$CHROOT" "$COPY" fi mkdir -p "$copydir/etc/libretools.d" { - if [[ -n ${CHROOTEXTRAPKG[@]:-} ]]; then - printf 'CHROOTEXTRAPKG=(' - printf "'%s' " "${CHROOTEXTRAPKG[@]}" - printf ')\n' + if [[ -n ${CHROOTEXTRAPKG[*]:-} ]]; then + declare -p CHROOTEXTRAPKG | sed -r 's/declare( -.)* //' else printf 'CHROOTEXTRAPKG=()\n' fi @@ -234,9 +268,8 @@ main() { # - overwrite \`/etc/pacman.d/mirrorlist'" # - set \`CacheDir' in \`/etc/pacman.conf'" # - apply -C or -M flags - set +u # if archroot_args is empty, it counts as unbound - archroot "${archroot_args[@]}" -r "$copydir" true - set -u + arch-nspawn "$copydir" true + arch_nspawn_flags=() # XXX dirty hack, don't apply -C or -M again fi ######################################################################## @@ -246,30 +279,41 @@ main() { noop|make|sync) :;; delete) if [[ -d $copydir ]]; then - normshell chroot_delete "$copydir" + _makechrootpkg delete_chroot "$copydir" "$COPY" fi ;; # Dealing with packages install-file) - normshell chroot_install_pkgs "$copydir" "$@" - normshell chroot_add_to_local_repo "$copydir" "$@" + _makechrootpkg install_packages "$copydir" "$@" + chroot_add_to_local_repo "$copydir" "$@" + ;; + install-name) + arch-nspawn "$copydir" pacman -Sy "$@" + ;; + update) + arch-nspawn "$copydir" pacman -Syu --noconfirm ;; - install-name) archroot -r "$copydir" pacman -Sy "$@";; - update) archroot -u "$copydir";; clean-pkgs) - trap "rm -f '$copydir'/clean '$copydir'/chrootexec" EXIT - cp -a "$(which chcleanup)" "$copydir/clean" - echo '#!/bin/bash' > "$copydir/chrootexec" - echo 'mkdir -p /build' >> "$copydir/chrootexec" - echo 'cd /build; /clean' >> "$copydir/chrootexec" + trap "rm -f '$copydir'/bin/chcleanup '$copydir'/chrootexec" EXIT + install -m755 "$(librelib chroot/chcleanup)" "$copydir/bin/chcleanup" + printf '%s\n' \ + '#!/bin/bash' \ + 'mkdir -p /build' \ + 'cd /build' \ + '/bin/chcleanup' \ + > "$copydir/chrootexec" chmod 755 "$copydir/chrootexec" - archroot -r "$copydir" /chrootexec + arch-nspawn "$copydir" /chrootexec ;; # Other - run) archroot -r "$copydir" "$@";; - enter) archroot -r "$copydir" bash;; + run) + arch-nspawn "$copydir" "$@" + ;; + enter) + arch-nspawn "$copydir" bash + ;; clean-repo) rm -rf "${copydir}"/repo/* make_empty_repo "$copydir" |