X-Git-Url: https://git.distorted.org.uk/~mdw/dvdrip/blobdiff_plain/7f06fa5b1a9a0517c77a5c4f521aaa9d5e6aa786..eac2ed1a81c1c4af7b154ef40627eed7cab9a467:/dvd-sector-copy.c?ds=sidebyside diff --git a/dvd-sector-copy.c b/dvd-sector-copy.c index f757e49..cdd2849 100644 --- a/dvd-sector-copy.c +++ b/dvd-sector-copy.c @@ -3,7 +3,7 @@ static void usage(FILE *fp) { fprintf(fp, - "usage: %s [-c] [-B PARAM=VALUE,...] [-R MAP]\n" + "usage: %s [-ci] [-B PARAM=VALUE,...] [-R MAP]\n" "\t[-b OUTMAP] [-r [START]-[END]] DEVICE OUTFILE\n", prog); } @@ -15,49 +15,6 @@ static double tvdiff(const struct timeval *tv_lo, (tv_hi->tv_usec - tv_lo->tv_usec)/1.0e6); } -static void carefully_write(int fd, const void *buf, size_t sz) -{ - const unsigned char *p = buf; - ssize_t n; - - if (fd < 0) return; - while (sz) { - n = write(fd, p, sz); - if (n < 0) { - if (errno == EINTR) continue; - bail_syserr(errno, "failed to write to output file"); - } - if (!n) bail("unexpected short write to output file"); - p += n; sz -= n; - } -} - -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 } @@ -313,6 +270,8 @@ static void render_badblock_progress(struct progress_item *item, progress_shownotice(render, bg, 7); } +static double alpha = 0.1; + static void update_progress(secaddr pos) { struct timeval now; @@ -321,8 +280,7 @@ static void update_progress(secaddr pos) gettimeofday(&now, 0); t = tvdiff(&last_time, &now); -#define ALPHA 0.1 -#define BETA (1 - ALPHA) +#define BETA (1 - alpha) if (t) { g = wcount ? pow(BETA, t) : 0.0; f = (1 - g)/(1 - BETA); @@ -332,7 +290,6 @@ static void update_progress(secaddr pos) last_time = now; last_pos = pos; } -#undef ALPHA #undef BETA throbix++; if (!throbber[throbix]) throbix = 0; @@ -736,11 +693,11 @@ static ssize_t find_good_sector(secaddr *pos_inout, secaddr end, recovered(bad_lo, end); *pos_inout = end; return (0); } - step = step_factor*(bad_hi - bad_lo); + step = (step_factor - 1)*(bad_hi - bad_lo); if (step < step_min) step = step_min; if (step_max && step > step_max) step = step_max; - if (step > end - bad_lo) step = end - bad_lo; - pos = bad_lo + step - 1; + if (step > end - bad_hi) step = end - bad_hi; + pos = bad_hi + step - 1; want = run_length_wanted(pos, step, end); n = recovery_read(&r, pos, want); #ifdef DEBUG @@ -983,7 +940,7 @@ int main(int argc, char *argv[]) { unsigned f = 0; const char *p; - uint64_t volsz; + off_t volsz; secaddr pos; off_t off; secaddr start, end, last; @@ -998,8 +955,8 @@ int main(int argc, char *argv[]) struct timeval tv0, tv1; double t, rate, tot; const char *rateunit, *totunit; - char timebuf[TIMESTRMAX]; - struct stat st; + char timebuf[TIMESTRMAX], id_in[MAXIDSZ], id_out[MAXIDSZ]; + dvd_reader_t *dvd_out; #ifdef DEBUG const struct file *file; char fn[MAXFNSZ]; @@ -1009,11 +966,12 @@ int main(int argc, char *argv[]) #define f_continue 2u #define f_fixup 4u #define f_stats 8u +#define f_checkid 16u #define f_write 256u set_prog(argv[0]); for (;;) { - opt = getopt(argc, argv, "hB:E:FR:X:b:cr:s"); if (opt < 0) break; + opt = getopt(argc, argv, "hB:E:FR:X:b:cir:s"); if (opt < 0) break; switch (opt) { case 'h': usage(stderr); exit(0); case 'B': @@ -1035,6 +993,8 @@ int main(int argc, char *argv[]) step_max = parse_int(&p, 1, SECLIMIT - 1, "step maximum"); else if (SKIP_PREFIX("retry")) max_retries = parse_int(&p, 0, INT_MAX, "retries"); + else if (SKIP_PREFIX("alpha")) + alpha = parse_float(&p, 0, 1, "average decay factor"); else if (SKIP_PREFIX("_badwait")) bad_block_delay = parse_float(&p, 0, DBL_MAX, "bad-block delay"); else if (SKIP_PREFIX("_blkwait")) @@ -1131,25 +1091,24 @@ int main(int argc, char *argv[]) } open_dvd(device, &dvdfd, &dvd); - if (fstat(dvdfd, &st)) - bail_syserr(errno, "failed to stat device `%s'", device); - if (S_ISREG(st.st_mode)) { - blksz = SECTORSZ; - volsz = st.st_size; - } else if (S_ISBLK(st.st_mode)) { - if (ioctl(dvdfd, BLKSSZGET, &blksz)) - bail_syserr(errno, "failed to get block size for `%s'", device); - if (ioctl(dvdfd, BLKGETSIZE64, &volsz)) - bail_syserr(errno, "failed to get volume size for `%s'", device); - } else - bail("can't use `%s' as source: expected file or block device", device); + blksz = SECTORSZ; volsz = device_size(dvdfd, device, &blksz); if (blksz != SECTORSZ) bail("device `%s' block size %d /= %d", device, blksz, SECTORSZ); if (volsz%SECTORSZ) bail("device `%s' volume size %"PRIu64" not a multiple of %d", device, volsz, SECTORSZ); + if (f&f_checkid) { + open_dvd(outfile, 0, &dvd_out); + if (dvd_id(id_in, dvd, DIF_MUSTIFOHASH, device) || + dvd_id(id_out, dvd_out, DIF_MUSTIFOHASH, device)) + exit(2); + if (STRCMP(id_in, !=, id_out)) + bail("DVD id mismatch: input `%s' is `%s'; output `%s' is `%s'", + device, id_in, outfile, id_out); + } + outfd = open(outfile, O_WRONLY | O_CREAT, 0666); if (outfd < 0) bail_syserr(errno, "failed to create output file `%s'", outfile);