~ubuntu-branches/ubuntu/hoary/cdrtools/hoary

« back to all changes in this revision

Viewing changes to cdrecord/cdrecord.c

  • Committer: Bazaar Package Importer
  • Author(s): Eduard Bloch
  • Date: 2002-04-09 10:03:06 UTC
  • Revision ID: james.westby@ubuntu.com-20020409100306-t4hagiv7gm0fhggv
Tags: upstream-1.10
ImportĀ upstreamĀ versionĀ 1.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* @(#)cdrecord.c       1.119 01/04/19 Copyright 1995-2001 J. Schilling */
 
2
#ifndef lint
 
3
static  char sccsid[] =
 
4
        "@(#)cdrecord.c 1.119 01/04/19 Copyright 1995-2001 J. Schilling";
 
5
#endif
 
6
/*
 
7
 *      Record data on a CD/CVD-Recorder
 
8
 *
 
9
 *      Copyright (c) 1995-2001 J. Schilling
 
10
 */
 
11
/*
 
12
 * This program is free software; you can redistribute it and/or modify
 
13
 * it under the terms of the GNU General Public License as published by
 
14
 * the Free Software Foundation; either version 2, or (at your option)
 
15
 * any later version.
 
16
 *
 
17
 * This program is distributed in the hope that it will be useful,
 
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
20
 * GNU General Public License for more details.
 
21
 *
 
22
 * You should have received a copy of the GNU General Public License
 
23
 * along with this program; see the file COPYING.  If not, write to
 
24
 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 
25
 */
 
26
 
 
27
#include <mconfig.h>
 
28
#include <stdio.h>
 
29
#include <standard.h>
 
30
#include <stdxlib.h>
 
31
#include <fctldefs.h>
 
32
#include <errno.h>
 
33
#include <sys/types.h>
 
34
#include <sys/time.h>
 
35
#ifdef  HAVE_SYS_RESOURCE_H
 
36
#include <sys/resource.h>       /* for rlimit */
 
37
#endif
 
38
#include <sys/stat.h>
 
39
#include <statdefs.h>
 
40
#include <unixstd.h>
 
41
#ifdef  HAVE_SYS_MMAN_H
 
42
#include <sys/mman.h>
 
43
#endif
 
44
#include <strdefs.h>
 
45
#include <utypes.h>
 
46
#include <intcvt.h>
 
47
#include <signal.h>
 
48
#include <schily.h>
 
49
 
 
50
#include <scg/scsireg.h>        /* XXX wegen SC_NOT_READY */
 
51
#include <scg/scsitransp.h>
 
52
#include <scg/scgcmd.h>         /* XXX fuer read_buffer */
 
53
#include "scsi_scan.h"
 
54
 
 
55
#include "auheader.h"
 
56
#include "cdrecord.h"
 
57
 
 
58
char    cdr_version[] = "1.10";
 
59
 
 
60
/*
 
61
 * Map toc/track types into names.
 
62
 */
 
63
char    *toc2name[] = {
 
64
                "CD-DA",
 
65
                "CD-ROM",
 
66
                "CD-ROM XA mode 1",
 
67
                "CD-ROM XA mode 2",
 
68
                "CD-I",
 
69
                "Illegal toc type 5",
 
70
                "Illegal toc type 6",
 
71
                "Illegal toc type 7",
 
72
};
 
73
 
 
74
/*
 
75
 * Map sector types into names.
 
76
 */
 
77
char    *st2name[] = {
 
78
                "Illegal sector type 0",
 
79
                "CD-ROM mode 1",
 
80
                "CD-ROM mode 2",
 
81
                "Illegal sector type 3",
 
82
                "CD-DA without preemphasis",
 
83
                "CD-DA with preemphasis",
 
84
                "Illegal sector type 6",
 
85
                "Illegal sector type 7",
 
86
};
 
87
 
 
88
/*
 
89
 * Map data block types into names.
 
90
 */
 
91
char    *db2name[] = {
 
92
                "Raw (audio)",
 
93
                "Raw (audio) with P/Q sub channel",
 
94
                "Raw (audio) with P/W sub channel",
 
95
                "Raw (audio) with P/W raw sub channel",
 
96
                "Reserved mode 4",
 
97
                "Reserved mode 5",
 
98
                "Reserved mode 6",
 
99
                "Vendor unique mode 7",
 
100
                "CD-ROM mode 1",
 
101
                "CD-ROM mode 2",
 
102
                "CD-ROM XA mode 1",
 
103
                "CD-ROM XA mode 2 form 1",
 
104
                "CD-ROM XA mode 2 form 2",
 
105
                "CD-ROM XA mode 2 form 1/2/mix",
 
106
                "Reserved mode 14",
 
107
                "Vendor unique mode 15",
 
108
};
 
109
 
 
110
int             debug;          /* print debug messages */
 
111
LOCAL   int     kdebug;         /* print kernel debug messages */
 
112
LOCAL   int     scsi_verbose;   /* SCSI verbose flag */
 
113
LOCAL   int     silent;         /* SCSI silent flag */
 
114
int             lverbose;       /* local verbose flag */
 
115
 
 
116
/*
 
117
 * NOTICE:      You should not make BUF_SIZE more than
 
118
 *              the buffer size of the CD-Recorder.
 
119
 *
 
120
 * Do not set BUF_SIZE to be more than 126 KBytes
 
121
 * if you are running cdrecord on a sun4c machine.
 
122
 *
 
123
 * WARNING:     Philips CDD 521 dies if BUF_SIZE is to big.
 
124
 */
 
125
/*#define       BUF_SIZE        (126*1024)*/
 
126
/*#define       BUF_SIZE        (100*1024)*/
 
127
#define BUF_SIZE        (63*1024)
 
128
/*#define       BUF_SIZE        (56*1024)*/
 
129
 
 
130
char    *buf;                   /* The transfer buffer */
 
131
long    bufsize;                /* The size of the transfer buffer */
 
132
int     data_secs_per_tr;       /* # of data secs per transfer */
 
133
int     audio_secs_per_tr;      /* # of audio secs per transfer */
 
134
 
 
135
BOOL    isgui;
 
136
int     didintr;
 
137
char    *driveropts;
 
138
 
 
139
struct timeval  starttime;
 
140
struct timeval  stoptime;
 
141
struct timeval  fixtime;
 
142
 
 
143
static  long    fs = -1L;       /* fifo (ring buffer) size */
 
144
 
 
145
EXPORT  int     main            __PR((int ac, char **av));
 
146
LOCAL   void    usage           __PR((int));
 
147
LOCAL   void    blusage         __PR((int));
 
148
LOCAL   void    intr            __PR((int sig));
 
149
LOCAL   void    intfifo         __PR((int sig));
 
150
LOCAL   void    exscsi          __PR((int excode, void *arg));
 
151
LOCAL   void    excdr           __PR((int excode, void *arg));
 
152
EXPORT  int     read_buf        __PR((int f, char *bp, int size));
 
153
EXPORT  int     get_buf         __PR((int f, char **bpp, int size));
 
154
LOCAL   int     write_track_data __PR((SCSI *scgp, cdr_t *, int , track_t *));
 
155
EXPORT  int     pad_track       __PR((SCSI *scgp, cdr_t *dp, int track, track_t *trackp,
 
156
                                     long startsec, Llong amt,
 
157
                                     BOOL dolast, Llong *bytesp));
 
158
EXPORT  int     write_buf       __PR((SCSI *scgp, cdr_t *dp, int track, track_t *trackp,
 
159
                                     char *bp, long startsec, long amt, int secsize,
 
160
                                     BOOL dolast, long *bytesp));
 
161
LOCAL   void    printdata       __PR((int, track_t *));
 
162
LOCAL   void    printaudio      __PR((int, track_t *));
 
163
LOCAL   void    checkfile       __PR((int, track_t *));
 
164
LOCAL   int     checkfiles      __PR((int, track_t *));
 
165
LOCAL   void    setpregaps      __PR((int, track_t *));
 
166
LOCAL   long    checktsize      __PR((int, track_t *));
 
167
LOCAL   void    checksize       __PR((track_t *));
 
168
LOCAL   BOOL    checkdsize      __PR((SCSI *scgp, cdr_t *dp, dstat_t *dsp, long tsize, int flags));
 
169
LOCAL   void    raise_fdlim     __PR((void));
 
170
LOCAL   void    gargs           __PR((int, char **, int *, track_t *, char **,
 
171
                                        int *, cdr_t **,
 
172
                                        int *, long *, int *, int *));
 
173
LOCAL   void    set_trsizes     __PR((cdr_t *, int, track_t *));
 
174
EXPORT  void    load_media      __PR((SCSI *scgp, cdr_t *, BOOL));
 
175
EXPORT  void    unload_media    __PR((SCSI *scgp, cdr_t *, int));
 
176
EXPORT  void    set_secsize     __PR((SCSI *scgp, int secsize));
 
177
LOCAL   void    check_recovery  __PR((SCSI *scgp, cdr_t *, int));
 
178
        void    audioread       __PR((SCSI *scgp, cdr_t *, int));
 
179
LOCAL   void    print_msinfo    __PR((SCSI *scgp, cdr_t *));
 
180
LOCAL   void    print_toc       __PR((SCSI *scgp, cdr_t *));
 
181
LOCAL   void    print_track     __PR((int, long, struct msf *, int, int, int));
 
182
LOCAL   void    prtimediff      __PR((const char *fmt,
 
183
                                        struct timeval *start,
 
184
                                        struct timeval *stop));
 
185
#if !defined(HAVE_SYS_PRIOCNTL_H)
 
186
LOCAL   int     rt_raisepri     __PR((int));
 
187
#endif
 
188
EXPORT  void    raisepri        __PR((int));
 
189
LOCAL   void    wait_input      __PR((void));
 
190
LOCAL   void    checkgui        __PR((void));
 
191
LOCAL   Llong   number          __PR((char* arg, int* retp));
 
192
EXPORT  int     getnum          __PR((char* arg, long* valp));
 
193
EXPORT  int     getllnum        __PR((char *arg, Llong* lvalp));
 
194
LOCAL   int     getbltype       __PR((char* optstr, long *typep));
 
195
 
 
196
struct exargs {
 
197
        SCSI    *scgp;
 
198
        cdr_t   *dp;
 
199
        int     old_secsize;
 
200
        int     flags;
 
201
        int     exflags;
 
202
} exargs;
 
203
 
 
204
EXPORT int 
 
205
main(ac, av)
 
206
        int     ac;
 
207
        char    *av[];
 
208
{
 
209
        char    *dev = NULL;
 
210
        int     timeout = 40;   /* Set default timeout to 40s CW-7502 is slow*/
 
211
        int     speed = 1;
 
212
        long    flags = 0L;
 
213
        int     toctype = -1;
 
214
        int     blanktype = 0;
 
215
        int     i;
 
216
        int     tracks = 0;
 
217
        int     trackno;
 
218
        long    tsize;
 
219
        track_t track[MAX_TRACK+2];     /* Max tracks + track 0 + track AA */
 
220
        cdr_t   *dp = (cdr_t *)0;
 
221
        dstat_t ds;
 
222
        long    startsec = 0L;
 
223
        int     errs = 0;
 
224
        SCSI    *scgp;
 
225
        char    errstr[80];
 
226
 
 
227
#ifdef __EMX__ 
 
228
        /* This gives wildcard expansion with Non-Posix shells with EMX */ 
 
229
        _wildcard(&ac, &av); 
 
230
#endif 
 
231
        save_args(ac, av);
 
232
 
 
233
        fillbytes(track, sizeof(track), '\0');
 
234
        raise_fdlim();
 
235
        gargs(ac, av, &tracks, track, &dev, &timeout, &dp, &speed, &flags,
 
236
                                                        &toctype, &blanktype);
 
237
        if (toctype < 0)
 
238
                comerrno(EX_BAD, "Internal error: Bad TOC type.\n");
 
239
 
 
240
        /*
 
241
         * Warning: you are not allowed to modify or to remove this
 
242
         * version printing code!
 
243
         */
 
244
#ifdef  DRV_DVD
 
245
        i = set_cdrcmds("mmc_dvd", (cdr_t **)NULL);
 
246
#endif
 
247
        if ((flags & F_MSINFO) == 0 || lverbose || flags & F_VERSION)
 
248
                printf("Cdrecord%s %s (%s-%s-%s) Copyright (C) 1995-2001 Jļæ½rg Schilling\n",
 
249
#ifdef  DRV_DVD
 
250
                                                                i?"-ProDVD":"",
 
251
#else
 
252
                                                                "",
 
253
#endif
 
254
                                                                cdr_version,
 
255
                                                                HOST_CPU, HOST_VENDOR, HOST_OS);
 
256
        if (flags & F_VERSION)
 
257
                exit(0);
 
258
 
 
259
        checkgui();
 
260
 
 
261
        if (debug || lverbose) {
 
262
                printf("TOC Type: %d = %s\n",
 
263
                        toctype, toc2name[toctype & TOC_MASK]);
 
264
        }
 
265
 
 
266
        if ((flags & (F_MSINFO|F_TOC|F_PRATIP|F_FIX|F_VERSION|F_CHECKDRIVE|F_INQUIRY|F_SCANBUS|F_RESET)) == 0) {
 
267
                /*
 
268
                 * Try to lock us im memory (will only work for root)
 
269
                 * but you need access to root anyway to use /dev/scg?
 
270
                 */
 
271
#if defined(HAVE_MLOCKALL) || defined(_POSIX_MEMLOCK)
 
272
                if (mlockall(MCL_CURRENT|MCL_FUTURE) < 0) {
 
273
                        errmsg("WARNING: Cannot do mlockall(2).\n");
 
274
                        errmsgno(EX_BAD, "WARNING: This causes a high risk for buffer underruns.\n");
 
275
                }
 
276
#endif
 
277
 
 
278
                raisepri(0); /* max priority */
 
279
                init_fifo(fs);
 
280
        }
 
281
 
 
282
        if ((flags & F_WAITI) != 0) {
 
283
                if (lverbose)
 
284
                        printf("Waiting for data on stdin...\n");
 
285
                wait_input();
 
286
        }
 
287
 
 
288
        /*
 
289
         * Call scg_remote() to force loading the remote SCSI transport library
 
290
         * code that is located in librscg instead of the dummy remote routines
 
291
         * that are located inside libscg.
 
292
         */
 
293
        scg_remote();
 
294
        if ((scgp = scg_open(dev, errstr, sizeof(errstr),
 
295
                                debug, (flags & F_MSINFO) == 0 || lverbose)) == (SCSI *)0) {
 
296
                        errmsg("%s%sCannot open SCSI driver.\n", errstr, errstr[0]?". ":"");
 
297
                        comerrno(EX_BAD, "For possible targets try 'cdrecord -scanbus'. Make sure you are root.\n");
 
298
        }
 
299
        scg_settimeout(scgp, timeout);
 
300
        scgp->verbose = scsi_verbose;
 
301
        scgp->silent = silent;
 
302
        scgp->debug = debug;
 
303
        scgp->kdebug = kdebug;
 
304
        scgp->cap->c_bsize = 2048;
 
305
 
 
306
 
 
307
        if ((flags & F_MSINFO) == 0 || lverbose) {
 
308
                char    *vers;
 
309
                char    *auth;
 
310
 
 
311
                /*
 
312
                 * Warning: you are not allowed to modify or to remove this 
 
313
                 * version checking code!
 
314
                 */
 
315
                vers = scg_version(0, SCG_VERSION);
 
316
                auth = scg_version(0, SCG_AUTHOR);
 
317
                printf("Using libscg version '%s-%s'\n", auth, vers);
 
318
                if (auth == 0 || strcmp("schily", auth) != 0) {
 
319
                        errmsgno(EX_BAD,
 
320
                        "Warning: using inofficial version of libscg (%s-%s '%s').\n",
 
321
                                auth, vers, scg_version(0, SCG_SCCS_ID));
 
322
                }
 
323
 
 
324
                vers = scg_version(scgp, SCG_VERSION);
 
325
                auth = scg_version(scgp, SCG_AUTHOR);
 
326
                if (lverbose > 1)
 
327
                        error("Using libscg transport code version '%s-%s'\n", auth, vers);
 
328
                if (auth == 0 || strcmp("schily", auth) != 0) {
 
329
                        errmsgno(EX_BAD,
 
330
                        "Warning: using inofficial libscg transport code version (%s-%s '%s').\n",
 
331
                                auth, vers, scg_version(scgp, SCG_SCCS_ID));
 
332
                }
 
333
 
 
334
                vers = scg_version(scgp, SCG_RVERSION);
 
335
                auth = scg_version(scgp, SCG_RAUTHOR);
 
336
                if (lverbose > 1 && vers && auth)
 
337
                        error("Using remote transport code version '%s-%s'\n", auth, vers);
 
338
                if (auth != 0 && strcmp("schily", auth) != 0) {
 
339
                        errmsgno(EX_BAD,
 
340
                        "Warning: using inofficial remote transport code version (%s-%s '%s').\n",
 
341
                                auth, vers, scg_version(scgp, SCG_RSCCS_ID));
 
342
                }
 
343
        }
 
344
        if (lverbose && driveropts)
 
345
                printf("Driveropts: '%s'\n", driveropts);
 
346
 
 
347
        bufsize = scg_bufsize(scgp, BUF_SIZE);
 
348
        if (debug)
 
349
                error("SCSI buffer size: %ld\n", bufsize);
 
350
        if ((buf = scg_getbuf(scgp, bufsize)) == NULL)
 
351
                comerr("Cannot get SCSI I/O buffer.\n");
 
352
 
 
353
        if ((flags & F_SCANBUS) != 0) {
 
354
                select_target(scgp, stdout);
 
355
                exit(0);
 
356
        }
 
357
        if ((flags & F_RESET) != 0) {
 
358
                if (scg_reset(scgp, SCG_RESET_NOP) < 0)
 
359
                        comerr("Cannot reset (OS does not implement reset).\n");
 
360
                if (scg_reset(scgp, SCG_RESET_TGT) >= 0)
 
361
                        exit(0);
 
362
                if (scg_reset(scgp, SCG_RESET_BUS) < 0)
 
363
                        comerr("Cannot reset target.\n");
 
364
                exit(0);
 
365
        }
 
366
        /*
 
367
         * First try to check which type of SCSI device we
 
368
         * have.
 
369
         */
 
370
        if (debug || lverbose)
 
371
                printf("atapi: %d\n", scg_isatapi(scgp));
 
372
        scgp->silent++;
 
373
        test_unit_ready(scgp);  /* eat up unit attention */
 
374
        scgp->silent--;
 
375
        if (!do_inquiry(scgp, (flags & F_MSINFO) == 0 || lverbose)) {
 
376
                errmsgno(EX_BAD, "Cannot do inquiry for CD/DVD-Recorder.\n");
 
377
                if (unit_ready(scgp))
 
378
                        errmsgno(EX_BAD, "The unit seems to be hung and needs power cycling.\n");
 
379
                exit(EX_BAD);
 
380
        }
 
381
 
 
382
        if ((flags & F_PRCAP) != 0) {
 
383
                print_capabilities(scgp);
 
384
                exit(0);
 
385
        }
 
386
        if ((flags & F_INQUIRY) != 0)
 
387
                exit(0);
 
388
 
 
389
        if (dp == (cdr_t *)NULL) {      /* No driver= option specified */
 
390
                dp = get_cdrcmds(scgp);
 
391
        } else if (!is_unknown_dev(scgp) && dp != get_cdrcmds(scgp)) {
 
392
                errmsgno(EX_BAD, "WARNING: Trying to use other driver on known device.\n");
 
393
        }
 
394
 
 
395
        if (!is_cddrive(scgp))
 
396
                comerrno(EX_BAD, "Sorry, no CD/DVD-Drive found on this target.\n");
 
397
        if (dp == (cdr_t *)0)
 
398
                comerrno(EX_BAD, "Sorry, no supported CD/DVD-Recorder found on this target.\n");
 
399
 
 
400
        if (((flags & (F_MSINFO|F_TOC|F_LOAD|F_EJECT)) == 0 || tracks > 0) &&
 
401
                                        (dp->cdr_flags & CDR_ISREADER) != 0) {
 
402
                BOOL    is_dvdr = FALSE;
 
403
 
 
404
                errmsgno(EX_BAD,
 
405
                "Sorry, no CD/DVD-Recorder or unsupported CD/DVD-Recorder found on this target.\n");
 
406
 
 
407
                is_mmc(scgp, &is_dvdr);
 
408
                if (is_dvdr && !set_cdrcmds("mmc_dvd", (cdr_t **)NULL)) {
 
409
                        errmsgno(EX_BAD,
 
410
                        "This version of cdrecord does not include DVD-R support code.\n");
 
411
                        errmsgno(EX_BAD,
 
412
                        "If you need DVD-R support, ask the Author for cdrecord-ProDVD.\n");
 
413
                }
 
414
                exit(EX_BAD);
 
415
        }
 
416
 
 
417
        if ((*dp->cdr_attach)(scgp, dp) != 0)
 
418
                comerrno(EX_BAD, "Cannot attach driver for CD/DVD-Recorder.\n");
 
419
 
 
420
        exargs.scgp        = scgp;
 
421
        exargs.dp          = dp;
 
422
        exargs.old_secsize = -1;
 
423
        exargs.flags       = flags;
 
424
 
 
425
        if ((flags & F_MSINFO) == 0 || lverbose) {
 
426
                printf("Using %s (%s).\n", dp->cdr_drtext, dp->cdr_drname);
 
427
                printf("Driver flags   : ");
 
428
                if ((dp->cdr_flags & CDR_SWABAUDIO) != 0)
 
429
                        printf("SWABAUDIO");
 
430
                printf("\n");
 
431
        }
 
432
        scgp->silent++;
 
433
        if ((debug || lverbose)) {
 
434
                tsize = -1;
 
435
                if ((*dp->cdr_buffer_cap)(scgp, &tsize, (long *)0) < 0 || tsize <= 0) {
 
436
                        if (read_buffer(scgp, buf, 4, 0) >= 0)
 
437
                                tsize = a_to_u_4_byte(buf);
 
438
                }
 
439
                if (tsize > 0) {
 
440
                        printf("Drive buf size : %lu = %lu KB\n",
 
441
                                                tsize, tsize >> 10);
 
442
                }
 
443
        }
 
444
        scgp->silent--;
 
445
 
 
446
        if (tracks > 0 && (debug || lverbose))
 
447
                printf("FIFO size      : %lu = %lu KB\n", fs, fs >> 10);
 
448
 
 
449
        if ((flags & F_CHECKDRIVE) != 0)
 
450
                exit(0);
 
451
 
 
452
        if (tracks == 0 && (flags & (F_FIX|F_BLANK)) == 0 && (flags & F_EJECT) != 0) {
 
453
                /*
 
454
                 * Do not check if the unit is ready here to allow to open
 
455
                 * an empty unit too.
 
456
                 */
 
457
                unload_media(scgp, dp, flags);
 
458
                exit(0);
 
459
        }
 
460
 
 
461
        flush();
 
462
        if (tracks > 1)
 
463
                sleep(2);       /* Let the user watch the inquiry messages */
 
464
 
 
465
        set_trsizes(dp, tracks, track);
 
466
        setpregaps(tracks, track);
 
467
        checkfiles(tracks, track);
 
468
        tsize = checktsize(tracks, track);
 
469
do_cue(tracks, track, 0);
 
470
 
 
471
        /*
 
472
         * Is this the right place to do this ?
 
473
         */
 
474
        check_recovery(scgp, dp, flags);
 
475
 
 
476
        if ((flags & F_FORCE) == 0)
 
477
                load_media(scgp, dp, TRUE);
 
478
 
 
479
        if ((flags & F_LOAD) != 0) {
 
480
                scgp->silent++;                 /* silently          */
 
481
                scsi_prevent_removal(scgp, 0);  /* allow manual open */
 
482
                scgp->silent--;                 /* if load failed... */
 
483
                exit(0);
 
484
        }
 
485
        exargs.old_secsize = sense_secsize(scgp, 1);
 
486
        if (exargs.old_secsize < 0)
 
487
                exargs.old_secsize = sense_secsize(scgp, 0);
 
488
        if (debug)
 
489
                printf("Current Secsize: %d\n", exargs.old_secsize);
 
490
        scgp->silent++;
 
491
        read_capacity(scgp);
 
492
        scgp->silent--;
 
493
        if (exargs.old_secsize < 0)
 
494
                exargs.old_secsize = scgp->cap->c_bsize;
 
495
        if (exargs.old_secsize != scgp->cap->c_bsize)
 
496
                errmsgno(EX_BAD, "Warning: blockdesc secsize %d differs from cap secsize %d\n",
 
497
                                exargs.old_secsize, scgp->cap->c_bsize);
 
498
 
 
499
        on_comerr(exscsi, &exargs);
 
500
 
 
501
        if (lverbose)
 
502
                printf("Current Secsize: %d\n", exargs.old_secsize);
 
503
 
 
504
        if (exargs.old_secsize > 0 && exargs.old_secsize != 2048) {
 
505
                /*
 
506
                 * Some drives (e.g. Plextor) don't like to write correctly
 
507
                 * in DAO mode if the sector size is set to 512 bytes.
 
508
                 * In addition, cdrecord -msinfo will not work properly
 
509
                 * if the sector size is not 2048 bytes.
 
510
                 */
 
511
                set_secsize(scgp, 2048);
 
512
        }
 
513
 
 
514
/*audioread(dp, flags);*/
 
515
/*unload_media(scgp, dp, flags);*/
 
516
/*return 0;*/
 
517
        fillbytes(&ds, sizeof(ds), '\0');
 
518
        if (flags & F_WRITE)
 
519
                ds.ds_cdrflags = RF_WRITE;
 
520
        if (flags & F_PRATIP) {
 
521
                lverbose++;                     /* XXX Hack */
 
522
        }
 
523
        if ((*dp->cdr_getdisktype)(scgp, dp, &ds) < 0) {
 
524
                errmsgno(EX_BAD, "Cannot get disk type.\n");
 
525
                exscsi(EX_BAD, &exargs);
 
526
                if ((flags & F_FORCE) == 0)
 
527
                        exit(EX_BAD);
 
528
        }
 
529
        if (flags & F_PRATIP) {
 
530
                lverbose--;                     /* XXX Hack */
 
531
                exscsi(0, &exargs);
 
532
                exit(0);
 
533
        }
 
534
        /*
 
535
         * The next actions should depend on the disk type.
 
536
         */
 
537
 
 
538
        /*
 
539
         * Dirty hack!
 
540
         * At least MMC drives will not return the next writable
 
541
         * address we expect when the drive's write mode is set
 
542
         * to DAO/SAO. We need this address for mkisofs and thus
 
543
         * it must be the first user accessible sector and not the
 
544
         * first sector of the pregap. Set_speed_dummy() witha a
 
545
         * 'speedp' f 0 sets the write mode to TAO on MMC drives.
 
546
         *
 
547
         * We set TAO unconditionally to make checkdsize() work
 
548
         * currectly in DAO mode too.
 
549
         *
 
550
         * XXX The ACER drive:
 
551
         * XXX Vendor_info    : 'ATAPI   '
 
552
         * XXX Identifikation : 'CD-R/RW 8X4X32  '
 
553
         * XXX Revision       : '5.EW'
 
554
         * XXX Will not return from -dummy to non-dummy without
 
555
         * XXX opening the tray.
 
556
         */
 
557
        scgp->silent++;
 
558
        (*dp->cdr_set_speed_dummy)(scgp, 0, flags & F_DUMMY);
 
559
        scgp->silent--;
 
560
 
 
561
        if (flags & F_MSINFO) {
 
562
                print_msinfo(scgp, dp);
 
563
                exscsi(0, &exargs);
 
564
                exit(0);
 
565
        }
 
566
        if (flags & F_TOC) {
 
567
                print_toc(scgp, dp);
 
568
                exscsi(0, &exargs);
 
569
                exit(0);
 
570
        }
 
571
 
 
572
#ifdef  XXX
 
573
        if ((*dp->cdr_check_session)() < 0) {
 
574
                exscsi(EX_BAD, &exargs);
 
575
                exit(EX_BAD);
 
576
        }
 
577
#endif
 
578
        if (tsize == 0) {
 
579
                if (tracks > 0) {
 
580
                        errmsgno(EX_BAD,
 
581
                        "WARNING: Track size unknown. Data may not fit on disk.\n");
 
582
                }
 
583
        } else if (!checkdsize(scgp, dp, &ds, tsize, flags)) {
 
584
                exscsi(EX_BAD, &exargs);
 
585
                exit(EX_BAD);
 
586
        }
 
587
        if (tracks > 0 && fs > 0l) {
 
588
                /*
 
589
                 * Start the extra process needed for improved buffering.
 
590
                 */
 
591
                if (!init_faio(tracks, track, bufsize))
 
592
                        fs = 0L;
 
593
                else
 
594
                        on_comerr(excdr, &exargs);
 
595
        }
 
596
        if ((*dp->cdr_set_speed_dummy)(scgp, &speed, flags & F_DUMMY) < 0) {
 
597
                errmsgno(EX_BAD, "Cannot set speed/dummy.\n");
 
598
                excdr(EX_BAD, &exargs);
 
599
                exit(EX_BAD);
 
600
        }
 
601
        if ((flags & (F_BLANK|F_FORCE)) == (F_BLANK|F_FORCE)) {
 
602
                wait_unit_ready(scgp, 120);
 
603
                scsi_blank(scgp, 0L, blanktype, FALSE);
 
604
                excdr(0, &exargs);
 
605
                exit(0);
 
606
        }
 
607
        /*
 
608
         * Last chance to quit!
 
609
         */
 
610
        printf("Starting to write CD/DVD at speed %d in %s mode for %s session.\n",
 
611
                speed,
 
612
                (flags & F_DUMMY) ? "dummy" : "write",
 
613
                (flags & F_MULTI) ? "multi" : "single");
 
614
        printf("Last chance to quit, starting %s write in 9 seconds.",
 
615
                (flags & F_DUMMY)?"dummy":"real");
 
616
        flush();
 
617
        signal(SIGINT, intr);
 
618
        for (i=9; --i >= 0;) {
 
619
                sleep(1);
 
620
                if (didintr) {
 
621
                        printf("\n");
 
622
                        goto restore_it;
 
623
                }
 
624
                printf("\b\b\b\b\b\b\b\b\b\b%d seconds.", i);
 
625
                flush();
 
626
        }
 
627
        printf(" Operation starts.");
 
628
        flush();
 
629
        signal(SIGINT, SIG_DFL);
 
630
        signal(SIGINT, intfifo);
 
631
        signal(SIGTERM, intfifo);
 
632
        printf("\n");
 
633
        if (tracks > 0 && fs > 0l) {
 
634
                /*
 
635
                 * Wait for the read-buffer to become full.
 
636
                 * This should be take no extra time if the input is a file.
 
637
                 * If the input is a pipe (e.g. mkisofs) this can take a
 
638
                 * while. If mkisofs dumps core before it starts writing,
 
639
                 * we abort before the writing process started.
 
640
                 */
 
641
                if (!await_faio()) {
 
642
                        errmsgno(EX_BAD, "Input buffer error, aborting.\n");
 
643
                        excdr(EX_BAD, &exargs);
 
644
                        exit(EX_BAD);
 
645
                }
 
646
        }
 
647
        if (gettimeofday(&starttime, (struct timezone *)0) < 0)
 
648
                errmsg("Cannot get start time\n");
 
649
 
 
650
        /*
 
651
         * Blank the media if we were requested to do so
 
652
         */
 
653
        if (flags & F_BLANK) {
 
654
                if ((*dp->cdr_blank)(scgp, 0L, blanktype) < 0) {
 
655
                        errmsgno(EX_BAD, "Cannot blank disk, aborting.\n");
 
656
                        excdr(EX_BAD, &exargs);
 
657
                        exit(EX_BAD);
 
658
                }
 
659
                if (gettimeofday(&fixtime, (struct timezone *)0) < 0)
 
660
                        errmsg("Cannot get blank time\n");
 
661
                if (lverbose)
 
662
                        prtimediff("Blanking time: ", &starttime, &fixtime);
 
663
 
 
664
                if (!wait_unit_ready(scgp, 240) || tracks == 0) {
 
665
                        excdr(0, &exargs);
 
666
                        exit(0);
 
667
                }
 
668
                /*
 
669
                 * Reset start time so we will not see blanking time and
 
670
                 * writing time counted together.
 
671
                 */
 
672
                if (gettimeofday(&starttime, (struct timezone *)0) < 0)
 
673
                        errmsg("Cannot get start time\n");
 
674
        }
 
675
        /*
 
676
         * Get the number of the next recordable track.
 
677
         */
 
678
        scgp->silent++;
 
679
        if (read_tochdr(scgp, dp, NULL, &trackno) < 0) {
 
680
                trackno = 0;
 
681
        }
 
682
        scgp->silent--;
 
683
        for (i = 1; i <= tracks; i++) {
 
684
                track[i].trackno = i + trackno;
 
685
        }
 
686
        trackno++;
 
687
        track[0].trackno = trackno;     /* XXX Hack for TEAC fixate */
 
688
 
 
689
        /*
 
690
         * Now we actually start writing to the CD/DVD.
 
691
         * XXX Check total size of the tracks and remaining size of disk.
 
692
         */
 
693
        if ((*dp->cdr_open_session)(scgp, dp, tracks, track, toctype, flags & F_MULTI) < 0) {
 
694
                errmsgno(EX_BAD, "Cannot open new session.\n");
 
695
                excdr(EX_BAD, &exargs);
 
696
                exit(EX_BAD);
 
697
        }
 
698
        if ((flags & F_DUMMY) == 0 && dp->cdr_opc) {
 
699
                if (debug || lverbose) {
 
700
                        printf("Performing OPC...\n");
 
701
                        flush();
 
702
                }
 
703
                if (dp->cdr_opc(scgp, NULL, 0, TRUE) < 0)
 
704
                        comerr("OPC failed.\n");
 
705
        }
 
706
 
 
707
        /*
 
708
         * As long as open_session() will do nothing but
 
709
         * set up parameters, we may leave fix_it here.
 
710
         * I case we have to add an open_session() for a drive
 
711
         * that wants to do something that modifies the disk
 
712
         * We have to think about a new solution.
 
713
         */
 
714
        if (flags & F_FIX)
 
715
                goto fix_it;
 
716
 
 
717
        if (flags & F_SAO) {
 
718
                if (debug || lverbose) {
 
719
                        printf("Sending CUE sheet...\n");
 
720
                        flush();
 
721
                }
 
722
                if ((*dp->cdr_send_cue)(scgp, tracks, track) < 0) {
 
723
                        errmsgno(EX_BAD, "Cannot send CUE sheet.\n");
 
724
                        excdr(EX_BAD, &exargs);
 
725
                        exit(EX_BAD);
 
726
                }
 
727
        }
 
728
        if ((flags & F_SAO)) {
 
729
                (*dp->cdr_next_wr_address)(scgp, 0, &track[0], &startsec);
 
730
                if (startsec <= 0 && startsec != -150) {
 
731
                        errmsgno(EX_BAD, "WARNING: Drive returns wrong startsec (%ld) using -150\n",
 
732
                                        startsec);
 
733
                        startsec = -150;
 
734
                }
 
735
 
 
736
                if (debug)
 
737
                        printf("SAO startsec: %ld\n", startsec);
 
738
 
 
739
                for (i = 1; i <= tracks; i++) {
 
740
                        track[i].trackstart += startsec +150;
 
741
                }
 
742
#ifdef  XXX
 
743
                if (debug || lverbose)
 
744
                        printf("Writing lead-in...\n");
 
745
 
 
746
                pad_track(scgp, dp, 1, &track[1], -150, (Llong)0,
 
747
                                        FALSE, 0);
 
748
#endif
 
749
        }
 
750
        /*
 
751
         * Need to set trackno to the real value from
 
752
         * the current disk status.
 
753
         */
 
754
        for (i = 1; i <= tracks; i++, trackno++) {
 
755
                startsec = 0L;
 
756
 
 
757
                /*
 
758
                 * trackno is the "real" track number while 'i' is a counter
 
759
                 * going from 1 to tracks.
 
760
                 */
 
761
                if ((*dp->cdr_open_track)(scgp, dp, trackno, &track[i]) < 0) {
 
762
                        errs++;
 
763
                        break;
 
764
                }
 
765
 
 
766
                if ((flags & F_SAO) == 0) {
 
767
                        if ((*dp->cdr_next_wr_address)(scgp, trackno, &track[i], &startsec) < 0) {
 
768
                                errs++;
 
769
                                break;
 
770
                        }
 
771
                        track[i].trackstart = startsec;
 
772
                }
 
773
                if (debug || lverbose) {
 
774
                        printf("Starting new track at sector: %ld\n",
 
775
                                                track[i].trackstart);
 
776
                        flush();
 
777
                }
 
778
                if (write_track_data(scgp, dp, trackno, &track[i]) < 0) {
 
779
                        errs++;
 
780
                        sleep(5);
 
781
                        request_sense(scgp);
 
782
                        (*dp->cdr_close_track)(scgp, trackno, &track[i]);
 
783
                        break;
 
784
                }
 
785
                if ((*dp->cdr_close_track)(scgp, trackno, &track[i]) < 0) {
 
786
                        /*
 
787
                         * Check for "Dummy blocks added" message first.
 
788
                         */
 
789
                        if (scg_sense_key(scgp) != SC_ILLEGAL_REQUEST ||
 
790
                                        scg_sense_code(scgp) != 0xB5) {
 
791
                                errs++;
 
792
                                break;
 
793
                        }
 
794
                }
 
795
        }
 
796
fix_it:
 
797
        if (gettimeofday(&stoptime, (struct timezone *)0) < 0)
 
798
                errmsg("Cannot get stop time\n");
 
799
        if (lverbose)
 
800
                prtimediff("Writing  time: ", &starttime, &stoptime);
 
801
 
 
802
        if ((flags & F_NOFIX) == 0) {
 
803
                if (lverbose) {
 
804
                        printf("Fixating...\n");
 
805
                        flush();
 
806
                }
 
807
                if ((*dp->cdr_fixate)(scgp, flags & F_MULTI, flags & F_DUMMY,
 
808
                                toctype, tracks, track) < 0) {
 
809
                        /*
 
810
                         * Ignore fixating errors in dummy mode.
 
811
                         */
 
812
                        if ((flags & F_DUMMY) == 0)
 
813
                                errs++;
 
814
                }
 
815
                if (gettimeofday(&fixtime, (struct timezone *)0) < 0)
 
816
                        errmsg("Cannot get fix time\n");
 
817
                if (lverbose)
 
818
                        prtimediff("Fixating time: ", &stoptime, &fixtime);
 
819
        }
 
820
 
 
821
restore_it:
 
822
        /*
 
823
         * Try to restore the old sector size and stop FIFO.
 
824
         */
 
825
        excdr(errs?-2:0, &exargs);
 
826
        exit(errs?-2:0);
 
827
        return (0);
 
828
}
 
829
 
 
830
LOCAL void 
 
831
usage(excode)
 
832
        int excode;
 
833
{
 
834
        errmsgno(EX_BAD, "Usage: %s [options] track1...trackn\n",
 
835
                get_progname());
 
836
 
 
837
        error("Options:\n");
 
838
        error("\t-version       print version information and exit\n");
 
839
        error("\tdev=target     SCSI target to use as CD/DVD-Recorder\n");
 
840
        error("\ttimeout=#      set the default SCSI command timeout to #.\n");
 
841
        error("\tdebug=#,-d     Set to # or increment misc debug level\n");
 
842
        error("\tkdebug=#,kd=#  do Kernel debugging\n");
 
843
        error("\t-verbose,-v    increment general verbose level by one\n");
 
844
        error("\t-Verbose,-V    increment SCSI command transport verbose level by one\n");
 
845
        error("\t-silent,-s     do not print status of failed SCSI commands\n");
 
846
        error("\tdriver=name    user supplied driver name, use with extreme care\n");
 
847
        error("\tdriveropts=opt a comma separated list of driver specific options\n");
 
848
        error("\t-checkdrive    check if a driver for the drive is present\n");
 
849
        error("\t-prcap         print drive capabilities for MMC compliant drives\n");
 
850
        error("\t-inq           do an inquiry for the drive and exit\n");
 
851
        error("\t-scanbus       scan the SCSI bus and exit\n");
 
852
        error("\t-reset         reset the SCSI bus with the cdrecorder (if possible)\n");
 
853
        error("\t-ignsize       ignore the known size of a medium (may cause problems)\n");
 
854
        error("\t-useinfo       use *.inf files to overwrite audio options.\n");
 
855
        error("\tspeed=#                set speed of drive\n");
 
856
        error("\tblank=type     blank a CD-RW disc (see blank=help)\n");
 
857
#ifdef  FIFO
 
858
        error("\tfs=#           Set fifo size to # (0 to disable, default is %ld MB)\n",
 
859
                                                        DEFAULT_FIFOSIZE/(1024L*1024L));
 
860
#endif
 
861
        error("\t-load          load the disk and exit (works only with tray loader)\n");
 
862
        error("\t-eject         eject the disk after doing the work\n");
 
863
        error("\t-dummy         do everything with laser turned off\n");
 
864
        error("\t-msinfo                retrieve multi-session info for mkisofs >= 1.10\n");
 
865
        error("\t-toc           retrieve and print TOC/PMA data\n");
 
866
        error("\t-atip          retrieve and print ATIP data\n");
 
867
        error("\t-multi         generate a TOC that allows multi session\n");
 
868
        error("\t               In this case default track type is CD-ROM XA2\n");
 
869
        error("\t-fix           fixate a corrupt or unfixated disk (generate a TOC)\n");
 
870
        error("\t-nofix         do not fixate disk after writing tracks\n");
 
871
        error("\t-waiti         wait until input is available before opening SCSI\n");
 
872
        error("\t-force         force to continue on some errors to allow blanking bad disks\n");
 
873
        error("\t-dao           Write disk in DAO mode. This option will be replaced in the future.\n");
 
874
        error("\ttsize=#                Length of valid data in next track\n");
 
875
        error("\tpadsize=#      Amount of padding for next track\n");
 
876
        error("\tpregap=#       Amount of pre-gap sectors before next track\n");
 
877
        error("\tdefpregap=#    Amount of pre-gap sectors for all but track #1\n");
 
878
        error("\tmcn=text       Set the media catalog number for this CD to 'text'\n");
 
879
        error("\tisrc=text      Set the ISRC number for the next track to 'text'\n");
 
880
        error("\tindex=list     Set the index list for the next track to 'list'\n");
 
881
 
 
882
        error("\t-audio         Subsequent tracks are CD-DA audio tracks\n");
 
883
        error("\t-data          Subsequent tracks are CD-ROM data mode 1 (default)\n");
 
884
        error("\t-mode2         Subsequent tracks are CD-ROM data mode 2\n");
 
885
        error("\t-xa1           Subsequent tracks are CD-ROM XA mode 1\n");
 
886
        error("\t-xa2           Subsequent tracks are CD-ROM XA mode 2\n");
 
887
        error("\t-cdi           Subsequent tracks are CDI tracks\n");
 
888
        error("\t-isosize       Use iso9660 file system size for next data track\n");
 
889
        error("\t-preemp                Audio tracks are mastered with 50/15 ļæ½s preemphasis\n");
 
890
        error("\t-nopreemp      Audio tracks are mastered with no preemphasis (default)\n");
 
891
        error("\t-pad           Pad data tracks with %d zeroed sectors\n", PAD_SECS);
 
892
        error("\t               Pad audio tracks to a multiple of %d bytes\n", AUDIO_SEC_SIZE);
 
893
        error("\t-nopad         Do not pad data tracks (default)\n");
 
894
        error("\t-shorttrack    Subsequent tracks may be non Red Book < 4 seconds if in DAO mode\n");
 
895
        error("\t-noshorttrack  Subsequent tracks must be >= 4 seconds\n");
 
896
        error("\t-swab          Audio data source is byte-swapped (little-endian/Intel)\n");
 
897
        error("The type of the first track is used for the toc type.\n");
 
898
        error("Currently only form 1 tracks are supported.\n");
 
899
        exit(excode);
 
900
}
 
901
 
 
902
LOCAL void
 
903
blusage(ret)
 
904
        int     ret;
 
905
{
 
906
        error("Blanking options:\n");
 
907
        error("\tall\t\tblank the entire disk\n");
 
908
        error("\tdisc\t\tblank the entire disk\n");
 
909
        error("\tdisk\t\tblank the entire disk\n");
 
910
        error("\tfast\t\tminimally blank the entire disk (PMA, TOC, pregap)\n");
 
911
        error("\tminimal\t\tminimally blank the entire disk (PMA, TOC, pregap)\n");
 
912
        error("\ttrack\t\tblank a track\n");
 
913
        error("\tunreserve\tunreserve a track\n");
 
914
        error("\ttrtail\t\tblank a track tail\n");
 
915
        error("\tunclose\t\tunclose last session\n");
 
916
        error("\tsession\t\tblank last session\n");
 
917
 
 
918
        exit(ret);
 
919
        /* NOTREACHED */
 
920
}
 
921
 
 
922
/* ARGSUSED */
 
923
LOCAL void
 
924
intr(sig)
 
925
        int     sig;
 
926
{
 
927
        sig = 0;        /* Fake usage for gcc */
 
928
 
 
929
        signal(SIGINT, intr);
 
930
 
 
931
        didintr++;
 
932
}
 
933
 
 
934
LOCAL void
 
935
intfifo(sig)
 
936
        int     sig;
 
937
{
 
938
        excdr(sig, NULL);
 
939
        exit(sig);
 
940
}
 
941
 
 
942
/* ARGSUSED */
 
943
LOCAL void
 
944
exscsi(excode, arg)
 
945
        int     excode;
 
946
        void    *arg;
 
947
{
 
948
        struct exargs   *exp = (struct exargs *)arg;
 
949
 
 
950
        /*
 
951
         * Try to restore the old sector size.
 
952
         */
 
953
        if (exp != NULL && exp->exflags == 0) {
 
954
 
 
955
                set_secsize(exp->scgp, exp->old_secsize);
 
956
                unload_media(exp->scgp, exp->dp, exp->flags);
 
957
 
 
958
                exp->exflags++; /* Make sure that it only get called once */
 
959
        }
 
960
}
 
961
 
 
962
LOCAL void
 
963
excdr(excode, arg)
 
964
        int     excode;
 
965
        void    *arg;
 
966
{
 
967
        exscsi(excode, arg);
 
968
 
 
969
#ifdef  FIFO
 
970
        kill_faio();
 
971
        wait_faio();
 
972
        if (debug || lverbose)
 
973
                fifo_stats();
 
974
#endif
 
975
}
 
976
 
 
977
EXPORT int
 
978
read_buf(f, bp, size)
 
979
        int     f;
 
980
        char    *bp;
 
981
        int     size;
 
982
{
 
983
        char    *p = bp;
 
984
        int     amount = 0;
 
985
        int     n;
 
986
 
 
987
        do {
 
988
                do {
 
989
                        n = read(f, p, size-amount);
 
990
                } while (n < 0 && (errno == EAGAIN || errno == EINTR));
 
991
                if (n < 0)
 
992
                        return (n);
 
993
                amount += n;
 
994
                p += n;
 
995
 
 
996
        } while (amount < size && n > 0);
 
997
        return (amount);
 
998
}
 
999
 
 
1000
EXPORT int
 
1001
get_buf(f, bpp, size)
 
1002
        int     f;
 
1003
        char    **bpp;
 
1004
        int     size;
 
1005
{
 
1006
        if (fs > 0) {
 
1007
/*              return (faio_read_buf(f, *bpp, size));*/
 
1008
                return (faio_get_buf(f, bpp, size));
 
1009
        } else {
 
1010
                return (read_buf(f, *bpp, size));
 
1011
        }
 
1012
}
 
1013
 
 
1014
LOCAL int
 
1015
write_track_data(scgp, dp, track, trackp)
 
1016
        SCSI    *scgp;
 
1017
        cdr_t   *dp;
 
1018
        int     track;
 
1019
        track_t *trackp;
 
1020
{
 
1021
        int     f;
 
1022
        int     isaudio;
 
1023
        long    startsec;
 
1024
        Llong   bytes_read = 0;
 
1025
        Llong   bytes   = 0;
 
1026
        Llong   savbytes = 0;
 
1027
        int     count;
 
1028
        Llong   tracksize;
 
1029
        int     secsize;
 
1030
        int     secspt;
 
1031
        int     bytespt;
 
1032
        int     bytes_to_read;
 
1033
        long    amount;
 
1034
        int     pad;
 
1035
        int     bswab;
 
1036
        BOOL    neednl  = FALSE;
 
1037
        BOOL    islast  = FALSE;
 
1038
        char    *bp     = buf;
 
1039
long bsize;
 
1040
long bfree;
 
1041
/*#define       BCAP*/
 
1042
#ifdef  BCAP
 
1043
int per;
 
1044
int oper = -1;
 
1045
#endif
 
1046
 
 
1047
        scgp->silent++;
 
1048
        if (read_buff_cap(scgp, &bsize, &bfree) < 0)
 
1049
                bsize = -1;
 
1050
        scgp->silent--;
 
1051
 
 
1052
 
 
1053
        if (is_packet(trackp))  /* XXX Ugly hack for now */
 
1054
                return (write_packet_data(scgp, dp, track, trackp));
 
1055
 
 
1056
        f = trackp->f;
 
1057
        isaudio = is_audio(trackp);
 
1058
        tracksize = trackp->tracksize;
 
1059
        startsec = trackp->trackstart;
 
1060
 
 
1061
        secsize = trackp->secsize;
 
1062
        secspt = trackp->secspt;
 
1063
        bytespt = secsize * secspt;
 
1064
        
 
1065
        pad = !isaudio && is_pad(trackp);       /* Pad only data tracks */
 
1066
        bswab = isaudio && is_swab(trackp);     /* Swab only audio tracks */
 
1067
 
 
1068
        if (debug) {
 
1069
                printf("secsize:%d secspt:%d bytespt:%d audio:%d pad:%d\n",
 
1070
                        secsize, secspt, bytespt, isaudio, pad);
 
1071
        }
 
1072
 
 
1073
        if (lverbose) {
 
1074
                if (tracksize > 0)
 
1075
                        printf("\rTrack %02d:   0 of %3lld MB written.",
 
1076
                               track, tracksize >> 20);
 
1077
                else
 
1078
                        printf("\rTrack %02d:   0 MB written.", track);
 
1079
                flush();
 
1080
                neednl = TRUE;
 
1081
        }
 
1082
 
 
1083
        do {
 
1084
                bytes_to_read = bytespt;
 
1085
                if (tracksize > 0) {
 
1086
                        if ((tracksize - bytes_read) > bytespt)
 
1087
                                bytes_to_read = bytespt;
 
1088
                        else
 
1089
                                bytes_to_read = tracksize - bytes_read;                         
 
1090
                }
 
1091
                count = get_buf(f, &bp, bytes_to_read);
 
1092
 
 
1093
                if (count < 0)
 
1094
                        comerr("read error on input file\n");
 
1095
                if (count == 0)
 
1096
                        break;
 
1097
                bytes_read += count;
 
1098
                if (tracksize >= 0 && bytes_read >= tracksize) {
 
1099
                        count -= bytes_read - tracksize;
 
1100
                        /*
 
1101
                         * Paranoia: tracksize is known (trackp->tracksize >= 0)
 
1102
                         * At this point, trackp->padsize should alway be set
 
1103
                         * if the tracksize is less than 300 sectors.
 
1104
                         */
 
1105
                        if (trackp->padsize == 0 &&
 
1106
                            (is_shorttrk(trackp) || (bytes_read/secsize) >= 300))
 
1107
                                islast = TRUE;
 
1108
                }
 
1109
 
 
1110
                if (bswab)
 
1111
                        swabbytes(bp, count);
 
1112
 
 
1113
                if (count < bytespt) {
 
1114
                        if (debug) {
 
1115
                                printf("\nNOTICE: reducing block size for last record.\n");
 
1116
                                neednl = FALSE;
 
1117
                        }
 
1118
 
 
1119
                        if ((amount = count % secsize) != 0) {
 
1120
                                amount = secsize - amount;
 
1121
                                fillbytes(&bp[count], amount, '\0');
 
1122
                                count += amount;
 
1123
                                printf("\nWARNING: padding up to secsize.\n");
 
1124
                                neednl = FALSE;
 
1125
                        }
 
1126
                        bytespt = count;
 
1127
                        secspt = count / secsize;
 
1128
                        /*
 
1129
                         * If tracksize is not known (trackp->tracksize < 0)
 
1130
                         * we may need to set trackp->padsize 
 
1131
                         * if the tracksize is less than 300 sectors.
 
1132
                         */
 
1133
                        if (trackp->padsize == 0 &&
 
1134
                            (is_shorttrk(trackp) || (bytes_read/secsize) >= 300))
 
1135
                                islast = TRUE;
 
1136
                }
 
1137
 
 
1138
again:
 
1139
                scgp->silent++;
 
1140
                amount = (*dp->cdr_write_trackdata)(scgp, bp, startsec, bytespt, secspt, islast);
 
1141
                scgp->silent--;
 
1142
                if (amount < 0) {
 
1143
                        if (scsi_in_progress(scgp)) {
 
1144
                                usleep(100000);
 
1145
                                goto again;
 
1146
                        }
 
1147
 
 
1148
                        printf("%swrite track data: error after %lld bytes\n",
 
1149
                                                        neednl?"\n":"", bytes);
 
1150
                        return (-1);
 
1151
                }
 
1152
                bytes += amount;
 
1153
                startsec += amount / secsize;
 
1154
 
 
1155
                if (lverbose && (bytes >= (savbytes + 0x100000))) {
 
1156
                        int     fper;
 
1157
 
 
1158
                        printf("\rTrack %02d: %3lld", track, bytes >> 20);
 
1159
                        if (tracksize > 0)
 
1160
                                printf(" of %3lld MB", tracksize >> 20);
 
1161
                        else
 
1162
                                printf(" MB");
 
1163
                        printf(" written");
 
1164
                        fper = fifo_percent(TRUE);
 
1165
                        if (fper >= 0)
 
1166
                                printf(" (fifo %3d%%)", fper);
 
1167
                        printf(".");
 
1168
                        savbytes = (bytes >> 20) << 20;
 
1169
                        flush();
 
1170
                        neednl = TRUE;
 
1171
                }
 
1172
#ifdef  BCAP
 
1173
                if (bsize >= 0) {
 
1174
                        read_buff_cap(scgp, 0, &bfree);
 
1175
                        per = 100*(bsize - bfree) / bsize;
 
1176
                        if (per != oper)
 
1177
                                printf("[buf %3d%%] %3ld %3ld\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b",
 
1178
                                        per, bsize >> 10, bfree >> 10);
 
1179
                        oper = per;
 
1180
                        flush();
 
1181
                }
 
1182
#endif
 
1183
        } while (tracksize < 0 || bytes_read < tracksize);
 
1184
 
 
1185
        if (!is_shorttrk(trackp) && (bytes / secsize) < 300) {
 
1186
                /*
 
1187
                 * If tracksize is not known (trackp->tracksize < 0) or 
 
1188
                 * for some strange reason we did not set padsize properly
 
1189
                 * we may need to modify trackp->padsize if
 
1190
                 * tracksize+padsize is less than 300 sectors.
 
1191
                 */
 
1192
                savbytes = roundup(trackp->padsize, secsize);
 
1193
                if (((bytes+savbytes) / secsize) < 300)
 
1194
                        trackp->padsize = 300 * secsize - bytes;
 
1195
        }
 
1196
        if (trackp->padsize) {
 
1197
                if (neednl) {
 
1198
                        printf("\n");
 
1199
                        neednl = FALSE;
 
1200
                }
 
1201
                if ((trackp->padsize >> 20) > 0) {
 
1202
                        neednl = TRUE;
 
1203
                } else if (lverbose) {
 
1204
                        printf("Track %02d: writing %3lld KB of pad data.\n",
 
1205
                                        track, (Llong)(trackp->padsize >> 10));
 
1206
                        neednl = FALSE;
 
1207
                }
 
1208
                pad_track(scgp, dp, track, trackp, startsec, trackp->padsize,
 
1209
                                        TRUE, &savbytes);
 
1210
                bytes += savbytes;
 
1211
                startsec += savbytes / secsize;
 
1212
        }
 
1213
        printf("%sTrack %02d: Total bytes read/written: %lld/%lld (%lld sectors).\n",
 
1214
               neednl?"\n":"", track, bytes_read, bytes, bytes/secsize);
 
1215
        flush();
 
1216
        return 0;
 
1217
}
 
1218
 
 
1219
EXPORT int
 
1220
pad_track(scgp, dp, track, trackp, startsec, amt, dolast, bytesp)
 
1221
        SCSI    *scgp;
 
1222
        cdr_t   *dp;
 
1223
        int     track;
 
1224
        track_t *trackp;
 
1225
        long    startsec;
 
1226
        Llong   amt;
 
1227
        BOOL    dolast;
 
1228
        Llong   *bytesp;
 
1229
{
 
1230
        Llong   bytes   = 0;
 
1231
        Llong   savbytes = 0;
 
1232
        int     secsize;
 
1233
        int     secspt;
 
1234
        int     bytespt;
 
1235
        int     amount;
 
1236
        BOOL    neednl  = FALSE;
 
1237
        BOOL    islast  = FALSE;
 
1238
 
 
1239
        secsize = trackp->secsize;
 
1240
        secspt = trackp->secspt;
 
1241
        bytespt = secsize * secspt;
 
1242
        
 
1243
        fillbytes(buf, bytespt, '\0');
 
1244
 
 
1245
        if ((amt >> 20) > 0) {
 
1246
                printf("\rTrack %02d:   0 of %3lld MB pad written.",
 
1247
                                                track, amt >> 20);
 
1248
                flush();
 
1249
        }
 
1250
        do {
 
1251
                if (amt < bytespt) {
 
1252
                        bytespt = roundup(amt, secsize);
 
1253
                        secspt = bytespt / secsize;     
 
1254
                }
 
1255
                if (dolast && (amt - bytespt) <= 0)
 
1256
                        islast = TRUE;
 
1257
 
 
1258
again:
 
1259
                scgp->silent++;
 
1260
                amount = (*dp->cdr_write_trackdata)(scgp, buf, startsec, bytespt, secspt, islast);
 
1261
                scgp->silent--;
 
1262
                if (amount < 0) {
 
1263
                        if (scsi_in_progress(scgp)) {
 
1264
                                usleep(100000);
 
1265
                                goto again;
 
1266
                        }
 
1267
 
 
1268
                        printf("%swrite track pad data: error after %lld bytes\n",
 
1269
                                                        neednl?"\n":"", bytes);
 
1270
                        if (bytesp)
 
1271
                                *bytesp = bytes;
 
1272
read_buff_cap(scgp, 0, 0);
 
1273
                        return (-1);
 
1274
                }
 
1275
                amt -= amount;
 
1276
                bytes += amount;
 
1277
                startsec += amount / secsize;
 
1278
 
 
1279
                if (lverbose && (bytes >= (savbytes + 0x100000))) {
 
1280
                        printf("\rTrack %02d: %3lld", track, bytes >> 20);
 
1281
                        savbytes = (bytes >> 20) << 20;
 
1282
                        flush();
 
1283
                        neednl = TRUE;
 
1284
                }
 
1285
        } while (amt > 0);
 
1286
 
 
1287
        if (bytesp)
 
1288
                *bytesp = bytes;
 
1289
        if (bytes == 0)
 
1290
                return (0);
 
1291
        return (bytes > 0 ? 1:-1);
 
1292
}
 
1293
 
 
1294
#ifdef  USE_WRITE_BUF
 
1295
EXPORT int
 
1296
write_buf(scgp, dp, track, trackp, bp, startsec, amt, secsize, dolast, bytesp)
 
1297
        SCSI    *scgp;
 
1298
        cdr_t   *dp;
 
1299
        int     track;
 
1300
        track_t *trackp;
 
1301
        char    *bp;
 
1302
        long    startsec;
 
1303
        long    amt;
 
1304
        int     secsize;
 
1305
        BOOL    dolast;
 
1306
        long    *bytesp;
 
1307
{
 
1308
        long    bytes   = 0;
 
1309
        long    savbytes = 0;
 
1310
/*      int     secsize;*/
 
1311
        int     secspt;
 
1312
        int     bytespt;
 
1313
        int     amount;
 
1314
        BOOL    neednl  = FALSE;
 
1315
        BOOL    islast  = FALSE;
 
1316
 
 
1317
/*      secsize = trackp->secsize;*/
 
1318
/*      secspt = trackp->secspt;*/
 
1319
 
 
1320
        secspt = bufsize/secsize;
 
1321
        secspt = min(255, secspt);
 
1322
        bytespt = secsize * secspt;
 
1323
        
 
1324
/*      fillbytes(buf, bytespt, '\0');*/
 
1325
 
 
1326
        if ((amt >> 20) > 0) {
 
1327
                printf("\rTrack %02d:   0 of %3ld MB pad written.",
 
1328
                                                track, amt >> 20);
 
1329
                flush();
 
1330
        }
 
1331
        do {
 
1332
                if (amt < bytespt) {
 
1333
                        bytespt = roundup(amt, secsize);
 
1334
                        secspt = bytespt / secsize;     
 
1335
                }
 
1336
                if (dolast && (amt - bytespt) <= 0)
 
1337
                        islast = TRUE;
 
1338
 
 
1339
                amount = (*dp->cdr_write_trackdata)(scgp, bp, startsec, bytespt, secspt, islast);
 
1340
                if (amount < 0) {
 
1341
                        printf("%swrite track data: error after %ld bytes\n",
 
1342
                                                        neednl?"\n":"", bytes);
 
1343
                        if (bytesp)
 
1344
                                *bytesp = bytes;
 
1345
read_buff_cap(scgp, 0, 0);
 
1346
                        return (-1);
 
1347
                }
 
1348
                amt -= amount;
 
1349
                bytes += amount;
 
1350
                startsec += amount / secsize;
 
1351
 
 
1352
                if (lverbose && (bytes >= (savbytes + 0x100000))) {
 
1353
                        printf("\rTrack %02d: %3ld", track, bytes >> 20);
 
1354
                        savbytes = (bytes >> 20) << 20;
 
1355
                        flush();
 
1356
                        neednl = TRUE;
 
1357
                }
 
1358
        } while (amt > 0);
 
1359
 
 
1360
        if (bytesp)
 
1361
                *bytesp = bytes;
 
1362
        return (bytes);
 
1363
}
 
1364
#endif  /* USE_WRITE_BUF */
 
1365
 
 
1366
LOCAL void
 
1367
printdata(track, trackp)
 
1368
        int     track;
 
1369
        track_t *trackp;
 
1370
{
 
1371
        if (trackp->tracksize >= 0) {
 
1372
                printf("Track %02d: data  %3lld MB        ",
 
1373
                                        track, (Llong)(trackp->tracksize >> 20));
 
1374
        } else {
 
1375
                printf("Track %02d: data  unknown length",
 
1376
                                        track);
 
1377
        }
 
1378
        if (trackp->padsize > 0) {
 
1379
                if ((trackp->padsize >> 20) > 0)
 
1380
                        printf(" padsize: %3lld MB", (Llong)(trackp->padsize >> 20));
 
1381
                else
 
1382
                        printf(" padsize: %3lld KB", (Llong)(trackp->padsize >> 10));
 
1383
        }
 
1384
        if (trackp->pregapsize != 150) {
 
1385
                printf(" pregapsize: %3ld", trackp->pregapsize);
 
1386
        }
 
1387
        printf("\n");
 
1388
}
 
1389
 
 
1390
LOCAL void
 
1391
printaudio(track, trackp)
 
1392
        int     track;
 
1393
        track_t *trackp;
 
1394
{
 
1395
        if (trackp->tracksize >= 0) {
 
1396
                printf("Track %02d: audio %3lld MB (%02d:%02d.%02d) %spreemp%s%s",
 
1397
                        track, (Llong)(trackp->tracksize >> 20),
 
1398
                        minutes(trackp->tracksize),
 
1399
                        seconds(trackp->tracksize),
 
1400
                        hseconds(trackp->tracksize),
 
1401
                        is_preemp(trackp) ? "" : "no ",
 
1402
                        is_swab(trackp) ? " swab":"",
 
1403
                        ((trackp->tracksize < 300L*trackp->secsize) ||
 
1404
                        (trackp->tracksize % trackp->secsize)) &&
 
1405
                        is_pad(trackp) ? " pad" : "");
 
1406
        } else {
 
1407
                printf("Track %02d: audio unknown length    %spreemp%s%s",
 
1408
                        track, is_preemp(trackp) ? "" : "no ",
 
1409
                        is_swab(trackp) ? " swab":"",
 
1410
                        (trackp->tracksize % trackp->secsize) && is_pad(trackp) ? " pad" : "");
 
1411
        }
 
1412
        if (trackp->padsize > 0) {
 
1413
                if ((trackp->padsize >> 20) > 0)
 
1414
                        printf(" padsize: %3lld MB", (Llong)(trackp->padsize >> 20));
 
1415
                else
 
1416
                        printf(" padsize: %3lld KB", (Llong)(trackp->padsize >> 10));
 
1417
                printf(" (%02d:%02d.%02d)",
 
1418
                        minutes(trackp->padsize),
 
1419
                        seconds(trackp->padsize),
 
1420
                        hseconds(trackp->padsize));
 
1421
        }
 
1422
        if (trackp->pregapsize != 150) {
 
1423
                printf(" pregapsize: %3ld", trackp->pregapsize);
 
1424
        }
 
1425
        printf("\n");
 
1426
}
 
1427
 
 
1428
LOCAL void
 
1429
checkfile(track, trackp)
 
1430
        int     track;
 
1431
        track_t *trackp;
 
1432
{
 
1433
        if (trackp->tracksize > 0 &&
 
1434
                        is_audio(trackp) &&
 
1435
                        ( (!is_shorttrk(trackp) &&
 
1436
                          (trackp->tracksize < 300L*trackp->secsize)) ||
 
1437
                        (trackp->tracksize % trackp->secsize)) &&
 
1438
                                                !is_pad(trackp)) {
 
1439
                errmsgno(EX_BAD, "Bad audio track size %lld for track %02d.\n",
 
1440
                                (Llong)trackp->tracksize, track);
 
1441
                errmsgno(EX_BAD, "Audio tracks must be at least %ld bytes and a multiple of %d.\n",
 
1442
                                300L*trackp->secsize, trackp->secsize);
 
1443
                comerrno(EX_BAD, "See -pad option.\n");
 
1444
        }
 
1445
        
 
1446
        if (!lverbose)
 
1447
                return;
 
1448
 
 
1449
        if (is_audio(trackp))
 
1450
                printaudio(track, trackp);
 
1451
        else
 
1452
                printdata(track, trackp);
 
1453
}
 
1454
 
 
1455
LOCAL int
 
1456
checkfiles(tracks, trackp)
 
1457
        int     tracks;
 
1458
        track_t *trackp;
 
1459
{
 
1460
        int     i;
 
1461
        int     isaudio = 1;
 
1462
 
 
1463
        for (i = 1; i <= tracks; i++) {
 
1464
                if (!is_audio(&trackp[i]))
 
1465
                        isaudio = 0;
 
1466
                checkfile(i, &trackp[i]);
 
1467
        }
 
1468
        return (isaudio);
 
1469
}
 
1470
 
 
1471
LOCAL void
 
1472
setpregaps(tracks, trackp)
 
1473
        int     tracks;
 
1474
        track_t *trackp;
 
1475
{
 
1476
        int     i;
 
1477
        int     sectype;
 
1478
        track_t *tp;
 
1479
 
 
1480
        /*
 
1481
         * Set some values for track 0 (the lead-in)
 
1482
         * XXX There should be a better place to do this.
 
1483
         */
 
1484
        sectype = trackp[1].sectype;
 
1485
        trackp[0].sectype = sectype;
 
1486
        trackp[0].dbtype = trackp[1].dbtype;
 
1487
 
 
1488
        for (i = 1; i <= tracks; i++) {
 
1489
                tp = &trackp[i];
 
1490
                if (tp->pregapsize == -1L) {
 
1491
                        tp->pregapsize = 150;           /* Default Pre GAP */
 
1492
                        if (sectype != tp->sectype) {
 
1493
                                tp->pregapsize = 255;   /* Pre GAP is 255 */
 
1494
                                tp->flags &= ~TI_PREGAP;
 
1495
                        }
 
1496
                }
 
1497
                sectype = tp->sectype;                  /* Save old sectype */
 
1498
        }
 
1499
        /*
 
1500
         * Set some values for track 0xAA (the lead-out)
 
1501
         * XXX There should be a better place to do this.
 
1502
         */
 
1503
        trackp[tracks+1].sectype = sectype;
 
1504
        trackp[tracks+1].dbtype = trackp[tracks].dbtype;
 
1505
}
 
1506
 
 
1507
LOCAL long
 
1508
checktsize(tracks, trackp)
 
1509
        int     tracks;
 
1510
        track_t *trackp;
 
1511
{
 
1512
        int     i;
 
1513
        Llong   curr;
 
1514
        Llong   total = -150;
 
1515
        Ullong  btotal;
 
1516
        track_t *tp;
 
1517
 
 
1518
        for (i = 1; i <= tracks; i++) {
 
1519
                tp = &trackp[i];
 
1520
                if (!is_pregap(tp))
 
1521
                        total += tp->pregapsize;
 
1522
 
 
1523
                if (lverbose > 1) {
 
1524
                        printf("track: %d start: %lld pregap: %ld\n",
 
1525
                                        i, total, tp->pregapsize);
 
1526
                }
 
1527
                tp->trackstart = total;
 
1528
                if (tp->tracksize >= 0) {
 
1529
                        curr = (tp->tracksize + (tp->secsize-1)) / tp->secsize;
 
1530
                        curr += (tp->padsize + (tp->secsize-1)) / tp->secsize;
 
1531
                        /*
 
1532
                         * Minimum track size is 4s
 
1533
                         */
 
1534
                        if (!is_shorttrk(tp) && curr < 300)
 
1535
                                curr = 300;
 
1536
                        if (is_tao(tp) && !is_audio(tp)) {
 
1537
                                curr += 2;
 
1538
                        }
 
1539
                        total += curr;
 
1540
                }
 
1541
        }
 
1542
        tp = &trackp[i];
 
1543
        tp->trackstart = total;
 
1544
        if (!lverbose)
 
1545
                return (total);
 
1546
 
 
1547
        btotal = (Ullong)total * 2352;
 
1548
/* XXX Sector Size ??? */
 
1549
        if (tracks > 0) {
 
1550
                printf("Total size:     %3llu MB (%02d:%02d.%02d) = %lld sectors\n",
 
1551
                        btotal >> 20,
 
1552
                        minutes(btotal),
 
1553
                        seconds(btotal),
 
1554
                        hseconds(btotal), total);
 
1555
                btotal += 150 * 2352;
 
1556
                printf("Lout start:     %3llu MB (%02d:%02d/%02d) = %lld sectors\n",
 
1557
                        btotal >> 20,
 
1558
                        minutes(btotal),
 
1559
                        seconds(btotal),
 
1560
                        frames(btotal), total);
 
1561
        }
 
1562
        return (total);
 
1563
}
 
1564
 
 
1565
LOCAL void
 
1566
checksize(trackp)
 
1567
        track_t *trackp;
 
1568
{
 
1569
        struct stat     st;
 
1570
        Llong           lsize;
 
1571
 
 
1572
        /*
 
1573
         * If the current input file is a regular file and
 
1574
         * 'padsize=' has not been specified,
 
1575
         * use fstat() or file parser to get the size of the file.
 
1576
         */
 
1577
        if (trackp->tracksize < 0 && (trackp->flags & TI_ISOSIZE) != 0) {
 
1578
                lsize = isosize(trackp->f);
 
1579
                trackp->tracksize = lsize;
 
1580
                if (trackp->tracksize != lsize)
 
1581
                        comerrno(EX_BAD, "This OS cannot handle large ISO-9660 images.\n");
 
1582
        }
 
1583
        if (trackp->tracksize < 0 && (trackp->flags & TI_NOAUHDR) == 0) {
 
1584
                lsize = ausize(trackp->f);
 
1585
                trackp->tracksize = lsize;
 
1586
                if (trackp->tracksize != lsize)
 
1587
                        comerrno(EX_BAD, "This OS cannot handle large audio images.\n");
 
1588
        }
 
1589
        if (trackp->tracksize < 0 && (trackp->flags & TI_NOAUHDR) == 0) {
 
1590
                lsize = wavsize(trackp->f);
 
1591
                trackp->tracksize = lsize;
 
1592
                if (trackp->tracksize != lsize)
 
1593
                        comerrno(EX_BAD, "This OS cannot handle large WAV images.\n");
 
1594
                if (trackp->tracksize > 0)      /* Force little endian input */
 
1595
                        trackp->flags |= TI_SWAB;
 
1596
        }
 
1597
        if (trackp->tracksize == AU_BAD_CODING) {
 
1598
                comerrno(EX_BAD, "Inappropriate audio coding in '%s'.\n",
 
1599
                                                        trackp->filename);
 
1600
        }
 
1601
        if (trackp->tracksize < 0 &&
 
1602
                        fstat(trackp->f, &st) >= 0 && S_ISREG(st.st_mode)) {
 
1603
                trackp->tracksize = st.st_size;
 
1604
        }
 
1605
}
 
1606
 
 
1607
LOCAL BOOL
 
1608
checkdsize(scgp, dp, dsp, tsize, flags)
 
1609
        SCSI    *scgp;
 
1610
        cdr_t   *dp;
 
1611
        dstat_t *dsp;
 
1612
        long    tsize;
 
1613
        int     flags;
 
1614
{
 
1615
        long    startsec = 0L;
 
1616
        long    endsec = 0L;
 
1617
 
 
1618
        scgp->silent++;
 
1619
        (*dp->cdr_next_wr_address)(scgp, /*i*/ 0, (track_t *)0, &startsec);
 
1620
        scgp->silent--;
 
1621
 
 
1622
        /*
 
1623
         * This only should happen when the drive is currently in DAO mode.
 
1624
         * We rely on the drive being in TAO mode, a negative value for
 
1625
         * startsec is not correct here it may be caused by bad firmware or
 
1626
         * by a drive in DAO mode. In DAO mode the drive will report the
 
1627
         * pre-gap as part of the writable area.
 
1628
         */
 
1629
        if (startsec < 0)
 
1630
                startsec = 0;
 
1631
 
 
1632
        /*
 
1633
         * Size limitations for CD's:
 
1634
         *
 
1635
         *              404850 == 90 min        Red book calls this the
 
1636
         *                                      first negative time
 
1637
         *                                      allows lead out start up to
 
1638
         *                                      block 404700
 
1639
         *
 
1640
         *              449850 == 100 min       This is the first time that
 
1641
         *                                      is no more representable
 
1642
         *                                      in a two digit BCD number.
 
1643
         *                                      allows lead out start up to
 
1644
         *                                      block 449700
 
1645
         */
 
1646
 
 
1647
        endsec = startsec + tsize;
 
1648
 
 
1649
        if (dsp->ds_maxblocks > 0) {
 
1650
                if (lverbose)
 
1651
                        printf("Blocks total: %ld Blocks current: %ld Blocks remaining: %ld\n",
 
1652
                                        dsp->ds_maxblocks,
 
1653
                                        dsp->ds_maxblocks - startsec,
 
1654
                                        dsp->ds_maxblocks - endsec);
 
1655
 
 
1656
                if (endsec > dsp->ds_maxblocks) {
 
1657
                        errmsgno(EX_BAD,
 
1658
                        "WARNING: Data may not fit on current disk.\n");
 
1659
 
 
1660
                        /* XXX Check for flags & CDR_NO_LOLIMIT */
 
1661
/*                      goto toolarge;*/
 
1662
                }
 
1663
                if (lverbose && dsp->ds_maxrblocks > 0)
 
1664
                        printf("RBlocks total: %ld RBlocks current: %ld RBlocks remaining: %ld\n",
 
1665
                                        dsp->ds_maxrblocks,
 
1666
                                        dsp->ds_maxrblocks - startsec,
 
1667
                                        dsp->ds_maxrblocks - endsec);
 
1668
                if (dsp->ds_maxrblocks > 0 && endsec > dsp->ds_maxrblocks) {
 
1669
                        errmsgno(EX_BAD,
 
1670
                        "Data does not fit on current disk.\n");
 
1671
                        goto toolarge;
 
1672
                }
 
1673
                if ((endsec > 404700) ||
 
1674
                    (dsp->ds_maxrblocks > 404700 && 449850 > dsp->ds_maxrblocks)) {
 
1675
                        /*
 
1676
                         * Assume that this must be a CD and not a DVD.
 
1677
                         * So this is a non Red Book compliant CD with a
 
1678
                         * capacity between 90 and 99 minutes.
 
1679
                         */
 
1680
                        if (dsp->ds_maxrblocks > 404700)
 
1681
                                printf("RedBook total: %ld RedBook current: %ld RedBook remaining: %ld\n",
 
1682
                                        404700L,
 
1683
                                        404700L - startsec,
 
1684
                                        404700L - endsec);
 
1685
                        if (endsec > 404700) {
 
1686
                                if ((flags & (F_IGNSIZE|F_FORCE)) == 0)
 
1687
                                        errmsgno(EX_BAD,
 
1688
                                        "Notice: Most recorders cannot write CD's >= 90 minutes.\n");
 
1689
                                        errmsgno(EX_BAD,
 
1690
                                        "Notice: Use -ignsize option to allow >= 90 minutes.\n");
 
1691
                                goto toolarge;
 
1692
                        }
 
1693
                }
 
1694
        } else {
 
1695
                if (endsec >= (405000-300)) {                   /*<90 min disk*/
 
1696
                        errmsgno(EX_BAD,
 
1697
                                "Data will not fit on any disk.\n");
 
1698
                        goto toolarge;
 
1699
                } else if (endsec >= (333000-150)) {            /* 74 min disk*/
 
1700
                        errmsgno(EX_BAD,
 
1701
                        "WARNING: Data may not fit on standard 74min disk.\n");
 
1702
                }
 
1703
        }
 
1704
        return (TRUE);
 
1705
toolarge:
 
1706
        if (dsp->ds_maxblocks < 449850) {
 
1707
                /*
 
1708
                 * Assume that this must be a CD and not a DVD.
 
1709
                 */
 
1710
                if (endsec > 449700) {
 
1711
                        errmsgno(EX_BAD, "Cannot write CD's >= 100 minutes.\n");
 
1712
                        return (FALSE);
 
1713
                }
 
1714
        }
 
1715
        if ((flags & (F_IGNSIZE|F_FORCE)) != 0)
 
1716
                return (TRUE);
 
1717
        return (FALSE);
 
1718
}
 
1719
 
 
1720
LOCAL void
 
1721
raise_fdlim()
 
1722
{
 
1723
#ifdef  RLIMIT_NOFILE
 
1724
 
 
1725
        struct rlimit   rlim;
 
1726
 
 
1727
        /*
 
1728
         * Set max # of file descriptors to be able to hold all files open
 
1729
         */
 
1730
        getrlimit(RLIMIT_NOFILE, &rlim);
 
1731
        rlim.rlim_cur = MAX_TRACK + 10;
 
1732
        if (rlim.rlim_cur > rlim.rlim_max)
 
1733
                errmsgno(EX_BAD,
 
1734
                        "warning: low file descriptor limit (%lld)\n",
 
1735
                                                (Llong)rlim.rlim_max);
 
1736
        setrlimit(RLIMIT_NOFILE, &rlim);
 
1737
 
 
1738
#endif  /* RLIMIT_NOFILE */
 
1739
}
 
1740
 
 
1741
char    *opts =
 
1742
"help,version,checkdrive,prcap,inq,scanbus,reset,ignsize,useinfo,dev*,timeout#,driver*,driveropts*,tsize&,padsize&,pregap&,defpregap&,speed#,load,eject,dummy,msinfo,toc,atip,multi,fix,nofix,waiti,debug#,d+,kdebug#,kd#,verbose+,v+,Verbose+,V+,silent,s,audio,data,mode2,xa1,xa2,cdi,isosize,nopreemp,preemp,nopad,pad,swab,fs&,blank&,pktsize#,packet,noclose,force,dao,scms,isrc*,mcn*,index*,shorttrack,noshorttrack";
 
1743
 
 
1744
LOCAL void
 
1745
gargs(ac, av, tracksp, trackp, devp, timeoutp, dpp, speedp, flagsp, toctypep, blankp)
 
1746
        int     ac;
 
1747
        char    **av;
 
1748
        int     *tracksp;
 
1749
        track_t *trackp;
 
1750
        cdr_t   **dpp;
 
1751
        char    **devp;
 
1752
        int     *timeoutp;
 
1753
        int     *speedp;
 
1754
        long    *flagsp;
 
1755
        int     *toctypep;
 
1756
        int     *blankp;
 
1757
{
 
1758
        int     cac;
 
1759
        char    * const*cav;
 
1760
        char    *driver = NULL;
 
1761
        char    *dev = NULL;
 
1762
        char    *isrc = NULL;
 
1763
        char    *mcn = NULL;
 
1764
        char    *tindex = NULL;
 
1765
        long    bltype = -1;
 
1766
        Llong   tracksize;
 
1767
        Llong   padsize;
 
1768
        long    pregapsize;
 
1769
        long    defpregap = -1L;
 
1770
        long    secsize;
 
1771
        int     pktsize;
 
1772
        int     speed = -1;
 
1773
        int     help = 0;
 
1774
        int     version = 0;
 
1775
        int     checkdrive = 0;
 
1776
        int     prcap = 0;
 
1777
        int     inq = 0;
 
1778
        int     scanbus = 0;
 
1779
        int     reset = 0;
 
1780
        int     ignsize = 0;
 
1781
        int     useinfo = 0;
 
1782
        int     load = 0;
 
1783
        int     eject = 0;
 
1784
        int     dummy = 0;
 
1785
        int     msinfo = 0;
 
1786
        int     toc = 0;
 
1787
        int     atip = 0;
 
1788
        int     multi = 0;
 
1789
        int     fix = 0;
 
1790
        int     nofix = 0;
 
1791
        int     waiti = 0;
 
1792
        int     audio;
 
1793
        int     autoaudio = 0;
 
1794
        int     data;
 
1795
        int     mode2;
 
1796
        int     xa1;
 
1797
        int     xa2;
 
1798
        int     cdi;
 
1799
        int     isize;
 
1800
        int     ispacket = 0;
 
1801
        int     noclose = 0;
 
1802
        int     force = 0;
 
1803
        int     dao = 0;
 
1804
        int     scms = 0;
 
1805
        int     preemp = 0;
 
1806
        int     nopreemp;
 
1807
        int     pad = 0;
 
1808
        int     bswab = 0;
 
1809
        int     nopad;
 
1810
        int     shorttrack = 0;
 
1811
        int     noshorttrack;
 
1812
        int     flags;
 
1813
        int     tracks = *tracksp;
 
1814
        int     tracktype = TOC_ROM;
 
1815
        int     sectype = ST_ROM_MODE1;
 
1816
        int     dbtype = DB_ROM_MODE1;
 
1817
        int     got_track;
 
1818
 
 
1819
        trackp[0].flags |= TI_TAO;
 
1820
        trackp[1].pregapsize = -1;
 
1821
        *flagsp |= F_WRITE;
 
1822
 
 
1823
        cac = --ac;
 
1824
        cav = ++av;
 
1825
        for (;; cac--, cav++) {
 
1826
                tracksize = (Llong)-1L;
 
1827
                padsize = (Llong)0L;
 
1828
                pregapsize = defpregap;
 
1829
                audio = data = mode2 = xa1 = xa2 = cdi = 0;
 
1830
                isize = nopreemp = nopad = noshorttrack = 0;
 
1831
                pktsize = 0;
 
1832
                isrc = NULL;
 
1833
                tindex = NULL;
 
1834
                if (getargs(&cac, &cav, opts,
 
1835
                                &help, &version, &checkdrive, &prcap,
 
1836
                                &inq, &scanbus, &reset, &ignsize,
 
1837
                                &useinfo,
 
1838
                                devp, timeoutp, &driver, &driveropts,
 
1839
                                getllnum, &tracksize,
 
1840
                                getllnum, &padsize,
 
1841
                                getnum, &pregapsize,
 
1842
                                getnum, &defpregap,
 
1843
                                &speed,
 
1844
                                &load, &eject, &dummy, &msinfo, &toc, &atip,
 
1845
                                &multi, &fix, &nofix, &waiti,
 
1846
                                &debug, &debug,
 
1847
                                &kdebug, &kdebug,
 
1848
                                &lverbose, &lverbose,
 
1849
                                &scsi_verbose, &scsi_verbose,
 
1850
                                &silent, &silent,
 
1851
                                &audio, &data, &mode2,
 
1852
                                &xa1, &xa2, &cdi,
 
1853
                                &isize,
 
1854
                                &nopreemp, &preemp,
 
1855
                                &nopad, &pad, &bswab, getnum, &fs,
 
1856
                                getbltype, &bltype, &pktsize,
 
1857
                                &ispacket, &noclose, &force,
 
1858
                                &dao, &scms,
 
1859
                                &isrc, &mcn, &tindex,
 
1860
                                &shorttrack, &noshorttrack) < 0) {
 
1861
                        errmsgno(EX_BAD, "Bad Option: %s.\n", cav[0]);
 
1862
                        usage(EX_BAD);
 
1863
                }
 
1864
                if (help)
 
1865
                        usage(0);
 
1866
                if (tracks == 0) {
 
1867
                        if (driver)
 
1868
                                set_cdrcmds(driver, dpp);
 
1869
                        if (version)
 
1870
                                *flagsp |= F_VERSION;
 
1871
                        if (checkdrive)
 
1872
                                *flagsp |= F_CHECKDRIVE;
 
1873
                        if (prcap)
 
1874
                                *flagsp |= F_PRCAP;
 
1875
                        if (inq)
 
1876
                                *flagsp |= F_INQUIRY;
 
1877
                        if (scanbus)
 
1878
                                *flagsp |= F_SCANBUS;
 
1879
                        if (reset)
 
1880
                                *flagsp |= F_RESET;
 
1881
                        if (ignsize)
 
1882
                                *flagsp |= F_IGNSIZE;
 
1883
                        if (load)
 
1884
                                *flagsp |= F_LOAD;
 
1885
                        if (eject)
 
1886
                                *flagsp |= F_EJECT;
 
1887
                        if (dummy)
 
1888
                                *flagsp |= F_DUMMY;
 
1889
                        if (msinfo)
 
1890
                                *flagsp |= F_MSINFO;
 
1891
                        if (toc) {
 
1892
                                *flagsp |= F_TOC;
 
1893
                                *flagsp &= ~F_WRITE;
 
1894
                        }
 
1895
                        if (atip) {
 
1896
                                *flagsp |= F_PRATIP;
 
1897
                                *flagsp &= ~F_WRITE;
 
1898
                        }
 
1899
                        if (multi) {
 
1900
                                *flagsp |= F_MULTI;
 
1901
                                tracktype = TOC_XA2;
 
1902
                                sectype = ST_ROM_MODE2;
 
1903
                                dbtype = DB_XA_MODE2;   /* XXX -multi nimmt DB_XA_MODE2_F1 !!! */
 
1904
                        }
 
1905
                        if (fix)
 
1906
                                *flagsp |= F_FIX;
 
1907
                        if (nofix)
 
1908
                                *flagsp |= F_NOFIX;
 
1909
                        if (waiti)
 
1910
                                *flagsp |= F_WAITI;
 
1911
                        if (force) 
 
1912
                                *flagsp |= F_FORCE;
 
1913
 
 
1914
                        if (bltype >= 0) {
 
1915
                                *flagsp |= F_BLANK;
 
1916
                                *blankp = bltype;
 
1917
                        }
 
1918
                        if (dao) {
 
1919
                                *flagsp |= F_SAO;
 
1920
                                trackp[0].flags &= ~TI_TAO;
 
1921
                        }
 
1922
                        if (mcn) {
 
1923
#ifdef  AUINFO
 
1924
                                setmcn(mcn, &trackp[0]);
 
1925
#else
 
1926
                                trackp[0].isrc = malloc(16);
 
1927
                                fillbytes(trackp[0].isrc, 16, '\0');
 
1928
                                strncpy(trackp[0].isrc, mcn, 13);
 
1929
#endif
 
1930
                                mcn = NULL;
 
1931
                        }
 
1932
                        version = checkdrive = prcap = inq = scanbus = reset = ignsize =
 
1933
                        load = eject = dummy = msinfo = toc = atip = multi = fix = nofix =
 
1934
                        waiti = force = dao = 0;
 
1935
                } else if ((version + checkdrive + prcap + inq + scanbus + reset + ignsize +
 
1936
                            load + eject + dummy + msinfo + toc + atip + multi + fix + nofix +
 
1937
                            waiti + force + dao) > 0 ||
 
1938
                                mcn != NULL)
 
1939
                        comerrno(EX_BAD, "Badly placed option. Global options must be before any track.\n");
 
1940
 
 
1941
                if (nopreemp)
 
1942
                        preemp = 0;
 
1943
                if (nopad)
 
1944
                        pad = 0;
 
1945
                if (noshorttrack)
 
1946
                        shorttrack = 0;
 
1947
 
 
1948
                if ((audio + data + mode2 + xa1 + xa2 + cdi) > 1) {
 
1949
                        errmsgno(EX_BAD, "Too many types for track %d.\n", tracks+1);
 
1950
                        comerrno(EX_BAD, "Only one of -audio, -data, -mode2, -xa1, -xa2, -cdi allowed.\n");
 
1951
                }
 
1952
                if (ispacket && audio) {
 
1953
                        comerrno(EX_BAD, "Audio data cannot be written in packet mode.\n");
 
1954
                }
 
1955
                got_track = getfiles(&cac, &cav, opts);
 
1956
                if (autoaudio) {
 
1957
                        autoaudio = 0;
 
1958
                        tracktype = TOC_ROM;
 
1959
                        sectype = ST_ROM_MODE1;
 
1960
                        dbtype = DB_ROM_MODE1;
 
1961
                }
 
1962
                if (got_track != 0 && (is_auname(cav[0]) || is_wavname(cav[0]))) {
 
1963
                        autoaudio++;
 
1964
                        audio++;
 
1965
                }
 
1966
                if (data) {
 
1967
                        tracktype = TOC_ROM;
 
1968
                        sectype = ST_ROM_MODE1;
 
1969
                        dbtype = DB_ROM_MODE1;
 
1970
                }
 
1971
                if (mode2) {
 
1972
                        tracktype = TOC_ROM;
 
1973
                        sectype = ST_ROM_MODE2;
 
1974
                        dbtype = DB_ROM_MODE2;
 
1975
                }
 
1976
                if (audio) {
 
1977
                        tracktype = TOC_DA;
 
1978
                        sectype = preemp ? ST_AUDIO_PRE : ST_AUDIO_NOPRE;
 
1979
                        dbtype = DB_RAW;
 
1980
                }
 
1981
                if (xa1) {
 
1982
                        tracktype = TOC_XA1;
 
1983
                        sectype = ST_ROM_MODE1;
 
1984
                        dbtype = DB_XA_MODE1;
 
1985
                }
 
1986
                if (xa2) {
 
1987
                        tracktype = TOC_XA2;
 
1988
                        sectype = ST_ROM_MODE2;
 
1989
                        dbtype = DB_XA_MODE2_F1;        /* XXX Das unterscheidet sich von -multi !!! */
 
1990
                }
 
1991
                if (cdi) {
 
1992
                        tracktype = TOC_CDI;
 
1993
                        sectype = ST_ROM_MODE2;
 
1994
                        dbtype = DB_XA_MODE2_F1;
 
1995
                }
 
1996
                if (tracks == 0)
 
1997
                        *toctypep = tracktype;
 
1998
 
 
1999
                flags = 0;
 
2000
                if ((sectype & ST_AUDIOMASK) != 0)
 
2001
                        flags |= TI_AUDIO;
 
2002
                if (isize) {
 
2003
                        flags |= TI_ISOSIZE;
 
2004
                        if ((*flagsp & F_MULTI) != 0)
 
2005
                                comerrno(EX_BAD, "Cannot get isosize for multi session disks.\n");
 
2006
                }
 
2007
                if (preemp)
 
2008
                        flags |= TI_PREEMP;
 
2009
                if (scms)
 
2010
                        flags |= TI_SCMS;
 
2011
 
 
2012
                if ((flags & TI_AUDIO) == 0 && padsize > (Llong)0L)
 
2013
                        pad = TRUE;
 
2014
                if (pad) {
 
2015
                        flags |= TI_PAD;
 
2016
                        if ((flags & TI_AUDIO) == 0 && padsize == (Llong)0L)
 
2017
                                padsize = (Llong)PAD_SIZE;
 
2018
                }
 
2019
                if (shorttrack && (*flagsp & F_SAO) != 0)
 
2020
                        flags |= TI_SHORT_TRACK;
 
2021
                if (noshorttrack)
 
2022
                        flags &= ~TI_SHORT_TRACK;
 
2023
                if (bswab)
 
2024
                        flags |= TI_SWAB;
 
2025
                if (ispacket) 
 
2026
                        flags |= TI_PACKET;
 
2027
                if (noclose) 
 
2028
                        flags |= TI_NOCLOSE;
 
2029
 
 
2030
                if ((*flagsp & F_SAO) == 0)
 
2031
                        flags |= TI_TAO;
 
2032
 
 
2033
                if (got_track == 0)
 
2034
                        break;
 
2035
                tracks++;
 
2036
 
 
2037
                if (tracks > MAX_TRACK)
 
2038
                        comerrno(EX_BAD, "Track limit (%d) exceeded\n",
 
2039
                                                                MAX_TRACK);
 
2040
 
 
2041
                if (strcmp("-", cav[0]) == 0) {
 
2042
                        trackp[tracks].f = STDIN_FILENO;
 
2043
 
 
2044
#if     defined(__CYGWIN32__) || defined(__EMX__)
 
2045
                        setmode(STDIN_FILENO, O_BINARY);
 
2046
#endif
 
2047
                } else {
 
2048
                        if (access(cav[0], R_OK) < 0)
 
2049
                                comerr("No read access for '%s'.\n", cav[0]);
 
2050
 
 
2051
                        if ((trackp[tracks].f = open(cav[0], O_RDONLY|O_BINARY)) < 0)
 
2052
                                comerr("Cannot open '%s'.\n", cav[0]);
 
2053
                }
 
2054
                if (!is_auname(cav[0]) && !is_wavname(cav[0]))
 
2055
                        flags |= TI_NOAUHDR;
 
2056
 
 
2057
                if ((*flagsp & F_SAO) != 0 && (flags & TI_AUDIO) != 0)
 
2058
                        flags |= TI_PREGAP;     /* Hack for now */
 
2059
                if (tracks == 1)
 
2060
                        flags &= ~TI_PREGAP;
 
2061
 
 
2062
                if (tracks == 1 && (pregapsize != -1L && pregapsize != 150))
 
2063
                        pregapsize = -1L;
 
2064
                secsize = tracktype == TOC_DA ? AUDIO_SEC_SIZE : DATA_SEC_SIZE;
 
2065
                trackp[tracks].filename = cav[0];;
 
2066
                trackp[tracks].trackstart = 0L;
 
2067
                trackp[tracks].tracksize = tracksize;
 
2068
                if (trackp[tracks].pregapsize < 0)
 
2069
                        trackp[tracks].pregapsize = pregapsize;
 
2070
                trackp[tracks+1].pregapsize = -1;
 
2071
                trackp[tracks].padsize = padsize;
 
2072
                trackp[tracks].secsize = secsize;
 
2073
                trackp[tracks].secspt = 0;      /* transfer size is set up in set_trsizes() */
 
2074
                trackp[tracks].pktsize = pktsize;
 
2075
                trackp[tracks].trackno = tracks;
 
2076
                trackp[tracks].sectype = sectype;
 
2077
                trackp[tracks].tracktype = tracktype;
 
2078
                trackp[tracks].dbtype = dbtype;
 
2079
                trackp[tracks].flags = flags;
 
2080
                trackp[tracks].nindex = 1;
 
2081
                trackp[tracks].tindex = 0;
 
2082
                checksize(&trackp[tracks]);
 
2083
                tracksize = trackp[tracks].tracksize;
 
2084
                if (!is_shorttrk(&trackp[tracks]) &&
 
2085
                    tracksize > 0 && (tracksize / secsize) < 300) {
 
2086
                        tracksize = roundup(tracksize, secsize);
 
2087
                        padsize = tracksize + roundup(padsize, secsize);
 
2088
                        if ((padsize / secsize) < 300) {
 
2089
                                trackp[tracks].padsize =
 
2090
                                        300 * secsize - tracksize;
 
2091
                        }
 
2092
                }
 
2093
#ifdef  AUINFO
 
2094
                if (useinfo) {
 
2095
                        auinfo(cav[0], tracks, trackp);
 
2096
                        if (tracks == 1)
 
2097
                                printf("pregap1: %ld\n", trackp[1].pregapsize);
 
2098
                }
 
2099
#endif
 
2100
                if (isrc) {
 
2101
#ifdef  AUINFO
 
2102
                        setisrc(isrc, &trackp[tracks]);
 
2103
#else
 
2104
                        trackp[tracks].isrc = malloc(16);
 
2105
                        fillbytes(trackp[tracks].isrc, 16, '\0');
 
2106
                        strncpy(trackp[tracks].isrc, isrc, 12);
 
2107
#endif
 
2108
                }
 
2109
                if (tindex) {
 
2110
#ifdef  AUINFO
 
2111
                        setindex(tindex, &trackp[tracks]);
 
2112
#endif
 
2113
                }
 
2114
 
 
2115
                if (debug) {
 
2116
                        printf("File: '%s' tracksize: %lld secsize: %d tracktype: %d = %s sectype: %X = %s dbtype: %s flags %X\n",
 
2117
                                cav[0], (Llong)trackp[tracks].tracksize, 
 
2118
                                trackp[tracks].secsize, 
 
2119
                                tracktype, toc2name[tracktype & TOC_MASK],
 
2120
                                sectype, st2name[sectype & ST_MASK], db2name[dbtype], flags);
 
2121
                }
 
2122
        }
 
2123
 
 
2124
        if (speed < 0 && speed != -1)
 
2125
                comerrno(EX_BAD, "Bad speed option.\n");
 
2126
 
 
2127
        if (fs < 0L && fs != -1L)
 
2128
                comerrno(EX_BAD, "Bad fifo size option.\n");
 
2129
 
 
2130
        dev = *devp;
 
2131
        cdr_defaults(&dev, &speed, &fs);
 
2132
        if (debug)
 
2133
                printf("dev: %s speed: %d fs: %ld\n", dev, speed, fs);
 
2134
 
 
2135
        if (speed >= 0)
 
2136
                *speedp = speed;
 
2137
 
 
2138
        if (fs < 0L)
 
2139
                fs = DEFAULT_FIFOSIZE;
 
2140
 
 
2141
        if (dev != *devp && (*flagsp & F_SCANBUS) == 0)
 
2142
                *devp = dev;
 
2143
 
 
2144
        if (!*devp && (*flagsp & (F_VERSION|F_SCANBUS)) == 0) {
 
2145
                errmsgno(EX_BAD, "No CD/DVD-Recorder device specified.\n");
 
2146
                usage(EX_BAD);
 
2147
        }
 
2148
        if (*flagsp & (F_LOAD|F_MSINFO|F_TOC|F_PRATIP|F_FIX|F_VERSION|F_CHECKDRIVE|F_PRCAP|F_INQUIRY|F_SCANBUS|F_RESET)) {
 
2149
                if (tracks != 0) {
 
2150
                        errmsgno(EX_BAD, "No tracks allowed with this option\n");
 
2151
                        usage(EX_BAD);
 
2152
                }
 
2153
                return;
 
2154
        }
 
2155
        if (tracks == 0 && (*flagsp & (F_LOAD|F_EJECT|F_BLANK)) == 0) {
 
2156
                errmsgno(EX_BAD, "No tracks specified. Need at least one.\n");
 
2157
                usage(EX_BAD);
 
2158
        }
 
2159
        *tracksp = tracks;
 
2160
        if (*flagsp & F_SAO) {
 
2161
                /*
 
2162
                 * Make sure that you change WRITER_MAXWAIT & READER_MAXWAIT
 
2163
                 * too if you change this timeout.
 
2164
                 */
 
2165
                if (*timeoutp < 200)            /* Lead in size is 2:30 */
 
2166
                        *timeoutp = 200;        /* 200s is 150s *1.33   */
 
2167
        }
 
2168
}
 
2169
 
 
2170
LOCAL void
 
2171
set_trsizes(dp, tracks, trackp)
 
2172
        cdr_t   *dp;
 
2173
        int     tracks;
 
2174
        track_t *trackp;
 
2175
{
 
2176
        int     i;
 
2177
 
 
2178
        /*
 
2179
         * We are using SCSI Group 0 write
 
2180
         * and cannot write more than 255 secs at once.
 
2181
         */
 
2182
        data_secs_per_tr = bufsize/DATA_SEC_SIZE;
 
2183
        audio_secs_per_tr = bufsize/AUDIO_SEC_SIZE;
 
2184
        data_secs_per_tr = min(255, data_secs_per_tr);
 
2185
        audio_secs_per_tr = min(255, audio_secs_per_tr);
 
2186
 
 
2187
        trackp[1].flags         |= TI_FIRST;
 
2188
        trackp[tracks].flags    |= TI_LAST;
 
2189
        
 
2190
        for (i = 1; i <= tracks; i++) {
 
2191
                trackp[i].secspt =
 
2192
                        is_audio(&trackp[i]) ?
 
2193
                                audio_secs_per_tr :
 
2194
                                data_secs_per_tr;
 
2195
                if (is_packet(&trackp[i]) && trackp[i].pktsize > 0) {
 
2196
                        if (trackp[i].secspt >= trackp[i].pktsize) {
 
2197
                                trackp[i].secspt = trackp[i].pktsize;
 
2198
                        } else {
 
2199
                                comerrno(EX_BAD,
 
2200
                                        "Track %d packet size %d exceeds buffer limit of %d sectors",
 
2201
                                        i, trackp[i].pktsize, trackp[i].secspt);
 
2202
                        }
 
2203
                }
 
2204
                if ((dp->cdr_flags & CDR_SWABAUDIO) != 0 &&
 
2205
                                        is_audio(&trackp[i])) {
 
2206
                        trackp[i].flags ^= TI_SWAB;
 
2207
                }
 
2208
        }
 
2209
}
 
2210
 
 
2211
EXPORT void
 
2212
load_media(scgp, dp, doexit)
 
2213
        SCSI    *scgp;
 
2214
        cdr_t   *dp;
 
2215
        BOOL    doexit;
 
2216
{
 
2217
        int     code;
 
2218
        int     key;
 
2219
 
 
2220
        /*
 
2221
         * Do some preparation before...
 
2222
         */
 
2223
        scgp->silent++;                 /* Be quiet if this fails       */
 
2224
        test_unit_ready(scgp);          /* First eat up unit attention  */
 
2225
        (*dp->cdr_load)(scgp);          /* now try to load media and    */
 
2226
        scsi_start_stop_unit(scgp, 1, 0);/* start unit in silent mode   */
 
2227
        scgp->silent--;
 
2228
 
 
2229
        if (!wait_unit_ready(scgp, 60)) {
 
2230
                code = scg_sense_code(scgp);
 
2231
                key = scg_sense_key(scgp);
 
2232
                scgp->silent++;
 
2233
                scsi_prevent_removal(scgp, 0);/* In case someone locked it */
 
2234
                scgp->silent--;
 
2235
 
 
2236
                if (!doexit)
 
2237
                        return;
 
2238
                if (key == SC_NOT_READY && (code == 0x3A || code == 0x30))
 
2239
                        comerrno(EX_BAD, "No disk / Wrong disk!\n");
 
2240
                comerrno(EX_BAD, "CD/DVD-Recorder not ready.\n");
 
2241
        }
 
2242
 
 
2243
        scsi_prevent_removal(scgp, 1);
 
2244
        scsi_start_stop_unit(scgp, 1, 0);
 
2245
        wait_unit_ready(scgp, 120);
 
2246
        scgp->silent++;
 
2247
        rezero_unit(scgp);      /* Is this needed? Not supported by some drvives */
 
2248
        scgp->silent--;
 
2249
        test_unit_ready(scgp);
 
2250
        scsi_start_stop_unit(scgp, 1, 0);
 
2251
        wait_unit_ready(scgp, 120);
 
2252
}
 
2253
 
 
2254
EXPORT void
 
2255
unload_media(scgp, dp, flags)
 
2256
        SCSI    *scgp;
 
2257
        cdr_t   *dp;
 
2258
        int     flags;
 
2259
{
 
2260
        scsi_prevent_removal(scgp, 0);
 
2261
        if ((flags & F_EJECT) != 0)
 
2262
                (*dp->cdr_unload)(scgp);
 
2263
}
 
2264
 
 
2265
EXPORT void
 
2266
set_secsize(scgp, secsize)
 
2267
        SCSI    *scgp;
 
2268
        int     secsize;
 
2269
{
 
2270
        if (secsize > 0) {
 
2271
                /*
 
2272
                 * Try to restore the old sector size.
 
2273
                 */
 
2274
                scgp->silent++;
 
2275
                select_secsize(scgp, secsize);
 
2276
                scgp->silent--;
 
2277
        }
 
2278
}
 
2279
 
 
2280
LOCAL void
 
2281
check_recovery(scgp, dp, flags)
 
2282
        SCSI    *scgp;
 
2283
        cdr_t   *dp;
 
2284
        int     flags;
 
2285
{
 
2286
        if ((*dp->cdr_check_recovery)(scgp)) {
 
2287
                errmsgno(EX_BAD, "Recovery needed.\n");
 
2288
                unload_media(scgp, dp, flags);
 
2289
                excdr(EX_BAD, NULL);    /* XXX &exargs ??? */
 
2290
                exit(EX_BAD);
 
2291
        }
 
2292
}
 
2293
 
 
2294
#define DEBUG
 
2295
void audioread(scgp, dp, flags)
 
2296
        SCSI    *scgp;
 
2297
        cdr_t   *dp;
 
2298
        int     flags;
 
2299
{
 
2300
#ifdef  DEBUG
 
2301
        int speed = 1;
 
2302
        int dummy = 0;
 
2303
 
 
2304
        if ((*dp->cdr_set_speed_dummy)(scgp, &speed, dummy) < 0)
 
2305
                exit(-1);
 
2306
        if ((*dp->cdr_set_secsize)(scgp, 2352) < 0)
 
2307
                exit(-1);
 
2308
        scgp->cap->c_bsize = 2352;
 
2309
 
 
2310
        read_scsi(scgp, buf, 1000, 1);
 
2311
        printf("XXX:\n");
 
2312
        write(1, buf, 512);
 
2313
        unload_media(scgp, dp, flags);
 
2314
        excdr(0, NULL); /* XXX &exargs ??? */
 
2315
        exit(0);
 
2316
#endif
 
2317
}
 
2318
 
 
2319
LOCAL void
 
2320
print_msinfo(scgp, dp)
 
2321
        SCSI    *scgp;
 
2322
        cdr_t   *dp;
 
2323
{
 
2324
        long    off;
 
2325
        long    fa;
 
2326
 
 
2327
        if ((*dp->cdr_session_offset)(scgp, &off) < 0) {
 
2328
                errmsgno(EX_BAD, "Cannot read session offset\n");
 
2329
                return;
 
2330
        }
 
2331
        if (lverbose)
 
2332
                printf("session offset: %ld\n", off);
 
2333
 
 
2334
        if (dp->cdr_next_wr_address(scgp, 0, (track_t *)0, &fa) < 0) {
 
2335
                errmsgno(EX_BAD, "Cannot read first writable address\n");
 
2336
                return;
 
2337
        }
 
2338
        printf("%ld,%ld\n", off, fa);
 
2339
}
 
2340
 
 
2341
LOCAL void
 
2342
print_toc(scgp, dp)
 
2343
        SCSI    *scgp;
 
2344
        cdr_t   *dp;
 
2345
{
 
2346
        int     first;
 
2347
        int     last;
 
2348
        long    lba;
 
2349
        long    xlba;
 
2350
        struct msf msf;
 
2351
        int     adr;
 
2352
        int     control;
 
2353
        int     mode;
 
2354
        int     i;
 
2355
 
 
2356
        scgp->silent++;
 
2357
        if (read_capacity(scgp) < 0) {
 
2358
                scgp->silent--;
 
2359
                errmsgno(EX_BAD, "Cannot read capacity\n");
 
2360
                return;
 
2361
        }
 
2362
        scgp->silent--;
 
2363
        if (read_tochdr(scgp, dp, &first, &last) < 0) {
 
2364
                errmsgno(EX_BAD, "Cannot read TOC/PMA\n");
 
2365
                return;
 
2366
        }
 
2367
        printf("first: %d last %d\n", first, last);
 
2368
        for (i = first; i <= last; i++) {
 
2369
                read_trackinfo(scgp, i, &lba, &msf, &adr, &control, &mode);
 
2370
                xlba = -150 +
 
2371
                        msf.msf_frame + (75*msf.msf_sec) + (75*60*msf.msf_min);
 
2372
                if (xlba == lba/4)
 
2373
                        lba = xlba;
 
2374
                print_track(i, lba, &msf, adr, control, mode);
 
2375
        }
 
2376
        i = 0xAA;
 
2377
        read_trackinfo(scgp, i, &lba, &msf, &adr, &control, &mode);
 
2378
        xlba = -150 +
 
2379
                msf.msf_frame + (75*msf.msf_sec) + (75*60*msf.msf_min);
 
2380
        if (xlba == lba/4)
 
2381
                lba = xlba;
 
2382
        print_track(i, lba, &msf, adr, control, mode);
 
2383
        if (lverbose > 1) {
 
2384
                scgp->silent++;
 
2385
                if (read_cdtext(scgp) < 0)
 
2386
                        errmsgno(EX_BAD, "No CD-Text or CD-Text unaware drive.\n");
 
2387
                scgp->silent++;
 
2388
        }
 
2389
}
 
2390
 
 
2391
LOCAL void
 
2392
print_track(track, lba, msp, adr, control, mode)
 
2393
        int     track;
 
2394
        long    lba;
 
2395
        struct msf *msp;
 
2396
        int     adr;
 
2397
        int     control;
 
2398
        int     mode;
 
2399
{
 
2400
        long    lba_512 = lba*4;
 
2401
 
 
2402
        if (track == 0xAA)
 
2403
                printf("track:lout ");
 
2404
        else
 
2405
                printf("track: %3d ", track);
 
2406
 
 
2407
        printf("lba: %9ld (%9ld) %02d:%02d:%02d adr: %X control: %X mode: %d\n",
 
2408
                        lba, lba_512,
 
2409
                        msp->msf_min,
 
2410
                        msp->msf_sec,
 
2411
                        msp->msf_frame,
 
2412
                        adr, control, mode);
 
2413
}
 
2414
 
 
2415
LOCAL void
 
2416
prtimediff(fmt, start, stop)
 
2417
        const   char    *fmt;
 
2418
        struct timeval  *start;
 
2419
        struct timeval  *stop;
 
2420
{
 
2421
        struct timeval tv;
 
2422
 
 
2423
        tv.tv_sec = stop->tv_sec - start->tv_sec;
 
2424
        tv.tv_usec = stop->tv_usec - start->tv_usec;
 
2425
        while (tv.tv_usec > 1000000) {
 
2426
                tv.tv_usec -= 1000000;
 
2427
                tv.tv_sec += 1;
 
2428
        }
 
2429
        while (tv.tv_usec < 0) {
 
2430
                tv.tv_usec += 1000000;
 
2431
                tv.tv_sec -= 1;
 
2432
        }
 
2433
        /*
 
2434
         * We need to cast timeval->* to long because
 
2435
         * of the broken sys/time.h in Linux.
 
2436
         */
 
2437
        printf("%s%4ld.%03lds\n", fmt, (long)tv.tv_sec, (long)tv.tv_usec/1000);
 
2438
        flush();
 
2439
}
 
2440
 
 
2441
#ifdef  HAVE_SYS_PRIOCNTL_H
 
2442
 
 
2443
#include <sys/procset.h>        /* Needed for SCO Openserver */
 
2444
#include <sys/priocntl.h>
 
2445
#include <sys/rtpriocntl.h>
 
2446
 
 
2447
EXPORT  void
 
2448
raisepri(pri)
 
2449
        int pri;
 
2450
{
 
2451
        int             pid;
 
2452
        int             classes;
 
2453
        int             ret;
 
2454
        pcinfo_t        info;
 
2455
        pcparms_t       param;
 
2456
        rtinfo_t        rtinfo;
 
2457
        rtparms_t       rtparam;
 
2458
 
 
2459
        pid = getpid();
 
2460
 
 
2461
        /* get info */
 
2462
        strcpy(info.pc_clname, "RT");
 
2463
        classes = priocntl(P_PID, pid, PC_GETCID, (void *)&info);
 
2464
        if (classes == -1)
 
2465
                comerr("Cannot get priority class id priocntl(PC_GETCID)\n");
 
2466
 
 
2467
        movebytes(info.pc_clinfo, &rtinfo, sizeof(rtinfo_t));
 
2468
 
 
2469
        /* set priority to max */
 
2470
        rtparam.rt_pri = rtinfo.rt_maxpri - pri;
 
2471
        rtparam.rt_tqsecs = 0;
 
2472
        rtparam.rt_tqnsecs = RT_TQDEF;
 
2473
        param.pc_cid = info.pc_cid;
 
2474
        movebytes(&rtparam, param.pc_clparms, sizeof(rtparms_t));
 
2475
        ret = priocntl(P_PID, pid, PC_SETPARMS, (void *)&param);
 
2476
        if (ret == -1) {
 
2477
                errmsg("WARNING: Cannot set priority class parameters priocntl(PC_SETPARMS)\n");
 
2478
                errmsgno(EX_BAD, "WARNING: This causes a high risk for buffer underruns.\n");
 
2479
        }
 
2480
}
 
2481
 
 
2482
#else   /* HAVE_SYS_PRIOCNTL_H */
 
2483
 
 
2484
#if defined(_POSIX_PRIORITY_SCHEDULING)
 
2485
/*
 
2486
 * XXX Ugly but needed because of a typo in /usr/iclude/sched.h on Linux.
 
2487
 * XXX This should be removed as soon as we are sure that Linux-2.0.29 is gone.
 
2488
 */
 
2489
#ifdef  __linux
 
2490
#define _P      __P
 
2491
#endif
 
2492
 
 
2493
#include <sched.h>
 
2494
 
 
2495
#ifdef  __linux
 
2496
#undef  _P
 
2497
#endif
 
2498
 
 
2499
LOCAL   int
 
2500
rt_raisepri(pri)
 
2501
        int pri;
 
2502
{
 
2503
        struct sched_param scp;
 
2504
 
 
2505
        /*
 
2506
         * Verify that scheduling is available
 
2507
         */
 
2508
#ifdef  _SC_PRIORITY_SCHEDULING
 
2509
        if (sysconf(_SC_PRIORITY_SCHEDULING) == -1) {
 
2510
                errmsg("WARNING: RR-scheduler not available, disabling.\n");
 
2511
                return(-1);
 
2512
        }
 
2513
#endif
 
2514
        fillbytes(&scp, sizeof(scp), '\0');
 
2515
        scp.sched_priority = sched_get_priority_max(SCHED_RR) - pri;
 
2516
        if (sched_setscheduler(0, SCHED_RR, &scp) < 0) {
 
2517
                errmsg("WARNING: Cannot set RR-scheduler\n");
 
2518
                return (-1);
 
2519
        }
 
2520
        return (0);
 
2521
}
 
2522
 
 
2523
#else   /* _POSIX_PRIORITY_SCHEDULING */
 
2524
 
 
2525
#ifdef  __CYGWIN32__
 
2526
 
 
2527
/*
 
2528
 * NOTE: Base.h from Cygwin-B20 has a second typedef for BOOL.
 
2529
 *       We define BOOL to make all local code use BOOL
 
2530
 *       from Windows.h and use the hidden __SBOOL for
 
2531
 *       our global interfaces.
 
2532
 *
 
2533
 * NOTE: windows.h from Cygwin-1.x includes a structure field named sample,
 
2534
 *       so me may not define our own 'sample' or need to #undef it now.
 
2535
 *       With a few nasty exceptions, Microsoft assumes that any global
 
2536
 *       defines or identifiers will begin with an Uppercase letter, so
 
2537
 *       there may be more of these problems in the future.
 
2538
 *
 
2539
 * NOTE: windows.h defines interface as an alias for struct, this 
 
2540
 *       is used by COM/OLE2, I guess it is class on C++
 
2541
 *       We man need to #undef 'interface'
 
2542
 */
 
2543
#define BOOL    WBOOL           /* This is the Win BOOL         */
 
2544
#define format  __format        /* Avoid format parameter hides global ... */
 
2545
#include <windows.h>
 
2546
#undef format
 
2547
#undef interface
 
2548
 
 
2549
LOCAL   int
 
2550
rt_raisepri(pri)
 
2551
        int pri;
 
2552
{
 
2553
        /* set priority class */
 
2554
        if (SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS) == FALSE) {
 
2555
                errmsgno(EX_BAD, "No realtime priority class possible.\n");
 
2556
                return (-1);
 
2557
        }
 
2558
 
 
2559
        /* set thread priority */
 
2560
        if (SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL-pri) == FALSE) {
 
2561
                errmsgno(EX_BAD, "Could not set realtime priority.\n");
 
2562
                return (-1);
 
2563
        }
 
