Some improvements to recoverdisk

This commit is contained in:
Poul-Henning Kamp 2009-03-11 10:37:02 +00:00
parent 05dc172526
commit 584f5546ee
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=189691
2 changed files with 48 additions and 19 deletions

View File

@ -32,7 +32,9 @@
.Nd recover data from hard disk or optical media
.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
@ -46,15 +48,24 @@ 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).
By default it uses block sizes of roughly 1 MB, 32kB, 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
.Pp
The options are as follows:
.Bl -tag -width indent
.It Fl b Ar bigsize
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
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
go well, this is the same as once per minute.
.It Fl w Ar wlist
Write the list of remaining blocks to read to the specified file if
.Nm
@ -106,6 +117,10 @@ 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
# If the disk hangs the system on read-errors try:
recoverdisk -b 0 /dev/ad3 /somewhere
.Ed
.Sh SEE ALSO
.Xr dd 1

View File

@ -26,7 +26,7 @@
volatile sig_atomic_t aborting = 0;
static size_t bigsize = 1024 * 1024;
static size_t medsize = 64 * 1024;
static size_t medsize;
static size_t minsize = 512;
struct lump {
@ -76,6 +76,7 @@ static void
save_worklist(void)
{
FILE *file;
struct lump *llp;
if (wworklist != NULL) {
(void)fprintf(stderr, "\nSaving worklist ...");
@ -85,14 +86,11 @@ save_worklist(void)
if (file == NULL)
err(1, "Error opening file %s", wworklist);
for (;;) {
lp = TAILQ_FIRST(&lumps);
if (lp == NULL)
break;
TAILQ_FOREACH(llp, &lumps, list)
fprintf(file, "%jd %jd %d\n",
(intmax_t)lp->start, (intmax_t)lp->len, lp->state);
TAILQ_REMOVE(&lumps, lp, list);
}
(intmax_t)llp->start, (intmax_t)llp->len,
llp->state);
fclose(file);
(void)fprintf(stderr, " done.\n");
}
}
@ -160,14 +158,21 @@ main(int argc, char * const argv[])
u_int sectorsize;
time_t t1, t2;
struct stat sb;
u_int n, snapshot = 60;
while ((ch = getopt(argc, argv, "r:w:")) != -1) {
while ((ch = getopt(argc, argv, "b:r:w:s:")) != -1) {
switch (ch) {
case 'b':
bigsize = strtoul(optarg, NULL, 0);
break;
case 'r':
rworklist = strdup(optarg);
if (rworklist == NULL)
err(1, "Cannot allocate enough memory");
break;
case 's':
snapshot = strtoul(optarg, NULL, 0);
break;
case 'w':
wworklist = strdup(optarg);
if (wworklist == NULL)
@ -197,15 +202,8 @@ main(int argc, char * const argv[])
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;
bigsize = (bigsize / sectorsize) * sectorsize;
error = ioctl(fdr, DIOCGMEDIASIZE, &t);
if (error < 0)
@ -215,6 +213,17 @@ main(int argc, char * const argv[])
flags |= O_CREAT | O_TRUNC;
}
if (bigsize < minsize)
bigsize = minsize;
for (ch = 0; (bigsize >> ch) > minsize; ch++)
continue;
medsize = bigsize >> (ch / 2);
medsize = (medsize / minsize) * minsize;
fprintf(stderr, "Bigsize = %u, medsize = %u, minsize = %u\n",
bigsize, medsize, minsize);
buf = malloc(bigsize);
if (buf == NULL)
err(1, "Cannot allocate %jd bytes buffer", (intmax_t)bigsize);
@ -238,6 +247,7 @@ main(int argc, char * const argv[])
t1 = 0;
start = len = i = state = 0;
PRINT_HEADER;
n = 0;
for (;;) {
lp = TAILQ_FIRST(&lumps);
if (lp == NULL)
@ -257,6 +267,10 @@ main(int argc, char * const argv[])
if (t1 != t2 || lp->len < (off_t)bigsize) {
PRINT_STATUS(start, i, len, state, d, t);
t1 = t2;
if (++n == snapshot) {
save_worklist();
n = 0;
}
}
if (i == 0) {
errx(1, "BOGUS i %10jd", (intmax_t)i);