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