recoverdisk.c revision 135911
1135911Sphk/* 2135911Sphk * ---------------------------------------------------------------------------- 3135911Sphk * "THE BEER-WARE LICENSE" (Revision 42): 4135911Sphk * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you 5135911Sphk * can do whatever you want with this stuff. If we meet some day, and you think 6135911Sphk * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 7135911Sphk * ---------------------------------------------------------------------------- 8135911Sphk * 9135911Sphk * $FreeBSD: head/sbin/recoverdisk/recoverdisk.c 135911 2004-09-28 22:00:01Z phk $ 10135911Sphk */ 11135911Sphk#include <stdio.h> 12135911Sphk#include <stdint.h> 13135911Sphk#include <stdlib.h> 14135911Sphk#include <errno.h> 15135911Sphk#include <fcntl.h> 16135911Sphk#include <err.h> 17135911Sphk#include <unistd.h> 18135911Sphk#include <sys/queue.h> 19135911Sphk#include <sys/disk.h> 20135911Sphk 21135911Sphk#define BIGSIZE (1024 * 1024) 22135911Sphk#define MEDIUMSIZE (64 * 1024) 23135911Sphk 24135911Sphkstruct lump { 25135911Sphk off_t start; 26135911Sphk off_t len; 27135911Sphk int state; 28135911Sphk TAILQ_ENTRY(lump) list; 29135911Sphk}; 30135911Sphk 31135911Sphkstatic TAILQ_HEAD(, lump) lumps = TAILQ_HEAD_INITIALIZER(lumps); 32135911Sphk 33135911Sphk 34135911Sphkstatic void 35135911Sphknew_lump(off_t start, off_t len, int state) 36135911Sphk{ 37135911Sphk struct lump *lp; 38135911Sphk 39135911Sphk lp = malloc(sizeof *lp); 40135911Sphk if (lp == NULL) 41135911Sphk err(1, "Malloc failed"); 42135911Sphk lp->start = start; 43135911Sphk lp->len = len; 44135911Sphk lp->state = state; 45135911Sphk TAILQ_INSERT_TAIL(&lumps, lp, list); 46135911Sphk} 47135911Sphk 48135911Sphkint 49135911Sphkmain(int argc, const char **argv) 50135911Sphk{ 51135911Sphk int fdr, fdw; 52135911Sphk struct lump *lp; 53135911Sphk off_t t, d; 54135911Sphk size_t i, j; 55135911Sphk int error; 56135911Sphk u_char *buf; 57135911Sphk u_int sectorsize; 58135911Sphk 59135911Sphk 60135911Sphk if (argc < 2) 61135911Sphk errx(1, "Usage: %s source-drive [destination]", argv[0]); 62135911Sphk 63135911Sphk buf = malloc(BIGSIZE); 64135911Sphk if (buf == NULL) 65135911Sphk err(1, "Cannot allocate %d bytes buffer", BIGSIZE); 66135911Sphk fdr = open(argv[1], O_RDONLY); 67135911Sphk if (fdr < 0) 68135911Sphk err(1, "Cannot open read descriptor %s", argv[1]); 69135911Sphk if (argc > 2) { 70135911Sphk fdw = open(argv[2], O_WRONLY); 71135911Sphk if (fdw < 0) 72135911Sphk err(1, "Cannot open write descriptor %s", argv[2]); 73135911Sphk } else { 74135911Sphk fdw = -1; 75135911Sphk } 76135911Sphk 77135911Sphk error = ioctl(fdr, DIOCGSECTORSIZE, §orsize); 78135911Sphk if (error < 0) 79135911Sphk err(1, "DIOCGSECTORSIZE failed"); 80135911Sphk 81135911Sphk error = ioctl(fdr, DIOCGMEDIASIZE, &t); 82135911Sphk if (error < 0) 83135911Sphk err(1, "DIOCGMEDIASIZE failed"); 84135911Sphk 85135911Sphk new_lump(0, t, 0); 86135911Sphk d = 0; 87135911Sphk 88135911Sphk for (;;) { 89135911Sphk lp = TAILQ_FIRST(&lumps); 90135911Sphk if (lp == NULL) 91135911Sphk break; 92135911Sphk TAILQ_REMOVE(&lumps, lp, list); 93135911Sphk while (lp->len > 0) { 94135911Sphk i = BIGSIZE; 95135911Sphk if (lp->len < BIGSIZE) 96135911Sphk i = lp->len; 97135911Sphk if (lp->state == 1) 98135911Sphk i = MEDIUMSIZE; 99135911Sphk if (lp->state > 1) 100135911Sphk i = sectorsize; 101135911Sphk printf("\r%13jd %7jd %13jd %3d %13jd %13jd %.8f", 102135911Sphk (intmax_t)lp->start, 103135911Sphk (intmax_t)i, 104135911Sphk (intmax_t)lp->len, 105135911Sphk lp->state, 106135911Sphk (intmax_t)d, 107135911Sphk (intmax_t)(t - d), 108135911Sphk (double)d/(double)t); 109135911Sphk if (i == 0) { 110135911Sphk errx(1, "BOGUS i %10jd", (intmax_t)i); 111135911Sphk } 112135911Sphk fflush(stdout); 113135911Sphk j = pread(fdr, buf, i, lp->start); 114135911Sphk if (j == i) { 115135911Sphk d += i; 116135911Sphk if (fdw >= 0) 117135911Sphk j = pwrite(fdw, buf, i, lp->start); 118135911Sphk else 119135911Sphk j = i; 120135911Sphk if (j != i) 121135911Sphk printf("\nWrite error at %jd/%d\n", 122135911Sphk lp->start, i); 123135911Sphk lp->start += i; 124135911Sphk lp->len -= i; 125135911Sphk continue; 126135911Sphk } 127135911Sphk printf("\n%jd %d failed %d\n", lp->start, i, errno); 128135911Sphk new_lump(lp->start, i, lp->state + 1); 129135911Sphk lp->start += i; 130135911Sphk lp->len -= i; 131135911Sphk } 132135911Sphk free(lp); 133135911Sphk } 134135911Sphk printf("\nCompleted\n"); 135135911Sphk exit (0); 136135911Sphk} 137135911Sphk 138