xref: /titanic_50/usr/src/cmd/cdrw/write_image.c (revision fa9e4066f08beec538e775443c5be79dd423fcab)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/types.h>
30 #include <stdlib.h>
31 #include <libintl.h>
32 #include <unistd.h>
33 #include "trackio.h"
34 #include "main.h"
35 #include "util.h"
36 #include "bstream.h"
37 #include "misc_scsi.h"
38 #include "msgs.h"
39 #include "device.h"
40 #include "mmc.h"
41 #include "transport.h"
42 
43 void
44 write_image(void)
45 {
46 	bstreamhandle h;
47 	off_t size;
48 	int no_size, ret;
49 
50 	get_media_type(target->d_fd);
51 
52 	/* DVD+RW does not have blanking and can be overwritten */
53 	if (device_type != DVD_PLUS_W) {
54 	(void) check_device(target, CHECK_DEVICE_NOT_READY |
55 	    CHECK_DEVICE_NOT_WRITABLE | CHECK_MEDIA_IS_NOT_WRITABLE |
56 	    EXIT_IF_CHECK_FAILED);
57 	} else {
58 		(void) check_device(target, CHECK_DEVICE_NOT_READY |
59 		EXIT_IF_CHECK_FAILED);
60 	}
61 
62 	write_init(TRACK_MODE_DATA);
63 
64 	if (image_file) {
65 		h = open_file_read_stream(image_file);
66 	} else {
67 		h = open_stdin_read_stream();
68 	}
69 
70 	if (h == NULL) {
71 		err_msg(gettext("Cannot open %s: %s\n"),
72 		    image_file ? image_file : "stdin", get_err_str());
73 		exit(1);
74 	}
75 	no_size = 0;
76 	ret = h->bstr_size(h, &size);
77 	if (ret == 0) {
78 		if ((str_errno == STR_ERR_NO_REG_FILE)) {
79 			no_size = 1;
80 		} else {
81 			err_msg(gettext("Cannot stat input file: %s\n"),
82 			    get_err_str());
83 			exit(1);
84 		}
85 	}
86 	if ((no_size == 0) && (size == 0)) {
87 		err_msg(gettext("Input size(0) not valid\n"));
88 		exit(1);
89 	}
90 	if (no_size == 0) {
91 		off_t cap;
92 		struct track_info *ti;
93 		uint_t bsize;
94 
95 		ti = (struct track_info *)my_zalloc(sizeof (*ti));
96 		if (write_mode == TAO_MODE)
97 		    if (!build_track_info(target, -1, ti)) {
98 			err_msg(
99 			    gettext("Unable to find out writable address\n"));
100 			exit(1);
101 			}
102 		if (use_media_stated_capacity) {
103 			cap = get_last_possible_lba(target);
104 			if (cap <= 0) {
105 				cap = read_format_capacity(target->d_fd,
106 				    &bsize);
107 			}
108 		} else {
109 			/*
110 			 * For DVD drives use read_format_capacity to retrieve
111 			 * the media size, it could be 3.6, 3.9, 4.2, 4.7, 9.2
112 			 */
113 			if (device_type == CD_RW) {
114 				cap = MAX_CD_BLKS;
115 			} else {
116 				/*
117 				 * For DVD drives use read_format_capacity to
118 				 * find media size, it can be 3.6, 3.9, 4.2,
119 				 * 4.7, 9.2
120 				 */
121 				cap = read_format_capacity(target->d_fd,
122 				    &bsize);
123 				/* sanity if not reasonable default to 4.7 GB */
124 				if (cap < MAX_CD_BLKS)
125 					cap = MAX_DVD_BLKS;
126 			}
127 		}
128 		if (cap == 0) {
129 			err_msg(gettext("Unable to find out media capacity\n"));
130 			exit(1);
131 		}
132 		if (device_type == CD_RW)
133 			cap = (cap + 1 - ti->ti_start_address) * 2048;
134 		else
135 			cap *= 2048 + 1;
136 
137 		if (size > cap) {
138 			err_msg(gettext("Size required (%lld bytes) is greater "
139 			    "than available space (%lld bytes).\n"), size, cap);
140 			exit(1);
141 		}
142 
143 		if (device_type == DVD_MINUS) {
144 			(void) printf(gettext("Preparing to write DVD\n"));
145 
146 			/* streamed file, we dont know the size to reserve */
147 			if (no_size == 1) {
148 				size = cap - 1;
149 			}
150 
151 			/* DAO requires that we reserve the size to write */
152 			if (debug)
153 				(void) printf(
154 				    "DAO_MODE:reserving track size of = 0x%x\n",
155 				    (uint32_t)(size/2048));
156 
157 			if (!set_reservation(target->d_fd, size/2048)) {
158 				(void) printf(gettext(
159 				    "Setting reservation failed\n"));
160 				exit(1);
161 			}
162 		} else if (device_type == DVD_PLUS_W) {
163 			/*
164 			 * DVD+RW requires that we format the media before
165 			 * writing.
166 			 */
167 			(void) print_n_flush(gettext("Formatting media..."));
168 			if (!format_media(target->d_fd)) {
169 				(void) printf(gettext(
170 				    "Could not format media\n"));
171 				exit(1);
172 			} else {
173 				int counter;
174 				uchar_t *di;
175 
176 				/* poll until format is done */
177 				di = (uchar_t *)my_zalloc(DISC_INFO_BLOCK_SIZE);
178 				(void) sleep(10);
179 				for (counter = 0; counter < 200; counter++) {
180 
181 				ret = read_disc_info(target->d_fd, di);
182 
183 				if ((SENSE_KEY(rqbuf) == 2) &&
184 				    (ASC(rqbuf) == 4)) {
185 					(void) print_n_flush(".");
186 					(void) sleep(5);
187 				} else {
188 					break;
189 					}
190 				}
191 			}
192 
193 			(void) printf(gettext("done\n"));
194 		}
195 
196 
197 		free(ti);
198 	}
199 
200 	write_next_track(TRACK_MODE_DATA, h);
201 
202 	h->bstr_close(h);
203 	write_fini();
204 	fini_device(target);
205 	exit(0);
206 }
207