bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Syntax Question...


From: Linda Walsh
Subject: Re: Syntax Question...
Date: Mon, 15 Aug 2011 00:45:58 -0700
User-agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.8.1.24) Gecko/20100228 Thunderbird/2.0.0.24 Mnenhy/0.7.6.666




` Linda Walsh wrote:

The latest error I got is a a simple type -- most of them probably are, with that many lines of code in ~3-4 weeks, there's bound to be -- trouble is I'm stubborn sometimes about 'punishing myself'' when I mess up...which isn't always productive! ;-)
Sometimes typo's used to work -- i.e. sometimes characters get
randomly deleted out of my source files --

Win7 drops keys randomly, and I don't always notice the effects....

anyway, you wanted....

I wouldn't regard them as a finished product...


#!/bin/bash -exu

# copyright(c) Linda Walsh 2011 ;
# create_snap_rdiff Version: 0.1; initial writing
# indended for eventual gnuish-open source license


#set -xuhmeB

export GLOBAL_SET_OPS="${-:-}"
shopt -s expand_aliases extglob shift_verbose xpg_echo
export 
PS4='>>${BASH_SOURCE:+${BASH_SOURCE[0]}}#${LINENO}${FUNCNAME:+(${FUNCNAME[0]})}>
 '
this="create_snap_rdiff"

progpath="$0"
prog="${progpath##*/}"
progdir="${progpath%/*}"
export progpid=$$

#base_mp="/home"
shopt -s expand_aliases extglob

alias sub=function
alias unless='if !'
typeset -xr sub unless

declare -a SAVE_ARGS=( "$@" )
typeset -xr snapdir='snapdir'

# in shell: white is black and black is white:
export b_false=1
export b_true=0
export Debug=$b_false  Verbose=$b_true  Silent=$b_false
export Quiet=$b_false  Force=""  loglevel=7
export base_mp=""

. "$progdir/snaplib.sh"
read progdir prog path export_blob <<<$(env_init "$progdir" "$prog" "$this")
export PATH="$path"
eval "$export_blob"

#echo "progdir=$progdir, prog=$prog, path=$path"
#echo "exportblob"

export PATH="$path"
eval "$export_blob"


if [[ $#<1 ]]; then 
        errx 50 "Need mount_path of fs to create snap_rdiff from"
fi

set "${SAVE_ARGS[@]}"

declare -a args
declare -a blob

function process_args { # {{{
        DebugPush ProcArgs
        args=( "${@}" )
        local -i argi=0
        # Arg Processing...
        while (($#>0)); do
                a="$1";shift;
                if [[ $a == "-v" || $a == "--verbose" ]]; then
                        ((Verbose=b_true,loglevel<6?loglevel=6:0,0))
                elif [[ $a == "-d" || $a == "--debug" ]]; then
                        echo "Debug Set"
                        ((Debug=b_true,loglevel<7?loglevel=7:0,0))
                elif [[ $a == "-f" ]] ; then
                        Force="$a";shift;continue;
                elif [[ $a =~ ^--force=.* ]]; then 
                        Force="${a#*=}"
                elif [[ $a == "--quiet" ]]; then
                        ((Quiet=b_true,loglevel>2?loglevel=2:0,0))
                elif [[ $a == "--silent" ]]; then
                        ((Silent=b_true,loglevel=0))
                elif [[ $a =~ --?.* ]]; then
                        { echo "Unknown option \"$a\", use --help for help"; } 
>&1
                        exit -1
                else
                        args[$argi]="$a"
                        ((++argi))
                fi
        done
        if [[ ${#args[*]} -ge 1 ]]; then
                echo -e "${args[@]}"
        else
                echo
        fi
        if [[ -z "$base_mp" && ${#args[*]}<1 ]]; then 
                errx 51 "Need mount_path of fs to create snap_rdiff from"
        fi
        DebugPop
}

args=( $(process_args "$@" ) )
set ${args[@]}

### allowed 'features' (to be set/queried, must be defined 1st)
# (to prevent feature-misnaming/mispelling)
#

def_Provide base_mp base_vg base_lv base_mp_diff
def_Provide clean_diff_dir
def_Provide daily_snap
def_Provide empty_snapvol
def_Provide filled_snapvol
def_Provide formatted_snapvol full_diff_dir
def_Provide labeled_diff_dir
def_Provide new_snapshot_wanted
def_Provide osnap_mp osnap_vg osnap_lv osnap_devpath
#def_Provide oldest_active_snapshot osnap_mp osnap_vg osnap_lv osnap_devpath
def_Provide oldest_active_snapshot
def_Provide root_dev
def_Provide snap_vol snap_mp snap_mp_dir snap_copy_complete



## provides base_mp
base_mp="${1:?}"
add_provides "base_mp"

#}}}

#devel options
export i_skip_mnt_clean_diff_dir=0
export i_skip_rsync=0
export i_skip_today_check=0
export i_skip_vol_create=0
export i_skip_new_snap=0



#needed init
##
## provides base_vg base_lv root_dev
##
read base_vg base_lv <<<$(get_vg_lv_from_mp "$base_mp")
root_dev="$(get_devnum / )"
verb "root_dev=$root_dev, base_vg=$base_vg, base_lv=$base_lv"
add_provides "base_vg" "base_lv" "root_dev"




##
## provides: new_snapshot_wanted
## requires: base_mp
## May-use:  Force
##
# won't return unless override is set or no backup today
((i_skip_today_check)) || {
        if have_dep "base_mp"; then
                chk_today_snap "$base_mp" "$Force"
                add_provides "new_snapshot_wanted"
        fi      
}



base_mp_diff="$base_mp.diff"
add_provides base_mp_diff






# Attempt to read snap-label info set after a successful rsync
read osnap_mp osnap_vg osnap_devpath <<<$(find_unsaved_snap_data 
"$base_mp_diff")
if [[ ${osnap_mp:-} && ${osnap_vg:-} && ${osnap_devpath:-} ]]; then
        osnap_vg="$(getVG_by_MntDir "$osnap_devpath")" && {
                add_provides osnap_vg
        }
        add_provides labeled_diff_dir
        add_provides full_diff_dir
        add_provides osnap_mp osnap_lv osnap_devpath
        ## now check to see if this diff has been copied to corresponding 
snapdir!
        check_snap_copy_complete "$osnap_mp"
fi




if ! have_dep labeled_diff_dir || have_dep snap_copy_complete   ; then
        # if doesn't exist we clean the 'diff' vol, and generate a new one 
        # using 'rsync'

        # clean diff dir
        ##
        ## provides: clean_diff_dir
        ## depends: !unsaved_snap_data_check
        ## removes: full_diff_dir
        ##
        ((!i_skip_mnt_clean_diff_dir)) && {
        if ( ! have_dep "labeled_diff_dir" || have_dep snap_copy_complete ) ; 
then
                        mnt_n_clean_diff_dir "$base_mp_diff" && {
                                add_provides "clean_diff_dir"
                                rm_provides "full_diff_dir"
                        }
                fi
        }

        # find oldest active snapshot
        ##
        ## provides: oldest_active_snapshot
        ## provides: osnap_mp osnap_vg osnap_lv osnap_devpath
        ##
        unset osnap_mp osnap_vg osnap_lv
        read osnap_mp osnap_vg osnap_lv osnap_devpath \
                                <<<$( find_oactv_snapshot "$base_lv" )
        if [[ ${osnap_mp:-} && ${osnap_vg:-} && ${osnap_lv:-} ]]; then
                add_provides "oldest_active_snapshot"
                add_provides "osnap_mp" "osnap_vg" "osnap_lv" "osnap_devpath"
        fi
        check_snap_copy_complete "${osnap_mp:-}"
        
        msg_level $_Info_ && {
                if have_dep snap_copy_complete; then
                        info "Have snap_copy_complete"
                else
                        info "snap_copy_complete is not set"
                fi      
        }


        ##
        ## provides: daily_snap
        ## depends: base_mp 
        ##
        if ((!i_skip_new_snap)); then 
                if have_dep "base_mp" "new_snapshot_wanted"; then
                        create_basemp_snap "$base_mp" && {
                                add_provides "daily_snap"
                                rm_provides "new_snapshot_wanted"
                        }
                fi
        fi


        
        ##
        ## create diff vol
        ##
        ## provides: full_diff_dir
        ## provides: labeled_diff_dir
        ## Depends: osnap_mp osnap_vg osnap_vg
        ##
        if ((!i_skip_rsync)) ; then
                if have_dep -v osnap_mp base_mp base_mp_diff ; then

                        # note, '**' must be quoted so bash's globstar won't 
expand it
                        declare -a exclude_pats=(       
                                "--exclude='.recycle/**'"                       
        "--exclude='BLISS/law/**'" 
                                "--exclude='BLISS/athenae/**'"  
"--exclude='BLISS/law.V2/**'"
                                "--exclude='BLISS/martin/**'"           
                                "--exclude='CPAN-ishtar-build-cache/**'" )
                
                        rsync_snapdiffs_to_base_mp_diff \
                         '\rsync_snapdiffs_to_base_callback' \
                         "$osnap_mp/." "$base_mp_diff"                  \
                         "$base_mp"  "${exclude_pats[@]}" && {
                                add_provides "full_diff_dir"
                        }
                fi
        fi
                                        

        

        ## write label on diff-vol if rdiff finished ok
        ##
        ## write_osnap_identifier_file
        ## Provides: labeled diff dir"
        ## Depsends: base_mp_diff full_diff_dir osnap_mp osnap_lv osnap_devpath
        ##
        if have_dep -v base_mp_diff full_diff_dir osnap_mp osnap_lv 
osnap_devpath; 
                then
                write_osnap_identifier_file \
                        "$base_mp_diff" "$osnap_mp" "$osnap_lv" 
"$osnap_devpath" && {
                        add_provides "labeled_diff_dir"
                }
        fi




        ## if have labeled_diffdir, then delete snapshot it came from
        ##
        ## destroy_old_snapshot_by_mp_n_devpath
        ## Provides: 
        ## Depends: labeled_diff_dir oldest_active_snapshot
        ## Deletes:
        if -v have_dep labeled_diff_dir osnap_mp osnap_devpath; then
                destroy_old_snapshot_by_mp_n_devpath "$osnap_mp" 
"$osnap_devpath" && {
                        rm_provides "oldest_active_snapshot"
                }
        fi      


### Getting here means we have a 'diff' vol that we need to move
### to a downwardly sized static vol that will contain the diff
### (a static snap)


##
## provides snap_vol
## provides osnap_devpath
## requires base_mp_diff base_vg osnap_lv osnap_vg
##
if have_dep -v base_mp_diff base_vg osnap_lv osnap_vg ;then 
        nextents="$(get_nextents_for_space_on_vg_w_minfree  \
                                                        "$base_mp_diff" 
"$base_vg" 10 )"
        $_sudo  $_lvcreate -l $nextents -r 256 -n "$osnap_lv"  "$osnap_vg" && {
                add_provides snap_vol
                osnap_devpath="/dev/$osnap_vg/$osnap_lv"
                add_provides osnap_devpath
        }
fi




## provides xfs_fs_for_oldest_snap_dir
## depends-on: oldest_snap_dir_lv
if have_dep osnap_lv base_lv osnap_devpath; then 
        osnap_xfs_label="${osnap_lv#"$base_lv-20"}"
        $_sudo make_xfs_snap_archive_vol \
                "${osnap_xfs_label:0:11}" "$osnap_devpath" && {
                add_provides empty_snapvol
                add_provides formatted_snapvol
        }
fi




## requires: base_mp base_lv osnap_lv 
## provides snap_mp
if have_dep base_mp base_lv osnap_lv; then
        obase_mp="/o${base_mp#/}"
        datedir="${osnap_lv#$base_lv-}"
        snap_mp="$base_mp/$snapdir/@GMT-$datedir"
        add_provides snap_mp
        if [[ -e $snap_mp ]]; then
                if [[ -d $snap_mp ]]; then 
                        if mp_dev_is_not_same_as_2nd_fs $snap_mp 
$base_mp/$snapdir; then
                                $_umount $snap_mp || 
                                        errx 54 "something mounted at $snap_mp 
and won't unmount"
                        fi      
                        $_sudo $_rmdir $snap_mp || {
                                errx 55 "won't mount on non-empty dir at 
$snap_mp"
                        }
                else 
                        if [[ $Force =~ rm_osnapdir_contents ]]; then
                                $rm -fr $snap_mp
                        fi
                        if [[ -e $snap_mp ]]; then
                                errx 52 "$snap_mp is either not a dir, or can't 
be removed"
                        fi
                fi
        fi
fi



## provides: snap_mp_dir
## requires: snap_mp
have_dep snap_mp && $_sudo mkdir $snap_mp && {
        add_provides snap_mp_dir
} || errx 56 "Can't create mount point $snap_mp"




#provides mounted_new_snap
#depends: snap_mp_dir formatted_snapvol
if have_dep snap_mp_dir formatted_snapvol osnap_devpath snap_mp; then
        $_sudo $_mount $osnap_devpath $snap_mp && {
                add_provides mounted_snapvol
        }
fi

if have_dep snap_mp; then 
        check_snap_copy_complete "$snap_mp"
fi
                
## provides: snap_copy_complete
## requires: mounted_new_snap

if have_dep base_mp_diff snap_mp; then
        if ! have_dep snap_copy_complete; then 
                $_sudo $_cp -a $base_mp_diff/. $snap_mp/. && {
                        $_sudo $_touch "$snap_mp/snap_copy_complete"
                        add_provides snap_copy_complete
                }
        fi
fi


function check_clean_diff_dir {
        local base_mp_diff="${1:?}"
        [[ -e $base_mp_diff/clean_diff_dir ]] &&
                add_provides clean_diff_dir
}

if have_dep base_mp_diff ; then 
        check_clean_diff_dir "$base_mp_diff"
fi

        
## provides: clean_diff_dir
## requires: snap_copy_complete base_mp_diff

if have_dep snap_copy_complete base_mp_diff;then
        mnt_n_clean_diff_dir "$base_mp_diff" && {
                $_sudo $_touch "$base_mp_diff/clean_diff_dir"
                add_provides clean_diff_dir
        }
fi

fi

# vim: ts=2 sw=2 fdm=marker fen number
#!/bin/bash 
#
# tracing active for now...

# today_has_snap: 0.1 initial writing,
# support routine for 'create_snap_rdiff'
# copyright (c) 2011 Linda A. Walsh <la_walsh <at> tlinx <dot> org)
# indended for eventual gnuish-open source license


# return true if today has snap, 
# return non-zero in any failure (including existence of today-snap)

this="today_has_snap"
progpath="$0"
prog="${progpath##*/}"
progdir="${progpath%/*}"
if [[ ${progdir:0:1} != '/' ]]; then
        preprog="$PWD"
        progdir="$preprog/$progdir"
fi

[[ $prog =~ bash ]] && prog="$this"

. "$progdir/snaplib.sh"
read progdir prog path export_blob <<<$(env_init "$progdir" "$prog" "$this")
export PATH="$path"
eval "$export_blob"



if [[ $# < 1 ]]; then
                                echo "$prog: need mount point"
                                exit -2;
fi
Vol="$1"
VG="$(getVG_by_MntDir $Vol)"
LV="$(getLV_by_MntDir $Vol)"

if [[ -z $VG || -z $LV ]]; then 
        echo "$Vol not found (VG=$VG), (LV=$LV)"
        exit -3
fi

SnapDir=snapdir
Dev=/dev/$VG/$LV
Prefix="snapdir/@GMT-"
snap_today="$(date +%Y.%m.%d-)"
snap_prefix="$Vol/$Prefix$snap_today*"
today_snaps="$('ls' -1 ${snap_prefix} 2>/dev/null |tr "\n" " " )"
if [[ -n $today_snaps && $today_snaps != $snap_prefix ]]; then
        echo "yes"
        exit 0
fi
exit 1 
# vim: ts=2 sw=2

#!/bin/bash

# snaplib.sh: 0.1 initial writing,
# support routiens for 'create_snap_rdiff'
# copyright (c) 2011 Linda A. Walsh <la_walsh <at> tlinx <dot> org)
# indended for eventual gnuish-open source license

export SL_progdir"" SL_prog=""

# why re-invent wheel; use syslog msg levels
typeset -xra _Levels_=( Emergency Alert  Critical 
                                                                                
                Error Warn Note Info Verbose )
#
# bash ext-patterns, <op>(content); 
#  <op> := '?' | '*' | '+' | '@' (match one of '|' separted patterns)
#           and '!' (any but one of the '|' separated patterns)
#
typeset -xra _Level_pats=(      'Emerg?(ency)' 'Alert'  'Crit?(ical)' \
                                                                                
                                'Err?(or)' 'Warn?(ing)?' 'Not@(e|ice)'\
                                                                                
                                '       Info' '@(Verbose|Debug?(ing))' )

typeset -ixr _Emerg_=0 _Alert_=1 _Crit_=2 _Error_=3 _Warn_=4 
typeset -ixr _Note_=5 _Info_=6 _Verbose_=7 _Debug_=7

loglevel=$_Debug_

typeset -ix __DEVEL__=${__DEVEL__:-0}

#Progs to get $_prog=path set in the parent ENV:
# Sprogs are ones that probably need 'sudo' to run w/full feature set we need
_Sprogs="bash cp dmsetup find lvcreate lvremove mount rmdir rsync"
_Sprogs="$_Sprogs umount vgchange vgs xargs touch lvs"
export _Progs="stat sudo perl cut grep rm $_Sprogs"
shopt -s expand_aliases extglob
alias sub=function
alias unless='if !'

# bitmask ops, need to be non-overlapping
# note -i attr required for arith eval at assignement
declare -ixr _D_=0
declare -ixr _D_Debug=0x01
declare -ixr _D_ProcArgs=0x02
declare -ixr _D_LowLevel=0x04
declare -ixr _D_Provides=0x08
declare -ixr _D_Define_Provides=0x10
declare -ixr _D_EnvInit=0x20
declare -ixr _D_PLists=0x40

# trace control for subs
declare -ix Trace_off=$((
                                                                                
                _D_Define_Provides      |
                                                                                
                _D_LowLevel                                     |
                                                                                
                _D_Provides                                     |
                                                                                
                _D_Debug                                                |
                                                                                
                _D_ProcArgs                                     |
                                                                                
                _D_ 
                                                                                
        ))

declare -ix Trace_on=$((
                                                                                
                _D_
                                                                                
        ))

                # for setting a local '_Debug' flag in a routine
declare -ix Local_Debug=$((
                                                                                
        _D_
                                                                        ))

alias DebugPop='test -n "$save_ops" && set -$save_ops'
alias DebugPop_preserve_status='local stat=$?;test -n "$save_ops" && { set 
-$save_ops; }; return $stat;'

function DebugPush_helper {
        local dbgflgs="${-:-}";set +x;
        local flag="${1:?}"
        if chkflg Trace_off "$flag";then dbgflgs="${dbgflgs//x/}" ;fi
        if chkflg Trace_on "$flag" ;then dbgflgs="${dbgflgs}x"  ;fi
        if chkflg Local_Debug "$flag" ; then _Debug=1; else _Debug=0; fi
        test -n "$dbgflgs" && set -$dbgflgs
        return 0; }
alias DebugPush='local save_ops="${-:-}" _Debug=; DebugPush_helper'

#function DebugPush { local save_ops="${-:-}"; debug $1 || set +x; }


# called Global to check unprefixed 'flag' val in
sub chkflg {
        local glob="${1:?}" op="${2:?}"
        chksave_ops="${-:-}";
        if [[ $(((${!glob} & _D_Debug))) -eq 0 ]] ; then 
                set +x
        fi
  test -z "${op:-}"  && {
                test -n "$chksave_ops" && set -$chksave_ops
                return 1
        }
  local dop="_D_$op"
  local -i vop="${!dop:-0}"
        local -i i_res
        (((i_res=vop&${!glob}),1))
        test -n "$chksave_ops" && set -$chksave_ops
        if ((i_res)) ; then return 0;
        else $(exit -1;); return;
        fi

}
                

#function init_errnos { # {{{
#       gcc -E -dM /usr/include/errno.h |
#               grep -P 'define\sE'|
#               sort -k3 -n|sed 's/^#define //; s/ /=/ ' | 
#               ( coproc parselast { 
#                               cat | (usleep 100000;grep -P '^[A-Z]+=[A-Z]+$' 
) |
#                               sed 's/=/=$/'
#                       }
#                       tee /proc/self/fd/${parselast[1]}} |
#                       egrep -P '^[A-Z]+=\d+$'; <$parselast[0] cat 
#               )
#       # }}}
#}


function env_init { # {{{
        DebugPush EnvInit
        local progdir=$1 prog=$2 progname_dfl=$3

        if [[ ${progdir:0:1} != '/' ]]; then
                local preprog="$PWD"
                progdir="$preprog/$progdir"
        fi
        progdir="${progdir%/.}"
        progdir="${progdir%/}"
        [[ $prog =~ bash ]] && prog="$progname_dfl"
        export PATH="$progdir:/usr/sbin:/sbin:/usr/bin:/bin:$PATH"
        SL_progdir="$progdir"
        SL_prog="$prog"
        declare -la export_blobs
        for p in $_Progs ;do
                pv="_$p"
                eval "typeset -xr $pv=\"$(type -p "$p")\""
                [[ -z ${!pv} ]] && errx -1 "Cannot find \"$p\" in PATH"
                export_blobs[${#export_blobs[@]}]="export $pv=\"${!pv}\";"
                #" #here for a vim parsing error
                # local a=1
        done
#       echo  "$SL_progdir" "$SL_prog" "$PATH" "${export_blobs[*]}" >&2
        echo  "$SL_progdir" "$SL_prog" "$PATH" "${export_blobs[@]}"
        # }}}
        DebugPop
}

function _in {
        local x=${1:?};shift
        while [[ $# -gt 0 ]]; do
                if [[ $x == $1 ]]; then return $b_true; fi
                shift;
        done
        return $b_false;
}

#
# three funcs in 1!!!:
# 0 args: return cur loglevel on stdout
# 1 arg:        (will return true/false in status)
#   int: return true  if (int < loglevel)
#   str: return true  if (it matches a log_pat and it's  lev < loglev)
# else return false!
#
function msg_level {
        [[ $# == 0 ]] && { echo "$loglevel"; return 0; }
        local lev=${1:?}
        local -i ilev
        if i=$lev ; then
                ((lev<=loglevel)) && return $b_true
        else
                set -o nocasematch      extglob #ensure set
                local -i i
                local pat
                for ((i=0; i<${#_Level_pats[*]}; ++i)); do
                        pat="${_Level_pats[i]}"
                        [[ $lev =~ $pat ]] && {
                                if ((i<=loglevel)); then return $b_true; fi
                        }
                done
        fi
        return $b_false
}


function msg {
        DebugPush LowLevel

        local -a internal_funcs=(warn verb info msg is_provided)

        if (( $#<1 )); then
                errx -2 "Internal Error to msg, Expected 1 or more params, got 
$#"
        fi      
        local level="${1:?}" 
        ((level>loglevel)) && return 0;
        shift;
        local passed_msg="$(printf "$@")"
        
        local funcs="${#FUNCNAME[*]}"
        if ((funcs>0)) ; then ((--funcs)); fi
        local caller=0
        local src="${BASH_SOURCE[0]}"
        local bln="${BASH_LINENO[0]}"
        local func="${FUNCNAME[0]}"
        while ! _in $func "${internal_funcs[@]}" ;do
                ((++caller))
                src="${BASH_SOURCE[$caller]}"
                bln="${BASH_LINENO[$caller]}"
                func="${FUNCNAME[$caller]}"
        done
        local ln="$LINENO"
        local eoln=$'\n'

        if [[ ${passed_msg:0-1:1} == $eoln ]] ; then eoln=""; fi

        printf "\n%s[%s] @ %s#%s(%s)@:\n\t%s%s" \
                "$prog" "${_Levels_[$level]}" \
                $src "$bln" "$func" \
                        "$passed_msg" "$eoln" >&2
        DebugPop
}

function warn { msg _Warn_ "$@";        }

function verb { msg _Verbose_ "$@"; }

function info { msg _Info_ "$@"; }

# a little used function
function echov { printf "%s=%s\n" "$1" "${!1}"; }


function errx { #{{{
        if [[ $# -lt 2 ]]; then
                echo "$SL_prog: internal error, wrong# params to errx #=$# ($*)"
        fi
        err="$1"
        shift
        from_func=${FUNCNAME[1]}
        from_lineno=${BASH_LINENO[1]}
        from_source=${BASH_SOURCE[1]}
        passed_msg="$(printf "$@")"
        eoln=$'\n'
        if [[ ${passwd_msg:0-1:1} == $eoln ]] ; then eoln=""; fi
        printf "\n${SL_prog}: line %s in function %s: %s%s" \
                "$from_lineno" "$from_func" "$passed_msg" "$eoln" >&2
        kill -TERM -$progpid
        kill -9 -$progpid               # one of these is bound to eventually 
work!  ;-)
#}}}
}



####
#### Mountpoint functions
####


function get_devname_of_mp { # {{{
        DebugPush MP_OPS
        if [[ $# != 1 ]]; then 
                DebugPop
                errx -9 "Internal error: getLV_by_MntDir expects mount point as 
arg, got $# args"
        fi
        local mp="${1:?}"
        local dev="$($_grep -P '\s'"$mp"'\s' /proc/mounts|$_cut -d\  -f1)"
        echo "$dev"
        DebugPop MP_OPS
        # }}}
}

function get_vg_lv_from_mp { #{{{
        DebugPush MP_OPS
        if [[ $# -lt 1 ]]; then 
                errx -11 "Internal error: get_vg_lv_from_mp expects mount point 
as arg, got $# args"
        fi
        local mp="$1"
        local dev="$(get_devname_of_mp "$mp")"
        local lv vg
        local glob="$($_dmsetup --noheadings splitname "$dev")"
        glob="${glob%:}"
        vg="${glob%:*}"
        lv="${glob#*:}"
        
        vg="${vg#/dev}"
        vg="${vg#/mapper}"
        vg="${vg#/}"

        test  -z "$vg" &&  {
                DebugPop
                errx 1 "dmsetup splitname returned no vg for mountpnt $mp"
        }
        test -z "$lv" && {
                DebugPop
                errx 2 "dmsetup splitname returned no lv for mountpnt $mp"
        }
        
        
        p="/dev/$vg"; test ! -d "$p" && { 
                DebugPop
                errx 3 "Does not exist: vg $p (mountpnt $mp)"
        }
        
        p="$p/$lv"; test ! -e "$p" && { 
                DebugPop
                errx 3 "Does not exist: vg/lv $p (mountpnt $mp)"
        }
        test -b "$p"  || {
                DebugPop
                errx 4 "Not a device: vg/lv $p (mountpnt $mp)"
        }

        echo -e "$vg" "$lv"

        DebugPop
        #}}}
}


function getLV_by_MntDir { # {{{
        if [[ $# != 1 ]]; then 
                errx -7 "Internal error: getLV_by_MntDir expects mount point as 
arg, got $# args"
        fi
        read vg lv <<<$(get_vg_lv_from_mp "$1")
        echo "lv"
        # }}}
}

function getVG_by_MntDir { # {{{
        if [[ $# != 1 ]]; then 
                errx -8 "Internal error: getVG_by_MntDir expects mount point as 
arg, got $# args"
        fi
        read vg lv <<<$(get_vg_lv_from_mp "$1")
        echo "vg"
        # }}}
}


function mp_is_not_same_as_2nd_fs { # {{{
        DebugPush MP_OPS
        local mp="$1" fs2="$2"
        local -i bad_param=2  bad_dev=3
        [[ -z $mp || -z $fs2 ]] && { DebugPop; return $b_fail ;}
        [[ $mp == $fs2 ]] && { DebugPop; return $b_false; }
        local - i mp_dev="$(get_devnum $mp)"
        local -i fs2_dev="$(get_devnum $fs2)"
        ((mp_dev==0 || fs2_dev==0)) && { DebugPop; return $b_fail;}
        local -i res=$((mp_dev==fs2_dev))
        DebugPop
        return $res
        #}}}
} 

function mp_dev_is_not_on_root_fs { #{{{
        mp="$1"
        mp_is_not_same_as_2nd_fs "$mp" "/"
        return $?
        #}}}
}

function mounted_fs_at {
        mp=${1?};
        mp_parent="${mp%/*}"
        if [[ -z $mp_parent ]]; then mp_parent="/"; fi
        if mp_dev_is_not_same_as_2nd_fs $mp $mp_parent ; then
                return 0; #true
        fi
        return 1; 
}





function get_most_recent_snapshot {   # {{{
        if [[ $# < 1 ]]; then
                errx -3 "Internal function 'get_most_recent_snapshot' called 
without mountpoint arg"
        fi
        local $snap_mp="$1"

        read snap_vg snap_lv <<<$(get_vg_lv_from_mp "$snap_mp" )

        if [[ -z $snap_vg || -z $snap_lv ]]; then 
                echo "$snap_mp not found (vg=$snap_vg), (lv=$snap_lv)"
                exit -3
        fi
        $latest="$(find_active_snapshots|sort|last -1)"
        
        Prefix="snapdir/@GMT-"
        snap_today="$(date +%Y.%m.%d-)"
        snap_prefix="$snap_mp/$Prefix$snap_today*"
        today_snaps="$('ls' -1 ${snap_prefix} |tr "\n" " " )"
        if [[ -n $today_snaps && $today_snaps != $snap_prefix ]]; then
                echo "yes"
                exit 0
        fi
        exit 1 
        # }}}
}



function chk_today_snap { # {{{
        DebugPush LowLevel
        local base_mp="${1:?}"
        local Force="${2:-""}"
        today_has_snap "$base_mp" && { 
                [[ $Force =~ .*snap_today.* ]]  && {
                        DebugPop
                        return 0
                }
                errx 10 "Error: already have a snap today; add 'snap_today'
        to force list (-f <comma-sep-list> ) to create anyway"
        }
        verb "No snap yet today"
        DebugPop
        return 0
        # }}}
}


function get_devnum { #{{{
        $_stat -c "%d" "$1" || errx -4 "stat on \"$1\" failed: \"$?\""
        #}}}
}



function mnt_n_clean_diff_dir { #{{{
        base_mp_diff=$1
        mp_dev_is_not_on_root_fs "$base_mp_diff" || 
                $_sudo  $_umount "$base_mp_diff" || errx 5 "umount 
$base_mp_diff failed: $?"

        mp_dev="$(get_devnum "$base_mp_diff")"

        [[ $root_dev == $mp_dev ]] && {
                $_grep -s "$base_mp_diff" /etc/fstab || \
                        errx 6 "$base_mp_diff not found in /etc/fstab"
                $_sudo $_mount "$base_mp_diff" || errx $? "mount 
\"$base_mp_diff\" failed: $?"
        }

        mp_dev="$(get_devnum $base_mp_diff)"
        [[ $root_dev == $mp_dev ]] && \
                errx 7 "Couldn't mount diff vol @ $base_mp_diff"

        cd "$base_mp_diff" || errx 11 "cd to $base_mp_diff, failed, stat=$?"
        curdir_dev="$(get_devnum . )"

        [[ $mp_dev != $curdir_dev ]] && \
                errx 8 "cd to $base_mp_diff and dev of \".\" != base_dev 
($mp_curdir != $curdir_dev)"

        [[ $curdir_dev == $root_dev || $PWD == / || $base_mp == / ]] && \
                errx 9 \
                "Sanity check failed, the diff dir looks like 'root'\n  Cannot 
use root as diff dir."
##
        [[ $(/bin/pwd) != $base_mp_diff ]] && \
                errx 13 "curdir $(/bin/pwd), != $base_mp_diff, not feel safe to 
proceed\n\
            are softlinks involved; next step (rm -fr *) is dangerous is not 
in\n\
                        directory we expect to be in)."
        $_sudo $_rm --one-file-system -fr * 
        verb "Line: $LINENO: mnt_n_clean_diff_dir: done"
        #}}}
}


function lv_names_attrs {
        $_sudo  $_lvs  --nosuffix --noheadings -o lv_name,lv_attr
}

function find_lv_by_filter {
        local perl_filt="${1:?}"
        lv_names_attrs | $_perl -ne "$perl_filt" 
}

function find_attrs_by_lv { # {{{
        local lv="${1:?}" 
        if [[ $lv =~ / ]]; then
                errx -40 "IntErr, volnames can't have '/' in them, passed a mp?"
        fi
        local subpat="$lv"'\s*(.*)'
        local perl_prg='
                m{^\s*'"$subpat"'} 
                                                and print "$1\n"'
        find_lv_by_filter "$perl_prg"
        # }}}
}

function check_snap_attr { # {{{
        local attr=${1:?} attr_name=${2:?}
        case "$attr_name" in 
                [sS]tatic)
                        test ${attr:0:1} == '-' && return 0
                        ;;
                [bB]ase|[oO]rigin)
                        test ${attr:0:1} == 'o' && return 0
                        ;;
                [sS]napshot)
                        test ${attr:0:1} == 's' && return 0
                        ;;
                [wW]ritable|[Ww]riteable)
                        test ${attr:1,1} == 'w' && return 0
                        ;;
                [aA]ctive)
                        test ${attr:4,1} == 'a' && return 0
                        ;;
                [sS]uspend)
                        test ${attr:4,1} == 's' && return 0
                        ;;
                [iI]nvalid)
                        test ${attr:4,1} == 'i' && return 0
                        ;;
                [oO]pen)
                        test ${attr:5,1} == 'o' && return 0
                        ;;
        esac
}

        

function find_snap_by_lv_name_flags { # {{{
        local base_lv=${1:?} flags=${2:?}
        local 
subpat="$base_lv"'-(20\d\d\.\d\d\.\d\d-\d\d\.\d\d\.\d\d)\s*'"$flags"
        local perl_prg='
                m{^\s*'"$subpat"'} 
                                                and print "$1\n"'
        find_lv_by_filter "$perl_prg"
        # }}}
}

function find_active_snapshots { # {{{
        local base_lv=${1:?}
        find_snap_by_lv_name_flags "$base_lv" "swi-a."
        # }}}
}


function find_mounted_active_snapshots { # {{{
        local base_lv=${1:?}
        find_snap_by_lv_name_flags "$base_lv" "swi-ao"
        # }}}
}

function find_unmounted_active_snapshots { # {{{
        local base_lv=${1:?}
        find_snap_by_lv_name_flags "$base_lv" "swi-a-"
        # }}}
}

# snaps are fs-images based on a snapshot, that are now static copies
function find_unmounted_snaps { # {{{
        local base_lv=${1:?}
        find_snap_by_lv_name_flags "$base_lv" "-wi-a-"
        # }}}
}

function find_mounted_snaps { # {{{
        local base_lv="${1:?}"
        find_snap_by_lv_name_flags "$base_lv" "-wi-ao"
        # }}}
}





function find_oactv_snapshot { # {{{
        local base_lv="${1:?}"
        export perl_prg='
                                        
m{^\s*'"$base_lv"'-(20\d\d\.\d\d\.\d\d-\d\d\.\d\d\.\d\d)\s*swi-ao} 
                                                and print "$1\n"'

        osnap_snapdate="$(find_active_snapshots "$base_lv"|sort -r|tail -1)"
        # above hs only the DT, so is nothing we neeed by itself
        # from it, we derive:
        osnap_mp_name="@GMT-$osnap_snapdate"
        osnap_lv="$base_lv-$osnap_snapdate"
        osnap_path_mp="$base_mp/$snapdir/$osnap_mp_name"
        
        read osnap_vg osnap_lv2 st <<<$(Mnt_to_VG+LV.pl "$osnap_path_mp";echo 
$?)
        ((st!=0)) && errx -5 "Mnt_to_VG_+LV for $osnap_path_mp failed with $?"
        osnap_devpath="/dev/$osnap_vg/$osnap_lv"

        echo "$osnap_path_mp" "$osnap_vg" "$osnap_lv" "$osnap_devpath"
        # }}}
}

export -f find_oactv_snapshot




        
function clear_obase { # {{{
        obase_mp=$1
        if [[ ! -d $obase_mp ]]; then 
                errx 19 "$obase_mp is not a directory"
        fi
        mp_dev_is_not_on_root_fs "$obase_mp" || {
                sudo umount "$obase_mp" || {
                        errx 20 "Couldn't clear $obase_mp -- umount failed\n"
                }
        }
        return 0
        # }}}
}




# no real reason to do this, (just made typing eaiser)
# when it was done by hand...can diff directly from the old volume;
# not sure of need to freeze....by maybe will anyway

function bind_oldest_active_snap_to_obase { # {{{
        mp_dev_is_not_on_root_fs $obase_mp || $_sudo $_umount $obase_mp || {
                errx 14 "could not clean mount point for old snapshot"
        }

        obase_mp="/o${base_mp#/}"
        #check snapdev!=rootdev, OR umount snapdev
        mp_dev_is_not_on_root_fs "$osnap_path_mp" || $_sudo $_umount 
"$osnap_path_mp"

        
        verb "Line: $LINENO: Before :mount --bind $osnap_path_mp "
        verb "Line: $LINENO: to $obase_mp: done"
        
        $_sudo $_mount --bind "$osnap_devpath" "$obase_mp" || \
                errx 10 "%s",\
                        "rbind of old snap $osnap_path_mp "\
                        "to $obase_mp failed: status was $?"

        verb "Line: $LINENO: mount --bind $osnap_path_mp to $obase_mp: done"

        #NOTE: echo's output is read by caller, vs. 'verb[ose]' out goes to 
stderr
        echo "$osnap_path_mp" "$osnap_vg" "$osnap_lv"  "$osnap_devpath"
        return 0        
        # }}}
}       

function status_in_exit_params { # {{{
        local status=$1; shift;
        local stat

        for stat in "$@"; do
                (($stat == $status)) && return 0 
                (exit -1);return
        done;
        # }}}
}


function create_basemp_snap { # {{{
        local base_mp="${1:?}"

        $_sudo  create_snap "$base_mp" || \
                { errx 11 "create_snap returned bad exit code $?"; }
        # }}}
}

function trim_dirchs { # {{{
        DebugPush LowLevel
        local str="$1"
        start=""
        while [[ $start != $str ]]; do
                start="$str"
                str="${str%/}"          # make sure no trailing slash 
(foo/./././)
                str="${str%/.}"         # no elim the normal case
        done                                                            # 
repeat in case passed nested string 
        echo "$str"
        DebugPop
        # }}}
}

function rsync_snapdiffs_to_base_mp_diff {  # {{{
        local callback="${1:?}"; shift;
        local osnap_mp="${1:?}"  base_mp_diff="${2:?}" base_mp="${3:?}"
        shift; shift; shift;
        local -a exclude_pats=( "$@" )

        # clean up any suffixes...dunno who might call us...(Really!)
        osnap_mp="$(trim_dirchs "$osnap_mp")"
        local osnap_vg osnap_lv
        read osnap_vg osnap_lv <<<$(get_vg_lv_from_mp "$osnap_mp")
        base_mp_diff="$(trim_dirchs "$base_mp_diff")"
        base_mp="$(trim_dirchs "$base_mp")"

        local cmd
        # construct cmd so we can print what we are executing!
        printf -v cmd "%s " \
                                "$_sudo" "$_rsync"                              
                        \
                                "-avHAX" "--one-file-system"            \
                                "--compare-dest=\"$base_mp/.\"" \
                                "${exclude_pats[@]}"                            
                \
                                "$osnap_mp/." "$base_mp_diff/." "&>" 
"/tmp/rsync-log-$$.log"

        echo "$cmd" >&2
        eval $cmd >&2
        local status=$?
        local -a rsync_fuzzy_ok_exit_codes=(0 24)
        status_in_exit_params "$status" "${rsync_fuzzy_ok_exit_codes[@]}"  || {
                local l1="rsync returned a 'shady' status ($status),"
                local l2="   so not proceeding log in /tmp/rsync-log-$$.log"
                errx 11 "$l1\n$l2"
        }       
        # else remove log
        $_rm -f /tmp/rsync-log-$$.log
        # and remove empty dirs in diff dir
        ( $_sudo $_find $base_mp_diff/. -depth -type d -print0 |
                $_sudo $_xargs -0 $_rmdir >&2 2>/dev/null  )    #ignore errs
        echo "$osnap_mp" "$osnap_vg" "$osnap_lv"
        return 0
        # }}}
}




function destroy_old_snapshot_by_mp_n_devpath { # {{{
        local osnap_mp="${1:?}" osnap_devpath="${2:?}"

        # now unmount old snap volume...
        $_sudo $_umount $osnap_mp || {
                note "umount failed, trying with force..."
                $_sudo $_umount $osnap_mp || {
                        errx 30 "Couldn't unmount old snapshot dir"
                }
        }
        
        $_sudo  $_dmsetup remove "$osnap_devpath" || {
                warn "dmsetup remove of $osnap_devpath failed"
                if [[ ! ($force =~ .*dmsetup_remove.* ) ]]; then
                        errx 31 "Won't remove with force unless give 
'dmsetup_remove' in force args"
                fi
                warn "using force to removee old snap\n"
                $_sudo $_dmsetup remove -f "$osnap_devpath" || {
                        errx 32 "force remove w/dmsetup of $oshap_devpath 
failed!"
                }
        }
        $_sudo $_lvremove "$osnap_devpath" || {
                warn "lvremove of old snap failed"
        }
        # }}}
}


function osnap_identifier_filename {
        # "snap-<Vol>-<date-time>"
        local osnap_lv="${1:?}" # may be incomplete fn during searches
        echo "snap-$osnap_lv"
}


function write_osnap_identifier_file {
        local dir="${1:?}"
        local onap_mp="${2:?}" osnap_lv="${3:?}" osnap_devpath="${4:?}"
        local osnap_idfn="$(osnap_identifier_filename "$osnap_lv")"
        local echo_st="$(printf "echo -e \"%s\\\n%s\\\n%s\" >%s\n" \
                "$osnap_mp" "$osnap_lv" "$osnap_devpath" "$osnap_idfn")"
        $_sudo bash -c "eval \"$echo_st\""
}

        



function find_unsaved_snap_data {  # {{{
        local bdiff_mp="${1:?}"
        local bdiff_vg bdiff_lv
        read bdiff_vg bdiff_lv <<<$(get_vg_lv_from_mp "$bdiff_mp")
        local osnap_lv_base="$(osnap_identifier_filename "${bdiff_lv%.diff}" )"
        local osnap_lv_pat="$osnap_lv_base"'-+([-0-9\.])'
        datafile="$( echo $bdiff_mp/$osnap_lv_pat )"
        if [[ -f "$datafile" && -r "$datafile" ]]; then
                local -xa vals
                getval_cmds="readarray vals <$datafile; echo "'"${vals[@]}" '
                read  osnap_mp osnap_lv osnap_devpath <<<$(tr "\n" " " 
<"$datafile" )
                if [[ -z $osnap_mp || -z $osnap_lv || -z $osnap_devpath ]]; then
                        errx -6 "$( printf \
                                "Data file incomplete or corrupt; mp=%s, vg=%s, 
lv=%s, dev=%s\n" \
                                        "$osnap_mp" "$osnap_lv" 
"$osnap_devpath" )"
                else 
                        echo "$osnap_mp" "$osnap_lv" "$osnap_devpath"
                        return 0
                fi
        else
                info "No unsaved snap data found on diff vol"
                echo ""
                return 1
        fi
        # }}}
}


##
## check_snap_copy_complete
## Checks & sets or removes if snap_copy_complete
## 


function check_snap_copy_complete {
        local snap_mp="${1:-}"
        # snap_mp of form parentVol/snapdir/@GMT-timestamp
        # need to find base parent vol for find_attrs_by_snap
        local vg lv
        read vg lv <<<$(get_vg_lv_from_mp "$snap_mp")
        attrs="$(find_attrs_by_lv "$lv")"
        if [[ -z $attrs || -z ${snap_mp:-} || ! -e $snap_mp/snap_copy_complete 
]]; 
                then rm_provides snap_copy_complete
        fi
        if check_snap_attr "$attrs" "snapshot"; then
                add_provides snap_copy_complete
        else
                rm_provides snap_copy_complete
        fi
        return 0
}




function get_nextents_for_space_on_vg_w_minfree { # {{{
        local base_mp_diff="${1:?}" base_vg="${2:?}" 
        local -i minfree="${3:?}"
        
        local -i sizek="$(sudo du --one-file-system -k -s $base_mp_diff|cut 
-f1)"

        ((minsize=sizek*100/(100-minfree) ))
        ((sizek<minsize)) &&    # sanity check: should always be true
                sizek=$minsize

        #get allocation extent size of VG
        local extent_sz=$(sudo vgs --noheadings --units b  \
                                                                                
--nosuffix -o vg_extent_size "$base_vg");

        #determine how many full extents will hold the size we want

        set -x
        ((size=sizek*1024))
        ((nextents=size/extent_sz))
        ((m=size%extent_sz))
        if ((m!=0));then 
                ((nextents++)) || /bin/true
        fi

        echo "$nextents"
        # }}}
}



##
## subs to handle 'defining' the names of allowed defines
## or test if a name is "allow" (defined); there is no Remove
##



declare -axl defined_Provides

# this holds names of 'vars' that contain white space separated names!
# array names prefixed with '_plist_'
declare -xr _plst_t='_plist_'
declare -axl defined_PLists

#test
sub _defined_plist {
        DebugPush PLists
        if  [[ ! "${defined_PLists:-}" || ${#defined_PLists[*]} -eq 0 ]]; then 
                DebugPop
                return $b_false
        fi
        local -l def_plist="${1:?}"
        for ((i=0;i<${#defined_PLists[*]};++i)); do
                [[ $def_plist == ${defined_PLists[$i]} ]] && {
                        DebugPop
                        return $b_true
                }
        done
        DebugPop
        return $b_false
}
alias is_plist=_defined_plist


sub add_PList_dep {  
        DebugPush PLists
        local -l plist="${1:?}"
        local -l subdep="${2:?}"
        if ! _defined_plist "$plist"; then 
                defined_PLists[${#defined_PLists[*]}]="$plist"
        fi
        plist="$_plst_t$plist"
        local -al plist_deps=( $plist )
        local -i found=0
        for ((i=0;i<${#plist_deps[*]};++i)); do
                if [[ $subdep == ${plist_deps[$i]} ]] ; then
                        found=1
                        break;
                fi
        done
        if ! ((found)) ; then 
                plist_deps[${#plist_deps[*]}]="$subdep"
                plist="$(echo  "${plist_deps[@]}" )"
        fi
        DebugPop
}



# sub to handle testing 'definedness'
sub _defined_provide { #{{{
        DebugPush Define_Provides
        if  [[ ! "${defined_Provides:-}"||${#defined_Provides[*]} -eq 0 ]]; 
then 
                DebugPop
                return $b_false
        fi
        local -l def_provided="${1:?}"
        local -i i
        for ((i=0;i<${#defined_Provides[*]};++i)); do
                [[ $def_provided == ${defined_Provides[$i]} ]] && {
                        DebugPop
                        return $b_true
                }
        done
        DebugPop
        return $b_false
}
alias _is_defined=_defined_provide

sub num_subdeps {
        DebugPush PLists
        local -l plist="${1:?}"
        if ! _defined_plist "$plist"; then 
                defined_PLists[${defined_PLists[*]}]="$plist"
        fi
        plist="$_plst_t$plist"
        local -al plist_deps=( $plist )
        echo "${#plist_deps[*]}"
        DebugPop
}


sub define_Provide {
        DebugPush Define_Provides
        echo "#defined_provides=${#defined_Provides[*]}"
        while [[ $# -gt 0 ]]; do
                local -l def_provide="${1:?}"
                shift
                local ch="$def_provide"
                ch="${ch:0:1}"
                if [[ $ch == @ ]]; then
                        def_provide="${def_provide:1}"
                        # rest of list are subdeps
                        while [[ $# -gt 0 ]]; do
                                local -l subdef_provide="${1:?}"
                                shift
                        define_Provide "?$subdef_provide" && {
                                add_PList_dep "$def_provide" "$subdef_provide"
                        }
                        done
                        if [[ $(num_subdeps "$def_provide") -lt 1 ]]; then 
                                errx -21 "IntErr def_Provide: list 
@$def_provide has no children!"
                        fi
                        break;
                elif [[ "$ch" == '?' ]]; then
                        def_provide="${def_provide:1}"
                        if ! _defined_provide "$def_provide"; then 
                                
defined_Provides[${#defined_Provides[*]}]="$def_provide"
                        fi
                else 
                        if ! _defined_provide "$def_provide"; then 
                                
defined_Provides[${#defined_Provides[*]}]="$def_provide"
                        else
                                errx -20 \
                                        "IntErr def_Provide: Attempt to 
redefine feature '$def_provide'"
                        fi
                fi
        done
        DebugPop
}       
alias def_Provide=define_Provide





##
## subs to handle if a feature or dep is actually defined or not;
## validity of names is checked in the above "define/_define provides"
##


#need to handle list test&set

declare -axl Provides=()

sub is_provided { #{{{
        #echo "#=$#, @=""$@" ""
        local -a args; args=( "$@" )
        DebugPush Provides
        if  [[ ! ${Provides:-} || ${#Provides[*]} -eq 0 ]]; then 
                DebugPop
                return $b_false
        fi
        local provided=""
        local -i pVerbose=0
        set -- "${args[@]}"
        while [[ $# -gt 0 ]]; do
                provided="${1:?}"
                if [[ $provided == -v ]]; then
                        pVerbose=1
                        shift; continue;
                fi
                if [[ "${provided:0:1}" == "@" ]]; then
                        provided="${provided:1}"
                        local -al plist_deps=( $plist )
                        local -i i
                        for ((i=0;i<${#plist_deps[*]};++i)); do
                                if ((pVerbose)); then 
                                        is_provided  -v "${plist_deps[$i]}"
                                else 
                                        is_provided  "${plist_deps[$i]}"
                                fi
                        done
                        continue        
                fi
                _is_defined $provided || {
                        errx -21 "IntErr is_provided: feature '$provided' is 
not defined"
                }
                shift;
                for ((i=0;i<${#Provides[*]};++i)); do
                        [[ $provided == ${Provides[$i]} ]] && continue 2;
                done
                if ((pVerbose)); then
                        warn "Missing feature/dependency \"$provided\"" 
                fi
                DebugPop
                return $b_false
        done;
        DebugPop
        return 0
}

alias have_dep="is_provided"



sub rm_provides {
        DebugPush Provides
        local -al nProvides
        local tbd_provide="${1:?}"
        _is_defined $tbd_provide || {
                errx -21 "IntErr rm_provides: feature '$tbd_provide' is not 
defined"
        }
        [[ -z "${Provides:-}" ]] && return

        if [[ "${tbd_provide:0:1}" == "@" ]]; then
                tbd_provide="${tbd_provide:1}"
                local -al plist_deps=( $plist )
                local -i i
                for ((i=0;i<${#plist_deps[*]};++i)); do
                        rm_provides "${plist_deps[$i]}"
                done
        else 
                local -i n=0 p=0
                local b_modified=$b_false
                while ((p<${#Provides[*]})); do
                        if [[ $tbd_provide != ${Provides[$p]} ]]; then
                                nProvides[$n]="${Provides[$p]}"
                                ((++n, ++p)) 
                        else
                                ((++p))
                                b_modified=$b_true
                        fi
                done    

                if [[ $b_modified ]]; then
                        Provides=()
                        for ((n=0;n<${#nProvides[*]};++n)); do
                                Provides[$n]=${nProvides[$n]}
                        done
                fi
        fi
        DebugPop
}

sub add_provides {
        DebugPush Provides
        local -l provided
        while [[ $# -gt 0 ]]; do
                provided="${1:?}"
                shift
                _is_defined $provided || {
                        errx -21 "IntErr add_provides: feature '$provided' is 
not defined"
                }
                if [[ "${provided:0:1}" == "@" ]]; then
                        provided="${provided:1}"
                        local -al plist_deps=( $plist )
                        for ((i=0;i<${#plist_deps[*]};++i)); do
                                add_provides "${plist_deps[$i]}"
                        done
                else 
                        if ! is_provided "$provided"; then 
                                if [[ -z "${Provides:-}" ]]; then
                                        Provides[0]="$provided"
                                else 
                                        Provides[${#Provides[*]}]="$provided"
                                fi
                        fi
                fi
        done
        DebugPop
}       

# vim: ts=2 sw=2 fdm=marker nofen number

reply via email to

[Prev in Thread] Current Thread [Next in Thread]