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