#!/bin/ksh
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
#  
#  
# Licensed Materials - Property of IBM 
#  
# (C) COPYRIGHT International Business Machines Corp. 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 
# @(#)72 1.1.1.1 src/avs/fs/mmfs/ts/admin/mmsdrquery.sh, mmfs, avs_rgpfs24, rgpfs24s011a 3/29/07 15:24:10
##########################################################################
#
# Retrieve the requested information form the mmsdrfs file.
#
#   Usage:  mmsdrquery queryType itemList [scope [norefresh]]
#
# where
#
#   queryType   specifies the type of infromation requested.  The supported
#               query types are defined in file mmsdrquerydef and can be
#               specified using either the appropriate keyword or its
#               corresponding integer value.
#
#   itemList    a colon-separated list describing the information that
#               is to be returned.  The supported items are defined in
#               file mmsdrquerydef and can be specified using the item's
#               keyword or integer value.  The 'all' keyword is equivalent
#               to requesting all currently defined items in the order
#               in which they appear in the mmsdrquerydef file.
#
#   scope       can be used to limit the number of the returned items.
#               The meaning and syntax of this parameter dependents on
#               the query type:
#
#               - for sdrq_cluster_info the only valid value is 'all'.
#
#               - for sdrq_node_info the same syntax must be used as
#                 for the -N option on mmchnode and similar commands.
#
#               - for sdrq_nsd_info the scope parameter can be either
#                 a list of NSD names, a list of file system device
#                 names, the keyword 'free_disks', or a fully-qualified
#                 path name for a file containing NSD or device names.
#                 All file system device names must include the /dev
#                 prefix to distinguish them from NSD names.
#
#               - for sdrq_fs_info the scope parameter can be either
#                 a colon-separated list of device names or one of
#                 the 'all' key words: all, all_local, or all_remote.
#
#               If ommitted, 'all' is assumed for all query types.
#
#   norefresh   (optional) assume the cached mmsdrfs data is current.
#
#
# The output consists of one or more records, containing the following
# colon-separated fields:
#
#    fixed eycatcher  - the character string 'mmsdrquery'
#    query type       - the value of the queryType input parameter
#    error indicator  - if not zero, the rest of the record is undefined
#    version number   - the value of $sdrq_current_format
#    reserved field 1
#    reserved field 2
#
# The remainder of the fields represent the values of the requested items
# in the same order as they appear in the itemList input parameter.
#
# If an unkown request type is specified, the error indicator field
# in the output line is set to 109 (ENOSYS).
#
# If the specified object in the scope parameter does not exist, the error
# indicator in the output line is set to 19 (ENODEV).
#
# If an individual item is unknown, or is not supported any more,
# the corresponding field in the output is set to "sdrq_unknown_item"
# or "sdr_obsolete_item" respectively.
#
##########################################################################

# Include global declarations and service routines.
. /usr/lpp/mmfs/bin/mmglobfuncs
. /usr/lpp/mmfs/bin/mmsdrfsdef
. /usr/lpp/mmfs/bin/mmsdrquerydef

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

# Local work files.  Names should be of the form:
#   fn=${tmpDir}fn.${mmcmd}.$$

LOCAL_FILES=" "

# Local declarations
usageMsg=39
typeset -l queryType_lc
typeset -l itemList_lc
integer seqNumber=0
rc=0
reserved=""


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

queryType=$arg1
queryType_lc=$queryType
itemList=$arg2
itemList_lc=$itemList
scope=$arg3
norefresh=$arg4

[[ -z $arg2 ]] && syntaxError "missingArgs" $usageMsg
[[ -n $arg5 ]] && syntaxError "extraArg"    $usageMsg "$arg5"


###########################################################
# Ensure that the local copy of the mmsdrfs is up-to-date.
###########################################################
if [[ -z $norefresh ]]
then
  gpfsInitOutput=$(gpfsInit nolock)
  setGlobalVar $? $gpfsInitOutput
fi


