Compare commits

..

57 Commits

Author SHA1 Message Date
9ac3548d81 Bug fix: Compilation warning for unsupported systems mutated into an error 2014-03-18 09:48:42 +00:00
1f0755c50e Bug fix: CD TAO with multiple tracks could cause a buffer overrun 2014-03-18 09:47:29 +00:00
b667218011 Branching for libburn bugfix release 1.3.6.pl01 2014-03-18 09:39:12 +00:00
5714fdd895 libburn release 1.3.6 is ready 2014-03-04 16:34:59 +00:00
cd8b81a3ca Documented changes and release timestamp 2014-03-04 10:05:49 +00:00
59c736570e Updated cdrskin tarball generator 2014-03-04 10:04:09 +00:00
b4a40f0a5e Made number transition to 1.3.6 2014-03-04 10:02:46 +00:00
e424c885fd Branching for libburn release 1.3.6 2014-03-04 09:24:54 +00:00
6e5c50bde4 Improved emulation of mode page 2A 2014-03-01 10:16:03 +00:00
174c22aeb7 Removed Linux compilability mock-up from sg-netbsd.c 2014-02-19 11:11:50 +00:00
31abdedade Inquiring GET PERFORMANCE independently of existence of mode page 2A 2014-02-16 20:41:57 +00:00
b6afe92e47 Improved workaround for missing mode page 2A 2014-02-14 20:03:01 +00:00
1d616b5944 Corrected size determination of NetBSD block devices 2014-02-13 20:55:27 +00:00
070ac64459 Mentioned support for NetBSD 2014-02-12 18:58:17 +00:00
ad95f1ff2b Silenced warnings about -Wchar-subscripts, added /usr/local for NetBSD 2014-02-11 08:28:44 +00:00
3edde5dc9d Introduced netbsd system adapter in tarball generator 2014-02-10 22:04:43 +00:00
cf5c7aa84f Inmplemented a system adapter for NetBSD 2014-02-10 21:36:34 +00:00
d40ab32360 Being more rugged towards missing MODE SENSE info 2014-02-10 21:33:50 +00:00
43e1daab23 Avoiding to have two file descriptors open to the same stdio drive 2014-02-07 18:08:28 +00:00
6e4d1cc53e Prepared for possible demise of mode page 2A 2014-02-05 19:20:08 +00:00
cdbbcbb923 Fixed bugs introduced with previous commit 2014-02-05 19:00:01 +00:00
7f31c9e985 Trying to better handle MMC violating replies of MODE SENSE (Block Descriptors) 2014-02-05 12:49:41 +00:00
dd0ceb6720 Implemented a generic verification whether a SPC device is a MMC device 2014-02-04 11:31:12 +00:00
5676a1953d Improved handling of stdio pseudo-drives after aborted burn runs 2014-01-15 17:50:33 +00:00
78627934f3 Updated copyright claim in sg-linux.c 2014-01-15 17:49:04 +00:00
217289f71a Adapted Linux SG_IO adapter to scsi/sg.h of git.kernel.org 2014-01-09 21:50:17 +00:00
1c6f6c084f Interpreting feature 0x107 when deciding from where to get speed info 2014-01-09 13:23:23 +00:00
658851a497 Registering all drive-media feature descriptors in burn_drive 2014-01-07 12:01:18 +00:00
2aa10d1099 Documented changes and release timestamp 2013-12-12 14:58:22 +00:00
ba8b1b5e17 Updated cdrskin tarball generator 2013-12-12 14:54:37 +00:00
ef17544eb9 Made number transition to 1.3.5 2013-12-12 14:52:30 +00:00
7f99a8e70e Better reaction on drive errors during burn_drive_scan_and_grab() 2013-11-21 09:21:29 +00:00
5f6281261d Corrected bugs introduced with rev 5180 2013-11-17 15:27:08 +00:00
04afd1c958 Resetting the drive failure status before starting random-access writing 2013-11-17 10:25:01 +00:00
83eac67cf5 Prevented a memory leak that in most cases was closed by a race condition 2013-11-16 17:05:40 +00:00
d09ecac4a8 Enforcing reasonable minimum read speeds even if the drive is lying 2013-11-15 10:24:31 +00:00
404f239207 Improved reaction on Linux SG_IO transport problems 2013-11-14 10:17:48 +00:00
0cd21eed54 Updated change log 2013-11-11 17:20:30 +00:00
119c0cf76d Bug fix: Drive LG BH16NS40 stalled on inspection of unformatted DVD+RW 2013-11-11 16:10:36 +00:00
edc90b880c New API call burn_disc_pretend_full_uncond() 2013-11-10 16:35:17 +00:00
ae4d296a60 Enforcing reasonable maximum read speeds even if the drive is lying 2013-11-08 09:54:15 +00:00
4880ca3b93 Closed potential memory leak introduced by rev 5168 2013-11-08 09:53:13 +00:00
429fed00c1 Closed potential memory leak introduced by rev 5168 2013-11-08 09:51:33 +00:00
87ab352d6f New API calls burn_drive_was_feat21_failure(), burn_write_opts_set_fail21h_sev() 2013-10-28 10:51:05 +00:00
6e372c9a6d Bug fix: Drive error reports were ignored during blanking and formatting 2013-10-10 16:20:39 +00:00
1f7dfb84fc Forgot to disable a debugging message 2013-10-09 13:46:47 +00:00
844dc958be Separately determining the maximum speeds for writing and reading 2013-10-09 09:24:09 +00:00
f6132a97a0 Made -version message more acceptable for K3B. Proposal of Omegaweapon. 2013-10-03 10:01:15 +00:00
642406b92e Reacted on warning of Debian buildd with clang 2013-09-16 17:28:55 +00:00
cc8ac3aefb Reacted on warnings of PLD Linux build log 2013-09-05 08:49:31 +00:00
2a8ae1be42 Reacted on warnings of PLD Linux 2013-09-04 14:18:08 +00:00
8d2e14a0b9 Closed a small memory leak with cdrskin -msinfo 2013-09-04 11:16:12 +00:00
9e02c17004 Closed a small memory leak with cdrskin -msinfo 2013-09-04 11:10:05 +00:00
669ccb9b43 Catching and defaulting mad responses to READ BUFFER CAPACITY 2013-09-04 11:00:30 +00:00
05ae7e51e4 Updated change log 2013-08-07 13:56:37 +00:00
db2ec50deb Updated cdrskin tarball generator 2013-08-07 13:52:34 +00:00
6b93e66cfd Made number transition to 1.3.3 2013-08-07 13:51:09 +00:00
36 changed files with 2623 additions and 402 deletions

View File

@ -1,4 +1,14 @@
SVN trunk (to become libburn-1.3.2 or higher)
libburn-1.3.6.tar.gz Tue Mar 04 2013
===============================================================================
* New system adapter for NetBSD
libburn-1.3.4.tar.gz Thu Dec 12 2013
===============================================================================
* Bug fix: Drive error reports were ignored during blanking and formatting
* Bug fix: Drive LG BH16NS40 stalls on inspection of unformatted DVD+RW
* New API call burn_disc_pretend_full_uncond()
libburn-1.3.2.tar.gz Wed Aug 07 2013
===============================================================================
* Bug fix: cdrskin -msinfo on DVD and BD reported
old session start = next writable address.
@ -15,7 +25,6 @@ SVN trunk (to become libburn-1.3.2 or higher)
* Improved granularity of SCSI log time measurement, now with timestamp
* Optional "make doc" now demands doxygen 1.8.4
libburn-1.3.0.pl01.tar.gz Fri May 31 2013
===============================================================================
* Bug fix: cdrskin -msinfo on DVD and BD reported

View File

@ -118,9 +118,9 @@ test_structest_CPPFLAGS = -Ilibburn
test_structest_LDADD = $(libburn_libburn_la_OBJECTS) $(LIBBURN_EXTRALIBS)
test_structest_SOURCES = test/structest.c
## cdrskin construction site - ts A60816 - B30807
## cdrskin construction site - ts A60816 - B40304
cdrskin_cdrskin_CPPFLAGS = -Ilibburn
cdrskin_cdrskin_CFLAGS = -DCdrskin_libburn_1_3_2
cdrskin_cdrskin_CFLAGS = -DCdrskin_libburn_1_3_6
# cdrskin_cdrskin_LDADD = $(libburn_libburn_la_OBJECTS) $(LIBBURN_EXTRALIBS)
# ts A80123, change proposed by Simon Huggins to cause dynamic libburn linking
@ -225,11 +225,13 @@ EXTRA_DIST = \
libburn/os-linux.h \
libburn/os-libcdio.h \
libburn/os-solaris.h \
libburn/os-netbsd.h \
libburn/sg-dummy.c \
libburn/sg-freebsd.c \
libburn/sg-linux.c \
libburn/sg-libcdio.c \
libburn/sg-solaris.c \
libburn/sg-netbsd.c \
COPYING \
NEWS \
ChangeLog \

26
README
View File

@ -6,12 +6,12 @@ This all is under GPL.
------------------------------------------------------------------------------
libburnia-project.org
By Mario Danic <mario.danic@gmail.com> and Thomas Schmitt <scdbackup@gmx.net>
Copyright (C) 2006-2013 Mario Danic, Thomas Schmitt
Copyright (C) 2006-2014 Mario Danic, Thomas Schmitt
Still containing parts of Libburn. By Derek Foreman <derek@signalmarketing.com>
and Ben Jansens <xor@orodu.net>
Copyright (C) 2002-2006 Derek Foreman and Ben Jansens
http://files.libburnia-project.org/releases/libburn-1.3.2.tar.gz
http://files.libburnia-project.org/releases/libburn-1.3.6.tar.gz
------------------------------------------------------------------------------
@ -19,10 +19,10 @@ Copyright (C) 2002-2006 Derek Foreman and Ben Jansens
From tarball
Obtain libburn-1.3.2.tar.gz, take it to a directory of your choice and do:
Obtain libburn-1.3.6.tar.gz, take it to a directory of your choice and do:
tar xzf libburn-1.3.2.tar.gz
cd libburn-1.3.2
tar xzf libburn-1.3.6.tar.gz
cd libburn-1.3.6
./configure --prefix=/usr
make
@ -137,7 +137,8 @@ These are libraries, language bindings, and middleware binaries which emulate
classical (and valuable) Linux tools.
Currently it is supported on GNU/Linux with kernels >= 2.4,
on FreeBSD with ATAPI/CAM enabled in the kernel (see man atapicam),
and on OpenSolaris (tested with kernel 5.11).
on OpenSolaris (tested with kernel 5.11),
on NetBSD (tested with 6.1.3).
On other X/Open compliant systems there will only be pseudo drives, but no
direct MMC operation on real CD/DVD/BD drives.
@ -713,6 +714,19 @@ Project history as far as known to me:
cdrskin itself. Several small bugs were fixed in xorriso. Its capabilities
to serve frontend programs in dialog mode have been improved.
- Thu Dec 12 2013 release 1.3.4:
A long standing hidden bug was fixed, which affected inspection of
unformatted DVD+RW.
xorriso now by default puts EL Torito boot images to low block addresses.
It can report and set read speeds. Several rarely occuring bugs were fixed.
- Tue Mar 04 2014 release 1.3.6
libburn learned to operate optical drives and media on NetBSD. libisofs got
a bug fix about HFS+ and enhancements about character set conversion.
Minor bugs were fixed in libisoburn. xorriso can now find files with names
which cannot be represented unchanged in ECMA-119, Joliet, or HFS+.
------------------------------------------------------------------------------
This program is free software; you can redistribute it and/or modify

View File

@ -1,7 +1,7 @@
AC_DEFUN([LIBBURNIA_SET_FLAGS],
[
case $target_os in
freebsd*)
freebsd* | netbsd*)
LDFLAGS="$LDFLAGS -L/usr/local/lib"
CPPFLAGS="$CPPFLAGS -I/usr/local/include"
;;

View File

@ -4,17 +4,17 @@
cdrskin. By Thomas Schmitt <scdbackup@gmx.net>
Integrated sub project of libburnia-project.org but also published via:
http://scdbackup.sourceforge.net/cdrskin_eng.html
http://scdbackup.sourceforge.net/cdrskin-1.3.2.tar.gz
http://scdbackup.sourceforge.net/cdrskin-1.3.6.tar.gz
Copyright (C) 2006-2013 Thomas Schmitt, provided under GPL version 2 or later.
Copyright (C) 2006-2014 Thomas Schmitt, provided under GPL version 2 or later.
------------------------------------------------------------------------------
cdrskin is a limited cdrecord compatibility wrapper which allows to use
most of the libburn features from the command line.
Currently it is supported on GNU/Linux with kernels >= 2.4,
on FreeBSD and on OpenSolaris.
Currently it is fully supported on GNU/Linux with kernels >= 2.4, on FreeBSD,
on OpenSolaris, and on NetBSD.
IDE drives under Linux 2.4. need kernel module ide-scsi.
ATA and SATA drives under FreeBSD need kernel module atapicam.
On other X/Open compliant systems there will only be emulated drives, but no
@ -26,10 +26,10 @@ By using this software you agree to the disclaimer at the end of this text
Compilation, First Glimpse, Installation
Obtain cdrskin-1.3.2.tar.gz, take it to a directory of your choice and do:
Obtain cdrskin-1.3.6.tar.gz, take it to a directory of your choice and do:
tar xzf cdrskin-1.3.2.tar.gz
cd cdrskin-1.3.2
tar xzf cdrskin-1.3.6.tar.gz
cd cdrskin-1.3.6
Within that directory execute:
@ -108,8 +108,9 @@ On Linux, full and insecure enabling of both for everybody would look like
chmod a+rw /dev/sr0 /dev/hda
This is equivalent to the traditional setup chmod a+x,u+s cdrecord.
On FreeBSD, device permissions are to be set in /etc/devfs.rules.
On FreeBSD, device rw-permissions are to be set in /etc/devfs.rules.
On Solaris, pfexec privileges may be restricted to "basic,sys_devices".
On NetBSD, rw-permission may be granted by chmod a+rw /dev/rcd?d.
See below "System Dependend Drive Permission Examples".
I strongly discourage to run cdrskin with setuid root or via sudo !
@ -464,7 +465,7 @@ closing it immediately, waiting, and only then opening it for real:
System Dependend Drive Permission Examples
Accessing the optical drives requires privileges which usually are granted
only to the superuser. Linux, FreeBSD and Solaris offer quite different
only to the superuser. Linux, FreeBSD, Solaris, NetBSD, offer quite different
approaches for avoiding the need for unrestricted privileges.
First check whether some friendly system setting already allows you to
@ -475,9 +476,9 @@ Those drives of which you see address and type strings are already usable.
If there remain drives invisible which the superuser can see by the same
command, then the following examples might help:
---------------------
On all three systems:
---------------------
---------------
On all systems:
---------------
Add the authorized users of CD drives to group "floppy" in /etc/group.
If missing: create this group.
Changes to /etc/group often only affect new login sessions. So log out and in
@ -537,6 +538,12 @@ Then allow the group r-access to the drives
The last two commands have to be executed after each boot. I do not know
the relevant device configuration files yet.
----------
On NetBSD:
----------
Allow rw-access to the drives
chgrp floppy /dev/rcd[01]d
chmod g+rw /dev/rcd[01]d
------------------------------------------------------------------------------
Project aspects and legal stuff

View File

@ -38,7 +38,7 @@ original="./libburn_svn_release.tgz"
# My changes are in $changes , mainly in $changes/cdrskin
changes="./libburn-release"
skin_release="1.3.2"
skin_release="1.3.6"
patch_level=""
# patch_level=".pl00"
skin_rev="$skin_release""$patch_level"

View File

@ -38,7 +38,7 @@ original="./libburn_svn.tgz"
# My changes are in $changes , mainly in $changes/cdrskin
changes="./libburn-develop"
skin_release="1.3.3"
skin_release="1.3.7"
patch_level=""
skin_rev="$skin_release""$patch_level"

View File

@ -2,7 +2,7 @@
.\" First parameter, NAME, should be all caps
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
.\" other parameters are allowed: see man(7), man(1)
.TH CDRSKIN 1 "Version 1.3.2, Aug 07, 2013"
.TH CDRSKIN 1 "Version 1.3.6, Mar 04, 2014"
.\" Please adjust this date whenever revising the manpage.
.\"
.\" Some roff macros, for reference:

View File

@ -1,6 +1,6 @@
/*
cdrskin.c , Copyright 2006-2013 Thomas Schmitt <scdbackup@gmx.net>
cdrskin.c , Copyright 2006-2014 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
A cdrecord compatible command line interface for libburn.
@ -87,7 +87,7 @@ or
/** The official program version */
#ifndef Cdrskin_prog_versioN
#define Cdrskin_prog_versioN "1.3.2"
#define Cdrskin_prog_versioN "1.3.6"
#endif
/** The official libburn interface revision to use.
@ -100,7 +100,7 @@ or
#define Cdrskin_libburn_minoR 3
#endif
#ifndef Cdrskin_libburn_micrO
#define Cdrskin_libburn_micrO 2
#define Cdrskin_libburn_micrO 6
#endif
@ -120,34 +120,34 @@ or
#undef Cdrskin_libburn_versioN
#endif
#ifdef Cdrskin_libburn_1_3_2
#define Cdrskin_libburn_versioN "1.3.2"
#ifdef Cdrskin_libburn_1_3_6
#define Cdrskin_libburn_versioN "1.3.6"
#endif
#ifdef Cdrskin_libburn_1_3_3
#define Cdrskin_libburn_versioN "1.3.3"
#ifdef Cdrskin_libburn_1_3_7
#define Cdrskin_libburn_versioN "1.3.7"
#endif
#ifndef Cdrskin_libburn_versioN
#define Cdrskin_libburn_1_3_2
#define Cdrskin_libburn_versioN "1.3.2"
#define Cdrskin_libburn_1_3_6
#define Cdrskin_libburn_versioN "1.3.6"
#endif
#ifdef Cdrskin_libburn_1_3_2
#ifdef Cdrskin_libburn_1_3_6
#undef Cdrskin_libburn_majoR
#undef Cdrskin_libburn_minoR
#undef Cdrskin_libburn_micrO
#define Cdrskin_libburn_majoR 1
#define Cdrskin_libburn_minoR 3
#define Cdrskin_libburn_micrO 2
#define Cdrskin_libburn_micrO 4
#endif
#ifdef Cdrskin_libburn_1_3_3
#ifdef Cdrskin_libburn_1_3_7
#undef Cdrskin_libburn_majoR
#undef Cdrskin_libburn_minoR
#undef Cdrskin_libburn_micrO
#define Cdrskin_libburn_majoR 1
#define Cdrskin_libburn_minoR 3
#define Cdrskin_libburn_micrO 3
#define Cdrskin_libburn_micrO 5
#endif
@ -3148,7 +3148,7 @@ set_severities:;
int major, minor, micro;
printf(
"Cdrecord 2.01-Emulation Copyright (C) 2006-2013, see libburnia-project.org\n");
"Cdrecord 2.01a27 Emulation. Copyright (C) 2006-2013, see libburnia-project.org\n");
if(o->fallback_program[0]) {
char *hargv[2];
@ -7191,6 +7191,21 @@ ex:
}
int Cdrskin_write_result_string(struct CdrskiN *skin, char *msg, int flag)
{
int ret;
if(skin->preskin->result_fd < 0) {
printf("%s",msg);
return(1);
}
ret= write(skin->preskin->result_fd, msg, strlen(msg));
if(ret != (int) strlen(msg))
return(0);
return(1);
}
/** Burn data via libburn according to the parameters set in skin.
@return <=0 error, 1 success
*/
@ -7525,10 +7540,7 @@ burn_failed:;
free_space= burn_disc_available_space(drive,o);
sprintf(msg,"%d\n",(int) (free_space/(off_t) 2048));
if(skin->preskin->result_fd>=0) {
write(skin->preskin->result_fd,msg,strlen(msg));
} else
printf("%s",msg);
Cdrskin_write_result_string(skin, msg, 0);
if(skin->track_counter>0)
fprintf(stderr,
"cdrskin: NOTE : %s burn run suppressed by option --tell_media_space\n",
@ -7937,11 +7949,8 @@ obtain_nwa:;
}
put_out:;
if(skin->preskin->result_fd>=0) {
sprintf(msg,"%d,%d\n",lba,nwa);
write(skin->preskin->result_fd,msg,strlen(msg));
} else
printf("%d,%d\n",lba,nwa);
sprintf(msg,"%d,%d\n",lba,nwa);
Cdrskin_write_result_string(skin, msg, 0);
if(strlen(skin->msifile)) {
FILE *fp;
@ -7959,6 +7968,8 @@ put_out:;
}
ret= 1;
ex:;
if(disc!=NULL)
burn_disc_free(disc);
return(ret);
}

