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