####################################
# Handle the different query types.
####################################
if [[ $queryType_lc = sdrq_cluster_info || $queryType = $sdrq_cluster_info ]]
then
  ###############################
  # Global cluster information
  ###############################

  # Retrieve and parse the version and nodeset header lines.
  versionLine=$($head -1 $mmsdrfsFile)
  nodesetHdrLine=$($grep "^$HOME_CLUSTER:$NODESET_HDR:" $mmsdrfsFile)
  IFS=":"
  set -f ; set -A v -- - $versionLine ; set +f
  set -f ; set -A w -- - $nodesetHdrLine ; set +f
  IFS="$IFS_sv"

  # If necessary, initialize the item list and print the header line.
  if [[ $itemList_lc = all ]]
  then
    itemList_lc="1001:1002:1003:1004:1005:1006:1007:1008:1009:1010:1011:1012:1013:1014:1015"
    hdrLine="mmsdrquery:sdrq_cluster_info:HEADER:version:reserved:reserved"
    hdrLine="${hdrLine}:sdrq_cluster_name:sdrq_cluster_id:sdrq_cluster_type"
    hdrLine="${hdrLine}:sdrq_primary_server:sdrq_secondary_server:sdrq_rsh_path"
    hdrLine="${hdrLine}:sdrq_rcp_path:sdrq_uid_domain:sdrq_security_level"
    hdrLine="${hdrLine}:sdrq_cipher_list:sdrq_tcp_port_number:sdrq_os_environment"
    hdrLine="${hdrLine}:sdrq_sdrfs_version:sdrq_sdrfs_format:sdrq_sdrfs_gennumber"
    print -- "${hdrLine}:"
  fi  # end of if [[ $itemList_lc = all ]]

  # Build the common header; assume everything will be all right.
  (( seqNumber += 1 ))
  result="mmsdrquery:sdrq_cluster_info:$rc:$sdrq_current_format:$reserved:$reserved"

  # Parse the item list and build the rest of the output line.
  IFS=":"
  for item in $itemList_lc
  do
    case $item in

      sdrq_cluster_name | $sdrq_cluster_name )
        result="${result}:${v[$CLUSTER_NAME_Field]}"
        ;;

      sdrq_cluster_id | $sdrq_cluster_id )
        result="${result}:${v[$CLUSTERID_Field]}"
        ;;

      sdrq_cluster_type | $sdrq_cluster_type )
        result="${result}:${v[$CLUSTER_TYPE_Field]}"
        ;;

      sdrq_primary_server | $sdrq_primary_server )
        result="${result}:${v[$PRIMARY_SERVER_Field]}"
        ;;

      sdrq_secondary_server | $sdrq_secondary_server )
        [[ ${v[$BACKUP_SERVER_Field]} = "_NOSECONDARY_" ]] &&  \
          v[$BACKUP_SERVER_Field]=""
        result="${result}:${v[$BACKUP_SERVER_Field]}"
        ;;

      sdrq_rsh_path | $sdrq_rsh_path )
        [[ -z ${v[$RSH_PATH_Field]} || ${v[$RSH_PATH_Field]} = "_DEFAULT_" ]] &&  \
          v[$RSH_PATH_Field]=$rsh
        result="${result}:${v[$RSH_PATH_Field]}"
        ;;

      sdrq_rcp_path | $sdrq_rcp_path )
        [[ -z ${v[$RCP_PATH_Field]} || ${v[$RCP_PATH_Field]} = "_DEFAULT_" ]] &&  \
          v[$RCP_PATH_Field]=$rcp
        result="${result}:${v[$RCP_PATH_Field]}"
        ;;

      sdrq_uid_domain | $sdrq_uid_domain )
        uidDomain=$(showCfgValue uidDomain)
        [[ -z $uidDomain ]] && uidDomain=${v[$CLUSTER_NAME_Field]}
        result="${result}:$uidDomain"
        ;;

      sdrq_sdrfs_version | $sdrq_sdrfs_version )
        result="${result}:${v[$SDRFS_VERSION_Field]}"
        ;;

      sdrq_sdrfs_format | $sdrq_sdrfs_format )
        result="${result}:${v[$SDRFS_FORMAT_Field]}"
        ;;

      sdrq_sdrfs_gennumber | $sdrq_sdrfs_gennumber )
        result="${result}:${v[$SDRFS_GENNUM_Field]}"
        ;;

      sdrq_security_level | $sdrq_security_level )
        result="${result}:${v[$SECLEVEL_Field]}"
        ;;

      sdrq_cipher_list | $sdrq_cipher_list )
        result="${result}:${w[$CIPHER_LIST_Field]}"
        ;;

      sdrq_tcp_port_number | $sdrq_tcp_port_number )
        result="${result}:${w[$TCP_PORT_Field]}"
        ;;

      sdrq_os_environment | $sdrq_os_environment )
        result="${result}:${w[$OS_ENVIRONMENT_Field]}"
        ;;

