#!/bin/ksh
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
#  
#  
# Licensed Materials - Property of IBM 
#  
# (C) COPYRIGHT International Business Machines Corp. 1999,2007 
# All Rights Reserved 
#  
# US Government Users Restricted Rights - Use, duplication or 
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 
#  
# IBM_PROLOG_END_TAG 
# @(#)84 1.473.1.23 src/avs/fs/mmfs/ts/admin/mmglobfuncs.sh, mmfs, avs_rgpfs24, rgpfs24s012a 4/18/07 15:05:42
#####################################################################
#
#  This file contains declarations and functions that are
#  common to most of the commands.  All mm commands must
#  read this dot script before they do anything else.
#
#  If a command needs additional dot scripts, they must
#  be read after this one.
#
#####################################################################

sourceFile="mmglobfuncs.sh"
PS4='${0##*/}:${sourceFile}[$LINENO]> '
[[ -n $DEBUGmmglobfuncs ]] && set -x

#-----------------------------------------------------------
# Determine the operating system name.
#-----------------------------------------------------------
osName=$(/bin/uname -s)


#-----------------------------------------------------------
# Set environment and save input arguments.
#-----------------------------------------------------------
unset ENV
umask 022
UMASK_sv=022
export PATH="/bin:/usr/bin:/sbin:/usr/sbin:/usr/lpp/mmfs/bin"
export PERL_BADLANG=0
integer argc=$#
cmdline=$*
mmcmd=${0##*/}
if [[ $mmcmd = mmremote && "$1" = mmrpc* ]]
then
  mmrpc="$1"
  shift 1
fi
arg1="$1"
arg2="$2"
arg3="$3"
arg4="$4"
arg5="$5"
arg6="$6"
arg7="$7"
arg8="$8"
arg9="$9"


#-----------------------------------------------------------
# Global variables and constants
#-----------------------------------------------------------
primaryServer=""                # primary server for cluster sdr files
backupServer=""                 # backup server for cluster sdr files
mmmode=""                       # mm mode (cluster type)
environmentType=""              # environment type
gpfsObjectInfo=""               # GPFS object info
sdrLocked=no                    # If yes, the sdr is locked.
gpfsLocked=no                   # If yes, the Gpfs object is locked.
envLocked=no                    # If yes, the local env update lock is held.
lockId=$$                       # identifier for sdr locking
getCredCalled=no                # If yes, the getCred function was executed.
new_krb5=""                     # newly-obtained DCE credentials
old_krb5="$KRB5CCNAME"          # DCE credentials prior to entering this script
new_KRBTKFILE="/tmp/tktmmfs$$"  # Kerberos ticket file for the command
old_KRBTKFILE="$KRBTKFILE"      # Kerberos file prior to entering this script
nodesetId=""                    # the nodeset to which the command applies
nsId=""                         # the nodeset to which this node belongs
preferredNode=0                 # the first node to try when shipping command
noUsageMsg=0                    # suppress the usage statement
integer newGenNumber=0          # generation number for the mmsdrfs file
integer sdrGenNumber=0          # most recent mmsdrfs generation number
integer sdrGenTimestamp=0       # timestamp of the mmsdrfs generation number
sdrfsFormatLevel=0              # the format level of the mmsdrfs file
IFS_sv="$IFS"                   # value of the IFS environment variable
ourNodeNumber=""                # the node number of this node
ourNodeName=""                  # the reliable node name of this node
ourShortName=""                 # the unqualified node name of this node
ourUid=$(/usr/bin/id -u)        # the uid of the process invoking the command

BLANKchar=" "
TABchar="	"
NO_MOUNT_CHECK="_NO_MOUNT_CHECK_"
MOUNT_CHECK_ONLY="_MOUNT_CHECK_ONLY_"
CHECK_ALL="_CHECK_ALL_"
RESIGN_FSMGR="_RESIGN_FSMGR_"
NO_FILE_COPY="_NO_FILE_COPY_"
LINK="_LINK_"
NO_LINK="_NO_LINK_"
UNKNOWN="_UNKNOWN_"
UNRESOLVED="-"


#-----------------------------------------------------------
# Return codes and constants for internal mm command use.
#-----------------------------------------------------------
# mm command unique values:
MM_Version3=3              # node runs version 2.3 or later
MM_IncompatibleCode=188    # installed GPFS code is not compatible
MM_FsMounted=189           # file system mounted somewhere
MM_KExtFailure=190         # kernel extension load/unload failure

# Values based on the AIX errno.h constants:
MM_RemoteNotFound=2        # remote cluster not found (ENOENT)
MM_QuorumWait=11           # daemon waits for quorum (EAGAIN)
MM_AccessDenied=13         # access denied (EACCES)
MM_NotJoined=16            # node has not joined the cluster (EBUSY)
MM_FsExists=17             # device already exists (EEXIST)
MM_FsNotFound=19           # device does not exist (ENODEV)
MM_DeviceNotFound=19       # device does not exist (ENODEV)
MM_InvalidName=22          # invalid (device) name (EINVAL)
MM_DaemonDown=50           # daemon not running (ENOCONNECT)
MM_UnknownCluster=70       # unknown cluster (ENETUNREACH)
MM_ConnectionReset=73      # connection reset (ECONNRESET)
MM_TimedOut=78             # connection timed out (ETIMEDOUT)
MM_HostDown=80             # host is down (EHOSTDOWN)
MM_Remotefs=93             # remote file system (EREMOTE)

# Values based on GPFS ShErrno.h constants modulo 256:
MM_ConnectTimeout=107      # connection timeout or error (E_NOTCONN)
MM_SecurityCfg=208         # failed to load security keys (E_SECURITY_CFG mod 256)
MM_AuthorizationFailed=214 # authorization failed (E_AUTHORIZATION_FAILED mod 256)


#-----------------------------------------------------------
# Well-known directories
#-----------------------------------------------------------
# Set the directory with the mm commands.
if [[ -n $MMFSDIR ]]
then
  mmcmdDir="${MMFSDIR}/bin"
elif [[ -z $mmcmdDir ]]
then
  mmcmdDir="/usr/lpp/mmfs/bin"
else
  : # mmcmdDir must have been set by the caller
fi

tscmdDir="$mmcmdDir"                           # directory with ts commands
mmdataDir="/usr/lpp/mmfs/data/"                # directory for various mm data files
mmsdrfsDir="/var/mmfs/gen/"                    # directory for various mm system files
mmfscfgDir="/var/mmfs/etc/"                    # directory for mmfs config files
tmpDir="/var/mmfs/tmp/"                        # directory for temporary files
mmbackupDir="/var/mmfs/mmbackup"               # directory for use by mmbackup
lockdir="/var/mmfs/etc/mmlock"                 # common lock directory
mmfsEnvLockDir="/var/mmfs/gen/mmfsEnvLockDir"  # local mmfsEnv lock directory
links=".links"                                 # directory with links to ts commands
rasDir="/var/adm/ras/"                         # directory for daemon log files
sslDir="/var/mmfs/ssl/"                        # directory for cluster security files
sslStageDir="/var/mmfs/ssl/stage/"             # directory for cluster security files
defaultAutomountDir="/gpfs/automountdir"       # default directory for automounts

# Keep the following two items in sync with globcfg.C
mmpmonDir="/var/mmfs/mmpmon/"                  # directory for use by mmpmon
mmpmonSocket="mmpmonSocket"                    # name of mmpmon named socket

# The env lock location can be altered with an environment variable.
[[ -n $mmfsEnvLockLocation ]] &&  \
   mmfsEnvLockDir="$mmfsEnvLockLocation/mmfsEnvLockDir"

# If the user is not root, relocate files used by
# mmls commands to /tmp instead of /var/mmfs/tmp.
[[ $ourUid -ne 0 ]] && tmpDir="/tmp/"

#-----------------------------------------------------------
# Well-known file names
#-----------------------------------------------------------
if [[ $ourUid -eq 0 ]]
then
  MULTIPLE_KEYS_5="${mmsdrfsDir}MULTIPLE_KEYS_5"          #esjxx ifdef file
# mkdir -p $mmsdrfsDir ; touch $MULTIPLE_KEYS_5           #esjxx ifdef file
fi

ignoreStartupMount=${mmfscfgDir}ignoreStartupMount # node-override for -A yes mounting
localMountOptions=${mmfscfgDir}localMountOptions   # node-specific mount options;
                                                   #  the suffix is the file system name
mmfscfgFile=${mmfscfgDir}mmfs.cfg              # mmfs.cfg file used by the daemon
mmfscfg=${mmfscfgDir}mmfs.cfg                  # mmfs.cfg file used by the daemon
haslock=${lockdir}/haslock                     # pid and node of command that has lock
hasEnvLock=${mmfsEnvLockDir}/hasEnvLock        # pid of cmd that has the mmfsEnv lock
mmsdrfsFile=${mmsdrfsDir}mmsdrfs               # cached copy of the mmsdrfs file
mmsdrfsTmp=${mmsdrfsDir}mmsdrfs.tmp            # uncommitted copy of the mmsdrfs file
mmsdrfsPrev=${mmsdrfsDir}mmsdrfs.prev          # previous version of the mmsdrfs file
uncommitted=${mmsdrfsDir}uncommitted           # empty file signifying commit in progress
mmfsNodeData=${mmsdrfsDir}mmfsNodeData         # local node data (hostname, ipa, etc.)
mmfsEnvLevel=${mmsdrfsDir}mmfsEnvLevel         # the suffix is equal to the gen number
                                               # of the local mmsdrfs file
mmfsVfsNumber=${mmsdrfsDir}mmfsVfsNumber       # the suffix is equal to the major number
                                               # assigned to /dev entries on this node
exclDiskFile=${mmsdrfsDir}exclDiskFile         # the suffix is equal to the file system
                                               # device name to which the disks belong
mmsdrfsGen=${tmpDir}mmsdrfsGen                 # the suffix is the file's gen number
mmauthKeyGen=${sslStageDir}mmauthKeyGen        # mmauth genkey file (format 1)
                                               #   the suffix is the key gen number
genkeyData=${sslStageDir}genkeyData            # mmauth genkey file (format 2)
                                               #   the suffix is the key gen number
mmfsNewKeyLevel=${mmsdrfsDir}mmfsNewKeyLevel   # the suffix is equal to the gen number
                                               # of the uncommitted private key file
mmfsCommittedKeyLevel=${mmsdrfsDir}mmfsCommittedKeyLevel # the suffix is the gen number
                                               # of the committed private key file
newPrivateKey=${sslDir}id_rsa_new              # uncommitted private key file
committedPrivateKey=${sslDir}id_rsa_committed  # committed private key file
newPublicKey=${sslDir}id_rsa_new.pub           # uncommitted public key file
committedPublicKey=${sslDir}id_rsa_committed.pub # committed public key file
newCertificate=${sslDir}id_rsa_new.cert        # uncommitted self-signed certificate
committedCertificate=${sslDir}id_rsa_committed.cert # committed self-signed certificate
publicKey=${sslDir}id_rsa.pub                  # link to the current public key
privateKey=${sslDir}id_rsa                     # private key file for the local cluster
                                               #   the suffix is the key gen number

mmSdrLockExp=${mmsdrfsDir}mmSdrLockExp         # contains gen number and exp. timestamp
nsdmap=${mmsdrfsDir}nsdmap                     # local disk name to pvid hints file
nsdpvol=${mmsdrfsDir}nsdpvol                   # local disk name to nsd name file
mmDirectMap=${mmsdrfsDir}mmDirectMap           # list of automountable file systems
startupMountFile=${mmsdrfsDir}automountFile    # fs to mount at startup time
automountFile=${mmsdrfsDir}automountFile       # fs to mount at startup time
authorizedKeys=${sslDir}authorized_keys        # list of autorized keys
knownCluster=${sslDir}known_cluster            # public key file for a remote cluster;
                                               #   the suffix is the cluster name.
authorizedCertificates=${sslDir}authorized_certificates # list of autorized certificates
knownCertificate=${sslDir}known_certificate    # certificate file for a remote cluster;
                                               #   the suffix is the cluster name.
certConfigFile=${sslDir}openssl.conf           # options for openssl certificate
opensslConfFile=${mmdataDir}openssl.conf       # template for openssl certificate
rerunmmfsFile=${mmsdrfsDir}rerunmmfsFile       # file telling runmmfs to respawn mmfsd
respawnlog=${mmsdrfsDir}runmmfs.respawnlog     # controls the rate of mmfsd respawn
respawnlog2=${mmsdrfsDir}runmmfs.respawnlog.$$ # controls the rate of mmfsd respawn
mmpmonNamedSocketFile=${mmpmonDir}${mmpmonSocket} # mmpmon named socket
mmsdrservPid=${mmsdrfsDir}mmsdrservPid         # contains pid of the mmsdrserv process

# To get error messages from mmsdrserv, specify a file name in the mmsdrservLog
# variable.  If this variable is not defined, all error msgs will be discarded.
#mmsdrservLog=${tmpDir}mmsdrservLog            # log records from the mmsdrserv daemon
[[ -z $mmsdrservLog ]] && mmsdrservLog="/dev/null"


#-----------------------------------------------------------
# Global working files
#-----------------------------------------------------------
adfile=${tmpDir}adapterFile.${mmcmd}.$$         # list of all node adapters
rnfile=${tmpDir}relNamesFile.${mmcmd}.$$        # list of all reliable hostnames
lslvOutput=${tmpDir}lslvOutput.${mmcmd}.$$      # lslv output
sdrNodeFile=${tmpDir}sdrNodeFile.${mmcmd}.$$    # node-related information
vsdNamesFile=${tmpDir}vsdNamesFile.${mmcmd}.$$  # list of all VSDs
volGroupFile=${tmpDir}volGroupFile.${mmcmd}.$$  # list of all global volume groups
allClusterNodes=${tmpDir}allClusterNodes.${mmcmd}.$$  # list of nodes in the cluster
allQuorumNodes=${tmpDir}allQuorumNodes.${mmcmd}.$$    # list of all quorum nodes
nodefile=${tmpDir}nodefile.${mmcmd}.$$          # list of nodes in the cluster
diskfile=${tmpDir}diskfile.${mmcmd}.$$          # list of disks in the cluster
newsdrfs=${tmpDir}newsdrfs.${mmcmd}.$$          # new version of mmsdrfs file
tmpsdrfs=${tmpDir}tmpsdrfs.${mmcmd}.$$          # temp file for building the mmsdrfs
mmsdrfsShadow=${mmsdrfsFile}.$$                 # temp copy of the sdr version of mmsdrfs
sdrfs=${tmpDir}sdrfs.${mmcmd}.$$                # local copy of the mmsdrfs file
oldsdrfs=${tmpDir}oldsdrfs.${mmcmd}.$$          # local copy of the mmsdrfs file
stanza=${tmpDir}stanza.${mmcmd}.$$              # /etc/filesystems stanza
oldstanza=${tmpDir}oldstanza.${mmcmd}.$$        # old version of /etc/filesystems stanza
newstanza=${tmpDir}newstanza.${mmcmd}.$$        # new version of /etc/filesystems stanza
newcfg=${tmpDir}newcfg.${mmcmd}.$$              # new version of mmfs.cfg file
remainingFs=${tmpDir}remainingFs.${mmcmd}.$$    # remaining file systems info
tmpfile=${tmpDir}tmpfile.${mmcmd}.$$            # temp file for misc use
tmpfile2=${tmpDir}tmpfile2.${mmcmd}.$$          # second temp file for misc use
tmpCfg=${tmpDir}tmpCfg.${mmcmd}.$$              # temp mmfs.cfg file
tmpNodes=${tmpDir}tmpNodes.${mmcmd}.$$          # temp file with node names
tmpDirectMap=${mmsdrfsDir}tmpDirectMap          # list of automountable file systems
tmpPublicKey=${sslStageDir}tmpPublicKey.${mmcmd}.$$      # temp public key file
tmpPrivateKey=${sslStageDir}tmpPrivateKey.${mmcmd}.$$    # temp private key file
tmpCertificate=${sslStageDir}tmpCertificate.${mmcmd}.$$  # temp certificate file
localAuthKeys=${tmpDir}localAuthKeys.${mmcmd}.$$         # local public keys
localCertificates=${tmpDir}localCertificates.${mmcmd}.$$ # local certificates
tmpAuthKeys=${tmpDir}tmpAuthKeys.${mmcmd}.$$             # temp authorized keys file
tmpKnownCluster="${tmpDir}knownCluster.$$_"              # temp known cluster key file
                                                         #  (suffix is the cluster name)
tmpAuthCertificates=${tmpDir}tmpAuthCertificates.${mmcmd}.$$ # authorized certificates
tmpKnownCertificate="${tmpDir}knownCertificate.$$_"      # temp known certificate file
                                                         #  (suffix is the cluster name)
unreachedNodes=${tmpDir}unreachedNodes.${mmcmd}.$$       # unreached nodes file
sgDiskLines=${tmpDir}sgDiskLines.${mmcmd}.$$             # disk lines file
diskNamesFile=${tmpDir}diskNamesFile.${mmcmd}.$$         # disk names file
nsdDataFile=${tmpDir}nsdDataFile.${mmcmd}.$$             # NSD data file
lqueryvgResult=${tmpDir}lqueryvgResult.${mmcmd}.$$       # lqueryvg output file
lspvOutputFile=${tmpDir}lspvOutputFile.${mmcmd}.$$       # lspv output file
tsOutputFile=${tmpDir}tsOutputFile.${mmcmd}.$$  # output file for a ts command
errMsg=${tmpDir}errMsg.${mmcmd}.$$              # temp file for error messages
                                                #  (erase as soon as not needed)
errMsg2=${tmpDir}errMsg2.${mmcmd}.$$            # temp file for error messages
                                                #  (erase as soon as not needed)


GLOBAL_FILES=" $adfile $rnfile $sdrNodeFile $sdrfs $newsdrfs $volGroupFile  \
               $tmpfile $tmpfile2 $tmpsdrfs $vsdNamesFile $diskfile  \
               $oldstanza $stanza $newstanza $newcfg $tmpCfg $tmpNodes  \
               $oldsdrfs $nodefile $sgDiskLines $diskNamesFile $nsdDataFile \
               $errMsg $errMsg2 $mmsdrfsShadow $lslvOutput $unreachedNodes  \
               $remainingFs $allClusterNodes $allQuorumNodes $lqueryvgResult  \
               $tmpAuthKeys ${tmpKnownCluster}* $tmpDirectMap $tmpPrivateKey \
               $tmpPublicKey $tsOutputFile $lspvOutputFile \
               $tmpCertificate $localCertificates  \
               $localAuthKeys $tmpAuthCertificates ${tmpKnownCertificate}* "


#-----------------------------------------------------------
# Full path names for GPFS commands
#-----------------------------------------------------------
daemonize=${mmcmdDir}/daemonize
lxtrace=${mmcmdDir}/lxtrace
mmchconfig=${mmcmdDir}/mmchconfig
mmchecksubsys=${mmcmdDir}/mmchecksubsys
mmclearfence=${mmcmdDir}/mmclearfence
mmcommon=${mmcmdDir}/mmcommon
mmcrclusterid=${mmcmdDir}/mmcrclusterid
mmcrfsc=${mmcmdDir}/mmcrfsc
mmdf=${mmcmdDir}/mmdf
mmdsh=${mmcmdDir}/mmdsh
mmdspmsg=${mmcmdDir}/mmdspmsg
mmdynamicmap=${mmcmdDir}/mmdynamicmap
mmexectsmcmd=${mmcmdDir}/mmexectsmcmd
mmexportfs=${mmcmdDir}/mmexportfs
mmfixcfg=${mmcmdDir}/mmfixcfg
mmfsadm=${mmcmdDir}/mmfsadm
mmfsenv=${mmcmdDir}/mmfsenv
mmfskxgetwpid=${mmcmdDir}/mmfskxgetwpid
mmfskxload=${mmcmdDir}/mmfskxload
mmfskxunload=${mmcmdDir}/mmfskxunload
mmfsmknod=${mmcmdDir}/mmfsmknod
mmimportfs=${mmcmdDir}/mmimportfs
mmkerninfo=${mmcmdDir}/mmkerninfo
mmlsnsd=${mmcmdDir}/mmlsnsd
mmmvfs=${mmcmdDir}/mmmvfs
mmremote=${mmcmdDir}/mmremote
mmsdrcli=${mmcmdDir}/mmsdrcli
mmsdrserv=${mmcmdDir}/mmsdrserv
mmsetrcmd=${mmcmdDir}/mmsetrcmd
mmssaclearfence=${mmcmdDir}/mmssaclearfence
mmstartup=${mmcmdDir}/mmstartup
mmsync=${mmcmdDir}/mmsync
mmtrace=${mmcmdDir}/mmtrace
runmmfs=${mmcmdDir}/runmmfs
tsadddisk=${tscmdDir}/tsadddisk
tsauth=${tscmdDir}/tsauth
tsaddrmap=${tscmdDir}/tsaddrmap
tsbackup=${tscmdDir}/tsbackup
tschfileset=${tscmdDir}/tschfileset
tschfs=${tscmdDir}/tschfs
tschmgr=${tscmdDir}/tschmgr
tschpolicy=${tscmdDir}/tschpolicy
tschpool=${tscmdDir}/tschpool
tscrefresh=${tscmdDir}/tscrefresh
tscrfileset=${tscmdDir}/tscrfileset
tscrfs=${tscmdDir}/tscrfs
tsctl=${tscmdDir}/tsctl
tsctlfs=${tscmdDir}/tsctlfs
tsdeldisk=${tscmdDir}/tsdeldisk
tsdelfileset=${tscmdDir}/tsdelfileset
tsdelfs=${tscmdDir}/tsdelfs
tsdsh=${tscmdDir}/tsdsh
tsfileid=${tscmdDir}/tsfileid
tsfindinode=${tscmdDir}/tsfindinode
tslinkfileset=${tscmdDir}/tslinkfileset
tslsfs=${tscmdDir}/tslsfs
tslsfileset=${tscmdDir}/tslsfileset
tslspolicy=${tscmdDir}/tslspolicy
tsmigrate=${tscmdDir}/tsmigrate
tsnsdaccess=${tscmdDir}/tsnsdaccess
tsremount=${tscmdDir}/tsremount
tsrestripefs=${tscmdDir}/tsrestripefs
tsstatus=${tscmdDir}/tsstatus
tsprclear=${tscmdDir}/tsprclear
tspreparedisk=${tscmdDir}/tspreparedisk
tsunlinkfileset=${tscmdDir}/tsunlinkfileset
nss_setmap=${tscmdDir}/nss_setmap


#-----------------------------------------------------------
# User exits
#-----------------------------------------------------------
mmsdrbackup=${mmfscfgDir}mmsdrbackup
nsddevices=${mmfscfgDir}nsddevices
remoteclusternodes=${mmfscfgDir}remoteclusternodes
sslrandfile=${mmfscfgDir}sslrandfile
syncfsconfig=${mmfscfgDir}syncfsconfig


#-----------------------------------------------------------
# RSCT peer domain commands
#-----------------------------------------------------------
export CT_MANAGEMENT_SCOPE=2
lsclcfg=/usr/bin/lsclcfg
lsnodeid=/usr/sbin/rsct/bin/lsnodeid
lsrsrcapi=/usr/bin/lsrsrc-api


#-----------------------------------------------------------
# Full path names for the GPFS daemon and kernel extension.
# The mmcmdSubdir and mmcmdSuffix components, if they are to
# have non-null values, must be set by the invoking module.
#-----------------------------------------------------------
mmfs=${mmcmdDir}/${mmcmdSubdir}/mmfs${mmcmdSuffix}
mmfsd=${mmcmdDir}/${mmcmdSubdir}/mmfsd${mmcmdSuffix}


#-----------------------------------------------------------
# Global declarations for parsing the mmsdrfs file
#-----------------------------------------------------------
# Line type identifiers and other constants.
VERSION_LINE='00_VERSION_LINE'
COMMENT_LINE='03_COMMENT'
NODESET_HDR='10_NODESET_HDR'
MEMBER_NODE='20_MEMBER_NODE'
SG_HEADR='30_SG_HEADR'
SG_ETCFS='40_SG_ETCFS'
SG_MOUNT='50_SG_MOUNT'
SG_DISKS='60_SG_DISKS'
MMFSCFG='70_MMFSCFG'
REM_CLUSTER='80_REM_CLUSTER'
REM_CLUSTER_KEY='82_REM_CLUSTER_KEY'
AUTHORIZED_CLUSTER='90_AUTHORIZED_CLUSTER'
AUTHORIZED_KEY='92_AUTHORIZED_KEY'
AUTHORIZED_FS='94_AUTHORIZED_FS'
HSMDATA='910_HSMDATA'
HSMVERSION='920_HSMVERSION'

CURRENT_SDRFS_FORMAT=1
CURRENT_SDRFS_VERSION=3
CURRENT_KEYFILE_FORMAT=2
COMPATIBLE_KEYFILE_FORMAT=2
GLOBAL_ID='%%9999%%'
FREE_DISK='~%BBBB%%'
DSM_DATA='~%DSM%%'
NO_DEVICE='~/~'
CHANGE_NSD='~/changeNsd/~'
HOME_CLUSTER="%%home%%"
availableField=""
obsoleteField=""
FREE_NODE='~%AAAA%%'            # obsolete
HA_SERVICES='~%HAS%%'           # obsolete
HA_CLUSTER_NAME='gpfs'          # obsolete
PRIMARY_NETWORK='gpfs'          # obsolete
SECONDARY_NETWORK='gpfs2'       # obsolete

# Global field definitions.
NODESETID_Field=1
LINE_TYPE_Field=2
DEV_NAME_Field=3
LINE_NUMBER_Field=4

# Definitions for the VERSION_LINE.
SDRFS_FORMAT_Field=4
SDRFS_VERSION_Field=5
SDRFS_GENNUM_Field=6
RUNNING_CMD_Field=7
CLUSTER_TYPE_Field=8
PRIMARY_SERVER_Field=9
BACKUP_SERVER_Field=10
HIGHEST_GPFS_DISK_NBR_Field=11
RSH_PATH_Field=12
RCP_PATH_Field=13
CLUSTERID_Field=14
CLUSTER_SUBTYPE_Field=15
GENNUM_TSTAMP_Field=16
GETOBJECT_PORT_Field=17         # obsolete
CLUSTER_NAME_Field=18
NEW_KEY_Field=19
SECLEVEL_Field=20
COMMITTED_KEY_Field=21
KEYFILE_FORMAT_Field=22
initialDiskNumber=1000

# Definitions for COMMENT lines.
COMMENT_TEXT_Field=5
warningText="   This is a machine generated file.  Do not edit!        "

# Definitions for NODESET_HDR lines.
NODE_COUNT_Field=5
COMM_PROTOCOL_Field=6
CIPHER_LIST_Field=7
TCP_PORT_Field=8
# obsolete_Field=9           # old CONVERSION_STATE_Field
# obsolete_Field=10          # old EVENTS_PORT_Field
# available_Field=11
MIN_DAEMON_VERSION_Field=12  # same as the maxFeatureLevel
MAX_DAEMON_VERSION_Field=13
OS_ENVIRONMENT_Field=14
# available_Field=15
EVENTS_PORT_Field=16
GETOBJECT_PORT_Field=17
defaultTcpPort=1191

# Definitions for MEMBER_NODE lines.
NODE_NUMBER_Field=5
NODE_NAME_Field=6
IPA_Field=7
REL_HOSTNAME_Field=8
DESIGNATION_Field=9
LAPI_ADAPTER_Field=10        # obsolete
LAPI_WINDOW_Field=11         # obsolete
SWITCH_NODE_NUMBER_Field=12  # obsolete
ADDNODE_STATE_Field=13
ADAPTER_TYPE_Field=14
DAEMON_NODENAME_Field=15
ADMIN_SHORTNAME_Field=16
DAEMON_VERSION_Field=17
PRODUCT_VERSION_Field=18
OS_NAME_Field=19
CORE_QUORUM_Field=20
GS_NODE_NUMBER_Field=21      # obsolete
noWindow="-1"
noSwitch="-1"
noNumber=0
DELETED_NODE="deleted"       # obsolete
QUORUM="quorum"
NONQUORUM="nonquorum"
MANAGER="manager"
CLIENT="client"
NEW_NODE="new"
OLD_NODE=""
quorumNode="Q"
nonQuorumNode="N"
maxQuorumNodes=128
maxRecQuorumNodes=7

# Definitions for SG_HEADR lines.
DEV_MINOR_Field=5
ODD_STATE_Field=6
FS_TYPE_Field=7
REMOTE_DEV_NAME_Field=8
remotefs="R"
localfs=""

# Definitions for SG_ETCFS lines.
ETCFS_TEXT_Field=5
MOUNT_POINT_Line=1
DEV_Line=2
VFS_Line=3
NODENAME_Line=4
MOUNT_Line=5
TYPE_Line=6
ACCOUNT_Line=7
OPTIONS_Line=8
DEV_Line_Prefix="	dev		= "
VFS_Line_Prefix="	vfs		= "
NODENAME_Line_Prefix="	nodename	= "
MOUNT_Line_Prefix="	mount		= "
TYPE_Line_Prefix="	type		= "
ACCOUNT_Line_Prefix="	account		= "
OPTIONS_Line_Prefix="	options		= "

# Definitions for SG_MOUNT lines.
RW_OPT_Field=5
MTIME_OPT_Field=6
ATIME_OPT_Field=7
QUOTA_OPT_Field=8
OTHER_OPT_Field=9
QUOTA_ACTIVATED="userquota;groupquota;filesetquota"
QUOTA_DISACTIVATED=""

# Definitions for SG_DISKS lines.
DISK_NAME_Field=5
DISK_SIZE_Field=6
FAILURE_GROUP_Field=7
DISK_USAGE_Field=8
PVID_Field=9
DISK_TYPE_Field=10         # disk type of the disk (e.g., vsd, lv, nsd-direct)
NSD_PRIMARY_NODE_Field=11
NSD_BACKUP_NODE_Field=12
DISK_SUBTYPE_Field=13      # ssa, pr, other; used for fencing
VPATH_FLAG_Field=14        # vpath or notvpath; used when deleting or importing
                           #   disks; SDD utilities may or may not be needed
NSD_SUBTYPE_Field=15       # disk type of the disk underlying the nsd
                           #   (e.g., vsd, lv, hdisk, vpath, generic)
NAME_SOURCE_Field=16       # disk name source (user-specified or cmd-generated)
NSD_SUBTYPE_DISKNAME_Field=17  #  disk name of the disk underlying the nsd
EXCLUDE_Field=18
PAXOS_Field=19
DISK_STATUS_Field=20
AIX_PVID_Field=21          # PVID of the underlying AIX disk (if applicable).
STORAGE_POOL_Field=22
DAEMON_NSD_PRIMARY_Field=23
DAEMON_NSD_BACKUP_Field=24
userSpecified="user"
cmdGenerated="cmd"
excludedDisk="excl"
includedDisk=""
PaxosDisk="quorumDisk"

# Definitions for MMFSCFG lines.
#
# Since mmfs.cfg values can contain the ':' character,
# everything past the first four fields, except trailing
# null fields, is considered to be mmfs.cfg text.

# Definitions for REM_CLUSTER lines.
CONTACT_NODES_Field=5

# Definitions for REM_CLUSTER_KEY lines.
# Definitions for AUTHORIZED_KEY lines.
KEY_Field=5

# Definitions for AUTHORIZED_CLUSTER lines.
GRANT_Field=5
# available_Field=6
CIPHER_LIST_Field=7
accessGranted="all"
accessDenied=""

# Definitions for AUTHORIZED_FS lines.
ACCESS_TYPE_Field=5
ROOTSQUASH_UID_Field=6
ROOTSQUASH_GID_Field=7

# Definitions for HSMDATA and HSMVERSION lines.
HSM_NODESET_Field=3
# Since these lines can contain the ':' character,
# everything past the first four fields, except trailing
# null fields, is considered to be free format text.


#-----------------------------------------------------------------------
#
# Set up the internal mm trace facility.
#
# Tracing is controlled through the mmScriptTrace environment variable.
#
# - If the variable is not set, tracing is disabled.
#
# - If the variable is set, and its value starts with a slash,
#   it is assumed to be the full path name for the file which
#   is to contain the trace results.  Otherwise, the trace results
#   are send to file /tmp/mmfs/mmScriptTrace.
#
# Examples:
#
#   $mmTRACE_ENTER "$*"
#
#   $mmTRACE "lock held by $lockHolderHostname $lockHolderPid"
#
#   $mmTRACE_EXIT "rc=$rc"
#
#-----------------------------------------------------------------------
if [[ -z $mmScriptTrace || $mmScriptTrace = "/dev/null" ]]
then
  mmTRACE_ENTER=_mmTRACE_ENTER_disabled
  mmTRACE_EXIT=_mmTRACE_EXIT_disabled
  mmTRACE=_mmTRACE_disabled
  mmScriptTrace="/dev/null"
else
  mmTRACE_ENTER=_mmTRACE_ENTER_enabled
  mmTRACE_EXIT=_mmTRACE_EXIT_enabled
  mmTRACE=_mmTRACE_enabled
  [[ $mmScriptTrace != /* ]] && \
    mmScriptTrace=/tmp/mmfs/mmScriptTrace
fi


#-----------------------------------------------------------
# Set release information.
#-----------------------------------------------------------
. /usr/lpp/mmfs/bin/mmprodname
sourceFile="mmglobfuncs.sh"


#------------------------------------------------------------------
#  Pull in operating system dependent declarations and functions.
#------------------------------------------------------------------
[[ -e ${mmcmdDir}/mmglobfuncs.$osName ]] && \
  . ${mmcmdDir}/mmglobfuncs.$osName
sourceFile="mmglobfuncs.sh"


#------------------------------------------------------------------
# Check whether site changed the mmfs.log location.
#------------------------------------------------------------------
if [[ -f $mmfscfg ]]
then
  logDir=$($awk '$1 == "logDir" {value = $2} END {print value}' $mmfscfg)
  [[ -n $logDir ]] && rasDir="${logDir}/"
fi


#------------------------------------------------------------------
# Make sure required directories exist.
#------------------------------------------------------------------
if [[ $ourUid -eq 0 ]]
then
  $mkdir -p $mmsdrfsDir $mmfscfgDir $tmpDir $rasDir $mmbackupDir
  $mkdir -m 0700 -p $sslDir $sslStageDir $mmpmonDir
fi


#-----------------------------------------------------------
# Frequently-used functions
#-----------------------------------------------------------


#######################################################################
#
# Internal tracing functions.  All of the functions interpret the
# argument list with which they are invoked as being the trace record.
#
#######################################################################

_mmTRACE_ENTER_enabled()
{
  typeset timestamp=$($perl -e 'print time')
  printf  "%7s  %7s  %16s  %-14s  %-6s  %s\n" \
           $$ $PPID $timestamp $mmcmd  "enter" "${0##*/}: $*" >> $mmScriptTrace
}

_mmTRACE_EXIT_enabled()
{
  typeset timestamp=$($perl -e 'print time')
  printf  "%7s  %7s  %16s  %-14s  %-6s  %s\n" \
           $$ $PPID $timestamp $mmcmd  "EXIT " "${0##*/}: $*" >> $mmScriptTrace
}

_mmTRACE_enabled()
{
  typeset timestamp=$($perl -e 'print time')
  printf  "%7s  %7s  %16s  %-14s  %-6s  %s\n" \
           $$ $PPID $timestamp $mmcmd  " " "${0##*/}: $*" >> $mmScriptTrace
}

_mmTRACE_ENTER_disabled()
{
   return 0
}

_mmTRACE_EXIT_disabled()
{
   return 0
}

_mmTRACE_disabled()
{
   return 0
}


####################################################################
#
# Function:  Prints the specified message to stdout
#
# Input:     $1 - number of the message to print
#            $2, $3, ... - arguments to pass to dspmsg
#
####################################################################
function printInfoMsg  # <msgNo> [ <arg> ... ]
{
  typeset sourceFile="mmglobfuncs.sh"
  [[ -n $DEBUG || -n $DEBUGprintInfoMsg ]] && set -x
  msgNo=$1
  typeset msgSet
  typeset printTimeStamp=no

  # Based on the message number, find the message text.
  case $msgNo in

    12  ) msgTxt=\
"%s: %s nodes added to the cluster out of %s nodes specified."
    ;;

    94  ) msgTxt=\
