/*
* Simple program to unstripe a RAID-5 array from disk image files.
* This worked successfully on a Buffalo Drive Station Quattro.
*
* Assumptions:
* Stripe width: 512 bytes (1 sector)
* Left Asymmetric (backward parity distribution)
*
* D1 D2 D3 D4
* ==============
* S1 S2 S3 SP
* S4 S5 SP S6
* S7 SP S8 S9
* SP S10 S11 S12
* S12 S13 S14 SP
* S15 S16 SP S17
* ...
*/
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#ifndef D1
#define D1 "/dev/loop1"
#define D2 "/dev/loop2"
#define D3 "/dev/loop3"
#define D4 "/dev/loop4"
#endif
#ifndef OUTFILE
#define OUTFILE "/tmp/diskimage.img"
#endif
/* For testing purposes, only iterate 10k times. */
#ifndef LOOPS
#define LOOPS 10000
#endif
#define STRIPE_SIZE 512
int main(int argc, char *argv[])
{
unsigned long start_sector = 0;
unsigned long long start_offset = 1024;
unsigned char buf[STRIPE_SIZE];
int i;
int sts = 0;
unsigned long iteration = 0;
FILE *fp1 = fopen(D1, "rb");
FILE *fp2 = fopen(D2, "rb");
FILE *fp3 = fopen(D3, "rb");
FILE *fp4 = fopen(D4, "rb");
FILE *outfp = fopen(OUTFILE, "wb");
FILE *fps[] =
{ fp1, fp2, fp3, fp4,
fp1, fp2, fp3, fp4,
fp1, fp2, fp3, fp4,
fp1, fp2, fp3, fp4 };
unsigned char stripe[] =
{ 0, 0, 0, 1,
0, 0, 1, 0,
0, 1, 0, 0,
1, 0, 0, 0 };
off_t offset = 0;
if (!fp1 || !fp2 || !fp3 || !fp4 || !outfp)
{
perror("fopen");
return 1;
}
if (argc > 1)
{
start_sector = strtoul(argv[1], NULL, 0);
start_offset = start_sector;
start_offset *= STRIPE_SIZE;
offset = start_offset;
fseeko(fp1, offset, SEEK_SET);
fseeko(fp2, offset, SEEK_SET);
fseeko(fp3, offset, SEEK_SET);
fseeko(fp4, offset, SEEK_SET);
}
while ((LOOPS==0 && !feof(fp4)) || (LOOPS && iteration < LOOPS)) {
for (i=0; i<16; i++)
{
sts = fread(buf, 1, STRIPE_SIZE, fps[i]);
/*
* Read stripe data sequentially, discard parity.
* Probably faster to read than seeking over discarded data?
*/
if (!stripe[i])
{
fwrite(buf, 1, STRIPE_SIZE, outfp);
}
}
printf("Iteration = %ld\n", iteration++);
}
return 0;
}