View File

@ -39,7 +39,7 @@ About any CD, DVD, or BD recorder produced in the recent ten years.
<BR>
<A HREF="http://libburnia-project.org">libburn</A>
supports recorders which are compliant to standards MMC-1 for CD and
MMC-5 for DVD or BD. Linux, FreeBSD, and Solaris allow to access drives
MMC-5 for DVD or BD. Linux, FreeBSD, Solaris, and NetBSD allow to access drives
connected via SCSI, PATA (aka IDE, ATA), USB, or SATA.
<BR>
</P>
@ -49,12 +49,14 @@ connected via SCSI, PATA (aka IDE, ATA), USB, or SATA.
<DL>
<DT>Linux with kernel 2.4 or higher (and libc, of course) :</DT>
<DD>With kernel 2.4 an ATA drive has to be under ide-scsi emulation.</DD>
<DD>With kernel 2.6 the drive should not be under ide-scsi.</DD>
<DD>With kernel 2.6 or higher the drive should not be under ide-scsi.</DD>
<DT>or FreeBSD (with libc, of course) :</DT>
<DD>ATA and SATA drives need atapicam running.</DD>
<DD>libcam has to be installed.</DD>
<DT>or Solaris (with libc, of course) :</DT>
<DD>Tested on kernel 5.11, hopefully suitable for older ones too.</DD>
<DT>or NetBSD (with libc, of course) :</DT>
<DD>Tested on 6.1.2 and 6.1.3</DD>
<DT>libpthread</DT>
<DD>is supposed to be a standard system component.</DD>
</DL>
@ -65,7 +67,7 @@ connected via SCSI, PATA (aka IDE, ATA), USB, or SATA.
GPL software included:<BR>
</H2>
<DL>
<DT>libburn-1.3.2</DT>
<DT>libburn-1.3.6</DT>
<DD>(founded by Derek Foreman and Ben Jansens,
developed and maintained since August 2006 by
Thomas Schmitt from team of libburnia-project.org)
@ -76,7 +78,7 @@ Thomas Schmitt from team of libburnia-project.org)
<P>
This program system has been tested on Intel/AMD with Linux, FreeBSD,
and OpenSolaris based operating systems.<BR>
OpenSolaris, and NetBSD based operating systems.<BR>
Ports to other usable systems are appreciated. Reports are welcome.
</P>
@ -110,7 +112,7 @@ DVD-R DL, which both support no -multi.
<DT>Being superuser avoids permission problems with /dev/srN resp. /dev/hdX .
</DT>
<DT>Ordinary users should then get granted access to the /dev files
as listed by option --devices. Linux and FreeBSD demand rw-permission.
as listed by option --devices. Linux, FreeBSD, and NetBSD demand rw-permission.
On Solaris it is r-permission and privileges "basic,sys_devices".</DT>
<DT>&nbsp;</DT>
@ -200,13 +202,13 @@ Standalone ISO 9660 multi-session CD/DVD/BD tool
<P>
<DL>
<DT>Download as source code (see README):</DT>
<DD><A HREF="cdrskin-1.3.2.tar.gz">cdrskin-1.3.2.tar.gz</A>
(950 KB).
<DD><A HREF="cdrskin-1.3.6.tar.gz">cdrskin-1.3.6.tar.gz</A>
(965 KB).
</DD>
<DD><A HREF="cdrskin-1.3.2.tar.gz.sig">cdrskin-1.3.2.tar.gz.sig</A></DD>
<DD><A HREF="cdrskin-1.3.6.tar.gz.sig">cdrskin-1.3.6.tar.gz.sig</A></DD>
<DD>
(detached GPG signature for verification by
<KBD>gpg --verify cdrskin-1.3.2.tar.gz.sig cdrskin-1.3.2.tar.gz</KBD>
<KBD>gpg --verify cdrskin-1.3.6.tar.gz.sig cdrskin-1.3.6.tar.gz</KBD>
<BR>
after <KBD>gpg --keyserver keys.gnupg.net --recv-keys ABC0A854</KBD>).
</DD>
@ -257,51 +259,38 @@ cdrskin_0.4.2.pl00-x86-suse9_0-static.tar.gz</A>, (310 KB), -static compiled,
<HR>
<P>
Enhancements towards previous stable version cdrskin-1.3.0:
Enhancements towards previous stable version cdrskin-1.3.4:
<UL>
<LI>
New option textfile_to_v07t=
</LI>
<LI>
New options cdtext_to_textfile= and cdtext_to_v07t=
</LI>
<LI>
New options extract_audio_to= , extract_tracks= , extract_basename= ,
--extract_dap
</LI>
<LI>
Improved granularity of SCSI log time measurement, now with timestamp
</LI>
<LI>
New cdrskin option --pacifier_with_newline
</LI>
<LI>New system adapter for NetBSD</LI>
<!--
<LI>none</LI>
-->
</UL>
Bug fixes towards cdrskin-1.3.0:
Bug fixes towards cdrskin-1.3.4:
<UL>
<LI>
cdrskin -msinfo on DVD and BD reported
old session start = next writable address.
Regression introduced by version 1.2.8.
(Also fixed by patch release 1.3.0.pl01 in may 2013.)
</LI>
<LI>
The signal handler aborted on SIGCONT, SIGTSTP, SIGTTIN, SIGTTOU
</LI>
<LI>none</LI>
<!--
<LI>none</LI>
-->
</UL>
<!--
Bug fixes of cdrskin-1.3.2.pl01 towards cdrskin-1.3.2:
<UL>
<LI>
cdrskin-1.3.2.tar.gz contained the outdated source code of cdrskin-1.3.0,
including the -msinfo bug.
</LI>
</UL>
-->
<HR>
<P>
<DL>
<DT><H3>Development snapshot, version 1.3.3 :</H3></DT>
<DD>Enhancements towards current stable version 1.3.2:
<DT><H3>Development snapshot, version 1.3.7 :</H3></DT>
<DD>Enhancements towards current stable version 1.3.6:
<UL>
<LI>none yet</LI>
<!--
@ -311,7 +300,7 @@ The signal handler aborted on SIGCONT, SIGTSTP, SIGTTIN, SIGTTOU
</UL>
</DD>
<DD>Bug fixes towards cdrskin-1.3.2:
<DD>Bug fixes towards cdrskin-1.3.6:
<UL>
<LI>none yet</LI>
<!--
@ -321,10 +310,10 @@ The signal handler aborted on SIGCONT, SIGTSTP, SIGTTIN, SIGTTOU
</DD>
<DD>&nbsp;</DD>
<DD><A HREF="README_cdrskin_devel">README 1.3.3</A>
<DD><A HREF="cdrskin__help_devel">cdrskin-1.3.3 --help</A></DD>
<DD><A HREF="cdrskin_help_devel">cdrskin-1.3.3 -help</A></DD>
<DD><A HREF="man_1_cdrskin_devel.html">man cdrskin (as of 1.3.3)</A></DD>
<DD><A HREF="README_cdrskin_devel">README 1.3.7</A>
<DD><A HREF="cdrskin__help_devel">cdrskin-1.3.7 --help</A></DD>
<DD><A HREF="cdrskin_help_devel">cdrskin-1.3.7 -help</A></DD>
<DD><A HREF="man_1_cdrskin_devel.html">man cdrskin (as of 1.3.7)</A></DD>
<DD>&nbsp;</DD>
<DT>Maintainers of cdrskin unstable packages please use SVN of
<A HREF="http://libburnia-project.org"> libburnia-project.org</A></DT>
@ -339,13 +328,13 @@ vanilla tools like make and gcc are needed.</DD>
</DD>
<DD>&nbsp;</DD>
<DT>The following download is intended for adventurous end users or
admins with full system souvereignty.</DT>
admins with full system sovereignty.</DT>
<DD>Source (./bootstrap is already applied, build tested, for more see
<A HREF="README_cdrskin_devel">upcoming README</A> ):
</DD>
<DD>
<A HREF="cdrskin-1.3.3.tar.gz">cdrskin-1.3.3.tar.gz</A>
(950 KB).
<A HREF="cdrskin-1.3.7.tar.gz">cdrskin-1.3.7.tar.gz</A>
(965 KB).
</DD>
<!-- This is not offered any more since spring 2008

View File

@ -1 +1 @@
#define Cdrskin_timestamP "2013.08.07.093001"
#define Cdrskin_timestamP "2014.03.04.110001"

View File

@ -12109,7 +12109,7 @@ Made number transition to 1.3.2
+ cdrskin/add_ts_changes_to_libburn_1_3_3
Updated cdrskin tarball generator
[]
07 Aug 2013 [5128]
ChangeLog
cdrskin/changelog.txt
Documented changes and release timestamp
@ -12131,13 +12131,383 @@ Documented changes and release timestamp
* Optional "make doc" now demands doxygen 1.8.4
[]
2013.08.07.134744 [5132]
Makefile.am
configure.ac
README
libburn/libburn.h
cdrskin/cdrskin.c
cdrskin/cdrskin.1
cdrskin/README
cdrskin/compile_cdrskin.sh
cdrskin/cdrskin_timestamp.h
cdrskin/cdrskin_eng.html
Made number transition to 1.3.3
07 Aug 2013 [5133]
- cdrskin/add_ts_changes_to_libburn_1_3_0
- cdrskin/add_ts_changes_to_libburn_1_3_1
+ cdrskin/add_ts_changes_to_libburn_1_3_2
+ cdrskin/add_ts_changes_to_libburn_1_3_3
Updated cdrskin tarball generator
07 Aug 2013 [5134]
ChangeLog
cdrskin/changelog.txt
Updated change log
07 Aug 2013 [5135]
svn move -m libburn release 1.3.2 is ready
http://svn.libburnia-project.org/libburn/branches/1.3.2
http://svn.libburnia-project.org/libburn/tags/1.3.2
------------------------------------ cycle - cdrskin-1.3.3 - 2013.08.07.135823
2013.09.04.105934 [5145]
libburn/mmc.c
Catching and defaulting mad responses to READ BUFFER CAPACITY
2013.09.04.110910 [5146] [5147]
cdrskin/cdrskin.c
Closed a small memory leak with cdrskin -msinfo
2013.09.04.141706 [5148]
cdrskin/cdrskin.c
Reacted on warnings of PLD Linux
2013.09.05.084834 [5152]
libburn/file.c
libburn/mmc.c
Reacted on warnings of PLD Linux build log
2013.09.16.172745 [5157]
libburn/async.c
Reacted on warning of Debian buildd with clang
2013.10.03.100011 [5158]
cdrskin/cdrskin.c
Made -version message more acceptable for K3B. Proposal of Omegaweapon.
2013.10.09.092306 [5161]
libburn/mmc.c
Separately determining the maximum speeds for writing and reading
2013.10.09.134543 [5163]
libburn/mmc.c
Forgot to disable a debugging message
2013.10.10.161931 [5164]
libburn/drive.c
libburn/spc.c
libburn/libdax_msgs.h
Bug fix: Drive error reports were ignored during blanking and formatting
2013.10.28.104957 [5168]
libburn/libburn.h
libburn/transport.h
libburn/drive.c
libburn/options.h
libburn/options.c
libburn/write.c
libburn/mmc.c
libburn/libburn.ver
New API calls burn_drive_was_feat21_failure(), burn_write_opts_set_fail21h_sev()
2013.11.08.095023 [5172]
libburn/write.c
Closed potential memory leak introduced by rev 5168
2013.11.08.095213 [5173] [5174]
libburn/mmc.c
Enforcing reasonable maximum read speeds even if the drive is lying
2013.11.10.163403 [5175]
libburn/libburn.h
libburn/drive.c
libburn/libburn.ver
New API call burn_disc_pretend_full_uncond()
2013.11.11.160915 [5177]
libburn/mmc.c
Bug fix: Drive LG BH16NS40 stalled on inspection of unformatted DVD+RW
11 Nov 2013 []
ChangeLog
cdrskin/cdrskin_eng.html
cdrskin/changelog.txt
Updated change log
------------------------------------ cycle - cdrskin-1.3.3 -
------------------------------------ cycle - cdrskin-1.3.3 - 2013.11.11.172016
* Bug fix: Drive error reports were ignored during blanking and formatting
* Bug fix: Drive LG BH16NS40 stalled on inspection of unformatted DVD+RW
* New API call burn_disc_pretend_full_uncond()
2013.11.14.101636 [5180]
libburn/libdax_msgs.h
libburn/spc.h
libburn/spc.c
libburn/sg-linux.c
Improved reaction on Linux SG_IO transport problems
2013.11.15.102314 [5182]
libburn/mmc.c
Enforcing reasonable minimum read speeds even if the drive is lying
2013.11.16.170431 [5184]
libburn/options.c
Prevented a memory leak that in most cases was closed by a race condition
2013.11.17.102351 [5185]
libburn/write.c
Resetting the drive failure status before starting random-access writing
2013.11.17.152544 [5187]
libburn/sg-linux.c
Corrected bugs introduced with rev 5180
2013.11.21.092012 [5189]
libburn/drive.c
Better reaction on drive errors during burn_drive_scan_and_grab()
12 Dec 2013 [5192]
svn copy -m Branching for libburn release 1.3.4
http://svn.libburnia-project.org/libburn/trunk
http://svn.libburnia-project.org/libburn/branches/1.3.4
2013.12.12.093001 [5193]
Makefile.am
configure.ac
README
libburn/libburn.h
cdrskin/cdrskin.c
cdrskin/cdrskin.1
cdrskin/README
cdrskin/compile_cdrskin.sh
cdrskin/cdrskin_timestamp.h
cdrskin/cdrskin_eng.html
Made number transition to 1.3.4
12 Dec 2013 [5194]
- cdrskin/add_ts_changes_to_libburn_1_3_2
- cdrskin/add_ts_changes_to_libburn_1_3_3
+ cdrskin/add_ts_changes_to_libburn_1_3_4
+ cdrskin/add_ts_changes_to_libburn_1_3_5
Updated cdrskin tarball generator
12 Dec 2013 [5195]
ChangeLog
cdrskin/changelog.txt
Documented changes and release timestamp
----------------------------------- release - cdrskin-1.3.4 - 2013.12.12.093001
* Bug fix: Drive error reports were ignored during blanking and formatting
* Bug fix: Drive LG BH16NS40 stalled on inspection of unformatted DVD+RW
* New API call burn_disc_pretend_full_uncond()
2013.12.12.140531 [5199]
Makefile.am
configure.ac
README
libburn/libburn.h
cdrskin/cdrskin.c
cdrskin/cdrskin.1
cdrskin/README
cdrskin/compile_cdrskin.sh
cdrskin/cdrskin_timestamp.h
cdrskin/cdrskin_eng.html
Made number transition to 1.3.5
12 Dec 2013 [5200]
- cdrskin/add_ts_changes_to_libburn_1_3_2
- cdrskin/add_ts_changes_to_libburn_1_3_3
+ cdrskin/add_ts_changes_to_libburn_1_3_4
+ cdrskin/add_ts_changes_to_libburn_1_3_5
Updated cdrskin tarball generator
12 Dec 2013 [5201]
ChangeLog
cdrskin/changelog.txt
Documented changes and release timestamp
------------------------------------ cycle - cdrskin-1.3.5 - 2013.12.12.140531
12 Dec 2013 [5202]
svn move -m libburn release 1.3.4 is ready
http://svn.libburnia-project.org/libburn/branches/1.3.4
http://svn.libburnia-project.org/libburn/tags/1.3.4
2014.01.07.115938 [5215]
libburn/transport.h
libburn/drive.h
libburn/drive.c
libburn/mmc.c
Registering all drive-media feature descriptors in burn_drive
2014.01.09.132159 [5216]
libburn/libburn.h
libburn/spc.c
libburn/mmc.h
libburn/mmc.c
Interpreting feature 0x107 when deciding from where to get speed info
2014.01.09.214841 [5218]
libburn/sg-linux.c
Adapted Linux SG_IO adapter to scsi/sg.h of git.kernel.org
2014.01.15.174741 [5225]
libburn/sg-linux.c
Updated copyright claim in sg-linux.c
2014.01.15.174907 [5226]
libburn/drive.h
libburn/drive.c
libburn/write.c
Improved handling of stdio pseudo-drives after aborted burn runs
2014.02.04.112944 [5233]
libburn/transport.h
libburn/spc.h
libburn/spc.c
Implemented a generic verification whether a SPC device is a MMC device
2014.02.05.124803 [5234]
libburn/spc.c
Trying to better handle MMC violating replies of MODE SENSE (Block Descriptors)
2014.02.05.185801 [5235]
libburn/spc.c
Fixed bugs introduced with previous commit
2014.02.05.191839 [5237]
libburn/libburn.h
libburn/transport.h
libburn/drive.c
libburn/options.c
libburn/async.c
libburn/spc.c
libburn/mmc.c
libburn/sg-freebsd.c
Prepared for possible demise of mode page 2A
2014.02.07.180650 [5238]
libburn/write.c
Avoiding to have two file descriptors open to the same stdio drive
2014.02.10.213159 [5244]
libburn/drive.c
libburn/spc.c
libburn/mmc.c
Being more rugged towards missing MODE SENSE info
2014.02.10.213500 [5245]
libburn/os.h
libburn/sg.c
+ libburn/os-netbsd.h
+ libburn/sg-netbsd.c
Inmplemented a system adapter for NetBSD
10 Feb 2014 [5246]
Makefile.am
Introduced NetBSD system adapter in tarball generator
11 Feb 2014 [5247]
configure.ac
acinclude.m4
Silenced warnings about -Wchar-subscripts, added /usr/local for NetBSD
12 Feb 2014 [5249]
doc/comments
cdrskin/README
Mentioned support for NetBSD
2014.02.13.205358 [5252]
libburn/sg-netbsd.c
Corrected size determination of NetBSD block devices
2014.02.14.200129 [5253]
libburn/drive.c
Improved workaround for missing mode page 2A
2014.02.16.203859 [5254]
libburn/spc.c
Inquiring GET PERFORMANCE independently of existence of mode page 2A
2014.02.19.111017 [5255]
libburn/os.h
libburn/sg.c
libburn/sg-netbsd.c
Removed Linux compilability mock-up from sg-netbsd.c
2014.03.01.101537 [5257]
libburn/libburn.h
libburn/transport.h
libburn/drive.c
Improved emulation of mode page 2A
04 Mar 2014 [5260]
svn copy -m Branching for libburn release 1.3.6
http://svn.libburnia-project.org/libburn/trunk
http://svn.libburnia-project.org/libburn/branches/1.3.6
2014.03.04.110001 [5261]
Makefile.am
configure.ac
README
libburn/libburn.h
cdrskin/cdrskin.c
cdrskin/cdrskin.1
cdrskin/README
cdrskin/compile_cdrskin.sh
cdrskin/cdrskin_timestamp.h
cdrskin/cdrskin_eng.html
Made number transition to 1.3.6
04 Mar 2014 [5262]
- cdrskin/add_ts_changes_to_libburn_1_3_4
- cdrskin/add_ts_changes_to_libburn_1_3_5
+ cdrskin/add_ts_changes_to_libburn_1_3_6
+ cdrskin/add_ts_changes_to_libburn_1_3_7
Updated cdrskin tarball generator
04 Mar 2014 []
ChangeLog
cdrskin/changelog.txt
Documented changes and release timestamp
----------------------------------- release - cdrskin-1.3.6 - 2014.03.04.110001
* New system adapter for NetBSD
[]
Makefile.am
configure.ac
README
libburn/libburn.h
cdrskin/cdrskin.c
cdrskin/cdrskin.1
cdrskin/README
cdrskin/compile_cdrskin.sh
cdrskin/cdrskin_timestamp.h
cdrskin/cdrskin_eng.html
Made number transition to 1.3.7
[]
- cdrskin/add_ts_changes_to_libburn_1_3_4
- cdrskin/add_ts_changes_to_libburn_1_3_5
+ cdrskin/add_ts_changes_to_libburn_1_3_6
+ cdrskin/add_ts_changes_to_libburn_1_3_7
Updated cdrskin tarball generator
[]
ChangeLog
cdrskin/changelog.txt
Documented changes and release timestamp
------------------------------------ cycle - cdrskin-1.3.7 -
[]
ChangeLog
@ -12145,7 +12515,7 @@ cdrskin/cdrskin_eng.html
cdrskin/changelog.txt
Updated change log
------------------------------------ cycle - cdrskin-1.3.3 -
------------------------------------ cycle - cdrskin-1.3.7 -
[]
ChangeLog
@ -12153,7 +12523,7 @@ cdrskin/cdrskin_eng.html
cdrskin/changelog.txt
Updated change log
------------------------------------ cycle - cdrskin-1.3.3 -
------------------------------------ cycle - cdrskin-1.3.7 -
**********************************************************************
@ -12165,7 +12535,12 @@ Important: When adding a public API function then add its name to file
TODO
===============================================================================
>>> consider an option to set the cdrskin startup message
>>> sg-netbsd.c os-netbsd.h
>>> check OpenBSD
----
CD-TEXT:
- with SAO

