Re: Improvements to src/tools/tools/recoverdisk
- From: Maxim Sobolev <sobomax@xxxxxxxxxxx>
- Date: Tue, 25 Apr 2006 12:48:43 -0700
Sounds cool, perhaps it's time to move recoverdisk into the base system to give it better exposure?
-Maxim
Ulrich Spoerlein wrote:
Dear Poul-Henning, current@,
I made two, what I call, improvements to recoverdisk. It only tries to
read in multiples of 512 bytes OR the sectorsize. This sucks for CD/DVD
with 2352 bytes sectorsize. My patch takes the native sectorsize into
account, when dimensioning BIG and MEDIUMSIZE.
Second feature is the saving and loading of the worklist. Again, not
very helpful for reading hard disks, but very useful for CDs. This way,
you can first try a scratched CD in drive A, then drive B and drive C.
You don't have to start all over again, but instead can profit from the
different error recovery mechanisms.
Previously, I did this with dd(1) and paper and pencil. Not funny.
Please try the attached patch, thanks!
Ulrich Spoerlein
------------------------------------------------------------------------
--- recoverdisk.orig.c Mon Apr 24 19:34:57 2006
+++ recoverdisk.c Tue Apr 25 14:11:44 2006
@@ -14,15 +14,20 @@
#include <err.h>
#include <errno.h>
#include <fcntl.h>
+#include <signal.h>
+#include <string.h>
+#include <sysexits.h>
#include <time.h>
#include <unistd.h>
#include <sys/queue.h>
#include <sys/disk.h>
#include <sys/stat.h>
-#define BIGSIZE (1046640)
-#define MEDIUMSIZE (63504)
-#define MINSIZE (512)
+#define MIN(a,b) (((a)<(b))?(a):(b))
+
+static off_t bigsize = 1024 * 1024;
+static off_t medsize = 64 * 1024;
+static off_t minsize = 512;
struct lump {
off_t start;
@@ -48,29 +53,119 @@
TAILQ_INSERT_TAIL(&lumps, lp, list);
}
+static struct lump *lp;
+static char *wworklist = NULL;
+static char *rworklist = NULL;
+
+/* Save the worklist, if -w was given */
+static void
+save_worklist(__unused int sig)
+{
+ FILE *file;
+
+ if (wworklist != NULL) {
+ 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);
+ }
+ fprintf(stderr, " done.\n");
+ }
+ exit(0);
+}
+
+static off_t
+read_worklist(off_t t)
+{
+ off_t s, l, d;
+ int state, lines;
+ FILE *file;
+
+ 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;
+ }
+ fprintf(stderr, " done.\n");
+
+ /* + * Return the number of bytes already read (at least not in
+ * worklist).
+ */
+ return (d);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "Usage: %s [-r worklist] [-w worklist] source-drive [destination]", "recoverdisk");
+ exit(EX_USAGE);
+}
+
int
-main(int argc, const char **argv)
+main(int argc, char * const argv[])
{
+ int ch;
int fdr, fdw;
- struct lump *lp;
off_t t, d;
size_t i, j;
int error, flags;
u_char *buf;
- u_int sectorsize, minsize;
+ u_int sectorsize;
time_t t1, t2;
struct stat sb;
+ while ((ch = getopt(argc, argv, "r:w:")) != -1) {
+ switch (ch) {
+ case 'w':
+ wworklist = strdup(optarg);
+ if (wworklist == NULL)
+ err(1, "Cannot allocate enough memory");
+ break;
+ case 'r':
+ rworklist = strdup(optarg);
+ if (rworklist == NULL)
+ err(1, "Cannot allocate enough memory");
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
- if (argc < 2)
- errx(1, "Usage: %s source-drive [destination]", argv[0]);
+ if (argc < 1)
+ usage();
- buf = malloc(BIGSIZE);
- if (buf == NULL)
- err(1, "Cannot allocate %d bytes buffer", BIGSIZE);
- fdr = open(argv[1], O_RDONLY);
+ fdr = open(argv[0], O_RDONLY);
if (fdr < 0)
- err(1, "Cannot open read descriptor %s", argv[1]);
+ err(1, "Cannot open read descriptor %s", argv[0]);
error = fstat(fdr, &sb);
if (error < 0)
@@ -80,46 +175,62 @@
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 {
- sectorsize = 1;
t = sb.st_size;
- minsize = MINSIZE;
flags |= O_CREAT | O_TRUNC;
}
- if (argc > 2) {
- fdw = open(argv[2], flags, DEFFILEMODE);
+ 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[2]);
+ err(1, "Cannot open write descriptor %s", argv[1]);
} else {
fdw = -1;
}
- new_lump(0, t, 0);
- d = 0;
+ if (rworklist != NULL) {
+ d = read_worklist(t);
+ } else {
+ new_lump(0, t, 0);
+ d = 0;
+ }
+
+ signal(SIGINT, save_worklist);
t1 = 0;
+ printf("%13s %7s %13s %5s %13s %13s %9s\n",
+ "start", "size", "len", "state", "done", "remaining", "% done");
for (;;) {
lp = TAILQ_FIRST(&lumps);
if (lp == NULL)
break;
- TAILQ_REMOVE(&lumps, lp, list);
while (lp->len > 0) {
- i = BIGSIZE;
- if (lp->len < BIGSIZE)
- i = lp->len;
+ i = MIN(lp->len, bigsize);
if (lp->state == 1)
- i = MEDIUMSIZE;
+ i = MIN(lp->len, medsize);
if (lp->state > 1)
- i = minsize;
+ i = MIN(lp->len, minsize);
time(&t2);
- if (t1 != t2 || lp->len < BIGSIZE) {
- printf("\r%13jd %7zu %13jd %3d %13jd %13jd %.8f",
+ if (t1 != t2 || lp->len < bigsize) {
+ printf("\r%13jd %7zu %13jd %5d %13jd %13jd %.7f",
(intmax_t)lp->start,
i, (intmax_t)lp->len,
@@ -152,9 +263,10 @@
lp->start += i;
lp->len -= i;
}
+ TAILQ_REMOVE(&lumps, lp, list);
free(lp);
}
printf("\nCompleted\n");
- exit (0);
+ return (0);
}
_______________________________________________
freebsd-current@xxxxxxxxxxx mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to "freebsd-current-unsubscribe@xxxxxxxxxxx"
- Follow-Ups:
- Re: Improvements to src/tools/tools/recoverdisk
- From: Poul-Henning Kamp
- Re: Improvements to src/tools/tools/recoverdisk
- References:
- Improvements to src/tools/tools/recoverdisk
- From: Ulrich Spoerlein
- Improvements to src/tools/tools/recoverdisk
- Prev by Date: Re: 6.1 RC1: won't boot install CD "BTX halted" on HP D530c with SATA drive
- Next by Date: Re: Improvements to src/tools/tools/recoverdisk
- Previous by thread: Improvements to src/tools/tools/recoverdisk
- Next by thread: Re: Improvements to src/tools/tools/recoverdisk
- Index(es):