}
}
+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 }
}
static void clear_progress(void)
{ clear_progress_internal(); fflush(stdout); }
+#ifdef DEBUG
+static void debug_clear_progress(void)
+ { if (progresslen) { putchar('\n'); progresslen = 0; } }
+#endif
static void vappend_progress(const char *fmt, va_list ap)
{ progresslen += vprintf(fmt, ap); }
__attribute__((format(printf, 1, 2)))
("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/
struct badblock *bad, *best;
unsigned char *p = buf;
- best = 0; lo = 0; hi = badblocks.n;
+ if (badblocks.n) {
+ best = 0; lo = 0; hi = badblocks.n;
#ifdef DEBUG
- clear_progress();
- printf(";; searching badblocks for %"PRIuSEC" .. %"PRIuSEC"\n",
- pos, pos + want);
+ debug_clear_progress();
+ printf(";; searching badblocks for %"PRIuSEC" .. %"PRIuSEC"\n",
+ pos, pos + want);
#endif
- while (lo < hi) {
- mid = lo + (hi - lo)/2; bad = &badblocks.v[mid];
+ while (lo < hi) {
+ mid = lo + (hi - lo)/2; bad = &badblocks.v[mid];
#ifdef DEBUG
- printf(";; try %zu (%"PRIuSEC" .. %"PRIuSEC")... ",
- mid, bad->start, bad->end);
+ printf(";; try %zu (%"PRIuSEC" .. %"PRIuSEC")... ",
+ mid, bad->start, bad->end);
#endif
- if (pos < bad->start) { D( printf("high\n"); ) best = bad; hi = mid; }
- else if (pos >= bad->end) { D( printf("low\n"); ) lo = mid + 1; }
- else { D( printf("match!\n"); ) errno = EIO; return (-1); }
- }
+ if (pos < bad->start) { D( printf("high\n"); ) best = bad; hi = mid; }
+ else if (pos >= bad->end) { D( printf("low\n"); ) lo = mid + 1; }
+ else { D( printf("match!\n"); ) errno = EIO; return (-1); }
+ }
#ifdef DEBUG
- if (best)
- printf(";; next is %"PRIuSEC" .. %"PRIuSEC"\n",
- best->start, best->end);
+ if (best)
+ printf(";; next is %"PRIuSEC" .. %"PRIuSEC"\n",
+ best->start, best->end);
#endif
- if (best && pos + want > best->start)
- { want = best->start - pos; fakeerr = EIO; }
-
+ if (best && pos + want > best->start)
+ { want = best->start - pos; fakeerr = EIO; }
+ }
done = 0;
while (want) {
if (vob)
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");
- }
+ open_file_on_demand(mapfile, &mapfp, "bad-sector region map");
fprintf(mapfp, "%"PRIuSEC" %"PRIuSEC"\n", bad_lo, bad_hi);
- fflush(mapfp);
- if (ferror(mapfp))
- bail_syserr(errno, "error writing bad-sector map file");
+ 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");
va_list ap;
va_start(ap, what);
- clear_progress();
+ debug_clear_progress();
printf(";; recovery buffer (");
vprintf(what, ap);
printf("): "
{
ssize_t n;
- assert(off + want <= r->sz);
+ assert(off <= r->sz); assert(want <= r->sz - off);
n = read_sectors(pos, r->buf + off*SECTORSZ, want);
return (n);
}
ssize_t n;
#ifdef DEBUG
- clear_progress();
+ debug_clear_progress();
show_recovery_buffer_map(r, "begin(%"PRIuSEC", %"PRIuSEC")", pos, want);
#endif
#ifdef DEBUG
printf(";; read high (%"PRIuSEC"@%"PRIuSEC", %"PRIuSEC")",
r->pos + pp, pp, nn);
-fflush(stdout);
+ fflush(stdout);
#endif
- n = recovery_read_sectors(r, pos, pp, nn);
+ n = recovery_read_sectors(r, r->pos + pp, pp, nn);
#ifdef DEBUG
printf(" -> %zd\n", n);
#endif
for (i = 0; i < 4; i++) {
n = recovery_read(&r, pos, want);
#ifdef DEBUG
- clear_progress();
+ debug_clear_progress();
printf(";; [retry] try reading %"PRIuSEC" .. %"PRIuSEC" -> %zd\n",
pos, pos + want, n);
#endif
want = run_length_wanted(pos, step, sz, end);
n = recovery_read(&r, pos, want);
#ifdef DEBUG
- clear_progress();
+ debug_clear_progress();
printf(";; [bound] try reading %"PRIuSEC" .. %"PRIuSEC" -> %zd\n",
pos, pos + want, n);
#endif
want = run_length_wanted(pos, step, sz, end);
n = recovery_read(&r, pos, want);
#ifdef DEBUG
- clear_progress();
+ debug_clear_progress();
printf(";; [limit] try reading %"PRIuSEC" .. %"PRIuSEC" -> %zd\n",
pos, pos + want, n);
#endif
else bad_hi = pos + n + 1;
}
recovered(bad_lo, bad_hi); *pos_inout = good;
- if (r.pos + r.start <= good && good <= r.pos + r.end) {
- rearrange_sectors(&r, 0, good - r.pos, r.pos + r.end - good);
- } else
+ if (good < r.pos + r.start || r.pos + r.end <= good)
n = 0;
+ else {
+ n = r.pos + r.end - good;
+ rearrange_sectors(&r, 0, good - r.pos, n);
+ }
+#ifdef DEBUG
+ show_recovery_buffer_map(&r, "returning %zd good sectors at %"PRIuSEC"",
+ n, good);
+#endif
return (n);
}
if (f&f_write) emit(pos, ev->pos);
pos = ev->pos;
#ifdef DEBUG
- clear_progress();
+ debug_clear_progress();
printf(";;\n");
#endif
}
set_live(ev->file);
#ifdef DEBUG
store_filename(fn, filetab.v[ev->file].id);
- clear_progress();
+ debug_clear_progress();
printf(";; %8"PRIuSEC": begin `%s'\n", pos, fn);
#endif
break;
"(sector %"PRIuSEC") in output file `%s'",
ev->pos, outfile);
#ifdef DEBUG
- clear_progress();
+ debug_clear_progress();
printf(";; %8"PRIuSEC": begin write\n", pos);
#endif
f |= f_write;
case EV_STOP:
f &= ~f_write;
#ifdef DEBUG
- clear_progress();
+ debug_clear_progress();
printf(";; %8"PRIuSEC": end write\n", pos);
#endif
break;
clear_live(ev->file);
#ifdef DEBUG
store_filename(fn, filetab.v[ev->file].id);
- clear_progress();
+ debug_clear_progress();
printf(";; %8"PRIuSEC": end `%s'\n", pos, fn);
#endif
break;
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");
#undef f_bogus
#undef f_continue