#!/bin/ksh
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
#  
#  
# Licensed Materials - Property of IBM 
#  
# (C) COPYRIGHT International Business Machines Corp. 2004,2006 
# 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.11.1.1 src/avs/fs/mmfs/ts/admin/mmlsquota.sh, mmfs, avs_rgpfs24, rgpfs24s002a 4/27/06 19:20:07
########################################################################
#
# Usage:
#   mmlsquota [-u User | -g Group | -j Fileset] [-v | -q] [-e]
#                [-C ClusterName] [Device1 Device2 ...]
#     or
#   mmlsquota -d {-u | -g | -j} [-C ClusterName] [Device1 Device2 ...]
#
########################################################################

# Include global declarations and service routines.
. /usr/lpp/mmfs/bin/mmglobfuncs
if [[ $ourUid -eq 0 ]]
then
  . /usr/lpp/mmfs/bin/mmsdrfsdef
  . /usr/lpp/mmfs/bin/mmfsfuncs
fi

sourceFile="mmlsquota.sh"
[[ -n $DEBUG || -n $DEBUGmmlsquota ]] && set -x
$mmTRACE_ENTER "$*"

# Local variables
usageMsg=452
integer rc=0
integer nodeCount=0
deviceList=""


#################################
# Process the command arguments.
#################################
[[ $arg1 = '-?' || $arg1 = '-h' || $arg1 = '--help' || $arg1 = '--' ]] &&  \
  syntaxError "help" $usageMsg

string1=""
Cstring=""
if [[ $arg1 = '-d' ]]
then
  # We come here to handle the -d form of the command.
  while getopts :C:dgju OPT
  do
    case $OPT in

      C) # Specify a cluster name.
         if [[ $OPTARG = *:* ]]
         then
           print -u2 "Disregarding the C operand because it contains a colon."
         else
           Cstring="$Cstring $OPTARG"
           COpt="-C"
         fi
         ;;

      d) string1="-d "
         dOpt="-d"
         ;;

      g) [[ -n $jOpt ]] && syntaxError "invalidCombination" $usageMsg "-j" "-g"
         [[ -n $uOpt ]] && syntaxError "invalidCombination" $usageMsg "-u" "-g"
         gOpt="-g"
         string1="$string1 -g"
         ;;

      j) [[ -n $gOpt ]] && syntaxError "invalidCombination" $usageMsg "-g" "-j"
         [[ -n $uOpt ]] && syntaxError "invalidCombination" $usageMsg "-u" "-j"
         jOpt="-j"
         string1="$string1 -j"
         ;;

      u) [[ -n $gOpt ]] && syntaxError "invalidCombination" $usageMsg "-g" "-u"
         [[ -n $jOpt ]] && syntaxError "invalidCombination" $usageMsg "-j" "-u"
         uOpt="-u"
         string1="$string1 -u"
         ;;

      :) syntaxError "missingValue" $usageMsg $OPTARG
         ;;

      +[dgju]) syntaxError "invalidOption" $usageMsg "$OPT"
         ;;

      *) syntaxError "invalidOption" $usageMsg $OPTARG
         ;;

    esac
  done  # end of while getopts :C:dgju OPT do

  # In this form, one of -g, -j, and -u are mandatory.
  [[ -z $gOpt && -z $jOpt && -z $uOpt ]] && syntaxError "missingArgs" $usageMsg

else
  # We come here to handle the non-"-d" form of the command.
  while getopts :C:eg:j:qu:v OPT
  do
    case $OPT in

      C) # Specify a cluster name.
         if [[ $OPTARG = *:* ]]
         then
           print -u2 "Disregarding the C operand because it contains a colon."
         else
           Cstring="$Cstring $OPTARG"
           COpt="-C"
         fi
         ;;

      e) string1="$string1 -e"
         eOpt="-e"
         ;;

      g) # Specify a group.
         [[ -n $gOpt ]] && syntaxError "multiple" $noUsageMsg "-$OPT"
         string1="$string1 -g $OPTARG"
         gOpt="-g"
         [[ -n $jOpt ]] && syntaxError "invalidCombination" $usageMsg "-j" "-g"
         [[ -n $uOpt ]] && syntaxError "invalidCombination" $usageMsg "-u" "-g"
         ;;

      j) # Specify a fileset.
         [[ -n $jOpt ]] && syntaxError "multiple" $noUsageMsg "-$OPT"
         string1="$string1 -j $OPTARG"
         jOpt="-j"
         [[ -n $gOpt ]] && syntaxError "invalidCombination" $usageMsg "-g" "-j"
         [[ -n $uOpt ]] && syntaxError "invalidCombination" $usageMsg "-u" "-j"
         ;;

      q) [[ -n $vOpt ]] && syntaxError "invalidCombination" $usageMsg "-v" "-q"
         string1="$string1 -q"
         qOpt="-q"
         ;;

      u) # Specify a user.
         [[ -n $uOpt ]] && syntaxError "multiple" $noUsageMsg "-$OPT"
         string1="$string1 -u $OPTARG"
         uOpt="-u"
         [[ -n $gOpt ]] && syntaxError "invalidCombination" $usageMsg "-g" "-u"
         [[ -n $jOpt ]] && syntaxError "invalidCombination" $usageMsg "-j" "-u"
         ;;

      v) [[ -n $qOpt ]] && syntaxError "invalidCombination" $usageMsg "-q" "-v"
         vOpt="-v"
         string1="$string1 -v"
         ;;

      :) syntaxError "missingValue" $usageMsg $OPTARG
         ;;

      +[egjquv]) syntaxError "invalidOption" $usageMsg "$OPT"
         ;;

      *) syntaxError "invalidOption" $usageMsg $OPTARG
         ;;

    esac
  done  # end of while getopts :C:eg:j:qu:v OPT do
