recoverdisk.c revision 136815
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 136815 2004-10-23 15:58:50Z des $ 10135911Sphk */ 11135911Sphk#include <stdio.h> 12135911Sphk#include <stdint.h> 13135911Sphk#include <stdlib.h> 14136257Sphk#include <err.h> 15135911Sphk#include <errno.h> 16135911Sphk#include <fcntl.h> 17136257Sphk#include <time.h> 18135911Sphk#include <unistd.h> 19135911Sphk#include <sys/queue.h> 20135911Sphk#include <sys/disk.h> 21135911Sphk 22135911Sphk#define BIGSIZE (1024 * 1024) 23135911Sphk#define MEDIUMSIZE (64 * 1024) 24135911Sphk 25135911Sphkstruct lump { 26135911Sphk off_t start; 27135911Sphk off_t len; 28135911Sphk int state; 29135911Sphk TAILQ_ENTRY(lump) list; 30135911Sphk}; 31135911Sphk 32135911Sphkstatic TAILQ_HEAD(, lump) lumps = TAILQ_HEAD_INITIALIZER(lumps); 33135911Sphk 34135911Sphk 35135911Sphkstatic void 36135911Sphknew_lump(off_t start, off_t len, int state) 37135911Sphk{ 38135911Sphk struct lump *lp; 39135911Sphk 40135911Sphk lp = malloc(sizeof *lp); 41135911Sphk if (lp == NULL) 42135911Sphk err(1, "Malloc failed"); 43135911Sphk lp->start = start; 44135911Sphk lp->len = len; 45135911Sphk lp->state = state; 46135911Sphk TAILQ_INSERT_TAIL(&lumps, lp, list); 47135911Sphk} 48135911Sphk 49135911Sphkint 50135911Sphkmain(int argc, const char **argv) 51135911Sphk{ 52135911Sphk int fdr, fdw; 53135911Sphk struct lump *lp; 54135911Sphk off_t t, d; 55135911Sphk size_t i, j; 56135911Sphk int error; 57135911Sphk u_char *buf; 58135911Sphk u_int sectorsize; 59136257Sphk time_t t1, t2; 60135911Sphk 61135911Sphk 62135911Sphk if (argc < 2) 63135911Sphk errx(1, "Usage: %s source-drive [destination]", argv[0]); 64135911Sphk 65135911Sphk buf = malloc(BIGSIZE); 66135911Sphk if (buf == NULL) 67135911Sphk err(1, "Cannot allocate %d bytes buffer", BIGSIZE); 68135911Sphk fdr = open(argv[1], O_RDONLY); 69135911Sphk if (fdr < 0) 70135911Sphk err(1, "Cannot open read descriptor %s", argv[1]); 71135911Sphk if (argc > 2) { 72135911Sphk fdw = open(argv[2], O_WRONLY); 73135911Sphk if (fdw < 0) 74135911Sphk err(1, "Cannot open write descriptor %s", argv[2]); 75135911Sphk } else { 76135911Sphk fdw = -1; 77135911Sphk } 78135911Sphk 79135911Sphk error = ioctl(fdr, DIOCGSECTORSIZE, §orsize); 80135911Sphk if (error < 0) 81135911Sphk err(1, "DIOCGSECTORSIZE failed"); 82135911Sphk 83135911Sphk error = ioctl(fdr, DIOCGMEDIASIZE, &t); 84135911Sphk if (error < 0) 85135911Sphk err(1, "DIOCGMEDIASIZE failed"); 86135911Sphk 87135911Sphk new_lump(0, t, 0); 88135911Sphk d = 0; 89135911Sphk 90136257Sphk t1 = 0; 91135911Sphk for (;;) { 92135911Sphk lp = TAILQ_FIRST(&lumps); 93135911Sphk if (lp == NULL) 94135911Sphk break; 95135911Sphk TAILQ_REMOVE(&lumps, lp, list); 96135911Sphk while (lp->len > 0) { 97135911Sphk i = BIGSIZE; 98135911Sphk if (lp->len < BIGSIZE) 99135911Sphk i = lp->len; 100135911Sphk if (lp->state == 1) 101135911Sphk i = MEDIUMSIZE; 102135911Sphk if (lp->state > 1) 103135911Sphk i = sectorsize; 104136257Sphk time(&t2); 105136257Sphk if (t1 != t2 || lp->len < BIGSIZE) { 106136815Sdes printf("\r%13jd %7zu %13jd %3d %13jd %13jd %.8f", 107136257Sphk (intmax_t)lp->start, 108136815Sdes i, 109136257Sphk (intmax_t)lp->len, 110136257Sphk lp->state, 111136257Sphk (intmax_t)d, 112136257Sphk (intmax_t)(t - d), 113136257Sphk (double)d/(double)t); 114136257Sphk t1 = t2; 115136257Sphk } 116135911Sphk if (i == 0) { 117135911Sphk errx(1, "BOGUS i %10jd", (intmax_t)i); 118135911Sphk } 119135911Sphk fflush(stdout); 120135911Sphk j = pread(fdr, buf, i, lp->start); 121135911Sphk if (j == i) { 122135911Sphk d += i; 123135911Sphk if (fdw >= 0) 124135911Sphk j = pwrite(fdw, buf, i, lp->start); 125135911Sphk else 126135911Sphk j = i; 127135911Sphk if (j != i) 128136815Sdes printf("\nWrite error at %jd/%zu\n", 129136815Sdes lp->start, i); 130135911Sphk lp->start += i; 131135911Sphk lp->len -= i; 132135911Sphk continue; 133135911Sphk } 134136815Sdes printf("\n%jd %zu failed %d\n", lp->start, i, errno); 135135911Sphk new_lump(lp->start, i, lp->state + 1); 136135911Sphk lp->start += i; 137135911Sphk lp->len -= i; 138135911Sphk } 139135911Sphk free(lp); 140135911Sphk } 141135911Sphk printf("\nCompleted\n"); 142135911Sphk exit (0); 143135911Sphk} 144135911Sphk 145