X-Git-Url: https://git.distorted.org.uk/~mdw/dvdrip/blobdiff_plain/53a3ad57a06b5709b3bd356ccdcb2a97d4acee81..48232a33dfecff3a7297300ed7087286d24033b6:/lib.c diff --git a/lib.c b/lib.c index 08616a7..2529f24 100644 --- a/lib.c +++ b/lib.c @@ -6,33 +6,65 @@ void set_prog(const char *p) { const char *q = strrchr(p, '/'); prog = q ? q + 1 : p; } void vmoan(const char *fmt, va_list ap) - { fprintf(stderr, "%s: ", prog); vfprintf(stderr, fmt, ap); } + { vmoan_syserr(0, fmt, ap); } -void moan(const char *fmt, ...) +void vmoan_syserr(int err, const char *fmt, va_list ap) { - va_list ap; - - va_start(ap, fmt); vmoan(fmt, ap); va_end(ap); + fprintf(stderr, "%s: ", prog); + vfprintf(stderr, fmt, ap); + if (err) fprintf(stderr, ": %s", strerror(errno)); fputc('\n', stderr); } +void moan(const char *fmt, ...) + { va_list ap; va_start(ap, fmt); vmoan(fmt, ap); va_end(ap); } + +void moan_syserr(int err, const char *fmt, ...) + { va_list ap; va_start(ap, fmt); vmoan_syserr(err, fmt, ap); va_end(ap); } + void bail(const char *fmt, ...) + { va_list ap; va_start(ap, fmt); vmoan(fmt, ap); va_end(ap); exit(2); } + +void bail_syserr(int err, const char *fmt, ...) { va_list ap; - va_start(ap, fmt); vmoan(fmt, ap); va_end(ap); - fputc('\n', stderr); + va_start(ap, fmt); vmoan_syserr(err, fmt, ap); va_end(ap); exit(2); } -void bail_syserr(int err, const char *fmt, ...) +double parse_float(const char **p_inout, unsigned f, + double min, double max, const char *what) { - va_list ap; + const char *p; + char *q; + double x; + int err; - va_start(ap, fmt); vmoan(fmt, ap); va_end(ap); - if (err) fprintf(stderr, ": %s", strerror(errno)); - fputc('\n', stderr); - exit(2); + err = errno; errno = 0; + p = *p_inout; + x = strtod(p, &q); + if (errno || x < min || x > max || (!(f&PNF_JUNK) && *q)) + bail("bad %s `%s'", what, p); + *p_inout = q; errno = err; + return (x); +} + +long parse_int(const char **p_inout, unsigned f, + long min, long max, const char *what) +{ + const char *p; + char *q; + long x; + int err; + + err = errno; errno = 0; + p = *p_inout; + x = strtoul(p, &q, 0); + if (errno || x < min || x > max || (!(f&PNF_JUNK) && *q)) + bail("bad %s `%s'", what, p); + *p_inout = q; errno = err; + return (x); } void sit(double t) @@ -87,6 +119,25 @@ void carefully_fclose(FILE *fp, const char *what) bail_syserr(errno, "error writing %s file", what); } +off_t device_size(int fd, const char *file, int *blksz_out) +{ + struct stat st; + uint64_t volsz; + + if (fstat(fd, &st)) + bail_syserr(errno, "failed to obtain status for `%s'", file); + if (S_ISREG(st.st_mode)) + volsz = st.st_size; + else if (S_ISBLK(st.st_mode)) { + if (ioctl(fd, BLKGETSIZE64, &volsz)) + bail_syserr(errno, "failed to get volume size for `%s'", file); + if (ioctl(fd, BLKSSZGET, blksz_out)) + bail_syserr(errno, "failed to get block size for `%s'", file); + } else + bail("can't read size for `%s': expected file or block device", file); + return ((off_t)volsz); +} + void store_filename(char *buf, ident id) { switch (id_kind(id)) { @@ -111,6 +162,57 @@ void store_filename(char *buf, ident id) } } +static char *copy_string(char *p, const char *q) +{ + while (*q) *p++ = *q++; + *p = 0; return (p); +} + +static char *copy_hex(char *p, const unsigned char *q, size_t sz) +{ + while (sz) { + sprintf(p, "%02x", *q); + p += 2; q++; sz--; + } + return (p); +} + +int dvd_id(char *p, dvd_reader_t *dvd, unsigned f, const char *file) +{ + char volid[33]; + unsigned char volsetid[16], discid[16]; + int rc; + size_t n; + + rc = DVDUDFVolumeInfo(dvd, + volid, sizeof(volid), + volsetid, sizeof(volsetid)); + if (!rc) { + p = copy_string(p, volid); + *p++ = '-'; + for (n = sizeof(volsetid); n && !volsetid[n - 1]; n--); + p = copy_hex(p, volsetid, n); + } else if (f&DIF_MUSTVOLINF) { + if (file) moan("failed to read volume info for `%s'", file); + else moan("failed to read volume info"); + return (-1); + } else + p = copy_string(p, ""); + + *p++ = ':'; + rc = DVDDiscID(dvd, discid); + if (!rc) + p = copy_hex(p, discid, sizeof(discid)); + else if (f&DIF_MUSTIFOHASH) { + if (file) moan("failed to determine disc id of `%s'", file); + else moan("failed to determine disc id"); + return (-1); + } else + p = copy_string(p, ""); + + return (0); +} + struct progress_state progress = PROGRESS_STATE_INIT; static struct banner_progress_item banner_progress; @@ -157,14 +259,15 @@ static void logfn(void *p, dvd_logger_level_t lev, static const dvd_logger_cb logger = { logfn }; #endif -void open_dvd(const char *device, int *fd_out, dvd_reader_t **dvd_out) +void open_dvd(const char *device, int mode, + int *fd_out, dvd_reader_t **dvd_out) { int fd; dvd_reader_t *dvd; int bannerp = 0; for (;;) { - fd = open(device, O_RDONLY); + fd = open(device, mode); if (fd >= 0 || errno != ENOMEDIUM) break; if (!bannerp) { show_banner("Waiting for disc to be inserted...");