#!/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" 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). # readvfstab() { while read special fsckdev mountp fstype fsckpass automnt mntopts; do case "$special" in '' ) # Ignore empty lines. continue ;; '#'* ) # Ignore comment lines. continue ;; '-') # Ignore "no-action" lines. continue ;; esac [ "x$mountp" = "x$1" ] && break done } # # 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). # readmnttab() { while read special mountp fstype mntopts mnttime; do [ "x$mountp" = "x$1" ] && break done } cecho() { echo $* echo $* >/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. # checkmessage() { cecho "" cecho "WARNING - Unable to repair the $3 filesystem. Run fsck" cecho "manually (fsck -F $2 $1)." cecho "" } 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) # checkfs() { # skip checking if the fsckdev is "-" [ "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 [ ! -x /usr/sbin/fsck ]; then 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 fi # If a filesystem-specific fsck binary is unavailable, then no # fsck pass is required. [ ! -x /usr/lib/fs/$2/fsck ] && [ ! -x /etc/fs/$2/fsck ] && return /usr/sbin/fsck -F $2 -m $1 >/dev/null 2>&1 if [ $? -ne 0 ]; then # Determine fsck options by file system type case $2 in ufs) foptions="-o p" ;; *) foptions="-y" ;; esac cecho "The $3 file system ($1) is being checked." /usr/sbin/fsck -F $2 $foptions $1 case $? in 0|40) # File system OK ;; 1|34|36|37|39) # couldn't fix the file system - fail checkmessage "$1" "$2" "$3" return 1 ;; 33) # already mounted return 0 ;; *) # fsck child process killed (+ error code 35) checkmessage2 "$1" "$2" "$3" "$?" return 1 ;; esac fi 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 # checkopt() { option= otherops= [ "x$2" = x- ] && return searchop="$1" set -- `IFS=, ; echo $2` while [ $# -gt 0 ]; do if [ "x$1" = "x$searchop" ]; then option="$1" else if [ -z "$otherops" ]; then otherops="$1" else otherops="${otherops},$1" fi fi shift done } # # 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. # hasopts() { opts="$1" allopts="$2" set -- `IFS=, ; echo $opts` while [ $# -gt 0 ]; do if [ "$1" != "remount" ]; then checkopt $1 $allopts # # Don't report errors if the filesystem is already # read-write when mounting it as read-only. # [ -z "$option" ] && [ "$1" = "ro" ] && \ checkopt rw $allopts [ -z "$option" ] && return 1 fi shift done 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. # mounted() { path="$1" fsopts="$2" fstype="$3" while read mntspec mntpath mnttype mntopts on; do [ "$mntpath" = "$path" ] || continue [ "$fstype" != "-" ] && [ "$mnttype" != "$fstype" ] && return 1 [ "$fsopts" = "-" ] && return 0 hasopts $fsopts $mntopts && return 0 done 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). # mountfs() { opts="$1" path="$2" special="$5" # # Take care of optional arguments # [ "$opts" = "-" ] && opts="" [ "$special" = "-" ] && special="" [ "$3" = "-" ] && type="" [ "$3" != "-" ] && type="-F $3" [ "$4" = "-" ] && fsopts="" [ "$4" != "-" ] && fsopts="-o $4" cmd="/sbin/mount $opts $type $fsopts $special $path" msg=`$cmd 2>&1` err=$? [ $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 }