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