2564
        return (0);
 
2565
}
 
2566
 
 
2567
#else
 
2568
 
 
2569
LOCAL   int
 
2570
rt_raisepri(pri)
 
2571
        int pri;
 
2572
{
 
2573
        return (-1);
 
2574
}
 
2575
 
 
2576
#endif  /* __CYGWIN32__ */
 
2577
 
 
2578
#endif  /* _POSIX_PRIORITY_SCHEDULING */
 
2579
 
 
2580
EXPORT  void
 
2581
raisepri(pri)
 
2582
        int pri;
 
2583
{
 
2584
        if (rt_raisepri(pri) >= 0)
 
2585
                return;
 
2586
#if     defined(HAVE_SETPRIORITY) && defined(PRIO_PROCESS)
 
2587
 
 
2588
        if (setpriority(PRIO_PROCESS, getpid(), -20 + pri) < 0) {
 
2589
                errmsg("WARNING: Cannot set priority using setpriority().\n");
 
2590
                errmsgno(EX_BAD, "WARNING: This causes a high risk for buffer underruns.\n");
 
2591
        }
 
2592
#else
 
2593
#ifdef  HAVE_DOSSETPRIORITY     /* RT priority on OS/2 */
 
2594
        /*
 
2595
         * Set priority to timecritical 31 - pri (arg)
 
2596
         */
 
2597
        DosSetPriority(0, 3, 31, 0);
 
2598
        DosSetPriority(0, 3, -pri, 0);
 
2599
#else
 
2600
#ifdef  HAVE_NICE
 
2601
        if (nice(-20 + pri) == -1) {
 
2602
                errmsg("WARNING: Cannot set priority using nice().\n");
 
2603
                errmsgno(EX_BAD, "WARNING: This causes a high risk for buffer underruns.\n");
 
2604
        }
 
2605
#else
 
2606
        errmsgno(EX_BAD, "WARNING: Cannot set priority on this OS.\n");
 
2607
        errmsgno(EX_BAD, "WARNING: This causes a high risk for buffer underruns.\n");
 
2608
#endif
 
2609
#endif
 
2610
#endif
 
2611
}
 
