+
+removable_dev ()
+{
+ output_format="${1}"
+ want_usb="${2}"
+ ret=
+
+ for sysblock in $(echo /sys/block/* | tr ' ' '\n' | grep -vE "/(loop|ram|dm-|fd)")
+ do
+ dev_ok=
+ if [ "$(cat ${sysblock}/removable)" = "1" ]
+ then
+ if [ -z "${want_usb}" ]
+ then
+ dev_ok="yes"
+ else
+ if readlink ${sysblock} | grep -q usb
+ then
+ dev_ok="yes"
+ fi
+ fi
+ fi
+
+ if [ "${dev_ok}" = "yes" ]
+ then
+ case "${output_format}" in
+ sys)
+ ret="${ret} ${sysblock}"
+ ;;
+ *)
+ devname=$(sys2dev "${sysblock}")
+ ret="${ret} ${devname}"
+ ;;
+ esac
+ fi
+ done
+
+ echo "${ret}"
+}
+
+removable_usb_dev ()
+{
+ output_format="${1}"
+
+ removable_dev "${output_format}" "want_usb"
+}
+
+non_removable_dev ()
+{
+ output_format="${1}"
+ ret=
+
+ for sysblock in $(echo /sys/block/* | tr ' ' '\n' | grep -vE "/(loop|ram|dm-|fd)")
+ do
+ if [ "$(cat ${sysblock}/removable)" = "0" ]
+ then
+ case "${output_format}" in
+ sys)
+ ret="${ret} ${sysblock}"
+ ;;
+ *)
+ devname=$(sys2dev "${sysblock}")
+ ret="${ret} ${devname}"
+ ;;
+ esac
+ fi
+ done
+
+ echo "${ret}"
+}
+
+link_files ()
+{
+ # create source's directory structure in dest, and recursively
+ # create symlinks in dest to to all files in source. if mask
+ # is non-empty, remove mask from all source paths when
+ # creating links (will be necessary if we change root, which
+ # live-boot normally does (into $rootmnt)).
+
+ # remove multiple /:s and ensure ending on /
+ local src_dir="$(echo "${1}"/ | sed -e 's|/\+|/|g')"
+ local dest_dir="$(echo "${2}"/ | sed -e 's|/\+|/|g')"
+ local src_mask="${3}"
+
+ # This check can only trigger on the inital, non-recursive call since
+ # we create the destination before recursive calls
+ if [ ! -d "${dest_dir}" ];
+ then
+ log_warning_msg "Must link_files into a directory"
+ return
+ fi
+
+ find "${src_dir}" -mindepth 1 -maxdepth 1 | while read x; do
+ local src="${x}"
+ local dest="${dest_dir}$(basename "${x}")"
+ if [ -d "${src}" ];
+ then
+ if [ -z "$(ls -A "${src}")" ];
+ then
+ continue
+ fi
+ if [ ! -d "${dest}" ];
+ then
+ mkdir -p "${dest}"
+ prev="$(dirname "${dest}")"
+ chown $(stat -c %u:%g "${prev}") "${dest}"
+ chmod $(stat -c %a "${prev}") "${dest}"
+ fi
+ link_files "${src}" "${dest}" "${src_mask}"
+ else
+ if [ -n "${src_mask}" ];
+ then
+ src="$(echo ${src} | sed "s|^${src_mask}||")"
+ fi
+ rm -rf "${dest}" 2> /dev/null
+ ln -s "${src}" "${dest}"
+ fi
+ done
+}
+
+do_union () {
+ local unionmountpoint="${1}" # directory where the union is mounted
+ local unionrw="${2}" # branch where the union changes are stored
+ local unionro1="${3}" # first underlying read-only branch (optional)
+ local unionro2="${4}" # second underlying read-only branch (optional)
+
+ if [ "${UNIONTYPE}" = "aufs" ]
+ then
+ rw_opt="rw"
+ ro_opt="rr+wh"
+ noxino_opt="noxino"
+ elif [ "${UNIONTYPE}" = "unionfs-fuse" ]
+ then
+ rw_opt="RW"
+ ro_opt="RO"
+ else
+ rw_opt="rw"
+ ro_opt="ro"
+ fi
+
+ case "${UNIONTYPE}" in
+ unionfs-fuse)
+ unionmountopts="-o cow -o noinitgroups -o default_permissions -o allow_other -o use_ino -o suid"
+ unionmountopts="${unionmountopts} ${unionrw}=${rw_opt}"
+ if [ -n "${unionro1}" ]
+ then
+ unionmountopts="${unionmountopts}:${unionro1}=${ro_opt}"
+ fi
+ if [ -n "${unionro2}" ]
+ then
+ unionmountopts="${unionmountopts}:${unionro2}=${ro_opt}"
+ fi
+ ( sysctl -w fs.file-max=391524 ; ulimit -HSn 16384
+ unionfs-fuse ${unionmountopts} "${unionmountpoint}" ) && \
+ ( mkdir -p /run/sendsigs.omit.d
+ pidof unionfs-fuse >> /run/sendsigs.omit.d/unionfs-fuse || true )
+ ;;
+
+ overlayfs)
+ # XXX: can unionro2 be used? (overlayfs only handles two dirs, but perhaps they can be chained?)
+ # XXX: and can unionro1 be optional? i.e. can overlayfs skip lowerdir?
+ unionmountopts="-o noatime,lowerdir=${unionro1},upperdir=${unionrw}"
+ mount -t ${UNIONTYPE} ${unionmountopts} ${UNIONTYPE} "${unionmountpoint}"
+ ;;
+
+ *)
+ 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
+}