Imported Upstream version 1.1.11
[platform/upstream/cdrkit.git] / wodim / wodim.c
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
270 void fifo_cleanup(void) {
271    kill_faio();
272 }
273
274 /* shared variables */
275 int     scandevs = 0;
276 char    *msifile = NULL;
277
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 
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 
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
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 
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 
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 
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
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 
1759 catchsig(int sig)
1760 {
1761         signal(sig, catchsig);
1762 }
1763
1764 static int 
1765 scsi_cb(void *arg)
1766 {
1767         comexit(EX_BAD);
1768         /* NOTREACHED */
1769         return (0);     /* Keep lint happy */
1770 }
1771
1772 static void 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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