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