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 #
25 # Copyright 2009 Sun Microsystems, Inc. All rights reserved.
26 # Use is subject to license terms.
27 #
28 # Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T
29 # All Rights Reserved
30 #
31
32 usage () {
33 if [ -n "$1" ]; then
34 echo "mountall: $1" 1>&2
35 fi
36 echo "Usage:\nmountall [-F FSType] [-l|-r|-g] [file_system_table]" 1>&2
37 exit 2
38 }
39
40 PATH=/usr/sbin:/usr/bin
41 TYPES=all
42 FSTAB=/etc/vfstab
43 err=0
44
45 # Clear these in case they were already set in our environment.
46 FSType=
47 GFLAG=
48 RFLAG=
49 LFLAG=
50 SFLAG=
51 RemoteFSTypes=
52
53 # checkmessage "fsck_device | mount_point"
54 #
55 # Simple auxilary routine to the shell function checkfs. Prints out
56 # instructions for a manual file system check before entering the shell.
57 #
58 checkmessage() {
59 echo "" > /dev/console
60 if [ "$1" != "" ] ; then
61 echo "WARNING - Unable to repair one or more \c" > /dev/console
62 echo "of the following filesystem(s):" > /dev/console
63 echo "\t$1" > /dev/console
64 else
65 echo "WARNING - Unable to repair one or more filesystems." \
66 > /dev/console
67 fi
68 echo "Run fsck manually (fsck filesystem...)." > /dev/console
69 echo "" > /dev/console
70 }
71
72 #
73 # checkfs raw_device fstype mountpoint
74 #
75 # Check the file system specified. The return codes from fsck have the
76 # following meanings.
77 # 0 - file system is unmounted and okay
78 # 32 - file system is unmounted and needs checking (fsck -m only)
79 # 33 - file system is already mounted
80 # 34 - cannot stat device
81 # 36 - uncorrectable errors detected - terminate normally (4.1 code 8)
82 # 37 - a signal was caught during processing (4.1 exit 12)
83 # 39 - uncorrectable errors detected - terminate rightaway (4.1 code 8)
84 # 40 - for root, same as 0 (used by rcS to remount root)
85 #
86 checkfs() {
87 /usr/sbin/fsck -F $2 -m $1 >/dev/null 2>&1
88
89 if [ $? -ne 0 ]
90 then
91 # Determine fsck options by file system type
92 case "$2" in
93 ufs) foptions="-o p"
94 ;;
95 *) foptions="-y"
96 ;;
97 esac
98
99 echo "The "$3" file system ("$1") is being checked."
100 /usr/sbin/fsck -F $2 ${foptions} $1
101
102 case $? in
103 0|40) # file system OK
104 ;;
105
106 *) # couldn't fix the file system
107 echo "/usr/sbin/fsck failed with exit code "$?"."
108 checkmessage "$1"
109 ;;
110 esac
111 fi
112 }
113
114 #
115 # Used to save an entry that we will want to mount either in
116 # a command file or as a mount point list.
117 #
118 # saveentry fstype options special mountp
119 #
120 saveentry() {
121 if [ "$ALTM" ]; then
122 echo "/sbin/mount -F $1 $2 $3 $4" >> $ALTM
123 else
124 mntlist="$mntlist $4"
125 fi
126 }
127
128 # Do the passed mount options include "global"?
129 isglobal() {
130 case ",${1}," in
131 *,global,*)
132 return 0
133 ;;
134 esac
135 return 1
136 }
137
138 # Is the passed fstype a "remote" one?
139 # Essentially: /usr/bin/grep "^$1" /etc/dfs/fstypes
140 isremote() {
141 for t in $RemoteFSTypes
142 do
143 [ "$t" = "$1" ] && return 0
144 done
145 return 1
146 }
147
148 # Get list of remote FS types (just once)
149 RemoteFSTypes=`while read t junk; do echo $t; done < /etc/dfs/fstypes`
150
151
152 #
153 # Process command line args
154 #
155 while getopts ?grlsF: c
156 do
157 case $c in
158 g) GFLAG="g";;
159 r) RFLAG="r";;
160 l) LFLAG="l";;
161 s) SFLAG="s";;
162 F) FSType="$OPTARG";
163 if [ "$TYPES" = "one" ]
164 then
165 echo "mountall: more than one FSType specified"
166 exit 2
167 fi
168 TYPES="one";
169
170 case $FSType in
171 ?????????*)
172 echo "mountall: FSType $FSType exceeds 8 characters"
173 exit 2
174 esac
175 ;;
176 \?) usage "";;
177 esac
178 done
179
180 shift `/usr/bin/expr $OPTIND - 1` # get past the processed args
181
182 if [ $# -gt 1 ]; then
183 usage "multiple arguments not supported"
184 fi
185
186 # get file system table name and make sure file exists
187 if [ $# = 1 ]; then
188 case $1 in
189 "-") FSTAB=""
190 ;;
191 *) FSTAB=$1
192 ;;
193 esac
194 fi
195 #
196 # if an alternate vfstab file is used or serial mode is specified, then
197 # use a mount command file
198 #
199 if [ $# = 1 -o "$SFLAG" ]; then
200 ALTM=/var/tmp/mount$$
201 rm -f $ALTM
202 fi
203
204 if [ "$FSTAB" != "" -a ! -s "$FSTAB" ]
205 then
206 echo "mountall: file system table ($FSTAB) not found"
207 exit 1
208 fi
209
210 #
211 # Check for incompatible args
212 #
213 if [ "$GFLAG" = "g" -a "$RFLAG$LFLAG" != "" -o \
214 "$RFLAG" = "r" -a "$GFLAG$LFLAG" != "" -o \
215 "$LFLAG" = "l" -a "$RFLAG$GFLAG" != "" ]
216 then
217 usage "options -g, -r and -l are mutually exclusive"
218 fi
219
220 if [ "$LFLAG" = "l" -a -n "$FSType" ]; then
221 # remote FSType not allowed
222 isremote "$FSType" &&
223 usage "option -l and FSType are incompatible"
224 fi
225
226 if [ "$RFLAG" = "r" -a -n "$FSType" ]; then
227 # remote FSType required
228 isremote "$FSType" ||
229 usage "option -r and FSType are incompatible"
230 fi
231
232 # file-system-table format:
233 #
234 # column 1: special- block special device or resource name
235 # column 2: fsckdev- char special device for fsck
236 # column 3: mountp- mount point
237 # column 4: fstype- File system type
238 # column 5: fsckpass- number if to be checked automatically
239 # column 6: automnt- yes/no for automatic mount
240 # column 7: mntopts- -o specific mount options
241
242 # White-space separates columns.
243 # Lines beginning with \"#\" are comments. Empty lines are ignored.
244 # a '-' in any field is a no-op.
245
246 #
247 # Read FSTAB, fsck'ing appropriate filesystems:
248 #
249 exec < $FSTAB
250 while read special fsckdev mountp fstype fsckpass automnt mntopts
251 do
252 case $special in
253 '#'* | '') # Ignore comments, empty lines
254 continue ;;
255 '-') # Ignore no-action lines
256 continue
257 esac
258
259 if [ "$automnt" != "yes" ]; then
260 continue
261 fi
262 if [ "$FSType" -a "$FSType" != "$fstype" ]; then
263 # ignore different fstypes
264 continue
265 fi
266
267 # The -g option is not in the man page, but according to
268 # PSARC/1998/255 it's used by Sun Cluster (via contract) to
269 # mount disk-based filesystems with the "global" option.
270 # Also, the -l option now skips those "global" mounts.
271 #
272 # Note: options -g -l -r are mutually exclusive
273 #
274 if [ -n "$GFLAG" ]; then
275 # Mount "local" filesystems that have
276 # the "global" option in mntopts.
277 isremote "$fstype" && continue
278 isglobal "$mntopts" || continue
279 fi
280 if [ -n "$LFLAG" ]; then
281 # Mount "local" filesystems, excluding
282 # those marked "global".
283 isremote "$fstype" && continue
284 isglobal "$mntopts" && continue
285 fi
286 if [ -n "$RFLAG" ]; then
287 # Mount "remote" filesystems.
288 isremote "$fstype" || continue
289 fi
290
291 if [ "$fstype" = "-" ]; then
292 echo "mountall: FSType of $special cannot be identified" 1>&2
293 continue
294 fi
295
296 if [ "$ALTM" -a "$mntopts" != "-" ]; then
297 OPTIONS="-o $mntopts" # Use mount options if any
298 else
299 OPTIONS=""
300 fi
301
302 #
303 # Ignore entries already mounted
304 #
305 /usr/bin/grep " $mountp " /etc/mnttab >/dev/null 2>&1 && continue
306
307 #
308 # Can't fsck if no fsckdev is specified
309 #
310 if [ "$fsckdev" = "-" ]; then
311 saveentry $fstype "$OPTIONS" $special $mountp
312 continue
313 fi
314 #
315 # For fsck purposes, we make a distinction between file systems
316 # that have a /usr/lib/fs/<fstyp>/fsckall script and those
317 # that don't. For those that do, just keep a list of them
318 # and pass the list to the fsckall script for that file
319 # file system type.
320 #
321 if [ -x /usr/lib/fs/$fstype/fsckall ]; then
322
323 #
324 # add fstype to the list of fstypes for which
325 # fsckall should be called, if it's not already
326 # in the list.
327 #
328 found=no
329 if [ "$fsckall_fstypes" != "" ] ; then
330 for fst in $fsckall_fstypes; do
331 if [ "$fst" = "$fstype" ] ; then
332 found=yes
333 break
334 fi
335 done
336 fi
337 if [ $found = no ] ; then
338 fsckall_fstypes="$fsckall_fstypes ${fstype}"
339 fi
340
341 #
342 # add the device to the name of devices to be passed
343 # to the fsckall program for this file system type
344 #
345 cmd="${fstype}_fscklist=\"\$${fstype}_fscklist $fsckdev\""
346 eval $cmd
347 saveentry $fstype "$OPTIONS" $special $mountp
348 continue
349 fi
350 #
351 # fsck everything else:
352 #
353 # fsck -m simply returns true if the filesystem is suitable for
354 # mounting.
355 #
356 /usr/sbin/fsck -m -F $fstype $fsckdev >/dev/null 2>&1
357 case $? in
358 0|40) saveentry $fstype "$OPTIONS" $special $mountp
359 continue
360 ;;
361 32) checkfs $fsckdev $fstype $mountp
362 saveentry $fstype "$OPTIONS" $special $mountp
363 continue
364 ;;
365 33) # already mounted
366 echo "$special already mounted"
367 ;;
368 34) # bogus special device
369 echo "Cannot stat $fsckdev - ignoring"
370 err=1
371 ;;
372 *) # uncorrectable errors
373 echo "$fsckdev uncorrectable error"
374 err=1
375 ;;
376 esac
377 done
378
379 #
380 # Call the fsckall programs
381 #
382 for fst in $fsckall_fstypes
383 do
384 cmd="/usr/lib/fs/$fst/fsckall \$${fst}_fscklist"
385 eval $cmd
386
387 case $? in
388 0) # file systems OK
389 ;;
390
391 *) # couldn't fix some of the filesystems
392 echo "fsckall failed with exit code "$?"."
393 checkmessage
394 ;;
395 esac
396 done
397
398 if [ "$ALTM" ]; then
399 if [ ! -f "$ALTM" ]; then
400 exit
401 fi
402 /sbin/sh $ALTM # run the saved mount commands
403 /usr/bin/rm -f $ALTM
404 exit
405 fi
406
407 if [ -n "$FSType" ]; then
408 /sbin/mount -a -F $FSType
409 exit
410 fi
411
412 # Some remote filesystems (e.g. cachefs or autofs) shouldn't be be mounted
413 # with mountall, so the list here is explicit (not from /etc/dfs/fstypes)
414 if [ "$RFLAG" ]; then
415 /sbin/mount -a -F nfs
416 /sbin/mount -a -F smbfs
417 exit
418 fi
419
420 if [ "$LFLAG" -o "$GFLAG" -o $err != 0 ]; then
421 [ -z "$mntlist" ] || /sbin/mount -a $mntlist
422 exit
423 fi
424
425 # else mount them all
426
427 /sbin/mount -a