core/larch-live/session-save/merge_overlay
2010-05-21 22:16:47 +00:00

229 lines
6.0 KiB
Bash
Executable File

#!/bin/sh
# merge_overlay - rebuild the overlays (clearing the top layer)
# Author: Michael Towers (larch42 at googlemail dot com)
#
# This file is part of the larch project.
#
# larch 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 2 of the License, or
# (at your option) any later version.
#
# larch 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 larch; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
#----------------------------------------------------------------------------
# 2009.08.23
# test if the script is started by root user. If not, exit
if [ $UID -ne 0 ]; then
echo "Only root can run ${APP}"; exit 1
fi
# Underlying system: /.livesys/system
# 'filter' layer: /.livesys/filter
# 'mods' layer: /.livesys/mods
# Overlay: /.livesys/overlay
domerge ()
{
# Make a directory for a merged union
merge_union=/.livesys/merge_union
rm -rf ${merge_union}
mkdir -p ${merge_union}
echo "Mounting merge union"
layers="/.livesys/overlay=${ovlmnt}:/.livesys/mods=${sqfmnt}"
mount -n -t ${utype} -o ro,${bropt}${layers} ${utype} ${merge_union}
if [ $? -ne 0 ]; then
echo "** Couldn't mount merge union."
return 1
fi
newmods ${merge_union}
res=$?
# Discard merge union
umount -n ${merge_union}
rm -r ${merge_union}
return ${res}
}
dofilter()
{
# Make a directory for a new filter
filter_new=/.livesys/filter_new
rm -rf ${filter_new}
mkdir -p ${filter_new}
# Make a directory for a new union
filter_union=/.livesys/filter_union
rm -rf ${filter_union}
mkdir -p ${filter_union}
echo "Mounting filter union"
layers="/.livesys/filter_new=${ovlwmnt}:/.livesys/system=${sqfmnt}"
mount -n -t ${utype} -o ${bropt}${layers} ${utype} ${filter_union}
if [ $? -ne 0 ]; then
echo "** Couldn't mount filter union."
return 1
fi
newfilter ${filter_union}
# Discard filter union
umount -n ${filter_union}
rm -r ${filter_union}
mksquashfs ${filter_new} "${overlaypath}/filter.tmp"
res=$?
# Discard filter build directory
rm -r ${filter_new}
if [ ${res} -ne 0 ]; then
echo "ERROR: Couldn't create ${overlaypath}/filter.tmp"
return 1
fi
return 0
}
newmods ()
{
olaydir=$1
echo "Building new 'mods' overlay to ${overlaypath}/mods.tmp"
# Recreate the desired layout in a new directory, using mount --bind
# ( this is probably over-complicated, but I got annoying warnings about
# conflicting permissions on the mount point when I didn't use a single
# source for squashfs - for some reason the squashfs root was set to
# mode 0777.)
# The other version was:
## root directories which are included in mods.sqf
#includedirs=""
#for d in bin boot etc home lib mnt opt root sbin srv usr var; do
# if [ -d ${olaydir}/${d} ]; then
# includedirs="${includedirs} ${olaydir}/${d}"
# fi
#done
## non-included /var directories
#vardirs="${olaydir}/var/log ${olaydir}/var/tmp ${olaydir}/var/cache/pacman/pkg"
#mksquashfs ${includedirs} "${overlaypath}/mods.tmp" -e ${vardirs}
#res=$?
#+++
mods2=/.livesys/mods2
rm -rf ${mods2}
mkdir -p ${mods2}
# root directories which are included in mods.sqf
includedirs=""
for d in bin boot etc home lib mnt opt root sbin srv usr var; do
if [ -d ${olaydir}/${d} ]; then
includedirs="${includedirs} ${d}"
mkdir ${mods2}/${d}
mount -n --bind ${olaydir}/${d} ${mods2}/${d}
fi
done
# non-included /var directories
vardirs="var/log var/tmp var/cache/pacman/pkg"
mksquashfs ${mods2} "${overlaypath}/mods.tmp" -e ${vardirs}
res=$?
for d in ${includedirs}; do
umount -n ${mods2}/${d}
done
rm -r ${mods2}
if [ ${res} -ne 0 ]; then
echo "ERROR: Couldn't create ${overlaypath}/mods.tmp"
return 1
fi
return 0
}
newfilter()
{
olaydir=$1
echo "Building new 'filter' overlay to ${overlaypath}/filter.tmp"
# 'Copy' existing filter
if [ -d /.livesys/filter ]; then
cd /.livesys/filter
find . -name .wh.\* | { cd "${olaydir}"
while read n; do
b="${n##*/}"
rm -rf "${n%/*}/${b:4}" &>/dev/null
done
}
fi
# Add relevant whiteouts from overlay
cd /.livesys/overlay
find . -name .wh.\* | { cd "${olaydir}"
while read n; do
b="${n##*/}"
d="${n%/*}"
if [ "${b}" = "${opq}" ]; then
rm -rf "${d}"
else
rm -rf "${d}/${b:4}" &>/dev/null
fi
done
}
}
# The overlay device (where the archives will be saved)
echo "Rebuild squashfs overlay"
if [ -d "$1" ]; then
overlaypath="$1"
else
echo "ERROR: invalid directory ($1)"
exit 1
fi
utype="$( cat /.livesys/utype )"
if [ "${utype}" = "aufs" ]; then
sqfmnt="rr"
ovlmnt="ro+wh"
ovlwmnt="rw"
bropt="br:"
opq=".wh..wh..opq"
# flush pseudo-links (which keep track of changed hard linked files)
auplink / flush
elif [ "${utype}" = "unionfs" ]; then
# It might well be that unionfs requires a writeable top layer, so the
# present code would need modifying ...
sqfmnt="ro"
ovlmnt="ro"
ovlwmnt="rw"
bropt="dirs="
opq=".wh.__dir_opaque"
else
echo "ERROR: Couldn't determine type of unification file-system"
exit 1
fi
if domerge && dofilter; then
echo "Merge successful"
else
rm -f "${overlaypath}/mods.tmp"
rm -f "${overlaypath}/filter.tmp"
exit 1
fi