"Deleting disks ..."
    ;;

    95  ) msgTxt=\
"Restriping %s ..."
    ;;

    96  ) msgTxt=\
"Replacing %s ..."
    ;;

    98  ) msgTxt=\
"%s: Processing disks that do not belong to any file system ..."
    ;;

    99  ) msgTxt=\
"Done"
    ;;

    143 ) msgTxt=\
"%s: %s: Processing user configuration file %s"
    ;;

    179 ) msgTxt=\
"flag value          description\n"\
"---- -------------- -----------------------------------------------------"
    ;;

    180 ) msgTxt=\
"root allowed"
    ;;

    181 ) msgTxt=\
"root remapped to"
    ;;

    182 ) msgTxt=\
"%s: Granting cluster %s access to file system %s:\n"\
"        access type %s; root credentials will not be remapped."
    ;;

    183 ) msgTxt=\
"%s: Granting cluster %s access to file system %s:\n"\
"        access type %s; root credentials will be remapped to %s:%s."
    ;;

    231 ) msgTxt=\
"%s: %s already belongs to volume group %s.\n"
    ;;

    241 ) msgTxt=\
"%s: %s: Starting force unmount of GPFS file systems"
    ;;

    242 ) msgTxt=\
"%s: %s: Unmount not finished after %s seconds.  Waiting %s more seconds"
    ;;

    243 ) msgTxt=\
"%s: %s: Unmount not finished after %s seconds"
    ;;

    244 ) msgTxt=\
"%s: %s: Shutting down GPFS daemons"
    ;;

    245 ) msgTxt=\
"%s: %s: Finished"
    ;;

    250 ) msgTxt=\
"%s: Processing file system %s ..."
    ;;

    251 ) msgTxt=\
"%s: Processing disk %s"
    ;;

    272 ) msgTxt=\
"%s: Command successfully completed"
    ;;

    331 ) msgTxt=\
"Automatic mount option"
    ;;

    332 ) msgTxt=\
"Exact mtime default mount option"
    ;;

    333 ) msgTxt=\
"Suppress atime default mount option"
    ;;

    339 ) msgTxt=\
"Verifying GPFS is stopped on all nodes ..."
    ;;

    373 ) msgTxt=\
"%s: %s: Mounting file systems ..."
    ;;

    392 ) msgTxt=\
"%s: %s: Starting GPFS ..."
    ;;

    400 ) msgTxt=\
"GPFS cluster information"
    ;;

    401 ) msgTxt=\
"GPFS cluster configuration servers:"
    ;;

    402 ) msgTxt=\
