#!/bin/ksh # IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # bos720 src/bos/usr/lib/nim/methods/c_update.sh 1.3.1.5 # # Licensed Materials - Property of IBM # # Restricted Materials of IBM # # COPYRIGHT International Business Machines Corp. 2002,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 # @(#)32 1.3.1.5 src/bos/usr/lib/nim/methods/c_update.sh, cmdnim, bos720 9/26/05 15:38:48 # # COMPONENT_NAME: CMDNIM # # FUNCTIONS: ./usr/lib/nim/methods/c_update.sh # # ORIGINS: 27 # # # (C) COPYRIGHT International Business Machines Corp. 2002 # All Rights Reserved # Licensed Materials - Property of IBM # US Government Users Restricted Rights - Use, duplication or # disclosure restricted by GSA ADP Schedule Contract with IBM Corp. # # include common NIM shell defines/functions NIMPATH=${0%/*} NIMPATH=${NIMPATH%/*} [[ ${NIMPATH} = ${0} ]] && NIMPATH=/usr/lpp/bos.sysmgt/nim NIM_METHODS="${NIMPATH}/methods" . ${NIM_METHODS}/c_sh_lib #---------------------------- local defines -------------------------------- #---------------------------- module globals -------------------------------- REQUIRED_ATTRS="location" OPTIONAL_ATTRS="source packages mount_opts rm_images installp_bundle gencopy_flags show_progress" location="" source="" packages="" installp_bundle="" gencopy_flags="" src_access="" show_progress="" #---------------------------- prep_source -------------------------------- # # NAME: prep_source # # FUNCTION: # prepares the source of the LPP images for use # # EXECUTION ENVIRONMENT: # # NOTES: # calls error on failure # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # source = source of LPP images # global: # access_pnt = local access point; declared in c_sh_lib # initialized in nim_mount function # # RETURNS: (int) # 0 = success # # OUTPUT: #------------------------------------------------------------------------------- function prep_source { typeset source=${1} # what kind of source? case ${source} in /dev/cd+([0-9])) # source is CDROM; pass the device to gencopy src_access=${source} ;; /dev/rmt+([0-9])) # source is tape; nothing to do because gencopy handles block size src_access=${source} ;; *) # assume source is a directory; make sure we've got local access nim_mount ${source} src_access=${access_pnt} ;; esac } # end of prep_source #---------------------- convert_packages_to_filenames -------------------------- # # NAME: convert_packages_to_filenames # # FUNCTION: # creates a list of file names based on package/fileset [level] names. # this removes prefixes. # # EXECUTION ENVIRONMENT: # # NOTES: # calls error on failure # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # location = location of packages (directory of lpp_source) # global: # packages = list of packages with optional levels # installp_bundle = bundle file with list of packages # bundle_access = local access point for installp bundle file # # RETURNS: (int) # 0 = success # 1 = failure # # OUTPUT: # stores the list of filenames in ${TMPDIR}/file_names.list # #------------------------------------------------------------------------------- function convert_packages_to_filenames { # parameters typeset location=${1} # local variables typeset i= # loop variable typeset -i index=0 # number of packages typeset -i k=1 # loop variable; the arrays start at index 1 typeset new_packages= # array of parsed package_names from packages typeset levels= # array of parsed levels from packages typeset found_file= # file name that matched output from gencopy -L typeset not_found= # list of files not found or can't delete # if an installp bundle is used, store the contents of the file in packages if [[ -n ${installp_bundle} ]] then packages="$( ${CAT} ${bundle_access} | ${AWK} '$0 !~ /#/ { print $0 }' )" [[ -z ${packages} ]] && error ${ERR_BUNDLE_FILE} ${bundle_access} fi # convert the list of packages/filesets with levels to file_names. # the expected input is a list of package names with corresponding # levels optional (i.e. bos.net 5.1.0.25 perl.rte bos 5.1.0.10 ...) # determine if there is a level associated with each package name # store the list of packages in the array new_packages and # store the list of associated package levels in the array levels # also remove any prefixes on the packages i.e. "R:cdrecord" for i in ${packages} do # is this a V.R.M.F level (i.e. 5.1.0.25) if [[ ${i} = [1-9].[0-9].[0-9].+([0-9])* ]] then # yes, store in the array of levels levels[$index]="${i}" else # not a level, must be a package name (( index = index + 1 )) # remove any prefixes (i.e. 'J:' or 'U:') for ISJE and UDI packages new_packages[$index]="${i##*:}" levels[$index]="" fi done # store the output from 'gencopy -L -d location' in TMPDIR/gencopy.list # the output of 'gencopy -L' is "file_name:package:fileset:v.r.m.f:*" ${GENCOPY} -L -d ${location} >${TMPDIR}/gencopy.list 2>${ERR} || \ err_from_cmd ${GENCOPY} # get a list of file_names from the specified packages and store the list # in TMPDIR/file_names.list >${TMPDIR}/file_names.list while (( k <= index )) do # was a level specified for this package? if [[ -n ${levels[$k]} ]] then # if the user specified name matches the package name or matches # the fileset name of an update image from the gencopy -L output # and the levels match, then print the file_name found_file=$( ${AWK} 'BEGIN { FS=":" } \ ($2 == name || ($3 == name && $5 !~ /[IRJP]/)) && $4 == level { print $1 }' \ name=${new_packages[$k]} level=${levels[$k]} ${TMPDIR}/gencopy.list 2>${ERR} ) [[ $? -ne 0 ]] && err_from_cmd ${AWK} if [[ -n $found_file ]]; then ${ECHO} "$found_file" >>${TMPDIR}/file_names.list else not_found="${not_found}\t${new_packages[$k]} ${levels[$k]}\n" fi else # if the user specified name matches the package name or matches # the fileset name of an update image from the gencopy -L output, # then print the file_name found_file=$( ${AWK} 'BEGIN { FS=":" } \ ($2 == name || ($3 == name && $5 !~ /[IRJP]/)) { print $1 }' \ name=${new_packages[$k]} ${TMPDIR}/gencopy.list 2>${ERR} ) [[ $? -ne 0 ]] && err_from_cmd ${AWK} if [[ -n $found_file ]]; then ${ECHO} "$found_file" >>${TMPDIR}/file_names.list else not_found="${not_found}\t${new_packages[$k]}\n" fi fi found_file= (( k = k + 1 )) done if [[ -n ${not_found} ]] then warning ${ERR_CANT_RM_FILESETS} "$( echo ${not_found} )" fi # success return 0 } # end of convert_packages_to_filenames #---------------------------- update_lpp_source -------------------------------- # # NAME: update_lpp_source # # FUNCTION: # adds or removes packages to or from an existing lpp_source using gencopy # # EXECUTION ENVIRONMENT: # # NOTES: # 1) the list of packages MUST be acceptable for gencopy # 2) calls error on failure # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # global: # location = location of target lpp_source # packages = list of packages to be added or removed # installp_bundle = bundle file with list of packages # bundle_access = local access point for installp bundle file # src_access = local access point for source of LPP images # # RETURNS: (int) # 0 = success # 1 = failure # # OUTPUT: #------------------------------------------------------------------------------- function update_lpp_source { # local variables typeset i= # loop variable typeset k= # loop variable typeset rm_list= # list of removed files typeset -i file_found=0 # set to 1 if a file is found typeset show_gencopy_output="-bv" # print copied files typeset show_rm_output="-e" # print removed files if [[ $show_progress = "no" ]] then show_gencopy_output="" show_rm_output="" fi # determine if this is an addition or removal of packages if [[ -n ${rm_images} ]] then # REMOVAL # convert the list of packages/filesets with levels to file_names # this function stores the list in TMPDIR/file_names.list convert_packages_to_filenames ${location} # ensure the list of filenames was created [[ ! -s ${TMPDIR}/file_names.list ]] && \ error ${ERR_FINDING_PACKAGES} ${location} "${packages}" # remove the files from the location for i in $( ${CAT} ${TMPDIR}/file_names.list ) do if [[ "${rm_list}" = *"\t${i}\n"* ]] then # already removed, so continue continue fi # Do a find to locate the file since it may be in any number # of subdirectories. While only one file should be found, do # a for loop in case the file is in multiple locations. for k in $( ${FIND} ${location} -name ${i} ) do if [[ -s ${k} ]] then # run RM with the -r flag to handle ismp directories # RM sends all output to stderr, capture stderr and # display it if there was no error and show_progress is yes ${RM} -r ${show_rm_output} ${k} 2>&1 >${TMPDIR}/rm.out if [[ $? != 0 ]]; then ${CP} ${TMPDIR}/rm.out ${ERR} err_from_cmd ${RM} else [[ $show_progress != "no" ]] && ${CAT} ${TMPDIR}/rm.out fi file_found=1 fi done if [[ $file_found -eq 1 ]] then # file was found; add to list of remove packages rm_list="${rm_list}\t${i}\n" else # warning - unable to find the file warning ${ERR_FILE_NOT_FND} ${i} ${location} fi file_found=0 done # NOTE: do not rebuild the .toc since M_UPDATE will call # check_lpp_source and this function will rebuild the .toc else # ADDITION # if packages is a file, then pass the file to gencopy with -f [[ -n ${installp_bundle} ]] && packages="-f ${bundle_access}" # use gencopy to copy the filesets from the source to the target # NOTE: gencopy will update the .toc file ${GENCOPY} ${gencopy_flags} ${show_gencopy_output} -t ${location} \ -d ${src_access} ${packages} 2>${ERR} || \ err_from_cmd ${GENCOPY} fi # SUCCESS return 0 } # end of update_lpp_source #----------------------------------- c_update ---------------------------------- # # NAME: c_update # # FUNCTION: # updates an lpp_source type NIM resource # # EXECUTION ENVIRONMENT: # # NOTES: # calls error on failure # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # global: # # RETURNS: (int) # 0 = success # 1 = failure # # OUTPUT: #------------------------------------------------------------------------------- # signal processing trap cleanup 0 trap err_signal 1 2 11 15 # NIM initialization nim_init # initialize local variables typeset c="" # set parameters from command line while getopts :a:qv c do case ${c} in a) # validate the attr ass parse_attr_ass "${OPTARG}" # include the assignment for use in this environment eval ${variable}=\"${value}\" ;; q) # show attr info cmd_what exit 0 ;; v) # verbose mode (for debugging) set -x for i in $(typeset +f) do typeset -ft $i done ;; \?) # unknown option error ${ERR_BAD_OPT} ${OPTARG} ;; esac done # need to ensure the location attribute was specified ck_attrs # set default flags for gencopy gencopy_flags=${gencopy_flags:-${DEFAULT_GENCOPY_FLAGS}} gencopy_flags=$( ck_gencopy_flags "${gencopy_flags}" ) # don't check for errors, since this should have been done in m_update # ensure that the location is a directory and a JFS or JFS2 filesystem; # we cannot update a CDROM filesystem ${C_STAT} -a location=${location} -a vfstype="0 3" -a no_error_msg="yes" \ 2>/dev/null || error ${ERR_INCORRECT_FS} ${location} # if this is an addition, prepare the source if [[ -n ${source} ]] then # if a source was specified, prepare the source device for use # NOTE: this function will set the global variable src_access prep_source ${source} fi # if a bundle file is used, prepare the bundle if [[ -n "${installp_bundle}" ]] then # setup local access prep_bundle fi # update the lpp_source update_lpp_source # finished exit 0