summaryrefslogtreecommitdiffstats
path: root/sbin/recoverdisk
diff options
context:
space:
mode:
authoruqs <uqs@FreeBSD.org>2011-05-01 20:14:10 +0000
committeruqs <uqs@FreeBSD.org>2011-05-01 20:14:10 +0000
commit93c524683245cc63bc9afe6342fc8206676f72cb (patch)
tree5f24a19c21c570eda26f31a207928cca58ff9591 /sbin/recoverdisk
parent3ec54ea2452241be093edb0903cfd06fe39b6573 (diff)
downloadFreeBSD-src-93c524683245cc63bc9afe6342fc8206676f72cb.zip
FreeBSD-src-93c524683245cc63bc9afe6342fc8206676f72cb.tar.gz
recoverdisk(8): treat output file consistently and abort on EINVAL
This improves usability a little as we no longer require using touch. Also reword the manpage wrt. parameters and fix usage() [1] With no media in a cd(4) drive, the reads will loop producing EINVAL, abort in that case [2]. Document the shortcoming of sectorsize and MAXPHYS (a quick solution to this might be having MAXPHYS as the "bigsize", in short testing it didn't make a difference on throughput). Submitted by: arundel [1] PR: bin/154528 [2]
Diffstat (limited to 'sbin/recoverdisk')
-rw-r--r--sbin/recoverdisk/recoverdisk.149
-rw-r--r--sbin/recoverdisk/recoverdisk.c19
2 files changed, 42 insertions, 26 deletions
diff --git a/sbin/recoverdisk/recoverdisk.1 b/sbin/recoverdisk/recoverdisk.1
index 1759a7d..9eff8f7 100644
--- a/sbin/recoverdisk/recoverdisk.1
+++ b/sbin/recoverdisk/recoverdisk.1
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 6, 2006
+.Dd May 1, 2011
.Dt RECOVERDISK 1
.Os
.Sh NAME
@@ -33,17 +33,20 @@
.Sh SYNOPSIS
.Nm
.Op Fl b Ar bigsize
-.Op Fl r Ar rlist
-.Op Fl s Ar snapshot
-.Op Fl w Ar wlist
-.Ar special
-.Op Ar file
+.Op Fl r Ar readlist
+.Op Fl s Ar interval
+.Op Fl w Ar writelist
+.Ar source
+.Op Ar destination
.Sh DESCRIPTION
The
.Nm
utility reads data from the
-.Ar special
+.Ar source
file until all blocks could be successfully read.
+If
+.Ar destination
+was specified all data is being written to that file.
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.
@@ -59,13 +62,13 @@ The options are as follows:
The size of reads attempted first.
The middle pass is roughly the logarithmic average of the bigsize and
the sectorsize.
-.It Fl r Ar rlist
+.It Fl r Ar readlist
Read the list of blocks and block sizes to read from the specified file.
-.It Fl s Ar snapshot
-How often we should update the worklist file while things go OK.
-The default is 60 and the units is "progress messages" so if things
+.It Fl s Ar interval
+How often we should update the writelist file while things go OK.
+The default is 60 and the unit is "progress messages" so if things
go well, this is the same as once per minute.
-.It Fl w Ar wlist
+.It Fl w Ar writelist
Write the list of remaining blocks to read to the specified file if
.Nm
is aborted via
@@ -102,20 +105,19 @@ Percent complete.
.Sh EXAMPLES
.Bd -literal
# recover data from failing hard drive ad3
-touch /data/lots_of_space
-recoverdisk /dev/ad3 /data/lots_of_space
+recoverdisk /dev/ad3 /data/disk.img
# 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
+recoverdisk /dev/cd0 /data/cd.iso
# continue reading from a broken CD and update the existing worklist
-recoverdisk -r worklist -w worklist /dev/acd0 /data/cd.iso
+recoverdisk -r worklist -w worklist /dev/cd0 /data/cd.iso
# recover a single file from the unreadable media
-touch file.avi; recoverdisk /cdrom/file.avi file.avi
+recoverdisk /cdrom/file.avi file.avi
# If the disk hangs the system on read-errors try:
recoverdisk -b 0 /dev/ad3 /somewhere
@@ -133,7 +135,7 @@ utility first appeared in
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 .
+.An Ulrich Sp\(:orlein Aq uqs@FreeBSD.org .
.Pp
This manual page was written by
.An Ulrich Sp\(:orlein .
@@ -144,4 +146,13 @@ 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.
+This is harmless and can be avoided by setting
+.Fl b
+to no more than 128kB.
+.\".Pp
+.\"When reading from optical media, a bug in the GEOM framework will
+.\"prevent it from seeing that the media has been removed.
+.\"The device can still be opened, but all reads will fail.
+.\"This is usually harmless, but will send
+.\".Nm
+.\"into an infinite loop.
diff --git a/sbin/recoverdisk/recoverdisk.c b/sbin/recoverdisk/recoverdisk.c
index f4a6b5d..3930ef1 100644
--- a/sbin/recoverdisk/recoverdisk.c
+++ b/sbin/recoverdisk/recoverdisk.c
@@ -86,7 +86,7 @@ save_worklist(void)
if (file == NULL)
err(1, "Error opening file %s", wworklist);
- TAILQ_FOREACH(llp, &lumps, list)
+ TAILQ_FOREACH(llp, &lumps, list)
fprintf(file, "%jd %jd %d\n",
(intmax_t)llp->start, (intmax_t)llp->len,
llp->state);
@@ -134,8 +134,8 @@ read_worklist(off_t t)
static void
usage(void)
{
- (void)fprintf(stderr,
- "usage: recoverdisk [-r worklist] [-w worklist] source-drive [destination]\n");
+ (void)fprintf(stderr, "usage: recoverdisk [-b bigsize] [-r readlist] "
+ "[-s interval] [-w writelist] source [destination]\n");
exit(1);
}
@@ -153,7 +153,7 @@ main(int argc, char * const argv[])
int fdr, fdw;
off_t t, d, start, len;
size_t i, j;
- int error, flags, state;
+ int error, state;
u_char *buf;
u_int sectorsize;
time_t t1, t2;
@@ -196,7 +196,6 @@ main(int argc, char * const argv[])
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, &sectorsize);
if (error < 0)
@@ -210,7 +209,6 @@ main(int argc, char * const argv[])
err(1, "DIOCGMEDIASIZE failed");
} else {
t = sb.st_size;
- flags |= O_CREAT | O_TRUNC;
}
if (bigsize < minsize)
@@ -229,9 +227,12 @@ main(int argc, char * const argv[])
err(1, "Cannot allocate %zu bytes buffer", bigsize);
if (argc > 1) {
- fdw = open(argv[1], flags, DEFFILEMODE);
+ fdw = open(argv[1], O_WRONLY | O_CREAT, DEFFILEMODE);
if (fdw < 0)
err(1, "Cannot open write descriptor %s", argv[1]);
+ if (ftruncate(fdw, t) < 0)
+ err(1, "Cannot truncate output %s to %jd bytes",
+ argv[1], (intmax_t)t);
} else
fdw = -1;
@@ -292,6 +293,10 @@ main(int argc, char * const argv[])
}
printf("\n%jd %zu failed (%s)\n",
lp->start, i, strerror(errno));
+ if (errno == EINVAL) {
+ printf("read() size too big? Try with -b 131072");
+ aborting = 1;
+ }
if (errno == ENXIO)
aborting = 1;
new_lump(lp->start, i, lp->state + 1);
OpenPOWER on IntegriCloud