[Android Software/Hacking General [Developers Only]] osm0sis:
So I still think this is beyond the scope of a more basic scripting thread like this, but here's the current /system_root mounting portions of the script from my unified Diffusion Installer Backend which I've just updated for /dev/block/mapper dynamic partition mount support:

BOOTMODE=false;
ps | grep zygote | grep -v grep >/dev/null && BOOTMODE=true;
$BOOTMODE || ps -A 2>/dev/null | grep zygote | grep -v grep >/dev/null && BOOTMODE=true;

[ "$ANDROID_ROOT" ] || ANDROID_ROOT=/system;

find_slot() {
local slot=$(getprop ro.boot.slot_suffix 2>/dev/null);
[ "$slot" ] || slot=$(grep -o 'androidboot.slot_suffix=.*$' /proc/cmdline | cut -d\ -f1 | cut -d= -f2);
if [ ! "$slot" ]; then
slot=$(getprop ro.boot.slot 2>/dev/null);
[ "$slot" ] || slot=$(grep -o 'androidboot.slot=.*$' /proc/cmdline | cut -d\ -f1 | cut -d= -f2);
[ "$slot" ] && slot=_$slot;
fi;
[ "$slot" ] && echo "$slot";
}
setup_mountpoint() {
[ -L $1 ] && mv -f $1 ${1}_link;
if [ ! -d $1 ]; then
rm -f $1;
mkdir -p $1;
fi;
}
is_mounted() { mount | grep -q " $1 "; }
mount_apex() {
[ -d /system_root/system/apex ] || return 1;
local apex dest loop minorx num;
setup_mountpoint /apex;
minorx=1;
[ -e /dev/block/loop1 ] && minorx=$(ls -l /dev/block/loop1 | awk '{ print $6 }');
num=0;
for apex in /system_root/system/apex/*; do
dest=/apex/$(basename $apex .apex);
[ "$dest" == /apex/com.android.runtime.release ] && dest=/apex/com.android.runtime;
mkdir -p $dest;
case $apex in
*.apex)
unzip -qo $apex apex_payload.img -d /apex;
mv -f /apex/apex_payload.img $dest.img;
mount -t ext4 -o ro,noatime $dest.img $dest 2>/dev/null;
if [ $? != 0 ]; then
while [ $num -lt 64 ]; do
loop=/dev/block/loop$num;
(mknod $loop b 7 $((num * minorx));
losetup $loop $dest.img) 2>/dev/null;
num=$((num + 1));
losetup $loop | grep -q $dest.img && break;
done;
mount -t ext4 -o ro,loop,noatime $loop $dest;
if [ $? != 0 ]; then
losetup -d $loop 2>/dev/null;
fi;
fi;
;;
*) mount -o bind $apex $dest;;
esac;
done;
export ANDROID_RUNTIME_ROOT=/apex/com.android.runtime;
export ANDROID_TZDATA_ROOT=/apex/com.android.tzdata;
export BOOTCLASSPATH=/apex/com.android.runtime/javalib/core-oj.jar:/apex/com.android.runtime/javalib/core-libart.jar:/apex/com.android.runtime/javalib/okhttp.jar:/apex/com.android.runtime/javalib/bouncycastle.jar:/apex/com.android.runtime/javalib/apache-xml.jar:/system/framework/framework.jar:/system/framework/ext.jar:/system/framework/telephony-common.jar:/system/framework/voip-common.jar:/system/framework/ims-common.jar:/system/framework/android.test.base.jar:/system/framework/telephony-ext.jar:/apex/com.android.conscrypt/javalib/conscrypt.jar:/apex/com.android.media/javalib/updatable-media.jar;
}
umount_apex() {
[ -d /apex ] || return 1;
local dest loop;
for dest in $(find /apex -type d -mindepth 1 -maxdepth 1); do
if [ -f $dest.img ]; then
loop=$(mount | grep $dest | cut -d" " -f1);
fi;
(umount -l $dest;
losetup -d $loop) 2>/dev/null;
done;
rm -rf /apex 2>/dev/null;
unset ANDROID_RUNTIME_ROOT ANDROID_TZDATA_ROOT BOOTCLASSPATH;
}
mount_all() {
if ! is_mounted /cache; then
mount /cache 2>/dev/null && UMOUNT_CACHE=1;
fi;
if ! is_mounted /data; then
mount /data && UMOUNT_DATA=1;
fi;
mount -o ro -t auto /vendor 2>/dev/null;
setup_mountpoint $ANDROID_ROOT;
if ! is_mounted $ANDROID_ROOT; then
mount -o ro -t auto $ANDROID_ROOT 2>/dev/null;
fi;
case $ANDROID_ROOT in
/system_root) setup_mountpoint /system;;
/system)
if ! is_mounted /system && ! is_mounted /system_root; then
setup_mountpoint /system_root;
mount -o ro -t auto /system_root;
elif [ -f /system/system/build.prop ]; then
setup_mountpoint /system_root;
mount --move /system /system_root;
fi;
if [ $? != 0 ]; then
(umount /system;
umount -l /system) 2>/dev/null;
if [ -d /dev/block/mapper ]; then
[ -e /dev/block/mapper/system ] || local slot=$(find_slot);
mount -o ro -t auto /dev/block/mapper/vendor$slot /vendor;
mount -o ro -t auto /dev/block/mapper/system$slot /system_root;
else
[ -e /dev/block/bootdevice/by-name/system ] || local slot=$(find_slot);
mount -o ro -t auto /dev/block/bootdevice/by-name/vendor$slot /vendor 2>/dev/null;
mount -o ro -t auto /dev/block/bootdevice/by-name/system$slot /system_root;
fi;
fi;
;;
esac;
if is_mounted /system_root; then
mount_apex;
if [ -f /system_root/build.prop ]; then
mount -o bind /system_root /system;
else
mount -o bind /system_root/system /system;
fi;
fi;
}
umount_all() {
(if [ ! -d /postinstall/tmp ]; then
umount /system;
umount -l /system;
if [ -e /system_root ]; then
umount /system_root;
umount -l /system_root;
fi;
fi;
umount /mnt/system;
umount -l /mnt/system;
umount_apex;
umount /vendor;
umount -l /vendor;
umount /mnt/vendor;
umount -l /mnt/vendor;
if [ "$UMOUNT_DATA" ]; then
umount /data;
umount -l /data;
fi;
if [ "$UMOUNT_CACHE" ]; then
umount /cache;
umount -l /cache;
fi) 2>/dev/null;
}
setup_env() {
$BOOTMODE && return 1;
mount -o bind /dev/urandom /dev/random;
if [ -L /etc ]; then
setup_mountpoint /etc;
cp -af /etc_link/* /etc;
sed -i 's; / ; /system_root ;' /etc/fstab;
fi;
umount_all;
mount_all;
OLD_LD_PATH=$LD_LIBRARY_PATH;
OLD_LD_PRE=$LD_PRELOAD;
OLD_LD_CFG=$LD_CONFIG_FILE;
unset LD_LIBRARY_PATH LD_PRELOAD LD_CONFIG_FILE;
if [ ! "$(getprop 2>/dev/null)" ]; then
getprop() {
local propdir propfile propval;
for propdir in / /system_root /system /vendor /odm /product; do
for propfile in default.prop build.prop; do
if [ "$propval" ]; then
break 2;
else
propval="$(file_getprop $propdir/$propfile $1 2>/dev/null)";
fi;
done;
done;
if [ "$propval" ]; then
echo "$propval";
else
echo "";
fi;
}
elif [ ! "$(getprop ro.build.type 2>/dev/null)" ]; then
getprop() {
($(which getprop) | grep "$1" | cut -d[ -f3 | cut -d] -f1) 2>/dev/null;
}
fi;
}
restore_env() {
$BOOTMODE && return 1;
local dir;
unset -f getprop;
[ "$OLD_LD_PATH" ] && export LD_LIBRARY_PATH=$OLD_LD_PATH;
[ "$OLD_LD_PRE" ] && export LD_PRELOAD=$OLD_LD_PRE;
[ "$OLD_LD_CFG" ] && export LD_CONFIG_FILE=$OLD_LD_CFG;
umount_all;
[ -L /etc_link ] && rm -rf /etc/*;
(for dir in /apex /system /system_root /etc; do
if [ -L "${dir}_link" ]; then
rmdir $dir;
mv -f ${dir}_link $dir;
fi;
done;
umount -l /dev/random) 2>/dev/null;
}

setup_env;

# insert script here

cd /;
restore_env;

I don't plan on updating it here, so if you want the latest version of this in the future you'll have to grab it from one of my Magisk module zips in customize.sh.

Also note that currently in LOS Recovery on dynamic/logical partition devices one would need to use the Advanced option "Mount /system" first before flashing since LOS Recovery doesn't automatically set up /dev/block/mapper like TWRP does. I'm looking into whether there's a way to script setting up /dev/block/mapper but I'm fairly certain it all happens in recovery code so we're probably out of luck, unless I can convince Lineage to automatically set it up as well. 🤷‍♂️

Edit

: Turns out Lineage also maps the logical partitions automatically, but only just before a zip is flashed. So all should work from within a zip. (y)

Updated the OP, however now the last few functions are f*cked thanks to XenForo XDA. :rolleyes:

Edit

: Ahah! Was able to fix them finally now that bitpushr tweaked XDA's WAF. 👌