1#!/sbin/sh 2# 3# CDDL HEADER START 4# 5# The contents of this file are subject to the terms of the 6# Common Development and Distribution License, Version 1.0 only 7# (the "License"). You may not use this file except in compliance 8# with the License. 9# 10# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 11# or http://www.opensolaris.org/os/licensing. 12# See the License for the specific language governing permissions 13# and limitations under the License. 14# 15# When distributing Covered Code, include this CDDL HEADER in each 16# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 17# If applicable, add the following below this CDDL HEADER, with the 18# fields enclosed by brackets "[]" replaced with your own identifying 19# information: Portions Copyright [yyyy] [name of copyright owner] 20# 21# CDDL HEADER END 22# 23# 24# Copyright 2005 Sun Microsystems, Inc. All rights reserved. 25# Use is subject to license terms. 26# 27 28PATH=/sbin:/usr/bin:/usr/sbin 29LC_ALL=C 30export PATH LC_ALL 31 32. /lib/svc/share/smf_include.sh 33. /lib/svc/share/fs_include.sh 34 35usage() 36{ 37 echo "usage: $0 [-r rootdir]" >&2 38 echo " 39See http://illumos.org/msg/SMF-8000-MY for more information on the use of 40this script." 41 exit 2; 42} 43 44repositorydir=etc/svc 45repository=repository 46 47myroot=/ 48while getopts r: opt; do 49 case "$opt" in 50 r) myroot=$OPTARG 51 if [ ! -d $myroot ]; then 52 echo "$myroot: not a directory" >&2 53 exit 1 54 fi 55 # validate directory and make sure it ends in '/'. 56 case "$myroot" in 57 //*) echo "$myroot: must begin with a single /" >&2 58 usage;; 59 /) echo "$myroot: alternate root cannot be /" >&2 60 usage;; 61 62 /*/) ;; # ends with / 63 /*) myroot="$myroot/";; # add final / 64 65 *) echo "$myroot: must be a full path" >&2 66 usage;; 67 esac;; 68 ?) usage;; 69 esac 70done 71 72if [ $OPTIND -le $# ]; then 73 # getopts(1) didn't slurp up everything. 74 usage 75fi 76 77# 78# Note that the below test is carefully constructed to fail *open*; if 79# anything goes wrong, it will drive onward. 80# 81if [ -x /usr/bin/id -a -x /usr/bin/grep ] && 82 /usr/bin/id 2>/dev/null | /usr/bin/grep -v '^[^=]*=0(' >/dev/null 2>&1; then 83 echo "$0: may only be invoked by root" >&2 84 exit 2 85fi 86 87echo >&2 " 88See http://illumos.org/msg/SMF-8000-MY for more information on the use of 89this script to restore backup copies of the smf(5) repository. 90 91If there are any problems which need human intervention, this script will 92give instructions and then exit back to your shell." 93 94if [ "$myroot" -eq / ]; then 95 system="system" 96 [ "`/sbin/zonename`" != global ] && system="zone" 97 echo >&2 " 98Note that upon full completion of this script, the $system will be rebooted 99using reboot(1M), which will interrupt any active services. 100" 101fi 102 103# check that the filesystem is as expected 104cd "$myroot" || exit 1 105cd "$myroot$repositorydir" || exit 1 106 107nouser=false 108rootro=false 109 110# check to make sure /usr is mounted 111if [ ! -x /usr/bin/pgrep ]; then 112 nouser=true 113fi 114 115if [ ! -w "$myroot" ]; then 116 rootro=true 117fi 118 119if [ "$nouser" = true -o "$rootro" = true ]; then 120 if [ "$nouser" = true -a "$rootro" = true ]; then 121 echo "The / filesystem is mounted read-only, and the /usr" >&2 122 echo "filesystem has not yet been mounted." >&2 123 elif [ "$nouser" = true ]; then 124 echo "The /usr filesystem has not yet been mounted." >&2 125 else 126 echo "The / filesystem is mounted read-only." >&2 127 fi 128 129 echo >&2 " 130This must be rectified before $0 can continue. 131 132If / or /usr are on SVM (md(7d)) partitions, first run 133 /lib/svc/method/svc-metainit 134 135To properly mount / and /usr, run: 136 /lib/svc/method/fs-root 137then 138 /lib/svc/method/fs-usr 139 140After those have completed successfully, re-run: 141 $0 $* 142 143to continue. 144" 145 exit 1 146fi 147 148# at this point, we know / is mounted read-write, and /usr is mounted. 149oldreps="` 150 /bin/ls -1rt $repository-*-[0-9]*[0-9] | \ 151 /bin/sed -e '/[^A-Za-z0-9_,.-]/d' -e 's/^'$repository'-//' 152`" 153 154if [ -z "$oldreps" ]; then 155 cat >&2 <<EOF 156There are no available backups of $myroot$repositorydir/$repository.db. 157The only available repository is "-seed-". Note that restoring the seed 158will lose all customizations, including those made by the system during 159the installation and/or upgrade process. 160 161EOF 162 prompt="Enter -seed- to restore from the seed, or -quit- to exit: \c" 163 default= 164else 165 cat >&2 <<EOF 166The following backups of $myroot$repositorydir/$repository.db exist, from 167oldest to newest: 168 169$oldreps 170 171The backups are named based on their type and the time what they were taken. 172Backups beginning with "boot" are made before the first change is made to 173the repository after system boot. Backups beginning with "manifest_import" 174are made after svc:/system/manifest-import:default finishes its processing. 175The time of backup is given in YYYYMMDD_HHMMSS format. 176 177Please enter either a specific backup repository from the above list to 178restore it, or one of the following choices: 179 180 CHOICE ACTION 181 ---------------- ---------------------------------------------- 182 boot restore the most recent post-boot backup 183 manifest_import restore the most recent manifest_import backup 184 -seed- restore the initial starting repository (All 185 customizations will be lost, including those 186 made by the install/upgrade process.) 187 -quit- cancel script and quit 188 189EOF 190 prompt="Enter response [boot]: \c" 191 default="boot" 192fi 193 194cont=false 195while [ $cont = false ]; do 196 echo "$prompt" 197 198 read x || exit 1 199 [ -z "$x" ] && x="$default" 200 201 case "$x" in 202 -seed-) 203 if [ $myroot != / -o "`/sbin/zonename`" = global ]; then 204 file="$myroot"lib/svc/seed/global.db 205 else 206 file="$myroot"lib/svc/seed/nonglobal.db 207 fi;; 208 -quit-) 209 echo "Exiting." 210 exit 0;; 211 /*) 212 file="$x";; 213 */*) 214 file="$myroot$x";; 215 ?*) 216 file="$myroot$repositorydir/repository-$x";; 217 *) file= ;; 218 esac 219 220 if [ -f $file ]; then 221 if [ -r $file ]; then 222 checkresults="`echo PRAGMA integrity_check\; | \ 223 /lib/svc/bin/sqlite $file >&1 | grep -v '^ok$'`" 224 225 if [ -n "$checkresults" ]; then 226 echo "$file: integrity check failed:" >&2 227 echo "$checkresults" >&2 228 echo 229 else 230 cont=true 231 fi 232 else 233 echo "$file: not readable" 234 fi 235 elif [ -n "$file" ]; then 236 echo "$file: not found" 237 fi 238done 239 240errors="$myroot"etc/svc/volatile/db_errors 241repo="$myroot$repositorydir/$repository.db" 242new="$repo"_old_"`date +%Y''%m''%d'_'%H''%M''%S`" 243 244steps= 245if [ "$myroot" = / ]; then 246 steps="$steps 247svc.startd(1M) and svc.configd(1M) will be quiesced, if running." 248fi 249 250if [ -r $repo ]; then 251 steps="$steps 252$repo 253 -- renamed --> $new" 254fi 255if [ -r $errors ]; then 256 steps="$steps 257$errors 258 -- copied --> ${new}_errors" 259fi 260 261cat >&2 <<EOF 262 263After confirmation, the following steps will be taken: 264$steps 265$file 266 -- copied --> $repo 267EOF 268 269if [ "$myroot" = / ]; then 270 echo "and the system will be rebooted with reboot(1M)." 271fi 272 273echo 274cont=false 275while [ $cont = false ]; do 276 echo "Proceed [yes/no]? \c" 277 read x || x=n 278 279 case "$x" in 280 [Yy]|[Yy][Ee][Ss]) 281 cont=true;; 282 [Nn]|[Nn][Oo]) 283 echo; echo "Exiting..." 284 exit 0; 285 esac; 286done 287 288umask 077 # we want files to be root-readable only. 289 290startd_msg= 291if [ "$myroot" = / ]; then 292 zone="`zonename`" 293 startd="`pgrep -z "$zone" -f svc.startd`" 294 295 echo 296 echo "Quiescing svc.startd(1M) and svc.configd(1M): \c" 297 if [ -n "$startd" ]; then 298 pstop $startd 299 startd_msg=\ 300"To start svc.start(1M) running, do: /usr/bin/prun $startd" 301 fi 302 pkill -z "$zone" -f svc.configd 303 304 sleep 1 # yes, this is hack 305 306 echo "done." 307fi 308 309if [ -r "$repo" ]; then 310 echo "$repo" 311 echo " -- renamed --> $new" 312 if mv $repo $new; then 313 : 314 else 315 echo "Failed. $startd_msg" 316 exit 1; 317 fi 318fi 319 320if [ -r $errors ]; then 321 echo "$errors" 322 echo " -- copied --> ${new}_errors" 323 if cp -p $errors ${new}_errors; then 324 : 325 else 326 mv -f $new $repo 327 echo "Failed. $startd_msg" 328 exit 1; 329 fi 330fi 331 332echo "$file" 333echo " -- copied --> $repo" 334 335if cp $file $repo.new.$$ && mv $repo.new.$$ $repo; then 336 : 337else 338 rm -f $repo.new.$$ ${new}_errors 339 mv -f $new $repo 340 echo "Failed. $startd_msg" 341 exit 1; 342fi 343 344echo 345echo "The backup repository has been successfully restored." 346echo 347 348if [ "$myroot" = / ]; then 349 echo "Rebooting in 5 seconds." 350 sleep 5 351 reboot 352fi 353