fi  # end of if [[ $arg1 = '-d' ]]

shift OPTIND-1

# Whatever is left is the blank-separated list of devices.
deviceList=$@


##################################
# Set up trap exception handling.
##################################
trap pretrap2 HUP INT QUIT KILL


####################################################################
# If invoked by a root user, call the gpfsInit function to ensure
# that the local copy of the mmsdrfs file and the rest of the GPFS
# system files are up-to-date.  There is no need to lock the sdr.
# Non-root users are not allowed to invoke commands on other nodes.
####################################################################
if [[ $ourUid -eq 0 ]]
then
  gpfsInitOutput=$(gpfsInit nolock)
  setGlobalVar $? $gpfsInitOutput
fi


###############################################
# Process any -C operands that were specified.
###############################################
deviceList2=""
for cname in $Cstring
do
  # Set the remote file system flag.
  remoteFsSpecified=yes

  # Generate a list of the devices GPFS knows for the specified cluster.
  # The awk script looks for SG_HEADR lines for the specified cluster.
  # For each such line, clusterName:fsName is added to deviceList2.
  dlist=$($awk -F: '                                                  \
    /^'$cname:$SG_HEADR:'/ {                                          \
      { print $'$NODESETID_Field' ":" $'$REMOTE_DEV_NAME_Field' " "}  \
    }                                                                 \
  ' $mmsdrfsFile)
  checkForErrors awk $?

  if [[ -z $dlist ]]
  then
    print -u2 "No remote file systems for cluster $cname were found."
  else
    deviceList2="$deviceList2 $dlist"
    [[ -n $remoteCluster && $cname != $remoteCluster ]] &&  \
      multipleClustersInvolved=yes
    remoteCluster=$cname
  fi
done  # end of for cname in $Cstring do


