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