2612
 
 
2613
#endif  /* HAVE_SYS_PRIOCNTL_H */
 
2614
 
 
2615
#ifdef  HAVE_SELECT
 
2616
/*
 
2617
 * sys/types.h and sys/time.h are already included.
 
2618
 */
 
2619
#else
 
2620
#       include <stropts.h>
 
2621
#       include <poll.h>
 
2622
 
 
2623
#ifndef INFTIM
 
2624
#define INFTIM  (-1)
 
2625
#endif
 
2626
#endif
 
2627
 
 
2628
#if     defined(HAVE_SELECT) && defined(NEED_SYS_SELECT_H)
 
2629
#include <sys/select.h>
 
2630
#endif
 
2631
 
 
2632
LOCAL void
 
2633
wait_input()
 
2634
{
 
2635
#ifdef  HAVE_SELECT
 
2636
        fd_set  in;
 
2637
 
 
2638
        FD_ZERO(&in);
 
2639
        FD_SET(STDIN_FILENO, &in);
 
2640
        select(1, &in, NULL, NULL, 0);
 
2641
#else
 
2642
        struct pollfd pfd;
 
2643
 
 
2644
        pfd.fd = STDIN_FILENO;
 
2645
        pfd.events = POLLIN;
 
2646
        pfd.revents = 0;
 
2647
        poll(&pfd, (unsigned long)1, INFTIM);
 
2648
#endif
 
2649
}
 
