xref: /illumos-gate/usr/src/cmd/svc/configd/restore_repository.sh (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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