"  Primary server:    %s"
    ;;

    403 ) msgTxt=\
"  Secondary server:  %s"
    ;;

    404 ) msgTxt=\
" Node  Daemon node name            IP address       Admin node name             Designation    "
    ;;

    405 ) msgTxt=\
" Summary information "
    ;;

    406 ) msgTxt=\
"File system attributes for %s:"
    ;;

    407 ) msgTxt=\
"Configuration data for cluster %s:"
    ;;

    408 ) msgTxt=\
"File systems in cluster %s:"
    ;;

    409 ) msgTxt=\
"(none)"
    ;;

    414 ) msgTxt=\
"quorum-manager"
    ;;

    416 ) msgTxt=\
"%s: %s: Processing node %s"
    ;;

    426 ) msgTxt=\
"%s: %s: Unmounting file systems ..."
    ;;

    427 ) msgTxt=\
"SHA digest (new):"
    ;;

    430 ) msgTxt=\
"  GPFS cluster name:         %s"
    ;;

    431 ) msgTxt=\
"quorum node"
    ;;

    434 ) msgTxt=\
"  GPFS cluster id:           %s"
    ;;

    435 ) msgTxt=\
"  Remote shell command:      %s"
    ;;

    436 ) msgTxt=\
"  Remote file copy command:  %s"
    ;;

    442 ) msgTxt=\
"Cluster name:"
    ;;

    443 ) msgTxt=\
"Cipher list:"
    ;;

    444 ) msgTxt=\
"SHA digest:"
    ;;

    445 ) msgTxt=\
"File system access:"
    ;;

    446 ) msgTxt=\
"Contact nodes:"
    ;;

    447 ) msgTxt=\
"File systems:"
    ;;

    451 ) msgTxt=\
"  GPFS UID domain:           %s"
    ;;

    453 ) msgTxt=\
"Verifying GPFS is stopped on all affected nodes ..."
    ;;

    473 ) msgTxt=\
"Verifying file system configuration information ..."
    ;;

    475 ) msgTxt=\
"quorum"
    ;;

    477 ) msgTxt=\
"File system %s %s is mounted on %s nodes in cluster %s:"
    ;;

    478 ) msgTxt=\
"File system %s is mounted on %s nodes in cluster %s:"
    ;;

    479 ) msgTxt=\
"File system %s %s is mounted on %s nodes in cluster %s."
    ;;

    480 ) msgTxt=\
"File system %s is mounted on %s nodes in cluster %s."
    ;;

    482 ) msgTxt=\
"manager"
    ;;

    490 ) msgTxt=\
"Local Name  Remote Name  Cluster name           Mount Point          Mount Options    Automount"
    ;;

    496 ) msgTxt=\
" Node number  Node name       Quorum  Nodes up  Total nodes  GPFS state  Remarks    "
    ;;

    497 ) msgTxt=\
" Node number  Node name        GPFS state "
    ;;

    501 ) msgTxt=\
" File system   Disk name    NSD volume ID      Primary node             Backup node          "
    ;;

    502 ) msgTxt=\
" Disk name    NSD volume ID      Device         Node name                Remarks       "
    ;;

    503 ) msgTxt=\
" File system   Disk name    Primary node             Backup node           "
    ;;

    506 ) msgTxt=\
"Disk name     IO performed on node     Device             Availability"
    ;;

    512 ) msgTxt=\
" Disk name    NSD volume ID      Device         Devtype  Node name                Remarks          "
    ;;

    519 ) msgTxt=\
"Additional mount options"
    ;;

    521 ) msgTxt=\
"File system %s %s is mounted on %s nodes:"
    ;;

    522 ) msgTxt=\
"File system %s is mounted on %s nodes:"
    ;;

    527 ) msgTxt=\
"%s still running . . .\n"
          printTimeStamp=yes
    ;;

    541 ) msgTxt=\
"File system %s %s is not mounted."
    ;;

    542 ) msgTxt=\
"File system %s %s is not mounted on any remote cluster nodes."
    ;;

    543 ) msgTxt=\
"File system %s %s is not mounted on any node in cluster %s."
    ;;

    544 ) msgTxt=\
"File system %s is not mounted."
    ;;

    545 ) msgTxt=\
"File system %s is not mounted on any remote cluster nodes."
    ;;

    546 ) msgTxt=\
"File system %s is not mounted on any node in cluster %s."
    ;;

    553 ) msgTxt=\
"File system %s %s is mounted on %s nodes."
    ;;

    554 ) msgTxt=\
"File system %s is mounted on %s nodes."
    ;;

    559 ) msgTxt=\
"Default mount point"
    ;;

    586 ) msgTxt=\
"The %s subsystem is already active."
    ;;

    # Message numbers above 1000 are in message set 60 (ts/fencing/fencing.msg).

    1018 ) msgTxt=\
"The disk specification must be in one of these formats:\n"\
"   -l logicalVolumeName        (e.g., '-l lv00')\n"\
"   -v volumeGroupName          (e.g., '-v vg00')\n"\
"   -h physicalDiskName         (e.g., '-h hdisk0')\n"\
"   -p physicalVolumeIdentifier (e.g., '-p 0003366423ba4d39')\n"
    ;;

    1019 ) msgTxt=\
"Usage:  %s <disk specification>\n"
    ;;

    1020 ) msgTxt=\
"Usage:  %s <disk specification> <node id list>"
    ;;

    1021 ) msgTxt=\
"Usage:  %s <disk specification> <node id>"
    ;;

    1022 ) msgTxt=\
"Usage:  %s <disk specification> <fence id>"
    ;;

    1023 ) msgTxt=\
"The node id list is a blank-separated list of one or more node ids."
    ;;

    *   )  # unknown message, ignore it.
      return 0
    ;;

  esac

  # Message numbers below 1000 are in message set 32 (ts/admin/admin.msg).
  # Message numbers above 1000 are in message set 60 (ts/fencing/fencing.msg).
  if [[ $msgNo -lt 1000 ]]
  then
    msgSet=32
  else
    msgSet=60
  fi

  if [[ $osName = AIX ]]
  then
    # Print the message - extra arguments are ignored.
    if [[ $printTimeStamp = yes ]]
    then
      print -- "$(date) $($dspmsg -s $msgSet mmfs.cat \
        $msgNo "$msgTxt" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9")"
    else
      print -- "$($dspmsg -s $msgSet mmfs.cat \
        $msgNo "$msgTxt" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9")"
    fi

  elif [[ $osName = Linux ]]
  then
    # Print the message - extra arguments are ignored.
    if [[ $printTimeStamp = yes ]]
    then
      print -- "$(date) $($mmdspmsg -s $msgSet mmfs.cat \
        $msgNo "$msgTxt" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9")"
    else
      print -- "$($mmdspmsg -s $msgSet mmfs.cat \
        $msgNo "$msgTxt" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9")"
    fi
  else
    checkForErrors "Unknown operating system $osName" 1
  fi

}  #----- end of function printInfoMsg ---------------------------


####################################################################
#
# Function:  Prints the specified message to stderr
#
# Input:     $1 - number of the message to print
#            $2, $3, ... - arguments to pass to dspmsg
#
####################################################################
function printErrorMsg  # <msgNo> [ <arg> ... ]
{
  typeset sourceFile="mmglobfuncs.sh"
  [[ -n $DEBUG || -n $DEBUGprintErrorMsg ]] && set -x
  msgNo=$1
  typeset msgSet
  typeset printTimeStamp=no

  # Based on the message number, find the message text
  case $msgNo in

    13  ) msgTxt=\
"%s: Incorrect option: %s"
    ;;

    19  ) msgTxt=\
"%s: Obsolete option: %s"
    ;;

    20  ) msgTxt=\
"%s: Interrupt received: No changes made."
    ;;

    23  ) msgTxt=\
"%s: Disk name must be specified in disk descriptor."
    ;;

    24  ) msgTxt=\
"%s: Disk usage must be dataOnly, metadataOnly, descOnly, or dataAndMetadata."
    ;;

    30  ) msgTxt=\
"%s: User specified failure group must be in the range from -1 to 4000."
    ;;

    32  ) msgTxt=\
"%s: Interrupt received: changes not propagated."
    ;;

    33  ) msgTxt=\
"%s: Interrupt received. Only -A, -Q, and -T were changed."
    ;;

    34  ) msgTxt=\
"Usage:  %s Device"
    ;;

    35  ) msgTxt=\
"%s: Restriping may not have finished."
    ;;

    36  ) msgTxt=\
"%s: %s option specified twice."
    ;;

    37  ) msgTxt=\
"%s: %s value must be yes or no."
    ;;

    38  ) msgTxt=\
"%s: Incorrect extra argument: %s"
    ;;

    39 ) msgTxt=\
"Usage: %s QueryType ItemList [Scope [norefresh]]"
    ;;

    40  ) msgTxt=\
"%s: Incorrect integer for %s: %s"
    ;;

    41  ) msgTxt=\
"%s: No disk descriptor file specified"
    ;;

    42  ) msgTxt=\
"%s: File %s already exists."
    ;;

    43  ) msgTxt=\
"%s: Cannot open %s"
    ;;

    44  ) msgTxt=\
"%s: Incompatible cluster types.  You cannot move file systems that were\n"\
"created by GPFS cluster type %s into GPFS cluster type %s."
    ;;

    45  ) msgTxt=\
"%s: %s must be greater than 0: %s"
    ;;

    47  ) msgTxt=\
"%s: Error converting %s into an NSD."
    ;;

    48  ) msgTxt=\
"%s: File system %s already exists in the cluster.\n"\
"    Use mmchfs -W to assign a new device name for the existing file system."
    ;;

    49  ) msgTxt=\
"%s: %s is defined to have mount point %s.\n"\
"    There is already such a mount point in the cluster.\n"\
"    Use mmchfs -T to assign a new mount point to the existing file system."
    ;;

    50  ) msgTxt=\
"%s: Error encountered while importing disk %s."
    ;;

    51  ) msgTxt=\
"%s: Disk %s already exists in the cluster."
    ;;

    53  ) msgTxt=\
"%s: At least one node in the cluster must be defined as a quorum node."
    ;;

    54  ) msgTxt=\
"%s: Incorrect node %s specified for command."
    ;;

    61  ) msgTxt=\
"%s: Use the dash character (-) to separate multiple node designations."
    ;;

    62  ) msgTxt=\
"%s: Use the semi-colon character (;) to separate the disk names."
    ;;

    63  ) msgTxt=\
"%s: GPFS is still active on %s"
    ;;

    78  ) msgTxt=\
"%s: %s must be from %s to %s: %s"
    ;;

    79  ) msgTxt=\
"%s: mmfixcfg failed while changing %s"
    ;;

    88  ) msgTxt=\
"%s: Duplicate disk specified: %s"
    ;;

    89  ) msgTxt=\
"%s: You cannot delete all disks"
    ;;

    97  ) msgTxt=\
"%s: %s must be greater than %s: %s"
    ;;

    100 ) msgTxt=\
"%s: tscrfs failed.  Cannot create %s"
    ;;

    101 ) msgTxt=\
"%s: Disk %s does not belong to file system %s."
    ;;

    102 ) msgTxt=\
"%s: Active disks are missing from the GPFS configuration data:"
    ;;

    103 ) msgTxt=\
"%s: Attention: File system %s may have some disks\n"\
"that are in a non-ready state.  Issue the command:\n"\
"  mmcommon recoverfs %s"
    ;;

    104 ) msgTxt=\
"%s: %s failed."
    ;;

    105 ) msgTxt=\
"%s: Failed to connect to remote cluster %s"
    ;;

    106 ) msgTxt=\
"%s: File system %s belongs to cluster %s.\n"\
"    Command is not allowed for remote file systems."
    ;;

    107 ) msgTxt=\
"%s: There is already an existing file system using %s"
    ;;

    108 ) msgTxt=\
"%s: File system %s not found in cluster %s"
    ;;

    109 ) msgTxt=\
"%s: GPFS is down on this node."
    ;;

    110 ) msgTxt=\
"%s: GPFS is not ready to handle commands yet."
    ;;

    111 ) msgTxt=\
"%s: %s refers to file system %s in cluster %s"
    ;;

    112 ) msgTxt=\
"%s: File system %s does not belong to cluster %s"
    ;;

    113 ) msgTxt=\
"%s: %s failed. Error code %s."
    ;;

    127 ) msgTxt=\
"%s: The main GPFS cluster configuration file is locked.  Retrying..."
    ;;

    128 ) msgTxt=\
"%s: Lock creation successful."
    ;;

    129 ) msgTxt=\
"%s: Timed out waiting for lock.  Try again later."
    ;;

    130 ) msgTxt=\
"%s: Disk %s is a tiebreaker disk and cannot be deleted."
    ;;

    131 ) msgTxt=\
"%s: GPFS detected more than eight quorum nodes while\n"\
"node quorum with tiebreaker disks is in use."
    ;;

    132 ) msgTxt=\
"%s: GPFS failed to initialize the tiebreaker disks."
    ;;

    133 ) msgTxt=\
"%s: Incorrect keyword: %s"
    ;;

    134 ) msgTxt=\
"%s: Adding node %s to the cluster will exceed\n"\
"the quorum node limit."
    ;;

    135 ) msgTxt=\
"%s: The %s kernel extension does not exist."
    ;;

    136 ) msgTxt=\
"%s: Unable to verify kernel/module configuration."
    ;;

    137 ) msgTxt=\
"%s: The GPFS daemon is still running; use the mmshutdown command."
    ;;

    138 ) msgTxt=\
"%s: Module %s is still in use.\n"\
"Unmount all GPFS file systems and issue the command:\n"\
"  mmfsadm cleanup"
    ;;

    139 ) msgTxt=\
"%s: Error unloading module %s."
    ;;

    140 ) msgTxt=\
"%s: Module %s is already loaded."
    ;;

    141 ) msgTxt=\
"%s: %s was not found in /proc/partitions."
    ;;

    142 ) msgTxt=\
"%s: GPFS is waiting for %s"
          printTimeStamp=yes
    ;;

    144 ) msgTxt=\
"%s: \"%s\" is set by the mmcrcluster processing.\n"\
"    Line in error: %s\n"\
"    The line is ignored; processing continues."
    ;;

    145 ) msgTxt=\
"%s: \"%s\" must be set with the %s command.\n"\
"    Line in error: %s\n"\
"    The line is ignored; processing continues."
    ;;

    146 ) msgTxt=\
"%s: \"%s\" is an obsolete parameter.\n"\
"    Line in error: %s\n"\
"    The line is ignored; processing continues."
    ;;

    147 ) msgTxt=\
"%s: \"%s\" cannot appear in a node-override section.\n"\
"    Line in error: %s\n"\
"    The line is ignored; processing continues."
    ;;

    148 ) msgTxt=\
"%s: Mount point can not be a relative path name: %s"
    ;;

    149 ) msgTxt=\
"%s: %s can not be a relative path name: %s"
    ;;

    150 ) msgTxt=\
"%s: Key file is not valid."
    ;;

    151 ) msgTxt=\
"%s: Key file mismatch."
    ;;

    152 ) msgTxt=\
"%s: Node %s already belongs to the GPFS cluster."
    ;;

    153 ) msgTxt=\
"%s: Incorrect value for %s option"
    ;;

    154 ) msgTxt=\
"%s: Adapter port name %s is not known on node %s."
    ;;

    155 ) msgTxt=\
"%s: There is nothing to commit.  You must first run:\n    %s"
    ;;

    156 ) msgTxt=\
"%s: The current authentication files are already committed."
    ;;

    157 ) msgTxt=\
"%s: There are uncommitted authentication files.  You must first run:\n    %s"
    ;;

    158 ) msgTxt=\
"%s: You must establish a cipher list first.  Run:\n    %s"
    ;;

    159 ) msgTxt=\
"%s: %s not found.  Ensure the OpenSSL code is properly installed."
    ;;

    160 ) msgTxt=\
"%s: For the logical volume specification \"-l %s\" to be valid\n"\
"%s must be the only logical volume in the volume group.\n"\
"However, volume group %s contains the following logical volumes:"
    ;;

    161 ) msgTxt=\
"%s: %s is not a valid logical volume."
    ;;

    162 ) msgTxt=\
"%s: %s is not a valid volume group name."
    ;;

    163 ) msgTxt=\
"%s: For the hdisk specification \"-h %s\" to be valid\n"\
"%s must be the only disk in the volume group.\n"\
"However, volume group %s contains the following disks:"
    ;;

    164 ) msgTxt=\
"%s: %s is not a valid physical volume name."
    ;;

    165 ) msgTxt=\
"%s: %s is not a valid physical volume id."
    ;;

    166 ) msgTxt=\
"Usage:  %s <disk specification>\n"
    ;;

    167 ) msgTxt=\
"The disk specification must be in one of these formats:\n"\
"   -l logicalVolumeName        (e.g., '-l lv00')\n"\
"   -v volumeGroupName          (e.g., '-v vg00')\n"\
"   -h physicalDiskName         (e.g., '-h hdisk0')\n"\
"   -p physicalVolumeIdentifier (e.g., '-p 0003366423ba4d39')\n"
    ;;

    168 ) msgTxt=\
"%s: Missing arguments"
    ;;

    169 ) msgTxt=\
"%s: The device name %s starts with a slash, but not /dev/."
    ;;

    170 ) msgTxt=\
"%s: The device name %s contains a slash, but not as its first character."
    ;;

    171 ) msgTxt=\
"%s: Unexpected error from %s.  Return code: %s"
    ;;

    172 ) msgTxt=\
"%s: Unknown user name %s"
    ;;

    173 ) msgTxt=\
"%s: Unknown group name %s"
    ;;

    174 ) msgTxt=\
"%s: The administrative adapter port name was not defined\n"\
"for nodes:\n\t %s\n"\
"Correct the problems and run mmchcluster -N again."
    ;;

    175 ) msgTxt=\
"%s: Daemon node adapter %s was not found on admin node %s."
    ;;

    176 ) msgTxt=\
"%s: Command failed for disks: %s"
    ;;

    177 ) msgTxt=\
"%s: No contact nodes were provided for cluster %s"
    ;;

    178 ) msgTxt=\
"%s: None of the contact nodes in cluster %s can be reached."
    ;;

    184 ) msgTxt=\
"Usage: %s [-a | -n NodeName]"
    ;;

    185 ) msgTxt=\
"Usage: %s Device [-W NewDeviceName]"
    ;;

    186 ) msgTxt=\
"Usage: %s [-d IntegerDelayValue] [-i CommandFile] [-p]\n"\
"        [-r IntegerRepeatValue] [-s] [-t IntegerTimeoutValue]"
    ;;

    187 ) msgTxt=\
"%s: Node %s returned ENODEV for disk %s."
    ;;

    188 ) msgTxt=\
"%s: Remote cluster %s was not found."
    ;;

    189 ) msgTxt=\
"%s: Name %s is not allowed.\n"\
"It contains the following invalid special character:  %s"
    ;;

    190 ) msgTxt=\
"%s: GPFS configuration data for file system %s\n"\
"may not be in agreement with the on-disk data for the file system.\n"\
"Issue the command:\n"\
"  mmcommon recoverfs %s"
    ;;

    191 ) msgTxt=\
"%s: Options %s and %s cannot be specified at the same time."
    ;;

    192 ) msgTxt=\
"%s: <nodelist> cannot be used with attribute %s"
    ;;

    193 ) msgTxt=\
"%s: There are no remote file systems."
    ;;

    194 ) msgTxt=\
"%s: Remote file system %s is not defined."
    ;;

    195 ) msgTxt=\
