diff options
-rw-r--r-- | archbuild.in | 9 | ||||
-rw-r--r-- | lib/common.sh | 51 | ||||
-rw-r--r-- | makechrootpkg.in | 17 | ||||
-rw-r--r-- | mkarchroot.in | 99 |
4 files changed, 119 insertions, 57 deletions
diff --git a/archbuild.in b/archbuild.in index bdb18c0..06c9815 100644 --- a/archbuild.in +++ b/archbuild.in @@ -51,19 +51,14 @@ if ${clean_first} || [[ ! -d "${chroots}/${repo}-${arch}" ]]; then [[ -d $copy ]] || continue msg2 "Deleting chroot copy '$(basename "${copy}")'..." - exec 9>"$copydir.lock" - if ! flock -n 9; then - stat_busy "Locking chroot copy '$copy'" - flock 9 - stat_done - fi + lock_open_write 9 "$copy.lock" "Locking chroot copy '$copy'" if [[ "$(stat -f -c %T "${copy}")" == btrfs ]]; then { type -P btrfs && btrfs subvolume delete "${copy}"; } &>/dev/null fi rm -rf --one-file-system "${copy}" done - exec 9>&- + lock_close 9 rm -rf --one-file-system "${chroots}/${repo}-${arch}" mkdir -p "${chroots}/${repo}-${arch}" diff --git a/lib/common.sh b/lib/common.sh index b39bbbc..932799e 100644 --- a/lib/common.sh +++ b/lib/common.sh @@ -104,6 +104,57 @@ in_array() { } ## +# usage : lock_open_write( $fd, $path, $wait_message ) +## +lock_open_write() { + local fd=$1 + local path=$2 + local msg=$3 + + # Only reopen the FD if it wasn't handed to us + if [[ $(readlink -f /dev/fd/$fd) != "${path}.lock" ]]; then + mkdir -p "${path%/*}" + eval "exec $fd>${path}.lock" + fi + + if ! flock -n $fd; then + stat_busy "$msg" + flock $fd + stat_done + fi +} + +## +# usage : lock_open_read( $fd, $path, $wait_message ) +## +lock_open_read() { + local fd=$1 + local path=$2 + local msg=$3 + + # Only reopen the FD if it wasn't handed to us + if [[ $(readlink -f /dev/fd/$fd) != "${path}.lock" ]]; then + mkdir -p "${path%/*}" + eval "exec $fd>${path}.lock" + fi + + if ! flock -sn $fd; then + stat_busy "$msg" + flock -s $fd + stat_done + fi +} + + +## +# usage : lock_close( $fd ) +## +lock_close() { + local fd=$1 + eval "exec $fd>&-" +} + +## # usage : get_full_version( [$pkgname] ) # return : full version spec, including epoch (if necessary), pkgver, pkgrel ## diff --git a/makechrootpkg.in b/makechrootpkg.in index e7e5f21..717e02f 100644 --- a/makechrootpkg.in +++ b/makechrootpkg.in @@ -119,23 +119,12 @@ chroottype=$(stat -f -c %T "$chrootdir") # Lock the chroot we want to use. We'll keep this lock until we exit. # Note this is the same FD number as in mkarchroot -exec 9>"$copydir.lock" -if ! flock -n 9; then - stat_busy "Locking chroot copy [$copy]" - flock 9 - stat_done -fi +lock_open_write 9 "$copydir.lock" "Locking chroot copy [$copy]" if [[ ! -d $copydir ]] || $clean_first; then # Get a read lock on the root chroot to make # sure we don't clone a half-updated chroot - exec 8>"$chrootdir/root.lock" - - if ! flock -sn 8; then - stat_busy "Locking clean chroot" - flock -s 8 - stat_done - fi + lock_open_read 8 "$chrootdir/root" "Locking clean chroot" stat_busy "Creating clean working copy [$copy]" if [[ "$chroottype" == btrfs ]]; then @@ -152,7 +141,7 @@ if [[ ! -d $copydir ]] || $clean_first; then stat_done # Drop the read lock again - exec 8>&- + lock_close 8 fi if [[ -n "${install_pkgs[*]}" ]]; then diff --git a/mkarchroot.in b/mkarchroot.in index 6598089..cff046f 100644 --- a/mkarchroot.in +++ b/mkarchroot.in @@ -13,8 +13,9 @@ m4_include(lib/common.sh) CHROOT_VERSION='v3' FORCE='n' -RUN='' +MODE='i' NOCOPY='n' +NONETWORK='n' working_dir='' @@ -22,49 +23,81 @@ APPNAME=$(basename "${0}") # usage: usage <exitvalue> usage() { - echo "Usage: ${APPNAME} [options] working-dir [package-list | app]" + echo "Usage: ${APPNAME} [options] working-dir [exta-arguments]" echo ' options:' - echo ' -r <app> Run "app" within the context of the chroot' - echo ' -u Update the chroot via pacman' echo ' -f Force overwrite of files in the working-dir' echo ' -C <file> Location of a pacman config file' echo ' -M <file> Location of a makepkg config file' echo ' -n Do not copy config files into the chroot' echo ' -c <dir> Set pacman cache' - echo ' -h This message' - exit 1 + echo ' -N Disable networking in the chroot' + echo ' modes:' + echo ' -i Install the packages "extra-arguments" in the chroot.' + echo ' This creates the chroot if it does not exist.' + echo ' This is the default mode.' + echo ' -r Run the command "extra-arguments" within the chroot' + echo ' -u Update the chroot via pacman' + echo ' -h Print this message' + + exit ${1-1} } -while getopts 'r:ufnhC:M:c:' arg; do +################################################################################ + +while getopts 'fC:M:nc:Niruh' arg; do case "${arg}" in - r) RUN="$OPTARG" ;; - u) RUN='pacman -Syu --noconfirm' ;; f) FORCE='y' ;; C) pac_conf="$OPTARG" ;; M) makepkg_conf="$OPTARG" ;; n) NOCOPY='y' ;; c) cache_dir="$OPTARG" ;; - h|?) usage ;; + N) NONETWORK='y' ;; + + i|r|u) MODE="$arg" ;; + h) usage 0 ;; + *) error "invalid argument '${arg}'"; usage ;; esac done -if (( $EUID != 0 )); then - die 'This script must be run as root.' -fi - shift $(($OPTIND - 1)) -if [[ -z $RUN ]] && (( $# < 2 )); then - die 'You must specify a directory and one or more packages.' -elif (( $# < 1 )); then - die 'You must specify a directory.' +case $MODE in + i) + case $# in + 0) die 'You must specify a directory and one or more packages.' ;; + 1) die 'You must specify one or more packages.' ;; + esac + ;; + r) + case $# in + 0) die 'You must specify a directory and a command.' ;; + 1) die 'You must specify a command.' ;; + esac + ;; + u) + case $# in + 0) die 'You must specify a directory.' ;; + 1) : ;; + 2) die 'Extra arguments' ;; + esac + ;; +esac + +working_dir="$(readlink -f "${1}")" +shift 1 +[[ -z $working_dir ]] && die 'Please specify a working directory.' + +if [[ $MODE == u ]]; then + MODE=r + set -- pacman -Syu --noconfirm fi -working_dir="$(readlink -f ${1})" -shift 1 +################################################################################ -[[ -z $working_dir ]] && die 'Please specify a working directory.' +if (( $EUID != 0 )); then + die 'This script must be run as root.' +fi if [[ -z $cache_dir ]]; then cache_dirs=($(pacman -v $cache_conf 2>&1 | grep '^Cache Dirs:' | sed 's/Cache Dirs:\s*//g')) @@ -112,29 +145,23 @@ copy_hostconf () { } chroot_lock () { - # Only reopen the FD if it wasn't handed to us - if [[ $(readlink -f /dev/fd/9) != "${working_dir}.lock" ]]; then - exec 9>"${working_dir}.lock" - fi - - # Lock the chroot. Take note of the FD number. - if ! flock -n 9; then - stat_busy "Locking chroot" - flock 9 - stat_done - fi + lock_open_write 9 "${working_dir}" "Locking chroot" } chroot_run() { local dir=$1 shift - systemd-nspawn -D "${dir}" "${mount_args[@]}" -- ${@} 2>/dev/null + local nspawn_args=(-D "$dir" "${mount_args[@]}") + if [[ $NONETWORK = y ]]; then + nspawn_args+=(--private-network) + fi + systemd-nspawn "${nspawn_args[@]}" -- "${@}" 2>/dev/null } # }}} umask 0022 -if [[ -n $RUN ]]; then +if [[ $MODE == r ]]; then # run chroot {{{ #Sanity check if [[ ! -f "${working_dir}/.arch-chroot" ]]; then @@ -147,10 +174,10 @@ if [[ -n $RUN ]]; then build_mount_args copy_hostconf - chroot_run "${working_dir}" ${RUN} + chroot_run "${working_dir}" "$@" # }}} -else +elif [[ $MODE == i ]]; then # {{{ build chroot if [[ -e $working_dir && $FORCE = 'n' ]]; then die "Working directory '${working_dir}' already exists - try using -f" |