1#!/bin/sh
2### BEGIN INIT INFO
3# Provides:             volatile
4# Required-Start:       $local_fs
5# Required-Stop:      $local_fs
6# Default-Start:        S
7# Default-Stop:
8# Short-Description:  Populate the volatile filesystem
9### END INIT INFO
10
11# Get ROOT_DIR
12DIRNAME=`dirname $0`
13ROOT_DIR=`echo $DIRNAME | sed -ne 's:/etc/.*::p'`
14
15[ -e ${ROOT_DIR}/etc/default/rcS ] && . ${ROOT_DIR}/etc/default/rcS
16# When running populate-volatile.sh at rootfs time, disable cache.
17[ -n "$ROOT_DIR" ] && VOLATILE_ENABLE_CACHE=no
18# If rootfs is read-only, disable cache.
19[ "$ROOTFS_READ_ONLY" = "yes" ] && VOLATILE_ENABLE_CACHE=no
20
21CFGDIR="${ROOT_DIR}/etc/default/volatiles"
22TMPROOT="${ROOT_DIR}/var/volatile/tmp"
23COREDEF="00_core"
24
25[ "${VERBOSE}" != "no" ] && echo "Populating volatile Filesystems."
26
27create_file() {
28	EXEC=""
29	[ -z "$2" ] && {
30		EXEC="
31		touch \"$1\";
32		"
33	} || {
34		EXEC="
35		cp \"$2\" \"$1\";
36		"
37	}
38	EXEC="
39	${EXEC}
40	chown ${TUSER}:${TGROUP} $1 || echo \"Failed to set owner -${TUSER}- for -$1-.\" >/dev/tty0 2>&1;
41	chmod ${TMODE} $1 || echo \"Failed to set mode -${TMODE}- for -$1-.\" >/dev/tty0 2>&1 "
42
43	test "$VOLATILE_ENABLE_CACHE" = yes && echo "$EXEC" >> /etc/volatile.cache.build
44
45	[ -e "$1" ] && {
46		[ "${VERBOSE}" != "no" ] && echo "Target already exists. Skipping."
47	} || {
48		if [ -z "$ROOT_DIR" ]; then
49			eval $EXEC
50		else
51			# Creating some files at rootfs time may fail and should fail,
52			# but these failures should not be logged to make sure the do_rootfs
53			# process doesn't fail. This does no harm, as this script will
54			# run on target to set up the correct files and directories.
55			eval $EXEC > /dev/null 2>&1
56		fi
57	}
58}
59
60mk_dir() {
61	EXEC="
62	mkdir -p \"$1\";
63	chown ${TUSER}:${TGROUP} $1 || echo \"Failed to set owner -${TUSER}- for -$1-.\" >/dev/tty0 2>&1;
64	chmod ${TMODE} $1 || echo \"Failed to set mode -${TMODE}- for -$1-.\" >/dev/tty0 2>&1 "
65
66	test "$VOLATILE_ENABLE_CACHE" = yes && echo "$EXEC" >> /etc/volatile.cache.build
67	[ -e "$1" ] && {
68		[ "${VERBOSE}" != "no" ] && echo "Target already exists. Skipping."
69	} || {
70		if [ -z "$ROOT_DIR" ]; then
71			eval $EXEC
72		else
73			# For the same reason with create_file(), failures should
74			# not be logged.
75			eval $EXEC > /dev/null 2>&1
76		fi
77	}
78}
79
80link_file() {
81	EXEC="
82	if [ -L \"$2\" ]; then
83		[ \"\$(readlink \"$2\")\" != \"$1\" ] && { rm -f \"$2\"; ln -sf \"$1\" \"$2\"; };
84	elif [ -d \"$2\" ]; then
85		if awk '\$2 == \"$2\" {exit 1}' /proc/mounts; then
86			cp -a $2/* $1 2>/dev/null;
87			cp -a $2/.[!.]* $1 2>/dev/null;
88			rm -rf \"$2\";
89			ln -sf \"$1\" \"$2\";
90		fi
91	else
92		ln -sf \"$1\" \"$2\";
93	fi
94        "
95
96	test "$VOLATILE_ENABLE_CACHE" = yes && echo "	$EXEC" >> /etc/volatile.cache.build
97
98	if [ -z "$ROOT_DIR" ]; then
99		eval $EXEC
100	else
101		# For the same reason with create_file(), failures should
102		# not be logged.
103		eval $EXEC > /dev/null 2>&1
104	fi
105}
106
107check_requirements() {
108	cleanup() {
109		rm "${TMP_INTERMED}"
110		rm "${TMP_DEFINED}"
111		rm "${TMP_COMBINED}"
112	}
113
114	CFGFILE="$1"
115
116	TMP_INTERMED="${TMPROOT}/tmp.$$"
117	TMP_DEFINED="${TMPROOT}/tmpdefined.$$"
118	TMP_COMBINED="${TMPROOT}/tmpcombined.$$"
119
120	sed 's@\(^:\)*:.*@\1@' ${ROOT_DIR}/etc/passwd | sort | uniq > "${TMP_DEFINED}"
121	cat ${CFGFILE} | grep -v "^#" | cut -s -d " " -f 2 > "${TMP_INTERMED}"
122	cat "${TMP_DEFINED}" "${TMP_INTERMED}" | sort | uniq > "${TMP_COMBINED}"
123	NR_DEFINED_USERS="`cat "${TMP_DEFINED}" | wc -l`"
124	NR_COMBINED_USERS="`cat "${TMP_COMBINED}" | wc -l`"
125
126	[ "${NR_DEFINED_USERS}" -ne "${NR_COMBINED_USERS}" ] && {
127		echo "Undefined users:"
128		diff "${TMP_DEFINED}" "${TMP_COMBINED}" | grep "^>"
129		cleanup
130		return 1
131	}
132
133
134	sed 's@\(^:\)*:.*@\1@' ${ROOT_DIR}/etc/group | sort | uniq > "${TMP_DEFINED}"
135	cat ${CFGFILE} | grep -v "^#" | cut -s -d " " -f 3 > "${TMP_INTERMED}"
136	cat "${TMP_DEFINED}" "${TMP_INTERMED}" | sort | uniq > "${TMP_COMBINED}"
137
138	NR_DEFINED_GROUPS="`cat "${TMP_DEFINED}" | wc -l`"
139	NR_COMBINED_GROUPS="`cat "${TMP_COMBINED}" | wc -l`"
140
141	[ "${NR_DEFINED_GROUPS}" -ne "${NR_COMBINED_GROUPS}" ] && {
142		echo "Undefined groups:"
143		diff "${TMP_DEFINED}" "${TMP_COMBINED}" | grep "^>"
144		cleanup
145		return 1
146	}
147
148	# Add checks for required directories here
149
150	cleanup
151	return 0
152}
153
154apply_cfgfile() {
155	CFGFILE="$1"
156	SKIP_REQUIREMENTS="$2"
157
158	[ "${VERBOSE}" != "no" ] && echo "Applying ${CFGFILE}"
159
160	[ "${SKIP_REQUIREMENTS}" == "yes" ] || check_requirements "${CFGFILE}" || {
161		echo "Skipping ${CFGFILE}"
162		return 1
163	}
164
165	cat ${CFGFILE} | sed 's/#.*//' | \
166	while read TTYPE TUSER TGROUP TMODE TNAME TLTARGET; do
167		test -z "${TLTARGET}" && continue
168		TNAME=${ROOT_DIR}${TNAME}
169		[ "${VERBOSE}" != "no" ] && echo "Checking for -${TNAME}-."
170
171		[ "${TTYPE}" = "l" ] && {
172			TSOURCE="$TLTARGET"
173			[ "${VERBOSE}" != "no" ] && echo "Creating link -${TNAME}- pointing to -${TSOURCE}-."
174			link_file "${TSOURCE}" "${TNAME}"
175			continue
176		}
177
178		[ "${TTYPE}" = "b" ] && {
179			TSOURCE="$TLTARGET"
180			[ "${VERBOSE}" != "no" ] && echo "Creating mount-bind -${TNAME}- from -${TSOURCE}-."
181			mount --bind "${TSOURCE}" "${TNAME}"
182			EXEC="
183	mount --bind \"${TSOURCE}\" \"${TNAME}\""
184			test "$VOLATILE_ENABLE_CACHE" = yes && echo "$EXEC" >> /etc/volatile.cache.build
185			continue
186		}
187
188		[ -L "${TNAME}" ] && {
189			[ "${VERBOSE}" != "no" ] && echo "Found link."
190			NEWNAME=`ls -l "${TNAME}" | sed -e 's/^.*-> \(.*\)$/\1/'`
191			echo ${NEWNAME} | grep -v "^/" >/dev/null && {
192				TNAME="`echo ${TNAME} | sed -e 's@\(.*\)/.*@\1@'`/${NEWNAME}"
193				[ "${VERBOSE}" != "no" ] && echo "Converted relative linktarget to absolute path -${TNAME}-."
194			} || {
195				TNAME="${NEWNAME}"
196				[ "${VERBOSE}" != "no" ] && echo "Using absolute link target -${TNAME}-."
197			}
198		}
199
200		case "${TTYPE}" in
201			"f")  [ "${VERBOSE}" != "no" ] && echo "Creating file -${TNAME}-."
202				TSOURCE="$TLTARGET"
203				[ "${TSOURCE}" = "none" ] && TSOURCE=""
204				create_file "${TNAME}" "${TSOURCE}" &
205				;;
206			"d")  [ "${VERBOSE}" != "no" ] && echo "Creating directory -${TNAME}-."
207				mk_dir "${TNAME}"
208				# Add check to see if there's an entry in fstab to mount.
209				;;
210			*)    [ "${VERBOSE}" != "no" ] && echo "Invalid type -${TTYPE}-."
211				continue
212				;;
213		esac
214	done
215	return 0
216}
217
218clearcache=0
219exec 9</proc/cmdline
220while read line <&9
221do
222	case "$line" in
223		*clearcache*)  clearcache=1
224			       ;;
225		*)	       continue
226			       ;;
227	esac
228done
229exec 9>&-
230
231if test -e ${ROOT_DIR}/etc/volatile.cache -a "$VOLATILE_ENABLE_CACHE" = "yes" -a "x$1" != "xupdate" -a "x$clearcache" = "x0"
232then
233	sh ${ROOT_DIR}/etc/volatile.cache
234else
235	rm -f ${ROOT_DIR}/etc/volatile.cache ${ROOT_DIR}/etc/volatile.cache.build
236
237	# Apply the core file with out checking requirements. ${TMPROOT} is
238	# needed by check_requirements but is setup by this file, so it must be
239	# processed first and without being checked.
240	[ -e "${CFGDIR}/${COREDEF}" ] && apply_cfgfile "${CFGDIR}/${COREDEF}" "yes"
241
242	# Fast path: check_requirements is slow and most of the time doesn't
243	# find any problems. If there are a lot of config files, it is much
244	# faster to to concatenate them all together and process them once to
245	# avoid the overhead of calling check_requirements repeatedly
246	TMP_FILE="${TMPROOT}/tmp_volatile.$$"
247	rm -f "$TMP_FILE"
248
249	CFGFILES="`ls -1 "${CFGDIR}" | grep -v "^${COREDEF}\$" | sort`"
250	for file in ${CFGFILES}; do
251		cat "${CFGDIR}/${file}" >> "$TMP_FILE"
252	done
253
254	if check_requirements "$TMP_FILE"
255	then
256		apply_cfgfile "$TMP_FILE" "yes"
257	else
258		# Slow path: One or more config files failed requirements.
259		# Process each one individually so the offending one can be
260		# skipped
261		for file in ${CFGFILES}; do
262			apply_cfgfile "${CFGDIR}/${file}"
263		done
264	fi
265	rm "$TMP_FILE"
266
267	[ -e ${ROOT_DIR}/etc/volatile.cache.build ] && sync && mv ${ROOT_DIR}/etc/volatile.cache.build ${ROOT_DIR}/etc/volatile.cache
268fi
269
270if [ -z "${ROOT_DIR}" ] && [ -f /etc/ld.so.cache ] && [ ! -f /var/run/ld.so.cache ]
271then
272	ln -s /etc/ld.so.cache /var/run/ld.so.cache
273fi
274