"%s: The GPFS configuration information is incorrect or not available."
    ;;

    196 ) msgTxt=\
"%s: Device name cannot be 'all'."
    ;;

    197 ) msgTxt=\
"%s: Each device specifies metadataOnly for disk usage.\n"\
"This file system could not store data."
    ;;

    198 ) msgTxt=\
"%s: Each device specifies dataOnly for disk usage.\n"\
"This file system could not store metadata."
    ;;

    199 ) msgTxt=\
"%s: Incorrect integer %s specified for failure group."
    ;;

    200 ) msgTxt=\
"%s: No file systems were found."
    ;;

    201 ) msgTxt=\
"%s: Incorrect server node %s in disk descriptor."
    ;;

    202 ) msgTxt=\
"%s: %s is the name of the local cluster."
    ;;

    204 ) msgTxt=\
"%s: Missing argument after %s option"
    ;;

    229 ) msgTxt=\
"Usage: %s [-CIVOSPDH] [-c] [-u] [-d disk] [-g volumeGroup]\n"\
"        [-l logicalVolume] [-G globalVolumeGroup] [-L globalLogicalVolume]\n"\
"        [-p physicalVolumeID ]\n"
    ;;

    230 ) msgTxt=\
"%s: %s is already in volume group %s and cannot be added to %s.\n"
    ;;

    232 ) msgTxt=\
"%s: Cannot find %s with %s.\n"
    ;;

    233 ) msgTxt=\
"%s: %s requires a value.\n"
    ;;

    234 ) msgTxt=\
"%s: Incorrect option: %s\n"
    ;;

    235 ) msgTxt=\
"%s: Interrupt received.\n"
    ;;

    236 ) msgTxt=\
"%s: Volume group %s cannot be imported on node\n"\
"%s because the disk with physical volume ID %s\n"\
"cannot be found."
    ;;

    237 ) msgTxt=\
"%s: Failed to obtain DCE credentials; dsrvtgt %s command rc=%s. Continuing."
    ;;

    238 ) msgTxt=\
"%s: Command is not allowed for remote file systems."
    ;;

    239 ) msgTxt=\
"%s: Disk usage %s is incompatible with storage pool %s."
    ;;

    240 ) msgTxt=\
"%s: File %s not found.  Recover the file or run mmauth genkey."
    ;;

    246 ) msgTxt=\
"Usage:\n"\
"  %s [-t UnmountTimeout]\n"\
"             [-a | -N {Node[,Node...] | NodeFile | NodeClass}]"
    ;;

    247 ) msgTxt=\
"%s: Disk with NSD volume id %s no longer\n"\
"          exists in the GPFS cluster configuration data but the NSD volume id\n"\
"          was not erased from the disk.  To remove the NSD volume id, issue\n"\
"             mmdelnsd -p %s"
    ;;

    248 ) msgTxt=\
"%s: Disk with NSD volume id %s no longer\n"\
"          exists in the GPFS cluster configuration data but the NSD volume id\n"\
"          was not erased from the disk.  To remove the NSD volume id, issue\n"\
"             mmdelnsd -p %s -N %s"
    ;;

    249 ) msgTxt=\
"Usage:\n"\
"   %s genkey {new | commit}\n"\
"      or\n"\
"   %s add    RemoteClusterName -k KeyFile [-l CipherList]\n"\
"      or\n"\
"   %s update RemoteClusterName {[-C NewClusterName] [-k KeyFile] [-l CipherList]}\n"\
"      or\n"\
"   %s delete {RemoteClusterName | all}\n"\
"      or\n"\
"   %s grant  {RemoteClusterName | all} -f {Device | all} [-a {rw | ro}] [-r {uid:gid | no}]\n"\
"      or\n"\
"   %s deny   {RemoteClusterName | all} -f {Device | all}\n"\
"      or\n"\
"   %s show   [RemoteClusterName | all]\n"
    ;;

    252 ) msgTxt=\
"%s: %s is not a remote file system known to GPFS."
    ;;

    257 ) msgTxt=\
"%s: An internode connection between GPFS nodes was disrupted."
    ;;

    258 ) msgTxt=\
"%s: No clusters are authorized to access this cluster."
    ;;

    259 ) msgTxt=\
"%s: Cluster %s is not authorized to access this cluster."
    ;;

    260 ) msgTxt=\
"Usage: %s %s %s"
    ;;

    261 ) msgTxt=\
"%s: Attention: There are no available valid VFS type values for mmfs in /etc/vfs."
    ;;

    262 ) msgTxt=\
"%s: There are no remote cluster definitions."
    ;;

    263 ) msgTxt=\
"%s: Remote cluster %s is not defined."
    ;;

    264 ) msgTxt=\
"%s: No disks specified"
    ;;

    265 ) msgTxt=\
"%s: Disk %s already belongs to file system %s."
    ;;

    266 ) msgTxt=\
"%s: File system %s has some disks that are in a non-ready state."
    ;;

    267 ) msgTxt=\
"%s: Attention: Not all disks were marked as available."
    ;;

    268 ) msgTxt=\
"%s: This GPFS cluster contains declarations for remote file systems and clusters.\n"\
"    You cannot delete the last node."
    ;;

    270 ) msgTxt=\
"%s: The following nodes could not be reached:\n"
    ;;

    271 ) msgTxt=\
"%s: Propagating the cluster configuration data to all\n"\
"  affected nodes.  This is an asynchronous process."
    ;;

    272 ) msgTxt=\
"%s: Command successfully completed"
    ;;

    273 ) msgTxt=\
"%s: There is no file system information in input file %s."
    ;;

    274 ) msgTxt=\
"%s: File system %s was not found in input file %s."
    ;;

    275 ) msgTxt=\
"%s: The following file systems were not imported:%s"
    ;;

    277 ) msgTxt=\
"%s: Attention: Unknown attribute specified: %s.  Press the ENTER key to continue."
    ;;

    278 ) msgTxt=\
"%s: Incorrect record found in the mmsdrfs file (code %s):"
    ;;

    279 ) msgTxt=\
"%s: There is no file system with mount point %s."
    ;;

    280 ) msgTxt=\
"%s: File system %s is already mounted at %s."
    ;;

    281 ) msgTxt=\
"%s: Mount point cannot be specified when mounting all file systems."
    ;;

    282 ) msgTxt=\
"%s: This node does not belong to a GPFS cluster."
    ;;

    283 ) msgTxt=\
"%s:  There is no record for this node in file %s.\n"\
"  Either the node is not part of the cluster, or the file is for a different cluster,\n"\
"  or not all of the node's adapter interfaces have been activated yet."
    ;;

    284 ) msgTxt=\
"Usage:\n"\
"  %s [-p NodeName] [-F mmsdrfsFile] [-R RemoteFileCopyCommand]"
    ;;

    285 ) msgTxt=\
"%s:  Node %s successfully restored."
    ;;

    286 ) msgTxt=\
"%s: Unexpected value for Gpfs object: %s"
    ;;

    287 ) msgTxt=\
"Usage:\n"\
"  %s Device {resume | start} -a\n"\
"             [-N {Node[,Node...] | NodeFile | NodeClass}]\n"\
"    or\n"\
"  %s Device {suspend | resume | stop | start | change}\n"\
"             -d \"DiskDesc[;DiskDesc...]\"\n"\
"             [-N {Node[,Node...] | NodeFile | NodeClass}]"
    ;;

    288 ) msgTxt=\
"%s: File system %s is not known to the GPFS cluster."
    ;;

    289 ) msgTxt=\
"Usage:\n"\
"  %s Attribute=value[,Attribute=value...] [-i | -I]\n"\
"               [-N {Node[,Node...] | NodeFile | NodeClass}]"
    ;;

    290 ) msgTxt=\
"%s: Node %s does not belong to the GPFS cluster,\n"\
"  or is represented multiple times on the command line."
    ;;

    291 ) msgTxt=\
"Usage:\n"\
"  %s Device {\"DiskDesc[;DiskDesc...]\" | -F DescFile} [-a] [-c]\n"\
"            [-r] [-N {Node[,Node...] | NodeFile | NodeClass}]"
    ;;

    292 ) msgTxt=\
"Usage: %s Device [-p]"
    ;;

    293 ) msgTxt=\
"%s: Invalid node designation specified: %s"
    ;;

    294 ) msgTxt=\
"%s: Operation not allowed for the local cluster."
    ;;

    295 ) msgTxt=\
"Usage:\n"\
"  %s Device DiskName {DiskDesc | -F DescFile} [-v {yes | no}]\n"\
"                   [-N {Node[,Node...] | NodeFile | NodeClass}]"
    ;;

    296 ) msgTxt=\
"Usage:\n"\
"  %s Device {\"DiskDesc[;DiskDesc...]\" | -F DescFile} [-a] [-r]\n"\
"    [-v {yes | no}] [-N {Node[,Node...] | NodeFile | NodeClass}]"
    ;;

    298 ) msgTxt=\
"Usage: %s Device [-d | -F | -m] [-P PoolName] [-q]"
    ;;

    299 ) msgTxt=\
"Usage: %s Device [-i] [-u BlkUtilPct] [-v]"
    ;;

    300 ) msgTxt=\
"Usage:\n"\
"  %s Device [-n | -y] [-v | -V] [-c | -o] [-t Directory]\n"\
"    [-N {Node[,Node...] | NodeFile | NodeClass}]"
    ;;

    301 ) msgTxt=\
"Usage:\n"\
"   %s Device [-d \"DiskName[;DiskName...]\"] [-e] [-L]\n"\
"      or\n"\
"   %s Device [-d \"DiskName[;DiskName...]\"] {-m | -M}"
    ;;

    302 ) msgTxt=\
"Usage:\n"\
"  %s Device {-m | -r | -b | -p | -R} [-P PoolName]\n"\
"    [-N {Node[,Node...] | NodeFile | NodeClass}]"
    ;;

    303 ) msgTxt=\
"Usage: %s [Device[ Device...]] | [-C ClusterName]"
    ;;

    304 ) msgTxt=\
"Usage: %s Device [Node]"
    ;;

    305 ) msgTxt=\
"%s: Mount point and device name cannot be equal: %s"
    ;;

    306 ) msgTxt=\
"%s: Interrupt received."
    ;;

    307 ) msgTxt=\
"%s: You must first generate an authentication key file. Run:\n"\
"   mmauth genkey new"
    ;;

    309 ) msgTxt=\
"%s: The -i option failed. Changes will take effect after GPFS is restarted."
    ;;

    310 ) msgTxt=\
"%s: This GPFS cluster contains file systems. You cannot delete the last node."
    ;;

    311 ) msgTxt=\
"%s: Attention: Failed to remove node-specific changes."
    ;;

    312 ) msgTxt=\
"%s: %s command cannot be executed.  Either none of the\n"\
"  nodes in the cluster are reachable, or GPFS is down on all of the nodes."
    ;;

    313 ) msgTxt=\
"%s: Attention: The file system may no longer be properly balanced"
    ;;

    314 ) msgTxt=\
"%s: To change the authentication key for the local cluster, run:\n"\
"   mmauth genkey"
    ;;

    315 ) msgTxt=\
"%s: %s not found in file system %s"
    ;;

    316 ) msgTxt=\
"%s: Remote cluster %s is already defined."
    ;;

    317 ) msgTxt=\
"%s: File system %s from cluster %s is already defined."
    ;;

    318 ) msgTxt=\
"%s: %s command failed.  Only %s changed."
    ;;

    319 ) msgTxt=\
" The volume group %s exists, but partition\n"\
"information cannot be determined.  Perhaps it needs to be varied on?\n"
    ;;

    321 ) msgTxt=\
"%s: %s does not exist or failed; automount mounting may not work."
    ;;

    322 ) msgTxt=\
"%s: The command must run on a node that is part of the cluster."
    ;;

    323 ) msgTxt=\
"%s: Command completed: No changes made"
    ;;

    324 ) msgTxt=\
"%s: Permission failure.  The command requires root authority to execute."
    ;;

    328 ) msgTxt=\
"%s: File %s does not contain node names."
    ;;

    329 ) msgTxt=\
"%s: File %s does not contain data."
    ;;

    330 ) msgTxt=\
"%s: Failed to obtain Kerberos credentials; ksrvtgt %s command rc=%s. Continuing."
    ;;

    334 ) msgTxt=\
"Usage:\n"\
"   %s {Device | all} [-a] [-A] [-B] [-d] [-D] [-E] [-f] [-F] [-i]\n"\
"                         [-I] [-j] [-k] [-K] [-m] [-M] [-n] [-o] [-P]\n"\
"                         [-Q] [-r] [-R] [-s] [-S] [-T] [-u] [-V] [-z]\n"
    ;;

    337 ) msgTxt=\
"%s:  Unable to determine the local device name for disk %s on node %s."
    ;;

    338 ) msgTxt=\
"%s:  Unknown GPFS execution environment %s"
    ;;

    340 ) msgTxt=\
"%s:  %s cannot be reached."
    ;;

    341 ) msgTxt=\
"%s:  Attention:  Unable to retrieve GPFS cluster files from node %s"
    ;;

    342 ) msgTxt=\
"%s:  Unable to retrieve GPFS cluster files from node %s"
    ;;

    343 ) msgTxt=\
"Usage:\n"\
"  %s -N {NodeDesc[,NodeDesc...] | NodeFile}\n"\
"              -p PrimaryServer [-s SecondaryServer]\n"\
"              [-r RemoteShellCommand] [-R RemoteFileCopyCommand]\n"\
"              [-C ClusterName] [-U DomainName] [-A] [-c ConfigFile]"
    ;;

    344 ) msgTxt=\
"%s:  Run the %s command until successful."
    ;;

    345 ) msgTxt=\
"%s: No nodes were found that matched the input specification."
    ;;

    346 ) msgTxt=\
"%s:  The same node was specified for both the primary and the secondary server."
    ;;

    347 ) msgTxt=\
"%s:  Node %s is specified more than once."
    ;;

    348 ) msgTxt=\
"%s:  Node %s was not added to the cluster.\n"\
"   The node appears to already belong to a GPFS cluster."
    ;;

    349 ) msgTxt=\
"%s:  The level of GPFS on node %s does not support the requested action."
    ;;

    350 ) msgTxt=\
"%s:  Make sure that the following nodes are available: %s"
    ;;

    351 ) msgTxt=\
"%s:  Removing GPFS cluster files from the nodes in the cluster . . . "
    ;;

    352 ) msgTxt=\
"%s:  %s is not a member of this cluster."
    ;;

    353 ) msgTxt=\
"%s:  The following nodes could not be added to the GPFS cluster:%s\n"\
"   Correct the problems and use the mmaddnode command to add these nodes\n"\
"   to the cluster."
    ;;

    354 ) msgTxt=\
"%s:  Information cannot be displayed.  Either none of the\n"\
"  nodes in the cluster are reachable, or GPFS is down on all of the nodes."
    ;;

    355 ) msgTxt=\
"Usage:\n"\
"  %s -N {NodeDesc[,NodeDesc...] | NodeFile}"
    ;;

    356 ) msgTxt=\
"Usage:\n"\
"  %s {-a | -N {Node[,Node...] | NodeFile | NodeClass}}"
    ;;

    357 ) msgTxt=\
"Usage:  %s "
    ;;

    358 ) msgTxt=\
"Usage:  %s Device [-L]"
    ;;

    359 ) msgTxt=\
"Usage:  %s {[-p PrimaryServer] [-s SecondaryServer]}\n"\
"           or\n"\
"         %s -p LATEST\n"\
"           or\n"\
"         %s {[-r RemoteShellCommand] [-R RemoteFileCopyCommand]}\n"\
"           or\n"\
"         %s -C ClusterName\n"\
"           or\n"\
"         %s -N {NodeDesc[,NodeDesc...] | NodeFile}"
    ;;

    360 ) msgTxt=\
"%s: Disk %s is the only disk in file system %s.\n"\
"You cannot replace a disk when it is the only remaining disk in the file system."
    ;;

    361 ) msgTxt=\
"Usage:  %s Device PolicyFilename [-t DescriptiveName] [-I {yes|test}]"
    ;;

    367 ) msgTxt=\
"%s: There are no available nodes on which to run the command."
    ;;

    370 ) msgTxt=\
"Usage:  %s"
    ;;

    371 ) msgTxt=\
"Usage:  %s Device Directory"
    ;;

    372 ) msgTxt=\
"Usage:  %s Device Directory"
    ;;

    374 ) msgTxt=\
"Usage:\n"\
"  %s [-f] [-a | -N {Node[,Node...] | NodeFile | NodeClass}]"
    ;;

    375 ) msgTxt=\
"%s:  %s cannot be used with attribute %s"
    ;;

    376 ) msgTxt=\
"%s:  Command is not supported in the %s environment."
    ;;

    377 ) msgTxt=\
"%s:  Command failed on nodes: %s"
    ;;

    378 ) msgTxt=\
"%s:  Cannot determine basic environment information.\n"\
"   Not enough nodes are available."
    ;;

    379 ) msgTxt=\
"%s:  Error retrieving data from %s to %s."
    ;;

    380 ) msgTxt=\
"%s:  The GPFS cluster data on %s is back level."
    ;;

    381 ) msgTxt=\
"%s:  The commit process failed."
    ;;

    382 ) msgTxt=\
"%s:  The GPFS cluster configuration data on %s\n"\
"is different from the data on %s."
    ;;

    383 ) msgTxt=\
"%s:  Failed to create a backup copy of the GPFS cluster data on %s."
    ;;

    384 ) msgTxt=\
"%s: GPFS cluster configuration server node %s cannot be removed."
    ;;

    385 ) msgTxt=\
"Usage:\n"\
"   %s add Device -f RemoteDevice -C RemoteClusterName\n"\
"                 -T Mountpoint [-o MountOptions] [-A {yes | no | automount}]\n"\
"      or\n"\
"   %s update Device [-f RemoteDevice] [-C RemoteClusterName]\n"\
"                [-T Mountpoint] [-o MountOptions] [-A {yes | no | automount}]\n"\
"      or\n"\
"   %s delete {Device | all | -C RemoteClusterName}\n"\
"      or\n"\
"   %s show   [Device | all | -C RemoteClusterName]\n"
    ;;

    386 ) msgTxt=\
"%s:  Error found while checking disk descriptor %s"
    ;;

    387 ) msgTxt=\
"%s: %s quitting.  None of the specified nodes are valid."
    ;;

    388 ) msgTxt=\
"Usage:\n"\
"   %s add RemoteClusterName -k KeyFile -n ContactNodes\n"\
"      or\n"\
"   %s update RemoteClusterName {[-C NewClusterName] [-k KeyFile] [-n ContactNodes]}\n"\
"      or\n"\
"   %s delete {RemoteClusterName | all}\n"\
"      or\n"\
"   %s show [RemoteClusterName | all]\n"
    ;;

    389 ) msgTxt=\
"%s: Command failed.  Examine previous error messages to determine cause."
    ;;

    390 ) msgTxt=\
"Usage:\n"\
"  %s {Device | DefaultMountPoint | all | all_local | all_remote} [-o MountOptions]\n"\
"          [-a | -N {Node[,Node...] | NodeFile | NodeClass}]\n"\
"      or\n"\
"  %s Device MountPoint [-o MountOptions]\n"\
"          [-a | -N {Node[,Node...] | NodeFile | NodeClass}]"
    ;;

    391 ) msgTxt=\
"Usage:\n"\
"  %s [-a | -N {Node[,Node...] | NodeFile | NodeClass}]\n"\
"            [-E EnvVar=value...]"
    ;;

    393 ) msgTxt=\
