diff options
-rw-r--r-- | Makefile.am | 6 | ||||
-rw-r--r-- | configure.ac | 17 | ||||
-rw-r--r-- | lib/block.sh | 92 | ||||
-rw-r--r-- | lib/cmd/build.sh | 15 | ||||
-rw-r--r-- | lib/cmd/install.sh | 12 | ||||
-rw-r--r-- | lib/cmd/opkg.sh | 12 | ||||
-rw-r--r-- | lib/cmd/shell.sh | 12 | ||||
-rw-r--r-- | lib/local.mk | 2 | ||||
-rw-r--r-- | lib/vardata.sh | 56 | ||||
-rw-r--r-- | locale/en_US.sh | 15 | ||||
-rw-r--r-- | man/prokit-build.8in | 5 | ||||
-rw-r--r-- | man/prokit-install.8in | 7 | ||||
-rw-r--r-- | man/prokit-opkg.8in | 5 | ||||
-rw-r--r-- | man/prokit-shell.8in | 7 | ||||
-rw-r--r-- | src/prokit.sh | 2 |
15 files changed, 255 insertions, 10 deletions
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 +# <http://www.gnu.org/licenses/>. + +[ "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 # <http://www.gnu.org/licenses/>. +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 # <http://www.gnu.org/licenses/>. +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 # <http://www.gnu.org/licenses/>. +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 +# <http://www.gnu.org/licenses/>. + +[ "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 <arch>] [-p <plat>] [-m <mirror>] [-F] '\ -'<suite> <root-dir>' +'<suite> <root>' 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='<root-dir> [<command> [<argument> ...]]' +msg_prokit_cmd_shell_usage='<root> [<command> [<argument> ...]]' msg_prokit_cmd_shell_exiting='Exiting...' # lib/cmd/opkg.sh msg_prokit_cmd_opkg_summary='manage packages with opkg' -msg_prokit_cmd_opkg_usage='<root-dir> [<option> ...] <sub-command> '\ +msg_prokit_cmd_opkg_usage='<root> [<option> ...] <sub-command> '\ '[<argument> ...]' # lib/cmd/build.sh msg_prokit_cmd_build_summary='build a package' -msg_prokit_cmd_build_usage='<root-dir> [<option> ...] <pkg-dir>' +msg_prokit_cmd_build_usage='<root> [<option> ...] <pkg-dir>' msg_prokit_cmd_build_not_a_dir='Not a directory: %s' # lib/profile.sh diff --git a/man/prokit-build.8in b/man/prokit-build.8in index 77ed078..5dc25de 100644 --- a/man/prokit-build.8in +++ b/man/prokit-build.8in @@ -5,12 +5,15 @@ prokit-build \- Build a package .SH SYNOPSIS -\fBprokit build\fP \fIroot-dir\fP [\fIoption\fP ...] \fIpkg-dir\fP +\fBprokit build\fP \fIroot\fP [\fIoption\fP ...] \fIpkg-dir\fP .SH DESCRIPTION \fBprokit build\fP runs \fBopkbuild\fP to build a package in an isolated file system environment, temporarily installing any missing build dependencies. .P +If \fIroot\fP is a block device node, the block device is mounted and +\fBopkbuild\fP is run in its file system. +.P \fIoption\fPs are \fBopkbuild\fP options. Run \fIprokit build -h .\fP for more information. .P diff --git a/man/prokit-install.8in b/man/prokit-install.8in index ef5f68d..4f10d34 100644 --- a/man/prokit-install.8in +++ b/man/prokit-install.8in @@ -6,10 +6,13 @@ prokit-install \- Install a system into a directory .SH SYNOPSIS \fBprokit install\fP [\fB-a\fP \fIarch\fP] [\fB-p\fP \fIplat\fP] -[\fB-m\fP \fImirror\fP] [\fB-F\fP] \fIsuite\fP \fIroot-dir\fP +[\fB-m\fP \fImirror\fP] [\fB-F\fP] \fIsuite\fP \fIroot\fP .SH DESCRIPTION -\fBprokit install\fP installs a basic system of \fIsuite\fP into \fIroot-dir\fP. +\fBprokit install\fP installs a basic system of \fIsuite\fP into \fIroot\fP. +.P +If \fIroot\fP is a block device node, the block device is mounted and a system +is installed into its file system. .P \fIsuite\fP can be a distribution like \fItrunk\fP; a channel and distribution like \fIdev/trunk\fP; a profile and distribution like \fIproteanos:trunk\fP; or diff --git a/man/prokit-opkg.8in b/man/prokit-opkg.8in index cfe8e9f..50b845a 100644 --- a/man/prokit-opkg.8in +++ b/man/prokit-opkg.8in @@ -5,12 +5,15 @@ prokit-opkg \- Manage packages with opkg .SH SYNOPSIS -\fBprokit opkg\fP \fIroot-dir\fP [\fIoption\fP ...] \fIsub-command\fP +\fBprokit opkg\fP \fIroot\fP [\fIoption\fP ...] \fIsub-command\fP [\fIargument\fP ...] .SH DESCRIPTION \fBprokit opkg\fP runs \fBopkg\fP in an isolated file system environment. .P +If \fIroot\fP is a block device node, the block device is mounted and \fBopkg\fP +is run in its file system. +.P \fIoption\fPs are \fBopkg\fP options and \fIsub-command\fP is an \fBopkg\fP sub-command. See the usage information for \fBopkg\fP for more information. .P diff --git a/man/prokit-shell.8in b/man/prokit-shell.8in index f42b15a..bb98ae1 100644 --- a/man/prokit-shell.8in +++ b/man/prokit-shell.8in @@ -5,12 +5,15 @@ prokit-shell \- Run a shell in an isolated environment .SH SYNOPSIS -\fBprokit shell\fP \fIroot-dir\fP [\fIcommand\fP [\fIargument\fP ...]] +\fBprokit shell\fP \fIroot\fP [\fIcommand\fP [\fIargument\fP ...]] .SH DESCRIPTION \fBprokit shell\fP starts a shell in an isolated file system environment (using \fBchroot\fP(8)) with basic file systems mounted. .P +If \fIroot\fP is a block device node, the block device is mounted and a shell is +started in its file system. +.P If a \fIcommand\fP is given (with optional \fIargument\fPs), it is executed in a non-interactive shell. @@ -20,6 +23,8 @@ non-interactive shell. # prokit shell $root echo Hello world .IP \[bu] # prokit shell $root 'opkg install build-essential-$(cat /etc/proteanos_arch)' +.IP \[bu] +# prokit shell /dev/sdb1 .SH COPYRIGHT Copyright (C) 2014 Patrick "P. J." McDermott diff --git a/src/prokit.sh b/src/prokit.sh index 037c233..5cfdb53 100644 --- a/src/prokit.sh +++ b/src/prokit.sh @@ -62,6 +62,7 @@ use() use locale use cmd +use vardata use getopt use rand @@ -71,6 +72,7 @@ main() load_locale load_cmds + init_vardata if ! get_options "${@}"; then cmd_help_main >&2 |