recoverdm-0.20/0000755000175000017500000000000011130673444013322 5ustar folkertfolkertrecoverdm-0.20/error.h0000644000175000017500000000004411130673444014622 0ustar folkertfolkertvoid error_exit(char *format, ...); recoverdm-0.20/recoverdm.c0000644000175000017500000002702311130673444015460 0ustar folkertfolkert#define _LARGEFILE64_SOURCE #include #include #include #include #include #include #include #include #include "io.h" #include "dev.h" #include "utils.h" #include "error.h" #define N_RETRIES 6 #define N_CD_RAW_RETRIES 6 #define DEFAULT_CD_SPEED 1 void version(void) { printf("recoverdm v" VERSION ", (c) 2003-2004 by folkert@vanheusden.com\n\n"); } void usage(void) { fprintf(stderr, "Usage: recoverdm -t -i -o [-l ] [-n # retries]\n"); fprintf(stderr, " [-s rotation speed (CD-ROM etc.)] [-r # CD/DVD RAW read retries]\n"); fprintf(stderr, " [-b start offset] [-p skip blocks count]\n"); fprintf(stderr, "Number of retries defaults to %d. For CD-ROMs it's advised to use 1.\n", N_RETRIES); fprintf(stderr, "Number of CD/DVD RAW read retries defaults to %d. It is advised to use at least 3.\n", N_CD_RAW_RETRIES); fprintf(stderr, "CD-ROM (and DVD) speed defaults to %d.\n", DEFAULT_CD_SPEED); fprintf(stderr, "Skip blocks count is how many sectors are skipped after non-read one. Use\n"); fprintf(stderr, "more to speed-up the recover process. Default is 1.\n"); fprintf(stderr, "Type can be:\n"); fprintf(stderr, "\tFILE\t\t1\n"); fprintf(stderr, "\tFLOPPY\t\t10\n"); fprintf(stderr, "\tFLOPPY_IDE\t11\n"); fprintf(stderr, "\tFLOPPY_SCSI\t12\n"); fprintf(stderr, "\tCDROM_IDE\t20\n"); fprintf(stderr, "\tCDROM_SCSI\t21\n"); fprintf(stderr, "\tDVD_IDE\t\t30\n"); fprintf(stderr, "\tDVD_SCSI\t31\n"); fprintf(stderr, "\tDISK_IDE\t40\n"); fprintf(stderr, "\tDISK_SCSI\t41\n"); fprintf(stderr, "-l generates a mapfile containing checksums and a list of badsectors. This map-\n"); fprintf(stderr, " file can then be used with `mergebad' to create one correct image from\n"); fprintf(stderr, " several damaged images\n"); } void lba_to_msf(off64_t lba, unsigned char *minute, unsigned char *second, unsigned char *frame) { if (lba >= -150) { *minute = (lba + 150) / (60 * 75); lba -= (*minute) * 60 * 75; *second = (lba + 150) / 75; lba -= (*second) * 75; *frame = (lba + 150); } else { *minute = (lba + 450150) / (60 * 75); lba -= (*minute) * 60 * 75; *second = (lba + 450150) / 75; lba -= (*second) * 75; *frame = (lba + 450150); } } int create_sector(unsigned char **sectors, int n_sectors, size_t block_size, char **psector_out) { short n_times_ok[n_sectors], max_n_ok=0; char selection[block_size]; char *sector_out = (char *)mymalloc(block_size, "sector"); int loop, max_n_ok_index=0; *psector_out = sector_out; memset(n_times_ok, 0x00, sizeof(n_times_ok)); memset(selection, 0x00, sizeof(selection)); /* do for every byte */ for(loop=0; loop 1 times used */ int count[256]; memset(count, 0x00, sizeof(count)); /* select byte -> chosen_byte * or -1 if all different */ /* first, count how many times every byte occured */ for(loop2=0; loop2 chosen_byte_count) { chosen_byte_count = count[loop2]; chosen_byte = loop2; } /* what to do with '== chosen_byte_counter'? ... */ } /* found a byte occuring frequently? then remember this byte * and remember how many times a sector "had it right" */ if (chosen_byte != -1) { /* keep track of how many tims a sector "had it right" */ for(loop2=0; loop2 max_n_ok) { max_n_ok = n_times_ok[loop]; max_n_ok_index = loop; } } /* then, for every byte that was not filled in, pick the byte from * the previously selected sector */ for(loop=0; loop= 3) { char **sector_list = (char **)mymalloc(sizeof(char *) * n_raw_retries, "sectorlist"); int loop; char *dummy = NULL; for(loop=0; loop= 600) (void)posix_fadvise(fdout, 0, 0, POSIX_FADV_SEQUENTIAL); // or POSIX_FADV_NOREUSE? #endif fdin = open64(file_in, O_RDONLY); if (fdin == -1) { printf("Cannot open file %s: this is beyond the capabilities\n", file_in); printf("of this program.\n"); return -1; } #if (_XOPEN_VERSION >= 600) (void)posix_fadvise(fdin, 0, 0, POSIX_FADV_SEQUENTIAL); // or POSIX_FADV_NOREUSE? #endif if (file_list != NULL) { dsecfile = fopen(file_list, "w"); if (!dsecfile) { printf("Cannot create file %s.\n", file_list); return -1; } #if (_XOPEN_VERSION >= 600) (void)posix_fadvise(fileno(dsecfile), 0, 0, POSIX_FADV_SEQUENTIAL); // or POSIX_FADV_NOREUSE? #endif } (void)init_device(fdin, dev_type, cd_speed); the_end = lseek64(fdin, (off64_t)0, SEEK_END); if (lseek64(fdin, start_offset, SEEK_SET) == -1) { printf("Problem seeking to start of file/device.\n"); return -1; } for(;;) { ssize_t rc; prevpos = curpos; curpos = lseek64(fdin, (off64_t)0, SEEK_CUR); printf("%lld\r", curpos); fflush(stdout); rc = READ(fdin, buffer, block_size); if (rc == 0) /* end of file/device */ break; if (rc > 0) { n = 0; if (lseek64(fdout, curpos, SEEK_SET) == -1) { fprintf(stderr, "Problem seeking in outputfile! [%d]\n", errno); break; } if (phantom_write(fdout, buffer, (size_t)rc) <= 0) { fprintf(stderr, "Error writing to file! [%d]\n", errno); break; } } else if (rc == -1) { n++; printf("error at %lld bytes, retrying: %d\n", curpos, n); fflush(stdout); if (n > 1) { if (prevpos != curpos) { fprintf(stderr, "Confused! Continuing...\n"); } } /* try seeking */ switch(n) { case 2: /* seek to last known good */ if (lastok != (off64_t)-1) { printf("seek to last known good...\n"); (void)lseek64(fdin, lastok, SEEK_SET); (void)clear_buffers(fdin, dev_type); (void)READ(fdin, buffer2, block_size); } break; case 3: /* seek to end */ if (the_end != (off64_t)-1) { printf("seek to end...\n"); (void)lseek64(fdin, the_end, SEEK_SET); (void)clear_buffers(fdin, dev_type); (void)READ(fdin, buffer2, block_size); } break; case 4: /* reset device */ printf("resetting device...\n"); (void)reset_device(fdin, dev_type); break; case 5: /* reset controller */ printf("resetting controller...\n"); (void)reset_controller(fdin, dev_type); break; } if (lseek64(fdin, curpos, SEEK_SET) == -1) { printf("Problem seeking in input-file! [%d] (current sector)\n", errno); } if (n == n_retries) { char ok = 1; /* always mark the sector as tricky */ if (dsecfile) { fprintf(dsecfile, "%lld %ld\n", curpos, block_size*skip_value); fflush(dsecfile); } n = 0; if (dev_type == DT_CDROM_IDE || dev_type == DT_CDROM_SCSI || dev_type == DT_DVD_IDE || dev_type == DT_DVD_SCSI) { char raw_buffer[2048]; fprintf(stderr, "Trying RAW read...\n"); if (get_raw_cd(fdin, dev_type, curpos, n_raw_cd_retries, raw_buffer) == 0) { if (lseek64(fdout, curpos, SEEK_SET) == -1) { fprintf(stderr, "Problem seeking in outputfile! [%d]\n", errno); ok = 0; } else if (phantom_write(fdout, raw_buffer, (size_t)2048) <= 0) { fprintf(stderr, "Error writing to file! [%d]\n", errno); ok = 0; } } else { ok = 0; } } printf("Tried reading %d times, failed doing that. Skiping %d blocks...\n", n_retries, skip_value); if (lseek64(fdin, curpos + (off64_t)block_size*skip_value, SEEK_SET) == -1) { fprintf(stderr, "Problem seeking in input-file! [%d] (sector %d after current)\n", errno, skip_value); } } } } close(fdout); close(fdin); if (dsecfile) fclose(dsecfile); printf("Done\n"); return 0; } recoverdm-0.20/io.h0000644000175000017500000000023411130673444014101 0ustar folkertfolkertssize_t READ (int fd, char *whereto, size_t len); ssize_t WRITE(int fd, char *whereto, size_t len); ssize_t phantom_write(int fd, char *in, size_t nbytes); recoverdm-0.20/Makefile0000644000175000017500000000134011130673444014760 0ustar folkertfolkertVERSION=0.20 CFLAGS=-Wall -Wshadow -Wconversion -Wwrite-strings -Winline -O2 -DVERSION=\"$(VERSION)\" LDFLAGS= OBJSr=recoverdm.o dev.o io.o utils.o error.o OBJSm=mergebad.o io.o utils.o error.o all: recoverdm mergebad recoverdm: $(OBJSr) $(CC) -Wall -W $(OBJSr) $(LDFLAGS) -o recoverdm mergebad: $(OBJSm) $(CC) -Wall -W $(OBJSm) $(LDFLAGS) -o mergebad install: cp recoverdm mergebad /usr/local/bin echo echo Oh, blatant plug: http://keetweej.vanheusden.com/wishlist.html clean: rm -f $(OBJSr) $(OBJSm) recoverdm mergebad core package: clean mkdir recoverdm-$(VERSION) cp *.c *.h *.1 Makefile readme.txt license.txt recoverdm-$(VERSION) tar czf recoverdm-$(VERSION).tgz recoverdm-$(VERSION) rm -rf recoverdm-$(VERSION) recoverdm-0.20/utils.h0000644000175000017500000000035211130673444014633 0ustar folkertfolkertvoid * mymalloc(size_t size, char *what); void * myrealloc(void *oldp, size_t newsize, char *what); off64_t get_filesize(char *filename); int copy_block(int fd_in, int fd_out, off64_t block_size); void myseek(int fd, off64_t offset); recoverdm-0.20/mergebad.c0000644000175000017500000003160111130673444015235 0ustar folkertfolkert#define _LARGEFILE64_SOURCE #include #include #include #include #include #include #include #include #include "io.h" #include "dev.h" #include "gen.h" #include "utils.h" #include "error.h" char verbose = 0; typedef struct { off64_t offset; off64_t block_size; } badblock; typedef struct { badblock *bb_list; int bb_list_size; int fd; /* fd of image */ char *filename; off64_t size; /* size of image */ } image; void version(void) { printf("mergebad v" VERSION ", (c) 2004 by folkert@vanheusden.com\n\n"); } int find_image_without_badblock(image *imgs, int n_imgs, off64_t offset) { int img_index, badblock_index; if (verbose >= 3) printf("> find_image_without_badblock(%p %d %lld)\n", imgs, n_imgs, offset); /* for each image... */ for(img_index=0; img_index= 4) printf("= %d/%d, %lld - %lld\n", img_index, badblock_index, cur_offset, cur_bb_end); /* see if the current offset is somewhere in the current bad block */ if (offset >= cur_offset && offset < cur_bb_end) { /* yes, offset is in a badblock for image with index 'img_index' and its badblockindex * is 'badblock_index', so we're not going to use this image */ ok = 0; break; } /* see if the offset of the current badblock is beyond the current offset: we can then * stop searching for this image: since this image seems not to have any badblocks for * offset 'offset', we can use this image */ else if (cur_offset > offset) { break; } } /* is this an image we can use? */ if (ok) { if (verbose >= 3) printf("< find_image_without_badblock: %d\n", img_index); return img_index; } } if (verbose >= 3) printf("< find_image_without_badblock: %d\n", img_index); /* no image found */ return -1; } void find_smallest_current_badblock(image *imgs, int n_imgs, off64_t offset, int *selected_image, int *selected_badblock) { off64_t smallest_block_size = (off64_t)1 << ((sizeof(off64_t) * 8) - 2); /* better not be > 2^62 bytes! */ int img_index, badblock_index; if (verbose >= 3) printf("> find_smallest_current_badblock(%p %d %lld %p %p)\n", imgs, n_imgs, offset, selected_image, selected_badblock); *selected_image = -1; *selected_badblock = -1; /* for each image... */ for(img_index=0; img_index= 4) printf("= %d/%d, %lld - %lld\n", img_index, badblock_index, cur_offset, cur_bb_end); /* see if the current offset is somewhere in the current bad block */ if (offset >= cur_offset && offset < cur_bb_end) { off64_t block_size_left = cur_bb_end - offset; /* # bytes left for current badblock relative to current offset: we * might have been able to get correct bytes (from another image) that * (partially) overlaps the current badblock */ if (verbose >= 4) printf("= # bytes left: %lld\n", block_size_left); /* is the end of this badblock nearer then the previous found one? (if any) */ if (block_size_left < smallest_block_size) { if (verbose >= 4) printf("! block selected\n"); *selected_image = img_index; *selected_badblock = badblock_index; smallest_block_size = block_size_left; break; } } } } if (verbose >= 3) printf("> find_smallest_current_badblock: %d %d (%lld)\n", *selected_image, *selected_badblock, smallest_block_size); } int find_badblock_after_offset(badblock *bb_list, int bb_list_size, off64_t offset) { int badblock_index; /* search from start of list (the lowest offset) upto the end */ for(badblock_index=0; badblock_index= offset) return badblock_index; } return -1; } int read_mapfile(char *filename, badblock **pbb, int *nbb) { int n_bb = 0; badblock *bbs = NULL; FILE *fh; if (verbose >= 2) printf("Reading mapfile from %s\n", filename); fh = fopen(filename, "rb"); if (!fh) { fprintf(stderr, "Problem opening %s for read! %s (%d)\n", filename, strerror(errno), errno); return -1; } #if (_XOPEN_VERSION >= 600) (void)posix_fadvise(fileno(fh), 0, 0, POSIX_FADV_SEQUENTIAL); // or POSIX_FADV_NOREUSE? #endif while(!feof(fh)) { off64_t offset; int block_size; fscanf(fh, "%lld %d", &offset, &block_size); bbs = (badblock *)myrealloc(bbs, sizeof(badblock) * (n_bb + 1), "badblocks list"); bbs[n_bb].offset = offset; bbs[n_bb].block_size = block_size; if (verbose >= 4) printf("%d] %lld %lld\n", n_bb, offset, block_size); n_bb++; } *pbb = bbs; *nbb = n_bb; return 0; } char select_most_occuring_byte(unsigned char *bytes, int n_imgs) { char selected_byte = 0; int loop; int counters[256]; int count_used = -1; memset(counters, 0x00, sizeof(counters)); /* count frequency for byte in each file */ for(loop=0; loop count_used) { count_used = counters[loop]; selected_byte = loop; } /* what to do with '== count_used'? ... */ } /* no bytes? that is definately an error :-) */ if (count_used == -1) error_exit("Internal error: no byte found!"); return selected_byte; } void usage(void) { fprintf(stderr, "-i \n"); fprintf(stderr, " With -i one selects a mapfile+imagefile to read.\n"); fprintf(stderr, "-o \n"); fprintf(stderr, " File to write output to.\n"); fprintf(stderr, "-l In case all inputimages had a badblock on the same\n"); fprintf(stderr, " place, this file will list those blocks.\n"); fprintf(stderr, "-s Limit or extend the size of the outputimage.\n"); fprintf(stderr, "-v Be verbose.\n"); fprintf(stderr, "-h This help.\n"); } int main(int argc, char *argv[]) { image *imgs = NULL; int n_imgs = 0; int loop; int fd_out = -1; off64_t offset = 0, length = 0; char *map_file = NULL; FILE *fh_map_file = NULL; version(); for(loop=1; loop= 600) (void)posix_fadvise(imgs[n_imgs].fd, 0, 0, POSIX_FADV_SEQUENTIAL); // or POSIX_FADV_NOREUSE? #endif /* remember filename */ imgs[n_imgs].filename = argv[loop]; /* get size of this image */ imgs[n_imgs].size = get_filesize(argv[loop]); if (verbose) printf("Adding image: %s/%lld number of badblocks: %d\n", imgs[n_imgs].filename, imgs[n_imgs].size, imgs[n_imgs].bb_list_size); n_imgs++; } else if (strcmp(argv[loop], "-o") == 0) { fd_out = open64(argv[++loop], O_WRONLY | O_CREAT | O_EXCL | O_SYNC, S_IRUSR | S_IWUSR); if (fd_out == -1) { fprintf(stderr, "Failed to create file %s: %s (%d)\n", argv[loop], strerror(errno), errno); return 3; } #if (_XOPEN_VERSION >= 600) (void)posix_fadvise(fd_out, 0, 0, POSIX_FADV_SEQUENTIAL); // or POSIX_FADV_NOREUSE? #endif if (verbose) printf("Writing output to: %s\n", argv[loop]); } else if (strcmp(argv[loop], "-l") == 0) { map_file = argv[++loop]; } else if (strcmp(argv[loop], "-s") == 0) { length = atoll(argv[++loop]); if (verbose) printf("Length set to: %d\n", length); } else if (strcmp(argv[loop], "-v") == 0) { verbose++; } else if (strcmp(argv[loop], "-h") == 0) { usage(); return 0; } else { fprintf(stderr, "Parameter '%s' is not recognized!\n", argv[loop]); return 9; } } if (n_imgs < 2) { fprintf(stderr, "Not enough input-images selected! (at least 2 required)\n"); return 10; } if (map_file) { fh_map_file = fopen(map_file, "w"); if (!fh_map_file) { fprintf(stderr, "Problem creating mapfile %s: %s (%d)\n", map_file, strerror(errno), errno); return 11; } #if (_XOPEN_VERSION >= 600) (void)posix_fadvise(fileno(fh_map_file), 0, 0, POSIX_FADV_SEQUENTIAL); // or POSIX_FADV_NOREUSE? #endif } if (length == (off64_t)0) { printf("No filelength given, using length of file %s: %lld\n", imgs[0].filename, (length = get_filesize(imgs[0].filename))); } for(offset=0; offset= 2) printf("Current offset: %lld\n", offset); /* find image which has no badblock at the current offset */ img_index = find_image_without_badblock(imgs, n_imgs, offset); /* image found? then copy upto the next badblock */ if (img_index != -1) { /* find next badblock */ int next_badblock = find_badblock_after_offset(imgs[img_index].bb_list, imgs[img_index].bb_list_size, offset); off64_t n_bytes_to_copy; /* no more badblocks in this image: copy image upto its end */ if (next_badblock == -1) { n_bytes_to_copy = min(imgs[img_index].size, length) - offset; } else { n_bytes_to_copy = imgs[img_index].bb_list[next_badblock].offset - offset; } if (verbose) printf("Will copy %lld bytes from file %s\n", n_bytes_to_copy, imgs[img_index].filename); /* seek in inputfile to location to read from */ myseek(imgs[img_index].fd, offset); /* copy the correct data! */ if (copy_block(imgs[img_index].fd, fd_out, n_bytes_to_copy) == -1) { fprintf(stderr, "There was a problem copying %lld bytes of data from file %s to the outputfile: %s (%d)\n", n_bytes_to_copy, imgs[img_index].filename, strerror(errno), errno); return 16; } offset += n_bytes_to_copy; } else { off64_t cur_offset, cur_bb_end; off64_t n_to_guess; char *output_buffer; int output_buffer_loop; unsigned char *guess_bytes; if (verbose) printf("No image without badblocks for current offset (%lld) found: \"guessing\" one or more bytes.\n", offset); guess_bytes = (unsigned char *)mymalloc(n_imgs, "temp buffer for bytes from each image to select from"); /* see what the smallest badblock is we're currently in */ find_smallest_current_badblock(imgs, n_imgs, offset, &img_index, &badblock_index); if (img_index == -1 || badblock_index == -1) error_exit("Internal error: could not find the badblock \"we're in\".\n"); /* see where this block ends */ cur_offset = imgs[img_index].bb_list[badblock_index].offset; cur_bb_end = cur_offset + imgs[img_index].bb_list[badblock_index].block_size; /* now that we known where the smalles badblock ends, we know how many bytes to 'guess' */ n_to_guess = cur_bb_end - offset; /* update mapfile */ if (fh_map_file) { fprintf(fh_map_file, "%lld %lld\n", offset, n_to_guess); fflush(fh_map_file); } if (verbose) { printf("\"Guessing\" %lld bytes\n", n_to_guess); printf("%s is the next file to be used\n", imgs[img_index].filename); } if (n_to_guess <= 0) error_exit("Number of \"bytes to guess\" less then 1!\n"); /** should be made 64bit safe: **/ /* it is not because if the badblock is too large for the memory, things * will fail here */ /* allocate block of memory: better not be larger then memory available :-) */ output_buffer = mymalloc(n_to_guess, "guessed bytes"); /* generate block */ for(output_buffer_loop=0; output_buffer_loop #include #include #include #include #include #include #include #include "io.h" #include "error.h" #include "gen.h" ssize_t READ(int fd, char *whereto, size_t len) { ssize_t cnt=0; while(len>0) { ssize_t rc; rc = read(fd, whereto, len); if (rc == -1) { if (errno != EINTR) { if (errno != EIO) error_exit("unexpected error while reading: %s (%d)\n", strerror(errno), errno); return -1; } } else if (rc == 0) { break; } else { whereto += rc; len -= rc; cnt += rc; } } return cnt; } ssize_t WRITE(int fd, char *whereto, size_t len) { ssize_t cnt=0; while(len>0) { ssize_t rc; rc = write(fd, whereto, len); if (rc == -1) { if (errno != EINTR) { fprintf(stderr, "WRITE::write: %d\n", errno); return -1; } } else if (rc == 0) { break; } else { whereto += rc; len -= rc; cnt += rc; } } return cnt; } ssize_t phantom_write(int fd, char *in, size_t nbytes) { ssize_t cnt = 0; size_t move_a_little; off64_t curpos; int dummy_rc; /* cannot create phantom blocks if in O_APPEND mode */ dummy_rc = fcntl(fd, F_GETFL); if (dummy_rc == -1) { fprintf(stderr, "phantom_write::fnctl: %d\n", errno); return -1; /* error */ } if ((dummy_rc & O_APPEND) == O_APPEND) return WRITE(fd, in, nbytes); /* in append you cannot create phantom blocks */ curpos = lseek64(fd, (off64_t)0, SEEK_CUR); /* could not determine current location, bail out */ if (curpos == -1) { fprintf(stderr, "phantom_write::lseek error: %d\n", errno); return -1; } /* determine how many bytes to seek to get at the start of * a sector */ move_a_little = 512 - (curpos & 511); if (move_a_little == 512) move_a_little = 0; else move_a_little = min(nbytes, move_a_little); while(nbytes > 0) { int rc; /* first, move to the start of sector. otherwhise a lseek() * will not have the effect of creating phantom blocks */ if (move_a_little > 0) { if ((rc = WRITE(fd, in, move_a_little)) <= 0) { fprintf(stderr, "phantom_write::WRITE: error\n"); return rc; } move_a_little -= rc; } /* if more then 512 bytes to write, try to create phantom * blocks */ else if (nbytes >= 512) { int loop = 0; char nulls = 1; for(loop=0; loop<512; loop++) { if (in[loop]) { nulls = 0; break; } } if (nulls) { if (lseek64(fd, (off64_t)512, SEEK_CUR) == -1) { fprintf(stderr, "phantom_write::lseek: %d\n", errno); return -1; } rc = 512; } else { if ((rc = WRITE(fd, in, 512)) <= 0) { fprintf(stderr, "phantom_write::WRITE: error: %d\n", errno); return rc; } } } else { if ((rc = WRITE(fd, in, nbytes)) <= 0) { fprintf(stderr, "phantom_write::WRITE: error: %d\n", errno); return rc; } } in += rc; cnt += rc; nbytes -= rc; } return cnt; } recoverdm-0.20/utils.c0000644000175000017500000000334011130673444014626 0ustar folkertfolkert#define _LARGEFILE64_SOURCE #include #include #include #include #include #include #include #include #include "io.h" #include "dev.h" #include "gen.h" #include "utils.h" #include "error.h" void * mymalloc(size_t size, char *what) { void *dummy = malloc(size); if (!dummy) error_exit("failed to allocate %d bytes for %s\n", size, what); return dummy; } void * myrealloc(void *oldp, size_t newsize, char *what) { void *dummy = realloc(oldp, newsize); if (!dummy) error_exit("failed to reallocate to %d bytes for %s\n", newsize, what); return dummy; } off64_t get_filesize(char *filename) { struct stat64 finfo; if (stat64(filename, &finfo) == -1) error_exit("Failed to retrieve length of file %s: %s (%d)\n", filename, strerror(errno), errno); return finfo.st_size; } int copy_block(int fd_in, int fd_out, off64_t block_size) { char buffer[512]; while (block_size > 0) { size_t sector_size = min(block_size, 512); /* read from inputfile */ if (READ(fd_in, buffer, sector_size) != sector_size) { fprintf(stderr, "Failed to read %d bytes from inputfile: %s (%d)\n", sector_size, strerror(errno), errno); return -1; } /* write to outputfile */ if (phantom_write(fd_out, buffer, sector_size) != sector_size) { fprintf(stderr, "Failed to write to outputfile: %s (%d)\n", strerror(errno), errno); return -1; } /* decrease number of bytes left */ block_size -= sector_size; } return 0; } void myseek(int fd, off64_t offset) { /* seek in inputfile to correct offset */ if (lseek64(fd, offset, SEEK_SET) == -1) error_exit("Failed to seek in file to offset %lld: %s (%d)\n", offset, strerror(errno), errno); } recoverdm-0.20/gen.h0000644000175000017500000000005211130673444014241 0ustar folkertfolkert#define min(x, y) ((x)<(y)?(x):(y)) recoverdm-0.20/error.c0000644000175000017500000000052611130673444014622 0ustar folkertfolkert#include #include #include #include #include #include void error_exit(char *format, ...) { va_list ap; fflush(NULL); va_start(ap, format); (void)vfprintf(stderr, format, ap); va_end(ap); fprintf(stderr, "errno=%d (if applicable)\n", errno); exit(EXIT_FAILURE); } recoverdm-0.20/recoverdm.10000644000175000017500000000000011130673444015360 0ustar folkertfolkertrecoverdm-0.20/dev.c0000644000175000017500000000556211130673444014254 0ustar folkertfolkert/* $Id: dev.c,v 0.14 2003/01/27 18:32:26 folkert Exp folkert $ * $Log: dev.c,v $ * Revision 0.14 2003/01/27 18:32:26 folkert * added RAW-mode for CD/DVD * */ #include #include #include #include #include #ifdef __linux__ #include #include #include #include #include #include #endif #include "dev.h" int init_device(int fd, int dev_type, int rotation_speed) { #ifdef __linux__ switch(dev_type) { case DT_FLOPPY: { struct floppy_max_errors fme; if (ioctl(fd, FDGETMAXERRS, &fme, sizeof(fme)) == -1) { perror("FDGETMAXERRS"); return -1; } fme.reset = 2; fme.recal = 3; if (ioctl(fd, FDSETMAXERRS, &fme, sizeof(fme)) == -1) { perror("FDSETMAXERRS"); return -1; } } break; case DT_CDROM_IDE: case DT_CDROM_SCSI: case DT_DVD_IDE: case DT_DVD_SCSI: { int speed = rotation_speed; if (ioctl(fd, CDROM_SELECT_SPEED, speed) == -1) { perror("CDROM_SELECT_SPEED"); return -1; } } break; } #endif return 0; } int clear_buffers(int fd, int dev_type) { #ifdef __linux__ switch(dev_type) { case DT_FLOPPY: if (ioctl(fd, FDFLUSH) == -1) { perror("FDFLUSH"); return -1; } break; } #endif return 0; } int reset_controller(int fd, int dev_type) { #ifdef __linux__ switch(dev_type) { case DT_FLOPPY: if (ioctl(fd, FDRESET) == -1) { perror("FDRESET"); return -1; } break; case DT_DISK_SCSI: if (ioctl(fd, SG_SCSI_RESET) == -1) { perror("SG_SCSI_RESET"); return -1; } break; } #endif return 0; } int reset_device(int fd, int dev_type) { #ifdef __linux__ switch(dev_type) { case DT_DISK_IDE: #if 0 /* tricky! */ if (ioctl(fd, HDIO_DRIVE_RESET) == -1) { perror("HDIO_DRIVE_RESET"); return -1; } #endif break; case DT_DISK_SCSI: #if 0 /* tricky! */ if (ioctl(fd, SCSI_IOCTL_STOP_UNIT) == -1) { perror("SCSI_IOCTL_STOP_UNIT"); return -1; } sleep(1); if (ioctl(fd, SCSI_IOCTL_START_UNIT) == -1) { perror("SCSI_IOCTL_START_UNIT"); return -1; } #endif break; case DT_CDROM_IDE: case DT_CDROM_SCSI: case DT_DVD_IDE: case DT_DVD_SCSI: if (ioctl(fd, CDROMRESET) == -1) { perror("CDROMRESET"); return -1; } break; } #endif return 0; } int read_raw_cd(int fd, unsigned char minute, unsigned char second, unsigned char frame, char *whereto) { #ifdef __linux__ char *pframe = (char *)malloc(CD_FRAMESIZE_RAWER); struct cdrom_msf *msf = (struct cdrom_msf *)pframe; msf -> cdmsf_min0 = msf -> cdmsf_min1 = minute; msf -> cdmsf_sec0 = msf -> cdmsf_sec1 = second; msf -> cdmsf_frame0 = msf -> cdmsf_frame1 = frame; if (ioctl(fd, CDROMREADRAW, msf) == -1) { if (errno != EIO) return -1; } memcpy(whereto, &pframe[12 + 4], 2048); return 0; #else return -1; #endif } recoverdm-0.20/license.txt0000644000175000017500000000017711130673444015512 0ustar folkertfolkertThe license of this program can be obtained from: http://www.vanheusden.com/license.txt It is actually the GNU Public License. recoverdm-0.20/readme.txt0000644000175000017500000000022411130673444015316 0ustar folkertfolkertGot suggestions/questions? Feel free to e-mail me at: folkert@vanheusden.com Want to buy me anything? http://keetweej.vanheusden.com/wishlist.html