summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sbin/recoverdisk/recoverdisk.c40
-rw-r--r--tools/tools/recoverdisk/README7
-rw-r--r--tools/tools/recoverdisk/recoverdisk.c40
3 files changed, 61 insertions, 26 deletions
diff --git a/sbin/recoverdisk/recoverdisk.c b/sbin/recoverdisk/recoverdisk.c
index 89c2f49..d30055a 100644
--- a/sbin/recoverdisk/recoverdisk.c
+++ b/sbin/recoverdisk/recoverdisk.c
@@ -18,9 +18,11 @@
#include <unistd.h>
#include <sys/queue.h>
#include <sys/disk.h>
+#include <sys/stat.h>
#define BIGSIZE (1024 * 1024)
#define MEDIUMSIZE (64 * 1024)
+#define MINSIZE (512)
struct lump {
off_t start;
@@ -53,10 +55,11 @@ main(int argc, const char **argv)
struct lump *lp;
off_t t, d;
size_t i, j;
- int error;
+ int error, flags;
u_char *buf;
- u_int sectorsize;
+ u_int sectorsize, minsize;
time_t t1, t2;
+ struct stat sb;
if (argc < 2)
@@ -68,22 +71,35 @@ main(int argc, const char **argv)
fdr = open(argv[1], O_RDONLY);
if (fdr < 0)
err(1, "Cannot open read descriptor %s", argv[1]);
+
+ 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)
+ err(1, "DIOCGSECTORSIZE failed");
+ minsize = sectorsize;
+
+ 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], O_WRONLY);
+ fdw = open(argv[2], flags, DEFFILEMODE);
if (fdw < 0)
err(1, "Cannot open write descriptor %s", argv[2]);
} else {
fdw = -1;
}
- error = ioctl(fdr, DIOCGSECTORSIZE, &sectorsize);
- if (error < 0)
- err(1, "DIOCGSECTORSIZE failed");
-
- error = ioctl(fdr, DIOCGMEDIASIZE, &t);
- if (error < 0)
- err(1, "DIOCGMEDIASIZE failed");
-
new_lump(0, t, 0);
d = 0;
@@ -100,7 +116,7 @@ main(int argc, const char **argv)
if (lp->state == 1)
i = MEDIUMSIZE;
if (lp->state > 1)
- i = sectorsize;
+ i = minsize;
time(&t2);
if (t1 != t2 || lp->len < BIGSIZE) {
printf("\r%13jd %7zu %13jd %3d %13jd %13jd %.8f",
diff --git a/tools/tools/recoverdisk/README b/tools/tools/recoverdisk/README
index 8766f41..4f7624a 100644
--- a/tools/tools/recoverdisk/README
+++ b/tools/tools/recoverdisk/README
@@ -1,7 +1,7 @@
$FreeBSD$
-This is a small tool which will read an entire disk(partition) using
-1M blocks and optionally write the read data to a file or disk.
+This is a small tool which will read an entire disk(partition) or file
+using 1M blocks and optionally write the read data to a file or disk.
If a read error happens, the 1M block gets put on the end of the worklist
and will be retried with 64k blocksize.
@@ -20,3 +20,6 @@ or salvage a floppy:
touch myfloppy.flp
recoverdisk /dev/fd0 myfloppy.flp
+or recover a single file from the unreadable media:
+
+ recoverdisk /cdrom/file.avi file.avi
diff --git a/tools/tools/recoverdisk/recoverdisk.c b/tools/tools/recoverdisk/recoverdisk.c
index 89c2f49..d30055a 100644
--- a/tools/tools/recoverdisk/recoverdisk.c
+++ b/tools/tools/recoverdisk/recoverdisk.c
@@ -18,9 +18,11 @@
#include <unistd.h>
#include <sys/queue.h>
#include <sys/disk.h>
+#include <sys/stat.h>
#define BIGSIZE (1024 * 1024)
#define MEDIUMSIZE (64 * 1024)
+#define MINSIZE (512)
struct lump {
off_t start;
@@ -53,10 +55,11 @@ main(int argc, const char **argv)
struct lump *lp;
off_t t, d;
size_t i, j;
- int error;
+ int error, flags;
u_char *buf;
- u_int sectorsize;
+ u_int sectorsize, minsize;
time_t t1, t2;
+ struct stat sb;
if (argc < 2)
@@ -68,22 +71,35 @@ main(int argc, const char **argv)
fdr = open(argv[1], O_RDONLY);
if (fdr < 0)
err(1, "Cannot open read descriptor %s", argv[1]);
+
+ 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)
+ err(1, "DIOCGSECTORSIZE failed");
+ minsize = sectorsize;
+
+ 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], O_WRONLY);
+ fdw = open(argv[2], flags, DEFFILEMODE);
if (fdw < 0)
err(1, "Cannot open write descriptor %s", argv[2]);
} else {
fdw = -1;
}
- error = ioctl(fdr, DIOCGSECTORSIZE, &sectorsize);
- if (error < 0)
- err(1, "DIOCGSECTORSIZE failed");
-
- error = ioctl(fdr, DIOCGMEDIASIZE, &t);
- if (error < 0)
- err(1, "DIOCGMEDIASIZE failed");
-
new_lump(0, t, 0);
d = 0;
@@ -100,7 +116,7 @@ main(int argc, const char **argv)
if (lp->state == 1)
i = MEDIUMSIZE;
if (lp->state > 1)
- i = sectorsize;
+ i = minsize;
time(&t2);
if (t1 != t2 || lp->len < BIGSIZE) {
printf("\r%13jd %7zu %13jd %3d %13jd %13jd %.8f",
OpenPOWER on IntegriCloud