"%s: The number of quorum nodes exceeds the maximum (%s) allowed."
    ;;

    394 ) msgTxt=\
"%s: Warning: The number of quorum nodes exceeds the suggested maximum (%s)."
    ;;

    395 ) msgTxt=\
"%s: Node %s is fenced out from disk %s."
    ;;

    396 ) msgTxt=\
"Usage:\n"\
"  %s {Device | MountPoint | all | all_local | all_remote} [-f]\n"\
"           [-a | -N {Node[,Node...] | NodeFile | NodeClass}]\n"\
"      or\n"\
"  %s Device -f -C {all_remote | ClusterName} [-N Node[,Node...]]"
    ;;

    397 ) msgTxt=\
"%s: Unable to find disk with NSD volume id %s."
    ;;

    398 ) msgTxt=\
"%s: GPFS was unable to obtain a lock from node %s."
    ;;

    399 ) msgTxt=\
"%s: Remount failed for file system %s. Error code %s."
    ;;

    410 ) msgTxt=\
"Usage:  %s -F DescFile [-v {yes | no}]\n"
    ;;

    411 ) msgTxt=\
"%s:  Failed while processing disk descriptor %s on node %s."
    ;;

    412 ) msgTxt=\
"%s:  Disk descriptor %s refers to an existing NSD %s"
    ;;

    413 ) msgTxt=\
"Usage:\n"\
"   %s {\"DiskName[;DiskName...]\" | -F DiskFile}\n"\
"      or\n"\
"   %s -p NSDId [-N Node[,Node]]"
    ;;

    415 ) msgTxt=\
"%s:  Disk descriptor %s should refer to an existing NSD.\n"\
"Use mmcrnsd to create the NSD."
    ;;

    417 ) msgTxt=\
"%s: Issue the command from a node that remains in the cluster."
    ;;

    418 ) msgTxt=\
"%s: No disks were found."
    ;;

    419 ) msgTxt=\
"Usage:  %s Device Directory [-c]"
    ;;

    420 ) msgTxt=\
"Usage:\n"\
"   %s Mountpoint Device {\"DiskDesc[;DiskDesc...]\" | -F DescFile}\n"\
"          [-A {yes | no | automount}] [-B BlockSize] [-D {posix | nfs4}]\n"\
"          [-E {yes | no}] [-j {cluster | scatter}]\n"\
"          [-k {posix | nfs4 | all}] [-K {no | whenpossible | always}]\n"\
"          [-m DefaultMetadataReplicas] [-M MaxMetadataReplicas]\n"\
"          [-n NumNodes] [-N NumInodes[:NumInodesToPreallocate]] [-Q {yes | no}]\n"\
"          [-r DefaultDataReplicas] [-R MaxDataReplicas]\n"\
"          [-S {yes | no}] [-v {yes | no}] [-z {yes | no}]\n"
    ;;

    421 ) msgTxt=\
"Usage:\n"\
"   %s Device [-A {yes | no | automount}] [-D {posix | nfs4}] [-E {yes | no}]\n"\
"                 [-F MaxNumInodes[:NumInodesToPreallocate]]\n"\
"                 [-k {posix | nfs4 | all}] [-K {no | whenpossible | always}]\n"\
"                 [-m DefaultMetadataReplicas] [-o MountOptions]\n"\
"                 [-Q {yes | no}] [-r DefaultDataReplicas] [-S {yes | no}]\n"\
"                 [-T Mountpoint] [-V] [-z {yes | no}]\n"\
"      or\n"\
"   %s Device [-W NewDeviceName]"
    ;;

    422 ) msgTxt=\
"%s:  Incorrect or missing remote shell command:  %s"
    ;;

    423 ) msgTxt=\
"%s:  Incorrect or missing remote file copy command:  %s"
    ;;

    424 ) msgTxt=\
"%s:  %s %s parameter must be an absolute pathname."
    ;;

    425 ) msgTxt=\
"Usage:\n"\
"   %s {[-r RemoteShellCommand] [-R RemoteFileCopyCommand]} [-f]\n"\
"      or\n"\
"   %s -C ClusterName"
    ;;

    428 ) msgTxt=\
"Usage:\n"\
"   %s [-a | -F | -f Device | -d \"DiskName[;DiskName...]\"]\n"\
"           [-L | -m | -M | -X] [-v]"
    ;;

    429 ) msgTxt=\
"%s: Disk %s is of an unknown type."
    ;;

    432 ) msgTxt=\
"%s: Disk name %s is already registered for use by GPFS."
    ;;

    433 ) msgTxt=\
"%s:  Node %s is being used as a primary or backup NSD server."
    ;;

    437 ) msgTxt=\
"%s:  Processing continues without lock protection."
    ;;

    438 ) msgTxt=\
"Usage:  %s {\"DiskDesc[;DiskDesc...]\" | -F DescFile}\n"
    ;;

    439 ) msgTxt=\
"Usage: %s Device [-d] [-Q]"
    ;;

    440 ) msgTxt=\
"%s: Command was unable to obtain the lock for the GPFS system data.\n"\
"    Unable to reach the holder of the lock %s.\n"\
"    Check the preceding messages, if any.  Follow the procedure outlined\n"\
"    in the GPFS Problem Determination Guide."
    ;;

    441 ) msgTxt=\
"vpath disk %s is not recognized as an IBM SDD device.\n"
    ;;

    448 ) msgTxt=\
"Usage:  %s "
    ;;

    449 ) msgTxt=\
"Usage:\n"\
"  %s [-L] [-s] [-v] [-a | -N {Node[,Node...] | NodeFile | NodeClass}]"
    ;;

    450 ) msgTxt=\
"%s: Disk %s belongs to vpath %s.\n"
    ;;

    452 ) msgTxt=\
"Usage:\n"\
"  %s [-u User | -g Group | -j Fileset] [-v | -q] [-e]\n"\
"              [-C ClusterName] [Device1 Device2 ...]\n"\
"    or\n"\
"  %s -d {-u | -g | -j} [-C ClusterName] [Device1 Device2 ...]\n"
    ;;

    454 ) msgTxt=\
"%s: Failed to stat %s."
    ;;

    455 ) msgTxt=\
"%s: %s is not a GPFS file system object."
    ;;

    456 ) msgTxt=\
"%s: The policy file cannot be determined."
    ;;

    457 ) msgTxt=\
"Usage:\n"\
"   %s {Device|Directory} [-P PolicyFile] [-I {yes|defer|test}]\n"\
"                 [-L n] [-D yyyy-mm-dd[@hh:mm[:ss]]] [-s WorkDirectory]\n"
    ;;

    458 ) msgTxt=\
"Usage:\n"\
"   %s Device -n ControlFile [-t {full | incremental}] [-s SortDir]\n"\
"      or\n"\
"   %s Device -R [-s SortDir]\n"
    ;;

    459 ) msgTxt=\
"Usage:  %s Device {\"FileName[,FileName...]\" | -f FileNameFile}\n"
    ;;

    460 ) msgTxt=\
"%s:  \"%s\" must be a absolute path name."
    ;;

    461 ) msgTxt=\
"%s: Device with major/minor numbers %s and %s already exists."
    ;;

    462 ) msgTxt=\
"%s:  %s was not created by GPFS or could not be refreshed."
    ;;

    469 ) msgTxt=\
"%s:  The %s option is not allowed for remote file systems."
    ;;

    470 ) msgTxt=\
"%s:  There are no available free disks.\n"\
"Disks must be prepared prior to invoking %s.\n"\
"Define the disks using the %s command."
    ;;

    472 ) msgTxt=\
"%s:  File system %s belongs to cluster %s.\n"\
"    The %s option is not allowed for remote file systems."
    ;;

    474 ) msgTxt=\
"%s:  %s not active on nodes: %s"
    ;;

    476 ) msgTxt=\
"%s: IP aliasing is not supported (%s).  Specify the main device."
    ;;

    481 ) msgTxt=\
"%s: The requested disks are not known to GPFS."
    ;;

    483 ) msgTxt=\
"%s:  %s is not a valid cipher list."
    ;;

    484 ) msgTxt=\
"Usage:\n"\
"   %s Device {suspend | resume}\n"\
"      or\n"\
"   %s Device {exclude | include}\n"\
"                  {-d \"DiskName[;DiskName...]\" | -F DiskFile | -G FailureGroup}\n"\
"      or\n"\
"   %s Device syncFSconfig\n"\
"                  {-n RemoteNodesFile | -C RemoteCluster} [-S SpecFile]\n"
    ;;

    485 ) msgTxt=\
"%s: Disk %s belongs to file system %s."
    ;;

    486 ) msgTxt=\
"%s: The following disks are not known to GPFS:\n%s"
    ;;

    487 ) msgTxt=\
"%s: No disks were specified that could be deleted."
    ;;

    488 ) msgTxt=\
"%s: Disk %s has been removed from the GPFS cluster\n"\
"          configuration data but the NSD volume id was not erased from\n"\
"          the disk.  To remove the NSD volume id, issue\n"\
"             mmdelnsd -p %s"
    ;;

    489 ) msgTxt=\
"%s:  Disk %s has been removed from the GPFS cluster data\n"\
"          configuration data but the NSD volume id was not erased from\n"\
"          the disk.  To remove the NSD volume id, issue\n"\
"             mmdelnsd -p %s -N %s"
    ;;

    491 ) msgTxt=\
"%s: Disk %s is not assigned a primary NSD server node."
    ;;

    492 ) msgTxt=\
"%s: The primary and backup NSD servers must be different nodes."
    ;;

    498 ) msgTxt=\
"%s: Cannot handle multiple interfaces for host %s."
    ;;

    499 ) msgTxt=\
"%s: Unexpected output from the 'host -t a %s' command:"
    ;;

    500 ) msgTxt=\
"%s: Host %s not found."
    ;;

    505 ) msgTxt=\
"%s: Disk name %s is not allowed.\n"\
"Names beginning with gpfs are reserved for use by GPFS."
    ;;

    507 ) msgTxt=\
"%s: File %s not found.\n"\
"   Recover the file, or generate and commit a new key using mmauth genkey."
    ;;

    508 ) msgTxt=\
"%s: Disk %s is too large."
    ;;

    509 ) msgTxt=\
"%s: Unexpected error obtaining the local environment update lock."
    ;;

    510 ) msgTxt=\
"%s: Local update lock is busy."
    ;;

    511 ) msgTxt=\
"%s: Failed to obtain the local environment update lock."
    ;;

    513 ) msgTxt=\
"Usage:\n"\
"   %s Device FilesetName [-t Comment]\n"
    ;;

    514 ) msgTxt=\
"Usage:\n"\
"   %s Device {FilesetName | -J JunctionPath}\n"\
"                      {[-j NewFileSetName] [-t Comment]}\n"
    ;;

    515 ) msgTxt=\
"Usage:\n"\
"   %s Device FilesetName [-J JunctionPath]\n"
    ;;

    516 ) msgTxt=\
"Usage:\n"\
"   %s Device {FilesetName | -J JunctionPath} [-f]\n"
    ;;

    517 ) msgTxt=\
"Usage:\n"\
"   %s Device FilesetName [-f]\n"
    ;;

    518 ) msgTxt=\
"Usage:\n"\
"   %s Device\n"\
"         [[Fileset[,Fileset...]] [-J Junction[,Junction...]] | -F FileName]\n"\
"         [-L] [-d] [-i]\n"
    ;;

    520 ) msgTxt=\
"%s: %s: Volume group %s has been varied on."
    ;;

    523 ) msgTxt=\
"%s: Permission denied for disk %s"
    ;;

    524 ) msgTxt=\
"%s: Disk %s was not found."
    ;;

    525 ) msgTxt=\
"%s: I/O error on %s"
    ;;

    526 ) msgTxt=\
"%s: %s is not a valid logical volume."
    ;;

    528 ) msgTxt=\
"%s: Disk %s belongs to back-level file system %s\n"\
"    or the state of the disk is not ready.\n"\
"    Use mmchfs -V to convert the file system to the latest format.\n"\
"    Use mmchdisk to change the state of a disk."
    ;;

    529 ) msgTxt=\
"%s: Failed while processing disk %s"
    ;;

    530 ) msgTxt=\
"%s: Device %s already exists on node %s"
    ;;

    531 ) msgTxt=\
"%s: Disk %s has no space for the quorum data structures.\n"\
"    Specify a different disk as tiebreaker disk."
    ;;

    532 ) msgTxt=\
"%s: Disk %s (pvid %s) is not known on node %s"
    ;;

    533 ) msgTxt=\
"%s: Import of volume group %s on node %s failed."
    ;;

    534 ) msgTxt=\
"%s: Volume group %s is not known on node %s."
    ;;

    535 ) msgTxt=\
"%s: %s: Unable to varyon volume group %s."
    ;;

    536 ) msgTxt=\
"%s: None of the quorum nodes can be reached."
    ;;

    537 ) msgTxt=\
"%s: The descriptor file contains more than one descriptor."
    ;;

    538 ) msgTxt=\
"%s: The descriptor file contains no descriptor."
    ;;

    539 ) msgTxt=\
"%s: Failed validating disk %s. Error code %s."
    ;;

    540 ) msgTxt=\
"Usage:\n"\
"   %s {Device | all | all_local | all_remote} [-L]\n"\
"                [-C {all | all_remote | ClusterName[,ClusterName...]}]"
    ;;

    547 ) msgTxt=\
"%s: Skipping disk %s on node %s."
    ;;

    548 ) msgTxt=\
"%s: Name %s is not allowed.\n"\
"It is longer than the maximum allowable length (%s)."
    ;;

    549 ) msgTxt=\
"%s: mmfskxload:  The format of the GPFS kernel extension\n"\
"is not correct for this version of AIX."
    ;;

    550 ) msgTxt=\
"%s: %s does not resolve to a directory in %s.\n"\
"    The junction must be within the specified file system."
    ;;

    551 ) msgTxt=\
"%s: Name %s is not allowed."
    ;;

    552 ) msgTxt=\
"%s: File system %s is not mounted."
    ;;

    555 ) msgTxt=\
"Usage: %s Device [-q | -d | -s SnapLatestName]"
    ;;

    556 ) msgTxt=\
"Usage: %s Device [-n | -f]"
    ;;

    558 ) msgTxt=\
"%s: Vpath disk %s has an underlying hdisk that already belongs to a volume group."
    ;;

    560 ) msgTxt=\
"Usage:\n"\
"  %s Device\n"\
"   {-d [NodeName]:{DiskName|DiskNum|BROKEN}:[PhysAddr1[PhysAddr2]] | -F DescFile}\n"\
"   [-o OutputFile] [-f NumThreads] [-t Directory]"
    ;;

    561 ) msgTxt=\
"%s: File %s either does not exist or has an incorrect format."
    ;;

    562 ) msgTxt=\
"%s: did not find any match with the input disk address."
    ;;

    563 ) msgTxt=\
"%s: Device %s is not mounted on node %s."
    ;;

    564 ) msgTxt=\
"%s: Command was unable to determine whether file system %s is mounted."
    ;;

    565 ) msgTxt=\
"%s: Backup control file %s from a previous backup does not exist."
    ;;

    566 ) msgTxt=\
"Usage:\n"\
"   %s Device {[-r | -a] [-s SnapDirName]} \n"\
"      or\n"\
"   %s Device [-q]"
    ;;

    567 ) msgTxt=\
"%s: Line %d of file %s is incorrect:"
    ;;

    568 ) msgTxt=\
"%s: Syntax error. The correct syntax is:\n  %s"
    ;;

    569 ) msgTxt=\
"%s: Incorrect range %s-%s specified."
    ;;

    570 ) msgTxt=\
"Usage:  %s {Device | all} -o ExportfsFile"
    ;;

    571 ) msgTxt=\
"Usage:\n"\
"   %s {Device | all} -i ImportfsFile [-S ChangeSpecFile]"
    ;;

    572 ) msgTxt=\
"%s: Insufficient free space in %s (%s minimum required)."
    ;;

    574 ) msgTxt=\
"%s: Directory %s does not exist."
    ;;

    575 ) msgTxt=\
"%s: The GPFS release level could not be determined on nodes:\n%s"
    ;;

    576 ) msgTxt=\
"%s: The GPFS release level could not be determined on any of the nodes."
    ;;

    577 ) msgTxt=\
"%s: Ensure the nodes are available and run:\n%s"
    ;;

    578 ) msgTxt=\
"%s: Upgrade the lower release level nodes and run:\n%s"
    ;;

    579 ) msgTxt=\
"%s: The GPFS release level in effect for the cluster remains unchanged.\n"\
"     Old level: %s (Release %s)"
    ;;

    580 ) msgTxt=\
"%s: The GPFS release level in effect for the cluster cannot be determined.\n"\
"     Assumed: %s (Release %s)"
    ;;

    581 ) msgTxt=\
"%s: The GPFS release level in effect for the cluster will be changed.\n"\
"     Old level: %s (Release %s)   New level: %s (Release %s)"
    ;;

    582 ) msgTxt=\
"%s: The cluster contains nodes that are at different GPFS release levels.\n"\
"     Lowest level: %s (Release %s)  Highest level: %s (Release %s)"
    ;;

    583 ) msgTxt=\
"%s: -V option requires all nodes in the cluster to be at the same GPFS release level."
    ;;

    585 ) msgTxt=\
"%s: Not able to associate %s on node %s with any known GPFS disk."
    ;;

    587 ) msgTxt=\
"%s: Unable to resolve address range for disk %s on node %s."
    ;;


    # Message numbers above 1000 are in message set 60 (ts/fencing/fencing.msg).

    1000 ) msgTxt=\
"%s: Could not clear fencing for disk %s."
    ;;

    1001 ) msgTxt=\
"%s: tspreemptabort of disk %s for nodes %s failed."
    ;;

    1002 ) msgTxt=\
"%s: Disk %s of type %s is not supported for fencing."
    ;;

    1003 ) msgTxt=\
"%s: Unable to fence in node %s for disk %s."
    ;;

    1004 ) msgTxt=\
"%s: None of the specified nodes belong to this GPFS cluster."
    ;;

    1005 ) msgTxt=\
"%s: A node cannot fence itself in."
    ;;

    1006 ) msgTxt=\
"%s: varyonLocalVolume:  tsprregister was unable to unfence disk %s."
    ;;

    1007 ) msgTxt=\
"%s: Unable to display fencing for disk %s."
    ;;

    1008 ) msgTxt=\
"%s: For the logical volume specification \"-l %s\" to be valid\n"\
"%s must be the only logical volume in the volume group.\n"\
"However, volume group %s contains logical volumes."
    ;;

    1009 ) msgTxt=\
"%s: %s is not a valid logical volume."
    ;;

    1010 ) msgTxt=\
"%s: %s is not a valid volume group name."
    ;;

    1011 ) msgTxt=\
"%s: For the hdisk specification \"-h %s\" to be valid\n"\
"%s must be the only disk in the volume group.\n"\
"However, volume group %s contains disks"
    ;;

    1012 ) msgTxt=\
"%s: %s is not a valid physical volume name."
    ;;

    1013 ) msgTxt=\
"%s: %s is not a valid physical volume id."
    ;;

    1014 ) msgTxt=\
"%s: Node %s does not have access to disk %s."
    ;;

    1015 ) msgTxt=\
"%s: Node %s does not hold a reservation for disk %s."
    ;;

    1016 ) msgTxt=\
"%s: SSA fencing support is not present on this node."
    ;;

    1017 ) msgTxt=\
