#!/usr/bin/ksh
# IBM_PROLOG_BEGIN_TAG 
# This is not an automatically generated prolog. 
#  
# Licensed Materials - Property of IBM 
#  
# (C) COPYRIGHT International Business Machines Corp. 2005 
# 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 

Version="1.0"

PATH="/usr/bin:/etc:/usr/sbin:/sbin"
export PATH=$PATH

USAGE="usage: chjava -b <path_to_package> -p <java_path_suffix> [-l <LPP_name_suffix>] [-q] 
ex: chjava -b /tmp/images/Java131.rte.bin -p A -l _A  
    This will create a package with an LPP name of Java131_A.rte.bin that installs to /usr/java131A .
ex: chjava -b \"/tmp/images/Java13*\" -p A   
ex: chjava -b \"Java131.rte.bin Java14.sdk\" -p A   

-b : Specifies the path to the install or update packages to alter.
-l : Specifies the suffix to add to the original LPP name when creating the new package.
-p : Specifies the suffix to add to the original /usr/java<version> install path when creating the new package. 
     Also specifies the suffix to add to the original LPP name if the -l flag isn't specified.
-q : Specifies to suppress informational messages and to only print the summary. \n"


TRUE=0
FALSE=1
OWD=`pwd`


# Default settings
quiet=$FALSE
breakAfterReplace=$FALSE
packageList=""
pathToPackage=""
oldLppName=""
newLppName=""
oldPath=""
newPath=""
workdir="./"
tempOsummary=""
tempNsummary=""
Osummary=""
Nsummary=""
packageType="update"
licenseFileset=$FALSE
msgFileset=$FALSE
javaFileset=$FALSE
rc=0



######################################
# Functions
######################################


function _print
   {
   if [[ $quiet = $FALSE ]] then
      print "$*"
   fi
   }
   
function _cleanupPackage
{

  _print "chjava: interupted by cltr-c, cleaning up : ${_workdir}${_package}_temp"
  cd ${OLDPWD}
  rm -rf ${_workdir}${_package}_temp

  exit 1
}

