1*10898Sroland.mainz@nrubsig.org#!/usr/bin/ksh93
2*10898Sroland.mainz@nrubsig.org
3*10898Sroland.mainz@nrubsig.org#
4*10898Sroland.mainz@nrubsig.org# CDDL HEADER START
5*10898Sroland.mainz@nrubsig.org#
6*10898Sroland.mainz@nrubsig.org# The contents of this file are subject to the terms of the
7*10898Sroland.mainz@nrubsig.org# Common Development and Distribution License (the "License").
8*10898Sroland.mainz@nrubsig.org# You may not use this file except in compliance with the License.
9*10898Sroland.mainz@nrubsig.org#
10*10898Sroland.mainz@nrubsig.org# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11*10898Sroland.mainz@nrubsig.org# or http://www.opensolaris.org/os/licensing.
12*10898Sroland.mainz@nrubsig.org# See the License for the specific language governing permissions
13*10898Sroland.mainz@nrubsig.org# and limitations under the License.
14*10898Sroland.mainz@nrubsig.org#
15*10898Sroland.mainz@nrubsig.org# When distributing Covered Code, include this CDDL HEADER in each
16*10898Sroland.mainz@nrubsig.org# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17*10898Sroland.mainz@nrubsig.org# If applicable, add the following below this CDDL HEADER, with the
18*10898Sroland.mainz@nrubsig.org# fields enclosed by brackets "[]" replaced with your own identifying
19*10898Sroland.mainz@nrubsig.org# information: Portions Copyright [yyyy] [name of copyright owner]
20*10898Sroland.mainz@nrubsig.org#
21*10898Sroland.mainz@nrubsig.org# CDDL HEADER END
22*10898Sroland.mainz@nrubsig.org#
23*10898Sroland.mainz@nrubsig.org
24*10898Sroland.mainz@nrubsig.org#
25*10898Sroland.mainz@nrubsig.org# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
26*10898Sroland.mainz@nrubsig.org# Use is subject to license terms.
27*10898Sroland.mainz@nrubsig.org#
28*10898Sroland.mainz@nrubsig.org
29*10898Sroland.mainz@nrubsig.org#
30*10898Sroland.mainz@nrubsig.org# simplefileattributetree1 - build a simple file tree (including file attributes)
31*10898Sroland.mainz@nrubsig.org#
32*10898Sroland.mainz@nrubsig.org
33*10898Sroland.mainz@nrubsig.org# Solaris needs /usr/xpg6/bin:/usr/xpg4/bin because the tools in /usr/bin are not POSIX-conformant
34*10898Sroland.mainz@nrubsig.orgexport PATH=/usr/xpg6/bin:/usr/xpg4/bin:/bin:/usr/bin
35*10898Sroland.mainz@nrubsig.org
36*10898Sroland.mainz@nrubsig.org# Make sure all math stuff runs in the "C" locale to avoid problems
37*10898Sroland.mainz@nrubsig.org# with alternative # radix point representations (e.g. ',' instead of
38*10898Sroland.mainz@nrubsig.org# '.' in de_DE.*-locales). This needs to be set _before_ any
39*10898Sroland.mainz@nrubsig.org# floating-point constants are defined in this script).
40*10898Sroland.mainz@nrubsig.orgif [[ "${LC_ALL}" != "" ]] ; then
41*10898Sroland.mainz@nrubsig.org    export \
42*10898Sroland.mainz@nrubsig.org        LC_MONETARY="${LC_ALL}" \
43*10898Sroland.mainz@nrubsig.org        LC_MESSAGES="${LC_ALL}" \
44*10898Sroland.mainz@nrubsig.org        LC_COLLATE="${LC_ALL}" \
45*10898Sroland.mainz@nrubsig.org        LC_CTYPE="${LC_ALL}"
46*10898Sroland.mainz@nrubsig.org        unset LC_ALL
47*10898Sroland.mainz@nrubsig.orgfi
48*10898Sroland.mainz@nrubsig.orgexport LC_NUMERIC=C
49*10898Sroland.mainz@nrubsig.org
50*10898Sroland.mainz@nrubsig.org
51*10898Sroland.mainz@nrubsig.orgfunction add_file_to_tree
52*10898Sroland.mainz@nrubsig.org{
53*10898Sroland.mainz@nrubsig.org	typeset treename=$1
54*10898Sroland.mainz@nrubsig.org	typeset filename=$2
55*10898Sroland.mainz@nrubsig.org	nameref destnodename=$3
56*10898Sroland.mainz@nrubsig.org	integer i
57*10898Sroland.mainz@nrubsig.org	typeset nodepath # full name of compound variable
58*10898Sroland.mainz@nrubsig.org	typeset -a pe # path elements
59*10898Sroland.mainz@nrubsig.org
60*10898Sroland.mainz@nrubsig.org	# first built an array containing the names of each path element
61*10898Sroland.mainz@nrubsig.org	# (e.g. "foo/var/baz"" results in an array containing "( 'foo' 'bar' 'baz' )")
62*10898Sroland.mainz@nrubsig.org	typeset IFS='/'
63*10898Sroland.mainz@nrubsig.org	pe+=( ${filename} )
64*10898Sroland.mainz@nrubsig.org
65*10898Sroland.mainz@nrubsig.org	[[ ${pe[0]} == '' ]] && pe[0]='/'
66*10898Sroland.mainz@nrubsig.org
67*10898Sroland.mainz@nrubsig.org	# walk path described via the "pe" array and build nodes if
68*10898Sroland.mainz@nrubsig.org	# there aren't any nodes yet
69*10898Sroland.mainz@nrubsig.org	nodepath="${treename}"
70*10898Sroland.mainz@nrubsig.org	for (( i=0 ; i < (${#pe[@]}-1) ; i++ )) ; do
71*10898Sroland.mainz@nrubsig.org		nameref x="${nodepath}"
72*10898Sroland.mainz@nrubsig.org		[[ ! -v x.node ]] && compound -A x.nodes
73*10898Sroland.mainz@nrubsig.org
74*10898Sroland.mainz@nrubsig.org		nodepath+=".nodes[${pe[i]}]"
75*10898Sroland.mainz@nrubsig.org	done
76*10898Sroland.mainz@nrubsig.org
77*10898Sroland.mainz@nrubsig.org	# insert element
78*10898Sroland.mainz@nrubsig.org	nameref node="${nodepath}"
79*10898Sroland.mainz@nrubsig.org	[[ ! -v node.elements ]] && compound -A node.elements
80*10898Sroland.mainz@nrubsig.org	node.elements[${pe[i]}]=(
81*10898Sroland.mainz@nrubsig.org		filepath="${filename}"
82*10898Sroland.mainz@nrubsig.org	)
83*10898Sroland.mainz@nrubsig.org
84*10898Sroland.mainz@nrubsig.org	destnodename="${!node}.elements[${pe[i]}]"
85*10898Sroland.mainz@nrubsig.org
86*10898Sroland.mainz@nrubsig.org	return 0
87*10898Sroland.mainz@nrubsig.org}
88*10898Sroland.mainz@nrubsig.org
89*10898Sroland.mainz@nrubsig.orgfunction parse_findls
90*10898Sroland.mainz@nrubsig.org{
91*10898Sroland.mainz@nrubsig.org	nameref out=$1
92*10898Sroland.mainz@nrubsig.org	typeset str="$2"
93*10898Sroland.mainz@nrubsig.org
94*10898Sroland.mainz@nrubsig.org	# find -ls on Solaris uses the following output format by default:
95*10898Sroland.mainz@nrubsig.org	#604302    3 -rw-r--r--   1 test001  users        2678 May  9 00:46 ./httpsresdump
96*10898Sroland.mainz@nrubsig.org
97*10898Sroland.mainz@nrubsig.org	integer out.inodenum="${str/~(Elr)[[:space:]]*([[:digit:]]+)[[:space:]]+([[:digit:]]+)[[:space:]]+([[:alpha:]-]+)[[:space:]]+([[:digit:]]+)[[:space:]]+([[:alnum:]]+)[[:space:]]+([[:alnum:]]+)[[:space:]]+([[:digit:]]+)[[:space:]]+([[:alpha:]]*[[:space:]]+[[:digit:]]*[[:space:]]+[[:digit:]:]+)[[:space:]]+(.+)/\1}"
98*10898Sroland.mainz@nrubsig.org	integer out.kbblocks="${str/~(Elr)[[:space:]]*([[:digit:]]+)[[:space:]]+([[:digit:]]+)[[:space:]]+([[:alpha:]-]+)[[:space:]]+([[:digit:]]+)[[:space:]]+([[:alnum:]]+)[[:space:]]+([[:alnum:]]+)[[:space:]]+([[:digit:]]+)[[:space:]]+([[:alpha:]]*[[:space:]]+[[:digit:]]*[[:space:]]+[[:digit:]:]+)[[:space:]]+(.+)/\2}"
99*10898Sroland.mainz@nrubsig.org	typeset out.mode="${str/~(Elr)[[:space:]]*([[:digit:]]+)[[:space:]]+([[:digit:]]+)[[:space:]]+([[:alpha:]-]+)[[:space:]]+([[:digit:]]+)[[:space:]]+([[:alnum:]]+)[[:space:]]+([[:alnum:]]+)[[:space:]]+([[:digit:]]+)[[:space:]]+([[:alpha:]]*[[:space:]]+[[:digit:]]*[[:space:]]+[[:digit:]:]+)[[:space:]]+(.+)/\3}"
100*10898Sroland.mainz@nrubsig.org	integer out.numlinks="${str/~(Elr)[[:space:]]*([[:digit:]]+)[[:space:]]+([[:digit:]]+)[[:space:]]+([[:alpha:]-]+)[[:space:]]+([[:digit:]]+)[[:space:]]+([[:alnum:]]+)[[:space:]]+([[:alnum:]]+)[[:space:]]+([[:digit:]]+)[[:space:]]+([[:alpha:]]*[[:space:]]+[[:digit:]]*[[:space:]]+[[:digit:]:]+)[[:space:]]+(.+)/\4}"
101*10898Sroland.mainz@nrubsig.org	compound out.owner=(
102*10898Sroland.mainz@nrubsig.org		typeset user="${str/~(Elr)[[:space:]]*([[:digit:]]+)[[:space:]]+([[:digit:]]+)[[:space:]]+([[:alpha:]-]+)[[:space:]]+([[:digit:]]+)[[:space:]]+([[:alnum:]]+)[[:space:]]+([[:alnum:]]+)[[:space:]]+([[:digit:]]+)[[:space:]]+([[:alpha:]]*[[:space:]]+[[:digit:]]*[[:space:]]+[[:digit:]:]+)[[:space:]]+(.+)/\5}"
103*10898Sroland.mainz@nrubsig.org		typeset group="${str/~(Elr)[[:space:]]*([[:digit:]]+)[[:space:]]+([[:digit:]]+)[[:space:]]+([[:alpha:]-]+)[[:space:]]+([[:digit:]]+)[[:space:]]+([[:alnum:]]+)[[:space:]]+([[:alnum:]]+)[[:space:]]+([[:digit:]]+)[[:space:]]+([[:alpha:]]*[[:space:]]+[[:digit:]]*[[:space:]]+[[:digit:]:]+)[[:space:]]+(.+)/\6}"
104*10898Sroland.mainz@nrubsig.org	)
105*10898Sroland.mainz@nrubsig.org	integer out.filesize="${str/~(Elr)[[:space:]]*([[:digit:]]+)[[:space:]]+([[:digit:]]+)[[:space:]]+([[:alpha:]-]+)[[:space:]]+([[:digit:]]+)[[:space:]]+([[:alnum:]]+)[[:space:]]+([[:alnum:]]+)[[:space:]]+([[:digit:]]+)[[:space:]]+([[:alpha:]]*[[:space:]]+[[:digit:]]*[[:space:]]+[[:digit:]:]+)[[:space:]]+(.+)/\7}"
106*10898Sroland.mainz@nrubsig.org	typeset out.date="${str/~(Elr)[[:space:]]*([[:digit:]]+)[[:space:]]+([[:digit:]]+)[[:space:]]+([[:alpha:]-]+)[[:space:]]+([[:digit:]]+)[[:space:]]+([[:alnum:]]+)[[:space:]]+([[:alnum:]]+)[[:space:]]+([[:digit:]]+)[[:space:]]+([[:alpha:]]*[[:space:]]+[[:digit:]]*[[:space:]]+[[:digit:]:]+)[[:space:]]+(.+)/\8}"
107*10898Sroland.mainz@nrubsig.org	typeset out.filepath="${str/~(Elr)[[:space:]]*([[:digit:]]+)[[:space:]]+([[:digit:]]+)[[:space:]]+([[:alpha:]-]+)[[:space:]]+([[:digit:]]+)[[:space:]]+([[:alnum:]]+)[[:space:]]+([[:alnum:]]+)[[:space:]]+([[:digit:]]+)[[:space:]]+([[:alpha:]]*[[:space:]]+[[:digit:]]*[[:space:]]+[[:digit:]:]+)[[:space:]]+(.+)/\9}"
108*10898Sroland.mainz@nrubsig.org
109*10898Sroland.mainz@nrubsig.org	return 0
110*10898Sroland.mainz@nrubsig.org}
111*10898Sroland.mainz@nrubsig.org
112*10898Sroland.mainz@nrubsig.orgfunction usage
113*10898Sroland.mainz@nrubsig.org{
114*10898Sroland.mainz@nrubsig.org	OPTIND=0
115*10898Sroland.mainz@nrubsig.org	getopts -a "${progname}" "${simplefileattributetree1_usage}" OPT '-?'
116*10898Sroland.mainz@nrubsig.org	exit 2
117*10898Sroland.mainz@nrubsig.org}
118*10898Sroland.mainz@nrubsig.org
119*10898Sroland.mainz@nrubsig.org# main
120*10898Sroland.mainz@nrubsig.orgbuiltin basename
121*10898Sroland.mainz@nrubsig.orgbuiltin dirname
122*10898Sroland.mainz@nrubsig.org
123*10898Sroland.mainz@nrubsig.orgset -o noglob
124*10898Sroland.mainz@nrubsig.orgset -o nounset
125*10898Sroland.mainz@nrubsig.org
126*10898Sroland.mainz@nrubsig.org# tree base
127*10898Sroland.mainz@nrubsig.orgcompound filetree
128*10898Sroland.mainz@nrubsig.org
129*10898Sroland.mainz@nrubsig.org# benchmark data
130*10898Sroland.mainz@nrubsig.orgcompound bench=(
131*10898Sroland.mainz@nrubsig.org	float start
132*10898Sroland.mainz@nrubsig.org	float stop
133*10898Sroland.mainz@nrubsig.org)
134*10898Sroland.mainz@nrubsig.org
135*10898Sroland.mainz@nrubsig.orgcompound appconfig=(
136*10898Sroland.mainz@nrubsig.org	typeset do_benchmarking=false
137*10898Sroland.mainz@nrubsig.org	compound do_record=(
138*10898Sroland.mainz@nrubsig.org		typeset content=false
139*10898Sroland.mainz@nrubsig.org		typeset filetype=false
140*10898Sroland.mainz@nrubsig.org	)
141*10898Sroland.mainz@nrubsig.org)
142*10898Sroland.mainz@nrubsig.org
143*10898Sroland.mainz@nrubsig.org
144*10898Sroland.mainz@nrubsig.orginteger i
145*10898Sroland.mainz@nrubsig.org
146*10898Sroland.mainz@nrubsig.orgtypeset progname="${ basename "${0}" ; }"
147*10898Sroland.mainz@nrubsig.org
148*10898Sroland.mainz@nrubsig.orgtypeset -r simplefileattributetree1_usage=$'+
149*10898Sroland.mainz@nrubsig.org[-?\n@(#)\$Id: simplefileattributetree1 (Roland Mainz) 2009-06-26 \$\n]
150*10898Sroland.mainz@nrubsig.org[-author?Roland Mainz <roland.mainz@nrubsig.org>]
151*10898Sroland.mainz@nrubsig.org[+NAME?simplefileattributetree1 - generate compound variable tree which contains file names and their attributes]
152*10898Sroland.mainz@nrubsig.org[+DESCRIPTION?\bsimplefileattributetree1\b is a simple variable tree
153*10898Sroland.mainz@nrubsig.org	demo which builds a compound variable tree based on the output
154*10898Sroland.mainz@nrubsig.org	of /usr/xpg4/bin/file which contains the file name, the file attributes
155*10898Sroland.mainz@nrubsig.org	and optionally file type and content]
156*10898Sroland.mainz@nrubsig.org[b:benchmark?Print time needed to generate the tree.]
157*10898Sroland.mainz@nrubsig.org[c:includecontent?Include the file\'s content in the tree, split into 1kb blocks.]
158*10898Sroland.mainz@nrubsig.org[t:includefiletype?Include the file type (output of /usr/xpg4/bin/file).]
159*10898Sroland.mainz@nrubsig.org
160*10898Sroland.mainz@nrubsig.orgpath
161*10898Sroland.mainz@nrubsig.org
162*10898Sroland.mainz@nrubsig.org[+SEE ALSO?\bksh93\b(1), \bfile\b(1), \bfind\b(1)]
163*10898Sroland.mainz@nrubsig.org'
164*10898Sroland.mainz@nrubsig.org
165*10898Sroland.mainz@nrubsig.orgwhile getopts -a "${progname}" "${simplefileattributetree1_usage}" OPT ; do
166*10898Sroland.mainz@nrubsig.org#	printmsg "## OPT=|${OPT}|, OPTARG=|${OPTARG}|"
167*10898Sroland.mainz@nrubsig.org	case ${OPT} in
168*10898Sroland.mainz@nrubsig.org		b)	appconfig.do_benchmarking="true"	;;
169*10898Sroland.mainz@nrubsig.org		+b)	appconfig.do_benchmarking="false"	;;
170*10898Sroland.mainz@nrubsig.org		c)	appconfig.do_record.content="true"	;;
171*10898Sroland.mainz@nrubsig.org		+c)	appconfig.do_record.content="false"	;;
172*10898Sroland.mainz@nrubsig.org		t)	appconfig.do_record.filetype="true"	;;
173*10898Sroland.mainz@nrubsig.org		+t)	appconfig.do_record.filetype="false"	;;
174*10898Sroland.mainz@nrubsig.org		*)	usage ;;
175*10898Sroland.mainz@nrubsig.org	esac
176*10898Sroland.mainz@nrubsig.orgdone
177*10898Sroland.mainz@nrubsig.orgshift $((OPTIND-1))
178*10898Sroland.mainz@nrubsig.org
179*10898Sroland.mainz@nrubsig.org
180*10898Sroland.mainz@nrubsig.org# argument prechecks
181*10898Sroland.mainz@nrubsig.orgif (( $# == 0 )) ; then
182*10898Sroland.mainz@nrubsig.org	print -u2 -f "%s: Missing <path> argument.\n" "${progname}"
183*10898Sroland.mainz@nrubsig.org	exit 1
184*10898Sroland.mainz@nrubsig.orgfi
185*10898Sroland.mainz@nrubsig.org
186*10898Sroland.mainz@nrubsig.org
187*10898Sroland.mainz@nrubsig.orgprint -u2 -f "# reading file names...\n"
188*10898Sroland.mainz@nrubsig.orgwhile (( $# > 0 )) ; do
189*10898Sroland.mainz@nrubsig.org	# "ulimit -c 0" use used to force ksh93 to use a seperate process for subshells,
190*10898Sroland.mainz@nrubsig.org	# this is used to work around a bug with LC_ALL changes bleeding through subshells
191*10898Sroland.mainz@nrubsig.org	IFS=$'\n' ; typeset -a findls_lines=( $(ulimit -c 0 ; LC_ALL=C find "$1" -type f -ls) ) ; IFS=$' \t\n'
192*10898Sroland.mainz@nrubsig.org	shift
193*10898Sroland.mainz@nrubsig.orgdone
194*10898Sroland.mainz@nrubsig.org
195*10898Sroland.mainz@nrubsig.org
196*10898Sroland.mainz@nrubsig.orgprint -u2 -f "# building tree...\n"
197*10898Sroland.mainz@nrubsig.org
198*10898Sroland.mainz@nrubsig.org${appconfig.do_benchmarking} && (( bench.start=SECONDS ))
199*10898Sroland.mainz@nrubsig.org
200*10898Sroland.mainz@nrubsig.orgfor (( i=0 ; i < ${#findls_lines[@]} ; i++ )) ; do
201*10898Sroland.mainz@nrubsig.org	compound parseddata
202*10898Sroland.mainz@nrubsig.org	typeset treenodename
203*10898Sroland.mainz@nrubsig.org
204*10898Sroland.mainz@nrubsig.org	# parse "find -ls" output
205*10898Sroland.mainz@nrubsig.org	parse_findls parseddata "${findls_lines[i]}"
206*10898Sroland.mainz@nrubsig.org
207*10898Sroland.mainz@nrubsig.org	# add node to tree and return it's absolute name in "treenodename"
208*10898Sroland.mainz@nrubsig.org	add_file_to_tree filetree "${parseddata.filepath}" treenodename
209*10898Sroland.mainz@nrubsig.org
210*10898Sroland.mainz@nrubsig.org	# merge parsed "find -ls" output into tree node
211*10898Sroland.mainz@nrubsig.org	nameref treenode="${treenodename}"
212*10898Sroland.mainz@nrubsig.org	treenode+=parseddata
213*10898Sroland.mainz@nrubsig.org
214*10898Sroland.mainz@nrubsig.org	# extras (calculated from the existing values in "parseddata")
215*10898Sroland.mainz@nrubsig.org	typeset treenode.dirname="${ dirname "${treenode.filepath}" ; }"
216*10898Sroland.mainz@nrubsig.org	typeset treenode.basename="${ basename "${treenode.filepath}" ; }"
217*10898Sroland.mainz@nrubsig.org
218*10898Sroland.mainz@nrubsig.org	if ${appconfig.do_record.filetype} ; then
219*10898Sroland.mainz@nrubsig.org		# Using /usr/(xpg4/)*/bin/file requires a |fork()|+|exec()| which makes the script a few hundred times slower... ;-(
220*10898Sroland.mainz@nrubsig.org		typeset treenode.filetype="$(file "${treenode.filepath}")"
221*10898Sroland.mainz@nrubsig.org	fi
222*10898Sroland.mainz@nrubsig.org
223*10898Sroland.mainz@nrubsig.org	if ${appconfig.do_record.content} ; then
224*10898Sroland.mainz@nrubsig.org		if [[ -r "${treenode.filepath}" ]] ; then
225*10898Sroland.mainz@nrubsig.org			# We use an array of compound variables here to support
226*10898Sroland.mainz@nrubsig.org			# files with holes (and later alternative streams, too)
227*10898Sroland.mainz@nrubsig.org			compound -a treenode.content
228*10898Sroland.mainz@nrubsig.org			integer cl=0
229*10898Sroland.mainz@nrubsig.org			while \
230*10898Sroland.mainz@nrubsig.org				{
231*10898Sroland.mainz@nrubsig.org					treenode.content[${cl}]=(
232*10898Sroland.mainz@nrubsig.org						typeset type="data" # (todo: "add support for "holes" (sparse files))
233*10898Sroland.mainz@nrubsig.org						typeset -b bin
234*10898Sroland.mainz@nrubsig.org					)
235*10898Sroland.mainz@nrubsig.org					read -n1024 treenode.content[${cl}].bin
236*10898Sroland.mainz@nrubsig.org				} ; do
237*10898Sroland.mainz@nrubsig.org				(( cl++ ))
238*10898Sroland.mainz@nrubsig.org			done < "${treenode.filepath}"
239*10898Sroland.mainz@nrubsig.org			unset treenode.content[${cl}]
240*10898Sroland.mainz@nrubsig.org
241*10898Sroland.mainz@nrubsig.org			typeset -A treenode.hashsum=(
242*10898Sroland.mainz@nrubsig.org				[md5]="$(sum -x md5 < "${treenode.filepath}")"
243*10898Sroland.mainz@nrubsig.org				[sha512]="$(sum -x sha512 < "${treenode.filepath}")"
244*10898Sroland.mainz@nrubsig.org			)
245*10898Sroland.mainz@nrubsig.org
246*10898Sroland.mainz@nrubsig.org			# we do this for internal debugging only
247*10898Sroland.mainz@nrubsig.org			if [[ "${ {
248*10898Sroland.mainz@nrubsig.org					integer j
249*10898Sroland.mainz@nrubsig.org					for (( j=0 ; j < ${#treenode.content[@]} ; j++ )) ; do
250*10898Sroland.mainz@nrubsig.org						printf "%B" treenode.content[$j].bin
251*10898Sroland.mainz@nrubsig.org					done
252*10898Sroland.mainz@nrubsig.org				} | sum -x sha512 ; }" != "${treenode.hashsum[sha512]}" ]] ; then
253*10898Sroland.mainz@nrubsig.org				# this should never happen...
254*10898Sroland.mainz@nrubsig.org				print -u2 -f "fatal hash mismatch for %s\n" "${treenode.filepath}"
255*10898Sroland.mainz@nrubsig.org				unset treenode.content treenode.hashsum
256*10898Sroland.mainz@nrubsig.org			fi
257*10898Sroland.mainz@nrubsig.org		fi
258*10898Sroland.mainz@nrubsig.org	fi
259*10898Sroland.mainz@nrubsig.orgdone
260*10898Sroland.mainz@nrubsig.org
261*10898Sroland.mainz@nrubsig.org${appconfig.do_benchmarking} && (( bench.stop=SECONDS ))
262*10898Sroland.mainz@nrubsig.org
263*10898Sroland.mainz@nrubsig.org
264*10898Sroland.mainz@nrubsig.orgif ${appconfig.do_benchmarking} ; then
265*10898Sroland.mainz@nrubsig.org	# print benchmark data
266*10898Sroland.mainz@nrubsig.org	print -u2 -f "# time used: %f\n" $((bench.stop - bench.start))
267*10898Sroland.mainz@nrubsig.orgfi
268*10898Sroland.mainz@nrubsig.org
269*10898Sroland.mainz@nrubsig.org# print variable tree
270*10898Sroland.mainz@nrubsig.orgprint -v filetree
271*10898Sroland.mainz@nrubsig.org
272*10898Sroland.mainz@nrubsig.orgexit 0
273*10898Sroland.mainz@nrubsig.org# EOF.
274