Compare commits
57 Commits
1.3.2
...
1.3.6.pl01
Author | SHA1 | Date | |
---|---|---|---|
9ac3548d81 | |||
1f0755c50e | |||
b667218011 | |||
5714fdd895 | |||
cd8b81a3ca | |||
59c736570e | |||
b4a40f0a5e | |||
e424c885fd | |||
6e5c50bde4 | |||
174c22aeb7 | |||
31abdedade | |||
b6afe92e47 | |||
1d616b5944 | |||
070ac64459 | |||
ad95f1ff2b | |||
3edde5dc9d | |||
cf5c7aa84f | |||
d40ab32360 | |||
43e1daab23 | |||
6e4d1cc53e | |||
cdbbcbb923 | |||
7f31c9e985 | |||
dd0ceb6720 | |||
5676a1953d | |||
78627934f3 | |||
217289f71a | |||
1c6f6c084f | |||
658851a497 | |||
2aa10d1099 | |||
ba8b1b5e17 | |||
ef17544eb9 | |||
7f99a8e70e | |||
5f6281261d | |||
04afd1c958 | |||
83eac67cf5 | |||
d09ecac4a8 | |||
404f239207 | |||
0cd21eed54 | |||
119c0cf76d | |||
edc90b880c | |||
ae4d296a60 | |||
4880ca3b93 | |||
429fed00c1 | |||
87ab352d6f | |||
6e372c9a6d | |||
1f7dfb84fc | |||
844dc958be | |||
f6132a97a0 | |||
642406b92e | |||
cc8ac3aefb | |||
2a8ae1be42 | |||
8d2e14a0b9 | |||
9e02c17004 | |||
669ccb9b43 | |||
05ae7e51e4 | |||
db2ec50deb | |||
6b93e66cfd |
13
ChangeLog
13
ChangeLog
@ -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
|
||||
|
@ -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
26
README
@ -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
|
||||
|
@ -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"
|
||||
;;
|
||||
|
@ -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
|
||||
|
@ -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"
|
@ -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"
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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> </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> </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> </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> </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
|
||||
|
@ -1 +1 @@
|
||||
#define Cdrskin_timestamP "2013.08.07.093001"
|
||||
#define Cdrskin_timestamP "2014.03.04.110001"
|
||||
|
@ -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
|
||||
|
@ -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."
|
||||
|
16
configure.ac
16
configure.ac
@ -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
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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,
|
||||
|
201
libburn/drive.c
201
libburn/drive.c
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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:;
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
438
libburn/mmc.c
438
libburn/mmc.c
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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
71
libburn/os-netbsd.h
Normal 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;
|
||||
|
19
libburn/os.h
19
libburn/os.h
@ -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 */
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
895
libburn/sg-netbsd.c
Normal 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;
|
||||
}
|
||||
|
19
libburn/sg.c
19
libburn/sg.c
@ -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 */
|
||||
|
||||
|
208
libburn/spc.c
208
libburn/spc.c
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Reference in New Issue
Block a user