#include #include #include #include #include #include #ifndef lint static char rcsid[] = "@(#) $Id: dcp.c,v 1.4 1997/06/09 15:35:59 wpaul Exp $"; #endif /* * This program copies data from one file to another, ignoring * read errors. It is useful for performing disk copies where the * original disk drive has some unrecoverable errors but still * contains a large amount of undamaged data. * * Note that you must compile this program with the SGI C compiler * in order for it to work correctly (gcc doesn't seem to handle * 64-bit offsets correctly on IRIX yet): * * % cc -D_SGI_SOURCE -o dcp dcp.c */ int main(argc, argv) int argc; char *argv[]; { char cbuf[419200]; char *cptr; int in, out; off_t cnt = 0; off_t rpos = 0, wpos = 0; if (argc < 3) { fprintf(stderr, "%s: infile outfile\n", argv[0]); exit(1); } /* * Align to 32-bit boundary. */ cptr = cbuf; while((unsigned long)cptr % 4) cptr++; if ((in = open(argv[1], O_RDONLY)) == -1) { perror("opening infile"); exit(1); } if ((out = open(argv[2], O_RDWR)) == -1) { perror("opening outfile"); exit(1); } while((cnt = read(in, cptr, 204800)) != 0) { if (cnt == -1) { perror("read"); /* * If the read fails, we want to skip over * this block, but we want to keep the input * and output pointers in sync. So we move * the write pointer ahead just as if things * had worked, and move the read pointer ahead * to match. */ wpos = lseek(out, (off_t)204800, SEEK_CUR); rpos = lseek(in, wpos, SEEK_SET); } else { write(out, cptr, cnt); wpos = lseek(out, (off_t)0, SEEK_CUR); rpos = lseek(in, (off_t)0, SEEK_CUR); } } close(in); close(out); printf("DONE\n"); printf("Read %llu bytes\n", rpos); printf("Wrote %llu bytes\n", wpos); exit(0); }