#     xxx | $xxx )
#       result="${result}:$sdrq_obsolete_item"
#       ;;

      * ) # Unrecognized item
        result="${result}:$sdrq_unknown_item"
        ;;
    esac  # end of case $item in

  done  # end of for item in $itemList_lc
  IFS="$IFS_sv"

  # Add trailing colon and print the result.
  print -- "${result}:"

elif [[ $queryType_lc = sdrq_node_info || $queryType = $sdrq_node_info ]]
then
  #############################
  # Node specific information
  #############################

  # Process the scope parameter for this query type:
  #   If scope is not specified, return information for all nodes.
  #   Otherwise, the scope parameter must confirm to the syntax of
  #   the -N option for mmchnode and similar commands.
  [[ -z $scope ]] && scope=all
  if [[ $scope != all ]]
  then
    # Allow any combination of the comma, semi-colon and/or the
    # colon character to be used as a list separator character.
    scope=$(print -- "$scope" | $sed 's/:/,/g')
    scope=$(print -- "$scope" | $sed 's/;/,/g')
    createVerifiedNodefile "$scope" $REL_HOSTNAME_Field $nodefile
    if [[ ! -s $nodefile ]]
    then
      # No nodes were found that matched the input specification.
      rc=$MM_DeviceNotFound   # device does not exist (ENODEV)
      result="mmsdrquery:sdrq_node_info:$rc:$sdrq_current_format:$reserved:$reserved"
      print -- "${result}:"
      cleanupAndExit $rc
    fi  # end of if [[ ! -s $nodefile ]]
  fi  # end of if [[ $scope != all ]]

  # If necessary, initialize the item list and print the header line.
  if [[ $itemList_lc = all ]]
  then
    itemList_lc="2001:2002:2003:2004:2005:2006:2007:2008:2009:2010"
    hdrLine="mmsdrquery:sdrq_node_info:HEADER:version:reserved:reserved"
    hdrLine="${hdrLine}:sdrq_node_number:sdrq_admin_interface:sdrq_daemon_interface"
    hdrLine="${hdrLine}:sdrq_daemon_ip_address:sdrq_client_node:sdrq_manager_node"
    hdrLine="${hdrLine}:sdrq_quorum_node:sdrq_product_version:sdrq_daemon_version"
    hdrLine="${hdrLine}:sdrq_os_name"
    print -- "${hdrLine}:"
  fi  # end of if [[ $itemList_lc = all ]]

  # Go through the mmsdrfs file and retrieve the requested information.
  $rm -f $tmpsdrfs $chnodes $diskLines
  IFS=":"
  exec 3<&-
  exec 3< $mmsdrfsFile
  while read -u3 sdrfsLine
  do
    # Parse the line.
    set -f ; set -A v -- - $sdrfsLine ; set +f

    IFS="$IFS_sv"
    getThisNode=""

    case ${v[$LINE_TYPE_Field]} in

      $MEMBER_NODE )
        if [[ $scope = all ]]
        then
          getThisNode=yes
        else
          getThisNode=$($grep -w ${v[$REL_HOSTNAME_Field]} $nodefile)
        fi

        if [[ -n $getThisNode ]]
        then
          # Build the common header; assume everything will be all right.
          (( seqNumber += 1 ))
          result="mmsdrquery:sdrq_node_info:$rc:$sdrq_current_format:$reserved:$reserved"

          # Parse the item list and build the rest of the output line.
          IFS=":"
          for item in $itemList_lc
          do
            case $item in

              sdrq_node_number | $sdrq_node_number )
                result="${result}:${v[$NODE_NUMBER_Field]}"
                ;;

              sdrq_admin_interface | $sdrq_admin_interface )
                result="${result}:${v[$REL_HOSTNAME_Field]}"
                ;;

              sdrq_daemon_interface | $sdrq_daemon_interface )
                [[ -z ${v[$DAEMON_NODENAME_Field]} ]] &&  \
                  v[$DAEMON_NODENAME_Field]=${v[$REL_HOSTNAME_Field]}
                result="${result}:${v[$DAEMON_NODENAME_Field]}"
                ;;

              sdrq_daemon_ip_address | $sdrq_daemon_ip_address )
                result="${result}:${v[$IPA_Field]}"
                ;;

              sdrq_client_node | $sdrq_client_node )
                [[ ${v[$DESIGNATION_Field]} = "$CLIENT" ]] &&  \
                  result="${result}:true" || result="${result}:false"
                ;;

              sdrq_manager_node | $sdrq_manager_node )
                [[ ${v[$DESIGNATION_Field]} = "$MANAGER" ]] &&  \
                  result="${result}:true" || result="${result}:false"
                ;;

              sdrq_quorum_node | $sdrq_quorum_node )
                [[ ${v[$CORE_QUORUM_Field]} = "$quorumNode" ]] &&  \
                  result="${result}:true" || result="${result}:false"
                ;;

              sdrq_product_version | $sdrq_product_version )
                result="${result}:${v[$PRODUCT_VERSION_Field]}"
                ;;

              sdrq_daemon_version | $sdrq_daemon_version )
                result="${result}:${v[$DAEMON_VERSION_Field]}"
                ;;

              sdrq_os_name | $sdrq_os_name )
                result="${result}:${v[$OS_NAME_Field]}"
                ;;

