}
}
+static void open_file_on_demand(const char *file, FILE **fp_inout,
+ const char *what)
+{
+ FILE *fp;
+
+ if (!*fp_inout) {
+ fp = fopen(file, "w");
+ if (!fp)
+ bail_syserr(errno, "failed to open %s file `%s'", what, file);
+ fprintf(fp, "## %s\n\n", what);
+ *fp_inout = fp;
+ }
+}
+
+static void check_write(FILE *fp, const char *what)
+{
+ fflush(fp);
+ if (ferror(fp)) bail_syserr(errno, "error writing %s file", what);
+}
+
+static void carefully_fclose(FILE *fp, const char *what)
+{
+ if (fp && (ferror(fp) || fclose(fp)))
+ bail_syserr(errno, "error writing %s file", what);
+}
+
#define DEFVEC(vtype, etype) \
typedef struct { etype *v; size_t n, sz; } vtype
#define VEC_INIT { 0, 0, 0 }
("copied %.1f%% (%"PRIuSEC" of %"PRIuSEC"; %.1f %sB/s, ETA %s)",
percent, pos, limit, rate, unit, etastr);
if (file && id_kind(file->id) == VOB) {
- append_progress(" -- %s %d %3.1f%%",
+ append_progress(" -- %s %d %.1f%%",
id_part(file->id) ? "title" : "menu",
id_title(file->id),
(pos - file->start)*100.0/
static int dvdfd = -1, outfd = -1;
static dvd_file_t *vob;
static const char *mapfile; static FILE *mapfp;
+static const char *errfile; static FILE *errfp;
struct badblock { secaddr start, end; };
DEFVEC(badblock_v, struct badblock);
}
if (n > 0) { done += n; pos += n; p += n*SECTORSZ; want -= n; }
- else if (!n || errno != EINTR) break;
+ else if (!n) break;
+ else if (errno == EIO && errfile) {
+ open_file_on_demand(errfile, &errfp, "bad-sector error log");
+ fprintf(errfp, "%"PRIuSEC" %"PRIuSEC"\n", pos, pos + 1);
+ check_write(errfp, "bad-sector error log");
+ break;
+ } else if (errno != EINTR) break;
}
if (fakeerr && !errno) errno = fakeerr;
return (!done && errno ? -1 : done);
moan("skipping %"PRIuSEC" bad sectors (%"PRIuSEC" .. %"PRIuSEC")",
bad_hi - bad_lo, bad_lo, bad_hi);
if (mapfile) {
- if (!mapfp) {
- mapfp = fopen(mapfile, "w");
- if (!mapfp)
- bail_syserr(errno, "failed to open bad-sector map file `%s'",
- optarg);
- fprintf(mapfp, "## bad sector map\n\n");
- }
- fprintf(mapfp, "%"PRIuSEC" %"PRIuSEC"\n", bad_lo, bad_hi);
- fflush(mapfp);
- if (ferror(mapfp))
- bail_syserr(errno, "error writing bad-sector map file");
+ open_file_on_demand(mapfile, &mapfp, "bad-sector region map");
+ fprintf(mapfp, "%"PRIuSEC" %"PRIuSEC"", bad_lo, bad_hi);
+ if (file)
+ fprintf(mapfp, " # %s #%d %"PRIuSEC"..%"PRIuSEC" of %"PRIuSEC" (%.1f%%)",
+ id_part(file->id) ? "title" : "menu",
+ id_title(file->id),
+ bad_lo - file->start, bad_hi - file->start,
+ file->end - file->start,
+ (bad_lo - file->start)*100.0/(file->end - file->start));
+ fputc('\n', mapfp);
+ check_write(mapfp, "bad-sector region map");
}
if (lseek(outfd, (off_t)(bad_hi - bad_lo)*SECTORSZ, SEEK_CUR) < 0)
bail_syserr(errno, "failed to seek past bad sectors");
- status = 1;
}
struct recoverybuf {
r->pos + pp, pp, nn);
fflush(stdout);
#endif
- n = recovery_read_sectors(r, pos + pp, pp, nn);
+ n = recovery_read_sectors(r, r->pos + pp, pp, nn);
#ifdef DEBUG
printf(" -> %zd\n", n);
#endif
n = r->pos + r->end - pos;
if (!n && want) n = -1;
+ else if (n > want) n = want;
end:
#ifdef DEBUG
bad_lo = pos; bad_hi = pos + 1;
for (;;) {
report_bad_blocks_progress(bad_lo, bad_hi, errno);
+#ifdef DEBUG
+ debug_clear_progress();
+ printf(";; bounding bad-block region: "
+ "%"PRIuSEC" ..%"PRIuSEC".. %"PRIuSEC"\n",
+ bad_lo, bad_hi - bad_lo, bad_hi);
+#endif
if (bad_hi >= end) {
clear_progress();
moan("giving up on this extent");
want = run_length_wanted(pos, step, sz, end);
n = recovery_read(&r, pos, want);
#ifdef DEBUG
- debug_clear_progress();
printf(";; [bound] try reading %"PRIuSEC" .. %"PRIuSEC" -> %zd\n",
pos, pos + want, n);
#endif
good = pos;
while (good > bad_hi) {
report_bad_blocks_progress(bad_lo, bad_hi, errno);
+#ifdef DEBUG
+ debug_clear_progress();
+ printf(";; limiting bad-block region: "
+ "%"PRIuSEC" ..%"PRIuSEC".. %"PRIuSEC" ..%"PRIuSEC".. %"PRIuSEC"\n",
+ bad_lo, bad_hi - bad_lo, bad_hi, good - bad_hi, good);
+#endif
pos = bad_hi + (good - bad_hi)/2;
step = pos - bad_lo;
want = run_length_wanted(pos, step, sz, end);
n = recovery_read(&r, pos, want);
#ifdef DEBUG
- debug_clear_progress();
printf(";; [limit] try reading %"PRIuSEC" .. %"PRIuSEC" -> %zd\n",
pos, pos + want, n);
#endif
{ rc = -1; goto end; }
if (!(f&PRF_HYPHEN)) while (ISSPACE(*p)) p++;
- if (*p) { rc = -1; goto end; }
+ if (*p && ((f&PRF_HYPHEN) || *p != '#')) { rc = -1; goto end; }
rc = 0;
end:
p = strrchr(argv[0], '/'); prog = p ? p + 1 : argv[0];
for (;;) {
- opt = getopt(argc, argv, "hFR:X:b:cr:"); if (opt < 0) break;
+ opt = getopt(argc, argv, "hE:FR:X:b:cr:"); if (opt < 0) break;
switch (opt) {
case 'h': usage(stderr); exit(0);
+ case 'E': errfile = optarg; break;
case 'F': f |= f_fixup; break;
case 'R':
fp = fopen(optarg, "r");
if (dvd) DVDClose(dvd);
if (dvdfd >= 0) close(dvdfd);
if (outfd >= 0) close(outfd);
- if (mapfp) {
- if (ferror(mapfp) || fclose(mapfp))
- bail_syserr(errno, "error writing bad-sector map file");
- }
+ carefully_fclose(mapfp, "bad-sector region map");
+ carefully_fclose(errfp, "bad-sector error log");
#undef f_bogus
#undef f_continue