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