From 2aa36a5df5c4f30ee41bcd15908be0de80027124 Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Mon, 20 Jun 2011 20:35:04 +0200 Subject: [PATCH] Adds -G and diff commands. --- HISTORY | 9 +++ Makefile.am | 164 ++++++++++++++++++++++++++------------------------- TODO | 8 --- check.c | 47 +++++++-------- configure.ac | 2 +- dry.c | 24 +++----- scan.c | 81 +++++++++++++++++++------ selftest.c | 7 ++- snapraid.1 | 7 ++- snapraid.c | 34 +++++++---- snapraid.d | 8 ++- snapraid.h | 2 +- snapraid.txt | 8 ++- state.c | 117 ++++++++++++++++++++++++++++-------- state.h | 19 +++++- sync.c | 13 +--- 16 files changed, 343 insertions(+), 207 deletions(-) diff --git a/HISTORY b/HISTORY index 923c526c..ec1921ec 100644 --- a/HISTORY +++ b/HISTORY @@ -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. diff --git a/Makefile.am b/Makefile.am index 92a6af92..0bb596e1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 diff --git a/TODO b/TODO index 7d4b3fbc..1b137214 100644 --- a/TODO +++ b/TODO @@ -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. diff --git a/check.c b/check.c index 827899a1..74bbc904 100644 --- a/check.c +++ b/check.c @@ -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;isub); + 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;jsub, 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;jblock_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;isub, 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;jsub, 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); diff --git a/selftest.c b/selftest.c index 4fffce0b..ee005bbf 100644 --- a/selftest.c +++ b/selftest.c @@ -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 */ diff --git a/snapraid.1 b/snapraid.1 index 68b4e933..6fce8403 100644 --- a/snapraid.1 +++ b/snapraid.1 @@ -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. diff --git a/snapraid.c b/snapraid.c index 553a2768..d221fda3 100644 --- a/snapraid.c +++ b/snapraid.c @@ -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); diff --git a/snapraid.d b/snapraid.d index 1d36c29a..bdb6e967 100644 --- a/snapraid.d +++ b/snapraid.d @@ -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. diff --git a/snapraid.h b/snapraid.h index ce7fd603..517956fe 100644 --- a/snapraid.h +++ b/snapraid.h @@ -22,7 +22,7 @@ /* snapraid */ void speed(void); -void selftest(void); +void selftest(int gui); #endif diff --git a/snapraid.txt b/snapraid.txt index 179d8fb6..89b3653d 100644 --- a/snapraid.txt +++ b/snapraid.txt @@ -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. diff --git a/state.c b/state.c index e77bb77a..197718c0 100644 --- a/state.c +++ b/state.c @@ -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;idiskarr);++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; } diff --git a/state.h b/state.h index 6f3d3c94..0833887a 100644 --- a/state.h +++ b/state.h @@ -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 diff --git a/sync.c b/sync.c index 25b2a754..c933873b 100644 --- a/sync.c +++ b/sync.c @@ -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