diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/tools/recoverdisk/Makefile | 9 | ||||
-rw-r--r-- | tools/tools/recoverdisk/recoverdisk.1 | 133 | ||||
-rw-r--r-- | tools/tools/recoverdisk/recoverdisk.c | 294 |
3 files changed, 0 insertions, 436 deletions
diff --git a/tools/tools/recoverdisk/Makefile b/tools/tools/recoverdisk/Makefile deleted file mode 100644 index 6733a4f..0000000 --- a/tools/tools/recoverdisk/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# $FreeBSD$ - -PROG= recoverdisk -WARNS?= 6 - -.include <bsd.prog.mk> - -test: ${PROG} - ./${PROG} /dev/ad0 diff --git a/tools/tools/recoverdisk/recoverdisk.1 b/tools/tools/recoverdisk/recoverdisk.1 deleted file mode 100644 index c5526b3..0000000 --- a/tools/tools/recoverdisk/recoverdisk.1 +++ /dev/null @@ -1,133 +0,0 @@ -.\" Copyright (c) 2006 Ulrich Spoerlein <uspoerlein@gmail.com> -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $FreeBSD$ -.\" -.Dd May 6, 2006 -.Dt RECOVERDISK 1 -.Os -.Sh NAME -.Nm recoverdisk -.Nd recover data from hard disk or optical media -.Sh SYNOPSIS -.Nm -.Op Fl r Ar rlist -.Op Fl w Ar wlist -.Ar special -.Op Ar file -.Sh DESCRIPTION -The -.Nm -utility reads data from the -.Ar special -file until all blocks could be successfully read. -It starts reading in multiples of the sector size. -Whenever a block fails, it is put to the end of the working queue and will be -read again, possibly with a smaller read size. -.Pp -It uses block sizes of roughly 1 MB, 64kB, and the native sector size (usually -512 bytes). -These figures are adjusted slightly, for devices whose sectorsize is not a -power of 2, e.g., audio CDs with a sector size of 2352 bytes. -.Pp -The options are as follows: -.Bl -tag -width indent -.It Fl r Ar rlist -Read the list of blocks and block sizes to read from the specified file. -.It Fl w Ar wlist -Write the list of remaining blocks to read to the specified file if -.Nm -is aborted via -.Dv SIGINT . -.El -.Pp -The -.Fl r -and -.Fl w -options can be specified together. -Especially, they can point to the same file, which will be updated on abort. -.Sh OUTPUT -The -.Nm -utility -prints several columns, detailing the progress -.Bl -tag -width remaining -.It Va start -Starting offset of the current block. -.It Va size -Read size of the current block. -.It Va len -Length of the current block. -.It Va state -Is increased for every failed read. -.It Va done -Number of bytes already read. -.It Va remaining -Number of bytes remaining. -.It Va "% done" -Percent complete. -.El -.Sh EXAMPLES -.Bd -literal -# recover data from failing hard drive ad3 -touch /data/lots_of_space -recoverdisk /dev/ad3 /data/lots_of_space - -# clone a hard disk -recoverdisk /dev/ad3 /dev/ad4 - -# read an ISO image from a CD-ROM -touch /data/cd.iso; recoverdisk /dev/acd0 /data/cd.iso - -# continue reading from a broken CD and update the existing worklist -recoverdisk -r worklist -w worklist /dev/acd0 /data/cd.iso - -# recover a single file from the unreadable media -touch file.avi; recoverdisk /cdrom/file.avi file.avi -.Ed -.Sh SEE ALSO -.Xr dd 1 -.Sh HISTORY -The -.Nm -utility first appeared in -.Fx 7.0 . -.Sh AUTHORS -.An -nosplit -The original implementation was done by -.An Poul-Henning Kamp Aq phk@FreeBSD.org -with minor improvements from -.An Ulrich Sp\(:orlein Aq uspoerlein@gmail.com . -.Pp -This manual page was written by -.An Ulrich Sp\(:orlein . -.Sh BUGS -Reading from media where the sectorsize is not a power of 2 will make all -1 MB reads fail. -This is due to the DMA reads being split up into blocks of at most 128kB. -These reads then fail if the sectorsize is not a divisor of 128kB. -When reading a full raw audio CD, this leads to roughly 700 error messages -flying by. -This is harmless. diff --git a/tools/tools/recoverdisk/recoverdisk.c b/tools/tools/recoverdisk/recoverdisk.c deleted file mode 100644 index 0dc5d7c..0000000 --- a/tools/tools/recoverdisk/recoverdisk.c +++ /dev/null @@ -1,294 +0,0 @@ -/*- - * ---------------------------------------------------------------------------- - * "THE BEER-WARE LICENSE" (Revision 42): - * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you - * can do whatever you want with this stuff. If we meet some day, and you think - * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp - * ---------------------------------------------------------------------------- - * - * $FreeBSD$ - */ -#include <sys/param.h> -#include <sys/queue.h> -#include <sys/disk.h> -#include <sys/stat.h> - -#include <err.h> -#include <errno.h> -#include <fcntl.h> -#include <signal.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> - -volatile sig_atomic_t aborting = 0; -static size_t bigsize = 1024 * 1024; -static size_t medsize = 64 * 1024; -static size_t minsize = 512; - -struct lump { - off_t start; - off_t len; - int state; - TAILQ_ENTRY(lump) list; -}; - -static TAILQ_HEAD(, lump) lumps = TAILQ_HEAD_INITIALIZER(lumps); - -static void -new_lump(off_t start, off_t len, int state) -{ - struct lump *lp; - - lp = malloc(sizeof *lp); - if (lp == NULL) - err(1, "Malloc failed"); - lp->start = start; - lp->len = len; - lp->state = state; - TAILQ_INSERT_TAIL(&lumps, lp, list); -} - -static struct lump *lp; -static char *wworklist = NULL; -static char *rworklist = NULL; - - -#define PRINT_HEADER \ - printf("%13s %7s %13s %5s %13s %13s %9s\n", \ - "start", "size", "block-len", "state", "done", "remaining", "% done") - -#define PRINT_STATUS(start, i, len, state, d, t) \ - printf("\r%13jd %7zu %13jd %5d %13jd %13jd %9.5f", \ - (intmax_t)start, \ - i, \ - (intmax_t)len, \ - state, \ - (intmax_t)d, \ - (intmax_t)(t - d), \ - 100*(double)d/(double)t) - -/* 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"); - } -} - -/* 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(1); -} - -static void -sighandler(__unused int sig) -{ - - aborting = 1; -} - -int -main(int argc, char * const argv[]) -{ - int ch; - int fdr, fdw; - off_t t, d, start, len; - size_t i, j; - int error, flags, state; - u_char *buf; - u_int sectorsize; - time_t t1, t2; - struct stat sb; - - while ((ch = getopt(argc, argv, "r:w:")) != -1) { - switch (ch) { - case 'r': - rworklist = strdup(optarg); - if (rworklist == NULL) - err(1, "Cannot allocate enough memory"); - break; - case 'w': - wworklist = strdup(optarg); - if (wworklist == NULL) - err(1, "Cannot allocate enough memory"); - break; - default: - usage(); - /* NOTREACHED */ - } - } - argc -= optind; - argv += optind; - - if (argc < 1 || argc > 2) - usage(); - - fdr = open(argv[0], O_RDONLY); - if (fdr < 0) - err(1, "Cannot open read descriptor %s", argv[0]); - - error = fstat(fdr, &sb); - if (error < 0) - err(1, "fstat failed"); - flags = O_WRONLY; - if (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode)) { - 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 { - t = sb.st_size; - flags |= O_CREAT | O_TRUNC; - } - - 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[1]); - } else - fdw = -1; - - if (rworklist != NULL) { - d = read_worklist(t); - } else { - new_lump(0, t, 0); - d = 0; - } - if (wworklist != NULL) - signal(SIGINT, sighandler); - - t1 = 0; - start = len = i = state = 0; - PRINT_HEADER; - for (;;) { - lp = TAILQ_FIRST(&lumps); - if (lp == NULL) - break; - while (lp->len > 0 && !aborting) { - /* These are only copied for printing stats */ - start = lp->start; - len = lp->len; - state = lp->state; - - i = MIN(lp->len, (off_t)bigsize); - if (lp->state == 1) - i = MIN(lp->len, (off_t)medsize); - if (lp->state > 1) - i = MIN(lp->len, (off_t)minsize); - time(&t2); - if (t1 != t2 || lp->len < (off_t)bigsize) { - PRINT_STATUS(start, i, len, state, d, t); - t1 = t2; - } - if (i == 0) { - errx(1, "BOGUS i %10jd", (intmax_t)i); - } - fflush(stdout); - j = pread(fdr, buf, i, lp->start); - if (j == i) { - d += i; - if (fdw >= 0) - j = pwrite(fdw, buf, i, lp->start); - else - j = i; - if (j != i) - printf("\nWrite error at %jd/%zu\n", - lp->start, i); - lp->start += i; - lp->len -= i; - continue; - } - printf("\n%jd %zu failed %d\n", lp->start, i, errno); - new_lump(lp->start, i, lp->state + 1); - lp->start += i; - lp->len -= i; - } - if (aborting) { - save_worklist(); - return (0); - } - TAILQ_REMOVE(&lumps, lp, list); - free(lp); - } - PRINT_STATUS(start, i, len, state, d, t); - printf("\nCompleted\n"); - return (0); -} |