function _breakdownPackage
   {
   typeset _pathToPackage=$1
   
   typeset _package=${_pathToPackage##*/}
   typeset _workdir=`pwd`"/"
   
   # Restore package
   trap "_cleanupPackage ${_workdir}${_package}_temp" 2
   _print "chjava: Breaking down package named:${_package} in directory ${_workdir}${_package}_temp ."
   _print "\n"
   
   rm -rf ${_package}_temp > /dev/null 2>&1
   mkdir ${_package}_temp   
   cd ${_package}_temp
   
   output=`restore -xvqf ../${_package} 2>&1`
   _rc=$?
   _print "$output"
   _print "\n"
   
   if [[ $_rc != 0 ]] then
      print "chjava: restore of package failed."
      exit 1
   fi
   
   # ar the liblpp.a files
   _print "chjava: - Breaking down the liblpp.a files into seperate packaging files."
   
   liblpps=`find . -name liblpp.a`   
   
   for liblpp in $liblpps
      do
      liblpp=${liblpp#./}
      _dir=${liblpp%liblpp.a}

      _print "chjava: - Breaking down ${_workdir}${_package}_temp/${liblpp} into ${_workdir}${_package}_temp/${_dir}temp"

      cd $_dir
      mkdir temp
      cd temp

      output=`ar -xv ../liblpp.a`
      _rc=$?
      _print "$output"
      _print "\n"
   
      if [[ $_rc != 0 ]] then
         print "chjava: ar of ${_workdir}${_package}_temp/${liblpp} failed."
         exit 1
      fi
      
      cd ${_workdir}${_package}_temp
      done

   cd ${_workdir}
   _print "chjava: Breaking down of package was successful.\n\n"
   }





function _modifyFilename
   {
   typeset _file=$1
   typeset _oldName=$2
   typeset _newName=$3

   typeset dir=${_file%/*}"/"
   typeset newfile=${_file##*/}
   newfile=` echo "${newfile}" | sed "s:$_oldName:$_newName:g" `
   if [[ ${_file} = ${dir}${newfile} ]] then
      return
   fi
   _print "mv ${_file} ${dir}${newfile}"
   output=`mv ${_file} ${dir}${newfile} 2>&1`
   _rc=$?
   if [[ $_rc != 0 ]] then
      print "chjava: Modifying filename failed."
      exit 1
   fi
   _print "$output"
   }




function _modifyFile
   {
   typeset _file=$1
   typeset _oldContent=$2
   typeset _newContent=$3

   _print "sed \"s:$_oldContent:$_newContent:g\" ${_file} > ${_file}.new ; mv -f ${_file}.new ${_file}"
   output=`sed "s:$_oldContent:$_newContent:g" ${_file} > ${_file}.new ; mv -f ${_file}.new ${_file}`
   _rc=$?
   if [[ $_rc != 0 ]] then
      print "chjava: Modifying file failed."
      exit 1
   fi
   _print "$output"
   }


function _modifyFileExceptLAR
   {
   typeset _file=$1
   typeset _oldContent=$2
   typeset _newContent=$3

#   _print "sed \"s:$_oldContent:$_newContent:g\" ${_file} > ${_file}.new ; mv ${_file}.new ${_file}"
#   output=`sed "s:$_oldContent:$_newContent:g" ${_file} > ${_file}.new ; mv ${_file}.new ${_file}`

   _print "awk '\$0 !~ /^LAR/ {gsub(\"${_oldContent}\",\"${_newContent}\", \$0); }; {print}' ${_file} > ${_file}.new ; mv -f ${_file}.new ${_file}"
   output=`awk '\$0 !~ /^LAR/ {gsub("'${_oldContent}'","'${_newContent}'", \$0); }; {print}' ${_file} > ${_file}.new ; mv -f ${_file}.new ${_file}`
   _rc=$?
   if [[ $_rc != 0 ]] then
      print "chjava: Modifying file failed."
      exit 1
   fi
   _print "$output"
   }




function _depth
   {
   typeset _path=$1
   
   _Depth=0 
   _path=${_path#/}
   _path=${_path%/}
   typeset _dir=""
   OIFS=$IFS
   IFS="/"
   for _dir in $_path
      do
      (( _Depth = _Depth + 1 ))
      done 
   IFS=$OIFS
   return $_Depth
   }




function _modifyPackage
   {
   typeset _pathToPackage=$1
   typeset _lppNameArg=$2
   typeset _pathNameArg=$3
   typeset _packageType=$4

   typeset _package=${_pathToPackage##*/}
   typeset _workdir=`pwd`"/"
   
   # Modify package
   tempOsummary="${tempOsummary}Original package: ${_package} \n"
   _print "chjava: Modifying package named:${_package} in directory ${_workdir}${_package}_temp ."
   _print "\n"

   # Create old and new LPP names and path names
   filenames="${_workdir}${_package}_temp/usr/lpp/Java*"
   files=`find $filenames -prune`
   for file in $files
      do
      typeset _oldLppName=${file##*/}
      _oldLppName=${_oldLppName%%.*}
      break
      done
   typeset _newLppName=${_oldLppName}${_lppNameArg}

   filenames="${_workdir}${_package}_temp/usr/java*"
   files=`find $filenames -prune`
   for file in $files
      do
      typeset _oldPath="/usr/"${file##*/}
      break
      done
   typeset _newPath=${_oldPath}${_pathNameArg}
   tempOsummary="${tempOsummary}Original path: ${_oldPath} \n"
   tempNsummary="${tempNsummary}New      path: ${_newPath} \n"

   # Modify fileset name directories
   if [[ $_packageType = "update" ]] then
      filenames="${_workdir}${_package}_temp/usr/lpp/*${_oldLppName}*"
      files=`find $filenames -prune`
      for file in $files
         do
         _modifyFilename $file ${_oldLppName} ${_newLppName}
         done
   fi

   if [[ $_packageType = "install" ]] then
      filenames="${_workdir}${_package}_temp/usr/lpp/*${_oldLppName}*"
   else
      filenames="${_workdir}${_package}_temp/usr/lpp/*/*${_oldLppName}*"
   fi
   files=`find $filenames -prune`
   for file in $files
      do
      _modifyFilename $file ${_oldLppName} ${_newLppName}
      done
   if [[ $_packageType = "install" ]] then
      filenames="${_workdir}${_package}_temp/usr/lpp/*${_newLppName}*"
   else
      filenames="${_workdir}${_package}_temp/usr/lpp/*/*${_newLppName}*"
   fi

   # Modify packaging file names
   if [[ $_packageType = "install" ]] then
      filenames="${_workdir}${_package}_temp/usr/lpp/*/temp/*${_oldLppName}*"
   else
      filenames="${_workdir}${_package}_temp/usr/lpp/*/*/*/temp/*${_oldLppName}*"
   fi
   files=`find $filenames -prune`
   for file in $files
      do
      _modifyFilename $file ${_oldLppName} ${_newLppName}
      done

   # Get previous fileset names from lpp_name
   typeset _num=0
   typeset filesets=`awk '/^Java/ {print $1}' ${_workdir}${_package}_temp/lpp_name`  
   for file in $filesets
      do
      (( _num = _num + 1 ))
      tempOsummary="${tempOsummary}Original fileset${_num}: ${file##*/} \n"
      done
   
   # Modify content of .inventory files, productid, and size files lpp_name from _oldLppName to _newLppName
   if [[ $_packageType = "install" ]] then
      filenames="${_workdir}${_package}_temp/usr/lpp/*/temp/productid"
   else
      filenames="${_workdir}${_package}_temp/usr/lpp/*/*/*/temp/productid"
   fi
   files=`find $filenames `
   for file in $files
      do
      _modifyFile $file ${_oldLppName} ${_newLppName}
      done

   if [[ $_packageType = "install" ]] then
      filenames="${_workdir}${_package}_temp/usr/lpp/*/temp/*.inventory"
   else
      filenames="${_workdir}${_package}_temp/usr/lpp/*/*/*/temp/*.inventory"
   fi
   files=`find $filenames `
   for file in $files
      do
      _modifyFile $file ${_oldLppName} ${_newLppName}
      done

   if [[ $_packageType = "install" ]] then
      filenames="${_workdir}${_package}_temp/usr/lpp/*/temp/*.size"
   else
      filenames="${_workdir}${_package}_temp/usr/lpp/*/*/*/temp/*.size"
   fi
   files=`find $filenames `
   for file in $files
      do
      _modifyFile $file ${_oldLppName} ${_newLppName}
      done

   filenames="${_workdir}${_package}_temp/lpp_name"
   files=`find $filenames `
   for file in $files
      do
      _modifyFileExceptLAR $file ${_oldLppName} ${_newLppName}
      done

   # Get new fileset names from lpp_name
   typeset _num=0
   typeset filesets=`awk '/^Java/ {print $1}' ${_workdir}${_package}_temp/lpp_name`  
   for file in $filesets
      do
      (( _num = _num + 1 ))
      tempNsummary="${tempNsummary}New      fileset${_num}: ${file##*/} \n"
      done
   
   # Modify content of packaging files from _oldPath to _newPath
   if [[ $_packageType = "install" ]] then
      filenames="${_workdir}${_package}_temp/usr/lpp/*/temp/*"
   else
      filenames="${_workdir}${_package}_temp/usr/lpp/*/*/*/temp/*"
   fi
   files=`find $filenames `
   for file in $files
      do
      _modifyFile $file ${_oldPath} ${_newPath}
      done
   filenames="${_workdir}${_package}_temp/lpp_name"
   files=`find $filenames `
   for file in $files
      do
      _modifyFile $file ${_oldPath} ${_newPath}
      done

   # Modify directory names from _oldPath to _newPath
   file="${_workdir}${_package}_temp${_oldPath}"
   typeset old=${_oldPath##*/}
   typeset new=${_newPath##*/}
   _modifyFilename $file ${old} ${new}

   _print "\n"
   }
   
   
   
   
function _rebuildPackage
   {
   typeset _pathToPackage=$1
   typeset _packageType=$2
   typeset _lppNameArg=$3
   
   typeset _package=${_pathToPackage##*/}
   typeset _workdir=`pwd`"/"
   
   #  package
   _print "chjava: Rebuilding package from directory ${_workdir}${_package}_temp ."
   _print "\n"
   
   if [[ $_packageType = "install" ]] then
      filenames="${_workdir}${_package}_temp/usr/lpp/*/temp"
   else
      filenames="${_workdir}${_package}_temp/usr/lpp/*/*/*/temp"
   fi
   files=`find $filenames -prune`

   _print "chjava: - rebuilding liblpp.a files."
   for file in $files
      do
      cd $file
      
      _print 'rm -f ../liblpp.a'
      output=`rm -f ../liblpp.a`
      _rc=$?
      _print "$output"
      _print "\n"
   
      if [[ $_rc != 0 ]] then
         print "chjava: rm of ${file}/../liblpp.a failed."
         exit 1
      fi

      _print 'ar -vq ../liblpp.a *'
      output=`ar -vq ../liblpp.a * 2>&1`
      _rc=$?
      _print "$output"
      _print "\n"
   
      if [[ $_rc != 0 ]] then
         print "chjava: ar of ${file}/../liblpp.a failed."
         exit 1
      fi

      cd ../
      rm -rf temp
      done

   typeset preDot=${_package%%\.*}
   typeset postDot=${_package#*\.}   
   if (( ${#preDot} == ${#package} )) then 
      # No dot found in package name
      typeset bff=${_package}${_lppNameArg}
   else
      typeset bff=${preDot}${_lppNameArg}"."${postDot}
   fi
 
   _print "chjava: - building package "
   cd ${_workdir}${_package}_temp
   _print "find . -print | backup -ivqpf ../$bff"
   output=`find . -print | backup -ivqpf ../$bff`
   _rc=$?
   _print "$output"
   _print "\n"
   if [[ $_rc != 0 ]] then
      print "chjava: backup failed."
      exit 1
   fi
   tempNsummary="New      package: ${bff} \n${tempNsummary}"
   
   cd ${_workdir}
   output=`rm -rf ${_workdir}${_package}_temp`
   trap "" 2
   }
   
   
   
   


######################################
# Main
######################################


#
# Examine passed in args
#
numRequiredArgsSatisfied=0
validCommand=$FALSE
lflag=$FALSE
pflag=$FALSE

while getopts :qBvb:l:p: arguments
   do
   case $arguments in 
      q)  quiet=$TRUE;;
      B)  breakAfterReplace=$TRUE;;
      b)  packageList=$OPTARG
          ((numRequiredArgsSatisfied = numRequiredArgsSatisfied + 1));;
      l)  lppNameArg=$OPTARG
          lflag=$TRUE
          ((numRequiredArgsSatisfied = numRequiredArgsSatisfied + 1));;
      p)  pathNameArg=$OPTARG
          pflag=$TRUE
          ((numRequiredArgsSatisfied = numRequiredArgsSatisfied + 1));;
      v)  print "Version $Version"
	  exit 0;;
      :)  print "$USAGE"
	  exit 99;;
      \?) print "$USAGE"
	  exit 99;;
   esac
   done
(( switchPositions = OPTIND - 1 ))
shift $switchPositions

if [[ $lflag = $FALSE ]] && [[ $pflag = $TRUE ]] then
   lppNameArg=$pathNameArg
   ((numRequiredArgsSatisfied = numRequiredArgsSatisfied + 1))
fi

if [[ $validCommand = $FALSE ]] && (( numRequiredArgsSatisfied != 3 )) then
   print "$USAGE"
   exit 99
fi

if [[ $lppNameArg = */* ]] || [[ $pathNameArg = */* ]] then 
   print "chjava: Suffix arguments cannot contain the \"/\" character. \n"
   exit 1
fi

packages=`ls ${packageList}`
if [[ $packages = "" ]] then
   print "chjava: package ${packageList} could not be accessed. \n"
   exit 1
fi   

for pathToPackage in `ls ${packageList}`
   do
   packageType="update"
   licenseFileset=$FALSE
   msgFileset=$FALSE
   javaFileset=$FALSE
   tempOsummary=""
   tempNsummary=""
   
   # Check for package existance and type
   if [[ ! -f $pathToPackage ]] then
      print "chjava: package ${pathToPackage} could not be accessed or is not a regular file. \n"
      exit 1
   fi
   output=`file ${pathToPackage} | grep 'backup/restore' > /dev/null`
   _rc=$?
   if [[ $_rc != 0 ]] then
      print "chjava:package ${pathToPackage} is not a backup/restore file type. \n"
      exit 1
   fi

   if [[ $pathToPackage != "" ]] then
      workdir="${pathToPackage%/*}/"
   fi
   
   if [[ "${pathToPackage}/" = $workdir ]] then
      workdir="./"
   fi
   
   # Check package
   cd $workdir
   workdir=`pwd`"/"
   package=${pathToPackage##*/}
   if [[ -d $pathToPackage ]] then
      print "chjava: package passed in with b flag must be a file."
      exit 1
   fi
   pathToPackage=${workdir}${package}
   
   
   #
   # Break down package
   #
   _breakdownPackage $pathToPackage 
   
   
   # Find type of package install or update
   # and whether this is a license or msg fileset
   while read -r line
      do
      num=0
      for part in $line
         do
         (( num = num + 1 ))
         if (( num == 3 )) then
            if [[ $part = "I" ]] then
               packageType="install"
	    fi
   	 fi
         if (( num == 4 )) then
            if [[ $part = *license* ]] then
               licenseFileset=$TRUE
	       javaFileset=$TRUE
	    fi
            if [[ $part = *msg* ]] then
               msgFileset=$TRUE
	       javaFileset=$TRUE
	    fi
            break 2
   	 fi
         done
      done < ${workdir}${package}_temp/lpp_name
   _print "chjava: package passed in is an ${packageType} type package."

   output=`find ${workdir}${package}_temp/usr/java* >/dev/null 2>&1`
   _rc=$?
   if [[ $_rc = 0 ]] then
      javaFileset=$TRUE
   fi
   
   if [[ $licenseFileset = $TRUE ]] || [[ $msgFileset = $TRUE ]] || [[ $javaFileset = $FALSE ]] then
      output=`rm -rf ${workdir}${package}_temp`
      tempOsummary="Original package: ${package} \n"
      if [[ $licenseFileset = $TRUE ]] then
         tempNsummary="New      package: UNCHANGED license fileset.\n"
      fi
      if [[ $msgFileset = $TRUE ]] then
         tempNsummary="New      package: UNCHANGED message fileset.\n"
      fi
      if [[ $javaFileset = $FALSE ]] then
         tempNsummary="New      package: UNCHANGED non-java fileset.\n"
      fi
   else
      _modifyPackage $pathToPackage $lppNameArg $pathNameArg $packageType
      if [[ $breakAfterReplace = $TRUE ]] then
         exit $rc
      fi   
   
      #
      # Rebuild package
      #
      _rebuildPackage $pathToPackage $packageType $lppNameArg
   fi

Osummary="${Osummary}${tempOsummary}"
Osummary="${Osummary}__________________________________________________\n"
Nsummary="${Nsummary}${tempNsummary}"
Nsummary="${Nsummary}\n"
done

if [[ $rc = "0" ]] then
   print "chjava: Summary:"
   o_text=$Osummary
   n_text=$Nsummary
   while [[ ${#o_text} > 0 ]]
      do
      text="${o_text%%\\n*}"
      print "$text"
      o_text=${o_text#*\\n}
      
      text="${n_text%%\\n*}"
      print "$text"
      n_text=${n_text#*\\n}
      done
   print "\n\n"
   print "chjava: Success"
else
   print "chjava: Failed"
fi
return $rc

cd $OWD > /dev/null