View File

@ -1,14 +1,14 @@
#!/bin/sh
# compile_cdrskin.sh
# Copyright 2005 - 2013 Thomas Schmitt, scdbackup@gmx.net, GPL v2 or later
# Copyright 2005 - 2014 Thomas Schmitt, scdbackup@gmx.net, GPL v2 or later
# to be executed within ./libburn-* resp ./cdrskin-*
debug_opts="-O2"
def_opts=
largefile_opts="-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1"
fifo_opts=""
libvers="-DCdrskin_libburn_1_3_2"
libvers="-DCdrskin_libburn_1_3_6"
# To be used if Makefile.am uses libburn_libburn_la_CFLAGS
# burn="libburn/libburn_libburn_la-"
@ -41,15 +41,15 @@ do
elif test "$i" = "-compile_dewav"
then
compile_dewav=1
elif test "$i" = "-libburn_1_3_2"
elif test "$i" = "-libburn_1_3_6"
then
libvers="-DCdrskin_libburn_1_3_2"
libvers="-DCdrskin_libburn_1_3_6"
libdax_audioxtr_o="$burn"libdax_audioxtr.o
libdax_msgs_o="$burn"libdax_msgs.o
cleanup_src_or_obj="$burn"cleanup.o
elif test "$i" = "-libburn_svn"
then
libvers="-DCdrskin_libburn_1_3_3"
libvers="-DCdrskin_libburn_1_3_7"
libdax_audioxtr_o="$burn"libdax_audioxtr.o
libdax_msgs_o="$burn"libdax_msgs.o
cleanup_src_or_obj="$burn"cleanup.o
@ -99,7 +99,7 @@ do
echo "Options:"
echo " -compile_cdrfifo compile program cdrskin/cdrfifo."
echo " -compile_dewav compile program test/dewav without libburn."
echo " -libburn_1_3_2 set macro to match libburn-1.3.2"
echo " -libburn_1_3_6 set macro to match libburn-1.3.6"
echo " -libburn_svn set macro to match current libburn-SVN."
echo " -dvd_obs_64k 64 KB default size for DVD/BD writing."
echo " -use_libcdio link with -lcdio because libburn uses it."

View File

