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