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 #
  25 # Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  26 # Use is subject to license terms.
  27 #
  28 #       Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T
  29 #         All Rights Reserved
  30 #
  31 
  32 usage () {
  33         if [ -n "$1" ]; then
  34                 echo "mountall: $1" 1>&2
  35         fi
  36         echo "Usage:\nmountall [-F FSType] [-l|-r|-g] [file_system_table]" 1>&2
  37         exit 2
  38 }
  39 
  40 PATH=/usr/sbin:/usr/bin
  41 TYPES=all
  42 FSTAB=/etc/vfstab
  43 err=0
  44 
  45 # Clear these in case they were already set in our environment.
  46 FSType=
  47 GFLAG=
  48 RFLAG=
  49 LFLAG=
  50 SFLAG=
  51 RemoteFSTypes=
  52 
  53 #       checkmessage "fsck_device | mount_point"
  54 #
  55 # Simple auxilary routine to the shell function checkfs. Prints out
  56 # instructions for a manual file system check before entering the shell.
  57 #
  58 checkmessage() {
  59         echo "" > /dev/console
  60         if [ "$1" != "" ] ; then
  61                 echo "WARNING - Unable to repair one or more \c" > /dev/console
  62                 echo "of the following filesystem(s):" > /dev/console
  63                 echo "\t$1" > /dev/console
  64         else
  65                 echo "WARNING - Unable to repair one or more filesystems." \
  66                         > /dev/console
  67         fi
  68         echo "Run fsck manually (fsck filesystem...)." > /dev/console
  69         echo "" > /dev/console
  70 }
  71 
  72 #
  73 #       checkfs raw_device fstype mountpoint
  74 #
  75 # Check the file system specified. The return codes from fsck have the
  76 # following meanings.
  77 #        0 - file system is unmounted and okay
  78 #       32 - file system is unmounted and needs checking (fsck -m only)
  79 #       33 - file system is already mounted
  80 #       34 - cannot stat device
  81 #       36 - uncorrectable errors detected - terminate normally (4.1 code 8)
  82 #       37 - a signal was caught during processing (4.1 exit 12)
  83 #       39 - uncorrectable errors detected - terminate rightaway (4.1 code 8)
  84 #       40 - for root, same as 0 (used by rcS to remount root)
  85 #
  86 checkfs() {
  87         /usr/sbin/fsck -F $2 -m $1  >/dev/null 2>&1
  88 
  89         if [ $? -ne 0 ]
  90         then
  91                 # Determine fsck options by file system type
  92                 case "$2" in
  93                 ufs)    foptions="-o p"
  94                         ;;
  95                 *)      foptions="-y"
  96                         ;;
  97                 esac
  98 
  99                 echo "The "$3" file system ("$1") is being checked."
 100                 /usr/sbin/fsck -F $2 ${foptions} $1
 101         
 102                 case $? in
 103                 0|40)   # file system OK
 104                         ;;
 105 
 106                 *)      # couldn't fix the file system
 107                         echo "/usr/sbin/fsck failed with exit code "$?"."
 108                         checkmessage "$1"
 109                         ;;
 110                 esac
 111         fi
 112 }
 113 
 114 #
 115 # Used to save an entry that we will want to mount either in
 116 # a command file or as a mount point list.
 117 #
 118 # saveentry fstype options special mountp
 119 #
 120 saveentry() {
 121         if [ "$ALTM" ]; then
 122                 echo "/sbin/mount -F $1 $2 $3 $4" >> $ALTM
 123         else
 124                 mntlist="$mntlist $4"
 125         fi
 126 }
 127 
 128 # Do the passed mount options include "global"?
 129 isglobal() {
 130         case ",${1}," in
 131         *,global,*)
 132                 return 0
 133                 ;;
 134         esac
 135         return 1
 136 }
 137 
 138 # Is the passed fstype a "remote" one?
 139 # Essentially: /usr/bin/grep "^$1" /etc/dfs/fstypes
 140 isremote() {
 141         for t in $RemoteFSTypes
 142         do
 143                 [ "$t" = "$1" ] && return 0
 144         done
 145         return 1
 146 }
 147 
 148 # Get list of remote FS types (just once)
 149 RemoteFSTypes=`while read t junk; do echo $t; done < /etc/dfs/fstypes`
 150 
 151 
 152 #
 153 # Process command line args
 154 #
 155 while getopts ?grlsF: c
 156 do
 157         case $c in
 158         g)      GFLAG="g";;
 159         r)      RFLAG="r";;
 160         l)      LFLAG="l";;
 161         s)      SFLAG="s";;
 162         F)      FSType="$OPTARG";
 163                 if [ "$TYPES" = "one" ]
 164                 then
 165                         echo "mountall: more than one FSType specified"
 166                         exit 2
 167                 fi
 168                 TYPES="one";
 169 
 170                 case $FSType in
 171                 ?????????*) 
 172                         echo "mountall: FSType $FSType exceeds 8 characters"
 173                         exit 2
 174                 esac
 175                 ;;
 176         \?)     usage "";;
 177         esac
 178 done
 179 
 180 shift `/usr/bin/expr $OPTIND - 1`       # get past the processed args
 181 
 182 if [ $# -gt 1 ]; then
 183         usage "multiple arguments not supported"
 184 fi
 185 
 186 # get file system table name and make sure file exists
 187 if [ $# = 1 ]; then
 188         case $1 in
 189         "-")    FSTAB=""
 190                 ;;
 191         *)      FSTAB=$1
 192                 ;;
 193         esac
 194 fi
 195 #
 196 # if an alternate vfstab file is used or serial mode is specified, then
 197 # use a mount command file
 198 #
 199 if [ $# = 1 -o "$SFLAG" ]; then
 200         ALTM=/var/tmp/mount$$
 201         rm -f $ALTM
 202 fi
 203 
 204 if [ "$FSTAB" != ""  -a  ! -s "$FSTAB" ]
 205 then
 206         echo "mountall: file system table ($FSTAB) not found"
 207         exit 1
 208 fi
 209 
 210 #
 211 # Check for incompatible args
 212 #
 213 if [ "$GFLAG" = "g" -a "$RFLAG$LFLAG" != "" -o \
 214      "$RFLAG" = "r" -a "$GFLAG$LFLAG" != "" -o \
 215      "$LFLAG" = "l" -a "$RFLAG$GFLAG" != "" ]
 216 then
 217         usage "options -g, -r and -l are mutually exclusive"
 218 fi
 219 
 220 if [ "$LFLAG" = "l" -a -n "$FSType" ]; then
 221         # remote FSType not allowed
 222         isremote "$FSType" &&
 223         usage "option -l and FSType are incompatible"
 224 fi
 225 
 226 if [ "$RFLAG" = "r" -a -n "$FSType" ]; then
 227         # remote FSType required
 228         isremote "$FSType" ||
 229         usage "option -r and FSType are incompatible"
 230 fi
 231 
 232 #       file-system-table format:
 233 #
 234 #       column 1:       special- block special device or resource name
 235 #       column 2:       fsckdev- char special device for fsck 
 236 #       column 3:       mountp- mount point
 237 #       column 4:       fstype- File system type
 238 #       column 5:       fsckpass- number if to be checked automatically
 239 #       column 6:       automnt-        yes/no for automatic mount
 240 #       column 7:       mntopts- -o specific mount options
 241 
 242 #       White-space separates columns.
 243 #       Lines beginning with \"#\" are comments.  Empty lines are ignored.
 244 #       a '-' in any field is a no-op.
 245 
 246 #
 247 # Read FSTAB, fsck'ing appropriate filesystems:
 248 #
 249 exec < $FSTAB
 250 while  read special fsckdev mountp fstype fsckpass automnt mntopts
 251 do
 252         case $special in
 253         '#'* | '')      #  Ignore comments, empty lines
 254                         continue ;;
 255         '-')            #  Ignore no-action lines
 256                         continue
 257         esac
 258 
 259         if [ "$automnt" != "yes" ]; then
 260                 continue
 261         fi
 262         if [ "$FSType" -a "$FSType" != "$fstype" ]; then
 263                 # ignore different fstypes
 264                 continue
 265         fi
 266 
 267         # The -g option is not in the man page, but according to
 268         # PSARC/1998/255 it's used by Sun Cluster (via contract) to
 269         # mount disk-based filesystems with the "global" option.
 270         # Also, the -l option now skips those "global" mounts.
 271         #
 272         # Note: options -g -l -r are mutually exclusive
 273         #
 274         if [ -n "$GFLAG" ]; then
 275                 # Mount "local" filesystems that have
 276                 # the "global" option in mntopts.
 277                 isremote "$fstype" && continue
 278                 isglobal "$mntopts" || continue
 279         fi
 280         if [ -n "$LFLAG" ]; then
 281                 # Mount "local" filesystems, excluding
 282                 # those marked "global".
 283                 isremote "$fstype" && continue
 284                 isglobal "$mntopts" && continue
 285         fi
 286         if [ -n "$RFLAG" ]; then
 287                 # Mount "remote" filesystems.
 288                 isremote "$fstype" || continue
 289         fi
 290 
 291         if [ "$fstype" = "-" ]; then
 292                 echo "mountall: FSType of $special cannot be identified" 1>&2
 293                 continue
 294         fi
 295 
 296         if [ "$ALTM" -a "$mntopts" != "-" ]; then
 297                 OPTIONS="-o $mntopts"           # Use mount options if any
 298         else
 299                 OPTIONS=""
 300         fi
 301 
 302         #
 303         # Ignore entries already mounted
 304         #
 305         /usr/bin/grep " $mountp " /etc/mnttab >/dev/null 2>&1 && continue
 306 
 307         #
 308         # Can't fsck if no fsckdev is specified
 309         #
 310         if [ "$fsckdev" = "-" ]; then
 311                 saveentry $fstype "$OPTIONS" $special $mountp
 312                 continue
 313         fi
 314         #
 315         # For fsck purposes, we make a distinction between file systems
 316         # that have a /usr/lib/fs/<fstyp>/fsckall script and those
 317         # that don't.  For those that do, just keep a list of them
 318         # and pass the list to the fsckall script for that file
 319         # file system type.
 320         # 
 321         if [ -x /usr/lib/fs/$fstype/fsckall ]; then
 322 
 323                 #
 324                 # add fstype to the list of fstypes for which
 325                 # fsckall should be called, if it's not already
 326                 # in the list.
 327                 #
 328                 found=no
 329                 if [ "$fsckall_fstypes" != "" ] ; then
 330                         for fst in $fsckall_fstypes; do
 331                                 if [ "$fst" = "$fstype" ] ; then
 332                                         found=yes
 333                                         break
 334                                 fi
 335                         done
 336                 fi
 337                 if [ $found = no ] ; then
 338                         fsckall_fstypes="$fsckall_fstypes ${fstype}"
 339                 fi
 340 
 341                 #
 342                 # add the device to the name of devices to be passed
 343                 # to the fsckall program for this file system type
 344                 #
 345                 cmd="${fstype}_fscklist=\"\$${fstype}_fscklist $fsckdev\""
 346                 eval $cmd
 347                 saveentry $fstype "$OPTIONS" $special $mountp
 348                 continue
 349         fi
 350         #
 351         # fsck everything else:
 352         #
 353         # fsck -m simply returns true if the filesystem is suitable for
 354         # mounting.
 355         #
 356         /usr/sbin/fsck -m -F $fstype $fsckdev >/dev/null 2>&1
 357         case $? in
 358         0|40)   saveentry $fstype "$OPTIONS" $special $mountp
 359                 continue
 360                 ;;
 361         32)     checkfs $fsckdev $fstype $mountp
 362                 saveentry $fstype "$OPTIONS" $special $mountp
 363                 continue
 364                 ;;
 365         33)     # already mounted
 366                 echo "$special already mounted"
 367                 ;;
 368         34)     # bogus special device
 369                 echo "Cannot stat $fsckdev - ignoring"
 370                 err=1
 371                 ;;
 372         *)      # uncorrectable errors
 373                 echo "$fsckdev uncorrectable error"
 374                 err=1
 375                 ;;
 376         esac
 377 done
 378 
 379 #
 380 # Call the fsckall programs
 381 #
 382 for fst in $fsckall_fstypes
 383 do
 384         cmd="/usr/lib/fs/$fst/fsckall \$${fst}_fscklist"
 385         eval $cmd
 386 
 387         case $? in
 388         0)      # file systems OK
 389                         ;;
 390 
 391         *)      # couldn't fix some of the filesystems
 392                 echo "fsckall failed with exit code "$?"."
 393                 checkmessage
 394                 ;;
 395         esac
 396 done
 397 
 398 if [ "$ALTM" ]; then
 399         if [ ! -f "$ALTM" ]; then
 400                 exit
 401         fi
 402         /sbin/sh $ALTM          # run the saved mount commands
 403         /usr/bin/rm -f $ALTM
 404         exit
 405 fi
 406 
 407 if [ -n "$FSType" ]; then
 408         /sbin/mount -a -F $FSType
 409         exit
 410 fi
 411 
 412 # Some remote filesystems (e.g. cachefs or autofs) shouldn't be be mounted
 413 # with mountall, so the list here is explicit (not from /etc/dfs/fstypes)
 414 if [ "$RFLAG" ]; then
 415         /sbin/mount -a -F nfs
 416         /sbin/mount -a -F smbfs
 417         exit
 418 fi
 419 
 420 if [ "$LFLAG" -o "$GFLAG" -o $err != 0 ]; then
 421         [ -z "$mntlist" ] || /sbin/mount -a $mntlist
 422         exit
 423 fi
 424 
 425 # else mount them all
 426 
 427 /sbin/mount -a