###################################################################
# Process any file systems that were specified one at a time.
# Loop through the device list and replace any remote file systems
# with the string "remoteClusterName:remoteFsName".
###################################################################
set -f
for device in $deviceList
do
  set +f

  # If the invocation is not for an explicitly-remote device, obtain the
  # needed information about the filesystem from the mmsdrfs file.
  if [[ $device != *:* ]]
  then
    findFSoutput=$(findFS "$device" $mmsdrfsFile)
    [[ -z $findFSoutput ]] && continue

    # Parse the output from the findFS function.
    set -f ; set -- $findFSoutput ; set +f
    fqDeviceName=$1
    deviceName=$2
    fsHomeCluster=$3
    remoteDevice=$4

    # If this is a remote file system, set fqDeviceName appropriately.
    if [[ $fsHomeCluster != $HOME_CLUSTER ]]
    then
      fqDeviceName="$fsHomeCluster:/dev/$remoteDevice"
      remoteFsSpecified=yes
      [[ -n $remoteCluster && $fsHomeCluster != $remoteCluster ]] &&  \
        multipleClustersInvolved=yes
      remoteCluster=$fsHomeCluster
    fi
  else
    fqDeviceName=$device
    deviceName=${fqDeviceName##*:}
    fsHomeCluster=${fqDeviceName%%:*}
    remoteDevice=$deviceName
    remoteFsSpecified=yes
    [[ -n $remoteCluster && $fsHomeCluster != $remoteCluster ]] &&  \
      multipleClustersInvolved=yes
    remoteCluster=$fsHomeCluster
  fi

  # If more than one file system requested, suppress error
  # messages that deal with individual file systems.
  # Such errors will go into the "unexpected" category.
  [[ -n $deviceList2 ]] && multipleDevicesInvolved=yes

  # Append the fully-qualified name to the list of fs names.
  deviceList2="$deviceList2 $fqDeviceName"
done  # end of for device in $deviceList do
set +f


########################################################################
# Invoke the command on the local node.
# Display any error messages and exit if any of the following are true:
#   - the command completed successfully
#   - there is an unacceptable error
#       (anything other than daemon down or quorum wait)
#   - one of the file systems is remote
#   - we are not running as UID 0
#   - this is a single node cluster
########################################################################
${mmcmdDir}/${links}/mmlsquota $string1 $deviceList2 2>$errMsg
rc=$(remapRC $?)
if [[ ($rc -ne $MM_DaemonDown && $rc -ne $MM_QuorumWait) ||
      $remoteFsSpecified = yes                           ||
      $ourUid -ne 0                                      ||
      $MMMODE = single ]]
then
  if [[ $rc -eq $MM_FsNotFound && -z $multipleDevicesInvolved ]]
  then
    if [[ $fsHomeCluster != $HOME_CLUSTER ]]
    then
      # The remote cluster does not know anything about this file system.
      printErrorMsg 108 $mmcmd $remoteDevice $fsHomeCluster
    else
      # Unexpected error.
      printErrorMsg 171 $mmcmd "file system $deviceName not found" $rc
    fi
  elif [[ $rc -eq $MM_Remotefs            &&
          $fsHomeCluster != $HOME_CLUSTER &&
          -z $multipleDevicesInvolved     ]]
  then
    # The file system is not owned by the remote cluster.
    [[ $device != *:* ]] &&  \
      printErrorMsg 111 $mmcmd $device $remoteDevice $fsHomeCluster
    printErrorMsg 112 $mmcmd $remoteDevice $fsHomeCluster
  elif [[ ($rc -eq $MM_HostDown            ||
           $rc -eq $MM_TimedOut            ||
           $rc -eq $MM_SecurityCfg         ||
           $rc -eq $MM_AuthorizationFailed ||
           $rc -eq $MM_UnknownCluster)        &&
           $fsHomeCluster != $HOME_CLUSTER    &&
           -z $multipleClustersInvolved       ]]
  then
    # Failed to connect to the remote cluster.
    [[ $rc -eq $MM_SecurityCfg ]] &&  \
      printErrorMsg 150 $mmcmd
    [[ $rc -eq $MM_AuthorizationFailed ]] &&  \
      printErrorMsg 151 $mmcmd
    printErrorMsg 105 $mmcmd $fsHomeCluster
  elif [[ $rc -eq $MM_DaemonDown ]]
  then
    # GPFS is down on this node.
    printErrorMsg 109 $mmcmd
  elif [[ $rc -eq $MM_QuorumWait ]]
  then
    # GPFS is not ready for commands.
    printErrorMsg 110 $mmcmd
  elif [[ $rc -eq $MM_ConnectionReset ]]
  then
    # An internode connection was reset.
    printErrorMsg 257 $mmcmd
  else
    # Either the command worked, or it is an unexpected error.
    if [[ -s $errMsg ]]
    then
      # Show the error messages from the daemon.
      $cat $errMsg 1>&2
    elif [[ $rc -ne 0 ]]
    then
      # tslsquota failed; there was no message from the daemon.
      printErrorMsg 104 "$mmcmd" "tslsquota $string1 $deviceList2"
    else
      :  # The command must have worked.
    fi
  fi  # end of if [[ $rc -eq $MM_FsNotFound && -z $multipleDevicesInvolved ]]
  cleanupAndExit $rc
fi  # end of if [[ ($rc -ne $MM_DaemonDown  && ...
$rm -f $errMsg


################################################################
# We come here if the command was invoked but the local daemon
# is not available; send the command to an active node.
################################################################

# Create a file with the reliable names of the nodes in the cluster.
nodeCount=$(getNodeFile $REL_HOSTNAME_Field $GLOBAL_ID $mmsdrfsFile $nodefile)
if [[ $nodeCount -eq 0 ]]
then
  # The cluster is empty; there is nobody to run the command.
  printErrorMsg 171 $mmcmd "getNodeFile (nodeCount=0)" 1
  cleanupAndExit
fi

# Try the nodes one by one until you find a node that can execute the command.
preferredNode=0     # We have no idea where to go first; let mmcommon decide.
$mmcommon linkCommand $preferredNode $nodefile mmlsquota $string1 $deviceList2
rc=$?

cleanupAndExit $rc

