Project

General

Profile

Download (26.2 KB) Statistics
| Branch: | Tag: | Revision:
##
# Copyright © 2019, Oracle and/or its affiliates. All rights reserved.
#
# Licensed under the Universal Permissive License v 1.0 as shown at
# http://oss.oracle.com/licenses/upl.
#
# Update this (and the VERSION_HISTORY in version.h) when the version changes.
VERSION = 1.58

#SAN = -fsanitize=thread
#SAN = -fsanitize=address
#GCOV_FLAGS = -fprofile-arcs -ftest-coverage
CFLAGS=-Wall -Wextra -Wshadow -Wconversion -Wpointer-arith -Wmissing-prototypes -Wwrite-strings -Wswitch-enum -Werror -g -O1 -pthread -std=gnu99 $(SAN) $(GCOV_FLAGS)
CPPFLAGS=-DVERSION=\"$(VERSION)\"
#CPPFLAGS+=-DSPEW_ENABLED

# It turns out that we need -lrt (probably because of clock_gettime()
# or else we'll end up with a dependency on glibc 2.17, which often is
# too advanced (e.g., on Oracle Linux 6.9)
LDLIBS=-lrt
LDFLAGS=-pthread $(SAN) $(GCOV_FLAGS)

VALGRIND = valgrind --leak-check=full --error-exitcode=3 -q

PARTAR = partar

default: $(PARTAR) parcp parrm $(PARTAR).1.gz parcp.1.gz parrm.1.gz

# Don't delete intermediate files (specify .SECONDARY with no dependencies)
.SECONDARY:

rpms: ../fss-parallel-tools-$(VERSION).tar.gz fss-parallel-tools.spec
mkdir -p ~/rpmbuild/SOURCES
mkdir -p ~/rpmbuild/SPECS
cp ../fss-parallel-tools-$(VERSION).tar.gz ~/rpmbuild/SOURCES
cp fss-parallel-tools.spec ~/rpmbuild/SPECS
cd ~/rpmbuild/SPECS;rpmbuild -ba fss-parallel-tools.spec
fss-parallel-tools.spec: fss-parallel-tools.spec.in Makefile
sed s/VERSION_DEFINED_IN_MAKEFILE/$(VERSION)/ < $< > $@
mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
current_dir := $(notdir $(patsubst %/,%,$(dir $(mkfile_path))))
SOURCES = gitrev.c $(wildcard *.c *.h common/*.c common/*.h) Makefile LICENSE

../fss-parallel-tools-$(VERSION).tar.gz: $(SOURCES)
tar czf $@ --transform 's,^,fss-parallel-tools/,' $(SOURCES)
tarball: ../fss-parallel-tools-$(VERSION).tar.gz

todo.o: todo.h
dircache.o: dircache.h malloc.h
htable.o: htable.h malloc.h
fwg.o: malloc.h fwg.h hashfun.h
stringset.o: stringset.h hashfun.h malloc.h

####################
# COMMON
####################
# sources
common/assert.o: common/assert.h common/backtrace.h common/spew.h version.h
COMMON_O += common/assert.o
COMMON_O += common/backtrace.o
common/backtrace.o: common/spew.h common/simplest-defs.h common/sparse.h common/backtrace.h
COMMON_O += common/debug-tag.o
common/debug-tag.o: common/debug-tag.h common/simplest-defs.h common/sparse.h
COMMON_O += common/error.o
common/error.o: common/error.h common/simplest-defs.h common/sparse.h
COMMON_O += common/spew.o
common/spew.o: common/spew.h common/backtrace.h common/simplest-defs.h common/tsan.h version.h common/debug-tag.h common/sparse.h common/error.h

fdleak.o: fdleak.h
putils.o: putils.h common/spew.h
parcp.o: putils.h malloc.h version.h sched.h vector-of-strings.h common/spew.h
$(PARTAR).o: putils.h malloc.h version.h sched.h vector-of-strings.h inodemap.h stringset.h vec.h fdleak.h fwg.h common/spew.h
parrm.o: putils.h malloc.h version.h sched.h vector-of-strings.h common/spew.h
vector-of-strings.o: vector-of-strings.h malloc.h
$(PARTAR): $(PARTAR).o putils.o sched.o vector-of-strings.o gitrev.o fwg.o stringset.o vec.o fdleak.o inodemap.o $(COMMON_O)
inodemap.o: inodemap.h malloc.h
parcp: parcp.o putils.o sched.o vector-of-strings.o gitrev.o inodemap.o todo.o $(COMMON_O)
parrm: parrm.o putils.o gitrev.o sched.o vector-of-strings.o $(COMMON_O)

.DELETE_ON_ERROR:

.SUFFIX: .1.gz
%.1.gz: %
PATH=$$PATH:. help2man -N --name="parallel implementation of $(subst par,,$<)" $< | gzip - > $@

gitrev.o: gitrev.c
# Don't create a new gitrev.c file if nothing changed. We don't want
# to rerun all the tests just because I modified the Makefile.
gitrev.c: $(filter-out gitrev.c,$(wildcard *.c *.h common/*.c common/*.h Makefile))
echo \#include \"version.h\" > gitrev_new.c
echo const char gitrev[] = \"$$(git diff-index --quiet HEAD -- || echo "++")$$(git rev-parse HEAD)\"\; >> gitrev_new.c
if ! diff gitrev_new.c gitrev.c >> /dev/null ; then mv gitrev_new.c gitrev.c; fi
setup: $(PARTAR)
rm -rf tar-1.30

# Tests

.PHONY: check
TESTS = fifo tar-1.30 linux-4.15 longfilename3
TESTS_T = $(patsubst %, %.test, $(TESTS))
check: parrm_eaccess_test.test
check: parrm_eaccess_test2.test
check: parrm_eaccess_test3.test
check: parrm_eaccess_test4.test
check: excld.test
check: excld-equal.test
check: error.test
check: linklink.test
check: permissions.test
check: $(TESTS_T) test_fib.run
check: decompression-errors.test
check: parcp0.test parcp1.test parcp2.test parcp3.test parcp4.test parcp5.test parcp6.test parcp7.test
.SUFFIX: .test
%.test: %.partar_test %.parcp_test %.parrm_test %.tar_test
touch $@

.SUFFIX: .partar_test
%.partar_test: %.partar1_diff %.partar2_diff %.partar3_diff %.partar4_diff partar1.test
touch $@

test_fib.run: test_fib
./test_fib
touch $@
$(info VAR="$(COMMON_O)")
test_fib: test_fib.o sched.o $(COMMON_O) gitrev.o
test_fib.o: malloc.h sched.h common/spew.h
sched.o: malloc.h sched.h common/spew.h

#

# These tests run partar in various ways and compare the output to what happened with tar.
# partar_diff1_test runs "partar pxf %.tar"
# partar_diff2_test runs "partar pxf - < %.tar"
# partar_diff3_test runs "partar pxzf %.tar.gz"
# partar_diff4_test runs "partar pxzf - < %.tar.gz"

# partar_test has things that are fifos in it, and we want to ignore
# diff error messages about those. That's what the grep is about in
# the diff line.

output-with-tar output-with-partar1 output-with-partar2 output-with-partar3 output-with-partar4 uncompressed-tars gzipped-tars:
mkdir -p $@

uncompressed-tars/%.tar: test-tars/%.tar.xz | uncompressed-tars
xzcat $< > $@

gzipped-tars/%.tar.gz: uncompressed-tars/%.tar | gzipped-tars
gzip < $< > $@

%.tar_done: uncompressed-tars/%.tar | output-with-tar
rm -rf $(patsubst uncompressed-tars/%.tar,output-with-tar/%, $<)
tar xf $< -C output-with-tar
touch $@

# partar1 tests makes sure that partar works with a named file
%.partar1_done: uncompressed-tars/%.tar $(PARTAR) | output-with-partar1
rm -rf $(patsubst uncompressed-tars/%.tar,output-with-partar1/%, $<)
$(VALGRIND) ./$(PARTAR) xf $< -C output-with-partar1
touch $@

%.partar1_diff: %.tar_done %.partar1_done
diff --no-dereference -r $(patsubst %.tar_done,output-with-tar/%,$<) $(patsubst %.tar_done,output-with-partar1/%,$<) | (! grep -v "is a fifo.*is a fifo")
touch $@

# partar2 tests make sure that partar works from stdin
%.partar2_done: uncompressed-tars/%.tar $(PARTAR) | output-with-partar2
rm -rf $(patsubst uncompressed-tars/%.tar,output-with-partar2/%, $<)
$(VALGRIND) ./$(PARTAR) xf - -C output-with-partar2 < $<
touch $@

%.partar2_diff: %.tar_done %.partar2_done
diff --no-dereference -r $(patsubst %.tar_done,output-with-tar/%,$<) $(patsubst %.tar_done,output-with-partar2/%,$<) | (! grep -v "is a fifo.*is a fifo")
touch $@

# partar3 tests make sure that partar works with a gzipped named file.
.SUFFIX: .partar3_done
%.partar3_done: gzipped-tars/%.tar.gz $(PARTAR) | output-with-partar3
rm -rf $(patsubst gzipped-tars/%.tar.gz,output-with-partar3/%, $<)
$(VALGRIND) ./$(PARTAR) xzf $< -C output-with-partar3
touch $@

.SUFFIX: .partar3_diff
%.partar3_diff: %.tar_done %.partar3_done
diff --no-dereference -r $(patsubst %.tar_done,output-with-tar/%,$<) $(patsubst %.tar_done,output-with-partar3/%,$<) | (! grep -v "is a fifo.*is a fifo")
touch $@

# partar4 tests make sure that partar works with a gzipped stdin
%.partar4_done: gzipped-tars/%.tar.gz $(PARTAR) | output-with-partar4
rm -rf $(patsubst gzipped-tars/%.tar.gz,output-with-partar4/%, $<)
$(VALGRIND) ./$(PARTAR) xzf - -C output-with-partar4 < $<
touch $@

%.partar4_diff: %.tar_done %.partar4_done
diff --no-dereference -r $(patsubst %.tar_done,output-with-tar/%,$<) $(patsubst %.tar_done,output-with-partar4/%,$<) | (! grep -v "is a fifo.*is a fifo")
touch $@

# Test untarring onto a read-only file
partar1.test: $(PARTAR) | partar1.test.dir
rm -rf $@.dir/src $@.dir/dst
mkdir -p $@.dir/src $@.dir/dst
touch $@.dir/dst/readonly
chmod guo-w $@.dir/dst/readonly
echo contents > $@.dir/src/readonly
chmod guo-w $@.dir/src/readonly
set -e; set -o pipefail; $(VALGRIND) ./$(PARTAR) c -C $@.dir/src readonly|$(VALGRIND) ./$(PARTAR) x -C $@.dir/dst
diff -r $@.dir/{src,dst}
touch $@

output-with-parcp output-to-rm output-of-partarred:
mkdir -p $@

.SUFFIX: .parcp_test
# Turn off valgrind for the big linux parcp
linux-4.15.parcp_test: VALGRIND=
%.parcp_test: parcp %.tar_done | output-with-parcp
rm -rf $(patsubst %.parcp_test,output-with-parcp/%, $@)
$(VALGRIND) ./parcp -P 3 $(patsubst %.parcp_test,output-with-tar/%, $@) $(patsubst %.parcp_test,output-with-parcp/%, $@)
diff --no-dereference -r $(patsubst %.parcp_test,output-with-tar/%, $@) $(patsubst %.parcp_test,output-with-parcp/%, $@) | (! grep -v "is a fifo.*is a fifo")
touch $@

.SUFFIX: .parrm_test
%.parrm_test: uncompressed-tars/%.tar parrm $(PARTAR) | output-to-rm
$(VALGRIND) ./$(PARTAR) xf - -C output-to-rm < $<
test -d $(patsubst %.parrm_test,output-to-rm/%,$@)
$(VALGRIND) ./parrm -P 3 $(patsubst %.parrm_test,output-to-rm/%,$@)
test ! -d $(patsubst %.parrm_test,output-to-rm/%,$@)
touch $@

# This test only works on a few cases, since the order of the files isn't unique
.SUFFIX: .tardiff_test
%.tardiff_test: %.tar_out %.partar_out
diff $^
touch $@

.SUFFIX: .tar_test
%.tar_test: %.partar_out %.tar_done | output-of-partarred
rm -rf $(patsubst %.partar_out,output-of-partarred/%,$<)
$(VALGRIND) ./$(PARTAR) xf $< -C output-of-partarred
diff --no-dereference -r $(patsubst %.tar_test,output-with-tar/%,$@) $(patsubst %.tar_test,output-of-partarred/%,$@) | (! grep -v "is a fifo.*is a fifo")
$(EXTRA_TEST)

# These two tests check to see what happens if parrm runs into a
# directory that it hasn't got permission to access. The whole
# directory, or a subdirectory, respectively.

ED = parrm_eaccess_test_dir
parrm_eaccess_test.test: parrm
-chmod u+rwx $(ED) > /dev/null 2>&1 ;true
rm -rf $(ED)
mkdir $(ED)
touch $(ED)/foo
chmod ugo-rwx $(ED)
rm -rf $(ED) > parrm_eaccess_test.out 2>&1 ; test $$? = 1
fgrep Permission parrm_eaccess_test.out > /dev/null
./parrm $(ED) > parrm_eaccess_test.out 2>&1 ; test $$? = 1
fgrep Permission parrm_eaccess_test.out > /dev/null
touch $@

ED2 = parrm_eaccess_test2_dir
parrm_eaccess_test2.test: parrm
chmod -R u+rwx $(ED2) > /dev/null 2>&1 ;true
rm -rf $(ED2)
mkdir -p $(ED2)/$(ED2)
touch $(ED2)/$(ED2)/foo
touch $(ED2)/foo
chmod ugo-rwx $(ED2)/$(ED2)
./parrm $(ED2) > $(ED2).out 2>&1 ; test $$? = 1
chmod -R u+rwx $(ED2) > /dev/null 2>&1 ;true
test ! -f $(ED2)/foo
test -f $(ED2)/$(ED2)/foo
touch $@

# And these are the same tests where we can access the dir but we cannot unlink it.
ED3 = parrm_eaccess_test3_dir
parrm_eaccess_test3.test: parrm
-chmod u+rwx $(ED3) > /dev/null 2>&1 ;true
rm -rf $(ED3)
mkdir $(ED3)
touch $(ED3)/foo
chmod ugo-w $(ED3)
ls -la $(ED3)
rm -rf $(ED3) > $(ED3).rm.out 2>&1 ; test $$? = 1
fgrep Permission $(ED3).rm.out > /dev/null
./parrm $(ED3) > $(ED3).parrm.out 2>&1 ; test $$? = 1
fgrep Permission $(ED3).parrm.out > /dev/null
touch $@

ED4 = parrm_eaccess_test4_dir
parrm_eaccess_test4.test: parrm
chmod -R u+rwx $(ED4) > /dev/null 2>&1 ;true
rm -rf $(ED4)
mkdir -p $(ED4)/$(ED4)
touch $(ED4)/$(ED4)/foo
touch $(ED4)/foo
chmod ugo-rx $(ED4)/$(ED4)
./parrm $(ED4) > $(ED4).out 2>&1 ; test $$? = 1
chmod -R u+rwx $(ED4) > /dev/null 2>&1 ;true
test ! -f $(ED4)/foo
test -f $(ED4)/$(ED4)/foo
touch $@

# Some tarballs have extra requirements that are hard to capture with diff. We'd really like to verify that the topology of two directories is the same, but I don't know how to get diff to really do it. So we'll have an ad hoc test that these two files really are the same.
longfilename3.tar_test: EXTRA_TEST = test output-of-partarred/longfilename3/aaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbccccccccccccccccdddddddddddddddeeeeeeeeeeeeeeffffffffffffffg -ef output-of-partarred/longfilename3/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb

.SUFFIX: .tar_out .partar_out
%.tar_out: %.tar_done
tar cf $@ $(patsubst %.tar_done,output-with-tar/%,$<)
%.partar_out: %.tar_done $(PARTAR)
(cd output-with-tar;../$(PARTAR) cf - $(patsubst %.tar_done,%,$<)) > $@

error.test: $(PARTAR)
! ./$(PARTAR) xf - < /dev/null 2> error.test.out
fgrep -q ": This does not look like a tar archive" error.test.out
fgrep -q ": Exiting with failure status due to previous errors" error.test.out
! ./$(PARTAR) xzf - < /dev/null 2> error.test.out
fgrep -q "gzip: stdin: unexpected end of file" error.test.out
fgrep -q ": Child returned status 1" error.test.out
fgrep -q ": Exiting with failure status due to previous errors" error.test.out
! ./$(PARTAR) cf error.tar output-with-tar/fifo no-such-file output-with-tar/fifo 2> error.test.out
fgrep -q ": no-such-file: Cannot stat: No such file or directory" error.test.out
fgrep -q ": Exiting with failure status due to previous errors" error.test.out
touch $@

# Test excluding files both in "c" mode and in "x" mode.
excld.test: tar-1.30.tar_done $(PARTAR)
rm -rf excld.dir.tar excld.dir.partar excld.odir.tar excld.odir.partar
mkdir excld.dir.tar excld.dir.partar excld.odir.tar excld.odir.partar
tar cf - -C output-with-tar/ --exclude d\?c tar-1.30 | tar xf - -C excld.dir.tar
$(VALGRIND) ./$(PARTAR) cf - -C output-with-tar/ --exclude d\?c tar-1.30 | tar xf - -C excld.dir.partar
diff -r excld.dir.tar excld.dir.partar
tar c -C output-with-tar/ tar-1.30 | tar x -C excld.odir.tar --exclude d\?c
diff -r excld.dir.tar excld.odir.tar
tar c -C output-with-tar/ tar-1.30 | $(VALGRIND) ./$(PARTAR) x -C excld.odir.partar --exclude d\?c
diff -r excld.dir.tar excld.odir.partar
touch $@

# Test excluding files both in "c" mode and in "x" mode same as above but uses --exclude=PATTERN.
excld-equal.test: tar-1.30.tar_done $(PARTAR)
rm -rf excld-equal.dir.tar excld-equal.dir.partar excld-equal.odir.tar excld-equal.odir.partar
mkdir excld-equal.dir.tar excld-equal.dir.partar excld-equal.odir.tar excld-equal.odir.partar
tar cf - -C output-with-tar/ --exclude=d\?c tar-1.30 | tar xf - -C excld-equal.dir.tar
$(VALGRIND) ./$(PARTAR) cf - -C output-with-tar/ --exclude=d\?c tar-1.30 | tar xf - -C excld-equal.dir.partar
diff -r excld-equal.dir.tar excld-equal.dir.partar
tar c -C output-with-tar/ tar-1.30 | tar x -C excld-equal.odir.tar --exclude d\?c
diff -r excld-equal.dir.tar excld-equal.odir.tar
tar c -C output-with-tar/ tar-1.30 | $(VALGRIND) ./$(PARTAR) x -C excld-equal.odir.partar --exclude=d\?c
diff -r excld-equal.dir.tar excld-equal.odir.partar
touch $@
# Test the same file appearing twice on the command line. tar makes a hardlink from the file to itself.
linklink.test: $(PARTAR)
echo a > linklink.txt
tar cf linklink.tar linklink.txt linklink.txt
$(VALGRIND) ./$(PARTAR) cf linklink.partar linklink.txt linklink.txt
# Don't run the diff unless we have a recent version of tar
if (tar --version|head -1|fgrep 1.3 > /dev/null); then diff linklink.tar linklink.partar; fi
mkdir -p linklink.tdir
tar xf linklink.tar -C linklink.tdir
mkdir -p linklink.pdir
tar xf linklink.partar -C linklink.pdir
diff -r linklink.tdir linklink.pdir
touch $@

# This isn't part of the standard tests, since it requires sudo to run properly.
permissions.sudo.test: $(PARTAR)
sudo rm -rf permissions.sudopartar.testdir permissions.sudountar.testdir
mkdir -p permissions.sudopartar.testdir
mkdir -p permissions.sudountar.testdir
sudo tar pxf test-tars/permissions.tar -C permissions.sudountar.testdir
sudo ./$(PARTAR) pxf test-tars/permissions.tar -C permissions.sudopartar.testdir
# for some reason tar doesn't set the mtime on partar/src/bin in those directories, so let's ignore bin.
(cd permissions.sudopartar.testdir; ls -lR)|sort | egrep -v "bin$$" > permissions.sudopartar.out
(cd permissions.sudountar.testdir; ls -lR)|sort | egrep -v "bin$$" > permissions.sudountar.out
diff permissions.sudopartar.out permissions.sudountar.out

# permissions test for not sudo
permissions.test: $(PARTAR)
rm -rf permissions.in.dir permissions.tar.out.dir permissions.partar.out.dir permissions.tar.ls permissions.partar.ls
mkdir -p permissions.in.dir/s
mkdir -p permissions.in.dir/s/d1
mkdir -p permissions.in.dir/s/d2
ls -l permissions.in.dir/s
chmod 770 permissions.in.dir/s/d1
chmod 750 permissions.in.dir/s/d2
ls -l permissions.in.dir/s
mkdir -p permissions.tar.out.dir
tar cf - -C permissions.in.dir s | tar xf - -C permissions.tar.out.dir
ls -l permissions.tar.out.dir/s | sort > permissions.tar.ls
mkdir -p permissions.partar.out.dir
tar cf - -C permissions.in.dir s | $(VALGRIND) ./$(PARTAR) xf - -C permissions.partar.out.dir
ls -l permissions.partar.out.dir/s | sort > permissions.partar.ls
diff permissions.tar.ls permissions.partar.ls
touch $@

# Test for detecting .gz and .xz inputs.
decompression-errors.test: ./partar
! ./partar xf test-tars/fifo.tar.xz 2> decompression-errors.out
fgrep "Input does not appear to be a tar file." decompression-errors.out > /dev/null
fgrep "Input appears to be xz compressed" decompression-errors.out > /dev/null
!(xzcat test-tars/fifo.tar.xz |gzip|./partar xf - 2> decompression-errors.out)
fgrep "Input does not appear to be a tar file." decompression-errors.out > /dev/null
fgrep "appears to be gzipped" decompression-errors.out > /dev/null
touch $@

%.dir:
mkdir $@

# Some specific tests for parcp
parcp0.test: parcp tar-1.30.tar_done | parcp0.test.dir
rm -rf $@.dir/*
./parcp --restore -- output-with-tar/tar-1.30 $@.dir
touch $@

parcp1.test: parcp
./parcp --version |fgrep $(VERSION) > /dev/null
./parcp --help |fgrep OPTION > /dev/null
touch $@

# test that if we copy into an existing file that is longer, that it's properly trunated
parcp2.test: parcp | parcp2.test.dir
rm -rf $@.dir/*
mkdir -p $@.dir/src $@.dir/dst/src
echo "hello" > $@.dir/src/hello
echo "hello there" > $@.dir/dst/src/hello
ls -i $@.dir/dst/src/hello > $@.dir/original.inode
./parcp -P 3 $@.dir/src $@.dir/dst
ls -i $@.dir/dst/src/hello > $@.dir/new.inode
diff $@.dir/src/hello $@.dir/dst/src/hello
diff $@.dir/new.inode $@.dir/original.inode
touch $@

parcp3.test: parcp | parcp3.dir
rm -rf $@.dir/*
mkdir -p $@.dir/src $@.dir/dst
# source and dest are the same symlink, so expect no change
ln -s unchanged $@.dir/src/uc
ln -s unchanged $@.dir/dst/uc
# source and dest are slightly different symlinks, the same length.
ln -s changed0 $@.dir/src/ch
ln -s changed1 $@.dir/dst/ch
# source and dest are different symlinks of different length.
ln -s shortch $@.dir/src/chlen
ln -s longerch $@.dir/dst/chlen
# source is symlink, dest is not there
ln -s notthere $@.dir/src/nt
# source is a symlink, dest is a dir
ln -s dest-was-dir $@.dir/src/wasdir
mkdir $@.dir/dst/wasdir
# source is a symlink, dest is a regular file.
ln -s dest-was-reg $@.dir/src/wasreg
touch $@.dir/dst/wasreg
#ls -l $@.dir/dst
ls -i parcp3.test.dir/dst/uc > $@.dir/original.uc.symlink
# source and dest are fifos. Make sure the inode is reused
mknod $@.dir/src/src_fifo_dst_fifo p
mknod $@.dir/dst/src_fifo_dst_fifo p
ls -i $@.dir/dst/src_fifo_dst_fifo > $@.dir/src_fifo_dst_fifo.original
# source is fifo and dest is regular. Make sure dest becomes fifo
mknod $@.dir/src/src_fifo_dst_reg p
touch $@.dir/dst/src_fifo_dst_reg
# source is regular and dest is fifo. Make sure dest becomes reg
touch $@.dir/src/src_reg_dst_fifo
mknod $@.dir/dst/src_reg_dst_fifo p
# source is file, dest is dir
touch $@.dir/src/src_reg_dst_dir
mkdir $@.dir/dst/src_reg_dst_dir
# source is dir, dest is file
mkdir $@.dir/src/src_dir_dst_reg
touch $@.dir/dst/src_dir_dst_reg
# two files that are the same inode in src, nothing in dst
touch $@.dir/src/src_two_inodes_dst_null.1
ln $@.dir/src/src_two_inodes_dst_null.1 $@.dir/src/src_two_inodes_dst_null.2
# two files the same inode in src, a file in dst
touch $@.dir/src/src_two_inodes_dst_reg.1
ln $@.dir/src/src_two_inodes_dst_reg.1 $@.dir/src/src_two_inodes_dst_reg.2
touch $@.dir/dst/src_two_inodes_dst_reg.1
# two files the same inode in src, two dirs in dst
touch $@.dir/src/src_two_inodes_dst_two_dirs.1
ln $@.dir/src/src_two_inodes_dst_two_dirs.1 $@.dir/src/src_two_inodes_dst_two_dirs.2
mkdir $@.dir/dst/src_two_inodes_dst_two_dirs.1
mkdir $@.dir/dst/src_two_inodes_dst_two_dirs.2
# three files the same inode in src, three files in dst, two of which are the same inode.
touch $@.dir/src/src_3_inodes_dst_3_files.1
ln $@.dir/src/src_3_inodes_dst_3_files.1 $@.dir/src/src_3_inodes_dst_3_files.2
ln $@.dir/src/src_3_inodes_dst_3_files.1 $@.dir/src/src_3_inodes_dst_3_files.3
touch $@.dir/dst/src_3_inodes_dst_3_files.1
ln $@.dir/dst/src_3_inodes_dst_3_files.1 $@.dir/dst/src_3_inodes_dst_3_files.2
touch $@.dir/dst/src_3_inodes_dst_3_files.3
# do the copy
$(VALGRIND) ./parcp $@.dir/src $@.dir/dst
ls -l $@.dir/dst
test -h $@.dir/dst/ch
ls -l $@.dir/dst/ch | fgrep "ch -> changed0"
ls -l $@.dir/dst/nt | fgrep "nt -> notthere"
ls -l $@.dir/dst/wasdir | fgrep "wasdir -> dest-was-dir"
ls -l $@.dir/dst/chlen | fgrep "chlen -> shortch"
test -h $@.dir/dst/wasreg
ls -l $@.dir/dst/wasreg| fgrep "wasreg -> dest-was-reg"
# test follows symlinks so we must do htis more carefully
ls -i parcp3.test.dir/dst/uc > $@.dir/new.uc.symlink
diff $@.dir/original.uc.symlink $@.dir/new.uc.symlink
ls -i $@.dir/dst/src_fifo_dst_fifo > $@.dir/src_fifo_dst_fifo.new
diff $@.dir/src_fifo_dst_fifo.new $@.dir/src_fifo_dst_fifo.original
test -p $@.dir/dst/src_fifo_dst_reg
test -f $@.dir/dst/src_reg_dst_fifo
test -f $@.dir/dst/src_reg_dst_dir
test -d $@.dir/dst/src_dir_dst_reg
test parcp3.test.dir/dst/src_two_inodes_dst_null.1 -ef parcp3.test.dir/dst/src_two_inodes_dst_null.2
test parcp3.test.dir/dst/src_two_inodes_dst_reg.1 -ef parcp3.test.dir/dst/src_two_inodes_dst_reg.2
test parcp3.test.dir/dst/src_3_inodes_dst_3_files.1 -ef parcp3.test.dir/dst/src_3_inodes_dst_3_files.2
test parcp3.test.dir/dst/src_3_inodes_dst_3_files.1 -ef parcp3.test.dir/dst/src_3_inodes_dst_3_files.3
touch $@

# Check --delete
parcp4.test: parcp | parcp4.test.dir
rm -rf $@.dir/*
mkdir -p $@.dir/src $@.dir/dst
mkdir -p $@.dir/dst/a/b/c/d/e
touch $@.dir/dst/a/b/c/d/e/f
mkdir -p $@.dir/dst/a/b/c/d/e2
touch $@.dir/dst/a/b/c/d/e2/f
mkdir -p $@.dir/src/x/y/z
mkdir -p $@.dir/src/a/w
touch $@.dir/src/a/w/foo
$(VALGRIND) ./parcp --delete $@.dir/src $@.dir/dst
diff -r $@.dir/src $@.dir/dst
touch $@

# Check --exclude-from
parcp5.test: parcp | parcp5.test.dir
rm -rf $@.dir/*
mkdir -p $@.dir/src $@.dir/dst
mkdir $@.dir/src/wanted
mkdir $@.dir/src/unwanted
touch $@.dir/src/wanted/file1.keep
touch $@.dir/src/wanted/file2.nokeep
touch $@.dir/src/wanted/file3.nokeep
echo unwanted > $@.dir/excludelist
echo wanted/file2.nokeep >> $@.dir/excludelist
echo file3.nokeep >> $@.dir/excludelist
$(VALGRIND) ./parcp --exclude-from=$@.dir/excludelist $@.dir/src $@.dir/dst
test -d $@.dir/dst/wanted
test -f $@.dir/dst/wanted/file1.keep
ls $@.dir/dst/wanted|fgrep -v file2.nokeep > /dev/null
ls $@.dir/dst/wanted|fgrep -v file3.nokeep > /dev/null
test ! -d $@.dir/dst/unwanted
touch $@

# Check --exclude-from with --delete
parcp6.test: parcp Makefile | parcp6.test.dir
rm -rf $@.dir/*
mkdir -p $@.dir/src $@.dir/dst
mkdir -p $@.dir/src/src_wanted
mkdir -p $@.dir/dst/dst_wanted
mkdir -p $@.dir/dst/dst_extra
mkdir -p $@.dir/dst/dst_extra2
mkdir -p $@.dir/dst/dst_kill
touch $@.dir/dst/dst_wanted/keepme
touch $@.dir/dst/dst_extra/dst_wanted_file
touch $@.dir/dst/dst_extra2/keep2
touch $@.dir/dst/dst_extra2/killme
touch $@.dir/dst/dst_kill/killme2
echo dst_wanted > $@.dir/excludelist
echo dst_wanted_file >> $@.dir/excludelist
echo dst_extra2/keep2 >> $@.dir/excludelist
$(VALGRIND) ./parcp --exclude-from=$@.dir/excludelist --delete $@.dir/src $@.dir/dst
test -f $@.dir/dst/dst_wanted/keepme
test -f $@.dir/dst/dst_extra/dst_wanted_file
test -f $@.dir/dst/dst_extra2/keep2
test ! -f $@.dir/dst/dst_extra2/killme
test ! -f $@.dir/dst/dst_kill/killme2
test ! -d $@.dir/dst/dst_kill
touch $@

# Check target contains a read-only file
# Three cases: 1) No such file in src
# 2) Exactly the same file in src
# 3) A different file in src
parcp7.test: parcp | parcp7.test.dir
rm -rf $@.dir/*
mkdir -p $@.dir/src $@.dir/dst
touch $@.dir/dst/no-such-file-in-src
chmod ugo-w $@.dir/dst/no-such-file-in-src
echo same in src > $@.dir/src/same-file-in-src
chmod ugo-w $@.dir/src/same-file-in-src
cp -a $@.dir/src/same-file-in-src $@.dir/dst/same-file-in-src
echo diffrent in src > $@.dir/src/diff-file-in-src
chmod ugo-w $@.dir/src/diff-file-in-src
echo diffrent in dst dst > $@.dir/dst/diff-file-in-src
chmod ugo-w $@.dir/dst/diff-file-in-src
ls -l $@.dir/{src,dst}
$(VALGRIND) ./parcp --delete $@.dir/src $@.dir/dst
ls -l $@.dir/{src,dst}
test ! -f $@.dir/dst/no-such-file-in-src
test -f $@.dir/dst/diff-file-in-src
test -f $@.dir/dst/same-file-in-src
diff -r $@.dir/{src,dst}
touch $@

parcp8.test: parcp | parcp7.test.dir
rm -rf $@.dir/*
mkdir -p $@.dir/src $@.dir/dst
touch $@.dir/src/rws-file
chmod +sx $@.dir/src/rws-file
./parcp $@.dir/src $@.dir/dst
test -x parcp8.test.dir/dst/rws-file
test -u parcp8.test.dir/dst/rws-file
echo touch $@

.PHONY: clean
clean:
rm -rf parrm parcp $(PARTAR) parrm.1.gz parcp.1.gz $(PARTAR).1.gz *.o output-with-tar output-to-rm output-with-parcp *.tar_done *.parrm_test *.parcp_test *.partar_test
rm -rf gitrev.c
rm -rf output-with-partar{1,2,3,4} output-of-partarred
rm -rf uncompressed-tars gzipped-tars
rm -rf *.partar{1,2,3,4}_diff
rm -rf *.partar{1,2,3,4}_done
rm -rf excld.dir.*tar excld.test
rm -rf excld-equal.dir.*tar excld-equal.test
if test -n "$$(find . -maxdepth 1 -name 'parrm_eaccess_test*_dir' -print -quit)"; then chmod -R u+rwx parrm_eaccess_test*_dir; fi
rm -rf parrm_eaccess_test*{.out,_dir}
rm -rf error.test.out error.tar linklink.tar linklink.partar linklink.tdir linklink.pdir linklink.txt excld.odir.partar excld.odir.tar
rm -rf permissions.in.dir permissions.tar.out.dir permissions.partar.out.dir permissions.tar.ls permissions.partar.ls
rm -rf *.ls *.test *.tar_test
rm -rf *.partar_out *.tar_out test1.out *.out
rm -rf test_fin
rm -f *.gcda *.gcno common/*.gcda common/*.gcno
rm -rf *.dir/
rm -rf *.1.gz
rm -f $(COMMON_O)
rm -rf partar_log
.PHONY: realclean
realclean: clean
(2-2/29)