2650
 
 
2651
LOCAL void
 
2652
checkgui()
 
2653
{
 
2654
        struct stat st;
 
2655
 
 
2656
        if (fstat(STDERR_FILENO, &st) >= 0 && !S_ISCHR(st.st_mode)) {
 
2657
                isgui = TRUE;
 
2658
                if (lverbose > 1)
 
2659
                        printf("Using remote (pipe) mode for interactive i/o.\n");
 
2660
        }
 
2661
}
 
2662
 
 
2663
LOCAL Llong
 
2664
number(arg, retp)
 
2665
        register char   *arg;
 
2666
                int     *retp;
 
2667
{
 
2668
        Llong   val     = 0;
 
2669
 
 
2670
        if (*retp != 1)
 
2671
                return (val);
 
2672
        if (*arg == '\0') {
 
2673
                *retp = -1;
 
2674
        } else if (*(arg = astoll(arg, &val))) {
 
2675
                if (*arg == 'p' || *arg == 'P') {
 
2676
                        val *= (1024*1024);
 
2677
                        val *= (1024*1024*1024);
 
2678
                        arg++;
 
2679
                }
 
2680
                if (*arg == 't' || *arg == 'T') {
 
2681
                        val *= (1024*1024);
 
2682
                        val *= (1024*1024);
 
2683
                        arg++;
 
2684
                }
 
2685
                if (*arg == 'g' || *arg == 'G') {
 
2686
                        val *= (1024*1024*1024);
 
2687
                        arg++;
 
2688
                }
 
2689
                if (*arg == 'm' || *arg == 'M') {
 
2690
                        val *= (1024*1024);
 
2691
                        arg++;
 
2692
                }
 
2693
                else if (*arg == 'f' || *arg == 'F') {
 
2694
                        val *= 2352;
 
2695
                        arg++;
 
2696
                }
 
2697
                else if (*arg == 's' || *arg == 'S') {
 
2698
                        val *= 2048;
 
2699
                        arg++;
 
2700
                }
 
2701
                else if (*arg == 'k' || *arg == 'K') {
 
2702
                        val *= 1024;
 
2703
                        arg++;
 
2704
                }
 
2705
                else if (*arg == 'b' || *arg == 'B') {
 
2706
                        val *= 512;
 
2707
                        arg++;
 
2708
                }
 
2709
                else if (*arg == 'w' || *arg == 'W') {
 
2710
                        val *= 2;
 
2711
                        arg++;
 
2712
                }
 
2713
                if (*arg == '*' || *arg == 'x')
 
2714
                        val *= number(++arg, retp);
 
2715
                else if (*arg != '\0')
 
2716
                        *retp = -1;
 
2717
        }
 
2718
        return (val);
 
2719
}
 
