From 65489cd1069b6e9cb592508103211984c43d3bbf Mon Sep 17 00:00:00 2001 From: P. J. McDermott Date: Mon, 25 May 2015 20:33:22 -0400 Subject: Merge branch 'feature/block-device-mounting' --- diff --git a/Makefile.am b/Makefile.am index b55f926..4d1657b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -56,6 +56,8 @@ pkgdatacmddir = $(pkgdatadir)/cmd pkgdataprofiledir = $(pkgdatadir)/profile pkgdatapackagedir = $(pkgdatadir)/package uninstall_dirs = \ + '$(DESTDIR)$(pkglocalstatedir)/mount' \ + '$(DESTDIR)$(pkglocalstatedir)' \ '$(DESTDIR)$(pkgdatapackagedir)' \ '$(DESTDIR)$(pkgdataprofiledir)' \ '$(DESTDIR)$(pkgdatacmddir)' \ @@ -92,6 +94,7 @@ do_subst = sed \ -e 's|[@]SH[@]|$(SH)|g' \ -e 's|[@]pkgdatadir[@]|$(pkgdatadir)|g' \ -e 's|[@]localedir[@]|$(localedir)|g' \ + -e 's|[@]pkglocalstatedir[@]|$(pkglocalstatedir)|g' \ -e "s|[@]cmds[@]|$(cmds)|g" \ -e "s|[@]profiles[@]|$(profiles)|g" \ -e "s|[@]textdomain[@]|$(textdomain)|g" @@ -150,6 +153,9 @@ wikiman: $(man1_MANS) $(man8_MANS) >"$${f}.mdwn"; \ done +install-exec-hook: + $(MKDIR_P) "$(DESTDIR)$(pkglocalstatedir)/mount" + install-data-local: $(locale_MESSAGES) @$(NORMAL_INSTALL) for f in $(locale_MESSAGES); do \ diff --git a/configure.ac b/configure.ac index a9e2c78..01d7dc1 100644 --- a/configure.ac +++ b/configure.ac @@ -27,6 +27,23 @@ AC_CONFIG_SRCDIR([src/prokit.sh]) AM_INIT_AUTOMAKE([gnu check-news dist-bzip2 dist-xz subdir-objects]) AM_SILENT_RULES([yes]) +if test "x${localstatedir}" = 'x${prefix}/var'; then + case "${prefix}" in + NONE | */local | */local/*) + pkglocalstatedir='/var/local/prokit' + ;; + /opt | /opt/*) + pkglocalstatedir='/var/opt/prokit' + ;; + *) + pkglocalstatedir='/var/lib/prokit' + ;; + esac +else + pkglocalstatedir='${localstatedir}/lib/prokit' +fi +AC_SUBST([pkglocalstatedir]) + AC_ARG_WITH( [sh], [AS_HELP_STRING([--with-sh], [POSIX-conformant shell with `local'])], diff --git a/lib/block.sh b/lib/block.sh new file mode 100644 index 0000000..ef1eed9 --- /dev/null +++ b/lib/block.sh @@ -0,0 +1,92 @@ +# Functions for mounting and unmounting block devices +# +# Copyright (C) 2015 Patrick "P. J." McDermott +# +# This file is part of the ProteanOS Development Kit. +# +# The ProteanOS Development Kit is free software: you can redistribute +# it and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# The ProteanOS Development Kit is distributed in the hope that it +# will be useful, but WITHOUT ANY WARRANTY; without even the implied +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with the ProteanOS Development Kit. If not, see +# . + +[ "x${_BLOCK_SM+set}" = 'xset' ] && return 0 +_BLOCK_SM=1 + +use rand +use vardata + +is_block() +{ + local dev="${1}" + + [ -b "${dev}" ] + return ${?} +} + +check_block() +{ + local dev="${1}" + + if ! [ -b "${dev}" ]; then + error 2 "$(get_msg 'block_device_invalid')" "${dev}" + fi +} + +block_mount() +{ + local dev="${1}" + local dir= + + check_block "${dev}" + + rand + dir="$(get_vardata_dir 'mount')/block-$(printf '%010d' ${rand_x})" + if ! mkdir "${dir}"; then + error 2 "$(get_msg 'block_mkdir_fail')" "${dir}" + fi + + if ! mount "${dev}" "${dir}"; then + rmdir "${dir}" + error 2 "$(get_msg 'block_mount_fail')" "${dev}" + fi + + printf '%s' "${dir}" + return 0 +} + +block_umount() +{ + local dir="${1}" + local i= + local timed_out= + + i=0 + timed_out=false + while ! umount "${dir}"; do + i=$(($i + 1)) + if [ ${i} -eq 10 ]; then + timed_out=true + break + fi + sleep 1 + done + + if ${timed_out}; then + error 2 "$(get_msg 'block_umount_fail')" "${dir}" + fi + + if ! rmdir "${dir}"; then + error 2 "$(get_msg 'block_rmdir_fail')" "${dir}" + fi + + return 0 +} diff --git a/lib/cmd/build.sh b/lib/cmd/build.sh index 32dca26..d22fa1e 100644 --- a/lib/cmd/build.sh +++ b/lib/cmd/build.sh @@ -18,6 +18,7 @@ # along with the ProteanOS Development Kit. If not, see # . +use block use profile use session use rand @@ -31,6 +32,7 @@ cmd_build_build_deps= cmd_build_main() { local root= + local dev= local opkbuild_optstring= local arch= local plat= @@ -43,9 +45,16 @@ cmd_build_main() fi root="${1}" - cmd_build_root="${root}" shift 1 + dev='' + if is_block "${root}"; then + dev="${root}" + root="$(block_mount "${dev}")" + fi + + cmd_build_root="${root}" + opkbuild_optstring="$(cat "${root}/usr/share/opkbuild/optstring")" arch="$(cat "${root}/etc/proteanos_arch")" plat="$(cat "${root}/etc/proteanos_plat")" @@ -91,6 +100,10 @@ cmd_build_main() cmd_build_fini session_end + + if [ "x${dev}" != 'x' ]; then + block_umount "${root}" + fi } cmd_build_make_deps_pkg() diff --git a/lib/cmd/install.sh b/lib/cmd/install.sh index ac817e0..a02a77c 100644 --- a/lib/cmd/install.sh +++ b/lib/cmd/install.sh @@ -21,6 +21,7 @@ use getopt use feed use profile +use block use dir use fd use pkg @@ -41,6 +42,7 @@ cmd_install_main() local profile= local mirror= local foreign= + local dev= if ! get_options "${@}"; then print_cmd_usage 'install' >&2 @@ -97,6 +99,12 @@ cmd_install_main() foreign=false fi + dev='' + if is_block "${chroot}"; then + dev="${chroot}" + chroot="$(block_mount "${dev}")" + fi + info "$(get_msg 'cmd_install_setting_up_chroot')" if [ -d "${chroot}" ] && ! dir_is_empty "${chroot}" 'lost+found'; then error 2 "$(get_msg 'cmd_install_chroot_dir_exists')" "${chroot}" @@ -119,6 +127,10 @@ cmd_install_main() fi rm "${chroot}/prokit/installing" + + if [ "x${dev}" != 'x' ]; then + block_umount "${chroot}" + fi } cmd_install_find_pkgs() diff --git a/lib/cmd/opkg.sh b/lib/cmd/opkg.sh index 9f0c0de..51b90dc 100644 --- a/lib/cmd/opkg.sh +++ b/lib/cmd/opkg.sh @@ -18,6 +18,7 @@ # along with the ProteanOS Development Kit. If not, see # . +use block use profile use session use rand @@ -27,6 +28,7 @@ cmd_opkg_opks= cmd_opkg_main() { local root= + local dev= local first_arg= local install_cmd= local arg= @@ -40,6 +42,12 @@ cmd_opkg_main() root="${1}" shift 1 + dev='' + if is_block "${root}"; then + dev="${root}" + root="$(block_mount "${dev}")" + fi + first_arg=true install_cmd=false cmd_opkg_opks='' @@ -84,6 +92,10 @@ cmd_opkg_main() cmd_opkg_fini session_end + + if [ "x${dev}" != 'x' ]; then + block_umount "${root}" + fi } cmd_opkg_fini() diff --git a/lib/cmd/shell.sh b/lib/cmd/shell.sh index dfff07f..b5b6d69 100644 --- a/lib/cmd/shell.sh +++ b/lib/cmd/shell.sh @@ -18,12 +18,14 @@ # along with the ProteanOS Development Kit. If not, see # . +use block use profile use session cmd_shell_main() { local root= + local dev= if [ ${#} -lt 1 ]; then print_cmd_usage 'shell' >&2 @@ -33,6 +35,12 @@ cmd_shell_main() root="${1}" shift 1 + dev='' + if is_block "${root}"; then + dev="${root}" + root="$(block_mount "${dev}")" + fi + . "${root}/etc/os-release" profile_set "${ID}" @@ -45,4 +53,8 @@ cmd_shell_main() session_exec "${@}" fi session_end + + if [ "x${dev}" != 'x' ]; then + block_umount "${root}" + fi } diff --git a/lib/local.mk b/lib/local.mk index 1ce768c..53b2d91 100644 --- a/lib/local.mk +++ b/lib/local.mk @@ -4,6 +4,7 @@ pkgdata_sources = \ lib/getopt.sh \ lib/fd.sh \ lib/dir.sh \ + lib/vardata.sh \ lib/archplat.sh \ lib/deps.sh \ lib/substvars.sh \ @@ -12,6 +13,7 @@ pkgdata_sources = \ lib/pkg.sh \ lib/mutex.sh \ lib/session.sh \ + lib/block.sh \ lib/opkg.sh \ lib/rand.sh \ lib/cmd.sh \ diff --git a/lib/vardata.sh b/lib/vardata.sh new file mode 100644 index 0000000..8800003 --- /dev/null +++ b/lib/vardata.sh @@ -0,0 +1,56 @@ +# Functions for getting variable/runtime data +# +# Copyright (C) 2015 Patrick "P. J." McDermott +# +# This file is part of the ProteanOS Development Kit. +# +# The ProteanOS Development Kit is free software: you can redistribute +# it and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# The ProteanOS Development Kit is distributed in the hope that it +# will be useful, but WITHOUT ANY WARRANTY; without even the implied +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with the ProteanOS Development Kit. If not, see +# . + +[ "x${_VARDATA_SM+set}" = 'xset' ] && return 0 +_VARDATA_SM=1 + +PKGLOCALSTATEDIR='@pkglocalstatedir@' +VARDATA_DIRS='mount' + +vardatadir= + +init_vardata() +{ + local dir= + + if ${in_place}; then + vardatadir="${builddir}/var" + for dir in ${VARDATA_DIRS}; do + mkdir -p "${vardatadir}/${dir}" + done + else + vardatadir="${PKGLOCALSTATEDIR}" + fi + + return 0 +} + +get_vardata_dir() +{ + local dir="${1}" + + case " ${VARDATA_DIRS} " in + *" ${dir} "*) + printf '%s/%s' "${vardatadir}" "${dir}" + ;; + esac + + return 0 +} diff --git a/locale/en_US.sh b/locale/en_US.sh index 3063cb0..efcc65b 100644 --- a/locale/en_US.sh +++ b/locale/en_US.sh @@ -48,6 +48,13 @@ msg_prokit_cant_lock_sessions='Cannot acquire sessions state lock' msg_prokit_install_running='Another instance of prokit is installing this '\ 'system' +# lib/block.sh +msg_prokit_block_device_invalid='Not a block device: %s' +msg_prokit_block_mkdir_fail='Failed to create block device mount point "%s"' +msg_prokit_block_mount_fail='Failed to mount block device "%s"' +msg_prokit_block_umount_fail='Failed to unmount block device mounted at "%s"' +msg_prokit_block_rmdir_fail='Failed to remove block device mount point "%s"' + # lib/rand.sh msg_prokit_rand_bad_x='Invalid random number generator seed value' @@ -73,7 +80,7 @@ There is NO WARRANTY, to the extent permitted by law.' # lib/cmd/install.sh msg_prokit_cmd_install_summary='install a system into a directory' msg_prokit_cmd_install_usage='[-a ] [-p ] [-m ] [-F] '\ -' ' +' ' msg_prokit_cmd_install_bad_archplat='Invalid combination of architecture "%s" '\ 'and platform "%s"' msg_prokit_cmd_install_selected_arch='Using architecture %s' @@ -92,17 +99,17 @@ msg_prokit_cmd_install_checksum_fail='Checksum of package file failed' # lib/cmd/shell.sh msg_prokit_cmd_shell_summary='run a shell in an isolated environment' -msg_prokit_cmd_shell_usage=' [ [ ...]]' +msg_prokit_cmd_shell_usage=' [ [ ...]]' msg_prokit_cmd_shell_exiting='Exiting...' # lib/cmd/opkg.sh msg_prokit_cmd_opkg_summary='manage packages with opkg' -msg_prokit_cmd_opkg_usage=' [