xref: /illumos-gate/usr/src/cmd/svc/shell/fs_include.sh (revision f998c95e3b7029fe5f7542e115f7474ddb8024d7)
1#!/bin/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 (the "License").
7# You may not use this file except in compliance with the License.
8#
9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10# or http://www.opensolaris.org/os/licensing.
11# See the License for the specific language governing permissions
12# and limitations under the License.
13#
14# When distributing Covered Code, include this CDDL HEADER in each
15# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16# If applicable, add the following below this CDDL HEADER, with the
17# fields enclosed by brackets "[]" replaced with your own identifying
18# information: Portions Copyright [yyyy] [name of copyright owner]
19#
20# CDDL HEADER END
21#
22#
23# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24# Use is subject to license terms.
25#
26# Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T.
27# All rights reserved.
28#
29#
30#ident	"%Z%%M%	%I%	%E% SMI"
31
32vfstab=${vfstab:=/etc/vfstab}
33
34#
35# readvfstab mount_point
36#   -> (special, fsckdev, mountp, fstype, fsckpass, automnt, mntopts)
37#
38#   A vfstab-like input stream is scanned for the mount point specified
39#   as $1.  Returns the fields of vfstab in the following shell
40#   variables:
41#
42#       special		block device
43#       fsckdev		raw device
44#       mountp		mount point (must match $1, if found)
45#       fstype		file system type
46#       fsckpass	fsck(1M) pass number
47#       automnt		automount flag (yes or no)
48#       mntopts		file system-specific mount options.
49#
50#   If the mount point can not be found in the standard input stream,
51#   then all fields are set to empty values.  This function assumes that
52#   stdin is already set /etc/vfstab (or other appropriate input
53#   stream).
54#
55readvfstab() {
56	while read special fsckdev mountp fstype fsckpass automnt mntopts; do
57		case "$special" in
58			'' )	# Ignore empty lines.
59				continue
60				;;
61
62			'#'* )	# Ignore comment lines.
63				continue
64				;;
65
66			'-')	# Ignore "no-action" lines.
67				continue
68				;;
69		esac
70
71		[ "x$mountp" = "x$1" ] && break
72	done
73}
74
75#
76# readmnttab mount_point
77#   -> (special, mountp, fstype, mntopts, mnttime)
78#
79#   A mnttab-like input stream is scanned for the mount point specified
80#   as $1.  Returns the fields of mnttab in the following shell
81#   variables:
82#
83#       special		block device
84#       mountp		mount point (must match $1, if found)
85#       fstype		file system type
86#       mntopts		file system-specific mount options.
87#	mnttime		time at which file system was mounted
88#
89#   If the mount point can not be found in the standard input stream,
90#   then all fields are set to empty values.  This function assumes that
91#   stdin is already set to /etc/mnttab (or other appropriate input
92#   stream).
93#
94readmnttab() {
95	while read special mountp fstype mntopts mnttime; do
96		[ "x$mountp" = "x$1" ] && break
97	done
98}
99
100cecho() {
101	echo $*
102	echo $* >/dev/msglog
103}
104
105#
106# checkmessage raw_device fstype mountpoint
107# checkmessage2 raw_device fstype mountpoint
108#
109#   Two simple auxilary routines to the shell function checkfs.  Both
110#   display instructions for a manual file system check.
111#
112checkmessage() {
113	cecho ""
114	cecho "WARNING - Unable to repair the $3 filesystem. Run fsck"
115	cecho "manually (fsck -F $2 $1)."
116	cecho ""
117}
118
119checkmessage2() {
120	cecho ""
121	cecho "WARNING - fatal error from fsck - error $4"
122	cecho "Unable to repair the $3 filesystem. Run fsck manually"
123	cecho "(fsck -F $2 $1)."
124	cecho ""
125}
126
127#
128# checkfs raw_device fstype mountpoint
129#
130#   Check the file system specified. The return codes from fsck have the
131#   following meanings.
132#
133#	 0	file system is unmounted and okay
134#	32	file system is unmounted and needs checking (fsck -m only)
135#	33	file system is already mounted
136#	34	cannot stat device
137#	35	modified root or something equally dangerous
138#	36	uncorrectable errors detected - terminate normally (4.1 code 8)
139#	37	a signal was caught during processing (4.1 exit 12)
140#	39	uncorrectable errors detected - terminate rightaway (4.1 code 8)
141#	40	 for root, same as 0 (used here to remount root)
142#
143checkfs() {
144	# skip checking if the fsckdev is "-"
145	[ "x$1" = x- ] && return
146
147	# if fsck isn't present, it is probably because either the mount of
148	# /usr failed or the /usr filesystem is badly damanged.  In either
149	# case, there is not much to be done automatically.  Fail with
150	# a message to the user.
151	if [ ! -x /usr/sbin/fsck ]; then
152		cecho ""
153		cecho "WARNING - /usr/sbin/fsck not found.  Most likely the"
154		cecho "mount of /usr failed or the /usr filesystem is badly"
155		cecho "damaged."
156		cecho ""
157		return 1
158	fi
159
160	# If a filesystem-specific fsck binary is unavailable, then no
161	# fsck pass is required.
162	[ ! -x /usr/lib/fs/$2/fsck ] && [ ! -x /etc/fs/$2/fsck ] && return
163
164	/usr/sbin/fsck -F $2 -m $1 >/dev/null 2>&1
165
166	if [ $? -ne 0 ]; then
167		# Determine fsck options by file system type
168		case $2 in
169			ufs)	foptions="-o p"
170				;;
171			*)	foptions="-y"
172				;;
173		esac
174
175		cecho "The $3 file system ($1) is being checked."
176		/usr/sbin/fsck -F $2 $foptions $1
177
178		case $? in
179		0|40)	# File system OK
180			;;
181
182		1|34|36|37|39)	# couldn't fix the file system - fail
183			checkmessage "$1" "$2" "$3"
184			return 1
185			;;
186		33)	# already mounted
187			return 0
188			;;
189
190		*)	# fsck child process killed (+ error code 35)
191			checkmessage2 "$1" "$2" "$3" "$?"
192			return 1
193			;;
194		esac
195	fi
196
197	return 0
198}
199
200#
201# checkopt option option-string
202# -> ($option, $otherops)
203#
204#   Check to see if a given mount option is present in the comma
205#   separated list gotten from vfstab.
206#
207#	Returns:
208#	${option}       : the option if found the empty string if not found
209#	${otherops}     : the option string with the found option deleted
210#
211checkopt() {
212	option=
213	otherops=
214
215	[ "x$2" = x- ] && return
216
217	searchop="$1"
218	set -- `IFS=, ; echo $2`
219
220	while [ $# -gt 0 ]; do
221		if [ "x$1" = "x$searchop" ]; then
222			option="$1"
223		else
224			if [ -z "$otherops" ]; then
225				otherops="$1"
226			else
227				otherops="${otherops},$1"
228			fi
229		fi
230		shift
231	done
232}
233
234#
235# hasopts $opts $allopts
236#
237#   Check if all options from the list $opts are present in $allopts.
238#   Both $opts and $allopts should be in comma separated format.
239#
240# Return 0 on success, and 1 otherwise.
241#
242hasopts() {
243	opts="$1"
244	allopts="$2"
245
246	set -- `IFS=, ; echo $opts`
247	while [ $# -gt 0 ]; do
248		if [ "$1" != "remount" ]; then
249			checkopt $1 $allopts
250			#
251			# Don't report errors if the filesystem is already
252			# read-write when mounting it as read-only.
253			#
254			[ -z "$option" ] && [ "$1" = "ro" ] && \
255				checkopt rw $allopts
256			[ -z "$option" ] && return 1
257		fi
258		shift
259	done
260	return 0
261}
262
263#
264# mounted $path $fsopts $fstype
265#
266#   Check whether the specified file system of the given type is currently
267#   mounted with all required filesystem options by going through /etc/mnttab
268#   in our standard input.
269#
270#   Return values:
271#   0	Success.
272#   1	The filesystem is not currently mounted, or mounted without required
273#	options, or a filesystem of a different type is mounted instead.
274#
275mounted() {
276	path="$1"
277	fsopts="$2"
278	fstype="$3"
279
280	while read mntspec mntpath mnttype mntopts on; do
281		[ "$mntpath" = "$path" ] || continue
282		[ "$fstype" != "-" ] && [ "$mnttype" != "$fstype" ] && return 1
283		[ "$fsopts" = "-" ] && return 0
284		hasopts $fsopts $mntopts && return 0
285	done
286	return 1
287}
288
289#
290# mountfs $opts $path $type $fsopts $special
291#
292#   Try to mount a filesystem.  If failed, display our standard error
293#   message on the console and print more details about what happened
294#   to our service log.
295#
296# Arguments:
297#   $opts	- options for mount(1M)				[optional]
298#   $path	- mount point
299#   $type	- file system type				[optional]
300#   $fsopts	- file system specific options (-o)		[optional]
301#   $special	- device on which the file system resides	[optional]
302#
303# Return codes:
304#   0		- success.
305#   otherwise	- error code returned by mount(1M).
306#
307mountfs() {
308	opts="$1"
309	path="$2"
310	special="$5"
311
312	#
313	# Take care of optional arguments
314	#
315	[ "$opts" = "-" ] && opts=""
316	[ "$special" = "-" ] &&	special=""
317	[ "$3" = "-" ] && type=""
318	[ "$3" != "-" ] && type="-F $3"
319	[ "$4" = "-" ] && fsopts=""
320	[ "$4" != "-" ] && fsopts="-o $4"
321
322	cmd="/sbin/mount $opts $type $fsopts $special $path"
323	msg=`$cmd 2>&1`
324	err=$?
325
326	[ $err = 0 ] && return 0
327
328	#
329	# If the specified file system is already mounted with all
330	# required options, and has the same filesystem type
331	# then ignore errors and return success
332	#
333	mounted $path $4 $3 < /etc/mnttab && return 0
334
335	echo "ERROR: $SMF_FMRI failed to mount $path "\
336	     "(see 'svcs -x' for details)" > /dev/msglog
337	echo "ERROR: $cmd failed, err=$err"
338	echo $msg
339	return $err
340}
341