From 5cc1b8be9f072032c1b6f97a9ba658cc8d2183bf Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Wed, 16 Feb 2022 18:53:16 +0000 Subject: [PATCH] dvd-sector-copy.c: Eliminate `struct source'; just make the things global. --- dvd-sector-copy.c | 199 ++++++++++++++++++++++++++---------------------------- 1 file changed, 96 insertions(+), 103 deletions(-) diff --git a/dvd-sector-copy.c b/dvd-sector-copy.c index 6e2737a..6fec2de 100644 --- a/dvd-sector-copy.c +++ b/dvd-sector-copy.c @@ -292,22 +292,19 @@ static void print_progress(const char *fmt, ...) va_end(ap); } -struct source { - dvd_reader_t *dvd; - int dvdfd; - struct file *file; - dvd_file_t *vob; - - unsigned f; -#define SRCF_ALLPROGRESS 1u - secaddr last_pos, limit, nsectors, ndone; - struct timeval last_time; - double wsum, wcount; - const char *mapfile; FILE *mapfp; -}; -#define SOURCE_INIT { 0, -1, 0, 0, 0, 0, 0, 0, 0, { 0, 0 }, 0.0, 0.0, 0, 0 } - -static void report_progress(struct source *src, secaddr pos) +static dvd_reader_t *dvd; +static int dvdfd = -1; +static struct file *file; +static dvd_file_t *vob; + +unsigned flags; +# define F_ALLPROGRESS 1u +static secaddr last_pos, limit, nsectors, ndone; +static struct timeval last_time; +static double wsum, wcount; +static const char *mapfile; static FILE *mapfp; + +static void report_progress(secaddr pos) { char etastr[32]; struct timeval now; @@ -319,22 +316,22 @@ static void report_progress(struct source *src, secaddr pos) #define BETA (1 - ALPHA) gettimeofday(&now, 0); - t = (now.tv_sec - src->last_time.tv_sec) + - (now.tv_usec - src->last_time.tv_usec)/1000000.0; + t = (now.tv_sec - last_time.tv_sec) + + (now.tv_usec - last_time.tv_usec)/1000000.0; if (t) { - g = src->wcount ? pow(BETA, t) : 0.0; f = (1 - g)/(1 - BETA); - src->wsum = f*(pos - src->last_pos)/t + g*src->wsum; - src->wcount = f + g*src->wcount; - src->ndone += pos - src->last_pos; - src->last_time = now; src->last_pos = pos; + g = wcount ? pow(BETA, t) : 0.0; f = (1 - g)/(1 - BETA); + wsum = f*(pos - last_pos)/t + g*wsum; + wcount = f + g*wcount; + ndone += pos - last_pos; + last_time = now; last_pos = pos; } - if (!src->wsum || !src->wcount) + if (!wsum || !wcount) { rate = 0; strcpy(etastr, "???"); } else { - rate = src->wsum/src->wcount; - eta = (int)((src->nsectors - src->ndone)/rate); + rate = wsum/wcount; + eta = (int)((nsectors - ndone)/rate); sprintf(etastr, "%d:%02d:%02d", eta/3600, (eta/60)%60, eta%60); } @@ -343,27 +340,26 @@ static void report_progress(struct source *src, secaddr pos) if (rate > 128) { rate /= 1024; unit = "M"; } if (rate > 128) { rate /= 1024; unit = "G"; } - if (src->f&SRCF_ALLPROGRESS) percent = pos*100.0/src->limit; - else percent = src->ndone*100.0/src->nsectors; + if (flags&F_ALLPROGRESS) percent = pos*100.0/limit; + else percent = ndone*100.0/nsectors; print_progress ("copied %.1f%% (%"PRIuSEC" of %"PRIuSEC"; %.1f %sB/s, ETA %s)", - percent, pos, src->limit, rate, unit, etastr); - if (src->file && id_kind(src->file->id) == VOB) { + percent, pos, limit, rate, unit, etastr); + if (file && id_kind(file->id) == VOB) { append_progress(" -- %s %d %3.1f%%", - id_part(src->file->id) ? "title" : "menu", - id_title(src->file->id), - (pos - src->file->start)*100.0/ - (src->file->end - src->file->start)); + id_part(file->id) ? "title" : "menu", + id_title(file->id), + (pos - file->start)*100.0/ + (file->end - file->start)); } #undef ALPHA #undef BETA } -static void report_bad_blocks_progress(struct source *src, - secaddr lo, secaddr hi, int err) +static void report_bad_blocks_progress(secaddr lo, secaddr hi, int err) { - report_progress(src, hi); + report_progress(hi); if (lo == hi) append_progress(": retrying bad sector"); else @@ -373,18 +369,17 @@ static void report_bad_blocks_progress(struct source *src, fflush(stdout); } -static ssize_t read_sectors(struct source *src, secaddr pos, - void *buf, secaddr want) +static ssize_t read_sectors(secaddr pos, void *buf, secaddr want) { ssize_t n; again: - if (src->vob) - n = DVDReadBlocks(src->vob, pos - src->file->start, want, buf); - else if (src->file) { - if (lseek(src->dvdfd, (off_t)pos*SECTORSZ, SEEK_SET) < 0) + if (vob) + n = DVDReadBlocks(vob, pos - file->start, want, buf); + else if (file) { + if (lseek(dvdfd, (off_t)pos*SECTORSZ, SEEK_SET) < 0) bail_syserr(errno, "failed to seek to sector %"PRIuSEC"", pos); - n = read(src->dvdfd, buf, want*SECTORSZ); + n = read(dvdfd, buf, want*SECTORSZ); if (n >= 0) n /= SECTORSZ; } else { memset(buf, 0, want*SECTORSZ); @@ -412,7 +407,7 @@ static void carefully_write(int fd, const void *buf, size_t sz) } } -static void emit(struct source *src, int outfd, secaddr start, secaddr end) +static void emit(int outfd, secaddr start, secaddr end) { #define BUFSECTORS 512 @@ -446,23 +441,23 @@ static void emit(struct source *src, int outfd, secaddr start, secaddr end) #endif if (least == -1) - { src->file = 0; src->vob = 0; } + { file = 0; vob = 0; } else { - src->file = &filetab.v[least]; - switch (id_kind(src->file->id)) { + file = &filetab.v[least]; + switch (id_kind(file->id)) { case RAW: - src->vob = 0; + vob = 0; break; case VOB: if (first_time) { clear_progress(); first_time = 0; } - src->vob = DVDOpenFile(src->dvd, id_title(src->file->id), - id_part(src->file->id) - ? DVD_READ_TITLE_VOBS - : DVD_READ_MENU_VOBS); - if (!src->vob) + vob = DVDOpenFile(dvd, id_title(file->id), + id_part(file->id) + ? DVD_READ_TITLE_VOBS + : DVD_READ_MENU_VOBS); + if (!vob) bail("failed to open %s %u", - id_part(src->file->id) ? "title" : "menu", - id_title(src->file->id)); + id_part(file->id) ? "title" : "menu", + id_title(file->id)); break; default: abort(); @@ -472,12 +467,12 @@ static void emit(struct source *src, int outfd, secaddr start, secaddr end) pos = start; while (pos < end) { want = end - pos; if (want > BUFSECTORS) want = BUFSECTORS; - n = read_sectors(src, pos, buf, want); + n = read_sectors(pos, buf, want); if (n <= 0) { - report_bad_blocks_progress(src, pos, pos, errno); + report_bad_blocks_progress(pos, pos, errno); for (i = 0; i < 4; i++) { - n = read_sectors(src, pos, buf, 1); + n = read_sectors(pos, buf, 1); if (n > 0) { clear_progress(); moan("sector %"PRIuSEC" read ok after retry", pos); @@ -488,7 +483,7 @@ static void emit(struct source *src, int outfd, secaddr start, secaddr end) bad_lo = pos; step = 1; bad_hi = pos + 1; for (;;) { - report_bad_blocks_progress(src, bad_lo, bad_hi, errno); + report_bad_blocks_progress(bad_lo, bad_hi, errno); if (bad_hi >= end) { clear_progress(); moan("giving up on this extent"); @@ -497,16 +492,16 @@ static void emit(struct source *src, int outfd, secaddr start, secaddr end) step *= 2; if (step > end - bad_lo) step = end - bad_lo; pos = bad_lo + step - 1; - n = read_sectors(src, pos, buf, 1); + n = read_sectors(pos, buf, 1); if (n > 0) break; bad_hi = pos + 1; } good = pos; while (good > bad_hi) { - report_bad_blocks_progress(src, bad_lo, bad_hi, errno); + report_bad_blocks_progress(bad_lo, bad_hi, errno); pos = bad_hi + (good - bad_hi)/2; - n = read_sectors(src, pos, buf, 1); + n = read_sectors(pos, buf, 1); if (n > 0) good = pos; else bad_hi = pos + 1; } @@ -515,17 +510,17 @@ static void emit(struct source *src, int outfd, secaddr start, secaddr end) clear_progress(); moan("skipping %"PRIuSEC" bad sectors (%"PRIuSEC" .. %"PRIuSEC")", bad_hi - bad_lo, bad_lo, bad_hi); - if (src->mapfile) { - if (!src->mapfp) { - src->mapfp = fopen(src->mapfile, "w"); - if (!src->mapfp) + if (mapfile) { + if (!mapfp) { + mapfp = fopen(mapfile, "w"); + if (!mapfp) bail_syserr(errno, "failed to open bad-sector map file `%s'", optarg); - fprintf(src->mapfp, "## bad sector map\n\n"); + fprintf(mapfp, "## bad sector map\n\n"); } - fprintf(src->mapfp, "%"PRIuSEC" %"PRIuSEC"\n", bad_lo, bad_hi); - fflush(src->mapfp); - if (ferror(src->mapfp)) + fprintf(mapfp, "%"PRIuSEC" %"PRIuSEC"\n", bad_lo, bad_hi); + fflush(mapfp); + if (ferror(mapfp)) bail_syserr(errno, "error writing bad-sector map file"); } if (outfd >= 0 && @@ -537,10 +532,10 @@ static void emit(struct source *src, int outfd, secaddr start, secaddr end) } if (n > 0) { carefully_write(outfd, buf, n*SECTORSZ); pos += n; } - report_progress(src, pos); fflush(stdout); + report_progress(pos); fflush(stdout); } - if (src->vob) { DVDCloseFile(src->vob); src->vob = 0; } + if (vob) { DVDCloseFile(vob); vob = 0; } #undef BUFSECTORS } @@ -607,7 +602,6 @@ int main(int argc, char *argv[]) uint64_t volsz; secaddr pos; off_t off; - struct source src = SOURCE_INIT; unsigned long start, end; const struct event *ev; const char *device = "/dev/dvd", *outfile = 0; @@ -665,8 +659,8 @@ int main(int argc, char *argv[]) bad_range_file: bail("bad range `%s' at `%s' line %zu", buf.p, optarg, i); case 'b': - if (src.mapfile) bail("can't have multiple map files"); - src.mapfile = optarg; + if (mapfile) bail("can't have multiple map files"); + mapfile = optarg; break; case 'c': f |= f_continue; break; case 'o': outfile = optarg; break; @@ -704,18 +698,18 @@ int main(int argc, char *argv[]) if (optind < argc) f |= f_bogus; if (f&f_bogus) { usage(stderr); exit(2); } - src.dvdfd = open(device, O_RDONLY); - if (src.dvdfd < 0) + dvdfd = open(device, O_RDONLY); + if (dvdfd < 0) bail_syserr(errno, "failed to open device `%s'", device); - if (fstat(src.dvdfd, &st)) + 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(src.dvdfd, BLKSSZGET, &blksz)) + if (ioctl(dvdfd, BLKSSZGET, &blksz)) bail_syserr(errno, "failed to get block size for `%s'", device); - if (ioctl(src.dvdfd, BLKGETSIZE64, &volsz)) + 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); @@ -743,25 +737,25 @@ int main(int argc, char *argv[]) put_event(EV_WRITE, 0, 0); #ifdef notdef - src.dvd = DVDOpen2(0, &logger, device); + dvd = DVDOpen2(0, &logger, device); #else - src.dvd = DVDOpen(device); + dvd = DVDOpen(device); #endif - if (!src.dvd) bail("failed to open DVD on `%s'", device); + if (!dvd) bail("failed to open DVD on `%s'", device); /* It's fast enough just to check everything. */ - put_menu(src.dvd, 0); + put_menu(dvd, 0); for (i = 1; i < 100; i++) { - put_menu(src.dvd, i); - put_title(src.dvd, i); + put_menu(dvd, i); + put_title(dvd, i); } put_file(mkident(RAW, 0, 0), 0, volsz/SECTORSZ); assert(filetab.n <= MAXFILES); - for (i = 0, src.limit = 0; i < filetab.n; i++) - if (filetab.v[i].end > src.limit) src.limit = filetab.v[i].end; + for (i = 0, limit = 0; i < filetab.n; i++) + if (filetab.v[i].end > limit) limit = filetab.v[i].end; - if (end > src.limit) end = src.limit; + if (end > limit) end = limit; #ifdef DEBUG printf("\n;; files:\n"); @@ -795,9 +789,9 @@ int main(int argc, char *argv[]) ev = &eventq.v[i]; switch (ev->ev) { case EV_WRITE: start = ev->pos; f |= f_write; break; - case EV_STOP: src.nsectors += ev->pos - start; f &= ~f_write; break; + case EV_STOP: nsectors += ev->pos - start; f &= ~f_write; break; } - if (ev->pos >= src.limit) break; + if (ev->pos >= limit) break; if (f&f_fixup) start = ev->pos; } eventq.n = i; @@ -806,11 +800,10 @@ int main(int argc, char *argv[]) n++; f |= f_write; } if (f&f_write) { - src.nsectors += src.limit - start; - put_event(EV_STOP, 0, src.limit); + nsectors += limit - start; + put_event(EV_STOP, 0, limit); } - if (n == 1 && (f&f_write)) - src.f |= SRCF_ALLPROGRESS; + if (n == 1 && (f&f_write)) flags |= F_ALLPROGRESS; f &= ~f_write; #ifdef DEBUG @@ -819,7 +812,7 @@ int main(int argc, char *argv[]) for (pos = 0, i = 0; i < eventq.n; i++) { ev = &eventq.v[i]; if (ev->pos > pos) { - if (f&f_write) emit(&src, outfd, pos, ev->pos); + if (f&f_write) emit(outfd, pos, ev->pos); pos = ev->pos; #ifdef DEBUG clear_progress(); @@ -836,7 +829,7 @@ int main(int argc, char *argv[]) #endif break; case EV_WRITE: - gettimeofday(&src.last_time, 0); src.last_pos = pos; + gettimeofday(&last_time, 0); last_pos = pos; if (outfd >= 0 && lseek(outfd, (off_t)ev->pos*SECTORSZ, SEEK_SET) < 0) bail_syserr(errno, @@ -870,14 +863,14 @@ int main(int argc, char *argv[]) if (progresslen) putchar('\n'); - if (outfd >= 0 && ftruncate(outfd, (off_t)src.limit*SECTORSZ) < 0) + if (outfd >= 0 && ftruncate(outfd, (off_t)limit*SECTORSZ) < 0) bail_syserr(errno, "failed to set output file `%s' length", outfile); - if (src.dvd) DVDClose(src.dvd); - if (src.dvdfd >= 0) close(src.dvdfd); + if (dvd) DVDClose(dvd); + if (dvdfd >= 0) close(dvdfd); if (outfd >= 0) close(outfd); - if (src.mapfp) { - if (ferror(src.mapfp) || fclose(src.mapfp)) + if (mapfp) { + if (ferror(mapfp) || fclose(mapfp)) bail_syserr(errno, "error writing bad-sector map file"); } -- 2.11.0