"%s: Node ID %s is not a valid SSA node ID.\n"\
"SSA node IDs must be a number in the range of 1 to 128."
    ;;

    1024 ) msgTxt=\
"%s: The SSA node id is not set."
    ;;

    1025 ) msgTxt=\
"%s: Unable to retrieve the SSA node id."
    ;;

    1026 ) msgTxt=\
"%s: Unable to set fencing for disk %s."
    ;;

    1027 ) msgTxt=\
"%s: Unable to clear PR reservations for disk %s."
    ;;

    *   )  # unknown message, ignore it.
      return 0
    ;;

  esac

  # Message numbers below 1000 are in message set 32 (ts/admin/admin.msg).
  # Message numbers above 1000 are in message set 60 (ts/fencing/fencing.msg).
  if [[ $msgNo -lt 1000 ]]
  then
    msgSet=32
  else
    msgSet=60
  fi

  if [[ $osName = AIX ]]
  then
    # Print the message - extra arguments are ignored.
    if [[ $printTimeStamp = yes ]]
    then
      print -u2 -- "$(date) $($dspmsg -s $msgSet mmfs.cat \
        $msgNo "$msgTxt" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9")"
    else
      print -u2 -- "$($dspmsg -s $msgSet mmfs.cat \
        $msgNo "$msgTxt" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9")"
    fi

  elif [[ $osName = Linux ]]
  then
    # Print the message - extra arguments are ignored.
    if [[ $printTimeStamp = yes ]]
    then
      print -u2 -- "$(date) $($mmdspmsg -s $msgSet mmfs.cat \
        $msgNo "$msgTxt" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9")"
    else
      print -u2 -- "$($mmdspmsg -s $msgSet mmfs.cat \
        $msgNo "$msgTxt" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9")"
    fi
  else
    checkForErrors "Unknown operating system $osName" 1
  fi

}  #----- end of function printErrorMsg --------------------------


##########################################################################
#
# Function:  Prints a syntax-related message, optionally followed
#            by usage message, and terminates the command
#
# Input:     $1 - indicator for the type of error
#            $2 - number of the usage message to issue;
#                 if 0, usage message is not printed
#            $3, $4, etc. - substitute parameters for the message
#
# Output:    Syntax-related message
#
# Returns:   No return.  The function invokes the cleanupAndExit routine.
#
# Note:      The usage message is assumed to have only one substitute
#            parameter, the command name.  The command name is allowed
#            to appear more than once in the usage statement.
#
##########################################################################
function syntaxError  # <reason> <usageMsg> [<sub1> [<sub2>...]]
{
  typeset sourceFile="mmglobfuncs.sh"
  [[ -n $DEBUG || -n $DEBUGsyntaxError ]] && set -x
  $mmTRACE_ENTER "$*"
  typeset reason=$1
  typeset usageMsg=$2
  typeset sub1="$3"
  typeset sub2="$4"
  typeset sub3="$5"
  typeset sub4="$6"
  typeset sub5="$7"

  # Print the appropriate message.
  case "$reason"
  in
    "multiple")        # Parameter specified more than once.
       printErrorMsg 36 "$mmcmd" "$sub1"
       ;;

    "missingArgs")     # Missing arguments.
       printErrorMsg 168 "$mmcmd"
       ;;

    "missingValue")    # Missing required value after flag.
       printErrorMsg 204 "$mmcmd" "$sub1"
       ;;

    "missingFile")     # Missing disk descriptor file.
       printErrorMsg 41 "$mmcmd"
       ;;

    "extraArg")        # Unexpected extra argument.
       printErrorMsg 38 "$mmcmd" "$sub1"
       ;;

    "invalidOption")   # Incorrect option.
       printErrorMsg 13 "$mmcmd" "$sub1"
       ;;

    "invalidCombination")  # Invalid combination of options.
       printErrorMsg 191 "$mmcmd" "$sub1" "$sub2"
       ;;

    "YesNoValue")      # Invalid yes|no parameter.
       printErrorMsg 37 "$mmcmd" "$sub1"
       ;;

    "keyword")         # Invalid keyword specified.
       printErrorMsg 133 "$mmcmd" "$sub1"
       ;;

    "invalidInt")      # Invalid parameter - must be an integer.
       printErrorMsg 40 "$mmcmd" "$sub1" "$sub2"
       ;;

    "cannotOpenFile")  # unable to open file.
       printErrorMsg 43 "$mmcmd" "$sub1"
       ;;

    "negativeInt" )    # Invalid parameter - must be positive integer.
       printErrorMsg 45 "$mmcmd" "$sub1" "$sub2"
       ;;

    "invalidRange")    # Invalid range.
       printErrorMsg 78 "$mmcmd" "$sub1" "$sub2" "$sub3" "$sub4"
       ;;

    "absolutePath")    # Parameter must be an absolute path name.
       printErrorMsg 148 "$mmcmd" "$sub1"
       ;;

    "absolutePath_2")  # Parameter must be an absolute path name.
       printErrorMsg 424 "$mmcmd" "$sub1" "$sub2"
       ;;

    "device1")         # Device name starts with a slash, but not /dev/.
       printErrorMsg 169 "$mmcmd" "$sub1"
       ;;

    "device2")         # Device name contains a slash, but not in column 1.
       printErrorMsg 170 "$mmcmd" "$sub1"
       ;;

    "invalidAttrValuePair")  # Invalid attribute on mmchconfig.
       : # No special message, usage will be printed shortly.
       ;;

    "incorrectSyntax")  # Incorrect syntax.
       printErrorMsg 568 "$mmcmd" "$sub1"
       ;;

    "incorrectRange")  # Incorrect range.
       printErrorMsg 569 "$mmcmd" "$sub1" "$sub2"
       ;;

    "obsoleteOption")  # Invalid (old) option specified.
       printErrorMsg 19 "$mmcmd" "$sub1"
       ;;

    "badSeparator_notSemicolon")  # Must use semi-colon as a separator.
       printErrorMsg 62 "$mmcmd"
       ;;

    "badSeparator_notDash")       # Must use dash as a separator.
       printErrorMsg 61 "$mmcmd"
       ;;

    "help")            # Show the usage message only.
       : # Usage will be printed shortly.
       ;;

    *)                 # unexpected code
       : # do nothing
       ;;

  esac  # end of case "$reason"

  # If necessary, print the usage statement.
  if [[ $usageMsg -ne 0 ]]
  then
    # Some usage messages put out the command name more than once.
    if [[ $usageMsg = 287 || $usageMsg = 301 || $usageMsg = 374 ||
          $usageMsg = 390 || $usageMsg = 413 || $usageMsg = 421 ||
          $usageMsg = 425 || $usageMsg = 452 || $usageMsg = 458 ||
          $usageMsg = 566 ]]
    then
      printErrorMsg $usageMsg "$mmcmd" "$mmcmd"

    elif [[ $usageMsg = 484 ]]
    then
      printErrorMsg $usageMsg "$mmcmd" "$mmcmd" "$mmcmd"

    elif [[ $usageMsg = 385 || $usageMsg = 388 ]]
    then
      printErrorMsg $usageMsg "$mmcmd" "$mmcmd" "$mmcmd" "$mmcmd"

    elif [[ $usageMsg = 359 ]]
    then
      printErrorMsg $usageMsg "$mmcmd" "$mmcmd" "$mmcmd" "$mmcmd" "$mmcmd"

    elif [[ $usageMsg = 249 ]]
    then
      printErrorMsg $usageMsg "$mmcmd" "$mmcmd" "$mmcmd" "$mmcmd" "$mmcmd" "$mmcmd" "$mmcmd"

    else
      printErrorMsg $usageMsg "$mmcmd"
    fi  # end of if [[ $usageMsg = 287 || ...
  fi  # end of if [[ $usageMsg -ne 0 ]]

  cleanupAndExit

}  #----- end of function syntaxError ----------------------------


###########################################################################
#
# Function:  Called if there is an interrupt before changes are committed.
#            Removes temporary files and unlocks the sdr if necessary.
#
# Input:     None
#
# Output:    None
#
# Returns:   Exits with code 2
#
###########################################################################
function pretrap
{
  typeset sourceFile="mmglobfuncs.sh"
  [[ -n $DEBUG || -n $DEBUGpretrap ]] && set -x
  $mmTRACE_ENTER "$*"
  typeset ec=0

  trap "" HUP INT QUIT KILL    # Disable traps so we won't get interrupted.

  [[ -z $MMMODE ]] && determineMode

  # We come here if an interrupt was received and
  # no changes have been made to the sdrfs file.
  # Display any buffered error messages that might be there.
  [[ -s $errMsg ]] && $cat $errMsg 1>&2
  printErrorMsg 20 $mmcmd
  $rm -f $GLOBAL_FILES $LOCAL_FILES

  if [[ $gpfsLocked = yes ]]
  then
    setRunningCommand null $primaryServer
    ec=$?
    if [[ $ec -ne 0 ]]
    then
      printErrorMsg 171 $mmcmd "function setRunningCommand" $ec
    fi
  fi

  [[ $envLocked = yes ]] && \
    freeEnvLock >/dev/null
  envLocked=no

  [[ $sdrLocked = yes ]] && \
    freeLockOnServer $primaryServer $ourNodeNumber >/dev/null
  sdrLocked=no

  trap - HUP INT QUIT KILL     # Restore interrupts.
  exit 2

}  #----- end of function pretrap --------------------------------


####################################################################
#
# Function:  Called if there is an interrupt to a command that
#            does not change system files.  Removes temporary files
#            and unlocks the sdr if necessary.
#
# Input:     None
#
# Output:    None
#
# Returns:   Exits with code 2
#
####################################################################
function pretrap2
{
  typeset sourceFile="mmglobfuncs.sh"
  [[ -n $DEBUG || -n $DEBUGpretrap2 ]] && set -x
  $mmTRACE_ENTER "$*"

  trap "" HUP INT QUIT KILL    # Disable traps so we can finish this.

  [[ -z $MMMODE ]] && determineMode

  # Interrupt received.
  # Display any buffered error messages that might be there.
  [[ -s $errMsg ]] && $cat $errMsg 1>&2
  printErrorMsg 306 $mmcmd
  $rm -f $GLOBAL_FILES $LOCAL_FILES

  [[ $envLocked = yes ]] && \
    freeEnvLock >/dev/null
  envLocked=no

  [[ $sdrLocked = yes ]] && \
    freeLockOnServer $primaryServer $ourNodeNumber >/dev/null
  sdrLocked=no

  trap - HUP INT QUIT KILL     # Restore interrupts.
  exit 2

}  #----- end of function pretrap2 -------------------------------


########################################################################
#
# Function:  Called if there is an interrupt to a command that
#            does not change system files.  Removes temporary files
#            and unlocks the sdr if necessary.
#
#            This silent trap routine is used by mmcommon and mmremote.
#
# Input:     None
#
# Output:    None
#
# Returns:   Exits with code 2
#
########################################################################
function pretrap3
{
  typeset sourceFile="mmglobfuncs.sh"
  [[ -n $DEBUG || -n $DEBUGpretrap3 ]] && set -x
  $mmTRACE_ENTER "$*"

  trap "" HUP INT QUIT KILL    # Disable traps so we can finish this.

  [[ -z $MMMODE ]] && determineMode

  # Interrupt received.
  $rm -f $GLOBAL_FILES $LOCAL_FILES

  [[ $envLocked = yes ]] && \
    freeEnvLock >/dev/null
  envLocked=no

  [[ $sdrLocked = yes ]] && \
    freeLockOnServer $primaryServer $ourNodeNumber >/dev/null
  sdrLocked=no

  trap - HUP INT QUIT KILL     # Restore interrupts.
  exit 2

}  #----- end of function pretrap3 -------------------------------


###########################################################################
#
# Function:  Called if there is an interrupt after changes were committed.
#            Removes temporary files and unlocks the sdr if necessary.
#
# Input:     None
#
# Output:    None
#
# Returns:   Exits with code 2
#
###########################################################################
function posttrap
{
  typeset sourceFile="mmglobfuncs.sh"
  [[ -n $DEBUG || -n $DEBUGposttrap ]] && set -x
  $mmTRACE_ENTER "$*"
  typeset ec=0

  trap "" HUP INT QUIT KILL    # Disable traps so we can finish this.

  [[ -z $MMMODE ]] && determineMode

  # Interrupt received: changes not propagated.
  # Display any buffered error messages that might be there.
  [[ -s $errMsg ]] && $cat $errMsg 1>&2
  printErrorMsg 32 $mmcmd
  $rm -f $GLOBAL_FILES $LOCAL_FILES

  if [[ $gpfsLocked = yes ]]
  then
    setRunningCommand null $primaryServer
    ec=$?
    if [[ $ec -ne 0 ]]
    then
      printErrorMsg 171 $mmcmd "function setRunningCommand" $ec
    fi
  fi

  [[ $envLocked = yes ]] && \
    freeEnvLock >/dev/null
  envLocked=no

  [[ $sdrLocked = yes ]] && \
    freeLockOnServer $primaryServer $ourNodeNumber >/dev/null
  sdrLocked=no

  trap - HUP INT QUIT KILL     # Restore interrupts.
  exit 2

}  #----- end of function posttrap -------------------------------


####################################################################
#
# Function:  This function must be called before a command exits,
#            either because of an unrecoverable error, or because
#            processing is completed.  The caller must issue all
#            error messages prior to calling this function.
#
#            This function does not return to its caller.
#
# Input:     $1 (optional) return code value to be used
#            $2 (optional) indicator not to unlock the sdr
#
# Output:    None
#
# Returns:   Default exit code is 1 unless a different value
#            is passed as a first parameter.
#
####################################################################
function cleanupAndExit  #  [ <rc> ]  [ doNotUnlock ]
{
  typeset sourceFile="mmglobfuncs.sh"
  [[ -n $DEBUG || -n $DEBUGcleanupAndExit ]] && set -x
  $mmTRACE_ENTER "$*"
  typeset doNotUnlock=$2
  typeset rc=1
  typeset ec=0

  [[ -n $1 ]] && rc=$1

  trap "" HUP INT QUIT KILL    # Disable traps so we can finish this.

  if [[ $gpfsLocked = yes && -z $doNotUnlock ]]
  then
    setRunningCommand null $primaryServer
    ec=$?
    if [[ $ec -ne 0 ]]
    then
      printErrorMsg 171 $mmcmd "function setRunningCommand" $ec
    fi
  fi

  if [[ $envLocked = yes && -z $doNotUnlock ]]
  then
    freeEnvLock > /dev/null
    envLocked=no
  fi

  if [[ $sdrLocked = yes && -z $doNotUnlock ]]
  then
    freeLockOnServer $primaryServer $ourNodeNumber >/dev/null
    sdrLocked=no
  fi

  [[ $getCredCalled = yes ]] &&  \
    freeCred

  $rm -f $GLOBAL_FILES $LOCAL_FILES >/dev/null 2>&1

  $mmTRACE_EXIT "rc=$rc"
  exit $rc

}  #----- end of function cleanupAndExit -------------------------


####################################################################
#
# Function:  Verifies that a command executed successfully.
#            If the return code from the command is not zero,
#            the function issues a message, performs cleanup,
#            and stops processing.
#
# Input:     $1 - name of the command to check
#            $2 - return code from the execution of the command
#
# Output:    None
#
# Returns:   0 - command finished successfully
#            If error, no return; processing is stopped.
#
####################################################################
function checkForErrors  # <command> <rc>
{
  if [ $2 != "0" ]
  then
    # Unexpected error
    printErrorMsg 171 "$mmcmd" "$1" $2
    cleanupAndExit
  fi

}  #----- end of function checkForErrors -------------------------


####################################################################
#
# Function:  Issue message 278 (corrupted mmsdrfs file).
#            Invoke cleanupAndExit to terminate the command.
#
# Input:     $1 - point of failure code
#            $2 - (optional) mmsdrfs line in error
#
# Output:    Message 278, followed by the line in error.
#
# Returns:   No return
#
####################################################################
function corruptedSdrFileExit  # <errCode> [ <lineInError> ]
{
  typeset errCode=$1
  typeset lineInError=$2

  printErrorMsg 278 $mmcmd  $errCode
  [[ -n $lineInError ]] && \
    print -u2 "$lineInError"
  cleanupAndExit $errCode

}  #----- end of function corruptedSdrFileExit -------------------


#####################################################################
#
# Function:  Verifies that the value of an attribute is an integer.
#            If the value ends with a suffix k, K, m, M, g or G, it is
#            converted to a simple integer.  If min and max values
#            are specified, the function verifies that the attribute
#            value is within that range.
#
# Input:     $1 - attribute name (needed for messages)
#            $2 - attribute value
#            $3 - minimum allowed value (optional)
#            $4 - maximum allowed value (optional)
#
# Output:    The converted attribute value
#
# Returns:   0 - Attribute value is legitimate
#            1 - (via cleanupAndExit) Attribute value is not valid
#
#####################################################################
function checkIntRange  # <attr> <value> [<min> <max>]
{
  typeset sourceFile="mmglobfuncs.sh"
  [[ -n $DEBUG || -n $DEBUGcheckIntRange ]] && set -x
  $mmTRACE_ENTER "$*"
  typeset attribute=$1
  typeset attrValue=$2
  typeset minValue=$3
  typeset maxValue=$4

  typeset -l value=$attrValue
  typeset -l low=$minValue
  typeset -l high=$maxValue
  typeset rc=0
  typeset -i result min max

  # Verify that the input value is an integer.
  # Convert if value has a k, K, m, M, g or G suffix.
  if [[ $value = k || $value = m || $value = g ]]
  then
    rc=1
  elif [[ $value != ${value%g} ]]
  then
    [[ -z ${value%%*([0-9])g} ]] && result=${value%g}*1073741824 || rc=1
  elif [[ $value != ${value%m} ]]
  then
    [[ -z ${value%%*([0-9])m} ]] && result=${value%m}*1048576 || rc=1
  elif [[ $value != ${value%k} ]]
  then
    [[ -z ${value%%*([0-9])k} ]] && result=${value%k}*1024 || rc=1
  else
    [[ -z ${value%%*([0-9])} ]] && result=$value || rc=1
  fi

  if [[ $rc -ne 0 ]]
  then
    # Invalid integer
    printErrorMsg 40 $mmcmd "$attribute" "$attrValue"
    cleanupAndExit
  fi

  # If range checking required, account for any k, K, m, or M suffixes.
  if [[ -n $minValue ]]
  then
    # Account for any k, K, m, or M suffixes in minValue or maxValue.
    # Since these are not user input, there should be no errors.
    if [[ $low != ${low%m} ]]
    then
      [[ -z ${low%%*([0-9])m} ]] && min=${low%m}*1048576 || rc=1
    elif [[ $low != ${low%k} ]]
    then
      [[ -z ${low%%*([0-9])k} ]] && min=${low%k}*1024 || rc=1
    else
      [[ -z ${low%%*([0-9])} ]] && min=$low || rc=1
    fi
    checkForErrors checkIntRange_min $rc
  fi  # end if [[ -n $minValue ]]

  if [[ -n $maxValue ]]
  then
    if [[ $high != ${high%m} ]]
    then
      [[ -z ${high%%*([0-9])m} ]] && max=${high%m}*1048576 || rc=1
    elif [[ $high != ${high%k} ]]
    then
      [[ -z ${high%%*([0-9])k} ]] && max=${high%k}*1024 || rc=1
    else
      [[ -z ${high%%*([0-9])} ]] && max=$high || rc=1
    fi
    checkForErrors checkIntRange_max $rc
  fi  # end if [[ -n $maxValue ]]

  # Ensure that value is within the specified range.
  if [[ -n $maxValue ]]
  then
    # Make sure that value is within the specified range.
    if [[ $result -lt $min || $result -gt $max ]]
    then
      # Value is out of range.
      printErrorMsg 78 $mmcmd "$attribute" "$minValue" "$maxValue" "$attrValue"
      cleanupAndExit
    fi
  elif [[ -n $minValue ]]
  then
    # Make sure that value is greater than the minimum required.
    if [[ $result -lt $min ]]
    then
      # Value is out of range.
      printErrorMsg 97 $mmcmd "$attribute" "$minValue" "$attrValue"
      cleanupAndExit
    fi
  else
    : # nothing to do.
  fi  # end if [[ -n $maxValue ]]

  # Everything looks OK, return the result.
  print -- "$result"
  return 0

}  #----- end of function checkIntRange --------------------------


