Sounds cool, perhaps it's time to move recoverdisk into the base system to give it better exposure? -Maxim Ulrich Spoerlein wrote: > Dear Poul-Henning, current_at_, > > I made two, what I call, improvements to recoverdisk. It only tries to > read in multiples of 512 bytes OR the sectorsize. This sucks for CD/DVD > with 2352 bytes sectorsize. My patch takes the native sectorsize into > account, when dimensioning BIG and MEDIUMSIZE. > > Second feature is the saving and loading of the worklist. Again, not > very helpful for reading hard disks, but very useful for CDs. This way, > you can first try a scratched CD in drive A, then drive B and drive C. > You don't have to start all over again, but instead can profit from the > different error recovery mechanisms. > > Previously, I did this with dd(1) and paper and pencil. Not funny. > > Please try the attached patch, thanks! > > Ulrich Spoerlein > > > ------------------------------------------------------------------------ > > --- recoverdisk.orig.c Mon Apr 24 19:34:57 2006 > +++ recoverdisk.c Tue Apr 25 14:11:44 2006 > _at__at_ -14,15 +14,20 _at__at_ > #include <err.h> > #include <errno.h> > #include <fcntl.h> > +#include <signal.h> > +#include <string.h> > +#include <sysexits.h> > #include <time.h> > #include <unistd.h> > #include <sys/queue.h> > #include <sys/disk.h> > #include <sys/stat.h> > > -#define BIGSIZE (1046640) > -#define MEDIUMSIZE (63504) > -#define MINSIZE (512) > +#define MIN(a,b) (((a)<(b))?(a):(b)) > + > +static off_t bigsize = 1024 * 1024; > +static off_t medsize = 64 * 1024; > +static off_t minsize = 512; > > struct lump { > off_t start; > _at__at_ -48,29 +53,119 _at__at_ > TAILQ_INSERT_TAIL(&lumps, lp, list); > } > > +static struct lump *lp; > +static char *wworklist = NULL; > +static char *rworklist = NULL; > + > +/* Save the worklist, if -w was given */ > +static void > +save_worklist(__unused int sig) > +{ > + FILE *file; > + > + if (wworklist != NULL) { > + fprintf(stderr, "\nSaving worklist ..."); > + fflush(stderr); > + > + file = fopen(wworklist, "w"); > + if (file == NULL) > + err(1, "Error opening file %s", wworklist); > + > + for (;;) { > + lp = TAILQ_FIRST(&lumps); > + if (lp == NULL) > + break; > + fprintf(file, "%jd %jd %d\n", > + (intmax_t)lp->start, (intmax_t)lp->len, lp->state); > + TAILQ_REMOVE(&lumps, lp, list); > + } > + fprintf(stderr, " done.\n"); > + } > + exit(0); > +} > + > +static off_t > +read_worklist(off_t t) > +{ > + off_t s, l, d; > + int state, lines; > + FILE *file; > + > + fprintf(stderr, "Reading worklist ..."); > + fflush(stderr); > + file = fopen(rworklist, "r"); > + if (file == NULL) > + err(1, "Error opening file %s", rworklist); > + > + lines = 0; > + d = t; > + for (;;) { > + ++lines; > + if (3 != fscanf(file, "%jd %jd %d\n", &s, &l, &state)) { > + if (!feof(file)) > + err(1, "Error parsing file %s at line %d", > + rworklist, lines); > + else > + break; > + } > + > + new_lump(s, l, state); > + d -= l; > + } > + fprintf(stderr, " done.\n"); > + > + /* > + * Return the number of bytes already read (at least not in > + * worklist). > + */ > + return (d); > +} > + > +static void > +usage(void) > +{ > + fprintf(stderr, "Usage: %s [-r worklist] [-w worklist] source-drive [destination]", "recoverdisk"); > + exit(EX_USAGE); > +} > + > int > -main(int argc, const char **argv) > +main(int argc, char * const argv[]) > { > + int ch; > int fdr, fdw; > - struct lump *lp; > off_t t, d; > size_t i, j; > int error, flags; > u_char *buf; > - u_int sectorsize, minsize; > + u_int sectorsize; > time_t t1, t2; > struct stat sb; > > + while ((ch = getopt(argc, argv, "r:w:")) != -1) { > + switch (ch) { > + case 'w': > + wworklist = strdup(optarg); > + if (wworklist == NULL) > + err(1, "Cannot allocate enough memory"); > + break; > + case 'r': > + rworklist = strdup(optarg); > + if (rworklist == NULL) > + err(1, "Cannot allocate enough memory"); > + break; > + default: > + usage(); > + } > + } > + argc -= optind; > + argv += optind; > > - if (argc < 2) > - errx(1, "Usage: %s source-drive [destination]", argv[0]); > + if (argc < 1) > + usage(); > > - buf = malloc(BIGSIZE); > - if (buf == NULL) > - err(1, "Cannot allocate %d bytes buffer", BIGSIZE); > - fdr = open(argv[1], O_RDONLY); > + fdr = open(argv[0], O_RDONLY); > if (fdr < 0) > - err(1, "Cannot open read descriptor %s", argv[1]); > + err(1, "Cannot open read descriptor %s", argv[0]); > > error = fstat(fdr, &sb); > if (error < 0) > _at__at_ -80,46 +175,62 _at__at_ > error = ioctl(fdr, DIOCGSECTORSIZE, §orsize); > if (error < 0) > err(1, "DIOCGSECTORSIZE failed"); > + > + /* > + * Make medsize roughly 64kB, depending on native sector > + * size. bigsize has to be a multiple of medsize. > + * For media with 2352 sectors, this will > + * result in 2352, 63504, and 1016064 bytes. > + */ > minsize = sectorsize; > + medsize = (medsize / sectorsize) * sectorsize; > + bigsize = medsize * 16; > > error = ioctl(fdr, DIOCGMEDIASIZE, &t); > if (error < 0) > err(1, "DIOCGMEDIASIZE failed"); > } else { > - sectorsize = 1; > t = sb.st_size; > - minsize = MINSIZE; > flags |= O_CREAT | O_TRUNC; > } > > - if (argc > 2) { > - fdw = open(argv[2], flags, DEFFILEMODE); > + buf = malloc(bigsize); > + if (buf == NULL) > + err(1, "Cannot allocate %jd bytes buffer", (intmax_t)bigsize); > + > + if (argc > 1) { > + fdw = open(argv[1], flags, DEFFILEMODE); > if (fdw < 0) > - err(1, "Cannot open write descriptor %s", argv[2]); > + err(1, "Cannot open write descriptor %s", argv[1]); > } else { > fdw = -1; > } > > - new_lump(0, t, 0); > - d = 0; > + if (rworklist != NULL) { > + d = read_worklist(t); > + } else { > + new_lump(0, t, 0); > + d = 0; > + } > + > + signal(SIGINT, save_worklist); > > t1 = 0; > + printf("%13s %7s %13s %5s %13s %13s %9s\n", > + "start", "size", "len", "state", "done", "remaining", "% done"); > for (;;) { > lp = TAILQ_FIRST(&lumps); > if (lp == NULL) > break; > - TAILQ_REMOVE(&lumps, lp, list); > while (lp->len > 0) { > - i = BIGSIZE; > - if (lp->len < BIGSIZE) > - i = lp->len; > + i = MIN(lp->len, bigsize); > if (lp->state == 1) > - i = MEDIUMSIZE; > + i = MIN(lp->len, medsize); > if (lp->state > 1) > - i = minsize; > + i = MIN(lp->len, minsize); > time(&t2); > - if (t1 != t2 || lp->len < BIGSIZE) { > - printf("\r%13jd %7zu %13jd %3d %13jd %13jd %.8f", > + if (t1 != t2 || lp->len < bigsize) { > + printf("\r%13jd %7zu %13jd %5d %13jd %13jd %.7f", > (intmax_t)lp->start, > i, > (intmax_t)lp->len, > _at__at_ -152,9 +263,10 _at__at_ > lp->start += i; > lp->len -= i; > } > + TAILQ_REMOVE(&lumps, lp, list); > free(lp); > } > printf("\nCompleted\n"); > - exit (0); > + return (0); > } >Received on Tue Apr 25 2006 - 17:48:53 UTC
This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:38:55 UTC