2 * Copyright (c) 2000,2001 Søren Schmidt
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
38 #include <sys/errno.h>
39 #include <sys/ioctl.h>
42 #include <sys/cdrio.h>
43 #include <sys/param.h>
48 void write_file(const char *, int);
49 void usage(const char *);
51 static int fd, quiet, saved_block_size;
52 static struct cdr_track track;
55 main(int argc, char **argv)
58 int eject=0, list=0, multi=0, preemp=0, speed=1, test_write=0;
59 char *devname = "/dev/acd0c", *prog_name;
63 while ((ch = getopt(argc, argv, "ef:lmpqs:t")) != -1) {
92 errx(EX_USAGE, "Invalid speed: %s", optarg);
109 if ((fd = open(devname, O_RDWR, 0)) < 0)
110 err(EX_NOINPUT, "open(%s)", devname);
112 if (ioctl(fd, CDRIOCWRITESPEED, &speed) < 0)
113 err(EX_IOERR, "ioctl(CDRIOCWRITESPEED)");
115 if (ioctl(fd, CDRIOCGETBLOCKSIZE, &saved_block_size) < 0)
116 err(EX_IOERR, "ioctl(CDRIOCGETBLOCKSIZE)");
118 err_set_exit(cleanup);
120 for (arg = 0; arg < argc; arg++) {
121 if (!strcmp(argv[arg], "fixate")) {
123 fprintf(stderr, "fixating CD, please wait..\n");
124 if (ioctl(fd, CDRIOCCLOSEDISK, &multi) < 0)
125 err(EX_IOERR, "ioctl(CDRIOCCLOSEDISK)");
128 if (!strcmp(argv[arg], "msinfo")) {
129 struct ioc_read_toc_single_entry entry;
131 bzero(&entry, sizeof(struct ioc_read_toc_single_entry));
132 entry.address_format = CD_LBA_FORMAT;
133 if (ioctl(fd, CDIOREADTOCENTRY, &entry) < 0)
134 err(EX_IOERR, "ioctl(CDIOREADTOCENTRY)");
135 if (ioctl(fd, CDRIOCNEXTWRITEABLEADDR, &addr) < 0)
136 err(EX_IOERR, "ioctl(CDRIOCNEXTWRITEABLEADDR)");
137 fprintf(stderr, "%d, %d\n",
138 ntohl(entry.entry.addr.lba), addr);
142 if (!strcmp(argv[arg], "erase") || !strcmp(argv[arg], "blank")){
143 int error, blank, percent;
145 if (!strcmp(argv[arg], "erase"))
150 fprintf(stderr, "%sing CD, please wait..\r",
151 blank == CDR_B_ALL ? "eras" : "blank");
153 if (ioctl(fd, CDRIOCBLANK, &blank) < 0)
154 err(EX_IOERR, "ioctl(CDRIOCBLANK)");
157 error = ioctl(fd, CDRIOCGETPROGRESS, &percent);
158 if (percent > 0 && !quiet)
160 "%sing CD - %d %% done \r",
162 "eras" : "blank", percent);
163 if (error || percent == 100)
170 if (!strcmp(argv[arg], "audio") || !strcmp(argv[arg], "raw")) {
171 track.test_write = test_write;
172 track.datablock_type = CDR_DB_RAW;
173 track.preemp = preemp;
177 if (!strcmp(argv[arg], "data") || !strcmp(argv[arg], "mode1")) {
178 track.test_write = test_write;
179 track.datablock_type = CDR_DB_ROM_MODE1;
184 if (!strcmp(argv[arg], "mode2")) {
185 track.test_write = test_write;
186 track.datablock_type = CDR_DB_ROM_MODE2;
191 if (!strcmp(argv[arg], "XAmode1")) {
192 track.test_write = test_write;
193 track.datablock_type = CDR_DB_XA_MODE1;
199 err(EX_NOINPUT, "no data format selected");
201 char file_buf[MAXPATHLEN + 1], *eol;
204 if ((fp = fopen(argv[arg], "r")) == NULL)
205 err(EX_NOINPUT, "fopen(%s)", argv[arg]);
207 while (fgets(file_buf, sizeof(file_buf), fp) != NULL) {
208 if (*file_buf == '#' || *file_buf == '\n')
210 if (eol = strchr(file_buf, '\n'))
212 write_file(file_buf, block_size);
217 err(EX_IOERR, "fgets(%s)", file_buf);
220 write_file(argv[arg], block_size);
223 if (ioctl(fd, CDRIOCSETBLOCKSIZE, &saved_block_size) < 0) {
225 err(EX_IOERR, "ioctl(CDRIOCSETBLOCKSIZE)");
229 if (ioctl(fd, CDIOCEJECT) < 0)
230 err(EX_IOERR, "ioctl(CDIOCEJECT)");
238 if (ioctl(fd, CDRIOCSETBLOCKSIZE, &saved_block_size) < 0)
239 err(EX_IOERR, "ioctl(CDRIOCSETBLOCKSIZE)");
243 usage(const char *prog_name)
245 fprintf(stderr, "Usage: %s [-f device] [-s speed] [-e] [-l] [-m] [-p]\n"
246 "\t[-q] [command] [command filename...]\n", prog_name);
251 write_file(const char *name, int block_size)
253 int addr, count, file, filesize, size;
254 char buf[2352*BLOCKS];
256 static int cdopen, done_stdin, tot_size = 0;
258 if (!strcmp(name, "-")) {
260 warn("skipping multiple usages of stdin");
266 else if ((file = open(name, O_RDONLY, 0)) < 0)
267 err(EX_NOINPUT, "open(%s)", name);
270 if (ioctl(fd, CDRIOCOPENDISK) < 0)
271 err(EX_IOERR, "ioctl(CDRIOCOPENDISK)");
275 if (ioctl(fd, CDRIOCOPENTRACK, &track) < 0)
276 err(EX_IOERR, "ioctl(CDRIOCOPENTRACK)");
278 if (ioctl(fd, CDRIOCNEXTWRITEABLEADDR, &addr) < 0)
279 err(EX_IOERR, "ioctl(CDRIOCNEXTWRITEABLEADDR)");
281 if (fstat(file, &stat) < 0)
282 err(EX_IOERR, "fstat(%s)", name);
283 filesize = stat.st_size / 1024;
286 fprintf(stderr, "next writeable LBA %d\n", addr);
287 if (file == STDIN_FILENO)
288 fprintf(stderr, "writing from stdin\n");
291 "writing from file %s size %d KB\n",
295 lseek(fd, addr * block_size, SEEK_SET);
298 filesize++; /* cheat, avoid divide by zero */
300 while ((count = read(file, buf, block_size * BLOCKS)) > 0) {
302 if (count % block_size) {
303 /* pad file to % block_size */
304 bzero(&buf[count], block_size * BLOCKS - count);
305 count = ((count / block_size) + 1) * block_size;
307 if ((res = write(fd, buf, count)) != count) {
308 fprintf(stderr, "\nonly wrote %d of %d bytes\n",
317 fprintf(stderr, "written this track %d KB", size/1024);
318 if (file != STDIN_FILENO) {
319 pct = (size / 1024) * 100 / filesize;
320 fprintf(stderr, " (%d%%)", pct);
322 fprintf(stderr, " total %d KB\r", tot_size/1024);
327 fprintf(stderr, "\n");
330 if (ioctl(fd, CDRIOCCLOSETRACK) < 0)
331 err(EX_IOERR, "ioctl(CDRIOCCLOSETRACK)");