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 (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 31 vfstab=${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(1M) 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 # 54 readvfstab() { 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 74 readswapdev() { 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 # 106 readmnttab() { 107 while read special mountp fstype mntopts mnttime; do 108 [ "x$mountp" = "x$1" ] && break 109 done 110 } 111 112 cecho() { 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 # 124 checkmessage() { 125 cecho "" 126 cecho "WARNING - Unable to repair the $3 filesystem. Run fsck" 127 cecho "manually (fsck -F $2 $1)." 128 cecho "" 129 } 130 131 checkmessage2() { 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 # 155 checkfs() { 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 # 223 checkopt() { 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 # 254 hasopts() { 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 # 287 mounted() { 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(1M) [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(1M). 318 # 319 mountfs() { 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 }