1*b30d1939SAndy Fiddaman########################################################################
2*b30d1939SAndy Fiddaman#                                                                      #
3*b30d1939SAndy Fiddaman#               This software is part of the ast package               #
4*b30d1939SAndy Fiddaman#          Copyright (c) 1994-2011 AT&T Intellectual Property          #
5*b30d1939SAndy Fiddaman#                      and is licensed under the                       #
6*b30d1939SAndy Fiddaman#                 Eclipse Public License, Version 1.0                  #
7*b30d1939SAndy Fiddaman#                    by AT&T Intellectual Property                     #
8*b30d1939SAndy Fiddaman#                                                                      #
9*b30d1939SAndy Fiddaman#                A copy of the License is available at                 #
10*b30d1939SAndy Fiddaman#          http://www.eclipse.org/org/documents/epl-v10.html           #
11*b30d1939SAndy Fiddaman#         (with md5 checksum b35adb5213ca9657e911e9befb180842)         #
12*b30d1939SAndy Fiddaman#                                                                      #
13*b30d1939SAndy Fiddaman#              Information and Software Systems Research               #
14*b30d1939SAndy Fiddaman#                            AT&T Research                             #
15*b30d1939SAndy Fiddaman#                           Florham Park NJ                            #
16*b30d1939SAndy Fiddaman#                                                                      #
17*b30d1939SAndy Fiddaman#                 Glenn Fowler <gsf@research.att.com>                  #
18*b30d1939SAndy Fiddaman#                                                                      #
19*b30d1939SAndy Fiddaman########################################################################
20*b30d1939SAndy Fiddaman: replicate directory hierarchies
21*b30d1939SAndy Fiddaman
22*b30d1939SAndy FiddamanCOMMAND=ditto
23*b30d1939SAndy Fiddamancase `(getopts '[-][123:xyz]' opt --xyz; echo 0$opt) 2>/dev/null` in
24*b30d1939SAndy Fiddaman0123)	ARGV0="-a $COMMAND"
25*b30d1939SAndy Fiddaman	USAGE=$'
26*b30d1939SAndy Fiddaman[-?
27*b30d1939SAndy Fiddaman@(#)$Id: ditto (AT&T Labs Research) 2010-11-22 $
28*b30d1939SAndy Fiddaman]
29*b30d1939SAndy Fiddaman'$USAGE_LICENSE$'
30*b30d1939SAndy Fiddaman[+NAME?ditto - replicate directory hierarchies]
31*b30d1939SAndy Fiddaman[+DESCRIPTION?\bditto\b replicates the \asource\a directory hierarchy
32*b30d1939SAndy Fiddaman	to the \adestination\a directory hierarchy. Both \asource\a and
33*b30d1939SAndy Fiddaman	\adestination\a may be of the form
34*b30d1939SAndy Fiddaman	[\auser\a@]][\ahost\a:]][\adirectory\a]]. At least one of
35*b30d1939SAndy Fiddaman	\ahost\a: or \adirectory\a must be specified. The current user is used
36*b30d1939SAndy Fiddaman	if \auser@\a is omitted, the local host is used if \ahost\a: is
37*b30d1939SAndy Fiddaman	omitted, and the user home directory is used if \adirectory\a is
38*b30d1939SAndy Fiddaman	omitted.]
39*b30d1939SAndy Fiddaman[+?Remote hosts and files are accessed via \bssh\b(1) or \brsh\b(1). \bksh\b(1),
40*b30d1939SAndy Fiddaman	\bpax\b(1), and \btw\b(1) must be installed on the local and remote hosts.]
41*b30d1939SAndy Fiddaman[+?For each source file \bditto\b does one of these actions:]{
42*b30d1939SAndy Fiddaman	[+chmod|chown?change the mode and/or ownership of the destination
43*b30d1939SAndy Fiddaman		file to match the source]
44*b30d1939SAndy Fiddaman	[+copy?copy the source file to the destination]
45*b30d1939SAndy Fiddaman	[+delete?delete the destination file]
46*b30d1939SAndy Fiddaman	[+skip?the destination file is not changed]
47*b30d1939SAndy Fiddaman}
48*b30d1939SAndy Fiddaman[+?The source and destination hierarchies are generated by \btw\b(1) with
49*b30d1939SAndy Fiddaman	the \b--logical\b option. An \b--expr\b option may
50*b30d1939SAndy Fiddaman	be specified to prune the search. The \btw\b searches are relative to
51*b30d1939SAndy Fiddaman	the \asource\a and \adestination\a directories.]
52*b30d1939SAndy Fiddaman[c:checksum?Copy if the \btw\b(1) 32x4 checksum mismatches.]
53*b30d1939SAndy Fiddaman[d:delete?Delete \adestination\a files that are not in the \asource\a.]
54*b30d1939SAndy Fiddaman[e:expr?\btw\b(1) select expression.]:[tw-expression]
55*b30d1939SAndy Fiddaman[m!:mode?Preserve file mode.]
56*b30d1939SAndy Fiddaman[n:show?Show the operations but do not exectute.]
57*b30d1939SAndy Fiddaman[o:owner?Preserve file user and group ownership.]
58*b30d1939SAndy Fiddaman[p:physical?Generate source and destination hierarchies by \btw\b(1) with
59*b30d1939SAndy Fiddaman	the \b--physical\b option.]
60*b30d1939SAndy Fiddaman[r:remote?The remote access protocol; either \bssh\b or
61*b30d1939SAndy Fiddaman	\brsh\b.]:[protocol:=ssh]
62*b30d1939SAndy Fiddaman[u:update?Copy only if the \asource\a file is newer than the
63*b30d1939SAndy Fiddaman	\adestination\a file.]
64*b30d1939SAndy Fiddaman[v:verbose?Trace the operations as they are executed.]
65*b30d1939SAndy Fiddaman[D:debug?Enable the debug trace.]
66*b30d1939SAndy Fiddaman
67*b30d1939SAndy Fiddamansource destination
68*b30d1939SAndy Fiddaman
69*b30d1939SAndy Fiddaman[+SEE ALSO?\brdist\b(1), \brsync\b(1), \brsh\b(1), \bssh\b(1), \btw\b(1)]
70*b30d1939SAndy Fiddaman'
71*b30d1939SAndy Fiddaman	;;
72*b30d1939SAndy Fiddaman*)	ARGV0=""
73*b30d1939SAndy Fiddaman	USAGE="de:[tw-expression]mnouvD source destination"
74*b30d1939SAndy Fiddaman	;;
75*b30d1939SAndy Fiddamanesac
76*b30d1939SAndy Fiddaman
77*b30d1939SAndy Fiddamanusage()
78*b30d1939SAndy Fiddaman{
79*b30d1939SAndy Fiddaman	OPTIND=0
80*b30d1939SAndy Fiddaman	getopts $ARGV0 "$USAGE" OPT '-?'
81*b30d1939SAndy Fiddaman	exit 2
82*b30d1939SAndy Fiddaman}
83*b30d1939SAndy Fiddaman
84*b30d1939SAndy Fiddamanparse() # id user@host:dir
85*b30d1939SAndy Fiddaman{
86*b30d1939SAndy Fiddaman	typeset id dir user host
87*b30d1939SAndy Fiddaman	id=$1
88*b30d1939SAndy Fiddaman	dir=$2
89*b30d1939SAndy Fiddaman	(( debug || ! exec )) && print -r $id $dir
90*b30d1939SAndy Fiddaman	if [[ $dir == *@* ]]
91*b30d1939SAndy Fiddaman	then
92*b30d1939SAndy Fiddaman		user=${dir%%@*}
93*b30d1939SAndy Fiddaman		dir=${dir#${user}@}
94*b30d1939SAndy Fiddaman	else
95*b30d1939SAndy Fiddaman		user=
96*b30d1939SAndy Fiddaman	fi
97*b30d1939SAndy Fiddaman	if [[ $dir == *:* ]]
98*b30d1939SAndy Fiddaman	then
99*b30d1939SAndy Fiddaman		host=${dir%%:*}
100*b30d1939SAndy Fiddaman		dir=${dir#${host}:}
101*b30d1939SAndy Fiddaman	else
102*b30d1939SAndy Fiddaman		host=
103*b30d1939SAndy Fiddaman	fi
104*b30d1939SAndy Fiddaman	if [[ $user ]]
105*b30d1939SAndy Fiddaman	then
106*b30d1939SAndy Fiddaman		user="-l $user"
107*b30d1939SAndy Fiddaman		if [[ ! $host ]]
108*b30d1939SAndy Fiddaman		then
109*b30d1939SAndy Fiddaman			host=$(hostname)
110*b30d1939SAndy Fiddaman		fi
111*b30d1939SAndy Fiddaman	fi
112*b30d1939SAndy Fiddaman	eval ${id}_user='$user'
113*b30d1939SAndy Fiddaman	eval ${id}_host='$host'
114*b30d1939SAndy Fiddaman	eval ${id}_dir='$dir'
115*b30d1939SAndy Fiddaman}
116*b30d1939SAndy Fiddaman
117*b30d1939SAndy Fiddaman# initialize
118*b30d1939SAndy Fiddaman
119*b30d1939SAndy Fiddamantypeset -A chown chmod
120*b30d1939SAndy Fiddamantypeset tw cp rm link
121*b30d1939SAndy Fiddamaninteger ntw=0 ncp=0 nrm=0 nlink=0 n
122*b30d1939SAndy Fiddaman
123*b30d1939SAndy Fiddamantypeset src_user src_host src_path src_type src_uid src_gid src_perm src_sum
124*b30d1939SAndy Fiddamantypeset dst_user dst_host dst_path dst_type dst_uid dst_gid dst_perm dst_sum
125*b30d1939SAndy Fiddamaninteger src_size src_mtime src_eof
126*b30d1939SAndy Fiddamaninteger dst_size dst_mtime dst_eof
127*b30d1939SAndy Fiddaman
128*b30d1939SAndy Fiddamaninteger debug=0 delete=0 exec=1 mode=1 owner=0 update=0 verbose=0 logical
129*b30d1939SAndy Fiddaman
130*b30d1939SAndy Fiddamantypeset remote=ssh trace
131*b30d1939SAndy Fiddamantypeset checksum='"-"' pax="pax"
132*b30d1939SAndy Fiddamantypeset paxreadflags="" paxwriteflags="--write --format=tgz --nosummary"
133*b30d1939SAndy Fiddaman
134*b30d1939SAndy Fiddamantw[ntw++]=tw
135*b30d1939SAndy Fiddaman(( logical=ntw ))
136*b30d1939SAndy Fiddamantw[ntw++]=--logical
137*b30d1939SAndy Fiddamantw[ntw++]=--chop
138*b30d1939SAndy Fiddamantw[ntw++]=--ignore-errors
139*b30d1939SAndy Fiddamantw[ntw++]=--expr=sort:name
140*b30d1939SAndy Fiddaman
141*b30d1939SAndy Fiddaman# grab the options
142*b30d1939SAndy Fiddaman
143*b30d1939SAndy Fiddamanwhile	getopts $ARGV0 "$USAGE" OPT
144*b30d1939SAndy Fiddamando	case $OPT in
145*b30d1939SAndy Fiddaman	c)	checksum=checksum ;;
146*b30d1939SAndy Fiddaman	d)	delete=1 ;;
147*b30d1939SAndy Fiddaman	e)	tw[ntw++]=--expr=\"$OPTARG\" ;;
148*b30d1939SAndy Fiddaman	m)	mode=0 ;;
149*b30d1939SAndy Fiddaman	n)	exec=0 verbose=1 ;;
150*b30d1939SAndy Fiddaman	o)	owner=1 ;;
151*b30d1939SAndy Fiddaman	p)	tw[logical]=--physical ;;
152*b30d1939SAndy Fiddaman	r)	remote=$OPTARG ;;
153*b30d1939SAndy Fiddaman	u)	update=1 ;;
154*b30d1939SAndy Fiddaman	v)	verbose=1 ;;
155*b30d1939SAndy Fiddaman	D)	debug=1 ;;
156*b30d1939SAndy Fiddaman	*)	usage ;;
157*b30d1939SAndy Fiddaman	esac
158*b30d1939SAndy Fiddamandone
159*b30d1939SAndy Fiddamanshift $OPTIND-1
160*b30d1939SAndy Fiddamanif (( $# != 2 ))
161*b30d1939SAndy Fiddamanthen	usage
162*b30d1939SAndy Fiddamanfi
163*b30d1939SAndy Fiddamantw[ntw++]=--expr=\''action:printf("%d\t%d\t%s\t%s\t%s\t%-.1s\t%o\t%s\t%s\n", size, mtime, '$checksum', uid, gid, mode, perm, path, symlink);'\'
164*b30d1939SAndy Fiddamanif (( exec ))
165*b30d1939SAndy Fiddamanthen
166*b30d1939SAndy Fiddaman	paxreadflags="$paxreadflags --read"
167*b30d1939SAndy Fiddamanfi
168*b30d1939SAndy Fiddamanif (( verbose ))
169*b30d1939SAndy Fiddamanthen
170*b30d1939SAndy Fiddaman	paxreadflags="$paxreadflags --verbose"
171*b30d1939SAndy Fiddamanfi
172*b30d1939SAndy Fiddaman
173*b30d1939SAndy Fiddaman# start the source and destination path list generators
174*b30d1939SAndy Fiddaman
175*b30d1939SAndy Fiddamanparse src "$1"
176*b30d1939SAndy Fiddamanparse dst "$2"
177*b30d1939SAndy Fiddaman
178*b30d1939SAndy Fiddaman# the |& command may exit before the exec &p
179*b30d1939SAndy Fiddaman# the print sync + read delays the |& until the exec &p finishes
180*b30d1939SAndy Fiddaman
181*b30d1939SAndy Fiddamanif [[ $src_host ]]
182*b30d1939SAndy Fiddamanthen	($remote $src_user $src_host "{ test ! -f .profile || . ./.profile ;} && cd $src_dir && read && ${tw[*]}") 2>&1 |&
183*b30d1939SAndy Fiddamanelse	(cd $src_dir && read && eval "${tw[@]}") 2>&1 |&
184*b30d1939SAndy Fiddamanfi
185*b30d1939SAndy Fiddamanexec 5<&p 7>&p
186*b30d1939SAndy Fiddamanprint -u7 sync
187*b30d1939SAndy Fiddamanexec 7>&-
188*b30d1939SAndy Fiddaman
189*b30d1939SAndy Fiddamanif [[ $dst_host ]]
190*b30d1939SAndy Fiddamanthen	($remote $dst_user $dst_host "{ test ! -f .profile || . ./.profile ;} && cd $dst_dir && read && ${tw[*]}") 2>&1 |&
191*b30d1939SAndy Fiddamanelse	(cd $dst_dir && read && eval "${tw[@]}") 2>&1 |&
192*b30d1939SAndy Fiddamanfi
193*b30d1939SAndy Fiddamanexec 6<&p 7>&p
194*b30d1939SAndy Fiddamanprint -u7 sync
195*b30d1939SAndy Fiddamanexec 7>&-
196*b30d1939SAndy Fiddaman
197*b30d1939SAndy Fiddaman# scan through the sorted path lists
198*b30d1939SAndy Fiddaman
199*b30d1939SAndy Fiddamanif (( exec ))
200*b30d1939SAndy Fiddamanthen
201*b30d1939SAndy Fiddaman	src_skip=*
202*b30d1939SAndy Fiddaman	dst_skip=*
203*b30d1939SAndy Fiddamanelse
204*b30d1939SAndy Fiddaman	src_skip=
205*b30d1939SAndy Fiddaman	dst_skip=
206*b30d1939SAndy Fiddamanfi
207*b30d1939SAndy Fiddamansrc_path='' src_eof=0
208*b30d1939SAndy Fiddamandst_path='' dst_eof=0
209*b30d1939SAndy Fiddamanifs=${IFS-$' \t\n'}
210*b30d1939SAndy FiddamanIFS=$'\t'
211*b30d1939SAndy Fiddamanwhile	:
212*b30d1939SAndy Fiddamando
213*b30d1939SAndy Fiddaman	# get the next source path
214*b30d1939SAndy Fiddaman
215*b30d1939SAndy Fiddaman	if [[ ! $src_path ]] &&	(( ! src_eof ))
216*b30d1939SAndy Fiddaman	then
217*b30d1939SAndy Fiddaman		if read -r -u5 text src_mtime src_sum src_uid src_gid src_type src_perm src_path src_link
218*b30d1939SAndy Fiddaman		then
219*b30d1939SAndy Fiddaman			if [[ $text != +([[:digit:]]) ]]
220*b30d1939SAndy Fiddaman			then
221*b30d1939SAndy Fiddaman				print -u2 $COMMAND: source: "'$text'"
222*b30d1939SAndy Fiddaman				src_path=
223*b30d1939SAndy Fiddaman				continue
224*b30d1939SAndy Fiddaman			fi
225*b30d1939SAndy Fiddaman			src_size=$text
226*b30d1939SAndy Fiddaman		elif (( dst_eof ))
227*b30d1939SAndy Fiddaman		then
228*b30d1939SAndy Fiddaman			break
229*b30d1939SAndy Fiddaman		elif (( src_size==0 ))
230*b30d1939SAndy Fiddaman		then
231*b30d1939SAndy Fiddaman			exit 1
232*b30d1939SAndy Fiddaman		else
233*b30d1939SAndy Fiddaman			src_path=
234*b30d1939SAndy Fiddaman			src_eof=1
235*b30d1939SAndy Fiddaman		fi
236*b30d1939SAndy Fiddaman	fi
237*b30d1939SAndy Fiddaman
238*b30d1939SAndy Fiddaman	# get the next destination path
239*b30d1939SAndy Fiddaman
240*b30d1939SAndy Fiddaman	if [[ ! $dst_path ]] && (( ! dst_eof ))
241*b30d1939SAndy Fiddaman	then
242*b30d1939SAndy Fiddaman		if read -r -u6 text dst_mtime dst_sum dst_uid dst_gid dst_type dst_perm dst_path dst_link
243*b30d1939SAndy Fiddaman		then
244*b30d1939SAndy Fiddaman			if [[ $text != +([[:digit:]]) ]]
245*b30d1939SAndy Fiddaman			then
246*b30d1939SAndy Fiddaman				print -u2 $COMMAND: destination: $text
247*b30d1939SAndy Fiddaman				dst_path=
248*b30d1939SAndy Fiddaman				continue
249*b30d1939SAndy Fiddaman			fi
250*b30d1939SAndy Fiddaman			dst_size=$text
251*b30d1939SAndy Fiddaman		elif (( src_eof ))
252*b30d1939SAndy Fiddaman		then
253*b30d1939SAndy Fiddaman			break
254*b30d1939SAndy Fiddaman		elif (( dst_size==0 ))
255*b30d1939SAndy Fiddaman		then
256*b30d1939SAndy Fiddaman			exit 1
257*b30d1939SAndy Fiddaman		else
258*b30d1939SAndy Fiddaman			dst_path=
259*b30d1939SAndy Fiddaman			dst_eof=1
260*b30d1939SAndy Fiddaman		fi
261*b30d1939SAndy Fiddaman	fi
262*b30d1939SAndy Fiddaman
263*b30d1939SAndy Fiddaman	# determine the { cp rm chmod chown } ops
264*b30d1939SAndy Fiddaman
265*b30d1939SAndy Fiddaman	if (( debug ))
266*b30d1939SAndy Fiddaman	then
267*b30d1939SAndy Fiddaman		[[ $src_path ]] && print -r -u2 -f $': src %8s %10s %s %s %s %s %3s %s\n' $src_size $src_mtime $src_sum $src_uid $src_gid $src_type $src_perm "$src_path"
268*b30d1939SAndy Fiddaman		[[ $dst_path ]] && print -r -u2 -f $': dst %8s %10s %s %s %s %s %3s %s\n' $dst_size $dst_mtime $dst_sum $dst_uid $dst_gid $dst_type $dst_perm "$dst_path"
269*b30d1939SAndy Fiddaman	fi
270*b30d1939SAndy Fiddaman	if [[ $src_path == $dst_path ]]
271*b30d1939SAndy Fiddaman	then
272*b30d1939SAndy Fiddaman		if [[ $src_type != $dst_type ]]
273*b30d1939SAndy Fiddaman		then
274*b30d1939SAndy Fiddaman			rm[nrm++]=$dst_path
275*b30d1939SAndy Fiddaman			if [[ $dst_path != $dst_skip ]]
276*b30d1939SAndy Fiddaman			then
277*b30d1939SAndy Fiddaman				if [[ $dst_type == d ]]
278*b30d1939SAndy Fiddaman				then
279*b30d1939SAndy Fiddaman					dst_skip="$dst_path/*"
280*b30d1939SAndy Fiddaman					print -r rm -r "'$dst_path'"
281*b30d1939SAndy Fiddaman				else
282*b30d1939SAndy Fiddaman					dst_skip=
283*b30d1939SAndy Fiddaman					print -r rm "'$dst_path'"
284*b30d1939SAndy Fiddaman				fi
285*b30d1939SAndy Fiddaman			fi
286*b30d1939SAndy Fiddaman		fi
287*b30d1939SAndy Fiddaman		if [[ $src_type == l ]]
288*b30d1939SAndy Fiddaman		then	if [[ $src_link != $dst_link ]]
289*b30d1939SAndy Fiddaman			then
290*b30d1939SAndy Fiddaman				cp[ncp++]=$src_path
291*b30d1939SAndy Fiddaman				if [[ $src_path != $src_skip ]]
292*b30d1939SAndy Fiddaman				then
293*b30d1939SAndy Fiddaman					src_skip=
294*b30d1939SAndy Fiddaman					print -r cp "'$src_path'"
295*b30d1939SAndy Fiddaman				fi
296*b30d1939SAndy Fiddaman			fi
297*b30d1939SAndy Fiddaman		elif [[ $src_type != d ]] && { (( update && src_mtime > dst_mtime )) || (( ! update )) && { (( src_size != dst_size )) || [[ $src_sum != $dst_sum ]] ;} ;}
298*b30d1939SAndy Fiddaman		then
299*b30d1939SAndy Fiddaman			if [[ $src_path != . ]]
300*b30d1939SAndy Fiddaman			then
301*b30d1939SAndy Fiddaman				cp[ncp++]=$src_path
302*b30d1939SAndy Fiddaman				if [[ $src_path != $src_skip ]]
303*b30d1939SAndy Fiddaman				then
304*b30d1939SAndy Fiddaman					src_skip=
305*b30d1939SAndy Fiddaman					print -r cp "'$src_path'"
306*b30d1939SAndy Fiddaman				fi
307*b30d1939SAndy Fiddaman			fi
308*b30d1939SAndy Fiddaman		else
309*b30d1939SAndy Fiddaman			if (( owner )) && [[ $src_uid != $dst_uid || $src_gid != $dst_gid ]]
310*b30d1939SAndy Fiddaman			then
311*b30d1939SAndy Fiddaman				chown[$src_uid.$src_gid]="${chown[$src_uid.$src_gid]}	'$src_path'"
312*b30d1939SAndy Fiddaman				if [[ $src_path != $src_skip ]]
313*b30d1939SAndy Fiddaman				then
314*b30d1939SAndy Fiddaman					src_skip=
315*b30d1939SAndy Fiddaman					print -r chown $src_uid.$src_gid "'$src_path'"
316*b30d1939SAndy Fiddaman				fi
317*b30d1939SAndy Fiddaman				if (( (src_perm & 07000) || mode && src_perm != dst_perm ))
318*b30d1939SAndy Fiddaman				then
319*b30d1939SAndy Fiddaman					chmod[$src_perm]="${chmod[$src_perm]}	'$src_path'"
320*b30d1939SAndy Fiddaman					if [[ $src_path != $src_skip ]]
321*b30d1939SAndy Fiddaman					then
322*b30d1939SAndy Fiddaman						src_skip=
323*b30d1939SAndy Fiddaman						print -r chmod $src_perm "'$src_path'"
324*b30d1939SAndy Fiddaman					fi
325*b30d1939SAndy Fiddaman				fi
326*b30d1939SAndy Fiddaman			elif (( mode && src_perm != dst_perm ))
327*b30d1939SAndy Fiddaman			then
328*b30d1939SAndy Fiddaman				chmod[$src_perm]="${chmod[$src_perm]}	'$src_path'"
329*b30d1939SAndy Fiddaman				if [[ $src_path != $src_skip ]]
330*b30d1939SAndy Fiddaman				then
331*b30d1939SAndy Fiddaman					src_skip=
332*b30d1939SAndy Fiddaman					print -r chmod $src_perm "'$src_path'"
333*b30d1939SAndy Fiddaman				fi
334*b30d1939SAndy Fiddaman			fi
335*b30d1939SAndy Fiddaman		fi
336*b30d1939SAndy Fiddaman		src_path=
337*b30d1939SAndy Fiddaman		dst_path=
338*b30d1939SAndy Fiddaman	elif [[ ! $dst_path || $src_path && $src_path < $dst_path ]]
339*b30d1939SAndy Fiddaman	then
340*b30d1939SAndy Fiddaman		if [[ $src_path != . ]]
341*b30d1939SAndy Fiddaman		then
342*b30d1939SAndy Fiddaman			cp[ncp++]=$src_path
343*b30d1939SAndy Fiddaman			if [[ $src_path != $src_skip ]]
344*b30d1939SAndy Fiddaman			then
345*b30d1939SAndy Fiddaman				if [[ $src_type == d ]]
346*b30d1939SAndy Fiddaman				then
347*b30d1939SAndy Fiddaman					src_skip="$src_path/*"
348*b30d1939SAndy Fiddaman					print -r cp -r "'$src_path'"
349*b30d1939SAndy Fiddaman				else
350*b30d1939SAndy Fiddaman					src_skip=
351*b30d1939SAndy Fiddaman					print -r cp "'$src_path'"
352*b30d1939SAndy Fiddaman				fi
353*b30d1939SAndy Fiddaman			fi
354*b30d1939SAndy Fiddaman		fi
355*b30d1939SAndy Fiddaman		src_path=
356*b30d1939SAndy Fiddaman	elif [[ $dst_path ]]
357*b30d1939SAndy Fiddaman	then
358*b30d1939SAndy Fiddaman		if (( delete ))
359*b30d1939SAndy Fiddaman		then
360*b30d1939SAndy Fiddaman			rm[nrm++]=$dst_path
361*b30d1939SAndy Fiddaman			if [[ $dst_path != $dst_skip ]]
362*b30d1939SAndy Fiddaman			then
363*b30d1939SAndy Fiddaman				if [[ $dst_type == d ]]
364*b30d1939SAndy Fiddaman				then
365*b30d1939SAndy Fiddaman					dst_skip="$dst_path/*"
366*b30d1939SAndy Fiddaman					print -r rm -r "'$dst_path'"
367*b30d1939SAndy Fiddaman				else
368*b30d1939SAndy Fiddaman					dst_skip=
369*b30d1939SAndy Fiddaman					print -r rm "'$dst_path'"
370*b30d1939SAndy Fiddaman				fi
371*b30d1939SAndy Fiddaman			fi
372*b30d1939SAndy Fiddaman		fi
373*b30d1939SAndy Fiddaman		dst_path=
374*b30d1939SAndy Fiddaman	fi
375*b30d1939SAndy Fiddamandone
376*b30d1939SAndy FiddamanIFS=$ifs
377*b30d1939SAndy Fiddaman
378*b30d1939SAndy Fiddaman(( exec )) || exit 0
379*b30d1939SAndy Fiddaman
380*b30d1939SAndy Fiddaman# generate, transfer and execute the { rm chown chmod } script
381*b30d1939SAndy Fiddaman
382*b30d1939SAndy Fiddamanif (( ${#rm[@]} || ${#chmod[@]} || ${#chown[@]} ))
383*b30d1939SAndy Fiddamanthen
384*b30d1939SAndy Fiddaman	{
385*b30d1939SAndy Fiddaman		if (( verbose ))
386*b30d1939SAndy Fiddaman		then
387*b30d1939SAndy Fiddaman			print -r -- set -x
388*b30d1939SAndy Fiddaman		fi
389*b30d1939SAndy Fiddaman		print -nr -- cd "'$dst_dir'"
390*b30d1939SAndy Fiddaman		n=0
391*b30d1939SAndy Fiddaman		for i in ${rm[@]}
392*b30d1939SAndy Fiddaman		do
393*b30d1939SAndy Fiddaman			if (( --n <= 0 ))
394*b30d1939SAndy Fiddaman			then
395*b30d1939SAndy Fiddaman				n=32
396*b30d1939SAndy Fiddaman				print
397*b30d1939SAndy Fiddaman				print -nr -- rm -rf
398*b30d1939SAndy Fiddaman			fi
399*b30d1939SAndy Fiddaman			print -nr -- " '$i'"
400*b30d1939SAndy Fiddaman		done
401*b30d1939SAndy Fiddaman		for i in ${!chown[@]}
402*b30d1939SAndy Fiddaman		do
403*b30d1939SAndy Fiddaman			n=0
404*b30d1939SAndy Fiddaman			for j in ${chown[$i]}
405*b30d1939SAndy Fiddaman			do
406*b30d1939SAndy Fiddaman				if (( --n <= 0 ))
407*b30d1939SAndy Fiddaman				then
408*b30d1939SAndy Fiddaman					n=32
409*b30d1939SAndy Fiddaman					print
410*b30d1939SAndy Fiddaman					print -nr -- chown $i
411*b30d1939SAndy Fiddaman				fi
412*b30d1939SAndy Fiddaman				print -nr -- " $j"
413*b30d1939SAndy Fiddaman			done
414*b30d1939SAndy Fiddaman		done
415*b30d1939SAndy Fiddaman		for i in ${!chmod[@]}
416*b30d1939SAndy Fiddaman		do
417*b30d1939SAndy Fiddaman			n=0
418*b30d1939SAndy Fiddaman			for j in ${chmod[$i]}
419*b30d1939SAndy Fiddaman			do
420*b30d1939SAndy Fiddaman				if (( --n <= 0 ))
421*b30d1939SAndy Fiddaman				then
422*b30d1939SAndy Fiddaman					n=32
423*b30d1939SAndy Fiddaman					print
424*b30d1939SAndy Fiddaman					print -nr -- chmod $i
425*b30d1939SAndy Fiddaman				fi
426*b30d1939SAndy Fiddaman				print -nr -- " $j"
427*b30d1939SAndy Fiddaman			done
428*b30d1939SAndy Fiddaman		done
429*b30d1939SAndy Fiddaman		print
430*b30d1939SAndy Fiddaman	} | {
431*b30d1939SAndy Fiddaman		if (( ! exec ))
432*b30d1939SAndy Fiddaman		then
433*b30d1939SAndy Fiddaman			cat
434*b30d1939SAndy Fiddaman		elif [[ $dst_host ]]
435*b30d1939SAndy Fiddaman		then
436*b30d1939SAndy Fiddaman			$remote $dst_user $dst_host sh
437*b30d1939SAndy Fiddaman		else
438*b30d1939SAndy Fiddaman			$SHELL
439*b30d1939SAndy Fiddaman		fi
440*b30d1939SAndy Fiddaman	}
441*b30d1939SAndy Fiddamanfi
442*b30d1939SAndy Fiddaman
443*b30d1939SAndy Fiddaman# generate, transfer and read back the { cp } tarball
444*b30d1939SAndy Fiddaman
445*b30d1939SAndy Fiddamanif (( ${#cp[@]} ))
446*b30d1939SAndy Fiddamanthen
447*b30d1939SAndy Fiddaman	{
448*b30d1939SAndy Fiddaman		cd $src_dir &&
449*b30d1939SAndy Fiddaman		print -r -f $'%s\n' "${cp[@]}" |
450*b30d1939SAndy Fiddaman		$pax $paxwriteflags
451*b30d1939SAndy Fiddaman	} | {
452*b30d1939SAndy Fiddaman		if [[ $dst_host ]]
453*b30d1939SAndy Fiddaman		then
454*b30d1939SAndy Fiddaman			$remote $dst_user $dst_host "{ test ! -f .profile || . ./.profile ;} && { test -d \"$dst_dir\" || mkdir -p \"$dst_dir\" ;} && cd \"$dst_dir\" && gunzip | $pax $paxreadflags"
455*b30d1939SAndy Fiddaman		else
456*b30d1939SAndy Fiddaman			( { test -d "$dst_dir" || mkdir -p "$dst_dir" ;} && cd "$dst_dir" && gunzip | $pax $paxreadflags )
457*b30d1939SAndy Fiddaman		fi
458*b30d1939SAndy Fiddaman	}
459*b30d1939SAndy Fiddaman	wait
460*b30d1939SAndy Fiddamanfi
461