#define _FILE_OFFSET_BITS 64 #include #include #include #include #include #include #include #define BS 4096 main(int argc,char **argv) { int old1; int old2; int new ; unsigned i; char buf[BS]; char *endnum, *source1, *source2; int rlen; int wlen; unsigned lastswitch=~0; if (argc<4 || argc>5) { fprintf(stderr, "Usage: %s source1 source2 target [start]\n" "source1 and source2 are the broken drives, new is the target drive\n" "start (default 0) says where on the drives to start (in 4KB blocks)\n" "The numbers in the output uually also refer to 4KB blocks\n", argv[0]); exit(1); } i=0; if (argc==5) { i=strtol(argv[4],&endnum,10); if (*endnum) { fprintf(stderr,"\"%s\" is not a number\n",argv[4]); exit(1); } } source1=argv[1]; old1=open(argv[1],O_RDONLY); if (old1==-1) { perror(argv[1]); exit(1); } source2=argv[2]; old2=open(argv[2],O_RDONLY); if (old2==-1) { perror(argv[2]); exit(1); } new =open(argv[3],O_WRONLY); if (new==-1) { perror(argv[3]); exit(1); } for (;;) { off_t off=i*(off_t)BS; if(lseek(old1,off,SEEK_SET)==(off_t)-1){ fprintf(stderr,"i=%d, source=%s\n",i,source1); perror("source lseek"); exit(1); } if(lseek(new,off,SEEK_SET)==(off_t)-1){ fprintf(stderr,"i=%d, new=%d\n",i,new); perror("target lseek"); exit(1); } rlen=read(old1,buf,BS); if (rlen==-1) { if (errno==EIO) { if (i==lastswitch) { fprintf(stderr,"error on both disks at %d, skipping write\n",i); i++; continue; } else { int tmp=old1; char *tmpstr=source1; old1=old2; source1=source2; old2=tmp; source2=tmpstr; lastswitch=i; fprintf(stderr,"switching to %s at %d\n",source1,i); } } else { fprintf(stderr,"i=%d, source=%d\n",i,source1); perror("source read"); exit(1); } } else if (rlen==0) { fprintf(stderr,"%s EOF at %d, done\n",source1,i); exit(0); } else { if (rlen