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