+ *)
+ unionmountopts="-o noatime,${noxino_opt},dirs=${unionrw}=${rw_opt}"
+ if [ -n "${unionro1}" ]
+ then
+ unionmountopts="${unionmountopts}:${unionro1}=${ro_opt}"
+ fi
+ if [ -n "${unionro2}" ]
+ then
+ unionmountopts="${unionmountopts}:${unionro2}=${ro_opt}"
+ fi
+ mount -t ${UNIONTYPE} ${unionmountopts} ${UNIONTYPE} "${unionmountpoint}"
+ ;;
+ esac
+}
+
+get_custom_mounts ()
+{
+ # Side-effect: leaves $devices with live.persist mounted in ${rootmnt}/live/persistent
+ # Side-effect: prints info to file $custom_mounts
+
+ local custom_mounts=${1}
+ shift
+ local devices=${@}
+
+ local bindings="/tmp/bindings.list"
+ local links="/tmp/links.list"
+ rm -rf ${bindings} ${links} 2> /dev/null
+
+ for device in ${devices}
+ do
+ if [ ! -b "${device}" ]
+ then
+ continue
+ fi
+
+ local device_name="$(basename ${device})"
+ local backing=$(mount_persistent_media ${device})
+ if [ -z "${backing}" ]
+ then
+ continue
+ fi
+
+ local include_list="${backing}/${persistence_list}"
+ if [ ! -r "${include_list}" ]
+ then
+ continue
+ fi
+
+ if [ -n "${DEBUG}" ] && [ -e "${include_list}" ]
+ then
+ cp ${include_list} ${rootmnt}/live/persistent/${persistence_list}.${device_name}
+ fi
+
+ while read source dest options # < ${include_list}
+ do
+ if echo ${source} | grep -qe "^[[:space:]]*\(#.*\)\?$"
+ then
+ # skipping empty or commented lines
+ continue
+ fi
+
+ if [ -z "${dest}" ]
+ then
+ dest="${source}"
+ fi
+
+ if trim_path ${source} | grep -q -e "^[^/]" -e "^\(.*/\)\?\.\.\?\(/.*\)\?$"
+ then
+ log_warning_msg "Skipping unsafe custom mount with source ${source}: the source must be an absolute path w.r.t. the persistent media root and cannot contain \".\" or \"..\""
+ continue
+ fi
+
+ if trim_path ${dest} | grep -q -e "^[^/]" -e "^/$" -e "^/live\(/.*\)\?$" -e "^/\(.*/\)\?\.\.\?\(/.*\)\?$"
+ then
+ log_warning_msg "Skipping unsafe custom mount with desination ${dest}: the destination must be an absolute path containing neither \".\" nor \"..\", and cannot be /live (or any sub-directory therein) or / (for the latter, use ${root_overlay_label}-type persistence instead)"
+ continue
+ fi
+
+ for opt in $(echo ${options} | tr ',' ' ');
+ do
+ case "${opt}" in
+ linkfiles|union)
+ ;;
+ *)
+ log_warning_msg "Skipping custom mount with unkown option: ${opt}"
+ continue 2
+ ;;
+ esac
+ done
+
+ # ensure that no multiple-/ occur in paths
+ local full_source="$(trim_path ${backing}/${source})"
+ local full_dest="$(trim_path ${rootmnt}/${dest})"
+ if echo ${options} | grep -qe "\<linkfiles\>";
+ then
+ echo "${device} ${full_source} ${full_dest} ${options}" >> ${links}
+ else
+ echo "${device} ${full_source} ${full_dest} ${options}" >> ${bindings}
+ fi
+ done < ${include_list}
+ done
+
+ # We sort the list according to destination so we're sure that
+ # we won't hide a previous mount. We also ignore duplicate
+ # destinations in a more or less arbitrary way.
+ [ -e "${bindings}" ] && sort -k3 -sbu ${bindings} >> ${custom_mounts} && rm ${bindings}
+
+ # After all mounts are considered we add symlinks so they
+ # won't be hidden by some mount.
+ [ -e "${links}" ] && sort -k3 -sbu ${links} >> ${custom_mounts} && rm ${links}
+}
+
+activate_custom_mounts ()
+{
+ local custom_mounts="${1}" # the ouput from get_custom_mounts()
+ local used_devices=""
+
+ while read device source dest options # < ${custom_mounts}
+ do
+ local opt_linkfiles=""
+ local opt_union=""
+ for opt in $(echo ${options} | tr ',' ' ');
+ do
+ case "${opt}" in
+ linkfiles)
+ opt_linkfiles="yes"
+ ;;
+ union)
+ opt_union="yes"
+ ;;
+ esac
+ done
+
+ if [ -n "${opt_linkfiles}" ] && [ -n "${opt_union}" ]
+ then
+ log_warning_msg "Skipping custom mount ${dest} with options ${options}: \"linkfiles\" and \"union\" are mutually exclusive options"
+ fi
+
+ if [ -n "$(what_is_mounted_on "${dest}")" ]
+ then
+ log_warning_msg "Skipping custom mount ${source} on ${dest}: $(what_is_mounted_on "${dest}") is already mounted there"
+ continue
+ fi
+
+ # FIXME: we don't handle already existing
+ # non-directory files in the paths of both $source and
+ # $dest.
+
+ if [ ! -d "${dest}" ]
+ then
+ # if ${dest} is in /home/$user, try fixing
+ # proper ownership
+ # FIXME: this should really be handled by
+ # live-config since we don't know for sure
+ # which uid a certain user has until then
+ if trim_path ${dest} | grep -qe "^${rootmnt}/*home/[^/]\+"
+ then
+ path="/"
+ for dir in $(echo ${dest} | sed -e 's|/\+| |g')
+ do
+ path=${path}/${dir}
+ if [ ! -e ${path} ]
+ then
+ mkdir -p ${path}
+ # assume that the intended user is the first, which is usually the case
+ chown 1000:1000 ${path}
+ fi
+ done
+ else
+ mkdir -p ${dest}
+ fi
+ fi
+
+ # if ${source} doesn't exist on our persistent media
+ # we bootstrap it with $dest from the live filesystem.
+ # this both makes sense and is critical if we're
+ # dealing with /etc or other system dir.
+ if [ ! -d "${source}" ]
+ then
+ if [ -n "${PERSISTENT_READONLY}" ]
+ then
+ continue
+ elif [ -n "${opt_union}" ] || [ -n "${opt_linkfiles}" ]
+ then
+ # unions and don't need to be bootstrapped
+ # linkfiles dirs can't be bootstrapped in a sensible way
+ mkdir "${source}"
+ chown --reference "${dest}" "${source}"
+ chmod --reference "${dest}" "${source}"
+ else
+ # ensure that $dest is not copied *into* $source
+ mkdir -p "$(dirname ${source})"
+ cp -a "${dest}" "${source}"
+ fi
+ fi
+
+ # XXX: If CONFIG_AUFS_ROBR is added to the Debian kernel we can
+ # ignore the loop below and set rofs_dest_backing=$dest
+ rofs_dest_backing=""
+ for d in ${rootmnt}/live/rofs/*
+ do
+ if [ -n "${rootmnt}" ]
+ then
+ rofs_dest_backing="${d}/$(echo ${dest} | sed -e "s|${rootmnt}||")"
+ else
+ rofs_dest_backing="${d}/${dest}"
+ fi
+ if [ -d "${rofs_dest_backing}" ]
+ then
+ break
+ else
+ rofs_dest_backing=""
+ fi
+ done
+
+ if [ -z "${PERSISTENT_READONLY}" ]
+ then
+ if [ -n "${opt_linkfiles}" ]
+ then
+ links_source="${source}"
+ links_dest="${dest}"
+ elif [ -n "${opt_union}" ]
+ then
+ do_union ${dest} ${source} ${rofs_dest_backing}
+ else
+ mount --bind "${source}" "${dest}"
+ fi
+ else
+ if [ -n "${opt_linkfiles}" ]
+ then
+ links_dest="${dest}"
+ dest="$(mktemp -d ${persistent_backing}/links_source-XXXXXX)"
+ links_source="${dest}"
+ fi
+ if [ -n "${rootmnt}" ]
+ then
+ cow_dir="$(echo ${dest} | sed -e "s|${rootmnt}|/cow/|")"
+ else
+ cow_dir="/live/cow/${dest}"
+ fi
+ mkdir -p ${cow_dir}
+ chown --reference "${source}" "${cow_dir}"
+ chmod --reference "${source}" "${cow_dir}"
+ do_union ${dest} ${cow_dir} ${source} ${rofs_dest_backing}
+ fi
+
+ if [ -n "${opt_linkfiles}" ]
+ then
+ link_files "${links_source}" "${links_dest}" "${rootmnt}"
+ fi
+
+ PERSISTENCE_IS_ON="1"
+ export PERSISTENCE_IS_ON
+
+ if echo ${used_devices} | grep -qve "^\(.* \)\?${device}\( .*\)\?$"
+ then
+ used_devices="${used_devices} ${device}"
+ fi
+ done < ${custom_mounts}
+
+ echo ${used_devices}
+}
+
+fix_home_rw_compatibility ()
+{
+ local device=${1}
+
+ if [ -n "${PERSISTENT_READONLY}" ]
+ then
+ return
+ fi
+
+ local backing="$(mount_persistent_media ${device})"
+ if [ -z "${backing}" ]
+ then
+ return
+ fi
+
+ local include_list="${backing}/${persistence_list}"
+ if [ ! -r "${include_list}" ]
+ then
+ echo "# home-rw backwards compatibility:
+/ /home" > "${include_list}"
+ fi