From: Mark Wooding Date: Wed, 16 Feb 2022 21:13:46 +0000 (+0000) Subject: dvd-sector-copy.c: Hoist out the common sector-range parsing machinery. X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~mdw/git/dvdrip/commitdiff_plain/87a145d259478ae7d7dcc789d368b8fa3566f323 dvd-sector-copy.c: Hoist out the common sector-range parsing machinery. --- diff --git a/dvd-sector-copy.c b/dvd-sector-copy.c index dceab3f..a43adb2 100644 --- a/dvd-sector-copy.c +++ b/dvd-sector-copy.c @@ -152,6 +152,7 @@ static void store_filename(char *buf, ident id) typedef uint_least32_t secaddr; #define PRIuSEC PRIuLEAST32 +#define SECLIMIT 0x00400000 #define MAXFILES (1 + 2*99 + 1) struct file { @@ -595,6 +596,49 @@ static int read_line(FILE *fp, struct buf *b) return (0); } +#define PRF_HYPHEN 1u +static int parse_range(const char *p, unsigned f, + secaddr *start_out, secaddr *end_out) +{ + char *q; + int err, rc; + unsigned long start, end; + + err = errno; + + if (ISDIGIT(*p)) { + start = strtoul(p, &q, 0); + if (errno || start >= SECLIMIT) { rc = -1; goto end; } + *start_out = start; p = q; + } else if (!(f&PRF_HYPHEN)) + { rc = -1; goto end; } + else + start = 0; + + if (f&PRF_HYPHEN) { + if (*p != '-') { rc = -1; goto end; } + p++; + } else { + if (!ISSPACE(*p)) { rc = -1; goto end; } + do p++; while (ISSPACE(*p)); + } + + if (ISDIGIT(*p)) { + end = strtoul(p, &q, 0); + if (errno || end > SECLIMIT || end < start) { rc = -1; goto end; } + *end_out = end; p = q; + } else if (!(f&PRF_HYPHEN)) + { rc = -1; goto end; } + + if (!(f&PRF_HYPHEN)) while (ISSPACE(*p)) p++; + if (*p) { rc = -1; goto end; } + + rc = 0; +end: + errno = err; + return (rc); +} + int main(int argc, char *argv[]) { unsigned f = 0; @@ -602,7 +646,7 @@ int main(int argc, char *argv[]) uint64_t volsz; secaddr pos; off_t off; - unsigned long start, end; + secaddr start, end; const struct event *ev; const char *device = "/dev/dvd", *outfile = 0; int opt, blksz; @@ -638,16 +682,9 @@ int main(int argc, char *argv[]) p = buf.p; i++; while (ISSPACE(*p)) p++; if (!*p || *p == '#') continue; - if (!ISDIGIT(*p)) goto bad_range_file; - start = strtoul(p, &p, 0); - if (errno || !ISSPACE(*p)) goto bad_range_file; - do p++; while (ISSPACE(*p)); - if (!ISDIGIT(*p)) goto bad_range_file; - end = strtoul(p, &p, 0); - if (errno || (*p && !ISSPACE(*p))) goto bad_range_file; - while (ISSPACE(*p)) p++; - if (*p) goto bad_range_file; - if (start > end) goto bad_range_file; + if (parse_range(p, 0, &start, &end) || + (last <= SECLIMIT && start < last)) + bail("bad range `%s' at `%s' line %zu", buf.p, optarg, i); if (start < end) { put_event(EV_WRITE, 0, start); put_event(EV_STOP, 0, end); @@ -656,8 +693,6 @@ int main(int argc, char *argv[]) if (ferror(fp)) bail_syserr(errno, "failed to read ranges file `%s'", optarg); break; - bad_range_file: - bail("bad range `%s' at `%s' line %zu", buf.p, optarg, i); case 'b': if (mapfile) bail("can't have multiple map files"); mapfile = optarg; @@ -665,32 +700,13 @@ int main(int argc, char *argv[]) case 'c': f |= f_continue; break; case 'o': outfile = optarg; break; case 'r': - err = errno; errno = 0; - p = optarg; - if (*p == '-') - start = 0; - else { - if (!ISDIGIT(*p)) goto bad_range; - start = strtoul(p, &p, 0); - if (errno || *p != '-') goto bad_range; - } - p++; - if (!*p) + start = 0; end = -1; + if (parse_range(optarg, PRF_HYPHEN, &start, &end)) + bail("bad range `%s'", optarg); + if (start < end) { put_event(EV_WRITE, 0, start); - else { - if (!ISDIGIT(*p)) goto bad_range; - end = strtoul(p, &p, 0); - if (errno || *p) goto bad_range; - if (start > end) goto bad_range; - if (start < end) { - put_event(EV_WRITE, 0, start); - put_event(EV_STOP, 0, end); - } + if (end <= SECLIMIT) put_event(EV_STOP, 0, end); } - errno = err; - break; - bad_range: - bail("bad range `%s'", optarg); break; default: f |= f_bogus; break; } @@ -774,7 +790,7 @@ int main(int argc, char *argv[]) switch (ev->ev) { case EV_WRITE: if (f&f_write) - bail("overlapping ranges: range from %lu still open at %"PRIuSEC"", + bail("overlapping ranges: range from %"PRIuSEC" still open at %"PRIuSEC"", start, ev->pos); n++; f |= f_write; start = ev->pos; break;