├── README.md └── files ├── init_resize2.sh ├── display_funcs.sh └── create-factory-reset.sh /README.md: -------------------------------------------------------------------------------- 1 | # Factory Reset Your Raspbian OS 2 | 3 | ### Description: 4 | ************************************************ 5 | In the normal process to reset or restore the Raspberry Pi OS (Raspbian), you need to unplug the SD Card, format the card, re-write the OS image and plug it back again. If you are doing some testing or development, it can be a pain to go over this process again. This git contains the scripts using which you can create a Raspberry Pi OS image which has an option to factory reset the OS without plugging out the SD Card. 6 | 7 | ## Usage: 8 | ************************************************ 9 | ### Ready to use images: 10 | These are based on the May 2020 version of the Raspberry Pi OS. 11 | https://mega.nz/folder/akREwKKB#SNdASVnpzOaj7rPtrgPW_w 12 | 13 | ### Prepare your own image by following the instructions given below on a linux based system 14 | 15 | | Image Versions | Free Space Required | 16 | |-------------------|---------------------------| 17 | | Lite | 10GB | 18 | | Minimal Desktop | 14GB | 19 | | Full Desktop | 25GB | 20 | 21 | 22 | 1. Clone the git using: 23 | ``` 24 | git clone https://github.com/shivasiddharth/RaspberryPi-Factory-Reset 25 | ``` 26 | 27 | 2. Download your preferred image, unzip them and place them in the files directory. 28 | 29 | 3. Change directory using: 30 | ``` 31 | cd /home/${USER}/RaspberryPi-Factory-Reset/files/ 32 | ``` 33 | 34 | 4. Make the script executable using: 35 | ``` 36 | sudo chmod +x ./create-factory-reset.sh 37 | ``` 38 | 39 | 5. Execute the script using: 40 | ``` 41 | sudo ./create-factory-reset.sh 42 | ``` 43 | 44 | 6. Copy the created image and write it to the SD Card and enjoy. 45 | 46 | ## Command to factory reset: 47 | ************************************************ 48 | ``` 49 | sudo su - 50 | /boot/factory_reset --reset 51 | ``` 52 | -------------------------------------------------------------------------------- /files/init_resize2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | reboot_pi () { 4 | umount /boot 5 | mount / -o remount,ro 6 | sync 7 | 8 | echo b > /proc/sysrq-trigger 9 | sleep 5 10 | exit 0 11 | } 12 | 13 | check_commands () { 14 | if ! command -v whiptail > /dev/null; then 15 | echo "whiptail not found" 16 | sleep 5 17 | return 1 18 | fi 19 | for COMMAND in grep cut sed parted fdisk findmnt partprobe; do 20 | if ! command -v $COMMAND > /dev/null; then 21 | FAIL_REASON="$COMMAND not found" 22 | return 1 23 | fi 24 | done 25 | return 0 26 | } 27 | 28 | 29 | get_variables () { 30 | ROOT_PART_DEV=$(findmnt / -o source -n) 31 | ROOT_PART_NAME=$(echo "$ROOT_PART_DEV" | cut -d "/" -f 3) 32 | ROOT_DEV_NAME=$(echo /sys/block/*/"${ROOT_PART_NAME}" | cut -d "/" -f 4) 33 | ROOT_DEV="/dev/${ROOT_DEV_NAME}" 34 | ROOT_PART_NUM=$(cat "/sys/block/${ROOT_DEV_NAME}/${ROOT_PART_NAME}/partition") 35 | 36 | BOOT_PART_DEV=$(findmnt /boot -o source -n) 37 | BOOT_PART_NAME=$(echo "$BOOT_PART_DEV" | cut -d "/" -f 3) 38 | BOOT_DEV_NAME=$(echo /sys/block/*/"${BOOT_PART_NAME}" | cut -d "/" -f 4) 39 | BOOT_PART_NUM=$(cat "/sys/block/${BOOT_DEV_NAME}/${BOOT_PART_NAME}/partition") 40 | 41 | OLD_DISKID=$(fdisk -l "$ROOT_DEV" | sed -n 's/Disk identifier: 0x\([^ ]*\)/\1/p') 42 | 43 | check_noobs 44 | 45 | ROOT_DEV_SIZE=$(cat "/sys/block/${ROOT_DEV_NAME}/size") 46 | TARGET_END=$((ROOT_DEV_SIZE - 1)) 47 | 48 | PARTITION_TABLE=$(parted -m "$ROOT_DEV" unit s print | tr -d 's') 49 | 50 | LAST_PART_NUM=$(echo "$PARTITION_TABLE" | tail -n 1 | cut -d ":" -f 1) 51 | 52 | ROOT_PART_LINE=$(echo "$PARTITION_TABLE" | grep -e "^${ROOT_PART_NUM}:") 53 | ROOT_PART_START=$(echo "$ROOT_PART_LINE" | cut -d ":" -f 2) 54 | ROOT_PART_END=$(echo "$ROOT_PART_LINE" | cut -d ":" -f 3) 55 | 56 | if [ "$NOOBS" = "1" ]; then 57 | EXT_PART_LINE=$(echo "$PARTITION_TABLE" | grep ":::;" | head -n 1) 58 | EXT_PART_NUM=$(echo "$EXT_PART_LINE" | cut -d ":" -f 1) 59 | EXT_PART_START=$(echo "$EXT_PART_LINE" | cut -d ":" -f 2) 60 | EXT_PART_END=$(echo "$EXT_PART_LINE" | cut -d ":" -f 3) 61 | fi 62 | } 63 | 64 | fix_partuuid() { 65 | DISKID="$(fdisk -l "$ROOT_DEV" | sed -n 's/Disk identifier: 0x\([^ ]*\)/\1/p')" 66 | 67 | sed -i "s/${OLD_DISKID}/${DISKID}/g" /etc/fstab 68 | sed -i "s/${OLD_DISKID}/${DISKID}/" /boot/cmdline.txt 69 | } 70 | 71 | 72 | 73 | 74 | 75 | main () { 76 | 77 | 78 | cat << 'EOF' | logger 79 | ## _____ _ 80 | ## | ___|_ _ ___| |_ ___ _ __ _ _ 81 | ## | |_ / _` |/ __| __/ _ \| '__| | | | 82 | ## | _| (_| | (__| || (_) | | | |_| | 83 | ## |_| \__,_|\___|\__\___/|_| \__, | 84 | ## |___/ 85 | ## ____ _ _ 86 | ## | _ \ ___ ___| |_ ___ _ __(_)_ __ __ _ 87 | ## | |_) / _ \/ __| __/ _ \| '__| | '_ \ / _` | 88 | ## | _ < __/\__ \ || (_) | | | | | | | (_| | 89 | ## |_| \_\___||___/\__\___/|_| |_|_| |_|\__, | 90 | ## |___/ 91 | EOF 92 | 93 | # dd bs=4M if=/opt/recovery.img of=/dev/mmcblk0p3 conv=fsync status=progress 94 | unzip -p /opt/recovery.img.zip \ 95 | | dd bs=4M \ 96 | of=/dev/mmcblk0p3 \ 97 | conv=fsync \ 98 | status=progress 99 | 100 | cp -f /boot/cmdline.txt_original /boot/cmdline.txt 101 | touch /boot/ssh 102 | 103 | return 0 104 | } 105 | 106 | mount -t proc proc /proc 107 | mount -t sysfs sys /sys 108 | mount -t tmpfs tmp /run 109 | mkdir -p /run/systemd 110 | 111 | mount /boot 112 | mount / -o remount,rw 113 | 114 | sync 115 | 116 | echo 1 > /proc/sys/kernel/sysrq 117 | 118 | if ! check_commands; then 119 | reboot_pi 120 | fi 121 | 122 | if main; then 123 | whiptail --infobox "restored filesystem. Rebooting in 5 seconds..." 20 60 124 | sleep 5 125 | else 126 | sleep 5 127 | whiptail --msgbox "Could not restore, rebooting" 20 60 128 | fi 129 | 130 | reboot_pi 131 | -------------------------------------------------------------------------------- /files/display_funcs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | # https://misc.flogisoft.com/bash/tip_colors_and_formatting 5 | 6 | bufferstring="" 7 | ev() 8 | { 9 | varname="$1" 10 | #let bufferstring 11 | bufferstring="${bufferstring}\n$1=${!varname}" 12 | } 13 | 14 | show_var() 15 | { 16 | varname="$1" 17 | echo "$1=${!varname}" 18 | } 19 | 20 | 21 | 22 | shellquote() 23 | { 24 | a="$1" 25 | 26 | #$a =~ s/[\n]/'\n'/go; 27 | #$a =~ s/[\002-\011\013-\032\\\#\?\`\(\)\{\}\[\]\^\*\<\=\>\~\|\; \"\!\$\&\'\202-\377]/\\$&/go; 28 | # quote newline as '\n' 29 | echo "$a" | sed -r "s/[\n]/'\n'/g" 30 | } 31 | 32 | parse_tokens() 33 | { 34 | a="$1" 35 | 36 | for K in "${!COLOR[@]}"; do 37 | #echo $K --- ${COLOR[$K]}; 38 | a="$(echo "$a" | sed -r "s/[$]{1,1}\{$K\}/${COLOR[$K]}/g")" 39 | done 40 | 41 | echo "$a" 42 | 43 | #eval 'echo' "$a" 44 | 45 | } 46 | # | sed -e 's/.*\bWARN.*/\x1b[7m&\x1b[0m/i' -e 's/.*\bERR.*/\x1b[93;41 m&\x1b[0m/i' 47 | 48 | 49 | pr_head() 50 | { 51 | declare alert_header="" 52 | [[ "$1" == "warn" ]] && \ 53 | alert_header=1 54 | 55 | while read -r line; do 56 | # printf "%s" "$data" 57 | 58 | if [[ $alert_header ]] ; then 59 | echo -en "${RED}" 60 | printf "%s" "${line:0:80}" 61 | echo -en "${RESET}" 62 | echo 63 | else 64 | parse_tokens "${line:0:80}" 65 | fi 66 | 67 | done 68 | # ansi chars line wrapping screws things up. 69 | } 70 | 71 | 72 | # | sed -e 's/.*\bWARN.*/\x1b[7m&\x1b[0m/i' -e 's/.*\bERR.*/\x1b[93;41 m&\x1b[0m/i' 73 | 74 | # # Reset 75 | # Color_Off='\033[0m' # Text Reset 76 | 77 | # # Regular Colors 78 | # Black='\033[0;30m' # Black 79 | # Red='\033[0;31m' # Red 80 | # Green='\033[0;32m' # Green 81 | # Yellow='\033[0;33m' # Yellow 82 | # Blue='\033[0;34m' # Blue 83 | # Purple='\033[0;35m' # Purple 84 | # Cyan='\033[0;36m' # Cyan 85 | # White='\033[0;37m' # White 86 | 87 | # In Bash, the character can be obtained with the following syntaxes: 88 | 89 | # \e 90 | # \033 91 | # \x1B 92 | 93 | 94 | pr_header() 95 | { 96 | 97 | [[ $# -gt 0 ]] && \ 98 | { 99 | line="$@" 100 | echo "" 101 | echo -en "${BLUE}${WHITEBG}" 102 | printf "%s" "${line:0:100}" 103 | echo -en "${RESET}" 104 | echo 105 | 106 | } || \ 107 | { 108 | while read -r line; do 109 | # printf "%s" "$data" 110 | echo -en "${PINK}" 111 | printf "%s" "${line:0:100}" 112 | echo -en "${RESET}" 113 | echo 114 | done 115 | 116 | } 117 | } 118 | 119 | 120 | 121 | pr_warn() 122 | { 123 | 124 | [[ $# -gt 0 ]] && \ 125 | { 126 | line=$1 127 | 128 | echo -en "${PINK}" 129 | printf "%s" "${line:0:80}" 130 | echo -en "${RESET}" 131 | echo 132 | 133 | } || \ 134 | { 135 | while read -r line; do 136 | # printf "%s" "$data" 137 | echo -en "${PINK}" 138 | printf "%s" "${line:0:80}" 139 | echo -en "${RESET}" 140 | echo 141 | done 142 | 143 | } 144 | } 145 | 146 | 147 | pr_ok() 148 | { 149 | 150 | [[ $# -gt 0 ]] && \ 151 | { 152 | line=$1 153 | 154 | echo -en "${GREEN}" 155 | printf "%s" "${line:0:80}" 156 | echo -en "${RESET}" 157 | echo 158 | 159 | } || \ 160 | { 161 | while read -r line; do 162 | # printf "%s" "$data" 163 | echo -en "${GREEN}" 164 | printf "%s" "${line:0:80}" 165 | echo -en "${RESET}" 166 | echo 167 | done 168 | 169 | } 170 | } 171 | 172 | 173 | 174 | pr_alert() 175 | { 176 | 177 | [[ $# -gt 0 ]] && \ 178 | { 179 | line=$1 180 | 181 | echo -en "${RED}${WHITEBG}" 182 | printf "%s" "${line:0:80}" 183 | echo -en "${RESET}" 184 | echo 185 | 186 | } || \ 187 | { 188 | while read -r line; do 189 | # printf "%s" "$data" 190 | echo -en "${RED}" 191 | printf "%s" "${line:0:80}" 192 | echo -en "${RESET}" 193 | echo 194 | done 195 | 196 | } 197 | # ansi chars line wrapping screws things up. 198 | } 199 | 200 | # takes a 201 | pr_table() 202 | { 203 | echo -e "$1" 204 | 205 | } 206 | 207 | printval() 208 | { 209 | msg=$1 210 | char='=' 211 | 212 | if [[ $(awk -F"${char}" '{print NF-1}' <<< "$msg") -eq 1 ]] ; then 213 | #echo hee11 214 | echo "${MAGENTAFG}${msg%%=*}${RESET}=${BLUE}${msg##*=}${RESET}" 215 | #${stringZ#a*C} 216 | # echo hee 217 | elif [[ "$msg" =~ ^vdvrergv$ ]] ;then 218 | echo "${BLUEFG}${msg}${RESET}" 219 | echo rgjerigo 220 | elif [[ "joijij2" == "joijio" ]] ;then 221 | echo rgjerigo 222 | else 223 | echo "${YELLOWFB}${msg}${RESET}" 224 | fi 225 | } 226 | 227 | wasX="" 228 | [[ "$-" =~ 'x' ]] && wasX=true && set +x 229 | 230 | ##$ bash --version # Must be at least version 4 to have associative arrays 231 | #GNU bash, version 4.2.24(1)-release (x86_64-pc-linux-gnu) 232 | 233 | # Define a few Colours 234 | BLACKFG=$(tput setaf 0 2>/dev/null ) 235 | BLACKBG=$(tput setab 0 2>/dev/null ) 236 | RED=$(tput setaf 1 2>/dev/null ) 237 | PINK=$(tput setaf 134 2>/dev/null ) 238 | REDFG=$(tput setaf 1 2>/dev/null ) 239 | REDBG=$(tput setab 1 2>/dev/null ) 240 | GREEN=$(tput setaf 2 2>/dev/null ) 241 | GREENFG=$(tput setaf 2 2>/dev/null ) 242 | GREENBG=$(tput setab 2 2>/dev/null ) 243 | YELLOWFG=$(tput setaf 3 2>/dev/null ) 244 | YELLOWBG=$(tput setab 3 2>/dev/null ) 245 | BLUE=$(tput setaf 4 2>/dev/null ) 246 | BLUEFG=$(tput setaf 4 2>/dev/null ) 247 | BLUEBG=$(tput setab 4 2>/dev/null ) 248 | MAGENTAFG=$(tput setaf 5 2>/dev/null ) 249 | MAGENTABG=$(tput setab 5 2>/dev/null ) 250 | CYANFG=$(tput setaf 6 2>/dev/null ) 251 | CYANBG=$(tput setab 6 2>/dev/null ) 252 | WHITEFG=$(tput setaf 7 2>/dev/null ) 253 | WHITEBG=$(tput setab 7 2>/dev/null ) 254 | PURPLE=$(tput setaf 8 2>/dev/null ) 255 | DEFAULTFG=$(tput setaf 9 2>/dev/null ) 256 | DEFAULTBG=$(tput setab 9 2>/dev/null ) 257 | PURPLE2=$(tput setaf 125 2>/dev/null ) 258 | BLINK=$(tput blink 2>/dev/null ) 259 | REVERSE=$(tput smso 2>/dev/null ) 260 | UNDERLINE=$(tput smul 2>/dev/null ) 261 | LIME_YELLOW=$(tput setaf 190 2>/dev/null ) 262 | POWDER_BLUE=$(tput setaf 153 2>/dev/null ) 263 | RESET=$(tput sgr0 2>/dev/null ) 264 | 265 | declare -A COLOR 266 | COLOR[BLACKFG]=${BLACKFG} 267 | COLOR[WHITEFG]=${WHITEFG} 268 | COLOR[DEFAULTFG]=${DEFAULTFG} 269 | COLOR[DEFAULTBG]=${DEFAULTBG} 270 | COLOR[POWDER_BLUE]=${POWDER_BLUE} 271 | COLOR[CYANFG]=${CYANFG} 272 | COLOR[CYANBG]=${CYANBG} 273 | COLOR[GREENFG]=${GREENFG} 274 | COLOR[GREENBG]=${GREENBG} 275 | COLOR[BLUEFG]=${BLUEFG} 276 | COLOR[BLUEBG]=${BLUEBG} 277 | COLOR[YELLOWFG]=${YELLOWFG} 278 | COLOR[YELLOWBG]=${YELLOWBG} 279 | COLOR[PINK]=${PINK} 280 | COLOR[RESET]=${RESET} 281 | COLOR[REDFG]=${REDFG} 282 | COLOR[REDBG]=${REDBG} 283 | 284 | 285 | 286 | [[ -n "${wasX}" ]] && set -x 287 | unset wasX -------------------------------------------------------------------------------- /files/create-factory-reset.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # fail on errors, undefined variables, and errors in pipes 4 | set -eu 5 | set -o pipefail 6 | 7 | scripts_dir="$(dirname "${BASH_SOURCE[0]}")" 8 | GIT_DIR="$(realpath $(dirname ${BASH_SOURCE[0]})/..)" 9 | 10 | # make sure we're running as the owner of the checkout directory 11 | RUN_AS="$(ls -ld "$scripts_dir" | awk 'NR==1 {print $3}')" 12 | if [ "$USER" != "$RUN_AS" ] 13 | then 14 | echo "This script must run as $RUN_AS, trying to change user..." 15 | exec sudo -u $RUN_AS $0 16 | fi 17 | 18 | echo "" 19 | read -r -p "Enter the fullname of the image that you want to use (without the img extension): " originalimage 20 | echo "" 21 | 22 | 23 | MOTD_SHOW_LIVE="" 24 | SET_PI_PASSWORD="" 25 | 26 | function main() 27 | { 28 | 29 | pr_header "entering main function" 30 | 31 | # paths for base, intermediate and restore images 32 | 33 | [ -f ${originalimage}.img ] || { echo "Live image not found '${originalimage}.img'" && exit; } 34 | 35 | IMG_ORIG=${originalimage}.img 36 | 37 | IMG_LIVE=${originalimage}.live.img 38 | 39 | IMG_RESTORE=${originalimage}.restore.img 40 | 41 | IMAGE_FILE_SIZE=$( stat -c %s ${IMG_ORIG} ) 42 | 43 | echo "Original image size: ${IMAGE_FILE_SIZE}" 44 | 45 | echo "" 46 | 47 | NEW_FILE_SIZE=$(((( ${IMAGE_FILE_SIZE}*3 ) + ( 512 * 1000 )) / 1024 )) 48 | 49 | echo "New image size: ${NEW_FILE_SIZE}K" 50 | 51 | # paths to src/dest file that is used for resetting in live image 52 | RECOVERY_SCRIPT_SOURCE="${DIR}/init_resize2.sh" 53 | [ -f ${RECOVERY_SCRIPT_SOURCE} ] || { echo "Not found ${RECOVERY_SCRIPT_SOURCE}" && exit; } 54 | RECOVERY_SCRIPT_TARGET=/usr/lib/raspi-config/init_resize2.sh 55 | 56 | # because of cloning the images, need to generate new UUIDs 57 | UUID_RESTORE=$(uuidgen) 58 | UUID_ROOTFS=$(uuidgen) 59 | 60 | # @TODO using the existing UUID_BOOT because it stays the same 61 | # UUID_BOOT=$(tr -dc 'a-f0-9' < /dev/urandom 2>/dev/null | \ 62 | # dd bs=1 count=8 2>/dev/null) 63 | 64 | # partuuid seems to get reset by resize.sh, however UUID doesn't seem to work 65 | set +o pipefail 66 | PARTUUID=$(tr -dc 'a-f0-9' < /dev/urandom 2>/dev/null | head -c8) 67 | set -o pipefail 68 | [ ! -z ${PARTUUID} ] || { echo "PARTUUID is empty '${PARTUUID}'" && exit; } 69 | 70 | pr_ok "PARTUUID generated is ${PARTUUID}" 71 | 72 | pr_header "2.2 make a copy of the pristine image for use as the live rootfs" 73 | 74 | [[ -f "${IMG_LIVE}" ]] && \ 75 | { 76 | pr_warn "live file ${IMG_LIVE} already, exists - overwriting" 77 | cp -f ${IMG_ORIG} ${IMG_LIVE} 78 | pr_ok "${IMG_LIVE} created" 79 | } || \ 80 | { 81 | cp -f ${IMG_ORIG} ${IMG_LIVE} 82 | pr_ok "${IMG_LIVE} created" 83 | } 84 | 85 | pr_header "2.3 create an img file for boot, recovery, and rootfs filesystems" 86 | 87 | PT_ORIG="$(sfdisk -d ${IMG_ORIG})" 88 | 89 | #get the device name for use in the greps 90 | PTABLE_DEVICE=$(echo "${PT_ORIG}" | egrep '^device: ' | cut -d' ' -f2) 91 | 92 | #get the existing sector start/sizes 93 | PTABLE_P1_START=$(echo "${PT_ORIG}" | egrep "^${PTABLE_DEVICE}1" | tr -s ' '| cut -d' ' -f4 | tr -d ',') 94 | PTABLE_P1_SIZE=$(echo "${PT_ORIG}" | egrep "^${PTABLE_DEVICE}1" | tr -s ' '| cut -d' ' -f6 | tr -d ',') 95 | 96 | PTABLE_P2_START=$(echo "${PT_ORIG}" | egrep "^${PTABLE_DEVICE}2" | tr -s ' '| cut -d' ' -f4 | tr -d ',') 97 | PTABLE_P2_SIZE=$(echo "${PT_ORIG}" | egrep "^${PTABLE_DEVICE}2" | tr -s ' '| cut -d' ' -f6 | tr -d ',') 98 | 99 | # PT_ORIG_P3_START=$(echo "${PT_ORIG}" | egrep "^${PTABLE_DEVICE}2" | tr -s ' '| cut -d' ' -f4 | tr -d ',') 100 | # PTABLE_P3_SIZE=$(echo "${}" | egrep "^${PTABLE_DEVICE}2" | tr -s ' '| cut -d' ' -f6 | tr -d ',') 101 | 102 | echo "found boot partition at ${PTABLE_P1_START} with size ${PTABLE_P1_SIZE}" 103 | echo "found root partition at ${PTABLE_P2_START} with size ${PTABLE_P2_SIZE}" 104 | 105 | sudo fdisk -l ${IMG_ORIG} | grep 'Sector size' 106 | 107 | # # set the size of the new recovery partition in bytes 108 | # ## $(( 2 * 1024**3 )) e.g. 2GiB 109 | # # this should be a multipe of 512 otherwise bad things might happen 110 | # P2_NEWSIZE_BYTES=4294967296 111 | # 112 | # # how many sectors is that? 113 | # P2_SECTORS=$(( ${P2_NEWSIZE_BYTES} / 512 )) 114 | P2_SECTORS=$(( ${PTABLE_P2_SIZE}*2 )) 115 | echo "P2 sectors is ${P2_SECTORS}" 116 | 117 | P2_END=$(( PTABLE_P2_START + ${P2_SECTORS} )) 118 | echo "P2_END is ${P2_END}" 119 | 120 | # use the sector at the end of P2, find how many bytes that is 121 | # start P3 at the next 8192 boundary after that 122 | PTABLE_P3_START=$(( ((((( P2_END * 512 ) / 8192) + 1) * 8192)/512) )) 123 | 124 | # this would need to be much bigger for the desktop/full fat img 125 | [[ -f "${IMG_RESTORE}" ]] && \ 126 | { 127 | pr_warn "restore file ${IMG_RESTORE} already, exists - overwriting" 128 | dd if=/dev/zero bs=1K count=${NEW_FILE_SIZE} > ${IMG_RESTORE} 129 | } || \ 130 | { 131 | dd if=/dev/zero bs=1K count=${NEW_FILE_SIZE} > ${IMG_RESTORE} 132 | # touch ${IMG_RESTORE} 133 | } 134 | 135 | pr_header "2.4 Verify that the img file was created" 136 | fdisk -lu ${IMG_RESTORE} 137 | 138 | pr_header "2.5 create the filesystem on the img file" 139 | pr_warn "making partition table..." 140 | 141 | #${IMG_RESTORE}2 : start=${PTABLE_P2_START}, size=${P2_SECTORS}, type=83 142 | 143 | sfdisk ${IMG_RESTORE} < /etc/shadow.new 374 | 375 | #sudo sed "s/^pi:\(.*\):\(.*\):\(.*\):\(.*\):\(.*\):\(.*\):\(.*\)/pi:${newpass}:\2:\3:\4:\5:\6:\7/" mnt/restore_rootfs/etc/shadow 376 | 377 | pr_alert "insert the pi user password" 378 | sudo awk -v var="${newpass}" \ 379 | -F: 'BEGIN{OFS=":";} $1=="pi"{$2=var}1' \ 380 | mnt/restore_rootfs/etc/shadow \ 381 | > shadow.1 \ 382 | && sudo cp -f shadow.1 mnt/restore_rootfs/etc/shadow 383 | 384 | sudo chown 0:42 mnt/restore_rootfs/etc/shadow 385 | sudo chmod 640 mnt/restore_rootfs/etc/shadow 386 | 387 | sudo awk -v var="${newpass}" \ 388 | -F: 'BEGIN{OFS=":";} $1=="pi"{$2=var}1' \ 389 | mnt/restore_recovery/etc/shadow \ 390 | > shadow.2 \ 391 | && sudo cp -f shadow.2 mnt/restore_recovery/etc/shadow 392 | 393 | sudo chown 0:42 mnt/restore_recovery/etc/shadow 394 | sudo chmod 640 mnt/restore_recovery/etc/shadow 395 | 396 | } 397 | 398 | 399 | # perl -pe 's|(root):(\$.*?:)|\1:\$6\$SALTsalt\$UiZikbV3VeeBPsg8./Q5DAfq9aj7CVZMDU6ffBiBLgUEpxv7LMXKbcZ9JSZnYDrZQftdG319XkbLVMvWcF/Vr/:|' \ 400 | # /etc/shadow > /etc/shadow.new 401 | # python -c "import crypt, getpass, pwd; \ 402 | # print crypt.crypt('password', '\$6\$SALTsalt\$')" 403 | 404 | pr_header "copy the recovery image to the recovery /opt dir for restoring" 405 | 406 | # dd if=${LOOP_RESTORE}p3 of=mnt/restore_recovery/opt/recovery.img bs=4M 407 | sudo dd bs=4M if=${LOOP_RESTORE}p3 | sudo zip mnt/restore_recovery/opt/recovery.img.zip - 408 | 409 | 410 | 411 | pr_header "recovery image..." 412 | pr_ok "recovery image is ${IMG_RESTORE}" 413 | 414 | } 415 | 416 | 417 | function cleanup() 418 | { 419 | 420 | pr_header "don't need partitions anymore unmount" 421 | sudo umount -f -d mnt/restore_boot || true 422 | sudo umount -f -d mnt/restore_rootfs || true 423 | sudo umount -f -d mnt/restore_recovery || true 424 | 425 | pr_header "detach loop devices" 426 | sudo losetup --detach-all 427 | 428 | } 429 | 430 | # get current source dir, even if its hidden in links 431 | SOURCE="${BASH_SOURCE[0]}" 432 | while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink 433 | DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" 434 | SOURCE="$(readlink "$SOURCE")" 435 | [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located 436 | done 437 | DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" 438 | 439 | source "${DIR}/display_funcs.sh" 440 | 441 | # if the script failed, cleanup previous run. 442 | # cleanup 443 | 444 | main 445 | 446 | cleanup 447 | --------------------------------------------------------------------------------