Merge commit 'brent/register_phys_mem'
[freebsd-src/fkvm-freebsd.git] / usr.sbin / burncd / burncd.c
blob2800f5236be5452f0504ef4846172af79830c3be
1 /*-
2 * Copyright (c) 2000,2001,2002 Søren Schmidt <sos@freebsd.org>
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer,
10 * without modification, immediately at the beginning of the file.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * $FreeBSD$
31 #include <unistd.h>
32 #include <stdint.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <err.h>
37 #include <sysexits.h>
38 #include <fcntl.h>
39 #include <sys/errno.h>
40 #include <sys/ioctl.h>
41 #include <sys/stat.h>
42 #include <sys/cdio.h>
43 #include <sys/cdrio.h>
44 #include <sys/dvdio.h>
45 #include <sys/param.h>
46 #include <arpa/inet.h>
48 #define BLOCKS 16
50 struct track_info {
51 int file;
52 char file_name[MAXPATHLEN + 1];
53 off_t file_size;
54 int block_size;
55 int block_type;
56 int pregap;
57 int addr;
59 static struct track_info tracks[100];
60 static int global_fd_for_cleanup, quiet, verbose, saved_block_size, notracks;
62 void add_track(char *, int, int, int);
63 void do_DAO(int fd, int, int);
64 void do_TAO(int fd, int, int, int);
65 void do_format(int, int, char *);
66 int write_file(int fd, struct track_info *);
67 int roundup_blocks(struct track_info *);
68 void cue_ent(struct cdr_cue_entry *, int, int, int, int, int, int, int);
69 void cleanup(int);
70 void usage(void);
72 int
73 main(int argc, char **argv)
75 int arg, addr, ch, fd;
76 int dao = 0, eject = 0, fixate = 0, list = 0, multi = 0, preemp = 0;
77 int nogap = 0, speed = 4 * 177, test_write = 0, force = 0;
78 int block_size = 0, block_type = 0, cdopen = 0, dvdrw = 0;
79 const char *dev;
81 if ((dev = getenv("CDROM")) == NULL)
82 dev = "/dev/acd0";
84 while ((ch = getopt(argc, argv, "def:Flmnpqs:tv")) != -1) {
85 switch (ch) {
86 case 'd':
87 dao = 1;
88 break;
90 case 'e':
91 eject = 1;
92 break;
94 case 'f':
95 dev = optarg;
96 break;
98 case 'F':
99 force = 1;
100 break;
102 case 'l':
103 list = 1;
104 break;
106 case 'm':
107 multi = 1;
108 break;
110 case 'n':
111 nogap = 1;
112 break;
114 case 'p':
115 preemp = 1;
116 break;
118 case 'q':
119 quiet = 1;
120 break;
122 case 's':
123 if (strcasecmp("max", optarg) == 0)
124 speed = CDR_MAX_SPEED;
125 else
126 speed = atoi(optarg) * 177;
127 if (speed <= 0)
128 errx(EX_USAGE, "Invalid speed: %s", optarg);
129 break;
131 case 't':
132 test_write = 1;
133 break;
135 case 'v':
136 verbose = 1;
137 break;
139 default:
140 usage();
143 argc -= optind;
144 argv += optind;
146 if (argc == 0)
147 usage();
149 if ((fd = open(dev, O_RDWR, 0)) < 0)
150 err(EX_NOINPUT, "open(%s)", dev);
152 if (ioctl(fd, CDRIOCGETBLOCKSIZE, &saved_block_size) < 0)
153 err(EX_IOERR, "ioctl(CDRIOCGETBLOCKSIZE)");
155 if (ioctl(fd, CDRIOCWRITESPEED, &speed) < 0)
156 err(EX_IOERR, "ioctl(CDRIOCWRITESPEED)");
158 global_fd_for_cleanup = fd;
159 err_set_exit(cleanup);
161 for (arg = 0; arg < argc; arg++) {
162 if (!strcasecmp(argv[arg], "fixate")) {
163 fixate = 1;
164 continue;
166 if (!strcasecmp(argv[arg], "eject")) {
167 eject = 1;
168 break;
170 if (!strcasecmp(argv[arg], "msinfo")) {
171 struct ioc_read_toc_single_entry entry;
172 struct ioc_toc_header header;
174 if (ioctl(fd, CDIOREADTOCHEADER, &header) < 0)
175 err(EX_IOERR, "ioctl(CDIOREADTOCHEADER)");
176 bzero(&entry, sizeof(struct ioc_read_toc_single_entry));
177 entry.address_format = CD_LBA_FORMAT;
178 entry.track = header.ending_track;
179 if (ioctl(fd, CDIOREADTOCENTRY, &entry) < 0)
180 err(EX_IOERR, "ioctl(CDIOREADTOCENTRY)");
181 if (ioctl(fd, CDRIOCNEXTWRITEABLEADDR, &addr) < 0)
182 err(EX_IOERR, "ioctl(CDRIOCNEXTWRITEABLEADDR)");
183 fprintf(stdout, "%d,%d\n",
184 ntohl(entry.entry.addr.lba), addr);
186 break;
188 if ((!strcasecmp(argv[arg], "erase") ||
189 !strcasecmp(argv[arg], "blank")) && !test_write) {
190 int blank, pct, last = 0;
192 if (!strcasecmp(argv[arg], "erase"))
193 blank = CDR_B_ALL;
194 else
195 blank = CDR_B_MIN;
196 if (!quiet)
197 fprintf(stderr, "%sing CD, please wait..\r",
198 blank == CDR_B_ALL ? "eras" : "blank");
200 if (ioctl(fd, CDRIOCBLANK, &blank) < 0)
201 err(EX_IOERR, "ioctl(CDRIOCBLANK)");
202 while (1) {
203 sleep(1);
204 if (ioctl(fd, CDRIOCGETPROGRESS, &pct) == -1)
205 err(EX_IOERR,"ioctl(CDRIOGETPROGRESS)");
206 if (pct > 0 && !quiet)
207 fprintf(stderr,
208 "%sing CD - %d %% done \r",
209 blank == CDR_B_ALL ?
210 "eras" : "blank", pct);
211 if (pct == 100 || (pct == 0 && last > 90))
212 break;
213 last = pct;
215 if (!quiet)
216 printf("\n");
217 continue;
219 if (!strcasecmp(argv[arg], "format") && !test_write) {
220 if (arg + 1 < argc &&
221 (!strcasecmp(argv[arg + 1], "dvd+rw") ||
222 !strcasecmp(argv[arg + 1], "dvd-rw")))
223 do_format(fd, force, argv[arg + 1]);
224 else
225 errx(EX_NOINPUT, "format media type invalid");
226 arg++;
227 continue;
229 if (!strcasecmp(argv[arg], "audio") || !strcasecmp(argv[arg], "raw")) {
230 block_type = CDR_DB_RAW;
231 block_size = 2352;
232 continue;
234 if (!strcasecmp(argv[arg], "data") || !strcasecmp(argv[arg], "mode1")) {
235 block_type = CDR_DB_ROM_MODE1;
236 block_size = 2048;
237 continue;
239 if (!strcasecmp(argv[arg], "mode2")) {
240 block_type = CDR_DB_ROM_MODE2;
241 block_size = 2336;
242 continue;
244 if (!strcasecmp(argv[arg], "xamode1")) {
245 block_type = CDR_DB_XA_MODE1;
246 block_size = 2048;
247 continue;
249 if (!strcasecmp(argv[arg], "xamode2")) {
250 block_type = CDR_DB_XA_MODE2_F2;
251 block_size = 2324;
252 continue;
254 if (!strcasecmp(argv[arg], "vcd")) {
255 block_type = CDR_DB_XA_MODE2_F2;
256 block_size = 2352;
257 dao = 1;
258 nogap = 1;
259 continue;
261 if (!strcasecmp(argv[arg], "dvdrw")) {
262 block_type = CDR_DB_ROM_MODE1;
263 block_size = 2048;
264 dvdrw = 1;
265 continue;
268 if (!block_size)
269 errx(EX_NOINPUT, "no data format selected");
270 if (list) {
271 char file_buf[MAXPATHLEN + 1], *eol;
272 FILE *fp;
274 if ((fp = fopen(argv[arg], "r")) == NULL)
275 err(EX_NOINPUT, "fopen(%s)", argv[arg]);
277 while (fgets(file_buf, sizeof(file_buf), fp) != NULL) {
278 if (*file_buf == '#' || *file_buf == '\n')
279 continue;
280 if ((eol = strchr(file_buf, '\n')))
281 *eol = '\0';
282 add_track(file_buf, block_size, block_type, nogap);
284 if (feof(fp))
285 fclose(fp);
286 else
287 err(EX_IOERR, "fgets(%s)", file_buf);
289 else
290 add_track(argv[arg], block_size, block_type, nogap);
292 if (notracks) {
293 if (dvdrw && notracks > 1)
294 errx(EX_USAGE, "DVD's only have 1 track");
295 if (ioctl(fd, CDIOCSTART, 0) < 0)
296 err(EX_IOERR, "ioctl(CDIOCSTART)");
297 if (!cdopen) {
298 if (ioctl(fd, CDRIOCINITWRITER, &test_write) < 0)
299 err(EX_IOERR, "ioctl(CDRIOCINITWRITER)");
300 cdopen = 1;
302 if (dao)
303 do_DAO(fd, test_write, multi);
304 else
305 do_TAO(fd, test_write, preemp, dvdrw);
307 if (!test_write && fixate && !dao && !dvdrw) {
308 if (!quiet)
309 fprintf(stderr, "fixating CD, please wait..\n");
310 if (ioctl(fd, CDRIOCFIXATE, &multi) < 0)
311 err(EX_IOERR, "ioctl(CDRIOCFIXATE)");
314 if (ioctl(fd, CDRIOCSETBLOCKSIZE, &saved_block_size) < 0) {
315 err_set_exit(NULL);
316 err(EX_IOERR, "ioctl(CDRIOCSETBLOCKSIZE)");
319 if (eject)
320 if (ioctl(fd, CDIOCEJECT) < 0)
321 err(EX_IOERR, "ioctl(CDIOCEJECT)");
322 close(fd);
323 exit(EX_OK);
326 void
327 add_track(char *name, int block_size, int block_type, int nogap)
329 struct stat sb;
330 int file;
331 static int done_stdin = 0;
333 if (!strcmp(name, "-")) {
334 if (done_stdin) {
335 warn("skipping multiple usages of stdin");
336 return;
338 file = STDIN_FILENO;
339 done_stdin = 1;
341 else if ((file = open(name, O_RDONLY, 0)) < 0)
342 err(EX_NOINPUT, "open(%s)", name);
343 if (fstat(file, &sb) < 0)
344 err(EX_IOERR, "fstat(%s)", name);
345 tracks[notracks].file = file;
346 strncpy(tracks[notracks].file_name, name, MAXPATHLEN);
347 if (file == STDIN_FILENO)
348 tracks[notracks].file_size = -1;
349 else
350 tracks[notracks].file_size = sb.st_size;
351 tracks[notracks].block_size = block_size;
352 tracks[notracks].block_type = block_type;
354 if (nogap && notracks)
355 tracks[notracks].pregap = 0;
356 else {
357 if (tracks[notracks - (notracks > 0)].block_type == block_type)
358 tracks[notracks].pregap = 150;
359 else
360 tracks[notracks].pregap = 255;
363 if (verbose) {
364 int pad = 0;
366 if (tracks[notracks].file_size / tracks[notracks].block_size !=
367 roundup_blocks(&tracks[notracks]))
368 pad = 1;
369 fprintf(stderr,
370 "adding type 0x%02x file %s size %jd KB %d blocks %s\n",
371 tracks[notracks].block_type, name,
372 (intmax_t)sb.st_size/1024,
373 roundup_blocks(&tracks[notracks]),
374 pad ? "(0 padded)" : "");
376 notracks++;
379 void
380 do_DAO(int fd, int test_write, int multi)
382 struct cdr_cuesheet sheet;
383 struct cdr_cue_entry cue[100];
384 int format = CDR_SESS_CDROM;
385 int addr, i, j = 0;
387 int bt2ctl[16] = { 0x0, -1, -1, -1, -1, -1, -1, -1,
388 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, -1, -1 };
390 int bt2df[16] = { 0x0, -1, -1, -1, -1, -1, -1, -1,
391 0x10, 0x30, 0x20, -1, 0x21, -1, -1, -1 };
393 if (ioctl(fd, CDRIOCNEXTWRITEABLEADDR, &addr) < 0)
394 err(EX_IOERR, "ioctl(CDRIOCNEXTWRITEABLEADDR)");
395 if (verbose)
396 fprintf(stderr, "next writeable LBA %d\n", addr);
398 cue_ent(&cue[j++], bt2ctl[tracks[0].block_type], 0x01, 0x00, 0x0,
399 (bt2df[tracks[0].block_type] & 0xf0) |
400 (tracks[0].block_type < 8 ? 0x01 : 0x04), 0x00, addr);
402 for (i = 0; i < notracks; i++) {
403 if (bt2ctl[tracks[i].block_type] < 0 ||
404 bt2df[tracks[i].block_type] < 0)
405 errx(EX_IOERR, "track type not supported in DAO mode");
407 if (tracks[i].block_type >= CDR_DB_XA_MODE1)
408 format = CDR_SESS_CDROM_XA;
410 if (i == 0) {
411 addr += tracks[i].pregap;
412 tracks[i].addr = addr;
414 cue_ent(&cue[j++], bt2ctl[tracks[i].block_type],
415 0x01, i+1, 0x1, bt2df[tracks[i].block_type],
416 0x00, addr);
419 else {
420 if (tracks[i].pregap) {
421 if (tracks[i].block_type > 0x7) {
422 cue_ent(&cue[j++],bt2ctl[tracks[i].block_type],
423 0x01, i+1, 0x0,
424 (bt2df[tracks[i].block_type] & 0xf0) |
425 (tracks[i].block_type < 8 ? 0x01 :0x04),
426 0x00, addr);
428 else
429 cue_ent(&cue[j++],bt2ctl[tracks[i].block_type],
430 0x01, i+1, 0x0,
431 bt2df[tracks[i].block_type],
432 0x00, addr);
434 tracks[i].addr = tracks[i - 1].addr +
435 roundup_blocks(&tracks[i - 1]);
437 cue_ent(&cue[j++], bt2ctl[tracks[i].block_type],
438 0x01, i+1, 0x1, bt2df[tracks[i].block_type],
439 0x00, addr + tracks[i].pregap);
441 if (tracks[i].block_type > 0x7)
442 addr += tracks[i].pregap;
444 addr += roundup_blocks(&tracks[i]);
447 cue_ent(&cue[j++], bt2ctl[tracks[i - 1].block_type], 0x01, 0xaa, 0x01,
448 (bt2df[tracks[i - 1].block_type] & 0xf0) |
449 (tracks[i - 1].block_type < 8 ? 0x01 : 0x04), 0x00, addr);
451 sheet.len = j * 8;
452 sheet.entries = cue;
453 sheet.test_write = test_write;
454 sheet.session_type = multi ? CDR_SESS_MULTI : CDR_SESS_NONE;
455 sheet.session_format = format;
456 if (verbose) {
457 u_int8_t *ptr = (u_int8_t *)sheet.entries;
459 fprintf(stderr,"CUE sheet:");
460 for (i = 0; i < sheet.len; i++)
461 if (i % 8)
462 fprintf(stderr," %02x", ptr[i]);
463 else
464 fprintf(stderr,"\n%02x", ptr[i]);
465 fprintf(stderr,"\n");
468 if (ioctl(fd, CDRIOCSENDCUE, &sheet) < 0)
469 err(EX_IOERR, "ioctl(CDRIOCSENDCUE)");
471 for (i = 0; i < notracks; i++) {
472 if (write_file(fd, &tracks[i]))
473 err(EX_IOERR, "write_file");
476 ioctl(fd, CDRIOCFLUSH);
479 void
480 do_TAO(int fd, int test_write, int preemp, int dvdrw)
482 struct cdr_track track;
483 int i;
485 for (i = 0; i < notracks; i++) {
486 track.test_write = test_write;
487 track.datablock_type = tracks[i].block_type;
488 track.preemp = preemp;
489 if (ioctl(fd, CDRIOCINITTRACK, &track) < 0)
490 err(EX_IOERR, "ioctl(CDRIOCINITTRACK)");
492 if (dvdrw)
493 tracks[i].addr = 0;
494 else
495 if (ioctl(fd, CDRIOCNEXTWRITEABLEADDR,
496 &tracks[i].addr) < 0)
497 err(EX_IOERR, "ioctl(CDRIOCNEXTWRITEABLEADDR)");
499 if (!quiet)
500 fprintf(stderr, "next writeable LBA %d\n",
501 tracks[i].addr);
502 if (write_file(fd, &tracks[i]))
503 err(EX_IOERR, "write_file");
504 if (ioctl(fd, CDRIOCFLUSH) < 0)
505 err(EX_IOERR, "ioctl(CDRIOCFLUSH)");
509 #define NTOH3B(x) ((x&0x0000ff)<<16) | (x&0x00ff00) | ((x&0xff0000)>>16)
511 void
512 do_format(int the_fd, int force, char *type)
514 struct cdr_format_capacities capacities;
515 struct cdr_format_params format_params;
516 int count, i, pct, last = 0;
518 if (ioctl(the_fd, CDRIOCREADFORMATCAPS, &capacities) == -1)
519 err(EX_IOERR, "ioctl(CDRIOCREADFORMATCAPS)");
521 if (verbose) {
522 fprintf(stderr, "format list entries=%zd\n",
523 capacities.length / sizeof(struct cdr_format_capacity));
524 fprintf(stderr, "current format: blocks=%u type=0x%x block_size=%u\n",
525 ntohl(capacities.blocks), capacities.type,
526 NTOH3B(capacities.block_size));
529 count = capacities.length / sizeof(struct cdr_format_capacity);
530 if (verbose) {
531 for (i = 0; i < count; ++i)
532 fprintf(stderr,
533 "format %d: blocks=%u type=0x%x param=%u\n",
534 i, ntohl(capacities.format[i].blocks),
535 capacities.format[i].type,
536 NTOH3B(capacities.format[i].param));
539 for (i = 0; i < count; ++i) {
540 if (!strcasecmp(type, "dvd+rw")) {
541 if (capacities.format[i].type == 0x26) {
542 break;
545 if (!strcasecmp(type, "dvd-rw")) {
546 if (capacities.format[i].type == 0x0) {
547 break;
551 if (i == count)
552 errx(EX_IOERR, "could not find a valid format capacity");
554 if (!quiet)
555 fprintf(stderr,"formatting with blocks=%u type=0x%x param=%u\n",
556 ntohl(capacities.format[i].blocks),
557 capacities.format[i].type,
558 NTOH3B(capacities.format[i].param));
560 if (!force && capacities.type == 2)
561 errx(EX_IOERR, "media already formatted (use -F to override)");
563 memset(&format_params, 0, sizeof(struct cdr_format_params));
564 format_params.fov = 1;
565 format_params.immed = 1;
566 format_params.length = ntohs(sizeof(struct cdr_format_capacity));
567 memcpy(&format_params.format, &capacities.format[i],
568 sizeof(struct cdr_format_capacity));
570 if(ioctl(the_fd, CDRIOCFORMAT, &format_params) == -1)
571 err(EX_IOERR, "ioctl(CDRIOCFORMAT)");
573 while (1) {
574 sleep(1);
575 if (ioctl(the_fd, CDRIOCGETPROGRESS, &pct) == -1)
576 err(EX_IOERR, "ioctl(CDRIOGETPROGRESS)");
577 if (pct > 0 && !quiet)
578 fprintf(stderr, "formatting DVD - %d %% done \r",
579 pct);
580 if (pct == 100 || (pct == 0 && last > 90))
581 break;
582 last = pct;
584 if (!quiet)
585 fprintf(stderr, "\n");
589 write_file(int fd, struct track_info *track_info)
591 off_t size, count, filesize;
592 char buf[2352*BLOCKS];
593 static off_t tot_size = 0;
595 filesize = track_info->file_size / 1024;
597 if (ioctl(fd, CDRIOCSETBLOCKSIZE, &track_info->block_size) < 0)
598 err(EX_IOERR, "ioctl(CDRIOCSETBLOCKSIZE)");
600 if (track_info->addr >= 0)
601 lseek(fd, track_info->addr * track_info->block_size, SEEK_SET);
603 if (verbose)
604 fprintf(stderr, "addr = %d size = %jd blocks = %d\n",
605 track_info->addr, (intmax_t)track_info->file_size,
606 roundup_blocks(track_info));
608 if (!quiet) {
609 if (track_info->file == STDIN_FILENO)
610 fprintf(stderr, "writing from stdin\n");
611 else
612 fprintf(stderr,
613 "writing from file %s size %jd KB\n",
614 track_info->file_name, (intmax_t)filesize);
616 size = 0;
618 while ((count = read(track_info->file, buf,
619 track_info->file_size == -1
620 ? track_info->block_size * BLOCKS
621 : MIN((track_info->file_size - size),
622 track_info->block_size * BLOCKS))) > 0) {
623 int res;
625 if (count % track_info->block_size) {
626 /* pad file to % block_size */
627 bzero(&buf[count],
628 (track_info->block_size * BLOCKS) - count);
629 count = ((count / track_info->block_size) + 1) *
630 track_info->block_size;
632 if ((res = write(fd, buf, count)) != count) {
633 if (res == -1)
634 fprintf(stderr, "\n%s\n", strerror(errno));
635 else
636 fprintf(stderr, "\nonly wrote %d of %jd"
637 " bytes\n", res, (intmax_t)count);
638 break;
640 size += count;
641 tot_size += count;
642 if (!quiet) {
643 int pct;
645 fprintf(stderr, "written this track %jd KB",
646 (intmax_t)size/1024);
647 if (track_info->file != STDIN_FILENO && filesize) {
648 pct = (size / 1024) * 100 / filesize;
649 fprintf(stderr, " (%d%%)", pct);
651 fprintf(stderr, " total %jd KB\r",
652 (intmax_t)tot_size / 1024);
654 if (track_info->file_size != -1
655 && size >= track_info->file_size)
656 break;
659 if (!quiet)
660 fprintf(stderr, "\n");
661 close(track_info->file);
662 return 0;
666 roundup_blocks(struct track_info *track)
668 return ((track->file_size + track->block_size - 1) / track->block_size);
671 void
672 cue_ent(struct cdr_cue_entry *cue, int ctl, int adr, int track, int idx,
673 int dataform, int scms, int lba)
675 cue->adr = adr;
676 cue->ctl = ctl;
677 cue->track = track;
678 cue->index = idx;
679 cue->dataform = dataform;
680 cue->scms = scms;
681 lba += 150;
682 cue->min = lba / (60*75);
683 cue->sec = (lba % (60*75)) / 75;
684 cue->frame = (lba % (60*75)) % 75;
687 void
688 cleanup(int dummy __unused)
690 if (ioctl(global_fd_for_cleanup, CDRIOCSETBLOCKSIZE,
691 &saved_block_size) < 0)
692 err(EX_IOERR, "ioctl(CDRIOCSETBLOCKSIZE)");
695 void
696 usage(void)
698 fprintf(stderr,
699 "usage: %s [-deFlmnpqtv] [-f device] [-s speed] [command]"
700 " [command file ...]\n", getprogname());
701 exit(EX_USAGE);