Adds -G and diff commands.

This commit is contained in:
Andrea Mazzoleni 2011-06-20 20:35:04 +02:00
parent a1b3c98c04
commit 2aa36a5df5
16 changed files with 343 additions and 207 deletions

View file

@ -1,6 +1,15 @@
SnapRAID HISTORY
================
1.5 2011/6
==========
* Changed the output of check/fix to allow a more easily postprocessing
with other tools like awk and sort.
* Added the hidden option -G/--gui to enable the output of progress
information for a potential GUI for SnapRAID.
* Added a new "diff" command to print the list of changes detected
at file level.
1.4 2011/6
==========
* Ignoring in sync System and Hidden files in Windows.

View file

@ -75,6 +75,7 @@ maintainer-clean-local:
rm -f snapraid.1 snapraid.txt
# Automatic testing
CHECKFLAGS =
check-local:
rm -rf test
@ -84,130 +85,133 @@ check-local:
mkdir test/disk2
mkdir test/disk3
echo --- Help
$(TESTENV) ./snapraid$(EXEEXT) -h
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -h
echo --- As empty, sync and check
$(TESTENV) ./snapraid$(EXEEXT) -v -c $(srcdir)/test-raid6.conf sync
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf check
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -v -c $(srcdir)/test-raid6.conf diff
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -v -c $(srcdir)/test-raid6.conf sync
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf check
echo --- Create some files, sync raid6 and check
$(TESTENV) ./mktest$(EXEEXT) generate 1 3 1000 4000
$(TESTENV) ./snapraid$(EXEEXT) -S -v -c $(srcdir)/test-raid6.conf sync
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid5.conf check
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf check
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -v -c $(srcdir)/test-raid6.conf diff
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -v -c $(srcdir)/test-raid6.conf sync
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid5.conf check
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf check
echo --- Create some more files, sync raid5 and check
$(TESTENV) ./mktest$(EXEEXT) generate 2 3 1000 4000
$(TESTENV) ./snapraid$(EXEEXT) -S -v -c $(srcdir)/test-raid5.conf sync
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid5.conf check
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -v -c $(srcdir)/test-raid5.conf diff
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -v -c $(srcdir)/test-raid5.conf sync
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid5.conf check
echo --- Extend raid5 to raid6 with fix and check
$(TESTENV) ./snapraid$(EXEEXT) -S -R -c $(srcdir)/test-raid6.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf fix 2>/dev/null
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid5.conf check
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf check
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -R -c $(srcdir)/test-raid6.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf fix 2>/dev/null
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid5.conf check
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf check
echo --- Dry
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid5.conf dry
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf dry
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid5.conf dry
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf dry
echo --- Delete some files, create some new, sync and check
rm test/disk1/1*
rm test/disk2/2*
rm test/disk3/3*
$(TESTENV) ./mktest$(EXEEXT) generate 3 3 100 4000
$(TESTENV) ./snapraid$(EXEEXT) -S -v -c $(srcdir)/test-raid6.conf sync
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf check
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -v -c $(srcdir)/test-raid6.conf sync
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf check
echo --- Move some files, sync and check
mv test/disk1/7* test/disk1/_a/
mv test/disk2/7* test/disk2/_a/
mv test/disk3/7* test/disk3/_a/
$(TESTENV) ./snapraid$(EXEEXT) -S -v -c $(srcdir)/test-raid6.conf sync
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf check
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -v -c $(srcdir)/test-raid6.conf sync
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf check
echo --- Delete one disk, fix and check with raid5
rm -r test/disk3
mkdir test/disk3
$(TESTENV) ./snapraid$(EXEEXT) -S -R -c $(srcdir)/test-raid5.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid5.conf fix 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf check
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -R -c $(srcdir)/test-raid5.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid5.conf fix 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf check
echo --- Delete two disks, fix and check with raid6
rm -r test/disk1
mkdir test/disk1
rm -r test/disk2
mkdir test/disk2
$(TESTENV) ./snapraid$(EXEEXT) -S -U -c $(srcdir)/test-raid5.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -R -c $(srcdir)/test-raid6.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf fix 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf check
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -U -c $(srcdir)/test-raid5.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -R -c $(srcdir)/test-raid6.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf fix 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf check
echo --- Sync after all the fixes with an empty drive to test -E
$(TESTENV) ./snapraid$(EXEEXT) -S -v -E -c $(srcdir)/test-raid6.conf sync
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -v -E -c $(srcdir)/test-raid6.conf sync
echo --- Delete some files and create some new, sync and check in multiple steps
rm test/disk1/4*
rm test/disk2/5*
rm test/disk3/6*
$(TESTENV) ./mktest$(EXEEXT) generate 4 3 100 4000
$(TESTENV) ./snapraid$(EXEEXT) -S -v -c $(srcdir)/test-raid6.conf -t 100 sync
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -v -c $(srcdir)/test-raid6.conf -t 700 sync
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -v -c $(srcdir)/test-raid6.conf -t 1000 sync
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -v -c $(srcdir)/test-raid6.conf sync
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf check
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -v -c $(srcdir)/test-raid6.conf -t 100 sync
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -v -c $(srcdir)/test-raid6.conf -t 700 sync
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -v -c $(srcdir)/test-raid6.conf -t 1000 sync
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -v -c $(srcdir)/test-raid6.conf sync
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf check
echo --- Delete some files, fix and check with raid5
rm test/disk1/1*
$(TESTENV) ./snapraid$(EXEEXT) -S -R -c $(srcdir)/test-raid5.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid5.conf fix 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf check
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -R -c $(srcdir)/test-raid5.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid5.conf fix 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf check
echo --- Delete some dirs, fix and check with raid5
rm -r test/disk2/_a
rm -r test/disk2/_b
$(TESTENV) ./snapraid$(EXEEXT) -S -R -c $(srcdir)/test-raid5.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid5.conf fix 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf check
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -R -c $(srcdir)/test-raid5.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid5.conf fix 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf check
echo --- Delete some dirs, fix and check with raid6
rm -r test/disk2/_a
rm -r test/disk2/_b
rm -r test/disk3/_a
rm -r test/disk3/_b
$(TESTENV) ./snapraid$(EXEEXT) -S -U -c $(srcdir)/test-raid5.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -R -c $(srcdir)/test-raid6.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf fix 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf check
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -U -c $(srcdir)/test-raid5.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -R -c $(srcdir)/test-raid6.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf fix 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf check
echo --- Delete the parity, fix and check with raid5
rm test/parity
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid5.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid5.conf fix 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf check
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid5.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid5.conf fix 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf check
echo --- Delete the parity and the q-parity, fix and check with raid6
rm test/parity
rm test/q-parity
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf fix 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf check
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf fix 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf check
echo --- Delete the parity and a disk, fix and check with raid6
rm test/parity
rm -r test/disk2/_a
rm -r test/disk2/_b
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf fix 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf check
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf fix 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf check
echo --- Delete the q-parity and a disk, fix and check with raid6
rm test/q-parity
rm -r test/disk3/_a
rm -r test/disk3/_b
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf fix 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf check
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf fix 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf check
echo --- Corrupt the parity, fix and check with raid5
$(TESTENV) ./mktest$(EXEEXT) damage 1 100 10000 test/parity
$(TESTENV) ./snapraid$(EXEEXT) -S -R -c $(srcdir)/test-raid5.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid5.conf fix 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf check
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -R -c $(srcdir)/test-raid5.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid5.conf fix 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf check
echo --- Corrupt the parity and the q-parity, fix and check with raid6
$(TESTENV) ./mktest$(EXEEXT) damage 2 100 10000 test/parity
$(TESTENV) ./mktest$(EXEEXT) damage 2 100 10000 test/q-parity
$(TESTENV) ./snapraid$(EXEEXT) -S -R -c $(srcdir)/test-raid6.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf fix 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf check
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -R -c $(srcdir)/test-raid6.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf fix 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf check
echo --- Corrupt some files, fix and check with raid5
$(TESTENV) ./mktest$(EXEEXT) damage 3 1 500 test/disk2/b*
$(TESTENV) ./mktest$(EXEEXT) append 3 500 test/disk2/c*
$(TESTENV) ./mktest$(EXEEXT) truncate 3 500 test/disk2/d*
$(TESTENV) ./snapraid$(EXEEXT) -S -R -c $(srcdir)/test-raid5.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid5.conf fix 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf check
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -R -c $(srcdir)/test-raid5.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid5.conf fix 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf check
echo --- Corrupt some files, fix and check with raid6
$(TESTENV) ./mktest$(EXEEXT) damage 4 1 500 test/disk2/_a/_a/*
$(TESTENV) ./mktest$(EXEEXT) damage 4 1 500 test/disk3/_a/_a/*
@ -217,10 +221,10 @@ check-local:
$(TESTENV) ./mktest$(EXEEXT) append 4 500 test/disk3/_b/_a/*
$(TESTENV) ./mktest$(EXEEXT) truncate 4 500 test/disk2/_b/_b/*
$(TESTENV) ./mktest$(EXEEXT) truncate 4 500 test/disk3/_b/_b/*
$(TESTENV) ./snapraid$(EXEEXT) -S -U -c $(srcdir)/test-raid5.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -R -c $(srcdir)/test-raid6.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf fix 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf check
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -U -c $(srcdir)/test-raid5.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -R -c $(srcdir)/test-raid6.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf fix 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf check
echo --- Another time with different values
$(TESTENV) ./mktest$(EXEEXT) damage 5 2 50 test/disk2/_a/_a/*
$(TESTENV) ./mktest$(EXEEXT) damage 5 2 50 test/disk3/_a/_a/*
@ -232,33 +236,33 @@ check-local:
$(TESTENV) ./mktest$(EXEEXT) append 5 1500 test/disk3/_b/_a/*
$(TESTENV) ./mktest$(EXEEXT) truncate 5 1500 test/disk2/_b/_b/*
$(TESTENV) ./mktest$(EXEEXT) truncate 5 1500 test/disk3/_b/_b/*
$(TESTENV) ./snapraid$(EXEEXT) -S -U -c $(srcdir)/test-raid5.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -R -c $(srcdir)/test-raid6.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf fix 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf check
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -U -c $(srcdir)/test-raid5.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -R -c $(srcdir)/test-raid6.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf fix 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf check
echo --- Corrupt the parity and some files, fix and check with raid6
$(TESTENV) ./mktest$(EXEEXT) damage 6 100 10000 test/parity
$(TESTENV) ./mktest$(EXEEXT) damage 6 1 500 test/disk1/_a/_a/*
$(TESTENV) ./mktest$(EXEEXT) damage 6 1 500 test/disk1/_a/_b/*
$(TESTENV) ./mktest$(EXEEXT) append 6 500 test/disk1/_b/_a/*
$(TESTENV) ./mktest$(EXEEXT) truncate 6 500 test/disk1/_b/_b/*
$(TESTENV) ./snapraid$(EXEEXT) -S -U -c $(srcdir)/test-raid5.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -R -c $(srcdir)/test-raid6.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf fix 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf check
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -U -c $(srcdir)/test-raid5.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -R -c $(srcdir)/test-raid6.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf fix 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf check
echo --- Corrupt the q-parity and some files, fix and check with raid6
$(TESTENV) ./mktest$(EXEEXT) damage 7 100 10000 test/q-parity
$(TESTENV) ./mktest$(EXEEXT) damage 7 1 500 test/disk1/_a/_a/*
$(TESTENV) ./mktest$(EXEEXT) damage 7 1 500 test/disk1/_a/_b/*
$(TESTENV) ./mktest$(EXEEXT) append 7 500 test/disk1/_b/_a/*
$(TESTENV) ./mktest$(EXEEXT) truncate 7 500 test/disk1/_b/_b/*
$(TESTENV) ./snapraid$(EXEEXT) -S -R -c $(srcdir)/test-raid5.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -R -c $(srcdir)/test-raid6.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf fix 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf check
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -R -c $(srcdir)/test-raid5.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -R -c $(srcdir)/test-raid6.conf check 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf fix 2>> test.log
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf check
echo --- Sync after all the fixes
$(TESTENV) ./snapraid$(EXEEXT) -S -v -c $(srcdir)/test-raid6.conf sync
$(TESTENV) ./snapraid$(EXEEXT) -S -c $(srcdir)/test-raid6.conf check
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -v -c $(srcdir)/test-raid6.conf sync
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -S -c $(srcdir)/test-raid6.conf check
echo Success!
# Manual testing

8
TODO
View file

@ -11,10 +11,6 @@ corruption.
* Adds a checksum for the content file. When reading if the file is invalid,
skip to another.
* Changes the output format allowing a more easy integration with other utilities
like sort. For example to allow to sort by file, disk or block all the output
messages in check/fix.
* Easy way to find duplicates using the computed hash.
* Easy way to find files using a specified block.
@ -24,10 +20,6 @@ integrity check of the existing ones.
It should restore only missing files, without recovering modified ones
or check validity of data of existing ones.
* Implement a "probe" command to check the state of files, without doing any operation.
It should prints all the changed, added and removed files.
Alternatively a -dryrun option for "sync".
* Rename sync->backup and fix->restore. It seems to me a naming expressing
better the meaning of the commands. But not yet sure.

47
check.c
View file

@ -97,7 +97,7 @@ static int repair(struct snapraid_state* state, unsigned i, unsigned diskmax, st
return 0;
}
fprintf(stderr, "%u: Parity data error\n", i);
fprintf(stderr, "error:%u:parity: Data error\n", i);
++error;
}
@ -119,7 +119,7 @@ static int repair(struct snapraid_state* state, unsigned i, unsigned diskmax, st
return 0;
}
fprintf(stderr, "%u: Q-Parity data error\n", i);
fprintf(stderr, "error:%u:qarity: Data error\n", i);
++error;
}
@ -143,7 +143,7 @@ static int repair(struct snapraid_state* state, unsigned i, unsigned diskmax, st
return 0;
}
fprintf(stderr, "%u: Parity/Q-Parity data error\n", i);
fprintf(stderr, "error:%u:parity/qarity: Data error\n", i);
++error;
}
@ -168,8 +168,6 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity
data_off_t countsize;
block_off_t countpos;
block_off_t countmax;
time_t start;
time_t last;
unsigned error;
unsigned unrecoverable_error;
unsigned recovered_error;
@ -224,8 +222,7 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity
countsize = 0;
countpos = 0;
start = time(0);
last = start;
state_progress_begin(state, blockstart, blockmax, countmax);
for(i=blockstart;i<blockmax;++i) {
unsigned failed_count;
int one_tocheck;
@ -308,11 +305,11 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity
/* check if the file was larger and now truncated */
if (ret == 1) {
fprintf(stderr, "File '%s' is larger than expected.\n", handle[j].path);
fprintf(stderr, "%u: Size error for file %s\n", i, block_file_get(block)->sub);
fprintf(stderr, "error:%u:%s:%s: Size error\n", i, handle[j].disk->name, block_file_get(block)->sub);
++error;
/* this is already a recovered error */
fprintf(stderr, "%u: Fixed size for file %s\n", i, block_file_get(block)->sub);
fprintf(stderr, "fixed:%u:%s:%s: Fixed size\n", i, handle[j].disk->name, block_file_get(block)->sub);
++recovered_error;
}
} else {
@ -325,7 +322,7 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity
failed[failed_count].handle = &handle[j];
++failed_count;
fprintf(stderr, "%u: Open error for file %s at position %u\n", i, block_file_get(block)->sub, block_file_pos(block));
fprintf(stderr, "error:%u:%s:%s: Open error at position %u\n", i, handle[j].disk->name, block_file_get(block)->sub, block_file_pos(block));
++error;
continue;
}
@ -335,7 +332,7 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity
&& handle[j].st.st_size > block_file_get(block)->size
) {
fprintf(stderr, "File '%s' is larger than expected.\n", handle[j].path);
fprintf(stderr, "%u: Size error for file %s\n", i, block_file_get(block)->sub);
fprintf(stderr, "error:%u:%s:%s: Size error\n", i, handle[j].disk->name, block_file_get(block)->sub);
++error;
/* if fragmented, it may be reopened, so store the notification */
@ -352,7 +349,7 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity
failed[failed_count].handle = &handle[j];
++failed_count;
fprintf(stderr, "%u: Read error for file %s at position %u\n", i, block_file_get(block)->sub, block_file_pos(block));
fprintf(stderr, "error:%u:%s:%s: Read error at position %u\n", i, handle[j].disk->name, block_file_get(block)->sub, block_file_pos(block));
++error;
continue;
}
@ -368,7 +365,7 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity
failed[failed_count].handle = &handle[j];
++failed_count;
fprintf(stderr, "%u: Data error for file %s at position %u\n", i, block_file_get(block)->sub, block_file_pos(block));
fprintf(stderr, "error:%u:%s:%s: Data error at position %u\n", i, handle[j].disk->name, block_file_get(block)->sub, block_file_pos(block));
++error;
continue;
}
@ -392,7 +389,7 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity
if (ret == -1) {
buffer_parity = 0; /* no parity to use */
fprintf(stderr, "%u: Parity read error\n", i);
fprintf(stderr, "error:%u:parity: Read error\n", i);
++error;
}
} else {
@ -406,7 +403,7 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity
if (ret == -1) {
buffer_qarity = 0; /* no qarity to use */
fprintf(stderr, "%u: Q-Parity read error\n", i);
fprintf(stderr, "error:%u:qarity: Read error\n", i);
++error;
}
} else {
@ -424,7 +421,7 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity
/* print a list of all the errors in files */
for(j=0;j<failed_count;++j) {
fprintf(stderr, "%u: Unrecoverable error for file %s at position %u\n", i, block_file_get(failed[j].block)->sub, block_file_pos(failed[j].block));
fprintf(stderr, "error:%u:%s:%s: Unrecoverable error at position %u\n", i, failed[j].handle->disk->name, block_file_get(failed[j].block)->sub, block_file_pos(failed[j].block));
}
} else {
/* check parity and q-parity only if all the blocks have it computed */
@ -434,7 +431,7 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity
if (buffer_parity != 0 && memcmp(buffer_parity, buffer[diskmax], state->block_size) != 0) {
buffer_parity = 0;
fprintf(stderr, "%u: Parity data error\n", i);
fprintf(stderr, "error:%u:parity: Data error\n", i);
++error;
}
@ -443,7 +440,7 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity
if (buffer_qarity != 0 && memcmp(buffer_qarity, buffer[diskmax + 1], state->block_size) != 0) {
buffer_qarity = 0;
fprintf(stderr, "%u: Q-Parity data error\n", i);
fprintf(stderr, "error:%u:qarity: Data error\n", i);
++error;
}
}
@ -469,7 +466,7 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity
goto bail;
}
fprintf(stderr, "%u: Fixed data error for file %s at position %u\n", i, block_file_get(failed[j].block)->sub, block_file_pos(failed[j].block));
fprintf(stderr, "fixed:%u:%s:%s: Fixed data error at position %u\n", i, failed[j].handle->disk->name, block_file_get(failed[j].block)->sub, block_file_pos(failed[j].block));
++recovered_error;
}
@ -488,7 +485,7 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity
goto bail;
}
fprintf(stderr, "%u: Fixed Parity error\n", i);
fprintf(stderr, "fixed:%u:parity: Fixed data error\n", i);
++recovered_error;
}
@ -504,7 +501,7 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity
goto bail;
}
fprintf(stderr, "%u: Fixed Q-Parity error\n", i);
fprintf(stderr, "fixed:%u:qarity: Fixed data error\n", i);
++recovered_error;
}
}
@ -516,16 +513,12 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity
++countpos;
/* progress */
if (state_progress(&start, &last, countpos, countmax, countsize)) {
printf("Stopping for interruption at block %u\n", i);
if (state_progress(state, i, countpos, countmax, countsize)) {
break;
}
}
if (countmax)
printf("%u%% completed, %u MiB processed\n", countpos * 100 / countmax, (unsigned)(countsize / (1024*1024)));
else
printf("Nothing to do\n");
state_progress_end(state, countpos, countmax, countsize);
bail:
for(j=0;j<diskmax;++j) {

View file

@ -1,6 +1,6 @@
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ([2.65])
AC_INIT([snapraid], [1.4], [], [], [http://snapraid.sourceforge.net])
AC_INIT([snapraid], [1.5], [], [], [http://snapraid.sourceforge.net])
AM_INIT_AUTOMAKE([foreign no-dependencies -Wall])
AC_CONFIG_SRCDIR([snapraid.c])
AC_CONFIG_HEADER([config.h])

24
dry.c
View file

@ -37,8 +37,6 @@ static int state_dry_process(struct snapraid_state* state, int parity_f, int qar
data_off_t countsize;
block_off_t countpos;
block_off_t countmax;
time_t start;
time_t last;
unsigned error;
buffer = malloc_nofail(state->block_size);
@ -54,8 +52,7 @@ static int state_dry_process(struct snapraid_state* state, int parity_f, int qar
countmax = blockmax - blockstart;
countsize = 0;
countpos = 0;
start = time(0);
last = start;
state_progress_begin(state, blockstart, blockmax, countmax);
for(i=blockstart;i<blockmax;++i) {
/* for each disk, process the block */
for(j=0;j<diskmax;++j) {
@ -68,7 +65,7 @@ static int state_dry_process(struct snapraid_state* state, int parity_f, int qar
ret = handle_close_if_different(&handle[j], block_file_get(block));
if (ret == -1) {
fprintf(stderr, "Stopping at block %u\n", i);
printf("Stopping at block %u\n", i);
++error;
goto bail;
}
@ -76,14 +73,14 @@ static int state_dry_process(struct snapraid_state* state, int parity_f, int qar
/* open the file for reading */
ret = handle_open(&handle[j], block_file_get(block));
if (ret == -1) {
fprintf(stderr, "%u: Open error for file %s at position %u\n", i, block_file_get(block)->sub, block_file_pos(block));
fprintf(stderr, "error:%u:%s:%s: Open error at position %u\n", i, handle[j].disk->name, block_file_get(block)->sub, block_file_pos(block));
++error;
continue;
}
read_size = handle_read(&handle[j], block, buffer, state->block_size);
if (read_size == -1) {
fprintf(stderr, "%u: Read error for file %s at position %u\n", i, block_file_get(block)->sub, block_file_pos(block));
fprintf(stderr, "error:%u:%s:%s: Read error at position %u\n", i, handle[j].disk->name, block_file_get(block)->sub, block_file_pos(block));
++error;
continue;
}
@ -95,7 +92,7 @@ static int state_dry_process(struct snapraid_state* state, int parity_f, int qar
if (parity_f != -1) {
ret = parity_read(state->parity, parity_f, i, buffer, state->block_size);
if (ret == -1) {
fprintf(stderr, "%u: Parity read error\n", i);
fprintf(stderr, "error:%u:parity: Read error\n", i);
++error;
}
}
@ -105,27 +102,22 @@ static int state_dry_process(struct snapraid_state* state, int parity_f, int qar
if (qarity_f != -1) {
ret = parity_read(state->qarity, qarity_f, i, buffer, state->block_size);
if (ret == -1) {
fprintf(stderr, "%u: Q-Parity read error\n", i);
fprintf(stderr, "error:%u:qarity: Read error\n", i);
++error;
}
}
}
/* count the number of processed block */
++countpos;
/* progress */
if (state_progress(&start, &last, countpos, countmax, countsize)) {
printf("Stopping for interruption at block %u\n", i);
if (state_progress(state, i, countpos, countmax, countsize)) {
break;
}
}
if (countmax)
printf("%u%% completed, %u MiB processed\n", countpos * 100 / countmax, (unsigned)(countsize / (1024*1024)));
else
printf("Nothing to do\n");
state_progress_end(state, countpos, countmax, countsize);
bail:
for(j=0;j<diskmax;++j) {

81
scan.c
View file

@ -118,7 +118,7 @@ static void scan_file_insert(struct snapraid_state* state, struct snapraid_disk*
/**
* Processes a file.
*/
static void scan_file(struct snapraid_scan* scan, struct snapraid_state* state, struct snapraid_disk* disk, const char* sub, const struct stat* st)
static void scan_file(struct snapraid_scan* scan, struct snapraid_state* state, int output, struct snapraid_disk* disk, const char* sub, const struct stat* st)
{
struct snapraid_file* file;
uint64_t inode;
@ -147,6 +147,14 @@ static void scan_file(struct snapraid_scan* scan, struct snapraid_state* state,
if (strcmp(file->sub, sub) != 0) {
++scan->count_moved;
if (state->gui) {
fprintf(stderr, "scan:move:%s:%s:%s\n", disk->name, file->sub, sub);
fflush(stderr);
}
if (output) {
printf("Move '%s/%s' '%s/%s'\n", disk->name, file->sub, disk->name, sub);
}
/* save the new name */
pathcpy(file->sub, sizeof(file->sub), sub);
@ -155,6 +163,11 @@ static void scan_file(struct snapraid_scan* scan, struct snapraid_state* state,
} else {
/* otherwise it's equal */
++scan->count_equal;
if (state->gui) {
fprintf(stderr, "scan:equal:%s:%s\n", disk->name, file->sub);
fflush(stderr);
}
}
/* nothing more to do */
@ -178,15 +191,19 @@ static void scan_file(struct snapraid_scan* scan, struct snapraid_state* state,
++scan->count_change;
scan_file_remove(state, disk, file);
if (state->gui) {
fprintf(stderr, "scan:change:%s:%s\n", disk->name, file->sub);
fflush(stderr);
}
if (output) {
printf("Change '%s/%s'\n", disk->name, file->sub);
}
/* and continue to reinsert it */
}
} else {
/* create the new file */
++scan->count_insert;
/* and continue to insert it */
}
/* insert it */
file = file_alloc(state->block_size, sub, st->st_size, st->st_mtime, st->st_ino);
/* mark it as present */
@ -199,7 +216,7 @@ static void scan_file(struct snapraid_scan* scan, struct snapraid_state* state,
/**
* Processes a directory.
*/
static void scan_dir(struct snapraid_scan* scan, struct snapraid_state* state, struct snapraid_disk* disk, const char* dir, const char* sub)
static void scan_dir(struct snapraid_scan* scan, struct snapraid_state* state, int output, struct snapraid_disk* disk, const char* dir, const char* sub)
{
DIR* d;
@ -266,7 +283,7 @@ static void scan_dir(struct snapraid_scan* scan, struct snapraid_state* state, s
}
#endif
scan_file(scan, state, disk, sub_next, &st);
scan_file(scan, state, output, disk, sub_next, &st);
} else {
if (state->verbose) {
printf("Excluding file '/%s'\n", sub_next);
@ -276,7 +293,7 @@ static void scan_dir(struct snapraid_scan* scan, struct snapraid_state* state, s
if (filter_path(&state->filterlist, sub_next, 1) == 0) {
pathslash(path_next, sizeof(path_next));
pathslash(sub_next, sizeof(sub_next));
scan_dir(scan, state, disk, path_next, sub_next);
scan_dir(scan, state, output, disk, path_next, sub_next);
} else {
if (state->verbose) {
printf("Excluding directory '/%s'\n", sub_next);
@ -299,7 +316,7 @@ static void scan_dir(struct snapraid_scan* scan, struct snapraid_state* state, s
}
}
void state_scan(struct snapraid_state* state)
void state_scan(struct snapraid_state* state, int output)
{
unsigned diskmax = tommy_array_size(&state->diskarr);
unsigned i;
@ -321,7 +338,7 @@ void state_scan(struct snapraid_state* state)
printf("Scanning disk %s...\n", disk->name);
scan_dir(&scan[i], state, disk, disk->dir, "");
scan_dir(&scan[i], state, output, disk, disk->dir, "");
/* check for removed files */
node = disk->filelist;
@ -333,8 +350,17 @@ void state_scan(struct snapraid_state* state)
/* remove if not present */
if (!file_flag_has(file, FILE_IS_PRESENT)) {
scan_file_remove(state, disk, file);
++scan[i].count_remove;
if (state->gui) {
fprintf(stderr, "scan:remove:%s:%s\n", disk->name, file->sub);
fflush(stderr);
}
if (output) {
printf("Remove '%s/%s'\n", disk->name, file->sub);
}
scan_file_remove(state, disk, file);
}
}
@ -346,6 +372,17 @@ void state_scan(struct snapraid_state* state)
/* next node */
node = node->next;
/* create the new file */
++scan->count_insert;
if (state->gui) {
fprintf(stderr, "scan:add:%s:%s\n", disk->name, file->sub);
fflush(stderr);
}
if (output) {
printf("Add '%s/%s'\n", disk->name, file->sub);
}
/* insert it */
scan_file_insert(state, disk, file);
}
@ -360,7 +397,7 @@ void state_scan(struct snapraid_state* state)
}
}
if (state->verbose) {
if (state->verbose || output) {
struct snapraid_scan total;
total.count_equal = 0;
@ -377,11 +414,19 @@ void state_scan(struct snapraid_state* state)
total.count_insert += scan[i].count_insert;
}
printf("\tequal %d\n", total.count_equal);
printf("\tmoved %d\n", total.count_moved);
printf("\tchanged %d\n", total.count_change);
printf("\tremoved %d\n", total.count_remove);
printf("\tadded %d\n", total.count_insert);
if (state->verbose) {
printf("\tequal %d\n", total.count_equal);
printf("\tmoved %d\n", total.count_moved);
printf("\tchanged %d\n", total.count_change);
printf("\tremoved %d\n", total.count_remove);
printf("\tadded %d\n", total.count_insert);
}
if (output) {
if (!total.count_moved && !total.count_change && !total.count_remove && !total.count_insert) {
printf("No difference\n");
}
}
}
free(scan);

View file

@ -230,10 +230,15 @@ static void hashtest(void)
}
}
void selftest(void)
void selftest(int gui)
{
unsigned i;
if (gui) {
fprintf(stderr, "selftest:\n");
fflush(stderr);
}
printf("Self test...\n");
/* large file check */

View file

@ -253,7 +253,7 @@ snapraid fix \(hyf JUST_DELETED_DIR/
.PD
.RE
.SH COMMANDS
SnapRAID provides three simple commands that allow to:
SnapRAID provides three simple commands (case sensitive) that allow to:
.PD 0
.IP \(bu
Make a backup/snapshot \(hy> \(a"sync\(a"
@ -262,6 +262,8 @@ Check for integrity \(hy> \(a"check\(a"
.IP \(bu
Restore the last backup/snapshot \(hy> \(a"fix\(a".
.PD
.PP
Take care that they should be written in lower case.
.TP
.B sync
Updates the redundancy information. All the modified files
@ -292,6 +294,7 @@ The \(a"content\(a" file is NOT modified.
The \(a"parity\(a" and \(a"q\(hyparity\(a" files are modified if necessary.
The files in the array are modified if necessary.
.SH OPTIONS
SnapRAID provides the following options (case sensitive):
.TP
.B \(hyc, \(hy\(hyconf CONFIG
Selects the configuration file. If not specified is assumed
@ -346,7 +349,7 @@ is located, and where storing the redundancy information.
This configuration file is located in /etc/snapraid.conf in Unix or
in the execution directory in Windows.
.PP
It should contain the following options:
It should contain the following options (case sensitive):
.TP
.B parity FILE
Defines the file to use to store the parity information.

View file

@ -71,14 +71,14 @@ struct option long_options[] = {
{ "expect-recoverable", 0, 0, 'R' },
{ "speed-test", 0, 0, 'T' },
{ "verbose", 0, 0, 'v' },
{ "gui", 0, 0, 'G' },
{ "help", 0, 0, 'h' },
{ "version", 0, 0, 'V' },
{ 0, 0, 0, 0 }
};
#endif
#define OPTIONS "c:f:s:t:ZESURTvhV"
#define OPTIONS "c:f:s:t:ZESURTvhVG"
volatile int global_interrupt = 0;
@ -91,15 +91,17 @@ void signal_handler(int signal)
}
}
#define OPERATION_SYNC 0
#define OPERATION_CHECK 1
#define OPERATION_FIX 2
#define OPERATION_DRY 3
#define OPERATION_DIFF 0
#define OPERATION_SYNC 1
#define OPERATION_CHECK 2
#define OPERATION_FIX 3
#define OPERATION_DRY 4
int main(int argc, char* argv[])
{
int c;
int verbose;
int gui;
int force_zero;
int force_empty;
int expect_unrecoverable;
@ -116,6 +118,7 @@ int main(int argc, char* argv[])
/* defaults */
conf = CONF;
verbose = 0;
gui = 0;
force_zero = 0;
force_empty = 0;
expect_unrecoverable = 0;
@ -175,6 +178,9 @@ int main(int argc, char* argv[])
case 'v' :
verbose = 1;
break;
case 'G' :
gui = 1;
break;
case 'h' :
usage();
exit(EXIT_SUCCESS);
@ -195,7 +201,9 @@ int main(int argc, char* argv[])
exit(EXIT_FAILURE);
}
if (strcmp(argv[optind], "sync") == 0) {
if (strcmp(argv[optind], "diff") == 0) {
operation = OPERATION_DIFF;
} else if (strcmp(argv[optind], "sync") == 0) {
operation = OPERATION_SYNC;
} else if (strcmp(argv[optind], "check") == 0) {
operation = OPERATION_CHECK;
@ -211,13 +219,17 @@ int main(int argc, char* argv[])
raid_init();
if (!skip_self_test)
selftest();
selftest(gui);
state_init(&state);
state_config(&state, conf, verbose, force_zero, force_empty, expect_unrecoverable, expect_recoverable);
state_config(&state, conf, verbose, gui, force_zero, force_empty, expect_unrecoverable, expect_recoverable);
if (operation == OPERATION_SYNC) {
if (operation == OPERATION_DIFF) {
state_read(&state);
state_scan(&state, 1);
} else if (operation == OPERATION_SYNC) {
if (!tommy_list_empty(&filterlist)) {
fprintf(stderr, "You cannot filter with the sync command\n");
exit(EXIT_FAILURE);
@ -225,7 +237,7 @@ int main(int argc, char* argv[])
state_read(&state);
state_scan(&state);
state_scan(&state, 0);
/* intercept Ctrl+C */
signal(SIGINT, &signal_handler);

View file

@ -152,12 +152,14 @@ Getting Started
:snapraid fix -f JUST_DELETED_DIR/
Commands
SnapRAID provides three simple commands that allow to:
SnapRAID provides three simple commands (case sensitive) that allow to:
* Make a backup/snapshot -> "sync"
* Check for integrity -> "check"
* Restore the last backup/snapshot -> "fix".
Take care that they should be written in lower case.
=sync
Updates the redundancy information. All the modified files
in the disk array are read, and the redundancy data is
@ -188,6 +190,8 @@ Commands
The files in the array are modified if necessary.
Options
SnapRAID provides the following options (case sensitive):
-c, --conf CONFIG
Selects the configuration file. If not specified is assumed
the file '/etc/snapraid.conf' in Unix, and 'snapraid.conf'
@ -242,7 +246,7 @@ Configuration
This configuration file is located in /etc/snapraid.conf in Unix or
in the execution directory in Windows.
It should contain the following options:
It should contain the following options (case sensitive):
=parity FILE
Defines the file to use to store the parity information.

View file

@ -22,7 +22,7 @@
/* snapraid */
void speed(void);
void selftest(void);
void selftest(int gui);
#endif

View file

@ -168,12 +168,14 @@ deleted directory, simply running the fix command like.
5 COMMANDS
==========
SnapRAID provides three simple commands that allow to:
SnapRAID provides three simple commands (case sensitive) that allow to:
* Make a backup/snapshot -> "sync"
* Check for integrity -> "check"
* Restore the last backup/snapshot -> "fix".
Take care that they should be written in lower case.
sync
Updates the redundancy information. All the modified files
in the disk array are read, and the redundancy data is
@ -207,6 +209,8 @@ SnapRAID provides three simple commands that allow to:
6 OPTIONS
=========
SnapRAID provides the following options (case sensitive):
-c, --conf CONFIG
Selects the configuration file. If not specified is assumed
the file '/etc/snapraid.conf' in Unix, and 'snapraid.conf'
@ -264,7 +268,7 @@ is located, and where storing the redundancy information.
This configuration file is located in /etc/snapraid.conf in Unix or
in the execution directory in Windows.
It should contain the following options:
It should contain the following options (case sensitive):
parity FILE
Defines the file to use to store the parity information.

117
state.c
View file

@ -29,6 +29,7 @@
void state_init(struct snapraid_state* state)
{
state->verbose = 0;
state->gui = 0;
state->force_zero = 0;
state->force_empty = 0;
state->expect_unrecoverable = 0;
@ -55,18 +56,25 @@ void state_done(struct snapraid_state* state)
tommy_list_foreach(&state->filterlist, (tommy_foreach_func*)filter_free);
}
void state_config(struct snapraid_state* state, const char* path, int verbose, int force_zero, int force_empty, int expect_unrecoverable, int expect_recoverable)
void state_config(struct snapraid_state* state, const char* path, int verbose, int gui, int force_zero, int force_empty, int expect_unrecoverable, int expect_recoverable)
{
FILE* f;
unsigned line;
unsigned content_count;
state->verbose = verbose;
state->gui = gui;
state->force_zero = force_zero;
state->force_empty = force_empty;
state->expect_unrecoverable = expect_unrecoverable;
state->expect_recoverable = expect_recoverable;
if (state->gui) {
fprintf(stderr, "version:%s\n", PACKAGE_VERSION);
fprintf(stderr, "conf:%s\n", path);
fflush(stderr);
}
f = fopen(path, "rt");
if (!f) {
if (errno == ENOENT) {
@ -186,6 +194,23 @@ void state_config(struct snapraid_state* state, const char* path, int verbose, i
fprintf(stderr, "With 'q-parity' you must have at least two 'content' specifications in '%s'\n", path);
exit(EXIT_FAILURE);
}
if (state->gui) {
unsigned i;
fprintf(stderr, "blocksize:%u\n", state->block_size);
for(i=0;i<tommy_array_size(&state->diskarr);++i) {
struct snapraid_disk* disk = tommy_array_get(&state->diskarr, i);
fprintf(stderr, "disk:%s:%s\n", disk->name, disk->dir);
}
if (state->qarity[0] != 0)
fprintf(stderr, "mode:raid6\n");
else
fprintf(stderr, "mode:raid5\n");
fprintf(stderr, "parity:%s\n", state->parity);
if (state->qarity[0] != 0)
fprintf(stderr, "qarity:%s\n", state->qarity);
fflush(stderr);
}
}
void state_read(struct snapraid_state* state)
@ -210,6 +235,10 @@ void state_read(struct snapraid_state* state)
struct snapraid_content* content = node->data;
pathcpy(path, sizeof(path), content->content);
if (state->gui) {
fprintf(stderr, "content:%s\n", path);
fflush(stderr);
}
printf("Loading state from %s...\n", path);
f = fopen(path, "rt");
@ -647,42 +676,80 @@ void state_filter(struct snapraid_state* state, tommy_list* filterlist)
}
}
void state_progress_begin(struct snapraid_state* state, block_off_t blockstart, block_off_t blockmax, block_off_t countmax)
{
if (state->gui) {
fprintf(stderr,"run:begin:%u:%u:%u\n", blockstart, blockmax, countmax);
fflush(stderr);
} else {
time_t now;
now = time(0);
state->progress_start = now;
state->progress_last = now;
}
}
void state_progress_end(struct snapraid_state* state, block_off_t countpos, block_off_t countmax, data_off_t countsize)
{
if (state->gui) {
fprintf(stderr, "run:end\n");
fflush(stderr);
} else {
unsigned countsize_MiB = (countsize + 1024*1024 - 1) / (1024*1024);
if (countmax)
printf("%u%% completed, %u MiB processed\n", countpos * 100 / countmax, countsize_MiB);
else
printf("Nothing to do\n");
}
}
#define PROGRESS_CLEAR " "
int state_progress(time_t* start, time_t* last, block_off_t countpos, block_off_t countmax, data_off_t countsize)
int state_progress(struct snapraid_state* state, block_off_t blockpos, block_off_t countpos, block_off_t countmax, data_off_t countsize)
{
time_t now;
if (state->gui) {
fprintf(stderr, "run:pos:%u:%u:\n", blockpos, countpos);
fflush(stderr);
} else {
time_t now;
now = time(0);
now = time(0);
if (*last != now) {
time_t delta = now - *start;
if (state->progress_last != now) {
time_t delta = now - state->progress_start;
printf("%u%%, %u MiB", countpos * 100 / countmax, (unsigned)(countsize / (1024*1024)));
printf("%u%%, %u MiB", countpos * 100 / countmax, (unsigned)(countsize / (1024*1024)));
if (delta != 0) {
printf(", %u MiB/s", (unsigned)(countsize / (1024*1024) / delta));
if (delta != 0) {
printf(", %u MiB/s", (unsigned)(countsize / (1024*1024) / delta));
}
if (delta > 5 && countpos > 0) {
unsigned m, h;
data_off_t todo = countmax - countpos;
m = todo * delta / (60 * countpos);
h = m / 60;
m = m % 60;
printf(", %u:%02u ETA%s", h, m, PROGRESS_CLEAR);
}
printf("\r");
fflush(stdout);
state->progress_last = now;
}
if (delta > 5 && countpos > 0) {
unsigned m, h;
data_off_t todo = countmax - countpos;
m = todo * delta / (60 * countpos);
h = m / 60;
m = m % 60;
printf(", %u:%02u ETA%s", h, m, PROGRESS_CLEAR);
}
printf("\r");
fflush(stdout);
*last = now;
}
/* stop if requested */
if (global_interrupt) {
printf("\n");
if (!state->gui) {
printf("\n");
printf("Stopping for interruption at block %u\n", blockpos);
}
return 1;
}

19
state.h
View file

@ -31,6 +31,7 @@ extern volatile int global_interrupt;
struct snapraid_state {
int verbose; /**< Verbose output. */
int gui; /**< Gui output. */
int force_zero; /**< Forced dangerous operations of synching file now with zero size. */
int force_empty; /**< Forced dangerous operations of synching disk now empty. */
int expect_unrecoverable; /**< Expect presence of unrecoverable error in checking or fixing. */
@ -44,6 +45,8 @@ struct snapraid_state {
tommy_list contentlist; /**< List of content files. */
tommy_array diskarr; /**< Disk array. */
tommy_list filterlist; /**< List of inclusion/exclusion. */
time_t progress_start; /**< Start of processing for progress visualization. */
time_t progress_last; /**< Last update of progress visualization. */
};
/**
@ -59,7 +62,7 @@ void state_done(struct snapraid_state* state);
/**
* Read the configuration file.
*/
void state_config(struct snapraid_state* state, const char* path, int verbose, int force_zero, int force_empty, int expect_unrecoverable, int expect_recoverable);
void state_config(struct snapraid_state* state, const char* path, int verbose, int gui, int force_zero, int force_empty, int expect_unrecoverable, int expect_recoverable);
/**
* Read the state.
@ -74,7 +77,7 @@ void state_write(struct snapraid_state* state);
/**
* Scans all the disks to update the state.
*/
void state_scan(struct snapraid_state* state);
void state_scan(struct snapraid_state* state, int output);
/**
* Syncs the parity data.
@ -96,10 +99,20 @@ void state_dry(struct snapraid_state* state, block_off_t blockstart, block_off_t
*/
void state_filter(struct snapraid_state* state, tommy_list* filterlist);
/**
* Begins the progress visualization.
*/
void state_progress_begin(struct snapraid_state* state, block_off_t blockstart, block_off_t blockmax, block_off_t countmax);
/**
* Ends the progress visualization.
*/
void state_progress_end(struct snapraid_state* state, block_off_t countpos, block_off_t countmax, data_off_t countsize);
/**
* Writes the progress.
*/
int state_progress(time_t* start, time_t* last, block_off_t countpos, block_off_t countmax, data_off_t countsize);
int state_progress(struct snapraid_state* state, block_off_t blockpos, block_off_t countpos, block_off_t countmax, data_off_t countsize);
#endif

13
sync.c
View file

@ -40,8 +40,6 @@ static int state_sync_process(struct snapraid_state* state, int parity_f, int qa
data_off_t countsize;
block_off_t countpos;
block_off_t countmax;
time_t start;
time_t last;
int ret;
unsigned unrecoverable_error;
@ -86,8 +84,7 @@ static int state_sync_process(struct snapraid_state* state, int parity_f, int qa
countsize = 0;
countpos = 0;
start = time(0);
last = start;
state_progress_begin(state, blockstart, blockmax, countmax);
for(i=blockstart;i<blockmax;++i) {
int one_invalid;
int ret;
@ -235,16 +232,12 @@ static int state_sync_process(struct snapraid_state* state, int parity_f, int qa
++countpos;
/* progress */
if (state_progress(&start, &last, countpos, countmax, countsize)) {
printf("Stopping for interruption at block %u\n", i);
if (state_progress(state, i, countpos, countmax, countsize)) {
break;
}
}
if (countmax)
printf("%u%% completed, %u MiB processed\n", countpos * 100 / countmax, (unsigned)(countsize / (1024*1024)));
else
printf("Nothing to do\n");
state_progress_end(state, countpos, countmax, countsize);
bail:
for(j=0;j<diskmax;++j) {