From owner-freebsd-current@FreeBSD.ORG Tue Apr 25 19:13:19 2006 Return-Path: X-Original-To: current@freebsd.org Delivered-To: freebsd-current@FreeBSD.ORG Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 0EB7A16A401 for ; Tue, 25 Apr 2006 19:13:19 +0000 (UTC) (envelope-from uspoerlein@gmail.com) Received: from nproxy.gmail.com (nproxy.gmail.com [64.233.182.189]) by mx1.FreeBSD.org (Postfix) with ESMTP id 38E7343D46 for ; Tue, 25 Apr 2006 19:13:17 +0000 (GMT) (envelope-from uspoerlein@gmail.com) Received: by nproxy.gmail.com with SMTP id m18so1036683nfc for ; Tue, 25 Apr 2006 12:13:16 -0700 (PDT) DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=beta; d=gmail.com; h=received:date:from:to:cc:subject:message-id:mail-followup-to:mime-version:content-type:content-disposition; b=HACipbkk5xy7Ea/R8EjSZBEyqP884LVA80+P8MbeXFHBBFcsl6+kNcEiR0FMOJFPYjeXYOQ454Hj0ouNlmppABKYZssEhTPsPiIrpmi3U+hxGy/ZxAZrRdmVZnSXlZjb9u853tOCHpS/cgRLgiclG9ShiH1hfMsejKMvl0rAFR0= Received: by 10.48.205.14 with SMTP id c14mr3947650nfg; Tue, 25 Apr 2006 12:13:16 -0700 (PDT) Received: from roadrunner.q.local ( [217.229.213.165]) by mx.gmail.com with ESMTP id l38sm1280271nfc.2006.04.25.12.13.04; Tue, 25 Apr 2006 12:13:16 -0700 (PDT) Received: from roadrunner.q.local (localhost [127.0.0.1]) by roadrunner.q.local (8.13.6/8.13.6) with ESMTP id k3PJCFg8001089; Tue, 25 Apr 2006 21:12:23 +0200 (CEST) (envelope-from uspoerlein@gmail.com) Received: (from q@localhost) by roadrunner.q.local (8.13.6/8.13.6/Submit) id k3PCEMtx024542; Tue, 25 Apr 2006 14:14:22 +0200 (CEST) (envelope-from uspoerlein@gmail.com) Date: Tue, 25 Apr 2006 14:14:22 +0200 From: Ulrich Spoerlein To: phk@freebsd.org Message-ID: <20060425121421.GB1105@roadrunner.q.local> Mail-Followup-To: phk@freebsd.org, current@freebsd.org MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="xXmbgvnjoT4axfJE" Content-Disposition: inline Cc: current@freebsd.org Subject: Improvements to src/tools/tools/recoverdisk X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 25 Apr 2006 19:13:19 -0000 --xXmbgvnjoT4axfJE Content-Type: multipart/mixed; boundary="cWoXeonUoKmBZSoM" Content-Disposition: inline --cWoXeonUoKmBZSoM Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Dear Poul-Henning, current@, 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 --=20 PGP Key ID: 20FEE9DD Encrypted mail welcome! Fingerprint: AEC9 AF5E 01AC 4EE1 8F70 6CBD E76E 2227 20FE E9DD Which is worse: ignorance or apathy? Don't know. Don't care. --cWoXeonUoKmBZSoM Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=patch Content-Transfer-Encoding: quoted-printable --- recoverdisk.orig.c Mon Apr 24 19:34:57 2006 +++ recoverdisk.c Tue Apr 25 14:11:44 2006 @@ -14,15 +14,20 @@ #include #include #include +#include +#include +#include #include #include #include #include #include =20 -#define BIGSIZE (1046640) -#define MEDIUMSIZE (63504) -#define MINSIZE (512) +#define MIN(a,b) (((a)<(b))?(a):(b)) + +static off_t bigsize =3D 1024 * 1024; +static off_t medsize =3D 64 * 1024; +static off_t minsize =3D 512; =20 struct lump { off_t start; @@ -48,29 +53,119 @@ TAILQ_INSERT_TAIL(&lumps, lp, list); } =20 +static struct lump *lp; +static char *wworklist =3D NULL; +static char *rworklist =3D NULL; + +/* Save the worklist, if -w was given */ +static void +save_worklist(__unused int sig) +{ + FILE *file; + + if (wworklist !=3D NULL) { + fprintf(stderr, "\nSaving worklist ..."); + fflush(stderr); + + file =3D fopen(wworklist, "w"); + if (file =3D=3D NULL) + err(1, "Error opening file %s", wworklist); + + for (;;) { + lp =3D TAILQ_FIRST(&lumps); + if (lp =3D=3D 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; +=09 + fprintf(stderr, "Reading worklist ..."); + fflush(stderr); + file =3D fopen(rworklist, "r"); + if (file =3D=3D NULL) + err(1, "Error opening file %s", rworklist); + + lines =3D 0; + d =3D t; + for (;;) { + ++lines; + if (3 !=3D 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 -=3D l; + } + fprintf(stderr, " done.\n"); + + /*=20 + * 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 [dest= ination]", "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; =20 + while ((ch =3D getopt(argc, argv, "r:w:")) !=3D -1) { + switch (ch) { + case 'w': + wworklist =3D strdup(optarg); + if (wworklist =3D=3D NULL) + err(1, "Cannot allocate enough memory"); + break; + case 'r': + rworklist =3D strdup(optarg); + if (rworklist =3D=3D NULL) + err(1, "Cannot allocate enough memory"); + break; + default: + usage(); + } + } + argc -=3D optind; + argv +=3D optind; =20 - if (argc < 2) - errx(1, "Usage: %s source-drive [destination]", argv[0]); + if (argc < 1) + usage(); =20 - buf =3D malloc(BIGSIZE); - if (buf =3D=3D NULL) - err(1, "Cannot allocate %d bytes buffer", BIGSIZE); - fdr =3D open(argv[1], O_RDONLY); + fdr =3D 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]); =20 error =3D fstat(fdr, &sb); if (error < 0) @@ -80,46 +175,62 @@ error =3D 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 =3D sectorsize; + medsize =3D (medsize / sectorsize) * sectorsize; + bigsize =3D medsize * 16; =20 error =3D ioctl(fdr, DIOCGMEDIASIZE, &t); if (error < 0) err(1, "DIOCGMEDIASIZE failed"); } else { - sectorsize =3D 1; t =3D sb.st_size; - minsize =3D MINSIZE; flags |=3D O_CREAT | O_TRUNC; } =20 - if (argc > 2) { - fdw =3D open(argv[2], flags, DEFFILEMODE); + buf =3D malloc(bigsize); + if (buf =3D=3D NULL) + err(1, "Cannot allocate %jd bytes buffer", (intmax_t)bigsize); + + if (argc > 1) { + fdw =3D 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 =3D -1; } =20 - new_lump(0, t, 0); - d =3D 0; + if (rworklist !=3D NULL) { + d =3D read_worklist(t); + } else { + new_lump(0, t, 0); + d =3D 0; + } + + signal(SIGINT, save_worklist); =20 t1 =3D 0; + printf("%13s %7s %13s %5s %13s %13s %9s\n", + "start", "size", "len", "state", "done", "remaining", "% done"); for (;;) { lp =3D TAILQ_FIRST(&lumps); if (lp =3D=3D NULL) break; - TAILQ_REMOVE(&lumps, lp, list); while (lp->len > 0) { - i =3D BIGSIZE; - if (lp->len < BIGSIZE) - i =3D lp->len; + i =3D MIN(lp->len, bigsize); if (lp->state =3D=3D 1) - i =3D MEDIUMSIZE; + i =3D MIN(lp->len, medsize); if (lp->state > 1) - i =3D minsize; + i =3D MIN(lp->len, minsize); time(&t2); - if (t1 !=3D t2 || lp->len < BIGSIZE) { - printf("\r%13jd %7zu %13jd %3d %13jd %13jd %.8f", + if (t1 !=3D t2 || lp->len < bigsize) { + printf("\r%13jd %7zu %13jd %5d %13jd %13jd %.7f", (intmax_t)lp->start, i,=20 (intmax_t)lp->len, @@ -152,9 +263,10 @@ lp->start +=3D i; lp->len -=3D i; } + TAILQ_REMOVE(&lumps, lp, list); free(lp); } printf("\nCompleted\n"); - exit (0); + return (0); } =20 --cWoXeonUoKmBZSoM-- --xXmbgvnjoT4axfJE Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.2.2 (FreeBSD) iD8DBQFEThKd524iJyD+6d0RAusvAKCUKUygQ5KDnyCD6n99t0IAYWvcKQCfTOQS 7fBlfjimLz3gj1R37zmFK00= =bAwp -----END PGP SIGNATURE----- --xXmbgvnjoT4axfJE--