#!/usr/bin/ksh # IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # bos71S src/bos/usr/sbin/rpm_share/rpm_share.sh 1.5.2.1 # # Licensed Materials - Property of IBM # # COPYRIGHT International Business Machines Corp. 2005,2014 # 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 # @(#)64 1.5.2.1 src/bos/usr/sbin/rpm_share/rpm_share.sh, cmdcorral, bos71S, s2014_32A5 7/30/14 18:27:45 check_space() { typeset ERROR='eval perror 87; return 1' typeset SNODE # source node typeset TNODE # target node typeset FLIST="$1" # file install list typeset DLIST="$2" # dir install list typeset RC=0 typeset SUM=0 typeset SIZE=0 typeset MINSIZE=16 [[ -z $FLIST || -z $DLIST ]] && $ERROR check_file $FLIST || $ERROR check_file $DLIST || $ERROR # Do the files. while read SNODE; do TNODE=${RPM_INST_ROOT}${SNODE} if [[ -L $SNODE && ! -L $TNODE ]]; then (( SUM = $SUM + $MINSIZE )) continue fi # If the target node exists AND is closed, subtract its space. if [[ -f $TNODE ]]; then isfopen $TNODE if [[ $? -eq 0 ]]; then SIZE=$(getfsize "$TNODE") || $ERROR (( SUM = $SUM - $SIZE )) fi fi SIZE=$(getfsize "$SNODE") || $ERROR (( SUM = $SUM + $SIZE )) done < $FLIST # Do the dirs while read SNODE; do TNODE=${RPM_INST_ROOT}${SNODE} [[ -d $SNODE && ! -d $TNODE ]] && (( SUM = $SUM + $MINSIZE )) done < $DLIST # Finalize the SUM, add a small buffer [[ $SUM -le 0 ]] && SUM=$MINSIZE addbuf SUM 5 $MINSIZE || $ERROR # Check the space. ck_exp_fs "$RPM_INST_ROOT" "$SUM" || $ERROR return 0 } # end of check_space() remove_files() { typeset ERROR='eval pmerror "remove_files()"; return 1' typeset NODE typeset RIR_NODE typeset CUR_LIST="$1" # current list typeset KEEP_LIST="$2" # keep list typeset RC=0 [[ -z $KEEP_LIST || -z $CUR_LIST ]] && $ERROR check_file $KEEP_LIST || $ERROR check_file $CUR_LIST || $ERROR while read RIR_NODE; do [[ ! -f $RIR_NODE && ! -L $RIR_NODE ]] && continue NODE=${RIR_NODE#*$RPM_INST_ROOT} RC=$(inlistf "$NODE" "$KEEP_LIST") || $ERROR case $RC in 1) # in the RPM databse, do nothing : ;; 0) # Not in the RPM database, remove $RM -f ${RIR_NODE} >/dev/null 2>&1 ;; *) $ERROR ;; esac done < $CUR_LIST return 0 } # end of remove_files() remove_dirs() { typeset ERROR='eval pmerror "remove_dirs()"; return 1' typeset NODE typeset RIR_NODE typeset CUR_LIST="$1" # current list typeset KEEP_LIST="$2" # keep list typeset RC=0 [[ -z $KEEP_LIST || -z $CUR_LIST ]] && $ERROR check_file $KEEP_LIST || $ERROR check_file $CUR_LIST || $ERROR while read RIR_NODE; do [[ ! -d $RIR_NODE || "$RIR_NODE" = "$RPM_INST_ROOT" ]] && continue NODE=${RIR_NODE#*$RPM_INST_ROOT} RC=$(inlistf "$NODE" "$KEEP_LIST") || $ERROR case $RC in 1) # in the RPM databse, do nothing : ;; 0) # Not in the RPM database, remove $RMDIR ${RIR_NODE} >/dev/null 2>&1 ;; *) $ERROR ;; esac done < $CUR_LIST return 0 } # end of remove_dirs() RPM_RC_EXIT() { cleanup exit "$RPM_RC" } # end of RPM_RC_EXIT() FAIL() { cleanup exit 1 } # end of FAIL() cleanup() { [[ -d $WORKDIR ]] && $RM -rf $WORKDIR } # end of cleanup() set_time_token() { typeset ERROR='eval pmerror "set_time_token()"; return 1' TIMETOKEN=${WORKDIR}/timetoken.$$.${RANDOM} > $TIMETOKEN || $ERROR check_file $TIMETOKEN || $ERROR ############################################################ ## Next, make sure the dates are reasonable by ## 1) Check that the current TIMETOKEN is not older ## than RPM_PACKAGES (dates messed up) ## 2) Test the rpm database lock. ## 3) Correct #2 if necessary. ############################################################ # If the dates are reasonable, we are done [[ $TIMETOKEN -nt $RPM_PACKAGES ]] && return 0 # Is another rpm install running? $RRPM -qa >/dev/null || $ERROR # Make the time correction. $TOUCH $RPM_PACKAGES $TIMETOKEN || $ERROR return 0 } # end of set_time_token() update_inst_root() { typeset ERROR='eval pmerror "update_inst_root()"; return 1' typeset NODE typeset RIR_NODE # RPM inst_root node typeset RC=0 ############################################################ ## Data files. ############################################################ export OACLFILE=${WORKDIR}/oaclfile.$$.${RANDOM} typeset RPM_DB_LIST=${WORKDIR}/rpm_db_list.$$.${RANDOM} typeset RIR_FILES=${WORKDIR}/rir_files.$$.${RANDOM} typeset RIR_DIRS=${WORKDIR}/rir_dirs.$$.${RANDOM} typeset FILE_ILIST=${WORKDIR}/fileilist.$$.${RANDOM} typeset DIR_ILIST=${WORKDIR}/dirilist.$$.${RANDOM} $RM -f $RPM_DB_LIST $RIR_FILES $RIR_DIRS $OACLFILE \ $FILE_ILIST $DIR_ILIST ############################################################ ## Ensure that $RPM_INST_ROOT exists and set the OACLFILE ## file variable. ############################################################ if [[ ! -d $RPM_INST_ROOT ]]; then $MKDIR -m 700 $RPM_INST_ROOT || $ERROR fi ############################################################ ## If inurid has run we do not need to save any files. ## To be safe we also blast the entire directory. ############################################################ $INURID -q >/dev/null 2>&1 if [[ $? -eq 1 ]]; then $RM -rf $RPM_INST_ROOT/* $TOUCH $RPM_INST_ROOT_INV return 0 fi ############################################################ ## Invalidate the current inventory list. ############################################################\ $RM -f $RPM_INST_ROOT_INV ############################################################ ## Create the rpm inst_root list. ############################################################ get_rpm_inst_root_list > $RPM_DB_LIST || $ERROR ############################################################ ## Create the list of RPM inst_root files. ############################################################ $FIND $RPM_INST_ROOT -xdev -type f -o -type l > $RIR_FILES || $ERROR ############################################################ ## Create the list of RPM inst_root dirs. ############################################################ $FIND $RPM_INST_ROOT -xdev -type d -o -type l > $RIR_DIRS || $ERROR revflines $RIR_DIRS || $ERROR ############################################################ ## Now remove anyhing in $RPM_INST_ROOT that is no longer ## in the RPM database. ############################################################ remove_files "$RIR_FILES" "$RPM_DB_LIST" || $ERROR remove_dirs "$RIR_DIRS" "$RPM_DB_LIST" || $ERROR ############################################################ ## Create the file and directory install lists. ############################################################ > $FILE_ILIST || $ERROR > $DIR_ILIST || $ERROR while read NODE; do RIR_NODE=${RPM_INST_ROOT}${NODE} if [[ -d $NODE && ! -d $RIR_NODE ]]; then echo "$NODE" >> $DIR_ILIST || $ERROR continue fi if [[ -f $NODE ]]; then if [[ ! -f $RIR_NODE || $NODE -nt $RIR_NODE ]]; then echo "$NODE" >> $FILE_ILIST || $ERROR continue fi fi done < $RPM_DB_LIST ############################################################ ## Make sure we have enough space to do the copy. ############################################################ check_space "$FILE_ILIST" "$DIR_ILIST" || $ERROR ############################################################ ## Lets update the directories first. ############################################################ while read NODE; do update_dir "$NODE" || $ERROR done < $DIR_ILIST ############################################################ ## Finally, update the files. ############################################################ while read NODE; do update_file "$NODE" || $ERROR done < $FILE_ILIST ############################################################ ## Update RPM_INST_ROOT_INV with the latest data ############################################################ check_fdup_space $RPM_DB_LIST 20 $RPM_INST_ROOT || $ERROR $CP $RPM_DB_LIST $RPM_INST_ROOT_INV || $ERROR $RM -f $RPM_DB_LIST $RIR_FILES $RIR_DIRS $OACLFILE \ $FILE_ILIST $DIR_ILIST return 0 } # end of update_inst_root() update_dir() { typeset ERROR='eval pmerror "update_dir()"; return 1' typeset ORIGDIR="$1" # original dir (to be copied) typeset NEWDIR # new dir (to be created) typeset PORIGDIR # parent dir of ORIGDIR typeset PNEWDIR # parent dir of NEWDIR # Check input parameters. [[ -n $ORIGDIR ]] || $ERROR NEWDIR=${RPM_INST_ROOT}${ORIGDIR} [[ -d "$NEWDIR" ]] && return 0 # no work to do check_dir $ORIGDIR || $ERROR ############################################################ ## Establish the parent dirs. ############################################################ PORIGDIR=$(getpdir $ORIGDIR) || $ERROR check_dir ${PORIGDIR} || $ERROR PNEWDIR=${RPM_INST_ROOT}${PORIGDIR} ############################################################ ## Does the new parent dir exist ? If yes, we are ready to ## do the update. If not, create it via recursive call. ## Note: ksh does not support more than 128 levels of ## recursion. ############################################################ if [[ ! -d "$PNEWDIR" ]]; then # create the parent directory update_dir "$PORIGDIR" || $ERROR fi # create the new dir if [[ -L "$ORIGDIR" ]]; then $RM -f $NEWDIR $CP -fph $ORIGDIR $NEWDIR || $ERROR else $MKDIR $NEWDIR || $ERROR fi # update the new dir's ownership and ACLs update_operms "$ORIGDIR" "$NEWDIR" || $ERROR return 0 } # end of update_dir() update_file() { typeset ERROR='eval pmerror "update_file()"; return 1' typeset ORIGFILE="$1" # original file (to be copied) typeset NEWFILE # new file (to be created) typeset PORIGDIR # parent dir of orig file # Check input parameters. [[ -z $ORIGFILE ]] && $ERROR NEWFILE=${RPM_INST_ROOT}${ORIGFILE} check_file "$ORIGFILE" || $ERROR ############################################################ ## Establish the parent dirs. ############################################################ PORIGDIR=$(getpdir $ORIGFILE) || $ERROR check_dir ${PORIGDIR} || $ERROR PNEWDIR=${RPM_INST_ROOT}${PORIGDIR} ############################################################ ## If the new parent dir does not exist, create it. ############################################################ if [[ ! -d "$PNEWDIR" ]]; then # create the parent directory update_dir "$PORIGDIR" || $ERROR fi ############################################################ ## Copy the file and update ownership + ACLs ############################################################ # Do the copy [[ -L $NEWFILE ]] && $RM -f $NEWFILE $CP -fph "$ORIGFILE" "$NEWFILE" || $ERROR # Update ownership + ACLs update_operms "$ORIGFILE" "$NEWFILE" || $ERROR return 0 } # end of update_file() ######################################################################## ## main MAIN Main ######################################################################## # Unset potential trouble makers unset BASH_ENV unset CDPATH unset ENV unset IFS unalias -a export PLATFORM=AIX export WORKDIR="" export TIMETOKEN="" export OACLFILE="" export RPM_RC=0 export EXP_REQUESTED=0 export BASELIB=/usr/lib/instl/baselib_sh export USER_POSIXLY_CORRECT="$POSIXLY_CORRECT" export SYNCROOT=/usr/sbin/syncroot export INURID=/usr/lib/instl/inurid [[ -n $INUBOSTYPE ]] && EXP_REQUESTED=1 # Set a trap to cleanup all temp files. trap 'cleanup' EXIT trap 'FAIL' 1 2 3 4 5 6 7 8 10 11 12 13 14 15 18 30 31 . $BASELIB || exit 1 if [[ -n "$RPM_SHARE_DEBUG" ]]; then set -x typeset F for F in $(typeset +f); do typeset -ft $F; done fi # Initialize CISAL methods init_baselib "rpm_share" || FAIL # Check for minimal work space ck_exp_fs ${WORKDIR} 1024 || FAIL ck_exp_fs ${OPTFS} 2048 || FAIL # Sync only? if [[ -n $RPM_SHARE_SYNCNOW ]]; then update_inst_root || FAIL cleanup exit 0 fi # Set the time token. set_time_token || FAIL # Turn off posix enforcement activated by init_baselib(), # unless the user asked for it. [[ -z $USER_POSIXLY_CORRECT ]] && unset POSIXLY_CORRECT # Execute the rpm command $RRPM "$@" RPM_RC=$? ############################################################ ## Did a change to the rpm database take place? If it did ## not, we are done. ############################################################ [[ $TIMETOKEN -nt $RPM_PACKAGES ]] && RPM_RC_EXIT ############################################################ ## Update $RPM_INST_ROOT root with any changes. ############################################################ update_inst_root || FAIL RPM_RC_EXIT