--- /dev/null
+--- cdrtools-2.01/cdrecord/drv_mmc.c.dvd 2004-05-25 00:36:01.000000000 +0200
++++ cdrtools-2.01/cdrecord/drv_mmc.c 2004-10-18 14:40:10.329455353 +0200
+@@ -84,8 +84,11 @@
+ EXPORT char *hasdrvopt __PR((char *optstr, char *optname));
+ LOCAL cdr_t *identify_mmc __PR((SCSI *scgp, cdr_t *, struct scsi_inquiry *));
+ LOCAL int attach_mmc __PR((SCSI *scgp, cdr_t *));
++LOCAL int attach_mdvd __PR((SCSI *scgp, cdr_t *));
+ EXPORT int check_writemodes_mmc __PR((SCSI *scgp, cdr_t *dp));
++LOCAL int check_writemodes_mdvd __PR((SCSI *scgp, cdr_t *dp));
+ LOCAL int deflt_writemodes_mmc __PR((SCSI *scgp, BOOL reset_dummy));
++LOCAL int deflt_writemodes_mdvd __PR((SCSI *scgp, BOOL reset_dummy));
+ LOCAL int get_diskinfo __PR((SCSI *scgp, struct disk_info *dip));
+ LOCAL void di_to_dstat __PR((struct disk_info *dip, dstat_t *dsp));
+ LOCAL int get_atip __PR((SCSI *scgp, struct atipinfo *atp));
+@@ -94,18 +97,27 @@
+ #endif
+ LOCAL int init_mmc __PR((SCSI *scgp, cdr_t *dp));
+ LOCAL int getdisktype_mmc __PR((SCSI *scgp, cdr_t *dp));
++LOCAL int getdisktype_mdvd __PR((SCSI *scgp, cdr_t *dp));
+ LOCAL int speed_select_mmc __PR((SCSI *scgp, cdr_t *dp, int *speedp));
++LOCAL int speed_select_mdvd __PR((SCSI *scgp, cdr_t *dp, int *speedp));
+ LOCAL int mmc_set_speed __PR((SCSI *scgp, int readspeed, int writespeed, int rotctl));
+ LOCAL int next_wr_addr_mmc __PR((SCSI *scgp, track_t *trackp, long *ap));
++LOCAL int next_wr_addr_mdvd __PR((SCSI *scgp, track_t *trackp, long *ap));
+ LOCAL int write_leadin_mmc __PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
+ LOCAL int open_track_mmc __PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
++LOCAL int open_track_mdvd __PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
+ LOCAL int close_track_mmc __PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
++LOCAL int close_track_mdvd __PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
+ LOCAL int open_session_mmc __PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
++LOCAL int open_session_mdvd __PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
+ LOCAL int waitfix_mmc __PR((SCSI *scgp, int secs));
+ LOCAL int fixate_mmc __PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
++LOCAL int fixate_mdvd __PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
+ LOCAL int blank_mmc __PR((SCSI *scgp, cdr_t *dp, long addr, int blanktype));
++LOCAL int format_mdvd __PR((SCSI *scgp, cdr_t *dp, int formattype));
+ LOCAL int send_opc_mmc __PR((SCSI *scgp, caddr_t, int cnt, int doopc));
+ LOCAL int opt1_mmc __PR((SCSI *scgp, cdr_t *dp));
++LOCAL int opt1_mdvd __PR((SCSI *scgp, cdr_t *dp));
+ LOCAL int opt2_mmc __PR((SCSI *scgp, cdr_t *dp));
+ LOCAL int scsi_sony_write __PR((SCSI *scgp, caddr_t bp, long sectaddr, long size, int blocks, BOOL islast));
+ LOCAL int gen_cue_mmc __PR((track_t *trackp, void *vcuep, BOOL needgap));
+@@ -197,6 +209,46 @@
+ opt2_mmc,
+ };
+
++cdr_t cdr_mdvd = {
++ 0, 0,
++ CDR_SWABAUDIO,
++ 370,370,
++ "mmc_mdvd",
++ "generic SCSI-3/mmc DVD-R(W) driver",
++ 0,
++ (dstat_t *)0,
++ identify_mmc,
++ attach_mdvd,
++ init_mmc,
++ getdisktype_mdvd,
++ scsi_load,
++ scsi_unload,
++ read_buff_cap,
++ cmd_dummy, /* recovery_needed */
++ (int(*)__PR((SCSI *, int)))cmd_dummy, /* recover */
++ speed_select_mdvd,
++ select_secsize,
++ next_wr_addr_mdvd,
++ (int(*)__PR((SCSI *, Ulong)))cmd_ill, /* reserve_track */
++ scsi_cdr_write,
++ (int(*)__PR((SCSI *scgp, int, track_t *)))cmd_dummy, /* gen_cue */
++ (int(*)__PR((SCSI *scgp, cdr_t *, track_t *)))cmd_dummy, /* send_cue */
++ write_leadin_mmc,
++ open_track_mdvd,
++ close_track_mdvd,
++ open_session_mdvd,
++ cmd_dummy,
++ cmd_dummy, /* abort */
++ read_session_offset,
++ fixate_mdvd,
++ stats_mmc,
++ blank_mmc,
++ format_mdvd,
++ send_opc_mmc,
++ opt1_mdvd,
++ opt2_mmc,
++};
++
+ /*
+ * Sony MMC CD-writer
+ */
+@@ -556,7 +608,21 @@
+ if (profile >= 0) {
+ if (lverbose)
+ print_profiles(scgp);
+- if (profile == 0 || profile == 0x12 || profile > 0x19) {
++ if (profile == 0 || profile >= 0x10 && profile <= 0x15 || profile > 0x19) {
++ /*
++ * 10h DVD-ROM
++ * 11h DVD-R
++ * 12h DVD-RAM
++ * 13h DVD-RW (Restricted overwrite)
++ * 14h DVD-RW (Sequential recording)
++ * 1Ah DVD+RW
++ * 1Bh DVD+R
++ *
++ */
++ if (profile == 0x11 || profile == 0x13 || profile == 0x14 || profile == 0x1A || profile == 0x1B) {
++ is_dvd = TRUE;
++ dp = &cdr_mdvd;
++ } else {
+ is_dvd = FALSE;
+ dp = &cdr_cd;
+
+@@ -578,23 +644,8 @@
+ errmsgno(EX_BAD,
+ "Found unsupported DVD-RAM media.\n");
+ return (dp);
+- } else { /* DVD+RW DVD+R */
+- errmsgno(EX_BAD,
+- "Found DVD+ media but DVD+R/DVD+RW support code is missing.\n");
+- errmsgno(EX_BAD,
+- "If you need DVD+R/DVD+RW support, ask the Author for cdrecord-ProDVD.\n");
+- errmsgno(EX_BAD,
+- "Free test versions and free keys for personal use are at ftp://ftp.berlios.de/pub/cdrecord/ProDVD/\n");
+- return (dp);
+ }
+- } else if (profile >= 0x10 && profile < 0x18) {
+- errmsgno(EX_BAD,
+- "Found DVD media but DVD-R/DVD-RW support code is missing.\n");
+- errmsgno(EX_BAD,
+- "If you need DVD-R/DVD-RW support, ask the Author for cdrecord-ProDVD.\n");
+- errmsgno(EX_BAD,
+- "Free test versions and free keys for personal use are at ftp://ftp.berlios.de/pub/cdrecord/ProDVD/\n");
+- return (dp);
++ }
+ }
+ } else {
+ if (xdebug)
+@@ -661,13 +712,12 @@
+ #endif
+ }
+ if (is_dvd) {
+- errmsgno(EX_BAD,
+- "Found DVD media but DVD-R/DVD-RW support code is missing.\n");
+- errmsgno(EX_BAD,
+- "If you need DVD-R/DVD-RW support, ask the Author for cdrecord-ProDVD.\n");
+- errmsgno(EX_BAD,
+- "Free test versions and free keys for personal use are at ftp://ftp.berlios.de/pub/cdrecord/ProDVD/\n");
++ errmsgno(EX_BAD,
++ "Found DVD media: using cdr_mdvd.\n");
++ dp = &cdr_mdvd;
+ }
++ dp->profile = profile;
++ dp->is_dvd = is_dvd;
+ return (dp);
+ }
+
+@@ -856,6 +906,42 @@
+ return (0);
+ }
+
++LOCAL int
++attach_mdvd(scgp, dp)
++ SCSI *scgp;
++ cdr_t *dp;
++{
++ struct cd_mode_page_2A *mp;
++
++
++ allow_atapi(scgp, TRUE);/* Try to switch to 10 byte mode cmds */
++
++ scgp->silent++;
++ mp = mmc_cap(scgp, NULL);/* Get MMC capabilities in allocated mp */
++ scgp->silent--;
++ if (mp == NULL)
++ return (-1); /* Pre SCSI-3/mmc drive */
++
++ dp->cdr_cdcap = mp; /* Store MMC cap pointer */
++
++ if (mp->loading_type == LT_TRAY)
++ dp->cdr_flags |= CDR_TRAYLOAD;
++ else if (mp->loading_type == LT_CADDY)
++ dp->cdr_flags |= CDR_CADDYLOAD;
++
++ if (mp->BUF != 0)
++ dp->cdr_flags |= CDR_BURNFREE;
++
++ check_writemodes_mdvd(scgp, dp);
++
++ if (driveropts != NULL) {
++ if (strcmp(driveropts, "help") == 0) {
++ mmc_opthelp(dp, 0);
++ }
++ }
++
++ return (0);
++}
+
+ EXPORT int
+ check_writemodes_mmc(scgp, dp)
+@@ -1007,6 +1093,77 @@
+ }
+
+ LOCAL int
++check_writemodes_mdvd(scgp, dp)
++ SCSI *scgp;
++ cdr_t *dp;
++{
++ Uchar mode[0x100];
++ int len;
++ struct cd_mode_page_05 *mp;
++
++ if (xdebug)
++ printf("Checking possible write modes: ");
++
++ deflt_writemodes_mdvd(scgp, FALSE);
++
++ fillbytes((caddr_t)mode, sizeof(mode), '\0');
++
++ scgp->silent++;
++ if (!get_mode_params(scgp, 0x05, "CD write parameter",
++ mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
++ scgp->silent--;
++ return (-1);
++ }
++ if (len == 0) {
++ scgp->silent--;
++ return (-1);
++ }
++
++ mp = (struct cd_mode_page_05 *)
++ (mode + sizeof(struct scsi_mode_header) +
++ ((struct scsi_mode_header *)mode)->blockdesc_len);
++
++ mp->test_write = 0;
++
++ /*We only check for PACKET and SAO since these are the only supported modes for DVD */
++ /*XXX these checks are irrelevant because they are not medium sensitive. ie the device returns
++ error only when it does not support a given mode for ALL mediums. It should check using
++ GET CONFIGURATION command.*/
++
++ mp->write_type = WT_PACKET;
++ mp->fp = 0;
++ i_to_4_byte(mp->packet_size, 0);
++
++ if (set_mode_params(scgp, "CD write parameter", mode, len, 0, -1)) {
++ dp->cdr_flags |= CDR_PACKET;
++ if (xdebug)
++ printf("PACKET ");
++ } else
++ dp->cdr_flags &= ~CDR_PACKET;
++ mp->fp = 0;
++ i_to_4_byte(mp->packet_size, 0);
++ mp->track_mode = TM_DATA;
++
++
++ mp->write_type = WT_SAO;
++
++ if (set_mode_params(scgp, "CD write parameter", mode, len, 0, -1)) {
++ dp->cdr_flags |= CDR_SAO;
++ if (xdebug)
++ printf("SAO ");
++ } else
++ dp->cdr_flags &= ~CDR_SAO;
++
++
++ if (xdebug)
++ printf("\n");
++
++ deflt_writemodes_mdvd(scgp, TRUE);
++ scgp->silent--;
++ return (0);
++}
++
++LOCAL int
+ deflt_writemodes_mmc(scgp, reset_dummy)
+ SCSI *scgp;
+ BOOL reset_dummy;
+@@ -1080,6 +1237,61 @@
+ return (0);
+ }
+
++LOCAL int
++deflt_writemodes_mdvd(scgp, reset_dummy)
++ SCSI *scgp;
++ BOOL reset_dummy;
++{
++ Uchar mode[0x100];
++ int len;
++ struct cd_mode_page_05 *mp;
++
++ fillbytes((caddr_t)mode, sizeof(mode), '\0');
++
++ scgp->silent++;
++ if (!get_mode_params(scgp, 0x05, "DVD write parameter",
++ mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
++ scgp->silent--;
++ return (-1);
++ }
++ if (len == 0) {
++ scgp->silent--;
++ return (-1);
++ }
++
++ mp = (struct cd_mode_page_05 *)
++ (mode + sizeof(struct scsi_mode_header) +
++ ((struct scsi_mode_header *)mode)->blockdesc_len);
++
++ mp->test_write = 0;
++ /*
++ * This is the only place where we reset mp->test_write (-dummy)
++ */
++ if (reset_dummy)
++ mp->test_write = 0;
++
++
++ /*
++ * Set default values:
++ * Write type = 02 (session at once)
++ *
++ * XXX Note: the same code appears in check_writemodes_mmc() and
++ * XXX in speed_select_mmc().
++ */
++ mp->write_type = WT_SAO;
++ mp->track_mode = TM_DATA;
++ mp->dbtype = DB_ROM_MODE1;
++ mp->session_format = SES_DA_ROM;
++
++
++ if (set_mode_params(scgp, "DVD write parameter", mode, len, 0, -1) < 0) {
++ scgp->silent--;
++ return (-1);
++ }
++ scgp->silent--;
++ return (0);
++}
++
+ #ifdef PRINT_ATIP
+ LOCAL void print_di __PR((struct disk_info *dip));
+ LOCAL void atip_printspeed __PR((char *fmt, int speedindex, char speedtab[]));
+@@ -1149,6 +1361,9 @@
+
+ if (dsp->ds_last_leadout == 0 && dsp->ds_maxblocks >= 0)
+ dsp->ds_last_leadout = dsp->ds_maxblocks;
++ dsp->ds_trfirst=dip->first_track;
++ dsp->ds_trlast=dip->last_track_ls;
++ dsp->ds_trfirst_ls=dip->first_track_ls;
+ }
+
+ LOCAL int
+@@ -1259,6 +1474,30 @@
+ }
+
+ LOCAL int
++getdisktype_mdvd(scgp, dp)
++ SCSI *scgp;
++ cdr_t *dp;
++{
++ int ret=0;
++ dstat_t *dsp = dp->cdr_dstat;
++
++ struct track_info track_info;
++ if(getdisktype_mmc(scgp, dp)<0)
++ return -1;
++
++ /* read rzone info to get the space left on disk */
++ /*ds_trlast is the last rzone on disk, can be invisible */
++ if(read_rzone_info(scgp, (caddr_t)&track_info, sizeof(track_info))>=0)
++ dsp->ds_maxblocks=a_to_u_4_byte(track_info.free_blocks)+a_to_4_byte(track_info.next_writable_addr);
++
++ dsp->ds_disktype&= ~DT_CD;
++ dsp->ds_disktype|= DT_DVD;
++
++ return (ret);
++
++}
++
++LOCAL int
+ getdisktype_mmc(scgp, dp)
+ SCSI *scgp;
+ cdr_t *dp;
+@@ -1688,6 +1927,7 @@
+ * But the standard is rounding the wrong way.
+ * Furtunately rounding down is guaranteed.
+ */
++ //val = curspeed*177;
+ val = curspeed*177;
+ if (val > 0xFFFF)
+ val = 0xFFFF;
+@@ -1700,6 +1940,7 @@
+
+ if (scsi_get_speed(scgp, 0, &val) >= 0) {
+ if (val > 0) {
++ printf("Speed set to %d KB/s\n", val);
+ curspeed = val / 176;
+ *speedp = curspeed;
+ }
+@@ -1762,6 +2003,68 @@
+ }
+
+ LOCAL int
++speed_select_mdvd(scgp, dp, speedp)
++ SCSI *scgp;
++ cdr_t *dp;
++ int *speedp;
++{
++ int retcode;
++ unsigned char perf_desc[28];
++ int write_speed = *speedp * 1385;
++ int val = 0, val2 = 0;
++ int i;
++
++ /* For the moment we just divide the CD speed by 7*/
++
++ if(speedp!=NULL)
++ (*speedp)=(*speedp)*8;
++
++ memset(perf_desc, 0, sizeof(perf_desc));
++
++ /* Write Rotation Control = ROTCTL_CLV
++ * | Restore Logical Unit Defaults = 0
++ * | Exact = 0
++ * | Random Access = 0)
++ */
++ perf_desc[0]= ROTCTL_CLV << 3 | 0 << 2 | 0 << 1 | 0;
++ /* Start LBA to 0 */
++ perf_desc[4] = 0;
++ perf_desc[5] = 0;
++ perf_desc[6] = 0;
++ perf_desc[7] = 0;
++ /* End LBA set to 0 (setting to 0xffffffff failed on my LG burner
++ */
++ perf_desc[8] = 0;
++ perf_desc[9] = 0;
++ perf_desc[10] = 0;
++ perf_desc[11] = 0;
++ /* Read Speed = 0xFFFF */
++ perf_desc[12] = 0;
++ perf_desc[13] = 0;
++ perf_desc[14] = 0xFF;
++ perf_desc[15] = 0xFF;
++ /* Read Time = 1s */
++ perf_desc[18] = 1000 >> 8;
++ perf_desc[19] = 1000 & 0xFF;
++ /* Write Speed */
++ perf_desc[20] = write_speed >> 24;
++ perf_desc[21] = write_speed >> 16 & 0xFF;
++ perf_desc[22] = write_speed >> 8 & 0xFF;
++ perf_desc[23] = write_speed & 0xFF;
++ /* Write Time = 1s */
++ perf_desc[26] = 1000 >> 8;
++ perf_desc[27] = 1000 & 0xFF;
++
++ //retcode = scsi_set_streaming(scgp, NULL, 0);
++ retcode = scsi_set_streaming(scgp, &perf_desc, sizeof(perf_desc));
++ if (retcode == -1) return retcode;
++ retcode = speed_select_mmc(scgp, dp, speedp);
++ if(speedp!=NULL)
++ (*speedp)=(*speedp)/7;
++ return retcode;
++}
++
++LOCAL int
+ next_wr_addr_mmc(scgp, trackp, ap)
+ SCSI *scgp;
+ track_t *trackp;
+@@ -1898,6 +2201,48 @@
+ };
+
+ LOCAL int
++next_wr_addr_mdvd(scgp, trackp, ap)
++ SCSI *scgp;
++ track_t *trackp;
++ long *ap;
++{
++ int track;
++ struct track_info track_info;
++ long next_addr;
++ int result = -1;
++ struct disk_info disk_info;
++ if (trackp){
++ track = trackp->trackno;
++ }
++
++ if (trackp != 0 && track > 0 && is_packet(trackp)) {
++ scgp->silent++;
++ result = read_rzone_info(scgp, (caddr_t)&track_info, sizeof(track_info));
++ scgp->silent--;
++ if (scsi_in_progress(scgp)){
++ return -1;
++ }
++
++ }
++
++ if (result < 0) {
++ /* Get the last rzone*/
++ if(read_disk_info(scgp,(caddr_t)&disk_info,8)<0)
++ return (-1);
++
++ if (read_rzone_info(scgp, (caddr_t)&track_info, sizeof(track_info)) < 0)
++ return (-1);
++ }
++ if (scgp->verbose)
++ scg_prbytes("track info:", (Uchar *)&track_info,
++ sizeof(track_info)-scg_getresid(scgp));
++ next_addr = a_to_4_byte(track_info.next_writable_addr);
++ if (ap)
++ *ap = next_addr;
++ return (0);
++}
++
++LOCAL int
+ open_track_mmc(scgp, dp, trackp)
+ SCSI *scgp;
+ cdr_t *dp;
+@@ -1978,6 +2323,45 @@
+ }
+
+ LOCAL int
++open_track_mdvd(scgp, dp, trackp)
++ SCSI *scgp;
++ cdr_t *dp;
++ track_t *trackp;
++{
++ Uchar mode[0x100];
++ int len;
++ struct cd_mode_page_05 *mp;
++
++ if (is_packet(trackp)) {
++ fillbytes((caddr_t)mode, sizeof(mode), '\0');
++
++ if (!get_mode_params(scgp, 0x05, "DVD write parameter",
++ mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len))
++ return (-1);
++ if (len == 0)
++ return (-1);
++
++ mp = (struct cd_mode_page_05 *)
++ (mode + sizeof(struct scsi_mode_header) +
++ ((struct scsi_mode_header *)mode)->blockdesc_len);
++
++ mp->write_type = WT_PACKET;
++ mp->LS_V = 1;
++ /*For now we set the link size to 0x10(32k) because Pioneer-A03 only support this */
++ mp->link_size=0x10;
++ mp->fp = 1;
++ i_to_4_byte(mp->packet_size, trackp->pktsize);
++ } else {
++ return 0;
++ }
++
++ if (!set_mode_params(scgp, "CD write parameter", mode, len, 0, trackp->secsize))
++ return (-1);
++
++ return (0);
++}
++
++LOCAL int
+ close_track_mmc(scgp, dp, trackp)
+ SCSI *scgp;
+ cdr_t *dp;
+@@ -2003,6 +2387,30 @@
+ return (0);
+ }
+
++LOCAL int
++close_track_mdvd(scgp, dp, trackp)
++ SCSI *scgp;
++ cdr_t *dp;
++ track_t *trackp;
++{
++ int ret;
++ if (!is_packet(trackp))
++ return (0);
++
++ if (scsi_flush_cache(scgp, (dp->cdr_cmdflags&F_IMMED) != 0) < 0) {
++ printf("Trouble flushing the cache\n");
++ return -1;
++ }
++ wait_unit_ready(scgp, 300); /* XXX Wait for ATAPI */
++ if (is_packet(trackp) && !is_noclose(trackp)) {
++ /* close the incomplete track */
++ ret = scsi_close_tr_session(scgp, 1, 0xFF, (dp->cdr_cmdflags&F_IMMED) != 0);
++ wait_unit_ready(scgp, 300); /* XXX Wait for ATAPI */
++ return (ret);
++ }
++ return (0);
++}
++
+ int toc2sess[] = {
+ SES_DA_ROM, /* CD-DA */
+ SES_DA_ROM, /* CD-ROM */
+@@ -2086,6 +2494,82 @@
+ }
+
+ LOCAL int
++open_session_mdvd(scgp, dp, trackp)
++ SCSI *scgp;
++ cdr_t *dp;
++ track_t *trackp;
++{
++ Uchar mode[0x100];
++ int tracks = trackp->tracks;
++
++ int len;
++ struct cd_mode_page_05 *mp;
++ Ulong totalsize;
++ int i;
++ struct track_info track_info;
++ int profile;
++
++ fillbytes((caddr_t)mode, sizeof(mode), '\0');
++
++ if (!get_mode_params(scgp, 0x05, "DVD write parameter",
++ mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len))
++ return (-1);
++ if (len == 0)
++ return (-1);
++
++ mp = (struct cd_mode_page_05 *)
++ (mode + sizeof(struct scsi_mode_header) +
++ ((struct scsi_mode_header *)mode)->blockdesc_len);
++ if(is_packet(trackp)){
++ mp->write_type=WT_PACKET;
++ mp->multi_session = (track_base(trackp)->tracktype & TOCF_MULTI) ? MS_MULTI : MS_NONE;
++ mp->fp=0;
++ mp->BUFE=1;
++ mp->track_mode=1;
++ }else{
++ mp->write_type = WT_SAO;
++ }
++
++
++ if (lverbose && dp->cdr_cdcap->BUF != 0)
++ printf("BURN-Free is %s.\n", mp->BUFE?"ON":"OFF");
++ if (driveropts != NULL) {
++ if ((strcmp(driveropts, "burnproof") == 0 ||
++ strcmp(driveropts, "burnfree") == 0) && dp->cdr_cdcap->BUF != 0) {
++ errmsgno(EX_BAD, "Turning BURN-Free on\n");
++ mp->BUFE = 1;
++ } else if ((strcmp(driveropts, "noburnproof") == 0 ||
++ strcmp(driveropts, "noburnfree") == 0)) {
++ errmsgno(EX_BAD, "Turning BURN-Free off\n");
++ mp->BUFE = 0;
++ } else if (strcmp(driveropts, "help") == 0) {
++ mmc_opthelp(dp, 0);
++ } else {
++ errmsgno(EX_BAD, "Bad driver opts '%s'.\n", driveropts);
++ mmc_opthelp(dp, EX_BAD);
++ }
++ }
++
++
++ if (!set_mode_params(scgp, "DVD write parameter", mode, len, 0, -1))
++ return (-1);
++
++
++ totalsize=0;
++ for(i=1;i<=tracks;i++) {
++ totalsize+=trackp[i].tracksecs;
++ }
++
++ profile = get_curprofile(scgp);
++ if(!is_packet(trackp) && profile != 0x1A){
++ /* in DAO mode we need to reserve space for the track*/
++ if(reserve_track(scgp, totalsize)<0)
++ return (-1);
++ }
++ return (0);
++}
++
++LOCAL int
+ waitfix_mmc(scgp, secs)
+ SCSI *scgp;
+ int secs;
+@@ -2215,6 +2699,25 @@
+ return (ret);
+ }
+
++LOCAL int
++fixate_mdvd(scgp, dp, trackp)
++ SCSI *scgp;
++ cdr_t *dp;
++ track_t *trackp;
++{
++ /*set a really BIG timeout and call fixate_mmc
++ The BIG timeout is needed in case there was a very short rzone to write at the
++ beginning of the disk, because lead-out needs to be at some distance.
++ */
++ scg_settimeout(scgp, 1000);
++ if(is_packet(trackp)){
++ scsi_close_tr_session(scgp, 2, 0, FALSE);
++ }
++ fixate_mmc(scgp, dp, trackp);
++ scg_settimeout(scgp, 200);
++
++}
++
+ char *blank_types[] = {
+ "entire disk",
+ "PMA, TOC, pregap",
+@@ -2226,6 +2729,12 @@
+ "reserved blanking type",
+ };
+
++char *format_types[] = {
++ "full format",
++ "background format",
++ "forced format",
++};
++
+ LOCAL int
+ blank_mmc(scgp, dp, addr, blanktype)
+ SCSI *scgp;
+@@ -2238,11 +2747,17 @@
+ BOOL cdrrw = FALSE; /* Read CD-RW */
+ BOOL cdwrw = FALSE; /* Write CD-RW */
+ int ret;
++ int profile;
+
+ mmc_check(scgp, &cdrr, &cdwr, &cdrrw, &cdwrw, NULL, NULL);
+ if (!cdwrw)
+ return (blank_dummy(scgp, dp, addr, blanktype));
+
++ profile = get_curprofile(scgp);
++ if (profile == 0x1A) {
++ printf("Error: this media does not support blanking, ignoring.\n");
++ return (blank_dummy(scgp, dp, addr, blanktype));
++ }
+ if (lverbose) {
+ printf("Blanking %s\n", blank_types[blanktype & 0x07]);
+ flush();
+@@ -2258,6 +2773,80 @@
+ }
+
+ LOCAL int
++format_mdvd(scgp, dp, formattype)
++ SCSI *scgp;
++ cdr_t *dp;
++ int formattype;
++{
++extern char *buf;
++ BOOL dvdwr = FALSE; /* Write DVD */
++ int ret;
++ int profile;
++ char addr[12];
++ struct disk_info *dip;
++
++ printf("format_mdvd\n");
++ mmc_check(scgp, NULL, NULL, NULL, NULL, NULL, &dvdwr);
++ if (!dvdwr)
++ return (format_dummy(scgp, dp, formattype));
++
++ printf("format_mdvd: drive is a dvd burner.\n");
++ profile = get_curprofile(scgp);
++ if (profile != 0x1A) {
++ printf("Error: only support DVD+RW formating, ignoring.\n");
++ return (format_dummy(scgp, dp, formattype));
++ }
++ printf("format_mdvd: media is a DVD+RW.\n");
++ dip = (struct disk_info *)buf;
++ if (get_diskinfo(scgp, dip) < 0)
++ return ret;
++
++ if (dip->disk_status & 3 && formattype != FORCE_FORMAT) {
++ printf("Error: disk already formated, ignoring.\n");
++ return ret;
++ }
++ addr[0] = 0; // "Reserved"
++ addr[1] = 2; // "IMMED" flag
++ addr[2] = 0; // "Descriptor Length" (MSB)
++ addr[3] = 8; // "Descriptor Length" (LSB)
++ addr[4+0] = 0xff;
++ addr[4+1] = 0xff;
++ addr[4+2] = 0xff;
++ addr[4+3] = 0xff;
++ addr[4+4] = 0x26<<2;
++ addr[4+5] = 0;
++ addr[4+6] = 0;
++ addr[4+7] = 0;
++ if (formattype == FORCE_FORMAT) {
++ printf("format_mdvd: forcing reformat.\n");
++ formattype = FULL_FORMAT;
++ addr[4+0] = 0;
++ addr[4+1] = 0;
++ addr[4+2] = 0;
++ addr[4+3] = 0;
++ addr[4+7] = 1;
++ } else {
++ printf("format_mdvd: media is unformated.\n");
++ }
++
++ if (lverbose) {
++ printf("Formating %s\n", format_types[formattype & 0x07]);
++ flush();
++ }
++ if (formattype == FULL_FORMAT) {
++ ret = scsi_format(scgp, &addr, sizeof(addr), FALSE);
++ } else {
++ ret = scsi_format(scgp, &addr, sizeof(addr), TRUE);
++ }
++ if (ret < 0)
++ return (ret);
++
++ wait_unit_ready(scgp, 90*60/curspeed); /* XXX Wait for ATAPI */
++ waitfix_mmc(scgp, 90*60/curspeed); /* XXX Wait for ATAPI */
++ return (ret);
++}
++
++LOCAL int
+ send_opc_mmc(scgp, bp, cnt, doopc)
+ SCSI *scgp;
+ caddr_t bp;
+@@ -2453,6 +3042,42 @@
+ }
+
+ LOCAL int
++opt1_mdvd(scgp, dp)
++ SCSI *scgp;
++ cdr_t *dp;
++{
++ int oflags = dp->cdr_dstat->ds_cdrflags;
++
++ if ((dp->cdr_dstat->ds_cdrflags & RF_AUDIOMASTER) != 0) {
++ printf("Turning Audio Master Q. R. on\n");
++ if (set_audiomaster_yamaha(scgp, dp, TRUE) < 0)
++ return (-1);
++ if (!debug && lverbose <= 1)
++ dp->cdr_dstat->ds_cdrflags &= ~RF_PRATIP;
++ if (getdisktype_mdvd(scgp, dp) < 0) {
++ dp->cdr_dstat->ds_cdrflags = oflags;
++ return (-1);
++ }
++ dp->cdr_dstat->ds_cdrflags = oflags;
++ if (oflags & RF_PRATIP) {
++ msf_t msf;
++ lba_to_msf(dp->cdr_dstat->ds_first_leadin, &msf);
++ printf("New start of lead in: %ld (%02d:%02d/%02d)\n",
++ (long)dp->cdr_dstat->ds_first_leadin,
++ msf.msf_min,
++ msf.msf_sec,
++ msf.msf_frame);
++ lba_to_msf(dp->cdr_dstat->ds_maxblocks, &msf);
++ printf("New start of lead out: %ld (%02d:%02d/%02d)\n",
++ (long)dp->cdr_dstat->ds_maxblocks,
++ msf.msf_min,
++ msf.msf_sec,
++ msf.msf_frame);
++ }
++ }
++ return (0);
++}
++LOCAL int
+ scsi_sony_write(scgp, bp, sectaddr, size, blocks, islast)
+ SCSI *scgp;
+ caddr_t bp; /* address of buffer */
+--- cdrtools-2.01/cdrecord/cdr_drv.c.dvd 2004-03-02 02:06:26.000000000 +0100
++++ cdrtools-2.01/cdrecord/cdr_drv.c 2004-10-18 14:37:32.427251472 +0200
+@@ -42,6 +42,7 @@
+ extern cdr_t cdr_oldcd;
+ extern cdr_t cdr_cd;
+ extern cdr_t cdr_mmc;
++extern cdr_t cdr_mdvd;
+ extern cdr_t cdr_mmc_sony;
+ extern cdr_t cdr_cd_dvd;
+ extern cdr_t cdr_philips_cdd521O;
+@@ -80,6 +81,7 @@
+ cdr_t *drivers[] = {
+ &cdr_cd_dvd,
+ &cdr_mmc,
++ &cdr_mdvd,
+ &cdr_mmc_sony,
+ &cdr_cd,
+ &cdr_oldcd,
+--- cdrtools-2.01/cdrecord/cdrecord.h.dvd 2004-05-25 00:36:01.000000000 +0200
++++ cdrtools-2.01/cdrecord/cdrecord.h 2004-10-18 14:37:32.428251328 +0200
+@@ -460,6 +460,13 @@
+ #define BLANK_SESSION 0x06 /* Erase the last session */
+
+ /*
++ * Defines for formating DVD (custom values)
++ */
++#define FULL_FORMAT 0x00 /* Interactive format */
++#define BACKGROUND_FORMAT 0x01 /* Background format */
++#define FORCE_FORMAT 0x02 /* Force reformat */
++
++/*
+ * Useful definitions for audio tracks
+ */
+ #define msample (44100 * 2) /* one 16bit audio sample */
+@@ -570,6 +577,12 @@
+ #define DSF_NEED_FORMAT 0x0800 /* Disk needs to be formatted */
+
+ /*
++ * Definitions for disktype flags
++ */
++#define DT_CD 0x001 /*is a CD */
++#define DT_DVD 0x002 /*is a DVD */
++
++/*
+ * Definitions for disk_status disk type
+ * used in "ds_type".
+ */
+@@ -709,6 +722,8 @@
+ int (*cdr_opc) __PR((SCSI *scgp, caddr_t bp, int cnt, int doopc)); /* Do OPC */
+ int (*cdr_opt1) __PR((SCSI *scgp, cdr_t *)); /* do early option processing*/
+ int (*cdr_opt2) __PR((SCSI *scgp, cdr_t *)); /* do late option processing */
++ int profile;
++ BOOL is_dvd;
+ };
+ #endif
+
+--- cdrtools-2.01/cdrecord/cdrecord.c.dvd 2004-09-08 19:26:35.000000000 +0200
++++ cdrtools-2.01/cdrecord/cdrecord.c 2004-10-18 14:37:32.436250174 +0200
+@@ -180,6 +180,7 @@
+ LOCAL void susage __PR((int));
+ LOCAL void usage __PR((int));
+ LOCAL void blusage __PR((int));
++LOCAL void formattypeusage __PR((int));
+ LOCAL void intr __PR((int sig));
+ LOCAL void catchsig __PR((int sig));
+ LOCAL int scsi_cb __PR((void *arg));
+@@ -216,9 +217,9 @@
+ LOCAL BOOL checkdsize __PR((SCSI *scgp, cdr_t *dp,
+ long tsize, int flags));
+ LOCAL void raise_fdlim __PR((void));
+-LOCAL void gargs __PR((int, char **, int *, track_t *, char **,
++LOCAL int gargs __PR((int, char **, int *, track_t *, char **,
+ int *, cdr_t **,
+- int *, long *, int *));
++ int *, long *, int *, int *));
+ LOCAL void set_trsizes __PR((cdr_t *, int, track_t *));
+ EXPORT void load_media __PR((SCSI *scgp, cdr_t *, BOOL));
+ EXPORT void unload_media __PR((SCSI *scgp, cdr_t *, int));
+@@ -238,6 +239,7 @@
+ LOCAL void wait_input __PR((void));
+ LOCAL void checkgui __PR((void));
+ LOCAL int getbltype __PR((char *optstr, long *typep));
++LOCAL int getformattype __PR((char *optstr, long *typep));
+ LOCAL void print_drflags __PR((cdr_t *dp));
+ LOCAL void print_wrmodes __PR((cdr_t *dp));
+ LOCAL BOOL check_wrmode __PR((cdr_t *dp, int wmode, int tflags));
+@@ -262,6 +264,7 @@
+ int speed = -1;
+ long flags = 0L;
+ int blanktype = 0;
++ int formattype = 0;
+ int i;
+ int tracks = 0;
+ int trackno;
+@@ -273,6 +276,9 @@
+ SCSI *scgp = NULL;
+ char errstr[80];
+ BOOL gracedone = FALSE;
++ int ispacket;
++ BOOL is_cdwr = FALSE;
++ BOOL is_dvdwr = FALSE;
+
+ #ifdef __EMX__
+ /* This gives wildcard expansion with Non-Posix shells with EMX */
+@@ -287,8 +293,8 @@
+ track[i].track = track[i].trackno = i;
+ track[0].tracktype = TOC_MASK;
+ raise_fdlim();
+- gargs(ac, av, &tracks, track, &dev, &timeout, &dp, &speed, &flags,
+- &blanktype);
++ ispacket = gargs(ac, av, &tracks, track, &dev, &timeout, &dp, &speed, &flags,
++ &blanktype, &formattype);
+ if ((track[0].tracktype & TOC_MASK) == TOC_MASK)
+ comerrno(EX_BAD, "Internal error: Bad TOC type.\n");
+
+@@ -349,11 +355,15 @@
+ # define CLONE_TITLE ""
+ #endif
+ if ((flags & F_MSINFO) == 0 || lverbose || flags & F_VERSION) {
+- printf("Cdrecord%s%s %s (%s-%s-%s) Copyright (C) 1995-2004 Jörg Schilling\n",
++ printf("Cdrecord%s%s %s-dvd (%s-%s-%s) Copyright (C) 1995-2004 Jörg Schilling\n",
+ PRODVD_TITLE,
+ CLONE_TITLE,
+ cdr_version,
+ HOST_CPU, HOST_VENDOR, HOST_OS);
++ printf("Note: This version is an unofficial (modified) version with DVD support\n");
++ printf("Note: and therefore may have bugs that are not present in the original.\n");
++ printf("Note: Please send bug reports or support requests to <warly@mandrakesoft.com>.\n");
++ printf("Note: The author of cdrecord should not be bothered with problems in this version.\n");
+
+ #if defined(SOURCE_MODIFIED) || !defined(IS_SCHILY_XCONFIG)
+ #define INSERT_YOUR_EMAIL_ADDRESS_HERE
+@@ -483,11 +493,16 @@
+ */
+ if ((scgp = scg_open(dev, errstr, sizeof (errstr),
+ debug, (flags & F_MSINFO) == 0 || lverbose)) == (SCSI *)0) {
++ if (dev != NULL || (flags & F_SCANBUS) == 0 || (scgp = scg_open("ATA", errstr, sizeof (errstr),
++ debug, (flags & F_MSINFO) == 0 || lverbose)) == (SCSI *)0) {
+ errmsg("%s%sCannot open SCSI driver.\n", errstr, errstr[0]?". ":"");
+ errmsgno(EX_BAD, "For possible targets try 'cdrecord -scanbus'.%s\n",
+ geteuid() ? " Make sure you are root.":"");
+ errmsgno(EX_BAD, "For possible transport specifiers try 'cdrecord dev=help'.\n");
+ exit(EX_BAD);
++ } else {
++ dev = "ATA";
++ }
+ }
+ /*
+ * XXX Below this point we do not need root privilleges anymore.
+@@ -619,6 +634,17 @@
+ } else if (!is_unknown_dev(scgp) && dp != get_cdrcmds(scgp)) {
+ errmsgno(EX_BAD, "WARNING: Trying to use other driver on known device.\n");
+ }
++ is_mmc(scgp, &is_cdwr, &is_dvdwr);
++ if (ispacket) {
++ if (is_dvdwr) {
++ track[0].flags |= TI_PACKET;
++ /*XXX put here to only affect DVD writing, should be in gargs.
++ * however if set in args for all mode, packet writing is then
++ * broken for all disc as cdrecord assume that PACKET imply TAO which
++ * is not true at all???? */
++ track[0].flags &= ~TI_TAO;
++ }
++ }
+
+ if (!is_cddrive(scgp))
+ comerrno(EX_BAD, "Sorry, no CD/DVD-Drive found on this target.\n");
+@@ -649,8 +675,6 @@
+ tracks > 0 ||
+ cuefilename != NULL) {
+
+- BOOL is_cdwr = FALSE;
+- BOOL is_dvdwr = FALSE;
+
+ if ((dp->cdr_flags & CDR_ISREADER) != 0) {
+ errmsgno(EX_BAD,
+@@ -660,7 +684,7 @@
+ if (!is_mmc(scgp, &is_cdwr, &is_dvdwr))
+ is_cdwr = TRUE; /* If it is not MMC, it must be a CD writer */
+
+- if (is_dvdwr && !set_cdrcmds("mmc_dvd", (cdr_t **)NULL)) {
++ if (is_dvdwr && !set_cdrcmds("mmc_mdvd", (cdr_t **)NULL)) {
+ errmsgno(EX_BAD,
+ "This version of cdrecord does not include DVD-R/DVD-RW support code.\n");
+ errmsgno(EX_BAD,
+@@ -965,11 +989,6 @@
+ print_toc(scgp, dp);
+ comexit(0);
+ }
+- if ((flags & F_FORMAT) != 0) {
+- errmsgno(EX_BAD, "Format option not implemented in this version.\n");
+- comexit(EX_BAD);
+- }
+-
+ #ifdef XXX
+ if ((*dp->cdr_check_session)() < 0) {
+ comexit(EX_BAD);
+@@ -1181,7 +1200,39 @@
+ if (gettimeofday(&starttime, (struct timezone *)0) < 0)
+ errmsg("Cannot get start time\n");
+
+- /*
++ if (flags & F_FORMAT) {
++ printf("cdrecord: media format asked\n");
++ /*
++ * Do not abort if OPC failes. Just give it a chance
++ * for better laser power calibration than without OPC.
++ *
++ * Ricoh drives return with a vendor unique sense code.
++ * This is most likely because they refuse to do OPC
++ * on a non blank media.
++ */
++ scgp->silent++;
++ do_opc(scgp, dp, flags);
++ scgp->silent--;
++ wait_unit_ready(scgp, 120);
++ if (gettimeofday(&starttime, (struct timezone *)0) < 0)
++ errmsg("Cannot get start time\n");
++
++ if ((*dp->cdr_format)(scgp, dp, formattype) < 0) {
++ errmsgno(EX_BAD, "Cannot format disk, aborting.\n");
++ comexit(EX_BAD);
++ }
++ if (gettimeofday(&fixtime, (struct timezone *)0) < 0)
++ errmsg("Cannot get format time\n");
++ if (lverbose)
++ prtimediff("Formatting time: ", &starttime, &fixtime);
++
++ if (!wait_unit_ready(scgp, 240) || tracks == 0) {
++ comexit(0);
++ }
++ if (gettimeofday(&starttime, (struct timezone *)0) < 0)
++ errmsg("Cannot get start time\n");
++ }
++ /*
+ * Blank the media if we were requested to do so
+ */
+ if (flags & F_BLANK) {
+@@ -1238,6 +1289,14 @@
+ trackno = 0;
+ }
+ scgp->silent--;
++
++ /* If it is DVD, the information in TOC is fabricated :)
++ The real information is from read disk info command*/
++ if((dp->cdr_dstat->ds_disktype&DT_DVD) && (dp->cdr_dstat->ds_trlast>0)){
++ trackno=dp->cdr_dstat->ds_trlast-1;
++ printf("trackno=%d\n",trackno);
++ }
++
+ if ((tracks + trackno) > MAX_TRACK) {
+ /*
+ * XXX How many tracks are allowed on a DVD?
+@@ -1422,8 +1481,8 @@
+ if (gracetime > 999)
+ gracetime = 999;
+
+- printf("Starting to write CD/DVD at speed %d in %s%s %s mode for %s session.\n",
+- (int)dp->cdr_dstat->ds_wspeed,
++ printf("Starting to write CD/DVD at speed %5.1f in %s%s %s mode for %s session.\n",
++ (float)dp->cdr_dstat->ds_wspeed,
+ (dp->cdr_cmdflags & F_DUMMY) ? "dummy" : "real",
+ (dp->cdr_cmdflags & F_FORCE) ? " force" : "",
+ wm2name[dp->cdr_dstat->ds_wrmode],
+@@ -1539,6 +1598,7 @@
+ (tlast.tv_sec * 1.0 + tlast.tv_usec * 0.000001);
+ if (fspeed > 999.0)
+ fspeed = 999.0;
++ if (dp->is_dvd) fspeed /= 9;
+ printf("Average write speed %5.1fx.\n", fspeed);
+ }
+
+@@ -1593,7 +1653,7 @@
+ error("\t-checkdrive check if a driver for the drive is present\n");
+ error("\t-prcap print drive capabilities for MMC compliant drives\n");
+ error("\t-inq do an inquiry for the drive and exit\n");
+- error("\t-scanbus scan the SCSI bus and exit\n");
++ error("\t-scanbus scan the SCSI and IDE buses and exit\n");
+ error("\t-reset reset the SCSI bus with the cdrecorder (if possible)\n");
+ error("\t-abort send an abort sequence to the drive (may help if hung)\n");
+ error("\t-overburn allow to write more than the official size of a medium\n");
+@@ -1601,7 +1661,8 @@
+ error("\t-useinfo use *.inf files to overwrite audio options.\n");
+ error("\tspeed=# set speed of drive\n");
+ error("\tblank=type blank a CD-RW disc (see blank=help)\n");
+- error("\t-format format a CD-RW/DVD-RW/DVD+RW disc\n");
++ error("\tformat format a CD-RW/DVD-RW/DVD+RW disc\n");
++ error("\tformattype=# select the format method for DVD+RW disc\n");
+ #ifdef FIFO
+ error("\tfs=# Set fifo size to # (0 to disable, default is %ld MB)\n",
+ DEFAULT_FIFOSIZE/(1024L*1024L));
+@@ -1687,6 +1748,18 @@
+ /* NOTREACHED */
+ }
+
++LOCAL void
++formattypeusage(ret)
++ int ret;
++{
++ error("Formating options:\n");
++ error("\tfull\t\tstandard formating\n");
++ error("\tbackground\t\tbackground formating\n");
++ error("\tforce\t\tforce reformat\n");
++
++ exit(ret);
++ /* NOTREACHED */
++}
+ /* ARGSUSED */
+ LOCAL void
+ intr(sig)
+@@ -2156,6 +2229,7 @@
+ usleep(wt*1000);
+ }
+ #endif
++ if (dp->is_dvd) fspeed /= 9;
+ printf(" %5.1fx", fspeed);
+ printf(".");
+ savbytes = (bytes >> 20) << 20;
+@@ -2969,10 +3043,13 @@
+ /*
+ * dsp->ds_maxblocks == 0 (disk capacity is unknown).
+ */
+- if (endsec >= (405000-300)) { /*<90 min disk*/
+- errmsgno(EX_BAD,
+- "Data will not fit on any disk.\n");
+- goto toolarge;
++ if (endsec >= (2300000)) {
++ errmsgno(EX_BAD,
++ "ERROR: Could not manage to find medium size, and more than 4.3 GB of data.\n");
++ goto toolarge;
++ } else if (endsec >= (405000-300)) { /*<90 min disk or DVD*/
++ errmsgno(EX_BAD,
++ "WARNING: Could not manage to find medium size, and more than 90 mins of data.\n");
+ } else if (endsec >= (333000-150)) { /* 74 min disk*/
+ errmsgno(EX_BAD,
+ "WARNING: Data may not fit on standard 74min disk.\n");
+@@ -3046,7 +3123,7 @@
+ }
+
+ char *opts =
+-"help,version,checkdrive,prcap,inq,scanbus,reset,abort,overburn,ignsize,useinfo,dev*,timeout#,driver*,driveropts*,setdropts,tsize&,padsize&,pregap&,defpregap&,speed#,load,lock,eject,dummy,msinfo,toc,atip,multi,fix,nofix,waiti,immed,debug#,d+,kdebug#,kd#,verbose+,v+,Verbose+,V+,x+,xd#,silent,s,audio,data,mode2,xa,xa1,xa2,xamix,cdi,isosize,nopreemp,preemp,nocopy,copy,nopad,pad,swab,fs&,ts&,blank&,format,pktsize#,packet,noclose,force,tao,dao,sao,raw,raw96r,raw96p,raw16,clone,scms,isrc*,mcn*,index*,cuefile*,textfile*,text,shorttrack,noshorttrack,gracetime#,minbuf#";
++"help,version,checkdrive,prcap,inq,scanbus,reset,abort,overburn,ignsize,useinfo,dev*,timeout#,driver*,driveropts*,setdropts,tsize&,padsize&,pregap&,defpregap&,speed#,load,lock,eject,dummy,msinfo,toc,atip,multi,fix,nofix,waiti,immed,debug#,d+,kdebug#,kd#,verbose+,v+,Verbose+,V+,x+,xd#,silent,s,audio,data,mode2,xa,xa1,xa2,xamix,cdi,isosize,nopreemp,preemp,nocopy,copy,nopad,pad,swab,fs&,ts&,blank&,format,formattype&,pktsize#,packet,noclose,force,tao,dao,sao,raw,raw96r,raw96p,raw16,clone,scms,isrc*,mcn*,index*,cuefile*,textfile*,text,shorttrack,noshorttrack,gracetime#,minbuf#";
+
+ /*
+ * Defines used to find whether a write mode has been specified.
+@@ -3056,8 +3133,8 @@
+ #define M_RAW 4 /* Raw mode */
+ #define M_PACKET 8 /* Packed mode */
+
+-LOCAL void
+-gargs(ac, av, tracksp, trackp, devp, timeoutp, dpp, speedp, flagsp, blankp)
++LOCAL int
++gargs(ac, av, tracksp, trackp, devp, timeoutp, dpp, speedp, flagsp, blankp, formatp)
+ int ac;
+ char **av;
+ int *tracksp;
+@@ -3068,6 +3145,7 @@
+ int *speedp;
+ long *flagsp;
+ int *blankp;
++ int *formatp;
+ {
+ int cac;
+ char * const*cav;
+@@ -3080,6 +3158,7 @@
+ char *textfile = NULL;
+ long bltype = -1;
+ int doformat = 0;
++ int formattype = -1;
+ Llong tracksize;
+ Llong padsize;
+ long pregapsize;
+@@ -3195,7 +3274,7 @@
+ &nopreemp, &preemp,
+ &nocopy, ©,
+ &nopad, &pad, &bswab, getnum, &fs, getnum, &bufsize,
+- getbltype, &bltype, &doformat, &pktsize,
++ getbltype, &bltype, &doformat, getformattype, &formattype, &pktsize,
+ &ispacket, &noclose, &force,
+ &tao, &dao, &dao, &raw, &raw96r, &raw96p, &raw16,
+ &clone,
+@@ -3276,8 +3355,14 @@
+ *flagsp |= F_BLANK;
+ *blankp = bltype;
+ }
+- if (doformat)
+- *flagsp |= F_FORMAT;
++ if (doformat > 0) {
++ *flagsp |= F_FORMAT;
++ *formatp |= FULL_FORMAT;
++ }
++ if (formattype >= 0) {
++ *flagsp |= F_FORMAT;
++ *formatp |= formattype;
++ }
+ if (ispacket)
+ wm |= M_PACKET;
+ if (tao)
+@@ -3724,14 +3809,14 @@
+ ((strncmp(*devp, "HELP", 4) == 0) ||
+ (strncmp(*devp, "help", 4) == 0))) {
+ *flagsp |= F_CHECKDRIVE; /* Set this for not calling mlockall() */
+- return;
++ return ispacket;
+ }
+ if (*flagsp & (F_LOAD|F_DLCK|F_SETDROPTS|F_MSINFO|F_TOC|F_PRATIP|F_FIX|F_VERSION|F_CHECKDRIVE|F_PRCAP|F_INQUIRY|F_SCANBUS|F_RESET|F_ABORT)) {
+ if (tracks != 0) {
+ errmsgno(EX_BAD, "No tracks allowed with this option\n");
+ susage(EX_BAD);
+ }
+- return;
++ return ispacket;
+ }
+ *tracksp = tracks;
+ if (*flagsp & F_SAO) {
+@@ -3760,12 +3845,13 @@
+ susage(EX_BAD);
+ }
+ cuefilename = cuefile;
+- return;
++ return ispacket;
+ }
+ if (tracks == 0 && (*flagsp & (F_LOAD|F_DLCK|F_EJECT|F_BLANK|F_FORMAT)) == 0) {
+ errmsgno(EX_BAD, "No tracks specified. Need at least one.\n");
+ susage(EX_BAD);
+ }
++ return ispacket;
+ }
+
+ LOCAL void
+@@ -4437,6 +4523,26 @@
+ return (TRUE);
+ }
+
++LOCAL int
++getformattype(optstr, typep)
++ char *optstr;
++ long *typep;
++{
++ if (streql(optstr, "full")) {
++ *typep = FULL_FORMAT;
++ } else if (streql(optstr, "background")) {
++ *typep = BACKGROUND_FORMAT;
++ } else if (streql(optstr, "force")) {
++ *typep = FORCE_FORMAT;
++ } else if (streql(optstr, "help")) {
++ formattypeusage(0);
++ } else {
++ error("Illegal blanking type '%s'.\n", optstr);
++ formattypeusage(EX_BAD);
++ return (-1);
++ }
++ return (TRUE);
++}
+ LOCAL void
+ print_drflags(dp)
+ cdr_t *dp;
+--- cdrtools-2.01/cdrecord/scsi_cdr.c.dvd 2004-05-25 00:36:01.000000000 +0200
++++ cdrtools-2.01/cdrecord/scsi_cdr.c 2004-10-18 14:37:32.439249741 +0200
+@@ -107,6 +107,8 @@
+ EXPORT int send_cue_sheet __PR((SCSI *scgp, caddr_t bp, long size));
+ EXPORT int read_buff_cap __PR((SCSI *scgp, long *, long *));
+ EXPORT int scsi_blank __PR((SCSI *scgp, long addr, int blanktype, BOOL immed));
++EXPORT int scsi_format __PR((SCSI *scgp, caddr_t addr, int size, BOOL background));
++EXPORT int scsi_set_streaming __PR((SCSI *scgp, caddr_t addr, int size));
+ EXPORT BOOL allow_atapi __PR((SCSI *scgp, BOOL new));
+ EXPORT int mode_select __PR((SCSI *scgp, Uchar *, int, int, int));
+ EXPORT int mode_sense __PR((SCSI *scgp, Uchar *dp, int cnt, int page, int pcf));
+@@ -519,6 +521,32 @@
+ }
+
+ EXPORT int
++scsi_set_streaming(scgp, perf_desc, size)
++ SCSI *scgp;
++ caddr_t perf_desc;
++ int size;
++{
++ register struct scg_cmd *scmd = scgp->scmd;
++
++ fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
++ scmd->addr = perf_desc;
++ scmd->size = size;
++ scmd->flags = SCG_DISRE_ENA;
++ scmd->cdb_len = SC_G5_CDBLEN;
++ scmd->sense_len = CCS_SENSE_LEN;
++ scmd->cdb.g5_cdb.cmd = 0xB6;
++ scmd->cdb.cmd_cdb[11] = 0;
++ scmd->cdb.cmd_cdb[10] = size;
++
++ scgp->cmdname = "set streaming";
++
++ printf("scsi_set_streaming\n");
++ if (scg_cmd(scgp) < 0)
++ return (-1);
++ return (0);
++}
++
++EXPORT int
+ scsi_set_speed(scgp, readspeed, writespeed, rotctl)
+ SCSI *scgp;
+ int readspeed;
+@@ -1042,6 +1070,32 @@
+ return (0);
+ }
+
++
++EXPORT int
++reserve_track(scgp, size)
++ SCSI *scgp;
++ Ulong size;
++
++{
++ register struct scg_cmd *scmd = scgp->scmd;
++
++ fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
++ scmd->flags = SCG_DISRE_ENA;
++ scmd->cdb_len = SC_G1_CDBLEN;
++ scmd->sense_len = CCS_SENSE_LEN;
++ scmd->cdb.g1_cdb.cmd = 0x53;
++ scmd->cdb.g1_cdb.lun = scg_lun(scgp);
++ i_to_4_byte(&scmd->cdb.g1_cdb.addr[3], size);
++
++ scgp->cmdname = "reserve track";
++
++ if (scg_cmd(scgp) < 0)
++ return (-1);
++
++ return (0);
++
++}
++
+ EXPORT int
+ read_rzone_info(scgp, bp, cnt)
+ SCSI *scgp;
+@@ -1323,6 +1377,69 @@
+ return (scg_cmd(scgp));
+ }
+
++EXPORT int
++scsi_format(scgp, addr, size, background)
++ SCSI *scgp;
++ caddr_t addr;
++ int size;
++ BOOL background;
++{
++ register struct scg_cmd *scmd = scgp->scmd;
++ int progress=0, ret=-1, pid=-1;
++ unsigned char sense_table[18];
++ int i;
++
++ printf("scsi_format: preparing\n");
++
++ fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
++ scmd->addr = addr;
++ scmd->size = size;
++ scmd->flags = SCG_DISRE_ENA;
++ scmd->cdb_len = SC_G5_CDBLEN;
++ scmd->sense_len = CCS_SENSE_LEN;
++ scmd->timeout = 160 * 60; /* Do not know what to set */
++ scmd->cdb.g5_cdb.cmd = 0x04; /* Format Unit */
++ scmd->cdb.cmd_cdb[1] = 0x11; /* "FmtData" and "Format Code" */
++ scmd->cdb.cmd_cdb[5] = 0;
++
++ scgp->cmdname = "format unit";
++
++ printf("scsi_format: running\n");
++ ret = (scg_cmd(scgp));
++ printf("scsi_format: post processing %d\n", ret);
++ if (ret == -1) return ret;
++ if (background) {
++ if ((pid=fork()) == (pid_t)-1)
++ perror ("- [unable to fork()]");
++ else {
++ if (!pid) {
++ while (1) {
++ if (test_unit_ready(scgp) >= 0)
++ break;
++ sleep(1);
++ }
++ return ret;
++ }
++ }
++ }
++ printf("Formating in progress: 0.00 %% done.");
++ sleep(20);
++ while (progress < 0xfff0) {
++ test_unit_ready(scgp);
++ request_sense_b(scgp, (caddr_t)sense_table, 18);
++ progress = sense_table[16]<<8|sense_table[17];
++ printf("\rFormating in progress: %.2f %% done [%d]. ", (float)(progress*100)/0x10000,progress);
++ usleep(10000);
++ /*for (i=0; i < 18; i++) {
++ printf("%d ", sense_table[i]);
++ }*/
++ }
++ sleep(10);
++ printf("\rFormating in progress: 100.00 %% done. \n");
++ if (pid) exit (0);
++ return ret;
++}
++
+ /*
+ * XXX First try to handle ATAPI:
+ * XXX ATAPI cannot handle SCSI 6 byte commands.
+--- cdrtools-2.01/libscg/scsitransp.c.dvd 2004-06-17 22:20:27.000000000 +0200
++++ cdrtools-2.01/libscg/scsitransp.c 2004-10-18 14:37:32.424251905 +0200
+@@ -108,6 +108,7 @@
+ EXPORT int scg_sense_key __PR((SCSI *scgp));
+ EXPORT int scg_sense_code __PR((SCSI *scgp));
+ EXPORT int scg_sense_qual __PR((SCSI *scgp));
++EXPORT unsigned char *scg_sense_table __PR((SCSI *scgp));
+ EXPORT void scg_fprintdev __PR((FILE *, struct scsi_inquiry *));
+ EXPORT void scg_printdev __PR((struct scsi_inquiry *));
+ EXPORT int scg_printf __PR((SCSI *scgp, const char *form, ...));
+@@ -1240,6 +1241,23 @@
+ }
+
+ /*
++ * Return all the SCSI sense table last command.
++ */
++EXPORT unsigned char *
++scg_sense_table(scgp)
++ SCSI *scgp;
++{
++ register struct scg_cmd *cp = scgp->scmd;
++
++ if(!scg_cmd_err(scgp))
++ return (0);
++
++ if (cp->sense.code >= 0x70)
++ return &(cp->sense);
++ return (0);
++}
++
++/*
+ * Return the SCSI sense code for last command.
+ */
+ EXPORT int
--- /dev/null
+diff -urN --exclude-from=- cdrtools-2.01/include/unls.h cdrtools-2.01-jh/include/unls.h
+--- cdrtools-2.01/include/unls.h 2003-06-16 00:41:23.000000000 +0300
++++ cdrtools-2.01-jh/include/unls.h 2004-02-02 18:31:22.000000000 +0200
+@@ -30,6 +30,10 @@
+ #include <prototyp.h>
+ #endif
+
++#ifdef USE_ICONV
++#include <iconv.h>
++#endif
++
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+@@ -43,6 +47,9 @@
+ char *charset;
+ unsigned char **page_uni2charset;
+ struct nls_unicode *charset2uni;
++#ifdef USE_ICONV
++ iconv_t iconv_d;
++#endif
+
+ void (*inc_use_count) __PR((void));
+ void (*dec_use_count) __PR((void));
+@@ -58,6 +65,9 @@
+ extern void unload_nls __PR((struct nls_table *));
+ extern struct nls_table *load_nls_default __PR((void));
+ extern int init_nls_file __PR((char * name));
++#ifdef USE_ICONV
++extern int init_nls_iconv __PR((char * name));
++#endif
+
+ #ifdef __cplusplus
+ }
+diff -urN --exclude-from=- cdrtools-2.01/libunls/libunls.mk cdrtools-2.01-jh/libunls/libunls.mk
+--- cdrtools-2.01/libunls/libunls.mk 2000-03-25 14:51:56.000000000 +0200
++++ cdrtools-2.01-jh/libunls/libunls.mk 2004-02-02 18:31:22.000000000 +0200
+@@ -8,6 +8,7 @@
+ INSDIR= lib
+ TARGETLIB= unls
+ #CPPOPTS += -Istdio
++CPPOPTS += -DUSE_ICONV
+ include Targets
+ LIBS=
+
+diff -urN --exclude-from=- cdrtools-2.01/libunls/nls.h cdrtools-2.01-jh/libunls/nls.h
+--- cdrtools-2.01/libunls/nls.h 2002-12-03 02:34:27.000000000 +0200
++++ cdrtools-2.01-jh/libunls/nls.h 2004-02-02 18:31:22.000000000 +0200
+@@ -111,5 +111,8 @@
+ extern int init_nls_cp10079 __PR((void));
+ extern int init_nls_cp10081 __PR((void));
+ extern int init_nls_file __PR((char * name));
++#ifdef USE_ICONV
++extern int init_nls_iconv __PR((char * name));
++#endif
+
+ #endif /* _NLS_H */
+diff -urN --exclude-from=- cdrtools-2.01/libunls/nls_iconv.c cdrtools-2.01-jh/libunls/nls_iconv.c
+--- cdrtools-2.01/libunls/nls_iconv.c 1970-01-01 02:00:00.000000000 +0200
++++ cdrtools-2.01-jh/libunls/nls_iconv.c 2004-02-02 18:31:22.000000000 +0200
+@@ -0,0 +1,96 @@
++/* @(#)nls_iconv.c 1.0 02/04/20 2002 J. Schilling */
++#ifndef lint
++static char sccsid[] =
++ "@(#)nls_iconv.c 1.0 02/01/20 2002 J. Schilling";
++#endif
++/*
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING. If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++/*
++ * Modifications to make the code portable Copyright (c) 2000 J. Schilling
++ *
++ * nls_iconv: create a pseudo-charset table to use iconv() provided by C
++ * library or libiconv by Bruno Haible
++ * The Unicode to charset table has only exact mappings.
++ *
++ *
++ * Jungshik Shin (jshin@mailaps.org) 04-Feb-2002
++ */
++
++#ifdef USE_ICONV
++#include <mconfig.h>
++#include <stdio.h>
++#include <stdxlib.h>
++#include <strdefs.h>
++#include "nls.h"
++#include <iconv.h>
++
++static void inc_use_count __PR((void));
++static void dec_use_count __PR((void));
++
++
++static void
++inc_use_count()
++{
++ MOD_INC_USE_COUNT;
++}
++
++static void
++dec_use_count()
++{
++ MOD_DEC_USE_COUNT;
++}
++
++int
++init_nls_iconv(charset)
++ char *charset;
++{
++ iconv_t iconv_d; /* iconv conversion descriptor */
++ struct nls_table *table;
++
++ /* give up if no charset is given */
++ if (charset == NULL)
++ return -1;
++
++ /* see if we already have a table with this name - built in tables
++ have precedence over iconv() - i.e. can't have the name of an
++ existing table. Also, we may have already registered this file
++ table */
++ if (find_nls(charset) != NULL)
++ return -1;
++
++ if ((iconv_d = iconv_open("UCS-2BE", charset)) == (iconv_t) -1)
++ return -1;
++
++
++ /* set up the table */
++ if ((table = (struct nls_table *)malloc(sizeof (struct nls_table)))
++ == NULL) {
++ return -1;
++ }
++
++ /* give the table the file name, so we can find it again if needed */
++ table->charset = strdup(charset);
++ table->iconv_d = iconv_d;
++ table->page_uni2charset = NULL;
++ table->charset2uni = NULL;
++ table->inc_use_count = inc_use_count;
++ table->dec_use_count = dec_use_count;
++ table->next = NULL;
++
++ /* register the table */
++ return register_nls(table);
++}
++#endif
+diff -urN --exclude-from=- cdrtools-2.01/libunls/Targets cdrtools-2.01-jh/libunls/Targets
+--- cdrtools-2.01/libunls/Targets 2002-12-03 02:34:27.000000000 +0200
++++ cdrtools-2.01-jh/libunls/Targets 2004-02-02 18:31:22.000000000 +0200
+@@ -39,4 +39,5 @@
+ nls_cp10029.c \
+ nls_cp10079.c \
+ nls_cp10081.c \
+- nls_file.c
++ nls_file.c \
++ nls_iconv.c
+diff -urN --exclude-from=- cdrtools-2.01/mkisofs/joliet.c cdrtools-2.01-jh/mkisofs/joliet.c
+--- cdrtools-2.01/mkisofs/joliet.c 2003-04-28 01:36:08.000000000 +0300
++++ cdrtools-2.01-jh/mkisofs/joliet.c 2004-02-03 14:15:17.000000000 +0200
+@@ -90,6 +90,11 @@
+ #include <unls.h> /* For UNICODE translation */
+ #include <schily.h>
+
++#ifdef USE_ICONV
++#include <iconv.h>
++#include <errno.h>
++#endif
++
+ static Uint jpath_table_index;
+ static struct directory **jpathlist;
+ static int next_jpath_index = 1;
+@@ -103,13 +108,23 @@
+ };
+
+ #ifdef UDF
+- void convert_to_unicode __PR((unsigned char *buffer,
++# ifdef USE_ICONV
++ size_t
++# else
++ void
++# endif
++ convert_to_unicode __PR((unsigned char *buffer,
+ int size, char *source, struct nls_table *inls));
+- int joliet_strlen __PR((const char *string));
++ int joliet_strlen __PR((const char *string, struct nls_table *inls));
+ #else
+-static void convert_to_unicode __PR((unsigned char *buffer,
++# ifdef USE_ICONV
++ static size_t
++# else
++ static void
++#endif
++ convert_to_unicode __PR((unsigned char *buffer,
+ int size, char *source, struct nls_table *inls));
+-static int joliet_strlen __PR((const char *string));
++static int joliet_strlen __PR((const char *string, struct nls_table *inls));
+ #endif
+ static void get_joliet_vol_desc __PR((struct iso_primary_descriptor *jvol_desc));
+ static void assign_joliet_directory_addresses __PR((struct directory *node));
+@@ -161,6 +176,20 @@
+ if (inls == onls)
+ return (c);
+
++#ifdef USE_ICONV
++ if(inls->charset2uni == NULL || onls->page_uni2charset == NULL) {
++ /*
++ * This shouldn't be reached
++ */
++ static BOOL iconv_warned = FALSE;
++ if(!iconv_warned) {
++ error("Warning: Iconv conversion not supported in conv_charset.\n");
++ iconv_warned = TRUE;
++ }
++ return (c);
++ }
++#endif
++
+ /* get high and low UNICODE bytes */
+ uh = inls->charset2uni[c].uni2;
+ ul = inls->charset2uni[c].uni1;
+@@ -186,10 +215,18 @@
+ *
+ * Notes:
+ */
+-#ifdef UDF
+-void
++#ifdef USE_ICONV
++# if UDF
++size_t
++# else
++static size_t
++# endif
+ #else
++# if UDF
++void
++# else
+ static void
++# endif
+ #endif
+ convert_to_unicode(buffer, size, source, inls)
+ unsigned char *buffer;
+@@ -216,6 +253,51 @@
+ tmpbuf = (Uchar *) source;
+ }
+
++#ifdef USE_ICONV
++ if (inls->iconv_d && inls->charset2uni==NULL &&
++ inls->page_uni2charset==NULL) {
++ char *inptr = tmpbuf;
++ char *outptr = buffer;
++ size_t inleft = strlen(tmpbuf);
++ size_t inlen = inleft;
++ size_t outleft = size;
++
++ iconv(inls->iconv_d, NULL, NULL, NULL, NULL);
++ if(iconv(inls->iconv_d, &inptr, &inleft, &outptr, &outleft) ==
++ (size_t)-1 && errno == EILSEQ) {
++ fprintf(stderr, "Incorrectly encoded string (%s) "
++ "encountered.\nPossibly creating an invalid "
++ "Joliet extension. Aborting.\n", source);
++ exit(1);
++ }
++
++ for (i = 0; (i + 1) < size - outleft; i += 2) { /* Size may be odd!!!*/
++ if (buffer[i]=='\0') {
++ switch (buffer[i+1]) { /* Invalid characters for Joliet */
++ case '*':
++ case '/':
++ case ':':
++ case ';':
++ case '?':
++ case '\\':
++ buffer[i+1]='_';
++ default:
++ if (buffer[i+1] == 0x7f ||
++ buffer[i+1] < 0x20)
++ buffer[i+1]='_';
++ }
++ }
++ }
++ if (size & 1) { /* beautification */
++ buffer[size - 1] = 0;
++ }
++ if (source == NULL) {
++ free(tmpbuf);
++ }
++ return (inlen - inleft);
++ }
++#endif
++
+ /*
+ * Now start copying characters. If the size was specified to be 0,
+ * then assume the input was 0 terminated.
+@@ -271,6 +353,9 @@
+ if (source == NULL) {
+ free(tmpbuf);
+ }
++#ifdef USE_ICONV
++ return j;
++#endif
+ }
+
+ /*
+@@ -287,12 +372,50 @@
+ #else
+ static int
+ #endif
+-joliet_strlen(string)
++joliet_strlen(string, inls)
+ const char *string;
++ struct nls_table *inls;
+ {
+ int rtn;
+
++#ifdef USE_ICONV
++ if (inls->iconv_d && inls->charset2uni==NULL &&
++ inls->page_uni2charset==NULL) {
++ /*
++ * we const-cast since we're sure iconv won't change
++ * the string itself
++ */
++ char *string_ptr = (char *)string;
++ size_t string_len = strlen(string);
++
++ /*
++ * iconv has no way of finding out the required size
++ * in the target
++ */
++
++ char *tmp, *tmp_ptr;
++ /* we assume that the maximum length is 2 * jlen */
++ size_t tmp_len = (size_t)jlen * 2 + 1;
++ tmp = e_malloc(tmp_len);
++ tmp_ptr = tmp;
++
++ iconv(inls->iconv_d, NULL, NULL, NULL, NULL);
++ iconv(inls->iconv_d, &string_ptr, &string_len, &tmp_ptr,
++ &tmp_len);
++
++ /*
++ * iconv advanced the tmp pointer with as many chars
++ * as it has written to it, so we add up the delta
++ */
++ rtn = (tmp_ptr - tmp);
++
++ free(tmp);
++ } else {
++ rtn = strlen(string) << 1;
++ }
++#else
+ rtn = strlen(string) << 1;
++#endif
+
+ /*
+ * We do clamp the maximum length of a Joliet string to be the
+@@ -480,16 +603,33 @@
+ /* compare the Unicode names */
+
+ while (*rpnt && *lpnt) {
++#ifdef USE_ICONV
++ size_t ri, li;
++
++ ri = convert_to_unicode(rtmp, 2, rpnt, rinls);
++ li = convert_to_unicode(ltmp, 2, lpnt, linls);
++ rpnt += ri;
++ lpnt += li;
++ if(!ri && !li)
++ return (0);
++ else if(ri && !li)
++ return (1);
++ else if(!ri && li)
++ return (-1);
++#else
+ convert_to_unicode(rtmp, 2, rpnt, rinls);
+ convert_to_unicode(ltmp, 2, lpnt, linls);
++#endif
+
+ if (a_to_u_2_byte(rtmp) < a_to_u_2_byte(ltmp))
+ return (-1);
+ if (a_to_u_2_byte(rtmp) > a_to_u_2_byte(ltmp))
+ return (1);
+
++#ifndef USE_ICONV
+ rpnt++;
+ lpnt++;
++#endif
+ }
+
+ if (*rpnt)
+@@ -574,10 +714,10 @@
+ }
+ #ifdef APPLE_HYB
+ if (USE_MAC_NAME(de))
+- namelen = joliet_strlen(de->hfs_ent->name);
++ namelen = joliet_strlen(de->hfs_ent->name, hfs_inls);
+ else
+ #endif /* APPLE_HYB */
+- namelen = joliet_strlen(de->name);
++ namelen = joliet_strlen(de->name, in_nls);
+
+ if (dpnt == root) {
+ jpath_table_l[jpath_table_index] = 1;
+@@ -742,10 +882,10 @@
+ #ifdef APPLE_HYB
+ /* Use the HFS name if it exists */
+ if (USE_MAC_NAME(s_entry1))
+- cvt_len = joliet_strlen(s_entry1->hfs_ent->name);
++ cvt_len = joliet_strlen(s_entry1->hfs_ent->name, hfs_inls);
+ else
+ #endif /* APPLE_HYB */
+- cvt_len = joliet_strlen(s_entry1->name);
++ cvt_len = joliet_strlen(s_entry1->name, in_nls);
+
+ /*
+ * Fix the record length
+@@ -891,12 +1031,12 @@
+ if (USE_MAC_NAME(s_entry))
+ /* Use the HFS name if it exists */
+ jpath_table_size +=
+- joliet_strlen(s_entry->hfs_ent->name) +
++ joliet_strlen(s_entry->hfs_ent->name, hfs_inls) +
+ offsetof(struct iso_path_table, name[0]);
+ else
+ #endif /* APPLE_HYB */
+ jpath_table_size +=
+- joliet_strlen(s_entry->name) +
++ joliet_strlen(s_entry->name, in_nls) +
+ offsetof(struct iso_path_table, name[0]);
+ if (jpath_table_size & 1) {
+ jpath_table_size++;
+@@ -918,13 +1058,13 @@
+ /* Use the HFS name if it exists */
+ s_entry->jreclen =
+ offsetof(struct iso_directory_record, name[0])
+- + joliet_strlen(s_entry->hfs_ent->name)
++ + joliet_strlen(s_entry->hfs_ent->name, hfs_inls)
+ + 1;
+ else
+ #endif /* APPLE_HYB */
+ s_entry->jreclen =
+ offsetof(struct iso_directory_record, name[0])
+- + joliet_strlen(s_entry->name)
++ + joliet_strlen(s_entry->name, in_nls)
+ + 1;
+ } else {
+ /*
+@@ -1072,6 +1212,9 @@
+ #endif
+
+ while (*rpnt && *lpnt) {
++#ifdef USE_ICONV
++ size_t ri, li;
++#endif
+ if (*rpnt == ';' && *lpnt != ';')
+ return (-1);
+ if (*rpnt != ';' && *lpnt == ';')
+@@ -1092,16 +1235,32 @@
+ return (1);
+ #endif
+
++#ifdef USE_ICONV
++
++ ri = convert_to_unicode(rtmp, 2, rpnt, rinls);
++ li = convert_to_unicode(ltmp, 2, lpnt, linls);
++ rpnt += ri;
++ lpnt += li;
++ if(!ri && !li)
++ return (0);
++ else if(ri && !li)
++ return (1);
++ else if(!ri && li)
++ return (-1);
++#else
+ convert_to_unicode(rtmp, 2, rpnt, rinls);
+ convert_to_unicode(ltmp, 2, lpnt, linls);
++#endif
+
+ if (a_to_u_2_byte(rtmp) < a_to_u_2_byte(ltmp))
+ return (-1);
+ if (a_to_u_2_byte(rtmp) > a_to_u_2_byte(ltmp))
+ return (1);
+
++#ifndef USE_ICONV
+ rpnt++;
+ lpnt++;
++#endif
+ }
+ if (*rpnt)
+ return (1);
+diff -urN --exclude-from=- cdrtools-2.01/mkisofs/Makefile cdrtools-2.01-jh/mkisofs/Makefile
+--- cdrtools-2.01/mkisofs/Makefile 2004-01-02 17:23:32.000000000 +0200
++++ cdrtools-2.01-jh/mkisofs/Makefile 2004-02-02 18:31:22.000000000 +0200
+@@ -32,6 +32,7 @@
+ CPPOPTS += -DUDF
+ CPPOPTS += -DDVD_VIDEO
+ CPPOPTS += -DSORTING
++CPPOPTS += -DUSE_ICONV
+ CPPOPTS += -I../libhfs_iso/
+ CPPOPTS += -DHAVE_CONFIG_H -DUSE_LIBSCHILY -DUSE_SCG \
+ '-DAPPID_DEFAULT="MKISOFS ISO 9660/HFS FILESYSTEM BUILDER & CDRECORD CD-R/DVD CREATOR (C) 1993 E.YOUNGDALE (C) 1997 J.PEARSON/J.SCHILLING"' \
+diff -urN --exclude-from=- cdrtools-2.01/mkisofs/mkisofs.c cdrtools-2.01-jh/mkisofs/mkisofs.c
+--- cdrtools-2.01/mkisofs/mkisofs.c 2004-01-07 01:23:46.000000000 +0200
++++ cdrtools-2.01-jh/mkisofs/mkisofs.c 2004-02-02 18:31:22.000000000 +0200
+@@ -59,6 +59,11 @@
+ #endif
+ #endif /* no_more_needed */
+
++#ifdef USE_ICONV
++#include <locale.h>
++#include <langinfo.h>
++#endif
++
+ struct directory *root = NULL;
+ int path_ind;
+
+@@ -223,6 +228,10 @@
+ int do_sort = 0; /* sort file data */
+ #endif /* SORTING */
+
++#ifdef USE_ICONV
++int iconv_possible;
++#endif
++
+ struct nls_table *in_nls = NULL; /* input UNICODE conversion table */
+ struct nls_table *out_nls = NULL; /* output UNICODE conversion table */
+ #ifdef APPLE_HYB
+@@ -2235,6 +2244,37 @@
+ init_nls_file(hfs_ocharset);
+ #endif /* APPLE_HYB */
+
++#ifdef USE_ICONV
++ iconv_possible = !(iso9660_level >= 4 || ((ocharset &&
++ strcmp(ocharset, icharset ? icharset : "")) &&
++ use_RockRidge) || apple_ext || apple_hyb);
++
++ setlocale(LC_CTYPE, "");
++
++ if (icharset == NULL && iconv_possible) {
++ char *charset = nl_langinfo(CODESET);
++ /* set to detected value but only if it is not pure US-ASCII */
++ if(strcmp(charset, "ANSI_X3.4-1968") != 0)
++ icharset = charset;
++
++ if(icharset && verbose > 0)
++ fprintf(stderr, "INFO:\t"
++ "%s character encoding detected by locale settings."
++ "\n\tAssuming %s encoded filenames on source "
++ "filesystem,\n"
++ "\tuse -input-charset to override.\n",
++ icharset, icharset);
++ }
++
++ if(iconv_possible) {
++ /*
++ * don't care if initialization fails
++ */
++ init_nls_iconv(icharset);
++ init_nls_iconv(ocharset);
++ }
++#endif
++
+ if (icharset == NULL) {
+ #if (defined(__CYGWIN32__) || defined(__CYGWIN__)) && !defined(IS_CYGWIN_1)
+ in_nls = load_nls("cp437");
+@@ -2262,6 +2302,12 @@
+ if (in_nls == NULL || out_nls == NULL) { /* Unknown charset specified */
+ fprintf(stderr, "Unknown charset\nKnown charsets are:\n");
+ list_nls(); /* List all known charset names */
++#ifdef USE_ICONV
++ if(!iconv_possible)
++ fprintf(stderr, "Iconv charsets cannot be used with "
++ "Apple extension, HFS, ISO9660 version 2 or\n"
++ "Rock Ridge.\n");
++#endif
+ exit(1);
+ }
+
+diff -urN --exclude-from=- cdrtools-2.01/mkisofs/mkisofs.h cdrtools-2.01-jh/mkisofs/mkisofs.h
+--- cdrtools-2.01/mkisofs/mkisofs.h 2003-12-28 15:38:51.000000000 +0200
++++ cdrtools-2.01-jh/mkisofs/mkisofs.h 2004-02-02 18:31:22.000000000 +0200
+@@ -501,9 +501,14 @@
+
+ /* joliet.c */
+ #ifdef UDF
++# ifdef USE_ICONV
++extern size_t convert_to_unicode __PR((unsigned char *buffer,
++ int size, char *source, struct nls_table *inls));
++# else
+ extern void convert_to_unicode __PR((unsigned char *buffer,
+ int size, char *source, struct nls_table *inls));
+-extern int joliet_strlen __PR((const char *string));
++# endif
++extern int joliet_strlen __PR((const char *string, struct nls_table *inls));
+ #endif
+ extern unsigned char conv_charset __PR((unsigned char, struct nls_table *,
+ struct nls_table *));
+diff -urN --exclude-from=- cdrtools-2.01/mkisofs/udf.c cdrtools-2.01-jh/mkisofs/udf.c
+--- cdrtools-2.01/mkisofs/udf.c 2003-04-28 01:34:52.000000000 +0300
++++ cdrtools-2.01-jh/mkisofs/udf.c 2004-02-02 18:31:22.000000000 +0200
+@@ -442,7 +442,7 @@
+ int i;
+ int expanded_length;
+
+- expanded_length = joliet_strlen(src);
++ expanded_length = joliet_strlen(src, in_nls);
+ if (expanded_length > 1024)
+ expanded_length = 1024;
+ if (expanded_length > (dst_size-1)*2)
--- /dev/null
+--- cdrtools-2.01/libscg/scsi-linux-sg.c.scan 2004-09-22 12:57:24.313986568 +0200
++++ cdrtools-2.01/libscg/scsi-linux-sg.c 2004-09-22 12:57:24.327984440 +0200
+@@ -287,6 +287,8 @@
+ return (0);
+ }
+
++#include <glob.h>
++
+ LOCAL int
+ scgo_open(scgp, device)
+ SCSI *scgp;
+@@ -301,8 +303,9 @@
+ register int t;
+ register int l;
+ register int nopen = 0;
+- char devname[64];
+- BOOL use_ata = FALSE;
++ char *devname;
++ BOOL use_ata = FALSE;
++ glob_t globbuf;
+
+ if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
+ errno = EINVAL;
+@@ -383,103 +386,91 @@
+ * look silly but there may be users that did boot from a SCSI hdd
+ * and connected 4 CD/DVD writers to both IDE cables in the PC.
+ */
+- if (use_ata) for (i = 0; i <= 25; i++) {
+- js_snprintf(devname, sizeof (devname), "/dev/hd%c", i+'a');
+- /* O_NONBLOCK is dangerous */
+- f = open(devname, O_RDWR | O_NONBLOCK);
+- if (f < 0) {
+- /*
+- * Set up error string but let us clear it later
+- * if at least one open succeeded.
+- */
+- if (scgp->errstr)
+- js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
+- "Cannot open '/dev/hd*'");
+- if (errno != ENOENT && errno != ENXIO && errno != ENODEV) {
++ if (use_ata) {
++ glob("/dev/hd[a-z]", GLOB_NOSORT, NULL, &globbuf);
++
++ for (i = 0; globbuf.gl_pathv && globbuf.gl_pathv[i] != NULL ; i++) {
++ devname = globbuf.gl_pathv[i];
++ f = open(devname, O_RDWR | O_NONBLOCK);
++ if (f < 0) {
++ /*
++ * Set up error string but let us clear it later
++ * if at least one open succeeded.
++ */
+ if (scgp->errstr)
+ js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
+- "Cannot open '%s'", devname);
+- return (0);
+- }
+- } else {
+- int iparm;
+-
+- if (ioctl(f, SG_GET_TIMEOUT, &iparm) < 0) {
+- if (scgp->errstr)
+- js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
+- "SCSI unsupported with '/dev/hd*'");
+- close(f);
+- continue;
++ "Cannot open '/dev/hd*'");
++ if (errno != ENOENT && errno != ENXIO && errno != ENODEV && errno != EACCES) {
++ if (scgp->errstr)
++ js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
++ "Cannot open '%s'", devname);
++ globfree(&globbuf);
++ return (0);
++ }
++ } else {
++ int iparm;
++
++ if (ioctl(f, SG_GET_TIMEOUT, &iparm) < 0) {
++ if (scgp->errstr)
++ js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
++ "SCSI unsupported with '/dev/hd*'");
++ close(f);
++ continue;
++ }
++ sg_clearnblock(f); /* Be very proper about this */
++ if (sg_setup(scgp, f, busno, tgt, tlun, devname[7]-'a')) {
++ globfree(&globbuf);
++ return (++nopen);
++ }
++ if (busno < 0 && tgt < 0 && tlun < 0)
++ nopen++;
+ }
+- sg_clearnblock(f); /* Be very proper about this */
+- if (sg_setup(scgp, f, busno, tgt, tlun, i))
+- return (++nopen);
+- if (busno < 0 && tgt < 0 && tlun < 0)
+- nopen++;
+ }
++ globfree(&globbuf);
+ }
+ if (use_ata && nopen == 0)
+ return (0);
+ if (nopen > 0 && scgp->errstr)
+ scgp->errstr[0] = '\0';
+
+- if (nopen == 0) for (i = 0; i < 32; i++) {
+- js_snprintf(devname, sizeof (devname), "/dev/sg%d", i);
+- /* O_NONBLOCK is dangerous */
+- f = open(devname, O_RDWR | O_NONBLOCK);
+- if (f < 0) {
+- /*
+- * Set up error string but let us clear it later
+- * if at least one open succeeded.
+- */
+- if (scgp->errstr)
+- js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
+- "Cannot open '/dev/sg*'");
+- if (errno != ENOENT && errno != ENXIO && errno != ENODEV) {
++ if (nopen == 0) {
++ glob("/dev/scd[0-9]", GLOB_NOSORT, NULL, &globbuf);
++ glob("/dev/scd[0-9][0-9]", GLOB_NOSORT|GLOB_APPEND, NULL, &globbuf);
++ /*glob("/dev/sg[a-z]", GLOB_NOSORT|GLOB_APPEND, NULL, &globbuf);*/
++
++ for (i = 0; globbuf.gl_pathv && globbuf.gl_pathv[i] != NULL ; i++) {
++ devname = globbuf.gl_pathv[i];
++
++ f = open(devname, O_RDWR | O_NONBLOCK);
++ if (f < 0) {
++ /*
++ * Set up error string but let us clear it later
++ * if at least one open succeeded.
++ */
+ if (scgp->errstr)
+ js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
+- "Cannot open '%s'", devname);
+- return (0);
++ "Cannot open '/dev/scd*'");
++ if (errno != ENOENT && errno != ENXIO && errno != ENODEV) {
++ if (scgp->errstr)
++ js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
++ "Cannot open '%s'", devname);
++ globfree(&globbuf);
++ return (0);
++ }
++ } else {
++ sg_clearnblock(f); /* Be very proper about this */
++ if (sg_setup(scgp, f, busno, tgt, tlun, -1)) {
++ globfree(&globbuf);
++ return (++nopen);
++ }
++ if (busno < 0 && tgt < 0 && tlun < 0)
++ nopen++;
+ }
+- } else {
+- sg_clearnblock(f); /* Be very proper about this */
+- if (sg_setup(scgp, f, busno, tgt, tlun, -1))
+- return (++nopen);
+- if (busno < 0 && tgt < 0 && tlun < 0)
+- nopen++;
+ }
+ }
+ if (nopen > 0 && scgp->errstr)
+ scgp->errstr[0] = '\0';
+
+- if (nopen == 0) for (i = 0; i <= 25; i++) {
+- js_snprintf(devname, sizeof (devname), "/dev/sg%c", i+'a');
+- /* O_NONBLOCK is dangerous */
+- f = open(devname, O_RDWR | O_NONBLOCK);
+- if (f < 0) {
+- /*
+- * Set up error string but let us clear it later
+- * if at least one open succeeded.
+- */
+- if (scgp->errstr)
+- js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
+- "Cannot open '/dev/sg*'");
+- if (errno != ENOENT && errno != ENXIO && errno != ENODEV) {
+- if (scgp->errstr)
+- js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
+- "Cannot open '%s'", devname);
+- return (0);
+- }
+- } else {
+- sg_clearnblock(f); /* Be very proper about this */
+- if (sg_setup(scgp, f, busno, tgt, tlun, -1))
+- return (++nopen);
+- if (busno < 0 && tgt < 0 && tlun < 0)
+- nopen++;
+- }
+- }
+- if (nopen > 0 && scgp->errstr)
+- scgp->errstr[0] = '\0';
+
+ openbydev:
+ if (device != NULL && *device != '\0') {
+--- cdrtools-2.01/libscg/scsi-linux-ata.c.scan 2004-06-12 12:48:12.000000000 +0200
++++ cdrtools-2.01/libscg/scsi-linux-ata.c 2004-09-22 12:57:24.330983984 +0200
+@@ -267,7 +267,7 @@
+ starget,
+ slun;
+
+- f = open(device, O_RDONLY | O_NONBLOCK);
++ f = open(device, O_RDWR | O_NONBLOCK);
+
+ if (f < 0) {
+ if (scgp->errstr)
+@@ -283,6 +283,9 @@
+ return (nopen);
+ }
+
++#include <glob.h>
++
++
+ LOCAL int
+ scan_internal(scgp, nopen)
+ SCSI *scgp;
+@@ -293,118 +296,62 @@
+ int schilly_bus,
+ target,
+ lun;
+- char device[128];
++ char *device;
++ glob_t globbuf;
++
+ /*
+ * try always with devfs
+ * unfortunatelly the solution with test of existing
+ * of '/dev/.devfsd' don't work, because it root.root 700
+ * and i don't like run suid root
+ */
+- BOOL DEVFS = TRUE;
++ BOOL DEVFS = FALSE;
+
+- if (DEVFS) {
+- for (i = 0; ; i++) {
+- sprintf(device, "/dev/cdroms/cdrom%i", i);
+- if ((f = open(device, O_RDONLY | O_NONBLOCK)) < 0) {
+- if (errno != ENOENT && errno != ENXIO && errno != ENODEV && errno != EACCES) {
+- if (scgp->debug > 4) {
+- js_fprintf((FILE *) scgp->errfile,
+- "try open(%s) return %i, errno %i, cancel\n", device, f, errno);
+- }
+- return (-2);
+- } else if (errno == ENOENT || errno == ENODEV) {
+- if (scgp->debug > 4) {
+- js_fprintf((FILE *) scgp->errfile,
+- "try open(%s) return %i, errno %i\n", device, f, errno);
+- }
+- if (0 == i) {
+- DEVFS = FALSE;
+- if (scgp->debug > 4) {
+- js_fprintf((FILE *) scgp->errfile,
+- "DEVFS not detected, continuing with old dev\n");
+- }
+- }
+- break;
+- }
++ glob("/dev/cdroms/cdrom*",
++ GLOB_NOSORT,
++ NULL, &globbuf);
++ glob("/dev/hd[a-z]",
++ GLOB_NOSORT|GLOB_APPEND,
++ NULL, &globbuf);
++ /*glob("/dev/scd*",
++ GLOB_NOSORT|GLOB_APPEND,
++ NULL, &globbuf);*/
++
++ for (i = 0; globbuf.gl_pathv && globbuf.gl_pathv[i] != NULL ; i++) {
++ device = globbuf.gl_pathv[i];
++ if ((f = open(device, O_RDWR | O_NONBLOCK)) < 0) {
++ if (errno != ENOENT && errno != ENXIO && errno != ENODEV && errno != EACCES) {
+ if (scgp->debug > 4) {
+- if (errno == EACCES) {
+- js_fprintf((FILE *) scgp->errfile,
+- "errno (EACCESS), you don't have the needed rights for %s\n",
+- device);
+- }
+ js_fprintf((FILE *) scgp->errfile,
+- "try open(%s) return %i, errno %i, trying next cdrom\n",
+- device, f, errno);
++ "try open(%s) return %i, errno %i, cancel\n", device, f, errno);
+ }
+- } else {
+- if (scgp->debug > 4) {
++ globfree(&globbuf);
++ return (-2);
++ }
++ if (scgp->debug > 4) {
++ if (errno == EACCES) {
+ js_fprintf((FILE *) scgp->errfile,
+- "try open(%s) return %i errno %i calling sg_mapdev(...)\n",
+- device, f, errno);
+- }
+- if (sg_amapdev(scgp, f, device, &schilly_bus, &target, &lun)) {
+- (++(*nopen));
+- } else {
+- close(f);
++ "errno (EACCESS), you don't have the needed rights for %s\n",
++ device);
+ }
++ js_fprintf((FILE *) scgp->errfile,
++ "try open(%s) return %i, errno %i, trying next cdrom\n",
++ device, f, errno);
+ }
+- }
+- }
+- if (!DEVFS) {
+- /* for /dev/sr0 - /dev/sr? */
+- for (i = 0; ; i++) {
+- sprintf(device, "/dev/sr%i", i);
+- if ((f = open(device, O_RDONLY | O_NONBLOCK)) < 0) {
+- if (errno != ENOENT && errno != ENXIO && errno != ENODEV && errno != EACCES) {
+- if (scgp->debug > 4) {
+- js_fprintf((FILE *) scgp->errfile,
+- "try open(%s) return %i, errno %i, cancel\n",
+- device, f, errno);
+- }
+- return (-2);
+- } else if (errno == ENOENT || errno == ENODEV) {
+- break;
+- }
+- } else {
+- if (sg_amapdev(scgp, f, device, &schilly_bus, &target, &lun)) {
+- (++(*nopen));
+- } else {
+- close(f);
+- }
++ } else {
++ if (scgp->debug > 4) {
++ js_fprintf((FILE *) scgp->errfile,
++ "try open(%s) return %i errno %i calling sg_mapdev(...)\n",
++ device, f, errno);
+ }
+- }
+-
+- /* for /dev/hda - /dev/hdz */
+- for (i = 'a'; i <= 'z'; i++) {
+- sprintf(device, "/dev/hd%c", i);
+- if ((f = open(device, O_RDONLY | O_NONBLOCK)) < 0) {
+- if (errno != ENOENT && errno != ENXIO && errno != EACCES) {
+- if (scgp->debug > 4) {
+- js_fprintf((FILE *) scgp->errfile,
+- "try open(%s) return %i, errno %i, cancel\n",
+- device, f, errno);
+- }
+- return (-2);
+- } else if (errno == ENOENT || errno == ENODEV) {
+- break;
+- }
++ if (sg_amapdev(scgp, f, device, &schilly_bus, &target, &lun)) {
++ (++(*nopen));
+ } else {
+- /* ugly hack, make better, when you can. Alex */
+- if (0 > ioctl(f, CDROM_DRIVE_STATUS, CDSL_CURRENT)) {
+- if (scgp->debug > 4) {
+- js_fprintf((FILE *) scgp->errfile,
+- "%s is not a cdrom, skipping\n",
+- device);
+- }
+- close(f);
+- } else if (sg_amapdev(scgp, f, device, &schilly_bus, &target, &lun)) {
+- (++(*nopen));
+- } else {
+- close(f);
+- }
++ close(f);
+ }
+ }
+ }
++ globfree(&globbuf);
+ return (0);
+ }
+
+--- cdrtools-2.01/libscg/scsi-linux-pg.c.scan 2004-01-15 01:54:36.000000000 +0100
++++ cdrtools-2.01/libscg/scsi-linux-pg.c 2004-09-22 12:59:04.107815600 +0200
+@@ -130,6 +130,8 @@
+ return (0);
+ }
+
++#include <glob.h>
++
+ LOCAL int
+ scgo_open(scgp, device)
+ SCSI *scgp;
+@@ -146,6 +148,8 @@
+ #endif
+ register int nopen = 0;
+ char devname[32];
++ glob_t globbuf;
++ int i;
+
+ if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
+ errno = EINVAL;
+@@ -217,10 +221,14 @@
+ scglocal(scgp)->scgfiles[busno][tgt][tlun] = f;
+ return (1);
+ } else {
++ const char *dev;
+ tlun = 0;
+- for (tgt = 0; tgt < MAX_TGT; tgt++) {
+- js_snprintf(devname, sizeof (devname), "/dev/pg%d", tgt);
+- f = open(devname, O_RDWR | O_NONBLOCK);
++ glob("/dev/pg[0-9]", GLOB_NOSORT, NULL, &globbuf);
++ glob("/dev/pg[0-9][0-9]", GLOB_NOSORT|GLOB_APPEND, NULL, &globbuf);
++ for (i = 0; globbuf.gl_pathv && globbuf.gl_pathv[i] != NULL ; i++) {
++ dev = globbuf.gl_pathv[i];
++ tgt = atoi(&dev[7]);
++ f = open(dev, O_RDWR | O_NONBLOCK);
+ if (f < 0) {
+ /*
+ * Set up error string but let us clear it later
+@@ -232,7 +240,8 @@
+ if (errno != ENOENT && errno != ENXIO && errno != ENODEV) {
+ if (scgp->errstr)
+ js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
+- "Cannot open '%s'", devname);
++ "Cannot open '%s'", dev);
++ globfree(&globbuf);
+ return (0);
+ }
+ } else {
+@@ -240,6 +249,8 @@
+ nopen++;
+ }
+ }
++ globfree(&globbuf);
++
+ }
+ if (nopen > 0 && scgp->errstr)
+ scgp->errstr[0] = '\0';