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 2006 Sun Microsystems, Inc. All rights reserved. 24# Use is subject to license terms. 25# 26#pragma ident "%Z%%M% %I% %E% SMI" 27# 28# Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T 29# All Rights Reserved 30# 31# 32 33usage () { 34 if [ -n "$1" ]; then 35 echo "umountall: $1" 1>&2 36 fi 37 echo "Usage:\n\tumountall [-k] [-s] [-F FSType] [-l|-r] [-n]" 1>&2 38 echo "\tumountall [-k] [-s] [-h host] [-n]" 1>&2 39 exit 2 40} 41 42MNTTAB=/etc/mnttab 43 44# This script is installed as both /sbin/umountall (as used in some 45# /sbin/rc? and /etc/init.d scripts) _and_ as /usr/sbin/umountall (typically 46# PATHed from the command line). As such it should not depend on /usr 47# being mounted (if /usr is a separate filesystem). 48# 49# /sbin/sh Bourne shell builtins we use: 50# echo 51# exit 52# getopts 53# test, [ ] 54# exec 55# read 56# 57# /sbin commands we use: 58# /sbin/uname 59# /sbin/umount 60# 61# The following /usr based commands may be used by this script (depending on 62# command line options). We will set our PATH to find them, but where they 63# are not present (eg, if /usr is not mounted) we will catch references to 64# them via shell functions conditionally defined after option processing 65# (don't use any of these commands before then). 66# 67# Command Command line option and use 68# /usr/bin/sleep -k, to sleep after an fuser -c -k on the mountpoint 69# /usr/sbin/fuser -k, to kill processes keeping a mount point busy 70# 71# In addition, we use /usr/bin/tail if it is available; if not we use 72# slower shell constructs to reverse a file. 73 74PATH=/sbin:/usr/sbin:/usr/bin 75 76# Clear these in case they were already set in our inherited environment. 77FSType= 78FFLAG= 79HOST= 80HFLAG= 81RFLAG= 82LFLAG= 83SFLAG= 84KFLAG= 85NFLAG= 86LOCALNAME= 87UMOUNTFLAG= 88 89 90while getopts ?rslkF:h:n c 91do 92 case $c in 93 r) RFLAG="r";; 94 l) LFLAG="l";; 95 s) SFLAG="s";; 96 k) KFLAG="k";; 97 h) if [ -n "$HFLAG" ]; then 98 usage "more than one host specified" 99 fi 100 HOST=$OPTARG 101 HFLAG="h" 102 LOCALNAME=`uname -n` 103 ;; 104 F) if [ -n "$FFLAG" ]; then 105 usage "more than one FStype specified" 106 fi 107 FSType=$OPTARG 108 FFLAG="f" 109 case $FSType in 110 ?????????*) 111 usage "FSType ${FSType} exceeds 8 characters" 112 esac; 113 ;; 114 n) NFLAG="n" 115 # Alias any commands that would perform real actions to 116 # something that tells what action would have been performed 117 UMOUNTFLAG="-V" 118 fuser () { 119 echo "fuser $*" 1>&2 120 } 121 sleep () { 122 : # No need to show where we'd sleep 123 } 124 ;; 125 \?) usage "" 126 ;; 127 esac 128done 129 130# Sanity checking: 131# 1) arguments beyond those supported 132# 2) can't specify both remote and local 133# 3) can't specify a host with -r or -l 134# 4) can't specify a fstype with -h 135# 5) can't specify this host with -h (checks only uname -n) 136# 6) can't be fstype nfs and local 137# 7) only fstype nfs is remote 138 139if [ $# -ge $OPTIND ]; then # 1 140 usage "additional arguments not supported" 141fi 142 143if [ -n "$RFLAG" -a -n "$LFLAG" ]; then # 2 144 usage "options -r and -l are incompatible" 145fi 146 147if [ \( -n "$RFLAG" -o -n "$LFLAG" \) -a "$HFLAG" = "h" ]; then # 3 148 usage "option -${RFLAG}${LFLAG} incompatible with -h option" 149fi 150 151if [ -n "$FFLAG" -a "$HFLAG" = "h" ]; then # 4 152 usage "Specifying FStype incompatible with -h option" 153fi 154 155if [ -n "$HFLAG" -a "$HOST" = "$LOCALNAME" ]; then # 5 156 usage "Specifying local host illegal for -h option" 157fi 158 159if [ "$FSType" = "nfs" -a "$LFLAG" = "l" ]; then # 6 160 usage "option -l and FSType nfs are incompatible" 161fi 162 163if [ -n "$FFLAG" -a "$FSType" != "nfs" -a -n "$RFLAG" ]; then # 7 164 usage "option -r and FSType ${FSType} are incompatible" 165fi 166 167ZONENAME=`zonename` 168 169# Check and if needed sync the boot archive before unmounting everything. 170# 171if [ -z "${RFLAG}${NFLAG}${HFLAG}${FSType}" -a "$ZONENAME" = "global" -a \ 172 `uname -p` = "i386" -a -x /sbin/bootadm ] ; then 173 /sbin/bootadm -a update_all 174fi 175 176# 177# Take advantage of parallel unmounting at this point if we have no 178# criteria to match and we are in the global zone 179# 180if [ -z "${SFLAG}${LFLAG}${RFLAG}${HFLAG}${KFLAG}${FFLAG}" -a \ 181 "$ZONENAME" = "global" ]; then 182 umount -a ${UMOUNTFLAG} 183 exit # with return code of the umount -a 184fi 185 186# 187# Catch uses of /usr commands when /usr is not mounted 188if [ -n "$KFLAG" -a -z "$NFLAG" ]; then 189 if [ ! -x /usr/sbin/fuser ]; then 190 fuser () { 191 echo "umountall: fuser -k skipped (no /usr)" 1>&2 192 # continue - not fatal 193 } 194 sleep () { 195 : # no point in sleeping if fuser is doing nothing 196 } 197 else 198 if [ ! -x /usr/bin/sleep ]; then 199 sleep () { 200 echo "umountall: sleep after fuser -k skipped (no /usr)" 1>&2 201 # continue - not fatal 202 } 203 fi 204 fi 205fi 206 207# 208# Shell function to avoid using /usr/bin/cut. Given a dev from a 209# fstype=nfs line in mnttab (eg, "host:/export) extract the host 210# component. 211print_host () { 212 OIFS=$IFS 213 IFS=":" 214 set -- $* 215 echo $1 216 IFS=$OIFS 217} 218 219# 220# doumounts echos its return code to stdout, so commands used within 221# this function should take care to produce no other output to stdout. 222doumounts () { 223 ( 224 rc=0 225 fslist="" 226 while read dev mountp fstype mode dummy 227 do 228 case "${mountp}" in 229 / | \ 230 /dev | \ 231 /dev/fd | \ 232 /devices | \ 233 /etc/mnttab | \ 234 /etc/svc/volatile | \ 235 /lib | \ 236 /proc | \ 237 /sbin | \ 238 /system/contract | \ 239 /system/object | \ 240 /tmp | \ 241 /usr | \ 242 /var | \ 243 /var/adm | \ 244 /var/run | \ 245 '' ) 246 # 247 # file systems possibly mounted in the kernel or 248 # in the methods of some of the file system 249 # services 250 # 251 continue 252 ;; 253 * ) 254 if [ -n "$HFLAG" ]; then 255 if [ "$fstype" = "nfs" ]; then 256 thishost=`print_host $dev` 257 if [ "$HOST" != "$thishost" ]; then 258 continue 259 fi 260 else 261 continue 262 fi 263 fi 264 if [ -n "$FFLAG" -a "$FSType" != "$fstype" ]; then 265 continue 266 fi 267 if [ -n "$LFLAG" -a "$fstype" = "nfs" ]; then 268 continue 269 fi 270 if [ -n "$RFLAG" -a "$fstype" != "nfs" ]; then 271 continue 272 fi 273 if [ "$ZONENAME" != "global" ]; then 274 for option in `echo $mode | tr , '\012'`; do 275 # 276 # should not see any zone options 277 # but our own 278 # 279 if [ "$option" = "zone=$ZONENAME" ]; then 280 break 281 fi 282 done 283 if [ "$option" != "zone=$ZONENAME" ]; then 284 continue 285 fi 286 fi 287 if [ -n "${KFLAG}" ]; then 288 fuser -c -k $mountp 1>&2 289 sleep 2 290 fi 291 if [ -n "$SFLAG" ]; then 292 umount ${UMOUNTFLAG} ${mountp} 1>&2 293 trc=$? 294 if [ $trc -ne 0 ]; then 295 rc=$trc 296 fi 297 else 298 # We want to umount in parallel 299 fslist="$fslist $mountp" 300 fi 301 esac 302 done 303 304 if [ -n "$fslist" ]; then 305 umount -a ${UMOUNTFLAG} $fslist 1>&2 306 trc=$? 307 if [ $trc -ne 0 ]; then 308 rc=$trc 309 fi 310 fi 311 312 echo $rc 313 ) 314} 315 316# 317# /etc/mnttab has the most recent mounts last. Reverse it so that we 318# may umount in opposite order to the original mounts. 319# 320 321if [ ! -x /usr/bin/tail ]; then 322 exec < $MNTTAB 323 REVERSED= 324 while read line; do 325 if [ -n "$REVERSED" ]; then 326 REVERSED="$line\n$REVERSED" 327 else 328 REVERSED="$line" 329 fi 330 done 331 332 error=`echo $REVERSED | doumounts` 333else 334 error=`tail -r $MNTTAB | doumounts` 335fi 336 337exit $error 338