summaryrefslogtreecommitdiff
path: root/src/recover.c
blob: c2c2eff09761c3949c3cb32cad23c10e6ceeda40 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include <errno.h>
#include "recover.h"

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;
	int res;

	// Initialization : we want to try to recover the beginning of the whole zone
	slices=slicesNew();
	sliceToRead=sliceNew(beginSector, endSector, S_UNKNOWN, NULL);
	if (sliceToRead==NULL) {
		exit(1);//TODO
	}
	slicesAppend(slices, sliceToRead);
	
	// Main loop 
	while (!end && slices->count < (endSector-beginSector)/depth) {
		// try to recover sliceToRead and split it if read error
		switch ( tryRecoverUntilError(sliceToRead, &firstError) ) {
			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
				break;
			default:
				exit(2); //TODO
		}

		/* Now, search the largest S_UNKNOWN zone
		 split it in two parts */
		sliceToRead=slicesFindLargest(slices, S_UNKNOWN);
		if ( sliceToRead == NULL ) { exit(3); } //TODO 

 		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; 
	}
	return slices;
}

int tryRecoverUntilError(slice_t *sliceToRead, address_t *firstError) {
	//TODO : implement realy that
	int res;

	if ( sliceToRead->begin == sliceToRead->end ) {
		res=0;
	} else {
		*firstError=(sliceToRead->begin + sliceToRead->end)/2;
		res=EIO;
	}
	return res;
}