1 /* @(#)cdrecord.c	1.417 19/01/08 Copyright 1995-2019 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static	UConst char sccsid[] =
5 	"@(#)cdrecord.c	1.417 19/01/08 Copyright 1995-2019 J. Schilling";
6 #endif
7 /*
8  *	Record data on a CD/CVD-Recorder
9  *
10  *	Copyright (c) 1995-2019 J. Schilling
11  */
12 /*
13  * The contents of this file are subject to the terms of the
14  * Common Development and Distribution License, Version 1.0 only
15  * (the "License").  You may not use this file except in compliance
16  * with the License.
17  *
18  * See the file CDDL.Schily.txt in this distribution for details.
19  * A copy of the CDDL is also available via the Internet at
20  * http://www.opensource.org/licenses/cddl1.txt
21  *
22  * When distributing Covered Code, include this CDDL HEADER in each
23  * file and include the License file CDDL.Schily.txt from this distribution.
24  */
25 
26 /*#define	TR_DEBUG*/
27 #include <schily/mconfig.h>
28 #include <schily/stdio.h>
29 #include <schily/standard.h>
30 #include <schily/stdlib.h>
31 #include <schily/fcntl.h>
32 #include <schily/errno.h>
33 #include <schily/time.h>
34 #include <schily/resource.h>	/* for rlimit */
35 #include <schily/stat.h>
36 #include <schily/unistd.h>
37 #include <schily/mman.h>
38 #include <schily/string.h>
39 #include <schily/utypes.h>
40 #include <schily/intcvt.h>
41 #include <schily/signal.h>
42 #include <schily/schily.h>
43 #include <schily/getargs.h>
44 #include <schily/nlsdefs.h>
45 #include <schily/priv.h>
46 
47 #include "xio.h"
48 
49 #include <scg/scsireg.h>	/* XXX wegen SC_NOT_READY */
50 #include <scg/scsitransp.h>
51 #include <scg/scgcmd.h>		/* XXX fuer read_buffer */
52 #include "scsi_scan.h"
53 
54 #include "auheader.h"
55 #include "cdrecord.h"
56 #include "cdrdeflt.h"
57 #include "movesect.h"
58 
59 
60 #ifdef	VMS
61 #include <vms_init.h>
62 #endif
63 
64 #include "version.h"
65 
66 char	cdr_version[] = VERSION;
67 
68 #if defined(_POSIX_PRIORITY_SCHEDULING) && _POSIX_PRIORITY_SCHEDULING -0 >= 0 && \
69     defined(HAVE_SCHED_SETSCHEDULER)
70 #ifdef  HAVE_SYS_PRIOCNTL_H	/* The preferred SYSvR4 schduler */
71 #else
72 #define	USE_POSIX_PRIORITY_SCHEDULING
73 #endif
74 #endif
75 
76 /*
77  * Map toc/track types into names.
78  */
79 char	*toc2name[] = {
80 		"CD-DA",
81 		"CD-ROM",
82 		"CD-ROM XA mode 1",
83 		"CD-ROM XA mode 2",
84 		"CD-I",
85 		"Illegal toc type 5",
86 		"Illegal toc type 6",
87 		"Illegal toc type 7",
88 };
89 
90 /*
91  * Map sector types into names.
92  */
93 char	*st2name[] = {
94 		"Illegal sector type 0",
95 		"CD-ROM mode 1",
96 		"CD-ROM mode 2",
97 		"Illegal sector type 3",
98 		"CD-DA without preemphasis",
99 		"CD-DA with preemphasis",
100 		"Illegal sector type 6",
101 		"Illegal sector type 7",
102 };
103 
104 /*
105  * Map data block types into names.
106  */
107 char	*db2name[] = {
108 		"Raw (audio)",
109 		"Raw (audio) with P/Q sub channel",
110 		"Raw (audio) with P/W packed sub channel",
111 		"Raw (audio) with P/W raw sub channel",
112 		"Reserved mode 4",
113 		"Reserved mode 5",
114 		"Reserved mode 6",
115 		"Vendor unique mode 7",
116 		"CD-ROM mode 1",
117 		"CD-ROM mode 2",
118 		"CD-ROM XA mode 2 form 1",
119 		"CD-ROM XA mode 2 form 1 (with subheader)",
120 		"CD-ROM XA mode 2 form 2",
121 		"CD-ROM XA mode 2 form 1/2/mix",
122 		"Reserved mode 14",
123 		"Vendor unique mode 15",
124 };
125 
126 /*
127  * Map write modes into names.
128  */
129 LOCAL	char	wm_none[] = "unknown";
130 LOCAL	char	wm_ill[]  = "illegal";
131 
132 char	*wm2name[] = {
133 		wm_none,
134 		"BLANK",
135 		"FORMAT",
136 		wm_ill,
137 		"PACKET",
138 		wm_ill,
139 		wm_ill,
140 		wm_ill,
141 		"TAO",
142 		wm_ill,
143 		wm_ill,
144 		wm_ill,
145 		"SAO",
146 		"SAO/RAW16",	/* Most liklely not needed */
147 		"SAO/RAW96P",
148 		"SAO/RAW96R",
149 		"RAW",
150 		"RAW/RAW16",
151 		"RAW/RAW96P",
152 		"RAW/RAW96R",
153 };
154 
155 	int	debug;		/* print debug messages		debug=#,-d  */
156 LOCAL	int	kdebug;		/* print kernel debug messages	kdebug#,kd# */
157 LOCAL	int	scsi_verbose;	/* SCSI verbose flag		-Verbose,-V */
158 LOCAL	int	silent;		/* SCSI silent flag		-silent,-s  */
159 	int	lverbose;	/* local verbose flag		-verbose,-v */
160 	int	xdebug;		/* extended debug flag		-x,xd=#	    */
161 
162 char	*buf;			/* The transfer buffer */
163 long	bufsize = -1;		/* The size of the transfer buffer */
164 
165 LOCAL	int	gracetime = GRACE_TIME;
166 LOCAL	int	raw_speed = -1;
167 LOCAL	int	dma_speed = -1;
168 LOCAL	int	dminbuf = -1;	/* XXX Hack for now drive min buf fill */
169 EXPORT	BOOL	isgui;
170 LOCAL	int	didintr;
171 EXPORT	char	*driveropts;
172 LOCAL	char	*cuefilename;
173 LOCAL	uid_t	oeuid = (uid_t)-1;
174 LOCAL	uid_t	ouid = (uid_t)-1;
175 LOCAL	BOOL	issetuid = FALSE;
176 LOCAL	char	*isobuf;	/* Buffer for doing -isosize on stdin	  */
177 LOCAL	int	isobsize;	/* The amount of remaining data in isobuf */
178 LOCAL	int	isoboff;	/* The current "read" offset in isobuf	  */
179 
180 struct timeval	starttime;
181 struct timeval	wstarttime;
182 struct timeval	stoptime;
183 struct timeval	fixtime;
184 
185 static	long	fs = -1L;	/* fifo (ring buffer) size */
186 
187 EXPORT	int 	main		__PR((int ac, char **av));
188 LOCAL	void	scg_openerr	__PR((char *errstr));
189 LOCAL	int	find_drive	__PR((SCSI *scgp, char *dev, int flags));
190 LOCAL	int	gracewait	__PR((cdr_t *dp, BOOL *didgracep));
191 LOCAL	void	cdrstats	__PR((cdr_t *dp));
192 LOCAL	void	susage		__PR((int));
193 LOCAL	void	usage		__PR((int));
194 LOCAL	void	blusage		__PR((int));
195 LOCAL	void	intr		__PR((int sig));
196 LOCAL	void	catchsig	__PR((int sig));
197 LOCAL	int	scsi_cb		__PR((void *arg));
198 LOCAL	void	intfifo		__PR((int sig));
199 LOCAL	void	exscsi		__PR((int excode, void *arg));
200 LOCAL	void	excdr		__PR((int excode, void *arg));
201 EXPORT	int	read_buf	__PR((int f, char *bp, int size));
202 EXPORT	int	fill_buf	__PR((int f, track_t *trackp, long secno,
203 							char *bp, int size));
204 EXPORT	int	get_buf		__PR((int f, track_t *trackp, long secno,
205 							char **bpp, int size));
206 EXPORT	int	write_secs	__PR((SCSI *scgp, cdr_t *dp, char *bp,
207 						long startsec, int bytespt,
208 						int secspt, BOOL islast));
209 EXPORT	int	write_track_data __PR((SCSI *scgp, cdr_t *, track_t *));
210 EXPORT	int	pad_track	__PR((SCSI *scgp, cdr_t *dp,
211 					track_t *trackp,
212 					long startsec, Llong amt,
213 					BOOL dolast, Llong *bytesp));
214 EXPORT	int	write_buf	__PR((SCSI *scgp, cdr_t *dp,
215 					track_t *trackp,
216 					char *bp, long startsec, Llong amt,
217 					int secsize,
218 					BOOL dolast, Llong *bytesp));
219 LOCAL	void	printdata	__PR((int, track_t *));
220 LOCAL	void	printaudio	__PR((int, track_t *));
221 LOCAL	void	checkfile	__PR((int, track_t *));
222 LOCAL	int	checkfiles	__PR((int, track_t *));
223 LOCAL	void	setleadinout	__PR((int, track_t *));
224 LOCAL	void	setpregaps	__PR((int, track_t *));
225 LOCAL	long	checktsize	__PR((int, track_t *));
226 LOCAL	void	opentracks	__PR((track_t *));
227 LOCAL	int	cvt_hidden	__PR((track_t *));
228 LOCAL	void	checksize	__PR((track_t *));
229 LOCAL	BOOL	checkdsize	__PR((SCSI *scgp, cdr_t *dp,
230 					long tsize, UInt32_t flags));
231 LOCAL	void	raise_fdlim	__PR((void));
232 LOCAL	void	raise_memlock	__PR((void));
233 LOCAL	int	getfilecount	__PR((int ac, char *const *av, const char *fmt));
234 LOCAL	void	gargs		__PR((int, char **, int *, track_t *,
235 					char **, char **,
236 					int *, cdr_t **,
237 					int *, UInt32_t *, int *));
238 LOCAL	int	default_wr_mode	__PR((int tracks, track_t *trackp,
239 					UInt32_t *flagsp, int *wmp, int flags));
240 LOCAL	void	etracks		__PR((char *opt));
241 LOCAL	void	set_trsizes	__PR((cdr_t *, int, track_t *));
242 EXPORT	void	load_media	__PR((SCSI *scgp, cdr_t *, BOOL));
243 EXPORT	void	unload_media	__PR((SCSI *scgp, cdr_t *, UInt32_t));
244 EXPORT	void	reload_media	__PR((SCSI *scgp, cdr_t *));
245 EXPORT	void	set_secsize	__PR((SCSI *scgp, int secsize));
246 LOCAL	int	_read_buffer	__PR((SCSI *scgp, int));
247 LOCAL	int	get_dmaspeed	__PR((SCSI *scgp, cdr_t *));
248 LOCAL	BOOL	do_opc		__PR((SCSI *scgp, cdr_t *, UInt32_t));
249 LOCAL	void	check_recovery	__PR((SCSI *scgp, cdr_t *, UInt32_t));
250 	void	audioread	__PR((SCSI *scgp, cdr_t *, int));
251 LOCAL	void	print_msinfo	__PR((SCSI *scgp, cdr_t *));
252 LOCAL	void	print_toc	__PR((SCSI *scgp, cdr_t *));
253 LOCAL	void	print_track	__PR((int, long, struct msf *, int, int, int));
254 #if !defined(HAVE_SYS_PRIOCNTL_H)
255 LOCAL	int	rt_raisepri	__PR((int));
256 #endif
257 EXPORT	void	raisepri	__PR((int));
258 LOCAL	void	wait_input	__PR((void));
259 LOCAL	void	checkgui	__PR((void));
260 LOCAL	int	getbltype	__PR((char *optstr, long *typep));
261 LOCAL	void	print_drflags	__PR((cdr_t *dp));
262 LOCAL	void	print_wrmodes	__PR((cdr_t *dp));
263 LOCAL	BOOL	check_wrmode	__PR((cdr_t *dp, UInt32_t wmode, int tflags));
264 LOCAL	void	set_wrmode	__PR((cdr_t *dp, UInt32_t wmode, int tflags));
265 LOCAL	void	linuxcheck	__PR((void));
266 LOCAL	void	priv_warn	__PR((const char *what, const char *msg));
267 #ifdef	TR_DEBUG
268 EXPORT	void	prtrack		__PR((track_t *trackp));
269 #endif
270 
271 struct exargs {
272 	SCSI		*scgp;		/* The open SCSI * pointer	    */
273 	cdr_t		*dp;		/* The pointer to the device driver */
274 	int		old_secsize;
275 	UInt32_t	flags;
276 	int		exflags;
277 } exargs;
278 
279 EXPORT int
main(ac,av)280 main(ac, av)
281 	int	ac;
282 	char	*av[];
283 {
284 	char	*dev = NULL;
285 #if	defined(USE_NLS)
286 	char	*dir;
287 #endif
288 	int	timeout = 40;	/* Set default timeout to 40s CW-7502 is slow*/
289 	int	speed = -1;
290 	UInt32_t flags = 0L;
291 	int	blanktype = 0;
292 	int	i;
293 	int	tracks = 0;
294 	int	trackno;
295 	long	tsize;
296 	track_t	track[MAX_TRACK+2];	/* Max tracks + track 0 + track AA */
297 	cdr_t	*dp = (cdr_t *)0;
298 	long	startsec = 0L;
299 	int	errs = 0;
300 	SCSI	*scgp = NULL;
301 	char	*scgopts = NULL;
302 	char	errstr[80];
303 	BOOL	gracedone = FALSE;
304 
305 #ifdef __EMX__
306 	/* This gives wildcard expansion with Non-Posix shells with EMX */
307 	_wildcard(&ac, &av);
308 #endif
309 #ifdef	HAVE_SOLARIS_PPRIV
310 	/*
311 	 * Try to gain additional privs on Solaris
312 	 */
313 	do_pfexec(ac, av,
314 		PRIV_FILE_DAC_READ,	/* to open /dev/ nodes for USCSICMD */
315 		PRIV_SYS_DEVICES,	/* to issue USCSICMD ioctl */
316 		PRIV_PROC_LOCK_MEMORY,	/* to grant realtime writes to CD-R */
317 		PRIV_PROC_PRIOCNTL,	/* to grant realtime writes to CD-R */
318 		PRIV_NET_PRIVADDR,	/* to access remote writer via RSCSI */
319 		NULL);
320 	/*
321 	 * Starting from here, we potentially have more privileges.
322 	 */
323 #endif
324 	save_args(ac, av);
325 	/*
326 	 * At this point, we should have the needed privileges, either because:
327 	 *
328 	 *	1)	We have been called by a privileged user (eg. root)
329 	 *	2)	This is a suid-root process
330 	 *	3)	This is a process that did call pfexec to gain privs
331 	 *	4)	This is a process that has been called via pfexec
332 	 *	5)	This is a process that gained privs via fcaps
333 	 *
334 	 * Case (1) is the only case where whe should not give up privileges
335 	 * because people would not expect it and because there will be no
336 	 * privilege escalation in this process.
337 	 */
338 	oeuid = geteuid();		/* Remember saved set uid	*/
339 	ouid = getuid();		/* Remember uid			*/
340 #ifdef	HAVE_ISSETUGID
341 	issetuid = issetugid();
342 #else
343 	issetuid = oeuid != ouid;
344 #endif
345 
346 #if	defined(USE_NLS)
347 	(void) setlocale(LC_ALL, "");
348 #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
349 #define	TEXT_DOMAIN "cdrecord"	/* Use this only if it weren't */
350 #endif
351 	dir = searchfileinpath("share/locale", F_OK,
352 					SIP_ANY_FILE|SIP_NO_PATH, NULL);
353 	if (dir)
354 		(void) bindtextdomain(TEXT_DOMAIN, dir);
355 	else
356 #if defined(PROTOTYPES) && defined(INS_BASE)
357 	(void) bindtextdomain(TEXT_DOMAIN, INS_BASE "/share/locale");
358 #else
359 	(void) bindtextdomain(TEXT_DOMAIN, "/usr/share/locale");
360 #endif
361 	(void) textdomain(TEXT_DOMAIN);
362 #endif
363 
364 
365 	fillbytes(track, sizeof (track), '\0');
366 	for (i = 0; i < MAX_TRACK+2; i++)
367 		track[i].track = track[i].trackno = i;
368 	track[0].tracktype = TOC_MASK;
369 	raise_fdlim();
370 	gargs(ac, av, &tracks, track, &dev, &scgopts, &timeout, &dp, &speed,
371 						&flags, &blanktype);
372 	if ((track[0].tracktype & TOC_MASK) == TOC_MASK)
373 		comerrno(EX_BAD, _("Internal error: Bad TOC type.\n"));
374 
375 	/*
376 	 * Attention: Additional restrictions to the CDDL are in place
377 	 * regarding this file. Please read both the files CDDL.Schily
378 	 * and cdrecord/LIMITATIONS for details.
379 	 *
380 	 * The Author does encourage you to not make changes not in
381 	 * consent with him. Since this is free software, you are of
382 	 * course free to make any modifications you seem fit. However,
383 	 * if you choose to do this, additional restrictions
384 	 * apply. Again, see cdrecord/LIMITATIONS for details.
385 	 *
386 	 * In order to comply with the restriction, the author suggests
387 	 * the following measures:
388 	 *
389 	 *	-	Clearly state that the current version is an
390 	 *		inofficial (modified) version and thus may have bugs
391 	 *		that are not present in the original.
392 	 *
393 	 *	-	Print your support e-mail address and tell people that
394 	 *		you will do complete support for this version of
395 	 *		cdrecord.
396 	 *
397 	 *		Or clearly state that there is absolutely no support
398 	 *		for the modified version you did create.
399 	 *
400 	 *	-	Tell the users not to ask the original author for
401 	 *		help.
402 	 *
403 	 * This limitation definitely also applies when you use any other
404 	 * cdrecord release together with libscg-0.6 or later, or when you
405 	 * use any amount of code from cdrecord-1.11a17 or later.
406 	 * In fact, it applies to any version of cdrecord.
407 	 *
408 	 * I am sorry for the inconvenience but I am forced to do this because
409 	 * some people create inofficial branches. These branches create
410 	 * problems but the initiators do not give support and thus cause the
411 	 * development of the official cdrecord versions to slow down because
412 	 * I am loaded with unneeded work.
413 	 *
414 	 * Please note that this is a memorandum on how I interpret the OSI
415 	 * rules at http://www.opensource.org/docs/definition.php
416 	 * If you use/modify/redistribute cdrecord, you need to accept it
417 	 * this way.
418 	 *
419 	 *
420 	 * The above statement is void if there has been neither a new version
421 	 * of cdrecord nor a new version of star from the original author
422 	 * within more then a year.
423 	 */
424 
425 	/*
426 	 * Begin restricted code for quality assurance.
427 	 */
428 
429 	/*
430 	 * Ugly, but Linux incude files violate POSIX and #define printf,
431 	 * so we cannot include the #ifdef inside the printf() arg list.
432 	 */
433 	i = set_cdrcmds("mmc_dvd", (cdr_t **)NULL);
434 
435 #	define	PRODVD_TITLE	i?"-ProDVD":""
436 #	define	PROBD_TITLE	"-ProBD"
437 #ifdef	CLONE_WRITE
438 #	define	CLONE_TITLE	"-Clone"
439 #else
440 #	define	CLONE_TITLE	""
441 #endif
442 	if ((flags & F_MSINFO) == 0 || lverbose || flags & F_VERSION) {
443 		printf(_("Cdrecord%s%s%s %s %s (%s-%s-%s) Copyright (C) 1995-2019 %s\n"),
444 								PRODVD_TITLE,
445 								PROBD_TITLE,
446 								CLONE_TITLE,
447 								cdr_version,
448 								VERSION_DATE,
449 								HOST_CPU, HOST_VENDOR, HOST_OS,
450 								_("Joerg Schilling"));
451 
452 #if	defined(SOURCE_MODIFIED) || !defined(IS_SCHILY_XCONFIG)
453 #define	INSERT_YOUR_EMAIL_ADDRESS_HERE
454 #define	NO_SUPPORT	0
455 		printf(_("NOTE: this version of cdrecord is an inofficial (modified) release of cdrecord\n"));
456 		printf(_("      and thus may have bugs that are not present in the original version.\n"));
457 #if	NO_SUPPORT
458 		printf(_("      The author of the modifications decided not to provide a support e-mail\n"));
459 		printf(_("      address so there is absolutely no support for this version.\n"));
460 #else
461 		printf(_("      Please send bug reports and support requests to <%s>.\n"), INSERT_YOUR_EMAIL_ADDRESS_HERE);
462 #endif
463 		printf(_("      The original author should not be bothered with problems of this version.\n"));
464 		printf("\n");
465 #endif
466 #if	!defined(IS_SCHILY_XCONFIG)
467 		printf(_("\nWarning: This version of cdrecord has not been configured via the standard\n"));
468 		printf(_("autoconfiguration method of the Schily makefile system. There is a high risk\n"));
469 		printf(_("that the code is not configured correctly and for this reason will not behave\n"));
470 		printf(_("as expected.\n"));
471 #endif
472 	}
473 
474 	if (flags & F_VERSION)
475 		exit(0);
476 	/*
477 	 * End restricted code for quality assurance.
478 	 */
479 	checkgui();
480 
481 	if (debug || lverbose) {
482 		printf(_("TOC Type: %d = %s\n"),
483 			track[0].tracktype & TOC_MASK,
484 			toc2name[track[0].tracktype & TOC_MASK]);
485 	}
486 
487 	if ((flags & (F_MSINFO|F_TOC|F_PRATIP|F_FIX|F_VERSION|F_CHECKDRIVE|F_INQUIRY|F_SCANBUS|F_RESET)) == 0) {
488 		/*
489 		 * Try to lock us im memory (will only work for root)
490 		 * but you need access to root anyway to send SCSI commands.
491 		 * We need to be root to open /dev/scg? or similar devices
492 		 * on other OS variants and we need to be root to be able
493 		 * to send SCSI commands at least on AIX and
494 		 * Solaris (USCSI only) regardless of the permissions for
495 		 * opening files
496 		 *
497 		 * XXX The folowing test used to be
498 		 * XXX #if defined(HAVE_MLOCKALL) || defined(_POSIX_MEMLOCK)
499 		 * XXX but the definition for _POSIX_MEMLOCK did change during
500 		 * XXX the last 8 years and the autoconf test is better for
501 		 * XXX the static case. sysconf() only makes sense if we like
502 		 * XXX to check dynamically.
503 		 */
504 		raise_memlock();
505 #if defined(HAVE_MLOCKALL)
506 		/*
507 		 * XXX mlockall() needs root privilleges.
508 		 */
509 		if (mlockall(MCL_CURRENT|MCL_FUTURE) < 0) {
510 			errmsg(_("WARNING: Cannot do mlockall(2).\n"));
511 			errmsgno(EX_BAD, _("WARNING: This causes a high risk for buffer underruns.\n"));
512 		}
513 #endif
514 
515 		/*
516 		 * XXX raisepri() needs root privilleges.
517 		 */
518 		raisepri(0); /* max priority */
519 		/*
520 		 * XXX shmctl(id, SHM_LOCK, 0) needs root privilleges.
521 		 * XXX So if we use SysV shared memory, wee need to be root.
522 		 *
523 		 * Note that not being able to set up a FIFO bombs us
524 		 * back to the DOS ages. Trying to run cdrecord without
525 		 * root privillegs is extremely silly, it breaks most
526 		 * of the advanced features. We need to be at least installed
527 		 * suid root or called by RBACs pfexec.
528 		 */
529 		fs = init_fifo(fs); /* Attach shared memory (still one process) */
530 	}
531 
532 	if ((flags & F_WAITI) != 0)
533 		wait_input();
534 
535 
536 	/*
537 	 * Call scg_remote() to force loading the remote SCSI transport library
538 	 * code that is located in librscg instead of the dummy remote routines
539 	 * that are located inside libscg.
540 	 */
541 	scg_remote();
542 	if (dev != NULL &&
543 	    ((strncmp(dev, "HELP", 4) == 0) ||
544 	    (strncmp(dev, "help", 4) == 0))) {
545 		scg_help(stderr);
546 		exit(0);
547 	}
548 	/*
549 	 * The following scg_open() call needs more privileges, so we check for
550 	 * sufficient privileges here.
551 	 * The check has been introduced as some Linux distributions miss the
552 	 * skills to perceive the necessity for the needed privileges. So we
553 	 * warn which features are impaired by actually missing privileges.
554 	 */
555 	if (!priv_eff_priv(SCHILY_PRIV_FILE_DAC_READ))
556 		priv_warn("file read", "You will not be able to open all needed devices.");
557 #ifndef	__SUNOS5
558 	/*
559 	 * Due to a design bug in the Solaris USCSI ioctl, we don't need
560 	 * PRIV_FILE_DAC_WRITE to send SCSI commands and most installations
561 	 * probably don't grant PRIV_FILE_DAC_WRITE. Once we need /dev/scg*,
562 	 * we would need to test for PRIV_FILE_DAC_WRITE also.
563 	 */
564 	if (!priv_eff_priv(SCHILY_PRIV_FILE_DAC_WRITE))
565 		priv_warn("file write", "You will not be able to open all needed devices.");
566 #endif
567 	if (!priv_eff_priv(SCHILY_PRIV_SYS_DEVICES))
568 		priv_warn("device",
569 		    "You may not be able to send all needed SCSI commands, this my cause various unexplainable problems.");
570 	if (!priv_eff_priv(SCHILY_PRIV_PROC_LOCK_MEMORY))
571 		priv_warn("memlock", "You may get buffer underruns.");
572 	if (!priv_eff_priv(SCHILY_PRIV_PROC_PRIOCNTL))
573 		priv_warn("priocntl", "You may get buffer underruns.");
574 	if (!priv_eff_priv(SCHILY_PRIV_NET_PRIVADDR))
575 		priv_warn("network", "You will not be able to do remote SCSI.");
576 
577 	/*
578 	 * XXX scg_open() needs root privilleges.
579 	 */
580 	if ((scgp = scg_open(dev, errstr, sizeof (errstr),
581 				debug, (flags & F_MSINFO) == 0 || lverbose)) == (SCSI *)0) {
582 			scg_openerr(errstr);
583 			/* NOTREACHED */
584 	}
585 
586 	/*
587 	 * Drop privs we do not need anymore.
588 	 * We no longer need:
589 	 *	file_dac_read,proc_lock_memory,proc_priocntl,net_privaddr
590 	 * We still need:
591 	 *	sys_devices
592 	 *
593 	 * If this is a suid-root process or if the real uid of
594 	 * this process is not root, we may have gained privileges
595 	 * from suid-root or pfexec and need to manage privileges in
596 	 * order to prevent privilege escalations for the user.
597 	 */
598 	if (issetuid || ouid != 0)
599 		priv_drop();
600 	/*
601 	 * This is only for OS that do not support fine grained privs.
602 	 *
603 	 * XXX Below this point we do not need root privilleges anymore.
604 	 */
605 	if (geteuid() != getuid()) {	/* AIX does not like to do this */
606 					/* If we are not root		*/
607 #ifdef	HAVE_SETREUID
608 		if (setreuid(-1, getuid()) < 0)
609 #else
610 #ifdef	HAVE_SETEUID
611 		if (seteuid(getuid()) < 0)
612 #else
613 		if (setuid(getuid()) < 0)
614 #endif
615 #endif
616 			comerr(_("Panic cannot set back effective uid.\n"));
617 	}
618 	/*
619 	 * WARNING: We now are no more able to do any privilleged operation
620 	 * unless we have been called by root.
621 	 *
622 	 * XXX It may be that we later get problems in init_faio() because
623 	 * XXX this function calls raisepri() to lower the priority slightly.
624 	 */
625 	scg_settimeout(scgp, timeout);
626 	if (scgopts) {
627 		i = scg_opts(scgp, scgopts);
628 		if (i <= 0)
629 			exit(i < 0 ? EX_BAD : 0);
630 	}
631 	scgp->flags |= SCGF_PERM_PRINT;
632 	scgp->verbose = scsi_verbose;
633 	scgp->silent = silent;
634 	scgp->debug = debug;
635 	scgp->kdebug = kdebug;
636 	scgp->cap->c_bsize = DATA_SEC_SIZE;
637 
638 
639 	if ((flags & F_MSINFO) == 0 || lverbose) {
640 		char	*vers;
641 		char	*auth;
642 
643 		/*
644 		 * Warning: If you modify this section of code, you must
645 		 * change the name of the program.
646 		 */
647 		vers = scg_version(0, SCG_VERSION);
648 		auth = scg_version(0, SCG_AUTHOR);
649 		printf(_("Using libscg version '%s-%s'.\n"), auth, vers);
650 		if (auth == 0 || strcmp("schily", auth) != 0) {
651 			errmsgno(EX_BAD,
652 			_("Warning: using inofficial version of libscg (%s-%s '%s').\n"),
653 				auth, vers, scg_version(0, SCG_SCCS_ID));
654 		}
655 
656 		vers = scg_version(scgp, SCG_VERSION);
657 		auth = scg_version(scgp, SCG_AUTHOR);
658 		if (lverbose > 1)
659 			error(_("Using libscg transport code version '%s-%s'\n"), auth, vers);
660 		if (auth == 0 || strcmp("schily", auth) != 0) {
661 			errmsgno(EX_BAD,
662 			_("Warning: using inofficial libscg transport code version (%s-%s '%s').\n"),
663 				auth, vers, scg_version(scgp, SCG_SCCS_ID));
664 		}
665 
666 		vers = scg_version(scgp, SCG_RVERSION);
667 		auth = scg_version(scgp, SCG_RAUTHOR);
668 		if (lverbose > 1 && vers && auth)
669 			error(_("Using remote transport code version '%s-%s'\n"), auth, vers);
670 		if (auth != 0 && strcmp("schily", auth) != 0) {
671 			errmsgno(EX_BAD,
672 			_("Warning: using inofficial remote transport code version (%s-%s '%s').\n"),
673 				auth, vers, scg_version(scgp, SCG_RSCCS_ID));
674 		}
675 	}
676 	if (lverbose && driveropts)
677 		printf(_("Driveropts: '%s'\n"), driveropts);
678 
679 /*	bufsize = scg_bufsize(scgp, CDR_BUF_SIZE);*/
680 	bufsize = scg_bufsize(scgp, bufsize);
681 	if (lverbose || debug)
682 		error(_("SCSI buffer size: %ld\n"), bufsize);
683 	if ((buf = scg_getbuf(scgp, bufsize)) == NULL)
684 		comerr(_("Cannot get SCSI I/O buffer.\n"));
685 
686 	if ((flags & F_SCANBUS) != 0) {
687 		i = select_target(scgp, stdout);
688 		if (i < 0) {
689 			scg_openerr("");
690 			/* NOTREACHED */
691 		}
692 		exit(0);
693 	}
694 	if (scg_scsibus(scgp) < 0 &&
695 				scg_target(scgp) < 0 && scg_lun(scgp) < 0) {
696 		i = find_drive(scgp, dev, flags);
697 		if (i < 0) {
698 			scg_openerr("");
699 			/* NOTREACHED */
700 		}
701 	}
702 	if ((flags & F_RESET) != 0) {
703 		if (scg_reset(scgp, SCG_RESET_NOP) < 0)
704 			comerr(_("Cannot reset (OS does not implement reset).\n"));
705 		if (scg_reset(scgp, SCG_RESET_TGT) >= 0)
706 			exit(0);
707 		if (scg_reset(scgp, SCG_RESET_BUS) < 0)
708 			comerr(_("Cannot reset target.\n"));
709 		exit(0);
710 	}
711 	/*
712 	 * First try to check which type of SCSI device we
713 	 * have.
714 	 */
715 	if (debug || lverbose)
716 		printf("atapi: %d\n", scg_isatapi(scgp));
717 	seterrno(0);
718 	scgp->silent++;
719 	i = test_unit_ready(scgp);	/* eat up unit attention */
720 	scgp->silent--;
721 	if (i < 0) {
722 		i = geterrno();
723 		if (i == EPERM || i == EACCES) {
724 			scg_openerr("");
725 			/* NOTREACHED */
726 		}
727 	}
728 	if (!do_inquiry(scgp, (flags & F_MSINFO) == 0 || lverbose)) {
729 		errmsgno(EX_BAD, _("Cannot do inquiry for CD/DVD/BD-Recorder.\n"));
730 		if (unit_ready(scgp))
731 			errmsgno(EX_BAD, _("The unit seems to be hung and needs power cycling.\n"));
732 		exit(EX_BAD);
733 	}
734 
735 	if ((flags & F_PRCAP) != 0) {
736 		print_capabilities(scgp);
737 		print_performance_mmc(scgp);
738 		print_capabilities_mmc4(scgp);
739 		if (get_curprofile(scgp) >= 0) {
740 			printf(_("\nSupported profiles according to MMC-4 feature list:\n"));
741 			print_profiles(scgp);
742 			printf(_("\nSupported features according to MMC-4 feature list:\n"));
743 			print_features(scgp);
744 		}
745 		exit(0);
746 	}
747 	if ((flags & F_INQUIRY) != 0)
748 		exit(0);
749 
750 	/*
751 	 * Here we start to use drive specific commands and not generic SCSI
752 	 * anymore. We first get the drive specific driver via get_cdrcmds().
753 	 */
754 
755 	if (dp == (cdr_t *)NULL) {	/* No driver= option specified	*/
756 		dp = get_cdrcmds(scgp);	/* Calls dp->cdr_identify()	*/
757 	} else if (!is_unknown_dev(scgp) && dp != get_cdrcmds(scgp)) {
758 		errmsgno(EX_BAD, _("WARNING: Trying to use other driver on known device.\n"));
759 	}
760 
761 	if (!is_cddrive(scgp))
762 		comerrno(EX_BAD, _("Sorry, no CD/DVD/BD-Drive found on this target.\n"));
763 	if (dp == (cdr_t *)0)
764 		comerrno(EX_BAD, _("Sorry, no supported CD/DVD/BD-Recorder found on this target.\n"));
765 	/*
766 	 * The driver is known, set up data structures...
767 	 */
768 	{
769 		cdr_t	*ndp;
770 		dstat_t	*dsp;
771 
772 		ndp = malloc(sizeof (cdr_t));
773 		dsp = malloc(sizeof (dstat_t));
774 		if (ndp == NULL || dsp == NULL)
775 			comerr(_("Cannot allocate memory for driver structure.\n"));
776 		movebytes(dp, ndp, sizeof (cdr_t));
777 		dp = ndp;
778 		dp->cdr_flags |= CDR_ALLOC;
779 		dp->cdr_cmdflags = flags;
780 
781 		fillbytes(dsp, sizeof (*dsp), '\0');
782 		dsp->ds_trackp		= track;
783 		dsp->ds_minbuf		= 0xFFFF;
784 		dsp->ds_layer_break	= -1;
785 		dp->cdr_dstat		= dsp;
786 	}
787 
788 	/*
789 	 * Reduce buffer size for older non-MMC drives.
790 	 * The Philips CDD-521 is known not to work with a DMA size > 63 kB.
791 	 */
792 	if (!is_mmc(scgp, NULL, NULL) && bufsize > CDR_OLD_BUF_SIZE)
793 		bufsize = CDR_OLD_BUF_SIZE;
794 
795 	if ((flags & (F_MSINFO|F_TOC|F_LOAD|F_DLCK|F_EJECT)) == 0 ||
796 	    tracks > 0 ||
797 	    cuefilename != NULL) {
798 
799 
800 		if ((dp->cdr_flags & CDR_ISREADER) != 0) {
801 			errmsgno(EX_BAD,
802 			_("Sorry, no CD/DVD/BD-Recorder or unsupported CD/DVD/BD-Recorder found on this target.\n"));
803 			comexit(EX_BAD);
804 		}
805 
806 	}
807 
808 	/*
809 	 * Set up data structures for current drive state.
810 	 */
811 	if ((*dp->cdr_attach)(scgp, dp) != 0)
812 		comerrno(EX_BAD, _("Cannot attach driver for CD/DVD/BD-Recorder.\n"));
813 
814 	if (lverbose > 1) {
815 		printf(_("Drive current speed: %d\n"), dp->cdr_dstat->ds_dr_cur_wspeed);
816 		printf(_("Drive default speed: %d\n"), dp->cdr_speeddef);
817 		printf(_("Drive max speed    : %d\n"), dp->cdr_speedmax);
818 	}
819 	if (speed > (int)dp->cdr_speedmax && (flags & F_FORCE) == 0)
820 		speed = dp->cdr_speedmax;
821 	if (speed < 0)
822 		speed = dp->cdr_speeddef;
823 
824 	if (lverbose > 1) {
825 		printf(_("Selected speed     : %d\n"), speed);
826 	}
827 	dp->cdr_dstat->ds_wspeed = speed; /* XXX Remove 'speed' in future */
828 
829 	exargs.scgp	   = scgp;
830 	exargs.dp	   = dp;
831 	exargs.old_secsize = -1;
832 	exargs.flags	   = flags;
833 
834 	if ((flags & F_MSINFO) == 0 || lverbose) {
835 		printf(_("Using %s (%s).\n"), dp->cdr_drtext, dp->cdr_drname);
836 		print_drflags(dp);
837 		print_wrmodes(dp);
838 	}
839 	scgp->silent++;
840 	if ((debug || lverbose)) {
841 		long	physbufsize = -1;
842 
843 		tsize = -1;
844 		(*dp->cdr_buffer_cap)(scgp, &tsize, (long *)0);
845 
846 		fillbytes(buf, 4, '\0');
847 		if (read_buffer(scgp, buf, 4, 0) >= 0 &&
848 		    scg_getresid(scgp) == 0) {
849 			physbufsize = a_to_u_3_byte(&buf[1]);
850 		}
851 		if (tsize > 0) {
852 			printf(_("Drive buf size : %lu = %lu KB\n"),
853 						tsize, tsize >> 10);
854 		}
855 		if (physbufsize > 0 && physbufsize != tsize) {
856 			printf(_("Drive pbuf size: %lu = %lu KB\n"),
857 					physbufsize, physbufsize >> 10);
858 		}
859 	}
860 	scgp->silent--;
861 
862 	dma_speed = get_dmaspeed(scgp, dp);
863 	if (dma_speed <= 0)
864 		errmsgno(EX_BAD, _("Warning: The DMA speed test has been skipped.\n"));
865 	if ((debug || lverbose) && dma_speed > 0) {
866 		/*
867 		 * We do not yet know what medium type is in...
868 		 */
869 		printf(_("Drive DMA Speed: %d kB/s %dx CD %dx DVD %dx BD\n"),
870 			dma_speed, dma_speed/176, dma_speed/1385,
871 			dma_speed/4495);
872 	}
873 	if ((tracks > 0 || cuefilename != NULL) && (debug || lverbose))
874 		printf(_("FIFO size      : %lu = %lu KB\n"), fs, fs >> 10);
875 
876 #ifdef	HAVE_LIB_EDC_ECC
877 	if ((flags & F_RAW) != 0 && (dp->cdr_dstat->ds_flags & DSF_NOCD) == 0)
878 		raw_speed = encspeed(debug || lverbose);
879 #endif
880 
881 	if ((flags & F_CHECKDRIVE) != 0)
882 		exit(0);
883 
884 	if (dp->cdr_flags2 & CDR2_NOCD) {
885 		for (i = 0; i < MAX_TRACK+2; i++)
886 			track[i].flags |= TI_NOCD;
887 
888 		if (flags & F_MULTI)  {
889 			if ((dp->cdr_flags & CDR_PACKET) == 0) {
890 				comerrno(EX_BAD,
891 				_("Drive does not support packet writing (needed for -multi).\n"));
892 			}
893 /*			flags &= F_TAO;*/
894 			flags |= F_SAO;
895 			dp->cdr_cmdflags = flags;
896 			for (i = 0; i < MAX_TRACK+2; i++) {
897 				track[i].flags &= ~TI_TAO;
898 				track[i].flags |= TI_SAO;
899 			}
900 		}
901 	}
902 
903 	if ((flags & F_ABORT) != 0) {
904 		/*
905 		 * flush cache is not supported by CD-ROMs avoid prob with -toc
906 		 */
907 		scgp->silent++;
908 		scsi_flush_cache(scgp, FALSE);
909 		(*dp->cdr_abort_session)(scgp, dp);
910 		scgp->silent--;
911 		exit(0);
912 	}
913 
914 	if (tracks == 0 && cuefilename == NULL &&
915 	    (flags & (F_FIX|F_BLANK)) == 0 && (flags & F_EJECT) != 0) {
916 		/*
917 		 * Do not check if the unit is ready here to allow to open
918 		 * an empty unit too.
919 		 */
920 		unload_media(scgp, dp, flags);
921 		exit(0);
922 	}
923 	flush();
924 
925 	if (cuefilename) {
926 		parsecue(cuefilename, track);
927 		tracks = track[0].tracks;
928 	} else {
929 		opentracks(track);
930 		tracks = track[0].tracks;
931 	}
932 
933 	if (tracks > 1)
934 		sleep(2);	/* Let the user watch the inquiry messages */
935 
936 	if (tracks > 0 && !check_wrmode(dp, flags, track[1].flags))
937 		comerrno(EX_BAD, _("Illegal write mode for this drive.\n"));
938 
939 	if ((track[0].flags & TI_TEXT) == 0 &&	/* CD-Text not yet processed */
940 	    (track[MAX_TRACK+1].flags & TI_TEXT) != 0) {
941 		/*
942 		 * CD-Text from textfile= or from CUE CDTEXTFILE will win
943 		 * over CD-Text from *.inf files and over CD-Text from
944 		 * CUE SONGWRITER, ...
945 		 */
946 		packtext(tracks, track);
947 		track[0].flags |= TI_TEXT;
948 	}
949 #ifdef	CLONE_WRITE
950 	if (flags & F_CLONE) {
951 		clone_toc(track);
952 		clone_tracktype(track);
953 	}
954 #endif
955 	setleadinout(tracks, track);
956 	set_trsizes(dp, tracks, track);
957 	setpregaps(tracks, track);
958 	checkfiles(tracks, track);
959 	tsize = checktsize(tracks, track);
960 
961 	/*
962 	 * Make wm2name[wrmode] work.
963 	 * This must be done after the track flags have been set up
964 	 * by the functions above.
965 	 */
966 	if (tracks == 0 && (flags & F_BLANK) != 0)
967 		dp->cdr_dstat->ds_wrmode = WM_BLANK;
968 	else if (tracks == 0 && (flags & F_FORMAT) != 0)
969 		dp->cdr_dstat->ds_wrmode = WM_FORMAT;
970 	else
971 		set_wrmode(dp, flags, track[1].flags);
972 
973 	/*
974 	 * Debug only
975 	 */
976 	{
977 		void	*cp = NULL;
978 
979 		(*dp->cdr_gen_cue)(track, &cp, FALSE);
980 		if (cp)
981 			free(cp);
982 	}
983 
984 	/*
985 	 * Create Lead-in data. Only needed in RAW mode.
986 	 */
987 	do_leadin(track);
988 
989 
990 	/*
991 	 * Install exit handler before we change the drive status.
992 	 */
993 	on_comerr(exscsi, &exargs);
994 
995 	if ((flags & F_FORCE) == 0)
996 		load_media(scgp, dp, TRUE);
997 
998 	if ((flags & (F_LOAD|F_DLCK)) != 0) {
999 		if ((flags & F_DLCK) == 0) {
1000 			scgp->silent++;		/* silently		*/
1001 			scsi_prevent_removal(
1002 				scgp, 0);	/* allow manual open	*/
1003 			scgp->silent--;		/* if load failed...	*/
1004 		}
1005 		exit(0);			/* we did not change status */
1006 	}
1007 	exargs.old_secsize = sense_secsize(scgp, 1);
1008 	if (exargs.old_secsize < 0)
1009 		exargs.old_secsize = sense_secsize(scgp, 0);
1010 	if (debug)
1011 		printf(_("Current Secsize: %d\n"), exargs.old_secsize);
1012 	scgp->silent++;
1013 	if (read_capacity(scgp) < 0) {
1014 		if (exargs.old_secsize > 0)
1015 			scgp->cap->c_bsize = exargs.old_secsize;
1016 	}
1017 	scgp->silent--;
1018 	if (exargs.old_secsize < 0)
1019 		exargs.old_secsize = scgp->cap->c_bsize;
1020 	if (exargs.old_secsize != scgp->cap->c_bsize)
1021 		errmsgno(EX_BAD, _("Warning: blockdesc secsize %d differs from cap secsize %d.\n"),
1022 				exargs.old_secsize, scgp->cap->c_bsize);
1023 
1024 	if (lverbose)
1025 		printf(_("Current Secsize: %d\n"), exargs.old_secsize);
1026 
1027 	if (exargs.old_secsize > 0 && exargs.old_secsize != DATA_SEC_SIZE) {
1028 		/*
1029 		 * Some drives (e.g. Plextor) don't like to write correctly
1030 		 * in SAO mode if the sector size is set to 512 bytes.
1031 		 * In addition, cdrecord -msinfo will not work properly
1032 		 * if the sector size is not 2048 bytes.
1033 		 */
1034 		set_secsize(scgp, DATA_SEC_SIZE);
1035 	}
1036 
1037 	/*
1038 	 * Is this the right place to do this ?
1039 	 */
1040 	check_recovery(scgp, dp, flags);
1041 
1042 /*audioread(dp, flags);*/
1043 /*unload_media(scgp, dp, flags);*/
1044 /*return 0;*/
1045 	if (flags & F_WRITE)
1046 		dp->cdr_dstat->ds_cdrflags |= RF_WRITE;
1047 	if (flags & F_BLANK)
1048 		dp->cdr_dstat->ds_cdrflags |= RF_BLANK;
1049 	if (flags & F_PRATIP || lverbose > 0) {
1050 		dp->cdr_dstat->ds_cdrflags |= RF_PRATIP;
1051 	}
1052 	if (flags & F_IMMED || dminbuf > 0) {
1053 		if (dminbuf <= 0)
1054 			dminbuf = 50;
1055 		if (lverbose <= 0)	/* XXX Hack needed for now */
1056 			lverbose++;
1057 		dp->cdr_dstat->ds_cdrflags |= RF_WR_WAIT;
1058 	}
1059 	if ((*dp->cdr_getdisktype)(scgp, dp) < 0) {
1060 		errmsgno(EX_BAD, _("Cannot get disk type.\n"));
1061 		if ((flags & F_FORCE) == 0)
1062 			comexit(EX_BAD);
1063 	}
1064 	if (flags & F_PRATIP) {
1065 		comexit(0);
1066 	}
1067 	if (cuefilename != 0 && (dp->cdr_dstat->ds_flags & DSF_NOCD) != 0)
1068 		comerrno(EX_BAD, _("Wrong media, the cuefile= option only works with CDs.\n"));
1069 	/*
1070 	 * The next actions should depend on the disk type.
1071 	 */
1072 	if (dma_speed > 0) {
1073 		if ((dp->cdr_dstat->ds_flags & DSF_BD) != 0)
1074 			dma_speed /= 4495;
1075 		else
1076 		if ((dp->cdr_dstat->ds_flags & DSF_DVD) == 0)
1077 			dma_speed /= 176;
1078 		else
1079 			dma_speed /= 1385;
1080 	}
1081 
1082 	/* BEGIN CSTYLED */
1083 	/*
1084 	 * Init drive to default modes:
1085 	 *
1086 	 * We set TAO unconditionally to make checkdsize() work
1087 	 * currectly in SAO mode too.
1088 	 *
1089 	 * At least MMC drives will not return the next writable
1090 	 * address we expect when the drive's write mode is set
1091 	 * to SAO. We need this address for mkisofs and thus
1092 	 * it must be the first user accessible sector and not the
1093 	 * first sector of the pregap.
1094 	 *
1095 	 * XXX The ACER drive:
1096 	 * XXX Vendor_info    : 'ATAPI   '
1097 	 * XXX Identifikation : 'CD-R/RW 8X4X32  '
1098 	 * XXX Revision       : '5.EW'
1099 	 * XXX Will not return from -dummy to non-dummy without
1100 	 * XXX opening the tray.
1101 	 */
1102 	/* END CSTYLED */
1103 	scgp->silent++;
1104 	if ((*dp->cdr_init)(scgp, dp) < 0)
1105 		comerrno(EX_BAD, _("Cannot init drive.\n"));
1106 	scgp->silent--;
1107 
1108 	if (flags & F_SETDROPTS) {
1109 		/*
1110 		 * Note that the set speed function also contains
1111 		 * drive option processing for speed related drive options.
1112 		 */
1113 		if ((*dp->cdr_opt1)(scgp, dp) < 0) {
1114 			errmsgno(EX_BAD, _("Cannot set up 1st set of driver options.\n"));
1115 		}
1116 		if ((*dp->cdr_set_speed_dummy)(scgp, dp, &speed) < 0) {
1117 			errmsgno(EX_BAD, _("Cannot set speed/dummy.\n"));
1118 		}
1119 		dp->cdr_dstat->ds_wspeed = speed; /* XXX Remove 'speed' in future */
1120 		if ((*dp->cdr_opt2)(scgp, dp) < 0) {
1121 			errmsgno(EX_BAD, _("Cannot set up 2nd set of driver options.\n"));
1122 		}
1123 		comexit(0);
1124 	}
1125 	/*
1126 	 * XXX If dp->cdr_opt1() ever affects the result for
1127 	 * XXX the multi session info we would need to move it here.
1128 	 */
1129 	if (flags & F_MEDIAINFO) {
1130 		(*dp->cdr_prdiskstatus)(scgp, dp);
1131 		comexit(0);
1132 	}
1133 	if (flags & F_MSINFO) {
1134 		print_msinfo(scgp, dp);
1135 		comexit(0);
1136 	}
1137 	if (flags & F_TOC) {
1138 		print_toc(scgp, dp);
1139 		comexit(0);
1140 	}
1141 	if ((flags & F_FORMAT) || (dp->cdr_dstat->ds_flags & DSF_NEED_FORMAT)) {
1142 		int	omode = dp->cdr_dstat->ds_wrmode;
1143 
1144 		dp->cdr_dstat->ds_wrmode = WM_FORMAT;
1145 		if (lverbose) {
1146 			printf(_("Format was %sneeded.\n"),
1147 			(dp->cdr_dstat->ds_flags & DSF_NEED_FORMAT) ? "" : _("not "));
1148 		}
1149 		/*
1150 		 * XXX Sollte hier (*dp->cdr_set_speed_dummy)() hin?
1151 		 */
1152 		if (gracewait(dp, &gracedone) < 0) {
1153 			/*
1154 			 * In case kill() did not work ;-)
1155 			 */
1156 			errs++;
1157 			goto restore_it;
1158 		}
1159 
1160 		wait_unit_ready(scgp, 120);
1161 		if (gettimeofday(&starttime, (struct timezone *)0) < 0)
1162 			errmsg(_("Cannot get start time.\n"));
1163 
1164 		if ((*dp->cdr_format)(scgp, dp, 0) < 0) {
1165 			errmsgno(EX_BAD, _("Cannot format medium.\n"));
1166 			comexit(EX_BAD);
1167 		}
1168 
1169 		if (gettimeofday(&fixtime, (struct timezone *)0) < 0)
1170 			errmsg(_("Cannot get format time.\n"));
1171 		if (lverbose)
1172 			prtimediff(_("Formatting time: "), &starttime, &fixtime);
1173 
1174 		if (!wait_unit_ready(scgp, 240) || tracks == 0) {
1175 			comexit(0);
1176 		}
1177 		dp->cdr_dstat->ds_wrmode = omode;
1178 
1179 		if (tracks > 0) {
1180 			int	cdrflags = dp->cdr_dstat->ds_cdrflags;
1181 
1182 			dp->cdr_dstat->ds_cdrflags &= ~RF_PRATIP;
1183 			if ((*dp->cdr_getdisktype)(scgp, dp) < 0) {
1184 				errmsgno(EX_BAD, _("Cannot get disk type.\n"));
1185 				if ((flags & F_FORCE) == 0)
1186 					comexit(EX_BAD);
1187 			}
1188 			dp->cdr_dstat->ds_cdrflags = cdrflags;
1189 		}
1190 	}
1191 
1192 #ifdef	XXX
1193 	if ((*dp->cdr_check_session)() < 0) {
1194 		comexit(EX_BAD);
1195 	}
1196 #endif
1197 	{
1198 		Int32_t omb = dp->cdr_dstat->ds_maxblocks;
1199 
1200 		if ((*dp->cdr_opt1)(scgp, dp) < 0) {
1201 			errmsgno(EX_BAD, _("Cannot set up 1st set of driver options.\n"));
1202 		}
1203 		if (tsize > 0 && omb != dp->cdr_dstat->ds_maxblocks) {
1204 			printf(_("Disk size changed by user options.\n"));
1205 			printf(_("Checking disk capacity according to new values.\n"));
1206 		}
1207 	}
1208 	if (tsize == 0) {
1209 		if (tracks > 0) {
1210 			errmsgno(EX_BAD,
1211 			_("WARNING: Total disk size unknown. Data may not fit on disk.\n"));
1212 		}
1213 	} else if (tracks > 0) {
1214 		/*
1215 		 * XXX How do we let the user check the remaining
1216 		 * XXX disk size witout starting the write process?
1217 		 */
1218 		if (((flags & F_BLANK) == 0) &&
1219 		    !checkdsize(scgp, dp, tsize, flags))
1220 			comexit(EX_BAD);
1221 	}
1222 	if (tracks > 0 && fs > 0L) {
1223 #if defined(USE_POSIX_PRIORITY_SCHEDULING) && defined(HAVE_SETREUID)
1224 		/*
1225 		 * Hack to work around the POSIX design bug in real time
1226 		 * priority handling: we need to be root even to lower
1227 		 * our priority.
1228 		 * Note that we need to find a more general way that works
1229 		 * even on OS that do not support setreuid() which is *BSD
1230 		 * and SUSv3 only.
1231 		 */
1232 		if (oeuid != getuid()) {
1233 			if (setreuid(-1, oeuid) < 0)
1234 				errmsg(_("Could set back effective uid.\n"));
1235 		}
1236 #endif
1237 		/*
1238 		 * Hack to support DVD+R/DL and the firmware problems
1239 		 * for BD-R found in the Lite-ON BD B LH-2B1S/AL09
1240 		 */
1241 		if (get_mediatype(scgp) >= MT_DVD) {
1242 			int	bls = get_blf(get_mediatype(scgp));
1243 			long	nbs;
1244 
1245 			bls *= 2048;			/* Count in bytes */
1246 			nbs = bufsize / bls * bls;
1247 			if (nbs == 0) {
1248 				for (nbs = bls; nbs > 2048; nbs /= 2)
1249 					if (nbs <= bufsize)
1250 						break;
1251 			}
1252 			if (nbs != bufsize) {
1253 				if (lverbose) {
1254 					printf(
1255 					_("Reducing transfer size from %ld to %ld bytes.\n"),
1256 									bufsize, nbs);
1257 				}
1258 				bufsize = nbs;
1259 				set_trsizes(dp, tracks, track);
1260 			}
1261 		}
1262 		/*
1263 		 * fork() here to start the extra process needed for
1264 		 * improved buffering.
1265 		 */
1266 		if (!init_faio(track, bufsize))
1267 			fs = 0L;
1268 		else
1269 			on_comerr(excdr, &exargs); /* Will be called first */
1270 
1271 #if defined(USE_POSIX_PRIORITY_SCHEDULING) && defined(HAVE_SETREUID)
1272 		/*
1273 		 * XXX Below this point we never need root privilleges anymore.
1274 		 */
1275 		if (geteuid() != getuid()) {	/* AIX does not like to do this */
1276 						/* If we are not root		*/
1277 			if (setreuid(-1, getuid()) < 0)
1278 				comerr(_("Panic cannot set back effective uid.\n"));
1279 		}
1280 #endif
1281 	}
1282 	if ((*dp->cdr_set_speed_dummy)(scgp, dp, &speed) < 0) {
1283 		errmsgno(EX_BAD, _("Cannot set speed/dummy.\n"));
1284 		if ((flags & F_FORCE) == 0)
1285 			comexit(EX_BAD);
1286 	}
1287 	dp->cdr_dstat->ds_wspeed = speed; /* XXX Remove 'speed' in future */
1288 	if ((flags & F_WRITE) != 0 && raw_speed >= 0) {
1289 		int	max_raw = (flags & F_FORCE) != 0 ? raw_speed:raw_speed/2;
1290 
1291 		if (getenv("CDR_FORCERAWSPEED")) {
1292 			errmsgno(EX_BAD,
1293 			_("WARNING: 'CDR_FORCERAWSPEED=' is set, buffer underruns may occur.\n"));
1294 			max_raw = raw_speed;
1295 		}
1296 
1297 		for (i = 1; i <= MAX_TRACK; i++) {
1298 			/*
1299 			 * Check for Clone tracks
1300 			 */
1301 			if ((track[i].sectype & ST_MODE_RAW) != 0)
1302 				continue;
1303 			/*
1304 			 * Check for non-data tracks
1305 			 */
1306 			if ((track[i].sectype & ST_MODE_MASK) == ST_MODE_AUDIO)
1307 				continue;
1308 
1309 			if (speed > max_raw) {
1310 				errmsgno(EX_BAD,
1311 				_("Processor too slow. Cannot write RAW data at speed %d.\n"),
1312 				speed);
1313 				comerrno(EX_BAD, _("Max RAW data speed on this processor is %d.\n"),
1314 				max_raw);
1315 			}
1316 			break;
1317 		}
1318 	}
1319 	if (tracks > 0 && (flags & F_WRITE) != 0 && dma_speed > 0) {
1320 		int	max_dma = (flags & F_FORCE) != 0 ? dma_speed:(dma_speed+1)*4/5;
1321 		char	*p = NULL;
1322 
1323 		if ((p = getenv("CDR_FORCESPEED")) != NULL) {
1324 			if ((dp->cdr_dstat->ds_cdrflags & RF_BURNFREE) == 0) {
1325 				errmsgno(EX_BAD,
1326 				_("WARNING: 'CDR_FORCESPEED=' is set.\n"));
1327 				errmsgno(EX_BAD,
1328 				_("WARNING: Use 'driveropts=burnfree' to avoid buffer underuns.\n"));
1329 			}
1330 			max_dma = dma_speed;
1331 		}
1332 
1333 		if (speed > max_dma) {
1334 			errmsgno(EX_BAD,
1335 			_("DMA speed too slow (OK for %dx). Cannot write at speed %dx.\n"),
1336 					max_dma, speed);
1337 			if ((dp->cdr_dstat->ds_cdrflags & RF_BURNFREE) == 0) {
1338 				errmsgno(EX_BAD, _("Max DMA data speed is %d.\n"), max_dma);
1339 				if (p == NULL || !streql(p, "any"))
1340 					comerrno(EX_BAD, _("Try to use 'driveropts=burnfree'.\n"));
1341 			}
1342 		}
1343 	}
1344 	if ((flags & (F_WRITE|F_BLANK)) != 0 &&
1345 				(dp->cdr_dstat->ds_flags & DSF_ERA) != 0) {
1346 		if (xdebug) {
1347 			printf(_("Current speed %d, medium low speed: %d medium high speed: %d\n"),
1348 				speed,
1349 				dp->cdr_dstat->ds_at_min_speed,
1350 				dp->cdr_dstat->ds_at_max_speed);
1351 		}
1352 		if (dp->cdr_dstat->ds_at_max_speed > 0 &&
1353 				speed <= 8 &&
1354 				speed > (int)dp->cdr_dstat->ds_at_max_speed) {
1355 			/*
1356 			 * Be careful here: 10x media may be written faster.
1357 			 * The current code will work as long as there is no
1358 			 * writer that can only write faster than 8x
1359 			 */
1360 			if ((flags & F_FORCE) == 0) {
1361 				errmsgno(EX_BAD,
1362 				_("Write speed %d of medium not sufficient for this writer.\n"),
1363 					dp->cdr_dstat->ds_at_max_speed);
1364 				comerrno(EX_BAD,
1365 				_("You may have used an ultra low speed medium on a high speed writer.\n"));
1366 			}
1367 		}
1368 
1369 		if ((dp->cdr_dstat->ds_flags & DSF_ULTRASPP_ERA) != 0 &&
1370 		    (speed < 16 || (dp->cdr_cdrw_support & CDR_CDRW_ULTRAP) == 0)) {
1371 			if ((dp->cdr_cdrw_support & CDR_CDRW_ULTRAP) == 0) {
1372 				comerrno(EX_BAD,
1373 				/* CSTYLED */
1374 				_("Trying to use ultra high speed+ medium on a writer which is not\ncompatible with ultra high speed+ media.\n"));
1375 			} else if ((flags & F_FORCE) == 0) {
1376 				comerrno(EX_BAD,
1377 				_("Probably trying to use ultra high speed+ medium on improper writer.\n"));
1378 			}
1379 		} else if ((dp->cdr_dstat->ds_flags & DSF_ULTRASP_ERA) != 0 &&
1380 		    (speed < 10 || (dp->cdr_cdrw_support & CDR_CDRW_ULTRA) == 0)) {
1381 			if ((dp->cdr_cdrw_support & CDR_CDRW_ULTRA) == 0) {
1382 				comerrno(EX_BAD,
1383 				/* CSTYLED */
1384 				_("Trying to use ultra high speed medium on a writer which is not\ncompatible with ultra high speed media.\n"));
1385 			} else if ((flags & F_FORCE) == 0) {
1386 				comerrno(EX_BAD,
1387 				_("Probably trying to use ultra high speed medium on improper writer.\n"));
1388 			}
1389 		}
1390 		if (dp->cdr_dstat->ds_at_min_speed >= 4 &&
1391 				dp->cdr_dstat->ds_at_max_speed > 4 &&
1392 				dp->cdr_dstat->ds_dr_max_wspeed <= 4) {
1393 			if ((flags & F_FORCE) == 0) {
1394 				comerrno(EX_BAD,
1395 				_("Trying to use high speed medium on low speed writer.\n"));
1396 			}
1397 		}
1398 		if ((int)dp->cdr_dstat->ds_at_min_speed > speed) {
1399 			if ((flags & F_FORCE) == 0) {
1400 				errmsgno(EX_BAD,
1401 				_("Write speed %d of writer not sufficient for this medium.\n"),
1402 					speed);
1403 				errmsgno(EX_BAD,
1404 				_("You did use a %s speed medium on an improper writer or\n"),
1405 				dp->cdr_dstat->ds_flags & DSF_ULTRASP_ERA ?
1406 				"ultra high": "high");
1407 				comerrno(EX_BAD,
1408 				_("you used a speed=# option with a speed too low for this medium.\n"));
1409 			}
1410 		}
1411 	}
1412 	if ((flags & (F_BLANK|F_FORCE)) == (F_BLANK|F_FORCE)) {
1413 		/*
1414 		 * This is a first "blind" blanking attempt.
1415 		 */
1416 		printf(_("Waiting for drive to calm down.\n"));
1417 		wait_unit_ready(scgp, 120);
1418 		if (gracewait(dp, &gracedone) < 0) {
1419 			/*
1420 			 * In case kill() did not work ;-)
1421 			 */
1422 			errs++;
1423 			goto restore_it;
1424 		}
1425 		scsi_blank(scgp, 0L, blanktype, FALSE);
1426 	}
1427 
1428 	/*
1429 	 * Last chance to quit!
1430 	 */
1431 	if (gracewait(dp, &gracedone) < 0) {
1432 		/*
1433 		 * In case kill() did not work ;-)
1434 		 */
1435 		errs++;
1436 		goto restore_it;
1437 	}
1438 	if (tracks > 0 && fs > 0L) {
1439 		/*
1440 		 * Wait for the read-buffer to become full.
1441 		 * This should be take no extra time if the input is a file.
1442 		 * If the input is a pipe (e.g. mkisofs) this can take a
1443 		 * while. If mkisofs dumps core before it starts writing,
1444 		 * we abort before the writing process started.
1445 		 */
1446 		if (!await_faio()) {
1447 			comerrno(EX_BAD, _("Input buffer error, aborting.\n"));
1448 		}
1449 	}
1450 	wait_unit_ready(scgp, 120);
1451 
1452 	starttime.tv_sec = 0;
1453 	wstarttime.tv_sec = 0;
1454 	stoptime.tv_sec = 0;
1455 	fixtime.tv_sec = 0;
1456 	if (gettimeofday(&starttime, (struct timezone *)0) < 0)
1457 		errmsg(_("Cannot get start time.\n"));
1458 
1459 	/*
1460 	 * Blank the media if we were requested to do so
1461 	 */
1462 	if (flags & F_BLANK) {
1463 		/*
1464 		 * Do not abort if OPC failes. Just give it a chance
1465 		 * for better laser power calibration than without OPC.
1466 		 *
1467 		 * Ricoh drives return with a vendor unique sense code.
1468 		 * This is most likely because they refuse to do OPC
1469 		 * on a non blank media.
1470 		 */
1471 		scgp->silent++;
1472 		do_opc(scgp, dp, flags);
1473 		scgp->silent--;
1474 		wait_unit_ready(scgp, 120);
1475 		if (gettimeofday(&starttime, (struct timezone *)0) < 0)
1476 			errmsg(_("Cannot get start time.\n"));
1477 
1478 		if ((*dp->cdr_blank)(scgp, dp, 0L, blanktype) < 0) {
1479 			errmsgno(EX_BAD, _("Cannot blank disk, aborting.\n"));
1480 			if (blanktype != BLANK_DISC) {
1481 				errmsgno(EX_BAD, _("Some drives do not support all blank types.\n"));
1482 				errmsgno(EX_BAD, _("Try again with cdrecord blank=all.\n"));
1483 			}
1484 			comexit(EX_BAD);
1485 		}
1486 		if (gettimeofday(&fixtime, (struct timezone *)0) < 0)
1487 			errmsg(_("Cannot get blank time.\n"));
1488 		if (lverbose)
1489 			prtimediff(_("Blanking time: "), &starttime, &fixtime);
1490 
1491 		/*
1492 		 * XXX Erst blank und dann format?
1493 		 * XXX Wenn ja, dann hier (flags & F_FORMAT) testen
1494 		 */
1495 		if (!wait_unit_ready(scgp, 240) || tracks == 0) {
1496 			comexit(0);
1497 		}
1498 		if (tracks > 0) {
1499 			int	cdrflags = dp->cdr_dstat->ds_cdrflags;
1500 
1501 			dp->cdr_dstat->ds_cdrflags &= ~RF_PRATIP;
1502 			if ((*dp->cdr_getdisktype)(scgp, dp) < 0) {
1503 				errmsgno(EX_BAD, _("Cannot get disk type.\n"));
1504 				if ((flags & F_FORCE) == 0)
1505 					comexit(EX_BAD);
1506 			}
1507 			if (!checkdsize(scgp, dp, tsize, flags))
1508 				comexit(EX_BAD);
1509 
1510 			dp->cdr_dstat->ds_cdrflags = cdrflags;
1511 		}
1512 		/*
1513 		 * Reset start time so we will not see blanking time and
1514 		 * writing time counted together.
1515 		 */
1516 		if (gettimeofday(&starttime, (struct timezone *)0) < 0)
1517 			errmsg(_("Cannot get start time.\n"));
1518 	}
1519 	if (tracks == 0 && (flags & F_FIX) == 0)
1520 		comerrno(EX_BAD, _("No tracks found.\n"));
1521 
1522 	/*
1523 	 * Get the number of last recorded track by reading the CD TOC.
1524 	 * As we start with track[0] (Lead In) and track[1] is the first
1525 	 * recordable tack in track[i], we get the right track numbers.
1526 	 * This will not allow to write DVDs with more than 100 sessions.
1527 	 */
1528 	scgp->silent++;
1529 	if (read_tochdr(scgp, dp, NULL, &trackno) < 0) {
1530 		trackno = 0;
1531 	}
1532 	scgp->silent--;
1533 	if ((tracks + trackno) > MAX_TRACK) {
1534 		/*
1535 		 * XXX How many tracks are allowed on a DVD -> 1024
1536 		 */
1537 		comerrno(EX_BAD, _("Too many tracks for this disk, last track number is %d.\n"),
1538 				tracks + trackno);
1539 	}
1540 
1541 	for (i = 0; i <= tracks+1; i++) {	/* Lead-in ... Lead-out */
1542 		track[i].trackno = i + trackno;	/* Set up real track #	*/
1543 		/*
1544 		 * As long as we implement virtual tracks for DVDs/BDs
1545 		 * and do not allow to write more than track at once,
1546 		 * we simply set all "trackno" entries to the next trackno.
1547 		 */
1548 		if ((dp->cdr_flags2 & CDR2_NOCD) && i > 0)
1549 			track[i].trackno = trackno + 1;
1550 	}
1551 
1552 	if ((*dp->cdr_opt2)(scgp, dp) < 0) {
1553 		errmsgno(EX_BAD, _("Cannot set up 2nd set of driver options.\n"));
1554 	}
1555 
1556 	/*
1557 	 * Now we actually start writing to the CD/DVD/BD.
1558 	 * XXX Check total size of the tracks and remaining size of disk.
1559 	 */
1560 	if ((*dp->cdr_open_session)(scgp, dp, track) < 0) {
1561 		comerrno(EX_BAD, _("Cannot open new session.\n"));
1562 	}
1563 	if (!do_opc(scgp, dp, flags))
1564 		comexit(EX_BAD);
1565 
1566 	/*
1567 	 * As long as open_session() will do nothing but
1568 	 * set up parameters, we may leave fix_it here.
1569 	 * I case we have to add an open_session() for a drive
1570 	 * that wants to do something that modifies the disk
1571 	 * We have to think about a new solution.
1572 	 */
1573 	if (flags & F_FIX)
1574 		goto fix_it;
1575 
1576 	/*
1577 	 * This call may modify trackp[i].trackstart for all tracks.
1578 	 */
1579 	if ((*dp->cdr_write_leadin)(scgp, dp, track) < 0)
1580 		comerrno(EX_BAD, _("Could not write Lead-in.\n"));
1581 
1582 	if (lverbose && (dp->cdr_dstat->ds_cdrflags & RF_LEADIN) != 0) {
1583 
1584 		if (gettimeofday(&fixtime, (struct timezone *)0) < 0)
1585 			errmsg(_("Cannot get lead-in write time.\n"));
1586 		prtimediff(_("Lead-in write time: "), &starttime, &fixtime);
1587 	}
1588 
1589 	if (gettimeofday(&wstarttime, (struct timezone *)0) < 0)
1590 		errmsg(_("Cannot get start time.\n"));
1591 	for (i = 1; i <= tracks; i++) {
1592 		startsec = 0L;
1593 
1594 		if ((*dp->cdr_open_track)(scgp, dp, &track[i]) < 0) {
1595 			errmsgno(EX_BAD, _("Cannot open next track.\n"));
1596 			/*
1597 			 * XXX We should try to avoid to fixate unwritten media
1598 			 * XXX e.g. when opening track 1 fails, but then we
1599 			 * XXX would need to keep track of whether the media
1600 			 * XXX was written yet. This could be done in *dp.
1601 			 */
1602 			errs++;
1603 			break;
1604 		}
1605 
1606 		/*
1607 		 * Do not change the next writable address in DAO & RAW mode.
1608 		 * XXX We should check whether this is still OK.
1609 		 * Definitely get next writable address it in case of multi session.
1610 		 */
1611 		if ((flags & (F_SAO|F_RAW)) == 0 ||
1612 		    ((dp->cdr_dstat->ds_flags & DSF_DVD) &&
1613 		    (flags & F_MULTI) != 0)) {
1614 			if ((*dp->cdr_next_wr_address)(scgp, &track[i], &startsec) < 0) {
1615 				errmsgno(EX_BAD, _("Cannot get next writable address.\n"));
1616 				errs++;
1617 				break;
1618 			}
1619 			track[i].trackstart = startsec;
1620 		}
1621 		if (debug || lverbose) {
1622 			if (track[i].trackno != track[i-1].trackno)
1623 				printf(_("Starting new track at sector: %ld\n"),
1624 						track[i].trackstart);
1625 			else
1626 				printf(_("Continuing track at sector: %ld\n"),
1627 						track[i].trackstart);
1628 			flush();
1629 		}
1630 		if (write_track_data(scgp, dp, &track[i]) < 0) {
1631 			if (cdr_underrun(scgp)) {
1632 				errmsgno(EX_BAD,
1633 				_("The current problem looks like a buffer underrun.\n"));
1634 				if ((dp->cdr_dstat->ds_cdrflags & RF_BURNFREE) == 0)
1635 					errmsgno(EX_BAD,
1636 				_("Try to use 'driveropts=burnfree'.\n"));
1637 				else {
1638 					errmsgno(EX_BAD,
1639 				_("It looks like 'driveropts=burnfree' does not work for this drive.\n"));
1640 					errmsgno(EX_BAD, _("Please report.\n"));
1641 				}
1642 
1643 				errmsgno(EX_BAD,
1644 				_("Make sure that you are root, enable DMA and check your HW/OS set up.\n"));
1645 			} else {
1646 				errmsgno(EX_BAD, _("A write error occured.\n"));
1647 				errmsgno(EX_BAD, _("Please properly read the error message above.\n"));
1648 			}
1649 			errs++;
1650 			sleep(5);
1651 			unit_ready(scgp);
1652 			(*dp->cdr_close_track)(scgp, dp, &track[i]);
1653 			break;
1654 		}
1655 		if ((*dp->cdr_close_track)(scgp, dp, &track[i]) < 0) {
1656 			/*
1657 			 * Check for "Dummy blocks added" message first.
1658 			 */
1659 			if (scg_sense_key(scgp) != SC_ILLEGAL_REQUEST ||
1660 					scg_sense_code(scgp) != 0xB5) {
1661 				errmsgno(EX_BAD, _("Cannot close track.\n"));
1662 				errs++;
1663 				break;
1664 			}
1665 		}
1666 	}
1667 fix_it:
1668 	if (gettimeofday(&stoptime, (struct timezone *)0) < 0)
1669 		errmsg(_("Cannot get stop time.\n"));
1670 	cdrstats(dp);
1671 
1672 	if (flags & F_RAW) {
1673 		if (lverbose) {
1674 			printf(_("Writing Leadout...\n"));
1675 			flush();
1676 		}
1677 		write_leadout(scgp, dp, track);
1678 	}
1679 	if ((flags & F_NOFIX) == 0) {
1680 		if (lverbose) {
1681 			printf(_("Fixating...\n"));
1682 			flush();
1683 		}
1684 		if ((*dp->cdr_fixate)(scgp, dp, track) < 0) {
1685 			/*
1686 			 * Ignore fixating errors in dummy mode.
1687 			 */
1688 			if ((flags & F_DUMMY) == 0) {
1689 				errmsgno(EX_BAD, _("Cannot fixate disk.\n"));
1690 				errs++;
1691 			}
1692 		}
1693 		if (gettimeofday(&fixtime, (struct timezone *)0) < 0)
1694 			errmsg(_("Cannot get fix time.\n"));
1695 		if (lverbose)
1696 			prtimediff(_("Fixating time: "), &stoptime, &fixtime);
1697 	}
1698 	if ((dp->cdr_dstat->ds_cdrflags & RF_DID_CDRSTAT) == 0) {
1699 		dp->cdr_dstat->ds_cdrflags |= RF_DID_CDRSTAT;
1700 		(*dp->cdr_stats)(scgp, dp);
1701 	}
1702 	if ((flags & (F_RAW|F_EJECT)) == F_RAW) {
1703 		/*
1704 		 * Most drives seem to forget to reread the TOC from disk
1705 		 * if they are in RAW mode.
1706 		 */
1707 		scgp->silent++;
1708 		if (read_tochdr(scgp, dp, NULL, NULL) < 0) {
1709 			scgp->silent--;
1710 			if ((flags & F_DUMMY) == 0)
1711 				reload_media(scgp, dp);
1712 		} else {
1713 			scgp->silent--;
1714 		}
1715 	}
1716 
1717 restore_it:
1718 	/*
1719 	 * Try to restore the old sector size and stop FIFO.
1720 	 */
1721 	comexit(errs?-2:0);
1722 	return (0);
1723 }
1724 
1725 LOCAL void
scg_openerr(errstr)1726 scg_openerr(errstr)
1727 	char	*errstr;
1728 {
1729 	errmsg(_("%s%sCannot open or use SCSI driver.\n"), errstr, errstr[0]?". ":"");
1730 	errmsgno(EX_BAD, _("For possible targets try 'cdrecord -scanbus'.%s\n"),
1731 				geteuid() ? _(" Make sure you are root."):"");
1732 	errmsgno(EX_BAD, _("For possible transport specifiers try 'cdrecord dev=help'.\n"));
1733 	exit(EX_BAD);
1734 }
1735 
1736 LOCAL int
find_drive(scgp,dev,flags)1737 find_drive(scgp, dev, flags)
1738 	SCSI	*scgp;
1739 	char	*dev;
1740 	int	flags;
1741 {
1742 	int	ntarget;
1743 
1744 	if ((flags & F_MSINFO) == 0)
1745 		error(_("No target specified, trying to find one...\n"));
1746 	ntarget = find_target(scgp, INQ_ROMD, -1);
1747 	if (ntarget < 0)
1748 		return (ntarget);
1749 	if (ntarget == 1) {
1750 		/*
1751 		 * Simple case, exactly one CD-ROM found.
1752 		 */
1753 		find_target(scgp, INQ_ROMD, 1);
1754 	} else if (ntarget <= 0 && (ntarget = find_target(scgp, INQ_WORM, -1)) == 1) {
1755 		/*
1756 		 * Exactly one CD-ROM acting as WORM found.
1757 		 */
1758 		find_target(scgp, INQ_WORM, 1);
1759 	} else if (ntarget <= 0) {
1760 		/*
1761 		 * No single CD-ROM or WORM found.
1762 		 */
1763 		errmsgno(EX_BAD, _("No CD/DVD/BD-Recorder target found.\n"));
1764 		errmsgno(EX_BAD, _("Your platform may not allow to scan for SCSI devices.\n"));
1765 		comerrno(EX_BAD, _("Call 'cdrecord dev=help' or ask your sysadmin for possible targets.\n"));
1766 	} else {
1767 		errmsgno(EX_BAD, _("Too many CD/DVD/BD-Recorder targets found.\n"));
1768 		select_target(scgp, stdout);
1769 		comerrno(EX_BAD, _("Select a target from the list above and use 'cdrecord dev=%s%sb,t,l'.\n"),
1770 			dev?dev:"", dev?(dev[strlen(dev)-1] == ':'?"":":"):"");
1771 	}
1772 	if ((flags & F_MSINFO) == 0)
1773 		error(_("Using dev=%s%s%d,%d,%d.\n"),
1774 			dev?dev:"", dev?(dev[strlen(dev)-1] == ':'?"":":"):"",
1775 			scg_scsibus(scgp), scg_target(scgp), scg_lun(scgp));
1776 
1777 	return (ntarget);
1778 }
1779 
1780 LOCAL int
gracewait(dp,didgracep)1781 gracewait(dp, didgracep)
1782 	cdr_t	*dp;
1783 	BOOL	*didgracep;
1784 {
1785 	int	i;
1786 	BOOL	didgrace = FALSE;
1787 
1788 	if (didgracep)
1789 		didgrace = *didgracep;
1790 
1791 	if (gracetime < MIN_GRACE_TIME)
1792 		gracetime = MIN_GRACE_TIME;
1793 	if (gracetime > 999)
1794 		gracetime = 999;
1795 
1796 	printf(_("Starting to write CD/DVD/BD at speed %d in %s%s %s mode for %s session.\n"),
1797 		(int)dp->cdr_dstat->ds_wspeed,
1798 		(dp->cdr_cmdflags & F_DUMMY) ? _("dummy") : _("real"),
1799 		(dp->cdr_cmdflags & F_FORCE) ? _(" force") : "",
1800 		wm2name[dp->cdr_dstat->ds_wrmode],
1801 		(dp->cdr_cmdflags & F_MULTI) ? _("multi") : _("single"));
1802 	if (didgrace) {
1803 		printf(_("No chance to quit anymore."));
1804 		goto grace_done;
1805 	}
1806 	printf(_("Last chance to quit, starting %s write in %d seconds."),
1807 		(dp->cdr_cmdflags & F_DUMMY)?_("dummy"):_("real"), gracetime);
1808 	flush();
1809 #ifdef	SIGINT
1810 	signal(SIGINT, intr);
1811 #endif
1812 #ifdef	SIGHUP
1813 	signal(SIGHUP, intr);
1814 #endif
1815 #ifdef	SIGTERM
1816 	signal(SIGTERM, intr);
1817 #endif
1818 	/*
1819 	 * Note to people who like to change this: I am geting patch requests
1820 	 * for an option to reduce the grace_time two times a year. I am not
1821 	 * willing to change things with respect to grace_time because it would
1822 	 * not reduce the needed time in a significant amount and because it
1823 	 * would break other things.
1824 	 */
1825 
1826 	for (i = gracetime; --i >= 0; ) {
1827 		sleep(1);
1828 		if (didintr) {
1829 			printf("\n");
1830 #ifdef	SIGINT
1831 			excdr(SIGINT, &exargs);
1832 			signal(SIGINT, SIG_DFL);
1833 #ifdef	HAVE_KILL
1834 			kill(getpid(), SIGINT);
1835 #endif
1836 #endif
1837 			/*
1838 			 * In case kill() did not work ;-)
1839 			 */
1840 			if (didgracep)
1841 				*didgracep = FALSE;
1842 			return (-1);
1843 		}
1844 		printf(_("\b\b\b\b\b\b\b\b\b\b\b\b\b%4d seconds."), i);
1845 		flush();
1846 	}
1847 grace_done:
1848 	printf(_(" Operation starts."));
1849 	flush();
1850 #ifdef	SIGINT
1851 	signal(SIGINT, SIG_DFL);
1852 #endif
1853 #ifdef	SIGHUP
1854 	signal(SIGHUP, SIG_DFL);
1855 #endif
1856 #ifdef	SIGTERM
1857 	signal(SIGTERM, SIG_DFL);
1858 #endif
1859 #ifdef	SIGINT
1860 	signal(SIGINT, intfifo);
1861 #endif
1862 #ifdef	SIGHUP
1863 	signal(SIGHUP, intfifo);
1864 #endif
1865 #ifdef	SIGTERM
1866 	signal(SIGTERM, intfifo);
1867 #endif
1868 	printf("\n");
1869 
1870 	if (didgracep)
1871 		*didgracep = TRUE;
1872 	return (0);
1873 }
1874 
1875 LOCAL void
cdrstats(dp)1876 cdrstats(dp)
1877 	cdr_t	*dp;
1878 {
1879 	float	secsps = 75.0;
1880 	int	nsecs;
1881 	float	fspeed;
1882 	struct timeval	tcur;
1883 	struct timeval	tlast;
1884 	BOOL	nostop = FALSE;
1885 
1886 	if (starttime.tv_sec == 0)
1887 		return;
1888 
1889 	if (stoptime.tv_sec == 0) {
1890 		gettimeofday(&stoptime, (struct timezone *)0);
1891 		nostop = TRUE;
1892 	}
1893 
1894 	if ((dp->cdr_dstat->ds_cdrflags & RF_DID_STAT) != 0)
1895 		return;
1896 	dp->cdr_dstat->ds_cdrflags |= RF_DID_STAT;
1897 
1898 	if (lverbose == 0)
1899 		return;
1900 
1901 	if (dp->cdr_cmdflags & F_FIX)
1902 		return;
1903 
1904 	if ((dp->cdr_cmdflags & (F_WRITE|F_BLANK)) == F_BLANK)
1905 		return;
1906 
1907 	tlast = wstarttime;
1908 	tcur = stoptime;
1909 
1910 	prtimediff(_("Writing  time: "), &starttime, &stoptime);
1911 
1912 	nsecs = dp->cdr_dstat->ds_endsec - dp->cdr_dstat->ds_startsec;
1913 
1914 	if (dp->cdr_dstat->ds_flags & DSF_DVD)
1915 		secsps = 676.27;
1916 	if (dp->cdr_dstat->ds_flags & DSF_BD)
1917 		secsps = 2195.07;
1918 
1919 	tlast.tv_sec = tcur.tv_sec - tlast.tv_sec;
1920 	tlast.tv_usec = tcur.tv_usec - tlast.tv_usec;
1921 	while (tlast.tv_usec < 0) {
1922 		tlast.tv_usec += 1000000;
1923 		tlast.tv_sec -= 1;
1924 	}
1925 	if (!nostop && nsecs != 0 && dp->cdr_dstat->ds_endsec > 0) {
1926 		/*
1927 		 * May not be known (e.g. cdrecord -)
1928 		 *
1929 		 * XXX if we later allow this code to know how much has
1930 		 * XXX actually been written, then we may remove the
1931 		 * XXX dependance from nostop & nsecs != 0
1932 		 */
1933 		fspeed = (nsecs / secsps) /
1934 			(tlast.tv_sec * 1.0 + tlast.tv_usec * 0.000001);
1935 		if (fspeed > 999.0)
1936 			fspeed = 999.0;
1937 		printf(_("Average write speed %5.1fx.\n"), fspeed);
1938 	}
1939 
1940 	if (dp->cdr_dstat->ds_minbuf <= 100) {
1941 		printf(_("Min drive buffer fill was %u%%\n"),
1942 			(unsigned int)dp->cdr_dstat->ds_minbuf);
1943 	}
1944 	if (dp->cdr_dstat->ds_buflow > 0) {
1945 		printf(_("Total of %ld possible drive buffer underruns predicted.\n"),
1946 			(long)dp->cdr_dstat->ds_buflow);
1947 	}
1948 }
1949 
1950 /*
1951  * Short usage
1952  */
1953 LOCAL void
susage(ret)1954 susage(ret)
1955 	int	ret;
1956 {
1957 	error(_("Usage: %s [options] track1...trackn\n"), get_progname());
1958 	error(_("\nUse\t%s -help\n"), get_progname());
1959 	error(_("to get a list of valid options.\n"));
1960 	error(_("\nUse\t%s blank=help\n"), get_progname());
1961 	error(_("to get a list of valid blanking options.\n"));
1962 	error(_("\nUse\t%s dev=b,t,l driveropts=help -checkdrive\n"), get_progname());
1963 	error(_("to get a list of drive specific options.\n"));
1964 	error(_("\nUse\t%s dev=help\n"), get_progname());
1965 	error(_("to get a list of possible SCSI transport specifiers.\n"));
1966 	exit(ret);
1967 	/* NOTREACHED */
1968 }
1969 
1970 LOCAL void
usage(excode)1971 usage(excode)
1972 	int excode;
1973 {
1974 	error(_("Usage: %s [options] track1...trackn\n"), get_progname());
1975 	error(_("Options:\n"));
1976 	error(_("\t-version	print version information and exit\n"));
1977 	error(_("\tdev=target	SCSI target to use as CD/DVD/BD-Recorder\n"));
1978 	error(_("\tscgopts=spec	SCSI options for libscg\n"));
1979 	error(_("\tgracetime=#	set the grace time before starting to write to #.\n"));
1980 	error(_("\ttimeout=#	set the default SCSI command timeout to #.\n"));
1981 	error(_("\tdebug=#,-d	Set to # or increment misc debug level\n"));
1982 	error(_("\tkdebug=#,kd=#	do Kernel debugging\n"));
1983 	error(_("\t-verbose,-v	increment general verbose level by one\n"));
1984 	error(_("\t-Verbose,-V	increment SCSI command transport verbose level by one\n"));
1985 	error(_("\t-silent,-s	do not print status of failed SCSI commands\n"));
1986 	error(_("\tdriver=name	user supplied driver name, use with extreme care\n"));
1987 	error(_("\tdriveropts=opt	a comma separated list of driver specific options\n"));
1988 	error(_("\t-setdropts	set driver specific options and exit\n"));
1989 	error(_("\t-checkdrive	check if a driver for the drive is present\n"));
1990 	error(_("\t-prcap		print drive capabilities for MMC compliant drives\n"));
1991 	error(_("\t-inq		do an inquiry for the drive and exit\n"));
1992 	error(_("\t-scanbus	scan the SCSI bus and exit\n"));
1993 	error(_("\t-reset		reset the SCSI bus with the cdrecorder (if possible)\n"));
1994 	error(_("\t-abort		send an abort sequence to the drive (may help if hung)\n"));
1995 	error(_("\t-overburn	allow to write more than the official size of a medium\n"));
1996 	error(_("\t-ignsize	ignore the known size of a medium (may cause problems)\n"));
1997 	error(_("\t-useinfo	use *.inf files to overwrite audio options.\n"));
1998 	error(_("\tspeed=#		set speed of drive\n"));
1999 	error(_("\tblank=type	blank a CD-RW disc (see blank=help)\n"));
2000 	error(_("\t-format		format a CD-RW/DVD-RW/DVD+RW disc\n"));
2001 #ifdef	FIFO
2002 	error(_("\tfs=#		Set fifo size to # (0 to disable, default is %ld MB)\n"),
2003 							DEFAULT_FIFOSIZE/(1024L*1024L));
2004 #endif
2005 	error(_("\tts=#		set maximum transfer size for a single SCSI command\n"));
2006 	error(_("\t-load		load the disk and exit (works only with tray loader)\n"));
2007 	error(_("\t-lock		load and lock the disk and exit (works only with tray loader)\n"));
2008 	error(_("\t-eject		eject the disk after doing the work\n"));
2009 	error(_("\t-dummy		do everything with laser turned off\n"));
2010 	error(_("\t-minfo		retrieve and print media information/status\n"));
2011 	error(_("\t-media-info	retrieve and print media information/status\n"));
2012 	error(_("\t-msinfo		retrieve multi-session info for mkisofs >= 1.10\n"));
2013 	error(_("\t-toc		retrieve and print TOC/PMA data\n"));
2014 	error(_("\t-atip		retrieve and print ATIP data\n"));
2015 	error(_("\t-multi		generate a TOC that allows multi session\n"));
2016 	error(_("\t		In this case default track type is CD-ROM XA mode 2 form 1 - 2048 bytes\n"));
2017 	error(_("\t-fix		fixate a corrupt or unfixated disk (generate a TOC)\n"));
2018 	error(_("\t-nofix		do not fixate disk after writing tracks\n"));
2019 	error(_("\t-waiti		wait until input is available before opening SCSI\n"));
2020 	error(_("\t-immed		Try to use the SCSI IMMED flag with certain long lasting commands\n"));
2021 	error(_("\t-force		force to continue on some errors to allow blanking bad disks\n"));
2022 	error(_("\t-tao		Write disk in TAO mode. This option will be replaced in the future.\n"));
2023 	error(_("\t-dao		Write disk in SAO mode. This option will be replaced in the future.\n"));
2024 	error(_("\t-sao		Write disk in SAO mode. This option will be replaced in the future.\n"));
2025 	error(_("\t-raw		Write disk in RAW mode. This option will be replaced in the future.\n"));
2026 	error(_("\t-raw96r		Write disk in RAW/RAW96R mode. This option will be replaced in the future.\n"));
2027 	error(_("\t-raw96p		Write disk in RAW/RAW96P mode. This option will be replaced in the future.\n"));
2028 	error(_("\t-raw16		Write disk in RAW/RAW16 mode. This option will be replaced in the future.\n"));
2029 #ifdef	CLONE_WRITE
2030 	error(_("\t-clone		Write disk in clone write mode.\n"));
2031 #endif
2032 	error(_("\ttsize=#		Length of valid data in next track\n"));
2033 	error(_("\tpadsize=#	Amount of padding for next track\n"));
2034 	error(_("\tpregap=#	Amount of pre-gap sectors before next track\n"));
2035 	error(_("\tdefpregap=#	Amount of pre-gap sectors for all but track #1\n"));
2036 	error(_("\tmcn=text	Set the media catalog number for this CD to 'text'\n"));
2037 	error(_("\tisrc=text	Set the ISRC number for the next track to 'text'\n"));
2038 	error(_("\tindex=list	Set the index list for the next track to 'list'\n"));
2039 	error(_("\t-text		Write CD-Text from information from *.inf or *.cue files\n"));
2040 	error(_("\ttextfile=name	Set the file with CD-Text data to 'name'\n"));
2041 	error(_("\tcuefile=name	Set the file with CDRWIN CUE data to 'name'\n"));
2042 
2043 	error(_("\t-audio		Subsequent tracks are CD-DA audio tracks\n"));
2044 	error(_("\t-data		Subsequent tracks are CD-ROM data mode 1 - 2048 bytes (default)\n"));
2045 	error(_("\t-mode2		Subsequent tracks are CD-ROM data mode 2 - 2336 bytes\n"));
2046 	error(_("\t-xa		Subsequent tracks are CD-ROM XA mode 2 form 1 - 2048 bytes\n"));
2047 	error(_("\t-xa1		Subsequent tracks are CD-ROM XA mode 2 form 1 - 2056 bytes\n"));
2048 	error(_("\t-xa2		Subsequent tracks are CD-ROM XA mode 2 form 2 - 2324 bytes\n"));
2049 	error(_("\t-xamix		Subsequent tracks are CD-ROM XA mode 2 form 1/2 - 2332 bytes\n"));
2050 	error(_("\t-cdi		Subsequent tracks are CDI tracks\n"));
2051 	error(_("\t-isosize	Use iso9660 file system size for next data track\n"));
2052 									/* micro-s */
2053 	error(_("\t-preemp		Audio tracks are mastered with 50/15 us preemphasis\n"));
2054 	error(_("\t-nopreemp	Audio tracks are mastered with no preemphasis (default)\n"));
2055 	error(_("\t-copy		Audio tracks have unlimited copy permission\n"));
2056 	error(_("\t-nocopy		Audio tracks may only be copied once for personal use (default)\n"));
2057 	error(_("\t-scms		Audio tracks will not have any copy permission at all\n"));
2058 	error(_("\t-pad		Pad data tracks with %d zeroed sectors\n"), PAD_SECS);
2059 	error(_("\t		Pad audio tracks to a multiple of %d bytes\n"), AUDIO_SEC_SIZE);
2060 	error(_("\t-nopad		Do not pad data tracks (default)\n"));
2061 	error(_("\t-shorttrack	Subsequent tracks may be non Red Book < 4 seconds if in SAO or RAW mode\n"));
2062 	error(_("\t-noshorttrack	Subsequent tracks must be >= 4 seconds\n"));
2063 	error(_("\t-swab		Audio data source is byte-swapped (little-endian/Intel)\n"));
2064 	error(_("The type of the first track is used for the toc type.\n"));
2065 	error(_("Currently only form 1 tracks are supported.\n"));
2066 	exit(excode);
2067 }
2068 
2069 LOCAL void
blusage(ret)2070 blusage(ret)
2071 	int	ret;
2072 {
2073 	error(_("Blanking options:\n"));
2074 	error(_("\tall\t\tblank the entire disk\n"));
2075 	error(_("\tdisc\t\tblank the entire disk\n"));
2076 	error(_("\tdisk\t\tblank the entire disk\n"));
2077 	error(_("\tfast\t\tminimally blank the entire disk (PMA, TOC, pregap)\n"));
2078 	error(_("\tminimal\t\tminimally blank the entire disk (PMA, TOC, pregap)\n"));
2079 	error(_("\ttrack\t\tblank a track\n"));
2080 	error(_("\tunreserve\tunreserve a track\n"));
2081 	error(_("\ttrtail\t\tblank a track tail\n"));
2082 	error(_("\tunclose\t\tunclose last session\n"));
2083 	error(_("\tsession\t\tblank last session\n"));
2084 
2085 	exit(ret);
2086 	/* NOTREACHED */
2087 }
2088 
2089 /* ARGSUSED */
2090 LOCAL void
intr(sig)2091 intr(sig)
2092 	int	sig;
2093 {
2094 	sig = 0;	/* Fake usage for gcc */
2095 
2096 #ifdef SIGINT
2097 	signal(SIGINT, intr);
2098 #endif
2099 	didintr++;
2100 }
2101 
2102 LOCAL void
catchsig(sig)2103 catchsig(sig)
2104 	int	sig;
2105 {
2106 #ifdef	HAVE_SIGNAL
2107 	signal(sig, catchsig);
2108 #endif
2109 }
2110 
2111 LOCAL int
scsi_cb(arg)2112 scsi_cb(arg)
2113 	void	*arg;
2114 {
2115 	comexit(EX_BAD);
2116 	/* NOTREACHED */
2117 	return (0);	/* Keep lint happy */
2118 }
2119 
2120 LOCAL void
intfifo(sig)2121 intfifo(sig)
2122 	int	sig;
2123 {
2124 	errmsgno(EX_BAD, _("Caught interrupt.\n"));
2125 	if (exargs.scgp) {
2126 		SCSI	*scgp = exargs.scgp;
2127 
2128 		if (scgp->running) {
2129 			if (scgp->cb_fun != NULL) {
2130 				comerrno(EX_BAD, _("Second interrupt. Doing hard abort.\n"));
2131 				/* NOTREACHED */
2132 			}
2133 			scgp->cb_fun = scsi_cb;
2134 			scgp->cb_arg = &exargs;
2135 			return;
2136 		}
2137 	}
2138 	comexit(sig);
2139 }
2140 
2141 /*
2142  * Restore SCSI drive status.
2143  */
2144 /* ARGSUSED */
2145 LOCAL void
exscsi(excode,arg)2146 exscsi(excode, arg)
2147 	int	excode;
2148 	void	*arg;
2149 {
2150 	struct exargs	*exp = (struct exargs *)arg;
2151 
2152 	/*
2153 	 * Try to restore the old sector size.
2154 	 */
2155 	if (exp != NULL && exp->exflags == 0) {
2156 		if (exp->scgp == NULL) {	/* Closed before */
2157 			return;
2158 		}
2159 		if (exp->scgp->running) {
2160 			return;
2161 		}
2162 		/*
2163 		 * flush cache is not supported by CD-ROMs avoid prob with -toc
2164 		 */
2165 		exp->scgp->silent++;
2166 		scsi_flush_cache(exp->scgp, FALSE);
2167 		(*exp->dp->cdr_abort_session)(exp->scgp, exp->dp);
2168 		exp->scgp->silent--;
2169 		set_secsize(exp->scgp, exp->old_secsize);
2170 		unload_media(exp->scgp, exp->dp, exp->flags);
2171 
2172 		exp->exflags++;	/* Make sure that it only get called once */
2173 	}
2174 }
2175 
2176 /*
2177  * excdr() is installed last with on_comerr() and thus will be called first.
2178  * We call exscsi() from here to control the order of calls.
2179  */
2180 LOCAL void
excdr(excode,arg)2181 excdr(excode, arg)
2182 	int	excode;
2183 	void	*arg;
2184 {
2185 	struct exargs	*exp = (struct exargs *)arg;
2186 
2187 	exscsi(excode, arg);	/* Restore/reset drive status */
2188 
2189 	cdrstats(exp->dp);
2190 	if ((exp->dp->cdr_dstat->ds_cdrflags & RF_DID_CDRSTAT) == 0) {
2191 		exp->dp->cdr_dstat->ds_cdrflags |= RF_DID_CDRSTAT;
2192 		if (exp->scgp && exp->scgp->running == 0)
2193 			(*exp->dp->cdr_stats)(exp->scgp, exp->dp);
2194 	}
2195 
2196 	/*
2197 	 * We no longer need SCSI, close it.
2198 	 */
2199 #ifdef	SCG_CLOSE_DEBUG
2200 	error("scg_close(%p)\n", exp->scgp);
2201 #endif
2202 	if (exp->scgp)
2203 		scg_close(exp->scgp);
2204 	exp->scgp = NULL;
2205 
2206 #ifdef	FIFO
2207 	kill_faio();
2208 	wait_faio();
2209 	if (debug || lverbose)
2210 		fifo_stats();
2211 #endif
2212 }
2213 
2214 EXPORT int
read_buf(f,bp,size)2215 read_buf(f, bp, size)
2216 	int	f;
2217 	char	*bp;
2218 	int	size;
2219 {
2220 	char	*p = bp;
2221 	int	amount = 0;
2222 	int	n;
2223 
2224 	if (isobsize > 0) {
2225 		if (size <= isobsize) {
2226 			movebytes(&isobuf[isoboff], bp, size);
2227 			isoboff += size;
2228 			isobsize -= size;
2229 			return (size);
2230 		} else {
2231 			amount = isobsize;
2232 			movebytes(&isobuf[isoboff], bp, isobsize);
2233 			isoboff += isobsize;
2234 			isobsize = 0;
2235 		}
2236 	}
2237 	do {
2238 		do {
2239 			n = read(f, p, size-amount);
2240 		} while (n < 0 && (geterrno() == EAGAIN || geterrno() == EINTR));
2241 		if (n < 0)
2242 			return (n);
2243 		amount += n;
2244 		p += n;
2245 
2246 	} while (amount < size && n > 0);
2247 	return (amount);
2248 }
2249 
2250 EXPORT int
fill_buf(f,trackp,secno,bp,size)2251 fill_buf(f, trackp, secno, bp, size)
2252 	int	f;
2253 	track_t	*trackp;
2254 	long	secno;
2255 	char	*bp;
2256 	int	size;
2257 {
2258 	int	amount = 0;
2259 	int	nsecs;
2260 	int	rsize;
2261 	int	rmod;
2262 	int	readoffset = 0;
2263 
2264 	nsecs = size / trackp->secsize;
2265 	if (nsecs < trackp->secspt) {
2266 		/*
2267 		 * Clear buffer to prepare for last transfer.
2268 		 * Make sure that a partial sector ends with NULs
2269 		 */
2270 		fillbytes(bp, trackp->secspt * trackp->secsize, '\0');
2271 	}
2272 
2273 	if (!is_raw(trackp)) {
2274 		amount = read_buf(f, bp, size);
2275 		if (amount != size) {
2276 			if (amount < 0)
2277 				return (amount);
2278 			/*
2279 			 * We got less than expected, clear rest of buf.
2280 			 */
2281 			fillbytes(&bp[amount], size-amount, '\0');
2282 		}
2283 		if (is_swab(trackp))
2284 			swabbytes(bp, amount);
2285 		return (amount);
2286 	}
2287 
2288 	rsize = nsecs * trackp->isecsize;
2289 	rmod  = size % trackp->secsize;
2290 	if (rmod > 0) {
2291 		rsize += rmod;
2292 		nsecs++;
2293 	}
2294 
2295 	readoffset = trackp->dataoff;
2296 	amount = read_buf(f, bp + readoffset, rsize);
2297 	if (is_swab(trackp))
2298 		swabbytes(bp + readoffset, amount);
2299 
2300 	if (trackp->isecsize == 2448 && trackp->secsize == 2368)
2301 		subrecodesecs(trackp, (Uchar *)bp, secno, nsecs);
2302 
2303 	scatter_secs(trackp, bp + readoffset, nsecs);
2304 
2305 	if (amount != rsize) {
2306 		if (amount < 0)
2307 			return (amount);
2308 		/*
2309 		 * We got less than expected, clear rest of buf.
2310 		 */
2311 		fillbytes(&bp[amount], rsize-amount, '\0');
2312 		nsecs = amount / trackp->isecsize;
2313 		rmod  = amount % trackp->isecsize;
2314 		amount = nsecs * trackp->secsize;
2315 		if (rmod > 0) {
2316 			nsecs++;
2317 			amount += rmod;
2318 		}
2319 	} else {
2320 		amount = size;
2321 	}
2322 	if ((trackp->sectype & ST_MODE_RAW) == 0) {
2323 		encsectors(trackp, (Uchar *)bp, secno, nsecs);
2324 		fillsubch(trackp, (Uchar *)bp, secno, nsecs);
2325 	} else {
2326 		scrsectors(trackp, (Uchar *)bp, secno, nsecs);
2327 		/*
2328 		 * If we are in cuefile= mode with FILE type BINARY we need to
2329 		 * take care as CUE files only know about a 2352 byte RAW mode.
2330 		 * We need to add the missing subchannel data now in this case.
2331 		 */
2332 		if (trackp->isecsize == 2352)
2333 			fillsubch(trackp, (Uchar *)bp, secno, nsecs);
2334 	}
2335 	return (amount);
2336 }
2337 
2338 EXPORT int
get_buf(f,trackp,secno,bpp,size)2339 get_buf(f, trackp, secno, bpp, size)
2340 	int	f;
2341 	track_t	*trackp;
2342 	long	secno;
2343 	char	**bpp;
2344 	int	size;
2345 {
2346 	if (fs > 0) {
2347 /*		return (faio_read_buf(f, *bpp, size));*/
2348 		return (faio_get_buf(f, bpp, size));
2349 	} else {
2350 		return (fill_buf(f, trackp, secno, *bpp, size));
2351 	}
2352 }
2353 
2354 EXPORT int
write_secs(scgp,dp,bp,startsec,bytespt,secspt,islast)2355 write_secs(scgp, dp, bp, startsec, bytespt, secspt, islast)
2356 	SCSI	*scgp;
2357 	cdr_t	*dp;
2358 	char	*bp;
2359 	long	startsec;
2360 	int	bytespt;
2361 	int	secspt;
2362 	BOOL	islast;
2363 {
2364 	int	amount;
2365 
2366 again:
2367 	scgp->silent++;
2368 	amount = (*dp->cdr_write_trackdata)(scgp, bp, startsec, bytespt, secspt, islast);
2369 	scgp->silent--;
2370 	if (amount < 0) {
2371 		if (scsi_in_progress(scgp)) {
2372 			/*
2373 			 * If we sleep too long, the drive buffer is empty
2374 			 * before we start filling it again. The max. CD speed
2375 			 * is ~ 10 MB/s (52x RAW writing). The max. DVD speed
2376 			 * is ~ 28 MB/s (20x DVD 1385 kB/s).
2377 			 * With 10 MB/s, a 1 MB buffer empties within 100ms.
2378 			 * With 28 MB/s, a 1 MB buffer empties within 37ms.
2379 			 */
2380 			if ((dp->cdr_dstat->ds_flags & DSF_NOCD) == 0) {
2381 				usleep(60000);	/* CD case */
2382 			} else {
2383 #ifndef	_SC_CLK_TCK
2384 				usleep(20000);	/* DVD/BD case */
2385 #else
2386 				if (sysconf(_SC_CLK_TCK) < 100)
2387 					usleep(20000);
2388 				else
2389 					usleep(10000);
2390 
2391 #endif
2392 			}
2393 			goto again;
2394 		}
2395 		return (-1);
2396 	}
2397 	return (amount);
2398 }
2399 
2400 EXPORT int
write_track_data(scgp,dp,trackp)2401 write_track_data(scgp, dp, trackp)
2402 	SCSI	*scgp;
2403 	cdr_t	*dp;
2404 	track_t	*trackp;
2405 {
2406 	int	track = trackp->trackno;
2407 	int	f = -1;
2408 	int	isaudio;
2409 	long	startsec;
2410 	Llong	bytes_read = 0;
2411 	Llong	bytes	= 0;
2412 	Llong	savbytes = 0;
2413 	int	count;
2414 	Llong	tracksize;
2415 	int	secsize;
2416 	int	secspt;
2417 	int	bytespt;
2418 	int	bytes_to_read;
2419 	long	amount;
2420 	int	pad;
2421 	BOOL	neednl	= FALSE;
2422 	BOOL	islast	= FALSE;
2423 	char	*bp	= buf;
2424 	struct timeval tlast;
2425 	struct timeval tcur;
2426 	float	secsps = 75.0;
2427 long bsize;
2428 long bfree;
2429 #define	BCAP
2430 #ifdef	BCAP
2431 int per = 0;
2432 #ifdef	XBCAP
2433 int oper = -1;
2434 #endif
2435 #endif
2436 
2437 	if (dp->cdr_dstat->ds_flags & DSF_DVD)
2438 		secsps = 676.27;
2439 	if (dp->cdr_dstat->ds_flags & DSF_BD)
2440 		secsps = 2195.07;
2441 
2442 	scgp->silent++;
2443 	if ((*dp->cdr_buffer_cap)(scgp, &bsize, &bfree) < 0)
2444 		bsize = -1L;
2445 	if (bsize == 0)		/* If we have no (known) buffer, we cannot */
2446 		bsize = -1L;	/* retrieve the buffer fill ratio	   */
2447 	scgp->silent--;
2448 
2449 
2450 	if (is_packet(trackp))	/* XXX Ugly hack for now */
2451 		return (write_packet_data(scgp, dp, trackp));
2452 
2453 	if (trackp->xfp != NULL)
2454 		f = xfileno(trackp->xfp);
2455 
2456 	isaudio = is_audio(trackp);
2457 	tracksize = trackp->tracksize;
2458 	startsec = trackp->trackstart;
2459 
2460 	secsize = trackp->secsize;
2461 	secspt = trackp->secspt;
2462 	bytespt = secsize * secspt;
2463 
2464 	pad = !isaudio && is_pad(trackp);	/* Pad only data tracks */
2465 
2466 	if (debug) {
2467 		printf(_("secsize:%d secspt:%d bytespt:%d audio:%d pad:%d\n"),
2468 			secsize, secspt, bytespt, isaudio, pad);
2469 	}
2470 
2471 	if (lverbose) {
2472 		if (tracksize > 0)
2473 			printf(_("\rTrack %02d:    0 of %4lld MB written."),
2474 				track, tracksize >> 20);
2475 		else
2476 			printf(_("\rTrack %02d:    0 MB written."), track);
2477 		flush();
2478 		neednl = TRUE;
2479 	}
2480 
2481 	gettimeofday(&tlast, (struct timezone *)0);
2482 	do {
2483 		bytes_to_read = bytespt;
2484 		if (tracksize > 0) {
2485 			if ((tracksize - bytes_read) > bytespt)
2486 				bytes_to_read = bytespt;
2487 			else
2488 				bytes_to_read = tracksize - bytes_read;
2489 		}
2490 		count = get_buf(f, trackp, startsec, &bp, bytes_to_read);
2491 
2492 		if (count < 0)
2493 			comerr(_("Read error on input file.\n"));
2494 		if (count == 0)
2495 			break;
2496 		bytes_read += count;
2497 		if (tracksize >= 0 && bytes_read >= tracksize) {
2498 			count -= bytes_read - tracksize;
2499 			/*
2500 			 * Paranoia: tracksize is known (trackp->tracksize >= 0)
2501 			 * At this point, trackp->padsize should alway be set
2502 			 * if the tracksize is less than 300 sectors.
2503 			 */
2504 			if (trackp->padsecs == 0 &&
2505 			    (is_shorttrk(trackp) || (bytes_read/secsize) >= 300))
2506 				islast = TRUE;
2507 		}
2508 
2509 		if (count < bytespt) {
2510 			if (debug) {
2511 				printf(_("\nNOTICE: reducing block size for last record.\n"));
2512 				neednl = FALSE;
2513 			}
2514 
2515 			if ((amount = count % secsize) != 0) {
2516 				amount = secsize - amount;
2517 				count += amount;
2518 				printf(
2519 				_("\nWARNING: padding up to secsize (by %ld bytes).\n"),
2520 					amount);
2521 				neednl = FALSE;
2522 			}
2523 			bytespt = count;
2524 			secspt = count / secsize;
2525 			/*
2526 			 * If tracksize is not known (trackp->tracksize < 0)
2527 			 * we may need to set trackp->padsize
2528 			 * if the tracksize is less than 300 sectors.
2529 			 */
2530 			if (trackp->padsecs == 0 &&
2531 			    (is_shorttrk(trackp) || (bytes_read/secsize) >= 300))
2532 				islast = TRUE;
2533 		}
2534 
2535 		amount = write_secs(scgp, dp, bp, startsec, bytespt, secspt, islast);
2536 		if (amount < 0) {
2537 			printf(_("%swrite track data: error after %lld bytes\n"),
2538 							neednl?"\n":"", bytes);
2539 			return (-1);
2540 		}
2541 		bytes += amount;
2542 		startsec += amount / secsize;
2543 
2544 		if (lverbose && (bytes >= (savbytes + 0x100000))) {
2545 			int	fper;
2546 			int	nsecs = (bytes - savbytes) / secsize;
2547 			float	fspeed;
2548 
2549 			gettimeofday(&tcur, (struct timezone *)0);
2550 			printf(_("\rTrack %02d: %4lld"), track, bytes >> 20);
2551 			if (tracksize > 0)
2552 				printf(_(" of %4lld MB"), tracksize >> 20);
2553 			else
2554 				printf(" MB");
2555 			printf(_(" written"));
2556 			fper = fifo_percent(TRUE);
2557 			if (fper >= 0)
2558 				printf(_(" (fifo %3d%%)"), fper);
2559 #ifdef	BCAP
2560 			/*
2561 			 * Work around a bug in the firmware from drives
2562 			 * developed by PIONEER in November 2009. This affects
2563 			 * drives labelled "Pioneer", "Plextor" and "TEAC".
2564 			 * Do no longer call cdr_buffer_cap() before the drive
2565 			 * buffer was not at least filled once to avoid that
2566 			 * the the drive throughs away all data.
2567 			 */
2568 			if (bsize > 0 && bytes > bsize) { /* buffer size known */
2569 				scgp->silent++;
2570 				per = (*dp->cdr_buffer_cap)(scgp, (long *)0, &bfree);
2571 				scgp->silent--;
2572 				if (per >= 0) {
2573 					per = 100*(bsize - bfree) / bsize;
2574 					if ((bsize - bfree) <= amount || per <= 5)
2575 						dp->cdr_dstat->ds_buflow++;
2576 					if (per < (int)dp->cdr_dstat->ds_minbuf &&
2577 					    (startsec*secsize) > bsize) {
2578 						dp->cdr_dstat->ds_minbuf = per;
2579 					}
2580 					printf(_(" [buf %3d%%]"), per);
2581 #ifdef	BCAPDBG
2582 					printf(" %3ld %3ld", bsize >> 10, bfree >> 10);
2583 #endif
2584 				}
2585 			}
2586 #endif
2587 
2588 			tlast.tv_sec = tcur.tv_sec - tlast.tv_sec;
2589 			tlast.tv_usec = tcur.tv_usec - tlast.tv_usec;
2590 			while (tlast.tv_usec < 0) {
2591 				tlast.tv_usec += 1000000;
2592 				tlast.tv_sec -= 1;
2593 			}
2594 			fspeed = (nsecs / secsps) /
2595 				(tlast.tv_sec * 1.0 + tlast.tv_usec * 0.000001);
2596 			if (fspeed > 999.0)
2597 				fspeed = 999.0;
2598 #ifdef	BCAP
2599 			if (bsize > 0 && per > dminbuf &&
2600 			    dp->cdr_dstat->ds_cdrflags & RF_WR_WAIT) {
2601 				int	wsecs = (per-dminbuf)*(bsize/secsize)/100;
2602 				int	msecs = 0x100000/secsize;
2603 				int	wt;
2604 				int	mt;
2605 				int	s = dp->cdr_dstat->ds_dr_cur_wspeed;
2606 
2607 
2608 				if (s <= 0) {
2609 					if (dp->cdr_dstat->ds_flags & DSF_NOCD)
2610 						s = 4;
2611 					else
2612 						s = 50;
2613 				}
2614 				if (wsecs > msecs)	/* Less that 1 MB */
2615 					wsecs = msecs;
2616 				wt = wsecs * 1000 / secsps / fspeed;
2617 				mt = (per-dminbuf)*(bsize/secsize)/100 * 1000 / secsps/s;
2618 
2619 				if (wt > mt)
2620 					wt = mt;
2621 				if (wt > 1000)		/* Max 1 second */
2622 					wt = 1000;
2623 				if (wt < 20)		/* Min 20 ms */
2624 					wt = 0;
2625 
2626 				if (xdebug)
2627 					printf(_(" |%3d %4dms %5dms|"), wsecs, wt, mt);
2628 				else
2629 					printf(_(" |%3d %4dms|"), wsecs, wt);
2630 				if (wt > 0)
2631 					usleep(wt*1000);
2632 			}
2633 #endif
2634 			printf(" %5.1fx", fspeed);
2635 			printf(".");
2636 			savbytes = (bytes >> 20) << 20;
2637 			flush();
2638 			neednl = TRUE;
2639 			tlast = tcur;
2640 		}
2641 #ifdef	XBCAP
2642 		if (bsize > 0) {			/* buffer size known */
2643 			(*dp->cdr_buffer_cap)(scgp, (long *)0, &bfree);
2644 			per = 100*(bsize - bfree) / bsize;
2645 			if (per != oper)
2646 				printf("[buf %3d%%] %3ld %3ld\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b",
2647 					per, bsize >> 10, bfree >> 10);
2648 			oper = per;
2649 			flush();
2650 		}
2651 #endif
2652 	} while (tracksize < 0 || bytes_read < tracksize);
2653 
2654 	if (!is_shorttrk(trackp) && (bytes / secsize) < 300) {
2655 		/*
2656 		 * If tracksize is not known (trackp->tracksize < 0) or
2657 		 * for some strange reason we did not set padsecs properly
2658 		 * we may need to modify trackp->padsecs if
2659 		 * tracksize+padsecs is less than 300 sectors.
2660 		 */
2661 		if ((trackp->padsecs + (bytes / secsize)) < 300)
2662 			trackp->padsecs = 300 - (bytes / secsize);
2663 	}
2664 	if (trackp->padsecs > 0) {
2665 		Llong	padbytes;
2666 
2667 		/*
2668 		 * pad_track() is based on secsize. Compute the amount of bytes
2669 		 * assumed by pad_track().
2670 		 */
2671 		padbytes = (Llong)trackp->padsecs * secsize;
2672 
2673 		if (neednl) {
2674 			printf("\n");
2675 			neednl = FALSE;
2676 		}
2677 		if ((padbytes >> 20) > 0) {
2678 			neednl = TRUE;
2679 		} else if (lverbose) {
2680 			printf(_("Track %02d: writing %3lld KB of pad data.\n"),
2681 					track, (Llong)(padbytes >> 10));
2682 			neednl = FALSE;
2683 		}
2684 		pad_track(scgp, dp, trackp, startsec, padbytes,
2685 					TRUE, &savbytes);
2686 		bytes += savbytes;
2687 		startsec += savbytes / secsize;
2688 	}
2689 	printf(_("%sTrack %02d: Total bytes read/written: %lld/%lld (%lld sectors).\n"),
2690 		neednl?"\n":"", track, bytes_read, bytes, bytes/secsize);
2691 	flush();
2692 	return (0);
2693 }
2694 
2695 EXPORT int
pad_track(scgp,dp,trackp,startsec,amt,dolast,bytesp)2696 pad_track(scgp, dp, trackp, startsec, amt, dolast, bytesp)
2697 	SCSI	*scgp;
2698 	cdr_t	*dp;
2699 	track_t	*trackp;
2700 	long	startsec;
2701 	Llong	amt;
2702 	BOOL	dolast;
2703 	Llong	*bytesp;
2704 {
2705 	int	track = trackp->trackno;
2706 	Llong	bytes	= 0;
2707 	Llong	savbytes = 0;
2708 	Llong	padsize = amt;
2709 	int	secsize;
2710 	int	secspt;
2711 	int	bytespt;
2712 	int	amount;
2713 	BOOL	neednl	= FALSE;
2714 	BOOL	islast	= FALSE;
2715 	struct timeval tlast;
2716 	struct timeval tcur;
2717 	float	secsps = 75.0;
2718 long bsize;
2719 long bfree;
2720 #define	BCAP
2721 #ifdef	BCAP
2722 int per;
2723 #ifdef	XBCAP
2724 int oper = -1;
2725 #endif
2726 #endif
2727 
2728 	if (dp->cdr_dstat->ds_flags & DSF_DVD)
2729 		secsps = 676.27;
2730 	if (dp->cdr_dstat->ds_flags & DSF_BD)
2731 		secsps = 2195.07;
2732 
2733 	scgp->silent++;
2734 	if ((*dp->cdr_buffer_cap)(scgp, &bsize, &bfree) < 0)
2735 		bsize = -1L;
2736 	if (bsize == 0)		/* If we have no (known) buffer, we cannot */
2737 		bsize = -1L;	/* retrieve the buffer fill ratio	   */
2738 	scgp->silent--;
2739 
2740 	secsize = trackp->secsize;
2741 	secspt = trackp->secspt;
2742 	bytespt = secsize * secspt;
2743 
2744 	fillbytes(buf, bytespt, '\0');
2745 
2746 	if ((amt >> 20) > 0) {
2747 		printf(_("\rTrack %02d:    0 of %4lld MB pad written."),
2748 						track, amt >> 20);
2749 		flush();
2750 	}
2751 	gettimeofday(&tlast, (struct timezone *)0);
2752 	do {
2753 		if (amt < bytespt) {
2754 			bytespt = roundup(amt, secsize);
2755 			secspt = bytespt / secsize;
2756 		}
2757 		if (dolast && (amt - bytespt) <= 0)
2758 			islast = TRUE;
2759 
2760 		if (is_raw(trackp)) {
2761 			encsectors(trackp, (Uchar *)buf, startsec, secspt);
2762 			fillsubch(trackp, (Uchar *)buf, startsec, secspt);
2763 		}
2764 
2765 		amount = write_secs(scgp, dp, buf, startsec, bytespt, secspt, islast);
2766 		if (amount < 0) {
2767 			printf(_("%swrite track pad data: error after %lld bytes\n"),
2768 							neednl?"\n":"", bytes);
2769 			if (bytesp)
2770 				*bytesp = bytes;
2771 (*dp->cdr_buffer_cap)(scgp, (long *)0, (long *)0);
2772 			return (-1);
2773 		}
2774 		amt -= amount;
2775 		bytes += amount;
2776 		startsec += amount / secsize;
2777 
2778 		if (lverbose && (bytes >= (savbytes + 0x100000))) {
2779 			int	nsecs = (bytes - savbytes) / secsize;
2780 			float	fspeed;
2781 
2782 			gettimeofday(&tcur, (struct timezone *)0);
2783 			printf(_("\rTrack %02d: %4lld"), track, bytes >> 20);
2784 			if (padsize > 0)
2785 				printf(_(" of %4lld MB"), padsize >> 20);
2786 			else
2787 				printf(" MB");
2788 			printf(_(" pad written"));
2789 			savbytes = (bytes >> 20) << 20;
2790 
2791 #ifdef	BCAP
2792 			/*
2793 			 * Work around a bug in the firmware from drives
2794 			 * developed by PIONEER in November 2009. This affects
2795 			 * drives labelled "Pioneer", "Plextor" and "TEAC".
2796 			 * Do no longer call cdr_buffer_cap() before the drive
2797 			 * buffer was not at least filled once to avoid that
2798 			 * the the drive throughs away all data.
2799 			 */
2800 			if (bsize > 0 && bytes > bsize) { /* buffer size known */
2801 				scgp->silent++;
2802 				per = (*dp->cdr_buffer_cap)(scgp, (long *)0, &bfree);
2803 				scgp->silent--;
2804 				if (per >= 0) {
2805 					per = 100*(bsize - bfree) / bsize;
2806 					if ((bsize - bfree) <= amount || per <= 5)
2807 						dp->cdr_dstat->ds_buflow++;
2808 					if (per < (int)dp->cdr_dstat->ds_minbuf &&
2809 					    (startsec*secsize) > bsize) {
2810 						dp->cdr_dstat->ds_minbuf = per;
2811 					}
2812 					printf(_(" [buf %3d%%]"), per);
2813 #ifdef	BCAPDBG
2814 					printf(" %3ld %3ld", bsize >> 10, bfree >> 10);
2815 #endif
2816 				}
2817 			}
2818 #endif
2819 			tlast.tv_sec = tcur.tv_sec - tlast.tv_sec;
2820 			tlast.tv_usec = tcur.tv_usec - tlast.tv_usec;
2821 			while (tlast.tv_usec < 0) {
2822 				tlast.tv_usec += 1000000;
2823 				tlast.tv_sec -= 1;
2824 			}
2825 			fspeed = (nsecs / secsps) /
2826 				(tlast.tv_sec * 1.0 + tlast.tv_usec * 0.000001);
2827 			if (fspeed > 999.0)
2828 				fspeed = 999.0;
2829 			printf(" %5.1fx", fspeed);
2830 			printf(".");
2831 			flush();
2832 			neednl = TRUE;
2833 			tlast = tcur;
2834 		}
2835 	} while (amt > 0);
2836 
2837 	if (bytesp)
2838 		*bytesp = bytes;
2839 	if (bytes == 0)
2840 		return (0);
2841 	return (bytes > 0 ? 1:-1);
2842 }
2843 
2844 #ifdef	USE_WRITE_BUF
2845 EXPORT int
write_buf(scgp,dp,trackp,bp,startsec,amt,secsize,dolast,bytesp)2846 write_buf(scgp, dp, trackp, bp, startsec, amt, secsize, dolast, bytesp)
2847 	SCSI	*scgp;
2848 	cdr_t	*dp;
2849 	track_t	*trackp;
2850 	char	*bp;
2851 	long	startsec;
2852 	Llong	amt;
2853 	int	secsize;
2854 	BOOL	dolast;
2855 	Llong	*bytesp;
2856 {
2857 	int	track = trackp->trackno;
2858 	Llong	bytes	= 0;
2859 	Llong	savbytes = 0;
2860 /*	int	secsize;*/
2861 	int	secspt;
2862 	int	bytespt;
2863 	int	amount;
2864 	BOOL	neednl	= FALSE;
2865 	BOOL	islast	= FALSE;
2866 
2867 /*	secsize = trackp->secsize;*/
2868 /*	secspt = trackp->secspt;*/
2869 
2870 	secspt = bufsize/secsize;
2871 	secspt = min(255, secspt);
2872 	bytespt = secsize * secspt;
2873 
2874 /*	fillbytes(buf, bytespt, '\0');*/
2875 
2876 	if ((amt >> 20) > 0) {
2877 		printf(_("\rTrack %02d:   0 of %4ld MB pad written."),
2878 						track, amt >> 20);
2879 		flush();
2880 	}
2881 	do {
2882 		if (amt < bytespt) {
2883 			bytespt = roundup(amt, secsize);
2884 			secspt = bytespt / secsize;
2885 		}
2886 		if (dolast && (amt - bytespt) <= 0)
2887 			islast = TRUE;
2888 
2889 		amount = write_secs(scgp, dp, bp, startsec, bytespt, secspt, islast);
2890 		if (amount < 0) {
2891 			printf(_("%swrite track data: error after %ld bytes\n"),
2892 							neednl?"\n":"", bytes);
2893 			if (bytesp)
2894 				*bytesp = bytes;
2895 (*dp->cdr_buffer_cap)(scgp, (long *)0, (long *)0);
2896 			return (-1);
2897 		}
2898 		amt -= amount;
2899 		bytes += amount;
2900 		startsec += amount / secsize;
2901 
2902 		if (lverbose && (bytes >= (savbytes + 0x100000))) {
2903 			printf(_("\rTrack %02d: %3ld"), track, bytes >> 20);
2904 			savbytes = (bytes >> 20) << 20;
2905 			flush();
2906 			neednl = TRUE;
2907 		}
2908 	} while (amt > 0);
2909 
2910 	if (bytesp)
2911 		*bytesp = bytes;
2912 	return (bytes);
2913 }
2914 #endif	/* USE_WRITE_BUF */
2915 
2916 LOCAL void
printdata(track,trackp)2917 printdata(track, trackp)
2918 	int	track;
2919 	track_t	*trackp;
2920 {
2921 	if (trackp->itracksize >= 0) {
2922 		printf(_("Track %02d: data  %4lld MB        "),
2923 					track, (Llong)(trackp->itracksize >> 20));
2924 	} else {
2925 		printf(_("Track %02d: data  unknown length"),
2926 					track);
2927 	}
2928 	if (trackp->padsecs > 0) {
2929 		Llong	padbytes = (Llong)trackp->padsecs * trackp->isecsize;
2930 
2931 		if ((padbytes >> 20) > 0)
2932 			printf(_(" padsize: %4lld MB"), (Llong)(padbytes >> 20));
2933 		else
2934 			printf(_(" padsize: %4lld KB"), (Llong)(padbytes >> 10));
2935 	}
2936 	if (trackp->pregapsize != (trackp->flags & TI_NOCD)? 0 : 150) {
2937 		printf(_(" pregapsize: %3ld"), trackp->pregapsize);
2938 	}
2939 	if (xdebug)
2940 		printf(" START: %ld SECTORS: %ld INDEX0 %ld",
2941 			trackp->trackstart, trackp->tracksecs, trackp->index0start);
2942 	printf("\n");
2943 }
2944 
2945 LOCAL void
printaudio(track,trackp)2946 printaudio(track, trackp)
2947 	int	track;
2948 	track_t	*trackp;
2949 {
2950 	if (trackp->itracksize >= 0) {
2951 		printf(_("Track %02d: audio %4lld MB (%02d:%02d.%02d) %spreemp%s%s"),
2952 			track, (Llong)(trackp->itracksize >> 20),
2953 			minutes(trackp->itracksize),
2954 			seconds(trackp->itracksize),
2955 			hseconds(trackp->itracksize),
2956 			is_preemp(trackp) ? "" : _("no "),
2957 			is_swab(trackp) ? _(" swab"):"",
2958 			((trackp->itracksize < 300L*trackp->isecsize) ||
2959 			(trackp->itracksize % trackp->isecsize)) &&
2960 			is_pad(trackp) ? _(" pad") : "");
2961 	} else {
2962 		printf(_("Track %02d: audio unknown length    %spreemp%s%s"),
2963 			track, is_preemp(trackp) ? "" : _("no "),
2964 			is_swab(trackp) ? _(" swab"):"",
2965 			(trackp->itracksize % trackp->isecsize) && is_pad(trackp) ? _(" pad") : "");
2966 	}
2967 	if (is_scms(trackp))
2968 		printf(" scms");
2969 	else if (is_copy(trackp))
2970 		printf(" copy");
2971 	else
2972 		printf("     ");
2973 
2974 	if (trackp->padsecs > 0) {
2975 		Llong	padbytes = (Llong)trackp->padsecs * trackp->isecsize;
2976 
2977 		if ((padbytes >> 20) > 0)
2978 			printf(_(" padsize: %4lld MB"), (Llong)(padbytes >> 20));
2979 		else
2980 			printf(_(" padsize: %4lld KB"), (Llong)(padbytes >> 10));
2981 		printf(" (%02d:%02d.%02d)",
2982 			Sminutes(trackp->padsecs),
2983 			Sseconds(trackp->padsecs),
2984 			Shseconds(trackp->padsecs));
2985 	}
2986 	if (trackp->pregapsize != ((trackp->flags & TI_NOCD)? 0 : 150) || xdebug > 0) {
2987 		printf(_(" pregapsize: %3ld"), trackp->pregapsize);
2988 	}
2989 	if (xdebug)
2990 		printf(" START: %ld SECTORS: %ld INDEX0 %ld",
2991 			trackp->trackstart, trackp->tracksecs, trackp->index0start);
2992 	printf("\n");
2993 }
2994 
2995 LOCAL void
checkfile(track,trackp)2996 checkfile(track, trackp)
2997 	int	track;
2998 	track_t	*trackp;
2999 {
3000 	if (trackp->itracksize > 0 &&
3001 			is_audio(trackp) &&
3002 			((!is_shorttrk(trackp) &&
3003 			(trackp->itracksize < 300L*trackp->isecsize)) ||
3004 			(trackp->itracksize % trackp->isecsize)) &&
3005 						!is_pad(trackp)) {
3006 		errmsgno(EX_BAD, _("Bad audio track size %lld for track %02d.\n"),
3007 				(Llong)trackp->itracksize, track);
3008 		errmsgno(EX_BAD, _("Audio tracks must be at least %ld bytes and a multiple of %d.\n"),
3009 				300L*trackp->isecsize, trackp->isecsize);
3010 
3011 		if (!is_shorttrk(trackp) && (trackp->itracksize < 300L*trackp->isecsize))
3012 			comerrno(EX_BAD, _("See -shorttrack option.\n"));
3013 		if (!is_pad(trackp) && (trackp->itracksize % trackp->isecsize))
3014 			comerrno(EX_BAD, _("See -pad option.\n"));
3015 	}
3016 
3017 	if (lverbose == 0 && xdebug == 0)
3018 		return;
3019 
3020 	if (is_audio(trackp))
3021 		printaudio(track, trackp);
3022 	else
3023 		printdata(track, trackp);
3024 }
3025 
3026 LOCAL int
checkfiles(tracks,trackp)3027 checkfiles(tracks, trackp)
3028 	int	tracks;
3029 	track_t	*trackp;
3030 {
3031 	int	i;
3032 	int	isaudio = 1;
3033 	int	starttrack = 1;
3034 	int	endtrack = tracks;
3035 
3036 	if (xdebug) {
3037 		/*
3038 		 * Include Lead-in & Lead-out.
3039 		 */
3040 		starttrack--;
3041 		endtrack++;
3042 	}
3043 	for (i = starttrack; i <= endtrack; i++) {
3044 		if (!is_audio(&trackp[i]))
3045 			isaudio = 0;
3046 		if (xdebug)
3047 			printf("SECTYPE %X ", trackp[i].sectype);
3048 		checkfile(i, &trackp[i]);
3049 	}
3050 	return (isaudio);
3051 }
3052 
3053 LOCAL void
setleadinout(tracks,trackp)3054 setleadinout(tracks, trackp)
3055 	int	tracks;
3056 	track_t	*trackp;
3057 {
3058 	/*
3059 	 * Set some values for track 0 (the lead-in)
3060 	 */
3061 	if (!is_clone(&trackp[0])) {
3062 		trackp[0].sectype = trackp[1].sectype;
3063 		trackp[0].dbtype  = trackp[1].dbtype;
3064 		trackp[0].dataoff = trackp[1].dataoff;
3065 
3066 		/*
3067 		 * XXX Which other flags should be copied to Track 0 ?
3068 		 */
3069 		if (is_audio(&trackp[1]))
3070 			trackp[0].flags |= TI_AUDIO;
3071 	}
3072 
3073 	/*
3074 	 * Set some values for track 0xAA (the lead-out)
3075 	 */
3076 	trackp[tracks+1].pregapsize = 0;
3077 	trackp[tracks+1].isecsize   = trackp[tracks].isecsize;
3078 	trackp[tracks+1].secsize    = trackp[tracks].secsize;
3079 
3080 	if (!is_clone(&trackp[0])) {
3081 		trackp[tracks+1].tracktype = trackp[tracks].tracktype;
3082 		trackp[tracks+1].sectype   = trackp[tracks].sectype;
3083 		trackp[tracks+1].dbtype    = trackp[tracks].dbtype;
3084 		trackp[tracks+1].dataoff   = trackp[tracks].dataoff;
3085 	}
3086 
3087 	trackp[tracks+1].flags = trackp[tracks].flags;
3088 }
3089 
3090 LOCAL void
setpregaps(tracks,trackp)3091 setpregaps(tracks, trackp)
3092 	int	tracks;
3093 	track_t	*trackp;
3094 {
3095 	int	i;
3096 	int	sectype;
3097 	long	pregapsize;
3098 	track_t	*tp;
3099 
3100 	sectype = trackp[1].sectype;
3101 	sectype &= ST_MASK;
3102 
3103 	for (i = 1; i <= tracks; i++) {
3104 		tp = &trackp[i];
3105 		if (tp->pregapsize == -1L) {
3106 			tp->pregapsize = 150;		/* Default CD Pre GAP*/
3107 			if (trackp->flags & TI_NOCD) {
3108 				tp->pregapsize = 0;
3109 			} else if (sectype != (tp->sectype & ST_MASK)) {
3110 				tp->pregapsize = 255;	/* Pre GAP is 255 */
3111 				tp->flags &= ~TI_PREGAP;
3112 			}
3113 		}
3114 		sectype = tp->sectype & ST_MASK;	/* Save old sectype */
3115 	}
3116 	trackp[tracks+1].pregapsize = 0;
3117 	trackp[tracks+1].index0start = 0;
3118 
3119 	for (i = 1; i <= tracks; i++) {
3120 		/*
3121 		 * index0start is set below tracksecks if this track contains
3122 		 * the pregap (index 0) of the next track.
3123 		 */
3124 		trackp[i].index0start = trackp[i].tracksecs;
3125 
3126 		pregapsize = trackp[i+1].pregapsize;
3127 		if (is_pregap(&trackp[i+1]) && pregapsize > 0)
3128 			trackp[i].index0start -= pregapsize;
3129 	}
3130 }
3131 
3132 /*
3133  * Check total size of the medium
3134  */
3135 LOCAL long
checktsize(tracks,trackp)3136 checktsize(tracks, trackp)
3137 	int	tracks;
3138 	track_t	*trackp;
3139 {
3140 	int	i;
3141 	Llong	curr;
3142 	Llong	total = -150;	/* CD track #1 pregap compensation */
3143 	Ullong	btotal;
3144 	track_t	*tp;
3145 
3146 	if (trackp->flags & TI_NOCD)
3147 		total = 0;
3148 	for (i = 1; i <= tracks; i++) {
3149 		tp = &trackp[i];
3150 		if (!is_pregap(tp))
3151 			total += tp->pregapsize;
3152 
3153 		if (lverbose > 1) {
3154 			printf(_("track: %d start: %lld pregap: %ld\n"),
3155 					i, total, tp->pregapsize);
3156 		}
3157 		tp->trackstart = total;
3158 		if (tp->itracksize >= 0) {
3159 			curr = (tp->itracksize + (tp->isecsize-1)) / tp->isecsize;
3160 			curr += tp->padsecs;
3161 			/*
3162 			 * Minimum track size is 4s
3163 			 */
3164 			if (!is_shorttrk(tp) && curr < 300)
3165 				curr = 300;
3166 			if ((trackp->flags & TI_NOCD) == 0) {
3167 				/*
3168 				 * XXX Was passiert hier bei is_packet() ???
3169 				 */
3170 				if (is_tao(tp) && !is_audio(tp)) {
3171 					curr += 2;
3172 				}
3173 			}
3174 			total += curr;
3175 		} else if (is_sao(tp) || is_raw(tp)) {
3176 			errmsgno(EX_BAD, _("Track %d has unknown length.\n"), i);
3177 			comerrno(EX_BAD,
3178 			_("Use tsize= option in %s mode to specify track size.\n"),
3179 			is_sao(tp) ? "SAO" : "RAW");
3180 		}
3181 	}
3182 	tp = &trackp[i];
3183 	tp->trackstart = total;
3184 	tp->tracksecs = 6750;		/* Size of first session Lead-Out */
3185 	if (!lverbose)
3186 		return (total);
3187 
3188 	if (trackp->flags & TI_NOCD)
3189 		btotal = (Ullong)total * 2048;
3190 	else
3191 		btotal = (Ullong)total * 2352;
3192 /* XXX CD Sector Size ??? */
3193 	if (tracks > 0) {
3194 		if (trackp->flags & TI_NOCD) {
3195 			printf(_("Total size:     %4llu MB = %lld sectors\n"),
3196 				btotal >> 20, total);
3197 		} else {
3198 			printf(_("Total size:     %4llu MB (%02d:%02d.%02d) = %lld sectors\n"),
3199 				btotal >> 20,
3200 				minutes(btotal),
3201 				seconds(btotal),
3202 				hseconds(btotal), total);
3203 			btotal += 150 * 2352;
3204 			printf(_("Lout start:     %4llu MB (%02d:%02d/%02d) = %lld sectors\n"),
3205 				btotal >> 20,
3206 				minutes(btotal),
3207 				seconds(btotal),
3208 				frames(btotal), total);
3209 		}
3210 	}
3211 	return (total);
3212 }
3213 
3214 LOCAL void
opentracks(trackp)3215 opentracks(trackp)
3216 	track_t	*trackp;
3217 {
3218 	track_t	*tp;
3219 	int	i;
3220 	int	tracks = trackp[0].tracks;
3221 
3222 	Llong	tracksize;
3223 	int	secsize;
3224 
3225 	if (trackp[1].flags & TI_USEINFO &&
3226 	    auinfhidden(trackp[1].filename, 1, trackp)) {
3227 		tracks = cvt_hidden(trackp);
3228 	}
3229 
3230 	for (i = 0; i <= tracks; i++) {
3231 		tp = &trackp[i];
3232 		if (i == 0 && tp->filename == NULL)
3233 			continue;
3234 
3235 		if (auinfosize(tp->filename, tp)) {
3236 			/*
3237 			 * If auinfosize() returns TRUE, then tp->filename does
3238 			 * not point to an audio file but to an *.inf file.
3239 			 * In this case, we open stdin to allow
3240 			 * cdda2wav | cdrecord
3241 			 */
3242 			tp->xfp = xopen(NULL, O_RDONLY|O_BINARY, 0, 0);
3243 			tp->flags |= TI_STDIN;
3244 		} else if (strcmp("-", tp->filename) == 0) {
3245 			/*
3246 			 * open stdin
3247 			 */
3248 			tp->xfp = xopen(NULL, O_RDONLY|O_BINARY, 0, 0);
3249 			tp->flags |= TI_STDIN;
3250 			if (((tp->flags & TI_ISOSIZE) != 0) &&
3251 			    !is_audio(tp) && (is_sao(tp) || is_raw(tp))) {
3252 				if ((exargs.flags & F_WAITI) == 0) {
3253 					exargs.flags |= F_WAITI;
3254 					wait_input();
3255 				}
3256 			}
3257 		} else {
3258 			if ((tp->xfp = xopen(tp->filename,
3259 					O_RDONLY|O_BINARY, 0, 0)) == NULL) {
3260 				comerr(_("Cannot open '%s'.\n"), tp->filename);
3261 			}
3262 		}
3263 
3264 		checksize(tp);
3265 		tracksize = tp->itracksize;
3266 		secsize = tp->isecsize;
3267 		if (!is_shorttrk(tp) &&
3268 		    tracksize > 0 && (tracksize / secsize) < 300) {
3269 
3270 			tracksize = roundup(tracksize, secsize);
3271 			if ((tp->padsecs +
3272 			    (tracksize / secsize)) < 300) {
3273 				tp->padsecs =
3274 					300 - tracksize / secsize;
3275 			}
3276 			if (xdebug) {
3277 				printf(_("TRACK %d SECTORS: %ld"),
3278 					i, tp->tracksecs);
3279 				printf(_(" pasdize %lld (%ld sectors)\n"),
3280 					(Llong)tp->padsecs * secsize,
3281 					tp->padsecs);
3282 			}
3283 		}
3284 #ifdef	AUINFO
3285 		if (tp->flags & TI_USEINFO) {
3286 			auinfo(tp->filename, i, trackp);
3287 			if (lverbose > 0 && i == 1)
3288 				printf("pregap1: %ld\n", trackp[1].pregapsize);
3289 		}
3290 #endif
3291 		/*
3292 		 * tracksecks is total numbers of sectors in track (starting from
3293 		 * index 0).
3294 		 */
3295 		if (tp->padsecs > 0)
3296 			tp->tracksecs += tp->padsecs;
3297 
3298 		if (debug) {
3299 			printf(_(
3300 			    "File: '%s' itracksize: %lld isecsize: %d tracktype: %d = %s sectype: %X = %s dbtype: %s flags %X\n"),
3301 				tp->filename, (Llong)tp->itracksize,
3302 				tp->isecsize,
3303 				tp->tracktype & TOC_MASK, toc2name[tp->tracktype & TOC_MASK],
3304 				tp->sectype, st2name[tp->sectype & ST_MASK], db2name[tp->dbtype], tp->flags);
3305 		}
3306 	}
3307 }
3308 
3309 LOCAL int
cvt_hidden(trackp)3310 cvt_hidden(trackp)
3311 	track_t	*trackp;
3312 {
3313 	register int	i;
3314 	register int	tracks;
3315 		int	trackno;
3316 		track_t	*tp0 = &trackp[0];
3317 		track_t	*tp1 = &trackp[1];
3318 
3319 	tp0->filename = tp1->filename;
3320 	tp0->trackstart = tp1->trackstart;
3321 	tp0->itracksize = tp1->itracksize;
3322 	tp0->tracksize = tp1->tracksize;
3323 	tp0->tracksecs = tp1->tracksecs;
3324 
3325 	tracks = tp0->tracks - 1;	/* Reduce number of tracks by one */
3326 	trackno = trackp[2].trackno;	/* Will become track # f. track 1 */
3327 	trackno -= 2;
3328 	if (trackno < 0)
3329 		trackno = 0;
3330 
3331 	for (i = 1; i < MAX_TRACK+1; i++) {
3332 		movebytes(&trackp[i+1], &trackp[i], sizeof (trackp[0]));
3333 	}
3334 	for (i = 0; i < MAX_TRACK+2; i++) {
3335 		trackp[i].track = i;
3336 		trackp[i].trackno = trackno + i;
3337 		trackp[i].tracks = tracks;
3338 	}
3339 	tp0->trackno = 0;
3340 	tp0->flags |= TI_HIDDEN;
3341 	tp1->flags |= TI_HIDDEN;
3342 	tp1->flags &= ~TI_PREGAP;
3343 	tp0->flags |= tp1->flags &
3344 			(TI_SWAB|TI_AUDIO|TI_COPY|TI_QUADRO|TI_PREEMP|TI_SCMS);
3345 	return (tracks);
3346 }
3347 
3348 LOCAL void
checksize(trackp)3349 checksize(trackp)
3350 	track_t	*trackp;
3351 {
3352 	struct stat	st;
3353 	Llong		lsize;
3354 	int		f = -1;
3355 
3356 	if (trackp->xfp != NULL)
3357 		f = xfileno(trackp->xfp);
3358 
3359 	/*
3360 	 * If the current input file is a regular file and
3361 	 * 'padsize=' has not been specified,
3362 	 * use fstat() or file parser to get the size of the file.
3363 	 */
3364 	if (trackp->itracksize < 0 && (trackp->flags & TI_ISOSIZE) != 0) {
3365 		if ((trackp->flags & TI_STDIN) != 0) {
3366 			if (trackp->track != 1)
3367 				comerrno(EX_BAD, _("-isosize on stdin only works for the first track.\n"));
3368 			isobuf = malloc(32 * 2048);
3369 			if (isobuf == NULL)
3370 				comerrno(EX_BAD, _("Cannot malloc iso size buffer.\n"));
3371 			isobsize = read_buf(f, isobuf, 32 * 2048);
3372 			lsize = bisosize(isobuf, isobsize);
3373 		} else {
3374 			lsize = isosize(f);
3375 		}
3376 		trackp->itracksize = lsize;
3377 		if (trackp->itracksize != lsize)
3378 			comerrno(EX_BAD, _("This OS cannot handle large ISO-9660 images.\n"));
3379 	}
3380 	if (trackp->itracksize < 0 && (trackp->flags & TI_NOAUHDR) == 0) {
3381 		lsize = ausize(f);
3382 		xmarkpos(trackp->xfp);
3383 		trackp->itracksize = lsize;
3384 		if (trackp->itracksize != lsize)
3385 			comerrno(EX_BAD, _("This OS cannot handle large audio images.\n"));
3386 	}
3387 	if (trackp->itracksize < 0 && (trackp->flags & TI_NOAUHDR) == 0) {
3388 		lsize = wavsize(f);
3389 		xmarkpos(trackp->xfp);
3390 		trackp->itracksize = lsize;
3391 		if (trackp->itracksize != lsize)
3392 			comerrno(EX_BAD, _("This OS cannot handle large WAV images.\n"));
3393 		if (trackp->itracksize > 0)	/* Force little endian input */
3394 			trackp->flags |= TI_SWAB;
3395 	}
3396 	if (trackp->itracksize == AU_BAD_CODING) {
3397 		comerrno(EX_BAD, _("Inappropriate audio coding in '%s'.\n"),
3398 							trackp->filename);
3399 	}
3400 	if (trackp->itracksize < 0 &&
3401 			fstat(f, &st) >= 0 && S_ISREG(st.st_mode)) {
3402 		trackp->itracksize = st.st_size;
3403 	}
3404 	if (trackp->itracksize >= 0) {
3405 		/*
3406 		 * We do not allow cdrecord to start if itracksize is not
3407 		 * a multiple of isecsize or we are allowed to pad to secsize via -pad.
3408 		 * For this reason, we may safely always assume padding.
3409 		 */
3410 		trackp->tracksecs = (trackp->itracksize + trackp->isecsize -1) / trackp->isecsize;
3411 		trackp->tracksize = (trackp->itracksize / trackp->isecsize) * trackp->secsize
3412 					+ trackp->itracksize % trackp->isecsize;
3413 	} else {
3414 		trackp->tracksecs = -1L;
3415 	}
3416 }
3417 
3418 LOCAL BOOL
checkdsize(scgp,dp,tsize,flags)3419 checkdsize(scgp, dp, tsize, flags)
3420 	SCSI	*scgp;
3421 	cdr_t	*dp;
3422 	long	tsize;
3423 	UInt32_t flags;
3424 {
3425 	long	startsec = 0L;
3426 	long	endsec = 0L;
3427 	dstat_t	*dsp = dp->cdr_dstat;
3428 
3429 	/*
3430 	 * Set the track pointer to NULL in order to signal the driver that we
3431 	 * like to get the next writable address for the next (unwritten)
3432 	 * session.
3433 	 */
3434 	scgp->silent++;
3435 	(*dp->cdr_next_wr_address)(scgp, (track_t *)0, &startsec);
3436 	scgp->silent--;
3437 
3438 	/*
3439 	 * This only should happen when the drive is currently in SAO mode.
3440 	 * We rely on the drive being in TAO mode, a negative value for
3441 	 * startsec is not correct here it may be caused by bad firmware or
3442 	 * by a drive in SAO mode. In SAO mode the drive will report the
3443 	 * pre-gap as part of the writable area.
3444 	 */
3445 	if (startsec < 0)
3446 		startsec = 0;
3447 
3448 	/*
3449 	 * Size limitations (sectors) for CD's:
3450 	 *
3451 	 *		404850 == 90 min	Red book calls this the
3452 	 *					first negative time
3453 	 *					allows lead out start up to
3454 	 *					block 404700
3455 	 *
3456 	 *		449850 == 100 min	This is the first time that
3457 	 *					is no more representable
3458 	 *					in a two digit BCD number.
3459 	 *					allows lead out start up to
3460 	 *					block 449700
3461 	 *
3462 	 *		~540000 == 120 min	The largest CD ever made.
3463 	 *
3464 	 *		~650000 == 1.3 GB	a Double Density (DD) CD.
3465 	 */
3466 
3467 	endsec = startsec + tsize;
3468 	dsp->ds_startsec = startsec;
3469 	dsp->ds_endsec = endsec;
3470 
3471 
3472 	if (dsp->ds_maxblocks > 0) {
3473 		/*
3474 		 * dsp->ds_maxblocks > 0 (disk capacity is known).
3475 		 */
3476 		if (lverbose)
3477 			printf(_("Blocks total: %ld Blocks current: %ld Blocks remaining: %ld\n"),
3478 					(long)dsp->ds_maxblocks,
3479 					(long)dsp->ds_maxblocks - startsec,
3480 					(long)dsp->ds_maxblocks - endsec);
3481 
3482 		if (endsec > dsp->ds_maxblocks) {
3483 			if (dsp->ds_flags & DSF_NOCD) { /* Not a CD */
3484 				/*
3485 				 * There is no overburning on DVD/BD...
3486 				 */
3487 				errmsgno(EX_BAD,
3488 				_("Data does not fit on current disk.\n"));
3489 				goto toolarge;
3490 			}
3491 			errmsgno(EX_BAD,
3492 			_("WARNING: Data may not fit on current disk.\n"));
3493 
3494 			/* XXX Check for flags & CDR_NO_LOLIMIT */
3495 /*			goto toolarge;*/
3496 		}
3497 		if (lverbose && dsp->ds_maxrblocks > 0)
3498 			printf(_("RBlocks total: %ld RBlocks current: %ld RBlocks remaining: %ld\n"),
3499 					(long)dsp->ds_maxrblocks,
3500 					(long)dsp->ds_maxrblocks - startsec,
3501 					(long)dsp->ds_maxrblocks - endsec);
3502 		if (dsp->ds_maxrblocks > 0 && endsec > dsp->ds_maxrblocks) {
3503 			errmsgno(EX_BAD,
3504 			_("Data does not fit on current disk.\n"));
3505 			goto toolarge;
3506 		}
3507 		if ((endsec > dsp->ds_maxblocks && endsec > 404700) ||
3508 		    (dsp->ds_maxrblocks > 404700 && 449850 > dsp->ds_maxrblocks)) {
3509 			/*
3510 			 * Assume that this must be a CD and not a DVD.
3511 			 * So this is a non Red Book compliant CD with a
3512 			 * capacity between 90 and 99 minutes.
3513 			 */
3514 			if (dsp->ds_maxrblocks > 404700)
3515 				printf(_("RedBook total: %ld RedBook current: %ld RedBook remaining: %ld\n"),
3516 					404700L,
3517 					404700L - startsec,
3518 					404700L - endsec);
3519 			if (endsec > dsp->ds_maxblocks && endsec > 404700) {
3520 				if ((flags & (F_IGNSIZE|F_FORCE)) == 0) {
3521 					errmsgno(EX_BAD,
3522 					_("Notice: Most recorders cannot write CD's >= 90 minutes.\n"));
3523 					errmsgno(EX_BAD,
3524 					_("Notice: Use -ignsize option to allow >= 90 minutes.\n"));
3525 				}
3526 				goto toolarge;
3527 			}
3528 		}
3529 	} else {
3530 		/*
3531 		 * dsp->ds_maxblocks == 0 (disk capacity is unknown).
3532 		 */
3533 		errmsgno(EX_BAD, _("Disk capacity is unknown.\n"));
3534 
3535 		if (endsec >= (405000-300)) {			/*<90 min disk*/
3536 			errmsgno(EX_BAD,
3537 				_("Data will not fit on any CD.\n"));
3538 			goto toolarge;
3539 		} else if (endsec >= (333000-150)) {		/* 74 min disk*/
3540 			errmsgno(EX_BAD,
3541 			_("WARNING: Data may not fit on standard 74min CD.\n"));
3542 		}
3543 	}
3544 	if (dsp->ds_maxblocks <= 0 || endsec <= dsp->ds_maxblocks)
3545 		return (TRUE);
3546 	/* FALLTHROUGH */
3547 toolarge:
3548 	if (dsp->ds_maxblocks > 0 && endsec > dsp->ds_maxblocks) {
3549 		if ((flags & (F_OVERBURN|F_IGNSIZE|F_FORCE)) != 0) {
3550 			if (dsp->ds_flags & DSF_NOCD) {		/* Not a CD */
3551 				errmsgno(EX_BAD,
3552 				_("Notice: -overburn is not expected to work with DVD/BD media.\n"));
3553 			}
3554 			errmsgno(EX_BAD,
3555 				_("Notice: Overburning active. Trying to write more than the official disk capacity.\n"));
3556 			return (TRUE);
3557 		} else {
3558 			if ((dsp->ds_flags & DSF_NOCD) == 0) {	/* A CD and not a DVD/BD */
3559 				errmsgno(EX_BAD,
3560 				_("Notice: Use -overburn option to write more than the official disk capacity.\n"));
3561 				errmsgno(EX_BAD,
3562 				_("Notice: Most CD-writers do overburning only on SAO or RAW mode.\n"));
3563 			}
3564 			return (FALSE);
3565 		}
3566 	}
3567 	if (dsp->ds_maxblocks < 449850) {
3568 		if (dsp->ds_flags & DSF_NOCD) {			/* A DVD/BD */
3569 			if (endsec <= dsp->ds_maxblocks)
3570 				return (TRUE);
3571 			if (dsp->ds_maxblocks <= 0) {
3572 				errmsgno(EX_BAD, _("DVD/BD capacity is unknown.\n"));
3573 				if ((flags & (F_IGNSIZE|F_FORCE)) != 0) {
3574 					errmsgno(EX_BAD,
3575 						_("Notice: -ignsize active.\n"));
3576 					return (TRUE);
3577 				}
3578 			}
3579 			errmsgno(EX_BAD, _("Cannot write more than remaining DVD/BD capacity.\n"));
3580 			return (FALSE);
3581 		}
3582 		/*
3583 		 * Assume that this must be a CD and not a DVD.
3584 		 */
3585 		if (endsec > 449700) {
3586 			errmsgno(EX_BAD, _("Cannot write CD's >= 100 minutes.\n"));
3587 			return (FALSE);
3588 		}
3589 	}
3590 	if ((flags & (F_IGNSIZE|F_FORCE)) != 0)
3591 		return (TRUE);
3592 	return (FALSE);
3593 }
3594 
3595 LOCAL void
raise_fdlim()3596 raise_fdlim()
3597 {
3598 #ifdef	RLIMIT_NOFILE
3599 
3600 	struct rlimit	rlim;
3601 
3602 	/*
3603 	 * Set max # of file descriptors to be able to hold all files open
3604 	 */
3605 	getrlimit(RLIMIT_NOFILE, &rlim);
3606 	if (rlim.rlim_cur >= (MAX_TRACK + 10))
3607 		return;
3608 
3609 	rlim.rlim_cur = MAX_TRACK + 10;
3610 	if (rlim.rlim_cur > rlim.rlim_max)
3611 		errmsgno(EX_BAD,
3612 			_("Warning: low file descriptor limit (%lld).\n"),
3613 						(Llong)rlim.rlim_max);
3614 	setrlimit(RLIMIT_NOFILE, &rlim);
3615 
3616 #endif	/* RLIMIT_NOFILE */
3617 }
3618 
3619 LOCAL void
raise_memlock()3620 raise_memlock()
3621 {
3622 #ifdef	RLIMIT_MEMLOCK
3623 	struct rlimit rlim;
3624 
3625 	rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
3626 
3627 	if (setrlimit(RLIMIT_MEMLOCK, &rlim) < 0)
3628 		errmsg(_("Warning: Cannot raise RLIMIT_MEMLOCK limits.\n"));
3629 #endif	/* RLIMIT_MEMLOCK */
3630 }
3631 
3632 LOCAL int
getfilecount(ac,av,fmt)3633 getfilecount(ac, av, fmt)
3634 	int		ac;
3635 	char	*const *av;
3636 	const char	*fmt;
3637 {
3638 	int	files = 0;
3639 
3640 	for (; ; --ac, av++) {
3641 		if (getfiles(&ac, &av, fmt) == 0)
3642 			break;
3643 		files++;
3644 	}
3645 	return (files);
3646 }
3647 
3648 
3649 char	*opts =
3650 /* CSTYLED */
3651 "help,version,checkdrive,prcap,inq,scanbus,reset,abort,overburn,ignsize,useinfo,dev*,scgopts*,timeout#,driver*,driveropts*,setdropts,tsize&,padsize&,pregap&,defpregap&,speed#,load,lock,eject,dummy,minfo,media-info,msinfo,toc,atip,multi,fix,nofix,waiti,immed,debug#,d+,kdebug#,kd#,verbose+,v+,Verbose+,V+,x+,xd#,silent,s,audio,data,mode2,xa,xa1,xa2,xamix,cdi,isosize,nopreemp,preemp,nocopy,copy,nopad,pad,swab,fs&,ts&,blank&,format,pktsize#,packet,noclose,force,tao,dao,sao,raw,raw96r,raw96p,raw16,clone,scms,isrc*,mcn*,index*,cuefile*,textfile*,text,shorttrack,noshorttrack,gracetime#,minbuf#";
3652 
3653 /*
3654  * Defines used to find whether a write mode has been specified.
3655  */
3656 #define	M_TAO		1	/* Track at Once mode */
3657 #define	M_SAO		2	/* Session at Once mode (also known as DAO) */
3658 #define	M_RAW		4	/* Raw mode */
3659 #define	M_PACKET	8	/* Packed mode */
3660 
3661 LOCAL void
gargs(ac,av,tracksp,trackp,devp,scgoptp,timeoutp,dpp,speedp,flagsp,blankp)3662 gargs(ac, av, tracksp, trackp, devp, scgoptp, timeoutp, dpp, speedp, flagsp, blankp)
3663 	int	ac;
3664 	char	**av;
3665 	int	*tracksp;
3666 	track_t	*trackp;
3667 	cdr_t	**dpp;
3668 	char	**devp;
3669 	char	**scgoptp;
3670 	int	*timeoutp;
3671 	int	*speedp;
3672 	UInt32_t *flagsp;
3673 	int	*blankp;
3674 {
3675 	int	cac;
3676 	char	* const*cav;
3677 	char	*driver = NULL;
3678 	char	*dev = NULL;
3679 	char	*isrc = NULL;
3680 	char	*mcn = NULL;
3681 	char	*tindex = NULL;
3682 	char	*cuefile = NULL;
3683 	char	*textfile = NULL;
3684 	long	bltype = -1;
3685 	int	doformat = 0;
3686 	Llong	tracksize;
3687 	Llong	padsize;
3688 	long	pregapsize;
3689 	long	defpregap = -1L;
3690 	int	pktsize;
3691 	int	speed = -1;
3692 	int	help = 0;
3693 	int	version = 0;
3694 	int	checkdrive = 0;
3695 	int	setdropts = 0;
3696 	int	prcap = 0;
3697 	int	inq = 0;
3698 	int	scanbus = 0;
3699 	int	reset = 0;
3700 	int	doabort = 0;
3701 	int	overburn = 0;
3702 	int	ignsize = 0;
3703 	int	useinfo = 0;
3704 	int	load = 0;
3705 	int	lock = 0;
3706 	int	eject = 0;
3707 	int	dummy = 0;
3708 	int	mediainfo = 0;
3709 	int	msinfo = 0;
3710 	int	toc = 0;
3711 	int	atip = 0;
3712 	int	multi = 0;
3713 	int	fix = 0;
3714 	int	nofix = 0;
3715 	int	waiti = 0;
3716 	int	immed = 0;
3717 	int	audio;
3718 	int	autoaudio = 0;
3719 	int	data;
3720 	int	mode2;
3721 	int	xa;
3722 	int	xa1;
3723 	int	xa2;
3724 	int	xamix;
3725 	int	cdi;
3726 	int	isize;
3727 	int	ispacket = 0;
3728 	int	noclose = 0;
3729 	int	force = 0;
3730 	int	tao = 0;
3731 	int	dao = 0;
3732 	int	raw = 0;
3733 	int	raw96r = 0;
3734 	int	raw96p = 0;
3735 	int	raw16 = 0;
3736 	int	clone = 0;
3737 	int	scms = 0;
3738 	int	preemp = 0;
3739 	int	nopreemp;
3740 	int	copy = 0;
3741 	int	nocopy;
3742 	int	pad = 0;
3743 	int	bswab = 0;
3744 	int	nopad;
3745 	int	usetext = 0;
3746 	int	shorttrack = 0;
3747 	int	noshorttrack;
3748 	int	flags;
3749 	int	tracks = *tracksp;
3750 	int	tracktype = TOC_ROM;
3751 /*	int	sectype = ST_ROM_MODE1 | ST_MODE_1;*/
3752 	int	sectype = SECT_ROM;
3753 	int	dbtype = DB_ROM_MODE1;
3754 	int	secsize = DATA_SEC_SIZE;
3755 	int	dataoff = 16;
3756 	int	ga_ret;
3757 	int	wm = 0;
3758 	int	ntracks;
3759 
3760 	trackp[0].flags |= TI_TAO;
3761 	trackp[1].pregapsize = -1;
3762 	*flagsp |= F_WRITE;
3763 
3764 	cac = --ac;
3765 	cav = ++av;
3766 	ntracks = getfilecount(ac, av, opts);
3767 	for (; ; cac--, cav++) {
3768 		tracksize = (Llong)-1L;
3769 		padsize = (Llong)0L;
3770 		pregapsize = defpregap;
3771 		audio = data = mode2 = xa = xa1 = xa2 = xamix = cdi = 0;
3772 		isize = nopreemp = nocopy = nopad = noshorttrack = 0;
3773 		pktsize = 0;
3774 		isrc = NULL;
3775 		tindex = NULL;
3776 		/*
3777 		 * Get options up to next file type arg.
3778 		 */
3779 		if ((ga_ret = getargs(&cac, &cav, opts,
3780 				&help, &version, &checkdrive, &prcap,
3781 				&inq, &scanbus, &reset, &doabort, &overburn, &ignsize,
3782 				&useinfo,
3783 				devp, scgoptp, timeoutp, &driver,
3784 				&driveropts, &setdropts,
3785 				getllnum, &tracksize,
3786 				getllnum, &padsize,
3787 				getnum, &pregapsize,
3788 				getnum, &defpregap,
3789 				&speed,
3790 				&load, &lock,
3791 				&eject, &dummy, &mediainfo, &mediainfo,
3792 				&msinfo, &toc, &atip,
3793 				&multi, &fix, &nofix, &waiti, &immed,
3794 				&debug, &debug,
3795 				&kdebug, &kdebug,
3796 				&lverbose, &lverbose,
3797 				&scsi_verbose, &scsi_verbose,
3798 				&xdebug, &xdebug,
3799 				&silent, &silent,
3800 				&audio, &data, &mode2,
3801 				&xa, &xa1, &xa2, &xamix, &cdi,
3802 				&isize,
3803 				&nopreemp, &preemp,
3804 				&nocopy, &copy,
3805 				&nopad, &pad, &bswab, getnum, &fs, getnum, &bufsize,
3806 				getbltype, &bltype, &doformat, &pktsize,
3807 				&ispacket, &noclose, &force,
3808 				&tao, &dao, &dao, &raw, &raw96r, &raw96p, &raw16,
3809 				&clone,
3810 				&scms, &isrc, &mcn, &tindex,
3811 				&cuefile, &textfile, &usetext,
3812 				&shorttrack, &noshorttrack,
3813 				&gracetime, &dminbuf)) < 0) {
3814 			errmsgno(EX_BAD, _("Bad Option: %s.\n"), cav[0]);
3815 			susage(EX_BAD);
3816 		}
3817 		if (help)
3818 			usage(0);
3819 		if (tracks == 0) {
3820 			if (driver)
3821 				set_cdrcmds(driver, dpp);
3822 			if (version) {
3823 				if (ntracks > 0)
3824 					etracks("version");
3825 				*flagsp |= F_VERSION;
3826 			}
3827 			if (checkdrive) {
3828 				if (ntracks > 0)
3829 					etracks("checkdrive");
3830 				*flagsp |= F_CHECKDRIVE;
3831 			}
3832 			if (prcap) {
3833 				if (ntracks > 0)
3834 					etracks("prcap");
3835 				*flagsp |= F_PRCAP;
3836 			}
3837 			if (inq) {
3838 				if (ntracks > 0)
3839 					etracks("inquiry");
3840 				*flagsp |= F_INQUIRY;
3841 			}
3842 			if (scanbus) {
3843 				if (ntracks > 0)
3844 					etracks("scanbus");
3845 				*flagsp |= F_SCANBUS;
3846 			}
3847 			if (reset) {
3848 				if (ntracks > 0)
3849 					etracks("reset");
3850 				*flagsp |= F_RESET;
3851 			}
3852 			if (doabort) {
3853 				if (ntracks > 0)
3854 					etracks("abort");
3855 				*flagsp |= F_ABORT;
3856 			}
3857 			if (overburn)
3858 				*flagsp |= F_OVERBURN;
3859 			if (ignsize)
3860 				*flagsp |= F_IGNSIZE;
3861 			if (load) {
3862 				if (ntracks > 0)
3863 					etracks("load");
3864 				*flagsp |= F_LOAD;
3865 			}
3866 			if (lock) {
3867 				if (ntracks > 0)
3868 					etracks("lock");
3869 				*flagsp |= F_DLCK;
3870 			}
3871 			if (eject)
3872 				*flagsp |= F_EJECT;
3873 			if (dummy)
3874 				*flagsp |= F_DUMMY;
3875 			if (setdropts) {
3876 				if (ntracks > 0)
3877 					etracks("setdropts");
3878 				*flagsp |= F_SETDROPTS;
3879 			}
3880 			if (mediainfo) {
3881 				if (ntracks > 0)
3882 					etracks("minfo");
3883 				*flagsp |= F_MEDIAINFO;
3884 				*flagsp &= ~F_WRITE;
3885 			}
3886 			if (msinfo) {
3887 				if (ntracks > 0)
3888 					etracks("msinfo");
3889 				*flagsp |= F_MSINFO;
3890 				*flagsp &= ~F_WRITE;
3891 			}
3892 			if (toc) {
3893 				if (ntracks > 0)
3894 					etracks("toc");
3895 				*flagsp |= F_TOC;
3896 				*flagsp &= ~F_WRITE;
3897 			}
3898 			if (atip) {
3899 				if (ntracks > 0)
3900 					etracks("atip");
3901 				*flagsp |= F_PRATIP;
3902 				*flagsp &= ~F_WRITE;
3903 			}
3904 			if (multi) {
3905 				/*
3906 				 * 2048 Bytes user data
3907 				 */
3908 				*flagsp |= F_MULTI;
3909 				tracktype = TOC_XA2;
3910 				sectype = ST_ROM_MODE2 | ST_MODE_2_FORM_1;
3911 				sectype = SECT_MODE_2_F1;
3912 				dbtype = DB_XA_MODE2;	/* XXX -multi nimmt DB_XA_MODE2_F1 !!! */
3913 				secsize = DATA_SEC_SIZE;	/* 2048 */
3914 				dataoff = 24;
3915 			}
3916 			if (fix) {
3917 				if (ntracks > 0)
3918 					etracks("fix");
3919 				*flagsp |= F_FIX;
3920 			}
3921 			if (nofix)
3922 				*flagsp |= F_NOFIX;
3923 			if (waiti)
3924 				*flagsp |= F_WAITI;
3925 			if (immed)
3926 				*flagsp |= F_IMMED;
3927 			if (force)
3928 				*flagsp |= F_FORCE;
3929 
3930 			if (bltype >= 0) {
3931 				*flagsp |= F_BLANK;
3932 				*blankp = bltype;
3933 			}
3934 			if (doformat)
3935 				*flagsp |= F_FORMAT;
3936 			if (ispacket)
3937 				wm |= M_PACKET;
3938 			if (tao)
3939 				wm |= M_TAO;
3940 			if (dao) {
3941 				*flagsp |= F_SAO;
3942 				trackp[0].flags &= ~TI_TAO;
3943 				trackp[0].flags |= TI_SAO;
3944 				wm |= M_SAO;
3945 
3946 			} else if ((raw == 0) && (raw96r + raw96p + raw16) > 0)
3947 				raw = 1;
3948 			if ((raw != 0) && (raw96r + raw96p + raw16) == 0)
3949 				raw96r = 1;
3950 			if (raw96r) {
3951 				if (!dao)
3952 					*flagsp |= F_RAW;
3953 				trackp[0].flags &= ~TI_TAO;
3954 				trackp[0].flags |= TI_RAW;
3955 				trackp[0].flags |= TI_RAW96R;
3956 				wm |= M_RAW;
3957 			}
3958 			if (raw96p) {
3959 				if (!dao)
3960 					*flagsp |= F_RAW;
3961 				trackp[0].flags &= ~TI_TAO;
3962 				trackp[0].flags |= TI_RAW;
3963 				wm |= M_RAW;
3964 			}
3965 			if (raw16) {
3966 				if (!dao)
3967 					*flagsp |= F_RAW;
3968 				trackp[0].flags &= ~TI_TAO;
3969 				trackp[0].flags |= TI_RAW;
3970 				trackp[0].flags |= TI_RAW16;
3971 				wm |= M_RAW;
3972 			}
3973 			if (mcn) {
3974 #ifdef	AUINFO
3975 				setmcn(mcn, &trackp[0]);
3976 #else
3977 				trackp[0].isrc = malloc(16);
3978 				fillbytes(trackp[0].isrc, 16, '\0');
3979 				strncpy(trackp[0].isrc, mcn, 13);
3980 #endif
3981 				mcn = NULL;
3982 			}
3983 			if ((raw96r + raw96p + raw16) > 1) {
3984 				errmsgno(EX_BAD, _("Too many raw modes.\n"));
3985 				comerrno(EX_BAD, _("Only one of -raw16, -raw96p, -raw96r allowed.\n"));
3986 			}
3987 			if ((tao + ispacket + dao + raw) > 1) {
3988 				errmsgno(EX_BAD, _("Too many write modes.\n"));
3989 				comerrno(EX_BAD, _("Only one of -packet, -dao, -raw allowed.\n"));
3990 			}
3991 			if (dao && (raw96r + raw96p + raw16) > 0) {
3992 				if (raw16)
3993 					comerrno(EX_BAD, _("SAO RAW writing does not allow -raw16.\n"));
3994 				if (!clone)
3995 					comerrno(EX_BAD, _("SAO RAW writing only makes sense in clone mode.\n"));
3996 #ifndef	CLONE_WRITE
3997 				comerrno(EX_BAD, _("SAO RAW writing not compiled in.\n"));
3998 #endif
3999 				comerrno(EX_BAD, _("SAO RAW writing not yet implemented.\n"));
4000 			}
4001 			if (clone) {
4002 				*flagsp |= F_CLONE;
4003 				trackp[0].flags |= TI_CLONE;
4004 #ifndef	CLONE_WRITE
4005 				comerrno(EX_BAD, _("Clone writing not compiled in.\n"));
4006 #endif
4007 			}
4008 			if (textfile) {
4009 				if (!checktextfile(textfile)) {
4010 					if ((*flagsp & F_WRITE) != 0) {
4011 						comerrno(EX_BAD,
4012 							_("Cannot use '%s' as CD-Text file.\n"),
4013 							textfile);
4014 					}
4015 				}
4016 				if ((*flagsp & F_WRITE) != 0) {
4017 					if ((dao + raw96r + raw96p) == 0)
4018 						comerrno(EX_BAD,
4019 							_("CD-Text needs -dao, -raw96r or -raw96p.\n"));
4020 				}
4021 				trackp[0].flags |= TI_TEXT;
4022 			}
4023 			version = checkdrive = prcap = inq = scanbus = reset = doabort =
4024 			overburn = ignsize =
4025 			load = lock = eject = dummy = mediainfo = msinfo =
4026 			toc = atip = multi = fix = nofix =
4027 			waiti = immed = force = dao = setdropts = 0;
4028 			raw96r = raw96p = raw16 = clone = 0;
4029 		} else if ((version + checkdrive + prcap + inq + scanbus +
4030 			    reset + doabort + overburn + ignsize +
4031 			    load + lock + eject + dummy + mediainfo + msinfo +
4032 			    toc + atip + multi + fix + nofix +
4033 			    waiti + immed + force + dao + setdropts +
4034 			    raw96r + raw96p + raw16 + clone) > 0 ||
4035 				mcn != NULL)
4036 			comerrno(EX_BAD, _("Badly placed option. Global options must be before any track.\n"));
4037 
4038 		if (nopreemp)
4039 			preemp = 0;
4040 		if (nocopy)
4041 			copy = 0;
4042 		if (nopad)
4043 			pad = 0;
4044 		if (noshorttrack)
4045 			shorttrack = 0;
4046 
4047 		if ((audio + data + mode2 + xa + xa1 + xa2 + xamix) > 1) {
4048 			errmsgno(EX_BAD, _("Too many types for track %d.\n"), tracks+1);
4049 			comerrno(EX_BAD, _("Only one of -audio, -data, -mode2, -xa, -xa1, -xa2, -xamix allowed.\n"));
4050 		}
4051 		if (ispacket && audio) {
4052 			comerrno(EX_BAD, _("Audio data cannot be written in packet mode.\n"));
4053 		}
4054 		/*
4055 		 * Check whether the next argument is a file type arg.
4056 		 * If this is true, then we got a track file name.
4057 		 * If getargs() did previously return NOTAFLAG, we may have hit
4058 		 * an argument that has been escaped via "--", so we may not
4059 		 * call getfiles() again in this case. If we would call
4060 		 * getfiles() and the current arg has been escaped and looks
4061 		 * like an option, a call to getfiles() would skip it.
4062 		 */
4063 		if (ga_ret < NOTAFLAG)
4064 			ga_ret = getfiles(&cac, &cav, opts);
4065 		if (autoaudio) {
4066 			autoaudio = 0;
4067 			tracktype = TOC_ROM;
4068 			sectype = ST_ROM_MODE1 | ST_MODE_1;
4069 			sectype = SECT_ROM;
4070 			dbtype = DB_ROM_MODE1;
4071 			secsize = DATA_SEC_SIZE;	/* 2048 */
4072 			dataoff = 16;
4073 		}
4074 		if (ga_ret >= NOTAFLAG && (is_auname(cav[0]) || is_wavname(cav[0]))) {
4075 			/*
4076 			 * We got a track and autodetection decided that it
4077 			 * is an audio track.
4078 			 */
4079 			autoaudio++;
4080 			audio++;
4081 		}
4082 		if (data) {
4083 			/*
4084 			 * 2048 Bytes user data
4085 			 */
4086 			tracktype = TOC_ROM;
4087 			sectype = ST_ROM_MODE1 | ST_MODE_1;
4088 			sectype = SECT_ROM;
4089 			dbtype = DB_ROM_MODE1;
4090 			secsize = DATA_SEC_SIZE;	/* 2048 */
4091 			dataoff = 16;
4092 		}
4093 		if (mode2) {
4094 			/*
4095 			 * 2336 Bytes user data
4096 			 */
4097 			tracktype = TOC_ROM;
4098 			sectype = ST_ROM_MODE2 | ST_MODE_2;
4099 			sectype = SECT_MODE_2;
4100 			dbtype = DB_ROM_MODE2;
4101 			secsize = MODE2_SEC_SIZE;	/* 2336 */
4102 			dataoff = 16;
4103 		}
4104 		if (audio) {
4105 			/*
4106 			 * 2352 Bytes user data
4107 			 */
4108 			tracktype = TOC_DA;
4109 			sectype = preemp ? ST_AUDIO_PRE : ST_AUDIO_NOPRE;
4110 			sectype |= ST_MODE_AUDIO;
4111 			sectype = SECT_AUDIO;
4112 			if (preemp)
4113 				sectype |= ST_PREEMPMASK;
4114 			dbtype = DB_RAW;
4115 			secsize = AUDIO_SEC_SIZE;	/* 2352 */
4116 			dataoff = 0;
4117 		}
4118 		if (xa) {
4119 			/*
4120 			 * 2048 Bytes user data
4121 			 */
4122 			if (tracktype != TOC_CDI)
4123 				tracktype = TOC_XA2;
4124 			sectype = ST_ROM_MODE2 | ST_MODE_2_FORM_1;
4125 			sectype = SECT_MODE_2_F1;
4126 			dbtype = DB_XA_MODE2;
4127 			secsize = DATA_SEC_SIZE;	/* 2048 */
4128 			dataoff = 24;
4129 		}
4130 		if (xa1) {
4131 			/*
4132 			 * 8 Bytes subheader + 2048 Bytes user data
4133 			 */
4134 			if (tracktype != TOC_CDI)
4135 				tracktype = TOC_XA2;
4136 			sectype = ST_ROM_MODE2 | ST_MODE_2_FORM_1;
4137 			sectype = SECT_MODE_2_F1;
4138 			dbtype = DB_XA_MODE2_F1;
4139 			secsize = 2056;
4140 			dataoff = 16;
4141 		}
4142 		if (xa2) {
4143 			/*
4144 			 * 2324 Bytes user data
4145 			 */
4146 			if (tracktype != TOC_CDI)
4147 				tracktype = TOC_XA2;
4148 			sectype = ST_ROM_MODE2 | ST_MODE_2_FORM_2;
4149 			sectype = SECT_MODE_2_F2;
4150 			dbtype = DB_XA_MODE2_F2;
4151 			secsize = 2324;
4152 			dataoff = 24;
4153 		}
4154 		if (xamix) {
4155 			/*
4156 			 * 8 Bytes subheader + 2324 Bytes user data
4157 			 */
4158 			if (tracktype != TOC_CDI)
4159 				tracktype = TOC_XA2;
4160 			sectype = ST_ROM_MODE2 | ST_MODE_2_MIXED;
4161 			sectype = SECT_MODE_2_MIX;
4162 			dbtype = DB_XA_MODE2_MIX;
4163 			secsize = 2332;
4164 			dataoff = 16;
4165 		}
4166 		if (cdi) {
4167 			tracktype = TOC_CDI;
4168 		}
4169 		if (tracks == 0) {
4170 			trackp[0].tracktype = tracktype;
4171 			trackp[0].dbtype = dbtype;
4172 			trackp[0].sectype = sectype;
4173 			trackp[0].isecsize = secsize;
4174 			trackp[0].secsize = secsize;
4175 			if ((*flagsp & F_RAW) != 0) {
4176 				trackp[0].secsize = is_raw16(&trackp[0]) ?
4177 						RAW16_SEC_SIZE:RAW96_SEC_SIZE;
4178 			}
4179 			if ((*flagsp & F_DUMMY) != 0)
4180 				trackp[0].tracktype |= TOCF_DUMMY;
4181 			if ((*flagsp & F_MULTI) != 0)
4182 				trackp[0].tracktype |= TOCF_MULTI;
4183 		}
4184 
4185 		flags = trackp[0].flags;
4186 
4187 		if ((sectype & ST_AUDIOMASK) != 0)
4188 			flags |= TI_AUDIO;
4189 		if (isize) {
4190 			flags |= TI_ISOSIZE;
4191 			if ((*flagsp & F_MULTI) != 0)
4192 				comerrno(EX_BAD, _("Cannot get isosize for multi session disks.\n"));
4193 			/*
4194 			 * As we do not get the padding from the ISO-9660
4195 			 * formatting utility, we need to force padding here.
4196 			 */
4197 			flags |= TI_PAD;
4198 			if (padsize == (Llong)0L)
4199 				padsize = (Llong)PAD_SIZE;
4200 		}
4201 
4202 		if ((flags & TI_AUDIO) != 0) {
4203 			if (preemp)
4204 				flags |= TI_PREEMP;
4205 			if (copy)
4206 				flags |= TI_COPY;
4207 			if (scms)
4208 				flags |= TI_SCMS;
4209 		}
4210 		if (pad || ((flags & TI_AUDIO) == 0 && padsize > (Llong)0L)) {
4211 			flags |= TI_PAD;
4212 			if ((flags & TI_AUDIO) == 0 && padsize == (Llong)0L)
4213 				padsize = (Llong)PAD_SIZE;
4214 		}
4215 		if (shorttrack && (*flagsp & (F_SAO|F_RAW)) != 0)
4216 			flags |= TI_SHORT_TRACK;
4217 		if (noshorttrack)
4218 			flags &= ~TI_SHORT_TRACK;
4219 		if (bswab)
4220 			flags |= TI_SWAB;
4221 		if (ispacket) {
4222 			flags |= TI_PACKET;
4223 			trackp[0].flags &= ~TI_TAO;
4224 		}
4225 		if (noclose)
4226 			flags |= TI_NOCLOSE;
4227 		if (useinfo)
4228 			flags |= TI_USEINFO;
4229 
4230 		if (ga_ret <= NOARGS) {
4231 			/*
4232 			 * All options have already been parsed and no more
4233 			 * file type arguments are present.
4234 			 */
4235 			break;
4236 		}
4237 		if (tracks == 0 && (wm == 0))
4238 			flags = default_wr_mode(tracks, trackp, flagsp, &wm, flags);
4239 		tracks++;
4240 
4241 		if (tracks > MAX_TRACK)
4242 			comerrno(EX_BAD, _("Track limit (%d) exceeded.\n"),
4243 								MAX_TRACK);
4244 		/*
4245 		 * Make 'tracks' immediately usable in track structure.
4246 		 */
4247 		{	register int i;
4248 			for (i = 0; i < MAX_TRACK+2; i++)
4249 				trackp[i].tracks = tracks;
4250 		}
4251 
4252 		if (strcmp("-", cav[0]) == 0)
4253 			*flagsp |= F_STDIN;
4254 
4255 		if (!is_auname(cav[0]) && !is_wavname(cav[0]))
4256 			flags |= TI_NOAUHDR;
4257 
4258 		if ((*flagsp & (F_SAO|F_RAW)) != 0 && (flags & TI_AUDIO) != 0)
4259 			flags |= TI_PREGAP;	/* Hack for now */
4260 		if (tracks == 1)
4261 			flags &= ~TI_PREGAP;
4262 
4263 		if (tracks == 1 && (pregapsize != -1L && pregapsize != 150))
4264 			pregapsize = -1L;
4265 		trackp[tracks].filename = cav[0];
4266 		trackp[tracks].trackstart = 0L;
4267 		trackp[tracks].itracksize = tracksize;
4268 		trackp[tracks].tracksize = tracksize;
4269 		trackp[tracks].tracksecs = -1L;
4270 		if (tracksize >= 0)
4271 			trackp[tracks].tracksecs = (tracksize+secsize-1)/secsize;
4272 		if (trackp[tracks].pregapsize < 0)
4273 			trackp[tracks].pregapsize = pregapsize;
4274 		trackp[tracks+1].pregapsize = -1;
4275 		trackp[tracks].padsecs = (padsize+2047)/2048;
4276 		trackp[tracks].isecsize = secsize;
4277 		trackp[tracks].secsize = secsize;
4278 		trackp[tracks].flags = flags;
4279 		/*
4280 		 * XXX Dies ist falsch: auch bei SAO/RAW kann
4281 		 * XXX secsize != isecsize sein.
4282 		 */
4283 		if ((*flagsp & F_RAW) != 0) {
4284 			if (is_raw16(&trackp[tracks]))
4285 				trackp[tracks].secsize = RAW16_SEC_SIZE;
4286 			else
4287 				trackp[tracks].secsize = RAW96_SEC_SIZE;
4288 #ifndef	HAVE_LIB_EDC_ECC
4289 			if ((sectype & ST_MODE_MASK) != ST_MODE_AUDIO) {
4290 				errmsgno(EX_BAD,
4291 					_("EDC/ECC library not compiled in.\n"));
4292 				comerrno(EX_BAD,
4293 					_("Data sectors are not supported in RAW mode.\n"));
4294 			}
4295 #endif
4296 		}
4297 		trackp[tracks].secspt = 0;	/* transfer size is set up in set_trsizes() */
4298 		trackp[tracks].pktsize = pktsize;
4299 		trackp[tracks].trackno = tracks;
4300 		trackp[tracks].sectype = sectype;
4301 #ifdef	CLONE_WRITE
4302 		if ((*flagsp & F_CLONE) != 0) {
4303 			trackp[tracks].isecsize = 2448;
4304 			trackp[tracks].sectype |= ST_MODE_RAW;
4305 			dataoff = 0;
4306 		}
4307 #endif
4308 		trackp[tracks].dataoff = dataoff;
4309 		trackp[tracks].tracktype = tracktype;
4310 		trackp[tracks].dbtype = dbtype;
4311 		trackp[tracks].flags = flags;
4312 		trackp[tracks].nindex = 1;
4313 		trackp[tracks].tindex = 0;
4314 		if (isrc) {
4315 #ifdef	AUINFO
4316 			setisrc(isrc, &trackp[tracks]);
4317 #else
4318 			trackp[tracks].isrc = malloc(16);
4319 			fillbytes(trackp[tracks].isrc, 16, '\0');
4320 			strncpy(trackp[tracks].isrc, isrc, 12);
4321 #endif
4322 		}
4323 		if (tindex) {
4324 #ifdef	AUINFO
4325 			setindex(tindex, &trackp[tracks]);
4326 #endif
4327 		}
4328 	}
4329 
4330 	if (dminbuf >= 0) {
4331 		if (dminbuf < 25 || dminbuf > 95)
4332 			comerrno(EX_BAD,
4333 			_("Bad minbuf=%d option (must be between 25 and 95).\n"),
4334 				dminbuf);
4335 	}
4336 
4337 	if (speed < 0 && speed != -1)
4338 		comerrno(EX_BAD, _("Bad speed option.\n"));
4339 
4340 	if (fs < 0L && fs != -1L)
4341 		comerrno(EX_BAD, _("Bad fifo size option.\n"));
4342 
4343 	if (bufsize < 0L && bufsize != -1L)
4344 		comerrno(EX_BAD, _("Bad transfer size option.\n"));
4345 
4346 	dev = *devp;
4347 	cdr_defaults(&dev, &speed, &fs, &bufsize, &driveropts);
4348 
4349 	if (bufsize < 0L)
4350 		bufsize = CDR_BUF_SIZE;
4351 	if (bufsize > CDR_MAX_BUF_SIZE)
4352 		bufsize = CDR_MAX_BUF_SIZE;
4353 
4354 	if (debug) {
4355 		printf(_("dev: '%s' speed: %d fs: %ld driveropts '%s'\n"),
4356 					dev, speed, fs, driveropts);
4357 	}
4358 	if (speed >= 0)
4359 		*speedp = speed;
4360 
4361 	if (fs < 0L)
4362 		fs = DEFAULT_FIFOSIZE;
4363 	if (fs < 2*bufsize) {
4364 		errmsgno(EX_BAD, _("Fifo size %ld too small, turning fifo off.\n"), fs);
4365 		fs = 0L;
4366 	}
4367 
4368 	if (dev != *devp && (*flagsp & F_SCANBUS) == 0)
4369 		*devp = dev;
4370 
4371 #ifdef	NO_SEARCH_FOR_DEVICE
4372 	if (!*devp && (*flagsp & (F_VERSION|F_SCANBUS)) == 0) {
4373 		errmsgno(EX_BAD, _("No CD/DVD/BD-Recorder device specified.\n"));
4374 		susage(EX_BAD);
4375 	}
4376 #endif
4377 	if (*devp &&
4378 	    ((strncmp(*devp, "HELP", 4) == 0) ||
4379 	    (strncmp(*devp, "help", 4) == 0))) {
4380 		*flagsp |= F_CHECKDRIVE; /* Set this for not calling mlockall() */
4381 		return;
4382 	}
4383 	if (*flagsp &
4384 	    (F_LOAD|F_DLCK|F_SETDROPTS|F_MEDIAINFO|F_MSINFO|F_TOC|F_PRATIP|
4385 	    F_FIX|F_VERSION|
4386 	    F_CHECKDRIVE|F_PRCAP|F_INQUIRY|F_SCANBUS|F_RESET|F_ABORT)) {
4387 		if (tracks != 0) {
4388 			errmsgno(EX_BAD, _("No tracks allowed with this option.\n"));
4389 			susage(EX_BAD);
4390 		}
4391 		return;
4392 	}
4393 	*tracksp = tracks;
4394 	if (*flagsp & F_SAO) {
4395 		/*
4396 		 * Make sure that you change WRITER_MAXWAIT & READER_MAXWAIT
4397 		 * too if you change this timeout.
4398 		 */
4399 		if (*timeoutp < 200)		/* Lead in size is 2:30 */
4400 			*timeoutp = 200;	/* 200s is 150s *1.33	*/
4401 	}
4402 	if (usetext) {
4403 		trackp[MAX_TRACK+1].flags |= TI_TEXT;
4404 	}
4405 	if (cuefile) {
4406 		if (tracks == 0 && (wm == 0))
4407 			flags = default_wr_mode(tracks, trackp, flagsp, &wm, flags);
4408 
4409 		if ((*flagsp & F_SAO) == 0 &&
4410 		    (*flagsp & F_RAW) == 0) {
4411 			errmsgno(EX_BAD, _("The cuefile= option only works with -sao/-raw.\n"));
4412 			susage(EX_BAD);
4413 		}
4414 		if (pad)
4415 			trackp[0].flags |= TI_PAD;
4416 		if (tracks > 0) {
4417 			errmsgno(EX_BAD, _("No tracks allowed with the cuefile= option.\n"));
4418 			susage(EX_BAD);
4419 		}
4420 		cuefilename = cuefile;
4421 		return;
4422 	}
4423 	if (tracks == 0 && (*flagsp & (F_LOAD|F_DLCK|F_EJECT|F_BLANK|F_FORMAT)) == 0) {
4424 		errmsgno(EX_BAD, _("No tracks specified. Need at least one.\n"));
4425 		susage(EX_BAD);
4426 	}
4427 }
4428 
4429 LOCAL int
default_wr_mode(tracks,trackp,flagsp,wmp,flags)4430 default_wr_mode(tracks, trackp, flagsp, wmp, flags)
4431 	int	tracks;
4432 	track_t	*trackp;
4433 	UInt32_t *flagsp;
4434 	int	*wmp;
4435 	int	flags;
4436 {
4437 	if (tracks == 0 && (*wmp == 0)) {
4438 		errmsgno(EX_BAD, _("No write mode specified.\n"));
4439 		errmsgno(EX_BAD, _("Assuming %s mode.\n"),
4440 				(*flagsp & F_MULTI)?"-tao":"-sao");
4441 		if ((*flagsp & F_MULTI) == 0)
4442 			errmsgno(EX_BAD, _("If your drive does not accept -sao, try -tao.\n"));
4443 		errmsgno(EX_BAD, _("Future versions of cdrecord may have different drive dependent defaults.\n"));
4444 		if (*flagsp & F_MULTI) {
4445 			*wmp |= M_TAO;
4446 		} else {
4447 			*flagsp |= F_SAO;
4448 			trackp[0].flags &= ~TI_TAO;
4449 			trackp[0].flags |= TI_SAO;
4450 			flags &= ~TI_TAO;
4451 			flags |= TI_SAO;
4452 			*wmp |= M_SAO;
4453 		}
4454 	}
4455 	return (flags);
4456 }
4457 
4458 LOCAL void
etracks(opt)4459 etracks(opt)
4460 	char	*opt;
4461 {
4462 	errmsgno(EX_BAD, _("No tracks allowed with '-%s'.\n"), opt);
4463 	susage(EX_BAD);
4464 }
4465 
4466 LOCAL void
set_trsizes(dp,tracks,trackp)4467 set_trsizes(dp, tracks, trackp)
4468 	cdr_t	*dp;
4469 	int	tracks;
4470 	track_t	*trackp;
4471 {
4472 	int	i;
4473 	int	secsize;
4474 	int	secspt;
4475 
4476 	trackp[1].flags		|= TI_FIRST;
4477 	trackp[tracks].flags	|= TI_LAST;
4478 
4479 	if (xdebug)
4480 		printf(_("Set Transfersizes start\n"));
4481 	for (i = 0; i <= tracks+1; i++) {
4482 		if ((dp->cdr_flags & CDR_SWABAUDIO) != 0 &&
4483 					is_audio(&trackp[i])) {
4484 			trackp[i].flags ^= TI_SWAB;
4485 		}
4486 		if (!is_audio(&trackp[i]))
4487 			trackp[i].flags &= ~TI_SWAB;	/* Only swab audio  */
4488 
4489 		/*
4490 		 * Use the biggest sector size to compute how many
4491 		 * sectors may fit into one single DMA buffer.
4492 		 */
4493 		secsize = trackp[i].secsize;
4494 		if (trackp[i].isecsize > secsize)
4495 			secsize = trackp[i].isecsize;
4496 
4497 		/*
4498 		 * We are using SCSI Group 0 write
4499 		 * and cannot write more than 255 secs at once.
4500 		 */
4501 		secspt = bufsize/secsize;
4502 		secspt = min(255, secspt);
4503 		trackp[i].secspt = secspt;
4504 
4505 		if (is_packet(&trackp[i]) && trackp[i].pktsize > 0) {
4506 			if (trackp[i].secspt >= trackp[i].pktsize) {
4507 				trackp[i].secspt = trackp[i].pktsize;
4508 			} else {
4509 				comerrno(EX_BAD,
4510 					_("Track %d packet size %d exceeds buffer limit of %d sectors"),
4511 					i, trackp[i].pktsize, trackp[i].secspt);
4512 			}
4513 		}
4514 		if (xdebug) {
4515 			printf(_("Track %d flags %X secspt %d secsize: %d isecsize: %d\n"),
4516 				i, trackp[i].flags, trackp[i].secspt,
4517 				trackp[i].secsize, trackp[i].isecsize);
4518 		}
4519 	}
4520 	if (xdebug)
4521 		printf(_("Set Transfersizes end\n"));
4522 }
4523 
4524 EXPORT void
load_media(scgp,dp,doexit)4525 load_media(scgp, dp, doexit)
4526 	SCSI	*scgp;
4527 	cdr_t	*dp;
4528 	BOOL	doexit;
4529 {
4530 	int	code;
4531 	int	key;
4532 	int	err;
4533 	BOOL	immed = (dp->cdr_cmdflags&F_IMMED) != 0;
4534 
4535 	/*
4536 	 * Do some preparation before...
4537 	 */
4538 	scgp->silent++;			/* Be quiet if this fails		*/
4539 	test_unit_ready(scgp);		/* First eat up unit attention		*/
4540 	if ((*dp->cdr_load)(scgp, dp) < 0) {	/* now try to load media and	*/
4541 		if (!doexit)
4542 			return;
4543 		comerrno(EX_BAD, _("Cannot load media.\n"));
4544 	}
4545 	scsi_start_stop_unit(scgp, 1, 0, immed); /* start unit in silent mode	*/
4546 	scgp->silent--;
4547 
4548 	if (!wait_unit_ready(scgp, 60)) {
4549 		code = scg_sense_code(scgp);
4550 		key = scg_sense_key(scgp);
4551 		scgp->silent++;
4552 		scsi_prevent_removal(scgp, 0); /* In case someone locked it */
4553 		scgp->silent--;
4554 
4555 		if (!doexit)
4556 			return;
4557 		if (key == SC_NOT_READY && (code == 0x3A || code == 0x30))
4558 			comerrno(EX_BAD, _("No disk / Wrong disk!\n"));
4559 		comerrno(EX_BAD, _("CD/DVD/BD-Recorder not ready.\n"));
4560 	}
4561 
4562 	scsi_prevent_removal(scgp, 1);
4563 	scsi_start_stop_unit(scgp, 1, 0, immed);
4564 	wait_unit_ready(scgp, 120);
4565 	/*
4566 	 * Linux-2.6.8.1 did break the SCSI pass through kernel interface.
4567 	 * Since then, many SCSI commands are filtered away by the Linux kernel
4568 	 * if we do not have root privilleges. Since REZERO UNIT is in the list
4569 	 * of filtered SCSI commands, it is a good indicator on whether we run
4570 	 * with the needed privileges. Failing here is better than failing later
4571 	 * with e.g. vendor unique commands, where cdrecord would miss
4572 	 * functionality or fail completely after starting to write.
4573 	 */
4574 	seterrno(0);
4575 	scgp->silent++;
4576 	code = rezero_unit(scgp); /* Not supported by some drives */
4577 	scgp->silent--;
4578 	err = geterrno();
4579 	if (code < 0 && (err == EPERM || err == EACCES)) {
4580 		linuxcheck();	/* For version 1.417 of cdrecord.c */
4581 		scg_openerr("");
4582 	}
4583 
4584 
4585 	test_unit_ready(scgp);
4586 	scsi_start_stop_unit(scgp, 1, 0, immed);
4587 	wait_unit_ready(scgp, 120);
4588 }
4589 
4590 EXPORT void
unload_media(scgp,dp,flags)4591 unload_media(scgp, dp, flags)
4592 	SCSI	*scgp;
4593 	cdr_t	*dp;
4594 	UInt32_t flags;
4595 {
4596 	scsi_prevent_removal(scgp, 0);
4597 	if ((flags & F_EJECT) != 0) {
4598 		if ((*dp->cdr_unload)(scgp, dp) < 0)
4599 			errmsgno(EX_BAD, _("Cannot eject media.\n"));
4600 	}
4601 }
4602 
4603 EXPORT void
reload_media(scgp,dp)4604 reload_media(scgp, dp)
4605 	SCSI	*scgp;
4606 	cdr_t	*dp;
4607 {
4608 	char	ans[2];
4609 #ifdef	F_GETFL
4610 	int	f = -1;
4611 #endif
4612 
4613 	errmsgno(EX_BAD, _("Drive needs to reload the media to return to proper status.\n"));
4614 	unload_media(scgp, dp, F_EJECT);
4615 
4616 	/*
4617 	 * Note that even Notebook drives identify as CDR_TRAYLOAD
4618 	 */
4619 	if ((dp->cdr_flags & CDR_TRAYLOAD) != 0) {
4620 		scgp->silent++;
4621 		load_media(scgp, dp, FALSE);
4622 		scgp->silent--;
4623 	}
4624 
4625 	scgp->silent++;
4626 	if (((dp->cdr_flags & CDR_TRAYLOAD) == 0) ||
4627 				!wait_unit_ready(scgp, 5)) {
4628 		static FILE	*tty = NULL;
4629 
4630 		printf(_("Re-load disk and hit <CR>"));
4631 		if (isgui)
4632 			printf("\n");
4633 		flush();
4634 
4635 		if (tty == NULL) {
4636 			tty = stdin;
4637 			if ((dp->cdr_cmdflags & F_STDIN) != 0)
4638 				tty = fileluopen(STDERR_FILENO, "rw");
4639 		}
4640 #ifdef	F_GETFL
4641 		if (tty != NULL)
4642 			f = fcntl(fileno(tty), F_GETFL, 0);
4643 		if (f < 0 || (f & O_ACCMODE) == O_WRONLY) {
4644 #ifdef	SIGUSR1
4645 			signal(SIGUSR1, catchsig);
4646 			printf(_("Controlling file not open for reading, send SIGUSR1 to continue.\n"));
4647 			flush();
4648 			pause();
4649 #endif
4650 		} else
4651 #endif
4652 		if (fgetline(tty, ans, 1) < 0)
4653 			comerrno(EX_BAD, _("Aborted by EOF on input.\n"));
4654 	}
4655 	scgp->silent--;
4656 
4657 	load_media(scgp, dp, TRUE);
4658 }
4659 
4660 EXPORT void
set_secsize(scgp,secsize)4661 set_secsize(scgp, secsize)
4662 	SCSI	*scgp;
4663 	int	secsize;
4664 {
4665 	if (secsize > 0) {
4666 		/*
4667 		 * Try to restore the old sector size.
4668 		 */
4669 		scgp->silent++;
4670 		select_secsize(scgp, secsize);
4671 		scgp->silent--;
4672 	}
4673 }
4674 
4675 /*
4676  * Carefully read the drive buffer.
4677  * Work around the inability to get the DMA residual count on Linux.
4678  */
4679 LOCAL int
_read_buffer(scgp,size)4680 _read_buffer(scgp, size)
4681 	SCSI	*scgp;
4682 	int	size;
4683 {
4684 	buf[size-2] = (char)0x55; buf[size-1] = (char)0xFF;
4685 	if (read_buffer(scgp, buf, size, 0) < 0 ||
4686 	    scg_getresid(scgp) != 0) {
4687 		errmsgno(EX_BAD,
4688 			_("Warning: 'read buffer' failed, DMA residual count %d.\n"),
4689 			scg_getresid(scgp));
4690 		return (-1);
4691 	}
4692 	/*
4693 	 * Work around unfriendly OS that do not return the
4694 	 * DMA residual count (e.g. Linux).
4695 	 */
4696 	if (buf[size-2] == (char)0x55 || buf[size-1] == (char)0xFF) {
4697 		errmsgno(EX_BAD,
4698 		_("Warning: DMA resid 0 for 'read buffer', actual data is too short.\n"));
4699 		return (-1);
4700 	}
4701 	return (0);
4702 }
4703 
4704 LOCAL int
get_dmaspeed(scgp,dp)4705 get_dmaspeed(scgp, dp)
4706 	SCSI	*scgp;
4707 	cdr_t	*dp;
4708 {
4709 	int	i;
4710 	long	t;
4711 	int	bs;
4712 	int	tsize;
4713 	int	maxdma;
4714 
4715 	fillbytes((caddr_t)buf, 4, '\0');
4716 	tsize = 0;
4717 	scgp->silent++;
4718 	i = read_buffer(scgp, buf, 4, 0);
4719 	scgp->silent--;
4720 	if (i < 0 || scg_getresid(scgp) != 0) {
4721 		errmsgno(EX_BAD, _("Warning: Cannot read drive buffer.\n"));
4722 		return (-1);
4723 	}
4724 	tsize = a_to_u_3_byte(&buf[1]);
4725 	if (tsize <= 0) {
4726 		errmsgno(EX_BAD, _("Warning: Drive returned invalid buffer size.\n"));
4727 		return (-1);
4728 	}
4729 
4730 	bs = bufsize;
4731 	if (tsize < bs)
4732 		bs = tsize;
4733 	if (bs > 0xFFFE)		/* ReadBuffer may hang w. >64k & USB */
4734 		bs = 0xFFFE;		/* Make it an even size < 64k	    */
4735 
4736 	scgp->silent++;
4737 	fillbytes((caddr_t)buf, bs, '\0');
4738 	if (read_buffer(scgp, buf, bs, 0) < 0) {
4739 		scgp->silent--;
4740 		errmsgno(EX_BAD,
4741 			_("Warning: Cannot read %d bytes from drive buffer.\n"),
4742 			bs);
4743 		return (-1);
4744 	}
4745 	for (i = bs-1; i >= 0; i--) {
4746 		if (buf[i] != '\0') {
4747 			break;
4748 		}
4749 	}
4750 	i++;
4751 	maxdma = i;
4752 	fillbytes((caddr_t)buf, bs, 0xFF);
4753 	if (read_buffer(scgp, buf, bs, 0) < 0) {
4754 		scgp->silent--;
4755 		return (-1);
4756 	}
4757 	scgp->silent--;
4758 	for (i = bs-1; i >= 0; i--) {
4759 		if ((buf[i] & 0xFF) != 0xFF) {
4760 			break;
4761 		}
4762 	}
4763 	i++;
4764 	if (i > maxdma)
4765 		maxdma = i;
4766 	if (maxdma < bs && (scg_getresid(scgp) != (bs - maxdma))) {
4767 		errmsgno(EX_BAD, _("Warning: OS does not return a correct DMA residual count.\n"));
4768 		errmsgno(EX_BAD, _("Warning: expected DMA residual count %d but got %d.\n"),
4769 			(bs - maxdma), scg_getresid(scgp));
4770 	}
4771 	/*
4772 	 * Some drives (e.g. 'HL-DT-ST' 'DVD-RAM GSA-H55N') are unreliable.
4773 	 * They return less data than advertized as buffersize (tsize).
4774 	 */
4775 	if (maxdma < bs) {
4776 		errmsgno(EX_BAD, _("Warning: drive returns unreliable data from 'read buffer'.\n"));
4777 		return (-1);
4778 	}
4779 	if (maxdma < bs)
4780 		bs = maxdma;
4781 
4782 	scgp->silent++;
4783 	if (_read_buffer(scgp, bs) < 0) {
4784 		scgp->silent--;
4785 		return (-1);
4786 	}
4787 	scgp->silent--;
4788 
4789 	if (gettimeofday(&starttime, (struct timezone *)0) < 0) {
4790 		errmsg(_("Cannot get DMA start time.\n"));
4791 		return (-1);
4792 	}
4793 
4794 	for (i = 0; i < 100; i++) {
4795 		if (_read_buffer(scgp, bs) < 0)
4796 			return (-1);
4797 	}
4798 	if (gettimeofday(&fixtime, (struct timezone *)0) < 0) {
4799 		errmsg(_("Cannot get DMA stop time.\n"));
4800 		return (-1);
4801 	}
4802 	timevaldiff(&starttime, &fixtime);
4803 	tsize = bs * 100;
4804 	t = fixtime.tv_sec * 1000 + fixtime.tv_usec / 1000;
4805 	if (t <= 0)
4806 		return (-1);
4807 #ifdef	DEBUG
4808 	error("Read Speed: %lu %ld %ld kB/s %ldx CD %ldx DVD %ldx BD\n",
4809 		tsize, t, tsize/t, tsize/t/176, tsize/t/1385, tsize/t/4495);
4810 #endif
4811 
4812 	return (tsize/t);
4813 }
4814 
4815 
4816 LOCAL BOOL
do_opc(scgp,dp,flags)4817 do_opc(scgp, dp, flags)
4818 	SCSI	*scgp;
4819 	cdr_t	*dp;
4820 	UInt32_t flags;
4821 {
4822 	if ((flags & F_DUMMY) == 0 && dp->cdr_opc) {
4823 		if (debug || lverbose) {
4824 			printf(_("Performing OPC...\n"));
4825 			flush();
4826 		}
4827 		if (dp->cdr_opc(scgp, NULL, 0, TRUE) < 0) {
4828 			errmsgno(EX_BAD, _("OPC failed.\n"));
4829 			if ((flags & F_FORCE) == 0)
4830 				return (FALSE);
4831 		}
4832 	}
4833 	return (TRUE);
4834 }
4835 
4836 LOCAL void
check_recovery(scgp,dp,flags)4837 check_recovery(scgp, dp, flags)
4838 	SCSI	*scgp;
4839 	cdr_t	*dp;
4840 	UInt32_t flags;
4841 {
4842 	if ((*dp->cdr_check_recovery)(scgp, dp)) {
4843 		errmsgno(EX_BAD, _("Recovery needed.\n"));
4844 		unload_media(scgp, dp, flags);
4845 		comexit(EX_BAD);
4846 	}
4847 }
4848 
4849 #ifndef	DEBUG
4850 #define	DEBUG
4851 #endif
4852 void
audioread(scgp,dp,flags)4853 audioread(scgp, dp, flags)
4854 	SCSI	*scgp;
4855 	cdr_t	*dp;
4856 	int	flags;
4857 {
4858 #ifdef	DEBUG
4859 	int speed = 1;
4860 	int	oflags = dp->cdr_cmdflags;
4861 
4862 	dp->cdr_cmdflags &= ~F_DUMMY;
4863 	if ((*dp->cdr_set_speed_dummy)(scgp, dp, &speed) < 0)
4864 		comexit(-1);
4865 	dp->cdr_dstat->ds_wspeed = speed; /* XXX Remove 'speed' in future */
4866 	dp->cdr_cmdflags = oflags;
4867 
4868 	if ((*dp->cdr_set_secsize)(scgp, 2352) < 0)
4869 		comexit(-1);
4870 	scgp->cap->c_bsize = 2352;
4871 
4872 	read_scsi(scgp, buf, 1000, 1);
4873 	printf("XXX:\n");
4874 	write(1, buf, 512);
4875 	unload_media(scgp, dp, flags);
4876 	comexit(0);
4877 #endif
4878 }
4879 
4880 LOCAL void
print_msinfo(scgp,dp)4881 print_msinfo(scgp, dp)
4882 	SCSI	*scgp;
4883 	cdr_t	*dp;
4884 {
4885 	long	off = 0;
4886 	long	fa = 0;
4887 
4888 	if ((*dp->cdr_session_offset)(scgp, &off) < 0) {
4889 		errmsgno(EX_BAD, _("Cannot read session offset.\n"));
4890 		return;
4891 	}
4892 	if (lverbose)
4893 		printf(_("session offset: %ld\n"), off);
4894 
4895 	/*
4896 	 * Set the track pointer to NULL in order to signal the driver that we
4897 	 * like to get the next writable address for the next (unwritten)
4898 	 * session.
4899 	 */
4900 	if (dp->cdr_next_wr_address(scgp, (track_t *)0, &fa) < 0) {
4901 		errmsgno(EX_BAD, _("Cannot read first writable address.\n"));
4902 		return;
4903 	}
4904 	printf("%ld,%ld\n", off, fa);
4905 }
4906 
4907 LOCAL void
print_toc(scgp,dp)4908 print_toc(scgp, dp)
4909 	SCSI	*scgp;
4910 	cdr_t	*dp;
4911 {
4912 	int	first;
4913 	int	last;
4914 	long	lba;
4915 	long	xlba;
4916 	struct msf msf;
4917 	int	adr;
4918 	int	control;
4919 	int	mode;
4920 	int	i;
4921 
4922 	scgp->silent++;
4923 	if (read_capacity(scgp) < 0) {
4924 		scgp->silent--;
4925 		errmsgno(EX_BAD, _("Cannot read capacity.\n"));
4926 		return;
4927 	}
4928 	scgp->silent--;
4929 	if (read_tochdr(scgp, dp, &first, &last) < 0) {
4930 		errmsgno(EX_BAD, _("Cannot read TOC/PMA.\n"));
4931 		return;
4932 	}
4933 	printf(_("first: %d last %d\n"), first, last);
4934 	for (i = first; i <= last; i++) {
4935 		read_trackinfo(scgp, i, &lba, &msf, &adr, &control, &mode);
4936 		xlba = -150 +
4937 			msf.msf_frame + (75*msf.msf_sec) + (75*60*msf.msf_min);
4938 		if (xlba == lba/4)
4939 			lba = xlba;
4940 		print_track(i, lba, &msf, adr, control, mode);
4941 	}
4942 	i = 0xAA;
4943 	read_trackinfo(scgp, i, &lba, &msf, &adr, &control, &mode);
4944 	xlba = -150 +
4945 		msf.msf_frame + (75*msf.msf_sec) + (75*60*msf.msf_min);
4946 	if (xlba == lba/4)
4947 		lba = xlba;
4948 	print_track(i, lba, &msf, adr, control, mode);
4949 	if (lverbose > 1) {
4950 		scgp->silent++;
4951 		if (read_cdtext(scgp) < 0)
4952 			errmsgno(EX_BAD, _("No CD-Text or CD-Text unaware drive.\n"));
4953 		scgp->silent++;
4954 	}
4955 }
4956 
4957 LOCAL void
print_track(track,lba,msp,adr,control,mode)4958 print_track(track, lba, msp, adr, control, mode)
4959 	int	track;
4960 	long	lba;
4961 	struct msf *msp;
4962 	int	adr;
4963 	int	control;
4964 	int	mode;
4965 {
4966 	long	lba_512 = lba*4;
4967 
4968 	if (track == 0xAA)
4969 		printf(_("track:lout "));
4970 	else
4971 		printf(_("track: %3d "), track);
4972 
4973 	printf("lba: %9ld (%9ld) %02d:%02d:%02d adr: %X control: %X mode: %d\n",
4974 			lba, lba_512,
4975 			msp->msf_min,
4976 			msp->msf_sec,
4977 			msp->msf_frame,
4978 			adr, control, mode);
4979 }
4980 
4981 #ifdef	HAVE_SYS_PRIOCNTL_H	/* The preferred SYSvR4 schduler */
4982 
4983 #include <sys/procset.h>	/* Needed for SCO Openserver */
4984 #include <sys/priocntl.h>
4985 #include <sys/rtpriocntl.h>
4986 
4987 EXPORT	void
raisepri(pri)4988 raisepri(pri)
4989 	int pri;
4990 {
4991 	int		pid;
4992 	int		classes;
4993 	int		ret;
4994 	pcinfo_t	info;
4995 	pcparms_t	param;
4996 	rtinfo_t	rtinfo;
4997 	rtparms_t	rtparam;
4998 
4999 	pid = getpid();
5000 
5001 	/* get info */
5002 	strcpy(info.pc_clname, "RT");
5003 	classes = priocntl(P_PID, pid, PC_GETCID, (void *)&info);
5004 	if (classes == -1)
5005 		comerr(_("Cannot get priority class id priocntl(PC_GETCID).\n"));
5006 
5007 	movebytes(info.pc_clinfo, &rtinfo, sizeof (rtinfo_t));
5008 
5009 	/* set priority to max */
5010 	rtparam.rt_pri = rtinfo.rt_maxpri - pri;
5011 	rtparam.rt_tqsecs = 0;
5012 	rtparam.rt_tqnsecs = RT_TQDEF;
5013 	param.pc_cid = info.pc_cid;
5014 	movebytes(&rtparam, param.pc_clparms, sizeof (rtparms_t));
5015 	ret = priocntl(P_PID, pid, PC_SETPARMS, (void *)&param);
5016 	if (ret == -1) {
5017 		errmsg(_("WARNING: Cannot set priority class parameters priocntl(PC_SETPARMS).\n"));
5018 		errmsgno(EX_BAD, _("WARNING: This causes a high risk for buffer underruns.\n"));
5019 	}
5020 }
5021 
5022 #else	/* !HAVE_SYS_PRIOCNTL_H */
5023 
5024 #ifdef	USE_POSIX_PRIORITY_SCHEDULING
5025 /*
5026  * The second best choice: POSIX real time scheduling.
5027  */
5028 /*
5029  * XXX Ugly but needed because of a typo in /usr/iclude/sched.h on Linux.
5030  * XXX This should be removed as soon as we are sure that Linux-2.0.29 is gone.
5031  */
5032 #ifdef	__linux
5033 #define	_P	__P
5034 #endif
5035 
5036 #include <sched.h>
5037 
5038 #ifdef	__linux
5039 #undef	_P
5040 #endif
5041 
5042 LOCAL	int
rt_raisepri(pri)5043 rt_raisepri(pri)
5044 	int pri;
5045 {
5046 	struct sched_param scp;
5047 
5048 	/*
5049 	 * Verify that scheduling is available
5050 	 */
5051 #ifdef	_SC_PRIORITY_SCHEDULING
5052 	if (sysconf(_SC_PRIORITY_SCHEDULING) == -1) {
5053 		errmsg(_("WARNING: RR-scheduler not available, disabling.\n"));
5054 		return (-1);
5055 	}
5056 #endif
5057 	fillbytes(&scp, sizeof (scp), '\0');
5058 	scp.sched_priority = sched_get_priority_max(SCHED_RR) - pri;
5059 	if (sched_setscheduler(0, SCHED_RR, &scp) < 0) {
5060 		errmsg(_("WARNING: Cannot set RR-scheduler.\n"));
5061 		return (-1);
5062 	}
5063 	return (0);
5064 }
5065 
5066 #else	/* !USE_POSIX_PRIORITY_SCHEDULING */
5067 
5068 #if defined(__CYGWIN32__) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(_MSC_VER)
5069 /*
5070  * Win32 specific priority settings.
5071  */
5072 /*
5073  * NOTE: Base.h from Cygwin-B20 has a second typedef for BOOL.
5074  *	 We define BOOL to make all local code use BOOL
5075  *	 from Windows.h and use the hidden __SBOOL for
5076  *	 our global interfaces.
5077  *
5078  * NOTE: windows.h from Cygwin-1.x includes a structure field named sample,
5079  *	 so me may not define our own 'sample' or need to #undef it now.
5080  *	 With a few nasty exceptions, Microsoft assumes that any global
5081  *	 defines or identifiers will begin with an Uppercase letter, so
5082  *	 there may be more of these problems in the future.
5083  *
5084  * NOTE: windows.h defines interface as an alias for struct, this
5085  *	 is used by COM/OLE2, I guess it is class on C++
5086  *	 We man need to #undef 'interface'
5087  *
5088  *	 These workarounds are now applied in schily/windows.h
5089  */
5090 #include <schily/windows.h>
5091 #undef interface
5092 
5093 LOCAL	int
rt_raisepri(pri)5094 rt_raisepri(pri)
5095 	int pri;
5096 {
5097 	int prios[] = {THREAD_PRIORITY_TIME_CRITICAL, THREAD_PRIORITY_HIGHEST};
5098 
5099 	/* set priority class */
5100 	if (SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS) == FALSE) {
5101 		errmsgno(EX_BAD, _("No realtime priority class possible.\n"));
5102 		return (-1);
5103 	}
5104 
5105 	/* set thread priority */
5106 	if (pri >= 0 && pri <= 1 && SetThreadPriority(GetCurrentThread(), prios[pri]) == FALSE) {
5107 		errmsgno(EX_BAD, _("Could not set realtime priority.\n"));
5108 		return (-1);
5109 	}
5110 	return (0);
5111 }
5112 
5113 #else
5114 /*
5115  * This OS does not support real time scheduling.
5116  */
5117 LOCAL	int
rt_raisepri(pri)5118 rt_raisepri(pri)
5119 	int pri;
5120 {
5121 	return (-1);
5122 }
5123 
5124 #endif	/* __CYGWIN32__ || __CYGWIN__ || __MINGW32__ */
5125 
5126 #endif	/* !USE_POSIX_PRIORITY_SCHEDULING */
5127 
5128 EXPORT	void
raisepri(pri)5129 raisepri(pri)
5130 	int pri;
5131 {
5132 	if (rt_raisepri(pri) >= 0)
5133 		return;
5134 #if	defined(HAVE_SETPRIORITY) && defined(PRIO_PROCESS)
5135 
5136 	if (setpriority(PRIO_PROCESS, getpid(), -20 + pri) < 0) {
5137 		errmsg(_("WARNING: Cannot set priority using setpriority().\n"));
5138 		errmsgno(EX_BAD, _("WARNING: This causes a high risk for buffer underruns.\n"));
5139 	}
5140 #else
5141 #ifdef	HAVE_DOSSETPRIORITY	/* RT priority on OS/2 */
5142 	/*
5143 	 * Set priority to timecritical 31 - pri (arg)
5144 	 */
5145 	DosSetPriority(0, 3, 31, 0);
5146 	DosSetPriority(0, 3, -pri, 0);
5147 #else
5148 #if	defined(HAVE_NICE) && !defined(__DJGPP__) /* DOS has nice but no multitasking */
5149 	if (nice(-NZERO + pri) == -1) {
5150 		errmsg(_("WARNING: Cannot set priority using nice().\n"));
5151 		errmsgno(EX_BAD, _("WARNING: This causes a high risk for buffer underruns.\n"));
5152 	}
5153 #else
5154 	errmsgno(EX_BAD, _("WARNING: Cannot set priority on this OS.\n"));
5155 	errmsgno(EX_BAD, _("WARNING: This causes a high risk for buffer underruns.\n"));
5156 #endif
5157 #endif
5158 #endif
5159 }
5160 
5161 #endif	/* HAVE_SYS_PRIOCNTL_H */
5162 
5163 #ifdef	HAVE_SELECT
5164 /*
5165  * sys/types.h and sys/time.h are already included.
5166  */
5167 #else	/* !HAVE_SELECT */
5168 #ifdef	HAVE_STROPTS_H
5169 #	include	<stropts.h>
5170 #endif
5171 #ifdef	HAVE_POLL_H
5172 #	include	<poll.h>
5173 #endif
5174 
5175 #ifndef	INFTIM
5176 #define	INFTIM	(-1)
5177 #endif
5178 #endif	/* !HAVE_SELECT */
5179 
5180 #include <schily/select.h>
5181 
5182 LOCAL void
wait_input()5183 wait_input()
5184 {
5185 #ifdef	HAVE_SELECT
5186 	fd_set	in;
5187 #else
5188 #ifdef	HAVE_POLL
5189 	struct pollfd pfd;
5190 #endif
5191 #endif
5192 	if (lverbose)
5193 		printf(_("Waiting for data on stdin...\n"));
5194 #ifdef	HAVE_SELECT
5195 	FD_ZERO(&in);
5196 	FD_SET(STDIN_FILENO, &in);
5197 	select(1, &in, NULL, NULL, 0);
5198 #else
5199 #ifdef	HAVE_POLL
5200 	pfd.fd = STDIN_FILENO;
5201 	pfd.events = POLLIN;
5202 	pfd.revents = 0;
5203 	poll(&pfd, (unsigned long)1, INFTIM);
5204 #endif
5205 #endif
5206 }
5207 
5208 LOCAL void
checkgui()5209 checkgui()
5210 {
5211 	struct stat st;
5212 
5213 	if (fstat(STDERR_FILENO, &st) >= 0 && !S_ISCHR(st.st_mode)) {
5214 		isgui = TRUE;
5215 		if (lverbose > 1)
5216 			printf(_("Using remote (pipe) mode for interactive i/o.\n"));
5217 	}
5218 }
5219 
5220 LOCAL int
getbltype(optstr,typep)5221 getbltype(optstr, typep)
5222 	char	*optstr;
5223 	long	*typep;
5224 {
5225 	if (streql(optstr, "all")) {
5226 		*typep = BLANK_DISC;
5227 	} else if (streql(optstr, "disc")) {
5228 		*typep = BLANK_DISC;
5229 	} else if (streql(optstr, "disk")) {
5230 		*typep = BLANK_DISC;
5231 	} else if (streql(optstr, "fast")) {
5232 		*typep = BLANK_MINIMAL;
5233 	} else if (streql(optstr, "minimal")) {
5234 		*typep = BLANK_MINIMAL;
5235 	} else if (streql(optstr, "track")) {
5236 		*typep = BLANK_TRACK;
5237 	} else if (streql(optstr, "unreserve")) {
5238 		*typep = BLANK_UNRESERVE;
5239 	} else if (streql(optstr, "trtail")) {
5240 		*typep = BLANK_TAIL;
5241 	} else if (streql(optstr, "unclose")) {
5242 		*typep = BLANK_UNCLOSE;
5243 	} else if (streql(optstr, "session")) {
5244 		*typep = BLANK_SESSION;
5245 	} else if (streql(optstr, "help")) {
5246 		blusage(0);
5247 	} else {
5248 		error(_("Illegal blanking type '%s'.\n"), optstr);
5249 		blusage(EX_BAD);
5250 		return (-1);
5251 	}
5252 	return (TRUE);
5253 }
5254 
5255 LOCAL void
print_drflags(dp)5256 print_drflags(dp)
5257 	cdr_t	*dp;
5258 {
5259 	printf(_("Driver flags   : "));
5260 
5261 	if ((dp->cdr_flags2 & CDR2_NOCD) != 0)
5262 		printf("NO-CD ");
5263 	if ((dp->cdr_flags2 & CDR2_BD) != 0)
5264 		printf("BD ");
5265 	if ((dp->cdr_flags & CDR_DVD) != 0)
5266 		printf("DVD ");
5267 
5268 	if ((dp->cdr_flags & CDR_MMC3) != 0)
5269 		printf("MMC-3 ");
5270 	else if ((dp->cdr_flags & CDR_MMC2) != 0)
5271 		printf("MMC-2 ");
5272 	else if ((dp->cdr_flags & CDR_MMC) != 0)
5273 		printf("MMC ");
5274 
5275 	if ((dp->cdr_flags & CDR_SWABAUDIO) != 0)
5276 		printf("SWABAUDIO ");
5277 	if ((dp->cdr_flags & CDR_BURNFREE) != 0)
5278 		printf("BURNFREE ");
5279 	if ((dp->cdr_flags & CDR_VARIREC) != 0)
5280 		printf("VARIREC ");
5281 	if ((dp->cdr_flags & CDR_GIGAREC) != 0)
5282 		printf("GIGAREC ");
5283 	if ((dp->cdr_flags & CDR_AUDIOMASTER) != 0)
5284 		printf("AUDIOMASTER ");
5285 	if ((dp->cdr_flags & CDR_FORCESPEED) != 0)
5286 		printf("FORCESPEED ");
5287 	if ((dp->cdr_flags & CDR_SPEEDREAD) != 0)
5288 		printf("SPEEDREAD ");
5289 	if ((dp->cdr_flags & CDR_DISKTATTOO) != 0)
5290 		printf("DISKTATTOO ");
5291 	if ((dp->cdr_flags & CDR_SINGLESESS) != 0)
5292 		printf("SINGLESESSION ");
5293 	if ((dp->cdr_flags & CDR_HIDE_CDR) != 0)
5294 		printf("HIDECDR ");
5295 	printf("\n");
5296 }
5297 
5298 LOCAL void
print_wrmodes(dp)5299 print_wrmodes(dp)
5300 	cdr_t	*dp;
5301 {
5302 	BOOL	needblank = FALSE;
5303 
5304 	printf("Supported modes: ");
5305 	if ((dp->cdr_flags & CDR_TAO) != 0) {
5306 		printf("TAO");
5307 		needblank = TRUE;
5308 	}
5309 	if ((dp->cdr_flags & CDR_PACKET) != 0) {
5310 		printf("%sPACKET", needblank?" ":"");
5311 		needblank = TRUE;
5312 	}
5313 	if ((dp->cdr_flags & CDR_SAO) != 0) {
5314 		printf("%sSAO", needblank?" ":"");
5315 		needblank = TRUE;
5316 	}
5317 #ifdef	__needed__
5318 	if ((dp->cdr_flags & (CDR_SAO|CDR_SRAW16)) == (CDR_SAO|CDR_SRAW16)) {
5319 		printf("%sSAO/R16", needblank?" ":"");
5320 		needblank = TRUE;
5321 	}
5322 #endif
5323 	if ((dp->cdr_flags & (CDR_SAO|CDR_SRAW96P)) == (CDR_SAO|CDR_SRAW96P)) {
5324 		printf("%sSAO/R96P", needblank?" ":"");
5325 		needblank = TRUE;
5326 	}
5327 	if ((dp->cdr_flags & (CDR_SAO|CDR_SRAW96R)) == (CDR_SAO|CDR_SRAW96R)) {
5328 		printf("%sSAO/R96R", needblank?" ":"");
5329 		needblank = TRUE;
5330 	}
5331 	if ((dp->cdr_flags & (CDR_RAW|CDR_RAW16)) == (CDR_RAW|CDR_RAW16)) {
5332 		printf("%sRAW/R16", needblank?" ":"");
5333 		needblank = TRUE;
5334 	}
5335 	if ((dp->cdr_flags & (CDR_RAW|CDR_RAW96P)) == (CDR_RAW|CDR_RAW96P)) {
5336 		printf("%sRAW/R96P", needblank?" ":"");
5337 		needblank = TRUE;
5338 	}
5339 	if ((dp->cdr_flags & (CDR_RAW|CDR_RAW96R)) == (CDR_RAW|CDR_RAW96R)) {
5340 		printf("%sRAW/R96R", needblank?" ":"");
5341 		needblank = TRUE;
5342 	}
5343 	if ((dp->cdr_flags & CDR_LAYER_JUMP) == CDR_LAYER_JUMP) {
5344 		printf("%sLAYER_JUMP", needblank?" ":"");
5345 		needblank = TRUE;
5346 	}
5347 	printf("\n");
5348 }
5349 
5350 LOCAL BOOL
check_wrmode(dp,wmode,tflags)5351 check_wrmode(dp, wmode, tflags)
5352 	cdr_t	*dp;
5353 	UInt32_t wmode;
5354 	int	tflags;
5355 {
5356 	int	cdflags = dp->cdr_flags;
5357 
5358 	if ((tflags & TI_PACKET) != 0 && (cdflags & CDR_PACKET) == 0) {
5359 		errmsgno(EX_BAD, _("Drive does not support PACKET recording.\n"));
5360 		return (FALSE);
5361 	}
5362 	if ((tflags & TI_TAO) != 0 && (cdflags & CDR_TAO) == 0) {
5363 		errmsgno(EX_BAD, _("Drive does not support TAO recording.\n"));
5364 		return (FALSE);
5365 	}
5366 	if ((wmode & F_SAO) != 0) {
5367 		if ((cdflags & CDR_SAO) == 0) {
5368 			errmsgno(EX_BAD, _("Drive does not support SAO recording.\n"));
5369 			if ((cdflags & CDR_RAW) != 0)
5370 				errmsgno(EX_BAD, _("Try -raw option.\n"));
5371 			return (FALSE);
5372 		}
5373 #ifdef	__needed__
5374 		if ((tflags & TI_RAW16) != 0 && (cdflags & CDR_SRAW16) == 0) {
5375 			errmsgno(EX_BAD, _("Drive does not support SAO/RAW16.\n"));
5376 			goto badsecs;
5377 		}
5378 #endif
5379 		if ((tflags & (TI_RAW|TI_RAW16|TI_RAW96R)) == TI_RAW && (cdflags & CDR_SRAW96P) == 0) {
5380 			errmsgno(EX_BAD, _("Drive does not support SAO/RAW96P.\n"));
5381 			goto badsecs;
5382 		}
5383 		if ((tflags & (TI_RAW|TI_RAW16|TI_RAW96R)) == (TI_RAW|TI_RAW96R) && (cdflags & CDR_SRAW96R) == 0) {
5384 			errmsgno(EX_BAD, _("Drive does not support SAO/RAW96R.\n"));
5385 			goto badsecs;
5386 		}
5387 	}
5388 	if ((wmode & F_RAW) != 0) {
5389 		if ((cdflags & CDR_RAW) == 0) {
5390 			errmsgno(EX_BAD, _("Drive does not support RAW recording.\n"));
5391 			return (FALSE);
5392 		}
5393 		if ((tflags & TI_RAW16) != 0 && (cdflags & CDR_RAW16) == 0) {
5394 			errmsgno(EX_BAD, _("Drive does not support RAW/RAW16.\n"));
5395 			goto badsecs;
5396 		}
5397 		if ((tflags & (TI_RAW|TI_RAW16|TI_RAW96R)) == TI_RAW && (cdflags & CDR_RAW96P) == 0) {
5398 			errmsgno(EX_BAD, _("Drive does not support RAW/RAW96P.\n"));
5399 			goto badsecs;
5400 		}
5401 		if ((tflags & (TI_RAW|TI_RAW16|TI_RAW96R)) == (TI_RAW|TI_RAW96R) && (cdflags & CDR_RAW96R) == 0) {
5402 			errmsgno(EX_BAD, _("Drive does not support RAW/RAW96R.\n"));
5403 			goto badsecs;
5404 		}
5405 	}
5406 	return (TRUE);
5407 
5408 badsecs:
5409 	if ((wmode & F_SAO) != 0)
5410 		cdflags &= ~(CDR_RAW16|CDR_RAW96P|CDR_RAW96R);
5411 	if ((wmode & F_RAW) != 0)
5412 		cdflags &= ~(CDR_SRAW96P|CDR_SRAW96R);
5413 
5414 	if ((cdflags & (CDR_SRAW96R|CDR_RAW96R)) != 0)
5415 		errmsgno(EX_BAD, _("Try -raw96r option.\n"));
5416 	else if ((cdflags & (CDR_SRAW96P|CDR_RAW96P)) != 0)
5417 		errmsgno(EX_BAD, _("Try -raw96p option.\n"));
5418 	else if ((cdflags & CDR_RAW16) != 0)
5419 		errmsgno(EX_BAD, _("Try -raw16 option.\n"));
5420 	return (FALSE);
5421 }
5422 
5423 LOCAL void
set_wrmode(dp,wmode,tflags)5424 set_wrmode(dp, wmode, tflags)
5425 	cdr_t	*dp;
5426 	UInt32_t wmode;
5427 	int	tflags;
5428 {
5429 	dstat_t	*dsp = dp->cdr_dstat;
5430 
5431 	if ((tflags & TI_PACKET) != 0) {
5432 		dsp->ds_wrmode = WM_PACKET;
5433 		return;
5434 	}
5435 	if ((tflags & TI_TAO) != 0) {
5436 		dsp->ds_wrmode = WM_TAO;
5437 		return;
5438 	}
5439 	if ((wmode & F_SAO) != 0) {
5440 		if ((tflags & (TI_RAW|TI_RAW16|TI_RAW96R)) == 0) {
5441 			dsp->ds_wrmode = WM_SAO;
5442 			return;
5443 		}
5444 		if ((tflags & TI_RAW16) != 0) {		/* Is this needed? */
5445 			dsp->ds_wrmode = WM_SAO_RAW16;
5446 			return;
5447 		}
5448 		if ((tflags & (TI_RAW|TI_RAW16|TI_RAW96R)) == TI_RAW) {
5449 			dsp->ds_wrmode = WM_SAO_RAW96P;
5450 			return;
5451 		}
5452 		if ((tflags & (TI_RAW|TI_RAW16|TI_RAW96R)) == (TI_RAW|TI_RAW96R)) {
5453 			dsp->ds_wrmode = WM_SAO_RAW96R;
5454 			return;
5455 		}
5456 	}
5457 	if ((wmode & F_RAW) != 0) {
5458 		if ((tflags & TI_RAW16) != 0) {
5459 			dsp->ds_wrmode = WM_RAW_RAW16;
5460 			return;
5461 		}
5462 		if ((tflags & (TI_RAW|TI_RAW16|TI_RAW96R)) == TI_RAW) {
5463 			dsp->ds_wrmode = WM_RAW_RAW96P;
5464 			return;
5465 		}
5466 		if ((tflags & (TI_RAW|TI_RAW16|TI_RAW96R)) == (TI_RAW|TI_RAW96R)) {
5467 			dsp->ds_wrmode = WM_RAW_RAW96R;
5468 			return;
5469 		}
5470 	}
5471 	dsp->ds_wrmode = WM_NONE;
5472 }
5473 
5474 /*
5475  * I am sorry that even for version 1.417 of cdrecord.c, I am forced to do
5476  * things like this, but defective versions of cdrecord cause a lot of
5477  * work load to me.
5478  *
5479  * Note that the intention to have non bastardized versions.
5480  *
5481  * It is bad to see that in special in the "Linux" business, companies
5482  * prefer a model with many proprietary differing programs
5483  * instead of cooperating with the program authors.
5484  */
5485 #if	defined(linux) || defined(__linux) || defined(__linux__)
5486 #ifdef	HAVE_UNAME
5487 #include <schily/utsname.h>
5488 #endif
5489 #endif
5490 
5491 LOCAL void
linuxcheck()5492 linuxcheck()				/* For version 1.417 of cdrecord.c */
5493 {
5494 #if	defined(linux) || defined(__linux) || defined(__linux__)
5495 #ifdef	HAVE_UNAME
5496 	struct	utsname	un;
5497 
5498 	if (uname(&un) >= 0) {
5499 		if ((un.release[0] == '2' && un.release[1] == '.') &&
5500 		    (un.release[2] > '6' ||
5501 		    (un.release[2] == '6' && un.release[3] == '.' && un.release[4] >= '8'))) {
5502 			errmsgno(EX_BAD,
5503 			_("Warning: Linux-2.6.8 introduced incompatible interface changes.\n"));
5504 			errmsgno(EX_BAD,
5505 			_("Warning: SCSI transport only works for suid root programs.\n"));
5506 
5507 			errmsgno(EX_BAD,
5508 			_("If you have unsolvable problems, please try Linux-2.4 or Solaris.\n"));
5509 		}
5510 	}
5511 #endif
5512 #endif
5513 }
5514 
5515 LOCAL void
priv_warn(what,msg)5516 priv_warn(what, msg)
5517 	const char	*what;
5518 	const char	*msg;
5519 {
5520 	errmsgno(EX_BAD, "Insufficient '%s' privileges. %s\n", what, msg);
5521 }
5522 
5523 #ifdef	TR_DEBUG
5524 EXPORT void
prtrack(trackp)5525 prtrack(trackp)
5526 	track_t	*trackp;
5527 {
5528 	error("Track:		%d\n", (int)(trackp - track_base(trackp)));
5529 	error("xfp:		%p\n", trackp->xfp);
5530 	error("filename:	%s\n", trackp->filename);
5531 	error("itracksize:	%lld\n", (Llong)trackp->itracksize);
5532 	error("tracksize:	%lld\n", (Llong)trackp->tracksize);
5533 	error("trackstart:	%ld\n", trackp->trackstart);
5534 	error("tracksecs:	%ld\n", trackp->tracksecs);
5535 	error("padsecs:	%ld\n", trackp->padsecs);
5536 	error("pregapsize:	%ld\n", trackp->pregapsize);
5537 	error("index0start:	%ld\n", trackp->index0start);
5538 	error("isecsize:	%d\n", trackp->isecsize);
5539 	error("secsize:	%d\n", trackp->secsize);
5540 	error("secspt:		%d\n", trackp->secspt);
5541 	error("pktsize:	%d\n", trackp->pktsize);
5542 	error("dataoff:	%d\n", trackp->dataoff);
5543 	error("tracks:		%d\n", trackp->tracks);
5544 	error("track:		%d\n", trackp->track);
5545 	error("trackno:	%d\n", trackp->trackno);
5546 	error("tracktype:	%d\n", trackp->tracktype);
5547 	error("dbtype:		%d\n", trackp->dbtype);
5548 	error("sectype:	%2.2X\n", trackp->sectype);
5549 	error("flags:		%X\n", trackp->flags);
5550 	error("nindex:		%d\n", trackp->nindex);
5551 
5552 }
5553 #endif
5554