summaryrefslogtreecommitdiff
path: root/src/recover.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/recover.c')
-rwxr-xr-xsrc/recover.c95
1 files changed, 76 insertions, 19 deletions
diff --git a/src/recover.c b/src/recover.c
index c2c2eff..0f305a1 100755
--- a/src/recover.c
+++ b/src/recover.c
@@ -1,7 +1,10 @@
#include <errno.h>
+#include <stdio.h>
#include "recover.h"
-slices_t *recover(char *src, char *dst, char*ddOpts, address_t beginSector, address_t endSector, int depth) {
+extern unsigned long c;
+
+slices_t *recover(char *src, char *dst, char*ddOpts, address_t beginSector, address_t endSector/*, int depth*/) {
slices_t *slices;
slice_t *sliceToRead;
address_t firstError=0, median;
@@ -16,17 +19,21 @@ slices_t *recover(char *src, char *dst, char*ddOpts, address_t beginSector, addr
slicesAppend(slices, sliceToRead);
// Main loop
- while (!end && slices->count < (endSector-beginSector)/depth) {
+ while (!end) { // && slices->count < (endSector-beginSector)/depth) {
// try to recover sliceToRead and split it if read error
- switch ( tryRecoverUntilError(sliceToRead, &firstError) ) {
+ switch ( tryRecoverUntilError(sliceToRead, &firstError, src, dst, ddOpts) ) {
case 0:
// slice recovery has been executed without read error
sliceToRead->status=S_RECOVERED;
break;
case EIO:
- // slice recovery has encuontered a readerror
- res=sliceSplit(sliceToRead, firstError, S_RECOVERED, S_UNREADABLE, S_UNKNOWN);
- if (res!=0) { exit(5); } //TODO
+ // slice recovery has encountered a readerror
+ res=sliceSplit(slices, sliceToRead, firstError, S_RECOVERED, S_UNREADABLE, S_UNKNOWN);
+ if (res<1) {
+ //TODO
+ printf("sliceSplit return %d\n", res);
+ exit(5);
+ }
break;
default:
exit(2); //TODO
@@ -35,34 +42,84 @@ slices_t *recover(char *src, char *dst, char*ddOpts, address_t beginSector, addr
/* Now, search the largest S_UNKNOWN zone
split it in two parts */
sliceToRead=slicesFindLargest(slices, S_UNKNOWN);
- if ( sliceToRead == NULL ) { exit(3); } //TODO
+ if ( sliceToRead == NULL ) {
+ // There is nothing more to recover, bailout
+ end=1;
+ continue;
+ }
+
median=(sliceToRead->begin+sliceToRead->end)/2;
- res=sliceSplit(sliceToRead, median, S_UNKNOWN, S_UNKNOWN, S_UNKNOWN);
- if (res!=0) { exit(4); } //TODO
-
- /* After splitting an S_UNKNOWN zone in two parts
- take the second for further analysis.
- We already now that this first one is just preceded by
- a read error, and errors are frequently grouped in zones,
- so trying to read a sector just after a faulty sector is
- most likely a waste of time.
- */
- sliceToRead=sliceToRead->next;
+ res=sliceSplit(slices, sliceToRead, median, S_UNKNOWN, S_UNKNOWN, S_UNKNOWN);
+ switch (res) {
+ case 1:
+ // No split, try analyse this zone
+ // Should be a slice of length 1
+ break;
+ case 2:
+ /* After splitting an S_UNKNOWN zone in two parts
+ take the second for further analysis.
+ We already now that this first one is just preceded by
+ a read error, and errors are frequently grouped in zones,
+ so trying to read a sector just after a faulty sector is
+ most likely a waste of time.
+ */
+ sliceToRead=sliceToRead->next;
+ break;
+ case 3:
+ // Internal error of sliceSlpit because this set of parameters prevent split by 3
+ exit(5); // TODO
+ break;
+ case -1:
+ // Memory error
+ exit(4); //TODO
+ break;
+ default:
+ // API error, all necessary cases are already listed
+ exit(6); // TODO
+ }
}
return slices;
}
-int tryRecoverUntilError(slice_t *sliceToRead, address_t *firstError) {
+int tryRecoverUntilError(slice_t *sliceToRead, address_t *firstError, char *src, char *dst, char*ddOpts) {
//TODO : implement realy that
+ char ddinvocation[256];
int res;
+ address_t seek, count;
+
+ c++; //XXX This is a debug counter
+ seek=sliceToRead->begin;
+ count=sliceToRead->end - seek + 1;
+ res=snprintf(ddinvocation, 255, "dd %s %s %s seek=%ld skip=%ld count=%ld", src, dst, ddOpts, seek, seek, count);
+ puts(ddinvocation);
+
+ // Simulate that we have systematically a read error at first sector
+ *firstError=sliceToRead->begin;
+ res=EIO;
+
+/*
+ // Simulate for each read, tha we have an error just in the middle if read for mor than one sector
if ( sliceToRead->begin == sliceToRead->end ) {
res=0;
} else {
*firstError=(sliceToRead->begin + sliceToRead->end)/2;
res=EIO;
}
+*/
+
+/*
+ // Simulate for each read a pseudo random error position and generate some cases of full read without error
+ int error=sliceToRead->begin + rand()%count;
+ if ( error % 42 == 0 ) {
+ res=0;
+ } else {
+ res=EIO;
+ *firstError=error;
+ }
+*/
+
return res;
}