+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);
+}
+
+/*----- Progress utilities ------------------------------------------------*/
+
+struct progress_state progress = PROGRESS_STATE_INIT;
+static struct banner_progress_item banner_progress;
+
+static void render_banner_progress(struct progress_item *item,
+ struct progress_render_state *render)
+{
+ struct banner_progress_item *bi = (struct banner_progress_item *)item;
+
+ progress_putleft(render, " %s", bi->msg);
+ progress_shownotice(render, 4, 7);
+}
+
+void show_banner(const char *msg)
+{
+ banner_progress._base.render = render_banner_progress;
+ progress_additem(&progress, &banner_progress._base);
+ banner_progress.msg = msg;
+ progress_update(&progress);
+}
+
+void hide_banner(void)
+{
+ if (!progress_removeitem(&progress, &banner_progress._base))
+ progress_update(&progress);
+}
+
+/*----- DVD utilities -----------------------------------------------------*/
+
+#ifdef notdef
+static void logfn(void *p, dvd_logger_level_t lev,
+ const char *fmt, va_list ap)
+{
+ switch (lev) {
+ case DVD_LOGGER_LEVEL_ERROR:
+ fprintf("%s (libdvdread error): ", prog);
+ break;
+ case DVD_LOGGER_LEVEL_WARN:
+ fprintf("%s (libdvdread warning): ", prog);
+ break;
+ default:
+ return;
+ }
+ vfprintf(stderr, fmt, ap);
+ fputc('\n', stderr);
+}
+static const dvd_logger_cb logger = { logfn };
+#endif
+
+int open_dvd(const char *device, int mode,
+ int *fd_out, dvd_reader_t **dvd_out)
+{
+ int fd = -1;
+ dvd_reader_t *dvd = 0;
+ int bannerp = 0, rc;
+
+ for (;;) {
+ fd = open(device, mode);
+ if (fd >= 0 || errno != ENOMEDIUM) break;
+ if (!bannerp) {
+ show_banner("Waiting for disc to be inserted...");
+ bannerp = 1;
+ }
+ sit(0.2);
+ }
+ if (bannerp) hide_banner();
+
+ if (fd < 0) {
+ moan_syserr(errno, "failed to open device `%s'", device);
+ rc = -1; goto end;
+ }
+
+ if (dvd_out) {
+#ifdef notdef
+ dvd = DVDOpen2(0, &logger, device);
+#else
+ dvd = DVDOpen(device);
+#endif
+ if (!dvd) {
+ moan("failed to open DVD on `%s'", device);
+ rc = -1; goto end;
+ }
+ }
+
+ if (fd_out) { *fd_out = fd; fd = -1; }
+ if (dvd_out) { *dvd_out = dvd; dvd = 0; }
+ rc = 0;
+
+end:
+ if (fd >= 0) close(fd);
+ DVDClose(dvd);
+ return (rc);
+}
+