2720
 
 
2721
EXPORT int
 
2722
getnum(arg, valp)
 
2723
        char    *arg;
 
2724
        long    *valp;
 
2725
{
 
2726
        int     ret = 1;
 
2727
 
 
2728
        *valp = (long)number(arg, &ret);
 
2729
        return (ret);
 
2730
}
 
2731
 
 
2732
EXPORT int
 
2733
getllnum(arg, lvalp)
 
2734
        char    *arg;
 
2735
        Llong   *lvalp;
 
2736
{
 
2737
        int     ret = 1;
 
2738
 
 
2739
        *lvalp = number(arg, &ret);
 
2740
        return (ret);
 
2741
}
 
2742
 
 
2743
LOCAL int
 
2744
getbltype(optstr, typep)
 
2745
        char    *optstr;
 
2746
        long    *typep;
 
2747
{
 
2748
        if (streql(optstr, "all")) {
 
2749
                *typep = BLANK_DISC;
 
2750
        } else if (streql(optstr, "disc")) {
 
2751
                *typep = BLANK_DISC;
 
2752
        } else if (streql(optstr, "disk")) {
 
2753
                *typep = BLANK_DISC;
 
2754
        } else if (streql(optstr, "fast")) {
 
2755
                *typep = BLANK_MINIMAL;
 
2756
        } else if (streql(optstr, "minimal")) {
 
2757
                *typep = BLANK_MINIMAL;
 
2758
        } else if (streql(optstr, "track")) {
 
2759
                *typep = BLANK_TRACK;
 
2760
        } else if (streql(optstr, "unreserve")) {
 
2761
                *typep = BLANK_UNRESERVE;
 
2762
        } else if (streql(optstr, "trtail")) {
 
2763
                *typep = BLANK_TAIL;
 
2764
        } else if (streql(optstr, "unclose")) {
 
2765
                *typep = BLANK_UNCLOSE;
 
2766
        } else if (streql(optstr, "session")) {
 
2767
                *typep = BLANK_SESSION;
 
2768
        } else if (streql(optstr, "help")) {
 
2769
                blusage(0);
 
2770
        } else {
 
2771
                error("Illegal blanking type '%s'.\n", optstr);
 
2772
                blusage(EX_BAD);
 
2773
                return (-1);
 
2774
        }
 
2775
        return (TRUE);
 
2776
}