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