[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
- Re: Syntax Question..., (continued)
- Re: Syntax Question..., Michael Witten, 2011/08/13
- Re: Syntax Question..., Linda Walsh, 2011/08/14
- Re: Syntax Question..., Pierre Gaston, 2011/08/14
- Re: Syntax Question..., Linda Walsh, 2011/08/14
- Re: Syntax Question..., Pierre Gaston, 2011/08/14
- Re: Syntax Question..., Linda Walsh, 2011/08/14
- Re: Syntax Question..., Dennis Williamson, 2011/08/14
- Re: Syntax Question..., Linda Walsh, 2011/08/14
- Re: Syntax Question..., Dennis Williamson, 2011/08/15
- Re: Syntax Question..., Linda Walsh, 2011/08/15
- Re: Syntax Question...,
Linda Walsh <=
- Re: Syntax Question..., Greg Wooledge, 2011/08/15
- Re: Syntax Question..., Linda Walsh, 2011/08/18
- Re: Syntax Question..., Greg Wooledge, 2011/08/18
- Re: Syntax Question..., Chet Ramey, 2011/08/18
- Re: Syntax Question..., Greg Wooledge, 2011/08/18
- Re: Syntax Question..., Chet Ramey, 2011/08/18
- Re: Syntax Question..., Greg Wooledge, 2011/08/18
- Re: Syntax Question..., Chet Ramey, 2011/08/18
- Re: Syntax Question..., Linda Walsh, 2011/08/18
- Re: Syntax Question..., Ken Irving, 2011/08/18