#             xxx | $xxx )
#               result="${result}:$sdrq_obsolete_item"
#               ;;

              * ) # Unrecognized item
                result="${result}:$sdrq_unknown_item"
                ;;
            esac  # end of case $item in

          done  # end of for item in $itemList_lc
          IFS="$IFS_sv"

          # Add trailing colon and print the result.
          print -- "${result}:"

        fi  # end of if [[ -n $getThisNode ]]
        ;;

      * )  # Not interested in any ohter lines.
        ;;

    esac  # end case ${v[$LINE_TYPE_Field]} in

    IFS=":"  # Change the separator back to ":" for the next iteration.

  done  # end while read -u3 sdrfsLine

  IFS="$IFS_sv"  # Restore the default IFS settings.


elif [[ $queryType_lc = sdrq_nsd_info || $queryType = $sdrq_nsd_info ]]
then
  #############################
  # NSD specific information
  #############################

#esjxx - Add code to put out messages for each specifically requested disk name
#esjxx   that was not found and for each fs device name that was given and that
#esjxx   does not exist or has no disks (because it is for a remote fs).  This
#esjxx   should also cover the free disk case

  # Process the scope parameter for this query type:
  #   If scope is not specified, return information for all disks.
  #   Otherwise, the scope parameter can be either a list of NSD names,
  #   file system device names, and/or the keyword 'free_disks', or
  #   a fully-qualified path name for a file containing NSD or device names.
  #   All file system device names must include the /dev prefix to distinguish
  #   them from NSD names.

  if [[ -z $scope || $scope = all ]]
  then
    scope=all

  elif [[ $scope = /* && $scope != +(/)dev+(/)* ]]
  then
    # The scope parameter is a path name for a file.
    # Verify the existence of the file and create our own copy.
    checkUserFile "$scope" $tmpfile
    [[ $? -ne 0 ]] && cleanupAndExit

  else
    # The scope parameter is a list of NSD and/or device names.
    # Allow any combination of the comma, semi-colon and/or the
    # colon character to be used as a list separator character.
    scope=$(print -- "$scope" | $sed 's/;/,/g')
    scope=$(print -- "$scope" | $sed 's/:/,/g')

    # Parse the list and put the items into a file.
    $rm -f $tmpfile
    IFS=","
    for token in $scope
    do
      [[ -z $token ]] && continue
      print -- "$token" >> $tmpfile
      checkForErrors "writing to file $tmpfile" $?
    done  # end for token in $scope
    IFS="$IFS_sv"
  fi  # end of if [[ -z $scope || $scope = all ]]

  # Separate the NSD names from the file system device names.
  if [[ $scope != all ]]
  then
    $rm -f $diskfile
    exec 3<&-
    exec 3< $tmpfile
    while read -u3 token
    do
      if [[ $token = +(/)dev+(/)* ]]
      then
        # Add the fs name to the list of file systems.
        fsList="${fsList} ${token##+(/)dev+(/)}"
      elif [[ $token = free_disks ]]
      then
        # Add the funny NO_DEVICE name to the list of file systems.
        fsList="${fsList} $NO_DEVICE"
      elif [[ $token = all ]]
      then
        # This will overwrite everything else.
        scope=all
        break
      else
        # This must be an NSD name.
        print -- "$token" >> $diskfile
        checkForErrors "writing to file $diskfile" $?
      fi
    done  # end of while read -u3 token

    # Ensure the fsList has a trailing blank.
    [[ -n $fsList ]] && fsList="${fsList} "
  fi  # end of if [[ $scope != all ]]

  # If necessary, initialize the item list and print the header line.
  if [[ $itemList_lc = all ]]
  then
    itemList_lc="3001:3002:3003:3004:3005:3006:3007:3008:3009:3010:3011"
    hdrLine="mmsdrquery:sdrq_nsd_info:HEADER:version:reserved:reserved"
    hdrLine="${hdrLine}:sdrq_nsd_name:sdrq_nsd_server_list:sdrq_backup_nsd_server_list"
    hdrLine="${hdrLine}:sdrq_fs_name:sdrq_storage_pool:sdrq_disk_usage"
    hdrLine="${hdrLine}:sdrq_failure_group:sdrq_nsd_id:sdrq_disk_subtype"
    hdrLine="${hdrLine}:sdrq_quorum_disk:sdrq_disk_status"
    print -- "${hdrLine}:"
  fi  # end of if [[ $itemList_lc = all ]]

  # Go through the mmsdrfs file and retrieve the requested information.
  $rm -f $tmpsdrfs $chnodes $diskLines
  IFS=":"
  exec 3<&-
  exec 3< $mmsdrfsFile
  while read -u3 sdrfsLine
  do
    # Parse the line.
    set -f ; set -A v -- - $sdrfsLine ; set +f

    IFS="$IFS_sv"

    case ${v[$LINE_TYPE_Field]} in

      $SG_DISKS )
        if [[ $scope = all || $fsList = *" ${v[$DEV_NAME_Field]} "* ]]
        then
          getThisDisk=yes
        elif [[ -s $diskfile ]]
        then
          getThisDisk=$($grep -w ${v[$DISK_NAME_Field]} $diskfile)
        else
          getThisDisk=""
        fi

        if [[ -n $getThisDisk ]]
        then
          # Build the common header; assume everything will be all right.
          (( seqNumber += 1 ))
          result="mmsdrquery:sdrq_nsd_info:$rc:$sdrq_current_format:$reserved:$reserved"

          # Parse the item list and build the rest of the output line.
          IFS=":"
          for item in $itemList_lc
          do
            case $item in

              sdrq_nsd_name | $sdrq_nsd_name )
                result="${result}:${v[$DISK_NAME_Field]}"
                ;;

              sdrq_nsd_server_list | $sdrq_nsd_server_list )
                result="${result}:${v[$NSD_PRIMARY_NODE_Field]}"
                ;;

              sdrq_backup_nsd_server_list | $sdrq_backup_nsd_server_list )
                result="${result}:${v[$NSD_BACKUP_NODE_Field]}"
                ;;

              sdrq_fs_name | $sdrq_fs_name )
                [[ ${v[$DEV_NAME_Field]} = "$NO_DEVICE" ]] &&  \
                  v[$DEV_NAME_Field]="free_disk"
                result="${result}:${v[$DEV_NAME_Field]}"
                ;;

              sdrq_storage_pool | $sdrq_storage_pool )
                [[ -z ${v[$STORAGE_POOL_Field]} ]] &&  \
                  v[$STORAGE_POOL_Field]="system"
                result="${result}:${v[$STORAGE_POOL_Field]}"
                ;;

              sdrq_disk_usage | $sdrq_disk_usage )
                result="${result}:${v[$DISK_USAGE_Field]}"
                ;;

              sdrq_failure_group | $sdrq_failure_group )
                result="${result}:${v[$FAILURE_GROUP_Field]}"
                ;;

              sdrq_nsd_id | $sdrq_nsd_id )
                result="${result}:${v[$PVID_Field]}"
                ;;

              sdrq_disk_subtype | $sdrq_disk_subtype )
                result="${result}:${v[$NSD_SUBTYPE_Field]}"
                ;;

              sdrq_quorum_disk | $sdrq_quorum_disk )
                [[ ${v[$PAXOS_Field]} = "$PaxosDisk" ]] &&  \
                  result="${result}:true" || result="${result}:false"
                ;;

              sdrq_disk_status | $sdrq_disk_status )
                [[ -z ${v[$DISK_STATUS_Field]} ]] &&  \
                  v[$DISK_STATUS_Field]="ready"
                result="${result}:${v[$DISK_STATUS_Field]}"
                ;;

#             xxx | $xxx )
#               result="${result}:$sdrq_obsolete_item"
#               ;;

              * ) # Unrecognized item
                result="${result}:$sdrq_unknown_item"
                ;;
            esac  # end of case $item in

          done  # end of for item in $itemList_lc
          IFS="$IFS_sv"

          # Add trailing colon and print the result.
          print -- "${result}:"

        fi  # end of if [[ -n $getThisDisk ]]
        ;;

      * )  # Not interested in any ohter lines.
        ;;

    esac  # end case ${v[$LINE_TYPE_Field]} in

    IFS=":"  # Change the separator back to ":" for the next iteration.

  done  # end while read -u3 sdrfsLine

  IFS="$IFS_sv"  # Restore the default IFS settings.


  if [[ $seqNumber -eq 0 ]]
  then
    # No disks were found that matched the input specification."
    rc=$MM_DeviceNotFound   # device does not exist (ENODEV)
    result="mmsdrquery:sdrq_nsd_info:$rc:$sdrq_current_format:$reserved:$reserved"
    print -- "${result}:"
    print -u2 "$mmcmd: No disks were found that matched the input specification."
  fi  # end of if [[ $seqNumber -eq 0 ]]


elif [[ $queryType_lc = sdrq_fs_info  || $queryType = $sdrq_fs_info ]]
then
  ###################################
  # File system specific information
  ###################################

#esjxx - Add code to put out messages for each specifically requested file system
#esjxx   that was not found.

  # Process the scope parameter for this query type:
  #   If scope is not specified, return information for all disks.
  #   Otherwise, the scope parameter can be either a list of device names
  #   or one of the 'all' key words: all, all_local, or all_remote.

  if [[ -z $scope || $scope = all ]]
  then
    scope=all

  elif [[ $scope = all_local || $scope = all_remote ]]
  then
    scope=$scope

# elif [[ $scope = /* && $scope != +(/)dev+(/)* ]]
# then
#   # The scope parameter is a path name for a file.
#   # Verify the existence of the file and create our own copy.
#   checkUserFile "$scope" $tmpfile
#   [[ $? -ne 0 ]] && cleanupAndExit

  else
    # The scope parameter is a list of device names.
    # Allow any combination of the comma, semi-colon and/or the
    # colon character to be used as a list separator character.
    scope=$(print -- "$scope" | $sed 's/;/,/g')
    scope=$(print -- "$scope" | $sed 's/:/,/g')

    # Parse the list of device names.
    $rm -f $tmpfile
    IFS=","
    for token in $scope
    do
      [[ -z $token ]] && continue
      # Add the fs name to the list of file systems.
      fsList="${fsList} ${token##+(/)dev+(/)}"
    done  # end for token in $scope
    IFS="$IFS_sv"

    # Ensure the fsList has a trailing blank.
    [[ -n $fsList ]] && fsList="${fsList} "
  fi  # end of if [[ -z $scope || $scope = all ]]

  # If necessary, initialize the item list and print the header line.
  if [[ $itemList_lc = all ]]
  then
    itemList_lc="4001:4002:4003:4004:4005:4006:4007:4008:4009:4010:4011:4012:4013:4014"
    hdrLine="mmsdrquery:sdrq_fs_info:HEADER:version:reserved:reserved"
    hdrLine="${hdrLine}:sdrq_device_name:sdrq_mount_point:sdrq_fs_type"
    hdrLine="${hdrLine}:sdrq_owning_cluster_name:sdrq_remote_device_name"
    hdrLine="${hdrLine}:sdrq_automount_option:sdrq_rw_options:sdrq_quota_option"
    hdrLine="${hdrLine}:sdrq_atime_option:sdrq_mtime_option:sdrq_other_mount_options"
    hdrLine="${hdrLine}:sdrq_mount_options:sdrq_drive_letter:sdrq_device_minor_number"
    print -- "${hdrLine}:"
  fi  # end of if [[ $itemList_lc = all ]]

  # Go through the mmsdrfs file and retrieve the requested information.
  $rm -f $tmpsdrfs $chnodes $diskLines
  IFS=":"
  exec 3<&-
  exec 3< $mmsdrfsFile
  while read -u3 sdrfsLine
  do
    # Parse the line.
    set -f ; set -A v -- - $sdrfsLine ; set +f

    IFS="$IFS_sv"

    case ${v[$LINE_TYPE_Field]} in

      $VERSION_LINE )
        ourClusterName=${v[$CLUSTER_NAME_Field]}
        ;;

      $SG_HEADR )
        # Starting the processing of a new file system.
        # See if the file system should be displayed.
        if [[ $scope  = all                                            ||
              $scope  = all_local  && ${v[$FS_TYPE_Field]} = $localfs  ||
              $scope  = all_remote && ${v[$FS_TYPE_Field]} = $remotefs ||
              $fsList = *" ${v[$DEV_NAME_Field]} "*                    ]]
        then
          getThisFileSystem=yes

          # Start collecting the potentially needed information.
          # The actual output will be constructed when all of the information
          # becomes available (when the SG_MOUNT line is processed).
          remoteDeviceName=${v[$REMOTE_DEV_NAME_Field]}
          deviceMinorNumber=${v[$DEV_MINOR_Field]}
          if [[ ${v[$FS_TYPE_Field]} = $localfs ]]
          then
            fsType=local
          else
            fsType=remote
          fi

        else
          getThisFileSystem=""
        fi  # end of if [[ $scope  = all ...
        ;;

      $SG_ETCFS )
        if [[ -n $getThisFileSystem ]]
        then
          # Save some more potentially needed information.
          stanzaLine=${v[$ETCFS_TEXT_Field]}
          if [[ ${v[$LINE_NUMBER_Field]} = $MOUNT_POINT_Line ]]
          then
            mountPoint=$stanzaLine
          elif [[ ${v[$LINE_NUMBER_Field]} -eq $MOUNT_Line ]]
          then
            value=${stanzaLine#*=$BLANKchar}
            if [[ $value = mmfs ]]
            then
              automountOption=yes
            elif [[ $value = false ]]
            then
              automountOption=no
            else
              automountOption=$value
            fi
          fi  # end of if [[ ${v[$LINE_NUMBER_Field]} = $MOUNT_POINT_Line ]]
        fi  # end of if [[ -n $getThisFileSystem ]]
        ;;


      $SG_MOUNT )
        if [[ -n $getThisFileSystem ]]
        then
          # Create a combined list of all mount options.
          rwOption=${v[$RW_OPT_Field]}
          quotaOption=${v[$QUOTA_OPT_Field]}
          atimeOption=${v[$ATIME_OPT_Field]}
          mtimeOption=${v[$MTIME_OPT_Field]}
          otherMountOptions=${v[$OTHER_OPT_Field]}
          allMountOptions="${rwOption},${atimeOption},${mtimeOption}"
          [[ -n $quotaOption ]] &&  \
            allMountOptions="${allMountOptions},${quotaOption}"
          [[ -n $otherMountOptions ]] &&  \
            allMountOptions="${allMountOptions},${otherMountOptions}"

          # At this point all of the needed information is available.
          # Build the common header; assume everything will be all right.
          (( seqNumber += 1 ))
          result="mmsdrquery:sdrq_fs_info:$rc:$sdrq_current_format:$reserved:$reserved"

          # Parse the item list and build the rest of the output line.
          IFS=":"
          for item in $itemList_lc
          do
            case $item in

              sdrq_device_name | $sdrq_device_name )
                result="${result}:${v[$DEV_NAME_Field]}"
                ;;

              sdrq_mount_point | $sdrq_mount_point )
                result="${result}:$mountPoint"
                ;;

              sdrq_fs_type | $sdrq_fs_type )
                result="${result}:$fsType"
                ;;

              sdrq_owning_cluster_name | $sdrq_owning_cluster_name )
                if [[ ${v[$NODESETID_Field]} = "$HOME_CLUSTER" ]]
                then
                  result="${result}:$ourClusterName"
                else
                  result="${result}:${v[$NODESETID_Field]}"
                fi
                ;;

              sdrq_remote_device_name | $sdrq_remote_device_name )
                if [[ -n $remoteDeviceName ]]
                then
                  result="${result}:$remoteDeviceName"
                else
                  result="${result}:${v[$DEV_NAME_Field]}"
                fi
                ;;

              sdrq_automount_option | $sdrq_automount_option )
                result="${result}:$automountOption"
                ;;

              sdrq_rw_options | $sdrq_rw_options )
                result="${result}:$rwOption"
                ;;

              sdrq_quota_option | $sdrq_quota_option )
                if [[ -n $quotaOption ]]
                then
                  result="${result}:$quotaOption"
                else
                  result="${result}:no"
                fi
                ;;

              sdrq_atime_option | $sdrq_atime_option )
                result="${result}:$atimeOption"
                ;;

              sdrq_mtime_option | $sdrq_mtime_option )
                result="${result}:$mtimeOption"
                ;;

              sdrq_other_mount_options | $sdrq_other_mount_options )
                result="${result}:$otherMountOptions"
                ;;

              sdrq_mount_options | $sdrq_mount_options )
                result="${result}:$allMountOptions"
                ;;

              sdrq_drive_letter | $sdrq_drive_letter )
                result="${result}:${v[$DRIVE_LETTER_Field]}"
                ;;

              sdrq_device_minor_number | $sdrq_device_minor_number )
                result="${result}:$deviceMinorNumber"
                ;;

#             xxx | $xxx )
#               result="${result}:$sdrq_obsolete_item"
#               ;;

              * ) # Unrecognized item
                result="${result}:$sdrq_unknown_item"
                ;;
            esac  # end of case $item in

          done  # end of for item in $itemList_lc
          IFS="$IFS_sv"

          # Add trailing colon and print the result.
          print -- "${result}:"

        fi  # end of if [[ -n $getThisFileSystem ]]
        ;;

      * )  # Not interested in any ohter lines.
        ;;

    esac  # end case ${v[$LINE_TYPE_Field]} in

    IFS=":"  # Change the separator back to ":" for the next iteration.

  done  # end while read -u3 sdrfsLine

  IFS="$IFS_sv"  # Restore the default IFS settings.

  if [[ $seqNumber -eq 0 ]]
  then
    # No file systems were found that matched the input specification."
    rc=$MM_DeviceNotFound   # device does not exist (ENODEV)
    result="mmsdrquery:sdrq_fs_info:$rc:$sdrq_current_format:$reserved:$reserved"
    print -- "${result}:"
    print -u2 "$mmcmd: No file systems were found that matched the input specification."
  fi  # end of if [[ $seqNumber -eq 0 ]]

else
  # Unkown query type
  print -u2 "$mmcmd:  Unknown query type $queryType"
  rc=$MM_NotSupported   # function not supported (ENOSYS)

  # Build the common header and print the result.
  result="mmsdrquery:$queryType:$rc:$sdrq_current_format:$seqNumber:$reserved:$reserved"
  print -- "${result}:"

fi  # end of if [[ $queryType_lc = sdrq_cluster_info || ...

cleanupAndExit $rc

