📄 growisofs.c
字号:
/* * growisofs 5.21 by Andy Polyakov <appro@fy.chalmers.se>. * * Use-it-on-your-own-risk, GPL bless... * * This front-end to mkisofs(8) was originally developed to facilitate * appending of data to ISO9660 volumes residing on random write access * DVD media such as DVD+RW, DVD-RAM, as well as plain files/iso images. * At later stages even support for multi-session recording to DVD * write-once media such as DVD+R and DVD-R was added. * * As for growing random access volumes. The idea is very simple. The * program appends new data as it was added to a multisession media and * then copies the new volume descriptor(s) to the beginning of media * thus effectively updating the root catalog reference... * * For further details see http://fy.chalmers.se/~appro/linux/DVD+RW/. * * Revision history: * * 1.1: * - flush cache before copying volume descriptors; * 2.0: * - support for /dev/raw*; * - support for set-root-uid operation (needed for /dev/raw*); * - support for first "session" burning (needed for "poor-man"); * - "poor-man" support for those who don't want to recompile the * kernel; * 2.1: * - mkisofs_pid typo; * 2.2: * - uninitialized in_device variable; * - -help option; * 3.0: * - support for DVD+R; * 3.1: * - -Z fails if a file system is present and stdin is not a tty; * 3.2: * - support for image burning (needed for DVD+R as you can't use dd); * 3.3: * - 'growisofs -Z /dev/scdN image.iso' is too confusing, implement * 'growisofs -Z /dev/scdN=image.iso' instead; * 4.0: * - transport C++-fication for better portability; * - support for -dvd-compat option (improved DVD+R/RW compatibility); * - -dvd-video implies -dvd-compat; * - support for SONY DRU-500A; * - progress indicator for -Z /dev/scdN=image.iso; * - agressive -poor-man-ing; * 4.1: * - uninitialized errno at exit from -Z /dev/scdN=image.iso; * 4.2: * - don't print initial bogus progress indicator values; * - apparently some firmwares exhibit ambiguity in DVD+R disc * finalizing code; * 5.0: * - enforced 32K write strategy (needed for DVD-R[W]); * - support for DVD-RW Restricted Overwrite Mode; * - support for DVD-R[W] Sequential Mode; * 5.1: * - support for writing speed control; * 5.2: * - re-make it work under Linux 2.2 kernel; * - progress indicator to display recording velocity; * - code to protect against overburns; * - undocumented -use-the-force-luke flag to overwrite the media * none interactively; * - brown-bag bug in "LONG WRITE IN PROGRESS" handling code fixed; * 5.3: * - Pioneer workarounds/fix-ups, most notably DVR-x05 doesn't seem * to digest immediate "SYNC CACHE"; * - support for DVD-RW Quick Format, upon release verified to work * with Pioneer DVR-x05; * - bug in DVD+RW overburn "protection" code fixed; * - media reload is moved here from dvd+rw-format; * - refuse to burn if session starts close to or beyond 4GB limit * (limitation of Linux isofs implementation); * - dry_run check is postponed all the way till the first write; * 5.4: * - split first write to two to avoid "empty DMA table?" in kernel log; * - setup_fds is introduced to assist ports to another platforms; * - set-root-uid assistant code directly at entry point (see main()); * - OpenBSD/NetBSD support added, it's worth noting that unlike 3.3 * port by Maarten Hofman, it's /dev/rcd?c which is expected to be * passed as argument, not /dev/cd?c. * 5.5: * - fix for ENOENT at unmount, I should have called myself with execlp, * not execl; * - security: chdir("/") in set-root-uid assistant; * - use /proc/mounts instead of MOUNTED (a.k.a. /etc/mtab) in Linux * umount code; * 5.6: * - unconditional exit in set-root-uid assistant, mostly for aesthetic * reasons; * - support for DVD-RW DAO recordings (whenever Pioneer-ish Quick * Format is not an option, DAO should fill in for it, as it's the * only recording strategy applicable after *minimal* blanking * procedure); * - support for SG_IO pass-through interface, or in other words * support for Linux 2>=5; * - 'growisofs -M /dev/cdrom=/dev/zero', this is basically a counter- * intuitive kludge assigned to fill up multi-session write-once * media for better compatibility with DVD-ROM/-Video units, to keep * it mountable [in the burner unit] volume descriptors from previous * session are copied to the new session; * - disable -dvd-compat with -M option and DVD+R, advice to fill up * the media as above instead; * - postpone Write Page setup all the way till after dry_run check; * - if recording to write-once media is terminated by external event, * leave the session opened, so that the recording can be resumed * (though no promises about final results are made, it's just that * leaving it open makes more sense than to close the session); * - ask unit to perform OPC if READ DISC INFORMATION doesn't return * any OPC descriptors; * - get rid of redundant Quick Grow in Restricted Overwrite; * - Solaris 2.x support is merged, it's volume manager aware, i.e. * you can run it with or without volume manager; * 5.7: * - Solaris USB workaround; * - 15 min timeout for FLUSH CACHE in DVD-RW DAO; * - revalidate recording speed; * - load media upon start-up (Linux used to auto-close tray upon open, * but not the others, which is why this functionality is added so * late); * 5.8: * - elder Ricoh firmwares seem to report events differently, which * triggered growisofs and dvd+rw-format to end-less loop at startup * [event handling was introduced in 5.6 for debugging purposes]; * - int ioctl_fd is transformed to void *ioctl_handle to facilitate * port to FreeBSD; * - FreeBSD support contributed by Matthew Dillon; * - volume descriptors from second session were discarded in * Restricted Overwrite since 5.6; * 5.9: * - some [SONY] firmwares make it impossible to tell apart minimally * and fully blanked media, so we need a way to engage DAO manually * [in DVD-RW]... let's treat multiple -dvd-compat options as "cry" * for DAO; * - refuse to finalize even DVD-R media with -M flag (advise to fill * it up with -M /dev/cdrom=/dev/zero too), apparently DVD-units * [or is it just SONY?] also "misplace" legacy lead-out in the same * manner as DVD+units; * - oops! DAO hung at >4MB buffer because of sign overflow; * - couple of human-readable error messages in poor_mans_pwrite64; * - work around Plextor firmware deficiency which [also] manifests as * end-less loop upon startup; * 5.10: * - increase timeout for OPC, NEC multi-format derivatives might * require more time to fulfill the OPC procedure; * - extended syntax for -use-the-force-luke option, it's now possible * to engage DVD-R[W] dummy mode by -use-the-force-luke=[tty,]dummy * for example, where "tty" substitutes for the original non-extended * option meaning, see the source for more easter eggs; * - FreeBSD: compile-time option to pass -M /dev/fd/0 to mkisofs to * make life easier for those who mount devfs, but not fdescfs; * - eliminate potential race conditions; * - avoid end-less loop if no media was in upon tray load; * - interpret value of MKISOFS environment variable as absolute path * to mkisofs binary; * - to facilitate for GUI front-ends return different exit codes, most * notably exit value of 128|errno denotes a fatal error upon program * startup [messages worth popping up in a separate modal dialog * perhaps?], errno - fatal error during recording and 1 - warnings * at exit; * - to facilitate for GUI front-ends auto-format blank DVD+RW media; * - Linux: fix for failure to copy volume descriptors when DVD-RW * Restricted Overwrite procedure is applied to patched kernel; * - FreeBSD: growisofs didn't close tray upon startup nor did the rest * of the tools work with open tray; * - bark at -o option and terminate execution, the "problem" was that * users seem to misspell -overburn once in a while, in which case it * was passed down to mkisofs and an iso-image was dumped to current * working directory instead of media; * - generalize -M /dev/cdrom=file.iso option, but if file.iso is not * /dev/zero, insist on sane -C argument to be passed prior -M and * double-verify the track starting address; * 5.11: * - authorship statement in -version output; * - make speed_factor floating point and print "Current Write Speed" * factor for informational purposes; * - Pioneer DVR-x06 exhibited degraded performance when recording DVD+; * - Pioneer DVR-x06 failed to complete DVD+ recording gracefully; * - alter set-root-uid behaviour under Linux from "PAM-junky" to more * conservative one; * 5.12: * - single Pioneer DVR-x06 user reported that very small fraction of * his recordings get terminted with "LONG WRITE IN PROGRESS," even * though growisofs explicitly reserves for this condition... It * turned out that at those rare occasions unit reported a lot of free * buffer space, which growisofs treated as error condition. It's not * clear if it's firmware deficiency, but growisofs reserves even for * this apparently rare condition now. * - [major] issue with MODE SENSE/SELECT on SANYO derivatives, such as * Optorite, is addressed; * - Linux can't open(2) a socket by /dev/fd/N, replace it with dup(2); * - more relaxed command line option parsing and simultaneously a * zealous check to make sure that no mkisofs options are passed * along with -[ZM] /dev/cdrom=image; * - report I/O error if input stream was less than 64K; * - -M /dev/cdrom=/dev/zero didn't relocate the lead-out in DVD-RW * Restricted Overwrite; * 5.13: * - workarounds for Panasonic/MATSUSHITA DVD-RAM LF-D310; * - Solaris: media load upon start-up; * 5.14: * - LG GSA-4040B failed to auto-format DVD+RW blanks; * - '| growisofs -Z /dev/cdrom=/dev/fd/0' failed with "already carries * isofs" even when running interactively, so I check on /dev/tty * instead of isatty(0); * - error output was confusing when overburn condition was raised in * dry-run mode; * - more sane default drain buffer size to minimize system load when * unit fails to return usable buffer utilization statistics under * "LONG WRITE IN PROGRESS" condition; * - progress indicator process was orphaned if -Z /dev/cdrom=file.iso * terminated prematurely; * - -overburn -Z /dev/cdrom=file.iso printed two "ignored" messages; * - Solaris: use large-file API in setup_fds; * - HP-UX: HP-UX support is contributed by HP; * - block signals in the beginning of recording, formally it shouldn't * be necessary, but is apparently needed for some units (is it?); * - prepare code for -speed even in DVD+ context, need a test-case... * - TEAC DV-W50D and Lite-On LDW-811S failed to set recording velocity, * deploy GET PERFORMANCE/SET STREAMING commands; * - Lite-On LDW-811S returns 0s in Write Speed descriptors in page 2A, * this would cause a problem if DVD+ speed control was implemented; * 5.15: * - confusing output when DAO mode is manually engaged and DVD-RW media * is minimally blanked; * - complement -use-the-force-luke=dao[:size] to arrange for piping * non-iso images in DAO mode (size is to be expressed in 2KB chunks); * - Pioneer DVR-x06 apparently needs larger timeout to avoid "the LUN * appears to be stuck" message in the beginning of DAO recording; * - HP-UX: fix-up umount code; * - HP-UX: make sure user doesn't pass /dev/rscsi/cXtYlZ, they should * stick to /dev/rdsk/cXtYdZ; * - implement -use-the-force-luke=seek:N -Z /dev/dvd=image to arrange * for 'builtin_dd if=image of=/dev/dvd obs=32k seek=N/16' (note that * N is expected to be expressed in 2KB chunks); * - skip overwrite check for blank media to avoid read errors at start, * which reportedly may cause bus reset in some configurations; * - make get_mmc_profile load media, explicit media load used to be on * per platform basis, while it doesn't have to; * - postpone handle_events till after dry-run checkpoint; * - error reporting revised; * - Optorite seems to insist on resuming suspended DVD+RW format, at * least it's apparently the only way to get *reliable* results * (formally this contradicts specification, which explicitly states * that format is to be resumed automatically and transparently); * - FreeBSD: FreeBSD 5-CURRENT since 2003-08-24, including 5.2 fails * to pull sense data automatically, at least for ATAPI transport, * so I reach for it myself (it's apparently a kernel bug, which * eventually will be fixed, but I keep the workaround code just in * case); * - -speed option in DVD+ context is enabled, upon release tested with * Plextor PX-708A; * - make builtin_dd print amount of transferred data, together with * -use-the-force-luke=seek:N it's easier to maintain "tar-formatted" * rewritable media; * 5.16: * - brown-bag bug in "LONG WRITE IN PROGRESS" code path; * 5.17: * - Linux: fix for /proc/sys/dev/cdrom/check_media set to 1; * - HP-UX: INQUIRY buffer is required to be 128 bytes. Well, "required" * is wrong word in this context, as it's apparently a kernel bug * addressed in PHKL_30038 (HPUX 11.11) and PHKL_30039 (HPUX 11.23). * This "change" affects all dvd+rw-tools, but I don't bump their * version numbers for this, as it's an "ugly" workaround for an * *external* problem; * - switch to GET PERFORMANCE even for current write speed (most * notably required for NEC and derivatives); * - the above change required adaptations for Pioneer and LG units, * which don't/fail to provide current write speed through GET * PERFORMANCE despite the fact that the command is mandatory; * - HP-UX: retain root privileges in setup_fds, SIOC_IO requires them; * - fix for COMMAND SEQUENCE ERROR in the beginning of DVD-recording; * - drop privileges prior mkisofs -version; * 5.18: * - refuse to run if ${SUDO_COMMAND} is set; * - minimize amount of compiler warnings on 64-bit platforms; * - skip count-down if no_tty_check is set; * - -use-the-force-luke=tracksize:size option by suggestion from K3b; * - Linux: fix for "Bad file descriptor" with DVD+RW kernel patch; * 5.19: * - IRIX: IRIX 6.x port is added; * - Solaris: get rid of media reload, which made it possible to improve * volume manager experience as well; * - address speed verification issues with NEC ND-2500 and Plextor * PX-708A; * - make DVD-RAM work in "poor-man" mode; * - average write speed report at the end of recording; * - LG GSA-4081B fails to "SET STREAMING" with "LBA OUT OF RANGE" for * DVD+RW media, but not e.g. DVD-R; * 5.20: * - DVD-RAM reload if recorded with -poor-man; * - -use-the-force-luke=wrvfy for WRITE AND VERIFY(10); * - "flushing cache" takes forever, from 5.19-1; * - HP-UX: inconsistency between /dev/rdsk and /dev/rscsi names; * - handle non-fatal OPC errors; * - DVD+R Double Layer support; * - -use-the-force-luke=4gms to allow ISO9660 directory structures * to cross 4GB boundary, the option is effective only with DVD+R DL * and for data to be accessible under Linux isofs a kernel patch is * required; * - more sane sanity check for -use-the-force-luke=tracksize:N; * - -use-the-force-luke=break:size to set Layer Break position for * Double Layer recordings; * - speed verification issue with 8x AccessTek derivatives addressed; * - -use-the-force-luke=noload to leave tray ejected at the end; * - allow to resume incomplete sessions recorded with -M option; * - Layer Break position sanity check with respect to dataset size; * - #if directive to get rid of sudo check at compile time with * 'make WARN=-DI_KNOW_ALL_ABOUT_SUDO'; * 5.21: * - Linux: fix for kernel version 2.6>=8, 2.6.8 itself is deficient, * but the problem can be worked around by installing this version * set-root-uid; */#define PRINT_VERSION(cmd) do { \ char *s=strrchr((cmd),'/'); \ s ? s++ : (s=(cmd)); \ printf ("* %.*sgrowisofs by <appro@fy.chalmers.se>,"\ " version 5.21,\n",(int)(s-(cmd)),(cmd)); \} while (0)#define _LARGEFILE_SOURCE #define _LARGEFILE64_SOURCE#define _FILE_OFFSET_BITS 64#if defined(__linux)/* ... and "engage" glibc large file support */#ifndef _GNU_SOURCE#define _GNU_SOURCE#endif#elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)#define off64_t off_t#define stat64 stat#define fstat64 fstat#define open64 open#define pread64 pread#define pwrite64 pwrite#define lseek64 lseek#endif#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <time.h>#include <errno.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/wait.h>#include <sys/mman.h>#include <signal.h>#include <poll.h>#include <assert.h>#include <sys/time.h>#define FATAL_START(err) (0x80|(err))#ifndef EMEDIUMTYPE#define EMEDIUMTYPE EINVAL#endif#ifndef ENOMEDIUM#define ENOMEDIUM ENODEV#endiftypedef ssize_t (*pwrite64_t)(int,const void *,size_t,off64_t);/* * Symbols from growisofs_mmc.cpp *//* * These might terminate the program if error appears fatal. * The return value is therefore is always sane and suitable * for assignment. */int get_mmc_profile (void *fd);int plusminus_r_C_parm (void *fd,char *C_parm);pwrite64_t poor_mans_setup (void *fd,off64_t leadout);/* * These never terminate the program. * Pay attention to the return value. */int media_reload (char *file,struct stat *ref);int fumount (int fd);off64_t get_capacity (void *fd);int poor_man_rewritable (void *fd,void *buf);/* simplified */struct iso_primary_descriptor { unsigned char type [1]; unsigned char id [5]; unsigned char void1 [80-5-1]; unsigned char volume_space_size [8]; unsigned char void2 [2048-80-8];};#define CD_BLOCK ((off64_t)2048)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -