#!/bin/sh # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T. # All rights reserved. # # #ident "%Z%%M% %I% %E% SMI" setvar vfstab = ${vfstab:=/etc/vfstab} # # readvfstab mount_point # -> (special, fsckdev, mountp, fstype, fsckpass, automnt, mntopts) # # A vfstab-like input stream is scanned for the mount point specified # as $1. Returns the fields of vfstab in the following shell # variables: # # special block device # fsckdev raw device # mountp mount point (must match $1, if found) # fstype file system type # fsckpass fsck(1M) pass number # automnt automount flag (yes or no) # mntopts file system-specific mount options. # # If the mount point can not be found in the standard input stream, # then all fields are set to empty values. This function assumes that # stdin is already set /etc/vfstab (or other appropriate input # stream). # proc readvfstab { while read special fsckdev mountp fstype fsckpass automnt mntopts { match $special { with '' # Ignore empty lines. continue with '#'* # Ignore comment lines. continue with '-' # Ignore "no-action" lines. continue } test "x$mountp" = "x$1" && break } } proc readswapdev { while read special fsckdev mountp fstype fsckpass automnt mntopts { # Ignore comments, empty lines, and no-action lines match $special { with '#'* | '' | '-' continue } test $fstype != swap && continue test "x$special" = "x$1" && break } } # # readmnttab mount_point # -> (special, mountp, fstype, mntopts, mnttime) # # A mnttab-like input stream is scanned for the mount point specified # as $1. Returns the fields of mnttab in the following shell # variables: # # special block device # mountp mount point (must match $1, if found) # fstype file system type # mntopts file system-specific mount options. # mnttime time at which file system was mounted # # If the mount point can not be found in the standard input stream, # then all fields are set to empty values. This function assumes that # stdin is already set to /etc/mnttab (or other appropriate input # stream). # proc readmnttab { while read special mountp fstype mntopts mnttime { test "x$mountp" = "x$1" && break } } proc cecho { echo $ifsjoin(ARGV) echo $ifsjoin(ARGV) >/dev/msglog } # # checkmessage raw_device fstype mountpoint # checkmessage2 raw_device fstype mountpoint # # Two simple auxilary routines to the shell function checkfs. Both # display instructions for a manual file system check. # proc checkmessage { cecho "" cecho "WARNING - Unable to repair the $3 filesystem. Run fsck" cecho "manually (fsck -F $2 $1)." cecho "" } proc checkmessage2 { cecho "" cecho "WARNING - fatal error from fsck - error $4" cecho "Unable to repair the $3 filesystem. Run fsck manually" cecho "(fsck -F $2 $1)." cecho "" } # # checkfs raw_device fstype mountpoint # # Check the file system specified. The return codes from fsck have the # following meanings. # # 0 file system is unmounted and okay # 32 file system is unmounted and needs checking (fsck -m only) # 33 file system is already mounted # 34 cannot stat device # 35 modified root or something equally dangerous # 36 uncorrectable errors detected - terminate normally (4.1 code 8) # 37 a signal was caught during processing (4.1 exit 12) # 39 uncorrectable errors detected - terminate rightaway (4.1 code 8) # 40 for root, same as 0 (used here to remount root) # proc checkfs { # skip checking if the fsckdev is "-" test "x$1" = x- && return # if fsck isn't present, it is probably because either the mount of # /usr failed or the /usr filesystem is badly damanged. In either # case, there is not much to be done automatically. Fail with # a message to the user. if test ! -x /usr/sbin/fsck { cecho "" cecho "WARNING - /usr/sbin/fsck not found. Most likely the" cecho "mount of /usr failed or the /usr filesystem is badly" cecho "damaged." cecho "" return 1 } # If a filesystem-specific fsck binary is unavailable, then no # fsck pass is required. test ! -x /usr/lib/fs/$2/fsck && test ! -x /etc/fs/$2/fsck && return /usr/sbin/fsck -F $2 -m $1 >/dev/null 2>&1 if test $Status -ne 0 { # Determine fsck options by file system type match $2 { with ufs setvar foptions = ""-o p"" with * setvar foptions = ""-y"" } cecho "The $3 file system ($1) is being checked." /usr/sbin/fsck -F $2 $foptions $1 match $Status { with 0|40 # File system OK with 1|34|36|37|39 # couldn't fix the file system - fail checkmessage $1 $2 $3 return 1 with 33 # already mounted return 0 with * # fsck child process killed (+ error code 35) checkmessage2 $1 $2 $3 "$Status" return 1 } } return 0 } # # checkopt option option-string # -> ($option, $otherops) # # Check to see if a given mount option is present in the comma # separated list gotten from vfstab. # # Returns: # ${option} : the option if found the empty string if not found # ${otherops} : the option string with the found option deleted # proc checkopt { setvar option = '' setvar otherops = '' test "x$2" = x- && return setvar searchop = "$1" set -- $(setvar IFS = ',' ; echo $2) while test $Argc -gt 0 { if test "x$1" = "x$searchop" { setvar option = "$1" } else { if test -z $otherops { setvar otherops = "$1" } else { setvar otherops = ""${otherops},$1"" } } shift } } # # hasopts $opts $allopts # # Check if all options from the list $opts are present in $allopts. # Both $opts and $allopts should be in comma separated format. # # Return 0 on success, and 1 otherwise. # proc hasopts { setvar opts = "$1" setvar allopts = "$2" set -- $(setvar IFS = ',' ; echo $opts) while test $Argc -gt 0 { if test $1 != "remount" { checkopt $1 $allopts # # Don't report errors if the filesystem is already # read-write when mounting it as read-only. # test -z $option && test $1 = "ro" && \ checkopt rw $allopts test -z $option && return 1 } shift } return 0 } # # mounted $path $fsopts $fstype # # Check whether the specified file system of the given type is currently # mounted with all required filesystem options by going through /etc/mnttab # in our standard input. # # Return values: # 0 Success. # 1 The filesystem is not currently mounted, or mounted without required # options, or a filesystem of a different type is mounted instead. # proc mounted { setvar path = "$1" setvar fsopts = "$2" setvar fstype = "$3" while read mntspec mntpath mnttype mntopts on { test $mntpath = $path || continue test $fstype != "-" && test $mnttype != $fstype && return 1 test $fsopts = "-" && return 0 hasopts $fsopts $mntopts && return 0 } return 1 } # # mountfs $opts $path $type $fsopts $special # # Try to mount a filesystem. If failed, display our standard error # message on the console and print more details about what happened # to our service log. # # Arguments: # $opts - options for mount(1M) [optional] # $path - mount point # $type - file system type [optional] # $fsopts - file system specific options (-o) [optional] # $special - device on which the file system resides [optional] # # Return codes: # 0 - success. # otherwise - error code returned by mount(1M). # proc mountfs { setvar opts = "$1" setvar path = "$2" setvar special = "$5" # # Take care of optional arguments # test $opts = "-" && setvar opts = """" test $special = "-" && setvar special = """" test $3 = "-" && setvar type = """" test $3 != "-" && setvar type = ""-F $3"" test $4 = "-" && setvar fsopts = """" test $4 != "-" && setvar fsopts = ""-o $4"" setvar cmd = ""/sbin/mount $opts $type $fsopts $special $path"" setvar msg = $($cmd ) setvar err = "$Status" test $err = 0 && return 0 # # If the specified file system is already mounted with all # required options, and has the same filesystem type # then ignore errors and return success # mounted $path $4 $3 < /etc/mnttab && return 0 echo "ERROR: $SMF_FMRI failed to mount $path "\ "(see 'svcs -x' for details)" > /dev/msglog echo "ERROR: $cmd failed, err=$err" echo $msg return $err }