summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorP. J. McDermott <pj@pehjota.net>2014-10-04 22:11:20 (EDT)
committer P. J. McDermott <pj@pehjota.net>2014-10-04 22:11:20 (EDT)
commit3d375aeb2f2cd9c629fd0e99d17f3f24742581ec (patch)
treee86a06842e0a130425fec8cefff983c2e42656b7 /lib
parent04f5e3222ec7dff74d63638dfacdcb5c9d7a8201 (diff)
session_*(): New functions
Diffstat (limited to 'lib')
-rw-r--r--lib/local.mk1
-rw-r--r--lib/session.sh134
2 files changed, 135 insertions, 0 deletions
diff --git a/lib/local.mk b/lib/local.mk
index 3de79f7..66d203f 100644
--- a/lib/local.mk
+++ b/lib/local.mk
@@ -10,6 +10,7 @@ pkgdata_sources = \
lib/feed.sh \
lib/pkg.sh \
lib/mutex.sh \
+ lib/session.sh \
lib/chroot.sh \
lib/opkg.sh \
lib/rand.sh \
diff --git a/lib/session.sh b/lib/session.sh
new file mode 100644
index 0000000..1430493
--- /dev/null
+++ b/lib/session.sh
@@ -0,0 +1,134 @@
+# Functions for managing prokit sessions
+#
+# Copyright (C) 2014 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${_SESSION_SM+set}" = 'xset' ] && return 0
+_SESSION_SM=1
+
+use rand
+use mutex
+use output
+use locale
+use profile
+
+session_id=
+session_root=
+session_arch=
+session_plat=
+session_atexit=
+
+session_begin()
+{
+ local root="${1}"
+ local atexit="${2}"
+
+ rand
+ session_id=${rand_x}
+ session_root="${root}"
+ session_arch="$(cat "${root}/etc/proteanos_arch")"
+ session_plat="$(cat "${root}/etc/proteanos_plat")"
+ session_atexit="${atexit}"
+
+ if ! mutex_lock_timeout "${session_root}/prokit/sessions.lock" 5; then
+ error 2 "$(get_msg 'cant_lock_sessions')"
+ fi
+
+ # Check for a sessions pool.
+ if [ -d "${session_root}/prokit/sessions" ]; then
+ if ! profile_file_systems_mounted; then
+ # If a sessions pool exists but the file systems aren't
+ # mounted, clean up the old sessions and mount the file
+ # systems.
+ rmdir "${session_root}/prokit/sessions/"*
+ session_mount
+ fi
+ else
+ # If the sessions pool doesn't exist, create it and mount the
+ # file systems.
+ mkdir "${session_root}/prokit/sessions"
+ session_mount
+ fi
+
+ # Register the session.
+ mkdir "${session_root}/prokit/sessions/${session_id}"
+
+ mutex_unlock "${session_root}/prokit/sessions.lock"
+}
+
+session_end()
+{
+ # Unregister the session.
+ rmdir "${session_root}/prokit/sessions/${session_id}"
+
+ if ! mutex_lock_timeout "${session_root}/prokit/sessions.lock" 5; then
+ error 2 "$(get_msg 'cant_lock_sessions')"
+ fi
+
+ # Clear the sessions pool. If there are no more sessions, unmount the
+ # file systems.
+ if rmdir "${session_root}/prokit/sessions" 2>/dev/null; then
+ session_umount
+ fi
+
+ mutex_unlock "${session_root}/prokit/sessions.lock"
+}
+
+session_id()
+{
+ printf '%d\n' ${session_id}
+ return 0
+}
+
+session_mount()
+{
+ local fs=
+ local dir=
+ local fstype=
+ local options=
+
+ while read fs dir fstype options; do
+ [ "x${dir}" = 'x' ] && continue
+ mount -t "${fstype}" -o "${options}" "${fs}" \
+ "${session_root}/${dir}"
+ done <<-EOF
+ $(profile_get_fstab "${session_arch}" "${session_plat}")
+ EOF
+}
+
+session_umount()
+{
+ local fs=
+ local dir=
+ local fstype=
+ local options=
+
+ while read fs dir fstype options; do
+ [ "x${dir}" = 'x' ] && continue
+ # umount sometimes complains that the /dev file system is busy.
+ # Here's a kludge to try to handle that. We better make sure
+ # bind mounts get unmounted; otherwise, `rm -Rf ${root}` can be
+ # painful.
+ while ! umount "${session_root}/${dir}"; do
+ sleep 1
+ done
+ done <<-EOF
+ $(profile_get_fstab "${session_arch}" "${session_plat}" | \
+ sed -n '1!G;h;$p')
+ EOF
+}