###############################################################################
#
# Function:  Check that a name does not violate any of the naming rules
#            about length or prohibited characters.
#
# Input:     nameType   - type of name being checked
#            maxLength  - maximum length of the name
#            name       - name to be checked
#
# Output:    none
#
# Returns:   0 if the name is ok; non-zero otherwise
#
###############################################################################
function checkName  # <nameType> <maxLength> <name>
{
  typeset sourceFile="mmglobfuncs.sh"
  [[ -n $DEBUG || -n $DEBUGcheckName ]] && set -x
  $mmTRACE_ENTER "$*"

  typeset nameType=$1
  typeset maxLength=$2
  typeset name="$3"

  typeset length
  typeset bannedFromAllNames=',:; 	"'  # includes blank and a tab char
  typeset bannedFromDeviceNames=']/?$&*()'
  typeset bannedFromDiskNames='].<>{}/\?`~!@#$%^&*()+=\\-'
  typeset rc=0

  # Return with success if the passed name is null.
  [[ -z $name ]] && return 0

  # Return with a non-zero return code if the name is too long.
  length=${#name}
  if [[ length -gt maxLength ]]
  then
    # The name is too long.
    printErrorMsg 548 $mmcmd '"'"$name"'"' $maxLength
    return 1
  fi

  # If only checking the length of the string, we are done.
  [[ $nameType = lengthCheckOnly ]] && return 0

  # Check if any of the common banned characters are present in the name;
  # the single-quote character must be tested for explicitly.
  [[ "$name" = *+([${bannedFromAllNames}])* || "$name" = *"'"* ]] && rc=1

  # Additional, name-specific checking.
  case $nameType in
    poolName | junctionName | filesetName )
        [[ "$name" = *+([${bannedFromDeviceNames}])* || "$name" = *"["* ]] &&  \
          rc=1
        ;;

    deviceName )
        [[ "${name##+(/)dev+(/)}" = *+([${bannedFromDeviceNames}])* || "$name" = *"["* ]] &&  \
          rc=1
        ;;

    diskName )
        [[ "$name" = *+([${bannedFromDiskNames}])* || "$name" = *"["* ]] &&  \
          rc=1
        ;;

    * )  : # The name must be OK.
        ;;
  esac  # end of case $nameType in

  # If a banned character was found, issue an appropriate message.
  if [[ $rc -ne 0 ]]
  then
    case $name in
      *\[* )  printErrorMsg 189 $mmcmd '"'"$name"'"' '['  ;;
      *\]* )  printErrorMsg 189 $mmcmd '"'"$name"'"' ']'  ;;
      *\.* )  printErrorMsg 189 $mmcmd '"'"$name"'"' '.'  ;;
      *\<* )  printErrorMsg 189 $mmcmd '"'"$name"'"' '<'  ;;
      *\>* )  printErrorMsg 189 $mmcmd '"'"$name"'"' '>'  ;;
      *\{* )  printErrorMsg 189 $mmcmd '"'"$name"'"' '{'  ;;
      *\}* )  printErrorMsg 189 $mmcmd '"'"$name"'"' '}'  ;;
      *\/* )  printErrorMsg 189 $mmcmd '"'"$name"'"' '/'  ;;
      *\?* )  printErrorMsg 189 $mmcmd '"'"$name"'"' '?'  ;;
      *\`* )  printErrorMsg 189 $mmcmd '"'"$name"'"' '`'  ;;
      *\~* )  printErrorMsg 189 $mmcmd '"'"$name"'"' '~'  ;;
      *\!* )  printErrorMsg 189 $mmcmd '"'"$name"'"' '!'  ;;
      *\@* )  printErrorMsg 189 $mmcmd '"'"$name"'"' '@'  ;;
      *\#* )  printErrorMsg 189 $mmcmd '"'"$name"'"' '#'  ;;
      *\$* )  printErrorMsg 189 $mmcmd '"'"$name"'"' '$'  ;;
      *\%* )  printErrorMsg 189 $mmcmd '"'"$name"'"' '%'  ;;
      *\^* )  printErrorMsg 189 $mmcmd '"'"$name"'"' '^'  ;;
      *\&* )  printErrorMsg 189 $mmcmd '"'"$name"'"' '&'  ;;
      *\** )  printErrorMsg 189 $mmcmd '"'"$name"'"' '*'  ;;
      *\(* )  printErrorMsg 189 $mmcmd '"'"$name"'"' '('  ;;
      *\)* )  printErrorMsg 189 $mmcmd '"'"$name"'"' ')'  ;;
      *\+* )  printErrorMsg 189 $mmcmd '"'"$name"'"' '+'  ;;
      *\-* )  printErrorMsg 189 $mmcmd '"'"$name"'"' '-'  ;;
      *\=* )  printErrorMsg 189 $mmcmd '"'"$name"'"' '='  ;;
      *\,* )  printErrorMsg 189 $mmcmd '"'"$name"'"' ','  ;;
      *\:* )  printErrorMsg 189 $mmcmd '"'"$name"'"' ':'  ;;
      *\;* )  printErrorMsg 189 $mmcmd '"'"$name"'"' ';'  ;;
      *\"* )  printErrorMsg 189 $mmcmd '"'"$name"'"' "\"" ;;
      *\'* )  printErrorMsg 189 $mmcmd '"'"$name"'"' "'"  ;;
      *\\* )  printErrorMsg 189 $mmcmd '"'"$name"'"' '\'  ;;
      *\ * )  printErrorMsg 189 $mmcmd '"'"$name"'"' 'blank character' ;;
      *\	* )  printErrorMsg 189 $mmcmd '"'"$name"'"' 'tab character' ;;
    esac  # end of case $name in
  fi  # end of if [[ $rc -ne 0 ]]

  return $rc

}  #----- end of function checkName ------------------------------


#########################################################################
#
# Function:  Verify that the user-supplied input file exists and
#            is not empty.  Rewrite the file to ensure there are
#            no carriage-return characters and that it contains
#            a newline character at the end of the file.
#
# Input:     $1 - name of the user-supplied input file
#            $2 - name of the file to create
#
# Output:    None explicit.
#
# Returns:   0  - file is ok and successfully rewritten
#            non-zero - file does not exist, empty or unexpected error
#
#########################################################################
function checkUserFile  # <inputFilename> <newFile>
{
  typeset sourceFile="mmglobfuncs.sh"
  [[ -n $DEBUG || -n $DEBUGcheckUserFile ]] && set -x
  typeset inputFile=$1
  typeset newFile=$2

  typeset operands

  # Verify input parameters.
  if [[ $# -lt 2 ]]
  then
    operands="<inputFilename> <newFile>"
    printErrorMsg 260 checkIntRange "$operands"
    cleanupAndExit
  fi

  # Ensure the file exists and is not empty.
  if [[ ! -r $inputFile ]]
  then
    # We cannot open the file.
    printErrorMsg 43 $mmcmd $inputFile
    return 1
  fi
  if [[ ! -s $inputFile ]]
  then
    # File is empty.
    printErrorMsg 329 $mmcmd $inputFile
    return 1
  fi

  # Remove any carriage-return chareacters.
  # If the source and target file names are identical,
  # create a local working copy first.
  if [[ $inputFile = $newFile ]]
  then
    $cp $inputFile $tmpfile
    checkForErrors "checkUserFile: cp $inputFile $tmpfile" $?
    LC_ALL=C $tr -d "\r" < $tmpfile > $newFile
    checkForErrors "checkUserFile: tr -d <$tmpfile >$newFile" $?
    $rm -f $tmpfile
  else
    LC_ALL=C $tr -d "\r" < $inputFile > $newFile
    checkForErrors "checkUserFile: tr -d <$inputFile >$newFile" $?
  fi

  # If necessary, add a newline character at the end of the file.
  if [[ $(LC_ALL=C $tail -c 1 $newFile) != $(printf "\n") ]]
  then
    printf "\n" >> $newFile
    checkForErrors "writing to file $newFile" $?
  fi

  return 0

}  #----- end of function checkUserFile ------------------


#############################################################################
#
# Function:  Determine what mode we are in (lc, single, ... ) and initialize
#            some global variables (primaryServer, backupServer, ... ).
#
# Input:     none
#
# Output:    The MMMODE environment variable is set to reflect mode.
#            The primaryServer and backupServer global variables are set.
#            The remote shell and file copy commands are reset to the user
#            specified path names.
#
# Returns:   0 in all cases
#
#############################################################################
function determineMode
{
  typeset sourceFile="mmglobfuncs.sh"
  [[ -n $DEBUG || -n $DEBUGdetermineMode ]] && set -x
  $mmTRACE_ENTER "$*"
  typeset versionLine=""
  typeset mmmode rshPath rcpPath

  if [[ -f $mmsdrfsFile ]]
  then
    # If the mmsdrfs file exists, parse the file's version line.
    versionLine=$($head -1 $mmsdrfsFile)
    IFS=':'
    set -f ; set -- $versionLine ; set +f
    IFS="$IFS_sv"

    # Perform a quick sanity check.
    [[ $2 != 00_VERSION_LINE ]] &&  \
      corruptedSdrFileExit 127 "$versionLine"

    # Retrieve the cluster type and other values.
    mmmode=$8
    primaryServer=$9
    backupServer=${10}
    rshPath=${12}
    rcpPath=${13}
    if [[ -n $rshPath && $rshPath != "_DEFAULT_" ]]
    then
      rsh="$rshPath"
      export GPFS_rshPath="$rshPath"
    fi
    if [[ -n $rcpPath && $rcpPath != "_DEFAULT_" ]]
    then
      rcp="$rcpPath"
      export GPFS_rcpPath="$rcpPath"
    fi
    environmentType=${15}
    [[ -z $environmentType ]] && environmentType=$mmmode
    [[ $mmmode != $environmentType && $environmentType != lc2 ]] && \
      environmentType="rpd"

  else
    # Otherwise, we have no idea what to do.
    mmmode=""
    environmentType=""
    # Unknown GPFS execution environment
    printErrorMsg 338 $mmcmd $mmmode
    cleanupAndExit

  fi  #  end if [[ -f $mmsdrfsFile ]]

  # Make the environment variables globally available.
  export MMMODE=$mmmode
  export environmentType=$environmentType

  return 0

}  #----- end of function determineMode --------------------------


#############################################################################
#
# Function:  Determine the value of the specified mmfs.cfg parameter.
#
# Input:     $1 - mmfs.cfg parameter name.
#            The rest of the parameters are optional.
#            $2 - check daemon indicator.  If the value is "yes" or
#                 "checkDaemon", the function will first make a tsctl
#                 call to determine the value from the running daemon.
#                 The default is not to check the daemon.
#            $3 - short node name. Default is $ourShortName.
#            $4 - mmfs.cfg file to use. Default is /var/mmfs/etc/mmfs.cfg.
#
# Output:    The value of the mmfs.cfg parameter or null.
#
# Returns:   0 - worked
#            1 - unexpected error
#
# Examples:  autoload=$(showCfgValue autoload)
#            pagepool=$(showCfgValue pagepool checkDaemon $shortName $mmfscfg)
#
#############################################################################
function showCfgValue  # <parmName> [<checkDaemon> [<nodeName> [<cfgFile>]]]
{
  typeset sourceFile="mmglobfuncs.sh"
  [[ -n $DEBUG || -n $DEBUGshowCfgValue ]] && set -x
  $mmTRACE_ENTER "$*"

  typeset parm=$1
  typeset checkDaemon=$2
  typeset node=$3
  typeset cfgFile=$4

  typeset parmValue rc

  # Set default values.
  [[ $checkDaemon != yes && $checkDaemon != checkDaemon ]] && checkDaemon=""
  [[ -z $node ]] && node=$ourShortName
  [[ -z $cfgFile ]] && cfgFile=$mmfscfgFile
  [[ ! -f $cfgFile ]] && return 1

  # If we need to determine the value of the parameter from the currently
  # running GPFS daemon, use the tsctl showCfgValue command.  If this fails,
  # for whatever reason, determine the value from the specified config file.
  # Note that boolean type parameters have different representation in the
  # daemon than in the mmfs.cfg file.  It is the callers responsibility to
  # do the necessary translation.
  if [[ -n $checkDaemon && $node = $ourShortName ]]
  then
    parmValue=$($tsctl showCfgValue $parm 2>/dev/null)
    rc=$?
    if [[ -n $parmValue && $rc -eq 0 ]]
    then
      print -- "$parmValue"
      return 0
    fi
  fi  # end of if [[ -n $checkDaemon ]]

  # Find the setting of the parameter from the specified config file.
  parmValue=$($awk '                                     \
    BEGIN { doNotIgnoreValue = 1 }                       \
    # If this is the end of a node-override section,     \
    # set the flag to accept parameter values.           \
    $1 == "[common]" {                                   \
      { doNotIgnoreValue = 1 }                           \
      { next }                                           \
    }                                                    \
    # If this is the start of a node-override section,   \
    # see if this section applies to our node.           \
    # If yes, we will not ignore subsequent parameters.  \
    # If not, subsequent parameters will be ignored.     \
    /^\[.*]/ || /^[       ]*\[.*]/ {                     \
      if ($1 == "['$node']" || $1 ~ /\['$node',/ ||      \
          $1 ~  /,'$node']/ || $1 ~ /,'$node',/)  {      \
        { doNotIgnoreValue = 1 }                         \
      } else {                                           \
        { doNotIgnoreValue = 0 }                         \
      }                                                  \
      { next }                                           \
    }                                                    \
    # If this line contains our parameter, save its      \
    # value, provided it is applicable to our node.      \
    $1 == "'$parm'" && doNotIgnoreValue {                \
      { parmValue = $2 }                                 \
    }                                                    \
    END { print parmValue }                              \
  ' $cfgFile)
  checkForErrors awk $?

  print -- "$parmValue"
  return 0

}  #----- end of function showCfgValue ---------------------------


##############################################################################
#
# Function:  Given a device name or a mount point, this routine
#            returns information about the file system.
#
# Input:     $1 - file system device name or mount point.
#            $2 - name of mmsdrfs file
#            $3 - (optional) keyword indicating whether device or
#                 mount point is used.  The default is deviceName.
#            $4 - (optional) suppress messages flag
#
# Output:    $1 - fully-qualified device name (/dev/...)
#            $2 - short device name (no /dev/ prefix)
#            $3 - cluster where the file system is defined
#            $4 - name of the remote device (no /dev/ prefix)
#            $5 - "odd state" flag indicating whether disks may be in
#                   an odd state (this can happen when a disk command
#                   did not complete normally); "yes" indicates there
#                   may be disks in an odd state, "no" indicates no
#            $6 - default mount point for the file system
#            $7 - default options string for the mount command
#
# Returns:   0 - file system found
#           19 - file system not found (ENODEV)
#           nn - some other unexpected error
#
##############################################################################
function findFS  # <device> <sdrfs> [{deviceName|mountPoint} [<suppressMsg>]]
{
  typeset sourceFile="mmglobfuncs.sh"
  [[ -n $DEBUG || -n $DEBUGfindFS ]] && set -x
  $mmTRACE_ENTER "$*"
  typeset inputValue=$1
  typeset sdrfs=$2
  typeset inputType=$3
  typeset suppressMsg=$4

  typeset rc=0
  typeset device deviceName fqDeviceName cluster result remoteDevice
  typeset oddState defaultOptions defaultMountPoint

  # Determine what type of search this is going to be:
  # by device name or by mount point.
  if [[ $inputType != mountPoint ]]
  then
    # Find the file system using its device name.
    inputType=deviceName
    device=$inputValue
    deviceName=${device##+(/)dev+(/)}

    # Verify the device name.
    if [[ $deviceName = /* ]]
    then
      # Name starts with a slash, but not /dev/.
      [[ -z $suppressMsg ]] && printErrorMsg 169 $mmcmd "$device"
      return 1
    elif [[ $deviceName = */* ]]
    then
      # Name contains a slash.
      [[ -z $suppressMsg ]] && printErrorMsg 170 $mmcmd "$device"
      return 1
    else
      : # The device name seems to be OK.
    fi
  else
    # Find the file system using its mount point.
    mountPoint=$inputValue

    # Verify the mount point.
    if [[ $mountPoint != /* ]]
    then
      # Mount point can not be a relative path name.
      [[ -z $suppressMsg ]] && printErrorMsg 148 $mmcmd "$mountPoint"
      return 1
    fi
  fi  # end of if [[ $inputType != mountpoint ]]

  # Retrieve the needed information for the file system.
  result=$($awk -F: '                                                         \
    BEGIN {                                                                   \
      # Assume the file system does not exist.                                \
      { fsFound = 0 }                                                         \
    }                                                                         \
                                                                              \
    $'$LINE_TYPE_Field' == "'$SG_HEADR'" {                                    \
      # Starting a new file system.  Save some values in case                 \
      # this turns out to be the fs that we are looking for.                  \
      if ( $'$REMOTE_DEV_NAME_Field' != "" ) {                                \
        { remoteDevName = $'$REMOTE_DEV_NAME_Field' }                         \
      } else {                                                                \
        { remoteDevName = $'$DEV_NAME_Field' }                                \
      }                                                                       \
      if ( $'$ODD_STATE_Field' == "" || $'$ODD_STATE_Field' == "no" ) {       \
        { oddStateField = "no" }                                              \
      } else {                                                                \
        { oddStateField = "yes" }                                             \
      }                                                                       \
      { fsType        = $'$FS_TYPE_Field' }                                   \
      { deviceName    = "" }                                                  \
      { next }                                                                \
    }                                                                         \
                                                                              \
    $'$LINE_TYPE_Field'   == "'$SG_ETCFS'"         &&                         \
    $'$LINE_NUMBER_Field' == "'$MOUNT_POINT_Line'"  {                         \
      # This line contains both the device name and the mount point.          \
      # Match one of the two fields based on the type of search.              \
      if ( search == "deviceName" && $'$DEV_NAME_Field'   == "'$deviceName'" ||   \
           search == "mountPoint" && $'$ETCFS_TEXT_Field' == "'$mountPoint'" ) {  \
        { homeCluster = $'$NODESETID_Field' }                                 \
        { deviceName  = $'$DEV_NAME_Field' }                                  \
        { mountPoint  = $'$ETCFS_TEXT_Field' }                                \
        { fsFound     = 1 }                                                   \
      }                                                                       \
      { next }                                                                \
    }                                                                         \
                                                                              \
    $'$LINE_TYPE_Field' == "'$SG_MOUNT'"  &&                                  \
    $'$DEV_NAME_Field'  == deviceName      {                                  \
      { options = $'$RW_OPT_Field' }                                          \
      if ( $'$MTIME_OPT_Field' != "" ) {                                      \
        { options = options ","$'$MTIME_OPT_Field' }                          \
      }                                                                       \
      if ( $'$ATIME_OPT_Field' != "" ) {                                      \
        { options = options ","$'$ATIME_OPT_Field' }                          \
      }                                                                       \
      if ( $'$OTHER_OPT_Field' != "" ) {                                      \
        { options = options ","$'$OTHER_OPT_Field' }                          \
      }                                                                       \
      if ( $'$QUOTA_OPT_Field' != "" ) {                                      \
        { options = options ",quota="$'$QUOTA_OPT_Field' }                    \
      }                                                                       \
      if ( fsType == "'$remotefs'" ) {                                        \
        { options = options ",dev="homeCluster":"remoteDevName }              \
        { options = options ",ldev="deviceName }                              \
      } else {                                                                \
        { options = options ",dev="deviceName }                               \
      }                                                                       \
      { exit }                                                                \
    }                                                                         \
                                                                              \
    END {                                                                     \
      # If the file system was found, print the result.                       \
      if ( fsFound ) {                                                        \
        { print homeCluster   " "                                             \
                deviceName    " "                                             \
                remoteDevName " "                                             \
                oddStateField " "                                             \
                mountPoint    " "                                             \
                options         }                                             \
      }                                                                       \
    }                                                                         \
  ' search=$inputType $sdrfs)
  checkForErrors awk $?

  # If nothing was found, print "not found" message (if not suppressed)
  # and return.
  if [[ -z $result ]]
  then
    if [[ -z $suppressMsg ]]
    then
      if [[ $inputType = mountPoint ]]
      then
        # There is no file system with the specified mount point.
        printErrorMsg 279 $mmcmd "$mountPoint"
      else
        # There is no file system with the specified device name.
        printErrorMsg 288 $mmcmd "$device"
      fi
    fi
    return $MM_FsNotFound
  fi  # end of if [[ -z $result ]]

  # If we are here, the file system exists;
  # parse the results of the awk.
  set -f ; set -- $result ; set +f
  cluster=$1
  deviceName=$2
  remoteDevice=$3
  oddState=$4
  defaultMountPoint=$5
  defaultOptions=$6

  fqDeviceName="/dev/$deviceName"

  # Output the data.
  print -- $fqDeviceName $deviceName $cluster $remoteDevice \
           $oddState $defaultMountPoint $defaultOptions
  return 0

}  #----- end of function findFS ---------------------------------


############################################################################
#
# Function:  Determine which nodes have the specified file systems mounted.
#
# Input:     $1 - file system to check or:  all, all_local, or all_remote
#            $2 - scope of mount checking (list of cluster names)
#            $3 - show output for individual nodes: yes, no, unformatted
#            $4 - (optional) assume cached data is current
#
# Output:    lists of nodes that have the specified file systems mounted
#
# Returns:   0 - command completed successfully
#            non-zero - error encountered
#
############################################################################
function lsmount   # <fsToShow> <scope> <showNodes> [norefresh]
{
  typeset sourceFile="mmglobfuncs.sh"
  [[ -n $DEBUG || -n $DEBUGlsmount ]] && set -x
  $mmTRACE_ENTER "$*"
  typeset fsToShow="$1"
  typeset scope="$2"
  typeset showNodes="$3"
  typeset -l refreshArg=$4

  typeset rc=0
  typeset oneCluster=false
  typeset hdrlineStripClusterName=no
  typeset nodelineStripClusterName=yes
  typeset fsToCheck fqDeviceName localDevName deviceName
  typeset fsList homeCluster headerMsg clusterName Coption
  typeset hdrLine linePrefix localCluster
  integer numNodes 

  # If more than one file system is requested or the file system name
  # is not fully-qualified, ensure the local environment is up-to-date
  # and generate a list of the file systems.

  # Process the file system parameter.
  if [[ $fsToShow = all  ||  $fsToShow = all_local ||
        $fsToShow = all_remote || $fsToShow != *:* ]]
  then
    # Either more than one file system is requested,
    # or the file system name is not fully-qualified.

    # Ensure the local environment is up-to-date.
    if [[ $refreshArg != "norefresh" ]]
    then
      gpfsInitOutput=$(gpfsInit nolock)
      setGlobalVar $? $gpfsInitOutput
    fi

    # Generate a list of the fully-qualified file system names.
    fsList=$($awk -F: '                                  \
      $'$LINE_TYPE_Field' == "'$SG_HEADR'" {             \
        if ( $'$DEV_NAME_Field' == "'$fsToShow'" ) {     \
          # This is the file system that we want.        \
          # See if the fs is local or remote.            \
          if ( $'$FS_TYPE_Field' == "'$remotefs'" ) {    \
            { printf $'$NODESETID_Field' ":"             \
                     $'$REMOTE_DEV_NAME_Field' ":"       \
                     $'$DEV_NAME_Field' }                \
          } else {                                       \
            { printf ":" $'$DEV_NAME_Field' ":" }        \
          }                                              \
          # Nothing else to do.                          \
          { exit  0 }                                    \
        } else if ( "'$fsToShow'" == "all" ) {           \
          # We want all file systems, local and remote.  \
          if ( $'$FS_TYPE_Field' == "'$remotefs'" ) {    \
            { printf $'$NODESETID_Field' ":"             \
                     $'$REMOTE_DEV_NAME_Field' ":"       \
                     $'$DEV_NAME_Field' "," }            \
          } else {                                       \
            { printf ":" $'$DEV_NAME_Field' ":," }       \
          }                                              \
                                                         \
        } else if ( "'$fsToShow'" == "all_local" ) {     \
          # We want all local file systems.              \
          if ( $'$FS_TYPE_Field' == "'$remotefs'" ) {    \
            { next }                                     \
          } else {                                       \
            { printf ":" $'$DEV_NAME_Field' ":," }       \
          }                                              \
                                                         \
        } else if ( "'$fsToShow'" == "all_remote" ) {    \
          # We want all remote file systems.             \
          if ( $'$FS_TYPE_Field' == "'$remotefs'" ) {    \
            { printf $'$NODESETID_Field' ":"             \
                     $'$REMOTE_DEV_NAME_Field' ":"       \
                     $'$DEV_NAME_Field' "," }            \
          } else {                                       \
            { next }                                     \
          }                                              \
        } else {                                         \
          { next }                                       \
        }                                                \
      }                                                  \
      END { printf "\n" }                                \
    ' $mmsdrfsFile)
    checkForErrors awk $?

    # Strip trailing commas, if any.
    fsList=${fsList%%,}

  else
    # Only one file system was specified using its fully-qualified name.
    fsList=$fsToShow
  fi  # end of if [[ $fsToShow = all || $fsToShow = all_local ...

  # Return if no file systems were found.
  if [[ -z $fsList ]]
  then
    if [[ $fsToShow = all || $fsToShow = all_local ]]
    then
      # No file systems were found in the cluster.
      printErrorMsg 200 $mmcmd
    elif [[ $fsToShow = all_remote ]]
    then
      # There are no remote file systems.
      printErrorMsg 193 $mmcmd
    else
      # The specified file system was not found.
      printErrorMsg 288 $mmcmd "$fsToShow"
    fi  # end of if [[ $fsToShow = all || $fsToShow = all_local ]]

    # Give up.
    return $MM_FsNotFound
  fi # #end of if [[ -z $fsList ]]

  # If the user did not specify the -C parameter on mmlsmount,
  # see if this cluster has knowledge of other clusters or if it
  # has granted access to its file systems to remote clusters.
  # If neither is true, suppress the cluster name in the output.
  if [[ $scope = NULL ]]
  then
    oneCluster=$($awk -F: '                               \
      $'$LINE_TYPE_Field' == "'$AUTHORIZED_CLUSTER'" ||   \
      $'$LINE_TYPE_Field' == "'$REM_CLUSTER'"         {   \
        { print "false" }                                 \
        { exit }                                          \
      }                                                   \
      END { print "true" }                                \
    ' $mmsdrfsFile)
    checkForErrors awk $?
  fi  # end of if [[ $scope = NULL ]]

  if [[ $showNodes = unformatted ]]
  then
    # Generate and print the header line.
    hdrLine="mmlsmount::HEADER:version:reserved:reserved"
    hdrLine="${hdrLine}:localDevName:realDevName:owningCluster"
    hdrLine="${hdrLine}:totalNodes:nodeIP:nodeName:clusterName"
    print -- "${hdrLine}:"

    # Generate the prefix for the data lines.
    linePrefix="mmlsmount::0:1::"

    # Find our cluster name (needed for the unformatted output).
    localCluster=$($head -1 $mmsdrfsFile | $GETVALUE $CLUSTER_NAME_Field)
  fi  # end of if [[ $showNodes = yes ]]

  # Process the list of file systems.
  IFS=','
  for fsToCheck in $fsList
  do
    # Parse the information for the file system to be checked.
    IFS=':'
    set -f ; set -- $fsToCheck ; set +f
    homeCluster=$1
    deviceName=$2
    localDevName=$3

    if [[ -z $homeCluster || $homeCluster = $HOME_CLUSTER ]]
    then
      fqDeviceName="$deviceName"
    else
      fqDeviceName="${homeCluster}:${deviceName}"
    fi

    # Process the mount check scope parameter.
    IFS=','
    for clusterName in $scope
    do
      IFS="$IFS_sv"

      # Determine the value for the -C option on tsstatus.
      if [[ $clusterName = all || $clusterName = NULL || $clusterName = $CHECK_ALL ]]
      then
        Coption=""
      else
        [[ $clusterName = "."  || $clusterName = all_local ]] &&  \
          clusterName=$($head -1 $mmsdrfsFile | $GETVALUE $CLUSTER_NAME_Field)
        Coption="-C $clusterName"
      fi

      # Determine whether to strip the cluster name from the header line
      # or from the node lines for each of the possible scenarios.
      # The normal case is to have the cluster name on the header line
      # and not on the node lines, but the behavior is different if the
      # -C was not specified or if a value of all or all_remote was given.
      # If -C was not specified and there is only one cluster, we will not
      # output cluster names.  If all or all_remote was specified for -C,
      # we will not output cluster names on the header line, but we will
      # show cluster names on the node lines.
      if [[ $clusterName = NULL && $oneCluster = true ]]
      then
        hdrlineStripClusterName=yes
        nodelineStripClusterName=yes
      elif [[ $clusterName = NULL       ||
              $clusterName = all        ||
              $clusterName = all_remote ]]
      then
        hdrlineStripClusterName=yes
        nodelineStripClusterName=no
      else
        hdrlineStripClusterName=no
        nodelineStripClusterName=yes
      fi

      # Determine whether anybody has the file system mounted.
      LC_ALL=C $tsstatus -m $fqDeviceName $Coption >$tmpfile 2>$errMsg
      rc=$(remapRC $?)
      if [[ $rc -eq 0 ]]
      then
        # The file system is mounted on at least one of the nodes that
        # we care about.  The list of node names is returned by tsstatus.
        #
        #   Note that the tsstatus output comes from the stripe group
        #   manager node which always resides in the cluster that owns
        #   the file system.  In the case of remote file systems, the
        #   manager node has no knowledge about the local name for the
        #   file system.  Therefore, we have to intercept the tsstatus
        #   output and replace the header line with one that is more
        #   meaningful for the local cluster.  To keep the code simple,
        #   we do this for both local and remote file systems.
        #
        if [[ -s $tmpfile ]]
        then
          # Determine the number of nodes that have the file system mounted.
          # We subtract 2 because tsstatus produces a blank line and a header.
          numNodes=$($awk 'END { print NR - 2 }' $tmpfile)

          # Generate the output for this file system.
          if [[ $showNodes = yes ]]
          then
            # We come here if a list of the nodes should be shown.
            # Construct a message to be used in place of the first line
            # in the tsstatus output.  If checking a remote file system,
            # the local device name can be passed as a command argument.
            if [[ $hdrlineStripClusterName = yes ]]
            then
              if [[ -n $localDevName ]]
              then
                headerMsg=$(printInfoMsg 521  \
                  "$localDevName" "($fqDeviceName)" "$numNodes")
              else
                headerMsg=$(printInfoMsg 522 "$fqDeviceName" "$numNodes")
              fi
            else
              if [[ -n $localDevName ]]
              then
                headerMsg=$(printInfoMsg 477  \
                  "$localDevName" "($fqDeviceName)" "$numNodes" "$clusterName")
              else
                headerMsg=$(printInfoMsg 478  \
                  "$fqDeviceName" "$numNodes" "$clusterName")
              fi
            fi

            # Filter the result from the tsstatus command and replace
            # the header line with our own version.
            $awk '                                                          \
              /File system/ && /is managed by node/ && /and mounted on:/ {  \
                { print "'"$headerMsg"'" }                                  \
                { next }                                                    \
              }                                                             \
              { if (stripClusterName == "yes") {                            \
                  { printf ("  %-15s %s \n", $1, $2) }                      \
                } else {                                                    \
                  { print $0 }                                              \
                }                                                           \
              }                                                             \
            ' stripClusterName="$nodelineStripClusterName" $tmpfile

          elif [[ $showNodes = unformatted ]]
          then
            # We come here if the information should be presented in
            # colon separated fields (mmlsmount -Y).
            [[ -z $localDevName ]] && localDevName="$deviceName"
            [[ -z $homeCluster  ]] && homeCluster="$localCluster"
            $awk '                                                           \
              NR > 2 { print "'$linePrefix':'$localDevName':'$deviceName':"  \
                             "'$homeCluster':'$numNodes':"$1":"$2":"$3":" }  \
            ' $tmpfile

          else
            # We come here if a list of the nodes is not desired.
            # Construct the summary message to be used in place of
            # the tsstatus output.  If checking a remote file system,
            # the local device name can be passed as a command argument.
            if [[ $hdrlineStripClusterName = yes ]]
            then
              if [[ -n $localDevName ]]
              then
                printInfoMsg 553 "$localDevName" "($fqDeviceName)" "$numNodes"
              else
                printInfoMsg 554 "$fqDeviceName" "$numNodes"
              fi
            else
              if [[ -n $localDevName ]]
              then
                printInfoMsg 479  \
                  "$localDevName" "($fqDeviceName)" "$numNodes" "$clusterName"
              else
                printInfoMsg 480 "$fqDeviceName" "$numNodes" "$clusterName"
              fi
            fi
          fi
        else
          # tstatus -m returned no data.  This should not be the case here.
          # Show error output, if any, and return.
          [[ -s $errMsg ]] && $cat $errMsg 1>&2
          $rm -f $errMsg

          # Unexpected error.
          printErrorMsg 171 $mmcmd "function lsmount - no tsstatus output" 1
          return 1
        fi  # end of if [[ -s $tmpfile ]]

      elif [[ $rc -eq 2 ]]
      then
        # The file system is not mounted on any of the nodes that
        # we are interested in.  That's OK, just put out a message.
        rc=0
        if [[ $showNodes = unformatted ]]
        then
          # We come here if the information should be presented in
          # colon separated fields (mmlsmount -Y).
          [[ -z $localDevName ]] && localDevName="$deviceName"
          [[ -z $homeCluster  ]] && homeCluster="$localCluster"
          print -- "${linePrefix}:${localDevName}:${deviceName}:${homeCluster}:0::::"
        elif [[ -n $localDevName ]]
        then
          if [[ -z $Coption ]]
          then
            # The file system is not mounted.
            printInfoMsg 541 "$localDevName" "($fqDeviceName)"
          else
            if [[ $clusterName = all_remote ]]
            then
              # The file system is not mounted in any remote cluster.
              printInfoMsg 542 "$localDevName" "($fqDeviceName)"
            else
              # The file system is not mounted in the specified cluster.
              printInfoMsg 543 "$localDevName" "($fqDeviceName)" "$clusterName"
            fi
          fi
        else
          if [[ -z $Coption ]]
          then
            # The file system is not mounted.
            printInfoMsg 544 "$fqDeviceName"
          else
            if [[ $clusterName = all_remote ]]
            then
              # The file system is not mounted in any remote cluster.
              printInfoMsg 545 "$fqDeviceName"
            else
              # The file system is not mounted in the specified cluster.
              printInfoMsg 546 "$fqDeviceName" "$clusterName"
            fi
          fi
        fi  # end of if [[ -n $localDevName ]]

      elif [[ $rc -ne $MM_DaemonDown && $rc -ne $MM_QuorumWait ]]
      then
        # Unexpected error.  Show error output, if any, and continue looping.
        if [[ -s $errMsg ]]
        then
          $cat $errMsg 1>&2
        else
          [[ $rc -ne 0 ]] &&  \
            printErrorMsg 113 "$mmcmd" "tsstatus -m $fqDeviceName $Coption" $rc
        fi
        $rm -f $errMsg
        # Command was unable to determine whether the file system is mounted.
        if [[ -n $localDevName ]]
        then
	  printErrorMsg 564 $mmcmd "$localDevName"
	else
	  printErrorMsg 564 $mmcmd "$fqDeviceName"
	fi

      else
        # GPFS is not ready on this node (rc is MM_DaemonDown or MM_QuorumWait).
        # Return quietly.
        $rm -f $errMsg
        return $rc
      fi  # end of if [[ $rc -eq 0 ]]

      # We were able to successfully determine whether the file
      # system is mounted on any node in the current cluster.
      # Move to the next cluster in the list.
      $rm -f $errMsg
      IFS=','
    done  # end of for clusterName in $scope

    # Move to the next file system.
    IFS=','
  done  # end of for fsTocheck in $fsList
  IFS="$IFS_sv"


  # Return to the caller.
  return $rc

}  #----- end of function lsmount --------------------------------


#############################################################################
#
# Function:  Determine if a remote node can be reached.
#
# Input:     $1 - node name (may be null)
#            Note:  Do not add more input parameters.
#                   This function can be called w/o input.
#
# Output:    None
#
# Returns:   0 - node can be reached
#            1 - node can not be reached
#
#############################################################################
function isNodeReachable  # <nodeName>
{
  typeset sourceFile="mmglobfuncs.sh"
  [[ -n $DEBUG || -n $DEBUGisNodeReachable ]] && set -x
  $mmTRACE_ENTER "$*"
  typeset nodeName=$1

  typeset maxPingCount=3
  typeset -i pingTimeout=4
  typeset -i pingCount=0
  typeset pingRc=1

  while [[ $pingRc -ne 0 && $pingCount -lt $maxPingCount ]]
  do
    (( pingCount += 1 ))
    (( pingTimeout += 1 ))
    $ping -w $pingTimeout -c 1 $nodeName >/dev/null 2>/dev/null
    pingRc=$?
#   [[ $pingRc -ne 0 ]] && \
#     print -u2 "$mmcmd: ping $nodeName failed ($pingCount); pingRc=$pingRc"
  done

  return $pingRc

}  #----- end of function isNodeReachable ------------------------


####################################################################
#
# Function:  Exec the specified command with the given argv[0]
#
# Input:     $1 - command path
#            $2 - argv[0]
#            $3, $4, ... - arguments to pass to the command
#
# Output:    depends on the executed command
#
# Returns:   No return if the exec call succeded.
#
####################################################################
function mmexecl  # <cmdpath> <argv0> [ <arg> ... ]
{
  # First, we attempt to execute the given command with naked exec,
  # without involving the shell.  A successful exec never returns.
  # If it does return, it means it failed, in which case we attempt
  # to execute the program again, this time using sh, to produce an
  # error message and an appropriate return code.
  $perl -e "{\
    \$arg0=\$ARGV[0]; \
    shift; \
    exec \$arg0 @ARGV; \
    exec \"sh -c \$arg0\"; \
  }" "$@"

  return $?

}  #----- end of function mmexecl --------------------------------