@ -1,4 +1,4 @@
AC_INIT([libburn], [1.3.2], [http://libburnia-project.org])
AC_INIT([libburn], [1.3.6], [http://libburnia-project.org])
AC_PREREQ([2.50])
dnl AC_CONFIG_HEADER([config.h])
@ -102,6 +102,8 @@ dnl 1.2.6 = libburn.so.4.79.0
dnl 1.2.8 = libburn.so.4.81.0
dnl 1.3.0 = libburn.so.4.83.0
dnl 1.3.2 = libburn.so.4.85.0
dnl 1.3.4 = libburn.so.4.87.0
dnl 1.3.6 = libburn.so.4.89.0
dnl
dnl So LT_CURRENT, LT_REVISION and LT_AGE get set directly here.
dnl SONAME of the emerging library is LT_CURRENT - LT_AGE.
@ -127,7 +129,7 @@ dnl
dnl As said: Only copies. Original in libburn/libburn.h : burn_header_version_*
BURN_MAJOR_VERSION=1
BURN_MINOR_VERSION=3
BURN_MICRO_VERSION=2
BURN_MICRO_VERSION=6
BURN_VERSION=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION.$BURN_MICRO_VERSION
AC_SUBST(BURN_MAJOR_VERSION)
@ -138,14 +140,14 @@ AC_SUBST(BURN_VERSION)
dnl Libtool versioning
LT_RELEASE=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION.$BURN_MICRO_VERSION
dnl
dnl This is the release version libburn-1.3.2
dnl This is the release version libburn-1.3.6
dnl ### This is the development version after above release version
dnl LT_CURRENT++, LT_AGE++ has not yet happened.
dnl ### LT_CURRENT++, LT_AGE++ has happened meanwhile.
dnl
dnl SONAME = 89 - 85 = 4 . Linux library name = libburn.so.4.85.0
LT_CURRENT=89
LT_AGE=85
dnl SONAME = 93 - 89 = 4 . Linux library name = libburn.so.4.89.0
LT_CURRENT=93
LT_AGE=89
LT_REVISION=0
LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE`
@ -338,7 +340,7 @@ if test x$enable_debug != xyes; then
CFLAGS="-DNDEBUG $CFLAGS"
else
if test x$GCC = xyes; then
CFLAGS="-g -pedantic -Wall -Wextra -Wno-unused-parameter $CFLAGS"
CFLAGS="-g -pedantic -Wall -Wextra -Wno-unused-parameter -Wno-char-subscripts $CFLAGS"
fi
CFLAGS="-DDEBUG $CFLAGS"
fi

View File

@ -10,9 +10,9 @@ optical discs. This page is about its capability to handle optical media.
For now this means CD-R, CD-RW, DVD-RAM, DVD+RW, DVD+R, DVD+R/DL, DVD-RW,
DVD-R, DVD-R/DL, BD-R, BD-RE.
Our scope is currently Linux 2.4 and 2.6, or FreeBSD, or Solaris . For ports
to other systems we would need : login on a development machine resp.
an OS ithat is installable on an AMD 64-bit PC, advise from a system person
Our scope is currently Linux 2.4 and 2.6, FreeBSD, OpenSolaris, or NetBSD.
For ports to other systems we would need : login on a development machine resp.
an OS that is installable on an AMD 64-bit PC, advise from a system person
about the equivalent of Linux sg or FreeBSD CAM, volunteers for testing of
realistic use cases.

View File

@ -353,7 +353,7 @@ void burn_disc_erase(struct burn_drive *drive, int fast)
/* a ssert(!SCAN_GOING()); */
/* a ssert(!find_worker(drive)); */
if((drive == NULL)) {
if(drive == NULL) {
libdax_msgs_submit(libdax_messenger, -1,
0x00020104,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
@ -643,8 +643,7 @@ void burn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
if (d->drive_role == 1) {
mvalid = 0;
if (d->mdata != NULL)
if (d->mdata->valid > 0)
mvalid = 1;
mvalid = 1;
if (!mvalid) {
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x00020113,

View File

@ -1,7 +1,7 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2013 Thomas Schmitt <scdbackup@gmx.net>
Copyright (c) 2006 - 2014 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
@ -80,6 +80,7 @@ int burn_setup_drive(struct burn_drive *d, char *fname)
d->do_stream_recording = 0;
d->stream_recording_start= 0;
d->role_5_nwa = 0;
d->features = NULL;
return 1;
}
@ -104,6 +105,7 @@ void burn_drive_free_subs(struct burn_drive *d)
if (d->stdio_fd >= 0)
close (d->stdio_fd);
d->stdio_fd = -1;
burn_feature_descr_free(&(d->features), 0);
sg_dispose_drive(d, 0);
}
@ -261,8 +263,9 @@ int burn_drive_inquire_media(struct burn_drive *d)
/* ts A71128 : run read_disc_info() for any recognizeable profile */
if (d->current_profile > 0 || d->current_is_guessed_profile ||
d->mdata->cdr_write || d->mdata->cdrw_write ||
d->mdata->dvdr_write || d->mdata->dvdram_write) {
(d->mdata->p2a_valid > 0 &&
(d->mdata->cdr_write || d->mdata->cdrw_write ||
d->mdata->dvdr_write || d->mdata->dvdram_write)) ) {
#define Libburn_knows_correct_state_after_loaD 1
#ifdef Libburn_knows_correct_state_after_loaD
@ -424,6 +427,8 @@ fprintf(stderr, "LIBBURN_DEBUG: burn_drive__is_rdwr: getfl_ret = %lX , O_RDWR =
}
/* flag bit0= ( not needed yet: grab even if it is already grabbed )
*/
int burn_drive_grab_stdio(struct burn_drive *d, int flag)
{
int stat_ret = -1, is_rdwr, ret;
@ -537,6 +542,10 @@ int burn_drive_grab(struct burn_drive *d, int le)
{ret = 0; goto ex;}
ex:;
if (d->cancel || burn_is_aborting(0)) {
d->unlock(d);
d->release(d);
}
d->silent_on_scsi_error = sose;
d->busy = BURN_DRIVE_IDLE;
burn_grab_restore_sig_action(signal_action_mem, 0);
@ -570,6 +579,7 @@ struct burn_drive *burn_drive_register(struct burn_drive *d)
d->toc_entry = NULL;
d->disc = NULL;
d->erasable = 0;
d->write_opts = NULL;
#ifdef Libburn_ticket_62_re_register_is_possiblE
/* ts A60904 : ticket 62, contribution by elmom */
@ -638,7 +648,7 @@ struct burn_drive *burn_drive_finish_enum(struct burn_drive *d)
t->released = 1;
} else {
/* ts A90602 */
d->mdata->valid = -1;
d->mdata->p2a_valid = -1;
sprintf(msg, "Unable to grab scanned drive %s", d->devname);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x0002016f, LIBDAX_MSGS_SEV_DEBUG,
@ -675,6 +685,10 @@ int burn_drive_mark_unready(struct burn_drive *d, int flag)
free(d->toc_entry);
d->toc_entry = NULL;
d->toc_entries = 0;
if (d->write_opts != NULL) {
burn_write_opts_free(d->write_opts);
d->write_opts = NULL;
}
if (d->disc != NULL) {
burn_disc_free(d->disc);
d->disc = NULL;
@ -844,7 +858,7 @@ void burn_wait_all(void)
void burn_disc_erase_sync(struct burn_drive *d, int fast)
{
int ret;
int ret, was_error = 0;
if (d->drive_role == 5) { /* Random access write-only drive */
ret = truncate(d->devname, (off_t) 0);
@ -898,12 +912,16 @@ void burn_disc_erase_sync(struct burn_drive *d, int fast)
ret = d->get_erase_progress(d);
if (ret == -2 || ret > 0)
break;
if (ret == -3)
was_error = 1;
sleep(1);
}
while (1) {
ret = d->get_erase_progress(d);
if(ret == -2)
break;
if (ret == -3)
was_error = 1;
if (ret >= 0)
d->progress.sector = ret;
sleep(1);
@ -918,6 +936,8 @@ void burn_disc_erase_sync(struct burn_drive *d, int fast)
if (d->drive_role == 1)
burn_drive_inquire_media(d);
d->busy = BURN_DRIVE_IDLE;
if (was_error)
d->cancel = 1;
}
/*
@ -927,6 +947,7 @@ void burn_disc_erase_sync(struct burn_drive *d, int fast)
void burn_disc_format_sync(struct burn_drive *d, off_t size, int flag)
{
int ret, buf_secs, err, i, stages = 1, pbase, pfill, pseudo_sector;
int was_error = 0;
off_t num_bufs;
char msg[80];
struct buffer *buf = NULL, *buf_mem = d->buffer;
@ -971,12 +992,16 @@ void burn_disc_format_sync(struct burn_drive *d, off_t size, int flag)
ret = d->get_erase_progress(d);
if (ret == -2 || ret > 0)
break;
if (ret == -3)
was_error = 1;
sleep(1);
}
while (1) {
pseudo_sector = d->get_erase_progress(d);
if(pseudo_sector == -2)
break;
if (pseudo_sector == -3)
was_error = 1;
if (pseudo_sector >= 0)
d->progress.sector = pseudo_sector / stages;
sleep(1);
@ -1040,6 +1065,8 @@ ex:;
d->progress.sector = 0x10000;
d->busy = BURN_DRIVE_IDLE;
d->buffer = buf_mem;
if (was_error)
d->cancel = 1;
BURN_FREE_MEM(buf);
}
@ -1194,6 +1221,8 @@ static void strip_spaces(char *str)
static int drive_getcaps(struct burn_drive *d, struct burn_drive_info *out)
{
struct burn_scsi_inquiry_data *id;
int i, profile;
struct burn_feature_descr *feat;
/* ts A61007 : now prevented in enumerate_common() */
#if 0
@ -1201,7 +1230,7 @@ static int drive_getcaps(struct burn_drive *d, struct burn_drive_info *out)
a ssert(d->mdata);
#endif
if(d->idata->valid <= 0 || d->mdata->valid <= 0)
if(d->idata->valid <= 0)
return 0;
id = (struct burn_scsi_inquiry_data *)d->idata;
@ -1214,18 +1243,48 @@ static int drive_getcaps(struct burn_drive *d, struct burn_drive_info *out)
strip_spaces(out->revision);
strncpy(out->location, d->devname, 16);
out->location[16] = '\0';
out->buffer_size = d->mdata->buffer_size;
out->read_dvdram = !!d->mdata->dvdram_read;
out->read_dvdr = !!d->mdata->dvdr_read;
out->read_dvdrom = !!d->mdata->dvdrom_read;
out->read_cdr = !!d->mdata->cdr_read;
out->read_cdrw = !!d->mdata->cdrw_read;
out->write_dvdram = !!d->mdata->dvdram_write;
out->write_dvdr = !!d->mdata->dvdr_write;
out->write_cdr = !!d->mdata->cdr_write;
out->write_cdrw = !!d->mdata->cdrw_write;
out->write_simulate = !!d->mdata->simulate;
out->c2_errors = !!d->mdata->c2_pointers;
if (d->mdata->p2a_valid > 0) {
out->buffer_size = d->mdata->buffer_size;
out->read_dvdram = !!d->mdata->dvdram_read;
out->read_dvdr = !!d->mdata->dvdr_read;
out->read_dvdrom = !!d->mdata->dvdrom_read;
out->read_cdr = !!d->mdata->cdr_read;
out->read_cdrw = !!d->mdata->cdrw_read;
out->write_dvdram = !!d->mdata->dvdram_write;
out->write_dvdr = !!d->mdata->dvdr_write;
out->write_cdr = !!d->mdata->cdr_write;
out->write_cdrw = !!d->mdata->cdrw_write;
out->write_simulate = !!d->mdata->simulate;
out->c2_errors = !!d->mdata->c2_pointers;
} else {
out->buffer_size = out->read_dvdram = out->read_dvdr = 0;
out->read_dvdrom = out->read_cdr = out->read_cdrw = 0;
out->write_dvdram = out->write_dvdr = out->write_cdr = 0;
out->write_cdrw = out->write_simulate = out->c2_errors = 0;
for (i = 0; i < d->num_profiles; i++) {
profile = (d->all_profiles[i * 4] << 8) |
d->all_profiles[i * 4 + 1];
if (profile == 0x09)
out->write_cdr = out->read_cdr = 1;
else if (profile == 0x0a)
out->write_cdrw = out->read_cdrw = 1;
else if (profile == 0x10)
out->read_dvdrom = 1;
else if (profile == 0x11)
out->write_dvdr = out->read_dvdr = 1;
else if (profile == 0x12)
out->write_dvdram = out->read_dvdram = 1;
}
/* Test Write bit of CD TAO, CD Mastering, DVD-R/-RW Write */
for (i = 0x002D; i <= 0x002F; i++)
if (burn_drive_has_feature(d, i, &feat, 0))
if (feat->data_lenght > 0)
out->write_simulate |=
!!(feat->data[0] & 4);
}
out->drive = d;
#ifdef Libburn_dummy_probe_write_modeS
@ -1544,23 +1603,17 @@ void burn_sectors_to_msf(int sectors, int *m, int *s, int *f)
int burn_drive_get_read_speed(struct burn_drive *d)
{
if(d->mdata->valid <= 0)
return 0;
return d->mdata->max_read_speed;
}
int burn_drive_get_write_speed(struct burn_drive *d)
{
if(d->mdata->valid <= 0)
return 0;
return d->mdata->max_write_speed;
}
/* ts A61021 : New API function */
int burn_drive_get_min_write_speed(struct burn_drive *d)
{
if(d->mdata->valid <= 0)
return 0;
return d->mdata->min_write_speed;
}
@ -1852,8 +1905,10 @@ int burn_drive_scan_and_grab(struct burn_drive_info *drive_infos[], char* adr,
*/
ret = burn_drive_grab(drive_infos[0]->drive, load);
if (ret != 1)
if (ret != 1) {
burn_drive_forget(drive_infos[0]->drive, 0);
return -1;
}
return 1;
}
@ -2476,6 +2531,13 @@ int burn_disc_pretend_full(struct burn_drive *d)
return 1;
}
/* ts B31110 API function */
int burn_disc_pretend_full_uncond(struct burn_drive *d)
{
d->status = BURN_DISC_FULL;
return 1;
}
/* ts A61021: new API function */
int burn_disc_read_atip(struct burn_drive *d)
{
@ -2490,7 +2552,8 @@ int burn_disc_read_atip(struct burn_drive *d)
if(d->drive_role != 1)
return 0;
if ((d->current_profile == -1 || d->current_is_cd_profile)
&& (d->mdata->cdrw_write || d->current_profile != 0x08)) {
&& ((d->mdata->p2a_valid > 0 && d->mdata->cdrw_write) ||
d->current_profile != 0x08)) {
d->read_atip(d);
/* >>> some control of success would be nice :) */
} else {
@ -2719,8 +2782,6 @@ int burn_speed_descriptor_copy(struct burn_speed_descriptor *from,
/* ts A61226 : free dynamically allocated sub data of struct scsi_mode_data */
int burn_mdata_free_subs(struct scsi_mode_data *m)
{
if(!m->valid)
return 0;
burn_speed_descriptor_destroy(&(m->speed_descriptors), 1);
return 1;
}
@ -2734,8 +2795,6 @@ int burn_drive_get_speedlist(struct burn_drive *d,
struct burn_speed_descriptor *sd, *csd = NULL;
(*speed_list) = NULL;
if(d->mdata->valid <= 0)
return 0;
for (sd = d->mdata->speed_descriptors; sd != NULL; sd = sd->next) {
ret = burn_speed_descriptor_new(&csd, NULL, csd, 0);
if (ret <= 0)
@ -2759,8 +2818,6 @@ int burn_drive_get_best_speed(struct burn_drive *d, int speed_goal,
if (speed_goal < 0)
best_speed = 2000000000;
*best_descr = NULL;
if(d->mdata->valid <= 0)
return 0;
for (sd = d->mdata->speed_descriptors; sd != NULL; sd = sd->next) {
if (flag & 1)
speed = sd->read_speed;
@ -2904,7 +2961,8 @@ int burn_disc_get_multi_caps(struct burn_drive *d, enum burn_write_types wt,
o->multi_session = o->multi_track = 0;
else if(wt == BURN_WRITE_NONE || wt == BURN_WRITE_SAO ||
wt == BURN_WRITE_TAO)
o->might_simulate = !!d->mdata->simulate;
o->might_simulate = !!(d->mdata->p2a_valid > 0 &&
d->mdata->simulate);
} else if (d->current_profile == 0x11 || d->current_profile == 0x14 ||
d->current_profile == 0x15) {
/* DVD-R , sequential DVD-RW , DVD-R/DL Sequential */
@ -3389,3 +3447,80 @@ int burn_disc_get_leadin_text(struct burn_drive *d,
return ret;
}
/* ts B31023 API */
/* Inquire for DVD-RW failure of TAO
*/
int burn_drive_was_feat21_failure(struct burn_drive *d)
{
return !!d->was_feat21h_failure;
}
/* ts B40106 */
int burn_feature_descr_new(struct burn_feature_descr **new,
unsigned char *descr, int descr_len, int flag)
{
struct burn_feature_descr *o;
*new = NULL;
if (descr_len < 4)
return 0;
(*new) = o = calloc(1, sizeof(struct burn_speed_descriptor));
if (o == NULL)
return -1;
o->feature_code = (descr[0] << 8) | descr[1];
o->flags = descr[2];
if (descr[3] > descr_len - 4)
o->data_lenght = 0;
else
o->data_lenght = descr[3];
o->data = NULL;
o->next = NULL;
if (o->data_lenght > 0) {
o->data = calloc(1, o->data_lenght);
if (o->data == NULL) {
burn_feature_descr_free(new, 0);
return -1;
}
memcpy(o->data, descr + 4, o->data_lenght);
}
return 1;
}
/* ts B40106 */
int burn_feature_descr_free(struct burn_feature_descr **descr, int flag)
{
struct burn_feature_descr *o, *next;
if (*descr == NULL)
return 0;
for (o = *descr; o != NULL; o = next) {
next = o->next;
if (o->data != NULL)
free(o->data);
free((char *) o);
}
*descr = NULL;
return 1;
}
/* ts B40107 */
int burn_drive_has_feature(struct burn_drive *d, int feature_code,
struct burn_feature_descr **descr, int flag)
{
struct burn_feature_descr *o;
for (o = d->features; o != NULL; o = o->next) {
if (o->feature_code == feature_code) {
if (descr != NULL)
*descr = o;
return 1;
}
}
return 0;
}

View File

@ -1,7 +1,7 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2011 Thomas Schmitt <scdbackup@gmx.net>
Copyright (c) 2006 - 2014 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
@ -19,6 +19,7 @@ struct command;
struct mempage;
struct scsi_mode_data;
struct burn_speed_descriptor;
struct burn_feature_descr;
#define LEAD_IN 1
#define GAP 2
@ -155,4 +156,18 @@ int burn_abort_5(int patience,
/* Send a default mode page 05 to CD and DVD-R-oids */
int burn_drive_send_default_page_05(struct burn_drive *d, int flag);
/* ts B40106 */
int burn_feature_descr_new(struct burn_feature_descr **new,
unsigned char *descr, int descr_len, int flag);
/* ts B40106 */
int burn_feature_descr_free(struct burn_feature_descr **new, int flag);
/* ts B40107 */
int burn_drive_has_feature(struct burn_drive *d, int feature_code,
struct burn_feature_descr **descr, int flag);
int burn_drive_grab_stdio(struct burn_drive *d, int flag);
#endif /* __DRIVE */

View File

@ -937,7 +937,7 @@ int burn_drive_extract_audio(struct burn_drive *drive,
char *target_path, int flag)
{
int fd = -1, ret, todo, sector_no, val, min, sec, fr;
int sectors_done= 0, last_reported = 0;
int sectors_done= 0;
off_t data_size, data_count = 0;
time_t last_pacified = 0, now;
char *msg = NULL, *buf = NULL;
@ -1023,7 +1023,6 @@ write_error:;
LIBDAX_MSGS_SEV_UPDATE,
LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 1);
last_reported = sectors_done;
}
}
if ((flag & 1)) {
@ -1035,7 +1034,6 @@ write_error:;
LIBDAX_MSGS_SEV_UPDATE,
LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
last_reported = sectors_done;
}
ret = 1;
ex:;

View File

@ -1,7 +1,7 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2013 Thomas Schmitt <scdbackup@gmx.net>
Copyright (c) 2006 - 2014 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
This is the official API definition of libburn.
@ -594,6 +594,11 @@ struct burn_drive_info
to inquire a device file address. ^^^^^ ALWAYS ^^^^^^^*/
char location[17];
/* NOTE: The capability to write particular media types is also
announced by their profile number being in the list returned
by burn_drive_get_all_profile(). This is the only way to
inquire types DVD-RW, DVD+R, DVD+R DL, DVD+RW, BD-R, BD-RE.
*/
/** Can the drive read DVD-RAM discs */
unsigned int read_dvdram:1;
/** Can the drive read DVD-R discs */
@ -617,11 +622,13 @@ struct burn_drive_info
/** Can the drive simulate a write */
unsigned int write_simulate:1;
/** Can the drive report C2 errors */
/** DEPRECATED: Can the drive report C2 errors */
unsigned int c2_errors:1;
/** The size of the drive's buffer (in kilobytes) */
/** DEPRECATED: The size of the drive's buffer (in kilobytes) */
int buffer_size;
/**
* The supported block types in tao mode.
* They should be tested with the desired block type.
@ -713,7 +720,11 @@ struct burn_progress {
struct burn_speed_descriptor {
/** Where this info comes from :
0 = misc , 1 = mode page 2Ah , 2 = ACh GET PERFORMANCE */
0 = misc
1 = mode page 2Ah
2 = ACh GET PERFORMANCE Type 03h
3 = ACh GET PERFORMANCE Type 00h Data Type 10h (read speed)
*/
int source;
/** The media type that was current at the time of report
@ -1237,6 +1248,14 @@ int burn_disc_pretend_blank(struct burn_drive *drive);
int burn_disc_pretend_full(struct burn_drive *drive);
/* ts B31110 */
/** WARNING: This overrides the safety measures against unsuitable media.
Sets the drive status to BURN_DISC_FULL unconditionally.
@since 1.3.4
*/
int burn_disc_pretend_full_uncond(struct burn_drive *drive);
/* ts A61021 */
/** Reads ATIP information from inserted media. To be obtained via
burn_drive_get_write_speed(), burn_drive_get_min_write_speed(),
@ -1626,7 +1645,7 @@ void burn_disc_erase(struct burn_drive *drive, int fast);
/** Format media for use with libburn. This currently applies to DVD-RW
in state "Sequential Recording" (profile 0014h) which get formatted to
state "Restricted Overwrite" (profile 0013h). DVD+RW can be "de-iced"
by setting bit2 of flag. DVD-RAM and BD-RE may get formatted initially
by setting bit4 of flag. DVD-RAM and BD-RE may get formatted initially
or re-formatted to adjust their Defect Managment.
This function usually returns while the drive is still in the process
of formatting. The formatting is done, when burn_drive_get_status()
@ -1814,6 +1833,18 @@ void burn_drive_cancel(struct burn_drive *drive);
int burn_drive_wrote_well(struct burn_drive *d);
/* ts B31023 */
/** Inquire whether a write error occured which is suspected to have happened
due to a false report about DVD-RW capability to be written in write type
BURN_WRITE_TAO.
@param d The drive to inquire.
@return 1= it seems that BURN_WRITE_TAO on DVD-RW caused error,
0= it does not seem so
@since 1.3.4
*/
int burn_drive_was_feat21_failure(struct burn_drive *d);
/** Convert a minute-second-frame (MSF) value to sector count
@param m Minute component
@param s Second component
@ -3055,6 +3086,29 @@ void burn_write_opts_set_has_mediacatalog(struct burn_write_opts *opts,
*/
void burn_write_opts_set_multi(struct burn_write_opts *opts, int multi);
/* ts B31024 */
/** Set the severity to be used with write error messages which are potentially
caused by not using write type BURN_WRITE_SAO on fast blanked DVD-RW.
Normally the call burn_write_opts_auto_write_type() can prevent such
errors by looking for MMC feature 21h "Incremental Streaming Writable"
which anounnces the capability for BURN_WRITE_TAO and multi session.
Regrettable many drives announce feature 21h even if they only can do
BURN_WRITE_SAO. This mistake becomes obvious by an early write error.
If you plan to call burn_drive_was_feat21_failure() and to repeat the
burn attempt with BURN_WRITE_SAO, then set the severity of the error
message low enough, so that the application does not see reason to abort.
@param opts The option object to be manipulated
@param severity Severity as with burn_msgs_set_severities().
"ALL" or empty text means the default severity that
is attributed to other kinds of write errors.
*/
void burn_write_opts_set_fail21h_sev(struct burn_write_opts *opts,
char *severity);
/* ts B11204 */
/** Submit an array of CD-TEXT packs which shall be written to the Lead-in
of a SAO write run on CD.
@ -3539,7 +3593,7 @@ void burn_version(int *major, int *minor, int *micro);
*/
#define burn_header_version_major 1
#define burn_header_version_minor 3
#define burn_header_version_micro 2
#define burn_header_version_micro 6
/** Note:
Above version numbers are also recorded in configure.ac because libtool
wants them as parameters at build time.

View File

@ -32,6 +32,7 @@ burn_disc_get_status;
burn_disc_next_track_is_damaged;
burn_disc_pretend_blank;
burn_disc_pretend_full;
burn_disc_pretend_full_uncond;
burn_disc_read;
burn_disc_read_atip;
burn_disc_remove_session;
@ -73,6 +74,7 @@ burn_drive_set_buffer_waiting;
burn_drive_set_speed;
burn_drive_set_stream_recording;
burn_drive_snooze;
burn_drive_was_feat21_failure;
burn_drive_wrote_well;
burn_fd_source_new;
burn_fifo_fill;
@ -175,6 +177,7 @@ burn_write_opts_free;
burn_write_opts_get_drive;
burn_write_opts_new;
burn_write_opts_set_dvd_obs;
burn_write_opts_set_fail21h_sev;
burn_write_opts_set_fillup;
burn_write_opts_set_force;
burn_write_opts_set_format;

View File

@ -520,7 +520,7 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
0x0002014a (SORRY,HIGH) = Cannot read desired amount of data
0x0002014b (SORRY,HIGH) = Drive is already registered resp. scanned
0x0002014c (FATAL,HIGH) = Emulated drive caught in SCSI function
0x0002014d (SORRY,HIGH) = Asynchromous SCSI error
0x0002014d (SORRY,HIGH) = Asynchronous SCSI error
0x0002014f (SORRY,HIGH) = Timeout with asynchronous SCSI command
0x00020150 (DEBUG,LOW) = Reporting asynchronous waiting time
0x00020151 (FAILURE,HIGH) = Read attempt on write-only drive
@ -606,6 +606,10 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
0x000201a2 (FAILURE,HIGH) = Error while writing to disk file
0x000201a3 (UPDATE,HIGH) = Progress message of burn_drive_extract_audio()
0x000201a4 (FAILURE,HIGH) = Failure to read audio sectors
0x000201a5 (FAILURE,HIGH) = Asynchronous SCSI error
0x000201a6 (FATAL,HIGH) = Lost connection to drive
0x000201a7 (FAILURE,HIGH) = SCSI command yielded host problem
0x000201a8 (FAILURE,HIGH) = SCSI command yielded driver problem
libdax_audioxtr:

View File

@ -1,7 +1,7 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2012 Thomas Schmitt <scdbackup@gmx.net>
Copyright (c) 2006 - 2014 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
@ -168,6 +168,22 @@ extern struct libdax_msgs *libdax_messenger;
#define Libburn_wait_for_buffer_min_perC 65
#define Libburn_wait_for_buffer_max_perC 95
/* ts B31107 The minimum values to be applied if maximum read speed is
requested. Some drives tell only the currently set speed and
thus cannot be made faster by using the highest told value.
(The fractions get added or subtracted to yield an integer
number on the safe side of the intended limit.)
*/
#define Libburn_cd_max_read_speeD (52 * 150)
#define Libburn_dvd_max_read_speeD (24 * 1385)
#define Libburn_bd_max_read_speeD (20 * 4495.625 + 0.5)
/* ts B31114 The maximum values for minimum speed
*/
#define Libburn_cd_min_read_speeD ( 1 * 150)
#define Libburn_dvd_min_read_speeD ( 1 * 1385)
#define Libburn_bd_min_read_speeD ( 1 * 4495.625 - 0.625)
static unsigned char MMC_GET_MSINFO[] =
{ 0x43, 0, 1, 0, 0, 0, 0, 16, 0, 0 };
@ -1007,9 +1023,8 @@ fprintf(stderr, "libburn_DEBUG: buffer sectors= %d bytes= %d\n",
/* ts A61112 : react on eventual error condition */
spc_decode_sense(c->sense, 0, &key, &asc, &ascq);
if (c->error && key != 0) {
/* >>> make this scsi_notify_error() when liberated */
int key, asc, ascq;
int err_sev = LIBDAX_MSGS_SEV_FATAL;
msg = calloc(1, 256);
if (msg != NULL) {
@ -1017,13 +1032,33 @@ fprintf(stderr, "libburn_DEBUG: buffer sectors= %d bytes= %d\n",
start, len);
scsi_error_msg(d, c->sense, 14, msg + strlen(msg),
&key, &asc, &ascq);
}
/* ts B31023 */
/* Memorize if on DVD-RW write mode is TAO/Incremental and
error [5 64 00] occurs within the first drive buffer fill.
*/
if (d->current_profile == 0x14 && d->write_opts != NULL &&
(d->progress.buffer_capacity == 0 ||
start < (int) d->progress.buffer_capacity / 2048) &&
key == 5 && asc == 0x64 && ascq == 0) {
if (d->write_opts->write_type == BURN_WRITE_TAO) {
d->was_feat21h_failure = 1 + (start == 0);
if (d->write_opts->feat21h_fail_sev != 0)
err_sev =
d->write_opts->feat21h_fail_sev;
}
}
if (msg != NULL) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x0002011d,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
err_sev, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
free(msg);
}
d->cancel = 1;
return BE_CANCELLED;
}
@ -1488,7 +1523,8 @@ static int mmc_read_toc_al(struct burn_drive *d, int *alloc_len)
SanDisk Cruzer U3 memory stick stalls on format 2.
Format 0 seems to be more conservative with read-only drives.
*/
if (!(d->mdata->cdrw_write || d->current_profile != 0x08)) {
if (!((d->mdata->p2a_valid > 0 && d->mdata->cdrw_write) ||
d->current_profile != 0x08)) {
ret = mmc_read_toc_fmt0(d);
goto ex;
}
@ -2454,8 +2490,11 @@ int mmc_read_cd_msf(struct burn_drive *d,
const struct burn_read_opts *o, struct buffer *buf, int flag)
{
int req, ret, dap_bit;
int report_recovered_errors = 0, subcodes_audio = 0, subcodes_data = 0;
int subcodes_audio = 0, subcodes_data = 0;
struct command *c;
#ifdef Libburn_mmc_report_recovereD
int report_recovered_errors = 0;
#endif
c = &(d->casual_command);
mmc_start_if_needed(d, 0);
@ -2464,10 +2503,13 @@ int mmc_read_cd_msf(struct burn_drive *d,
dap_bit = flag & 1;
if (o != NULL) {
report_recovered_errors = o->report_recovered_errors;
subcodes_audio = o->subcodes_audio;
subcodes_data = o->subcodes_data;
dap_bit |= o->dap_bit;
#ifdef Libburn_mmc_report_recovereD
report_recovered_errors = o->report_recovered_errors;
#endif
}
scsi_init_command(c, MMC_READ_CD_MSF, sizeof(MMC_READ_CD_MSF));
@ -2482,11 +2524,12 @@ int mmc_read_cd_msf(struct burn_drive *d,
req = main_ch & 0xf8;
/* ts A61106 : LG GSA-4082B dislikes this. key=5h asc=24h ascq=00h
#ifdef Libburn_mmc_report_recovereD
/* ts A61106 : LG GSA-4082B dislikes this. key=5h asc=24h ascq=00h */
if (d->busy == BURN_DRIVE_GRABBING || report_recovered_errors)
req |= 2;
*/
#endif /* Libburn_mmc_report_recovereD */
c->opcode[9] = req;
c->opcode[10] = 0;
@ -2530,9 +2573,13 @@ int mmc_read_cd(struct burn_drive *d, int start, int len,
const struct burn_read_opts *o, struct buffer *buf, int flag)
{
int temp, req, ret, dap_bit;
int report_recovered_errors = 0, subcodes_audio = 0, subcodes_data = 0;
int subcodes_audio = 0, subcodes_data = 0;
struct command *c;
#ifdef Libburn_mmc_report_recovereD
int report_recovered_errors = 0;
#endif
/* # define Libburn_read_cd_by_msF 1 */
#ifdef Libburn_read_cd_by_msF
@ -2554,10 +2601,13 @@ int mmc_read_cd(struct burn_drive *d, int start, int len,
dap_bit = flag & 1;
if (o != NULL) {
report_recovered_errors = o->report_recovered_errors;
subcodes_audio = o->subcodes_audio;
subcodes_data = o->subcodes_data;
dap_bit |= o->dap_bit;
#ifdef Libburn_mmc_report_recovereD
report_recovered_errors = o->report_recovered_errors;
#endif
}
scsi_init_command(c, MMC_READ_CD, sizeof(MMC_READ_CD));
@ -2578,11 +2628,11 @@ int mmc_read_cd(struct burn_drive *d, int start, int len,
c->opcode[6] = len & 0xFF;
req = main_ch & 0xf8;
/* ts A61106 : LG GSA-4082B dislikes this. key=5h asc=24h ascq=00h
#ifdef Libburn_mmc_report_recovereD
/* ts A61106 : LG GSA-4082B dislikes this. key=5h asc=24h ascq=00h */
if (d->busy == BURN_DRIVE_GRABBING || report_recovered_errors)
req |= 2;
*/
#endif /* Libburn_mmc_report_recovereD */
c->opcode[9] = req;
c->opcode[10] = 0;
@ -2773,7 +2823,7 @@ ex:;
void mmc_set_speed(struct burn_drive *d, int r, int w)
{
struct command *c;
int ret, end_lba = 0;
int ret, end_lba = 0, get_max, get_min;
struct burn_speed_descriptor *best_sd = NULL;
c = &(d->casual_command);
@ -2783,15 +2833,51 @@ void mmc_set_speed(struct burn_drive *d, int r, int w)
if (r <= 0 || w <= 0) {
/* ts A70712 : now searching for best speed descriptor */
if (w > 0 && r <= 0)
/* ts B31030 : keeping max read speed from sinking too low */
if (r <= 0) {
get_max = (r == 0);
get_min = (r == -1);
burn_drive_get_best_speed(d, r, &best_sd, 1 | 2);
else
if (best_sd != NULL) {
r = best_sd->read_speed;
end_lba = best_sd->end_lba;
}
if (get_max) {
if (d->current_is_cd_profile) {
if (r < Libburn_cd_max_read_speeD)
r = Libburn_cd_max_read_speeD;
} else if (d->current_profile >= 0x10 &&
d->current_profile <= 0x2f) {
if (r < Libburn_dvd_max_read_speeD)
r = Libburn_dvd_max_read_speeD;
} else if (d->current_profile >= 0x40 &&
d->current_profile <= 0x43) {
if (r < Libburn_bd_max_read_speeD)
r = Libburn_bd_max_read_speeD;
}
} else if(get_min) {
if (d->current_is_cd_profile) {
if (r > Libburn_cd_min_read_speeD)
r = Libburn_cd_min_read_speeD;
} else if (d->current_profile >= 0x10 &&
d->current_profile <= 0x2f) {
if (r > Libburn_dvd_min_read_speeD)
r = Libburn_dvd_min_read_speeD;
} else if (d->current_profile >= 0x40 &&
d->current_profile <= 0x43) {
if (r > Libburn_bd_min_read_speeD)
r = Libburn_bd_min_read_speeD;
}
}
}
if (w <= 0) {
burn_drive_get_best_speed(d, w, &best_sd, 2);
if (best_sd != NULL) {
w = best_sd->write_speed;
d->nominal_write_speed = w;
r = best_sd->read_speed;
end_lba = best_sd->end_lba;
if (best_sd != NULL) {
w = best_sd->write_speed;
d->nominal_write_speed = w;
if (end_lba < best_sd->end_lba)
end_lba = best_sd->end_lba;
}
}
}
@ -2843,6 +2929,7 @@ static int mmc_get_configuration_al(struct burn_drive *d, int *alloc_len)
struct command *c = NULL;
int phys_if_std = 0;
char *phys_name = "";
struct burn_feature_descr *recent_feature = NULL, *new_feature;
/* Enable this to get loud and repeated reports about the feature set :
# define Libburn_print_feature_descriptorS 1
@ -2864,6 +2951,8 @@ static int mmc_get_configuration_al(struct burn_drive *d, int *alloc_len)
d->current_is_supported_profile = 0;
d->current_is_guessed_profile = 0;
d->num_profiles = 0;
if (d->features != NULL)
burn_feature_descr_free(&(d->features), 0);
d->current_has_feat21h = 0;
d->current_feat21h_link_size = -1;
d->current_feat23h_byte4 = 0;
@ -2995,6 +3084,17 @@ static int mmc_get_configuration_al(struct burn_drive *d, int *alloc_len)
descr_len = 4 + descr[3];
feature_code = (descr[0] << 8) | descr[1];
feature_is_current = descr[2] & 1;
ret = burn_feature_descr_new(&new_feature, descr,
up_to - descr, 0);
if (ret > 0) {
if (d->features == NULL)
d->features = new_feature;
else
recent_feature->next = new_feature;
recent_feature = new_feature;
}
if (only_current && !feature_is_current)
continue;
@ -3422,6 +3522,10 @@ int mmc_read_buffer_capacity(struct burn_drive *d)
(data[4]<<24)|(data[5]<<16)|(data[6]<<8)|data[7];
d->progress.buffer_available =
(data[8]<<24)|(data[9]<<16)|(data[10]<<8)|data[11];
if (d->progress.buffer_capacity < d->progress.buffer_available) {
/* Default mad buffer usage to 50 percent */
d->progress.buffer_available = d->progress.buffer_capacity / 2;
}
d->pessimistic_buffer_free = d->progress.buffer_available;
d->pbf_altered = 0;
if (d->progress.buffered_bytes >= d->progress.buffer_capacity){
@ -4107,41 +4211,182 @@ ex:;
}
/* ts A61225 */
/* @param flag bit0= register speed descriptors
/* ts B40107 : Outsourced from mmc_get_performance_al()
*/
static int mmc_get_write_performance_al(struct burn_drive *d,
int *alloc_len, int *max_descr, int flag)
static int new_burn_speed_descr(struct burn_drive *d, int sd_source,
struct burn_speed_descriptor **sd, int flag)
{
struct buffer *buf = NULL;
int len, i, b, num_descr, ret, old_alloc_len;
int exact_bit, read_speed, write_speed;
int ret;
/* >>> ts B10702: This rule seems questionable:
TSST SH-203 delivers here for CD only 7040k
whereas mode page 2Ah gives 1412k to 7056k
*/
/* if this call delivers usable data then they should override
previously recorded min/max speed and not compete with them */
ret = burn_speed_descriptor_new(&(d->mdata->speed_descriptors),
NULL, d->mdata->speed_descriptors, 0);
if (ret <= 0)
return ret;
*sd = d->mdata->speed_descriptors;
(*sd)->source = sd_source;
if (d->current_profile > 0) {
(*sd)->profile_loaded = d->current_profile;
strcpy((*sd)->profile_name, d->current_profile_text);
}
return 1;
}
/* ts B40107 : Outsourced from mmc_get_performance_al()
and extended for descr_type 0x00
@param flag bit0= register speed descriptors
*/
static int interpret_performance(struct burn_drive *d, struct command *c,
int descr_type, int *alloc_len, int *max_descr,
int *num_descr, int flag)
{
int len, i, b, ret, old_alloc_len;
int exact_bit, read_speed, write_speed, start_speed;
int min_write_speed = 0x7fffffff, max_write_speed = 0;
int min_read_speed = 0x7fffffff, max_read_speed = 0;
struct command *c = NULL;
unsigned long end_lba;
unsigned char *pd;
struct burn_speed_descriptor *sd;
/* A61225 : 1 = report about speed descriptors */
/* ts A61225 : 1 = report about speed descriptors */
static int speed_debug = 0;
len = mmc_four_char_to_int(c->page->data);
old_alloc_len = *alloc_len;
*alloc_len = len + 4;
if (len + 4 > old_alloc_len)
len = old_alloc_len - 4;
*num_descr = ( *alloc_len - 8 ) / 16;
if (*max_descr == 0) {
*max_descr = *num_descr;
{ret = 1; goto ex;}
}
if (old_alloc_len < 16)
{ret = 1; goto ex;}
if (len < 12)
{ret = 0; goto ex;}
min_write_speed = d->mdata->min_write_speed;
max_write_speed = d->mdata->max_write_speed;
pd = c->page->data;
if (*num_descr > *max_descr)
*num_descr = *max_descr;
for (i = 0; i < *num_descr && (flag & 1); i++) {
end_lba = read_speed = write_speed = start_speed = 0;
if (descr_type == 0x03) {
exact_bit = !!(pd[8 + i*16] & 2);
for (b = 0; b < 4 ; b++) {
end_lba += pd[8 + i*16 + 4 + b]
<< (24 - 8 * b);
read_speed += pd[8 + i*16 + 8 + b]
<< (24 - 8 * b);
write_speed += pd[8 + i*16 + 12 + b]
<< (24 - 8 * b);
}
if (end_lba > 0x7ffffffe)
end_lba = 0x7ffffffe;
if (speed_debug)
fprintf(stderr,
"LIBBURN_DEBUG: kB/s: write=%d read=%d end=%lu exact=%d\n",
write_speed, read_speed,
end_lba, exact_bit);
ret = new_burn_speed_descr(d, 2, &sd, 0);
if (ret > 0) {
sd->wrc = (pd[8 + i*16] >> 3 ) & 3;
sd->exact = exact_bit;
sd->mrw = pd[8 + i*16] & 1;
sd->end_lba = end_lba;
sd->write_speed = write_speed;
sd->read_speed = read_speed;
}
} else { /* descr_type == 0 */
for (b = 0; b < 4 ; b++) {
start_speed += pd[8 + i*16 + 4 + b]
<< (24 - 8 * b);
end_lba += pd[8 + i*16 + 8 + b]
<< (24 - 8 * b);
read_speed += pd[8 + i*16 + 12 + b]
<< (24 - 8 * b);
}
if (speed_debug)
fprintf(stderr,
"LIBBURN_DEBUG: start=%d end=%d lba=%lu\n",
start_speed, read_speed, end_lba);
if (end_lba > 0x7ffffffe)
end_lba = 0x7ffffffe;
ret = new_burn_speed_descr(d, 3, &sd, 0);
if (ret > 0) {
sd->end_lba = end_lba;
sd->read_speed = start_speed;
}
if (start_speed > 0 && start_speed < min_read_speed)
min_read_speed = start_speed;
if (start_speed > max_read_speed)
max_read_speed = start_speed;
ret = new_burn_speed_descr(d, 3, &sd, 0);
if (ret > 0) {
sd->end_lba = end_lba;
sd->read_speed = read_speed;
}
}
if ((int) end_lba > d->mdata->max_end_lba)
d->mdata->max_end_lba = end_lba;
if ((int) end_lba < d->mdata->min_end_lba)
d->mdata->min_end_lba = end_lba;
if (write_speed > 0 && write_speed < min_write_speed)
min_write_speed = write_speed;
if (write_speed > max_write_speed)
max_write_speed = write_speed;
if (read_speed > 0 && read_speed < min_read_speed)
min_read_speed = read_speed;
if (read_speed > max_read_speed)
max_read_speed = read_speed;
}
if (min_write_speed < 0x7fffffff)
d->mdata->min_write_speed = min_write_speed;
if (max_write_speed > 0)
d->mdata->max_write_speed = max_write_speed;
/* there is no mdata->min_read_speed yet
if (min_read_speed < 0x7fffffff)
d->mdata->min_read_speed = min_read_speed;
*/
if (max_read_speed > 0)
d->mdata->max_read_speed = max_read_speed;
ret = 1;
ex:;
return ret;
}
/* ts A61225 */
/* @param flag bit0= register speed descriptors
*/
static int mmc_get_performance_al(struct burn_drive *d, int descr_type,
int *alloc_len, int *max_descr, int flag)
{
int num_descr, ret;
struct buffer *buf = NULL;
struct command *c = NULL;
BURN_ALLOC_MEM(buf, struct buffer, 1);
BURN_ALLOC_MEM(c, struct command, 1);
if (d->current_profile <= 0)
if (d->current_profile < 0)
mmc_get_configuration(d);
if (*alloc_len < 8)
{ret = 0; goto ex;}
if (descr_type != 0x00 && descr_type != 0x03)
{ret = 0; goto ex;}
scsi_init_command(c, MMC_GET_PERFORMANCE,
sizeof(MMC_GET_PERFORMANCE));
@ -4152,9 +4397,11 @@ static int mmc_get_write_performance_al(struct burn_drive *d,
*/
c->dxfer_len = *alloc_len;
if (descr_type == 0x00)
c->opcode[1] = 0x10; /* Data Type: nominal read performance */
c->opcode[8] = ( *max_descr >> 8 ) & 0xff;
c->opcode[9] = ( *max_descr >> 0 ) & 0xff;
c->opcode[10] = 3;
c->opcode[10] = descr_type;
c->retry = 1;
c->page = buf;
c->page->sectors = 0;
@ -4172,86 +4419,12 @@ static int mmc_get_write_performance_al(struct burn_drive *d,
if (c->error)
{ret = 0; goto ex;}
len = mmc_four_char_to_int(c->page->data);
old_alloc_len = *alloc_len;
*alloc_len = len + 4;
if (len + 4 > old_alloc_len)
len = old_alloc_len - 4;
num_descr = ( *alloc_len - 8 ) / 16;
if (*max_descr == 0) {
*max_descr = num_descr;
{ret = 1; goto ex;}
}
if (old_alloc_len < 16)
{ret = 1; goto ex;}
if (len < 12)
{ret = 0; goto ex;}
/* ts B10702 : overriding the questionable override rule */
min_write_speed = d->mdata->min_write_speed;
max_write_speed = d->mdata->max_write_speed;
ret = interpret_performance(d, c, descr_type, alloc_len, max_descr,
&num_descr, flag);
if (ret <= 0)
goto ex;
pd = c->page->data;
if (num_descr > *max_descr)
num_descr = *max_descr;
for (i = 0; i < num_descr && (flag & 1); i++) {
exact_bit = !!(pd[8 + i*16] & 2);
end_lba = read_speed = write_speed = 0;
for (b = 0; b < 4 ; b++) {
end_lba += pd[8 + i*16 + 4 + b] << (24 - 8 * b);
read_speed += pd[8 + i*16 + 8 + b] << (24 - 8 * b);
write_speed += pd[8 + i*16 + 12 + b] << (24 - 8 * b);
}
if (end_lba > 0x7ffffffe)
end_lba = 0x7ffffffe;
if (speed_debug)
fprintf(stderr,
"LIBBURN_DEBUG: kB/s: write=%d read=%d end=%lu exact=%d\n",
write_speed, read_speed, end_lba, exact_bit);
/* ts A61226 */
ret = burn_speed_descriptor_new(&(d->mdata->speed_descriptors),
NULL, d->mdata->speed_descriptors, 0);
if (ret > 0) {
sd = d->mdata->speed_descriptors;
sd->source = 2;
if (d->current_profile > 0) {
sd->profile_loaded = d->current_profile;
strcpy(sd->profile_name,
d->current_profile_text);
}
sd->wrc = (pd[8 + i*16] >> 3 ) & 3;
sd->exact = exact_bit;
sd->mrw = pd[8 + i*16] & 1;
sd->end_lba = end_lba;
sd->write_speed = write_speed;
sd->read_speed = read_speed;
}
if ((int) end_lba > d->mdata->max_end_lba)
d->mdata->max_end_lba = end_lba;
if ((int) end_lba < d->mdata->min_end_lba)
d->mdata->min_end_lba = end_lba;
if (write_speed < min_write_speed)
min_write_speed = write_speed;
if (write_speed > max_write_speed)
max_write_speed = write_speed;
if (read_speed < min_read_speed)
min_read_speed = read_speed;
if (read_speed > max_read_speed)
max_read_speed = read_speed;
}
if (min_write_speed < 0x7fffffff)
d->mdata->min_write_speed = min_write_speed;
if (max_write_speed > 0)
d->mdata->max_write_speed = max_write_speed;
/* there is no mdata->min_read_speed yet
if (min_read_speed < 0x7fffffff)
d->mdata->min_read_speed = min_read_speed;
*/
if (max_read_speed > 0)
d->mdata->max_read_speed = max_read_speed;
ret = num_descr;
ex:;
BURN_FREE_MEM(buf);
@ -4260,7 +4433,7 @@ ex:;
}
int mmc_get_write_performance(struct burn_drive *d)
int mmc_get_performance(struct burn_drive *d, int descr_type, int flag)
{
int alloc_len = 8, max_descr = 0, ret;
@ -4271,27 +4444,37 @@ int mmc_get_write_performance(struct burn_drive *d)
/* first command execution to learn number of descriptors and
dxfer_len
*/
ret = mmc_get_write_performance_al(d, &alloc_len, &max_descr, 0);
ret = mmc_get_performance_al(d, descr_type, &alloc_len, &max_descr, 0);
if (max_descr > 0 && ret > 0) {
/* Some drives announce only 1 descriptor if asked for 0.
So ask twice for non-0 descriptors.
*/
ret = mmc_get_write_performance_al(d, &alloc_len, &max_descr,
0);
ret = mmc_get_performance_al(d, descr_type,
&alloc_len, &max_descr, 0);
}
/*
fprintf(stderr,"LIBBURN_DEBUG: ACh alloc_len = %d , ret = %d\n",
alloc_len, ret);
*/
if (max_descr > 0 && ret > 0)
if (max_descr > 0 && ret > 0) {
/* final execution with announced length */
max_descr = (alloc_len - 8) / 16;
ret = mmc_get_write_performance_al(d, &alloc_len, &max_descr,
1);
ret = mmc_get_performance_al(d, descr_type,
&alloc_len, &max_descr, 1);
}
return ret;
}
int mmc_get_write_performance(struct burn_drive *d)
{
int ret;
ret = mmc_get_performance(d, 0x03, 0);
return ret;
}
/* ts A61229 : outsourced from spc_select_write_params() */
/* Note: Page data is not zeroed here to allow preset defaults. Thus
memset(pd, 0, 2 + d->mdata->write_page_length);
@ -4881,7 +5064,7 @@ int mmc_get_media_product_id(struct burn_drive *d,
/* Check whether the drive supports format 11h */
has_11h = 0;
ret = mmc_read_disc_structure(d, 0, 0, 4, 0xff, &reply,
ret = mmc_read_disc_structure(d, 0, 0, 0xff, 4, &reply,
&reply_len, 0);
if (ret > 0) {
for (i = 0; i < reply_len; i += 4) {
@ -5137,6 +5320,7 @@ int mmc_setup_drive(struct burn_drive *d)
d->wfb_timeout_sec = Libburn_wait_for_buffer_tio_seC;
d->wfb_min_percent = Libburn_wait_for_buffer_min_perC;
d->wfb_max_percent = Libburn_wait_for_buffer_max_perC;
d->sent_default_page_05 = 0;
return 1;
}

View File

@ -1,7 +1,7 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Copyright (c) 2006 - 2014 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
@ -127,6 +127,9 @@ int mmc_get_phys_format_info(struct burn_drive *d, int *disk_category,
int mmc_get_leadin_text(struct burn_drive *d,
unsigned char **text_packs, int *num_packs, int flag);
/* ts B40107 */
int mmc_get_performance(struct burn_drive *d, int descr_type, int flag);
#ifdef Libburn_develop_quality_scaN
/* B21108 ts */

View File

@ -20,6 +20,7 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger;
@ -43,7 +44,8 @@ struct burn_write_opts *burn_write_opts_new(struct burn_drive *drive)
opts->toc_entry = NULL;
opts->toc_entries = 0;
opts->simulate = 0;
opts->underrun_proof = drive->mdata->underrun_proof;
opts->underrun_proof = drive->mdata->p2a_valid > 0 &&
drive->mdata->underrun_proof;
opts->perform_opc = 1;
opts->obs = -1;
@ -78,6 +80,25 @@ void burn_write_opts_free(struct burn_write_opts *opts)
free(opts);
}
int burn_write_opts_clone(struct burn_write_opts *from,
struct burn_write_opts **to, int flag)
{
if (*to != NULL)
burn_write_opts_free(*to);
if (from == NULL)
return 1;
*to = calloc(1, sizeof(struct burn_write_opts));
if (*to == NULL) {
libdax_msgs_submit(libdax_messenger, -1, 0x00000003,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Out of virtual memory", 0, 0);
return -1;
}
memcpy(*to, from, sizeof(struct burn_write_opts));
(*to)->refcount= 1;
return 1;
}
struct burn_read_opts *burn_read_opts_new(struct burn_drive *drive)
{
struct burn_read_opts *opts;
@ -152,17 +173,6 @@ void burn_write_opts_set_format(struct burn_write_opts *opts, int format)
int burn_write_opts_set_simulate(struct burn_write_opts *opts, int sim)
{
/* <<< ts A70529 :
One cannot predict the ability to simulate from page 05h
information alone. This check is now done later in
function burn_write_opts_auto_write_type().
if (opts->drive->mdata->simulate) {
opts->simulate = sim;
return 1;
}
return 0;
*/
opts->simulate = !!sim;
return 1;
}
@ -170,9 +180,8 @@ int burn_write_opts_set_simulate(struct burn_write_opts *opts, int sim)
int burn_write_opts_set_underrun_proof(struct burn_write_opts *opts,
int underrun_proof)
{
if (opts->drive->mdata->valid <= 0)
return 0;
if (opts->drive->mdata->underrun_proof) {
if (opts->drive->mdata->p2a_valid <= 0 ||
opts->drive->mdata->underrun_proof) {
opts->underrun_proof = underrun_proof;
return 1;
}
@ -204,6 +213,21 @@ void burn_write_opts_set_multi(struct burn_write_opts *opts, int multi)
}
/* ts B31024 */
/* API */
void burn_write_opts_set_fail21h_sev(struct burn_write_opts *opts,
char *severity)
{
int ret, sevno;
ret = libdax_msgs__text_to_sev(severity, &sevno, 0);
if (ret <= 0)
opts->feat21h_fail_sev = 0;
else
opts->feat21h_fail_sev = sevno;
}
/* ts B11204 */
/* @param flag bit0=do not verify checksums
bit1= repair mismatching checksums

View File

@ -1,6 +1,6 @@
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2012 Thomas Schmitt <scdbackup@gmx.net>
Copyright (c) 2006 - 2013 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
@ -81,9 +81,19 @@ struct burn_write_opts
unsigned char mediacatalog[13];
/** Session format */
int format;
/* internal use only */
unsigned char control;
/* Whether to keep medium appendable */
unsigned char multi;
/* ts B31024 */
/* The severity to be attributed to error messages about failed
write attempt with blank DVD-RW, possibly due to falsely reported
feature 21h Incremental Streaming Writable
*/
int feat21h_fail_sev;
};
/* Default value for burn_write_opts.stdio_flush_size
@ -139,4 +149,9 @@ struct burn_read_opts
};
int burn_write_opts_clone(struct burn_write_opts *from,
struct burn_write_opts **to, int flag);
#endif /* BURN__OPTIONS_H */

71
libburn/os-netbsd.h Normal file
View File

@ -0,0 +1,71 @@
/* os-netbsd.h
Operating system specific libburn definitions and declarations. Included
by os.h in case of compilation for
NetBSD 6
with MMC transport adapter sg-netbsd.c
>>> for OpenBSD too ?
Copyright (C) 2010 - 2014 Thomas Schmitt <scdbackup@gmx.net>
provided under GPLv2+
Derived 2014 from libburn/os-solaris.c
*/
/** List of all signals which shall be caught by signal handlers and trigger
a graceful abort of libburn. (See man signal.h)
*/
/* Once as system defined macros */
#define BURN_OS_SIGNAL_MACRO_LIST \
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, \
SIGABRT, SIGEMT, SIGFPE, SIGBUS, SIGSEGV, \
SIGSYS, SIGPIPE, SIGALRM, SIGTERM, SIGXCPU, \
SIGXFSZ, SIGVTALRM, SIGPROF, SIGUSR1, SIGUSR2
/* Once as text 1:1 list of strings for messages and interpreters */
#define BURN_OS_SIGNAL_NAME_LIST \
"SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGTRAP", \
"SIGABRT", "SIGEMT", "SIGFPE", "SIGBUS", "SIGSEGV", \
"SIGSYS", "SIGPIPE", "SIGALRM", "SIGTERM", "SIGXCPU", \
"SIGXFSZ", "SIGVTALRM", "SIGPROF", "SIGUSR1", "SIGUSR2"
/* The number of above list items */
#define BURN_OS_SIGNAL_COUNT 20
/** To list all signals which shall surely not be caught */
#define BURN_OS_NON_SIGNAL_MACRO_LIST \
SIGKILL, SIGURG, SIGSTOP, SIGTSTP, SIGCONT, \
SIGCHLD, SIGTTIN, SIGTTOU, SIGIO, SIGWINCH, \
SIGINFO, SIGPWR
/* The number of above list items */
#define BURN_OS_NON_SIGNAL_COUNT 12
/* The maximum size for a (SCSI) i/o transaction */
/* Important : MUST be at least 32768 ! */
/* My Blu-ray burner LG GGW-H20 writes junk if stream recording is combined
with buffer size 32 kB. So stream recording is allowed only with size 64k.
*/
/* >>> ??? Does it do 64 kB ? */
#define BURN_OS_TRANSPORT_BUFFER_SIZE 65536
/* To hold the position of the most recently delivered address from
device enumeration.
*/
struct burn_drive_enumerator_struct {
int cdno;
};
#define BURN_OS_DEFINE_DRIVE_ENUMERATOR_T \
typedef struct burn_drive_enumerator_struct burn_drive_enumerator_t;
/* The list of operating system dependent elements in struct burn_drive.
Usually they are initialized in sg-*.c:enumerate_common().
*/
#define BURN_OS_TRANSPORT_DRIVE_ELEMENTS \
int fd;

View File

@ -3,7 +3,8 @@
Operating system specific libburn definitions and declarations.
The macros defined here are used by libburn modules in order to
avoid own system dependent case distinctions.
Copyright (C) 2009 Thomas Schmitt <scdbackup@gmx.net>, provided under GPLv2+
Copyright (C) 2009 - 2014 Thomas Schmitt <scdbackup@gmx.net>,
provided under GPLv2+
*/
#ifndef BURN_OS_H_INCLUDED
@ -14,6 +15,12 @@
*/
/* <<< Until it is known whether this adapter would work on OpenBSD too */
#ifdef __NetBSD__
#define Libburn_use_sg_netbsD
#endif
#ifdef Libburn_use_sg_dummY
@ -29,6 +36,15 @@
#include "os-libcdio.h"
#else
#ifdef Libburn_use_sg_netbsD
/* To become: # ifdef __NetBSD__ */
/* -------------------------- NetBSD with SCIOCCOMMAND --------------------- */
#include "os-netbsd.h"
#else
#ifdef __FreeBSD__
@ -72,6 +88,7 @@
#endif /* ! __linux */
#endif /* ! __FreeBSD__kernel__ */
#endif /* ! __FreeBSD__ */
#endif /* ! Libburn_use_sg_netbsD */
#endif /* ! Libburn_use_libcdiO */
#endif /* ! Libburn_use_sg_dummY */

View File

@ -492,13 +492,13 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
out.idata = calloc(1, sizeof(struct burn_scsi_inquiry_data));
out.idata->valid = 0;
out.mdata = calloc(1, sizeof(struct scsi_mode_data));
out.mdata->valid = 0;
if (out.idata == NULL || out.mdata == NULL) {
libdax_msgs_submit(libdax_messenger, -1, 0x00020108,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Could not allocate new drive object", 0, 0);
return;
}
out.mdata->p2a_valid = 0;
memset(&out.params, 0, sizeof(struct params));
t = burn_drive_register(&out);

View File

@ -1,7 +1,7 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2013 Thomas Schmitt <scdbackup@gmx.net>
Copyright (c) 2006 - 2014 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
@ -436,7 +436,8 @@ static int sgio_test(int fd)
c_end_time = burn_get_time(0);
sgio_log_reply(s.cmdp, NO_TRANSFER, NULL, 0, NULL,
s.sbp, s.sb_len_wr, c_end_time - c_start_time, 0);
(unsigned char *) (s.sbp),
s.sb_len_wr, c_end_time - c_start_time, 0);
return ret;
}
@ -483,7 +484,8 @@ static int sgio_inquiry_cd_drive(int fd, char *fname)
}
sgio_log_reply(s.cmdp, FROM_DRIVE, buf->data, s.dxfer_len, NULL,
s.sbp, s.sb_len_wr, c_end_time - c_start_time, 0);
(unsigned char *) (s.sbp),
s.sb_len_wr, c_end_time - c_start_time, 0);
if (s.sb_len_wr > 0 || s.host_status != Libburn_sg_host_oK ||
s.driver_status != Libburn_sg_driver_oK) {
@ -492,7 +494,8 @@ static int sgio_inquiry_cd_drive(int fd, char *fname)
sprintf(msg + strlen(msg), " , sense data=");
msg_pt = msg + strlen(msg);
for (i = 0 ; i < s.sb_len_wr; i++)
sprintf(msg_pt + i * 3, " %2.2X", s.sbp[i]);
sprintf(msg_pt + i * 3, " %2.2X",
((unsigned char *) (s.sbp))[i]);
}
libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
@ -1884,6 +1887,167 @@ int sg_release(struct burn_drive *d)
return 0;
}
/* @return -1= transport failed, give up drive
0= transport failed, do not retry
1= transport succeeded
2- transport failed, please retry
*/
static int evaluate_transport_success(struct burn_drive *d, struct command *c,
FILE *fp,
unsigned short host_status,
unsigned short driver_status)
{
int ret, do_retry= 0, give_up_drive= 0, sev;
char *msg = NULL, *host_problem, *driver_problem, *driver_sugg;
BURN_ALLOC_MEM(msg, char, 161);
if ((host_status == Libburn_sg_host_oK &&
(driver_status & 0xf7) == Libburn_sg_driver_oK) || c->error)
{ret = 1; goto ex;} /* No transport problems */
/* See http://www.tldp.org/HOWTO/SCSI-Generic-HOWTO/x291.html */
switch(host_status) {
case 0x00:
host_problem =
"SG_ERR_DID_OK (No error)";
break; case 0x01:
host_problem =
"SG_ERR_DID_NO_CONNECT (Could not connect before timeout period)";
give_up_drive= 1;
break; case 0x02:
host_problem =
"SG_ERR_DID_BUS_BUSY (Bus stayed busy through time out period)";
break; case 0x03:
host_problem =
"SG_ERR_DID_TIME_OUT (Timed out for miscellaneous reasons)";
break; case 0x04:
host_problem =
"SG_ERR_DID_BAD_TARGET (Bad target, device not responding ?)";
give_up_drive= 1;
break; case 0x05:
host_problem =
"SG_ERR_DID_ABORT (Told to abort)";
break; case 0x06:
host_problem =
"SG_ERR_DID_PARITY (Parity error)";
break; case 0x07:
host_problem =
"SG_ERR_DID_ERROR (Internal error detected in the host adapter)";
give_up_drive= 1;
break; case 0x08:
host_problem =
"SG_ERR_DID_RESET (The SCSI bus or the device have been reset)";
give_up_drive= 1;
break; case 0x09:
host_problem =
"SG_ERR_DID_BAD_INTR (Got an unexpected interrupt)";
break; case 0x0a:
host_problem =
"SG_ERR_DID_PASSTHROUGH (Force command past mid-layer)";
break; case 0x0b:
host_problem =
"SG_ERR_DID_SOFT_ERROR (The low level driver wants a retry)";
do_retry = 1;
break; default:
host_problem =
"? (unknown host_status code)";
}
if (host_status != Libburn_sg_host_oK) {
sprintf(msg, "SCSI command %2.2Xh yielded host problem: ",
(unsigned int) c->opcode[0]);
sprintf(msg+strlen(msg), "0x%x %s",
(unsigned int) host_status, host_problem);
sev = LIBDAX_MSGS_SEV_FAILURE;
if (do_retry && !give_up_drive)
sev = LIBDAX_MSGS_SEV_DEBUG;
libdax_msgs_submit(libdax_messenger, d->global_index,
0x000201a7, sev, LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0);
sprintf(msg, "--- SG_IO: host_status= 0x%x %s",
(unsigned int) host_status, host_problem);
scsi_log_message(d, fp, msg, 0);
}
switch (driver_status & 0x07) {
case 0:
driver_problem = "SG_ERR_DRIVER_OK";
break; case 1:
driver_problem = "SG_ERR_DRIVER_BUSY";
break; case 2:
driver_problem = "SG_ERR_DRIVER_SOFT";
break; case 3:
driver_problem = "SG_ERR_DRIVER_MEDIA";
break; case 4:
driver_problem = "SG_ERR_DRIVER_ERROR";
break; case 5:
driver_problem = "SG_ERR_DRIVER_INVALID";
break; case 6:
driver_problem = "SG_ERR_DRIVER_TIMEOUT";
break; case 7:
driver_problem = "SG_ERR_DRIVER_HARD";
break; default:
driver_problem = "(unknown driver_status code)";
}
switch (driver_status & 0xf0) {
case 0:
driver_sugg = "(no suggestion)";
break; case 0x10:
driver_sugg = "SG_ERR_SUGGEST_RETRY";
do_retry = 1;
break; case 0x20:
driver_sugg = "SG_ERR_SUGGEST_ABORT";
give_up_drive= 1;
break; case 0x30:
driver_sugg = "SG_ERR_SUGGEST_REMAP";
give_up_drive= 1;
break; case 0x40:
driver_sugg = "SG_ERR_SUGGEST_DIE";
give_up_drive= 1;
break; case 0x80:
driver_sugg = "SG_ERR_SUGGEST_SENSE";
default:
driver_sugg = "(unknown driver_status suggestion)";
}
if ((driver_status & 0xf7) != Libburn_sg_driver_oK) {
sprintf(msg, "SCSI command %2.2Xh yielded driver problem: ",
(unsigned int) c->opcode[0]);
sprintf(msg+strlen(msg), "driver_status= 0x%x %s / %s",
(unsigned int) driver_status,
driver_problem, driver_sugg);
sev = LIBDAX_MSGS_SEV_FAILURE;
if (do_retry && !give_up_drive)
sev = LIBDAX_MSGS_SEV_DEBUG;
libdax_msgs_submit(libdax_messenger, d->global_index,
0x000201a8, sev, LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0);
sprintf(msg, "--- SG_IO: driver_status= 0x%x %s / %s",
(unsigned int) driver_status,
driver_problem, driver_sugg);
scsi_log_message(d, fp, msg, 0);
}
if (! do_retry)
c->error = 1;
ret = give_up_drive ? -1 : do_retry ? 2 : 0;
ex:;
BURN_FREE_MEM(msg);
return ret;
}
static void react_on_drive_loss(struct burn_drive *d, struct command *c,
FILE *fp)
{
sg_close_drive(d);
d->released = 1;
d->busy = BURN_DRIVE_IDLE;
d->cancel = 1;
c->error = 1;
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x000201a6,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Lost connection to drive", 0, 0);
scsi_log_message(d, fp, "--- SG_IO: Gave up connection to drive", 0);
}
/** Sends a SCSI command to the drive, receives reply and evaluates wether
the command succeeded or shall be retried or finally failed.
@ -1923,8 +2087,6 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
"\n-----------------------------------------\n");
}
}
if (burn_sg_log_scsi & 3)
scsi_log_cmd(c,fp,0);
/* ts A61010 : with no fd there is no chance to send an ioctl */
if (d->fd < 0) {
@ -1932,8 +2094,11 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
{ret = 0; goto ex;}
}
c->error = 0;
memset(&s, 0, sizeof(sg_io_hdr_t));
if (burn_sg_log_scsi & 3)
scsi_log_cmd(c,fp,0);
s.interface_id = 'S';
@ -2012,32 +2177,33 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Failed to transfer command to drive",
errno, 0);
sg_close_drive(d);
d->released = 1;
d->busy = BURN_DRIVE_IDLE;
c->error = 1;
sprintf(msg, "--- SG_IO: return= -1 , ");
sprintf(msg + strlen(msg), "errno= %d , ", errno);
sprintf(msg + strlen(msg),
"host_status= 0x%x , driver_status= 0x%x",
(unsigned int) s.host_status,
(unsigned int) s.driver_status);
scsi_log_message(d, fp, msg, 0);
react_on_drive_loss(d, c, fp);
{ret = -1; goto ex;}
}
done = scsi_eval_cmd_outcome(d, c, fp, s.sbp, s.sb_len_wr,
done = scsi_eval_cmd_outcome(d, c, fp,
(unsigned char *) (s.sbp),
s.sb_len_wr,
start_time, s.timeout, i, 0);
if (d->cancel)
done = 1;
break;
ret = evaluate_transport_success(d, c, fp,
s.host_status, s.driver_status);
if (ret == -1)
react_on_drive_loss(d, c, fp);
if (ret <= 0)
{ret = -1; goto ex;}
if (d->cancel)
break;
/* if ! done : loop for retry */;
}
if (s.host_status != Libburn_sg_host_oK ||
(s.driver_status != Libburn_sg_driver_oK && !c->error)) {
sprintf(msg,
"SCSI command %2.2Xh indicates host or driver error:",
(unsigned int) c->opcode[0]);
sprintf(msg+strlen(msg),
" host_status= %xh , driver_status= %xh",
(unsigned int) s.host_status,
(unsigned int) s.driver_status);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x0002013b,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
}
ret = 1;
ex:;
BURN_FREE_MEM(msg);

895
libburn/sg-netbsd.c Normal file
View File

@ -0,0 +1,895 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/*
Copyright (c) 2010 - 2014 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
Derived 2014 from libburn/sg-solaris.c with information learned from
dvd+rw-tools, http://fxr.watson.org/fxr/source/sys/scsiio.h?v=NETBSD,
http://netbsd.gw.com/cgi-bin/man-cgi?scsi+4+NetBSD-current,
and experiments made by Freddy Fisker.
*/
/*
This is the main operating system dependent SCSI part of libburn. It implements
the transport level aspects of SCSI control and command i/o.
Present implementation: NetBSD 6, ioctl SCIOCCOMMAND
>>> ??? for OpenBSD too ?
PORTING:
Porting libburn typically will consist of adding a new operating system case
to the following switcher files:
os.h Operating system specific libburn definitions and declarations.
sg.c Operating system dependent transport level modules.
and of deriving the following system specific files from existing examples:
os-*.h Included by os.h. You will need some general system knowledge
about signals and knowledge about the storage object needs of your
transport level module sg-*.c.
sg-*.c This source module. You will need special system knowledge about
how to detect all potentially available drives, how to open them,
eventually how to exclusively reserve them, how to perform
SCSI transactions, how to inquire the (pseudo-)SCSI driver.
You will not need to care about CD burning, MMC or other high-level
SCSI aspects.
Said sg-*.c operations are defined by a public function interface, which has
to be implemented in a way that provides libburn with the desired services:
sg_id_string() returns an id string of the SCSI transport adapter.
It may be called before initialization but then may
return only a preliminary id.
sg_initialize() performs global initialization of the SCSI transport
adapter and eventually needed operating system
facilities. Checks for compatibility of supporting
software components.
sg_shutdown() performs global finalizations and releases golbally
aquired resources.
sg_give_next_adr() iterates over the set of potentially useful drive
address strings.
scsi_enumerate_drives() brings all available, not-whitelist-banned, and
accessible drives into libburn's list of drives.
sg_dispose_drive() finalizes adapter specifics of struct burn_drive
on destruction. Releases resources which were aquired
underneath scsi_enumerate_drives().
sg_drive_is_open() tells wether libburn has the given drive in use.
sg_grab() opens the drive for SCSI commands and ensures
undisturbed access.
sg_release() closes a drive opened by sg_grab()
sg_issue_command() sends a SCSI command to the drive, receives reply,
and evaluates wether the command succeeded or shall
be retried or finally failed.
sg_obtain_scsi_adr() tries to obtain SCSI address parameters.
burn_os_is_2k_seekrw() tells whether the given path leads to a file object
that can be used in 2 kB granularity by lseek(2),
read(2), and possibly write(2) if not read-only..
E.g. a USB stick or a hard disk.
burn_os_stdio_capacity() estimates the emulated media space of stdio-drives.
burn_os_open_track_src() opens a disk file in a way that allows best
throughput with file reading and/or SCSI write command
transmission.
burn_os_alloc_buffer() allocates a memory area that is suitable for file
descriptors issued by burn_os_open_track_src().
The buffer size may be rounded up for alignment
reasons.
burn_os_free_buffer() delete a buffer obtained by burn_os_alloc_buffer().
Porting hints are marked by the text "PORTING:".
Send feedback to libburn-hackers@pykix.org .
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
/** PORTING : ------- OS dependent headers and definitions ------ */
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>
#ifdef Libburn_os_has_statvfS
#include <sys/statvfs.h>
#endif /* Libburn_os_has_stavtfS */
#include <sys/ioctl.h>
#include <sys/scsiio.h>
/** PORTING : ------ libburn portable headers and definitions ----- */
#include "transport.h"
#include "drive.h"
#include "sg.h"
#include "spc.h"
#include "sbc.h"
#include "debug.h"
#include "toc.h"
#include "util.h"
#include "init.h"
#include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger;
/* is in portable part of libburn */
int burn_drive_is_banned(char *device_address);
int burn_drive_resolve_link(char *path, char adr[],
int *recursion_count, int flag); /* drive.c */
/* Whether to log SCSI commands:
bit0= log in /tmp/libburn_sg_command_log
bit1= log to stderr
bit2= flush every line
*/
extern int burn_sg_log_scsi;
/* ------------------------------------------------------------------------ */
/* PORTING: Private definitions. Port only if needed by public functions. */
/* (Public functions are listed below) */
/* ------------------------------------------------------------------------ */
/* Storage object is in libburn/init.c
whether to strive for exclusive access to the drive
*/
extern int burn_sg_open_o_excl;
/* ------------------------------------------------------------------------ */
/* PORTING: Private functions. Port only if needed by public functions */
/* (Public functions are listed below) */
/* ------------------------------------------------------------------------ */
static int sg_close_drive(struct burn_drive * d)
{
if (d->fd != -1) {
close(d->fd);
d->fd = -1;
return 1;
}
return 0;
}
/* ----------------------------------------------------------------------- */
/* PORTING: Private functions which contain publicly needed functionality. */
/* Their portable part must be performed. So it is probably best */
/* to replace the non-portable part and to call these functions */
/* in your port, too. */
/* ----------------------------------------------------------------------- */
/** Wraps a detected drive into libburn structures and hands it over to
libburn drive list.
*/
static void enumerate_common(char *fname,
int bus_no, int host_no,
int channel_no, int target_no, int lun_no)
{
int ret;
struct burn_drive out;
/* General libburn drive setup */
burn_setup_drive(&out, fname);
/* This transport adapter uses SCSI-family commands and models
(seems the adapter would know better than its boss, if ever) */
ret = burn_scsi_setup_drive(&out, bus_no, host_no, channel_no,
target_no, lun_no, 0);
if (ret <= 0)
return;
/* PORTING: ------------------- non portable part --------------- */
/* Transport adapter is NetBSD SCIOCCOMMAND */
/* Adapter specific handles and data */
out.fd = -1;
/* PORTING: ---------------- end of non portable part ------------ */
/* Adapter specific functions with standardized names */
out.grab = sg_grab;
out.release = sg_release;
out.drive_is_open = sg_drive_is_open;
out.issue_command = sg_issue_command;
/* Finally register drive and inquire drive information */
burn_drive_finish_enum(&out);
}
static int start_enum_rcdNx(burn_drive_enumerator_t *idx, int flag)
{
idx->cdno = -1;
return 1;
}
/* Trying /dev/rcd[0..63][dc] */
#define Libburn_netbsd_max_cdnuM 63
static int next_enum_rcdNx(burn_drive_enumerator_t *idx,
char adr[], int adr_size, int flag)
{
static char suffix[2] = {'d', 'c'};
struct stat stbuf;
int i, stat_ret;
char path[16];
while (idx->cdno < Libburn_netbsd_max_cdnuM) {
idx->cdno++;
for (i = 0; i < 2; i++) {
sprintf(path, "/dev/rcd%d%c", idx->cdno, suffix[i]);
stat_ret = stat(path, &stbuf);
if (stat_ret == -1)
continue;
if (!S_ISCHR(stbuf.st_mode))
continue;
if ((int) strlen(path) >= adr_size)
continue;
strcpy(adr, path);
return 1;
}
}
return 0;
}
/* Searching the first byte address that cannot be lseeked and read
*/
static int guess_size_by_seek_set(int fd, off_t *bytes, int flag)
{
static off_t abs_limit = ((off_t) 1024) * 1024 * 1024 * 1024 * 1024;
off_t i, step = ((off_t) 1024) * 1024 * 1024 * 1024, ret;
char buf[1];
*bytes = 0;
for (i = step; i < abs_limit; i += step) {
ret = lseek(fd, i, SEEK_SET);
if (ret == -1) {
i -= step;
step = step >> 1;
if (step > 0)
continue;
return 1;
}
ret = read(fd, buf, 1);
if (ret == -1) {
i -= step;
step = step >> 1;
if (step > 0)
continue;
return 1;
}
*bytes = i + 1;
}
return 0;
}
/* ------------------------------------------------------------------------ */
/* PORTING: Public functions. These MUST be ported. */
/* ------------------------------------------------------------------------ */
/** Returns the id string of the SCSI transport adapter and eventually
needed operating system facilities.
This call is usable even if sg_initialize() was not called yet. In that
case a preliminary constant message might be issued if detailed info is
not available yet.
@param msg returns id string
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_id_string(char msg[1024], int flag)
{
sprintf(msg, "internal NetBSD SCIOCCOMMAND adapter sg-netbsd");
return 1;
}
/** Performs global initialization of the SCSI transport adapter and eventually
needed operating system facilities. Checks for compatibility of supporting
software components.
@param msg returns ids and/or error messages of eventual helpers
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_initialize(char msg[1024], int flag)
{
return sg_id_string(msg, 0);
}
/** Performs global finalization of the SCSI transport adapter and eventually
needed operating system facilities. Releases globally aquired resources.
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_shutdown(int flag)
{
return 1;
}
/** Finalizes BURN_OS_TRANSPORT_DRIVE_ELEMENTS, the components of
struct burn_drive which are defined in os-*.h.
The eventual initialization of those components was made underneath
scsi_enumerate_drives().
This will be called when a burn_drive gets disposed.
@param d the drive to be finalized
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_dispose_drive(struct burn_drive *d, int flag)
{
return 1;
}
/** Returns the next index number and the next enumerated drive address.
The enumeration has to cover all available and accessible drives. It is
allowed to return addresses of drives which are not available but under
some (even exotic) circumstances could be available. It is on the other
hand allowed, only to hand out addresses which can really be used right
in the moment of this call. (This implementation chooses the former.)
@param idx An opaque handle. Make no own theories about it.
@param adr Takes the reply
@param adr_size Gives maximum size of reply including final 0
@param initialize 1 = start new,
0 = continue, use no other values for now
-1 = finish
@return 1 = reply is a valid address , 0 = no further address available
-1 = severe error (e.g. adr_size too small)
*/
int sg_give_next_adr(burn_drive_enumerator_t *idx,
char adr[], int adr_size, int initialize)
{
int ret;
if (initialize == 1) {
ret = start_enum_rcdNx(idx, 0);
if (ret <= 0)
return ret;
} else if (initialize == -1) {
return 0;
}
ret = next_enum_rcdNx(idx, adr, adr_size, 0);
return ret;
}
/** Brings all available, not-whitelist-banned, and accessible drives into
libburn's list of drives.
*/
int scsi_enumerate_drives(void)
{
burn_drive_enumerator_t idx;
int initialize = 1, ret, i_bus_no = -1, buf_size = 4096;
int i_host_no = -1, i_channel_no = -1, i_target_no = -1, i_lun_no = -1;
char *buf = NULL;
BURN_ALLOC_MEM(buf, char, buf_size);
while(1) {
ret = sg_give_next_adr(&idx, buf, buf_size, initialize);
initialize = 0;
if (ret <= 0)
break;
if (burn_drive_is_banned(buf))
continue;
sg_obtain_scsi_adr(buf, &i_bus_no, &i_host_no,
&i_channel_no, &i_target_no, &i_lun_no);
enumerate_common(buf,
i_bus_no, i_host_no, i_channel_no,
i_target_no, i_lun_no);
}
sg_give_next_adr(&idx, buf, buf_size, -1);
ret = 1;
ex:;
BURN_FREE_MEM(buf);
return ret;
}
/** Tells whether libburn has the given drive in use or exclusively reserved.
If it is "open" then libburn will eventually call sg_release() on it when
it is time to give up usage resp. reservation.
*/
/** Published as burn_drive.drive_is_open() */
int sg_drive_is_open(struct burn_drive * d)
{
return (d->fd != -1);
}
/** Opens the drive for SCSI commands and - if burn activities are prone
to external interference on your system - obtains an exclusive access lock
on the drive. (Note: this is not physical tray locking.)
A drive that has been opened with sg_grab() will eventually be handed
over to sg_release() for closing and unreserving.
*/
int sg_grab(struct burn_drive *d)
{
char *msg = NULL;
int os_errno, ret;
BURN_ALLOC_MEM(msg, char, 4096);
if (d->fd != -1) {
d->released = 0;
{ret = 1; goto ex;}
}
d->fd = open(d->devname, O_RDWR | O_NDELAY);
if (d->fd == -1) {
os_errno = errno;
sprintf(msg, "Could not grab drive '%s'", d->devname);
/* (errno == ENXIO is a device file with no drive attached) */
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020003,
errno == ENXIO ? LIBDAX_MSGS_SEV_DEBUG :
LIBDAX_MSGS_SEV_SORRY,
LIBDAX_MSGS_PRIO_HIGH,
msg, os_errno, 0);
{ret = 0; goto ex;}
}
d->released = 0;
/* Make sure by INQUIRY that this is really a MMC drive */
ret = spc_confirm_cd_drive(d, 0);
if (ret <= 0)
goto revoke;
/* # define Libburn_sg_netbsd_scsi_debuG */
#ifdef Libburn_sg_netbsd_scsi_debuG
{
static int sc_db = SC_DB_CMDS | SC_DB_FLOW;
ret = ioctl(d->fd, SCIOCDEBUG, &sc_db);
if (ret == -1)
fprintf(stderr,
"libburn_DEBUG: ioctl(%d, SCIOCDEBUG, &(0x%X)) returns %d, errno = %d\n",
d->fd, (unsigned int) sc_db, ret, errno);
}
#endif
{ret = 1; goto ex;}
revoke:;
sprintf(msg, "Could not grab drive '%s'.", d->devname);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020003,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
if (d->fd >= 0) {
close(d->fd);
d->fd = -1;
d->released = 1;
}
ret = 0;
ex:;
BURN_FREE_MEM(msg);
return ret;
}
/** PORTING: Is mainly about the call to sg_close_drive() and whether it
implements the demanded functionality.
*/
/** Gives up the drive for SCSI commands and releases eventual access locks.
(Note: this is not physical tray locking.)
*/
int sg_release(struct burn_drive *d)
{
if (d->fd < 0)
return 0;
sg_close_drive(d);
return 0;
}
/** Sends a SCSI command to the drive, receives reply and evaluates wether
the command succeeded or shall be retried or finally failed.
Returned SCSI errors shall not lead to a return value indicating failure.
The callers get notified by c->error. An SCSI failure which leads not to
a retry shall be notified via scsi_notify_error().
The Libburn_log_sg_commandS facility might be of help when problems with
a drive have to be examined. It shall stay disabled for normal use.
@return: 1 success , <=0 failure
*/
int sg_issue_command(struct burn_drive *d, struct command *c)
{
int i, timeout_ms, ret, key, asc, ascq, done = 0, sense_len, max_sl;
time_t start_time;
scsireq_t req;
char msg[160];
static FILE *fp = NULL;
c->error = 0;
if (d->fd == -1)
return 0;
if (burn_sg_log_scsi & 1) {
if (fp == NULL) {
fp= fopen("/tmp/libburn_sg_command_log", "a");
fprintf(fp,
"\n-----------------------------------------\n");
}
}
if (burn_sg_log_scsi & 3)
scsi_log_cmd(c,fp,0);
if (c->timeout > 0)
timeout_ms = c->timeout;
else
timeout_ms = 200000;
memset (&req, 0, sizeof(req));
memcpy(req.cmd, c->opcode, c->oplen);
req.cmdlen = c->oplen;
req.databuf = (caddr_t) c->page->data;
req.flags = SCCMD_ESCAPE; /* probably to make req.cmdlen significant */
req.timeout = timeout_ms;
max_sl = sizeof(c->sense) > SENSEBUFLEN ?
SENSEBUFLEN : sizeof(c->sense);
req.senselen = max_sl;
if (c->dir == TO_DRIVE) {
req.datalen = c->page->bytes;
req.flags |= SCCMD_WRITE;
} else if (c->dir == FROM_DRIVE) {
req.flags |= SCCMD_READ;
if (c->dxfer_len >= 0)
req.datalen = c->dxfer_len;
else
req.datalen = BUFFER_SIZE;
/* touch page so we can use valgrind */
memset(c->page->data, 0, BUFFER_SIZE);
} else {
req.flags |= SCCMD_READ;
req.datalen = 0;
}
/* retry-loop */
start_time = time(NULL);
for(i = 0; !done; i++) {
memset(c->sense, 0, sizeof(c->sense));
c->start_time = burn_get_time(0);
ret = ioctl(d->fd, SCIOCCOMMAND, &req);
/* <<< Fault mock-up
if (c->opcode[0] == 0x28) {
ret = -1;
errno = 9;
}
*/
c->end_time = burn_get_time(0);
/* #define Libburn_debug_sg_netbsD */
#ifdef Libburn_debug_sg_netbsD
fprintf(stderr, "libburn_DEBUG: ret= %d, retsts = 0x%X, senselen_used = %d, status = 0x%X, error= 0x%X\n", ret, (unsigned int) req.retsts, (int) req.senselen_used, (unsigned int) req.status, req.error);
fprintf(stderr, "libburn_DEBUG: datalen_used = %u\n",
(unsigned int) req.datalen_used);
#endif
if (ret != 0 ||
(req.retsts != SCCMD_SENSE && req.retsts != SCCMD_OK)) {
sprintf(msg, "Failed to transfer command to drive. (ioctl(%d, SCIOCCOMMAND) = %d, scsireq_t.retsts = 0x%X, errno= %d)",
d->fd, ret, (unsigned int) req.retsts, errno);
if (burn_sg_log_scsi & 3)
scsi_log_message(d, fp, msg, 0);
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x0002010c,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
msg, errno, 0);
sg_close_drive(d);
d->released = 1;
d->busy = BURN_DRIVE_IDLE;
c->error = 1;
return -1;
}
sense_len = 0;
if (req.retsts == SCCMD_SENSE) {
memcpy(c->sense, req.sense, max_sl);
sense_len = req.senselen > max_sl ?
max_sl : req.senselen;
}
spc_decode_sense(c->sense, sense_len, &key, &asc, &ascq);
if (key || asc || ascq)
sense_len = req.senselen;
else
sense_len = 0;
/* <<< Fault mock-up
if (c->opcode[0] == 0x5a) {
req.datalen_used = 0;
memset(c->page->data, 0, BUFFER_SIZE);
}
*/
if (c->dir == FROM_DRIVE && sense_len == 0 &&
req.datalen > 0 && req.datalen_used < req.datalen) {
sprintf(msg, "Short reply from SCSI command %2.2X: expected: %d, got: %d, req.retsts: 0x%X",
(unsigned int) c->opcode[0],
(int) req.datalen, (int) req.datalen_used,
(unsigned int) req.retsts);
if (burn_sg_log_scsi & 3)
scsi_log_message(d, fp, msg, 0);
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x00000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
if (req.datalen_used == 0)
c->error = 1;
c->dxfer_len = req.datalen_used;
}
done = scsi_eval_cmd_outcome(d, c, fp, c->sense, sense_len,
start_time, timeout_ms, i, 0);
if (d->cancel)
done = 1;
} /* end of retry-loop */
return 1;
}
/** Tries to obtain SCSI address parameters.
@return 1 is success , 0 is failure
*/
int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
int *target_no, int *lun_no)
{
int ret, fd = -1;
struct scsi_addr addr;
fd = open(path, O_RDWR | O_NDELAY);
if (fd == -1)
return 0;
*bus_no = *host_no = *channel_no = *target_no = *lun_no = 0;
memset(&addr, 0, sizeof(addr));
ret = ioctl(fd, SCIOCIDENTIFY, &addr);
if (ret != 0)
{ret = 0; goto ex;}
if (addr.type != TYPE_SCSI)
{ret = 0; goto ex;}
*bus_no = *host_no = addr.addr.scsi.scbus;
*channel_no = 0;
*target_no = addr.addr.scsi.target;
*lun_no = addr.addr.scsi.lun;
ret = 1;
ex:;
if (fd != -1)
close(fd);
return (0);
}
/** Tells wether a text is a persistent address as listed by the enumeration
functions.
*/
int sg_is_enumerable_adr(char* adr)
{
burn_drive_enumerator_t idx;
int initialize = 1, ret;
char buf[64];
while(1) {
ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize);
initialize = 0;
if (ret <= 0)
break;
if (strcmp(adr, buf) == 0) {
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
return 1;
}
}
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
return (0);
}
/* Return 1 if the given path leads to a regular file or a device that can be
seeked, read, and possibly written with 2 kB granularity.
*/
int burn_os_is_2k_seekrw(char *path, int flag)
{
struct stat stbuf;
int l, i, dev, tl;
char try[16], *cpt;
/* >>> ??? Is this a comprehensive list of lseek()-capable devices ? */
/* http://www.netbsd.org/docs/guide/en/chap-rmmedia.html */
static char dev_names[][4] = {
"fd", "rfd", "sd" , "cd", "rcd", "wd", ""};
if (path[0] == 0)
return 0;
if (stat(path, &stbuf) == -1)
return 0;
if (S_ISREG(stbuf.st_mode))
return 1;
if (S_ISBLK(stbuf.st_mode))
return 1;
/* Look for known device names which promise the desired capabilities */
if (strncmp(path, "/dev/", 5) != 0)
return 0;
l = strlen(path);
for (dev = 0; dev_names[dev][0] != 0; dev++) {
sprintf(try, "/dev/%s", dev_names[dev]);
tl = strlen(try);
if (strncmp(path, try, tl) != 0)
continue;
cpt = path + tl;
l -= tl;
for (i = 0; i < Libburn_netbsd_max_cdnuM; i++) {
sprintf(try + tl, "%d", i);
if (strncmp(path, try, strlen(try)) == 0)
break;
}
if (i >= Libburn_netbsd_max_cdnuM)
continue;
tl += strlen(try + tl);
if (l == tl)
return 1;
if (l > tl + 1)
continue;
if (path[l - 1] >= 'a' && path[l - 1] <= 'z')
return 1;
}
return 0;
}
/** Estimate the potential payload capacity of a file address.
@param path The address of the file to be examined. If it does not
exist yet, then the directory will be inquired.
@param bytes The pointed value gets modified, but only if an estimation is
possible.
@return -2 = cannot perform necessary operations on file object
-1 = neither path nor dirname of path exist
0 = could not estimate size capacity of file object
1 = estimation has been made, bytes was set
*/
int burn_os_stdio_capacity(char *path, off_t *bytes)
{
struct stat stbuf;
int ret;
#ifdef Libburn_os_has_statvfS
struct statvfs vfsbuf;
#endif
char *testpath = NULL, *cpt;
off_t add_size = 0;
BURN_ALLOC_MEM(testpath, char, 4096);
testpath[0] = 0;
if (stat(path, &stbuf) == -1) {
strcpy(testpath, path);
cpt = strrchr(testpath, '/');
if(cpt == NULL)
strcpy(testpath, ".");
else if(cpt == testpath)
testpath[1] = 0;
else
*cpt = 0;
if (stat(testpath, &stbuf) == -1)
{ret = -1; goto ex;}
} else if(S_ISBLK(stbuf.st_mode)) {
int open_mode = O_RDONLY, fd;
fd = open(path, open_mode);
if (fd == -1)
{ret = -2; goto ex;}
*bytes = lseek(fd, 0, SEEK_END);
if (*bytes <= 0)
guess_size_by_seek_set(fd, bytes, 0);
close(fd);
if (*bytes == -1) {
*bytes = 0;
{ret = 0; goto ex;}
}
} else if(S_ISREG(stbuf.st_mode)) {
add_size = stbuf.st_blocks * (off_t) 512;
strcpy(testpath, path);
} else
{ret = 0; goto ex;}
if (testpath[0]) {
#ifdef Libburn_os_has_statvfS
if (statvfs(testpath, &vfsbuf) == -1)
{ret = -2; goto ex;}
*bytes = add_size + ((off_t) vfsbuf.f_frsize) *
(off_t) vfsbuf.f_bavail;
#else /* Libburn_os_has_statvfS */
{ret = 0; goto ex;}
#endif /* ! Libburn_os_has_stavtfS */
}
ret = 1;
ex:;
BURN_FREE_MEM(testpath);
return ret;
}
/* ts A91122 : an interface to open(O_DIRECT) or similar OS tricks. */
#ifdef Libburn_read_o_direcT
/* No special O_DIRECT-like precautions are implemented here */
#endif /* Libburn_read_o_direcT */
int burn_os_open_track_src(char *path, int open_flags, int flag)
{
int fd;
fd = open(path, open_flags);
return fd;
}
void *burn_os_alloc_buffer(size_t amount, int flag)
{
void *buf = NULL;
buf = calloc(1, amount);
return buf;
}
int burn_os_free_buffer(void *buffer, size_t amount, int flag)
{
if (buffer == NULL)
return 0;
free(buffer);
return 1;
}

View File

@ -1,7 +1,7 @@
/* sg.c
Switcher for operating system dependent transport level modules of libburn.
Copyright (C) 2009 - 2010 Thomas Schmitt <scdbackup@gmx.net>,
Copyright (C) 2009 - 2014 Thomas Schmitt <scdbackup@gmx.net>,
provided under GPLv2+
*/
@ -11,6 +11,12 @@
#endif
/* <<< Until it is known whether this adapter would work on OpenBSD too */
#ifdef __NetBSD__
#define Libburn_use_sg_netbsD
#endif
#ifdef Libburn_use_sg_dummY
#include "sg-dummy.c"
@ -20,6 +26,12 @@
#include "sg-libcdio.c"
#else
#ifdef Libburn_use_sg_netbsD
/* To become: # ifdef __NetBSD__ */
#include "sg-netbsd.c"
#else
#ifdef __FreeBSD__
@ -58,11 +70,11 @@
static int intentional_compiler_warning(void)
{
int INTENTIONAL_COMPILER_WARNING_;
int Cannot_recognize_GNU_Linux_nor_FreeBSD_nor_Solaris_;
int Cannot_recognize_GNU_Linux_nor_FreeBSD_nor_Solaris_nor_NetBSD_;
int Have_to_use_dummy_MMC_transport_adapter_;
int This_libburn_will_not_be_able_to_operate_on_real_CD_drives;
int Have_to_use_dummy_MMC_transport_adapter;
int Cannot_recognize_GNU_Linux_nor_FreeBSD_nor_Solaris;
int Cannot_recognize_GNU_Linux_nor_FreeBSD_nor_Solaris_nor_NetBSD;
int INTENTIONAL_COMPILER_WARNING;
return(0);
@ -74,6 +86,7 @@ static int intentional_compiler_warning(void)
#endif /* ! __linux */
#endif /* ! __FreeBSD_kernel__ */
#endif /* ! __FreeBSD__ */
#endif /* ! Libburn_use_sg_netbsD */
#endif /* ! Libburn_use_libcdiO */
#endif /* ! Libburn_use_sg_dummY */

View File

@ -1,7 +1,7 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2013 Thomas Schmitt <scdbackup@gmx.net>
Copyright (c) 2006 - 2014 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
@ -261,7 +261,34 @@ void spc_request_sense(struct burn_drive *d, struct buffer *buf)
d->issue_command(d, c);
}
/* @return -2 = drive is ready , -1 = not ready, but no progress reported
static int spc_report_async_error(struct burn_drive *d,
int key, int asc, int ascq, int flag)
{
char *msg = NULL;
unsigned char sense[14];
int ret;
BURN_ALLOC_MEM(msg, char, BURN_DRIVE_ADR_LEN + 160);
sprintf(msg, "Asynchronous SCSI error : ");
sense[0] = 0x70; /* Fixed format sense data */
sense[2] = key;
sense[12] = asc;
sense[13] = ascq;
scsi_error_msg(d, sense, 14, msg + strlen(msg), &key, &asc, &ascq);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x000201a5,
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
ret = 1;
ex:;
BURN_FREE_MEM(msg);
return ret;
}
/* @return -3 = other error reported
-2 = drive is ready ,
-1 = not ready, but no progress reported ,
>= 0 progress indication between 0 and 65535
*/
int spc_get_erase_progress(struct burn_drive *d)
@ -279,6 +306,14 @@ int spc_get_erase_progress(struct burn_drive *d)
ret = spc_test_unit_ready_r(d, &key, &asc, &ascq, &progress);
if (ret > 0)
{ret = -2; goto ex;}
/* Check key, asc, ascq for errors other than "not yet ready" */
if (key != 0 &&
(key != 0x2 || asc != 0x04 || ascq == 0x02 || ascq ==0x03)) {
spc_report_async_error(d, key, asc, ascq, 0);
ret= -3; goto ex;
}
if (progress >= 0)
{ret = progress; goto ex;}
@ -317,6 +352,8 @@ void spc_inquiry(struct burn_drive *d)
c->dir = FROM_DRIVE;
d->issue_command(d, c);
id = (struct burn_scsi_inquiry_data *)d->idata;
id->peripheral = 0x7f; /* SPC-3: incabable undefined peripheral type */
id->version = 0; /* SPC-3: no claim for conformance */
memset(id->vendor, 0, 9);
memset(id->product, 0, 17);
memset(id->revision, 0, 5);
@ -324,6 +361,8 @@ void spc_inquiry(struct burn_drive *d)
id->valid = -1;
goto ex;
}
id->peripheral = ((char *) c->page->data)[0];
id->version = ((char *) c->page->data)[2];
memcpy(id->vendor, c->page->data + 8, 8);
memcpy(id->product, c->page->data + 16, 16);
memcpy(id->revision, c->page->data + 32, 4);
@ -367,10 +406,39 @@ void spc_allow(struct burn_drive *d)
d->issue_command(d, c);
}
/* ts B40216 : Outsourced from spc_sense_caps_al().
To be called by spc_sense_caps() after spc_sense_caps_al()
*/
static int spc_try_get_performance(struct burn_drive *d, int flag)
{
int ret;
struct burn_feature_descr *feature_descr;
/* ts B40107 : Feature 0x107 announces availability of GET PERFORMANCE
Its WSPD bit announces Type 3.
Try this even if the feature is not current.
*/
ret = burn_drive_has_feature(d, 0x107, &feature_descr, 0);
if (ret <= 0)
return ret;
if (feature_descr->data_lenght <= 0)
return 1;
if (feature_descr->data[0] & 2) /* WSPD */
ret = mmc_get_write_performance(d);
/* Get read performance */
mmc_get_performance(d, 0x00, 0);
return 1;
}
/*
ts A70518 - A90603 : Do not call with *alloc_len < 10
*/
/** flag&1= do only inquire alloc_len */
/** @param flag bit0= do only inquire alloc_len
@return 1=ok , <=0 error ,
2=Block Descriptor Length > 0, retry with flag bit1
*/
static int spc_sense_caps_al(struct burn_drive *d, int *alloc_len, int flag)
{
struct buffer *buf = NULL;
@ -394,7 +462,7 @@ static int spc_sense_caps_al(struct burn_drive *d, int *alloc_len, int flag)
/* ts A90602 : Clearing mdata before command execution */
m = d->mdata;
m->valid = 0;
m->p2a_valid = 0;
burn_mdata_free_subs(m);
memset(buf, 0, sizeof(struct buffer));
@ -411,7 +479,7 @@ static int spc_sense_caps_al(struct burn_drive *d, int *alloc_len, int flag)
d->issue_command(d, c);
if (c->error) {
memset(buf, 0, sizeof(struct buffer));
m->valid = -1;
m->p2a_valid = -1;
was_error = 1;
}
@ -420,6 +488,22 @@ static int spc_sense_caps_al(struct burn_drive *d, int *alloc_len, int flag)
*/
block_descr_len = c->page->data[6] * 256 + c->page->data[7];
if (block_descr_len + 8 + 2 > *alloc_len) {
if (block_descr_len + 8 + 2 > BUFFER_SIZE || !(flag & 1)) {
m->p2a_valid = -1;
sprintf(msg,
"MODE SENSE page 2A with oversized Block Descriptors: %s : %d",
d->devname, block_descr_len);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x0002016e, LIBDAX_MSGS_SEV_DEBUG,
LIBDAX_MSGS_PRIO_LOW, msg, 0, 0);
{ret = 0; goto ex;}
}
*alloc_len = block_descr_len + 10;
{ret = 2; goto ex;}
}
/* Skip over Mode Data Header and block descriptors */
page = c->page->data + 8 + block_descr_len;
@ -438,7 +522,7 @@ static int spc_sense_caps_al(struct burn_drive *d, int *alloc_len, int flag)
*/
page_length = page[1];
old_alloc_len = *alloc_len;
*alloc_len = page_length + 10;
*alloc_len = page_length + 10 + block_descr_len;
if (flag & 1)
{ret = !was_error; goto ex;}
if (page_length + 10 > old_alloc_len)
@ -447,7 +531,7 @@ static int spc_sense_caps_al(struct burn_drive *d, int *alloc_len, int flag)
/* ts A90602 : page_length N asserts page[N+1]. (see SPC-1 8.3.3) */
/* ts B11031 : qemu drive has a page_length of 18 */
if (page_length < 18) {
m->valid = -1;
m->p2a_valid = -1;
sprintf(msg, "MODE SENSE page 2A too short: %s : %d",
d->devname, page_length);
libdax_msgs_submit(libdax_messenger, d->global_index,
@ -489,13 +573,11 @@ static int spc_sense_caps_al(struct burn_drive *d, int *alloc_len, int flag)
m->max_end_lba = 0;
if (!was_error)
m->valid = 1;
mmc_get_configuration(d);
m->p2a_valid = 1;
/* ts A61225 : end of MMC-1 , begin of MMC-3 */
if (page_length < 30) /* no write speed descriptors ? */
goto try_mmc_get_performance;
goto no_speed_descriptors;
m->cur_write_speed = page[28] * 256 + page[29];
@ -549,24 +631,7 @@ static int spc_sense_caps_al(struct burn_drive *d, int *alloc_len, int flag)
"LIBBURN_DEBUG: 5Ah,2Ah min_write_speed = %d , max_write_speed = %d\n",
m->min_write_speed, m->max_write_speed);
try_mmc_get_performance:;
if (m->cdrw_write || page_length >= 32) {
/* ts A90823:
One has to avoid U3 enhanced memory sticks here. On my
SuSE 10.2 a SanDisk Cruzer 4GB stalls at the second occasion
of ACh GET PERFORMANCE. (The first one is obviously called
by the OS at plug time.)
This pseudo drive returns no write capabilities and a page
length of 28. MMC-3 describes page length 32. Regrettably
MMC-2 prescribes a page length of 26. Here i have to trust
m->cdrw_write to reliably indicate any MMC-2 burner.
*/
ret = mmc_get_write_performance(d);
if (ret > 0 && speed_debug)
fprintf(stderr,
"LIBBURN_DEBUG: ACh min_write_speed = %d , max_write_speed = %d\n",
m->min_write_speed, m->max_write_speed);
}
no_speed_descriptors:;
ret = !was_error;
ex:
@ -585,13 +650,19 @@ void spc_sense_caps(struct burn_drive *d)
if (mmc_function_spy(d, "sense_caps") <= 0)
return;
mmc_get_configuration(d);
/* first command execution to learn Allocation Length */
alloc_len = start_len;
ret = spc_sense_caps_al(d, &alloc_len, 1);
/*
fprintf(stderr,"LIBBURN_DEBUG: 5Ah alloc_len = %d , ret = %d\n",
alloc_len, ret);
*/
if (ret == 2) {
/* ts B40205: Unexpectedly found Block Descriptors.
Repeat with new alloc_len.
*/
ret = spc_sense_caps_al(d, &alloc_len, 1);
if (ret == 2)
goto try_get_performance;
}
/* ts B11103:
qemu ATAPI DVD-ROM delivers only 28.
SanDisk Cruzer U3 memory stick throws error on alloc_len < 30.
@ -600,6 +671,9 @@ void spc_sense_caps(struct burn_drive *d)
if (alloc_len >= minimum_len && ret > 0)
/* second execution with announced length */
spc_sense_caps_al(d, &alloc_len, 0);
try_get_performance:;
spc_try_get_performance(d, 0);
}
@ -629,7 +703,6 @@ void spc_sense_error_params(struct burn_drive *d)
c->page->sectors = 0;
c->dir = FROM_DRIVE;
d->issue_command(d, c);
m = d->mdata;
page = c->page->data + 8;
d->params.retries = page[3];
@ -655,6 +728,8 @@ void spc_select_error_params(struct burn_drive *d,
scsi_init_command(c, SPC_MODE_SELECT, sizeof(SPC_MODE_SELECT));
c->retry = 1;
if (d->mdata->retry_page_valid <= 0)
d->mdata->retry_page_length = 0;
c->opcode[8] = 8 + 2 + d->mdata->retry_page_length;
c->page = buf;
c->page->bytes = 0;
@ -714,9 +789,11 @@ void spc_sense_write_params(struct burn_drive *d)
if (!c->error) {
page = c->page->data + 8;
m->write_page_length = page[1];
m->write_page_valid = 1;
} else
m->write_page_valid = 0;
if (m->write_page_length > 0)
m->write_page_valid = 1;
else
m->write_page_length = 0x32;
}
mmc_read_disc_info(d);
/* ts A70212 : try to setup d->media_capacity_remaining */
@ -1019,8 +1096,14 @@ int burn_scsi_setup_drive(struct burn_drive *d, int bus_no, int host_no,
return -1;
}
d->idata->valid = 0;
d->mdata->valid = 0;
d->mdata->p2a_valid = 0;
d->mdata->max_read_speed = 0;
d->mdata->cur_read_speed = 0;
d->mdata->max_write_speed = 0;
d->mdata->cur_write_speed = 0;
d->mdata->speed_descriptors = NULL;
d->mdata->write_page_length = 0x32;
d->mdata->write_page_valid = 0;
if (!(flag & 1)) {
ret = spc_setup_drive(d);
if (ret<=0)
@ -1660,7 +1743,7 @@ int scsi_log_reply(unsigned char *opcode, int data_dir, unsigned char *data,
l = 18;
if ((sense[0] & 0x7f) == 0x72 ||
(sense[0] & 0x7f) == 0x73)
l = sense[7] + 7 + 1; /* SPC-5 4.5.2. */
l = sense[7] + 7 + 1; /* SPC-3 4.5.2. */
if (l > sense_len)
l = sense_len;
fprintf(fp, "+++ sense data =");
@ -1712,6 +1795,22 @@ int scsi_log_err(struct burn_drive *d, struct command *c,
return ret;
}
/* ts B31112 */
int scsi_log_message(struct burn_drive *d, void *fp_in, char * msg, int flag)
{
int ret;
FILE *fp = fp_in;
if (fp != NULL && (fp == stderr || (burn_sg_log_scsi & 1))) {
fprintf(fp, "%s\n", msg);
if (burn_sg_log_scsi & 4)
fflush(fp);
}
if (fp == stderr || !(burn_sg_log_scsi & 2))
return 1;
ret = scsi_log_message(d, stderr, msg, flag);
return ret;
}
/* ts B00808 */
/*
@ -1787,3 +1886,34 @@ ex:;
BURN_FREE_MEM(msg);
return done;
}
int spc_confirm_cd_drive(struct burn_drive *d, int flag)
{
char *msg = NULL;
int ret;
BURN_ALLOC_MEM(msg, char, strlen(d->devname) + 1024);
spc_inquiry(d);
if (d->idata->valid < 0) {
sprintf(msg, "INQUIRY failed with drive '%s'", d->devname);
libdax_msgs_submit(libdax_messenger, -1, 0x0002000a,
LIBDAX_MSGS_SEV_FAILURE,
LIBDAX_MSGS_PRIO_HIGH, msg, 0,0);
ret = 0; goto ex;
}
if (d->idata->peripheral != 0x5) {
sprintf(msg, "Does not identify itself as CD-ROM drive '%s'",
d->devname);
libdax_msgs_submit(libdax_messenger, -1, 0x0002000a,
LIBDAX_MSGS_SEV_FAILURE,
LIBDAX_MSGS_PRIO_HIGH, msg, 0,0);
ret = 0; goto ex;
}
ret = 1;
ex:;
BURN_FREE_MEM(msg);
return ret;
}

View File

@ -1,7 +1,7 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2013 Thomas Schmitt <scdbackup@gmx.net>
Copyright (c) 2006 - 2014 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
@ -98,6 +98,9 @@ int scsi_log_err(struct burn_drive *d, struct command *c,
void *fp, unsigned char sense[18],
int sense_len, int flag);
/* ts B31112 */
int scsi_log_message(struct burn_drive *d, void *fp, char * msg, int flag);
/* ts B00728 */
int spc_decode_sense(unsigned char *sense, int senselen,
int *key, int *asc, int *ascq);
@ -113,6 +116,11 @@ int scsi_eval_cmd_outcome(struct burn_drive *d, struct command *c, void *fp_in,
time_t start_time, int timeout_ms,
int loop_count, int flag);
/* ts B40204 */
/* Verify by INQUIRY that the drive is indeed a MMC device.
*/
int spc_confirm_cd_drive(struct burn_drive *d, int flag);
/* The waiting time before eventually retrying a failed SCSI command.
Before each retry wait Libburn_scsi_retry_incR longer than with

View File

@ -1,7 +1,7 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2013 Thomas Schmitt <scdbackup@gmx.net>
Copyright (c) 2006 - 2014 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
@ -73,15 +73,23 @@ struct command
struct burn_scsi_inquiry_data
{
char peripheral; /* bit0-4: device type should be 5
bit5-7: qualifier must be 0 */
char version; /* should be 3 (SPC-1) to 5 (SPC-3) (or higher ?)
but is often 0. */
char vendor[9];
char product[17];
char revision[5];
int valid;
};
struct scsi_mode_data
{
int p2a_valid;
int buffer_size;
int dvdram_read;
int dvdram_write;
@ -93,8 +101,13 @@ struct scsi_mode_data
int cdr_read;
int cdr_write;
int simulate;
int c2_pointers;
int underrun_proof;
int max_read_speed;
int cur_read_speed;
int max_write_speed;
int cur_write_speed;
/* ts A61021 */
int min_write_speed;
@ -105,15 +118,10 @@ struct scsi_mode_data
int max_end_lba;
struct burn_speed_descriptor *speed_descriptors;
int cur_read_speed;
int cur_write_speed;
int retry_page_length;
int retry_page_valid;
int write_page_length;
int write_page_valid;
int c2_pointers;
int valid;
int underrun_proof;
};
@ -131,6 +139,26 @@ struct burn_format_descr {
};
/* ts B40106 : represents a Feature Descriptor as of mmc5r03c.pdf 5.2.2
There can be many of them. Thus a linked list.
*/
struct burn_feature_descr {
unsigned short feature_code;
unsigned char flags; /* bit0= current
bit1= persistent
bit2-5= version
*/
unsigned char data_lenght;
/* Additional bytes after the first 4 bytes of the descriptor */
unsigned char *data;
struct burn_feature_descr *next;
};
/** Gets initialized in enumerate_common() and burn_drive_register() */
struct burn_drive
{
@ -182,12 +210,24 @@ struct burn_drive
unsigned char all_profiles[256];
int num_profiles;
/* ts B40106 : All feature descriptors as read from drive */
struct burn_feature_descr *features;
/* ts A70128 : MMC-to-MMC feature info from 46h for DVD-RW.
Quite internal. Regard as opaque :)
*/
/* 1 = incremental recording available, 0 = not available */
int current_has_feat21h;
/* Some drives announce feature 21h on fast-blanked DVD-RW
although they cannot write them in Incremental mode.
0= does not look like the recent write run failed due to
Incremental on fast blanked DVD-RW
1= it seems to have happened
2= it seems to have happened with write address 0
*/
int was_feat21h_failure;
/* Link Size item number 0 from feature 0021h descriptor */
int current_feat21h_link_size;
@ -356,6 +396,13 @@ struct burn_drive
volatile int cancel;
volatile enum burn_drive_status busy;
/* During write runs, this points to a copy of the applied
struct burn_write_opts. Only read this underneath
burn_disc_write_sync() which removes the copy when done.
Especially do not read it from outside the write thread.
*/
struct burn_write_opts *write_opts;
/* ts A70929 */
pid_t thread_pid;
int thread_pid_valid;

View File

@ -1101,7 +1101,7 @@ int burn_write_track(struct burn_write_opts *o, struct burn_session *s,
struct burn_drive *d = o->drive;
int i, tmp = 0, open_ended = 0, ret= 0, nwa, lba;
int sectors;
char msg[80];
char msg[160];
d->rlba = -150;
@ -1318,7 +1318,7 @@ int burn_disc_init_write_status(struct burn_write_opts *o,
{
struct burn_drive *d = o->drive;
struct burn_track *t = NULL;
int sx, tx;
int sx, tx, ret;
d->cancel = 0;
@ -1363,6 +1363,13 @@ int burn_disc_init_write_status(struct burn_write_opts *o,
if (o->fill_up_media && t != NULL)
burn_track_set_fillup(t, 1);
d->was_feat21h_failure = 0;
if(d->write_opts != NULL)
burn_write_opts_free(d->write_opts);
ret = burn_write_opts_clone(o, &(d->write_opts), 0);
if (ret <= 0)
return ret;
d->busy = BURN_DRIVE_WRITING;
return 1;
@ -2124,13 +2131,16 @@ int burn_dvd_write_session(struct burn_write_opts *o,
if (d->current_profile == 0x11 || d->current_profile == 0x14 ||
d->current_profile == 0x15) {
/* DVD-R , DVD-RW Sequential, DVD-R/DL Sequential */
multi_mem = o->multi;
if (!is_last_session)
o->multi = 1;
ret = burn_disc_close_session_dvd_minus_r(o);
o->multi = multi_mem;
if (ret <= 0)
return 0;
/* If feature 21h failed on write 0: do not close session */
if (d->was_feat21h_failure != 2) {
multi_mem = o->multi;
if (!is_last_session)
o->multi = 1;
ret = burn_disc_close_session_dvd_minus_r(o);
o->multi = multi_mem;
if (ret <= 0)
return 0;
}
} else if (d->current_profile == 0x12 || d->current_profile == 0x43) {
/* DVD-RAM , BD-RE */
/* ??? any finalization needed ? */;
@ -2850,10 +2860,10 @@ ex:;
close(d->stdio_fd);
d->stdio_fd = -1;
/* update media state records */
/* update pseudo-media state records by re-grabbing */
burn_drive_mark_unready(d, 8);
burn_drive_grab_stdio(d, 1);
/* <<< d->busy = BURN_DRIVE_IDLE; */
return ret;
}
@ -3129,6 +3139,10 @@ ex:;
burn_os_free_buffer((char *) d->buffer,
sizeof(struct buffer), 0);
d->buffer = buffer_mem;
if (d->write_opts != NULL) {
burn_write_opts_free(d->write_opts);
d->write_opts = NULL;
}
return;
}
@ -3137,6 +3151,7 @@ int burn_random_access_write(struct burn_drive *d, off_t byte_address,
char *data, off_t data_count, int flag)
{
int alignment = 0, start, upto, chunksize, err, fd = -1, ret;
int do_close = 0, getfl_ret;
char msg[81], *rpt;
struct buffer *buf = NULL, *buffer_mem = d->buffer;
@ -3209,11 +3224,27 @@ int burn_random_access_write(struct burn_drive *d, off_t byte_address,
"Drive is busy on attempt to write random access",0,0);
{ret = 0; goto ex;}
}
if(d->drive_role != 1) {
fd = burn_stdio_open_write(d, byte_address, 2048, 0);
if (fd == -1)
{ret = 0; goto ex;}
if (d->drive_role != 1) {
if (d->stdio_fd >= 0) {
/* Avoid to have a read-only fd open */
getfl_ret = fcntl(d->stdio_fd, F_GETFL);
if (((O_RDWR | O_WRONLY | O_RDONLY) & getfl_ret) ==
O_RDONLY) {
close(d->stdio_fd);
d->stdio_fd = -1;
}
}
if (d->stdio_fd >= 0) {
/* Avoid to have two fds open */
fd = d->stdio_fd;
} else {
fd = burn_stdio_open_write(d, byte_address, 2048, 0);
if (fd == -1)
{ret = 0; goto ex;}
do_close = 1;
}
}
d->cancel = 0;
d->busy = BURN_DRIVE_WRITING_SYNC;
d->buffer = buf;
@ -3240,7 +3271,7 @@ int burn_random_access_write(struct burn_drive *d, off_t byte_address,
}
if (err == BE_CANCELLED) {
d->busy = BURN_DRIVE_IDLE;
if(fd >= 0)
if(fd >= 0 && do_close)
close(fd);
{ret = -(start * 2048 - byte_address); goto ex;}
}
@ -3256,7 +3287,7 @@ int burn_random_access_write(struct burn_drive *d, off_t byte_address,
d->needs_sync_cache = 0;
}
if(fd >= 0)
if(fd >= 0 && do_close)
close(fd);
d->buffer = buffer_mem;
d->busy = BURN_DRIVE_IDLE;