1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <stdio.h> 30*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 31*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 32*7c478bd9Sstevel@tonic-gate #include <errno.h> 33*7c478bd9Sstevel@tonic-gate #include <limits.h> 34*7c478bd9Sstevel@tonic-gate #include <unistd.h> 35*7c478bd9Sstevel@tonic-gate #include <libintl.h> 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate #include "main.h" 38*7c478bd9Sstevel@tonic-gate #include "util.h" 39*7c478bd9Sstevel@tonic-gate #include "misc_scsi.h" 40*7c478bd9Sstevel@tonic-gate #include "mmc.h" 41*7c478bd9Sstevel@tonic-gate #include "bstream.h" 42*7c478bd9Sstevel@tonic-gate #include "device.h" 43*7c478bd9Sstevel@tonic-gate #include "msgs.h" 44*7c478bd9Sstevel@tonic-gate #include "transport.h" 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate struct t_data { 47*7c478bd9Sstevel@tonic-gate bstreamhandle h; 48*7c478bd9Sstevel@tonic-gate struct track_info ti; 49*7c478bd9Sstevel@tonic-gate }; 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate int read_audio_track(cd_device *dev, struct track_info *ti, bstreamhandle h); 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate #define READ_BURST 24 /* < 64K in all cases */ 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate /* 56*7c478bd9Sstevel@tonic-gate * This reads the data off of a cd while updating the progress indicator. 57*7c478bd9Sstevel@tonic-gate * We want to do this in smaller chunks since some CD drives have 58*7c478bd9Sstevel@tonic-gate * problems with larger reads. 59*7c478bd9Sstevel@tonic-gate */ 60*7c478bd9Sstevel@tonic-gate static int 61*7c478bd9Sstevel@tonic-gate read_data_track(cd_device *dev, struct track_info *ti, bstreamhandle h) 62*7c478bd9Sstevel@tonic-gate { 63*7c478bd9Sstevel@tonic-gate int blksize; 64*7c478bd9Sstevel@tonic-gate uint32_t blks_read, cblk, read_chunk, read_size; 65*7c478bd9Sstevel@tonic-gate uchar_t *buf; 66*7c478bd9Sstevel@tonic-gate int ret, sav; 67*7c478bd9Sstevel@tonic-gate int link_blks_count; 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate buf = NULL; 70*7c478bd9Sstevel@tonic-gate ret = 0; 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate /* 73*7c478bd9Sstevel@tonic-gate * the last link_blks_count blocks may not exist or be completely 74*7c478bd9Sstevel@tonic-gate * filled. We need to record the amount to avoid bailing out if 75*7c478bd9Sstevel@tonic-gate * they cannot be read. 76*7c478bd9Sstevel@tonic-gate */ 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate if (dev->d_blksize == 512) { 79*7c478bd9Sstevel@tonic-gate blksize = 512; 80*7c478bd9Sstevel@tonic-gate link_blks_count = 8; 81*7c478bd9Sstevel@tonic-gate } else { 82*7c478bd9Sstevel@tonic-gate blksize = 2048; 83*7c478bd9Sstevel@tonic-gate link_blks_count = 2; 84*7c478bd9Sstevel@tonic-gate } 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate buf = (uchar_t *)my_zalloc(READ_BURST * blksize); 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate print_n_flush(gettext("Reading track %d..."), ti->ti_track_no); 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate if (verbose) 91*7c478bd9Sstevel@tonic-gate print_n_flush("Track size is %u...", ti->ti_track_size); 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate init_progress(); 94*7c478bd9Sstevel@tonic-gate cblk = ti->ti_start_address; 95*7c478bd9Sstevel@tonic-gate blks_read = 0; 96*7c478bd9Sstevel@tonic-gate while (blks_read < ti->ti_track_size) { 97*7c478bd9Sstevel@tonic-gate /* Last few are special */ 98*7c478bd9Sstevel@tonic-gate read_chunk = ti->ti_track_size - blks_read - link_blks_count; 99*7c478bd9Sstevel@tonic-gate read_chunk = (read_chunk > READ_BURST) ? READ_BURST : 100*7c478bd9Sstevel@tonic-gate read_chunk; 101*7c478bd9Sstevel@tonic-gate if (read_chunk == 0) { 102*7c478bd9Sstevel@tonic-gate /* Time for last link blocks */ 103*7c478bd9Sstevel@tonic-gate read_chunk = link_blks_count; 104*7c478bd9Sstevel@tonic-gate } 105*7c478bd9Sstevel@tonic-gate read_size = read_chunk * blksize; 106*7c478bd9Sstevel@tonic-gate if (read10(dev->d_fd, cblk, read_chunk, buf, read_size)) { 107*7c478bd9Sstevel@tonic-gate if (h->bstr_write(h, buf, read_size) != read_size) { 108*7c478bd9Sstevel@tonic-gate goto read_data_track_failed; 109*7c478bd9Sstevel@tonic-gate } 110*7c478bd9Sstevel@tonic-gate } else { 111*7c478bd9Sstevel@tonic-gate if (blks_read != 112*7c478bd9Sstevel@tonic-gate (ti->ti_track_size - link_blks_count)) { 113*7c478bd9Sstevel@tonic-gate goto read_data_track_failed; 114*7c478bd9Sstevel@tonic-gate } else { 115*7c478bd9Sstevel@tonic-gate /* Read can fail for last link sectors */ 116*7c478bd9Sstevel@tonic-gate errno = 0; 117*7c478bd9Sstevel@tonic-gate } 118*7c478bd9Sstevel@tonic-gate } 119*7c478bd9Sstevel@tonic-gate blks_read += read_chunk; 120*7c478bd9Sstevel@tonic-gate cblk += read_chunk; 121*7c478bd9Sstevel@tonic-gate (void) progress((void *)(ti->ti_track_size), blks_read); 122*7c478bd9Sstevel@tonic-gate } 123*7c478bd9Sstevel@tonic-gate /* l10n_NOTE : 'done' as in "Reading track 1...done" */ 124*7c478bd9Sstevel@tonic-gate (void) str_print(gettext("done.\n"), progress_pos); 125*7c478bd9Sstevel@tonic-gate ret = 1; 126*7c478bd9Sstevel@tonic-gate read_data_track_failed: 127*7c478bd9Sstevel@tonic-gate sav = errno; 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate free(buf); 130*7c478bd9Sstevel@tonic-gate errno = sav; 131*7c478bd9Sstevel@tonic-gate return (ret); 132*7c478bd9Sstevel@tonic-gate } 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate static void 135*7c478bd9Sstevel@tonic-gate ensure_media_space(uint32_t total_nblks, uchar_t end_tno) 136*7c478bd9Sstevel@tonic-gate { 137*7c478bd9Sstevel@tonic-gate off_t nblks_avail; 138*7c478bd9Sstevel@tonic-gate uint_t bsize; 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate get_media_type(target->d_fd); 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate if (use_media_stated_capacity) { 143*7c478bd9Sstevel@tonic-gate nblks_avail = get_last_possible_lba(target); 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate if (nblks_avail <= 0) { 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate /* most newer drives use READ FORMAT CAPACITY */ 148*7c478bd9Sstevel@tonic-gate nblks_avail = read_format_capacity(target->d_fd, 149*7c478bd9Sstevel@tonic-gate &bsize); 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate /* if both methods fail no choice but to bail out */ 152*7c478bd9Sstevel@tonic-gate if (nblks_avail <= 0) { 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate err_msg(gettext( 155*7c478bd9Sstevel@tonic-gate "Cannot find out media capacity.\n")); 156*7c478bd9Sstevel@tonic-gate exit(1); 157*7c478bd9Sstevel@tonic-gate } 158*7c478bd9Sstevel@tonic-gate } 159*7c478bd9Sstevel@tonic-gate } else { 160*7c478bd9Sstevel@tonic-gate if (device_type == CD_RW) { 161*7c478bd9Sstevel@tonic-gate nblks_avail = MAX_CD_BLKS; 162*7c478bd9Sstevel@tonic-gate } else { 163*7c478bd9Sstevel@tonic-gate /* 164*7c478bd9Sstevel@tonic-gate * For DVD drives use read_format_capacity as default 165*7c478bd9Sstevel@tonic-gate * retrieve the media size, it can be 3.6, 3.9, 4.2, 166*7c478bd9Sstevel@tonic-gate * 4.7, or 9.2 GB 167*7c478bd9Sstevel@tonic-gate */ 168*7c478bd9Sstevel@tonic-gate nblks_avail = 169*7c478bd9Sstevel@tonic-gate read_format_capacity(target->d_fd, &bsize); 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate /* sanity check. if not reasonable default to 4.7 GB */ 172*7c478bd9Sstevel@tonic-gate if (nblks_avail < MAX_CD_BLKS) { 173*7c478bd9Sstevel@tonic-gate nblks_avail = MAX_DVD_BLKS; 174*7c478bd9Sstevel@tonic-gate } 175*7c478bd9Sstevel@tonic-gate } 176*7c478bd9Sstevel@tonic-gate } 177*7c478bd9Sstevel@tonic-gate 178*7c478bd9Sstevel@tonic-gate if ((total_nblks + end_tno*300) > nblks_avail) { 179*7c478bd9Sstevel@tonic-gate err_msg(gettext("Not enough space on the media.\n")); 180*7c478bd9Sstevel@tonic-gate if (debug) { 181*7c478bd9Sstevel@tonic-gate (void) printf("Need %u only found %u \n", 182*7c478bd9Sstevel@tonic-gate (total_nblks + end_tno*300), 183*7c478bd9Sstevel@tonic-gate (uint32_t)nblks_avail); 184*7c478bd9Sstevel@tonic-gate } 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate exit(1); 187*7c478bd9Sstevel@tonic-gate } 188*7c478bd9Sstevel@tonic-gate } 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate /* 191*7c478bd9Sstevel@tonic-gate * This copies both audio and data CDs. It first reads the TOC of the source CD 192*7c478bd9Sstevel@tonic-gate * and creates a temp file with the CD image. After this is completed it creates 193*7c478bd9Sstevel@tonic-gate * the target CD using TAO mode. 194*7c478bd9Sstevel@tonic-gate */ 195*7c478bd9Sstevel@tonic-gate void 196*7c478bd9Sstevel@tonic-gate copy_cd(void) 197*7c478bd9Sstevel@tonic-gate { 198*7c478bd9Sstevel@tonic-gate cd_device *src; 199*7c478bd9Sstevel@tonic-gate char *p; 200*7c478bd9Sstevel@tonic-gate uchar_t *toc, end_tno; 201*7c478bd9Sstevel@tonic-gate int blksize, i; 202*7c478bd9Sstevel@tonic-gate int audio_cd, data_cd; 203*7c478bd9Sstevel@tonic-gate uint32_t total_nblks; 204*7c478bd9Sstevel@tonic-gate int ret; 205*7c478bd9Sstevel@tonic-gate struct t_data *tlist; 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate print_n_flush(gettext("Analyzing source CD...")); 208*7c478bd9Sstevel@tonic-gate (void) check_device(target, 209*7c478bd9Sstevel@tonic-gate CHECK_DEVICE_NOT_WRITABLE|EXIT_IF_CHECK_FAILED); 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate /* if source drive is specified on the command line */ 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate if (copy_src) { 214*7c478bd9Sstevel@tonic-gate p = my_zalloc(PATH_MAX); 215*7c478bd9Sstevel@tonic-gate if (lookup_device(copy_src, p) == 0) { 216*7c478bd9Sstevel@tonic-gate err_msg(gettext("Cannot find device %s"), copy_src); 217*7c478bd9Sstevel@tonic-gate err_msg(gettext(" or no media in the drive\n")); 218*7c478bd9Sstevel@tonic-gate exit(1); 219*7c478bd9Sstevel@tonic-gate } 220*7c478bd9Sstevel@tonic-gate src = get_device(copy_src, p); 221*7c478bd9Sstevel@tonic-gate if (src == NULL) { 222*7c478bd9Sstevel@tonic-gate err_msg(gettext("Unable to open %s\n"), copy_src); 223*7c478bd9Sstevel@tonic-gate exit(1); 224*7c478bd9Sstevel@tonic-gate } 225*7c478bd9Sstevel@tonic-gate free(p); 226*7c478bd9Sstevel@tonic-gate } else { 227*7c478bd9Sstevel@tonic-gate /* source is same as target drive */ 228*7c478bd9Sstevel@tonic-gate src = target; 229*7c478bd9Sstevel@tonic-gate } 230*7c478bd9Sstevel@tonic-gate 231*7c478bd9Sstevel@tonic-gate (void) check_device(src, CHECK_TYPE_NOT_CDROM | CHECK_NO_MEDIA | 232*7c478bd9Sstevel@tonic-gate CHECK_DEVICE_NOT_READY | EXIT_IF_CHECK_FAILED); 233*7c478bd9Sstevel@tonic-gate 234*7c478bd9Sstevel@tonic-gate toc = (uchar_t *)my_zalloc(4); 235*7c478bd9Sstevel@tonic-gate if (!read_toc(src->d_fd, 0, 0, 4, toc)) { 236*7c478bd9Sstevel@tonic-gate err_msg(gettext("Cannot read table of contents\n")); 237*7c478bd9Sstevel@tonic-gate exit(1); 238*7c478bd9Sstevel@tonic-gate } 239*7c478bd9Sstevel@tonic-gate end_tno = toc[3]; 240*7c478bd9Sstevel@tonic-gate free(toc); 241*7c478bd9Sstevel@tonic-gate tlist = (struct t_data *)my_zalloc(end_tno * sizeof (struct t_data)); 242*7c478bd9Sstevel@tonic-gate 243*7c478bd9Sstevel@tonic-gate audio_cd = data_cd = 0; 244*7c478bd9Sstevel@tonic-gate total_nblks = 0; 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate /* build track information so we can copy it over */ 247*7c478bd9Sstevel@tonic-gate for (i = 1; i <= end_tno; i++) { 248*7c478bd9Sstevel@tonic-gate struct track_info *ti; 249*7c478bd9Sstevel@tonic-gate 250*7c478bd9Sstevel@tonic-gate ti = &tlist[i - 1].ti; 251*7c478bd9Sstevel@tonic-gate if (!build_track_info(src, i, ti)) { 252*7c478bd9Sstevel@tonic-gate err_msg(gettext( 253*7c478bd9Sstevel@tonic-gate "Cannot get information for track %d\n"), i); 254*7c478bd9Sstevel@tonic-gate exit(1); 255*7c478bd9Sstevel@tonic-gate } 256*7c478bd9Sstevel@tonic-gate total_nblks += ti->ti_track_size; 257*7c478bd9Sstevel@tonic-gate if (ti->ti_track_mode & 4) 258*7c478bd9Sstevel@tonic-gate data_cd = 1; 259*7c478bd9Sstevel@tonic-gate else 260*7c478bd9Sstevel@tonic-gate audio_cd = 1; 261*7c478bd9Sstevel@tonic-gate 262*7c478bd9Sstevel@tonic-gate /* Now some sanity checks on the track information */ 263*7c478bd9Sstevel@tonic-gate if ((ti->ti_flags & TI_SESSION_NO_VALID) && 264*7c478bd9Sstevel@tonic-gate (ti->ti_session_no != 1)) { 265*7c478bd9Sstevel@tonic-gate err_msg( 266*7c478bd9Sstevel@tonic-gate gettext("Copying multisession CD is not supported\n")); 267*7c478bd9Sstevel@tonic-gate exit(1); 268*7c478bd9Sstevel@tonic-gate } 269*7c478bd9Sstevel@tonic-gate if ((ti->ti_flags & TI_PACKET_MODE) || 270*7c478bd9Sstevel@tonic-gate (ti->ti_flags & TI_BLANK_TRACK) || 271*7c478bd9Sstevel@tonic-gate (ti->ti_flags & TI_DAMAGED_TRACK) || 272*7c478bd9Sstevel@tonic-gate (data_cd && audio_cd) || (ti->ti_data_mode == 2)) { 273*7c478bd9Sstevel@tonic-gate 274*7c478bd9Sstevel@tonic-gate err_msg(gettext("CD format is not supported\n")); 275*7c478bd9Sstevel@tonic-gate exit(1); 276*7c478bd9Sstevel@tonic-gate } 277*7c478bd9Sstevel@tonic-gate if ((ti->ti_flags & TI_NWA_VALID) && 278*7c478bd9Sstevel@tonic-gate (ti->ti_nwa != 0xffffffff)) { 279*7c478bd9Sstevel@tonic-gate err_msg(gettext("Cannot copy incomplete discs\n")); 280*7c478bd9Sstevel@tonic-gate exit(1); 281*7c478bd9Sstevel@tonic-gate } 282*7c478bd9Sstevel@tonic-gate } 283*7c478bd9Sstevel@tonic-gate /* l10n_NOTE : 'done' as in "Analyzing source CD...done" */ 284*7c478bd9Sstevel@tonic-gate (void) printf(gettext("done.\n")); 285*7c478bd9Sstevel@tonic-gate 286*7c478bd9Sstevel@tonic-gate if (data_cd) { 287*7c478bd9Sstevel@tonic-gate blksize = 2048; 288*7c478bd9Sstevel@tonic-gate } else { 289*7c478bd9Sstevel@tonic-gate /* audio cd */ 290*7c478bd9Sstevel@tonic-gate blksize = 2352; 291*7c478bd9Sstevel@tonic-gate } 292*7c478bd9Sstevel@tonic-gate 293*7c478bd9Sstevel@tonic-gate /* In case of audio CDs, build_track_info() returns 2352 sized nblks */ 294*7c478bd9Sstevel@tonic-gate if (src->d_blksize == 512 && data_cd) { 295*7c478bd9Sstevel@tonic-gate total_nblks /= 4; 296*7c478bd9Sstevel@tonic-gate } 297*7c478bd9Sstevel@tonic-gate (void) printf(gettext("\nCopying %d %s track%s : %ld kbytes\n\n"), 298*7c478bd9Sstevel@tonic-gate end_tno, (audio_cd == 1) ? gettext("audio") : gettext("data"), 299*7c478bd9Sstevel@tonic-gate (end_tno > 1) ? "s" : "", (long)((total_nblks*blksize)/1024)); 300*7c478bd9Sstevel@tonic-gate 301*7c478bd9Sstevel@tonic-gate if (!check_avail_temp_space(total_nblks*blksize)) { 302*7c478bd9Sstevel@tonic-gate err_msg(gettext("Not enough space in temporary directory\n")); 303*7c478bd9Sstevel@tonic-gate err_msg( 304*7c478bd9Sstevel@tonic-gate gettext("Use -m to specify alternate temporary directory\n")); 305*7c478bd9Sstevel@tonic-gate exit(1); 306*7c478bd9Sstevel@tonic-gate } 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate /* 309*7c478bd9Sstevel@tonic-gate * If we can check available space on the target media at this 310*7c478bd9Sstevel@tonic-gate * Stage, then it is always better. We cannot check DVD+R(W) 311*7c478bd9Sstevel@tonic-gate * as this media may be formatted and not blank. 312*7c478bd9Sstevel@tonic-gate */ 313*7c478bd9Sstevel@tonic-gate if (target && (src != target) && (device_type != DVD_PLUS) && 314*7c478bd9Sstevel@tonic-gate (device_type != DVD_PLUS_W) && (!check_device(target, 315*7c478bd9Sstevel@tonic-gate CHECK_NO_MEDIA|CHECK_MEDIA_IS_NOT_BLANK))) { 316*7c478bd9Sstevel@tonic-gate ensure_media_space(total_nblks, end_tno); 317*7c478bd9Sstevel@tonic-gate } 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate /* for each track */ 320*7c478bd9Sstevel@tonic-gate for (i = 1; i <= end_tno; i++) { 321*7c478bd9Sstevel@tonic-gate tlist[i - 1].h = open_temp_file_stream(); 322*7c478bd9Sstevel@tonic-gate if (tlist[i - 1].h == NULL) { 323*7c478bd9Sstevel@tonic-gate err_msg(gettext("Cannot create temporary file : %s\n"), 324*7c478bd9Sstevel@tonic-gate get_err_str()); 325*7c478bd9Sstevel@tonic-gate exit(1); 326*7c478bd9Sstevel@tonic-gate } 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate if (audio_cd) 329*7c478bd9Sstevel@tonic-gate ret = read_audio_track(src, &tlist[i - 1].ti, 330*7c478bd9Sstevel@tonic-gate tlist[i - 1].h); 331*7c478bd9Sstevel@tonic-gate else 332*7c478bd9Sstevel@tonic-gate ret = read_data_track(src, &tlist[i - 1].ti, 333*7c478bd9Sstevel@tonic-gate tlist[i - 1].h); 334*7c478bd9Sstevel@tonic-gate if (ret == 0) { 335*7c478bd9Sstevel@tonic-gate err_msg(gettext("Error reading track %d : %s\n"), i, 336*7c478bd9Sstevel@tonic-gate get_err_str()); 337*7c478bd9Sstevel@tonic-gate if (debug) 338*7c478bd9Sstevel@tonic-gate (void) printf("%x %x %x %x\n", uscsi_status, 339*7c478bd9Sstevel@tonic-gate SENSE_KEY(rqbuf), ASC(rqbuf), ASCQ(rqbuf)); 340*7c478bd9Sstevel@tonic-gate exit(1); 341*7c478bd9Sstevel@tonic-gate } 342*7c478bd9Sstevel@tonic-gate } 343*7c478bd9Sstevel@tonic-gate 344*7c478bd9Sstevel@tonic-gate /* 345*7c478bd9Sstevel@tonic-gate * We've finished copying the CD. If source and destination are the same 346*7c478bd9Sstevel@tonic-gate * or they where not specified then eject the disk and wait for a new 347*7c478bd9Sstevel@tonic-gate * disk to be inserted. 348*7c478bd9Sstevel@tonic-gate */ 349*7c478bd9Sstevel@tonic-gate 350*7c478bd9Sstevel@tonic-gate while ((target == NULL) || 351*7c478bd9Sstevel@tonic-gate check_device(target, CHECK_NO_MEDIA|CHECK_MEDIA_IS_NOT_BLANK)) { 352*7c478bd9Sstevel@tonic-gate if (target != NULL) { 353*7c478bd9Sstevel@tonic-gate (void) eject_media(target); 354*7c478bd9Sstevel@tonic-gate } 355*7c478bd9Sstevel@tonic-gate 356*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 357*7c478bd9Sstevel@tonic-gate print_n_flush( 358*7c478bd9Sstevel@tonic-gate gettext("Insert a blank media in the drive and press Enter.")); 359*7c478bd9Sstevel@tonic-gate (void) fflush(stdin); 360*7c478bd9Sstevel@tonic-gate if (target) { 361*7c478bd9Sstevel@tonic-gate fini_device(target); 362*7c478bd9Sstevel@tonic-gate target = NULL; 363*7c478bd9Sstevel@tonic-gate } 364*7c478bd9Sstevel@tonic-gate (void) getchar(); 365*7c478bd9Sstevel@tonic-gate (void) sleep(4); 366*7c478bd9Sstevel@tonic-gate (void) setup_target(SCAN_WRITERS); 367*7c478bd9Sstevel@tonic-gate } 368*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 369*7c478bd9Sstevel@tonic-gate (void) setreuid(ruid, 0); 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate if ((device_type != DVD_PLUS) && (device_type != DVD_PLUS_W)) { 372*7c478bd9Sstevel@tonic-gate ensure_media_space(total_nblks, end_tno); 373*7c478bd9Sstevel@tonic-gate write_init(audio_cd ? TRACK_MODE_AUDIO : TRACK_MODE_DATA); 374*7c478bd9Sstevel@tonic-gate } 375*7c478bd9Sstevel@tonic-gate 376*7c478bd9Sstevel@tonic-gate /* for each track */ 377*7c478bd9Sstevel@tonic-gate for (i = 0; i < end_tno; i++) { 378*7c478bd9Sstevel@tonic-gate /* 379*7c478bd9Sstevel@tonic-gate * DVD's dont contain tracks and need to be written in DAO 380*7c478bd9Sstevel@tonic-gate * mode. 381*7c478bd9Sstevel@tonic-gate */ 382*7c478bd9Sstevel@tonic-gate if (device_type != CD_RW) { 383*7c478bd9Sstevel@tonic-gate if (end_tno > 1) { 384*7c478bd9Sstevel@tonic-gate err_msg(gettext( 385*7c478bd9Sstevel@tonic-gate "Media state is not suitable for this" 386*7c478bd9Sstevel@tonic-gate " write mode.\n")); 387*7c478bd9Sstevel@tonic-gate } 388*7c478bd9Sstevel@tonic-gate write_mode = DAO_MODE; 389*7c478bd9Sstevel@tonic-gate 390*7c478bd9Sstevel@tonic-gate /* 391*7c478bd9Sstevel@tonic-gate * DVD-R(W) and DVD+R needs to have space reserved 392*7c478bd9Sstevel@tonic-gate * prior to writing. 393*7c478bd9Sstevel@tonic-gate */ 394*7c478bd9Sstevel@tonic-gate if ((device_type == DVD_MINUS) || 395*7c478bd9Sstevel@tonic-gate (device_type == DVD_PLUS)) { 396*7c478bd9Sstevel@tonic-gate if (!set_reservation(target->d_fd, 397*7c478bd9Sstevel@tonic-gate total_nblks + 1)) { 398*7c478bd9Sstevel@tonic-gate (void) printf(gettext( 399*7c478bd9Sstevel@tonic-gate "Setting reservation failed\n")); 400*7c478bd9Sstevel@tonic-gate exit(1); 401*7c478bd9Sstevel@tonic-gate } 402*7c478bd9Sstevel@tonic-gate } 403*7c478bd9Sstevel@tonic-gate } 404*7c478bd9Sstevel@tonic-gate 405*7c478bd9Sstevel@tonic-gate write_next_track(audio_cd ? TRACK_MODE_AUDIO : TRACK_MODE_DATA, 406*7c478bd9Sstevel@tonic-gate tlist[i].h); 407*7c478bd9Sstevel@tonic-gate 408*7c478bd9Sstevel@tonic-gate /* 409*7c478bd9Sstevel@tonic-gate * Running in simulation mode and writing several tracks is 410*7c478bd9Sstevel@tonic-gate * useless so bail after the first track is done. 411*7c478bd9Sstevel@tonic-gate */ 412*7c478bd9Sstevel@tonic-gate 413*7c478bd9Sstevel@tonic-gate if (simulation && (end_tno != 1)) { 414*7c478bd9Sstevel@tonic-gate (void) printf(gettext( 415*7c478bd9Sstevel@tonic-gate "Simulation mode : skipping remaining tracks\n")); 416*7c478bd9Sstevel@tonic-gate break; 417*7c478bd9Sstevel@tonic-gate } 418*7c478bd9Sstevel@tonic-gate } 419*7c478bd9Sstevel@tonic-gate 420*7c478bd9Sstevel@tonic-gate write_fini(); 421*7c478bd9Sstevel@tonic-gate /* close the temp file handles */ 422*7c478bd9Sstevel@tonic-gate for (i = 0; i < end_tno; i++) 423*7c478bd9Sstevel@tonic-gate (tlist[i].h)->bstr_close(tlist[i].h); 424*7c478bd9Sstevel@tonic-gate free(tlist); 425*7c478bd9Sstevel@tonic-gate fini_device(target); 426*7c478bd9Sstevel@tonic-gate exit(0); 427*7c478bd9Sstevel@tonic-gate } 428