-#!/bin/sh
+#!/bin/bash
-# casper-snapshot - utility to do Debian Live systems snapshots
+# casper-snapshot - utility to manage Debian Live systems snapshots
#
-# This program mount a /tmpfs under ~/Desktop and save the /cow
-# filesystem in it for reusing in another session.
+# This program mount a device (fallback to /tmpfs under /mnt/snapshot
+# and save the /cow (or a different dir) filesystem in it for reusing
+# in another casper session. Look at manpage for more info.
#
# Copyright (C) 2006 Marco Amadori <marco.amadori@gmail.com>
#
PROGRAM="`basename ${0}`"
VERSION=0.0.1
+
# Source casper conf
if [ -e /etc/casper.conf ]; then
. /etc/casper.conf
else
- USERNAME=`cat /etc/passwd | grep "999" | cut -f1 -d ':'`
+ USERNAME=$(cat /etc/passwd | grep "999" | cut -f1 -d ':')
+ HOSTNAME=$(hostname)
+ BUILD_SYSTEM="Debian"
+fi
+
+export USERNAME USERFULLNAME HOSTNAME BUILD_SYSTEM
+
+# Source helper functions
+helpers="/usr/share/initramfs-tools/scripts/casper-helpers"
+if [ -e "${helpers}" ]; then
+ . "${helpers}"
+else
+ echo "Error: I cannot found helper functions \"${helpers}\"."
+ exit 1
fi
+# Define LSB log_* functions.
+# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
+. /lib/lsb/init-functions
+
+# Some defaults:
+MOUNTP="/mnt/casper-snapshot"
+COW="/cow"
+DEV=""
+DEST="${MOUNTP}/casper-sn.cpio.gz"
+TYPE="cpio"
+DESKTOP_LINK=/home/$USERNAME/Desktop/casper-snapshot
+
Header ()
{
echo "${PROGRAM} - utility to do Debian Live snapshots"
echo
- echo "Usage: ${PROGRAM} [-c|--cow DIRECTORY] [-d|--dest DIRECTORY] [-o|--output FILE] [-t|--type TYPE]"
+ echo "Usage: ${PROGRAM} [-c|--cow DIRECTORY] [-d|--device DEVICE] [-o|--output FILE] [-t|--type TYPE]"
+ echo "Usage: ${PROGRAM} [-r|--resync-string STRING]"
echo "Usage: ${PROGRAM} [-h|--help]"
echo "Usage: ${PROGRAM} [-u|--usage]"
echo "Usage: ${PROGRAM} [-v|--version]"
echo " -c, --cow: specifies the copy on write directory (default: /cow)."
echo " -d, --destination: specifies the output snapshot directory (default: /home/\$USERNAME/Desktop/casper-snapshot)."
echo " -o, --output: specifies the output image file (default: $type dependent)."
+ echo " -r, --resync-string: internally used to resync previous made snapshots."
echo " -t,--type: specifies the snapshot type between \'squashfs\', \'ext2\' or \'cpio\'.gz archive (default: cpio)"
+ echo -e "\nLook at casper-snapshot(1) man page for more information."
exit 0
}
esac
}
-Lastline()
-{
- while read lines ; do
- line=${lines}
- done
- echo "${line}"
-}
-
-Base_path ()
-{
- testpath="${1}"
- mounts="`awk '{print $2}' /proc/mounts`"
- testpath="`realpath ${testpath}`"
-
- while true ; do
- if echo "${mounts}" | grep -qs "^${testpath}" ; then
- set -- `echo "${mounts}" | grep "^${testpath}" | Lastline`
- echo ${1}
- break
- else
- testpath=`dirname $testpath`
- fi
- done
-}
-
Is_same_mount ()
{
dir1="`Base_path ${1}`"
case "${1}" in
-c|--cow)
SNAP_COW="${2}"; shift 2 ;;
- -d|--destination)
- SNAP_DEST="${2}"; shift 2 ;;
+ -d|--device)
+ SNAP_DEV="${2}"; shift 2 ;;
-o|--output)
SNAP_OUTPUT="${2}"; shift 2 ;;
-t|--type)
SNAP_TYPE="${2}"; shift 2 ;;
+ -r|--resync-string)
+ SNAP_RSTRING="${2}"; break ;;
-h|--help)
Help; shift ;;
-u|--usage)
done
}
-Defaults ()
+Mount_device ()
{
- DEF_COW="/cow"
+ dev="${1}"
+
+ if [ ! -d "${MOUNTP}" ]; then
+ mkdir -p "${MOUNTP}"
+ fi
+
+ if [ -n "${dev}" ]; then
+ # create a temp
+ mount -t tmpfs -o rw tmpfs "${MOUNTP}"
+ if [ ! -L /home/$USERNAME/Desktop/casper-snapshot ]; then
+ ln -s "${MOUNTP}" /home/$USERNAME/Desktop/casper-snapshot
+ fi
+ else
+ if [ -b "${dev}" ] ; then
+ try_mount "${dev}" "${MOUNTP}" rw
+ fi
+ fi
+}
- # Bad options handling
- if [ -z "${SNAP_COW}" ]; then
- COW="${DEF_COW}"
+Defaults ()
+{
+ if [ -n "${SNAP_RSTRING}" ]; then
+ COW=$(echo "${SNAP_RSTRING}" | cut -f1 -d ':')
+ DEV=$(echo "${SNAP_RSTRING}" | cut -f2 -d ':')
+ DEST=$(echo "${SNAP_RSTRING}" | cut -f3 -d ':')
+
+ case "${DEST}" in
+ *.cpio.gz|*.cpz|*.gz)
+ TYPE="cpio" ;;
+ *.squashfs|*.squ})
+ TYPE="squashfs" ;;
+ "")
+ TYPE="ext2" ;;
+ *.ext2|*.ext)
+ TYPE="ext2" ;;
+ *)
+ Usage "Unregognized String" ;;
+ esac
else
- COW="${SNAP_COW}"
+ DEF_COW="/cow"
+ # Bad options handling
+ if [ -z "${SNAP_COW}" ]; then
+ COW="${DEF_COW}"
+ else
+ COW="${SNAP_COW}"
+ fi
+
+ case "${SNAP_TYPE}" in
+ "cpio"|"squashfs"|"ext2")
+ TYPE="${SNAP_TYPE}"
+ ;;
+ "")
+ TYPE="cpio" ;;
+ *)
+ Usage "Error: unrecognized snapshot type"
+ ;;
+ esac
+ #if [ -d
+ #if Is_same_mount
fi
+
+ Mount_device $DEV
+ DEST="${MOUNTP}/${DEST}"
+
+ # check vars
if [ ! -d "${COW}" ]; then
Usage "Error: ${COW} is not a directory"
fi
+}
- case "${SNAP_TYPE}" in
- "cpio"|"squashfs"|"ext2")
- TYPE="${SNAP_TYPE}"
- ;;
- "")
- TYPE="cpio" ;;
- *)
- Usage "Error: unrecognized snapshot type"
- ;;
- esac
-
- #if [ -d
- #if Is_same_mount
-
+Clean ()
+{
+ if [ -n "$DEV" ]; then
+ umount "${MOUNTP}"
+ rmdir "${MOUNTP}"
+ rm
+ fi
}
Main ()
Parse_args "${@}"
Defaults
Do_snapshot
+ Clean
}
Main "${@}"
# This file should go in /etc/casper.conf
# Supported variables are:
-# USERNAME, USERFULLNAME, HOST, BUILD_SYSTEM
+# USERNAME, USERFULLNAME, HOSTNAME, BUILD_SYSTEM
export USERNAME="casper"
export USERFULLNAME="Live session user"
-export HOST="live"
+export HOSTNAME="live"
export BUILD_SYSTEM="Debian"
# Default-Start: 1 2 3 4 5
# Default-Stop: 0 6
# Short-Description: Casper init script
-# Description: Does the proper shutdown in a casper booted system.
+# Description: Resyncs snapshots, evantually caches files in order
+# to let remove the media.
### END INIT INFO
# Author: Tollef Fog Heen <tfheen@canonical.com>
#
PATH=/usr/sbin:/usr/bin:/sbin:/bin
NAME=casper
-SCRIPTNAME=/etc/init.d/$NAME
+SCRIPTNAME=/etc/init.d/${NAME}
+DO_SNAPSHOT=/sbin/${NAME}-snapshot
# Exit if system was not booted by casper
grep -qs boot=casper /proc/cmdline || exit 0
fi
}
-do_sync ()
-{
- # copy the tmp media on the snapshot media
- fromdir="${1}"
- todev="${2}"
- tmnt="/mnt/temp_snap"
-
- mkdir "${tmnt}" && \
- mount "${todev}" "${tmnt}" -o rw && \
- cd "${fromdir}" && \
- find . -print0 | cpio -pumd0 "${tmnt}" && \
- umount "${tmnt}" && \
- rmdir "${tmnt}"
-}
-
do_stop ()
{
- # check for netboot
- if [ ! -z "${NETBOOT}" ] || grep -qs netboot /proc/cmdline || grep -qsi root=/dev/nfs /proc/cmdline || grep -qsi root=/dev/cifs /proc/cmdline ; then
- return 0
- fi
-
if [ ! -z "${ROOTSNAP}" ]; then
- do_sync "/cow" "${ROOTSNAP}"
+ $DO_SNAPSHOT --resync-string="${ROOTSNAP}"
fi
if [ ! -z "${HOMESNAP}" ]; then
- do_sync "/home" "${HOMESNAP}"
+ $DO_SNAPSHOT --resync-string="${HOMESNAP}"
+ fi
+
+ # check for netboot
+ if [ ! -z "${NETBOOT}" ] || grep -qs netboot /proc/cmdline || grep -qsi root=/dev/nfs /proc/cmdline || grep -qsi root=/dev/cifs /proc/cmdline ; then
+ return 0
fi
for path in $(which halt) $(which reboot) /etc/rc?.d /etc/default; do
# XXX - i18n
echo "Please remove the disc and close the tray (if any) then press ENTER: "
if [ -x /sbin/usplash_write ]; then
- /sbin/usplash_write "TIMEOUT 86400"
- /sbin/usplash_write "TEXT-URGENT Please remove the disc, close the tray (if any)"
- /sbin/usplash_write "TEXT-URGENT and press ENTER to continue"
+ /sbin/usplash_write "TIMEOUT 86400"
+ /sbin/usplash_write "TEXT-URGENT Please remove the disc, close the tray (if any)"
+ /sbin/usplash_write "TEXT-URGENT and press ENTER to continue"
fi
read x < /dev/console
[ "$VERBOSE" != no ] && log_end_msg 0
;;
stop)
- log_begin_msg "Caching reboot files..."
+ log_begin_msg "${NAME} is resyncing snapshots and caching reboot files..."
do_stop
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
exit 3
;;
esac
-
+casper (1.77+debian-2) unstable; urgency=medium
+
+ [ Marco Amadori ]
+ * Improved snapshotting (but still experimental).
+ * Renamed "host=" boot parameter to "hostname=" and shell variable "HOST" to
+ "HOSTNAME" for consistence, with linux and with username/USERNAME, as
+ requested by many people.
+ * Fixed a "keyb=" typo.
+ * Added dependence on lsb-base (used by init-script and
+ casper-snapshot).
+ * Removed DM support (obsolete).
+ * Changed a bit locale and keyboard handling.
+ * Fixed locale generation.
+ * Urgency is set to medium to try reaching Etch with important
+ features/bugfixes.
+
+ [ Otavio Salvador ]
+ * Really lowered usplash conflicts since Debian doesn't has 0.4.
+
+ -- Marco Amadori <marco.amadori@gmail.com> Mon, 30 Oct 2006 17:06:48 +0100
+
casper (1.77+debian-1) unstable; urgency=low
* New upstream release.
Package: casper
Architecture: any
-Depends: initramfs-tools (>= 0.40), user-setup, sudo
-Conflicts: usplash (<< 0.4-0)
+Depends: initramfs-tools (>= 0.40), user-setup, sudo, lsb-base (>= 3.0-6)
+Conflicts: usplash (<< 0.3-0)
Recommends: live-package
-Suggests: dmsetup, squashft-tools, genext2fs
+Suggests: squashfs-tools, genext2fs
Tag: admin::boot, admin::filesystem, implemented-in::shell, protocol::smb, role::plugin, scope::utility, special::completely-tagged, works-with-format::iso9660
Description: Debian Live initramfs generator
Casper provides an initramfs generator suited for booting a Debian Live systems
Package: casper
Architecture: any
-Depends: initramfs-tools (>= 0.40), user-setup, sudo
-Conflicts: usplash (<< 0.4-0)
+Depends: initramfs-tools (>= 0.40), user-setup, sudo, lsb-base (>= 3.0-6)
+Conflicts: usplash (<< 0.3-0)
Recommends: live-package
-Suggests: dmsetup, squashft-tools, genext2fs
+Suggests: squashfs-tools, genext2fs
Tag: admin::boot, admin::filesystem, implemented-in::shell, protocol::smb, role::plugin, scope::utility, special::completely-tagged, works-with-format::iso9660
Description: Debian Live initramfs generator
Casper provides an initramfs generator suited for booting a Debian Live systems
Architecture: any
Section: misc
Priority: extra
-Depends: initramfs-tools (>= 0.40ubuntu11), dmsetup, user-setup, sudo
+Depends: initramfs-tools (>= 0.40ubuntu11), user-setup, sudo
Conflicts: usplash (<< 0.4-27)
Tag: admin::boot, admin::filesystem, implemented-in::shell, protocol::smb, role::plugin, scope::utility, special::completely-tagged, works-with-format::iso9660
Description: Run a "live" preinstalled system from read-only media
.B casper-snapshot
.RB [\| \-c \||\| \-\-cow
.IR DIRECTORY \|]
-.RB [\| \-d \||\| \-\-destination
-.IR DIRECTORY \||\| FILE \|]
+.RB [\| \-d \||\| \-\-device
+.IR DEVICE \|]
+.RB [\| \-e \||\| \-\-exclude\-list
+.IR FILE \|]
.RB [\| \-o \||\| \-\-output
.IR FILE \|]
.RB [\| \-t \||\| \-\-type
.IR TYPE \|]
.PP
-.B make-live
+.B casper-snapshot
+.RB \-r \||\| \-\-resync\-string
+.IR STRING
+.br
+.B casper-snapshot
.RB \-h \||\| \-\-help
.br
-.B make-live
+.B casper-snapshot
.RB \-u \||\| \-\-usage
.br
-.B make-live
+.B casper-snapshot
.RB \-v \||\| \-\-version
.SH DESCRIPTION
-Casper-snapshot is a script useful to build the right types of persistent image files supported by casper.
+Casper-snapshot is a script useful to build the right types of persistent image files supported by casper, it is also used on exit by the casper init script to resync the boot-found snapshots devices.
.SH OPTIONS
.TP
specifies the input directory to be cloned in the image file.
This parameters often does not need to be specified as the default of "/cow" for it should be right for most uses, however it could be handy to specify "/home" and type ext2 for the type to prepare an image file suited to be directly mounted by casper as home.
.TP
-.BI "\-d, \-\-destination" DIRECTORY
+.BI "\-d, \-\-device" DEVICE
+the device on where the media which the snapshot/persistence file/partition will be put. If not specified a tmpfs will be used and linked on user's desktop to move it where he/her wants. If the device has not a filesystem on it, an ext2 fs will be created in it and labeled like --output options or with a sane default.
+.TP
+.BI "\-e, \-\-exclude\-list" FILE
+you could pass a list of filenames/path that should not be saved. This exclude list will be remebered on the target snapshotting media for reuse.
.TP
.BI "\-o, \-\-output" FILE
+the filename/label to be used for the output file/partition, if left blank it could search for a proper file on the device or use the whole partition.
+.TP
+.BI "\-r, \-\-resync\-string" STRING
+internally used on resyncs.
.TP
.BI "\-t, \-\-type" TYPE
.TH CASPER 7 "Thu, 28 Sep 2006" "1.69" "Initramfs-tools hook"
.SH NAME
-casper \- an hook for initramfs-tools to boot live systems.
+casper \- a hook for initramfs-tools to boot live systems.
.SH SYNOPSIS
.B BOOT=casper
.B casper-getty
This enable a special serial login shell (experimental).
.TP
-.BI "host=" HOSTNAME " , userfullname=" USERFULLNAME " , username=" USERNAME
+.BI "hostname=" HOSTNAME " , userfullname=" USERFULLNAME " , username=" USERNAME
Those parameters lets you override values read from the config file.
.TP
-.BI "keyb=" KEYBOARD " | kbd-chooser/method=" KEYBOARD "; console-setup/layoutcode=" LAYOUT ", console-setup/variantcode=" VARIANT
-Configure the running keyboard as specified, if this one misses casper behave as "keyb=us" was specified. (It will be interfered from "locale=" somewhere in the future). You could also specify layout and variant (no defaults).
+.BI "keyb=" KEYBOARD " | kbd-chooser/method=" KEYBOARD " ; console-setup/layoutcode=" LAYOUT " , console-setup/variantcode=" VARIANT " , console-setup/modelcode" CODE
+Configure the running keyboard as specified, if this one misses casper behave as "keyb=us" was specified. It will be interfered from "locale=" if locale is only 2 lowecase letters as a special case. You could also specify layout, variant, and code (no defaults).
.TP
.BI ip= IFACE,ADDRESS,NETMASK,GATEWAY [ :IFACE,ADDRESS,NETMASK,GATEWAY "]*"
Let you specify the name(s) and the options of the interface(s) that should be configured at boot time. Do not specify it if you want to use dhcp (default).
This way dhcp and static configuration is just skipped and the system will use the (must be) media-preconfigured /etc/network/interfaces instead.
.TP
.BI "locale=" LOCALE " | debian-installer/locale=" LOCALE
-Configure the running locale as specified, if not present the live-media rootfs configured locale will be used and if also this one misses casper behave as "locale=en_US.UTF-8" was specified.
+Configure the running locale as specified, if not present the live-media rootfs configured locale will be used and if also this one misses casper behave as "locale=en_US.UTF-8" was specified. If only 2 lowercase letter are specified (like "it"), the "maybe wanted" locale is generated (like it:IT.UTF-8), in this case if also "keyb=" is unspecified is set with those 2 lowercase letters (keyb=it).
.TP
.BI live-media= DEVICE " | bootfrom=" DEVICE
If you specify one of this two equivalent forms, casper will try first to look on this device for the "/casper" directory where it should lie the read-only root filesystem, if it did not find it, the normal scan for block devices will be performed.
cp /etc/casper.conf ${DESTDIR}/etc
fi
-# Needed for devmapper
-if [ -e /sbin/dmsetup ]; then
- manual_add_modules cloop
- copy_exec /sbin/blockdev /sbin
- copy_exec /sbin/dmsetup /sbin
- manual_add_modules dm-snapshot
-fi
-
# We need losetup
copy_exec /sbin/losetup /sbin
copy_exec /usr/lib/casper/casper-md5check /bin
cp /usr/share/initramfs-tools/scripts/casper-functions $DESTDIR/scripts
+cp /usr/share/initramfs-tools/scripts/casper-helpers $DESTDIR/scripts
auto_add_modules net
root_persistence="casper-rw"
home_persistence="home-rw"
-root_snapshot="casper-sn"
-home_snapshot="home-sn"
+root_snapshot_label="casper-sn"
+home_snapshot_label="home-sn"
USERNAME="casper"
USERFULLNAME="Live session user"
-HOST="live"
+HOSTNAME="live"
BUILD_SYSTEM="Debian"
mkdir -p $mountpoint
[ -f /etc/casper.conf ] && . /etc/casper.conf
+export USERNAME USERFULLNAME HOSTNAME BUILD_SYSTEM
-export USERNAME USERFULLNAME HOST BUILD_SYSTEM
-
-if [ "${BUILD_SYSTEM}" == "Ubuntu" ]; then
- MP_QUIET="-Q"
-else
- MP_QUIET="-q"
-fi
+. /scripts/casper-helpers
parse_cmdline ()
{
export USERFULLNAME=${x#userfullname=}
export CASPERCONF="changed"
;;
- host=*)
- export HOST=${x#host=}
+ hostname=*)
+ export HOSTNAME=${x#hostname=}
export CASPERCONF="changed"
;;
username=*)
kbd-chooser/method=*)
export KBD=${x#kbd-chooser/method=} ;;
keyb=*)
- export KBD=${x#kbd=} ;;
+ export KBD=${x#keyb=} ;;
console-setup/layoutcode=*)
export CSLAYOUT=${x#console-setup/layoutcode=} ;;
console-setup/variantcode=*)
is_casper_path() {
path=$1
if [ -d "$path/casper" ]; then
- if [ "$(echo $path/casper/*.cloop)" != "$path/casper/*.cloop" ] ||
- [ "$(echo $path/casper/*.squashfs)" != "$path/casper/*.squashfs" ] ||
+ if [ "$(echo $path/casper/*.squashfs)" != "$path/casper/*.squashfs" ] ||
[ "$(echo $path/casper/*.ext2)" != "$path/casper/*.ext2" ] ||
[ "$(echo $path/casper/*.dir)" != "$path/casper/*.dir" ]; then
return 0
return 1
}
-subdevices() {
- sysblock=$1
- r=""
- for dev in "${sysblock}" "${sysblock}"/*; do
- if [ -e "${dev}/dev" ]; then
- r="${r} ${dev}"
- fi
- done
- echo ${r}
-}
-
get_backing_device() {
case "$1" in
- *.cloop)
- echo $(setup_loop "$1" "cloop" "/sys/block/cloop*")
- ;;
*.squashfs|*.ext2)
echo $(setup_loop "$1" "loop" "/sys/block/loop*")
;;
mount_images_in_directory() {
directory="$1"
rootmnt="$2"
- if match_files_in_dir "$directory/casper/*.cloop"; then
- # Let's hope there's just one matching *.cloop... FIXME
- setup_devmapper $(get_backing_device "$directory/casper/*.cloop") "$rootmnt"
- elif match_files_in_dir "$directory/casper/*.squashfs" ||
+ if match_files_in_dir "$directory/casper/*.squashfs" ||
match_files_in_dir "$directory/casper/*.ext2" ||
match_files_in_dir "$directory/casper/*.dir"; then
setup_unionfs "$directory/casper" "$rootmnt"
fi
}
-sys2dev() {
- sysdev=${1#/sys}
- echo "/dev/$(udevinfo -q name -p ${sysdev} 2>/dev/null|| echo ${sysdev##*/})"
-}
-
-setup_loop() {
- local fspath=$1
- local module=$2
- local pattern=$3
-
- modprobe "${MP_QUIET}" -b "$module"
- udevsettle
-
- for loopdev in $pattern; do
- if [ "$(cat $loopdev/size)" -eq 0 ]; then
- dev=$(sys2dev "${loopdev}")
- losetup "$dev" "$fspath"
- echo "$dev"
- return 0
- fi
- done
- panic "No loop devices available"
-}
-
get_fstype() {
local FSTYPE
local FSSIZE
/lib/udev/vol_id -t $1 2>/dev/null
}
-setup_devmapper() {
- backdev="$1"
- rootmnt="$2"
-
- modprobe "${MP_QUIET}" -b dm-mod
- COW_DEVICE=/dev/ram1
- COW_NAME="casper-cow"
-
- BACKING_FILE_SIZE=$(blockdev --getsize "$backdev")
- MAX_COW_SIZE=$(blockdev --getsize "$COW_DEVICE")
- CHUNK_SIZE=8 # sectors
-
- if [ -z "$COW_SIZE" -o "$COW_SIZE" -gt "$MAX_COW_SIZE" ]; then
- COW_SIZE=$MAX_COW_SIZE
- fi
-
- echo "0 $COW_SIZE linear $COW_DEVICE 0" | dmsetup create $COW_NAME
-
- echo "0 $BACKING_FILE_SIZE snapshot $backdev /dev/mapper/$COW_NAME p $CHUNK_SIZE" | \
- dmsetup create casper-snapshot
- if [ "$(get_fstype $backdev)" = "unknown" ]; then
- panic "Unknown file system type on $backdev"
- fi
- mount -t $(get_fstype "$backdev") /dev/mapper/casper-snapshot $rootmnt || panic "Can not mount /dev/mapper/casper/snapshot on $rootmnt"
-
- mkdir -p "$rootmnt/rofs"
- echo "0 $BACKING_FILE_SIZE linear $backdev 0" | dmsetup create casper-backing
- mount -t $(get_fstype "$backdev") /dev/mapper/casper-backing "$rootmnt/rofs"
-}
-
is_nice_device() {
sysfs_path="${1#/sys}"
if /lib/udev/path_id "${sysfs_path}" | grep -E -q "ID_PATH=(usb|pci-[^-]*-[ide|scsi|usb])"; then
return 1
}
-where_is_mounted() {
- device=$1
- if grep -q "^$device " /proc/mounts; then
- grep "^$device " /proc/mounts | read d mountpoint rest
- echo $mountpoint
- return 0
- fi
- return 1
-}
-
-used_fs_size ()
-{
- # Returns used fs kbytes + 5% more
- # You could pass a block device as $1 or the mount point as $2
-
- dev="${1}"
- mountp="${2}"
-
- if [ -z "${mountp}" ]; then
- mountp=$(where_is_mounted "${dev}")
- if [ "$?" -gt 0 ]; then
- mountp=/mnt/tmp_fs_size
- mkdir -p "${mountp}"
- mount -t $(get_fstype "${dev}") -o ro "${dev}" "${mountp}"
- doumount=1
- fi
- fi
-
- size=$(du -ks ${mountp} | cut -f1)
- size=$(expr ${size} + ${size}/20 ) # FIXME: 5% more to be sure
- needed_space=$(expr ${size} * 1024)
-
- if [ ! -z "${doumount}" ]; then
- umount "${mountp}"
- rmdir "${mountp}"
- fi
- echo "${needed_space}"
-}
-
copy_live_to() {
copyfrom="${1}"
copytodev="${2}"
return 0
}
-try_mount ()
-{
- dev="${1}"
- mountp="${2}"
- opts="${3}"
-
- if where_is_mounted ${dev} > /dev/null; then
- mount -o remount,"${opts}" ${dev} $(where_is_mounted ${dev}) || panic "Remounting failed"
- mount -o bind $(where_is_mounted ${dev}) ${mountp} || panic "Cannot bind-mount"
- else
- mount -t $(get_fstype "${dev}") -o "${opts}" "${dev}" "${mountp}" || panic "Cannot mount ${dev} on ${mountp}"
- fi
-}
-
-find_cow_device() {
- pers_label="${1}"
- cow_backing="/${pers_label}-backing"
- for sysblock in $(echo /sys/block/* | tr ' ' '\n' | grep -v loop); do
- for dev in $(subdevices "${sysblock}"); do
- devname=$(sys2dev "${dev}")
- if [ "$(/lib/udev/vol_id -l $devname 2>/dev/null)" = "${pers_label}" ]; then
- echo "$devname"
- return
- elif [ "$(get_fstype ${devname})" = "vfat" ]; then # FIXME: all supported block devices should be scanned
- mkdir -p "${cow_backing}"
- try_mount "${devname}" "${cow_backing}" "rw"
- if [ -e "${cow_backing}/${pers_label}" ]; then
- echo $(setup_loop "${cow_backing}/${pers_label}" "loop" "/sys/block/loop*")
- return 0
- else
- umount ${cow_backing}
- fi
- fi
- done
- done
-}
-
-find_files()
-# return the first of $filenames found on vfat and ext2 devices
-# FIXME: merge with above function
-{
- filenames="${1}"
- snap_backing="/snap-backing"
- for sysblock in $(echo /sys/block/* | tr ' ' '\n' | grep -v loop); do
- for dev in $(subdevices "${sysblock}"); do
- devname=$(sys2dev "${dev}")
- devfstype="$(get_fstype ${devname})"
- if [ "${devfstype}" = "vfat" ] || [ "${devfstype}" = "ext2" ] ; then # FIXME: all supported block devices should be scanned
- mkdir -p "${snap_backing}"
- try_mount "${devname}" "${snap_backing}" "ro"
- for filename in ${filenames}; do
- if [ -e "${snap_backing}/${filename}" ]; then
- echo "${devname} ${snap_backing} ${filename}"
- return 0
- fi
- done
- umount ${snap_backing}
- fi
- done
- done
-}
-
do_netmount() {
rc=1
todir="${2}"
snap_type="${3}"
- size=$(used_fs_size "${fromdev}")
+ #size=$(used_fs_size "${fromdev}")
if [ -b "${fromdev}" ]; then
# look for free mem
- if [ ! -z "${HOMEMOUNTED}" ] && [ "${snap_type}" = "HOME" ]; then
- freespace="$(df -k ${copytodev} | grep -s ${copytodev} | awk '{print $4}')"
+ if [ -n "${HOMEMOUNTED}" -a "${snap_type}" = "HOME" ]; then
+ todev=$(cat /proc/mounts | grep -s " $(base_path ${todir}) " | awk '{print $1}' )
+ freespace=$(df -k | grep -s ${todev} | awk '{print $4}')
else
freespace=$( expr $(awk '/MemFree/{print $2}' /proc/meminfo) + $( cat /proc/meminfo | grep Cached | head -n 1 | awk '/Cached/{print $2}' - ))
fi
+
tomount="/mnt/tmpsnap"
- mkdir -p "${tomount}"
- mount -t $(get_fstype "${fromdev}") -o ro "${fromdev}" "${tomount}"
- cp -a "${tomount}"/* ${todir}
- umount "${tomount}"
+ if [ ! -d "${tomount}" ] ; then
+ mkdir -p "${tomount}"
+ fi
- if echo ${fromdev} | grep -qs loop; then
- losetup -d "${fromdev}"
+ fstype=$(get_fstype "${fromdev}")
+ if [ -n "${fstype}" ]; then
+ # Copying stuff...
+ mount -t "${fstype}" -o ro "${fromdev}" "${tomount}"
+ cp -a "${tomount}"/* ${todir}
+ umount "${tomount}"
+ else
+ log_warning_msg "Unrecognized fstype: ${fstype} on ${fromdev}:${snap_type}"
fi
+ rmdir "${tomount}"
+ if echo ${fromdev} | grep -qs loop; then
+ losetup -d "${fromdev}"
+ fi
return 0
else
return 1
try_snap ()
{
+ # Look for $snap_label.* in block devices and copy the contents to $snap_mount
+ # and remember the device and filename for resync on exit in casper.init
+
snap_label="${1}"
snap_mount="${2}"
snap_type="${3}"
- snapdata=$(find_files "${snap_label}.squashfs ${snap_label}.cpio.gz ${snap_label}.cpz ${snap_label}.gz")
+ snapdata=$(find_files "${snap_label}.squashfs ${snap_label}.cpio.gz ${snap_label}.ext2")
if [ ! -z "${snapdata}" ]; then
- snapdev=$(echo ${snapdata} | cut -f1 -d ' ')
- snapback=$(echo ${snapdata} | cut -f2 -d ' ')
- snapfile=$(echo ${snapdata} | cut -f3 -d ' ')
- if echo "${snapfile}" | grep -qs "squashfs" ; then
- # squashfs snapshot
- if ! do_snap_copy $( get_backing_device "${snapback}/${snapfile}" ) "${snap_mount}" "${snap_type}"; then
+ snapdev="$(echo ${snapdata} | cut -f1 -d ' ')"
+ snapback="$(echo ${snapdata} | cut -f2 -d ' ')"
+ snapfile="$(echo ${snapdata} | cut -f3 -d ' ')"
+ if echo "${snapfile}" | grep -qs '\(squashfs\|ext2\)'; then
+ # squashfs or ext2 snapshot
+ dev=$(get_backing_device "${snapback}/${snapfile}")
+ if ! do_snap_copy "${dev}" "${snap_mount}" "${snap_type}"; then
log_warning_msg "Impossible to include the ${snapfile} Snapshot"
return 1
fi
else
# cpio.gz snapshot
- if ! (cd "${snap_mount}" && zcat "${snapback}/${snapfile}" | cpio -i -u -d ) ; then
+ if ! (cd "${snap_mount}" && zcat "${snapback}/${snapfile}" | cpio -i -u -d 2>/dev/null) ; then
log_warning_msg "Impossible to include the ${snapfile} Snapshot"
return 1
fi
fi
umount "${snapback}"
- else # try pure snapshot device better elif.. rework all that routine
- if ! do_snap_copy $(find_cow_device "${snap_label}") "${snap_mount}" "${snap_type}"; then
+ else
+ dev=$(find_cow_device "${snap_label}")
+ if [ -b ${dev} ]; then
+ if echo "${dev}" | grep -qs loop; then
+ # strange things happens, user confused?
+ snaploop=$( losetup ${dev} | awk '{print $3}' | tr -d '()' )
+ snapfile=$(basename ${snaploop})
+ snapdev=$(cat /proc/mounts | awk '{print $2,$1}' | grep -es "^$( dirname ${snaploop} )" | cut -f2 -d ' ')
+ else
+ snapdev="${dev}"
+ fi
+ if ! do_snap_copy "${dev}" "${snap_mount}" "${snap_type}" ; then
+ log_warning_msg "Impossible to include the ${snap_label} Snapshot"
+ return 1
+ else
+ if [ -n "${snapfile}" ]; then
+ # it was a loop device, user confused
+ umount ${snapdev}
+ fi
+ fi
+ else
log_warning_msg "Impossible to include the ${snap_label} Snapshot"
return 1
fi
fi
- echo "export ${snap_type}SNAP=${snapdev}:${snapfile}" >> /etc/casper.conf # for resync on reboot/halt
+ echo "export ${snap_type}SNAP="${snap_mount}":${snapdev}:${snapfile}" >> /etc/casper.conf # for resync on reboot/halt
return 0
}
-do_others_persistences ()
-{
- # directly mount /home
- # FIXME: add a custom mounts configurable system
- homecow=$(find_cow_device "${home_persistence}" )
- if [ -b "${homecow}" ]; then
- mount ${homecow} -t $(get_fstype "${homecow}") -o rw "${rootmnt}/home"
- export HOMEMOUNTED=1
- else
- [ "$quiet" != "y" ] && log_warning_msg "Unable to find the persistent home medium"
- fi
-
- # Look for snapshots to copy in
- try_snap "${root_snapshot}" "${rootmnt}" "ROOT"
- try_snap "${home_snapshot}" "${rootmnt}/home" "HOME"
-}
-
setup_unionfs() {
image_directory="$1"
rootmnt="$2"
cow_fstype="tmpfs"
# Looking for "${root_persistence}" device or file
- if [ ! -z "${PERSISTENT}" ]; then
+ if [ -n "${PERSISTENT}" ]; then
cowprobe=$(find_cow_device "${root_persistence}")
if [ -b "${cowprobe}" ]; then
cowdevice=${cowprobe}
mount -t unionfs -o dirs=/cow=rw:$rofsstring unionfs "$rootmnt" || panic "Unionfs mount failed"
# Adding other custom mounts
- if [ ! -z "${PERSISTENT}" ]; then
- do_others_persistences
+ if [ -n "${PERSISTENT}" ]; then
+ # directly mount /home
+ # FIXME: add a custom mounts configurable system
+ homecow=$(find_cow_device "${home_persistence}" )
+ if [ -b "${homecow}" ]; then
+ mount -t $(get_fstype "${homecow}") -o rw "${homecow}" "${rootmnt}/home"
+ export HOMEMOUNTED=1 # used to proper calculate free space in do_snap_copy()
+ else
+ [ "$quiet" != "y" ] && log_warning_msg "Unable to find the persistent home medium"
+ fi
+ # Look for other snapshots to copy in
+ try_snap "${root_snapshot_label}" "${rootmnt}" "ROOT"
+ try_snap "${home_snapshot_label}" "${rootmnt}/home" "HOME"
fi
- if [ ! -z "${SHOWMOUNTS}" ]; then
+ if [ -n "${SHOWMOUNTS}" ]; then
for d in ${rofslist}; do
mkdir -p "${rootmnt}/casper/${d##*/}"
case d in
fi
# shows cow fs on /cow for use by casper-snapshot
- mkdir -p "$rootmnt/cow"
- mount -o bind /cow "$rootmnt/cow"
+ mkdir -p "${rootmnt}/cow"
+ mount -o bind /cow "${rootmnt}/cow"
}
check_dev ()
#!/bin/sh
PREREQ=""
+DESCRIPTION="Copying config on real root fs..."
+
+. /scripts/casper-functions
prereqs()
{
;;
esac
-
+log_begin_msg "$DESCRIPTION"
+
if [ -f /etc/casper.conf ] ; then
if [ ! -z "${CASPERCONF}" ]; then
# Updating casper.conf
sed -i -e 's/\(USERNAME="\).*"/\1'"${USERNAME}"'"/g' \
-e 's/\(USERFULLNAME="\).*"/\1'"${USERFULLNAME}"'"/g' \
- -e 's/\(HOST="\).*"/\1'"${HOST}"'"/g' /etc/casper.conf
+ -e 's/\(HOSTNAME="\).*"/\1'"${HOSTNAME}"'"/g' /etc/casper.conf
fi
cp -p /etc/casper.conf /root/etc/casper.conf
cat <<EOF >/root/etc/casper.conf
export USERNAME="$USERNAME"
export USERFULLNAME="$USERFULLNAME"
-export HOST="$HOST"
+export HOSTNAME="$HOSTNAME"
EOF
fi
grep_file=/root/etc/environment
fi
-if [ ! -z "${grep_file}" ]; then
+if [ -n "${grep_file}" ]; then
locale=$(grep -s 'LANG=' ${grep_file} | sed s/'LANG='// | tr -d '"' )
else
grep_file=/root/etc/default/locale
fi
if [ "${set_locale}" ]; then
+ if echo "${locale}" | grep -sqE '^[[:lower:]]{2}$' ; then
+ # input is like "locale=it", so we will convert and setup also the keyboard
+ if [ -z "${KBD}" ]; then
+ # FIXME: look if this keyb is supported
+ KBD="${locale}"
+ fi
+ uploc=$(echo "${locale}" | tr '[a-z]' '[A-Z]')
+ locale="${locale}_${uploc}.UTF-8"
+ fi
LANG=$(grep "^${locale}" /root/usr/share/i18n/SUPPORTED | grep UTF-8 |sed -e 's, .*,,' -e q)
- printf 'LANG="%s"\n' "${LANG}" >> "${grep_file}"
+
+ if [ -z "${LANG}" ]; then
+ log_warning_message "Locale ${locale} is unsupported."
+ fi
+
if [ "${BUILD_SYSTEM}" == "Debian" ]; then
+ printf 'LANG=%s\n' "${LANG}" >> "${grep_file}"
+ printf '%s UTF-8\n' "${LANG}" >> /root/etc/locale.gen
chroot /root /usr/sbin/locale-gen
else
+ printf 'LANG="%s"\n' "${LANG}" > "${grep_file}"
chroot /root /usr/sbin/locale-gen "${LANG}"
fi
fi
log_begin_msg "$DESCRIPTION"
-echo "$HOST" > /root/etc/hostname
+echo "$HOSTNAME" > /root/etc/hostname
cat > /root/etc/hosts <<EOF
127.0.0.1 localhost
-127.0.1.1 $HOST
+127.0.1.1 $HOSTNAME
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
csmodel=
# commandline
-if [ ! -z "${KBD}" ]; then
+if [ -n "${KBD}" ]; then
kbd="${KBD}"
fi
-if [ ! -z "${CSLAYOUT}" ]; then
+if [ -n "${CSLAYOUT}" ]; then
cslayout="${CSLAYOUT}"
fi
-if [ ! -z "${CSVARIANT}" ]; then
+if [ -n "${CSVARIANT}" ]; then
csvariant="${CSVARIANT}"
fi
-if [ ! -z "${CSMODEL}" ]; then
+if [ -n "${CSMODEL}" ]; then
csmodel="${CSMODEL}"
fi
--- /dev/null
+## Casper helper functions, used by casper on boot and by casper-snapshot
+
+if [ "${BUILD_SYSTEM}" == "Ubuntu" ]; then
+ MP_QUIET="-Q"
+else
+ MP_QUIET="-q"
+fi
+
+sys2dev() {
+ sysdev=${1#/sys}
+ echo "/dev/$(udevinfo -q name -p ${sysdev} 2>/dev/null|| echo ${sysdev##*/})"
+}
+
+subdevices() {
+ sysblock=$1
+ r=""
+ for dev in "${sysblock}" "${sysblock}"/*; do
+ if [ -e "${dev}/dev" ]; then
+ r="${r} ${dev}"
+ fi
+ done
+ echo ${r}
+}
+
+where_is_mounted() {
+ device=$1
+ if grep -q "^$device " /proc/mounts; then
+ grep "^$device " /proc/mounts | read d mountpoint rest
+ echo $mountpoint
+ return 0
+ fi
+ return 1
+}
+
+lastline() {
+ while read lines ; do
+ line=${lines}
+ done
+ echo "${line}"
+}
+
+base_path ()
+{
+ testpath="${1}"
+ mounts="$(awk '{print $2}' /proc/mounts)"
+ testpath="$(busybox realpath ${testpath})"
+
+ while true ; do
+ if echo "${mounts}" | grep -qs "^${testpath}" ; then
+ set -- `echo "${mounts}" | grep "^${testpath}" | lastline`
+ echo ${1}
+ break
+ else
+ testpath=`dirname $testpath`
+ fi
+ done
+}
+
+used_fs_size ()
+{
+ # Returns used fs kbytes + 5% more
+ # You could pass a block device as $1 or the mount point as $2
+
+ dev="${1}"
+ mountp="${2}"
+
+ if [ -z "${mountp}" ]; then
+ mountp=$(where_is_mounted "${dev}")
+ if [ "$?" -gt 0 ]; then
+ mountp=/mnt/tmp_fs_size
+ mkdir -p "${mountp}"
+ mount -t $(get_fstype "${dev}") -o ro "${dev}" "${mountp}"
+ doumount=1
+ fi
+ fi
+
+ size=$(du -ks ${mountp} | cut -f1)
+ size=$(expr ${size} + ${size}/20 ) # FIXME: 5% more to be sure
+ needed_space=$(expr ${size} * 1024)
+
+ if [ ! -z "${doumount}" ]; then
+ umount "${mountp}"
+ rmdir "${mountp}"
+ fi
+ echo "${needed_space}"
+}
+
+setup_loop() {
+ local fspath=$1
+ local module=$2
+ local pattern=$3
+
+ modprobe "${MP_QUIET}" -b "$module"
+ udevsettle
+
+ for loopdev in $pattern; do
+ if [ "$(cat $loopdev/size)" -eq 0 ]; then
+ dev=$(sys2dev "${loopdev}")
+ losetup "$dev" "$fspath"
+ echo "$dev"
+ return 0
+ fi
+ done
+ panic "No loop devices available"
+}
+
+try_mount ()
+{
+ dev="${1}"
+ mountp="${2}"
+ opts="${3}"
+
+ if where_is_mounted ${dev} > /dev/null; then
+ mount -o remount,"${opts}" ${dev} $(where_is_mounted ${dev}) || panic "Remounting failed"
+ mount -o bind $(where_is_mounted ${dev}) ${mountp} || panic "Cannot bind-mount"
+ else
+ mount -t $(get_fstype "${dev}") -o "${opts}" "${dev}" "${mountp}" || panic "Cannot mount ${dev} on ${mountp}"
+ fi
+}
+
+find_cow_device() {
+ pers_label="${1}"
+ cow_backing="/${pers_label}-backing"
+ for sysblock in $(echo /sys/block/* | tr ' ' '\n' | grep -v loop); do
+ for dev in $(subdevices "${sysblock}"); do
+ devname=$(sys2dev "${dev}")
+ if [ "$(/lib/udev/vol_id -l $devname 2>/dev/null)" = "${pers_label}" ]; then
+ echo "$devname"
+ return
+ elif [ "$(get_fstype ${devname})" = "vfat" ]; then # FIXME: all supported block devices should be scanned
+ mkdir -p "${cow_backing}"
+ try_mount "${devname}" "${cow_backing}" "rw"
+ if [ -e "${cow_backing}/${pers_label}" ]; then
+ echo $(setup_loop "${cow_backing}/${pers_label}" "loop" "/sys/block/loop*")
+ return 0
+ else
+ umount ${cow_backing}
+ fi
+ fi
+ done
+ done
+}
+
+find_files()
+# return the first of $filenames found on vfat and ext2 devices
+# FIXME: merge with above function
+{
+ filenames="${1}"
+ snap_backing="/snap-backing"
+ for sysblock in $(echo /sys/block/* | tr ' ' '\n' | grep -v loop); do
+ for dev in $(subdevices "${sysblock}"); do
+ devname=$(sys2dev "${dev}")
+ devfstype="$(get_fstype ${devname})"
+ if [ "${devfstype}" = "vfat" ] || [ "${devfstype}" = "ext2" ] ; then # FIXME: all supported block devices should be scanned
+ mkdir -p "${snap_backing}"
+ try_mount "${devname}" "${snap_backing}" "ro"
+ for filename in ${filenames}; do
+ if [ -e "${snap_backing}/${filename}" ]; then
+ echo "${devname} ${snap_backing} ${filename}"
+ return 0
+ fi
+ done
+ umount ${snap_backing}
+ fi
+ done
+ done
+}
+
+