#!/bin/sh
set -e

# /usr/share/bilibop/make_unpersistent_rules

# Remove some persistent udev rules files (cd & net) and replace them by links
# to unpersistent files (in /run/udev/rules.d); ...or restore them.
# This is made because these persistent rules files are cumulative, and so are
# not very adapted for an operating system on external hard disk or usb key.

### BEGIN ###

PATH="/sbin:/bin:/usr/bin"
PROG="${0##*/}"
SOPTS="ho:rsv"
LOPTS="help,only:,restore,status,verbose"

ETC_RULES_DIR="/etc/udev/rules.d"
RUN_RULES_DIR="/run/udev/rules.d"

if [ -f /etc/udev/udev.conf ]; then
	. /etc/udev/udev.conf
fi
udev_root="${udev_root:-/dev}"
udev_root="${udev_root%/}"

status=""
restore=""
verbose=""
only=""
TYPE=""
SKIP=""

short_usage() {
	cat <<EOF
Usage:
  ${PROG} -h|--help
  ${PROG} -s|--status
  ${PROG} [-v|--verbose] [-r|--restore] [-o|--only cd|net]
EOF
}

usage() {
	cat <<EOF
${PROG} replaces some persistent udev rules files by
links to unpersistent files (in ${RUN_RULES_DIR}).
This is done to avoid cumulative informations about optical drives
and network interfaces.

Usage: ${PROG} [OPTIONS]

OPTIONS:
  -h, --help
      Display this help and exit.

  -o TYPE, --only TYPE
      Apply actions only for the specified TYPE of rules (cd or net).

  -r, --restore
      Remove links to unpersistent rules files and restore persistent
      (static) udev rules files.

  -s, --status
      Display the status of each rules file and exit.

  -v, --verbose
      Be verbose.
EOF
}

execute() {
	if [ -n "${verbose}" ]; then
		echo "> ${@}"
	fi
	"${@}"
}


set +e
### Parse options ##############################################################
ARGS="$(getopt -o ${SOPTS} --long ${LOPTS} -n ${PROG} -- "${@}")"
if [ "${?}" != "0" ]; then
	short_usage >&2
	exit 1
else
	eval set -- "${ARGS}"
fi
################################################################################
set -e


while true; do
	case "${1}" in
		-h|--help)
			usage
			exit 0
			;;
		-o|--only)
			only="${2}"
			shift 2
			;;
		-r|--restore)
			restore="true"
			shift
			;;
		-s|--status)
			status="true"
			shift
			;;
		-v|--verbose)
			verbose="-v"
			shift
			;;
		--)
			shift
			break
			;;
		*)
			unknown_argument "${1}" >&2
			short_usage >&2
			exit 1
			;;
	esac
done

if [ "${status}" = "true" ]; then
	for rules in 70-persistent-cd.rules 70-persistent-net.rules; do
		printf "%s\t" "${rules}"
		if [ -h "${ETC_RULES_DIR}/${rules}" ]; then
			printf "%s " ":link: ->"
			readlink -f ${ETC_RULES_DIR}/${rules}
		elif [ -f "${ETC_RULES_DIR}/${rules}" ]; then
			printf "%s " ":file: =="
			ls ${ETC_RULES_DIR}/${rules}
		else
			printf "%s\n"   ":none: ()"
		fi
	done
	exit 0
fi

# Now, analyse the results.
case "${only}" in
	cd)
		TYPE="cd"
		SKIP="net"
		;;
	net)
		TYPE="net"
		SKIP="cd"
		;;
	"")
		TYPE="cd net"
		SKIP=""
		;;
	*)
		unknown_argument "${only}" >&2
		short_usage >&2
		exit 1
		;;
esac

make_regular() {
	persistent="${ETC_RULES_DIR}/70-persistent-${1}.rules"
	if [ -h "${persistent}" ]; then
		unpersistent="$(readlink -f ${persistent})"
		execute rm ${verbose} ${persistent}
		if [ -f "${unpersistent}" ]; then
			execute mv ${verbose} ${unpersistent} ${persistent}
		else
			execute touch ${persistent}
		fi

	elif [ ! -f "${persistent}" ]; then
		unpersistent="${RUN_RULES_DIR}/70-persistent-${1}.rules"
		if [ -f "${unpersistent}" ]; then
			execute mv ${verbose} ${unpersistent} ${persistent}
		else
			execute touch ${persistent}
		fi
	fi
}

make_symlink() {
	persistent="${ETC_RULES_DIR}/70-persistent-${1}.rules"
	unpersistent="${RUN_RULES_DIR}/70-persistent-${1}.rules"
	if [ -h "${persistent}" ]; then
		target="$(readlink -f ${persistent})"
		if	[ "${target}" = "${unpersistent}" ]; then
			[ -f "${target}" ] || execute touch ${target}
			# nothing else to do:
			continue
		else
			#[ -d "${RUN_RULES_DIR}" ] || execute mkdir -p ${RUN_RULES_DIR}
			[ -f "${target}" ] && execute mv ${verbose} ${target} ${unpersistent}
			execute rm ${verbose} ${persistent}
		fi

	elif [ -f "${persistent}" ]; then
		#[ -d "${RUN_RULES_DIR}" ] || execute mkdir -p ${RUN_RULES_DIR}
		execute mv ${verbose} ${persistent} ${unpersistent}
	fi

	#[ -e "${persistent}" ] && execute rm ${verbose} ${persistent}
	[ -e "${unpersistent}" ] || execute touch ${unpersistent}
	execute ln -s ${verbose} ${unpersistent} ${persistent}
}

# And run...
if [ "${restore}" = "true" ]; then
	for	i in ${TYPE}; do
		make_regular ${i}
	done
	for	i in ${SKIP}; do
		make_symlink ${i}
	done

else
	for	i in ${TYPE}; do
		make_symlink ${i}
	done
	for	i in ${SKIP}; do
		make_regular ${i}
	done
fi

### END ###
# vim: ts=4 sts=4 sw=4
