summaryrefslogtreecommitdiff
path: root/src/chroot-tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/chroot-tools')
-rw-r--r--src/chroot-tools/Makefile21
-rwxr-xr-xsrc/chroot-tools/chcleanup13
-rwxr-xr-xsrc/chroot-tools/distcc-tool16
-rw-r--r--src/chroot-tools/hooks-chcleanup.sh7
-rw-r--r--src/chroot-tools/hooks-check.sh25
-rw-r--r--src/chroot-tools/hooks-distcc.sh2
-rwxr-xr-xsrc/chroot-tools/indent35
-rwxr-xr-xsrc/chroot-tools/librechroot132
-rwxr-xr-xsrc/chroot-tools/libremakepkg146
-rw-r--r--src/chroot-tools/makechrootpkg.sh.patch120
10 files changed, 366 insertions, 151 deletions
diff --git a/src/chroot-tools/Makefile b/src/chroot-tools/Makefile
index 0540636..97ca688 100644
--- a/src/chroot-tools/Makefile
+++ b/src/chroot-tools/Makefile
@@ -1,11 +1,13 @@
# These files are coming from devtools
copy_files = makechrootpkg.sh.in mkarchroot.in arch-nspawn.in
# These are programs that we will use internally, but shouldn't be in PATH
-libexecs = mkarchroot arch-nspawn distcc-tool chcleanup
+libexecs = mkarchroot arch-nspawn distcc-tool chcleanup indent
no-progs = $(libexecs)
# These are the shell libraries we will use
libs = makechrootpkg.sh $(wildcard hooks-*.sh)
+pots = $(libexecs) $(libs)
+
pkglibexecdir = $(libexecdir)/libretools/chroot
clean_files = makechrootpkg.sh.ugly* *~
include ../../common.mk
@@ -25,20 +27,19 @@ makechrootpkg.sh.in: %.sh.in: $(devtoolsdir)/%.in
cp $< $@
makechrootpkg.sh.ugly: %.ugly: %.in %.patch Makefile
cp $*.in $@
- @echo 'PATCH $@ $*.patch'; patch $@ $*.patch || { rm -f -- '$@'; false; }
+ @echo 'PATCH $@ $*.patch'; patch $@ $*.patch
makechrootpkg.sh: %: %.ugly Makefile
- @echo 'EDIT < $< > $@'; $(edit) <'$<' >'$@' || { rm -f -- '$@'; false; }
- @echo 'INDENT $@'; $(call indent,$@) || { rm -f -- '$@'; false; }
+ @echo 'EDIT < $< > $@'; $(edit) <'$<' >'$@'
+ @echo 'INDENT $@'; $(call indent,$@)
mkarchroot: mkarchroot.in Makefile
@echo '< $< M4_EDIT | SED > $@'
- @<'$<' $(edit) | sed 's|arch-nspawn|$$(librelib chroot/&)|' >'$@' || { rm -f -- '$@'; false; }
- @echo 'CHMOD $<'; chmod 755 "$@" || { rm -f -- '$@'; false; }
+ @<'$<' $(edit) | sed -e 's|arch-nspawn|$$(librelib chroot/&)|' -e 's/pacstrap/env -i &/' >'$@'
+ @echo 'CHMOD $<'; chmod 755 "$@"
archroot: %: %.in Makefile
@echo "GEN $@"
- @$(edit) <"$<" >"$@" || { rm -f -- '$@'; false; }
- @chmod 755 "$@" || { rm -f -- '$@'; false; }
+ @$(edit) <"$<" >"$@"
+ @chmod 755 "$@"
-distcc-tool.pot: distcc-tool
- xgettext --omit-header -i --from-code=UTF-8 -L shell --keyword={error,errusage} -o $@ $<
+distcc-tool.pot: xgettext-keywords-sh+=--keyword=errusage
diff --git a/src/chroot-tools/chcleanup b/src/chroot-tools/chcleanup
index a43065b..9ad121e 100755
--- a/src/chroot-tools/chcleanup
+++ b/src/chroot-tools/chcleanup
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
set -eE
-# (c) Nicolás Reynolds <fauno@parabola.nu>
+# Copyright (C) Nicolás Reynolds <fauno@parabola.nu>
# Released under GPLv3
#
# Performs chroot cleanup smartly, it only removes the unneeded packages or
@@ -53,19 +53,18 @@ fi
source /etc/libretools.d/chroot.conf
# If we're running makepkg
-if [ -f PKGBUILD ]; then
+if [[ -f PKGBUILD ]]; then
export CARCH="$(. /etc/makepkg.conf; printf '%s' "$CARCH")"
- source PKGBUILD
+ source ./PKGBUILD
CHROOTEXTRAPKG+=("${depends[@]}"
"${makedepends[@]}"
"${checkdepends[@]}")
fi
msg "Cleaning chroot..."
-msg2 "Fetching updated package lists..."
-pacman -Sy || {
- warning "There was an error updating package lists, ignoring."
-}
+
+# Sync the local repo with pacman
+cp /repo/repo.db /var/lib/pacman/sync/repo.db
# Setup the temporary directory
TEMPDIR="$(mktemp --tmpdir -d $(basename $0).XXXXX)"
diff --git a/src/chroot-tools/distcc-tool b/src/chroot-tools/distcc-tool
index 7633029..9f78ead 100755
--- a/src/chroot-tools/distcc-tool
+++ b/src/chroot-tools/distcc-tool
@@ -2,7 +2,7 @@
# -*- tab-width: 4; sh-basic-offset: 4 -*-
# distcc-tool
-# Copyright 2013 Luke Shumaker
+# Copyright (C) 2013-2014 Luke Shumaker
#
# This file is part of Parabola.
#
@@ -32,6 +32,8 @@ if ! type gettext &>/dev/null; then
gettext() { echo "$@"; }
fi
+q0="$(printf '%q' "$0")" # quoted $0
+
panic() {
echo "$(gettext 'panic: malformed call to internal function')" >&2
exit 1
@@ -50,7 +52,7 @@ print() {
}
usage() {
- print "Usage: $0 COMMAND [COMMAND-ARGS]"
+ print "Usage: %s COMMAND [COMMAND-ARGS]" "$q0"
print "Tool for using distcc within a networkless chroot"
echo
print "Commands:"
@@ -125,7 +127,7 @@ parse_DISTCC_HOSTS() {
*@*)
# SSH_HOST doesn't allow custom port numbers, and even if it
# did, ssh would complain about MITM. Instead, we'll count on
- # ssh ProxyCommand being configured to used `client`.
+ # ssh ProxyCommand being configured to use `client`.
newhosts+=("$HOSTSPEC")
;;
# GLOBAL_OPTION
@@ -135,7 +137,7 @@ parse_DISTCC_HOSTS() {
;;
# ZEROCONF
+zeroconf)
- error "%s does not support the +zeroconf option" "$0"
+ error "%s does not support the +zeroconf option" "$q0"
exit 1
;;
# TCP_HOST or OLDSTYLE_TCP_HOST
@@ -159,7 +161,7 @@ parse_DISTCC_HOSTS() {
# set up port forwaring
if $forward_ports; then
- socat TCP-LISTEN:${newport},fork SYSTEM:"$0 client $HOSTID ${PORT:-3632}" &
+ socat TCP-LISTEN:${newport},fork SYSTEM:"$q0 client $HOSTID ${PORT:-3632}" &
pids+=($!)
fi
@@ -222,8 +224,8 @@ odaemon() {
local chrootpath=$1
umask 111
- socat UNIX-LISTEN:"$chrootpath/socket",fork SYSTEM:"$0 server" &
- trap "kill -- $!; rm -f '$chrootpath/socket'" EXIT
+ socat UNIX-LISTEN:"$chrootpath/socket",fork SYSTEM:"$q0 server" &
+ trap "kill -- $!; rm -f -- $(printf '%q' "$chrootpath/socket")" EXIT
wait
}
diff --git a/src/chroot-tools/hooks-chcleanup.sh b/src/chroot-tools/hooks-chcleanup.sh
index 09e6dd9..86c872c 100644
--- a/src/chroot-tools/hooks-chcleanup.sh
+++ b/src/chroot-tools/hooks-chcleanup.sh
@@ -1,16 +1,15 @@
#!/usr/bin/env bash
set -euE
-hooks_pre_build+=("clean_chroot")
+hook_pre_build+=("clean_chroot")
clean_chroot() (
set +x
local copydir=$1
if $INCHROOT; then
- cd /build
+ cd /startdir
sudo -u nobody "$(librelib chroot/chcleanup)"
else
- librechroot -l "$copydir" clean-pkgs
+ librechroot "${librechroot_flags[@]}" clean-pkgs
fi
- r=$?; echo clean_chroot returning $r; return $r
)
diff --git a/src/chroot-tools/hooks-check.sh b/src/chroot-tools/hooks-check.sh
index e8120b8..2702f95 100644
--- a/src/chroot-tools/hooks-check.sh
+++ b/src/chroot-tools/hooks-check.sh
@@ -1,30 +1,11 @@
#!/usr/bin/env bash
set -euE
-hook_check_pkgbuild+=("check_pkgbuild_dependencies")
-check_pkgbuild_dependencies() {
+hook_check_pkgbuild+=("check_pkgbuild_nonfree")
+check_pkgbuild_nonfree() {
local s=0
sudo -EH -u "$LIBREUSER" pkgbuild-check-nonfree -f || s=$?
- case $s in
- 0) :;;
- 15) error "This PKGBUILD links to known unfree packages"; return 1;;
- *) warning "pkgbuild-check-nonfree failed to run";;
- esac
-}
-
-hook_check_pkgbuild+=("check_pkgbuild_license")
-check_pkgbuild_license() {
- local s=0
- sudo -EH -u "$LIBREUSER" pkgbuild-check-licenses -f || s=$?
- for i in 1 2 4; do
- if [[ $i -eq $(($s & $i)) ]]; then
- case $i in
- 1) warning "pkgbuild-check-licenses encountered an error";;
- 2) warning "This PKGBUILD has an uncommon license";;
- 4) error "This PKGBUILD has a known nonfree license"; ret=1;;
- esac
- fi
- done
+ pkgbuild-summarize-nonfree $s
}
#hook_check_pkgbuild+=("check_pkgbuild_namcap")
diff --git a/src/chroot-tools/hooks-distcc.sh b/src/chroot-tools/hooks-distcc.sh
index 9e42242..d8d708a 100644
--- a/src/chroot-tools/hooks-distcc.sh
+++ b/src/chroot-tools/hooks-distcc.sh
@@ -75,7 +75,7 @@ distcc_stop() {
if [[ -f "$copydir/run/distcc-tool.pid" ]]; then
- odaemon=$(cat "$copydir/distcc-tool.pid")
+ odaemon=$(< "$copydir/distcc-tool.pid")
kill -- "$odaemon"
rm -f -- \
diff --git a/src/chroot-tools/indent b/src/chroot-tools/indent
new file mode 100755
index 0000000..0e2d0e0
--- /dev/null
+++ b/src/chroot-tools/indent
@@ -0,0 +1,35 @@
+#!/usr/bin/env perl
+use warnings;
+use strict;
+use constant BUFFER_SIZE => 40;
+binmode(STDIN);
+binmode(STDOUT);
+
+exit(1) if ($#ARGV != 0);
+my $indent = $ARGV[0];
+
+my $print_indent = 1;
+my $buffer;
+my $size;
+my $c;
+while (1) {
+ $size = sysread(STDIN, $buffer, BUFFER_SIZE);
+ last if ($size < 1);
+ for (0..$size-1) {
+ $c = substr($buffer, $_, 1);
+ if ($c eq "\n") {
+ syswrite(STDOUT, $indent) if ($print_indent);
+ # XXX: SYSTEMD-STDOUT HACK
+ #syswrite(STDOUT, $c, 1);
+ syswrite(STDOUT, "\r\n", 2);
+ $print_indent = 1;
+ } elsif ($c eq "\r") {
+ syswrite(STDOUT, $c, 1);
+ $print_indent = 1;
+ } else {
+ syswrite(STDOUT, $indent) if ($print_indent);
+ syswrite(STDOUT, $c, 1);
+ $print_indent = 0;
+ }
+ }
+}
diff --git a/src/chroot-tools/librechroot b/src/chroot-tools/librechroot
index 0b3ad43..051148d 100755
--- a/src/chroot-tools/librechroot
+++ b/src/chroot-tools/librechroot
@@ -2,9 +2,9 @@
set -euE
# librechroot
-# Copyright 2010 Nicolás Reynolds
-# Copyright 2011 Joshua Haase
-# Copyright 2012-2013 Luke Shumaker
+# Copyright (C) 2010 Nicolás Reynolds
+# Copyright (C) 2011 Joshua Haase
+# Copyright (C) 2012-2014 Luke Shumaker
#
# This file is part of Parabola.
#
@@ -21,10 +21,11 @@ set -euE
# You should have received a copy of the GNU General Public License
# along with Parabola. If not, see <http://www.gnu.org/licenses/>.
-# HACKING: if a command is added or removed, it must be changed in 3 places:
+# HACKING: if a command is added or removed, it must be changed in 4 places:
# - the usage() text
# - the commands=() array
-# - the case statement in main()
+# - the case statement in main() that checks the number of arguments
+# - the case statement in main() that runs them
. $(librelib conf)
load_files chroot
@@ -88,16 +89,16 @@ usage() {
unless the copy name is manually specified as an absolute path,
in which case, that path is used.'
echo
- prose 'The current settings for the above varibles are:'
+ prose 'The current settings for the above variables are:'
printf ' CHROOTDIR : %s\n' "${CHROOTDIR:-$(_ 'ERROR: NO SETTING')}"
printf ' CHROOT : %s\n' "${CHROOT:-$(_ 'ERROR: NO SETTING')}"
printf ' COPY : %s\n' "$COPY"
printf ' rootdir : %s\n' "${rootdir:-$(_ 'ERROR')}"
printf ' copydir : %s\n' "${copydir:-$(_ 'ERROR')}"
echo
- prose 'If the chroot, or copy does not exist, it will be created
+ prose 'If the chroot or copy does not exist, it will be created
automatically. A chroot by default contains the packages in the
- group "base-devel", and any packages named in $CHROOTEXTRAPKG.
+ group "base-devel" and any packages named in $CHROOTEXTRAPKG.
Unless the `-C` or `-M` flags are used, the configuration files
that this program installs are the stock versions supplied in the
packages, not the versions from your host system. Other tools
@@ -136,8 +137,8 @@ usage() {
flag 'update' 'Like `pacman -Syu`'
flag 'clean-pkgs' 'Remove all packages from the chroot copy that
are not in base-devel, $CHROOTEXTRAPKG, or named
- as a dependency in the file `/build/PKGBUILD` in
- the chroot copy'
+ as a dependency in the file `/startdir/PKGBUILD`
+ in the chroot copy'
print ' Other:'
flag "run $(_ CMD...)" 'Run CMD in the chroot copy'
flag 'enter' 'Enter an interactive shell in the chroot copy'
@@ -150,7 +151,7 @@ readonly commands=(
run enter clean-repo help
)
-# set $rootdir and $copydir; blank them on error
+# Print code to set $rootdir and $copydir; blank them on error
calculate_directories() {
# Don't assume that CHROOTDIR or CHROOT are set,
# but assume that COPY is set.
@@ -174,12 +175,37 @@ calculate_directories() {
declare -p copydir
}
+check_mountpoint() {
+ local file=$1
+ local mountpoint="$(df -P "$file"|sed '1d;s/.*\s//')"
+ local mountopts=($(LC_ALL=C mount|awk "{ if (\$3==\"$mountpoint\") { gsub(/[(,)]/, \" \", \$6); print \$6 } }"))
+ ! in_array nosuid "${mountopts[@]}" && ! in_array noexec "${mountopts[@]}"
+}
+
arch_nspawn_flags=()
sysd_nspawn_flags=()
arch-nspawn() {
local copydir=$1; shift
+ # XXX: SYSTEMD-STDOUT HACK
+ if [[ -t 1 ]]; then
+ cmd=("$@")
+ else
+ # This perl script is similar to `sed 's|\n|\r\n|g'`, (or, more
+ # correctly, `sed 's|$|\r|'`) but it does't line-buffer.
+ local perlcmd='
+my $size;
+my $buffer;
+while(1) {
+ $size=sysread(STDIN, $buffer, 40);
+ last if ($size < 1);
+ $buffer =~ s/\n/\r\n/g;
+ syswrite(STDOUT, $buffer);
+}'
+ cmd=(bash --noprofile --norc -c "set -o pipefail; $(printf '%q ' "$@") |& perl -e $(printf '%q' "$perlcmd")")
+ fi
+
set +u # if an array is empty, it counts as unbound
- "$_arch_nspawn" "${arch_nspawn_flags[@]}" "$copydir" "${sysd_nspawn_flags[@]}" -- "$@"
+ "$_arch_nspawn" "${arch_nspawn_flags[@]}" "$copydir" "${sysd_nspawn_flags[@]}" -- "${cmd[@]}"
set -u
}
@@ -197,22 +223,65 @@ main() {
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;;
+ *) usage >&2; return 1;;
esac
done
shift $(($OPTIND - 1))
if [[ $# -lt 1 ]]; then
error "Must specify a command"
- usage >/dev/stderr
+ usage >&2
return 1
fi
mode=$1
if ! in_array "$mode" "${commands[@]}"; then
error "Unrecognized command: %s" "$mode"
- usage >/dev/stderr
+ usage >&2
return 1
fi
shift
+ case "$mode" in
+ noop|make|sync|delete|update|enter|clean-pkgs|clean-repo)
+ if [[ $# -gt 0 ]]; then
+ error 'Command `%s` does not take any arguments: %s' "$mode" "$*"
+ usage >&2
+ return 1
+ fi
+ :;;
+ install-file)
+ if [[ $# -lt 1 ]]; then
+ error 'Command `%s` requires at least one file' "$mode"
+ usage >&2
+ return 1
+ else
+ local missing=()
+ local file
+ for file in "$@"; do
+ if ! [[ -f $file ]]; then
+ missing+=("$file")
+ fi
+ done
+ if [[ ${#missing[@]} -gt 0 ]]; then
+ error "%s: file(s) not found: %s" "$mode" "${missing[*]}"
+ return 1
+ fi
+ fi
+ :;;
+ install-name)
+ if [[ $# -lt 1 ]]; then
+ error 'Command `%s` requires at least one package name' "$mode"
+ usage >&2
+ return 1
+ fi
+ :;;
+ run)
+ if [[ $# -lt 1 ]]; then
+ error 'Command `%s` requires at least one argument' "$mode"
+ usage >&2
+ return 1
+ fi
+ :;;
+ esac
+
if [[ $mode == help ]]; then
usage
@@ -236,11 +305,28 @@ main() {
umask 0022
+ # XXX: SYSTEMD-STDIN HACK
+ if ! [[ -t 0 ]]; then
+ error "Input is not a TTY"
+ plain "https://labs.parabola.nu/issues/420"
+ plain "https://bugs.freedesktop.org/show_bug.cgi?id=70290"
+ prose "Due to a bug in systemd-nspawn, redirecting stdin is not
+ supported. We have been able to mitigate the problems
+ with redirecting stdout, but until the bug is fixed,
+ redirecting stdin will only end in pain." >&2
+ return 1
+ fi
+
# Keep this lock as long as we are running
# 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 ! check_mountpoint "$copydir.lock"; then
+ error "Chroot copy is mounted with nosuid or noexec options: [%s]" "$COPY"
+ return 1
+ fi
+
if [[ ! -d $rootdir ]]; then
msg "Creating 'root' copy for chroot [%s]" "$CHROOT"
set +u # if an array is empty, it counts as unbound
@@ -256,10 +342,12 @@ main() {
mkdir -p "$copydir/etc/libretools.d"
{
- if [[ -n ${CHROOTEXTRAPKG[*]:-} ]]; then
- declare -p CHROOTEXTRAPKG | sed -r 's/declare( -.)* //'
+ if [[ ${#CHROOTEXTRAPKG[*]} -eq 0 ]]; then
+ echo 'CHROOTEXTRAPKG=()'
else
- printf 'CHROOTEXTRAPKG=()\n'
+ printf 'CHROOTEXTRAPKG=('
+ printf '%q ' "${CHROOTEXTRAPKG[@]}"
+ printf ')\n'
fi
} > "$copydir"/etc/libretools.d/chroot.conf
@@ -293,15 +381,17 @@ main() {
arch-nspawn "$copydir" pacman -Sy "$@"
;;
update)
- arch-nspawn "$copydir" pacman -Syu --noconfirm
+ # umount resolv.conf so that it can be upgraded, if nescessary
+ # this disables DNS, so fetch everything first
+ arch-nspawn "$copydir" bash -c 'pacman -Syuw --noconfirm && umount /etc/resolv.conf && pacman -Su --noconfirm'
;;
clean-pkgs)
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' \
+ 'mkdir -p /startdir' \
+ 'cd /startdir' \
'/bin/chcleanup' \
> "$copydir/chrootexec"
chmod 755 "$copydir/chrootexec"
diff --git a/src/chroot-tools/libremakepkg b/src/chroot-tools/libremakepkg
index a59315b..26080bc 100755
--- a/src/chroot-tools/libremakepkg
+++ b/src/chroot-tools/libremakepkg
@@ -2,9 +2,9 @@
set -euE
# libremakepkg
-# Copyright 2010-2011 Nicolás Reynolds
-# Copyright 2011 Joshua Ismael Haase Hernández
-# Copyright 2012-2013 Luke Shumaker
+# Copyright (C) 2010-2011 Nicolás Reynolds
+# Copyright (C) 2011 Joshua Ismael Haase Hernández
+# Copyright (C) 2012-2014 Luke Shumaker
#
# This file is part of Parabola.
#
@@ -25,15 +25,18 @@ set -euE
. $(librelib messages)
. $(librelib chroot/makechrootpkg.sh)
+set -o pipefail
shopt -s nullglob
umask 0022
# Global variables:
+readonly _indent="$(librelib chroot/indent)"
readonly INCHROOT=$([[ -f /.arch-chroot ]] && echo true || echo false)
NONET=true # can be changed with the -N flag
-# {SRC,LOG,PKG}DEST set at runtime by makepkg.conf
+# {PKG,SRC,SRCPKG,LOG}DEST set at runtime by makepkg.conf
# MAKEFLAGS, PACKAGER set at runtime by makepkg.conf
# LIBREUSER, LIBREHOME are set by conf.sh
+librechroot_flags=()
# Hooks ########################################################################
@@ -47,6 +50,25 @@ hook_check_pkg=(:)
# Boring/mundane functions #####################################################
+indent() {
+ "$_indent" ' | '
+}
+
+# Usage: _check_perms_dir $directory
+# Make sure that $directory is readable and executable (searchable) by 'nobody'
+check_directory_permissions() (
+ local dir=$1
+ # `cd` to the directory, then test `.`; that way if parent
+ # directories aren't readable, we aren't testing for that. We
+ # only need the last element in `$dir`.
+ cd "$dir"
+ if ! sudo -u nobody test -r . -a -x .; then
+ error "Directory '%s' must be readable by user 'nobody'" "$dir"
+ return 1
+ fi
+ return 0
+)
+
# Usage: exit_copy $copydir $src_owner
# End immediately, but copy log files out
exit_copy() {
@@ -62,17 +84,18 @@ exit_copy() {
run_hook() {
local hookname=$1; shift
local hookvar="hook_${hookname}[@]"
+
local fails=()
- msg "Running hook: %s" "$hookname"
for hook in "${!hookvar}"; do
- msg2 'hook: %s' "$hook"
- "$hook" "$@" || { error "result: %s" $?; fails+=("$hook"); }
- done
+ "$hook" "$@" || fails+=("$hook")
+ done |& indent
+
if [[ ${#fails[@]} -gt 0 ]]; then
error "Failure(s) in %s: %s" "$hookname" "${fails[*]}"
return 1
+ else
+ return 0
fi
- return 0
}
# Usage: add_to_local_repo $copydir $pkgfiles...
@@ -88,25 +111,32 @@ add_to_local_repo() {
done
}
+hook_post_build+=('cleanup')
+cleanup() {
+ local copydir=$1
+ rm -f -- "$copydir"/chroot{prepare,build}
+}
+
build() (
local copydir=$1; shift
- local cmd=(/chrootbuild "$@")
+ local repack=$1; shift
- run_hook pre_build "$copydir"
- trap "run_hook post_build '$copydir'" EXIT
-
- local netflag=''
+ local run_ynet=()
+ local run_nnet=()
if $INCHROOT; then
- ! $NONET || netflag='-n'
- unshare $netflag -- "${cmd[@]}"
+ run_ynet=(unshare)
+ run_nnet=(unshare -n)
else
- ! $NONET || netflag='-N'
- librechroot $netflag \
- -r "$PWD:/startdir_host" \
- -r "$SRCDEST:/srcdest_host" \
- -l "$copydir" \
- run "${cmd[@]}"
+ run_ynet=(librechroot "${librechroot_flags[@]}" run)
+ run_nnet=(librechroot "${librechroot_flags[@]}" -N run)
fi
+ $NONET || run_nnet=("${run_ynet[@]}")
+
+ prepare_chroot "$copydir" "$LIBREHOME" "$repack" false
+ "${run_ynet[@]}" /chrootprepare false "$@" |& indent
+ run_hook pre_build "$copydir"
+ trap "run_hook post_build '$copydir'" EXIT
+ "${run_nnet[@]}" /chrootbuild false "$@" |& indent
)
# The main program #############################################################
@@ -118,7 +148,7 @@ usage() {
prose 'If run from outside of a chroot, command will make the following
configuration changes in the chroot:'
bullet 'whatever changes `librechroot` makes.'
- bullet 'set `PKGDEST` and `SRCDEST` in `/etc/makepkg.conf`'
+ bullet 'set `{PKG,SRC,SRCPKG,LOG}DEST` in `/etc/makepkg.conf`'
bullet 'set `PACKAGER` in `/etc/makepkg.conf` to reflect the value
outside of the chroot.'
bullet '(maybe) delete `/build/.makepkg.conf`'
@@ -134,8 +164,12 @@ usage() {
the documentation there.'
echo
print 'Options:'
+ print ' %s options:' librechroot
flag "-n <$(_ CHROOT)>" 'Name of the chroot to use'
flag "-l <$(_ COPY)>" 'Name of, or absolute path to, the chroot copy to use'
+ flag "-w <$(_ 'PATH[:PATH]')>" 'Bind mount a file or directory, read/write'
+ flag "-r <$(_ 'PATH[:PATH]')>" 'Bind mount a file or directory, read-only'
+ print ' %s options:' libremakepkg
flag '-N' "Don't disable networking during build() and
package(). PLEASE don't use this unless you
have a special reason, its use is a violation
@@ -159,10 +193,14 @@ main() {
local chroot=''
# Parse command line options ###########################################
- while getopts 'n:l:NRh' flag ; do
+ while getopts 'n:l:w:r:NRh' flag ; do
case "${flag}" in
- n) if $INCHROOT; then err_chflag "$flag"; else chroot=$OPTARG; fi;;
- l) if $INCHROOT; then err_chflag "$flag"; else copy=$OPTARG; fi;;
+ n) if $INCHROOT; then err_chflag "$flag"; else
+ chroot=$OPTARG; fi;;
+ l) if $INCHROOT; then err_chflag "$flag"; else
+ copy=$OPTARG; fi;;
+ w|r) if $INCHROOT; then err_chflag "$flag"; else
+ librechroot_flags+=(-$flag "$OPTARG"); fi;;
N) NONET=false;;
R) repack=true; makepkg_args+=(-R);;
h) usage; return 0;;
@@ -190,6 +228,15 @@ main() {
fi
unset chroot
+ # Load makepkg configuration ###########################################
+ # Note that all of these are globals
+ PKGDEST="$(get_var makepkg PKGDEST "$PWD")"
+ SRCDEST="$(get_var makepkg SRCDEST "$PWD")"
+ SRCPKGDEST="$(get_var makepkg SRCPKGDEST "$PWD")"
+ LOGDEST="$(get_var makepkg LOGDEST "$PWD")"
+ MAKEFLAGS="$(get_var makepkg MAKEFLAGS '')"
+ PACKAGER="$(get_var makepkg PACKAGER '')"
+
# Quick sanity check ###################################################
if (( EUID )); then
@@ -203,14 +250,17 @@ main() {
exit 1
fi
- # Load makepkg configuration ###########################################
- # Note that all of these are globals
- SRCDEST="$(get_conf_makepkg SRCDEST "$PWD")"
- PKGDEST="$(get_conf_makepkg PKGDEST "$PWD")"
- LOGDEST="$(get_conf_makepkg LOGDEST "$PWD")"
- mkdir -p "$SRCDEST" "$PKGDEST" "$LOGDEST"
- MAKEFLAGS="$(get_conf_makepkg MAKEFLAGS '')"
- PACKAGER="$(get_conf_makepkg PACKAGER '')"
+ # Make sure that the various *DEST directories exist
+ mkdir -p -- "$PKGDEST" "$SRCDEST" "$SRCPKGDEST" "$LOGDEST"
+ # Check the permissions for $startdir and $SRCDEST
+ (
+ declare -i ret=0
+ check_directory_permissions "$PWD" || ret=1
+ if ! [[ "$PWD" -ef "$SRCDEST" ]]; then
+ check_directory_permissions "$SRCDEST" || ret=1
+ fi
+ exit $ret
+ )
# OK, we are starting now ##############################################
@@ -218,32 +268,40 @@ main() {
lock 9 "/build/.lock" \
"Waiting for existing lock on build directory to be released"
else
+ librechroot_flags+=(
+ -r "$PWD:/startdir_host"
+ -r "$SRCDEST:/srcdest_host"
+ -n "$CHROOT"
+ -l "$copy"
+ )
+
# Obtain a lock on the chroot
lock 9 "$copydir.lock" \
"Waiting for existing lock on chroot copy to be released: [%s]" "$copy"
# Create the chroot if it does not exist
- librechroot -n "$CHROOT" -l "$copy" make
+ msg 'Initializing the chroot...'
+ librechroot "${librechroot_flags[@]}" make |& indent
fi
# Set target CARCH
# note that we waited until after locking/creating the chroot to do this
- export CARCH="$(MAKEPKG_CONF=$copydir/etc/makepkg.conf get_conf_makepkg CARCH)"
+ export CARCH="$(MAKEPKG_CONF=$copydir/etc/makepkg.conf get_var makepkg CARCH)"
# Pre-build
+ msg 'Starting pre-build activities...'
run_hook check_pkgbuild
- download_sources "$copydir" "$LIBREUSER"
- prepare_chroot "$copydir" "$LIBREHOME" "$repack" false
- clean_chroot "$copydir"
+ msg 'Downloading sources...'
+ download_sources "$copydir" "$LIBREUSER" |& indent
# Build
+ msg 'Starting to build the package...'
trap "exit_copy '$copydir' '$LIBREUSER'" EXIT
- warning 'Entering build...'
- build "$copydir" "${makepkg_args[@]}"
+ build "$copydir" "$repack" "${makepkg_args[@]}"
+
# Post-build
- warning 'Entering hook check_pkg...'
+ msg 'Starting post-build activities...'
run_hook check_pkg
- warning 'Entering add_to_local_repo ...'
- add_to_local_repo "$copydir" "$copydir"/pkgdest/*.pkg.tar*
+ add_to_local_repo "$copydir" "$copydir"/pkgdest/*.pkg.tar* |& indent
}
main "$@"
diff --git a/src/chroot-tools/makechrootpkg.sh.patch b/src/chroot-tools/makechrootpkg.sh.patch
index f5b8ed7..540e6ba 100644
--- a/src/chroot-tools/makechrootpkg.sh.patch
+++ b/src/chroot-tools/makechrootpkg.sh.patch
@@ -1,5 +1,5 @@
---- makechrootpkg.sh.in 2013-09-08 23:01:20.000000000 -0400
-+++ makechrootpkg.sh.ugly 2013-09-09 15:43:06.000000000 -0400
+--- makechrootpkg.sh.in 2014-01-05 18:51:41.463720929 -0500
++++ makechrootpkg.sh.ugly 2014-02-09 20:20:25.021630727 -0500
@@ -12,6 +12,7 @@
shopt -s nullglob
@@ -8,8 +8,8 @@
_makepkg_args=(-s --noconfirm -L --holdver)
makepkg_args=("${_makepkg_args[@]}")
repack=false
-@@ -26,9 +27,10 @@
- declare -i ret=0
+@@ -29,9 +30,10 @@
+ bindmounts_rw=()
copy=$USER
-[[ -n $SUDO_USER ]] && copy=$SUDO_USER
@@ -20,15 +20,15 @@
usage() {
echo "Usage: ${0##*/} [options] -r <chrootdir> [--] [makepkg args]"
-@@ -62,6 +64,7 @@
+@@ -67,6 +69,7 @@
exit 1
}
+parse_options_init() {
- while getopts 'hcur:I:l:nT' arg; do
+ while getopts 'hcur:I:l:nTD:d:' arg; do
case "$arg" in
h) usage ;;
-@@ -86,9 +89,6 @@
+@@ -93,9 +96,6 @@
[[ ! -d $chrootdir ]] && die "No chroot dir defined, or invalid path '%s'" "$passeddir"
[[ ! -d $chrootdir/root ]] && die "Missing chroot dir root directory. Try using: mkarchroot %s/root base-devel" "$chrootdir"
@@ -38,9 +38,9 @@
if [[ ${copy:0:1} = / ]]; then
copydir=$copy
else
-@@ -103,30 +103,47 @@
- repack=true
- fi
+@@ -115,30 +115,48 @@
+ esac
+ done
-if [[ -n $SUDO_USER ]]; then
+if [[ -n ${SUDO_USER:-} ]]; then
@@ -54,8 +54,9 @@
+# Usage: load_vars $makepkg_conf
+# Globals:
+# - SRCDEST
-+# - LOGDEST
++# - SRCPKGDEST
+# - PKGDEST
++# - LOGDEST
+# - MAKEFLAGS
+# - PACKAGER
load_vars() {
@@ -63,7 +64,7 @@
[[ -f $makepkg_conf ]] || return 1
- for var in {SRC,PKG,LOG}DEST MAKEFLAGS PACKAGER; do
+ for var in {SRC,SRCPKG,PKG,LOG}DEST MAKEFLAGS PACKAGER; do
- [[ -z ${!var} ]] && eval $(grep "^${var}=" "$makepkg_conf")
+ [[ -z ${!var:-} ]] && eval $(grep "^${var}=" "$makepkg_conf")
done
@@ -92,7 +93,7 @@
# Get a read lock on the root chroot to make
# sure we don't clone a half-updated chroot
slock 8 "$chrootdir/root.lock" "Locking clean chroot"
-@@ -147,10 +164,15 @@
+@@ -159,11 +177,16 @@
# Drop the read lock again
lock_close 8
@@ -100,6 +101,7 @@
}
-clean_temporary() {
+- stat_busy "Removing temporary copy [%s]" "$copy"
+# Usage: delete_chroot $copydir [$copy]
+delete_chroot() {
+ local copydir=$1
@@ -107,10 +109,11 @@
+ # Detect chrootdir filesystem type
+ local chroottype=$(stat -f -c %T "$copydir")
+
- stat_busy "Removing temporary copy [%s]" "$copy"
- if [[ "$chroottype" == btrfs ]]; then
++ stat_busy "Removing chroot copy [%s]" "$copy"
+ if [[ "$chroottype" == btrfs ]] && ! mountpoint -q "$copydir"; then
btrfs subvolume delete "$copydir" >/dev/null ||
-@@ -166,9 +188,14 @@
+ die "Unable to delete subvolume %s" "$copydir"
+@@ -178,9 +201,14 @@
stat_done
}
@@ -125,7 +128,7 @@
for install_pkg in "${install_pkgs[@]}"; do
pkgname="${install_pkg##*/}"
cp "$install_pkg" "$copydir/$pkgname"
-@@ -179,11 +206,19 @@
+@@ -193,11 +221,19 @@
rm "$copydir/$pkgname"
done
@@ -147,9 +150,9 @@
$repack || rm -rf "$copydir/build"
mkdir -p "$copydir/build"
-@@ -217,12 +252,12 @@
+@@ -236,12 +272,12 @@
- chown -R nobody "$copydir"/{build,pkgdest,logdest,srcdest,startdir}
+ chown -R nobody "$copydir"/{build,pkgdest,srcpkgdest,logdest,srcdest,startdir}
- if [[ -n $MAKEFLAGS ]]; then
+ if [[ -n ${MAKEFLAGS:-} ]]; then
@@ -162,22 +165,26 @@
sed -i '/^PACKAGER=/d' "$copydir/etc/makepkg.conf"
echo "PACKAGER='${PACKAGER}'" >> "$copydir/etc/makepkg.conf"
fi
-@@ -235,6 +270,14 @@
+@@ -254,20 +290,38 @@
chmod 440 "$copydir/etc/sudoers.d/nobody-pacman"
fi
+ if ! grep -q '^\[repo\]' "$copydir/etc/pacman.conf"; then
-+ cat >> "$copydir/etc/pacman.conf" <<EOF
-+[repo]
++ local line=$(grep -n '^\[' "$copydir/etc/pacman.conf" |grep -Fv ':[options]'|sed 's/:.*//;1q')
++ local ins='[repo]
+SigLevel = Optional TrustAll
+Server = file:///repo
-+EOF
++'
++ sed -i "${line}i${ins//$'\n'/\n}" "$copydir/etc/pacman.conf"
+ fi
+
# This is a little gross, but this way the script is recreated every time in the
# working copy
++ printf $'#!/bin/bash\n%s\n_chrootprepare "$@"' "$(declare -f _chrootprepare)" \
++ > "$copydir/chrootprepare"
++ chmod +x "$copydir/chrootprepare"
printf $'#!/bin/bash\n%s\n_chrootbuild %q "$@"' "$(declare -f _chrootbuild)" \
-@@ -242,13 +285,19 @@
+ "$run_namcap" >"$copydir/chrootbuild"
chmod +x "$copydir/chrootbuild"
}
@@ -199,7 +206,7 @@
makepkg --config="$copydir/etc/makepkg.conf" --verifysource -o
else
( export SRCDEST BUILDDIR="$builddir"
-@@ -258,7 +307,7 @@
+@@ -277,10 +331,10 @@
(( $? != 0 )) && die "Could not download sources."
# Clean up garbage from verifysource
@@ -207,8 +214,20 @@
+ rm -rf "$builddir"
}
- _chrootbuild() {
-@@ -295,6 +344,7 @@
+-_chrootbuild() {
++_chrootprepare() {
+ # This function isn't run in makechrootpkg,
+ # so no global variables
+ local run_namcap="$1"; shift
+@@ -291,6 +345,7 @@
+ shopt -s nullglob
+
+ # XXX: Workaround makepkg disliking read-only dirs
++ rm -rf -- /srcdest/* /startdir/*
+ ln -sft /srcdest /srcdest_host/*
+ ln -sft /startdir /startdir_host/*
+
+@@ -316,11 +371,29 @@
# Safety check
if [[ ! -w PKGBUILD ]]; then
@@ -216,7 +235,30 @@
echo "Can't write to PKGBUILD!"
exit 1
fi
-@@ -312,12 +362,24 @@
+
+- sudo -u nobody makepkg "${makepkg_args[@]}" || exit 1
++ # Sync deps now, as networking may be disabled during _chrootbuild
++ cp /repo/repo.db /var/lib/pacman/sync/repo.db
++ sudo -u nobody makepkg "${makepkg_args[@]}" -o
++}
++
++_chrootbuild() {
++ # This function isn't run in makechrootpkg,
++ # so no global variables
++ local run_namcap="$1"; shift
++ local makepkg_args=("$@")
++
++ . /etc/profile
++ export HOME=/build
++ shopt -s nullglob
++
++ cd /startdir
++
++ sudo -u nobody makepkg "${makepkg_args[@]}" -e || exit 1
+
+ if $run_namcap; then
+ pacman -S --needed --noconfirm namcap
+@@ -333,12 +406,24 @@
exit 0
}
@@ -239,9 +281,9 @@
+ local l
for l in "$copydir"/logdest/*; do
+ [[ $l == */logpipe.* ]] && continue
chown "$src_owner" "$l"
- mv "$l" "$LOGDEST"
-@@ -325,6 +387,10 @@
+@@ -352,6 +437,10 @@
}
# }}}
@@ -252,9 +294,9 @@
umask 0022
load_vars /etc/makepkg.conf
-@@ -335,27 +401,37 @@
- [[ -d $SRCDEST ]] || SRCDEST=$PWD
- [[ -d $LOGDEST ]] || LOGDEST=$PWD
+@@ -363,30 +452,45 @@
+ [[ -d $SRCPKGDEST ]] || SRCPKGDEST=$PWD
+ [[ -d $LOGDEST ]] || LOGDEST=$PWD
-create_chroot
+# Lock the chroot we want to use. We'll keep this lock until we exit.
@@ -264,7 +306,9 @@
+ sync_chroot "$chrootdir" "$copy"
+fi
- $update_first && arch-nspawn "$copydir" pacman -Syu --noconfirm
+ $update_first && arch-nspawn "$copydir" \
+ "${bindmounts_ro[@]}" "${bindmounts_rw[@]}" \
+ pacman -Syu --noconfirm
-[[ -n ${install_pkgs[*]} ]] && install_packages
+if [[ -n ${install_pkgs[*]:-} ]]; then
@@ -283,6 +327,12 @@
if arch-nspawn "$copydir" \
--bind-ro="$PWD:/startdir_host" \
--bind-ro="$SRCDEST:/srcdest_host" \
+ "${bindmounts_ro[@]}" "${bindmounts_rw[@]}" \
++ /chrootprepare &&
++ arch-nspawn "$copydir" \
++ --bind-ro="$PWD:/startdir_host" \
++ --bind-ro="$SRCDEST:/srcdest_host" \
++ "${bindmounts_ro[@]}" "${bindmounts_rw[@]}" \
/chrootbuild "${makepkg_args[@]}"
then
- move_products
@@ -296,7 +346,7 @@
if (( ret != 0 )); then
if $temp_chroot; then
-@@ -366,3 +442,4 @@
+@@ -397,3 +501,4 @@
else
true
fi