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