Date: Thu, 4 May 2006 22:50:17 GMT From: Ulrich Spoerlein <uspoerlein@gmail.com> To: freebsd-bugs@FreeBSD.org Subject: Re: bin/96677: Improvements for src/tools/tools/recoverdisk Message-ID: <200605042250.k44MoHuU098307@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR bin/96677; it has been noted by GNATS. From: Ulrich Spoerlein <uspoerlein@gmail.com> To: Maxim Konovalov <maxim@macomnet.ru> Cc: bug-followup@freebsd.org Subject: Re: bin/96677: Improvements for src/tools/tools/recoverdisk Date: Thu, 4 May 2006 15:56:17 +0200 Here's a simple alternative, that only sets a flag in the signal handler. Ulrich Spoerlein --- recoverdisk.c.orig Thu Dec 15 19:41:42 2005 +++ recoverdisk.c Thu May 4 15:51:08 2006 @@ -1,4 +1,4 @@ -/* +/*- * ---------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you @@ -8,21 +8,29 @@ * * $FreeBSD: src/tools/tools/recoverdisk/recoverdisk.c,v 1.4.4.1 2005/12/15 03:50:03 sobomax Exp $ */ +#include <stdbool.h> #include <stdio.h> #include <stdint.h> #include <stdlib.h> #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 (1024 * 1024) -#define MEDIUMSIZE (64 * 1024) -#define MINSIZE (512) +#define MIN(a,b) (((a)<(b))?(a):(b)) + +static bool aborting = false; + +static size_t bigsize = 1024 * 1024; +static size_t medsize = 64 * 1024; +static size_t minsize = 512; struct lump { off_t start; @@ -33,7 +41,6 @@ static TAILQ_HEAD(, lump) lumps = TAILQ_HEAD_INITIALIZER(lumps); - static void new_lump(off_t start, off_t len, int state) { @@ -48,29 +55,128 @@ 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(void) +{ + FILE *file; + + if (wworklist != NULL) { + (void)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); + } + (void)fprintf(stderr, " done.\n"); + } + exit(0); +} + +/* Read the worklist if -r was given */ +static off_t +read_worklist(off_t t) +{ + off_t s, l, d; + int state, lines; + FILE *file; + + (void)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; + } + (void)fprintf(stderr, " done.\n"); + + /* + * Return the number of bytes already read + * (at least not in worklist). + */ + return (d); +} + +static void +usage(void) +{ + (void)fprintf(stderr, + "usage: recoverdisk [-r worklist] [-w worklist] source-drive [destination]\n"); + exit(EX_USAGE); +} + +static void +sighandler(__unused int sig) +{ + aborting = true; + signal(SIGINT, SIG_DFL); +} + 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; + 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 || argc > 2) + 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) @@ -80,46 +186,66 @@ 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; + } + + if (wworklist != NULL) { + signal(SIGINT, sighandler); + /* Has this any effect on pread/pwrite at all? */ + siginterrupt(SIGINT, 1); + } 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; + while (lp->len > 0 && !aborting) { + 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, @@ -152,9 +278,13 @@ lp->start += i; lp->len -= i; } + + if (aborting) + save_worklist(); + + TAILQ_REMOVE(&lumps, lp, list); free(lp); } printf("\nCompleted\n"); - exit (0); + return (0); } -
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200605042250.k44MoHuU098307>