Compare commits
111 Commits
ZeroSevenT
...
ZeroSevenS
Author | SHA1 | Date | |
---|---|---|---|
335b2b0ffc | |||
3505b761f4 | |||
cbb9125bd9 | |||
8385908bb3 | |||
e081477a8f | |||
da1d260753 | |||
95865ee34d | |||
eb8b8faa3b | |||
39fd8b922d | |||
7ead54c8b9 | |||
2a85fc7d91 | |||
1e42a76415 | |||
734759190a | |||
16ffa10831 | |||
cdfc357064 | |||
df612390d3 | |||
77971f3680 | |||
5c75d583d7 | |||
2ff03841d7 | |||
a88745c82e | |||
96167b3d8e | |||
1ca38962d4 | |||
80bcabfd57 | |||
d9239aeafc | |||
758a197d06 | |||
ed972271ec | |||
0544ac8cd3 | |||
12a2be8d86 | |||
509db68d82 | |||
00ed59f34e | |||
2b8e8c2521 | |||
e3ff0bb0f6 | |||
8efb24ca6d | |||
d53c5db98e | |||
0320b7bf2a | |||
cee271f9cb | |||
c2a3e3677d | |||
fc3445215b | |||
4ce8bd45cf | |||
08169d63bc | |||
e13b6369ba | |||
d3988dd74b | |||
ef42052900 | |||
240afa7c3a | |||
5b72e5d06e | |||
4aa08e32ff | |||
eb34561262 | |||
dd85e37ac8 | |||
e566340261 | |||
7e86db207c | |||
a30ecd1abb | |||
45b28b6c31 | |||
afedcdd72b | |||
b8a98e0728 | |||
b238ad5a51 | |||
28f4454a9d | |||
cb8c23ed5a | |||
54bb1ab395 | |||
872068ba7c | |||
2bd800ed14 | |||
da0b3b3939 | |||
93aa6ccc6f | |||
d6edfc9961 | |||
2945ab61d7 | |||
d35f7d0de1 | |||
e335aa26b4 | |||
496d794bcd | |||
c88a428d5e | |||
dc8ecdd77e | |||
259d1cd2b7 | |||
7fddf9ffc5 | |||
6109a7bc08 | |||
9b28a9b272 | |||
f39ff2c2f6 | |||
c8e0472637 | |||
acb2f3b173 | |||
504677de4f | |||
ae8f65e956 | |||
c2c10e263e | |||
43761c55ef | |||
b28165f10b | |||
25489521bb | |||
79a33ca2ac | |||
738b83ac03 | |||
677b007100 | |||
0fc685fc85 | |||
ca2cae9b0a | |||
055876d6b7 | |||
9160b1dcbb | |||
0f37170759 | |||
ce3d4dbed3 | |||
f9acd4ee3d | |||
d118b82a13 | |||
76a4c0ac44 | |||
83f80364c5 | |||
9064b56c56 | |||
405e6b020e | |||
ffe80264c7 | |||
d158e7f456 | |||
4384b0c006 | |||
e78353b7dd | |||
3c2ad1be42 | |||
937a226543 | |||
cca24711b8 | |||
e646686145 | |||
f3070d2e71 | |||
e0c501a59a | |||
39a7d18266 | |||
de8ecab9b4 | |||
e9a6b9c36d | |||
e65ccb2b5e |
@ -1,12 +1,12 @@
|
|||||||
Derek Foreman <derek@signalmarketing.com> and Ben Jansens <xor@orodu.net>
|
Derek Foreman <derek@signalmarketing.com> and Ben Jansens <xor@orodu.net>
|
||||||
Copyright (C) 2002-2006 Derek Foreman and Ben Jansens
|
Copyright (C) 2002-2006 Derek Foreman and Ben Jansens
|
||||||
Mario Danic <mario.danic@gmail.com>, Thomas Schmitt <scdbackup@gmx.net>
|
Mario Danic <mario.danic@gmail.com>, Thomas Schmitt <scdbackup@gmx.net>
|
||||||
Copyright (C) 2006-2009 Mario Danic, Thomas Schmitt
|
Copyright (C) 2006-2010 Mario Danic, Thomas Schmitt
|
||||||
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License version 2 as
|
it under the terms of the GNU General Public License version 2 or later
|
||||||
published by the Free Software Foundation.
|
as published by the Free Software Foundation.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
16
Makefile.am
16
Makefile.am
@ -12,6 +12,9 @@ lib_LTLIBRARIES = libburn/libburn.la
|
|||||||
# Build libraries
|
# Build libraries
|
||||||
libburn_libburn_la_LDFLAGS = \
|
libburn_libburn_la_LDFLAGS = \
|
||||||
-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
|
-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
|
||||||
|
# This causes undesired .o names
|
||||||
|
# configure.ac appends -D options to variable CFLAG
|
||||||
|
### libburn_libburn_la_CFLAGS = $(LIBBURN_DVD_OBS_64K)
|
||||||
libburn_libburn_la_LIBADD = $(LIBBURN_ARCH_LIBS) $(THREAD_LIBS)
|
libburn_libburn_la_LIBADD = $(LIBBURN_ARCH_LIBS) $(THREAD_LIBS)
|
||||||
libburn_libburn_la_SOURCES = \
|
libburn_libburn_la_SOURCES = \
|
||||||
libburn/async.c \
|
libburn/async.c \
|
||||||
@ -25,6 +28,8 @@ libburn_libburn_la_SOURCES = \
|
|||||||
libburn/debug.h \
|
libburn/debug.h \
|
||||||
libburn/drive.c \
|
libburn/drive.c \
|
||||||
libburn/drive.h \
|
libburn/drive.h \
|
||||||
|
libburn/ecma130ab.c \
|
||||||
|
libburn/ecma130ab.h \
|
||||||
libburn/error.h \
|
libburn/error.h \
|
||||||
libburn/file.c \
|
libburn/file.c \
|
||||||
libburn/file.h \
|
libburn/file.h \
|
||||||
@ -65,9 +70,6 @@ libburn_libburn_la_SOURCES = \
|
|||||||
libburn/write.h \
|
libburn/write.h \
|
||||||
version.h
|
version.h
|
||||||
|
|
||||||
## libburn/lec.c \
|
|
||||||
## libburn/lec.h \
|
|
||||||
|
|
||||||
## libburn/sg-@ARCH@.c \
|
## libburn/sg-@ARCH@.c \
|
||||||
|
|
||||||
libinclude_HEADERS = \
|
libinclude_HEADERS = \
|
||||||
@ -108,9 +110,9 @@ test_structest_CPPFLAGS = -Ilibburn
|
|||||||
test_structest_LDADD = $(libburn_libburn_la_OBJECTS) $(LIBBURN_EXTRALIBS)
|
test_structest_LDADD = $(libburn_libburn_la_OBJECTS) $(LIBBURN_EXTRALIBS)
|
||||||
test_structest_SOURCES = test/structest.c
|
test_structest_SOURCES = test/structest.c
|
||||||
|
|
||||||
## cdrskin construction site - ts A60816 - A90507
|
## cdrskin construction site - ts A60816 - B00122
|
||||||
cdrskin_cdrskin_CPPFLAGS = -Ilibburn
|
cdrskin_cdrskin_CPPFLAGS = -Ilibburn
|
||||||
cdrskin_cdrskin_CFLAGS = -DCdrskin_libburn_0_7_1
|
cdrskin_cdrskin_CFLAGS = -DCdrskin_libburn_0_7_6
|
||||||
|
|
||||||
# cdrskin_cdrskin_LDADD = $(libburn_libburn_la_OBJECTS) $(LIBBURN_EXTRALIBS)
|
# cdrskin_cdrskin_LDADD = $(libburn_libburn_la_OBJECTS) $(LIBBURN_EXTRALIBS)
|
||||||
# ts A80123, change proposed by Simon Huggins to cause dynamic libburn linking
|
# ts A80123, change proposed by Simon Huggins to cause dynamic libburn linking
|
||||||
@ -197,10 +199,14 @@ EXTRA_DIST = \
|
|||||||
cdrskin/wiki_plain.txt \
|
cdrskin/wiki_plain.txt \
|
||||||
cdrskin/cleanup.h \
|
cdrskin/cleanup.h \
|
||||||
cdrskin/cleanup.c \
|
cdrskin/cleanup.c \
|
||||||
|
libburn/os-dummy.h \
|
||||||
libburn/os-freebsd.h \
|
libburn/os-freebsd.h \
|
||||||
libburn/os-linux.h \
|
libburn/os-linux.h \
|
||||||
|
libburn/os-libcdio.h \
|
||||||
|
libburn/sg-dummy.c \
|
||||||
libburn/sg-freebsd.c \
|
libburn/sg-freebsd.c \
|
||||||
libburn/sg-linux.c \
|
libburn/sg-linux.c \
|
||||||
|
libburn/sg-libcdio.c \
|
||||||
COPYING \
|
COPYING \
|
||||||
NEWS \
|
NEWS \
|
||||||
ChangeLog \
|
ChangeLog \
|
||||||
|
109
README
109
README
@ -6,12 +6,12 @@ This all is under GPL.
|
|||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
libburn-project.org
|
libburn-project.org
|
||||||
By Mario Danic <mario.danic@gmail.com> and Thomas Schmitt <scdbackup@gmx.net>
|
By Mario Danic <mario.danic@gmail.com> and Thomas Schmitt <scdbackup@gmx.net>
|
||||||
Copyright (C) 2006-2009 Mario Danic, Thomas Schmitt
|
Copyright (C) 2006-2010 Mario Danic, Thomas Schmitt
|
||||||
Still containing parts of Libburn. By Derek Foreman <derek@signalmarketing.com>
|
Still containing parts of Libburn. By Derek Foreman <derek@signalmarketing.com>
|
||||||
and Ben Jansens <xor@orodu.net>
|
and Ben Jansens <xor@orodu.net>
|
||||||
Copyright (C) 2002-2006 Derek Foreman and Ben Jansens
|
Copyright (C) 2002-2006 Derek Foreman and Ben Jansens
|
||||||
|
|
||||||
http://files.libburnia-project.org/releases/libburn-0.7.0.pl00.tar.gz
|
http://files.libburnia-project.org/releases/libburn-0.7.6.pl00.tar.gz
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -19,10 +19,10 @@ Copyright (C) 2002-2006 Derek Foreman and Ben Jansens
|
|||||||
|
|
||||||
From tarball
|
From tarball
|
||||||
|
|
||||||
Obtain libburn-0.7.0.pl00.tar.gz, take it to a directory of your choice and do:
|
Obtain libburn-0.7.6.pl00.tar.gz, take it to a directory of your choice and do:
|
||||||
|
|
||||||
tar xzf libburn-0.7.0.pl00.tar.gz
|
tar xzf libburn-0.7.6.pl00.tar.gz
|
||||||
cd libburn-0.7.0
|
cd libburn-0.7.6
|
||||||
./configure --prefix=/usr
|
./configure --prefix=/usr
|
||||||
make
|
make
|
||||||
|
|
||||||
@ -57,6 +57,30 @@ Do in a directory of your choice:
|
|||||||
Warning: The trunk might contain experimental features which might not
|
Warning: The trunk might contain experimental features which might not
|
||||||
persist until next release.
|
persist until next release.
|
||||||
|
|
||||||
|
|
||||||
|
Special ./configure options
|
||||||
|
|
||||||
|
In some situations Linux may deliver a better write performance to drives if
|
||||||
|
the track input is read with O_DIRECT (see man 2 open). The API call
|
||||||
|
burn_os_open_track_src() and the input readers of cdrskin and libburn fifo
|
||||||
|
can be told to use this peculiar read mode by:
|
||||||
|
--enable-track-src-odirect
|
||||||
|
|
||||||
|
But often libburn call burn_write_opts_set_dvd_obs(opts, 64*1024) will yield
|
||||||
|
even better performance in such a situation. 64k can be made default at
|
||||||
|
configure time by:
|
||||||
|
--enable-dvd-obs-64k
|
||||||
|
This may be combined with above --enable-track-src-odirect .
|
||||||
|
|
||||||
|
Alternatively the transport of SCSI commands can be done via libcdio-0.83.
|
||||||
|
You may install it and re-run libburn's ./configure with option
|
||||||
|
--enable-libcdio
|
||||||
|
|
||||||
|
Make sure to re-compile all source files after running ./configure
|
||||||
|
make clean ; make
|
||||||
|
make install
|
||||||
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
An important part of the project, libisofs, is hosted in a bzr repository at
|
An important part of the project, libisofs, is hosted in a bzr repository at
|
||||||
@ -137,7 +161,8 @@ The project components (list subject to growth, hopefully):
|
|||||||
Rock Ridge extensions. Manipulation is not only adding or
|
Rock Ridge extensions. Manipulation is not only adding or
|
||||||
overwriting of files but also deleting, renaming, attribute
|
overwriting of files but also deleting, renaming, attribute
|
||||||
changing, incremental backups, activating boot images, and
|
changing, incremental backups, activating boot images, and
|
||||||
extracting of files from ISO images to disk.
|
extracting of files from ISO images to disk. An own ISO 9660
|
||||||
|
extension stores ACLs, xattr, and MD5 of file content.
|
||||||
See xorriso/README for more.
|
See xorriso/README for more.
|
||||||
|
|
||||||
- "test" is a collection of application gestures and examples given by the
|
- "test" is a collection of application gestures and examples given by the
|
||||||
@ -164,8 +189,8 @@ Applications must use 64 bit off_t. E.g. by defining
|
|||||||
#define _LARGEFILE_SOURCE
|
#define _LARGEFILE_SOURCE
|
||||||
#define _FILE_OFFSET_BITS 64
|
#define _FILE_OFFSET_BITS 64
|
||||||
or take special precautions to interface with the libraries by 64 bit integers
|
or take special precautions to interface with the libraries by 64 bit integers
|
||||||
where the .h files prescribe off_t. Not to use 64 bit file i/o will keep the
|
where the .h files prescribe off_t. To reduce libburn's off_t size to 32 bit
|
||||||
application from producing and processing ISO images of more than 2 GB size.
|
will keep it from processing tracks of more than 2 GB size.
|
||||||
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
@ -425,12 +450,57 @@ Project history as far as known to me:
|
|||||||
supported profiles. It works around some pitfalls with U3 enhanced memory
|
supported profiles. It works around some pitfalls with U3 enhanced memory
|
||||||
sticks which emulate a CD-ROM.
|
sticks which emulate a CD-ROM.
|
||||||
|
|
||||||
|
- 27 Aug 2009 libisoburn-0.4.0.pl00 can record MD5 checksums by which one may
|
||||||
|
verify the session or single data files in the image. When comparing image
|
||||||
|
files with files in the local filesystem, the MD5 sums avoid the need for
|
||||||
|
reading file content from the image.
|
||||||
|
|
||||||
|
- 22 Sep 2009 libisoburn-0.4.0.pl01 fixes a bug in xorriso option -cut_out.
|
||||||
|
|
||||||
|
- 08 Oct 2009 libisofs-0.6.24 fixes a bug which could cause the loss of blanks
|
||||||
|
in file names when a new session got added to an ISO image. With names
|
||||||
|
shorter than 251 characters this happened only to trailing blanks.
|
||||||
|
|
||||||
|
- 08 Oct 2009 libisoburn-0.4.0.pl02 fixes bugs with xorriso option -for_backup,
|
||||||
|
with xorrisofs -help, and with xorrecord -help.
|
||||||
|
|
||||||
|
- 12 Oct 2009 libburn-0.7.2 fixes a bug with CD TAO multi-track dummy sessions.
|
||||||
|
It can retrieve media product info and can process track input which was
|
||||||
|
prepared for CD-ROM XA Mode 2 Form 1. cdrskin now performs option -minfo.
|
||||||
|
|
||||||
|
- 28 Oct 2009 libisoburn-0.4.4 fixes a bug with cdrecord emulation and
|
||||||
|
introduces new information options about media type and ISO image id strings.
|
||||||
|
On Linux it helps with mounting two sessions of the same media
|
||||||
|
simultaneously.
|
||||||
|
|
||||||
|
- 12 Nov 2009 libburn-0.7.2.pl01 works around problems with Pioneer DVR-216D.
|
||||||
|
DVD-R runs made the drive stuck. Ejecting the tray did not work properly.
|
||||||
|
|
||||||
|
- 06 Dec 2009 libburn-0.7.4 works around problems with newer DVD burners,
|
||||||
|
provides throughput enhancements with hampered busses on Linux, and new
|
||||||
|
API calls to log SCSI commands and to control the libburn fifo.
|
||||||
|
|
||||||
|
- 09 Dec 2009 libisoburn-0.4.6 allows performance tuning of output to DVD
|
||||||
|
drives or disk files.
|
||||||
|
|
||||||
|
- 26 Dec 2009 libburn-0.7.4.pl01 fixes the release tarball which was lacking
|
||||||
|
the files of the generic system adapter for X/Open.
|
||||||
|
|
||||||
|
- 29 Dec 2009 Our project received a donation for purchasing a fine small
|
||||||
|
computer which shall serve as OS farm for development and support.
|
||||||
|
|
||||||
|
- 20 Jan 2010 Version 0.6.26 of libisofs fixes minor bugs and shall enhance
|
||||||
|
portability.
|
||||||
|
|
||||||
|
- 22 Jan 2010 libburn-0.7.6 has an improved system adapter for FreeBSD,
|
||||||
|
fixes bugs about the generic X/Open system adapter, and allows to use
|
||||||
|
libcdio >= 0.83 as SCSI transport facility.
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License version 2 or later
|
||||||
the Free Software Foundation. To be exact: version 2 of that License.
|
as published by the Free Software Foundation.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
@ -448,16 +518,16 @@ other copyrighted code has been replaced by ours and by copyright-free
|
|||||||
contributions of our friends:
|
contributions of our friends:
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
We, the copyright holders, agree on the interpretation that
|
We, the copyright holders, agree on the interpretation that dynamical linking
|
||||||
dynamical linking of our libraries constitutes "use of" and
|
of our libraries constitutes "use of" and not "derivation from" our work in
|
||||||
not "derivation from" our work in the sense of GPL, provided
|
the sense of GPL, provided those libraries are compiled from our unaltered
|
||||||
those libraries are compiled from our unaltered code.
|
code or from altered code published under GPL.
|
||||||
|
|
||||||
Thus you may link our libraries dynamically with applications
|
So we will not raise legal protest if you link our libraries dynamically with
|
||||||
which are not under GPL. You may distribute our libraries and
|
applications which are not under GPL, or if you distribute our libraries
|
||||||
application tools in binary form, if you fulfill the usual
|
and application tools in binary form, as long as you fulfill the usual
|
||||||
condition of GPL to offer a copy of the source code -altered
|
condition of GPL to offer a copy of their source code -altered or unaltered-
|
||||||
or unaltered- under GPL.
|
under GPL.
|
||||||
|
|
||||||
We ask you politely to use our work in open source spirit
|
We ask you politely to use our work in open source spirit
|
||||||
and with the due reference to the entire open source community.
|
and with the due reference to the entire open source community.
|
||||||
@ -474,4 +544,5 @@ means to qualify for GPL.
|
|||||||
For now we are firmly committed to maintain one single license: GPL.
|
For now we are firmly committed to maintain one single license: GPL.
|
||||||
|
|
||||||
signed: Mario Danic, Thomas Schmitt
|
signed: Mario Danic, Thomas Schmitt
|
||||||
|
Agreement joined later by: Vreixo Formoso
|
||||||
|
|
||||||
|
10
acinclude.m4
10
acinclude.m4
@ -6,16 +6,20 @@ AC_DEFUN([TARGET_SHIZZLE],
|
|||||||
AC_MSG_CHECKING([target operating system])
|
AC_MSG_CHECKING([target operating system])
|
||||||
|
|
||||||
|
|
||||||
case $target in
|
case $target_os in
|
||||||
*-*-linux*)
|
linux*)
|
||||||
ARCH=linux
|
ARCH=linux
|
||||||
LIBBURN_ARCH_LIBS=
|
LIBBURN_ARCH_LIBS=
|
||||||
;;
|
;;
|
||||||
*-*-freebsd*)
|
freebsd*)
|
||||||
ARCH=freebsd
|
ARCH=freebsd
|
||||||
LIBBURN_ARCH_LIBS=-lcam
|
LIBBURN_ARCH_LIBS=-lcam
|
||||||
LIBBURNIA_PKGCONFDIR=$(echo "$libdir" | sed 's/\/lib$/\/libdata/')/pkgconfig
|
LIBBURNIA_PKGCONFDIR=$(echo "$libdir" | sed 's/\/lib$/\/libdata/')/pkgconfig
|
||||||
;;
|
;;
|
||||||
|
kfreebsd*-gnu)
|
||||||
|
ARCH=freebsd
|
||||||
|
LIBBURN_ARCH_LIBS=-lcam
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
ARCH=
|
ARCH=
|
||||||
LIBBURN_ARCH_LIBS=
|
LIBBURN_ARCH_LIBS=
|
||||||
|
@ -4,17 +4,18 @@
|
|||||||
cdrskin. By Thomas Schmitt <scdbackup@gmx.net>
|
cdrskin. By Thomas Schmitt <scdbackup@gmx.net>
|
||||||
Integrated sub project of libburnia-project.org but also published via:
|
Integrated sub project of libburnia-project.org but also published via:
|
||||||
http://scdbackup.sourceforge.net/cdrskin_eng.html
|
http://scdbackup.sourceforge.net/cdrskin_eng.html
|
||||||
http://scdbackup.sourceforge.net/cdrskin-0.7.1.tar.gz
|
http://scdbackup.sourceforge.net/cdrskin-0.7.6.pl00.tar.gz
|
||||||
|
|
||||||
Copyright (C) 2006-2009 Thomas Schmitt, provided under GPL version 2.
|
Copyright (C) 2006-2010 Thomas Schmitt, provided under GPL version 2 or later.
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
cdrskin is a limited cdrecord compatibility wrapper which allows to use
|
cdrskin is a limited cdrecord compatibility wrapper which allows to use
|
||||||
most of the libburn features from the command line.
|
most of the libburn features from the command line.
|
||||||
|
|
||||||
Currently it is supported on Linux with kernels >= 2.4 and on FreeBSD versions
|
Currently it is supported on Linux with kernels >= 2.4 and on FreeBSD.
|
||||||
with ATAPI/CAM support enabled in the kernel, see atapicam(4).
|
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
|
On other X/Open compliant systems there will only be emulated drives, but no
|
||||||
direct MMC operation on real CD/DVD/BD drives.
|
direct MMC operation on real CD/DVD/BD drives.
|
||||||
|
|
||||||
@ -24,10 +25,10 @@ By using this software you agree to the disclaimer at the end of this text
|
|||||||
|
|
||||||
Compilation, First Glimpse, Installation
|
Compilation, First Glimpse, Installation
|
||||||
|
|
||||||
Obtain cdrskin-0.7.1.tar.gz, take it to a directory of your choice and do:
|
Obtain cdrskin-0.7.6.pl00.tar.gz, take it to a directory of your choice and do:
|
||||||
|
|
||||||
tar xzf cdrskin-0.7.1.tar.gz
|
tar xzf cdrskin-0.7.6.pl00.tar.gz
|
||||||
cd cdrskin-0.7.1
|
cd cdrskin-0.7.6
|
||||||
|
|
||||||
Within that directory execute:
|
Within that directory execute:
|
||||||
|
|
||||||
@ -35,8 +36,7 @@ Within that directory execute:
|
|||||||
make
|
make
|
||||||
|
|
||||||
This will already produce a cdrskin binary. But it will be necessary to
|
This will already produce a cdrskin binary. But it will be necessary to
|
||||||
install libburn in order to use this binary. Installation of libburn is
|
install libburn in order to use this binary.
|
||||||
beyond the scope of cdrskin. For this, see included libburn docs.
|
|
||||||
|
|
||||||
In order to surely get a standalone binary, execute
|
In order to surely get a standalone binary, execute
|
||||||
|
|
||||||
@ -73,7 +73,7 @@ It is not necessary for the standalone cdrskin binary to have libburn
|
|||||||
installed, since it incorporates the necessary libburn parts at compile time.
|
installed, since it incorporates the necessary libburn parts at compile time.
|
||||||
It will not collide with an installed version of libburn either.
|
It will not collide with an installed version of libburn either.
|
||||||
But libpthread must be installed on the system and glibc has to match. (See
|
But libpthread must be installed on the system and glibc has to match. (See
|
||||||
below for a way to create a statically linked binary.)
|
below for a way to create a totally static linked binary.)
|
||||||
|
|
||||||
To install the man page, you may do: echo $MANPATH and choose one of the
|
To install the man page, you may do: echo $MANPATH and choose one of the
|
||||||
listed directories to copy the man-page under its ./man1 directory. Like:
|
listed directories to copy the man-page under its ./man1 directory. Like:
|
||||||
@ -398,6 +398,25 @@ drive. See man page section FILES for a way to lift that ban.
|
|||||||
|
|
||||||
Special compilation variations
|
Special compilation variations
|
||||||
|
|
||||||
|
All following options of ./configure and cdrskin/compile_cdrskin.sh are
|
||||||
|
combinable.
|
||||||
|
|
||||||
|
In some situations Linux may deliver a better write performance to drives if
|
||||||
|
the track input is read with O_DIRECT (see man 2 open). The API call
|
||||||
|
burn_os_open_track_src() and the input readers of cdrskin and libburn fifo
|
||||||
|
can be told to use this peculiar read mode by:
|
||||||
|
--enable-track-src-odirect
|
||||||
|
|
||||||
|
But often cdrskin option dvd_obs=64k will yield even better performance in
|
||||||
|
such a situation. 64k can be made default at compile time by
|
||||||
|
cdrskin/compile_cdrskin.sh -dvd_obs_64k
|
||||||
|
It can also be enabled at configure time by
|
||||||
|
./configure ... --enable-dvd-obs-64k ...
|
||||||
|
|
||||||
|
Alternatively the transport of SCSI commands can be done via libcdio-0.83.
|
||||||
|
You may install it and re-run libburn's ./configure with option
|
||||||
|
--enable-libcdio
|
||||||
|
|
||||||
You may get a (super fat) statically linked binary by :
|
You may get a (super fat) statically linked binary by :
|
||||||
cdrskin/compile_cdrskin.sh -static
|
cdrskin/compile_cdrskin.sh -static
|
||||||
if your system supports static linking, at all. This will not help with kernels
|
if your system supports static linking, at all. This will not help with kernels
|
||||||
@ -441,7 +460,7 @@ contributions in a due way.
|
|||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License version 2
|
it under the terms of the GNU General Public License version 2 or later
|
||||||
as published by the Free Software Foundation.
|
as published by the Free Software Foundation.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
@ -457,7 +476,7 @@ contributions in a due way.
|
|||||||
Based on and sub project of:
|
Based on and sub project of:
|
||||||
libburnia-project.org
|
libburnia-project.org
|
||||||
By Mario Danic <mario.danic@gmail.com> and Thomas Schmitt <scdbackup@gmx.net>
|
By Mario Danic <mario.danic@gmail.com> and Thomas Schmitt <scdbackup@gmx.net>
|
||||||
Copyright (C) 2006-2009 Mario Danic, Thomas Schmitt
|
Copyright (C) 2006-2010 Mario Danic, Thomas Schmitt
|
||||||
|
|
||||||
libburnia-project.org is inspired by and in other components still containing
|
libburnia-project.org is inspired by and in other components still containing
|
||||||
parts of
|
parts of
|
||||||
@ -468,34 +487,3 @@ See toplevel README for an overview of the current copyright situation in
|
|||||||
libburnia-project.org.
|
libburnia-project.org.
|
||||||
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
cdrskin is currently copyright Thomas Schmitt only.
|
|
||||||
It adopts the following commitment by the toplevel copyright holders:
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
We, the copyright holders, agree on the interpretation that
|
|
||||||
dynamical linking of our libraries constitutes "use of" and
|
|
||||||
not "derivation from" our work in the sense of GPL, provided
|
|
||||||
those libraries are compiled from our unaltered code.
|
|
||||||
|
|
||||||
Thus you may link our libraries dynamically with applications
|
|
||||||
which are not under GPL. You may distribute our libraries and
|
|
||||||
application tools in binary form, if you fulfill the usual
|
|
||||||
condition of GPL to offer a copy of the source code -altered
|
|
||||||
or unaltered- under GPL.
|
|
||||||
|
|
||||||
We ask you politely to use our work in open source spirit
|
|
||||||
and with the due reference to the entire open source community.
|
|
||||||
|
|
||||||
If there should really arise the case where above clarification
|
|
||||||
does not suffice to fulfill a clear and neat request in open source
|
|
||||||
spirit that would otherwise be declined for mere formal reasons,
|
|
||||||
only in that case we will duely consider to issue a special license
|
|
||||||
covering only that special case.
|
|
||||||
It is the open source idea of responsible freedom which will be
|
|
||||||
decisive and you will have to prove that you exhausted all own
|
|
||||||
means to qualify for GPL.
|
|
||||||
|
|
||||||
For now we are firmly committed to maintain one single license: GPL.
|
|
||||||
|
|
||||||
signed for cdrskin: Thomas Schmitt
|
|
||||||
|
@ -38,7 +38,7 @@ original="./libburn_svn_release.tgz"
|
|||||||
# My changes are in $changes , mainly in $changes/cdrskin
|
# My changes are in $changes , mainly in $changes/cdrskin
|
||||||
changes="./libburn-release"
|
changes="./libburn-release"
|
||||||
|
|
||||||
skin_release="0.7.0"
|
skin_release="0.7.6"
|
||||||
patch_level=".pl00"
|
patch_level=".pl00"
|
||||||
skin_rev="$skin_release""$patch_level"
|
skin_rev="$skin_release""$patch_level"
|
||||||
|
|
@ -38,7 +38,7 @@ original="./libburn_svn.tgz"
|
|||||||
# My changes are in $changes , mainly in $changes/cdrskin
|
# My changes are in $changes , mainly in $changes/cdrskin
|
||||||
changes="./libburn-develop"
|
changes="./libburn-develop"
|
||||||
|
|
||||||
skin_release="0.7.1"
|
skin_release="0.7.7"
|
||||||
patch_level=""
|
patch_level=""
|
||||||
skin_rev="$skin_release""$patch_level"
|
skin_rev="$skin_release""$patch_level"
|
||||||
|
|
@ -25,6 +25,11 @@
|
|||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
|
|
||||||
|
#ifndef Cdrfifo_standalonE
|
||||||
|
/* <<< until release of 0.7.4 : for Libburn_has_open_trac_srC */
|
||||||
|
#include "../libburn/libburn.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "cdrfifo.h"
|
#include "cdrfifo.h"
|
||||||
|
|
||||||
|
|
||||||
@ -120,7 +125,7 @@ struct CdrfifO {
|
|||||||
struct burn_source object.
|
struct burn_source object.
|
||||||
@param chunk_size Size of buffer block for a single transaction (0=default)
|
@param chunk_size Size of buffer block for a single transaction (0=default)
|
||||||
@param buffer_size Size of fifo buffer
|
@param buffer_size Size of fifo buffer
|
||||||
@param flag Unused yet
|
@param flag bit0= Debugging verbosity
|
||||||
@return 1 on success, <=0 on failure
|
@return 1 on success, <=0 on failure
|
||||||
*/
|
*/
|
||||||
int Cdrfifo_new(struct CdrfifO **ff, int source_fd, int dest_fd,
|
int Cdrfifo_new(struct CdrfifO **ff, int source_fd, int dest_fd,
|
||||||
@ -174,7 +179,13 @@ int Cdrfifo_new(struct CdrfifO **ff, int source_fd, int dest_fd,
|
|||||||
o->follow_up_fd_idx= -1;
|
o->follow_up_fd_idx= -1;
|
||||||
o->next= o->prev= NULL;
|
o->next= o->prev= NULL;
|
||||||
o->chain_idx= 0;
|
o->chain_idx= 0;
|
||||||
|
|
||||||
|
#ifdef Libburn_has_open_trac_srC
|
||||||
|
o->buffer= burn_os_alloc_buffer((size_t) buffer_size, 0);
|
||||||
|
#else
|
||||||
o->buffer= TSOB_FELD(char,buffer_size);
|
o->buffer= TSOB_FELD(char,buffer_size);
|
||||||
|
#endif /* ! Libburn_has_open_trac_srC */
|
||||||
|
|
||||||
if(o->buffer==NULL)
|
if(o->buffer==NULL)
|
||||||
goto failed;
|
goto failed;
|
||||||
return(1);
|
return(1);
|
||||||
@ -226,8 +237,14 @@ int Cdrfifo_destroy(struct CdrfifO **ff, int flag)
|
|||||||
|
|
||||||
if(o->iso_fs_descr!=NULL)
|
if(o->iso_fs_descr!=NULL)
|
||||||
free((char *) o->iso_fs_descr);
|
free((char *) o->iso_fs_descr);
|
||||||
|
|
||||||
if(o->buffer!=NULL)
|
if(o->buffer!=NULL)
|
||||||
|
#ifdef Libburn_has_open_trac_srC
|
||||||
|
burn_os_free_buffer(o->buffer, o->buffer_size, 0);
|
||||||
|
#else
|
||||||
free((char *) o->buffer);
|
free((char *) o->buffer);
|
||||||
|
#endif /* Libburn_has_open_trac_srC */
|
||||||
|
|
||||||
free((char *) o);
|
free((char *) o);
|
||||||
(*ff)= NULL;
|
(*ff)= NULL;
|
||||||
return(1);
|
return(1);
|
||||||
@ -616,7 +633,7 @@ return: <0 = error , 0 = idle , 1 = did some work
|
|||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
double buffer_space;
|
double buffer_space;
|
||||||
int can_read,can_write,ret,did_work= 0,idx,sod,eop_is_near,eop_idx;
|
int can_read,can_write= 0,ret,did_work= 0,idx,sod,eop_is_near,eop_idx;
|
||||||
|
|
||||||
buffer_space= Cdrfifo_tell_buffer_space(o,0);
|
buffer_space= Cdrfifo_tell_buffer_space(o,0);
|
||||||
if(o->dest_fd>=0) if(FD_ISSET((o->dest_fd),wts)) {
|
if(o->dest_fd>=0) if(FD_ISSET((o->dest_fd),wts)) {
|
||||||
@ -659,6 +676,46 @@ return: <0 = error , 0 = idle , 1 = did some work
|
|||||||
after_write:;
|
after_write:;
|
||||||
if(o->source_fd>=0) if(FD_ISSET((o->source_fd),rds)) {
|
if(o->source_fd>=0) if(FD_ISSET((o->source_fd),rds)) {
|
||||||
can_read= o->buffer_size - o->write_idx;
|
can_read= o->buffer_size - o->write_idx;
|
||||||
|
|
||||||
|
#ifdef Libburn_has_open_trac_srC
|
||||||
|
|
||||||
|
/* ts A91115
|
||||||
|
This chunksize must be aligned to filesystem blocksize.
|
||||||
|
*/
|
||||||
|
#define Cdrfifo_o_direct_chunK 32768
|
||||||
|
|
||||||
|
if(o->write_idx < o->read_idx && o->write_idx + can_read > o->read_idx)
|
||||||
|
can_read= o->read_idx - o->write_idx;
|
||||||
|
if(o->fd_in_limit>=0.0)
|
||||||
|
if(can_read > o->fd_in_limit - o->fd_in_counter)
|
||||||
|
can_read= o->fd_in_limit - o->fd_in_counter;
|
||||||
|
/* Make sure to read with properly aligned size */
|
||||||
|
if(can_read > Cdrfifo_o_direct_chunK)
|
||||||
|
can_read= Cdrfifo_o_direct_chunK;
|
||||||
|
else if(can_read < Cdrfifo_o_direct_chunK)
|
||||||
|
can_read= -1;
|
||||||
|
ret= 0;
|
||||||
|
if(can_read>0)
|
||||||
|
ret= read(o->source_fd,o->buffer+o->write_idx,can_read);
|
||||||
|
if(can_read < 0) {
|
||||||
|
/* waiting for a full Cdrfifo_o_direct_chunK to fit */
|
||||||
|
if(can_write <= 0 && o->dest_fd >= 0) {
|
||||||
|
fd_set rds,wts,exs;
|
||||||
|
struct timeval wt;
|
||||||
|
|
||||||
|
FD_ZERO(&rds);
|
||||||
|
FD_ZERO(&wts);
|
||||||
|
FD_ZERO(&exs);
|
||||||
|
FD_SET((o->dest_fd),&wts);
|
||||||
|
wt.tv_sec= 0;
|
||||||
|
wt.tv_usec= 10000;
|
||||||
|
select(o->dest_fd + 1,&rds, &wts, &exs, &wt);
|
||||||
|
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
|
||||||
|
#else /* Libburn_has_open_trac_srC */
|
||||||
|
|
||||||
if(can_read>o->chunk_size)
|
if(can_read>o->chunk_size)
|
||||||
can_read= o->chunk_size;
|
can_read= o->chunk_size;
|
||||||
if(o->write_idx<o->read_idx && o->write_idx+can_read > o->read_idx)
|
if(o->write_idx<o->read_idx && o->write_idx+can_read > o->read_idx)
|
||||||
@ -669,6 +726,9 @@ after_write:;
|
|||||||
ret= 0;
|
ret= 0;
|
||||||
if(can_read>0)
|
if(can_read>0)
|
||||||
ret= read(o->source_fd,o->buffer+o->write_idx,can_read);
|
ret= read(o->source_fd,o->buffer+o->write_idx,can_read);
|
||||||
|
|
||||||
|
#endif /* ! Libburn_has_open_trac_srC */
|
||||||
|
|
||||||
if(ret==-1) {
|
if(ret==-1) {
|
||||||
|
|
||||||
/* >>> handle input error */;
|
/* >>> handle input error */;
|
||||||
|
@ -33,7 +33,7 @@ struct CdrfifO;
|
|||||||
struct burn_source object.
|
struct burn_source object.
|
||||||
@param chunk_size Size of buffer block for a single transaction (0=default)
|
@param chunk_size Size of buffer block for a single transaction (0=default)
|
||||||
@param buffer_size Size of fifo buffer
|
@param buffer_size Size of fifo buffer
|
||||||
@param flag unused yet
|
@param flag bit0= Debugging verbosity
|
||||||
@return 1 on success, <=0 on failure
|
@return 1 on success, <=0 on failure
|
||||||
*/
|
*/
|
||||||
int Cdrfifo_new(struct CdrfifO **ff, int source_fd, int dest_fd,
|
int Cdrfifo_new(struct CdrfifO **ff, int source_fd, int dest_fd,
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
.\" First parameter, NAME, should be all caps
|
.\" First parameter, NAME, should be all caps
|
||||||
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
||||||
.\" other parameters are allowed: see man(7), man(1)
|
.\" other parameters are allowed: see man(7), man(1)
|
||||||
.TH CDRSKIN 1 "Sep 10, 2009"
|
.TH CDRSKIN 1 "Jan 19, 2010"
|
||||||
.\" Please adjust this date whenever revising the manpage.
|
.\" Please adjust this date whenever revising the manpage.
|
||||||
.\"
|
.\"
|
||||||
.\" Some roff macros, for reference:
|
.\" Some roff macros, for reference:
|
||||||
@ -796,6 +796,11 @@ Level 2 additionally reports about option settings derived from arguments or
|
|||||||
startup files. Level 3 is for debugging and useful mainly in conjunction with
|
startup files. Level 3 is for debugging and useful mainly in conjunction with
|
||||||
somebody who had a look into the program sourcecode.
|
somebody who had a look into the program sourcecode.
|
||||||
.TP
|
.TP
|
||||||
|
.BI \-V
|
||||||
|
Enable logging of SCSI commands to stderr. This allows expert examination
|
||||||
|
of the interaction between libburn and the drive. The commands are specified
|
||||||
|
in SCSI-3 standards SPC, SBC, MMC.
|
||||||
|
.TP
|
||||||
.BI \-waiti
|
.BI \-waiti
|
||||||
Wait until input data is available at stdin or EOF occurs at stdin.
|
Wait until input data is available at stdin or EOF occurs at stdin.
|
||||||
Only then begin to access any drives.
|
Only then begin to access any drives.
|
||||||
@ -894,6 +899,14 @@ Both, write_start_address and direct_write_amount size must be aligned to a
|
|||||||
media dependend transaction size. With DVD-RAM, BD-RE, DVD+RW this is 2k, with
|
media dependend transaction size. With DVD-RAM, BD-RE, DVD+RW this is 2k, with
|
||||||
overwriteable DVD-RW it is 32k.
|
overwriteable DVD-RW it is 32k.
|
||||||
.TP
|
.TP
|
||||||
|
.BI dvd_obs= default|32k|64k
|
||||||
|
Linux specific:
|
||||||
|
Set the number of bytes to be transmitted with each write operation to DVD
|
||||||
|
or BD media. Tracks get padded up to the next multiple of this write
|
||||||
|
size. A number of 64 KB may improve throughput with bus systems which
|
||||||
|
show latency problems. The default depends on media type, option
|
||||||
|
stream_recording=, and on compile time options.
|
||||||
|
.TP
|
||||||
.BI fallback_program= command
|
.BI fallback_program= command
|
||||||
Set a command name to be executed if cdrskin encounters a known cdrecord
|
Set a command name to be executed if cdrskin encounters a known cdrecord
|
||||||
option which it does not yet support. If a non-empty command is given with
|
option which it does not yet support. If a non-empty command is given with
|
||||||
@ -1008,6 +1021,22 @@ which can only do DAO but not Incremental Streaming.
|
|||||||
.BI \--single_track
|
.BI \--single_track
|
||||||
Accept only the last argument of the command line as track source address.
|
Accept only the last argument of the command line as track source address.
|
||||||
.TP
|
.TP
|
||||||
|
.BI stdio_sync= on|off|number
|
||||||
|
Set the number of bytes after which to force output to drives with prefix
|
||||||
|
"stdio:". This forcing keeps the memory from being clogged with lots of
|
||||||
|
pending data for slow devices. Default "on" is the same as "16m".
|
||||||
|
Forced output can be disabled by "off".
|
||||||
|
.TP
|
||||||
|
.BI stream_recording= on|off|number
|
||||||
|
By setting "on" request that compliance to the desired speed setting is
|
||||||
|
preferred over management of write errors. With DVD-RAM and BD this can
|
||||||
|
bring effective write speed near to the nominal write speed of the media.
|
||||||
|
But it will also disable the automatic use of replacement blocks
|
||||||
|
if write errors occur. It might as well be disliked or ignored by the drive.
|
||||||
|
.br
|
||||||
|
If a number is given, then error management stays enabled for all byte
|
||||||
|
addresses below that number. Any number below 16s is the same as "off".
|
||||||
|
.TP
|
||||||
.BI tao_to_sao_tsize= size
|
.BI tao_to_sao_tsize= size
|
||||||
Set an exact fixed size for the next track to be in effect only if the track
|
Set an exact fixed size for the next track to be in effect only if the track
|
||||||
source cannot deliver a size prediction and no tsize= was specified and an
|
source cannot deliver a size prediction and no tsize= was specified and an
|
||||||
@ -1194,17 +1223,6 @@ Linux specific:
|
|||||||
Use and report literal Bus,Target,Lun addresses rather than real SCSI and
|
Use and report literal Bus,Target,Lun addresses rather than real SCSI and
|
||||||
pseudo ATA addresses. This method is outdated and was never compatible with
|
pseudo ATA addresses. This method is outdated and was never compatible with
|
||||||
original cdrecord.
|
original cdrecord.
|
||||||
.TP
|
|
||||||
.BI stream_recording="on"|"off"|number
|
|
||||||
By setting "on" request that compliance to the desired speed setting is
|
|
||||||
preferred over management of write errors. With DVD-RAM and BD this can
|
|
||||||
bring effective write speed near to the nominal write speed of the media.
|
|
||||||
But it will also disable the automatic use of replacement blocks
|
|
||||||
if write errors occur. It might as well be disliked or ignored by the drive.
|
|
||||||
.br
|
|
||||||
If a number is given, then error management stays enabled for all byte
|
|
||||||
addresses below that number. Any number below 16s is the same as "off".
|
|
||||||
.TP
|
|
||||||
.BI --xa1-ignore
|
.BI --xa1-ignore
|
||||||
Silently interpret option -xa1 as -data. This may be necessary if a frontent
|
Silently interpret option -xa1 as -data. This may be necessary if a frontent
|
||||||
does not prepare -xa1 block headers but insists in using option -xa1.
|
does not prepare -xa1 block headers but insists in using option -xa1.
|
||||||
@ -1224,7 +1242,7 @@ cdrskin dev=0,1,0 -checkdrive
|
|||||||
.br
|
.br
|
||||||
cdrskin dev=ATA:1,0,0 -v -atip
|
cdrskin dev=ATA:1,0,0 -v -atip
|
||||||
.br
|
.br
|
||||||
cdrskin dev=/dev/hdc -toc
|
cdrskin dev=/dev/hdc -minfo
|
||||||
.SS
|
.SS
|
||||||
.B Prepare CD-RW or DVD-RW for re-use, DVD-RAM or BD-RE for first use:
|
.B Prepare CD-RW or DVD-RW for re-use, DVD-RAM or BD-RE for first use:
|
||||||
.br
|
.br
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
cdrskin.c , Copyright 2006-2009 Thomas Schmitt <scdbackup@gmx.net>
|
cdrskin.c , Copyright 2006-2010 Thomas Schmitt <scdbackup@gmx.net>
|
||||||
Provided under GPL version 2. See future commitment below.
|
Provided under GPL version 2 or later. See future commitment below.
|
||||||
|
|
||||||
A cdrecord compatible command line interface for libburn.
|
A cdrecord compatible command line interface for libburn.
|
||||||
|
|
||||||
@ -88,7 +88,7 @@ or
|
|||||||
|
|
||||||
/** The official program version */
|
/** The official program version */
|
||||||
#ifndef Cdrskin_prog_versioN
|
#ifndef Cdrskin_prog_versioN
|
||||||
#define Cdrskin_prog_versioN "0.7.1"
|
#define Cdrskin_prog_versioN "0.7.6"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** The official libburn interface revision to use.
|
/** The official libburn interface revision to use.
|
||||||
@ -101,7 +101,7 @@ or
|
|||||||
#define Cdrskin_libburn_minoR 7
|
#define Cdrskin_libburn_minoR 7
|
||||||
#endif
|
#endif
|
||||||
#ifndef Cdrskin_libburn_micrO
|
#ifndef Cdrskin_libburn_micrO
|
||||||
#define Cdrskin_libburn_micrO 1
|
#define Cdrskin_libburn_micrO 6
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -135,44 +135,43 @@ or
|
|||||||
#endif /* Cdrskin_libburn_cvs_A60220_tS */
|
#endif /* Cdrskin_libburn_cvs_A60220_tS */
|
||||||
|
|
||||||
|
|
||||||
#ifdef Cdrskin_libburn_0_7_0
|
#ifdef Cdrskin_libburn_0_7_6
|
||||||
#define Cdrskin_libburn_versioN "0.7.0"
|
#define Cdrskin_libburn_versioN "0.7.6"
|
||||||
#define Cdrskin_libburn_from_pykix_svN 1
|
#define Cdrskin_libburn_from_pykix_svN 1
|
||||||
#endif /* Cdrskin_libburn_0_7_0 */
|
#endif /* Cdrskin_libburn_0_7_6 */
|
||||||
|
|
||||||
#ifdef Cdrskin_libburn_0_7_1
|
#ifdef Cdrskin_libburn_0_7_7
|
||||||
#define Cdrskin_libburn_versioN "0.7.1"
|
#define Cdrskin_libburn_versioN "0.7.7"
|
||||||
#define Cdrskin_libburn_from_pykix_svN 1
|
#define Cdrskin_libburn_from_pykix_svN 1
|
||||||
|
|
||||||
/* Place novelty switch macros here.
|
/* Place novelty switch macros here.
|
||||||
Move them down to Cdrskin_libburn_from_pykix_svN on version leap
|
Move them down to Cdrskin_libburn_from_pykix_svN on version leap
|
||||||
*/
|
*/
|
||||||
#define Cdrskin_libburn_has_product_iD 1
|
|
||||||
#define Cdrskin_libburn_has_cdxa_conV 1
|
|
||||||
|
|
||||||
#endif /* Cdrskin_libburn_0_7_1 */
|
|
||||||
|
#endif /* Cdrskin_libburn_0_7_7 */
|
||||||
|
|
||||||
#ifndef Cdrskin_libburn_versioN
|
#ifndef Cdrskin_libburn_versioN
|
||||||
#define Cdrskin_libburn_0_7_0
|
#define Cdrskin_libburn_0_7_6
|
||||||
#define Cdrskin_libburn_versioN "0.7.0"
|
#define Cdrskin_libburn_versioN "0.7.6"
|
||||||
#define Cdrskin_libburn_from_pykix_svN 1
|
#define Cdrskin_libburn_from_pykix_svN 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef Cdrskin_libburn_0_7_0
|
#ifdef Cdrskin_libburn_0_7_6
|
||||||
#undef Cdrskin_libburn_majoR
|
#undef Cdrskin_libburn_majoR
|
||||||
#undef Cdrskin_libburn_minoR
|
#undef Cdrskin_libburn_minoR
|
||||||
#undef Cdrskin_libburn_micrO
|
#undef Cdrskin_libburn_micrO
|
||||||
#define Cdrskin_libburn_majoR 0
|
#define Cdrskin_libburn_majoR 0
|
||||||
#define Cdrskin_libburn_minoR 7
|
#define Cdrskin_libburn_minoR 7
|
||||||
#define Cdrskin_libburn_micrO 0
|
#define Cdrskin_libburn_micrO 6
|
||||||
#endif
|
#endif
|
||||||
#ifdef Cdrskin_libburn_0_7_1
|
#ifdef Cdrskin_libburn_0_7_7
|
||||||
#undef Cdrskin_libburn_majoR
|
#undef Cdrskin_libburn_majoR
|
||||||
#undef Cdrskin_libburn_minoR
|
#undef Cdrskin_libburn_minoR
|
||||||
#undef Cdrskin_libburn_micrO
|
#undef Cdrskin_libburn_micrO
|
||||||
#define Cdrskin_libburn_majoR 0
|
#define Cdrskin_libburn_majoR 0
|
||||||
#define Cdrskin_libburn_minoR 7
|
#define Cdrskin_libburn_minoR 7
|
||||||
#define Cdrskin_libburn_micrO 1
|
#define Cdrskin_libburn_micrO 7
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -324,10 +323,15 @@ or
|
|||||||
/** A macro which is able to eat up a function call like printf() */
|
/** A macro which is able to eat up a function call like printf() */
|
||||||
#ifdef Cdrskin_extra_leaN
|
#ifdef Cdrskin_extra_leaN
|
||||||
#define ClN(x)
|
#define ClN(x)
|
||||||
|
#define Cdrskin_no_cdrfifO 1
|
||||||
#else
|
#else
|
||||||
#define ClN(x) x
|
#define ClN(x) x
|
||||||
|
#ifdef Cdrskin_use_libburn_fifO
|
||||||
|
/*
|
||||||
|
# define Cdrskin_no_cdrfifO 1
|
||||||
|
*/
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/** Verbosity level for pacifying progress messages */
|
/** Verbosity level for pacifying progress messages */
|
||||||
#define Cdrskin_verbose_progresS 1
|
#define Cdrskin_verbose_progresS 1
|
||||||
@ -867,12 +871,12 @@ backward:;
|
|||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
#ifndef Cdrskin_extra_leaN
|
#ifndef Cdrskin_no_cdrfifO
|
||||||
|
|
||||||
/* Program is to be linked with cdrfifo.c */
|
/* Program is to be linked with cdrfifo.c */
|
||||||
#include "cdrfifo.h"
|
#include "cdrfifo.h"
|
||||||
|
|
||||||
#else /* ! Cdrskin_extra_leaN */
|
#else /* ! Cdrskin_no_cdrfifO */
|
||||||
|
|
||||||
/* Dummy */
|
/* Dummy */
|
||||||
|
|
||||||
@ -880,7 +884,7 @@ struct CdrfifO {
|
|||||||
int dummy;
|
int dummy;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* Cdrskin_extra_leaN */
|
#endif /* Cdrskin_no_cdrfifO */
|
||||||
|
|
||||||
|
|
||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
@ -943,6 +947,10 @@ struct CdrtracK {
|
|||||||
|
|
||||||
struct burn_track *libburn_track;
|
struct burn_track *libburn_track;
|
||||||
|
|
||||||
|
#ifdef Cdrskin_use_libburn_fifO
|
||||||
|
struct burn_source *libburn_fifo;
|
||||||
|
#endif /* Cdrskin_use_libburn_fifO */
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int Cdrtrack_destroy(struct CdrtracK **o, int flag);
|
int Cdrtrack_destroy(struct CdrtracK **o, int flag);
|
||||||
@ -1000,6 +1008,9 @@ int Cdrtrack_new(struct CdrtracK **track, struct CdrskiN *boss,
|
|||||||
o->ff_fifo= NULL;
|
o->ff_fifo= NULL;
|
||||||
o->ff_idx= -1;
|
o->ff_idx= -1;
|
||||||
o->libburn_track= NULL;
|
o->libburn_track= NULL;
|
||||||
|
#ifdef Cdrskin_use_libburn_fifO
|
||||||
|
o->libburn_fifo= NULL;
|
||||||
|
#endif /* Cdrskin_use_libburn_fifO */
|
||||||
|
|
||||||
ret= Cdrskin_get_source(boss,o->source_path,&(o->fixed_size),
|
ret= Cdrskin_get_source(boss,o->source_path,&(o->fixed_size),
|
||||||
&(o->tao_to_sao_tsize),&(o->use_data_image_size),
|
&(o->tao_to_sao_tsize),&(o->use_data_image_size),
|
||||||
@ -1036,7 +1047,7 @@ int Cdrtrack_destroy(struct CdrtracK **o, int flag)
|
|||||||
if(track==NULL)
|
if(track==NULL)
|
||||||
return(0);
|
return(0);
|
||||||
|
|
||||||
#ifndef Cdrskin_extra_leaN
|
#ifndef Cdrskin_no_cdrfifO
|
||||||
Cdrfifo_destroy(&(track->fifo),0);
|
Cdrfifo_destroy(&(track->fifo),0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1122,6 +1133,61 @@ int Cdrtrack_get_source_path(struct CdrtracK *track,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef Cdrskin_use_libburn_fifO
|
||||||
|
|
||||||
|
int Cdrtrack_get_libburn_fifo(struct CdrtracK *track,
|
||||||
|
struct burn_source **fifo, int flag)
|
||||||
|
{
|
||||||
|
*fifo= track->libburn_fifo;
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Cdrtrack_report_fifo(struct CdrtracK *track, int flag)
|
||||||
|
{
|
||||||
|
int size, free_bytes, ret;
|
||||||
|
int total_min_fill, interval_min_fill, put_counter, get_counter;
|
||||||
|
int empty_counter, full_counter;
|
||||||
|
double fifo_percent;
|
||||||
|
char *status_text;
|
||||||
|
|
||||||
|
if(track->libburn_fifo == NULL)
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
/* Check for open input or leftover bytes in liburn fifo */
|
||||||
|
ret = burn_fifo_inquire_status(track->libburn_fifo, &size, &free_bytes,
|
||||||
|
&status_text);
|
||||||
|
if(ret >= 0 && size - free_bytes > 1) {
|
||||||
|
/* not clear why free_bytes is reduced by 1 */
|
||||||
|
fprintf(stderr,
|
||||||
|
"cdrskin: FATAL : Fifo still contains data after burning has ended.\n");
|
||||||
|
fprintf(stderr,
|
||||||
|
"cdrskin: FATAL : %d bytes left.\n", size - free_bytes - 1);
|
||||||
|
fprintf(stderr,
|
||||||
|
"cdrskin: FATAL : This indicates an overflow of the last track.\n");
|
||||||
|
fprintf(stderr,
|
||||||
|
"cdrskin: NOTE : The media might appear ok but is probably truncated.\n");
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
burn_fifo_get_statistics(track->libburn_fifo, &total_min_fill,
|
||||||
|
&interval_min_fill, &put_counter, &get_counter,
|
||||||
|
&empty_counter, &full_counter);
|
||||||
|
fifo_percent= 100.0*((double) total_min_fill)/(double) size;
|
||||||
|
if(fifo_percent==0 && total_min_fill>0)
|
||||||
|
fifo_percent= 1;
|
||||||
|
fflush(stdout);
|
||||||
|
fprintf(stderr,"Cdrskin: fifo had %d puts and %d gets.\n",
|
||||||
|
put_counter,get_counter);
|
||||||
|
fprintf(stderr,
|
||||||
|
"Cdrskin: fifo was %d times empty and %d times full, min fill was %.f%%.\n",
|
||||||
|
empty_counter, full_counter, fifo_percent);
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* Cdrskin_use_libburn_fifO */
|
||||||
|
|
||||||
|
|
||||||
int Cdrtrack_get_fifo(struct CdrtracK *track, struct CdrfifO **fifo, int flag)
|
int Cdrtrack_get_fifo(struct CdrtracK *track, struct CdrfifO **fifo, int flag)
|
||||||
{
|
{
|
||||||
*fifo= track->fifo;
|
*fifo= track->fifo;
|
||||||
@ -1236,7 +1302,7 @@ int Cdrtrack_activate_image_size(struct CdrtracK *track, double *size_used,
|
|||||||
}
|
}
|
||||||
track->extracting_container= 1;
|
track->extracting_container= 1;
|
||||||
|
|
||||||
#ifndef Cdrskin_extra_leaN
|
#ifndef Cdrskin_no_cdrfifO
|
||||||
if(track->ff_fifo!=NULL)
|
if(track->ff_fifo!=NULL)
|
||||||
Cdrfifo_set_fd_in_limit(track->ff_fifo,track->fixed_size,track->ff_idx,0);
|
Cdrfifo_set_fd_in_limit(track->ff_fifo,track->fixed_size,track->ff_idx,0);
|
||||||
#endif
|
#endif
|
||||||
@ -1300,6 +1366,7 @@ int Cdrtrack_seek_isosize(struct CdrtracK *track, int fd, int flag)
|
|||||||
bit0=debugging verbosity
|
bit0=debugging verbosity
|
||||||
bit1=open as source for direct write:
|
bit1=open as source for direct write:
|
||||||
no audio extract, no minimum track size
|
no audio extract, no minimum track size
|
||||||
|
bit2=permission to use burn_os_open_track_src() (evtl O_DIRECT)
|
||||||
@return <=0 error, 1 success
|
@return <=0 error, 1 success
|
||||||
*/
|
*/
|
||||||
int Cdrtrack_open_source_path(struct CdrtracK *track, int *fd, int flag)
|
int Cdrtrack_open_source_path(struct CdrtracK *track, int *fd, int flag)
|
||||||
@ -1389,8 +1456,15 @@ int Cdrtrack_open_source_path(struct CdrtracK *track, int *fd, int flag)
|
|||||||
return(-1);
|
return(-1);
|
||||||
if(is_wav==-3)
|
if(is_wav==-3)
|
||||||
return(0);
|
return(0);
|
||||||
if(is_wav==0)
|
if(is_wav==0) {
|
||||||
*fd= open(track->source_path,O_RDONLY);
|
if(track->track_type != BURN_MODE1 ||
|
||||||
|
(track->cdxa_conversion & 0x7fffffff))
|
||||||
|
flag&= ~4; /* Better avoid O_DIRECT with odd sectors */
|
||||||
|
if(flag & 4)
|
||||||
|
*fd= burn_os_open_track_src(track->source_path, O_RDONLY, 0);
|
||||||
|
else
|
||||||
|
*fd= open(track->source_path, O_RDONLY);
|
||||||
|
}
|
||||||
if(*fd==-1) {
|
if(*fd==-1) {
|
||||||
fprintf(stderr,"cdrskin: failed to open source address '%s'\n",
|
fprintf(stderr,"cdrskin: failed to open source address '%s'\n",
|
||||||
track->source_path);
|
track->source_path);
|
||||||
@ -1454,7 +1528,7 @@ int Cdrtrack_open_source_path(struct CdrtracK *track, int *fd, int flag)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef Cdrskin_extra_leaN
|
#ifndef Cdrskin_no_cdrfifO
|
||||||
|
|
||||||
/** Install a fifo object between data source and libburn.
|
/** Install a fifo object between data source and libburn.
|
||||||
Its parameters are known to track.
|
Its parameters are known to track.
|
||||||
@ -1476,7 +1550,8 @@ int Cdrtrack_attach_fifo(struct CdrtracK *track, int *outlet_fd,
|
|||||||
*outlet_fd= -1;
|
*outlet_fd= -1;
|
||||||
if(track->fifo_size<=0)
|
if(track->fifo_size<=0)
|
||||||
return(2);
|
return(2);
|
||||||
ret= Cdrtrack_open_source_path(track,&source_fd,flag&1);
|
ret= Cdrtrack_open_source_path(track,&source_fd,
|
||||||
|
(flag&1) | (4 * (track->fifo_size >= 256 * 1024)));
|
||||||
if(ret<=0)
|
if(ret<=0)
|
||||||
return(ret);
|
return(ret);
|
||||||
if(pipe(pipe_fds)==-1)
|
if(pipe(pipe_fds)==-1)
|
||||||
@ -1493,7 +1568,7 @@ int Cdrtrack_attach_fifo(struct CdrtracK *track, int *outlet_fd,
|
|||||||
|
|
||||||
/* >>> ??? obtain track sector size and use instead of 2048 ? */
|
/* >>> ??? obtain track sector size and use instead of 2048 ? */
|
||||||
|
|
||||||
ret= Cdrfifo_new(&ff,source_fd,pipe_fds[1],2048,track->fifo_size,0);
|
ret= Cdrfifo_new(&ff,source_fd,pipe_fds[1],2048,track->fifo_size, flag & 1);
|
||||||
if(ret<=0)
|
if(ret<=0)
|
||||||
return(ret);
|
return(ret);
|
||||||
if(previous_fifo!=NULL)
|
if(previous_fifo!=NULL)
|
||||||
@ -1516,18 +1591,100 @@ int Cdrtrack_attach_fifo(struct CdrtracK *track, int *outlet_fd,
|
|||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* ! Cdrskin_no_cdrfifO */
|
||||||
|
|
||||||
/** Read data into the fifo until either it is full or the data source is
|
|
||||||
exhausted.
|
#ifndef Cdrskin_extra_leaN
|
||||||
|
|
||||||
|
#ifdef Cdrskin_use_libburn_fifO
|
||||||
|
|
||||||
|
/** Read data into the eventual libburn fifo until either fifo_start_at bytes
|
||||||
|
are read (-1 = no limit), it is full or or the data source is exhausted.
|
||||||
@return <=0 error, 1 success
|
@return <=0 error, 1 success
|
||||||
*/
|
*/
|
||||||
|
int Cdrtrack_fill_libburn_fifo(struct CdrtracK *track, int fifo_start_at,
|
||||||
|
int flag)
|
||||||
|
{
|
||||||
|
int ret, bs= 32 * 1024;
|
||||||
|
int buffer_size, buffer_free;
|
||||||
|
double data_image_size;
|
||||||
|
char buf[64 * 1024], *buffer_text;
|
||||||
|
|
||||||
|
if(fifo_start_at == 0)
|
||||||
|
return(2);
|
||||||
|
if(track->libburn_fifo == NULL)
|
||||||
|
return(2);
|
||||||
|
|
||||||
|
if(fifo_start_at>0 && fifo_start_at<track->fifo_size)
|
||||||
|
printf(
|
||||||
|
"cdrskin: NOTE : Input buffer will be initially filled up to %d bytes\n",
|
||||||
|
fifo_start_at);
|
||||||
|
printf("Waiting for reader process to fill input buffer ... ");
|
||||||
|
fflush(stdout);
|
||||||
|
ret= burn_fifo_fill(track->libburn_fifo, fifo_start_at,
|
||||||
|
(fifo_start_at == -1));
|
||||||
|
if(ret < 0)
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
/** Ticket 55: check fifos for input, throw error on 0-bytes from stdin
|
||||||
|
@return <=0 abort run, 1 go on with burning
|
||||||
|
*/
|
||||||
|
ret= burn_fifo_inquire_status(track->libburn_fifo, &buffer_size,
|
||||||
|
&buffer_free, &buffer_text);
|
||||||
|
if(track->is_from_stdin) {
|
||||||
|
if(ret<0 || buffer_size <= buffer_free) {
|
||||||
|
fprintf(stderr,"\ncdrskin: FATAL : (First track) fifo did not read a single byte from stdin\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to obtain ISO 9660 Volume Descriptors and size from fifo.
|
||||||
|
Not an error if there is no ISO 9660. */
|
||||||
|
if(track->iso_fs_descr != NULL)
|
||||||
|
free(track->iso_fs_descr);
|
||||||
|
track->iso_fs_descr = NULL;
|
||||||
|
if(buffer_size - buffer_free >= 64 * 1024) {
|
||||||
|
ret= burn_fifo_peek_data(track->libburn_fifo, buf, 64 * 1024, 0);
|
||||||
|
if(ret == 1) {
|
||||||
|
track->iso_fs_descr = calloc(1, bs);
|
||||||
|
if(track->iso_fs_descr == NULL)
|
||||||
|
return(-1);
|
||||||
|
memcpy(track->iso_fs_descr, buf + bs, bs);
|
||||||
|
ret= Scan_for_iso_size((unsigned char *) buf + bs, &data_image_size, 0);
|
||||||
|
if(ret > 0)
|
||||||
|
track->data_image_size= data_image_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* Cdrskin_use_libburn_fifO */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef Cdrskin_no_cdrfifO
|
||||||
|
|
||||||
|
int Cdrtrack_fill_fifo(struct CdrtracK *track, int fifo_start_at, int flag)
|
||||||
|
{
|
||||||
|
return(Cdrtrack_fill_libburn_fifo(track, fifo_start_at, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* Cdrskin_no_cdrfifO */
|
||||||
|
|
||||||
int Cdrtrack_fill_fifo(struct CdrtracK *track, int fifo_start_at, int flag)
|
int Cdrtrack_fill_fifo(struct CdrtracK *track, int fifo_start_at, int flag)
|
||||||
{
|
{
|
||||||
int ret,buffer_fill,buffer_space;
|
int ret,buffer_fill,buffer_space;
|
||||||
double data_image_size;
|
double data_image_size;
|
||||||
|
|
||||||
if(track->fifo==NULL || fifo_start_at==0)
|
if(fifo_start_at==0)
|
||||||
return(2);
|
return(2);
|
||||||
|
if(track->fifo==NULL) {
|
||||||
|
#ifdef Cdrskin_use_libburn_fifO
|
||||||
|
ret= Cdrtrack_fill_libburn_fifo(track, fifo_start_at, 0);
|
||||||
|
return(ret);
|
||||||
|
#else
|
||||||
|
return(2);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
if(fifo_start_at>0 && fifo_start_at<track->fifo_size)
|
if(fifo_start_at>0 && fifo_start_at<track->fifo_size)
|
||||||
printf(
|
printf(
|
||||||
"cdrskin: NOTE : Input buffer will be initially filled up to %d bytes\n",
|
"cdrskin: NOTE : Input buffer will be initially filled up to %d bytes\n",
|
||||||
@ -1557,6 +1714,7 @@ int Cdrtrack_fill_fifo(struct CdrtracK *track, int fifo_start_at, int flag)
|
|||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* ! Cdrskin_no_cdrfifO */
|
||||||
#endif /* ! Cdrskin_extra_leaN */
|
#endif /* ! Cdrskin_extra_leaN */
|
||||||
|
|
||||||
|
|
||||||
@ -1568,10 +1726,11 @@ int Cdrtrack_add_to_session(struct CdrtracK *track, int trackno,
|
|||||||
/*
|
/*
|
||||||
bit0= debugging verbosity
|
bit0= debugging verbosity
|
||||||
bit1= apply padding hack (<<< should be unused for now)
|
bit1= apply padding hack (<<< should be unused for now)
|
||||||
|
bit2= permission to use O_DIRECT (if enabled at compile time)
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
struct burn_track *tr;
|
struct burn_track *tr;
|
||||||
struct burn_source *src= NULL;
|
struct burn_source *src= NULL, *fd_src= NULL;
|
||||||
double padding,lib_padding;
|
double padding,lib_padding;
|
||||||
int ret,sector_pad_up;
|
int ret,sector_pad_up;
|
||||||
double fixed_size;
|
double fixed_size;
|
||||||
@ -1583,7 +1742,7 @@ int Cdrtrack_add_to_session(struct CdrtracK *track, int trackno,
|
|||||||
|
|
||||||
/* Note: track->track_type may get set in here */
|
/* Note: track->track_type may get set in here */
|
||||||
if(track->source_fd==-1) {
|
if(track->source_fd==-1) {
|
||||||
ret= Cdrtrack_open_source_path(track,&source_fd,(flag&1));
|
ret= Cdrtrack_open_source_path(track, &source_fd, flag & (4 | 1));
|
||||||
if(ret<=0)
|
if(ret<=0)
|
||||||
goto ex;
|
goto ex;
|
||||||
}
|
}
|
||||||
@ -1615,10 +1774,8 @@ int Cdrtrack_add_to_session(struct CdrtracK *track, int trackno,
|
|||||||
burn_track_set_default_size(tr, (off_t) track->tao_to_sao_tsize);
|
burn_track_set_default_size(tr, (off_t) track->tao_to_sao_tsize);
|
||||||
burn_track_set_byte_swap(tr,
|
burn_track_set_byte_swap(tr,
|
||||||
(track->track_type==BURN_AUDIO && track->swap_audio_bytes));
|
(track->track_type==BURN_AUDIO && track->swap_audio_bytes));
|
||||||
#ifdef Cdrskin_libburn_has_cdxa_conV
|
|
||||||
if(!(track->cdxa_conversion & (1 << 31)))
|
if(!(track->cdxa_conversion & (1 << 31)))
|
||||||
burn_track_set_cdxa_conv(tr, track->cdxa_conversion & 0x7fffffff);
|
burn_track_set_cdxa_conv(tr, track->cdxa_conversion & 0x7fffffff);
|
||||||
#endif
|
|
||||||
|
|
||||||
fixed_size= track->fixed_size;
|
fixed_size= track->fixed_size;
|
||||||
if((flag&2) && track->padding>0) {
|
if((flag&2) && track->padding>0) {
|
||||||
@ -1630,6 +1787,41 @@ int Cdrtrack_add_to_session(struct CdrtracK *track, int trackno,
|
|||||||
}
|
}
|
||||||
src= burn_fd_source_new(track->source_fd,-1,(off_t) fixed_size);
|
src= burn_fd_source_new(track->source_fd,-1,(off_t) fixed_size);
|
||||||
|
|
||||||
|
#ifdef Cdrskin_use_libburn_fifO
|
||||||
|
|
||||||
|
if(src != NULL && track->fifo == NULL) {
|
||||||
|
int fifo_enabled, fifo_size, fifo_start_at, chunksize, chunks;
|
||||||
|
int Cdrskin_get_fifo_par(struct CdrskiN *skin, int *fifo_enabled,
|
||||||
|
int *fifo_size, int *fifo_start_at, int flag);
|
||||||
|
|
||||||
|
Cdrskin_get_fifo_par(track->boss, &fifo_enabled, &fifo_size, &fifo_start_at,
|
||||||
|
0);
|
||||||
|
fd_src= src;
|
||||||
|
|
||||||
|
if(track->track_type == BURN_AUDIO)
|
||||||
|
chunksize= 2352;
|
||||||
|
else if (track->cdxa_conversion == 1)
|
||||||
|
chunksize= 2056;
|
||||||
|
else
|
||||||
|
chunksize= 2048;
|
||||||
|
chunks= fifo_size / chunksize;
|
||||||
|
if(chunks > 1 && fifo_enabled) {
|
||||||
|
src= burn_fifo_source_new(fd_src, chunksize, chunks,
|
||||||
|
(chunksize * chunks >= 128 * 1024));
|
||||||
|
if((flag & 1) || src == NULL)
|
||||||
|
fprintf(stderr, "cdrskin_DEBUG: %s libburn fifo of %d bytes\n",
|
||||||
|
src != NULL ? "installed" : "failed to install",
|
||||||
|
chunksize * chunks);
|
||||||
|
track->libburn_fifo= src;
|
||||||
|
if(src == NULL) {
|
||||||
|
src= fd_src;
|
||||||
|
fd_src= NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* Cdrskin_use_libburn_fifO */
|
||||||
|
|
||||||
if(src==NULL) {
|
if(src==NULL) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"cdrskin: FATAL : Could not create libburn data source object\n");
|
"cdrskin: FATAL : Could not create libburn data source object\n");
|
||||||
@ -1642,6 +1834,8 @@ int Cdrtrack_add_to_session(struct CdrtracK *track, int trackno,
|
|||||||
burn_session_add_track(session,tr,BURN_POS_END);
|
burn_session_add_track(session,tr,BURN_POS_END);
|
||||||
ret= 1;
|
ret= 1;
|
||||||
ex:
|
ex:
|
||||||
|
if(fd_src!=NULL)
|
||||||
|
burn_source_free(fd_src);
|
||||||
if(src!=NULL)
|
if(src!=NULL)
|
||||||
burn_source_free(src);
|
burn_source_free(src);
|
||||||
return(ret);
|
return(ret);
|
||||||
@ -1692,7 +1886,7 @@ int Cdrtrack_get_sectors(struct CdrtracK *track, int flag)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef Cdrskin_extra_leaN
|
#ifndef Cdrskin_no_cdrfifO
|
||||||
|
|
||||||
/** Try to read bytes from the track's fifo outlet and eventually discard
|
/** Try to read bytes from the track's fifo outlet and eventually discard
|
||||||
them. Not to be called unless the track is completely written.
|
them. Not to be called unless the track is completely written.
|
||||||
@ -1713,7 +1907,7 @@ int Cdrtrack_has_input_left(struct CdrtracK *track, int flag)
|
|||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* ! Cdrskin_extra_leaN */
|
#endif /* ! Cdrskin_no_cdrfifO */
|
||||||
|
|
||||||
|
|
||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
@ -2140,6 +2334,8 @@ int Cdrpreskin_fallback(struct CdrpreskiN *preskin, int argc, char **argv,
|
|||||||
int i, wp= 1;
|
int i, wp= 1;
|
||||||
char *ept, *upt;
|
char *ept, *upt;
|
||||||
|
|
||||||
|
if(preskin->fallback_program[0] == 0)
|
||||||
|
return(1);
|
||||||
if(getuid()!=geteuid() && !preskin->allow_setuid) {
|
if(getuid()!=geteuid() && !preskin->allow_setuid) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"cdrskin: SORRY : uid and euid differ. Will not start external fallback program.\n");
|
"cdrskin: SORRY : uid and euid differ. Will not start external fallback program.\n");
|
||||||
@ -2676,6 +2872,9 @@ set_dev:;
|
|||||||
printf(
|
printf(
|
||||||
" --drive_scsi_exclusive try to exclusively reserve device files\n");
|
" --drive_scsi_exclusive try to exclusively reserve device files\n");
|
||||||
printf(" /dev/srN, /dev/scdM, /dev/stK of drive.\n");
|
printf(" /dev/srN, /dev/scdM, /dev/stK of drive.\n");
|
||||||
|
printf(" dvd_obs=\"default\"|number\n");
|
||||||
|
printf(
|
||||||
|
" set number of bytes per DVD/BD write: 32k or 64k\n");
|
||||||
#ifdef Cdrskin_burn_drive_eject_brokeN
|
#ifdef Cdrskin_burn_drive_eject_brokeN
|
||||||
printf(
|
printf(
|
||||||
" eject_device=<path> set the device address for command eject\n");
|
" eject_device=<path> set the device address for command eject\n");
|
||||||
@ -2726,6 +2925,11 @@ set_dev:;
|
|||||||
printf(
|
printf(
|
||||||
" byte addresses below that number.\n");
|
" byte addresses below that number.\n");
|
||||||
#endif
|
#endif
|
||||||
|
printf(" stdio_sync=\"default\"|\"off\"|number\n");
|
||||||
|
printf(
|
||||||
|
" set number of bytes after which to force output\n");
|
||||||
|
printf(
|
||||||
|
" to drives with prefix \"stdio:\".\n");
|
||||||
|
|
||||||
#ifdef Cdrskin_allow_libburn_taO
|
#ifdef Cdrskin_allow_libburn_taO
|
||||||
printf(
|
printf(
|
||||||
@ -2791,7 +2995,9 @@ see_cdrskin_eng_html:;
|
|||||||
"\tdev=target\tpseudo-SCSI target to use as CD-Recorder\n");
|
"\tdev=target\tpseudo-SCSI target to use as CD-Recorder\n");
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"\tgracetime=#\tset the grace time before starting to write to #.\n");
|
"\tgracetime=#\tset the grace time before starting to write to #.\n");
|
||||||
fprintf(stderr,"\t-v\t\tincrement verbose level by one\n");
|
fprintf(stderr,"\t-v\t\tincrement general verbose level by one\n");
|
||||||
|
fprintf(stderr,
|
||||||
|
"\t-V\t\tincrement SCSI command transport verbose level by one\n");
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"\tdriveropts=opt\topt= one of {burnfree,noburnfree,help}\n");
|
"\tdriveropts=opt\topt= one of {burnfree,noburnfree,help}\n");
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
@ -2918,12 +3124,16 @@ see_cdrskin_eng_html:;
|
|||||||
} else if(strcmp(argv[i],"-tao")==0) {
|
} else if(strcmp(argv[i],"-tao")==0) {
|
||||||
strcpy(o->write_mode_name,"TAO");
|
strcpy(o->write_mode_name,"TAO");
|
||||||
|
|
||||||
|
} else if(strcmp(argv[i],"-V")==0 || strcmp(argv[i],"-Verbose")==0) {
|
||||||
|
burn_set_scsi_logging(2 | 4); /* log SCSI to stderr */
|
||||||
|
|
||||||
} else if(strcmp(argv[i],"-v")==0 || strcmp(argv[i],"-verbose")==0) {
|
} else if(strcmp(argv[i],"-v")==0 || strcmp(argv[i],"-verbose")==0) {
|
||||||
(o->verbosity)++;
|
(o->verbosity)++;
|
||||||
ClN(printf("cdrskin: verbosity level : %d\n",o->verbosity));
|
ClN(printf("cdrskin: verbosity level : %d\n",o->verbosity));
|
||||||
set_severities:;
|
set_severities:;
|
||||||
if(o->verbosity>=Cdrskin_verbose_debuG)
|
if(o->verbosity>=Cdrskin_verbose_debuG)
|
||||||
Cdrpreskin_set_severities(o,"NEVER","DEBUG",0);
|
Cdrpreskin_set_severities(o,"NEVER","DEBUG",0);
|
||||||
|
|
||||||
} else if(strcmp(argv[i],"-vv")==0 || strcmp(argv[i],"-vvv")==0 ||
|
} else if(strcmp(argv[i],"-vv")==0 || strcmp(argv[i],"-vvv")==0 ||
|
||||||
strcmp(argv[i],"-vvvv")==0) {
|
strcmp(argv[i],"-vvvv")==0) {
|
||||||
(o->verbosity)+= strlen(argv[i])-1;
|
(o->verbosity)+= strlen(argv[i])-1;
|
||||||
@ -2933,7 +3143,17 @@ set_severities:;
|
|||||||
int major, minor, micro;
|
int major, minor, micro;
|
||||||
|
|
||||||
printf(
|
printf(
|
||||||
"Cdrecord 2.01-Emulation Copyright (C) 2006-2009, see libburnia-project.org\n");
|
"Cdrecord 2.01-Emulation Copyright (C) 2006-2010, see libburnia-project.org\n");
|
||||||
|
if(o->fallback_program[0]) {
|
||||||
|
char *hargv[2];
|
||||||
|
|
||||||
|
printf("Fallback program : %s\n",o->fallback_program);
|
||||||
|
printf("Fallback version :\n");
|
||||||
|
hargv[0]= argv[0];
|
||||||
|
hargv[1]= "-version";
|
||||||
|
Cdrpreskin_fallback(o,2,hargv,1); /* dirty never come back */
|
||||||
|
}
|
||||||
|
printf("System adapter : %s\n", burn_scsi_transport_id(0));
|
||||||
printf("libburn interface : %d.%d.%d\n",
|
printf("libburn interface : %d.%d.%d\n",
|
||||||
burn_header_version_major, burn_header_version_minor,
|
burn_header_version_major, burn_header_version_minor,
|
||||||
burn_header_version_micro);
|
burn_header_version_micro);
|
||||||
@ -2949,15 +3169,6 @@ set_severities:;
|
|||||||
|
|
||||||
printf("Version timestamp : %s\n",Cdrskin_timestamP);
|
printf("Version timestamp : %s\n",Cdrskin_timestamP);
|
||||||
printf("Build timestamp : %s\n",Cdrskin_build_timestamP);
|
printf("Build timestamp : %s\n",Cdrskin_build_timestamP);
|
||||||
if(o->fallback_program[0]) {
|
|
||||||
char *hargv[2];
|
|
||||||
|
|
||||||
printf("Fallback program : %s\n",o->fallback_program);
|
|
||||||
printf("Fallback version :\n");
|
|
||||||
hargv[0]= argv[0];
|
|
||||||
hargv[1]= "-version";
|
|
||||||
Cdrpreskin_fallback(o,2,hargv,1); /* dirty never come back */
|
|
||||||
}
|
|
||||||
{ret= 2; goto ex;}
|
{ret= 2; goto ex;}
|
||||||
|
|
||||||
} else if(strcmp(argv[i],"-waiti")==0) {
|
} else if(strcmp(argv[i],"-waiti")==0) {
|
||||||
@ -2974,7 +3185,9 @@ set_severities:;
|
|||||||
final_checks:;
|
final_checks:;
|
||||||
if(flag&1)
|
if(flag&1)
|
||||||
goto ex;
|
goto ex;
|
||||||
|
if(o->verbosity >= Cdrskin_verbose_debuG)
|
||||||
|
ClN(fprintf(stderr,
|
||||||
|
"cdrskin: DEBUG : Using %s\n", burn_scsi_transport_id(0)));
|
||||||
if(o->do_waiti) {
|
if(o->do_waiti) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"cdrskin: Option -waiti pauses program until input appears at stdin\n");
|
"cdrskin: Option -waiti pauses program until input appears at stdin\n");
|
||||||
@ -3105,19 +3318,10 @@ ex:;
|
|||||||
|
|
||||||
|
|
||||||
/** List of furter wishes towards libburn:
|
/** List of furter wishes towards libburn:
|
||||||
- write mode which does not demand a track size in advance
|
|
||||||
- obtain minimum drive speed (for cdrskin -atip)
|
|
||||||
- obtain MMC profile of inserted media (for cdrskin -v -atip)
|
|
||||||
- a possibility to implement cdrskin -multi
|
|
||||||
- a possibilty to implement cdrskin -reset
|
- a possibilty to implement cdrskin -reset
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/** <<< Hopefully obsolete:
|
|
||||||
Limit to prevent int rollovers within libburn as long as not everything is
|
|
||||||
changed to 64 bit off_t : 2 GB minus 800 MB for eventual computations.
|
|
||||||
#define Cdrskin_tracksize_maX 1308622848
|
|
||||||
*/
|
|
||||||
#define Cdrskin_tracksize_maX 1024.0*1024.0*1024.0*1024.0
|
#define Cdrskin_tracksize_maX 1024.0*1024.0*1024.0*1024.0
|
||||||
|
|
||||||
|
|
||||||
@ -3166,6 +3370,8 @@ struct CdrskiN {
|
|||||||
int dummy_mode;
|
int dummy_mode;
|
||||||
int force_is_set;
|
int force_is_set;
|
||||||
int stream_recording_is_set; /* see burn_write_opts_set_stream_recording() */
|
int stream_recording_is_set; /* see burn_write_opts_set_stream_recording() */
|
||||||
|
int dvd_obs; /* DVD write chunk size: 0, 32k or 64k */
|
||||||
|
int stdio_sync; /* stdio fsync interval: -1, 0, >=32 */
|
||||||
int single_track;
|
int single_track;
|
||||||
int prodvd_cli_compatible;
|
int prodvd_cli_compatible;
|
||||||
|
|
||||||
@ -3384,6 +3590,8 @@ int Cdrskin_new(struct CdrskiN **skin, struct CdrpreskiN *preskin, int flag)
|
|||||||
o->dummy_mode= 0;
|
o->dummy_mode= 0;
|
||||||
o->force_is_set= 0;
|
o->force_is_set= 0;
|
||||||
o->stream_recording_is_set= 0;
|
o->stream_recording_is_set= 0;
|
||||||
|
o->dvd_obs= 0;
|
||||||
|
o->stdio_sync= 0;
|
||||||
o->single_track= 0;
|
o->single_track= 0;
|
||||||
o->prodvd_cli_compatible= 0;
|
o->prodvd_cli_compatible= 0;
|
||||||
o->do_devices= 0;
|
o->do_devices= 0;
|
||||||
@ -3558,6 +3766,8 @@ int Cdrskin_get_fifo_par(struct CdrskiN *skin, int *fifo_enabled,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef Cdrskin_no_cdrfifO
|
||||||
|
|
||||||
/** Create and install fifo objects between track data sources and libburn.
|
/** Create and install fifo objects between track data sources and libburn.
|
||||||
The sources and parameters are known to skin.
|
The sources and parameters are known to skin.
|
||||||
@return <=0 error, 1 success
|
@return <=0 error, 1 success
|
||||||
@ -3567,6 +3777,20 @@ int Cdrskin_attach_fifo(struct CdrskiN *skin, int flag)
|
|||||||
struct CdrfifO *ff= NULL;
|
struct CdrfifO *ff= NULL;
|
||||||
int ret,i,hflag;
|
int ret,i,hflag;
|
||||||
|
|
||||||
|
#ifdef Cdrskin_use_libburn_fifO
|
||||||
|
|
||||||
|
int profile_number;
|
||||||
|
char profile_name[80];
|
||||||
|
|
||||||
|
/* Refuse here and thus use libburn fifo only with single track, non-CD */
|
||||||
|
ret= burn_disc_get_profile(skin->drives[skin->driveno].drive,
|
||||||
|
&profile_number, profile_name);
|
||||||
|
if(profile_number != 0x09 && profile_number != 0x0a &&
|
||||||
|
skin->track_counter == 1)
|
||||||
|
return(1);
|
||||||
|
|
||||||
|
#endif /* Cdrskin_use_libburn_fifO */
|
||||||
|
|
||||||
skin->fifo= NULL;
|
skin->fifo= NULL;
|
||||||
for(i=0;i<skin->track_counter;i++) {
|
for(i=0;i<skin->track_counter;i++) {
|
||||||
hflag= (skin->verbosity>=Cdrskin_verbose_debuG);
|
hflag= (skin->verbosity>=Cdrskin_verbose_debuG);
|
||||||
@ -3598,6 +3822,8 @@ int Cdrskin_attach_fifo(struct CdrskiN *skin, int flag)
|
|||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* ! Cdrskin_no_cdrfifO */
|
||||||
|
|
||||||
|
|
||||||
/** Read data into the track fifos until either #1 is full or its data source
|
/** Read data into the track fifos until either #1 is full or its data source
|
||||||
is exhausted.
|
is exhausted.
|
||||||
@ -3940,7 +4166,7 @@ int Cdrskin_abort_handler(struct CdrskiN *skin, int signum, int flag)
|
|||||||
if(skin->preskin->abort_handler==3)
|
if(skin->preskin->abort_handler==3)
|
||||||
fprintf(stderr,"cdrskin: ABORT : Trying to ignore any further signals\n");
|
fprintf(stderr,"cdrskin: ABORT : Trying to ignore any further signals\n");
|
||||||
|
|
||||||
#ifndef Cdrskin_extra_leaN
|
#ifndef Cdrskin_no_cdrfifO
|
||||||
if(skin->fifo!=NULL)
|
if(skin->fifo!=NULL)
|
||||||
Cdrfifo_close_all(skin->fifo,0);
|
Cdrfifo_close_all(skin->fifo,0);
|
||||||
#endif
|
#endif
|
||||||
@ -5270,14 +5496,8 @@ int Cdrskin_atip(struct CdrskiN *skin, int flag)
|
|||||||
burn_lba_to_msf(end_lba,&m_lo,&s_lo,&f_lo);
|
burn_lba_to_msf(end_lba,&m_lo,&s_lo,&f_lo);
|
||||||
printf(" ATIP start of lead out: %d (%-2.2d:%-2.2d/%-2.2d)\n",
|
printf(" ATIP start of lead out: %d (%-2.2d:%-2.2d/%-2.2d)\n",
|
||||||
end_lba, m_lo, s_lo, f_lo);
|
end_lba, m_lo, s_lo, f_lo);
|
||||||
|
|
||||||
#ifdef Cdrskin_libburn_has_product_iD
|
|
||||||
|
|
||||||
if(current_is_cd)
|
if(current_is_cd)
|
||||||
manuf= burn_guess_cd_manufacturer(min, sec, fr, m_lo, s_lo, f_lo, 0);
|
manuf= burn_guess_cd_manufacturer(min, sec, fr, m_lo, s_lo, f_lo, 0);
|
||||||
|
|
||||||
#endif /* Cdrskin_libburn_has_product_iD */
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* Cdrskin_libburn_has_get_start_end_lbA */
|
#endif /* Cdrskin_libburn_has_get_start_end_lbA */
|
||||||
@ -5285,8 +5505,6 @@ int Cdrskin_atip(struct CdrskiN *skin, int flag)
|
|||||||
printf(" 1T speed low: %.f 1T speed high: %.f\n",x_speed_min,x_speed_max);
|
printf(" 1T speed low: %.f 1T speed high: %.f\n",x_speed_min,x_speed_max);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef Cdrskin_libburn_has_product_iD
|
|
||||||
|
|
||||||
ret= burn_disc_get_media_id(drive, &product_id, &media_code1, &media_code2,
|
ret= burn_disc_get_media_id(drive, &product_id, &media_code1, &media_code2,
|
||||||
&book_type, 0);
|
&book_type, 0);
|
||||||
if(ret > 0 && (!current_is_cd) &&
|
if(ret > 0 && (!current_is_cd) &&
|
||||||
@ -5294,9 +5512,6 @@ int Cdrskin_atip(struct CdrskiN *skin, int flag)
|
|||||||
|
|
||||||
manuf= burn_guess_manufacturer(profile_number, media_code1, media_code2, 0);
|
manuf= burn_guess_manufacturer(profile_number, media_code1, media_code2, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* Cdrskin_libburn_has_product_iD */
|
|
||||||
|
|
||||||
if(product_id != NULL)
|
if(product_id != NULL)
|
||||||
printf("Product Id: %s\n", product_id);
|
printf("Product Id: %s\n", product_id);
|
||||||
if(manuf != NULL)
|
if(manuf != NULL)
|
||||||
@ -5312,14 +5527,8 @@ int Cdrskin_atip(struct CdrskiN *skin, int flag)
|
|||||||
if(book_type != NULL)
|
if(book_type != NULL)
|
||||||
free(book_type);
|
free(book_type);
|
||||||
product_id= media_code1= media_code2= book_type= NULL;
|
product_id= media_code1= media_code2= book_type= NULL;
|
||||||
|
|
||||||
#ifdef Cdrskin_libburn_has_product_iD
|
|
||||||
ret= burn_disc_get_media_id(drive, &product_id, &media_code1,
|
ret= burn_disc_get_media_id(drive, &product_id, &media_code1,
|
||||||
&media_code2, &book_type, 1);
|
&media_code2, &book_type, 1);
|
||||||
#else
|
|
||||||
ret= 0;
|
|
||||||
#endif /* Cdrskin_libburn_has_product_iD */
|
|
||||||
|
|
||||||
if(ret > 0) {
|
if(ret > 0) {
|
||||||
if(profile_number == 0x11 || profile_number == 0x13 ||
|
if(profile_number == 0x11 || profile_number == 0x13 ||
|
||||||
profile_number == 0x14 || profile_number == 0x15)
|
profile_number == 0x14 || profile_number == 0x15)
|
||||||
@ -5852,16 +6061,28 @@ int Cdrskin_burn_pacifier(struct CdrskiN *skin,
|
|||||||
bit0= growisofs style
|
bit0= growisofs style
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
double bytes_to_write,written_bytes= 0.0,written_total_bytes= 0.0,buffer_size;
|
double bytes_to_write= 0.0;
|
||||||
|
double written_bytes= 0.0,written_total_bytes= 0.0;
|
||||||
double fixed_size,padding,sector_size,speed_factor;
|
double fixed_size,padding,sector_size,speed_factor;
|
||||||
double measured_total_speed,measured_speed;
|
double measured_total_speed,measured_speed;
|
||||||
double elapsed_time,elapsed_total_time,current_time;
|
double elapsed_time,elapsed_total_time,current_time;
|
||||||
double estim_time,estim_minutes,estim_seconds,percent;
|
double estim_time,estim_minutes,estim_seconds,percent;
|
||||||
int ret,fifo_percent,fill,space,advance_interval=0,new_mb,old_mb,time_to_tell;
|
int ret,fifo_percent,fill,advance_interval=0,new_mb,old_mb,time_to_tell;
|
||||||
int fs,bs,old_track_idx,buffer_fill,formatting= 0,use_data_image_size;
|
int old_track_idx,buffer_fill,formatting= 0,use_data_image_size;
|
||||||
char fifo_text[80],mb_text[40];
|
char fifo_text[80],mb_text[40], pending[40];
|
||||||
char *debug_mark= ""; /* use this to prepend a marker text for experiments */
|
char *debug_mark= ""; /* use this to prepend a marker text for experiments */
|
||||||
|
|
||||||
|
#ifndef Cdrskin_no_cdrfifO
|
||||||
|
double buffer_size;
|
||||||
|
int fs, bs, space;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef Cdrskin_use_libburn_fifO
|
||||||
|
struct burn_source *current_fifo= NULL;
|
||||||
|
int size, free_space;
|
||||||
|
char *status_text= "";
|
||||||
|
#endif /* Cdrskin_use_libburn_fifO */
|
||||||
|
|
||||||
/* for debugging */
|
/* for debugging */
|
||||||
static double last_fifo_in= 0.0,last_fifo_out= 0.0,curr_fifo_in,curr_fifo_out;
|
static double last_fifo_in= 0.0,last_fifo_out= 0.0,curr_fifo_in,curr_fifo_out;
|
||||||
|
|
||||||
@ -5965,9 +6186,14 @@ thank_you_for_patience:;
|
|||||||
if(skin->verbosity>=Cdrskin_verbose_progresS) {
|
if(skin->verbosity>=Cdrskin_verbose_progresS) {
|
||||||
if(skin->is_writing)
|
if(skin->is_writing)
|
||||||
fprintf(stderr,"\n");
|
fprintf(stderr,"\n");
|
||||||
|
pending[0]= 0;
|
||||||
|
/*
|
||||||
|
if(bytes_to_write > 0 && skin->verbosity >= Cdrskin_verbose_debuG)
|
||||||
|
sprintf(pending, " pnd %.f", bytes_to_write - written_total_bytes);
|
||||||
|
*/
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"\rcdrskin: thank you for being patient for %.f seconds ",
|
"\rcdrskin: thank you for being patient for %.f seconds%21.21s",
|
||||||
elapsed_total_time);
|
elapsed_total_time, pending);
|
||||||
}
|
}
|
||||||
advance_interval= 1;
|
advance_interval= 1;
|
||||||
}
|
}
|
||||||
@ -6032,6 +6258,37 @@ thank_you_for_patience:;
|
|||||||
fifo_text[0]= 0;
|
fifo_text[0]= 0;
|
||||||
curr_fifo_in= last_fifo_in;
|
curr_fifo_in= last_fifo_in;
|
||||||
curr_fifo_out= last_fifo_out;
|
curr_fifo_out= last_fifo_out;
|
||||||
|
|
||||||
|
#ifdef Cdrskin_use_libburn_fifO
|
||||||
|
|
||||||
|
/* Inquire fifo fill and format fifo pacifier text */
|
||||||
|
if(skin->fifo == NULL && skin->supposed_track_idx >= 0 &&
|
||||||
|
skin->supposed_track_idx < skin->track_counter &&
|
||||||
|
skin->fifo_size > 0) {
|
||||||
|
Cdrtrack_get_libburn_fifo(skin->tracklist[skin->supposed_track_idx],
|
||||||
|
¤t_fifo, 0);
|
||||||
|
if(current_fifo != NULL) {
|
||||||
|
ret= burn_fifo_inquire_status(current_fifo, &size, &free_space,
|
||||||
|
&status_text);
|
||||||
|
if(ret <= 0 || ret >= 4) {
|
||||||
|
strcpy(fifo_text, "(fifo 0%) ");
|
||||||
|
} else if(ret == 1) {
|
||||||
|
burn_fifo_next_interval(current_fifo, &fill);
|
||||||
|
fifo_percent= 100.0 * ((double) fill) / (double) size;
|
||||||
|
if(fifo_percent<100 && fill>0)
|
||||||
|
fifo_percent++;
|
||||||
|
sprintf(fifo_text, "(fifo %3d%%) ", fifo_percent);
|
||||||
|
} else
|
||||||
|
strcpy(fifo_text, "(fifo 100%) ");
|
||||||
|
} else if(skin->fifo_size > 0) {
|
||||||
|
strcpy(fifo_text, "(fifo 100%) ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* Cdrskin_use_libburn_fifO */
|
||||||
|
|
||||||
|
#ifndef Cdrskin_no_cdrfifO
|
||||||
|
|
||||||
if(skin->fifo!=NULL) {
|
if(skin->fifo!=NULL) {
|
||||||
ret= Cdrfifo_get_buffer_state(skin->fifo,&fill,&space,0);
|
ret= Cdrfifo_get_buffer_state(skin->fifo,&fill,&space,0);
|
||||||
buffer_size= fill+space;
|
buffer_size= fill+space;
|
||||||
@ -6060,6 +6317,9 @@ thank_you_for_patience:;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* ! Cdrskin_no_cdrfifO */
|
||||||
|
|
||||||
if(skin->supposed_track_idx >= 0 &&
|
if(skin->supposed_track_idx >= 0 &&
|
||||||
skin->supposed_track_idx < skin->track_counter) {
|
skin->supposed_track_idx < skin->track_counter) {
|
||||||
/* fixed_size,padding are fetched above via Cdrtrack_get_size() */;
|
/* fixed_size,padding are fetched above via Cdrtrack_get_size() */;
|
||||||
@ -6570,7 +6830,8 @@ int Cdrskin_direct_write(struct CdrskiN *skin, int flag)
|
|||||||
&source_path,&source_fd,&is_from_stdin,0);
|
&source_path,&source_fd,&is_from_stdin,0);
|
||||||
if(source_fd==-1) {
|
if(source_fd==-1) {
|
||||||
ret= Cdrtrack_open_source_path(skin->tracklist[0],&source_fd,
|
ret= Cdrtrack_open_source_path(skin->tracklist[0],&source_fd,
|
||||||
2|(skin->verbosity>=Cdrskin_verbose_debuG));
|
2 | (skin->verbosity >= Cdrskin_verbose_debuG) |
|
||||||
|
(4 * (skin->fifo_size >= 256 * 1024)));
|
||||||
if(ret<=0)
|
if(ret<=0)
|
||||||
goto ex;
|
goto ex;
|
||||||
}
|
}
|
||||||
@ -6737,15 +6998,19 @@ int Cdrskin_burn(struct CdrskiN *skin, int flag)
|
|||||||
struct burn_progress p;
|
struct burn_progress p;
|
||||||
struct burn_drive *drive;
|
struct burn_drive *drive;
|
||||||
int ret,loop_counter= 0,max_track= -1,i,hflag,nwa,num, wrote_well= 2;
|
int ret,loop_counter= 0,max_track= -1,i,hflag,nwa,num, wrote_well= 2;
|
||||||
int fifo_disabled= 0,fifo_percent,total_min_fill,min_buffer_fill= 101;
|
int fifo_disabled= 0, min_buffer_fill= 101;
|
||||||
int use_data_image_size, needs_early_fifo_fill= 0,iso_size= -1;
|
int use_data_image_size, needs_early_fifo_fill= 0,iso_size= -1;
|
||||||
double put_counter,get_counter,empty_counter,full_counter;
|
|
||||||
double start_time,last_time;
|
double start_time,last_time;
|
||||||
double total_count= 0.0,last_count= 0.0,size,padding,sector_size= 2048.0;
|
double total_count= 0.0,last_count= 0.0,size,padding,sector_size= 2048.0;
|
||||||
char *doing;
|
char *doing;
|
||||||
char *source_path;
|
char *source_path;
|
||||||
int source_fd, is_from_stdin;
|
int source_fd, is_from_stdin;
|
||||||
|
|
||||||
|
#ifndef Cdrskin_no_cdrfifO
|
||||||
|
double put_counter, get_counter, empty_counter, full_counter;
|
||||||
|
int total_min_fill, fifo_percent;
|
||||||
|
#endif
|
||||||
|
|
||||||
if(skin->tell_media_space)
|
if(skin->tell_media_space)
|
||||||
doing= "estimating";
|
doing= "estimating";
|
||||||
else
|
else
|
||||||
@ -6804,6 +7069,11 @@ burn_failed:;
|
|||||||
hflag= (skin->verbosity>=Cdrskin_verbose_debuG);
|
hflag= (skin->verbosity>=Cdrskin_verbose_debuG);
|
||||||
if(i==skin->track_counter-1)
|
if(i==skin->track_counter-1)
|
||||||
Cdrtrack_ensure_padding(skin->tracklist[i],hflag&1);
|
Cdrtrack_ensure_padding(skin->tracklist[i],hflag&1);
|
||||||
|
|
||||||
|
/* if(skin->fifo_size >= 256 * 1024) */
|
||||||
|
|
||||||
|
hflag|= 4;
|
||||||
|
|
||||||
ret= Cdrtrack_add_to_session(skin->tracklist[i],i,session,hflag);
|
ret= Cdrtrack_add_to_session(skin->tracklist[i],i,session,hflag);
|
||||||
if(ret<=0) {
|
if(ret<=0) {
|
||||||
fprintf(stderr,"cdrskin: FATAL : Cannot add track %d to session.\n",i+1);
|
fprintf(stderr,"cdrskin: FATAL : Cannot add track %d to session.\n",i+1);
|
||||||
@ -6939,6 +7209,13 @@ burn_failed:;
|
|||||||
#ifdef Cdrskin_libburn_has_stream_recordinG
|
#ifdef Cdrskin_libburn_has_stream_recordinG
|
||||||
burn_write_opts_set_stream_recording(o, skin->stream_recording_is_set);
|
burn_write_opts_set_stream_recording(o, skin->stream_recording_is_set);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef Cdrskin_dvd_obs_default_64K
|
||||||
|
if(skin->dvd_obs == 0)
|
||||||
|
burn_write_opts_set_dvd_obs(o, 64 * 1024);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
burn_write_opts_set_dvd_obs(o, skin->dvd_obs);
|
||||||
|
burn_write_opts_set_stdio_fsync(o, skin->stdio_sync);
|
||||||
|
|
||||||
if(skin->dummy_mode) {
|
if(skin->dummy_mode) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
@ -7062,6 +7339,14 @@ fifo_filling_failed:;
|
|||||||
if(skin->fifo==NULL || fifo_disabled) {
|
if(skin->fifo==NULL || fifo_disabled) {
|
||||||
usleep(20000);
|
usleep(20000);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
#ifdef Cdrskin_no_cdrfifO
|
||||||
|
|
||||||
|
/* Should never happen as skin->fifo should be NULL */
|
||||||
|
usleep(20000);
|
||||||
|
|
||||||
|
#else /* Cdrskin_no_cdrfifO */
|
||||||
|
|
||||||
ret= Cdrfifo_try_to_work(skin->fifo,20000,NULL,NULL,0);
|
ret= Cdrfifo_try_to_work(skin->fifo,20000,NULL,NULL,0);
|
||||||
if(ret<0) {
|
if(ret<0) {
|
||||||
int abh;
|
int abh;
|
||||||
@ -7087,7 +7372,11 @@ fifo_filling_failed:;
|
|||||||
fprintf(stderr,"\ncdrskin_debug: fifo ended work with ret=%d\n",ret);
|
fprintf(stderr,"\ncdrskin_debug: fifo ended work with ret=%d\n",ret);
|
||||||
fifo_disabled= 1;
|
fifo_disabled= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* ! Cdrskin_no_cdrfifO */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* ! Cdrskin_extra_leaN */
|
#else /* ! Cdrskin_extra_leaN */
|
||||||
usleep(20000);
|
usleep(20000);
|
||||||
#endif /* Cdrskin_extra_leaN */
|
#endif /* Cdrskin_extra_leaN */
|
||||||
@ -7127,6 +7416,19 @@ fifo_filling_failed:;
|
|||||||
|
|
||||||
#ifndef Cdrskin_extra_leaN
|
#ifndef Cdrskin_extra_leaN
|
||||||
|
|
||||||
|
#ifdef Cdrskin_use_libburn_fifO
|
||||||
|
|
||||||
|
if(skin->fifo == NULL && skin->verbosity>=Cdrskin_verbose_progresS) {
|
||||||
|
/* >>> this should rather be done for each track
|
||||||
|
(for now this libburn_fifo should only be used with single track)
|
||||||
|
*/
|
||||||
|
Cdrtrack_report_fifo(skin->tracklist[skin->track_counter - 1], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* Cdrskin_use_libburn_fifO */
|
||||||
|
|
||||||
|
#ifndef Cdrskin_no_cdrfifO
|
||||||
|
|
||||||
if(skin->fifo!=NULL && skin->fifo_size>0 && wrote_well) {
|
if(skin->fifo!=NULL && skin->fifo_size>0 && wrote_well) {
|
||||||
int dummy,final_fill;
|
int dummy,final_fill;
|
||||||
Cdrfifo_get_buffer_state(skin->fifo,&final_fill,&dummy,0);
|
Cdrfifo_get_buffer_state(skin->fifo,&final_fill,&dummy,0);
|
||||||
@ -7174,6 +7476,11 @@ fifo_full_at_end:;
|
|||||||
"Cdrskin: fifo was %.f times empty and %.f times full, min fill was %d%%.\n",
|
"Cdrskin: fifo was %.f times empty and %.f times full, min fill was %d%%.\n",
|
||||||
empty_counter,full_counter,fifo_percent);
|
empty_counter,full_counter,fifo_percent);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* ! Cdrskin_no_cdrfifO */
|
||||||
|
|
||||||
|
if(skin->verbosity>=Cdrskin_verbose_progresS) {
|
||||||
drive_status= burn_drive_get_status(drive, &p);
|
drive_status= burn_drive_get_status(drive, &p);
|
||||||
|
|
||||||
#ifdef Cdrskin_libburn_has_buffer_min_filL
|
#ifdef Cdrskin_libburn_has_buffer_min_filL
|
||||||
@ -7471,7 +7778,7 @@ int Cdrskin_setup(struct CdrskiN *skin, int argc, char **argv, int flag)
|
|||||||
""
|
""
|
||||||
};
|
};
|
||||||
static char ignored_full_options[][41]= {
|
static char ignored_full_options[][41]= {
|
||||||
"-d", "-Verbose", "-V", "-silent", "-s", "-setdropts", "-prcap",
|
"-d", "-silent", "-s", "-setdropts", "-prcap",
|
||||||
"-reset", "-abort", "-overburn", "-ignsize", "-useinfo",
|
"-reset", "-abort", "-overburn", "-ignsize", "-useinfo",
|
||||||
"-fix", "-nofix",
|
"-fix", "-nofix",
|
||||||
"-raw", "-raw96p", "-raw16", "-raw96r",
|
"-raw", "-raw96p", "-raw16", "-raw96r",
|
||||||
@ -7813,6 +8120,22 @@ set_driveropts:;
|
|||||||
} else if(strcmp(argv[i],"-dummy")==0) {
|
} else if(strcmp(argv[i],"-dummy")==0) {
|
||||||
skin->dummy_mode= 1;
|
skin->dummy_mode= 1;
|
||||||
|
|
||||||
|
} else if(strncmp(argv[i], "-dvd_obs=", 9)==0) {
|
||||||
|
value_pt= argv[i] + 9;
|
||||||
|
goto dvd_obs;
|
||||||
|
} else if(strncmp(argv[i], "dvd_obs=", 8)==0) {
|
||||||
|
value_pt= argv[i] + 8;
|
||||||
|
dvd_obs:;
|
||||||
|
if(strcmp(value_pt, "default") == 0)
|
||||||
|
num= 0;
|
||||||
|
else
|
||||||
|
num = Scanf_io_size(value_pt,0);
|
||||||
|
if(num != 0 && num != 32768 && num != 65536) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"cdrskin: SORRY : Option dvd_obs= accepts only sizes 0, 32k, 64k\n");
|
||||||
|
} else
|
||||||
|
skin->dvd_obs= num;
|
||||||
|
|
||||||
} else if(strcmp(argv[i],"-eject")==0) {
|
} else if(strcmp(argv[i],"-eject")==0) {
|
||||||
skin->do_eject= 1;
|
skin->do_eject= 1;
|
||||||
if(skin->verbosity>=Cdrskin_verbose_cmD)
|
if(skin->verbosity>=Cdrskin_verbose_cmD)
|
||||||
@ -8203,6 +8526,26 @@ set_speed:;
|
|||||||
if(skin->verbosity>=Cdrskin_verbose_cmD)
|
if(skin->verbosity>=Cdrskin_verbose_cmD)
|
||||||
ClN(printf("cdrskin: speed : %f\n",skin->x_speed));
|
ClN(printf("cdrskin: speed : %f\n",skin->x_speed));
|
||||||
|
|
||||||
|
} else if(strncmp(argv[i], "-stdio_sync=", 12)==0) {
|
||||||
|
value_pt= argv[i] + 12;
|
||||||
|
goto stdio_sync;
|
||||||
|
} else if(strncmp(argv[i], "stdio_sync=", 11)==0) {
|
||||||
|
value_pt= argv[i] + 11;
|
||||||
|
stdio_sync:;
|
||||||
|
if(strcmp(value_pt, "default") == 0 || strcmp(value_pt, "on") == 0)
|
||||||
|
num= 0;
|
||||||
|
else if(strcmp(value_pt, "off") == 0)
|
||||||
|
num= -1;
|
||||||
|
else
|
||||||
|
num = Scanf_io_size(value_pt,0);
|
||||||
|
if(num > 0)
|
||||||
|
num/= 2048;
|
||||||
|
if(num != -1 && num != 0 && (num < 32 || num > 512 * 1024)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"cdrskin: SORRY : Option stdio_sync= accepts only sizes -1, 0, 32k ... 1g\n");
|
||||||
|
} else
|
||||||
|
skin->stdio_sync= num;
|
||||||
|
|
||||||
} else if(strncmp(argv[i],"-stream_recording=",18)==0) {
|
} else if(strncmp(argv[i],"-stream_recording=",18)==0) {
|
||||||
value_pt= argv[i]+18;
|
value_pt= argv[i]+18;
|
||||||
goto set_stream_recording;
|
goto set_stream_recording;
|
||||||
@ -8282,6 +8625,8 @@ track_too_large:;
|
|||||||
if(skin->smallest_tsize<0 || skin->smallest_tsize>skin->fixed_size)
|
if(skin->smallest_tsize<0 || skin->smallest_tsize>skin->fixed_size)
|
||||||
skin->smallest_tsize= skin->fixed_size;
|
skin->smallest_tsize= skin->fixed_size;
|
||||||
|
|
||||||
|
} else if(strcmp(argv[i],"-V")==0 || strcmp(argv[i],"-Verbose")==0) {
|
||||||
|
/* is handled in Cdrpreskin_setup() */;
|
||||||
} else if(strcmp(argv[i],"-v")==0 || strcmp(argv[i],"-verbose")==0) {
|
} else if(strcmp(argv[i],"-v")==0 || strcmp(argv[i],"-verbose")==0) {
|
||||||
/* is handled in Cdrpreskin_setup() */;
|
/* is handled in Cdrpreskin_setup() */;
|
||||||
} else if(strcmp(argv[i],"-vv")==0 || strcmp(argv[i],"-vvv")==0 ||
|
} else if(strcmp(argv[i],"-vv")==0 || strcmp(argv[i],"-vvv")==0 ||
|
||||||
@ -8472,13 +8817,13 @@ ignore_unknown:;
|
|||||||
if(skin->track_counter>0) {
|
if(skin->track_counter>0) {
|
||||||
skin->do_burn= 1;
|
skin->do_burn= 1;
|
||||||
|
|
||||||
#ifndef Cdrskin_extra_leaN
|
#ifndef Cdrskin_no_cdrfifO
|
||||||
if(!skin->do_direct_write) {
|
if(!skin->do_direct_write) {
|
||||||
ret= Cdrskin_attach_fifo(skin,0);
|
ret= Cdrskin_attach_fifo(skin,0);
|
||||||
if(ret<=0)
|
if(ret<=0)
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
#endif /* ! Cdrskin_extra_leaN */
|
#endif /* ! Cdrskin_no_cdrfifO */
|
||||||
|
|
||||||
}
|
}
|
||||||
return(1);
|
return(1);
|
||||||
|
@ -50,7 +50,8 @@ via SCSI, PATA (aka IDE, ATA), USB, or SATA.
|
|||||||
<DD>With kernel 2.4 an ATA drive has to be under ide-scsi emulation.</DD>
|
<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 the drive should not be under ide-scsi.</DD>
|
||||||
<DT>or FreeBSD (with libc, of course) :</DT>
|
<DT>or FreeBSD (with libc, of course) :</DT>
|
||||||
<DD>ATAPI/CAM support has to be enabled in the kernel, see atapicam(4).</DD>
|
<DD>ATA and SATA drives need atapicam running.</DD>
|
||||||
|
<DD>libcam has to be installed.</DD>
|
||||||
<DT>libpthread</DT>
|
<DT>libpthread</DT>
|
||||||
<DD>is supposed to be a standard system component.</DD>
|
<DD>is supposed to be a standard system component.</DD>
|
||||||
</DL>
|
</DL>
|
||||||
@ -61,7 +62,7 @@ via SCSI, PATA (aka IDE, ATA), USB, or SATA.
|
|||||||
GPL software included:<BR>
|
GPL software included:<BR>
|
||||||
</H2>
|
</H2>
|
||||||
<DL>
|
<DL>
|
||||||
<DT>libburn-0.7.0</DT>
|
<DT>libburn-0.7.6</DT>
|
||||||
<DD>(founded by Derek Foreman and Ben Jansens,
|
<DD>(founded by Derek Foreman and Ben Jansens,
|
||||||
developed and maintained since August 2006 by
|
developed and maintained since August 2006 by
|
||||||
Thomas Schmitt from team of libburnia-project.org)
|
Thomas Schmitt from team of libburnia-project.org)
|
||||||
@ -111,7 +112,7 @@ as listed by option --devices.</DT>
|
|||||||
<DT>Get info about a particular drive or loaded media:</DT>
|
<DT>Get info about a particular drive or loaded media:</DT>
|
||||||
<DD>$<KBD> cdrskin dev=0,1,0 -checkdrive</KBD></DD>
|
<DD>$<KBD> cdrskin dev=0,1,0 -checkdrive</KBD></DD>
|
||||||
<DD>$<KBD> cdrskin dev=ATA:1,0,0 -v -atip</KBD></DD>
|
<DD>$<KBD> cdrskin dev=ATA:1,0,0 -v -atip</KBD></DD>
|
||||||
<DD>$<KBD> cdrskin dev=/dev/hdc -toc</KBD></DD>
|
<DD>$<KBD> cdrskin dev=/dev/hdc -minfo</KBD></DD>
|
||||||
|
|
||||||
<DT>Prepare CD-RW or DVD-RW for re-use, DVD-RAM or BD-RE for first use:</DT>
|
<DT>Prepare CD-RW or DVD-RW for re-use, DVD-RAM or BD-RE for first use:</DT>
|
||||||
<DD>$<KBD> cdrskin -v dev=/dev/sg1 blank=as_needed -eject</KBD></DD>
|
<DD>$<KBD> cdrskin -v dev=/dev/sg1 blank=as_needed -eject</KBD></DD>
|
||||||
@ -193,8 +194,8 @@ Standalone ISO 9660 multi-session CD/DVD/BD tool
|
|||||||
<P>
|
<P>
|
||||||
<DL>
|
<DL>
|
||||||
<DT>Download as source code (see README):</DT>
|
<DT>Download as source code (see README):</DT>
|
||||||
<DD><A HREF="cdrskin-0.7.0.pl00.tar.gz">cdrskin-0.7.0.pl00.tar.gz</A>
|
<DD><A HREF="cdrskin-0.7.6.pl00.tar.gz">cdrskin-0.7.6.pl00.tar.gz</A>
|
||||||
(750 KB).
|
(810 KB).
|
||||||
</DD>
|
</DD>
|
||||||
<DD>
|
<DD>
|
||||||
The cdrskin tarballs are source code identical with libburn releases
|
The cdrskin tarballs are source code identical with libburn releases
|
||||||
@ -243,16 +244,19 @@ cdrskin_0.4.2.pl00-x86-suse9_0-static.tar.gz</A>, (310 KB), -static compiled,
|
|||||||
<HR>
|
<HR>
|
||||||
|
|
||||||
<P>
|
<P>
|
||||||
Enhancements towards previous stable version cdrskin-0.6.8.pl00:
|
Enhancements towards previous stable version cdrskin-0.7.4.pl00:
|
||||||
<UL>
|
<UL>
|
||||||
<LI>Adapted to pitfalls of U3 memory sticks which appear as CD-ROM drives</LI>
|
<LI>
|
||||||
<LI>Listing all supported profiles with option -atip -v</LI>
|
Made FreeBSD system adapter safe from mutal burn spoiling and drive deadlock
|
||||||
|
</LI>
|
||||||
|
<LI>Experimental system adapter via GNU libcdio on X/Open systems</LI>
|
||||||
|
<LI>Experimentally using FreeBSD system adapter for Debian kfreebsd</LI>
|
||||||
<!--
|
<!--
|
||||||
<LI>none</LI>
|
<LI>none</LI>
|
||||||
-->
|
-->
|
||||||
</UL>
|
</UL>
|
||||||
|
|
||||||
Bug fixes towards cdrskin-0.6.8.pl00:
|
Bug fixes towards cdrskin-0.7.4.pl00:
|
||||||
<UL>
|
<UL>
|
||||||
<LI>none</LI>
|
<LI>none</LI>
|
||||||
<!--
|
<!--
|
||||||
@ -263,22 +267,17 @@ Bug fixes towards cdrskin-0.6.8.pl00:
|
|||||||
|
|
||||||
<P>
|
<P>
|
||||||
<DL>
|
<DL>
|
||||||
<DT><H3>Development snapshot, version 0.7.1 :</H3></DT>
|
<DT><H3>Development snapshot, version 0.7.7 :</H3></DT>
|
||||||
<DD>Enhancements towards current stable version 0.7.0.pl00:
|
<DD>Enhancements towards current stable version 0.7.6.pl00:
|
||||||
<UL>
|
<UL>
|
||||||
<LI>New option --long_toc, now printing media summary at end of TOC</LI>
|
|
||||||
<LI>New -atip report lines "Product Id:" and "Producer:"</LI>
|
|
||||||
<LI>Emulation of some -minfo output</LI>
|
|
||||||
<LI>Better interpretation of options -mode2, -xa, -xa1, -xa2</LI>
|
|
||||||
<LI>New option --xa1-ignore</LI>
|
|
||||||
<!--
|
|
||||||
<LI>none yet</LI>
|
<LI>none yet</LI>
|
||||||
|
<!--
|
||||||
-->
|
-->
|
||||||
|
|
||||||
</UL>
|
</UL>
|
||||||
</DD>
|
</DD>
|
||||||
|
|
||||||
<DD>Bug fixes towards cdrskin-0.7.0.pl00:
|
<DD>Bug fixes towards cdrskin-0.7.6.pl00:
|
||||||
<UL>
|
<UL>
|
||||||
<LI>none yet</LI>
|
<LI>none yet</LI>
|
||||||
<!--
|
<!--
|
||||||
@ -287,10 +286,10 @@ Bug fixes towards cdrskin-0.6.8.pl00:
|
|||||||
</DD>
|
</DD>
|
||||||
|
|
||||||
<DD> </DD>
|
<DD> </DD>
|
||||||
<DD><A HREF="README_cdrskin_devel">README 0.7.1</A>
|
<DD><A HREF="README_cdrskin_devel">README 0.7.7</A>
|
||||||
<DD><A HREF="cdrskin__help_devel">cdrskin_0.7.1 --help</A></DD>
|
<DD><A HREF="cdrskin__help_devel">cdrskin_0.7.7 --help</A></DD>
|
||||||
<DD><A HREF="cdrskin_help_devel">cdrskin_0.7.1 -help</A></DD>
|
<DD><A HREF="cdrskin_help_devel">cdrskin_0.7.7 -help</A></DD>
|
||||||
<DD><A HREF="man_1_cdrskin_devel.html">man cdrskin (as of 0.7.1)</A></DD>
|
<DD><A HREF="man_1_cdrskin_devel.html">man cdrskin (as of 0.7.7)</A></DD>
|
||||||
<DD> </DD>
|
<DD> </DD>
|
||||||
<DT>Maintainers of cdrskin unstable packages please use SVN of
|
<DT>Maintainers of cdrskin unstable packages please use SVN of
|
||||||
<A HREF="http://libburnia-project.org"> libburnia-project.org</A></DT>
|
<A HREF="http://libburnia-project.org"> libburnia-project.org</A></DT>
|
||||||
@ -310,8 +309,8 @@ admins with full system souvereignty.</DT>
|
|||||||
<A HREF="README_cdrskin_devel">upcoming README</A> ):
|
<A HREF="README_cdrskin_devel">upcoming README</A> ):
|
||||||
</DD>
|
</DD>
|
||||||
<DD>
|
<DD>
|
||||||
<A HREF="cdrskin-0.7.1.tar.gz">cdrskin-0.7.1.tar.gz</A>
|
<A HREF="cdrskin-0.7.7.tar.gz">cdrskin-0.7.7.tar.gz</A>
|
||||||
(780 KB).
|
(810 KB).
|
||||||
</DD>
|
</DD>
|
||||||
|
|
||||||
<!-- This is not offered any more since spring 2008
|
<!-- This is not offered any more since spring 2008
|
||||||
|
@ -1 +1 @@
|
|||||||
#define Cdrskin_timestamP "2009.10.09.200730"
|
#define Cdrskin_timestamP "2010.01.22.130001"
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,19 +1,26 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
# compile_cdrskin.sh
|
# compile_cdrskin.sh
|
||||||
# Copyright 2005 - 2009 Thomas Schmitt, scdbackup@gmx.net, GPL version 2
|
# Copyright 2005 - 2010 Thomas Schmitt, scdbackup@gmx.net, GPL
|
||||||
# to be executed within ./libburn-* resp ./cdrskin-*
|
# to be executed within ./libburn-* resp ./cdrskin-*
|
||||||
|
|
||||||
debug_opts="-O2"
|
debug_opts="-O2"
|
||||||
def_opts=
|
def_opts=
|
||||||
largefile_opts="-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1"
|
largefile_opts="-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1"
|
||||||
libvers="-DCdrskin_libburn_0_7_1"
|
fifo_opts="-DCdrskin_use_libburn_fifO"
|
||||||
cleanup_src_or_obj="libburn/cleanup.o"
|
libvers="-DCdrskin_libburn_0_7_6"
|
||||||
libdax_msgs_o="libburn/libdax_msgs.o"
|
|
||||||
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
|
# To be used if Makefile.am uses libburn_libburn_la_CFLAGS
|
||||||
|
# burn="libburn/libburn_libburn_la-"
|
||||||
|
burn="libburn/"
|
||||||
|
|
||||||
|
cleanup_src_or_obj="$burn"cleanup.o
|
||||||
|
libdax_msgs_o="$burn"libdax_msgs.o
|
||||||
|
libdax_audioxtr_o="$burn"libdax_audioxtr.o
|
||||||
do_strip=0
|
do_strip=0
|
||||||
static_opts=
|
static_opts=
|
||||||
warn_opts="-Wall"
|
warn_opts="-Wall"
|
||||||
|
libcdio=
|
||||||
fifo_source="cdrskin/cdrfifo.c"
|
fifo_source="cdrskin/cdrfifo.c"
|
||||||
compile_cdrskin=1
|
compile_cdrskin=1
|
||||||
compile_cdrfifo=0
|
compile_cdrfifo=0
|
||||||
@ -31,20 +38,20 @@ do
|
|||||||
then
|
then
|
||||||
libvers="-DCdrskin_libburn_cvs_A60220_tS"
|
libvers="-DCdrskin_libburn_cvs_A60220_tS"
|
||||||
libdax_audioxtr_o=
|
libdax_audioxtr_o=
|
||||||
libdax_msgs_o="libburn/message.o"
|
libdax_msgs_o="$burn"message.o
|
||||||
cleanup_src_or_obj="-DCleanup_has_no_libburn_os_H cdrskin/cleanup.c"
|
cleanup_src_or_obj="-DCleanup_has_no_libburn_os_H cdrskin/cleanup.c"
|
||||||
elif test "$i" = "-libburn_0_7_0"
|
elif test "$i" = "-libburn_0_7_6"
|
||||||
then
|
then
|
||||||
libvers="-DCdrskin_libburn_0_7_0"
|
libvers="-DCdrskin_libburn_0_7_6"
|
||||||
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
|
libdax_audioxtr_o="$burn"libdax_audioxtr.o
|
||||||
libdax_msgs_o="libburn/libdax_msgs.o"
|
libdax_msgs_o="$burn"libdax_msgs.o
|
||||||
cleanup_src_or_obj="libburn/cleanup.o"
|
cleanup_src_or_obj="$burn"cleanup.o
|
||||||
elif test "$i" = "-libburn_svn"
|
elif test "$i" = "-libburn_svn"
|
||||||
then
|
then
|
||||||
libvers="-DCdrskin_libburn_0_7_1"
|
libvers="-DCdrskin_libburn_0_7_7"
|
||||||
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
|
libdax_audioxtr_o="$burn"libdax_audioxtr.o
|
||||||
libdax_msgs_o="libburn/libdax_msgs.o"
|
libdax_msgs_o="$burn"libdax_msgs.o
|
||||||
cleanup_src_or_obj="libburn/cleanup.o"
|
cleanup_src_or_obj="$burn"cleanup.o
|
||||||
elif test "$i" = "-newapi" -o "$i" = "-experimental"
|
elif test "$i" = "-newapi" -o "$i" = "-experimental"
|
||||||
then
|
then
|
||||||
def_opts="$def_opts -DCdrskin_new_api_tesT"
|
def_opts="$def_opts -DCdrskin_new_api_tesT"
|
||||||
@ -55,6 +62,9 @@ do
|
|||||||
elif test "$i" = "-no_largefile"
|
elif test "$i" = "-no_largefile"
|
||||||
then
|
then
|
||||||
largefile_opts=
|
largefile_opts=
|
||||||
|
elif test "$i" = "-dvd_obs_64k"
|
||||||
|
then
|
||||||
|
def_opts="$def_opts -DCdrskin_dvd_obs_default_64K"
|
||||||
elif test "$i" = "-do_not_compile_cdrskin"
|
elif test "$i" = "-do_not_compile_cdrskin"
|
||||||
then
|
then
|
||||||
compile_cdrskin=0
|
compile_cdrskin=0
|
||||||
@ -66,6 +76,19 @@ do
|
|||||||
elif test "$i" = "-do_strip"
|
elif test "$i" = "-do_strip"
|
||||||
then
|
then
|
||||||
do_strip=1
|
do_strip=1
|
||||||
|
elif test "$i" = "-use_libburn_fifo"
|
||||||
|
then
|
||||||
|
fifo_opts="-DCdrskin_use_libburn_fifO"
|
||||||
|
elif test "$i" = "-use_no_libburn_fifo"
|
||||||
|
then
|
||||||
|
fifo_opts=""
|
||||||
|
elif test "$i" = "-use_no_cdrfifo"
|
||||||
|
then
|
||||||
|
fifo_source=
|
||||||
|
fifo_opts="-DCdrskin_use_libburn_fifO -DCdrskin_no_cdrfifO"
|
||||||
|
elif test "$i" = "-use_libcdio"
|
||||||
|
then
|
||||||
|
libcdio="-lcdio"
|
||||||
elif test "$i" = "-g"
|
elif test "$i" = "-g"
|
||||||
then
|
then
|
||||||
debug_opts="-g"
|
debug_opts="-g"
|
||||||
@ -75,9 +98,13 @@ do
|
|||||||
echo "Options:"
|
echo "Options:"
|
||||||
echo " -compile_cdrfifo compile program cdrskin/cdrfifo."
|
echo " -compile_cdrfifo compile program cdrskin/cdrfifo."
|
||||||
echo " -compile_dewav compile program test/dewav without libburn."
|
echo " -compile_dewav compile program test/dewav without libburn."
|
||||||
echo " -libburn_0_7_0 set macro to match libburn-0.7.0"
|
echo " -libburn_0_7_6 set macro to match libburn-0.7.6"
|
||||||
echo " -libburn_svn set macro to match current libburn-SVN."
|
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."
|
||||||
echo " -do_not_compile_cdrskin omit compilation of cdrskin/cdrskin."
|
echo " -do_not_compile_cdrskin omit compilation of cdrskin/cdrskin."
|
||||||
|
echo " -use_no_libburn_fifo use cdrfifo even for single track non-CD"
|
||||||
|
echo " -use_no_cdrfifo always use fifo of libburn and never cdrfifo"
|
||||||
echo " -experimental use newly introduced libburn features."
|
echo " -experimental use newly introduced libburn features."
|
||||||
echo " -oldfashioned use pre-0.2.2 libburn features only."
|
echo " -oldfashioned use pre-0.2.2 libburn features only."
|
||||||
echo " -do_diet produce capability reduced lean version."
|
echo " -do_diet produce capability reduced lean version."
|
||||||
@ -98,13 +125,14 @@ echo "Build timestamp : $timestamp"
|
|||||||
|
|
||||||
if test "$compile_cdrskin"
|
if test "$compile_cdrskin"
|
||||||
then
|
then
|
||||||
echo "compiling program cdrskin/cdrskin.c $static_opts $debug_opts $libvers $def_opts $cleanup_src_or_obj"
|
echo "compiling program cdrskin/cdrskin.c $fifo_source $static_opts $debug_opts $libvers $fifo_opts $def_opts $cleanup_src_or_obj $libcdio"
|
||||||
cc -I. \
|
cc -I. \
|
||||||
$warn_opts \
|
$warn_opts \
|
||||||
$static_opts \
|
$static_opts \
|
||||||
$debug_opts \
|
$debug_opts \
|
||||||
$libvers \
|
$libvers \
|
||||||
$largefile_opts \
|
$largefile_opts \
|
||||||
|
$fifo_opts \
|
||||||
$def_opts \
|
$def_opts \
|
||||||
\
|
\
|
||||||
-DCdrskin_build_timestamP='"'"$timestamp"'"' \
|
-DCdrskin_build_timestamP='"'"$timestamp"'"' \
|
||||||
@ -116,31 +144,33 @@ then
|
|||||||
\
|
\
|
||||||
$cleanup_src_or_obj \
|
$cleanup_src_or_obj \
|
||||||
\
|
\
|
||||||
libburn/async.o \
|
"$burn"async.o \
|
||||||
libburn/debug.o \
|
"$burn"debug.o \
|
||||||
libburn/drive.o \
|
"$burn"drive.o \
|
||||||
libburn/file.o \
|
"$burn"file.o \
|
||||||
libburn/init.o \
|
"$burn"init.o \
|
||||||
libburn/options.o \
|
"$burn"options.o \
|
||||||
libburn/source.o \
|
"$burn"source.o \
|
||||||
libburn/structure.o \
|
"$burn"structure.o \
|
||||||
\
|
\
|
||||||
libburn/sg.o \
|
"$burn"sg.o \
|
||||||
libburn/write.o \
|
"$burn"write.o \
|
||||||
libburn/read.o \
|
"$burn"read.o \
|
||||||
$libdax_audioxtr_o \
|
$libdax_audioxtr_o \
|
||||||
$libdax_msgs_o \
|
$libdax_msgs_o \
|
||||||
\
|
\
|
||||||
libburn/mmc.o \
|
"$burn"mmc.o \
|
||||||
libburn/sbc.o \
|
"$burn"sbc.o \
|
||||||
libburn/spc.o \
|
"$burn"spc.o \
|
||||||
libburn/util.o \
|
"$burn"util.o \
|
||||||
\
|
\
|
||||||
libburn/sector.o \
|
"$burn"sector.o \
|
||||||
libburn/toc.o \
|
"$burn"toc.o \
|
||||||
\
|
\
|
||||||
libburn/crc.o \
|
"$burn"crc.o \
|
||||||
|
"$burn"ecma130ab.o \
|
||||||
\
|
\
|
||||||
|
$libcdio \
|
||||||
-lpthread
|
-lpthread
|
||||||
|
|
||||||
ret=$?
|
ret=$?
|
||||||
@ -182,8 +212,8 @@ then
|
|||||||
-DDewav_without_libburN \
|
-DDewav_without_libburN \
|
||||||
-o test/dewav \
|
-o test/dewav \
|
||||||
test/dewav.c \
|
test/dewav.c \
|
||||||
libburn/libdax_audioxtr.o \
|
"$burn"libdax_audioxtr.o \
|
||||||
libburn/libdax_msgs.o \
|
"$burn"libdax_msgs.o \
|
||||||
\
|
\
|
||||||
-lpthread
|
-lpthread
|
||||||
|
|
||||||
|
79
configure.ac
79
configure.ac
@ -1,4 +1,4 @@
|
|||||||
AC_INIT([libburn], [0.7.1], [http://libburnia-project.org])
|
AC_INIT([libburn], [0.7.6], [http://libburnia-project.org])
|
||||||
AC_PREREQ([2.50])
|
AC_PREREQ([2.50])
|
||||||
dnl AC_CONFIG_HEADER([config.h])
|
dnl AC_CONFIG_HEADER([config.h])
|
||||||
|
|
||||||
@ -7,7 +7,7 @@ AC_CANONICAL_TARGET
|
|||||||
|
|
||||||
AM_INIT_AUTOMAKE([subdir-objects])
|
AM_INIT_AUTOMAKE([subdir-objects])
|
||||||
|
|
||||||
dnl Notes by ts A71207 - A90827 :
|
dnl Notes by ts A71207 - B00122 :
|
||||||
dnl
|
dnl
|
||||||
dnl Regrettably the meaning of the various version types was misunderstood
|
dnl Regrettably the meaning of the various version types was misunderstood
|
||||||
dnl before version 0.4.1.
|
dnl before version 0.4.1.
|
||||||
@ -74,6 +74,9 @@ dnl 0.6.4 = libburn.so.4.29.0
|
|||||||
dnl 0.6.6 = libburn.so.4.31.0
|
dnl 0.6.6 = libburn.so.4.31.0
|
||||||
dnl 0.6.8 = libburn.so.4.33.0
|
dnl 0.6.8 = libburn.so.4.33.0
|
||||||
dnl 0.7.0 = libburn.so.4.35.0
|
dnl 0.7.0 = libburn.so.4.35.0
|
||||||
|
dnl 0.7.2 = libburn.so.4.37.0
|
||||||
|
dnl 0.7.4 = libburn.so.4.39.0
|
||||||
|
dnl 0.7.6 = libburn.so.4.41.0
|
||||||
dnl
|
dnl
|
||||||
dnl So LT_CURRENT, LT_REVISION and LT_AGE get set directly here.
|
dnl So LT_CURRENT, LT_REVISION and LT_AGE get set directly here.
|
||||||
dnl SONAME of the emerging library is LT_CURRENT - LT_AGE.
|
dnl SONAME of the emerging library is LT_CURRENT - LT_AGE.
|
||||||
@ -99,7 +102,7 @@ dnl
|
|||||||
dnl As said: Only copies. Original in libburn/libburn.h : burn_header_version_*
|
dnl As said: Only copies. Original in libburn/libburn.h : burn_header_version_*
|
||||||
BURN_MAJOR_VERSION=0
|
BURN_MAJOR_VERSION=0
|
||||||
BURN_MINOR_VERSION=7
|
BURN_MINOR_VERSION=7
|
||||||
BURN_MICRO_VERSION=1
|
BURN_MICRO_VERSION=6
|
||||||
BURN_VERSION=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION.$BURN_MICRO_VERSION
|
BURN_VERSION=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION.$BURN_MICRO_VERSION
|
||||||
|
|
||||||
AC_SUBST(BURN_MAJOR_VERSION)
|
AC_SUBST(BURN_MAJOR_VERSION)
|
||||||
@ -110,15 +113,15 @@ AC_SUBST(BURN_VERSION)
|
|||||||
dnl Libtool versioning
|
dnl Libtool versioning
|
||||||
LT_RELEASE=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION.$BURN_MICRO_VERSION
|
LT_RELEASE=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION.$BURN_MICRO_VERSION
|
||||||
dnl
|
dnl
|
||||||
dnl ts A90827
|
dnl ts B00122
|
||||||
dnl ### This is the release version libburn-0.7.0 = libburn.so.4.35.0
|
dnl This is the release version libburn-0.7.6 = libburn.so.4.41.0
|
||||||
dnl This is the development version after above release version
|
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 not yet happened.
|
||||||
dnl ### LT_CURRENT++, LT_AGE++ has happened meanwhile.
|
dnl ### LT_CURRENT++, LT_AGE++ has happened meanwhile.
|
||||||
dnl
|
dnl
|
||||||
dnl SONAME = 39 - 35 = 4 . Linux library name = libburn.so.4.35.0
|
dnl SONAME = 45 - 41 = 4 . Linux library name = libburn.so.4.41.0
|
||||||
LT_CURRENT=39
|
LT_CURRENT=45
|
||||||
LT_AGE=35
|
LT_AGE=41
|
||||||
LT_REVISION=0
|
LT_REVISION=0
|
||||||
LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE`
|
LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE`
|
||||||
|
|
||||||
@ -178,6 +181,63 @@ dnl If this would be done more specifically in Makefile.am
|
|||||||
dnl via libburn_libburn_la_CFLAGS then undesired .o file names would emerge
|
dnl via libburn_libburn_la_CFLAGS then undesired .o file names would emerge
|
||||||
CFLAGS="$CFLAGS $STATVFS_DEF"
|
CFLAGS="$CFLAGS $STATVFS_DEF"
|
||||||
|
|
||||||
|
dnl ts A91122
|
||||||
|
AC_ARG_ENABLE(track-src-odirect,
|
||||||
|
[ --enable-track-src-odirect Enable use of O_DIRECT with track input, default=no],
|
||||||
|
, enable_track_src_odirect=no)
|
||||||
|
if test x$enable_track_src_odirect = xyes; then
|
||||||
|
LIBBURN_O_DIRECT_DEF="-DLibburn_read_o_direcT"
|
||||||
|
echo "enabled use of O_DIRECT with track input"
|
||||||
|
else
|
||||||
|
LIBBURN_O_DIRECT_DEF=
|
||||||
|
echo "disabled use of O_DIRECT with track input"
|
||||||
|
fi
|
||||||
|
dnl Avoid the need for libburn_libburn_la_CFLAGS in Makefile.am (ugly .o names)
|
||||||
|
dnl ### AC_SUBST(LIBBURN_O_DIRECT_DEF)
|
||||||
|
CFLAGS="$CFLAGS $LIBBURN_O_DIRECT_DEF"
|
||||||
|
|
||||||
|
dnl ts A91116
|
||||||
|
AC_ARG_ENABLE(dvd-obs-64k,
|
||||||
|
[ --enable-dvd-obs-64k 64 KB default size for DVD/BD writing, default=no],
|
||||||
|
, enable_fifo_odirect=no)
|
||||||
|
if test x$enable_dvd_obs_64k = xyes; then
|
||||||
|
LIBBURN_DVD_OBS_64K="-DLibburn_dvd_obs_default_64K"
|
||||||
|
echo "enabled write size default 64 KB on DVD and BD"
|
||||||
|
else
|
||||||
|
LIBBURN_DVD_OBS_64K=
|
||||||
|
echo "disabled write size default 64 KB on DVD and BD"
|
||||||
|
fi
|
||||||
|
CFLAGS="$CFLAGS $LIBBURN_DVD_OBS_64K"
|
||||||
|
|
||||||
|
dnl ts A91218
|
||||||
|
AC_ARG_ENABLE(libcdio,
|
||||||
|
[ --enable-libcdio Enable EXPERIMENTAL use of libcdio as system adapter, default=no],
|
||||||
|
, enable_libcdio=no)
|
||||||
|
if test x$enable_libcdio = xyes; then
|
||||||
|
dnl Check whether there is libcdio-devel and libcdio-runtime.
|
||||||
|
dnl If not, erase this macro
|
||||||
|
LIBCDIO_DEF="-DLibburn_use_libcdiO"
|
||||||
|
dnl The empty yes case obviously causes -lcdio to be linked
|
||||||
|
AC_CHECK_HEADER(cdio/cdio.h, AC_CHECK_LIB(cdio, mmc_last_cmd_sense, , LIBCDIO_DEF= ), LIBCDIO_DEF= )
|
||||||
|
else
|
||||||
|
LIBCDIO_DEF=
|
||||||
|
fi
|
||||||
|
if test x$LIBCDIO_DEF = x
|
||||||
|
then
|
||||||
|
if test x$enable_libcdio = xyes
|
||||||
|
then
|
||||||
|
echo "WARNING: could not enable use of libcdio as system adapter"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "enabled EXPERIMENTAL use of libcdio as system adapter"
|
||||||
|
CFLAGS="$CFLAGS $LIBCDIO_DEF"
|
||||||
|
|
||||||
|
LIBCDIO_REQUIRED=0.83
|
||||||
|
PKG_CHECK_MODULES(LIBCDIO, libcdio >= $LIBCDIO_REQUIRED)
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
dnl Add compiler-specific flags
|
dnl Add compiler-specific flags
|
||||||
|
|
||||||
dnl See if the user wants aggressive optimizations of the code
|
dnl See if the user wants aggressive optimizations of the code
|
||||||
@ -197,7 +257,6 @@ else
|
|||||||
CFLAGS="$CFLAGS -DDEBUG"
|
CFLAGS="$CFLAGS -DDEBUG"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
dnl Determine target directory for libburn-*.pc
|
dnl Determine target directory for libburn-*.pc
|
||||||
dnl Important: Must be performed _after_ TARGET_SHIZZLE
|
dnl Important: Must be performed _after_ TARGET_SHIZZLE
|
||||||
dnl
|
dnl
|
||||||
|
@ -73,9 +73,9 @@ compatible for a good while.
|
|||||||
@subsection libburner-help Libburner --help
|
@subsection libburner-help Libburner --help
|
||||||
<pre>
|
<pre>
|
||||||
Usage: test/libburner
|
Usage: test/libburner
|
||||||
[--drive <address>|<driveno>|"-"] [--audio]
|
[--drive address|driveno|"-"] [--audio]
|
||||||
[--blank_fast|--blank_full|--format] [--try_to_simulate]
|
[--blank_fast|--blank_full|--format] [--try_to_simulate]
|
||||||
[--multi] [<one or more imagefiles>|"-"]
|
[--multi] [one or more imagefiles|"-"]
|
||||||
Examples
|
Examples
|
||||||
A bus scan (needs rw-permissions to see a drive):
|
A bus scan (needs rw-permissions to see a drive):
|
||||||
test/libburner --drive -
|
test/libburner --drive -
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
libburnia-project.org Optical Media Rotisserie Recipes as of January 2009
|
libburnia-project.org Optical Media Rotisserie Recipes as of January 2010
|
||||||
|
|
||||||
Content:
|
Content:
|
||||||
- TAO Multi-Session CD Cookbook (CD-R, CD-RW)
|
- TAO Multi-Session CD Cookbook (CD-R, CD-RW)
|
||||||
@ -86,7 +86,7 @@ parameters:
|
|||||||
BUFE Buffer Underrun protection 0=off, 1=on
|
BUFE Buffer Underrun protection 0=off, 1=on
|
||||||
Test Write -dummy mode for writing 0=off, 1=on
|
Test Write -dummy mode for writing 0=off, 1=on
|
||||||
Write Type Packet/TAO/SAO/RAW 01h = TAO
|
Write Type Packet/TAO/SAO/RAW 01h = TAO
|
||||||
Multi-session Wether to keep appendable 00b = finalize
|
Multi-session Whether to keep appendable 00b = finalize
|
||||||
11b = keep appendable
|
11b = keep appendable
|
||||||
Track Mode Describes frame type 4 for data , 0 for audio
|
Track Mode Describes frame type 4 for data , 0 for audio
|
||||||
Data Block Type Layout of payload blocks 8 for 2048 byte data blocks
|
Data Block Type Layout of payload blocks 8 for 2048 byte data blocks
|
||||||
@ -119,19 +119,22 @@ A track must at least contain 300 payload blocks: 4 seconds of audio or
|
|||||||
600 KiB of data.
|
600 KiB of data.
|
||||||
(mmc5r03c.pdf 6.3.3.1.2)
|
(mmc5r03c.pdf 6.3.3.1.2)
|
||||||
|
|
||||||
The track has to be closed by 5Bh CLOSE TRACK SESSION Close Function 001b.
|
Up to december 2009 the track was closed by 5Bh CLOSE TRACK SESSION Close
|
||||||
Older MMC specifies a valid Logical Track Number FFh to depict the open track.
|
Function 001b. Older MMC specifies a valid Logical Track Number FFh to depict
|
||||||
MMC-5 is quite silent about this. FFh works for my drives.
|
the open track. MMC-5 is quite silent about this. FFh worked for my drives.
|
||||||
(mmc5r03c.pdf 6.3.3.1.2)
|
(mmc5r03c.pdf 6.3.3.1.2)
|
||||||
|
This is omitted since libburn-0.7.4, relying entirely on 35h SYNCHRONIZE CACHE.
|
||||||
|
First appeared a drive where CLOSE TRACK fails in simulation mode, later
|
||||||
|
another one produced error replies even with real burning.
|
||||||
|
|
||||||
After that, a new track may be written beginning with sending the mode page 05h
|
After that, a new track may be written beginning with sending the mode page 05h
|
||||||
again. It is not tested wether 05h can be omitted if Track Mode and Data Block
|
again. It is not tested whether 05h can be omitted if Track Mode and Data Block
|
||||||
Type are the same as with the previous track.
|
Type are the same as with the previous track.
|
||||||
The new track will be added to the session which was opened by the first track.
|
The new track will be added to the session which was opened by the first track.
|
||||||
|
|
||||||
After the last track of a session, 5Bh CLOSE TRACK SESSION Close Function 010b
|
After the last track of a session, 5Bh CLOSE TRACK SESSION Close Function 010b
|
||||||
with Logical Track Number 0 closes the session. It depends on the Multi-Session
|
with Logical Track Number 0 closes the session. It depends on the Multi-Session
|
||||||
value in mode page 05h wether the disc is finalized or stays appendable.
|
value in mode page 05h whether the disc is finalized or stays appendable.
|
||||||
(mmc5r03c.pdf 6.3.3.1.3)
|
(mmc5r03c.pdf 6.3.3.1.3)
|
||||||
|
|
||||||
|
|
||||||
@ -202,7 +205,7 @@ for finalized disc.
|
|||||||
In libburn the address of the first track in the last session is obtained from
|
In libburn the address of the first track in the last session is obtained from
|
||||||
the last session's POINT = A0h and from the track descriptor with the POINT
|
the last session's POINT = A0h and from the track descriptor with the POINT
|
||||||
value matching the PMIN value of the A0h descriptor.
|
value matching the PMIN value of the A0h descriptor.
|
||||||
Untested is wether POINT = B0h and 52h READ TRACK INFORMATION are always in
|
Untested is whether POINT = B0h and 52h READ TRACK INFORMATION are always in
|
||||||
sync. libburn uses the info provided by 52h READ TRACK INFORMATION.
|
sync. libburn uses the info provided by 52h READ TRACK INFORMATION.
|
||||||
|
|
||||||
|
|
||||||
@ -308,7 +311,7 @@ A Write Parameters mode page 05h has to be composed and transmitted via
|
|||||||
BUFE Buffer Underrun protection 0=off, 1=on
|
BUFE Buffer Underrun protection 0=off, 1=on
|
||||||
Test Write -dummy mode for writing 0=off, 1=on
|
Test Write -dummy mode for writing 0=off, 1=on
|
||||||
Write Type Packet/TAO/SAO/RAW 02h = SAO
|
Write Type Packet/TAO/SAO/RAW 02h = SAO
|
||||||
Multi-session Wether to keep appendable 00b = finalize
|
Multi-session Whether to keep appendable 00b = finalize
|
||||||
11b = keep appendable
|
11b = keep appendable
|
||||||
Track Mode Describes frame type 0 (is ignored)
|
Track Mode Describes frame type 0 (is ignored)
|
||||||
Data Block Type Layout of payload blocks 0 (is ignored)
|
Data Block Type Layout of payload blocks 0 (is ignored)
|
||||||
@ -349,7 +352,7 @@ There is no separator between the tracks of a pure mode SAO session.
|
|||||||
(If the session was mixed mode, there would be extended Pre-gaps and Post-gaps
|
(If the session was mixed mode, there would be extended Pre-gaps and Post-gaps
|
||||||
between data mode tracks and audio mode tracks.)
|
between data mode tracks and audio mode tracks.)
|
||||||
(libburn sends its own buffer to the drive at the end of each track but does
|
(libburn sends its own buffer to the drive at the end of each track but does
|
||||||
not sync the drive's chache. It is unclear wether this separation of tracks
|
not sync the drive's chache. It is unclear whether this separation of tracks
|
||||||
on the level of 2Ah WRITE is necessary with a pure mode session. It does not
|
on the level of 2Ah WRITE is necessary with a pure mode session. It does not
|
||||||
harm in any case and would probably be unavoidable if audio and data tracks
|
harm in any case and would probably be unavoidable if audio and data tracks
|
||||||
were mixed.)
|
were mixed.)
|
||||||
@ -755,7 +758,8 @@ The only known way to get full speed from DVD-RAM or BD-RE with enabled defect
|
|||||||
management is the use of AAh WRITE12 with Streaming Bit set to 1.
|
management is the use of AAh WRITE12 with Streaming Bit set to 1.
|
||||||
(mmc5r03c.pdf 6.45)
|
(mmc5r03c.pdf 6.45)
|
||||||
With some DVD-RAM drives this fails if a write buffer is not full 32 kB.
|
With some DVD-RAM drives this fails if a write buffer is not full 32 kB.
|
||||||
With the tested BD-RE one has to write full 64 kB buffers.
|
With the tested BD-RE one must write full 64 kB buffers, or else writing
|
||||||
|
might not get into effect at all.
|
||||||
|
|
||||||
Although it seems not optimal, this is specified not only to disable the
|
Although it seems not optimal, this is specified not only to disable the
|
||||||
cumbersome checkread but also to ignore known defects and to write data
|
cumbersome checkread but also to ignore known defects and to write data
|
||||||
@ -769,7 +773,8 @@ MMC-5 does not guarantee AAh WRITE12 to work on DVD-RAM or BD-RE at all.
|
|||||||
None of the features of profiles 0012h and 0043h promises the existence of
|
None of the features of profiles 0012h and 0043h promises the existence of
|
||||||
AAh WRITE12.
|
AAh WRITE12.
|
||||||
(mmc5r03c.pdf 5.4.13, 6.45)
|
(mmc5r03c.pdf 5.4.13, 6.45)
|
||||||
Nevertheless it worked on all tested drives if proper alignment was observed.
|
Nevertheless it worked on all tested drives if proper alignment and block
|
||||||
|
size was observed.
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
@ -841,6 +846,8 @@ This chain gives the start addresses of sessions. The sector count minus start
|
|||||||
address gives the size of a particular session. ECMA-119 explains how to
|
address gives the size of a particular session. ECMA-119 explains how to
|
||||||
retrieve more info from the PVD (e.g. the volume id).
|
retrieve more info from the PVD (e.g. the volume id).
|
||||||
|
|
||||||
|
See also the multi-session example in libisofs/doc/checksums.txt.
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -933,7 +940,7 @@ Multi-Session by the application.
|
|||||||
LS_V Link size valid 1=true
|
LS_V Link size valid 1=true
|
||||||
Test Write -dummy mode for writing 0=off, 1=on
|
Test Write -dummy mode for writing 0=off, 1=on
|
||||||
Write Type Packet/TAO/SAO/RAW 00h = Incremental (Packet)
|
Write Type Packet/TAO/SAO/RAW 00h = Incremental (Packet)
|
||||||
Multi-session Wether to keep appendable 00b = finalize
|
Multi-session Whether to keep appendable 00b = finalize
|
||||||
11b = keep appendable
|
11b = keep appendable
|
||||||
Track Mode Describes frame type 5 [*1]
|
Track Mode Describes frame type 5 [*1]
|
||||||
Data Block Type Layout of payload blocks 8 [*2]
|
Data Block Type Layout of payload blocks 8 [*2]
|
||||||
@ -980,7 +987,7 @@ from the reply of 51h READ DISC INFORMATION requesting Data Type 000b
|
|||||||
Multiple tracks are permissible in a single session. After all of them have
|
Multiple tracks are permissible in a single session. After all of them have
|
||||||
been written, 5Bh CLOSE TRACK SESSION Close Function 010b with Logical Track
|
been written, 5Bh CLOSE TRACK SESSION Close Function 010b with Logical Track
|
||||||
Number 0 closes the session. It depends on the Multi-Session value in mode
|
Number 0 closes the session. It depends on the Multi-Session value in mode
|
||||||
page 05h wether the disc is finalized or stays appendable.
|
page 05h whether the disc is finalized or stays appendable.
|
||||||
(mmc5r03c.pdf 6.3.3.2.3)
|
(mmc5r03c.pdf 6.3.3.2.3)
|
||||||
|
|
||||||
|
|
||||||
@ -1005,7 +1012,7 @@ The mode page 05h to be sent :
|
|||||||
LS_V Link size valid 0=false [*3]
|
LS_V Link size valid 0=false [*3]
|
||||||
Test Write -dummy mode for writing 0=off, 1=on
|
Test Write -dummy mode for writing 0=off, 1=on
|
||||||
Write Type Packet/TAO/SAO/RAW 02h = DAO (same code as SAO)
|
Write Type Packet/TAO/SAO/RAW 02h = DAO (same code as SAO)
|
||||||
Multi-session Wether to keep appendable 00b = finalize
|
Multi-session Whether to keep appendable 00b = finalize
|
||||||
Track Mode Describes frame type 5 [*1]
|
Track Mode Describes frame type 5 [*1]
|
||||||
Data Block Type Layout of payload blocks 8 [*2]
|
Data Block Type Layout of payload blocks 8 [*2]
|
||||||
Link Size ??? 0 [*3]
|
Link Size ??? 0 [*3]
|
||||||
@ -1222,7 +1229,7 @@ No mode page 05h is to be sent.
|
|||||||
growisofs sends a page but the specs clearly state that one shall not do.
|
growisofs sends a page but the specs clearly state that one shall not do.
|
||||||
(mmc5r03c.pdf 7.5.3)
|
(mmc5r03c.pdf 7.5.3)
|
||||||
|
|
||||||
It is optional wether a track size is reserved in advance or not. Eventually
|
It is optional whether a track size is reserved in advance or not. Eventually
|
||||||
this is done by 53h RESERVE TRACK, RMZ=ARSV=0. Reservation size should better
|
this is done by 53h RESERVE TRACK, RMZ=ARSV=0. Reservation size should better
|
||||||
already be aligned to 32 KiB.
|
already be aligned to 32 KiB.
|
||||||
(mmc5r03c.pdf 6.31)
|
(mmc5r03c.pdf 6.31)
|
||||||
|
@ -627,7 +627,8 @@ int burn_fifo_start(struct burn_source *source, int flag)
|
|||||||
fs->is_started = -1;
|
fs->is_started = -1;
|
||||||
|
|
||||||
/* create and set up ring buffer */;
|
/* create and set up ring buffer */;
|
||||||
fs->buf = calloc(fs->chunksize, fs->chunks);
|
fs->buf = burn_os_alloc_buffer(
|
||||||
|
((size_t) fs->chunksize) * (size_t) fs->chunks, 0);
|
||||||
if (fs->buf == NULL) {
|
if (fs->buf == NULL) {
|
||||||
/* >>> could not start ring buffer */;
|
/* >>> could not start ring buffer */;
|
||||||
return -1;
|
return -1;
|
||||||
|
112
libburn/drive.c
112
libburn/drive.c
@ -90,6 +90,7 @@ void burn_drive_free_subs(struct burn_drive *d)
|
|||||||
if (d->stdio_fd >= 0)
|
if (d->stdio_fd >= 0)
|
||||||
close (d->stdio_fd);
|
close (d->stdio_fd);
|
||||||
d->stdio_fd = -1;
|
d->stdio_fd = -1;
|
||||||
|
sg_dispose_drive(d, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -424,10 +425,6 @@ struct burn_drive *burn_drive_finish_enum(struct burn_drive *d)
|
|||||||
char msg[BURN_DRIVE_ADR_LEN + 160];
|
char msg[BURN_DRIVE_ADR_LEN + 160];
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* ts A60821
|
|
||||||
<<< debug: for tracing calls which might use open drive fds */
|
|
||||||
int mmc_function_spy(struct burn_drive *d, char * text);
|
|
||||||
|
|
||||||
d->drive_role = 1; /* MMC drive */
|
d->drive_role = 1; /* MMC drive */
|
||||||
|
|
||||||
t = burn_drive_register(d);
|
t = burn_drive_register(d);
|
||||||
@ -910,6 +907,29 @@ static int drive_getcaps(struct burn_drive *d, struct burn_drive_info *out)
|
|||||||
out->write_simulate = !!d->mdata->simulate;
|
out->write_simulate = !!d->mdata->simulate;
|
||||||
out->c2_errors = !!d->mdata->c2_pointers;
|
out->c2_errors = !!d->mdata->c2_pointers;
|
||||||
out->drive = d;
|
out->drive = d;
|
||||||
|
|
||||||
|
#ifdef Libburn_dummy_probe_write_modeS
|
||||||
|
|
||||||
|
/* ts A91112 */
|
||||||
|
/* Set default block types. The call d->probe_write_modes() is quite
|
||||||
|
obtrusive. It may be performed explicitely by new API call
|
||||||
|
burn_drive_probe_cd_write_modes().
|
||||||
|
*/
|
||||||
|
if (out->write_dvdram || out->write_dvdr ||
|
||||||
|
out->write_cdrw || out->write_cdr) {
|
||||||
|
out->tao_block_types = d->block_types[BURN_WRITE_TAO] =
|
||||||
|
BURN_BLOCK_MODE1 | BURN_BLOCK_RAW0;
|
||||||
|
out->sao_block_types = d->block_types[BURN_WRITE_SAO] =
|
||||||
|
BURN_BLOCK_SAO;
|
||||||
|
} else {
|
||||||
|
out->tao_block_types = d->block_types[BURN_WRITE_TAO] = 0;
|
||||||
|
out->sao_block_types = d->block_types[BURN_WRITE_SAO] = 0;
|
||||||
|
}
|
||||||
|
out->raw_block_types = d->block_types[BURN_WRITE_RAW] = 0;
|
||||||
|
out->packet_block_types = 0;
|
||||||
|
|
||||||
|
#else /* Libburn_dummy_probe_write_modeS */
|
||||||
|
|
||||||
/* update available block types for burners */
|
/* update available block types for burners */
|
||||||
if (out->write_dvdram || out->write_dvdr ||
|
if (out->write_dvdram || out->write_dvdr ||
|
||||||
out->write_cdrw || out->write_cdr)
|
out->write_cdrw || out->write_cdr)
|
||||||
@ -918,6 +938,30 @@ static int drive_getcaps(struct burn_drive *d, struct burn_drive_info *out)
|
|||||||
out->sao_block_types = d->block_types[BURN_WRITE_SAO];
|
out->sao_block_types = d->block_types[BURN_WRITE_SAO];
|
||||||
out->raw_block_types = d->block_types[BURN_WRITE_RAW];
|
out->raw_block_types = d->block_types[BURN_WRITE_RAW];
|
||||||
out->packet_block_types = d->block_types[BURN_WRITE_PACKET];
|
out->packet_block_types = d->block_types[BURN_WRITE_PACKET];
|
||||||
|
|
||||||
|
#endif /* ! Libburn_dummy_probe_write_modeS */
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ts A91112 - B00114 API */
|
||||||
|
/* Probe available CD write modes and block types.
|
||||||
|
*/
|
||||||
|
int burn_drive_probe_cd_write_modes(struct burn_drive_info *dinfo)
|
||||||
|
{
|
||||||
|
struct burn_drive *d = dinfo->drive;
|
||||||
|
|
||||||
|
if (d == NULL)
|
||||||
|
return 0;
|
||||||
|
if (dinfo->write_dvdram || dinfo->write_dvdr ||
|
||||||
|
dinfo->write_cdrw || dinfo->write_cdr)
|
||||||
|
d->probe_write_modes(d);
|
||||||
|
dinfo->tao_block_types = d->block_types[BURN_WRITE_TAO];
|
||||||
|
dinfo->sao_block_types = d->block_types[BURN_WRITE_SAO];
|
||||||
|
dinfo->raw_block_types = d->block_types[BURN_WRITE_RAW];
|
||||||
|
dinfo->packet_block_types = d->block_types[BURN_WRITE_PACKET];
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1278,6 +1322,7 @@ int burn_drive__fd_from_special_adr(char *adr)
|
|||||||
int burn_drive_grab_dummy(struct burn_drive_info *drive_infos[], char *fname)
|
int burn_drive_grab_dummy(struct burn_drive_info *drive_infos[], char *fname)
|
||||||
{
|
{
|
||||||
int ret = -1, fd = -1, role = 0;
|
int ret = -1, fd = -1, role = 0;
|
||||||
|
int is_block_dev = 0;
|
||||||
/* divided by 512 it needs to fit into a signed long integer */
|
/* divided by 512 it needs to fit into a signed long integer */
|
||||||
off_t size = ((off_t) (512 * 1024 * 1024 - 1) * (off_t) 2048);
|
off_t size = ((off_t) (512 * 1024 * 1024 - 1) * (off_t) 2048);
|
||||||
off_t read_size = -1;
|
off_t read_size = -1;
|
||||||
@ -1294,17 +1339,18 @@ int burn_drive_grab_dummy(struct burn_drive_info *drive_infos[], char *fname)
|
|||||||
else
|
else
|
||||||
ret = stat(fname, &stbuf);
|
ret = stat(fname, &stbuf);
|
||||||
if (ret != -1) {
|
if (ret != -1) {
|
||||||
|
is_block_dev = burn_os_is_2k_seekrw(fname, 0);
|
||||||
if (S_ISREG(stbuf.st_mode))
|
if (S_ISREG(stbuf.st_mode))
|
||||||
read_size = stbuf.st_size;
|
read_size = stbuf.st_size;
|
||||||
else if (S_ISBLK(stbuf.st_mode)) {
|
else if (is_block_dev) {
|
||||||
ret = burn_os_stdio_capacity(fname,
|
ret = burn_os_stdio_capacity(fname,
|
||||||
&read_size);
|
&read_size);
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
read_size = -1;
|
read_size = (off_t) 0x7ffffff0 *
|
||||||
|
(off_t) 2048;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ret == -1 || S_ISBLK(stbuf.st_mode) ||
|
if (ret == -1 || is_block_dev || S_ISREG(stbuf.st_mode)) {
|
||||||
S_ISREG(stbuf.st_mode)) {
|
|
||||||
ret = burn_os_stdio_capacity(fname, &size);
|
ret = burn_os_stdio_capacity(fname, &size);
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
libdax_msgs_submit(libdax_messenger, -1,
|
libdax_msgs_submit(libdax_messenger, -1,
|
||||||
@ -1520,14 +1566,23 @@ int burn_drive_is_enumerable_adr(char *adr)
|
|||||||
#define BURN_DRIVE_MAX_LINK_DEPTH 20
|
#define BURN_DRIVE_MAX_LINK_DEPTH 20
|
||||||
|
|
||||||
/* ts A60922 ticket 33 */
|
/* ts A60922 ticket 33 */
|
||||||
int burn_drive_resolve_link(char *path, char adr[], int *recursion_count)
|
/* @param flag bit0= no debug messages
|
||||||
|
bit1= resolve only links,
|
||||||
|
do not rely on drive list for resolving via st_rdev
|
||||||
|
*/
|
||||||
|
int burn_drive_resolve_link(char *path, char adr[], int *recursion_count,
|
||||||
|
int flag)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
char link_target[4096], msg[4096+100], link_adr[4096], *adrpt;
|
char link_target[4096], msg[4096+100], link_adr[4096], *adrpt;
|
||||||
|
struct stat stbuf;
|
||||||
|
|
||||||
burn_drive_adr_debug_msg("burn_drive_resolve_link( %s )", path);
|
if (flag & 1)
|
||||||
|
burn_drive_adr_debug_msg("burn_drive_resolve_link( %s )",
|
||||||
|
path);
|
||||||
if (*recursion_count >= BURN_DRIVE_MAX_LINK_DEPTH) {
|
if (*recursion_count >= BURN_DRIVE_MAX_LINK_DEPTH) {
|
||||||
burn_drive_adr_debug_msg(
|
if (flag & 1)
|
||||||
|
burn_drive_adr_debug_msg(
|
||||||
"burn_drive_resolve_link aborts because link too deep",
|
"burn_drive_resolve_link aborts because link too deep",
|
||||||
NULL);
|
NULL);
|
||||||
return 0;
|
return 0;
|
||||||
@ -1535,12 +1590,15 @@ int burn_drive_resolve_link(char *path, char adr[], int *recursion_count)
|
|||||||
(*recursion_count)++;
|
(*recursion_count)++;
|
||||||
ret = readlink(path, link_target, sizeof(link_target));
|
ret = readlink(path, link_target, sizeof(link_target));
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
burn_drive_adr_debug_msg("readlink( %s ) returns -1", path);
|
if (flag & 1)
|
||||||
|
burn_drive_adr_debug_msg("readlink( %s ) returns -1",
|
||||||
|
path);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (ret >= sizeof(link_target) - 1) {
|
if (ret >= sizeof(link_target) - 1) {
|
||||||
sprintf(msg,"readlink( %s ) returns %d (too much)", path, ret);
|
sprintf(msg,"readlink( %s ) returns %d (too much)", path, ret);
|
||||||
burn_drive_adr_debug_msg(msg, NULL);
|
if (flag & 1)
|
||||||
|
burn_drive_adr_debug_msg(msg, NULL);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
link_target[ret] = 0;
|
link_target[ret] = 0;
|
||||||
@ -1553,10 +1611,25 @@ int burn_drive_resolve_link(char *path, char adr[], int *recursion_count)
|
|||||||
} else
|
} else
|
||||||
adrpt = link_target;
|
adrpt = link_target;
|
||||||
}
|
}
|
||||||
ret = burn_drive_convert_fs_adr_sub(adrpt, adr, recursion_count);
|
if (flag & 2) {
|
||||||
sprintf(msg,"burn_drive_convert_fs_adr( %s ) returns %d",
|
/* Link-only recursion */
|
||||||
link_target, ret);
|
if (lstat(adrpt, &stbuf) == -1) {
|
||||||
burn_drive_adr_debug_msg(msg, NULL);
|
;
|
||||||
|
} else if((stbuf.st_mode & S_IFMT) == S_IFLNK) {
|
||||||
|
ret = burn_drive_resolve_link(adrpt, adr,
|
||||||
|
recursion_count, flag);
|
||||||
|
} else {
|
||||||
|
strcpy(adr, adrpt);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Link and device number recursion */
|
||||||
|
ret = burn_drive_convert_fs_adr_sub(adrpt, adr,
|
||||||
|
recursion_count);
|
||||||
|
sprintf(msg,"burn_drive_convert_fs_adr( %s ) returns %d",
|
||||||
|
link_target, ret);
|
||||||
|
}
|
||||||
|
if (flag & 1)
|
||||||
|
burn_drive_adr_debug_msg(msg, NULL);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1730,7 +1803,7 @@ int burn_drive_convert_fs_adr_sub(char *path, char adr[], int *rec_count)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if((stbuf.st_mode & S_IFMT) == S_IFLNK) {
|
if((stbuf.st_mode & S_IFMT) == S_IFLNK) {
|
||||||
ret = burn_drive_resolve_link(path, adr, rec_count);
|
ret = burn_drive_resolve_link(path, adr, rec_count, 0);
|
||||||
if(ret > 0)
|
if(ret > 0)
|
||||||
return 1;
|
return 1;
|
||||||
burn_drive_adr_debug_msg("link fallback via stat( %s )", path);
|
burn_drive_adr_debug_msg("link fallback via stat( %s )", path);
|
||||||
@ -2569,6 +2642,9 @@ int burn_drive_equals_adr(struct burn_drive *d1, char *adr2_in, int role2)
|
|||||||
if (S_ISBLK(stbuf1.st_mode) && S_ISBLK(stbuf2.st_mode) &&
|
if (S_ISBLK(stbuf1.st_mode) && S_ISBLK(stbuf2.st_mode) &&
|
||||||
stbuf1.st_rdev == stbuf2.st_rdev)
|
stbuf1.st_rdev == stbuf2.st_rdev)
|
||||||
return 1; /* same major,minor device number */
|
return 1; /* same major,minor device number */
|
||||||
|
if (S_ISCHR(stbuf1.st_mode) && S_ISCHR(stbuf2.st_mode) &&
|
||||||
|
stbuf1.st_rdev == stbuf2.st_rdev)
|
||||||
|
return 1; /* same major,minor device number */
|
||||||
|
|
||||||
/* Are both filesystem objects related to the same MMC drive */
|
/* Are both filesystem objects related to the same MMC drive */
|
||||||
if (conv_ret2 <= 0)
|
if (conv_ret2 <= 0)
|
||||||
|
850
libburn/ecma130ab.c
Normal file
850
libburn/ecma130ab.c
Normal file
@ -0,0 +1,850 @@
|
|||||||
|
|
||||||
|
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||||
|
|
||||||
|
/* ts A91016 : libburn/ecma130ab.c is the replacement for old libburn/lec.c
|
||||||
|
|
||||||
|
Copyright 2009, Thomas Schmitt <scdbackup@gmx.net>, libburnia-project.org
|
||||||
|
|
||||||
|
This code module implements the production of RSPC parity bytes (P- and Q-
|
||||||
|
parity) and the scrambling of raw CD-ROM sectors as specified in ECMA-130:
|
||||||
|
http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-130.pdf
|
||||||
|
|
||||||
|
The following statements about Galois Fields have been learned mostly from
|
||||||
|
http://www.cs.utk.edu/~plank/plank/papers/CS-96-332.pdf
|
||||||
|
by James S. Plank after an e-mail exchange with Norbert Preining.
|
||||||
|
|
||||||
|
The output has been compared with the output of the old code of libburn
|
||||||
|
which was labeled "borrowed HEAVILY from cdrdao" and claimed by Joerg
|
||||||
|
Schilling to stem from code by Heiko Eissfeldt.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------
|
||||||
|
Note: In this text, "^" denotes exponentiation and not the binary exor
|
||||||
|
operation. Confusingly in the C code "^" is said exor.
|
||||||
|
Note: This is not C1, C2 which is rather mentioned in ECMA-130 Annex C and
|
||||||
|
always performed inside the drive.
|
||||||
|
-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
RSPC resp. P- and Q-Parity
|
||||||
|
|
||||||
|
ECMA-130 Annex A prescribes to compute the parity bytes for P-columns and
|
||||||
|
Q-diagonals by RSPC based on a Galois Field GF(2^8) with enumerating
|
||||||
|
polynomials x^8+x^4+x^3+x^2+1 (i.e. 0x11d) and x^1 (i.e. 0x02).
|
||||||
|
Bytes 12 to 2075 of a audio-sized sector get ordered in two byte words
|
||||||
|
as 24 rows and 43 columns. Then this matrix is split into a LSB matrix
|
||||||
|
and a MSB matrix of the same layout. Parity bytes are to be computed
|
||||||
|
from these 8-bit values.
|
||||||
|
2 P-bytes cover each column of 24 bytes. They get appended to the matrix
|
||||||
|
as rows 24 and 25.
|
||||||
|
2 Q-bytes cover each the 26 diagonals of the extended matrix.
|
||||||
|
|
||||||
|
Both parity byte pairs have to be computed so that extended rows or
|
||||||
|
diagonals match this linear equation:
|
||||||
|
H x V = (0,0)
|
||||||
|
H is a 2-row matrix of size n matching the length of the V ectors
|
||||||
|
[ 1 1 ... 1 1 ]
|
||||||
|
[ x^(n-1) x^(n-2) x^1 1 ]
|
||||||
|
Vp represents a P-row. It is a byte vector consisting of row bytes at
|
||||||
|
position 0 to 23 and the two parity bytes which shall be determined
|
||||||
|
at position 24 and 25. So Hp has 26 columns.
|
||||||
|
Vq represents a Q-diagonal. It is a byte vector consisting of diagonal
|
||||||
|
bytes at position 0 to 42 and the two parity bytes at position 43 and 44.
|
||||||
|
So Hq has 45 columns. The Q-diagonals cover P-parity bytes.
|
||||||
|
|
||||||
|
By applying some high school algebra one gets the parity bytes b0, b1 of
|
||||||
|
vector V = (n_payload_bytes, b0 , b1) as
|
||||||
|
|
||||||
|
b0 = ( H[n] * SUM(n_payload_bytes) - H[0..(n-1)] x n_payload_bytes )
|
||||||
|
/ (H[n+1] - H[n])
|
||||||
|
b1 = - SUM(n_payload_bytes) - b0
|
||||||
|
|
||||||
|
H[i] is the i-the element of the second row of matrix H. E.g. H[0] = x^(n-1)
|
||||||
|
The result has to be computed by Galois field arithmetics. See below.
|
||||||
|
|
||||||
|
The P-parity bytes of each column get reunited as LSB and MSB of two words.
|
||||||
|
word1 gets written to positions 1032 to 1074, word0 to 1075 to 1117.
|
||||||
|
The Q-parity bytes of each diagonal get reunited too. word1 goes to 1118
|
||||||
|
to 1143, word0 to 1144 to 1169.
|
||||||
|
>>> I do not read this swap of word1 and word0 from ECMA-130 Annex A.
|
||||||
|
>>> But the new output matches the old output only if it is done that way.
|
||||||
|
>>> See correctness reservation below.
|
||||||
|
|
||||||
|
Algebra on Galois fields is the same as on Rational Numbers.
|
||||||
|
But arithmetics is defined by operations on polynomials rather than the
|
||||||
|
usual integer arithmetics on binary numbers.
|
||||||
|
Addition and subtraction are identical with the binary exor operator.
|
||||||
|
Multiplication and division would demand polynomial division, e.g. by the
|
||||||
|
euclidian algorithm. The computing path over logarithms and powers follows
|
||||||
|
algebra and allows to reduce the arithmetic task to table lookups, additions
|
||||||
|
modulo 255, and exor operations. Note that the logarithms are natural
|
||||||
|
numbers, not polynomials. They get added or subtracted by the usual addition
|
||||||
|
(not by exor) and their polynomial power depends on their value modulo 255.
|
||||||
|
|
||||||
|
Needed are a logarithm table and a power table (or inverse logarithm table)
|
||||||
|
for Galois Field GF(2^8) which will serve to perform the peculiar
|
||||||
|
multiplication and division operation of Galois fields.
|
||||||
|
|
||||||
|
The power table is simply an enumeration of x^n accorting to
|
||||||
|
GF-multiplication. It also serves as second line of matrix H for the parity
|
||||||
|
equations:
|
||||||
|
Hp[i] = gfpow[25-i] , i out of {0,..,25}
|
||||||
|
Hq[i] = gfpow[44-i] , i out of {0,..,44}
|
||||||
|
|
||||||
|
The logarithm table is the inverse permutation of the power table.
|
||||||
|
|
||||||
|
Some simplifications apply to the implementation:
|
||||||
|
In the world of Galois fields there is no difference between - and +.
|
||||||
|
The term (H[n+1] - H[n]) is constant: 3.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
Scrambling
|
||||||
|
|
||||||
|
ECMA-130 Annex B prescribes to exor the byte stream of an audio-sized sector
|
||||||
|
with a sequence of pseudo random bytes. It mentions polynomial x^15+x+1 and
|
||||||
|
a 15-bit register.
|
||||||
|
It shows a diagram of a Feedback Shift Register with 16 bit boxes, though.
|
||||||
|
|
||||||
|
Comparing this with explanations in
|
||||||
|
http://www.newwaveinstruments.com/resources/articles/m_sequence_linear_feedback_shift_register_lfsr.htm
|
||||||
|
one can recognize the diagram as a Fibonacci Implementation. But there seems
|
||||||
|
really to be one bit box too many.
|
||||||
|
|
||||||
|
The difference of both lengths is expressed in function next_bit() by
|
||||||
|
the constants 0x3fff,0x4000 for 15 bit versus 0x7fff,0x8000 for 16 bits.
|
||||||
|
Comparing the output of both alternatives with the old scrambler output
|
||||||
|
lets 15 bit win for now.
|
||||||
|
|
||||||
|
So the prescription is to start with 15 bit value 1, to use the lowest bit
|
||||||
|
as output, to shift the bits down by one, to exor the output bit with the
|
||||||
|
next lowest bit, and to put that exor result into bit 14 of the register.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
Correctness Reservation
|
||||||
|
|
||||||
|
In both cases, parity and scrambling, the goal for now is to replicate the
|
||||||
|
output of the dismissed old lec.c by output which is based on published
|
||||||
|
specs and own implementation code. Whether they comply to ECMA-130 is a
|
||||||
|
different question which can only be answered by real test cases for
|
||||||
|
raw CD recording.
|
||||||
|
|
||||||
|
Of course this implementation will be corrected so that it really complies
|
||||||
|
to ECMA-130 as soon as evidence emerges that it does not yet.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
/* Power and logarithm tables for GF(2^8), parity matrices for ECMA-130.
|
||||||
|
Generated by burn_rspc_setup_tables() and burn_rspc_print_tables().
|
||||||
|
|
||||||
|
The highest possible sum of gflog[] values is is 508. So the table gfpow[]
|
||||||
|
with period 255 was manually unrolled to 509 elements to avoid one modulo
|
||||||
|
255 operation in burn_rspc_mult().
|
||||||
|
Proposed by D. Hugh Redelmeier.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
static unsigned char gfpow[509] = {
|
||||||
|
1, 2, 4, 8, 16, 32, 64, 128, 29, 58,
|
||||||
|
116, 232, 205, 135, 19, 38, 76, 152, 45, 90,
|
||||||
|
180, 117, 234, 201, 143, 3, 6, 12, 24, 48,
|
||||||
|
96, 192, 157, 39, 78, 156, 37, 74, 148, 53,
|
||||||
|
106, 212, 181, 119, 238, 193, 159, 35, 70, 140,
|
||||||
|
5, 10, 20, 40, 80, 160, 93, 186, 105, 210,
|
||||||
|
185, 111, 222, 161, 95, 190, 97, 194, 153, 47,
|
||||||
|
94, 188, 101, 202, 137, 15, 30, 60, 120, 240,
|
||||||
|
253, 231, 211, 187, 107, 214, 177, 127, 254, 225,
|
||||||
|
223, 163, 91, 182, 113, 226, 217, 175, 67, 134,
|
||||||
|
17, 34, 68, 136, 13, 26, 52, 104, 208, 189,
|
||||||
|
103, 206, 129, 31, 62, 124, 248, 237, 199, 147,
|
||||||
|
59, 118, 236, 197, 151, 51, 102, 204, 133, 23,
|
||||||
|
46, 92, 184, 109, 218, 169, 79, 158, 33, 66,
|
||||||
|
132, 21, 42, 84, 168, 77, 154, 41, 82, 164,
|
||||||
|
85, 170, 73, 146, 57, 114, 228, 213, 183, 115,
|
||||||
|
230, 209, 191, 99, 198, 145, 63, 126, 252, 229,
|
||||||
|
215, 179, 123, 246, 241, 255, 227, 219, 171, 75,
|
||||||
|
150, 49, 98, 196, 149, 55, 110, 220, 165, 87,
|
||||||
|
174, 65, 130, 25, 50, 100, 200, 141, 7, 14,
|
||||||
|
28, 56, 112, 224, 221, 167, 83, 166, 81, 162,
|
||||||
|
89, 178, 121, 242, 249, 239, 195, 155, 43, 86,
|
||||||
|
172, 69, 138, 9, 18, 36, 72, 144, 61, 122,
|
||||||
|
244, 245, 247, 243, 251, 235, 203, 139, 11, 22,
|
||||||
|
44, 88, 176, 125, 250, 233, 207, 131, 27, 54,
|
||||||
|
108, 216, 173, 71, 142,
|
||||||
|
1, 2, 4, 8, 16, 32, 64, 128, 29, 58,
|
||||||
|
116, 232, 205, 135, 19, 38, 76, 152, 45, 90,
|
||||||
|
180, 117, 234, 201, 143, 3, 6, 12, 24, 48,
|
||||||
|
96, 192, 157, 39, 78, 156, 37, 74, 148, 53,
|
||||||
|
106, 212, 181, 119, 238, 193, 159, 35, 70, 140,
|
||||||
|
5, 10, 20, 40, 80, 160, 93, 186, 105, 210,
|
||||||
|
185, 111, 222, 161, 95, 190, 97, 194, 153, 47,
|
||||||
|
94, 188, 101, 202, 137, 15, 30, 60, 120, 240,
|
||||||
|
253, 231, 211, 187, 107, 214, 177, 127, 254, 225,
|
||||||
|
223, 163, 91, 182, 113, 226, 217, 175, 67, 134,
|
||||||
|
17, 34, 68, 136, 13, 26, 52, 104, 208, 189,
|
||||||
|
103, 206, 129, 31, 62, 124, 248, 237, 199, 147,
|
||||||
|
59, 118, 236, 197, 151, 51, 102, 204, 133, 23,
|
||||||
|
46, 92, 184, 109, 218, 169, 79, 158, 33, 66,
|
||||||
|
132, 21, 42, 84, 168, 77, 154, 41, 82, 164,
|
||||||
|
85, 170, 73, 146, 57, 114, 228, 213, 183, 115,
|
||||||
|
230, 209, 191, 99, 198, 145, 63, 126, 252, 229,
|
||||||
|
215, 179, 123, 246, 241, 255, 227, 219, 171, 75,
|
||||||
|
150, 49, 98, 196, 149, 55, 110, 220, 165, 87,
|
||||||
|
174, 65, 130, 25, 50, 100, 200, 141, 7, 14,
|
||||||
|
28, 56, 112, 224, 221, 167, 83, 166, 81, 162,
|
||||||
|
89, 178, 121, 242, 249, 239, 195, 155, 43, 86,
|
||||||
|
172, 69, 138, 9, 18, 36, 72, 144, 61, 122,
|
||||||
|
244, 245, 247, 243, 251, 235, 203, 139, 11, 22,
|
||||||
|
44, 88, 176, 125, 250, 233, 207, 131, 27, 54,
|
||||||
|
108, 216, 173, 71,
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned char gflog[256] = {
|
||||||
|
0, 0, 1, 25, 2, 50, 26, 198, 3, 223,
|
||||||
|
51, 238, 27, 104, 199, 75, 4, 100, 224, 14,
|
||||||
|
52, 141, 239, 129, 28, 193, 105, 248, 200, 8,
|
||||||
|
76, 113, 5, 138, 101, 47, 225, 36, 15, 33,
|
||||||
|
53, 147, 142, 218, 240, 18, 130, 69, 29, 181,
|
||||||
|
194, 125, 106, 39, 249, 185, 201, 154, 9, 120,
|
||||||
|
77, 228, 114, 166, 6, 191, 139, 98, 102, 221,
|
||||||
|
48, 253, 226, 152, 37, 179, 16, 145, 34, 136,
|
||||||
|
54, 208, 148, 206, 143, 150, 219, 189, 241, 210,
|
||||||
|
19, 92, 131, 56, 70, 64, 30, 66, 182, 163,
|
||||||
|
195, 72, 126, 110, 107, 58, 40, 84, 250, 133,
|
||||||
|
186, 61, 202, 94, 155, 159, 10, 21, 121, 43,
|
||||||
|
78, 212, 229, 172, 115, 243, 167, 87, 7, 112,
|
||||||
|
192, 247, 140, 128, 99, 13, 103, 74, 222, 237,
|
||||||
|
49, 197, 254, 24, 227, 165, 153, 119, 38, 184,
|
||||||
|
180, 124, 17, 68, 146, 217, 35, 32, 137, 46,
|
||||||
|
55, 63, 209, 91, 149, 188, 207, 205, 144, 135,
|
||||||
|
151, 178, 220, 252, 190, 97, 242, 86, 211, 171,
|
||||||
|
20, 42, 93, 158, 132, 60, 57, 83, 71, 109,
|
||||||
|
65, 162, 31, 45, 67, 216, 183, 123, 164, 118,
|
||||||
|
196, 23, 73, 236, 127, 12, 111, 246, 108, 161,
|
||||||
|
59, 82, 41, 157, 85, 170, 251, 96, 134, 177,
|
||||||
|
187, 204, 62, 90, 203, 89, 95, 176, 156, 169,
|
||||||
|
160, 81, 11, 245, 22, 235, 122, 117, 44, 215,
|
||||||
|
79, 174, 213, 233, 230, 231, 173, 232, 116, 214,
|
||||||
|
244, 234, 168, 80, 88, 175
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define Libburn_use_h_matriceS 1
|
||||||
|
|
||||||
|
#ifdef Libburn_use_h_matriceS
|
||||||
|
|
||||||
|
/* On my AMD 2x64 bit 3000 MHz processor h[i] costs about 7 % more time
|
||||||
|
than using gfpow[25-i] resp. gfpow[44-1]. I blame this on the more
|
||||||
|
condensed data representation which slightly increases the rate of cache
|
||||||
|
hits.
|
||||||
|
Nevertheless this effect is very likely depending on the exact cache
|
||||||
|
size and architecture. In general, using h[] saves more than 8000
|
||||||
|
subtractions per sector.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Parity matrices H as prescribed by ECMA-130 Annex A.
|
||||||
|
Actually just reverted order start pieces of gfpow[].
|
||||||
|
*/
|
||||||
|
static unsigned char h26[26] = {
|
||||||
|
3, 143, 201, 234, 117, 180, 90, 45, 152, 76,
|
||||||
|
38, 19, 135, 205, 232, 116, 58, 29, 128, 64,
|
||||||
|
32, 16, 8, 4, 2, 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned char h45[45] = {
|
||||||
|
238, 119, 181, 212, 106, 53, 148, 74, 37, 156,
|
||||||
|
78, 39, 157, 192, 96, 48, 24, 12, 6, 3,
|
||||||
|
143, 201, 234, 117, 180, 90, 45, 152, 76, 38,
|
||||||
|
19, 135, 205, 232, 116, 58, 29, 128, 64, 32,
|
||||||
|
16, 8, 4, 2, 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* Libburn_use_h_matriceS */
|
||||||
|
|
||||||
|
|
||||||
|
/* Pseudo-random bytes which of course are exactly the same as with the
|
||||||
|
previously used code.
|
||||||
|
Generated by function print_ecma_130_scrambler().
|
||||||
|
*/
|
||||||
|
static unsigned char ecma_130_annex_b[2340] = {
|
||||||
|
1, 128, 0, 96, 0, 40, 0, 30, 128, 8,
|
||||||
|
96, 6, 168, 2, 254, 129, 128, 96, 96, 40,
|
||||||
|
40, 30, 158, 136, 104, 102, 174, 170, 252, 127,
|
||||||
|
1, 224, 0, 72, 0, 54, 128, 22, 224, 14,
|
||||||
|
200, 4, 86, 131, 126, 225, 224, 72, 72, 54,
|
||||||
|
182, 150, 246, 238, 198, 204, 82, 213, 253, 159,
|
||||||
|
1, 168, 0, 126, 128, 32, 96, 24, 40, 10,
|
||||||
|
158, 135, 40, 98, 158, 169, 168, 126, 254, 160,
|
||||||
|
64, 120, 48, 34, 148, 25, 175, 74, 252, 55,
|
||||||
|
1, 214, 128, 94, 224, 56, 72, 18, 182, 141,
|
||||||
|
182, 229, 182, 203, 54, 215, 86, 222, 190, 216,
|
||||||
|
112, 90, 164, 59, 59, 83, 83, 125, 253, 225,
|
||||||
|
129, 136, 96, 102, 168, 42, 254, 159, 0, 104,
|
||||||
|
0, 46, 128, 28, 96, 9, 232, 6, 206, 130,
|
||||||
|
212, 97, 159, 104, 104, 46, 174, 156, 124, 105,
|
||||||
|
225, 238, 200, 76, 86, 181, 254, 247, 0, 70,
|
||||||
|
128, 50, 224, 21, 136, 15, 38, 132, 26, 227,
|
||||||
|
75, 9, 247, 70, 198, 178, 210, 245, 157, 135,
|
||||||
|
41, 162, 158, 249, 168, 66, 254, 177, 128, 116,
|
||||||
|
96, 39, 104, 26, 174, 139, 60, 103, 81, 234,
|
||||||
|
188, 79, 49, 244, 20, 71, 79, 114, 180, 37,
|
||||||
|
183, 91, 54, 187, 86, 243, 126, 197, 224, 83,
|
||||||
|
8, 61, 198, 145, 146, 236, 109, 141, 237, 165,
|
||||||
|
141, 187, 37, 179, 91, 53, 251, 87, 3, 126,
|
||||||
|
129, 224, 96, 72, 40, 54, 158, 150, 232, 110,
|
||||||
|
206, 172, 84, 125, 255, 97, 128, 40, 96, 30,
|
||||||
|
168, 8, 126, 134, 160, 98, 248, 41, 130, 158,
|
||||||
|
225, 168, 72, 126, 182, 160, 118, 248, 38, 194,
|
||||||
|
154, 209, 171, 28, 127, 73, 224, 54, 200, 22,
|
||||||
|
214, 142, 222, 228, 88, 75, 122, 183, 99, 54,
|
||||||
|
169, 214, 254, 222, 192, 88, 80, 58, 188, 19,
|
||||||
|
49, 205, 212, 85, 159, 127, 40, 32, 30, 152,
|
||||||
|
8, 106, 134, 175, 34, 252, 25, 129, 202, 224,
|
||||||
|
87, 8, 62, 134, 144, 98, 236, 41, 141, 222,
|
||||||
|
229, 152, 75, 42, 183, 95, 54, 184, 22, 242,
|
||||||
|
142, 197, 164, 83, 59, 125, 211, 97, 157, 232,
|
||||||
|
105, 142, 174, 228, 124, 75, 97, 247, 104, 70,
|
||||||
|
174, 178, 252, 117, 129, 231, 32, 74, 152, 55,
|
||||||
|
42, 150, 159, 46, 232, 28, 78, 137, 244, 102,
|
||||||
|
199, 106, 210, 175, 29, 188, 9, 177, 198, 244,
|
||||||
|
82, 199, 125, 146, 161, 173, 184, 125, 178, 161,
|
||||||
|
181, 184, 119, 50, 166, 149, 186, 239, 51, 12,
|
||||||
|
21, 197, 207, 19, 20, 13, 207, 69, 148, 51,
|
||||||
|
47, 85, 220, 63, 25, 208, 10, 220, 7, 25,
|
||||||
|
194, 138, 209, 167, 28, 122, 137, 227, 38, 201,
|
||||||
|
218, 214, 219, 30, 219, 72, 91, 118, 187, 102,
|
||||||
|
243, 106, 197, 239, 19, 12, 13, 197, 197, 147,
|
||||||
|
19, 45, 205, 221, 149, 153, 175, 42, 252, 31,
|
||||||
|
1, 200, 0, 86, 128, 62, 224, 16, 72, 12,
|
||||||
|
54, 133, 214, 227, 30, 201, 200, 86, 214, 190,
|
||||||
|
222, 240, 88, 68, 58, 179, 83, 53, 253, 215,
|
||||||
|
1, 158, 128, 104, 96, 46, 168, 28, 126, 137,
|
||||||
|
224, 102, 200, 42, 214, 159, 30, 232, 8, 78,
|
||||||
|
134, 180, 98, 247, 105, 134, 174, 226, 252, 73,
|
||||||
|
129, 246, 224, 70, 200, 50, 214, 149, 158, 239,
|
||||||
|
40, 76, 30, 181, 200, 119, 22, 166, 142, 250,
|
||||||
|
228, 67, 11, 113, 199, 100, 82, 171, 125, 191,
|
||||||
|
97, 176, 40, 116, 30, 167, 72, 122, 182, 163,
|
||||||
|
54, 249, 214, 194, 222, 209, 152, 92, 106, 185,
|
||||||
|
239, 50, 204, 21, 149, 207, 47, 20, 28, 15,
|
||||||
|
73, 196, 54, 211, 86, 221, 254, 217, 128, 90,
|
||||||
|
224, 59, 8, 19, 70, 141, 242, 229, 133, 139,
|
||||||
|
35, 39, 89, 218, 186, 219, 51, 27, 85, 203,
|
||||||
|
127, 23, 96, 14, 168, 4, 126, 131, 96, 97,
|
||||||
|
232, 40, 78, 158, 180, 104, 119, 110, 166, 172,
|
||||||
|
122, 253, 227, 1, 137, 192, 102, 208, 42, 220,
|
||||||
|
31, 25, 200, 10, 214, 135, 30, 226, 136, 73,
|
||||||
|
166, 182, 250, 246, 195, 6, 209, 194, 220, 81,
|
||||||
|
153, 252, 106, 193, 239, 16, 76, 12, 53, 197,
|
||||||
|
215, 19, 30, 141, 200, 101, 150, 171, 46, 255,
|
||||||
|
92, 64, 57, 240, 18, 196, 13, 147, 69, 173,
|
||||||
|
243, 61, 133, 209, 163, 28, 121, 201, 226, 214,
|
||||||
|
201, 158, 214, 232, 94, 206, 184, 84, 114, 191,
|
||||||
|
101, 176, 43, 52, 31, 87, 72, 62, 182, 144,
|
||||||
|
118, 236, 38, 205, 218, 213, 155, 31, 43, 72,
|
||||||
|
31, 118, 136, 38, 230, 154, 202, 235, 23, 15,
|
||||||
|
78, 132, 52, 99, 87, 105, 254, 174, 192, 124,
|
||||||
|
80, 33, 252, 24, 65, 202, 176, 87, 52, 62,
|
||||||
|
151, 80, 110, 188, 44, 113, 221, 228, 89, 139,
|
||||||
|
122, 231, 99, 10, 169, 199, 62, 210, 144, 93,
|
||||||
|
172, 57, 189, 210, 241, 157, 132, 105, 163, 110,
|
||||||
|
249, 236, 66, 205, 241, 149, 132, 111, 35, 108,
|
||||||
|
25, 237, 202, 205, 151, 21, 174, 143, 60, 100,
|
||||||
|
17, 235, 76, 79, 117, 244, 39, 7, 90, 130,
|
||||||
|
187, 33, 179, 88, 117, 250, 167, 3, 58, 129,
|
||||||
|
211, 32, 93, 216, 57, 154, 146, 235, 45, 143,
|
||||||
|
93, 164, 57, 187, 82, 243, 125, 133, 225, 163,
|
||||||
|
8, 121, 198, 162, 210, 249, 157, 130, 233, 161,
|
||||||
|
142, 248, 100, 66, 171, 113, 191, 100, 112, 43,
|
||||||
|
100, 31, 107, 72, 47, 118, 156, 38, 233, 218,
|
||||||
|
206, 219, 20, 91, 79, 123, 116, 35, 103, 89,
|
||||||
|
234, 186, 207, 51, 20, 21, 207, 79, 20, 52,
|
||||||
|
15, 87, 68, 62, 179, 80, 117, 252, 39, 1,
|
||||||
|
218, 128, 91, 32, 59, 88, 19, 122, 141, 227,
|
||||||
|
37, 137, 219, 38, 219, 90, 219, 123, 27, 99,
|
||||||
|
75, 105, 247, 110, 198, 172, 82, 253, 253, 129,
|
||||||
|
129, 160, 96, 120, 40, 34, 158, 153, 168, 106,
|
||||||
|
254, 175, 0, 124, 0, 33, 192, 24, 80, 10,
|
||||||
|
188, 7, 49, 194, 148, 81, 175, 124, 124, 33,
|
||||||
|
225, 216, 72, 90, 182, 187, 54, 243, 86, 197,
|
||||||
|
254, 211, 0, 93, 192, 57, 144, 18, 236, 13,
|
||||||
|
141, 197, 165, 147, 59, 45, 211, 93, 157, 249,
|
||||||
|
169, 130, 254, 225, 128, 72, 96, 54, 168, 22,
|
||||||
|
254, 142, 192, 100, 80, 43, 124, 31, 97, 200,
|
||||||
|
40, 86, 158, 190, 232, 112, 78, 164, 52, 123,
|
||||||
|
87, 99, 126, 169, 224, 126, 200, 32, 86, 152,
|
||||||
|
62, 234, 144, 79, 44, 52, 29, 215, 73, 158,
|
||||||
|
182, 232, 118, 206, 166, 212, 122, 223, 99, 24,
|
||||||
|
41, 202, 158, 215, 40, 94, 158, 184, 104, 114,
|
||||||
|
174, 165, 188, 123, 49, 227, 84, 73, 255, 118,
|
||||||
|
192, 38, 208, 26, 220, 11, 25, 199, 74, 210,
|
||||||
|
183, 29, 182, 137, 182, 230, 246, 202, 198, 215,
|
||||||
|
18, 222, 141, 152, 101, 170, 171, 63, 63, 80,
|
||||||
|
16, 60, 12, 17, 197, 204, 83, 21, 253, 207,
|
||||||
|
1, 148, 0, 111, 64, 44, 48, 29, 212, 9,
|
||||||
|
159, 70, 232, 50, 206, 149, 148, 111, 47, 108,
|
||||||
|
28, 45, 201, 221, 150, 217, 174, 218, 252, 91,
|
||||||
|
1, 251, 64, 67, 112, 49, 228, 20, 75, 79,
|
||||||
|
119, 116, 38, 167, 90, 250, 187, 3, 51, 65,
|
||||||
|
213, 240, 95, 4, 56, 3, 82, 129, 253, 160,
|
||||||
|
65, 184, 48, 114, 148, 37, 175, 91, 60, 59,
|
||||||
|
81, 211, 124, 93, 225, 249, 136, 66, 230, 177,
|
||||||
|
138, 244, 103, 7, 106, 130, 175, 33, 188, 24,
|
||||||
|
113, 202, 164, 87, 59, 126, 147, 96, 109, 232,
|
||||||
|
45, 142, 157, 164, 105, 187, 110, 243, 108, 69,
|
||||||
|
237, 243, 13, 133, 197, 163, 19, 57, 205, 210,
|
||||||
|
213, 157, 159, 41, 168, 30, 254, 136, 64, 102,
|
||||||
|
176, 42, 244, 31, 7, 72, 2, 182, 129, 182,
|
||||||
|
224, 118, 200, 38, 214, 154, 222, 235, 24, 79,
|
||||||
|
74, 180, 55, 55, 86, 150, 190, 238, 240, 76,
|
||||||
|
68, 53, 243, 87, 5, 254, 131, 0, 97, 192,
|
||||||
|
40, 80, 30, 188, 8, 113, 198, 164, 82, 251,
|
||||||
|
125, 131, 97, 161, 232, 120, 78, 162, 180, 121,
|
||||||
|
183, 98, 246, 169, 134, 254, 226, 192, 73, 144,
|
||||||
|
54, 236, 22, 205, 206, 213, 148, 95, 47, 120,
|
||||||
|
28, 34, 137, 217, 166, 218, 250, 219, 3, 27,
|
||||||
|
65, 203, 112, 87, 100, 62, 171, 80, 127, 124,
|
||||||
|
32, 33, 216, 24, 90, 138, 187, 39, 51, 90,
|
||||||
|
149, 251, 47, 3, 92, 1, 249, 192, 66, 208,
|
||||||
|
49, 156, 20, 105, 207, 110, 212, 44, 95, 93,
|
||||||
|
248, 57, 130, 146, 225, 173, 136, 125, 166, 161,
|
||||||
|
186, 248, 115, 2, 165, 193, 187, 16, 115, 76,
|
||||||
|
37, 245, 219, 7, 27, 66, 139, 113, 167, 100,
|
||||||
|
122, 171, 99, 63, 105, 208, 46, 220, 28, 89,
|
||||||
|
201, 250, 214, 195, 30, 209, 200, 92, 86, 185,
|
||||||
|
254, 242, 192, 69, 144, 51, 44, 21, 221, 207,
|
||||||
|
25, 148, 10, 239, 71, 12, 50, 133, 213, 163,
|
||||||
|
31, 57, 200, 18, 214, 141, 158, 229, 168, 75,
|
||||||
|
62, 183, 80, 118, 188, 38, 241, 218, 196, 91,
|
||||||
|
19, 123, 77, 227, 117, 137, 231, 38, 202, 154,
|
||||||
|
215, 43, 30, 159, 72, 104, 54, 174, 150, 252,
|
||||||
|
110, 193, 236, 80, 77, 252, 53, 129, 215, 32,
|
||||||
|
94, 152, 56, 106, 146, 175, 45, 188, 29, 177,
|
||||||
|
201, 180, 86, 247, 126, 198, 160, 82, 248, 61,
|
||||||
|
130, 145, 161, 172, 120, 125, 226, 161, 137, 184,
|
||||||
|
102, 242, 170, 197, 191, 19, 48, 13, 212, 5,
|
||||||
|
159, 67, 40, 49, 222, 148, 88, 111, 122, 172,
|
||||||
|
35, 61, 217, 209, 154, 220, 107, 25, 239, 74,
|
||||||
|
204, 55, 21, 214, 143, 30, 228, 8, 75, 70,
|
||||||
|
183, 114, 246, 165, 134, 251, 34, 195, 89, 145,
|
||||||
|
250, 236, 67, 13, 241, 197, 132, 83, 35, 125,
|
||||||
|
217, 225, 154, 200, 107, 22, 175, 78, 252, 52,
|
||||||
|
65, 215, 112, 94, 164, 56, 123, 82, 163, 125,
|
||||||
|
185, 225, 178, 200, 117, 150, 167, 46, 250, 156,
|
||||||
|
67, 41, 241, 222, 196, 88, 83, 122, 189, 227,
|
||||||
|
49, 137, 212, 102, 223, 106, 216, 47, 26, 156,
|
||||||
|
11, 41, 199, 94, 210, 184, 93, 178, 185, 181,
|
||||||
|
178, 247, 53, 134, 151, 34, 238, 153, 140, 106,
|
||||||
|
229, 239, 11, 12, 7, 69, 194, 179, 17, 181,
|
||||||
|
204, 119, 21, 230, 143, 10, 228, 7, 11, 66,
|
||||||
|
135, 113, 162, 164, 121, 187, 98, 243, 105, 133,
|
||||||
|
238, 227, 12, 73, 197, 246, 211, 6, 221, 194,
|
||||||
|
217, 145, 154, 236, 107, 13, 239, 69, 140, 51,
|
||||||
|
37, 213, 219, 31, 27, 72, 11, 118, 135, 102,
|
||||||
|
226, 170, 201, 191, 22, 240, 14, 196, 4, 83,
|
||||||
|
67, 125, 241, 225, 132, 72, 99, 118, 169, 230,
|
||||||
|
254, 202, 192, 87, 16, 62, 140, 16, 101, 204,
|
||||||
|
43, 21, 223, 79, 24, 52, 10, 151, 71, 46,
|
||||||
|
178, 156, 117, 169, 231, 62, 202, 144, 87, 44,
|
||||||
|
62, 157, 208, 105, 156, 46, 233, 220, 78, 217,
|
||||||
|
244, 90, 199, 123, 18, 163, 77, 185, 245, 178,
|
||||||
|
199, 53, 146, 151, 45, 174, 157, 188, 105, 177,
|
||||||
|
238, 244, 76, 71, 117, 242, 167, 5, 186, 131,
|
||||||
|
51, 33, 213, 216, 95, 26, 184, 11, 50, 135,
|
||||||
|
85, 162, 191, 57, 176, 18, 244, 13, 135, 69,
|
||||||
|
162, 179, 57, 181, 210, 247, 29, 134, 137, 162,
|
||||||
|
230, 249, 138, 194, 231, 17, 138, 140, 103, 37,
|
||||||
|
234, 155, 15, 43, 68, 31, 115, 72, 37, 246,
|
||||||
|
155, 6, 235, 66, 207, 113, 148, 36, 111, 91,
|
||||||
|
108, 59, 109, 211, 109, 157, 237, 169, 141, 190,
|
||||||
|
229, 176, 75, 52, 55, 87, 86, 190, 190, 240,
|
||||||
|
112, 68, 36, 51, 91, 85, 251, 127, 3, 96,
|
||||||
|
1, 232, 0, 78, 128, 52, 96, 23, 104, 14,
|
||||||
|
174, 132, 124, 99, 97, 233, 232, 78, 206, 180,
|
||||||
|
84, 119, 127, 102, 160, 42, 248, 31, 2, 136,
|
||||||
|
1, 166, 128, 122, 224, 35, 8, 25, 198, 138,
|
||||||
|
210, 231, 29, 138, 137, 167, 38, 250, 154, 195,
|
||||||
|
43, 17, 223, 76, 88, 53, 250, 151, 3, 46,
|
||||||
|
129, 220, 96, 89, 232, 58, 206, 147, 20, 109,
|
||||||
|
207, 109, 148, 45, 175, 93, 188, 57, 177, 210,
|
||||||
|
244, 93, 135, 121, 162, 162, 249, 185, 130, 242,
|
||||||
|
225, 133, 136, 99, 38, 169, 218, 254, 219, 0,
|
||||||
|
91, 64, 59, 112, 19, 100, 13, 235, 69, 143,
|
||||||
|
115, 36, 37, 219, 91, 27, 123, 75, 99, 119,
|
||||||
|
105, 230, 174, 202, 252, 87, 1, 254, 128, 64,
|
||||||
|
96, 48, 40, 20, 30, 143, 72, 100, 54, 171,
|
||||||
|
86, 255, 126, 192, 32, 80, 24, 60, 10, 145,
|
||||||
|
199, 44, 82, 157, 253, 169, 129, 190, 224, 112,
|
||||||
|
72, 36, 54, 155, 86, 235, 126, 207, 96, 84,
|
||||||
|
40, 63, 94, 144, 56, 108, 18, 173, 205, 189,
|
||||||
|
149, 177, 175, 52, 124, 23, 97, 206, 168, 84,
|
||||||
|
126, 191, 96, 112, 40, 36, 30, 155, 72, 107,
|
||||||
|
118, 175, 102, 252, 42, 193, 223, 16, 88, 12,
|
||||||
|
58, 133, 211, 35, 29, 217, 201, 154, 214, 235,
|
||||||
|
30, 207, 72, 84, 54, 191, 86, 240, 62, 196,
|
||||||
|
16, 83, 76, 61, 245, 209, 135, 28, 98, 137,
|
||||||
|
233, 166, 206, 250, 212, 67, 31, 113, 200, 36,
|
||||||
|
86, 155, 126, 235, 96, 79, 104, 52, 46, 151,
|
||||||
|
92, 110, 185, 236, 114, 205, 229, 149, 139, 47,
|
||||||
|
39, 92, 26, 185, 203, 50, 215, 85, 158, 191,
|
||||||
|
40, 112, 30, 164, 8, 123, 70, 163, 114, 249,
|
||||||
|
229, 130, 203, 33, 151, 88, 110, 186, 172, 115,
|
||||||
|
61, 229, 209, 139, 28, 103, 73, 234, 182, 207,
|
||||||
|
54, 212, 22, 223, 78, 216, 52, 90, 151, 123,
|
||||||
|
46, 163, 92, 121, 249, 226, 194, 201, 145, 150,
|
||||||
|
236, 110, 205, 236, 85, 141, 255, 37, 128, 27,
|
||||||
|
32, 11, 88, 7, 122, 130, 163, 33, 185, 216,
|
||||||
|
114, 218, 165, 155, 59, 43, 83, 95, 125, 248,
|
||||||
|
33, 130, 152, 97, 170, 168, 127, 62, 160, 16,
|
||||||
|
120, 12, 34, 133, 217, 163, 26, 249, 203, 2,
|
||||||
|
215, 65, 158, 176, 104, 116, 46, 167, 92, 122,
|
||||||
|
185, 227, 50, 201, 213, 150, 223, 46, 216, 28,
|
||||||
|
90, 137, 251, 38, 195, 90, 209, 251, 28, 67,
|
||||||
|
73, 241, 246, 196, 70, 211, 114, 221, 229, 153
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
/* This is the new implementation of P- and Q-parity generation.
|
||||||
|
It needs about the same computing time as the old implementation (both
|
||||||
|
with gcc -O2 on AMD 64 bit). Measurements indicate that about 280 MIPS
|
||||||
|
are needed for 48x CD speed (7.1 MB/s).
|
||||||
|
*/
|
||||||
|
|
||||||
|
static unsigned char burn_rspc_mult(unsigned char a, unsigned char b)
|
||||||
|
{
|
||||||
|
if (a == 0 || b == 0)
|
||||||
|
return 0;
|
||||||
|
/* Optimization of (a == 0 || b == 0) by D. Hugh Redelmeier
|
||||||
|
if((((int)a - 1) | ((int)b - 1)) < 0)
|
||||||
|
return 0;
|
||||||
|
*/
|
||||||
|
|
||||||
|
return gfpow[gflog[a] + gflog[b]];
|
||||||
|
/* % 255 not necessary because gfpow is unrolled up to index 510 */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Divide by polynomial 0x03. Derived from burn_rspc_div() and using the
|
||||||
|
unrolled size of the gfpow[] array.
|
||||||
|
*/
|
||||||
|
static unsigned char burn_rspc_div_3(unsigned char a)
|
||||||
|
{
|
||||||
|
if (a == 0)
|
||||||
|
return 0;
|
||||||
|
return gfpow[230 + gflog[a]];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void burn_rspc_p0p1(unsigned char *sector, int col,
|
||||||
|
unsigned char *p0_lsb, unsigned char *p0_msb,
|
||||||
|
unsigned char *p1_lsb, unsigned char *p1_msb)
|
||||||
|
{
|
||||||
|
unsigned char *start, b;
|
||||||
|
unsigned int i, sum_v_lsb = 0, sum_v_msb = 0;
|
||||||
|
unsigned int hxv_lsb = 0, hxv_msb = 0;
|
||||||
|
|
||||||
|
start = sector + 12 + 2 * col;
|
||||||
|
for(i = 0; i < 24; i++) {
|
||||||
|
b = *start;
|
||||||
|
sum_v_lsb ^= b;
|
||||||
|
|
||||||
|
#ifdef Libburn_use_h_matriceS
|
||||||
|
hxv_lsb ^= burn_rspc_mult(b, h26[i]);
|
||||||
|
#else
|
||||||
|
hxv_lsb ^= burn_rspc_mult(b, gfpow[25 - i]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
b = *(start + 1);
|
||||||
|
sum_v_msb ^= b;
|
||||||
|
|
||||||
|
#ifdef Libburn_use_h_matriceS
|
||||||
|
hxv_msb ^= burn_rspc_mult(b, h26[i]);
|
||||||
|
#else
|
||||||
|
hxv_msb ^= burn_rspc_mult(b, gfpow[25 - i]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
start += 86;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 3 = gfpow[1] ^ gfpow[0] , 2 = gfpow[1] */
|
||||||
|
*p0_lsb = burn_rspc_div_3(burn_rspc_mult(2, sum_v_lsb) ^ hxv_lsb);
|
||||||
|
*p0_msb = burn_rspc_div_3(burn_rspc_mult(2, sum_v_msb) ^ hxv_msb);
|
||||||
|
*p1_lsb = sum_v_lsb ^ *p0_lsb;
|
||||||
|
*p1_msb = sum_v_msb ^ *p0_msb;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void burn_rspc_parity_p(unsigned char *sector)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
unsigned char p0_lsb, p0_msb, p1_lsb, p1_msb;
|
||||||
|
|
||||||
|
/* Loop over P columns */
|
||||||
|
for(i = 0; i < 43; i++) {
|
||||||
|
burn_rspc_p0p1(sector, i, &p0_lsb, &p0_msb, &p1_lsb, &p1_msb);
|
||||||
|
sector[2162 + 2 * i] = p0_lsb;
|
||||||
|
sector[2162 + 2 * i + 1] = p0_msb;
|
||||||
|
sector[2076 + 2 * i] = p1_lsb;
|
||||||
|
sector[2076 + 2 * i + 1] = p1_msb;
|
||||||
|
|
||||||
|
#ifdef Libburn_with_lec_generatoR
|
||||||
|
if(verbous) {
|
||||||
|
printf("p %2d : %2.2X %2.2X ", i,
|
||||||
|
(unsigned int) p0_lsb, (unsigned int) p0_msb);
|
||||||
|
printf("%2.2X %2.2X ",
|
||||||
|
(unsigned int) p1_lsb, (unsigned int) p1_msb);
|
||||||
|
printf("-> %d,%d\n", 2162 + 2 * i, 2076 + 2 * i);
|
||||||
|
}
|
||||||
|
#endif /* Libburn_with_lec_generatoR */
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void burn_rspc_q0q1(unsigned char *sector, int diag,
|
||||||
|
unsigned char *q0_lsb, unsigned char *q0_msb,
|
||||||
|
unsigned char *q1_lsb, unsigned char *q1_msb)
|
||||||
|
{
|
||||||
|
unsigned char *start, b;
|
||||||
|
unsigned int i, idx, sum_v_lsb = 0, sum_v_msb = 0;
|
||||||
|
unsigned int hxv_lsb = 0, hxv_msb = 0;
|
||||||
|
|
||||||
|
start = sector + 12;
|
||||||
|
idx = 2 * 43 * diag;
|
||||||
|
for(i = 0; i < 43; i++) {
|
||||||
|
if (idx >= 2236)
|
||||||
|
idx -= 2236;
|
||||||
|
b = start[idx];
|
||||||
|
sum_v_lsb ^= b;
|
||||||
|
|
||||||
|
#ifdef Libburn_use_h_matriceS
|
||||||
|
hxv_lsb ^= burn_rspc_mult(b, h45[i]);
|
||||||
|
#else
|
||||||
|
hxv_lsb ^= burn_rspc_mult(b, gfpow[44 - i]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
b = start[idx + 1];
|
||||||
|
sum_v_msb ^= b;
|
||||||
|
|
||||||
|
#ifdef Libburn_use_h_matriceS
|
||||||
|
hxv_msb ^= burn_rspc_mult(b, h45[i]);
|
||||||
|
#else
|
||||||
|
hxv_msb ^= burn_rspc_mult(b, gfpow[44 - i]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
idx += 88;
|
||||||
|
}
|
||||||
|
/* 3 = gfpow[1] ^ gfpow[0] , 2 = gfpow[1] */
|
||||||
|
*q0_lsb = burn_rspc_div_3(burn_rspc_mult(2, sum_v_lsb) ^ hxv_lsb);
|
||||||
|
*q0_msb = burn_rspc_div_3(burn_rspc_mult(2, sum_v_msb) ^ hxv_msb);
|
||||||
|
*q1_lsb = sum_v_lsb ^ *q0_lsb;
|
||||||
|
*q1_msb = sum_v_msb ^ *q0_msb;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void burn_rspc_parity_q(unsigned char *sector)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
unsigned char q0_lsb, q0_msb, q1_lsb, q1_msb;
|
||||||
|
|
||||||
|
/* Loop over Q diagonals */
|
||||||
|
for(i = 0; i < 26; i++) {
|
||||||
|
burn_rspc_q0q1(sector, i, &q0_lsb, &q0_msb, &q1_lsb, &q1_msb);
|
||||||
|
sector[2300 + 2 * i] = q0_lsb;
|
||||||
|
sector[2300 + 2 * i + 1] = q0_msb;
|
||||||
|
sector[2248 + 2 * i] = q1_lsb;
|
||||||
|
sector[2248 + 2 * i + 1] = q1_msb;
|
||||||
|
|
||||||
|
#ifdef Libburn_with_lec_generatoR
|
||||||
|
if(verbous) {
|
||||||
|
printf("q %2d : %2.2X %2.2X ", i,
|
||||||
|
(unsigned int) q0_lsb, (unsigned int) q0_msb);
|
||||||
|
printf("%2.2X %2.2X ",
|
||||||
|
(unsigned int) q1_lsb, (unsigned int) q1_msb);
|
||||||
|
printf("-> %d,%d\n", 2300 + 2 * i, 2248 + 2 * i);
|
||||||
|
}
|
||||||
|
#endif /* Libburn_with_lec_generatoR */
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
/* The new implementation of the ECMA-130 Annex B scrambler.
|
||||||
|
It is totally unoptimized. One should make use of larger word operations.
|
||||||
|
Measurements indicate that about 50 MIPS are needed for 48x CD speed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void burn_ecma130_scramble(unsigned char *sector)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
unsigned char *s;
|
||||||
|
|
||||||
|
s = sector + 12;
|
||||||
|
for (i = 0; i < 2340; i++)
|
||||||
|
s[i] ^= ecma_130_annex_b[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
/* The following code is not needed for libburn but rather documents the
|
||||||
|
origin of the tables above. In libburn it will not be compiled.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef Libburn_with_lec_generatoR
|
||||||
|
|
||||||
|
|
||||||
|
/* This function produced the content of gflog[] and gfpow[]
|
||||||
|
*/
|
||||||
|
static int burn_rspc_setup_tables(void)
|
||||||
|
{
|
||||||
|
unsigned int b, l;
|
||||||
|
|
||||||
|
memset(gflog, 0, sizeof(gflog));
|
||||||
|
memset(gfpow, 0, sizeof(gfpow));
|
||||||
|
b = 1;
|
||||||
|
for (l = 0; l < 255; l++) {
|
||||||
|
gfpow[l] = (unsigned char) b;
|
||||||
|
gflog[b] = (unsigned char) l;
|
||||||
|
b = b << 1;
|
||||||
|
if (b & 256)
|
||||||
|
b = b ^ 0x11d;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* This function printed the content of gflog[] and gfpow[] as C code
|
||||||
|
and compared the content with the tables of the old implementation.
|
||||||
|
h26[] and h45[] are reverted order copies of gfpow[]
|
||||||
|
*/
|
||||||
|
static int burn_rspc_print_tables(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
printf("static unsigned char gfpow[255] = {");
|
||||||
|
printf("\n\t");
|
||||||
|
for(i= 0; i < 255; i++) {
|
||||||
|
printf("%3u, ", gfpow[i]);
|
||||||
|
|
||||||
|
#ifdef Libburn_with_old_lec_comparisoN
|
||||||
|
if(gfpow[i] != gf8_ilog[i])
|
||||||
|
fprintf(stderr, "*** ILOG %d : %d != %d ***\n", i, gfpow[i], gf8_ilog[i]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if((i % 10) == 9)
|
||||||
|
printf("\n\t");
|
||||||
|
}
|
||||||
|
printf("\n};\n\n");
|
||||||
|
|
||||||
|
printf("static unsigned char gflog[256] = {");
|
||||||
|
printf("\n\t");
|
||||||
|
for(i= 0; i < 256; i++) {
|
||||||
|
printf(" %3u,", gflog[i]);
|
||||||
|
|
||||||
|
#ifdef Libburn_with_old_lec_comparisoN
|
||||||
|
if(gflog[i] != gf8_log[i])
|
||||||
|
fprintf(stderr, "*** LOG %d : %d != %d ***\n", i, gflog[i], gf8_log[i]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if((i % 10) == 9)
|
||||||
|
printf("\n\t");
|
||||||
|
}
|
||||||
|
printf("\n};\n\n");
|
||||||
|
|
||||||
|
printf("static unsigned char h26[26] = {");
|
||||||
|
printf("\n\t");
|
||||||
|
for(i= 0; i < 26; i++) {
|
||||||
|
printf(" %3u,", gfpow[25 - i]);
|
||||||
|
if((i % 10) == 9)
|
||||||
|
printf("\n\t");
|
||||||
|
}
|
||||||
|
printf("\n};\n\n");
|
||||||
|
|
||||||
|
printf("static unsigned char h45[45] = {");
|
||||||
|
printf("\n\t");
|
||||||
|
for(i= 0; i < 45; i++) {
|
||||||
|
printf(" %3u,",gfpow[44 - i]);
|
||||||
|
if((i % 10) == 9)
|
||||||
|
printf("\n\t");
|
||||||
|
}
|
||||||
|
printf("\n};\n\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* This code was used to generate the content of array ecma_130_annex_b[].
|
||||||
|
*/
|
||||||
|
static unsigned short ecma_130_fsr = 1;
|
||||||
|
|
||||||
|
static int next_bit(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = ecma_130_fsr & 1;
|
||||||
|
ecma_130_fsr = (ecma_130_fsr >> 1) & 0x3fff;
|
||||||
|
if (ret ^ (ecma_130_fsr & 1))
|
||||||
|
ecma_130_fsr |= 0x4000;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int print_ecma_130_scrambler(void)
|
||||||
|
{
|
||||||
|
int i, j, b;
|
||||||
|
|
||||||
|
ecma_130_fsr = 1;
|
||||||
|
printf("static unsigned char ecma_130_annex_b[2340] = {");
|
||||||
|
printf("\n\t");
|
||||||
|
for (i = 0; i < 2340; i++) {
|
||||||
|
b = 0;
|
||||||
|
for (j = 0; j < 8; j++)
|
||||||
|
b |= next_bit() << j;
|
||||||
|
|
||||||
|
printf("%3u, ", b);
|
||||||
|
if ((i % 10) == 9)
|
||||||
|
printf("\n\t");
|
||||||
|
}
|
||||||
|
printf("\n};\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef Libburn_with_general_rspc_diV
|
||||||
|
|
||||||
|
/* This is a general polynomial division function.
|
||||||
|
burn_rspc_div_3() has been derived from this by setting b to constant 3.
|
||||||
|
*/
|
||||||
|
static unsigned char burn_rspc_div(unsigned char a, unsigned char b)
|
||||||
|
{
|
||||||
|
int d;
|
||||||
|
|
||||||
|
if (a == 0)
|
||||||
|
return 0;
|
||||||
|
if (b == 0)
|
||||||
|
return -1;
|
||||||
|
d = gflog[a] - gflog[b];
|
||||||
|
if (d < 0)
|
||||||
|
d += 255;
|
||||||
|
return gfpow[d];
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* Libburn_with_general_rspc_diV */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* Libburn_with_lec_generatoR */
|
||||||
|
|
23
libburn/ecma130ab.h
Normal file
23
libburn/ecma130ab.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
|
||||||
|
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||||
|
|
||||||
|
/* ts A91016 : libburn/ecma130ab.h is the replacement for old libburn/lec.h
|
||||||
|
|
||||||
|
Copyright 2009, Thomas Schmitt <scdbackup@gmx.net>, libburnia-project.org
|
||||||
|
|
||||||
|
This code module implements the computations prescribed in ECMA-130 Annex A
|
||||||
|
and B. For explanations of the underlying mathematics see ecma130ab.c .
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef Libburn_ecma130ab_includeD
|
||||||
|
#define Libburn_ecma130ab_includeD 1
|
||||||
|
|
||||||
|
void burn_rspc_parity_p(unsigned char *sector);
|
||||||
|
|
||||||
|
void burn_rspc_parity_q(unsigned char *sector);
|
||||||
|
|
||||||
|
void burn_ecma130_scramble(unsigned char *sector);
|
||||||
|
|
||||||
|
#endif /* ! Libburn_ecma130ab_includeD */
|
||||||
|
|
189
libburn/file.c
189
libburn/file.c
@ -1,5 +1,6 @@
|
|||||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||||
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -27,8 +28,6 @@ an unreadable disc */
|
|||||||
/* This is a generic OS oriented function wrapper which compensates
|
/* This is a generic OS oriented function wrapper which compensates
|
||||||
shortcommings of read() in respect to a guaranteed amount of return data.
|
shortcommings of read() in respect to a guaranteed amount of return data.
|
||||||
See man 2 read , paragraph "RETURN VALUE".
|
See man 2 read , paragraph "RETURN VALUE".
|
||||||
Possibly libburn/file.c is not the right storage location for this.
|
|
||||||
To make it ready for a move, this function is not declared static.
|
|
||||||
*/
|
*/
|
||||||
static int read_full_buffer(int fd, unsigned char *buffer, int size)
|
static int read_full_buffer(int fd, unsigned char *buffer, int size)
|
||||||
{
|
{
|
||||||
@ -211,7 +210,7 @@ static int fifo_read(struct burn_source *source,
|
|||||||
int size)
|
int size)
|
||||||
{
|
{
|
||||||
struct burn_source_fifo *fs = source->data;
|
struct burn_source_fifo *fs = source->data;
|
||||||
int ret, todo, rpos, bufsize, diff;
|
int ret, todo, rpos, bufsize, diff, counted = 0;
|
||||||
|
|
||||||
if (fs->end_of_consumption) {
|
if (fs->end_of_consumption) {
|
||||||
/* ??? msg: reading has been ended already */;
|
/* ??? msg: reading has been ended already */;
|
||||||
@ -256,6 +255,9 @@ static int fifo_read(struct burn_source *source,
|
|||||||
"Forwarded input error ends output", 0, 0);
|
"Forwarded input error ends output", 0, 0);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (!counted)
|
||||||
|
fs->empty_counter++;
|
||||||
|
counted = 1;
|
||||||
fifo_sleep(0);
|
fifo_sleep(0);
|
||||||
}
|
}
|
||||||
diff = fs->buf_writepos - rpos; /* read volatile only once */
|
diff = fs->buf_writepos - rpos; /* read volatile only once */
|
||||||
@ -285,6 +287,7 @@ static int fifo_read(struct burn_source *source,
|
|||||||
(size - todo), fs->buf_readpos, (double) fs->out_counter);
|
(size - todo), fs->buf_readpos, (double) fs->out_counter);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
fs->get_counter++;
|
||||||
return (size - todo);
|
return (size - todo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,8 +315,10 @@ static void fifo_free(struct burn_source *source)
|
|||||||
burn_fifo_abort(fs, 0);
|
burn_fifo_abort(fs, 0);
|
||||||
if (fs->inp != NULL)
|
if (fs->inp != NULL)
|
||||||
burn_source_free(fs->inp);
|
burn_source_free(fs->inp);
|
||||||
|
|
||||||
if (fs->buf != NULL)
|
if (fs->buf != NULL)
|
||||||
free(fs->buf);
|
burn_os_free_buffer(fs->buf,
|
||||||
|
((size_t) fs->chunksize) * (size_t) fs->chunks, 0);
|
||||||
free((char *) fs);
|
free((char *) fs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -321,7 +326,8 @@ static void fifo_free(struct burn_source *source)
|
|||||||
int burn_fifo_source_shoveller(struct burn_source *source, int flag)
|
int burn_fifo_source_shoveller(struct burn_source *source, int flag)
|
||||||
{
|
{
|
||||||
struct burn_source_fifo *fs = source->data;
|
struct burn_source_fifo *fs = source->data;
|
||||||
int ret, bufsize, diff, wpos, rpos, trans_end, free_bytes;
|
int ret, bufsize, diff, wpos, rpos, trans_end, free_bytes, fill;
|
||||||
|
int counted;
|
||||||
char *bufpt;
|
char *bufpt;
|
||||||
pthread_t thread_handle_storage;
|
pthread_t thread_handle_storage;
|
||||||
|
|
||||||
@ -335,6 +341,7 @@ int burn_fifo_source_shoveller(struct burn_source *source, int flag)
|
|||||||
|
|
||||||
/* wait for enough buffer space available */
|
/* wait for enough buffer space available */
|
||||||
wpos = fs->buf_writepos;
|
wpos = fs->buf_writepos;
|
||||||
|
counted = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
rpos = fs->buf_readpos;
|
rpos = fs->buf_readpos;
|
||||||
diff = rpos - wpos;
|
diff = rpos - wpos;
|
||||||
@ -345,18 +352,28 @@ int burn_fifo_source_shoveller(struct burn_source *source, int flag)
|
|||||||
free_bytes = diff - 1;
|
free_bytes = diff - 1;
|
||||||
else {
|
else {
|
||||||
free_bytes = (bufsize - wpos) + rpos - 1;
|
free_bytes = (bufsize - wpos) + rpos - 1;
|
||||||
if (bufsize - wpos < fs->chunksize)
|
if (bufsize - wpos < fs->inp_read_size)
|
||||||
trans_end = 1;
|
trans_end = 1;
|
||||||
}
|
}
|
||||||
if (free_bytes >= fs->chunksize)
|
if (free_bytes >= fs->inp_read_size)
|
||||||
break;
|
break;
|
||||||
|
if (!counted)
|
||||||
|
fs->full_counter++;
|
||||||
|
counted = 1;
|
||||||
fifo_sleep(0);
|
fifo_sleep(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fill = bufsize - free_bytes - 1;
|
||||||
|
if (fill < fs->total_min_fill)
|
||||||
|
fs->total_min_fill = fill;
|
||||||
|
if (fill < fs->interval_min_fill)
|
||||||
|
fs->interval_min_fill = fill;
|
||||||
|
|
||||||
/* prepare the receiving memory */
|
/* prepare the receiving memory */
|
||||||
bufpt = fs->buf + wpos;
|
bufpt = fs->buf + wpos;
|
||||||
if (trans_end) {
|
if (trans_end) {
|
||||||
bufpt = calloc(fs->chunksize, 1);
|
bufpt = burn_os_alloc_buffer(
|
||||||
|
(size_t) fs->inp_read_size, 0);
|
||||||
if (bufpt == NULL) {
|
if (bufpt == NULL) {
|
||||||
libdax_msgs_submit(libdax_messenger, -1,
|
libdax_msgs_submit(libdax_messenger, -1,
|
||||||
0x00000003,
|
0x00000003,
|
||||||
@ -370,15 +387,13 @@ int burn_fifo_source_shoveller(struct burn_source *source, int flag)
|
|||||||
/* Obtain next chunk */
|
/* Obtain next chunk */
|
||||||
if (fs->inp->read != NULL)
|
if (fs->inp->read != NULL)
|
||||||
ret = fs->inp->read(fs->inp,
|
ret = fs->inp->read(fs->inp,
|
||||||
(unsigned char *) bufpt, fs->chunksize);
|
(unsigned char *) bufpt, fs->inp_read_size);
|
||||||
else
|
else
|
||||||
ret = fs->inp->read_xt( fs->inp,
|
ret = fs->inp->read_xt( fs->inp,
|
||||||
(unsigned char *) bufpt, fs->chunksize);
|
(unsigned char *) bufpt, fs->inp_read_size);
|
||||||
if (ret > 0)
|
if (ret == 0)
|
||||||
fs->in_counter += ret;
|
|
||||||
else if (ret == 0)
|
|
||||||
break; /* EOF */
|
break; /* EOF */
|
||||||
else {
|
else if (ret < 0) {
|
||||||
libdax_msgs_submit(libdax_messenger, -1, 0x00020153,
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020153,
|
||||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
"Read error on fifo input", errno, 0);
|
"Read error on fifo input", errno, 0);
|
||||||
@ -387,17 +402,21 @@ int burn_fifo_source_shoveller(struct burn_source *source, int flag)
|
|||||||
fs->input_error = EIO;
|
fs->input_error = EIO;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
fs->in_counter += ret;
|
||||||
|
fs->put_counter++;
|
||||||
|
|
||||||
/* activate read chunk */
|
/* activate read chunk */
|
||||||
if (ret > fs->chunksize) /* beware of ill custom burn_source */
|
if (ret > fs->inp_read_size)
|
||||||
ret = fs->chunksize;
|
/* beware of ill custom burn_source */
|
||||||
|
ret = fs->inp_read_size;
|
||||||
if (trans_end) {
|
if (trans_end) {
|
||||||
/* copy to end of buffer */
|
/* copy to end of buffer */
|
||||||
memcpy(fs->buf + wpos, bufpt, bufsize - wpos);
|
memcpy(fs->buf + wpos, bufpt, bufsize - wpos);
|
||||||
/* copy to start of buffer */
|
/* copy to start of buffer */
|
||||||
memcpy(fs->buf, bufpt + (bufsize - wpos),
|
memcpy(fs->buf, bufpt + (bufsize - wpos),
|
||||||
fs->chunksize - (bufsize - wpos));
|
fs->inp_read_size - (bufsize - wpos));
|
||||||
free(bufpt);
|
burn_os_free_buffer(bufpt, (size_t) fs->inp_read_size,
|
||||||
|
0);
|
||||||
if (ret >= bufsize - wpos)
|
if (ret >= bufsize - wpos)
|
||||||
fs->buf_writepos = ret - (bufsize - wpos);
|
fs->buf_writepos = ret - (bufsize - wpos);
|
||||||
else
|
else
|
||||||
@ -433,7 +452,9 @@ int burn_fifo_source_shoveller(struct burn_source *source, int flag)
|
|||||||
So in both cases the consumer is aware that reading is futile
|
So in both cases the consumer is aware that reading is futile
|
||||||
or even fatal.
|
or even fatal.
|
||||||
*/
|
*/
|
||||||
free(fs->buf); /* Give up fifo buffer. Next fifo might start soon. */
|
if(fs->buf != NULL)
|
||||||
|
burn_os_free_buffer(fs->buf,
|
||||||
|
((size_t) fs->chunksize) * (size_t) fs->chunks, 0);
|
||||||
fs->buf = NULL;
|
fs->buf = NULL;
|
||||||
|
|
||||||
fs->thread_handle= NULL;
|
fs->thread_handle= NULL;
|
||||||
@ -450,7 +471,9 @@ int burn_fifo_cancel(struct burn_source *source)
|
|||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@param flag bit0= allow larger read chunks
|
||||||
|
*/
|
||||||
struct burn_source *burn_fifo_source_new(struct burn_source *inp,
|
struct burn_source *burn_fifo_source_new(struct burn_source *inp,
|
||||||
int chunksize, int chunks, int flag)
|
int chunksize, int chunks, int flag)
|
||||||
{
|
{
|
||||||
@ -477,6 +500,10 @@ struct burn_source *burn_fifo_source_new(struct burn_source *inp,
|
|||||||
fs->thread_pid = 0;
|
fs->thread_pid = 0;
|
||||||
fs->thread_is_valid = 0;
|
fs->thread_is_valid = 0;
|
||||||
fs->inp = NULL; /* set later */
|
fs->inp = NULL; /* set later */
|
||||||
|
if (flag & 1)
|
||||||
|
fs->inp_read_size = 32 * 1024;
|
||||||
|
else
|
||||||
|
fs->inp_read_size = chunksize;
|
||||||
fs->chunksize = chunksize;
|
fs->chunksize = chunksize;
|
||||||
fs->chunks = chunks;
|
fs->chunks = chunks;
|
||||||
fs->buf = NULL;
|
fs->buf = NULL;
|
||||||
@ -485,6 +512,9 @@ struct burn_source *burn_fifo_source_new(struct burn_source *inp,
|
|||||||
fs->input_error = 0;
|
fs->input_error = 0;
|
||||||
fs->end_of_consumption = 0;
|
fs->end_of_consumption = 0;
|
||||||
fs->in_counter = fs->out_counter = 0;
|
fs->in_counter = fs->out_counter = 0;
|
||||||
|
fs->total_min_fill = fs->interval_min_fill = 0;
|
||||||
|
fs->put_counter = fs->get_counter = 0;
|
||||||
|
fs->empty_counter = fs->full_counter = 0;
|
||||||
|
|
||||||
src = burn_source_new();
|
src = burn_source_new();
|
||||||
if (src == NULL) {
|
if (src == NULL) {
|
||||||
@ -550,34 +580,89 @@ int burn_fifo_inquire_status(struct burn_source *source,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int burn_fifo_peek_data(struct burn_source *source, char *buf, int bufsize,
|
/* ts A91125 : API */
|
||||||
|
void burn_fifo_get_statistics(struct burn_source *source,
|
||||||
|
int *total_min_fill, int *interval_min_fill,
|
||||||
|
int *put_counter, int *get_counter,
|
||||||
|
int *empty_counter, int *full_counter)
|
||||||
|
{
|
||||||
|
struct burn_source_fifo *fs = source->data;
|
||||||
|
|
||||||
|
*total_min_fill = fs->total_min_fill;
|
||||||
|
*interval_min_fill = fs->interval_min_fill;
|
||||||
|
*put_counter = fs->put_counter;
|
||||||
|
*get_counter = fs->get_counter;
|
||||||
|
*empty_counter = fs->empty_counter;
|
||||||
|
*full_counter = fs->full_counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ts A91125 : API */
|
||||||
|
void burn_fifo_next_interval(struct burn_source *source,
|
||||||
|
int *interval_min_fill)
|
||||||
|
{
|
||||||
|
struct burn_source_fifo *fs = source->data;
|
||||||
|
int size, free_bytes, ret;
|
||||||
|
char *status_text;
|
||||||
|
|
||||||
|
*interval_min_fill = fs->interval_min_fill;
|
||||||
|
ret = burn_fifo_inquire_status(source,
|
||||||
|
&size, &free_bytes, &status_text);
|
||||||
|
fs->interval_min_fill = size - free_bytes - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* @param flag bit0= do not copy to buf but only wait until the fifo has read
|
||||||
|
bufsize or input ended.
|
||||||
|
The same happens if buf is NULL.
|
||||||
|
bit1= fill to max fifo size
|
||||||
|
*/
|
||||||
|
int burn_fifo_fill_data(struct burn_source *source, char *buf, int bufsize,
|
||||||
int flag)
|
int flag)
|
||||||
{
|
{
|
||||||
int size, free_bytes, ret, wait_count= 0;
|
int size, free_bytes, ret, wait_count= 0;
|
||||||
char *status_text;
|
char *status_text;
|
||||||
struct burn_source_fifo *fs = source->data;
|
struct burn_source_fifo *fs = source->data;
|
||||||
|
|
||||||
|
if (buf == NULL)
|
||||||
|
flag |= 1;
|
||||||
|
|
||||||
/* Eventually start fifo thread by reading 0 bytes */
|
/* Eventually start fifo thread by reading 0 bytes */
|
||||||
ret = fifo_read(source, (unsigned char *) NULL, 0);
|
ret = fifo_read(source, (unsigned char *) NULL, 0);
|
||||||
if (ret<0)
|
if (ret<0)
|
||||||
return 0;
|
{ret = 0; goto ex;}
|
||||||
|
|
||||||
/* wait for at least bufsize bytes being ready */
|
/* wait for at least bufsize bytes being ready */
|
||||||
while (1) {
|
while (1) {
|
||||||
ret= burn_fifo_inquire_status(source,
|
ret= burn_fifo_inquire_status(source,
|
||||||
&size, &free_bytes, &status_text);
|
&size, &free_bytes, &status_text);
|
||||||
if (size < bufsize) {
|
if (flag & 2) {
|
||||||
libdax_msgs_submit(libdax_messenger, -1, 0x0002015c,
|
bufsize = size - (size % fs->inp_read_size) -
|
||||||
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
fs->inp_read_size;
|
||||||
"Fifo size is smaller than desired peek buffer", 0, 0);
|
if (bufsize <= 0)
|
||||||
return -1;
|
{ret = 0; goto ex;}
|
||||||
|
}
|
||||||
|
if (size - fs->inp_read_size < bufsize) {
|
||||||
|
if (flag & 1) {
|
||||||
|
bufsize = size - (size % fs->inp_read_size) -
|
||||||
|
fs->inp_read_size;
|
||||||
|
if (bufsize <= 0)
|
||||||
|
{ret = 0; goto ex;}
|
||||||
|
} else {
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1,
|
||||||
|
0x0002015c, LIBDAX_MSGS_SEV_FAILURE,
|
||||||
|
LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
"Fifo size too small for desired peek buffer",
|
||||||
|
0, 0);
|
||||||
|
{ret = -1; goto ex;}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (fs->out_counter > 0 || (ret & 4) || fs->buf == NULL) {
|
if (fs->out_counter > 0 || (ret & 4) || fs->buf == NULL) {
|
||||||
libdax_msgs_submit(libdax_messenger, -1, 0x0002015e,
|
libdax_msgs_submit(libdax_messenger, -1, 0x0002015e,
|
||||||
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
"Fifo is already under consumption when peeking is desired",
|
"Fifo is already under consumption when peeking is desired",
|
||||||
0, 0);
|
0, 0);
|
||||||
return -1;
|
{ret = -1; goto ex;}
|
||||||
}
|
}
|
||||||
if(size - free_bytes >= bufsize) {
|
if(size - free_bytes >= bufsize) {
|
||||||
|
|
||||||
@ -586,17 +671,33 @@ int burn_fifo_peek_data(struct burn_source *source, char *buf, int bufsize,
|
|||||||
"libburn_DEBUG: after waiting cycle %d : fifo %s , %d bytes\n",
|
"libburn_DEBUG: after waiting cycle %d : fifo %s , %d bytes\n",
|
||||||
wait_count, status_text, size - free_bytes);
|
wait_count, status_text, size - free_bytes);
|
||||||
*/
|
*/
|
||||||
|
if(!(flag & 1))
|
||||||
memcpy(buf, fs->buf, bufsize);
|
memcpy(buf, fs->buf, bufsize);
|
||||||
return 1;
|
{ret = 1; goto ex;}
|
||||||
}
|
}
|
||||||
if (ret&2) { /* input has ended, not enough data arrived */
|
|
||||||
|
if (ret & 2) {
|
||||||
|
/* input has ended, not enough data arrived */
|
||||||
|
if (flag & 1)
|
||||||
|
{ret = 0; goto ex;}
|
||||||
libdax_msgs_submit(libdax_messenger, -1, 0x0002015d,
|
libdax_msgs_submit(libdax_messenger, -1, 0x0002015d,
|
||||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
"Fifo input ended short of desired peek buffer size",
|
"Fifo input ended short of desired peek buffer size",
|
||||||
0, 0);
|
0, 0);
|
||||||
return 0;
|
{ret = 0; goto ex;}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (free_bytes < fs->inp_read_size) {
|
||||||
|
/* Usable fifo size filled, not enough data arrived */
|
||||||
|
if (flag & 1)
|
||||||
|
{ret = 0; goto ex;}
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020174,
|
||||||
|
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
"Fifo alignment does not allow desired read size",
|
||||||
|
0, 0);
|
||||||
|
{ret = 0; goto ex;}
|
||||||
|
}
|
||||||
|
|
||||||
usleep(100000);
|
usleep(100000);
|
||||||
wait_count++;
|
wait_count++;
|
||||||
|
|
||||||
@ -608,5 +709,25 @@ int burn_fifo_peek_data(struct burn_source *source, char *buf, int bufsize,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
}
|
}
|
||||||
return(0);
|
ret = 0;
|
||||||
|
ex:;
|
||||||
|
fs->total_min_fill = fs->interval_min_fill = fs->buf_writepos;
|
||||||
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ts A80713 : API */
|
||||||
|
int burn_fifo_peek_data(struct burn_source *source, char *buf, int bufsize,
|
||||||
|
int flag)
|
||||||
|
{
|
||||||
|
return burn_fifo_fill_data(source, buf, bufsize, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ts A91125 : API */
|
||||||
|
int burn_fifo_fill(struct burn_source *source, int bufsize, int flag)
|
||||||
|
{
|
||||||
|
return burn_fifo_fill_data(source, NULL, bufsize,
|
||||||
|
1 | ((flag & 1) << 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@ struct burn_source_fifo {
|
|||||||
|
|
||||||
/* the burn_source for which this fifo is acting as proxy */
|
/* the burn_source for which this fifo is acting as proxy */
|
||||||
struct burn_source *inp;
|
struct burn_source *inp;
|
||||||
|
int inp_read_size;
|
||||||
|
|
||||||
/* <<< up to now it was only a pipe. This is on its way out. */
|
/* <<< up to now it was only a pipe. This is on its way out. */
|
||||||
int outlet[2];
|
int outlet[2];
|
||||||
@ -51,6 +52,14 @@ struct burn_source_fifo {
|
|||||||
|
|
||||||
off_t in_counter;
|
off_t in_counter;
|
||||||
off_t out_counter;
|
off_t out_counter;
|
||||||
|
|
||||||
|
int total_min_fill;
|
||||||
|
int interval_min_fill;
|
||||||
|
int put_counter;
|
||||||
|
int get_counter;
|
||||||
|
int empty_counter;
|
||||||
|
int full_counter;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,6 +59,12 @@ int burn_sg_open_o_nonblock = 1;
|
|||||||
to unconditional abort of the process */
|
to unconditional abort of the process */
|
||||||
int burn_sg_open_abort_busy = 0;
|
int burn_sg_open_abort_busy = 0;
|
||||||
|
|
||||||
|
|
||||||
|
/* The message returned from sg_id_string() and/or sg_initialize()
|
||||||
|
*/
|
||||||
|
static char sg_initialize_msg[1024] = {""};
|
||||||
|
|
||||||
|
|
||||||
/* ts A61002 */
|
/* ts A61002 */
|
||||||
|
|
||||||
#include "cleanup.h"
|
#include "cleanup.h"
|
||||||
@ -75,6 +81,13 @@ burn_abort_handler_t burn_global_signal_handler = NULL;
|
|||||||
/* ts A70223 : wether implemented untested profiles are supported */
|
/* ts A70223 : wether implemented untested profiles are supported */
|
||||||
int burn_support_untested_profiles = 0;
|
int burn_support_untested_profiles = 0;
|
||||||
|
|
||||||
|
/* ts A91111 :
|
||||||
|
whether to log SCSI commands (to be implemented in sg-*.c)
|
||||||
|
bit0= log in /tmp/libburn_sg_command_log
|
||||||
|
bit1= log to stderr
|
||||||
|
bit2= flush every line
|
||||||
|
*/
|
||||||
|
int burn_sg_log_scsi = 0;
|
||||||
|
|
||||||
/* ts A60925 : ticket 74 */
|
/* ts A60925 : ticket 74 */
|
||||||
/** Create the messenger object for libburn. */
|
/** Create the messenger object for libburn. */
|
||||||
@ -103,6 +116,14 @@ int burn_initialize(void)
|
|||||||
ret = burn_msgs_initialize();
|
ret = burn_msgs_initialize();
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
ret = sg_initialize(sg_initialize_msg, 0);
|
||||||
|
if (ret <= 0) {
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1,
|
||||||
|
0x00020175,
|
||||||
|
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
sg_initialize_msg, 0, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
burn_running = 1;
|
burn_running = 1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -130,10 +151,22 @@ void burn_finish(void)
|
|||||||
/* ts A60924 : ticket 74 */
|
/* ts A60924 : ticket 74 */
|
||||||
libdax_msgs_destroy(&libdax_messenger,0);
|
libdax_msgs_destroy(&libdax_messenger,0);
|
||||||
|
|
||||||
|
sg_shutdown(0);
|
||||||
|
|
||||||
burn_running = 0;
|
burn_running = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ts A91226 */
|
||||||
|
/** API function. See libburn.h */
|
||||||
|
char *burn_scsi_transport_id(int flag)
|
||||||
|
{
|
||||||
|
if (!burn_running)
|
||||||
|
sg_id_string(sg_initialize_msg, 0);
|
||||||
|
return sg_initialize_msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ts A60813 */
|
/* ts A60813 */
|
||||||
/** API function. See libburn.h */
|
/** API function. See libburn.h */
|
||||||
void burn_preset_device_open(int exclusive, int blocking, int abort_on_busy)
|
void burn_preset_device_open(int exclusive, int blocking, int abort_on_busy)
|
||||||
@ -414,3 +447,9 @@ int burn_set_messenger(void *messenger)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ts A91111 API */
|
||||||
|
void burn_set_scsi_logging(int flag)
|
||||||
|
{
|
||||||
|
burn_sg_log_scsi = flag & 7;
|
||||||
|
}
|
||||||
|
@ -9,8 +9,10 @@ Applications must use 64 bit off_t. E.g. by defining
|
|||||||
#define _LARGEFILE_SOURCE
|
#define _LARGEFILE_SOURCE
|
||||||
#define _FILE_OFFSET_BITS 64
|
#define _FILE_OFFSET_BITS 64
|
||||||
or take special precautions to interface with the library by 64 bit integers
|
or take special precautions to interface with the library by 64 bit integers
|
||||||
where this .h files prescribe off_t. Not to use 64 bit file i/o will keep the
|
where this .h files prescribe off_t.
|
||||||
application from producing and processing ISO images of more than 2 GB size.
|
|
||||||
|
To prevent 64 bit file i/o in the library would keep the application from
|
||||||
|
processing tracks of more than 2 GB size.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@ -141,19 +143,22 @@ enum burn_write_types
|
|||||||
only raw block types are supported
|
only raw block types are supported
|
||||||
With DVD and BD media: not supported.
|
With DVD and BD media: not supported.
|
||||||
|
|
||||||
ts A90901: THIS HAS BEEN DISABLED because its implementation
|
ts A90901: This had been disabled because its implementation
|
||||||
relied on code from cdrdao which is not understood
|
relied on code from cdrdao which is not understood
|
||||||
currently.
|
currently.
|
||||||
A burn run will abort with "FATAL" error message
|
A burn run will abort with "FATAL" error message
|
||||||
if this mode is attempted.
|
if this mode is attempted.
|
||||||
@since 0.7.2
|
@since 0.7.2
|
||||||
|
ts A91016: Re-implemented according to ECMA-130 Annex A and B.
|
||||||
|
Now understood, explained and not stemming from cdrdao.
|
||||||
|
@since 0.7.4
|
||||||
*/
|
*/
|
||||||
BURN_WRITE_RAW,
|
BURN_WRITE_RAW,
|
||||||
|
|
||||||
/** In replies this indicates that not any writing will work.
|
/** In replies this indicates that not any writing will work.
|
||||||
As parameter for inquiries it indicates that no particular write
|
As parameter for inquiries it indicates that no particular write
|
||||||
mode shall is specified.
|
mode shall is specified.
|
||||||
Do not use for setting a write mode for burning. It won't work.
|
Do not use for setting a write mode for burning. It will not work.
|
||||||
*/
|
*/
|
||||||
BURN_WRITE_NONE
|
BURN_WRITE_NONE
|
||||||
};
|
};
|
||||||
@ -759,6 +764,19 @@ int burn_abort_pacifier(void *handle, int patience, int elapsed);
|
|||||||
*/
|
*/
|
||||||
void burn_set_verbosity(int level);
|
void burn_set_verbosity(int level);
|
||||||
|
|
||||||
|
/* ts A91111 */
|
||||||
|
/** Enable resp. disable logging of SCSI commands (currently Linux only).
|
||||||
|
This call can be made at any time - even before burn_initialize().
|
||||||
|
It is in effect for all active drives and currently not very thread
|
||||||
|
safe for multiple drives.
|
||||||
|
@param flag Bitfield for control purposes. The default is 0.
|
||||||
|
bit0= log to file /tmp/libburn_sg_command_log
|
||||||
|
bit1= log to stderr
|
||||||
|
bit2= flush output after each line
|
||||||
|
@since 0.7.4
|
||||||
|
*/
|
||||||
|
void burn_set_scsi_logging(int flag);
|
||||||
|
|
||||||
/* ts A60813 */
|
/* ts A60813 */
|
||||||
/** Set parameters for behavior on opening device files. To be called early
|
/** Set parameters for behavior on opening device files. To be called early
|
||||||
after burn_initialize() and before any bus scan. But not mandatory at all.
|
after burn_initialize() and before any bus scan. But not mandatory at all.
|
||||||
@ -849,12 +867,12 @@ void burn_allow_untested_profiles(int yes);
|
|||||||
If the path leads to an existing file of any type other than directory,
|
If the path leads to an existing file of any type other than directory,
|
||||||
then the result is a sequential write-only stdio-drive = drive role 3.
|
then the result is a sequential write-only stdio-drive = drive role 3.
|
||||||
|
|
||||||
The special address form "stdio:/dev/fd/<number>" is interpreted literally
|
The special address form "stdio:/dev/fd/{number}" is interpreted literally
|
||||||
as reference to open file descriptor <number>. This address form coincides
|
as reference to open file descriptor {number}. This address form coincides
|
||||||
with real files on some systems, but it is in fact hardcoded in libburn.
|
with real files on some systems, but it is in fact hardcoded in libburn.
|
||||||
Special address "stdio:-" means stdout = "stdio:/dev/fd/1".
|
Special address "stdio:-" means stdout = "stdio:/dev/fd/1".
|
||||||
The role of such a drive is determined by the file type obtained via
|
The role of such a drive is determined by the file type obtained via
|
||||||
fstat(<number>).
|
fstat({number}).
|
||||||
|
|
||||||
Roles 2 and 3 perform all their eventual data transfer activities on a file
|
Roles 2 and 3 perform all their eventual data transfer activities on a file
|
||||||
via standard i/o functions open(2), lseek(2), read(2), write(2), close(2).
|
via standard i/o functions open(2), lseek(2), read(2), write(2), close(2).
|
||||||
@ -1046,6 +1064,19 @@ int burn_drive_obtain_scsi_adr(char *path, int *bus_no, int *host_no,
|
|||||||
*/
|
*/
|
||||||
int burn_drive_grab(struct burn_drive *drive, int load);
|
int burn_drive_grab(struct burn_drive *drive, int load);
|
||||||
|
|
||||||
|
/* ts B00114 */
|
||||||
|
/* Probe available CD write modes and block types. In earlier versions this
|
||||||
|
was done unconditionally on drive examination or aquiration. But it is
|
||||||
|
lengthy and obtrusive, up to spoiling burn runs on the examined drives.
|
||||||
|
So now this probing is omitted by default. All drives which announce to be
|
||||||
|
capable of CD or DVD writing, get blindly attributed the capability for
|
||||||
|
SAO and TAO. Applications which are interested in RAW modes or want to
|
||||||
|
rely on the traditional write mode information, may use this call.
|
||||||
|
@param drive_info drive object to be inquired
|
||||||
|
@return >0 indicates success, <=0 means failure
|
||||||
|
@since 0.7.6
|
||||||
|
*/
|
||||||
|
int burn_drive_probe_cd_write_modes(struct burn_drive_info *drive_info);
|
||||||
|
|
||||||
/* ts A90824 */
|
/* ts A90824 */
|
||||||
/** Calm down or alert a drive. Some drives stay alert after reading for
|
/** Calm down or alert a drive. Some drives stay alert after reading for
|
||||||
@ -1054,7 +1085,7 @@ int burn_drive_grab(struct burn_drive *drive, int load);
|
|||||||
sense to calm down the drive if no read operation is expected for the
|
sense to calm down the drive if no read operation is expected for the
|
||||||
next few seconds. The drive will get alert automatically if operations
|
next few seconds. The drive will get alert automatically if operations
|
||||||
are required.
|
are required.
|
||||||
@param drive The drive to influence.
|
@param d The drive to influence.
|
||||||
@param flag Bitfield for control purposes
|
@param flag Bitfield for control purposes
|
||||||
bit0= become alert (else start snoozing)
|
bit0= become alert (else start snoozing)
|
||||||
This is not mandatory to allow further drive operations
|
This is not mandatory to allow further drive operations
|
||||||
@ -1078,7 +1109,7 @@ void burn_drive_release(struct burn_drive *drive, int eject);
|
|||||||
eject button disabled. This physically locked drive state will last until
|
eject button disabled. This physically locked drive state will last until
|
||||||
the drive is grabbed again and released via burn_drive_release().
|
the drive is grabbed again and released via burn_drive_release().
|
||||||
Programs like eject, cdrecord, growisofs will break that ban too.
|
Programs like eject, cdrecord, growisofs will break that ban too.
|
||||||
@param drive The drive to release and leave locked.
|
@param d The drive to release and leave locked.
|
||||||
@param flag Bitfield for control purposes (unused yet, submit 0)
|
@param flag Bitfield for control purposes (unused yet, submit 0)
|
||||||
@return 1 means success, <=0 means failure
|
@return 1 means success, <=0 means failure
|
||||||
@since 0.4.0
|
@since 0.4.0
|
||||||
@ -1171,7 +1202,7 @@ char *burn_guess_cd_manufacturer(int m_li, int s_li, int f_li,
|
|||||||
/* ts A90909 */
|
/* ts A90909 */
|
||||||
/** Retrieve some media information which is mainly specific to CD. For other
|
/** Retrieve some media information which is mainly specific to CD. For other
|
||||||
media only the bits in reply parameter valid are supposed to be meaningful.
|
media only the bits in reply parameter valid are supposed to be meaningful.
|
||||||
@param drive The drive to query.
|
@param d The drive to query.
|
||||||
@param disc_type A string saying either "CD-DA or CD-ROM", or "CD-I",
|
@param disc_type A string saying either "CD-DA or CD-ROM", or "CD-I",
|
||||||
or ""CD-ROM XA", or "undefined".
|
or ""CD-ROM XA", or "undefined".
|
||||||
@param disc_id A 32 bit number read from the media. (Meaning unclear yet)
|
@param disc_id A 32 bit number read from the media. (Meaning unclear yet)
|
||||||
@ -1562,9 +1593,11 @@ void burn_drive_cancel(struct burn_drive *drive);
|
|||||||
|
|
||||||
|
|
||||||
/* ts A61223 */
|
/* ts A61223 */
|
||||||
/** Inquire whether the most recent write run was successful. Reasons for
|
/** Inquire whether the most recent asynchronous media job was successful.
|
||||||
non-success may be: rejection of burn parameters, abort during fatal errors
|
This applies to burn_disc_erase(), burn_disc_format(), burn_disc_write().
|
||||||
during write, a call to burn_drive_cancel() by the application thread.
|
Reasons for non-success may be: rejection of burn parameters, abort due to
|
||||||
|
fatal errors during write, blank or format, a call to burn_drive_cancel()
|
||||||
|
by the application thread.
|
||||||
@param d The drive to inquire.
|
@param d The drive to inquire.
|
||||||
@return 1=burn seems to have went well, 0=burn failed
|
@return 1=burn seems to have went well, 0=burn failed
|
||||||
@since 0.2.6
|
@since 0.2.6
|
||||||
@ -1772,6 +1805,58 @@ void burn_source_free(struct burn_source *s);
|
|||||||
struct burn_source *burn_file_source_new(const char *path,
|
struct burn_source *burn_file_source_new(const char *path,
|
||||||
const char *subpath);
|
const char *subpath);
|
||||||
|
|
||||||
|
|
||||||
|
/* ts A91122 : An interface to open(O_DIRECT) or similar OS tricks. */
|
||||||
|
|
||||||
|
/** Opens a file with eventual acceleration preparations which may depend
|
||||||
|
on the operating system and on compile time options of libburn.
|
||||||
|
You may use this call instead of open(2) for opening file descriptors
|
||||||
|
which shall be handed to burn_fd_source_new().
|
||||||
|
This should only be done for tracks with BURN_BLOCK_MODE1 (2048 bytes
|
||||||
|
per block).
|
||||||
|
|
||||||
|
If you use this call then you MUST allocate the buffers which you use
|
||||||
|
with read(2) by call burn_os_alloc_buffer(). Read sizes MUST be a multiple
|
||||||
|
of a safe buffer amount. Else you risk that track data get altered during
|
||||||
|
transmission.
|
||||||
|
burn_disk_write() will allocate a suitable read/write buffer for its own
|
||||||
|
operations. A fifo created by burn_fifo_source_new() will allocate
|
||||||
|
suitable memory for its buffer if called with flag bit0 and a multiple
|
||||||
|
of a safe buffer amount.
|
||||||
|
@param path The file address to open
|
||||||
|
@param open_flags The flags as of man 2 open. Normally just O_RDONLY.
|
||||||
|
@param flag Bitfield for control purposes (unused yet, submit 0).
|
||||||
|
@return A file descriptor as of open(2). Finally to be disposed
|
||||||
|
by close(2).
|
||||||
|
-1 indicates failure.
|
||||||
|
@since 0.7.4
|
||||||
|
*/
|
||||||
|
int burn_os_open_track_src(char *path, int open_flags, int flag);
|
||||||
|
|
||||||
|
/** Allocate a memory area that is suitable for reading with a file descriptor
|
||||||
|
opened by burn_os_open_track_src().
|
||||||
|
@param amount Number of bytes to allocate. This should be a multiple
|
||||||
|
of the operating system's i/o block size. 32 KB is
|
||||||
|
guaranteed by libburn to be safe.
|
||||||
|
@param flag Bitfield for control purposes (unused yet, submit 0).
|
||||||
|
@return The address of the allocated memory, or NULL on failure.
|
||||||
|
A non-NULL return value has finally to be disposed via
|
||||||
|
burn_os_free_buffer().
|
||||||
|
@since 0.7.4
|
||||||
|
*/
|
||||||
|
void *burn_os_alloc_buffer(size_t amount, int flag);
|
||||||
|
|
||||||
|
/** Dispose a memory area which was obtained by burn_os_alloc_buffer(),
|
||||||
|
@param buffer Memory address to be freed.
|
||||||
|
@param amount The number of bytes which was allocated at that
|
||||||
|
address.
|
||||||
|
@param flag Bitfield for control purposes (unused yet, submit 0).
|
||||||
|
@return 1 success , <=0 failure
|
||||||
|
@since 0.7.4
|
||||||
|
*/
|
||||||
|
int burn_os_free_buffer(void *buffer, size_t amount, int flag);
|
||||||
|
|
||||||
|
|
||||||
/** Creates a data source for an image file (a track) from an open
|
/** Creates a data source for an image file (a track) from an open
|
||||||
readable filedescriptor, an eventually open readable subcodes file
|
readable filedescriptor, an eventually open readable subcodes file
|
||||||
descriptor and eventually a fixed size in bytes.
|
descriptor and eventually a fixed size in bytes.
|
||||||
@ -1810,7 +1895,17 @@ struct burn_source *burn_fd_source_new(int datafd, int subfd, off_t size);
|
|||||||
a particular chunksize. E.g. libisofs demands 2048.
|
a particular chunksize. E.g. libisofs demands 2048.
|
||||||
@param chunks The number of chunks to be allocated in ring buffer.
|
@param chunks The number of chunks to be allocated in ring buffer.
|
||||||
This value must be >= 2.
|
This value must be >= 2.
|
||||||
@param flag Bitfield for control purposes (unused yet, submit 0).
|
@param flag Bitfield for control purposes:
|
||||||
|
bit0= The read method of inp is capable of delivering
|
||||||
|
arbitrary amounts of data per call. Not only one
|
||||||
|
sector.
|
||||||
|
Suitable for inp from burn_file_source_new()
|
||||||
|
and burn_fd_source_new() if not the fd has
|
||||||
|
exotic limitations on read size.
|
||||||
|
You MUST use this on inp which uses an fd opened
|
||||||
|
with burn_os_open_track_src().
|
||||||
|
Better do not use with other inp types.
|
||||||
|
@since 0.7.4
|
||||||
@return A pointer to the newly created burn_source.
|
@return A pointer to the newly created burn_source.
|
||||||
Later both burn_sources, inp and the returned fifo, have
|
Later both burn_sources, inp and the returned fifo, have
|
||||||
to be disposed by calling burn_source_free() for each.
|
to be disposed by calling burn_source_free() for each.
|
||||||
@ -1843,12 +1938,42 @@ struct burn_source *burn_fifo_source_new(struct burn_source *inp,
|
|||||||
int burn_fifo_inquire_status(struct burn_source *fifo, int *size,
|
int burn_fifo_inquire_status(struct burn_source *fifo, int *size,
|
||||||
int *free_bytes, char **status_text);
|
int *free_bytes, char **status_text);
|
||||||
|
|
||||||
|
/* ts A91125 */
|
||||||
|
/** Inquire various counters which reflect the fifo operation.
|
||||||
|
@param fifo The fifo object to inquire
|
||||||
|
@param total_min_fill The minimum number of bytes in the fifo. Beginning
|
||||||
|
from the moment when fifo consumption is enabled.
|
||||||
|
@param interval_min_fill The minimum byte number beginning from the moment
|
||||||
|
when fifo consumption is enabled or from the
|
||||||
|
most recent moment when burn_fifo_next_interval()
|
||||||
|
was called.
|
||||||
|
@param put_counter The number of data transactions into the fifo.
|
||||||
|
@param get_counter The number of data transactions out of the fifo.
|
||||||
|
@param empty_counter The number of times the fifo was empty.
|
||||||
|
@param full_counter The number of times the fifo was full.
|
||||||
|
@since 0.7.4
|
||||||
|
*/
|
||||||
|
void burn_fifo_get_statistics(struct burn_source *fifo,
|
||||||
|
int *total_min_fill, int *interval_min_fill,
|
||||||
|
int *put_counter, int *get_counter,
|
||||||
|
int *empty_counter, int *full_counter);
|
||||||
|
|
||||||
|
/* ts A91125 */
|
||||||
|
/** Inquire the fifo minimum fill counter for intervals and reset that counter.
|
||||||
|
@param fifo The fifo object to inquire
|
||||||
|
@param interval_min_fill The minimum number of bytes in the fifo. Beginning
|
||||||
|
from the moment when fifo consumption is enabled
|
||||||
|
or from the most recent moment when
|
||||||
|
burn_fifo_next_interval() was called.
|
||||||
|
@since 0.7.4
|
||||||
|
*/
|
||||||
|
void burn_fifo_next_interval(struct burn_source *fifo, int *interval_min_fill);
|
||||||
|
|
||||||
/* ts A80713 */
|
/* ts A80713 */
|
||||||
/** Obtain a preview of the first input data of a fifo which was created
|
/** Obtain a preview of the first input data of a fifo which was created
|
||||||
by burn_fifo_source_new(). The data will later be delivered normally to
|
by burn_fifo_source_new(). The data will later be delivered normally to
|
||||||
the consumer track of the fifo.
|
the consumer track of the fifo.
|
||||||
bufsize may not be larger than the fifo size (chunk_size * chunks).
|
bufsize may not be larger than the fifo size (chunk_size * chunks) - 32k.
|
||||||
This call will succeed only if data consumption by the track has not
|
This call will succeed only if data consumption by the track has not
|
||||||
started yet, i.e. best before the call to burn_disc_write().
|
started yet, i.e. best before the call to burn_disc_write().
|
||||||
It will start the worker thread of the fifo with the expectable side
|
It will start the worker thread of the fifo with the expectable side
|
||||||
@ -1856,17 +1981,33 @@ int burn_fifo_inquire_status(struct burn_source *fifo, int *size,
|
|||||||
data have arrived or until it becomes clear that this will not happen.
|
data have arrived or until it becomes clear that this will not happen.
|
||||||
The call may be repeated with increased bufsize. It will always yield
|
The call may be repeated with increased bufsize. It will always yield
|
||||||
the bytes beginning from the first one in the fifo.
|
the bytes beginning from the first one in the fifo.
|
||||||
@param fifo The fifo object to inquire
|
@param fifo The fifo object to inquire resp. start
|
||||||
@param buf Pointer to memory of at least bufsize bytes where to
|
@param buf Pointer to memory of at least bufsize bytes where to
|
||||||
deliver the peeked data
|
deliver the peeked data.
|
||||||
@param bufsize Number of bytes to peek from the start of the fifo data
|
@param bufsize Number of bytes to peek from the start of the fifo data
|
||||||
@param flag Bitfield for control purposes (unused yet, submit 0).
|
@param flag Bitfield for control purposes (unused yet, submit 0).
|
||||||
@return <0 on severe error, 0 if not enough data, 1 if bufsize bytes read
|
@return <0 on severe error, 0 if not enough data, 1 if bufsize bytes read
|
||||||
@since 0.5.0
|
@since 0.5.0
|
||||||
*/
|
*/
|
||||||
int burn_fifo_peek_data(struct burn_source *source, char *buf, int bufsize,
|
int burn_fifo_peek_data(struct burn_source *fifo, char *buf, int bufsize,
|
||||||
int flag);
|
int flag);
|
||||||
|
|
||||||
|
/* ts A91125 */
|
||||||
|
/** Start the fifo worker thread and wait either until the requested number
|
||||||
|
of bytes have arrived or until it becomes clear that this will not happen.
|
||||||
|
Filling will go on asynchronously after burn_fifo_fill() returned.
|
||||||
|
This call and burn_fifo_peek_data() do not disturb each other.
|
||||||
|
@param fifo The fifo object to start
|
||||||
|
@param fill Number of bytes desired. Expect to get return 1 if
|
||||||
|
at least fifo size - 32k were read.
|
||||||
|
@param flag Bitfield for control purposes.
|
||||||
|
bit0= fill fifo to maximum size
|
||||||
|
@return <0 on severe error, 0 if not enough data,
|
||||||
|
1 if desired amount or fifo full
|
||||||
|
@since 0.7.4
|
||||||
|
*/
|
||||||
|
int burn_fifo_fill(struct burn_source *fifo, int fill, int flag);
|
||||||
|
|
||||||
|
|
||||||
/* ts A70328 */
|
/* ts A70328 */
|
||||||
/** Sets a fixed track size after the data source object has already been
|
/** Sets a fixed track size after the data source object has already been
|
||||||
@ -2103,6 +2244,32 @@ void burn_write_opts_set_force(struct burn_write_opts *opts, int use_force);
|
|||||||
void burn_write_opts_set_stream_recording(struct burn_write_opts *opts,
|
void burn_write_opts_set_stream_recording(struct burn_write_opts *opts,
|
||||||
int value);
|
int value);
|
||||||
|
|
||||||
|
/* ts A91115 */
|
||||||
|
/** Overrides the write chunk size for DVD and BD media which is normally
|
||||||
|
determined according to media type and setting of stream recording.
|
||||||
|
A chunk size of 64 KB may improve throughput with bus systems which show
|
||||||
|
latency problems.
|
||||||
|
@param opts The write opts to change
|
||||||
|
@param obs Number of bytes which shall be sent by a single write command.
|
||||||
|
0 means automatic size, 32768 and 65336 are the only other
|
||||||
|
accepted sizes for now.
|
||||||
|
@since 0.7.4
|
||||||
|
*/
|
||||||
|
void burn_write_opts_set_dvd_obs(struct burn_write_opts *opts, int obs);
|
||||||
|
|
||||||
|
/* ts A91115 */
|
||||||
|
/** Sets the rythm by which stdio pseudo drives force their output data to
|
||||||
|
be consumed by the receiving storage device. This forcing keeps the memory
|
||||||
|
from being clogged with lots of pending data for slow devices.
|
||||||
|
@param opts The write opts to change
|
||||||
|
@param rythm Number of 2KB output blocks after which fsync(2) is
|
||||||
|
performed. -1 means no fsync(), 0 means default,
|
||||||
|
elsewise the value must be >= 32.
|
||||||
|
Default is currently 8192 = 16 MB.
|
||||||
|
@since 0.7.4
|
||||||
|
*/
|
||||||
|
void burn_write_opts_set_stdio_fsync(struct burn_write_opts *opts, int rythm);
|
||||||
|
|
||||||
|
|
||||||
/** Sets whether to read in raw mode or not
|
/** Sets whether to read in raw mode or not
|
||||||
@param opts The read opts to change
|
@param opts The read opts to change
|
||||||
@ -2449,7 +2616,7 @@ void burn_version(int *major, int *minor, int *micro);
|
|||||||
*/
|
*/
|
||||||
#define burn_header_version_major 0
|
#define burn_header_version_major 0
|
||||||
#define burn_header_version_minor 7
|
#define burn_header_version_minor 7
|
||||||
#define burn_header_version_micro 1
|
#define burn_header_version_micro 6
|
||||||
/** Note:
|
/** Note:
|
||||||
Above version numbers are also recorded in configure.ac because libtool
|
Above version numbers are also recorded in configure.ac because libtool
|
||||||
wants them as parameters at build time.
|
wants them as parameters at build time.
|
||||||
@ -2499,6 +2666,15 @@ These two advises are mutually exclusive.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* ts A91226 */
|
||||||
|
/** Obtain the id string of the SCSI transport interface.
|
||||||
|
This interface may be a system specific adapter module of libburn or
|
||||||
|
an adapter to a supporting library like libcdio.
|
||||||
|
@flag Bitfield for control puposes, submit 0 for now
|
||||||
|
@return A pointer to the id string. Do not alter the string content.
|
||||||
|
@since 0.7.6
|
||||||
|
*/
|
||||||
|
char *burn_scsi_transport_id(int flag);
|
||||||
|
|
||||||
/* ts A60924 : ticket 74 */
|
/* ts A60924 : ticket 74 */
|
||||||
/** Control queueing and stderr printing of messages from libburn.
|
/** Control queueing and stderr printing of messages from libburn.
|
||||||
@ -2746,4 +2922,31 @@ BURN_END_DECLS
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* ts A91205 */
|
||||||
|
/* The following experiments may be interesting in future:
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Perform OPC explicitely.
|
||||||
|
# define Libburn_pioneer_dvr_216d_with_opC 1
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Load mode page 5 and modify it rather than composing from scratch.
|
||||||
|
# define Libburn_pioneer_dvr_216d_load_mode5 1
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Inquire drive events and react by reading configuration or starting unit.
|
||||||
|
# define Libburn_pioneer_dvr_216d_get_evenT 1
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ts A91112 */
|
||||||
|
/* Do not probe CD modes but declare only data and audio modes supported.
|
||||||
|
For other modes resp. real probing one has to call
|
||||||
|
burn_drive_probe_cd_write_modes().
|
||||||
|
|
||||||
|
*/
|
||||||
|
#define Libburn_dummy_probe_write_modeS 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /*LIBBURN_H*/
|
#endif /*LIBBURN_H*/
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
|
|
||||||
/* libdax_msgs
|
/* libdax_msgs
|
||||||
Message handling facility of libdax.
|
Message handling facility of libdax.
|
||||||
Copyright (C) 2006 - 2009 Thomas Schmitt <scdbackup@gmx.net>,
|
Copyright (C) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>,
|
||||||
provided under GPL version 2
|
provided under GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
|
|
||||||
/* libdax_msgs
|
/* libdax_msgs
|
||||||
Message handling facility of libdax.
|
Message handling facility of libdax.
|
||||||
Copyright (C) 2006-2009 Thomas Schmitt <scdbackup@gmx.net>,
|
Copyright (C) 2006-2010 Thomas Schmitt <scdbackup@gmx.net>,
|
||||||
provided under GPL version 2
|
provided under GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@ -528,7 +528,7 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
|
|||||||
0x00020159 (DEBUG,HIGH) = TOC Format 0 returns inconsistent data
|
0x00020159 (DEBUG,HIGH) = TOC Format 0 returns inconsistent data
|
||||||
0x0002015a (NOTE,HIGH) = Could not examine busy device
|
0x0002015a (NOTE,HIGH) = Could not examine busy device
|
||||||
0x0002015b (HINT,HIGH) = Busy '...' seems to be a hard disk, as '...1' exists
|
0x0002015b (HINT,HIGH) = Busy '...' seems to be a hard disk, as '...1' exists
|
||||||
0x0002015c (FAILURE,HIGH) = Fifo size is smaller than desired peek buffer
|
0x0002015c (FAILURE,HIGH) = Fifo size too small for desired peek buffer
|
||||||
0x0002015d (FAILURE,HIGH) = Fifo input ended short of desired peek buffer size
|
0x0002015d (FAILURE,HIGH) = Fifo input ended short of desired peek buffer size
|
||||||
0x0002015e (FATAL,HIGH) = Fifo is already under consumption when peeking
|
0x0002015e (FATAL,HIGH) = Fifo is already under consumption when peeking
|
||||||
0x0002015f (MISHAP,HIGH) = Damaged CD table-of-content detected and truncated
|
0x0002015f (MISHAP,HIGH) = Damaged CD table-of-content detected and truncated
|
||||||
@ -551,6 +551,9 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
|
|||||||
0x00020171 (NOTE,HIGH) = Closing BD-R with accidently open session
|
0x00020171 (NOTE,HIGH) = Closing BD-R with accidently open session
|
||||||
0x00020172 (SORRY,HIGH) = Read start address larger than number of readable blocks
|
0x00020172 (SORRY,HIGH) = Read start address larger than number of readable blocks
|
||||||
0x00020173 (FAILURE,HIGH) = Drive tells NWA smaller than last written address
|
0x00020173 (FAILURE,HIGH) = Drive tells NWA smaller than last written address
|
||||||
|
0x00020174 (SORRY,HIGH) = Fifo alignment does not allow desired read size
|
||||||
|
0x00020175 (FATAL,HIGH) = Supporting library is too old
|
||||||
|
0x00020176 (NOTE,HIGH) = Stream recording disabled because of small OS buffer
|
||||||
|
|
||||||
|
|
||||||
libdax_audioxtr:
|
libdax_audioxtr:
|
||||||
|
234
libburn/mmc.c
234
libburn/mmc.c
@ -28,6 +28,8 @@
|
|||||||
/* ts A70223 : in init.c */
|
/* ts A70223 : in init.c */
|
||||||
extern int burn_support_untested_profiles;
|
extern int burn_support_untested_profiles;
|
||||||
|
|
||||||
|
static int mmc_get_configuration_al(struct burn_drive *d, int *alloc_len);
|
||||||
|
|
||||||
|
|
||||||
#ifdef Libburn_log_in_and_out_streaM
|
#ifdef Libburn_log_in_and_out_streaM
|
||||||
/* <<< ts A61031 */
|
/* <<< ts A61031 */
|
||||||
@ -177,7 +179,7 @@ static unsigned char MMC_GET_CONFIGURATION[] =
|
|||||||
{ 0x46, 0, 0, 0, 0, 0, 0, 16, 0, 0 };
|
{ 0x46, 0, 0, 0, 0, 0, 0, 16, 0, 0 };
|
||||||
|
|
||||||
static unsigned char MMC_SYNC_CACHE[] = { 0x35, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
static unsigned char MMC_SYNC_CACHE[] = { 0x35, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||||
static unsigned char MMC_GET_EVENT[] = { 0x4A, 1, 0, 0, 16, 0, 0, 0, 8, 0 };
|
static unsigned char MMC_GET_EVENT[] = { 0x4A, 1, 0, 0, 0x7e, 0, 0, 0, 8, 0 };
|
||||||
static unsigned char MMC_CLOSE[] = { 0x5B, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
static unsigned char MMC_CLOSE[] = { 0x5B, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||||
static unsigned char MMC_TRACK_INFO[] = { 0x52, 0, 0, 0, 0, 0, 0, 16, 0, 0 };
|
static unsigned char MMC_TRACK_INFO[] = { 0x52, 0, 0, 0, 0, 0, 0, 16, 0, 0 };
|
||||||
|
|
||||||
@ -243,11 +245,6 @@ int mmc_function_spy(struct burn_drive *d, char * text)
|
|||||||
d->cancel = 1;
|
d->cancel = 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (d->is_stopped && strcmp(text, "stop_unit") != 0 &&
|
|
||||||
strcmp(text, "start_unit") != 0) {
|
|
||||||
d->start_unit(d);
|
|
||||||
d->is_stopped = 0;
|
|
||||||
}
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,12 +273,29 @@ int mmc_int_to_four_char(unsigned char *data, int num)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int mmc_start_for_bit0 = 0;
|
||||||
|
|
||||||
|
/* @param flag bit0= the calling function should need no START UNIT.
|
||||||
|
(Handling depends on mmc_start_for_bit0)
|
||||||
|
*/
|
||||||
|
int mmc_start_if_needed(struct burn_drive *d, int flag)
|
||||||
|
{
|
||||||
|
if (!d->is_stopped)
|
||||||
|
return 2;
|
||||||
|
if ((flag & 1) && !mmc_start_for_bit0)
|
||||||
|
return 2;
|
||||||
|
d->start_unit(d);
|
||||||
|
d->is_stopped = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void mmc_send_cue_sheet(struct burn_drive *d, struct cue_sheet *s)
|
void mmc_send_cue_sheet(struct burn_drive *d, struct cue_sheet *s)
|
||||||
{
|
{
|
||||||
struct buffer buf;
|
struct buffer buf;
|
||||||
struct command c;
|
struct command c;
|
||||||
|
|
||||||
|
mmc_start_if_needed(d, 0);
|
||||||
if (mmc_function_spy(d, "mmc_send_cue_sheet") <= 0)
|
if (mmc_function_spy(d, "mmc_send_cue_sheet") <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -313,6 +327,7 @@ int mmc_reserve_track(struct burn_drive *d, off_t size)
|
|||||||
int lba;
|
int lba;
|
||||||
char msg[80];
|
char msg[80];
|
||||||
|
|
||||||
|
mmc_start_if_needed(d, 0);
|
||||||
if (mmc_function_spy(d, "mmc_reserve_track") <= 0)
|
if (mmc_function_spy(d, "mmc_reserve_track") <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -347,6 +362,7 @@ int mmc_read_track_info(struct burn_drive *d, int trackno, struct buffer *buf,
|
|||||||
{
|
{
|
||||||
struct command c;
|
struct command c;
|
||||||
|
|
||||||
|
mmc_start_if_needed(d, 1);
|
||||||
if (mmc_function_spy(d, "mmc_read_track_info") <= 0)
|
if (mmc_function_spy(d, "mmc_read_track_info") <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -399,6 +415,7 @@ int mmc_get_nwa(struct burn_drive *d, int trackno, int *lba, int *nwa)
|
|||||||
int ret, num, alloc_len = 20;
|
int ret, num, alloc_len = 20;
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
|
|
||||||
|
mmc_start_if_needed(d, 1);
|
||||||
if (mmc_function_spy(d, "mmc_get_nwa") <= 0)
|
if (mmc_function_spy(d, "mmc_get_nwa") <= 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -409,6 +426,11 @@ int mmc_get_nwa(struct burn_drive *d, int trackno, int *lba, int *nwa)
|
|||||||
*lba = mmc_four_char_to_int(data + 8);
|
*lba = mmc_four_char_to_int(data + 8);
|
||||||
*nwa = mmc_four_char_to_int(data + 12);
|
*nwa = mmc_four_char_to_int(data + 12);
|
||||||
num = mmc_four_char_to_int(data + 16);
|
num = mmc_four_char_to_int(data + 16);
|
||||||
|
|
||||||
|
#ifdef Libburn_pioneer_dvr_216d_load_mode5
|
||||||
|
/* >>> memorize track mode : data[6] & 0xf */;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (d->current_profile == 0x1a || d->current_profile == 0x13 ||
|
if (d->current_profile == 0x1a || d->current_profile == 0x13 ||
|
||||||
d->current_profile == 0x12 || d->current_profile == 0x43) {
|
d->current_profile == 0x12 || d->current_profile == 0x43) {
|
||||||
/* overwriteable */
|
/* overwriteable */
|
||||||
@ -519,17 +541,19 @@ void mmc_get_event(struct burn_drive *d)
|
|||||||
{
|
{
|
||||||
struct buffer buf;
|
struct buffer buf;
|
||||||
struct command c;
|
struct command c;
|
||||||
int alloc_len= 8;
|
int alloc_len = 8, len, evt_code, loops = 0;
|
||||||
|
unsigned char *evt;
|
||||||
|
|
||||||
if (mmc_function_spy(d, "mmc_get_event") <= 0)
|
if (mmc_function_spy(d, "mmc_get_event") <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
again:;
|
||||||
scsi_init_command(&c, MMC_GET_EVENT, sizeof(MMC_GET_EVENT));
|
scsi_init_command(&c, MMC_GET_EVENT, sizeof(MMC_GET_EVENT));
|
||||||
/*
|
c.dxfer_len = 8;
|
||||||
c.oplen = sizeof(MMC_GET_EVENT);
|
|
||||||
memcpy(c.opcode, MMC_GET_EVENT, sizeof(MMC_GET_EVENT));
|
/* >>> have a burn_drive element for Notification Class */;
|
||||||
*/
|
c.opcode[4] = 0x7e;
|
||||||
c.dxfer_len = alloc_len;
|
|
||||||
c.opcode[7] = (c.dxfer_len >> 8) & 0xff;
|
c.opcode[7] = (c.dxfer_len >> 8) & 0xff;
|
||||||
c.opcode[8] = c.dxfer_len & 0xff;
|
c.opcode[8] = c.dxfer_len & 0xff;
|
||||||
c.retry = 1;
|
c.retry = 1;
|
||||||
@ -538,11 +562,66 @@ void mmc_get_event(struct burn_drive *d)
|
|||||||
c.page->sectors = 0;
|
c.page->sectors = 0;
|
||||||
c.dir = FROM_DRIVE;
|
c.dir = FROM_DRIVE;
|
||||||
d->issue_command(d, &c);
|
d->issue_command(d, &c);
|
||||||
burn_print(12, "0x%x:0x%x:0x%x:0x%x\n",
|
if (c.error)
|
||||||
c.page->data[0], c.page->data[1], c.page->data[2],
|
return;
|
||||||
c.page->data[3]);
|
|
||||||
burn_print(12, "event: %d:%d:%d:%d\n", c.page->data[4],
|
evt = c.page->data;
|
||||||
c.page->data[5], c.page->data[6], c.page->data[7]);
|
len = ((evt[0] << 8) | evt[1]) + 2;
|
||||||
|
if (len < 8)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* >>> memorize evt[3] in burn_drive element for Notification Class */;
|
||||||
|
if (evt[3] == 0) /* No event */
|
||||||
|
return;
|
||||||
|
|
||||||
|
evt_code = evt[4] & 0xf;
|
||||||
|
if (evt_code == 0) /* No change */
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (evt[2] & 7) {
|
||||||
|
case 0: /* no events supported */
|
||||||
|
return;
|
||||||
|
case 1: /* Operational change */
|
||||||
|
if (((evt[6] << 8) | evt[7])) {
|
||||||
|
alloc_len = 8;
|
||||||
|
mmc_get_configuration_al(d, &alloc_len);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2: /* Power Management */
|
||||||
|
if (evt[5] >= 2)
|
||||||
|
d->start_unit(d);
|
||||||
|
break;
|
||||||
|
case 3: /* External request */
|
||||||
|
|
||||||
|
/* >>> report about external request */;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 4: /* Media */
|
||||||
|
if (evt_code == 2) {
|
||||||
|
d->start_unit(d);
|
||||||
|
alloc_len = 8;
|
||||||
|
mmc_get_configuration_al(d, &alloc_len);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 5: /* Multiple Host Events */
|
||||||
|
|
||||||
|
/* >>> report about foreign host interference */;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6: /* Device busy */
|
||||||
|
if (evt_code == 1 && evt[5]) {
|
||||||
|
|
||||||
|
/* >>> wait the time announced in evt[6],[7]
|
||||||
|
as 100ms units */;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: /* reserved */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
loops++;
|
||||||
|
if (loops < 100)
|
||||||
|
goto again;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -687,6 +766,7 @@ void mmc_write_12(struct burn_drive *d, int start, struct buffer *buf)
|
|||||||
struct command c;
|
struct command c;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
|
mmc_start_if_needed(d, 0);
|
||||||
if (mmc_function_spy(d, "mmc_write_12") <= 0)
|
if (mmc_function_spy(d, "mmc_write_12") <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -729,6 +809,7 @@ int mmc_write(struct burn_drive *d, int start, struct buffer *buf)
|
|||||||
O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR);
|
O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR);
|
||||||
#endif /* Libburn_log_in_and_out_streaM */
|
#endif /* Libburn_log_in_and_out_streaM */
|
||||||
|
|
||||||
|
mmc_start_if_needed(d, 0);
|
||||||
if (mmc_function_spy(d, "mmc_write") <= 0)
|
if (mmc_function_spy(d, "mmc_write") <= 0)
|
||||||
return BE_CANCELLED;
|
return BE_CANCELLED;
|
||||||
|
|
||||||
@ -1022,6 +1103,7 @@ static int mmc_read_toc_fmt0(struct burn_drive *d)
|
|||||||
{
|
{
|
||||||
int alloc_len = 4, ret;
|
int alloc_len = 4, ret;
|
||||||
|
|
||||||
|
mmc_start_if_needed(d, 1);
|
||||||
if (mmc_function_spy(d, "mmc_read_toc_fmt0") <= 0)
|
if (mmc_function_spy(d, "mmc_read_toc_fmt0") <= 0)
|
||||||
return -1;
|
return -1;
|
||||||
ret = mmc_read_toc_fmt0_al(d, &alloc_len);
|
ret = mmc_read_toc_fmt0_al(d, &alloc_len);
|
||||||
@ -1404,6 +1486,7 @@ void mmc_read_toc(struct burn_drive *d)
|
|||||||
{
|
{
|
||||||
int alloc_len = 4, ret;
|
int alloc_len = 4, ret;
|
||||||
|
|
||||||
|
mmc_start_if_needed(d, 1);
|
||||||
if (mmc_function_spy(d, "mmc_read_toc") <= 0)
|
if (mmc_function_spy(d, "mmc_read_toc") <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -1434,6 +1517,7 @@ int mmc_read_multi_session_c1(struct burn_drive *d, int *trackno, int *start)
|
|||||||
struct burn_track **tracks;
|
struct burn_track **tracks;
|
||||||
struct burn_toc_entry toc_entry;
|
struct burn_toc_entry toc_entry;
|
||||||
|
|
||||||
|
mmc_start_if_needed(d, 1);
|
||||||
if (mmc_function_spy(d, "mmc_read_multi_session_c1") <= 0)
|
if (mmc_function_spy(d, "mmc_read_multi_session_c1") <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -1631,7 +1715,7 @@ static int mmc_read_disc_info_al(struct burn_drive *d, int *alloc_len)
|
|||||||
d->disc_info_valid |= (!!(data[7] & 128)) << 1;
|
d->disc_info_valid |= (!!(data[7] & 128)) << 1;
|
||||||
if (len + 2 > 31 && (data[7] & 64)) {
|
if (len + 2 > 31 && (data[7] & 64)) {
|
||||||
memcpy(d->disc_bar_code, data + 24, 8);
|
memcpy(d->disc_bar_code, data + 24, 8);
|
||||||
d->disc_bar_code[9] = 0;
|
d->disc_bar_code[8] = 0;
|
||||||
d->disc_info_valid |= 4;
|
d->disc_info_valid |= 4;
|
||||||
}
|
}
|
||||||
if (len + 2 > 32 && (data[7] & 16)) {
|
if (len + 2 > 32 && (data[7] & 16)) {
|
||||||
@ -1766,11 +1850,16 @@ regard_as_blank:;
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ts A61217 : Note for future
|
/* ts A61217 :
|
||||||
growisofs performs OPC if (data[0]<<8)|data[1]<=32
|
growisofs performs OPC if (data[0]<<8)|data[1]<=32
|
||||||
which indicates no OPC entries are attached to the
|
which indicates no OPC entries are attached to the
|
||||||
reply from the drive.
|
reply from the drive.
|
||||||
|
ts A91104 :
|
||||||
|
Actually growisofs performs OPC only on DVD-R[W].
|
||||||
*/
|
*/
|
||||||
|
d->num_opc_tables = 0;
|
||||||
|
if(((data[0] << 8) | data[1]) > 32) /* i.e. > 34 bytes are available */
|
||||||
|
d->num_opc_tables = data[33];
|
||||||
|
|
||||||
/* ts A61219 : mmc5r03c.pdf 6.22.3.1.13 BG Format Status
|
/* ts A61219 : mmc5r03c.pdf 6.22.3.1.13 BG Format Status
|
||||||
0=blank (not yet started)
|
0=blank (not yet started)
|
||||||
@ -1818,6 +1907,7 @@ void mmc_read_disc_info(struct burn_drive *d)
|
|||||||
{
|
{
|
||||||
int alloc_len = 34, ret;
|
int alloc_len = 34, ret;
|
||||||
|
|
||||||
|
mmc_start_if_needed(d, 1);
|
||||||
if (mmc_function_spy(d, "mmc_read_disc_info") <= 0)
|
if (mmc_function_spy(d, "mmc_read_disc_info") <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -1849,6 +1939,7 @@ void mmc_read_atip(struct burn_drive *d)
|
|||||||
4234, 5646, 7056, 8468, -12, -13, -14, -15};
|
4234, 5646, 7056, 8468, -12, -13, -14, -15};
|
||||||
/* 24, 32, 40, 48, -, -, -, - */
|
/* 24, 32, 40, 48, -, -, -, - */
|
||||||
|
|
||||||
|
mmc_start_if_needed(d, 1);
|
||||||
if (mmc_function_spy(d, "mmc_read_atip") <= 0)
|
if (mmc_function_spy(d, "mmc_read_atip") <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -2006,6 +2097,7 @@ void mmc_read_sectors(struct burn_drive *d,
|
|||||||
int errorblock, req;
|
int errorblock, req;
|
||||||
struct command c;
|
struct command c;
|
||||||
|
|
||||||
|
mmc_start_if_needed(d, 0);
|
||||||
if (mmc_function_spy(d, "mmc_read_sectors") <= 0)
|
if (mmc_function_spy(d, "mmc_read_sectors") <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -2076,6 +2168,7 @@ void mmc_erase(struct burn_drive *d, int fast)
|
|||||||
{
|
{
|
||||||
struct command c;
|
struct command c;
|
||||||
|
|
||||||
|
mmc_start_if_needed(d, 0);
|
||||||
if (mmc_function_spy(d, "mmc_erase") <= 0)
|
if (mmc_function_spy(d, "mmc_erase") <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -2097,6 +2190,7 @@ void mmc_read_lead_in(struct burn_drive *d, struct buffer *buf)
|
|||||||
int len;
|
int len;
|
||||||
struct command c;
|
struct command c;
|
||||||
|
|
||||||
|
mmc_start_if_needed(d, 0);
|
||||||
if (mmc_function_spy(d, "mmc_read_lead_in") <= 0)
|
if (mmc_function_spy(d, "mmc_read_lead_in") <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -2125,6 +2219,7 @@ void mmc_perform_opc(struct burn_drive *d)
|
|||||||
{
|
{
|
||||||
struct command c;
|
struct command c;
|
||||||
|
|
||||||
|
mmc_start_if_needed(d, 0);
|
||||||
if (mmc_function_spy(d, "mmc_perform_opc") <= 0)
|
if (mmc_function_spy(d, "mmc_perform_opc") <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -2157,14 +2252,11 @@ int mmc_set_streaming(struct burn_drive *d,
|
|||||||
unsigned char *pd;
|
unsigned char *pd;
|
||||||
int key, asc, ascq;
|
int key, asc, ascq;
|
||||||
|
|
||||||
|
mmc_start_if_needed(d, 1);
|
||||||
if (mmc_function_spy(d, "mmc_set_streaming") <= 0)
|
if (mmc_function_spy(d, "mmc_set_streaming") <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
scsi_init_command(&c, MMC_SET_STREAMING, sizeof(MMC_SET_STREAMING));
|
scsi_init_command(&c, MMC_SET_STREAMING, sizeof(MMC_SET_STREAMING));
|
||||||
/*
|
|
||||||
c.oplen = sizeof(MMC_SET_STREAMING);
|
|
||||||
memcpy(c.opcode, MMC_SET_STREAMING, sizeof(MMC_SET_STREAMING));
|
|
||||||
*/
|
|
||||||
c.retry = 1;
|
c.retry = 1;
|
||||||
c.page = &buf;
|
c.page = &buf;
|
||||||
c.page->bytes = 28;
|
c.page->bytes = 28;
|
||||||
@ -2218,26 +2310,10 @@ int mmc_set_streaming(struct burn_drive *d,
|
|||||||
d->issue_command(d, &c);
|
d->issue_command(d, &c);
|
||||||
if (c.error) {
|
if (c.error) {
|
||||||
if (c.sense[2]!=0 && !d->silent_on_scsi_error) {
|
if (c.sense[2]!=0 && !d->silent_on_scsi_error) {
|
||||||
|
|
||||||
#ifdef NIX
|
|
||||||
sprintf(msg,
|
|
||||||
"SCSI error on set_streaming(%d): key=%X asc=%2.2Xh ascq=%2.2Xh",
|
|
||||||
w_speed,
|
|
||||||
c.sense[2],c.sense[12],c.sense[13]);
|
|
||||||
libdax_msgs_submit(libdax_messenger,
|
|
||||||
d->global_index,
|
|
||||||
0x00020124,
|
|
||||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
msg, 0, 0);
|
|
||||||
#else /* NIX */
|
|
||||||
|
|
||||||
sprintf(msg,
|
sprintf(msg,
|
||||||
"SCSI error on set_streaming(%d): ", w_speed);
|
"SCSI error on set_streaming(%d): ", w_speed);
|
||||||
scsi_error_msg(d, c.sense, 14, msg + strlen(msg),
|
scsi_error_msg(d, c.sense, 14, msg + strlen(msg),
|
||||||
&key, &asc, &ascq);
|
&key, &asc, &ascq);
|
||||||
|
|
||||||
#endif /* !NIX */
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2251,6 +2327,7 @@ void mmc_set_speed(struct burn_drive *d, int r, int w)
|
|||||||
int ret, end_lba = 0;
|
int ret, end_lba = 0;
|
||||||
struct burn_speed_descriptor *best_sd = NULL;
|
struct burn_speed_descriptor *best_sd = NULL;
|
||||||
|
|
||||||
|
mmc_start_if_needed(d, 1);
|
||||||
if (mmc_function_spy(d, "mmc_set_speed") <= 0)
|
if (mmc_function_spy(d, "mmc_set_speed") <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -2364,7 +2441,7 @@ static int mmc_get_configuration_al(struct burn_drive *d, int *alloc_len)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
old_alloc_len = *alloc_len;
|
old_alloc_len = *alloc_len;
|
||||||
*alloc_len = len = mmc_four_char_to_int(c.page->data);
|
*alloc_len = len = mmc_four_char_to_int(c.page->data) + 4;
|
||||||
if (len > old_alloc_len)
|
if (len > old_alloc_len)
|
||||||
len = old_alloc_len;
|
len = old_alloc_len;
|
||||||
if (len < 8 || len > 4096)
|
if (len < 8 || len > 4096)
|
||||||
@ -2591,6 +2668,7 @@ void mmc_get_configuration(struct burn_drive *d)
|
|||||||
{
|
{
|
||||||
int alloc_len = 8, ret;
|
int alloc_len = 8, ret;
|
||||||
|
|
||||||
|
mmc_start_if_needed(d, 1);
|
||||||
if (mmc_function_spy(d, "mmc_get_configuration") <= 0)
|
if (mmc_function_spy(d, "mmc_get_configuration") <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -2794,6 +2872,7 @@ int mmc_read_format_capacities(struct burn_drive *d, int top_wanted)
|
|||||||
{
|
{
|
||||||
int alloc_len = 4, ret;
|
int alloc_len = 4, ret;
|
||||||
|
|
||||||
|
mmc_start_if_needed(d, 1);
|
||||||
if (mmc_function_spy(d, "mmc_read_format_capacities") <= 0)
|
if (mmc_function_spy(d, "mmc_read_format_capacities") <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -2822,9 +2901,7 @@ void mmc_sync_cache(struct burn_drive *d)
|
|||||||
c.oplen = sizeof(MMC_SYNC_CACHE);
|
c.oplen = sizeof(MMC_SYNC_CACHE);
|
||||||
*/
|
*/
|
||||||
c.retry = 1;
|
c.retry = 1;
|
||||||
|
|
||||||
c.opcode[1] |= 2; /* ts A70918 : Immed */
|
c.opcode[1] |= 2; /* ts A70918 : Immed */
|
||||||
|
|
||||||
c.page = NULL;
|
c.page = NULL;
|
||||||
c.dir = NO_TRANSFER;
|
c.dir = NO_TRANSFER;
|
||||||
|
|
||||||
@ -2852,6 +2929,7 @@ void mmc_sync_cache(struct burn_drive *d)
|
|||||||
d->cancel = 1;
|
d->cancel = 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spc_wait_unit_attention(d, 3600, "SYNCHRONIZE CACHE", 0) <= 0)
|
if (spc_wait_unit_attention(d, 3600, "SYNCHRONIZE CACHE", 0) <= 0)
|
||||||
d->cancel = 1;
|
d->cancel = 1;
|
||||||
else
|
else
|
||||||
@ -2874,11 +2952,6 @@ int mmc_read_buffer_capacity(struct burn_drive *d)
|
|||||||
|
|
||||||
scsi_init_command(&c, MMC_READ_BUFFER_CAPACITY,
|
scsi_init_command(&c, MMC_READ_BUFFER_CAPACITY,
|
||||||
sizeof(MMC_READ_BUFFER_CAPACITY));
|
sizeof(MMC_READ_BUFFER_CAPACITY));
|
||||||
/*
|
|
||||||
memcpy(c.opcode, MMC_READ_BUFFER_CAPACITY,
|
|
||||||
sizeof(MMC_READ_BUFFER_CAPACITY));
|
|
||||||
c.oplen = sizeof(MMC_READ_BUFFER_CAPACITY);
|
|
||||||
*/
|
|
||||||
c.dxfer_len = alloc_len;
|
c.dxfer_len = alloc_len;
|
||||||
c.opcode[7] = (c.dxfer_len >> 8) & 0xff;
|
c.opcode[7] = (c.dxfer_len >> 8) & 0xff;
|
||||||
c.opcode[8] = c.dxfer_len & 0xff;
|
c.opcode[8] = c.dxfer_len & 0xff;
|
||||||
@ -2946,6 +3019,7 @@ int mmc_format_unit(struct burn_drive *d, off_t size, int flag)
|
|||||||
int key, asc, ascq;
|
int key, asc, ascq;
|
||||||
int full_format_type = 0x00; /* Full Format (or 0x10 for DVD-RW ?) */
|
int full_format_type = 0x00; /* Full Format (or 0x10 for DVD-RW ?) */
|
||||||
|
|
||||||
|
mmc_start_if_needed(d, 0);
|
||||||
if (mmc_function_spy(d, "mmc_format_unit") <= 0)
|
if (mmc_function_spy(d, "mmc_format_unit") <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
size_mode = (flag >> 1) & 3;
|
size_mode = (flag >> 1) & 3;
|
||||||
@ -3687,6 +3761,7 @@ int mmc_get_write_performance(struct burn_drive *d)
|
|||||||
{
|
{
|
||||||
int alloc_len = 8, max_descr = 0, ret;
|
int alloc_len = 8, max_descr = 0, ret;
|
||||||
|
|
||||||
|
mmc_start_if_needed(d, 1);
|
||||||
if (mmc_function_spy(d, "mmc_get_write_performance") <= 0)
|
if (mmc_function_spy(d, "mmc_get_write_performance") <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -3729,10 +3804,9 @@ int mmc_compose_mode_page_5(struct burn_drive *d,
|
|||||||
pd[4] = 8;
|
pd[4] = 8;
|
||||||
/* Link size dummy */
|
/* Link size dummy */
|
||||||
pd[5] = 0;
|
pd[5] = 0;
|
||||||
|
|
||||||
} else if ((d->current_profile == 0x14 || d->current_profile == 0x11 ||
|
} else if ((d->current_profile == 0x14 || d->current_profile == 0x11 ||
|
||||||
d->current_profile == 0x15)
|
d->current_profile == 0x15)
|
||||||
&& o->write_type == BURN_WRITE_SAO) {
|
&& o->write_type == BURN_WRITE_SAO) {
|
||||||
/* ts A70205 : DVD-R[W][/DL] : Disc-at-once, DAO */
|
/* ts A70205 : DVD-R[W][/DL] : Disc-at-once, DAO */
|
||||||
/* Learned from dvd+rw-tools and mmc5r03c.pdf .
|
/* Learned from dvd+rw-tools and mmc5r03c.pdf .
|
||||||
See doc/cookbook.txt for more detailed references. */
|
See doc/cookbook.txt for more detailed references. */
|
||||||
@ -3741,8 +3815,17 @@ int mmc_compose_mode_page_5(struct burn_drive *d,
|
|||||||
pd[2] = ((!!o->underrun_proof) << 6)
|
pd[2] = ((!!o->underrun_proof) << 6)
|
||||||
| ((!!o->simulate) << 4)
|
| ((!!o->simulate) << 4)
|
||||||
| 2;
|
| 2;
|
||||||
/* No multi-session , FP = 0 , Track Mode = 5 */
|
|
||||||
|
/* No multi-session , FP = 0 , Copy = 0, Track Mode = 5 */
|
||||||
pd[3] = 5;
|
pd[3] = 5;
|
||||||
|
|
||||||
|
#ifdef Libburn_pioneer_dvr_216d_load_mode5
|
||||||
|
|
||||||
|
/* >>> use track mode from mmc_get_nwa() */
|
||||||
|
/* >>> pd[3] = (pd[3] & ~0xf) | (d->track_inf[5] & 0xf); */
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Data Block Type = 8 */
|
/* Data Block Type = 8 */
|
||||||
pd[4] = 8;
|
pd[4] = 8;
|
||||||
|
|
||||||
@ -3819,6 +3902,7 @@ int mmc_read_10(struct burn_drive *d, int start,int amount, struct buffer *buf)
|
|||||||
{
|
{
|
||||||
struct command c;
|
struct command c;
|
||||||
|
|
||||||
|
mmc_start_if_needed(d, 0);
|
||||||
if (mmc_function_spy(d, "mmc_read_10") <= 0)
|
if (mmc_function_spy(d, "mmc_read_10") <= 0)
|
||||||
return -1;
|
return -1;
|
||||||
;
|
;
|
||||||
@ -3877,6 +3961,7 @@ int mmc_read_capacity(struct burn_drive *d)
|
|||||||
int alloc_len= 8;
|
int alloc_len= 8;
|
||||||
|
|
||||||
d->media_read_capacity = 0x7fffffff;
|
d->media_read_capacity = 0x7fffffff;
|
||||||
|
mmc_start_if_needed(d, 1);
|
||||||
if (mmc_function_spy(d, "mmc_read_capacity") <= 0)
|
if (mmc_function_spy(d, "mmc_read_capacity") <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -3960,7 +4045,9 @@ int mmc_read_disc_structure(struct burn_drive *d,
|
|||||||
char **reply, int *reply_len, int flag)
|
char **reply, int *reply_len, int flag)
|
||||||
{
|
{
|
||||||
int alloc_len = 4, ret;
|
int alloc_len = 4, ret;
|
||||||
|
char msg[80];
|
||||||
|
|
||||||
|
mmc_start_if_needed(d, 1);
|
||||||
if (mmc_function_spy(d, "mmc_read_disc_structure") <= 0)
|
if (mmc_function_spy(d, "mmc_read_disc_structure") <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -3971,7 +4058,49 @@ int mmc_read_disc_structure(struct burn_drive *d,
|
|||||||
fprintf(stderr,"LIBBURN_DEBUG: ADh alloc_len = %d , ret = %d\n",
|
fprintf(stderr,"LIBBURN_DEBUG: ADh alloc_len = %d , ret = %d\n",
|
||||||
alloc_len, ret);
|
alloc_len, ret);
|
||||||
*/
|
*/
|
||||||
if (alloc_len >= 12 && ret > 0)
|
if (ret <= 0)
|
||||||
|
return ret;
|
||||||
|
if (alloc_len < 12) {
|
||||||
|
sprintf(msg,
|
||||||
|
"READ DISC STRUCTURE announces only %d bytes of reply\n",
|
||||||
|
alloc_len);
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
|
||||||
|
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
|
||||||
|
msg, 0, 0);
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
/* ts A91205
|
||||||
|
LG GH22LS30 revision 1.00 returns for DVD-R format
|
||||||
|
code 0x0E an allocation length of 4 (= 0 payload).
|
||||||
|
A MS-Windows tool can inquire media code "RITEKF1",
|
||||||
|
though.
|
||||||
|
This macro causes a try to unconditionally read the
|
||||||
|
desired payload bytes. The drive then returns 35
|
||||||
|
bytes as requested and the media id is "RITEKF1".
|
||||||
|
Nevertheless this is not a generally usable gesture
|
||||||
|
because older Linux USB dislikes requests to fetch
|
||||||
|
more bytes than the drive will deliver.
|
||||||
|
|
||||||
|
# define Libburn_enforce_structure_code_0x0E 1
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef Libburn_enforce_structure_code_0x0E
|
||||||
|
if (format == 0x0E) {
|
||||||
|
alloc_len = min_len + 4;
|
||||||
|
ret = mmc_read_disc_structure_al(d, &alloc_len,
|
||||||
|
media_type, layer_number, format, min_len,
|
||||||
|
reply, reply_len, 0);
|
||||||
|
if (*reply_len < min_len || *reply == NULL)
|
||||||
|
ret = 0;
|
||||||
|
sprintf(msg, "READ DISC STRUCTURE returns %d bytes of required %d\n",
|
||||||
|
*reply_len + 4, min_len + 4);
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
|
||||||
|
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
|
||||||
|
msg, 0, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} else
|
||||||
ret = mmc_read_disc_structure_al(d, &alloc_len,
|
ret = mmc_read_disc_structure_al(d, &alloc_len,
|
||||||
media_type, layer_number, format, min_len,
|
media_type, layer_number, format, min_len,
|
||||||
reply, reply_len, 0);
|
reply, reply_len, 0);
|
||||||
@ -4253,6 +4382,7 @@ int mmc_setup_drive(struct burn_drive *d)
|
|||||||
d->needs_close_session = 0;
|
d->needs_close_session = 0;
|
||||||
d->needs_sync_cache = 0;
|
d->needs_sync_cache = 0;
|
||||||
d->bg_format_status = -1;
|
d->bg_format_status = -1;
|
||||||
|
d->num_opc_tables = -1;
|
||||||
d->last_lead_in = -2000000000;
|
d->last_lead_in = -2000000000;
|
||||||
d->last_lead_out = -2000000000;
|
d->last_lead_out = -2000000000;
|
||||||
d->disc_type = 0xff;
|
d->disc_type = 0xff;
|
||||||
|
@ -68,6 +68,9 @@ int mmc_compose_mode_page_5(struct burn_drive *d,
|
|||||||
const struct burn_write_opts *o,
|
const struct burn_write_opts *o,
|
||||||
unsigned char *pd);
|
unsigned char *pd);
|
||||||
|
|
||||||
|
/* ts A70201 */
|
||||||
|
int mmc_four_char_to_int(unsigned char *data);
|
||||||
|
|
||||||
/* ts A70812 : return 0 = ok , return BE_CANCELLED = error occured */
|
/* ts A70812 : return 0 = ok , return BE_CANCELLED = error occured */
|
||||||
int mmc_read_10(struct burn_drive *d, int start, int amount,
|
int mmc_read_10(struct burn_drive *d, int start, int amount,
|
||||||
struct buffer *buf);
|
struct buffer *buf);
|
||||||
@ -90,4 +93,12 @@ int mmc_get_media_product_id(struct burn_drive *d,
|
|||||||
char **product_id, char **media_code1, char **media_code2,
|
char **product_id, char **media_code1, char **media_code2,
|
||||||
char **book_type, int flag);
|
char **book_type, int flag);
|
||||||
|
|
||||||
|
|
||||||
|
/* ts A60910 (estimated) */
|
||||||
|
int mmc_function_spy(struct burn_drive *d, char * text);
|
||||||
|
|
||||||
|
/* ts A91118 */
|
||||||
|
int mmc_start_if_needed(struct burn_drive *d, int flag);
|
||||||
|
|
||||||
|
|
||||||
#endif /*__MMC*/
|
#endif /*__MMC*/
|
||||||
|
@ -39,6 +39,8 @@ struct burn_write_opts *burn_write_opts_new(struct burn_drive *drive)
|
|||||||
opts->fill_up_media = 0;
|
opts->fill_up_media = 0;
|
||||||
opts->force_is_set = 0;
|
opts->force_is_set = 0;
|
||||||
opts->do_stream_recording = 0;
|
opts->do_stream_recording = 0;
|
||||||
|
opts->dvd_obs_override = 0;
|
||||||
|
opts->stdio_fsync_size = Libburn_stdio_fsync_limiT;
|
||||||
opts->has_mediacatalog = 0;
|
opts->has_mediacatalog = 0;
|
||||||
opts->format = BURN_CDROM;
|
opts->format = BURN_CDROM;
|
||||||
opts->multi = 0;
|
opts->multi = 0;
|
||||||
@ -389,6 +391,25 @@ void burn_write_opts_set_stream_recording(struct burn_write_opts *opts,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ts A91115: API */
|
||||||
|
void burn_write_opts_set_dvd_obs(struct burn_write_opts *opts, int obs)
|
||||||
|
{
|
||||||
|
if (obs != 0 && obs != 32 * 1024 && obs != 64 * 1024)
|
||||||
|
return;
|
||||||
|
opts->dvd_obs_override = obs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ts A91115: API */
|
||||||
|
void burn_write_opts_set_stdio_fsync(struct burn_write_opts *opts, int rythm)
|
||||||
|
{
|
||||||
|
if (rythm == -1)
|
||||||
|
opts->stdio_fsync_size = 0;
|
||||||
|
else if (rythm == 0)
|
||||||
|
opts->stdio_fsync_size = Libburn_stdio_fsync_limiT;
|
||||||
|
else if (rythm >= 32)
|
||||||
|
opts->stdio_fsync_size = rythm;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ts A70901: API */
|
/* ts A70901: API */
|
||||||
|
@ -51,9 +51,19 @@ struct burn_write_opts
|
|||||||
|
|
||||||
/* ts A80412 : whether to use WRITE12 with Streaming bit set
|
/* ts A80412 : whether to use WRITE12 with Streaming bit set
|
||||||
rather than WRITE10. Speeds up DVD-RAM. Might help with BD-RE.
|
rather than WRITE10. Speeds up DVD-RAM. Might help with BD-RE.
|
||||||
This gets transferred to burn_drive.do_stream_recording */
|
This gets transferred to burn_drive.do_stream_recording
|
||||||
|
*/
|
||||||
int do_stream_recording;
|
int do_stream_recording;
|
||||||
|
|
||||||
|
/* ts A91115 : override value for .obs on DVD media.
|
||||||
|
Only values 0, 32K and 64K are allowed for now. */
|
||||||
|
int dvd_obs_override;
|
||||||
|
|
||||||
|
/* ts A91115 : size of the fsync() interval for stdio writing.
|
||||||
|
Values 0 or >= 32 counted in 2 KB blocks. */
|
||||||
|
int stdio_fsync_size;
|
||||||
|
|
||||||
|
|
||||||
/** A disc can have a media catalog number */
|
/** A disc can have a media catalog number */
|
||||||
int has_mediacatalog;
|
int has_mediacatalog;
|
||||||
unsigned char mediacatalog[13];
|
unsigned char mediacatalog[13];
|
||||||
@ -64,6 +74,11 @@ struct burn_write_opts
|
|||||||
unsigned char multi;
|
unsigned char multi;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Default value for burn_write_opts.stdio_flush_size
|
||||||
|
*/
|
||||||
|
#define Libburn_stdio_fsync_limiT 8192
|
||||||
|
|
||||||
|
|
||||||
/** Options for disc reading operations. This should be created with
|
/** Options for disc reading operations. This should be created with
|
||||||
burn_read_opts_new() and freed with burn_read_opts_free(). */
|
burn_read_opts_new() and freed with burn_read_opts_free(). */
|
||||||
struct burn_read_opts
|
struct burn_read_opts
|
||||||
|
@ -57,5 +57,7 @@ typedef struct burn_drive_enumeration_state *burn_drive_enumerator_t;
|
|||||||
To be initialized and used within sg-*.c .
|
To be initialized and used within sg-*.c .
|
||||||
*/
|
*/
|
||||||
#define BURN_OS_TRANSPORT_DRIVE_ELEMENTS \
|
#define BURN_OS_TRANSPORT_DRIVE_ELEMENTS \
|
||||||
struct cam_device* cam;
|
struct cam_device* cam; \
|
||||||
|
int lock_fd; \
|
||||||
|
|
||||||
|
|
||||||
|
72
libburn/os-libcdio.h
Normal file
72
libburn/os-libcdio.h
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
|
||||||
|
/* os-libcdio.h
|
||||||
|
Operating system specific libburn definitions and declarations. Included
|
||||||
|
by os.h in case of compilation for
|
||||||
|
Unknown X/Open-like systems
|
||||||
|
with GNU libcdio MMC transport adapter sg-libcdio.c
|
||||||
|
|
||||||
|
Copyright (C) 2009 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/** List of all signals which shall be caught by signal handlers and trigger
|
||||||
|
a graceful abort of libburn. (See man 7 signal.)
|
||||||
|
*/
|
||||||
|
/* Once as system defined macros */
|
||||||
|
#define BURN_OS_SIGNAL_MACRO_LIST \
|
||||||
|
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT, \
|
||||||
|
SIGFPE, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM, \
|
||||||
|
SIGUSR1, SIGUSR2, SIGXCPU, SIGTSTP, SIGTTIN, \
|
||||||
|
SIGTTOU
|
||||||
|
|
||||||
|
/* Once as text 1:1 list of strings for messages and interpreters */
|
||||||
|
#define BURN_OS_SIGNAL_NAME_LIST \
|
||||||
|
"SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGABRT", \
|
||||||
|
"SIGFPE", "SIGSEGV", "SIGPIPE", "SIGALRM", "SIGTERM", \
|
||||||
|
"SIGUSR1", "SIGUSR2", "SIGXCPU", "SIGTSTP", "SIGTTIN", \
|
||||||
|
"SIGTTOU"
|
||||||
|
|
||||||
|
/* The number of above list items */
|
||||||
|
#define BURN_OS_SIGNAL_COUNT 16
|
||||||
|
|
||||||
|
/** To list all signals which shall surely not be caught */
|
||||||
|
#define BURN_OS_NON_SIGNAL_MACRO_LIST \
|
||||||
|
SIGKILL, SIGCHLD, SIGSTOP
|
||||||
|
|
||||||
|
/* The number of above list items */
|
||||||
|
#define BURN_OS_NON_SIGNAL_COUNT 3
|
||||||
|
|
||||||
|
|
||||||
|
/* 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.
|
||||||
|
This makes it worth to have a special case for Linux buffer size here.
|
||||||
|
*/
|
||||||
|
#ifdef __linux
|
||||||
|
#define BURN_OS_TRANSPORT_BUFFER_SIZE 65536
|
||||||
|
#else
|
||||||
|
/* (It might be risky to use 64k. FreeBSD is said to can only 32k.) */
|
||||||
|
#define BURN_OS_TRANSPORT_BUFFER_SIZE 32768
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* To hold the position of the most recently delivered address from
|
||||||
|
device enumeration.
|
||||||
|
*/
|
||||||
|
struct burn_drive_enumerator_struct {
|
||||||
|
char **ppsz_cd_drives;
|
||||||
|
char **pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
#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 \
|
||||||
|
void *p_cdio; /* actually a pointer to CdIo_t */ \
|
||||||
|
char libcdio_name[4096]; /* The drive path as used by libcdio */ \
|
||||||
|
|
19
libburn/os.h
19
libburn/os.h
@ -13,6 +13,15 @@
|
|||||||
Operating system case distinction
|
Operating system case distinction
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef Libburn_use_libcdiO
|
||||||
|
|
||||||
|
|
||||||
|
/* -------------------------- X/Open with GNU libcdio ---------------------- */
|
||||||
|
#include "os-libcdio.h"
|
||||||
|
|
||||||
|
|
||||||
|
#else
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
|
|
||||||
|
|
||||||
@ -20,6 +29,14 @@
|
|||||||
#include "os-freebsd.h"
|
#include "os-freebsd.h"
|
||||||
|
|
||||||
|
|
||||||
|
#else
|
||||||
|
#ifdef __FreeBSD_kernel__
|
||||||
|
|
||||||
|
|
||||||
|
/* ----------------------- FreeBSD with CAM under Debian ------------------- */
|
||||||
|
#include "os-freebsd.h"
|
||||||
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#ifdef __linux
|
#ifdef __linux
|
||||||
|
|
||||||
@ -36,7 +53,9 @@
|
|||||||
|
|
||||||
|
|
||||||
#endif /* ! __linux */
|
#endif /* ! __linux */
|
||||||
|
#endif /* ! __FreeBSD__kernel__ */
|
||||||
#endif /* ! __FreeBSD__ */
|
#endif /* ! __FreeBSD__ */
|
||||||
|
#endif /* ! Libburn_use_libcdiO */
|
||||||
|
|
||||||
|
|
||||||
#endif /* ! BURN_OS_H_INCLUDED */
|
#endif /* ! BURN_OS_H_INCLUDED */
|
||||||
|
@ -17,7 +17,27 @@
|
|||||||
int mmc_function_spy(struct burn_drive *d, char * text);
|
int mmc_function_spy(struct burn_drive *d, char * text);
|
||||||
|
|
||||||
|
|
||||||
/* spc command set */
|
/* START STOP UNIT as of SBC-1 and SBC-2
|
||||||
|
0: Opcode 0x1B
|
||||||
|
1: bit0= Immed
|
||||||
|
bit1-7= reserved
|
||||||
|
2: reserved
|
||||||
|
3: reserved
|
||||||
|
4: bit0= Start (else Stop unit)
|
||||||
|
bit1= Load/Eject (according to Start resp. Stop)
|
||||||
|
bit2-3= reserved
|
||||||
|
bit4-7= Power Condition
|
||||||
|
0= Start Valid: process Start and Load/Eject bits
|
||||||
|
1= assume Active state
|
||||||
|
2= assume Idle state
|
||||||
|
3= assume Stanby state
|
||||||
|
(5= SBC-1 only: assume Sleep state)
|
||||||
|
7= transfer control of power conditions to logical unit
|
||||||
|
10= force idle condition timer to 0
|
||||||
|
11= force standby condition timer to 0
|
||||||
|
All others are reserved.
|
||||||
|
5: Control (set to 0)
|
||||||
|
*/
|
||||||
static unsigned char SBC_LOAD[] = { 0x1b, 0, 0, 0, 3, 0 };
|
static unsigned char SBC_LOAD[] = { 0x1b, 0, 0, 0, 3, 0 };
|
||||||
static unsigned char SBC_UNLOAD[] = { 0x1b, 0, 0, 0, 2, 0 };
|
static unsigned char SBC_UNLOAD[] = { 0x1b, 0, 0, 0, 2, 0 };
|
||||||
static unsigned char SBC_START_UNIT[] = { 0x1b, 0, 0, 0, 1, 0 };
|
static unsigned char SBC_START_UNIT[] = { 0x1b, 0, 0, 0, 1, 0 };
|
||||||
@ -31,11 +51,6 @@ void sbc_load(struct burn_drive *d)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
scsi_init_command(&c, SBC_LOAD, sizeof(SBC_LOAD));
|
scsi_init_command(&c, SBC_LOAD, sizeof(SBC_LOAD));
|
||||||
/*
|
|
||||||
memcpy(c.opcode, SBC_LOAD, sizeof(SBC_LOAD));
|
|
||||||
c.oplen = sizeof(SBC_LOAD);
|
|
||||||
c.page = NULL;
|
|
||||||
*/
|
|
||||||
c.retry = 1;
|
c.retry = 1;
|
||||||
|
|
||||||
/* ts A70921 : Had to revoke Immed because of LG GSA-4082B */
|
/* ts A70921 : Had to revoke Immed because of LG GSA-4082B */
|
||||||
@ -59,25 +74,24 @@ void sbc_eject(struct burn_drive *d)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
scsi_init_command(&c, SBC_UNLOAD, sizeof(SBC_UNLOAD));
|
scsi_init_command(&c, SBC_UNLOAD, sizeof(SBC_UNLOAD));
|
||||||
/*
|
/* c.opcode[1] |= 1; / * ts A70918 : Immed , ts B00109 : revoked */
|
||||||
memcpy(c.opcode, SBC_UNLOAD, sizeof(SBC_UNLOAD));
|
|
||||||
c.oplen = sizeof(SBC_UNLOAD);
|
|
||||||
c.page = NULL;
|
|
||||||
*/
|
|
||||||
|
|
||||||
c.opcode[1] |= 1; /* ts A70918 : Immed */
|
|
||||||
|
|
||||||
c.page = NULL;
|
c.page = NULL;
|
||||||
c.dir = NO_TRANSFER;
|
c.dir = NO_TRANSFER;
|
||||||
d->issue_command(d, &c);
|
d->issue_command(d, &c);
|
||||||
|
/* ts A70918 : Wait long. A late eject could surprise or hurt user.
|
||||||
|
ts B00109 : Asynchronous eject revoked, as one cannot reliably
|
||||||
|
distinguish out from unready.
|
||||||
if (c.error)
|
if (c.error)
|
||||||
return;
|
return;
|
||||||
/* ts A70918 : Wait long. A late eject could surprise or hurt user. */
|
|
||||||
spc_wait_unit_attention(d, 1800, "STOP UNIT (+ EJECT)", 0);
|
spc_wait_unit_attention(d, 1800, "STOP UNIT (+ EJECT)", 0);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ts A61118 : is it necessary to tell the drive to get ready for use ? */
|
|
||||||
int sbc_start_unit(struct burn_drive *d)
|
/* ts A91112 : Now with flag */
|
||||||
|
/* @param flag bit0= asynchronous waiting
|
||||||
|
*/
|
||||||
|
int sbc_start_unit_flag(struct burn_drive *d, int flag)
|
||||||
{
|
{
|
||||||
struct command c;
|
struct command c;
|
||||||
int ret;
|
int ret;
|
||||||
@ -87,17 +101,37 @@ int sbc_start_unit(struct burn_drive *d)
|
|||||||
|
|
||||||
scsi_init_command(&c, SBC_START_UNIT, sizeof(SBC_START_UNIT));
|
scsi_init_command(&c, SBC_START_UNIT, sizeof(SBC_START_UNIT));
|
||||||
c.retry = 1;
|
c.retry = 1;
|
||||||
c.opcode[1] |= 1; /* ts A70918 : Immed */
|
c.opcode[1] |= (flag & 1); /* ts A70918 : Immed */
|
||||||
c.dir = NO_TRANSFER;
|
c.dir = NO_TRANSFER;
|
||||||
d->issue_command(d, &c);
|
d->issue_command(d, &c);
|
||||||
if (c.error)
|
if (c.error)
|
||||||
return 0;
|
return 0;
|
||||||
/* ts A70918 : now asynchronous */
|
if (!(flag & 1))
|
||||||
d->is_stopped = 0;
|
return 1;
|
||||||
|
/* ts A70918 : asynchronous */
|
||||||
ret = spc_wait_unit_attention(d, 1800, "START UNIT", 0);
|
ret = spc_wait_unit_attention(d, 1800, "START UNIT", 0);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int sbc_start_unit(struct burn_drive *d)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
d->is_stopped = 0; /* no endless starting attempts */
|
||||||
|
|
||||||
|
/* Asynchronous, not to block controller by waiting */
|
||||||
|
ret = sbc_start_unit_flag(d, 1);
|
||||||
|
if (ret <= 0)
|
||||||
|
return ret;
|
||||||
|
/* Synchronous to catch Pioneer DVR-216D which is ready too early.
|
||||||
|
A pending START UNIT can prevent ejecting of the tray.
|
||||||
|
*/
|
||||||
|
ret = sbc_start_unit_flag(d, 0);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ts A90824 : Trying to reduce drive noise */
|
/* ts A90824 : Trying to reduce drive noise */
|
||||||
int sbc_stop_unit(struct burn_drive *d)
|
int sbc_stop_unit(struct burn_drive *d)
|
||||||
{
|
{
|
||||||
|
@ -21,6 +21,8 @@
|
|||||||
#include "libdax_msgs.h"
|
#include "libdax_msgs.h"
|
||||||
extern struct libdax_msgs *libdax_messenger;
|
extern struct libdax_msgs *libdax_messenger;
|
||||||
|
|
||||||
|
#include "ecma130ab.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef Libburn_log_in_and_out_streaM
|
#ifdef Libburn_log_in_and_out_streaM
|
||||||
/* <<< ts A61031 */
|
/* <<< ts A61031 */
|
||||||
@ -734,6 +736,57 @@ int sector_headers_is_ok(struct burn_write_opts *o, int mode)
|
|||||||
int sector_headers(struct burn_write_opts *o, unsigned char *out,
|
int sector_headers(struct burn_write_opts *o, unsigned char *out,
|
||||||
int mode, int leadin)
|
int mode, int leadin)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#ifdef Libburn_ecma130ab_includeD
|
||||||
|
|
||||||
|
struct burn_drive *d = o->drive;
|
||||||
|
unsigned int crc;
|
||||||
|
int min, sec, frame;
|
||||||
|
int modebyte = -1;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = sector_headers_is_ok(o, mode);
|
||||||
|
if (ret != 2)
|
||||||
|
return !!ret;
|
||||||
|
modebyte = 1;
|
||||||
|
|
||||||
|
out[0] = 0;
|
||||||
|
memset(out + 1, 0xFF, 10); /* sync */
|
||||||
|
out[11] = 0;
|
||||||
|
|
||||||
|
if (leadin) {
|
||||||
|
burn_lba_to_msf(d->rlba, &min, &sec, &frame);
|
||||||
|
out[12] = dec_to_bcd(min) + 0xA0;
|
||||||
|
out[13] = dec_to_bcd(sec);
|
||||||
|
out[14] = dec_to_bcd(frame);
|
||||||
|
out[15] = modebyte;
|
||||||
|
} else {
|
||||||
|
burn_lba_to_msf(d->alba, &min, &sec, &frame);
|
||||||
|
out[12] = dec_to_bcd(min);
|
||||||
|
out[13] = dec_to_bcd(sec);
|
||||||
|
out[14] = dec_to_bcd(frame);
|
||||||
|
out[15] = modebyte;
|
||||||
|
}
|
||||||
|
if (mode & BURN_MODE1) {
|
||||||
|
crc = crc_32(out, 2064);
|
||||||
|
out[2064] = crc & 0xFF;
|
||||||
|
crc >>= 8;
|
||||||
|
out[2065] = crc & 0xFF;
|
||||||
|
crc >>= 8;
|
||||||
|
out[2066] = crc & 0xFF;
|
||||||
|
crc >>= 8;
|
||||||
|
out[2067] = crc & 0xFF;
|
||||||
|
}
|
||||||
|
if (mode & BURN_MODE1) {
|
||||||
|
memset(out + 2068, 0, 8);
|
||||||
|
burn_rspc_parity_p(out);
|
||||||
|
burn_rspc_parity_q(out);
|
||||||
|
}
|
||||||
|
burn_ecma130_scramble(out);
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
#else /* Libburn_ecma130ab_includeD */
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = sector_headers_is_ok(o, mode);
|
ret = sector_headers_is_ok(o, mode);
|
||||||
@ -750,8 +803,52 @@ int sector_headers(struct burn_write_opts *o, unsigned char *out,
|
|||||||
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
"Raw CD write modes are not supported", 0, 0);
|
"Raw CD write modes are not supported", 0, 0);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
#endif /* ! Libburn_ecma130ab_includeD */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
void process_q(struct burn_drive *d, unsigned char *q)
|
||||||
|
{
|
||||||
|
unsigned char i[5];
|
||||||
|
int mode;
|
||||||
|
|
||||||
|
mode = q[0] & 0xF;
|
||||||
|
/* burn_print(12, "mode: %d : ", mode);*/
|
||||||
|
switch (mode) {
|
||||||
|
case 1:
|
||||||
|
/* burn_print(12, "tno = %d : ", q[1]);
|
||||||
|
burn_print(12, "index = %d\n", q[2]);
|
||||||
|
*/
|
||||||
|
/* q[1] is the track number (starting at 1) q[2] is the index
|
||||||
|
number (starting at 0) */
|
||||||
|
#warning this is totally bogus
|
||||||
|
if (q[1] - 1 > 99)
|
||||||
|
break;
|
||||||
|
if (q[2] > d->toc->track[q[1] - 1].indices) {
|
||||||
|
burn_print(12, "new index at %d\n", d->alba);
|
||||||
|
d->toc->track[q[1] - 1].index[q[2]] = d->alba;
|
||||||
|
d->toc->track[q[1] - 1].indices++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
/* XXX dont ignore these */
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
/* burn_print(12, "ISRC data in mode 3 q\n");*/
|
||||||
|
i[0] = isrc[(q[1] << 2) >> 2];
|
||||||
|
/* burn_print(12, "0x%x 0x%x 0x%x 0x%x 0x%x\n", q[1], q[2], q[3], q[4], q[5]);
|
||||||
|
burn_print(12, "ISRC - %c%c%c%c%c\n", i[0], i[1], i[2], i[3], i[4]);
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
|
||||||
|
/* ts A61009 : if reactivated then witout Assert */
|
||||||
|
a ssert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* this needs more info. subs in the data? control/adr? */
|
/* this needs more info. subs in the data? control/adr? */
|
||||||
|
|
||||||
@ -766,7 +863,7 @@ int sector_identify(unsigned char *data)
|
|||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
scramble(data);
|
burn_ecma130_scramble(data);
|
||||||
check mode byte for 1 or 2
|
check mode byte for 1 or 2
|
||||||
test parity to see if it's a valid sector
|
test parity to see if it's a valid sector
|
||||||
if invalid, return BURN_MODE_AUDIO;
|
if invalid, return BURN_MODE_AUDIO;
|
||||||
|
@ -7,8 +7,8 @@ the transport level aspects of SCSI control and command i/o.
|
|||||||
|
|
||||||
Present implementation: default dummy which enables libburn only to work
|
Present implementation: default dummy which enables libburn only to work
|
||||||
with stdio: pseudo drive addresses.
|
with stdio: pseudo drive addresses.
|
||||||
For real implementations see sg-linux.c or sg-freebsd.c
|
For real implementations see sg-linux.c, sg-freebsd.c,
|
||||||
|
sg-libcdio.c
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@ -19,6 +19,7 @@ Present implementation: default dummy which enables libburn only to work
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#ifdef Libburn_os_has_statvfS
|
#ifdef Libburn_os_has_statvfS
|
||||||
#include <sys/statvfs.h>
|
#include <sys/statvfs.h>
|
||||||
@ -38,6 +39,59 @@ Present implementation: default dummy which enables libburn only to work
|
|||||||
extern struct libdax_msgs *libdax_messenger;
|
extern struct libdax_msgs *libdax_messenger;
|
||||||
|
|
||||||
|
|
||||||
|
/** 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)
|
||||||
|
{
|
||||||
|
strcpy(msg, "internal X/Open adapter sg-dummy");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Performs global initialization of the SCSI transport adapter and eventually
|
||||||
|
needed operating system facilities. Checks for compatibility 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.
|
||||||
|
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.
|
/** Returns the next index number and the next enumerated drive address.
|
||||||
The enumeration has to cover all available and accessible drives. It is
|
The enumeration has to cover all available and accessible drives. It is
|
||||||
allowed to return addresses of drives which are not available but under
|
allowed to return addresses of drives which are not available but under
|
||||||
@ -152,6 +206,23 @@ int sg_is_enumerable_adr(char *adr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
if (stat(path, &stbuf) == -1)
|
||||||
|
return 0;
|
||||||
|
if (S_ISREG(stbuf.st_mode))
|
||||||
|
return 1;
|
||||||
|
if (S_ISBLK(stbuf.st_mode))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Estimate the potential payload capacity of a file address.
|
/** Estimate the potential payload capacity of a file address.
|
||||||
@param path The address of the file to be examined. If it does not
|
@param path The address of the file to be examined. If it does not
|
||||||
exist yet, then the directory will be inquired.
|
exist yet, then the directory will be inquired.
|
||||||
@ -214,7 +285,7 @@ int burn_os_stdio_capacity(char *path, off_t *bytes)
|
|||||||
|
|
||||||
if (statvfs(testpath, &vfsbuf) == -1)
|
if (statvfs(testpath, &vfsbuf) == -1)
|
||||||
return -2;
|
return -2;
|
||||||
*bytes = add_size + ((off_t) vfsbuf.f_bsize) *
|
*bytes = add_size + ((off_t) vfsbuf.f_frsize) *
|
||||||
(off_t) vfsbuf.f_bavail;
|
(off_t) vfsbuf.f_bavail;
|
||||||
|
|
||||||
#else /* Libburn_os_has_statvfS */
|
#else /* Libburn_os_has_statvfS */
|
||||||
@ -227,3 +298,39 @@ int burn_os_stdio_capacity(char *path, off_t *bytes)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -29,12 +29,28 @@ and of deriving the following system specific files from existing examples:
|
|||||||
Said sg-*.c operations are defined by a public function interface, which has
|
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:
|
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
|
sg_give_next_adr() iterates over the set of potentially useful drive
|
||||||
address strings.
|
address strings.
|
||||||
|
|
||||||
scsi_enumerate_drives() brings all available, not-whitelist-banned, and
|
scsi_enumerate_drives() brings all available, not-whitelist-banned, and
|
||||||
accessible drives into libburn's list of drives.
|
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_drive_is_open() tells wether libburn has the given drive in use.
|
||||||
|
|
||||||
sg_grab() opens the drive for SCSI commands and ensures
|
sg_grab() opens the drive for SCSI commands and ensures
|
||||||
@ -48,8 +64,25 @@ sg_issue_command() sends a SCSI command to the drive, receives reply,
|
|||||||
|
|
||||||
sg_obtain_scsi_adr() tries to obtain SCSI address parameters.
|
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_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:".
|
Porting hints are marked by the text "PORTING:".
|
||||||
Send feedback to libburn-hackers@pykix.org .
|
Send feedback to libburn-hackers@pykix.org .
|
||||||
@ -230,6 +263,61 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
|
|||||||
/* ------------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
|
||||||
|
/** 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)
|
||||||
|
{
|
||||||
|
strcpy(msg, "internal FreeBSD CAM adapter sg-freebsd-port");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Performs global initialization of the SCSI transport adapter and eventually
|
||||||
|
needed operating system facilities. Checks for compatibility 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.
|
/** Returns the next index number and the next enumerated drive address.
|
||||||
The enumeration has to cover all available and accessible drives. It is
|
The enumeration has to cover all available and accessible drives. It is
|
||||||
allowed to return addresses of drives which are not available but under
|
allowed to return addresses of drives which are not available but under
|
||||||
@ -299,7 +387,7 @@ try_item:; /* This spaghetti loop keeps the number of tabs small */
|
|||||||
break;
|
break;
|
||||||
snprintf(buf, sizeof (buf), "/dev/%s%d",
|
snprintf(buf, sizeof (buf), "/dev/%s%d",
|
||||||
result->periph_name, result->unit_number);
|
result->periph_name, result->unit_number);
|
||||||
if(adr_size <= strlen(buf)
|
if(adr_size <= strlen(buf))
|
||||||
return -1;
|
return -1;
|
||||||
strcpy(adr, buf);
|
strcpy(adr, buf);
|
||||||
|
|
||||||
@ -323,7 +411,7 @@ try_item:; /* This spaghetti loop keeps the number of tabs small */
|
|||||||
int scsi_enumerate_drives(void)
|
int scsi_enumerate_drives(void)
|
||||||
{
|
{
|
||||||
burn_drive_enumerator_t idx;
|
burn_drive_enumerator_t idx;
|
||||||
int initialize = 1;
|
int initialize = 1, ret;
|
||||||
char buf[64];
|
char buf[64];
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
@ -338,6 +426,7 @@ int scsi_enumerate_drives(void)
|
|||||||
idx.result->target_lun);
|
idx.result->target_lun);
|
||||||
}
|
}
|
||||||
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
|
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -360,11 +449,12 @@ int sg_drive_is_open(struct burn_drive * d)
|
|||||||
*/
|
*/
|
||||||
int sg_grab(struct burn_drive *d)
|
int sg_grab(struct burn_drive *d)
|
||||||
{
|
{
|
||||||
int count;
|
|
||||||
struct cam_device *cam;
|
struct cam_device *cam;
|
||||||
|
|
||||||
if(d->cam != NULL)
|
if(d->cam != NULL) {
|
||||||
return 0;
|
d->released = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
cam = cam_open_device(d->devname, O_RDWR);
|
cam = cam_open_device(d->devname, O_RDWR);
|
||||||
if (cam == NULL) {
|
if (cam == NULL) {
|
||||||
@ -515,7 +605,7 @@ int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
|
|||||||
int *target_no, int *lun_no)
|
int *target_no, int *lun_no)
|
||||||
{
|
{
|
||||||
burn_drive_enumerator_t idx;
|
burn_drive_enumerator_t idx;
|
||||||
int initialize = 1;
|
int initialize = 1, ret;
|
||||||
char buf[64];
|
char buf[64];
|
||||||
struct periph_match_result* result;
|
struct periph_match_result* result;
|
||||||
|
|
||||||
@ -524,7 +614,7 @@ int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
|
|||||||
initialize = 0;
|
initialize = 0;
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
break;
|
break;
|
||||||
if (strcmp(adr, buf) != 0)
|
if (strcmp(path, buf) != 0)
|
||||||
continue;
|
continue;
|
||||||
result = &(idx->ccb.cdm.matches[i].result.periph_result);
|
result = &(idx->ccb.cdm.matches[i].result.periph_result);
|
||||||
*bus_no = result->path_id;
|
*bus_no = result->path_id;
|
||||||
@ -546,7 +636,7 @@ int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
|
|||||||
int sg_is_enumerable_adr(char* adr)
|
int sg_is_enumerable_adr(char* adr)
|
||||||
{
|
{
|
||||||
burn_drive_enumerator_t idx;
|
burn_drive_enumerator_t idx;
|
||||||
int initialize = 1;
|
int initialize = 1, ret;
|
||||||
char buf[64];
|
char buf[64];
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
@ -564,6 +654,47 @@ int sg_is_enumerable_adr(char* adr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ts B00115 */
|
||||||
|
/* Return 1 if the given path leads to a regular file or a device that can be
|
||||||
|
seeked, written, and read with 2 kB granularity.
|
||||||
|
*/
|
||||||
|
int burn_os_is_2k_seekrw(char *path, int flag)
|
||||||
|
{
|
||||||
|
struct stat stbuf;
|
||||||
|
char *spt;
|
||||||
|
int i, e;
|
||||||
|
|
||||||
|
if (stat(path, &stbuf) == -1)
|
||||||
|
return 0;
|
||||||
|
if (S_ISREG(stbuf.st_mode))
|
||||||
|
return 1;
|
||||||
|
if (!S_ISCHR(stbuf.st_mode))
|
||||||
|
return 0;
|
||||||
|
spt = strrchr(path, '/');
|
||||||
|
if (spt == NULL)
|
||||||
|
spt = path;
|
||||||
|
else
|
||||||
|
spt++;
|
||||||
|
e = strlen(spt);
|
||||||
|
for (i = strlen(spt) - 1; i > 0; i--)
|
||||||
|
if (spt[i] >= '0' && spt[i] <= '9')
|
||||||
|
e = i;
|
||||||
|
if (strncmp(spt, "da", e) == 0) /* SCSI disk. E.g. USB stick. */
|
||||||
|
return 1;
|
||||||
|
if (strncmp(spt, "cd", e) == 0) /* SCSI CD drive might be writeable. */
|
||||||
|
return 1;
|
||||||
|
if (strncmp(spt, "ad", e) == 0) /* IDE hard drive */
|
||||||
|
return 1;
|
||||||
|
if (strncmp(spt, "acd", e) == 0) /* IDE CD drive might be writeable */
|
||||||
|
return 1;
|
||||||
|
if (strncmp(spt, "fd", e) == 0) /* Floppy disk */
|
||||||
|
return 1;
|
||||||
|
if (strncmp(spt, "fla", e) == 0) /* Flash drive */
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ts A70909 */
|
/* ts A70909 */
|
||||||
/** Estimate the potential payload capacity of a file address.
|
/** Estimate the potential payload capacity of a file address.
|
||||||
@param path The address of the file to be examined. If it does not
|
@param path The address of the file to be examined. If it does not
|
||||||
@ -623,9 +754,45 @@ int burn_os_stdio_capacity(char *path, off_t *bytes)
|
|||||||
if (testpath[0]) {
|
if (testpath[0]) {
|
||||||
if (statvfs(testpath, &vfsbuf) == -1)
|
if (statvfs(testpath, &vfsbuf) == -1)
|
||||||
return -2;
|
return -2;
|
||||||
*bytes = add_size + ((off_t) vfsbuf.f_bsize) *
|
*bytes = add_size + ((off_t) vfsbuf.f_frsize) *
|
||||||
(off_t) vfsbuf.f_bavail;
|
(off_t) vfsbuf.f_bavail;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/file.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/poll.h>
|
#include <sys/poll.h>
|
||||||
@ -16,10 +17,12 @@
|
|||||||
|
|
||||||
#include <err.h> /* XXX */
|
#include <err.h> /* XXX */
|
||||||
|
|
||||||
|
|
||||||
/* ts A70909 */
|
/* ts A70909 */
|
||||||
#include <sys/statvfs.h>
|
#include <sys/statvfs.h>
|
||||||
|
|
||||||
|
/* ts B00121 */
|
||||||
|
#include <sys/disk.h> /* DIOCGMEDIASIZE */
|
||||||
|
|
||||||
|
|
||||||
#include "transport.h"
|
#include "transport.h"
|
||||||
#include "drive.h"
|
#include "drive.h"
|
||||||
@ -54,6 +57,79 @@ int burn_drive_is_banned(char *device_address);
|
|||||||
int mmc_function_spy(struct burn_drive *d, char * text);
|
int mmc_function_spy(struct burn_drive *d, char * text);
|
||||||
|
|
||||||
|
|
||||||
|
/* ts B00113
|
||||||
|
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;
|
||||||
|
|
||||||
|
/* ts B00114 */
|
||||||
|
/* Storage object is in libburn/init.c
|
||||||
|
whether to strive for exclusive access to the drive
|
||||||
|
*/
|
||||||
|
extern int burn_sg_open_o_excl;
|
||||||
|
|
||||||
|
|
||||||
|
/* ts A91227 */
|
||||||
|
/** 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)
|
||||||
|
{
|
||||||
|
strcpy(msg, "internal FreeBSD CAM adapter sg-freebsd");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ts A91227 */
|
||||||
|
/** Performs global initialization of the SCSI transport adapter and eventually
|
||||||
|
needed operating system facilities. Checks for compatibility 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ts A91227 */
|
||||||
|
/** 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ts A61021 : Moved most code from scsi_enumerate_drives under
|
/* ts A61021 : Moved most code from scsi_enumerate_drives under
|
||||||
sg_give_next_adr() */
|
sg_give_next_adr() */
|
||||||
/* Some helper functions for scsi_give_next_adr() */
|
/* Some helper functions for scsi_give_next_adr() */
|
||||||
@ -72,6 +148,8 @@ static int sg_init_enumerator(burn_drive_enumerator_t *idx_)
|
|||||||
|
|
||||||
if ((idx->fd = open(XPT_DEVICE, O_RDWR)) == -1) {
|
if ((idx->fd = open(XPT_DEVICE, O_RDWR)) == -1) {
|
||||||
warn("couldn't open %s", XPT_DEVICE);
|
warn("couldn't open %s", XPT_DEVICE);
|
||||||
|
free(idx);
|
||||||
|
idx = NULL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +221,7 @@ static int sg_next_enumeration_buffer(burn_drive_enumerator_t *idx_)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Returns the next index number and the next enumerated drive address.
|
/** Returns the next index object state and the next enumerated drive address.
|
||||||
@param idx An opaque handle. Make no own theories about it.
|
@param idx An opaque handle. Make no own theories about it.
|
||||||
@param adr Takes the reply
|
@param adr Takes the reply
|
||||||
@param adr_size Gives maximum size of reply including final 0
|
@param adr_size Gives maximum size of reply including final 0
|
||||||
@ -197,9 +275,15 @@ int sg_give_next_adr(burn_drive_enumerator_t *idx_,
|
|||||||
struct periph_match_result* result;
|
struct periph_match_result* result;
|
||||||
|
|
||||||
result = &(idx->ccb.cdm.matches[idx->i].result.periph_result);
|
result = &(idx->ccb.cdm.matches[idx->i].result.periph_result);
|
||||||
|
/* ts B00112 : we really want only "cd" devices.
|
||||||
|
|
||||||
if (idx->skip_device ||
|
if (idx->skip_device ||
|
||||||
strcmp(result->periph_name, "pass") == 0)
|
strcmp(result->periph_name, "pass") == 0)
|
||||||
break;
|
break;
|
||||||
|
*/
|
||||||
|
if (idx->skip_device ||
|
||||||
|
strcmp(result->periph_name, "cd") != 0)
|
||||||
|
break;
|
||||||
ret = snprintf(adr, adr_size, "/dev/%s%d",
|
ret = snprintf(adr, adr_size, "/dev/%s%d",
|
||||||
result->periph_name, result->unit_number);
|
result->periph_name, result->unit_number);
|
||||||
if(ret >= adr_size)
|
if(ret >= adr_size)
|
||||||
@ -210,7 +294,7 @@ int sg_give_next_adr(burn_drive_enumerator_t *idx_,
|
|||||||
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
/* printf(stderr, "unknown match type\n"); */
|
/* fprintf(stderr, "unknown match type\n"); */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
(idx->i)++;
|
(idx->i)++;
|
||||||
@ -285,6 +369,10 @@ int sg_close_drive(struct burn_drive * d)
|
|||||||
cam_close_device(d->cam);
|
cam_close_device(d->cam);
|
||||||
d->cam = NULL;
|
d->cam = NULL;
|
||||||
}
|
}
|
||||||
|
if (d->lock_fd > 0) {
|
||||||
|
close(d->lock_fd);
|
||||||
|
d->lock_fd = -1;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,7 +426,9 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
|
|||||||
out.lun = lun_no;
|
out.lun = lun_no;
|
||||||
|
|
||||||
out.devname = burn_strdup(fname);
|
out.devname = burn_strdup(fname);
|
||||||
|
|
||||||
out.cam = NULL;
|
out.cam = NULL;
|
||||||
|
out.lock_fd = -1;
|
||||||
|
|
||||||
out.start_lba= -2000000000;
|
out.start_lba= -2000000000;
|
||||||
out.end_lba= -2000000000;
|
out.end_lba= -2000000000;
|
||||||
@ -430,6 +520,8 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
|
|||||||
/* Operating system adapter is CAM */
|
/* Operating system adapter is CAM */
|
||||||
/* Adapter specific handles and data */
|
/* Adapter specific handles and data */
|
||||||
out.cam = NULL;
|
out.cam = NULL;
|
||||||
|
out.lock_fd = -1;
|
||||||
|
|
||||||
/* Adapter specific functions */
|
/* Adapter specific functions */
|
||||||
out.grab = sg_grab;
|
out.grab = sg_grab;
|
||||||
out.release = sg_release;
|
out.release = sg_release;
|
||||||
@ -442,14 +534,143 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
|
|||||||
|
|
||||||
#endif /* ! Scsi_freebsd_make_own_enumeratE */
|
#endif /* ! Scsi_freebsd_make_own_enumeratE */
|
||||||
|
|
||||||
/* ts A61021: do not believe this:
|
|
||||||
we use the sg reference count to decide whether we can use the
|
/* Lock the inode associated to dev_fd and the inode associated to devname.
|
||||||
drive or not.
|
Return OS errno, number of pass device of dev_fd, locked fd to devname,
|
||||||
if refcount is not one, drive is open somewhere else.
|
error message.
|
||||||
|
A return value of > 0 means success, <= 0 means failure.
|
||||||
*/
|
*/
|
||||||
|
static int freebsd_dev_lock(int dev_fd, char *devname,
|
||||||
|
int *os_errno, int *pass_dev_no, int *lock_fd, char msg[4096],
|
||||||
|
int flag)
|
||||||
|
{
|
||||||
|
int lock_denied = 0, fd_stbuf_valid, name_stbuf_valid, i, pass_l = 100;
|
||||||
|
int max_retry = 3, tries = 0;
|
||||||
|
struct stat fd_stbuf, name_stbuf;
|
||||||
|
char pass_name[16], *lock_name;
|
||||||
|
|
||||||
|
*os_errno = 0;
|
||||||
|
*pass_dev_no = -1;
|
||||||
|
*lock_fd = -1;
|
||||||
|
msg[0] = 0;
|
||||||
|
|
||||||
|
fd_stbuf_valid = !fstat(dev_fd, &fd_stbuf);
|
||||||
|
|
||||||
|
/* Try to find name of pass device by inode number */
|
||||||
|
lock_name = (char *) "effective device";
|
||||||
|
if(fd_stbuf_valid) {
|
||||||
|
for (i = 0; i < pass_l; i++) {
|
||||||
|
sprintf(pass_name, "/dev/pass%d", i);
|
||||||
|
if (stat(pass_name, &name_stbuf) != -1)
|
||||||
|
if(fd_stbuf.st_ino == name_stbuf.st_ino &&
|
||||||
|
fd_stbuf.st_dev == name_stbuf.st_dev)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i < pass_l) {
|
||||||
|
lock_name = pass_name;
|
||||||
|
*pass_dev_no = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
name_stbuf_valid = !stat(devname, &name_stbuf);
|
||||||
|
for (tries= 0; tries <= max_retry; tries++) {
|
||||||
|
lock_denied = flock(dev_fd, LOCK_EX | LOCK_NB);
|
||||||
|
*os_errno = errno;
|
||||||
|
if (lock_denied) {
|
||||||
|
if (errno == EAGAIN && tries < max_retry) {
|
||||||
|
/* <<< debugging
|
||||||
|
fprintf(stderr,
|
||||||
|
"\nlibcdio_DEBUG: EAGAIN pass, tries= %d\n",
|
||||||
|
tries);
|
||||||
|
*/
|
||||||
|
usleep(2000000);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sprintf(msg,
|
||||||
|
"Device busy. flock(LOCK_EX) failed on %s of %s",
|
||||||
|
strlen(lock_name) > 2000 || *pass_dev_no < 0 ?
|
||||||
|
"pass device" : lock_name,
|
||||||
|
strlen(devname) > 2000 ? "drive" : devname);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
fprintf(stderr, "libburn_DEBUG: flock obtained on %s of %s\n",
|
||||||
|
lock_name, devname);
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Eventually lock the official device node too */
|
||||||
|
if (fd_stbuf_valid && name_stbuf_valid &&
|
||||||
|
(fd_stbuf.st_ino != name_stbuf.st_ino ||
|
||||||
|
fd_stbuf.st_dev != name_stbuf.st_dev)) {
|
||||||
|
|
||||||
|
*lock_fd = open(devname, O_RDONLY);
|
||||||
|
if (*lock_fd == 0) {
|
||||||
|
close(*lock_fd);
|
||||||
|
*lock_fd = -1;
|
||||||
|
} if (*lock_fd > 0) {
|
||||||
|
for (tries = 0; tries <= max_retry; tries++) {
|
||||||
|
lock_denied =
|
||||||
|
flock(*lock_fd, LOCK_EX | LOCK_NB);
|
||||||
|
if (lock_denied) {
|
||||||
|
if (errno == EAGAIN &&
|
||||||
|
tries < max_retry) {
|
||||||
|
/* <<< debugging
|
||||||
|
fprintf(stderr,
|
||||||
|
"\nlibcdio_DEBUG: EAGAIN dev, tries= %d\n",
|
||||||
|
tries);
|
||||||
|
*/
|
||||||
|
|
||||||
|
usleep(2000000);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
close(*lock_fd);
|
||||||
|
*lock_fd = -1;
|
||||||
|
sprintf(msg,
|
||||||
|
"Device busy. flock(LOCK_EX) failed on %s",
|
||||||
|
strlen(devname) > 4000 ? "drive" : devname);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
fprintf(stderr, "libburn_DEBUG: flock obtained on %s\n",
|
||||||
|
devname);
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int sg_lock(struct burn_drive *d, int flag)
|
||||||
|
{
|
||||||
|
int ret, os_errno, pass_dev_no = -1, flock_fd = -1;
|
||||||
|
char msg[4096];
|
||||||
|
|
||||||
|
ret = freebsd_dev_lock(d->cam->fd, d->devname,
|
||||||
|
&os_errno, &pass_dev_no, &flock_fd, msg, 0);
|
||||||
|
if (ret <= 0) {
|
||||||
|
libdax_msgs_submit(libdax_messenger, d->global_index,
|
||||||
|
0x00020008,
|
||||||
|
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
msg, os_errno, 0);
|
||||||
|
sg_close_drive(d);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (d->lock_fd > 0)
|
||||||
|
close(d->lock_fd);
|
||||||
|
d->lock_fd = flock_fd;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int sg_grab(struct burn_drive *d)
|
int sg_grab(struct burn_drive *d)
|
||||||
{
|
{
|
||||||
int count;
|
|
||||||
struct cam_device *cam;
|
struct cam_device *cam;
|
||||||
|
|
||||||
if (mmc_function_spy(d, "sg_grab") <= 0)
|
if (mmc_function_spy(d, "sg_grab") <= 0)
|
||||||
@ -462,22 +683,19 @@ int sg_grab(struct burn_drive *d)
|
|||||||
|
|
||||||
cam = cam_open_device(d->devname, O_RDWR);
|
cam = cam_open_device(d->devname, O_RDWR);
|
||||||
if (cam == NULL) {
|
if (cam == NULL) {
|
||||||
libdax_msgs_submit(libdax_messenger, d->global_index, 0x00020003,
|
libdax_msgs_submit(libdax_messenger, d->global_index,
|
||||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
0x00020003,
|
||||||
"Could not grab drive", 0/*os_errno*/, 0);
|
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
"Could not grab drive", errno, 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* er = ioctl(fd, SG_GET_ACCESS_COUNT, &count);*/
|
d->cam = cam;
|
||||||
count = 1;
|
if (burn_sg_open_o_excl & 63)
|
||||||
if (1 == count) {
|
if (sg_lock(d, 0) <= 0)
|
||||||
d->cam = cam;
|
return 0;
|
||||||
fcntl(cam->fd, F_SETOWN, getpid());
|
fcntl(cam->fd, F_SETOWN, getpid());
|
||||||
d->released = 0;
|
d->released = 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
|
||||||
burn_print(1, "could not acquire drive - already open\n");
|
|
||||||
sg_close_drive(d);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -505,11 +723,11 @@ int sg_release(struct burn_drive *d)
|
|||||||
|
|
||||||
int sg_issue_command(struct burn_drive *d, struct command *c)
|
int sg_issue_command(struct burn_drive *d, struct command *c)
|
||||||
{
|
{
|
||||||
int done = 0;
|
int done = 0, err, sense_len, ret;
|
||||||
int err;
|
|
||||||
union ccb *ccb;
|
union ccb *ccb;
|
||||||
|
|
||||||
char buf[161];
|
char buf[161];
|
||||||
|
static FILE *fp = NULL;
|
||||||
|
|
||||||
snprintf(buf, sizeof (buf), "sg_issue_command d->cam=%p d->released=%d",
|
snprintf(buf, sizeof (buf), "sg_issue_command d->cam=%p d->released=%d",
|
||||||
(void*)d->cam, d->released);
|
(void*)d->cam, d->released);
|
||||||
mmc_function_spy(NULL, buf);
|
mmc_function_spy(NULL, buf);
|
||||||
@ -518,6 +736,15 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
|
|||||||
c->error = 0;
|
c->error = 0;
|
||||||
return 0;
|
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);
|
||||||
|
|
||||||
c->error = 0;
|
c->error = 0;
|
||||||
|
|
||||||
@ -566,12 +793,6 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
|
|||||||
/* touch page so we can use valgrind */
|
/* touch page so we can use valgrind */
|
||||||
memset(c->page->data, 0, BUFFER_SIZE);
|
memset(c->page->data, 0, BUFFER_SIZE);
|
||||||
} else {
|
} else {
|
||||||
/* ts A90430 */
|
|
||||||
/* a ssert(c->page->bytes > 0); */
|
|
||||||
if (c->page->bytes <= 0) {
|
|
||||||
c->error = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
ccb->csio.dxfer_len = c->page->bytes;
|
ccb->csio.dxfer_len = c->page->bytes;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -587,20 +808,24 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
|
|||||||
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
"Failed to transfer command to drive",
|
"Failed to transfer command to drive",
|
||||||
errno, 0);
|
errno, 0);
|
||||||
cam_freeccb(ccb);
|
|
||||||
sg_close_drive(d);
|
sg_close_drive(d);
|
||||||
d->released = 1;
|
d->released = 1;
|
||||||
d->busy = BURN_DRIVE_IDLE;
|
d->busy = BURN_DRIVE_IDLE;
|
||||||
c->error = 1;
|
c->error = 1;
|
||||||
return -1;
|
{ret = -1; goto ex;}
|
||||||
}
|
}
|
||||||
/* XXX */
|
/* XXX */
|
||||||
|
|
||||||
|
/* ts B00110 */
|
||||||
|
/* Better curb sense_len */
|
||||||
|
sense_len = ccb->csio.sense_len;
|
||||||
|
if (sense_len > sizeof(c->sense))
|
||||||
|
sense_len = sizeof(c->sense);
|
||||||
memcpy(c->sense, &ccb->csio.sense_data, ccb->csio.sense_len);
|
memcpy(c->sense, &ccb->csio.sense_data, ccb->csio.sense_len);
|
||||||
if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
|
if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
|
||||||
if (!c->retry) {
|
if (!c->retry) {
|
||||||
c->error = 1;
|
c->error = 1;
|
||||||
cam_freeccb(ccb);
|
{ret = 1; goto ex;}
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
switch (scsi_error(d, c->sense, 0)) {
|
switch (scsi_error(d, c->sense, 0)) {
|
||||||
case RETRY:
|
case RETRY:
|
||||||
@ -615,8 +840,58 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
|
|||||||
done = 1;
|
done = 1;
|
||||||
}
|
}
|
||||||
} while (!done);
|
} while (!done);
|
||||||
|
ret = 1;
|
||||||
|
ex:;
|
||||||
|
if (c->error)
|
||||||
|
scsi_notify_error(d, c, c->sense, 18, 0);
|
||||||
|
|
||||||
|
if (burn_sg_log_scsi & 3)
|
||||||
|
/* >>> Need own duration time measurement. Then remove bit1 */
|
||||||
|
scsi_log_err(c, fp, c->sense, 0, (c->error != 0) | 2);
|
||||||
|
|
||||||
cam_freeccb(ccb);
|
cam_freeccb(ccb);
|
||||||
return 1;
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ts B00115 */
|
||||||
|
/* Return 1 if the given path leads to a regular file or a device that can be
|
||||||
|
seeked, read and eventually written with 2 kB granularity.
|
||||||
|
*/
|
||||||
|
int burn_os_is_2k_seekrw(char *path, int flag)
|
||||||
|
{
|
||||||
|
struct stat stbuf;
|
||||||
|
char *spt;
|
||||||
|
int i, e;
|
||||||
|
|
||||||
|
if (stat(path, &stbuf) == -1)
|
||||||
|
return 0;
|
||||||
|
if (S_ISREG(stbuf.st_mode))
|
||||||
|
return 1;
|
||||||
|
if (!S_ISCHR(stbuf.st_mode))
|
||||||
|
return 0;
|
||||||
|
spt = strrchr(path, '/');
|
||||||
|
if (spt == NULL)
|
||||||
|
spt = path;
|
||||||
|
else
|
||||||
|
spt++;
|
||||||
|
e = strlen(spt);
|
||||||
|
for (i = strlen(spt) - 1; i > 0; i--)
|
||||||
|
if (spt[i] >= '0' && spt[i] <= '9')
|
||||||
|
e = i;
|
||||||
|
if (strncmp(spt, "da", e) == 0) /* SCSI disk. E.g. USB stick. */
|
||||||
|
return 1;
|
||||||
|
if (strncmp(spt, "cd", e) == 0) /* SCSI CD drive might be writeable. */
|
||||||
|
return 1;
|
||||||
|
if (strncmp(spt, "ad", e) == 0) /* IDE hard drive */
|
||||||
|
return 1;
|
||||||
|
if (strncmp(spt, "acd", e) == 0) /* IDE CD drive might be writeable */
|
||||||
|
return 1;
|
||||||
|
if (strncmp(spt, "fd", e) == 0) /* Floppy disk */
|
||||||
|
return 1;
|
||||||
|
if (strncmp(spt, "fla", e) == 0) /* Flash drive */
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -637,6 +912,7 @@ int burn_os_stdio_capacity(char *path, off_t *bytes)
|
|||||||
char testpath[4096], *cpt;
|
char testpath[4096], *cpt;
|
||||||
long blocks;
|
long blocks;
|
||||||
off_t add_size = 0;
|
off_t add_size = 0;
|
||||||
|
int fd, ret;
|
||||||
|
|
||||||
testpath[0] = 0;
|
testpath[0] = 0;
|
||||||
blocks = *bytes / 512;
|
blocks = *bytes / 512;
|
||||||
@ -671,6 +947,15 @@ int burn_os_stdio_capacity(char *path, off_t *bytes)
|
|||||||
#endif /* Libburn_if_this_was_linuX */
|
#endif /* Libburn_if_this_was_linuX */
|
||||||
|
|
||||||
|
|
||||||
|
} else if(S_ISCHR(stbuf.st_mode)) {
|
||||||
|
fd = open(path, O_RDONLY);
|
||||||
|
if (fd == -1)
|
||||||
|
return -2;
|
||||||
|
ret = ioctl(fd, DIOCGMEDIASIZE, &add_size);
|
||||||
|
close(fd);
|
||||||
|
if (ret == -1)
|
||||||
|
return -2;
|
||||||
|
*bytes = add_size;
|
||||||
} else if(S_ISREG(stbuf.st_mode)) {
|
} else if(S_ISREG(stbuf.st_mode)) {
|
||||||
add_size = stbuf.st_blocks * (off_t) 512;
|
add_size = stbuf.st_blocks * (off_t) 512;
|
||||||
strcpy(testpath, path);
|
strcpy(testpath, path);
|
||||||
@ -680,9 +965,45 @@ int burn_os_stdio_capacity(char *path, off_t *bytes)
|
|||||||
if (testpath[0]) {
|
if (testpath[0]) {
|
||||||
if (statvfs(testpath, &vfsbuf) == -1)
|
if (statvfs(testpath, &vfsbuf) == -1)
|
||||||
return -2;
|
return -2;
|
||||||
*bytes = add_size + ((off_t) vfsbuf.f_bsize) *
|
*bytes = add_size + ((off_t) vfsbuf.f_frsize) *
|
||||||
(off_t) vfsbuf.f_bavail;
|
(off_t) vfsbuf.f_bavail;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
928
libburn/sg-libcdio.c
Normal file
928
libburn/sg-libcdio.c
Normal file
@ -0,0 +1,928 @@
|
|||||||
|
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
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: GNU libcdio , for X/Open compliant operating systems
|
||||||
|
|
||||||
|
|
||||||
|
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 .
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/** 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 */
|
||||||
|
|
||||||
|
#ifdef __linux
|
||||||
|
/* for ioctl(BLKGETSIZE) */
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <linux/fs.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __FreeBSD__
|
||||||
|
#define Libburn_is_on_freebsD 1
|
||||||
|
#endif
|
||||||
|
#ifdef __FreeBSD_kernel__
|
||||||
|
#define Libburn_is_on_freebsD 1
|
||||||
|
#endif
|
||||||
|
#ifdef Libburn_is_on_freebsD
|
||||||
|
/* To avoid ATAPI devices */
|
||||||
|
#define Libburn_guess_freebsd_atapi_devicE 1
|
||||||
|
/* To obtain size of disk-like devices */
|
||||||
|
#include <sys/disk.h> /* DIOCGMEDIASIZE */
|
||||||
|
#endif /* Libburn_is_on_freebsD */
|
||||||
|
|
||||||
|
#define Libburn_guess_freebsd_atapi_devicE 1
|
||||||
|
|
||||||
|
#include <cdio/cdio.h>
|
||||||
|
#include <cdio/logging.h>
|
||||||
|
#include <cdio/mmc.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* The waiting time before eventually retrying a failed SCSI command.
|
||||||
|
Before each retry wait Libburn_sg_linux_retry_incR longer than with
|
||||||
|
the previous one.
|
||||||
|
*/
|
||||||
|
#define Libburn_sg_libcdio_retry_usleeP 100000
|
||||||
|
#define Libburn_sg_libcdio_retry_incR 100000
|
||||||
|
|
||||||
|
|
||||||
|
/** PORTING : ------ libburn portable headers and definitions ----- */
|
||||||
|
|
||||||
|
#include "transport.h"
|
||||||
|
#include "drive.h"
|
||||||
|
#include "sg.h"
|
||||||
|
#include "spc.h"
|
||||||
|
/* collides with symbols of <cdio/mmc.h>
|
||||||
|
#include "mmc.h"
|
||||||
|
*/
|
||||||
|
#include "sbc.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "toc.h"
|
||||||
|
#include "util.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)
|
||||||
|
{
|
||||||
|
CdIo_t *p_cdio;
|
||||||
|
|
||||||
|
if (d->p_cdio != NULL) {
|
||||||
|
p_cdio = (CdIo_t *) d->p_cdio;
|
||||||
|
cdio_destroy(p_cdio);
|
||||||
|
d->p_cdio = NULL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int sg_give_next_adr_raw(burn_drive_enumerator_t *idx,
|
||||||
|
char adr[], int adr_size, int initialize)
|
||||||
|
{
|
||||||
|
char **pos;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
if (initialize == 1) {
|
||||||
|
idx->pos = idx->ppsz_cd_drives =
|
||||||
|
cdio_get_devices(DRIVER_DEVICE);
|
||||||
|
if (idx->ppsz_cd_drives == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (pos = idx->ppsz_cd_drives ; pos != NULL; pos++) {
|
||||||
|
if (*pos == NULL)
|
||||||
|
break;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (initialize == -1) {
|
||||||
|
if (*(idx->ppsz_cd_drives) != NULL)
|
||||||
|
cdio_free_device_list(idx->ppsz_cd_drives);
|
||||||
|
idx->ppsz_cd_drives = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef Libburn_guess_freebsd_atapi_devicE
|
||||||
|
try_next:;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (idx->pos == NULL)
|
||||||
|
return 0;
|
||||||
|
if (*(idx->pos) == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#ifdef Libburn_guess_freebsd_atapi_devicE
|
||||||
|
if (strncmp(*(idx->pos), "/dev/acd", 8) == 0) {
|
||||||
|
(idx->pos)++;
|
||||||
|
goto try_next;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (strlen(*(idx->pos)) >= adr_size)
|
||||||
|
return -1;
|
||||||
|
strcpy(adr, *(idx->pos));
|
||||||
|
(idx->pos)++;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------- */
|
||||||
|
/* 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, char *cdio_name,
|
||||||
|
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 libcdio */
|
||||||
|
/* Adapter specific handles and data */
|
||||||
|
out.p_cdio = NULL;
|
||||||
|
strcpy(out.libcdio_name, fname);
|
||||||
|
if (strlen(cdio_name) < sizeof(out.libcdio_name))
|
||||||
|
strcpy(out.libcdio_name, cdio_name);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
char *version_text;
|
||||||
|
|
||||||
|
sprintf(msg, "sg-libcdio h%d with libcdio ", LIBCDIO_VERSION_NUM);
|
||||||
|
|
||||||
|
#if LIBCDIO_VERSION_NUM < 83
|
||||||
|
|
||||||
|
LIBBURN_MISCONFIGURATION = 0;
|
||||||
|
INTENTIONAL_ABORT_OF_COMPILATION__HEADERFILE_cdio_version_dot_h_TOO_OLD__NEED_libcdio_VERSION_NUM_83 = 0;
|
||||||
|
LIBBURN_MISCONFIGURATION_ = 0;
|
||||||
|
|
||||||
|
#endif /* LIBCDIO_VERSION_NUM < 83 */
|
||||||
|
|
||||||
|
version_text = (char *) cdio_version_string;
|
||||||
|
strncat(msg, version_text, 800);
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
int cdio_ver;
|
||||||
|
char *msg_pt;
|
||||||
|
|
||||||
|
cdio_loglevel_default = CDIO_LOG_ASSERT;
|
||||||
|
|
||||||
|
msg[0] = 0;
|
||||||
|
sg_id_string(msg, 0);
|
||||||
|
cdio_ver = libcdio_version_num;
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
|
||||||
|
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
msg , 0, 0);
|
||||||
|
if (cdio_ver < LIBCDIO_VERSION_NUM) {
|
||||||
|
strcat(msg, " ---> ");
|
||||||
|
msg_pt = msg + strlen(msg);
|
||||||
|
sprintf(msg_pt,
|
||||||
|
"libcdio TOO OLD: numeric version %d , need at least %d",
|
||||||
|
cdio_ver, LIBCDIO_VERSION_NUM);
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1,
|
||||||
|
0x00000002,
|
||||||
|
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
msg_pt, 0, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** 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 latter.)
|
||||||
|
@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, recursion_count = 0;
|
||||||
|
char path[4096];
|
||||||
|
|
||||||
|
ret = sg_give_next_adr_raw(idx, adr, adr_size, initialize);
|
||||||
|
if (ret <= 0)
|
||||||
|
return ret;
|
||||||
|
if (strlen(adr) >= sizeof(path))
|
||||||
|
return ret;
|
||||||
|
strcpy(path, adr);
|
||||||
|
ret = burn_drive_resolve_link(path, adr, &recursion_count, 2);
|
||||||
|
return (ret >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** 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, recursion_count = 0;
|
||||||
|
int i_host_no = -1, i_channel_no = -1, i_target_no = -1, i_lun_no = -1;
|
||||||
|
char buf[4096], target[4096];
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
ret = sg_give_next_adr_raw(&idx, buf, sizeof(buf), initialize);
|
||||||
|
initialize = 0;
|
||||||
|
if (ret <= 0)
|
||||||
|
break;
|
||||||
|
ret = burn_drive_resolve_link(buf, target, &recursion_count,2);
|
||||||
|
if (ret <= 0)
|
||||||
|
strcpy(target, buf);
|
||||||
|
if (burn_drive_is_banned(target))
|
||||||
|
continue;
|
||||||
|
sg_obtain_scsi_adr(buf, &i_bus_no, &i_host_no,
|
||||||
|
&i_channel_no, &i_target_no, &i_lun_no);
|
||||||
|
enumerate_common(target, buf,
|
||||||
|
i_bus_no, i_host_no, i_channel_no,
|
||||||
|
i_target_no, i_lun_no);
|
||||||
|
}
|
||||||
|
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** 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->p_cdio != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** 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)
|
||||||
|
{
|
||||||
|
CdIo_t *p_cdio;
|
||||||
|
char *am_eff, msg[4096], *am_wanted;
|
||||||
|
int os_errno, second_try = 0;
|
||||||
|
|
||||||
|
if (d->p_cdio != NULL) {
|
||||||
|
d->released = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (d->libcdio_name[0] == 0) /* just to be sure it is initialized */
|
||||||
|
strcpy(d->libcdio_name, d->devname);
|
||||||
|
am_wanted = (burn_sg_open_o_excl & 63) ? "MMC_RDWR_EXCL" : "MMC_RDWR";
|
||||||
|
try_to_open:;
|
||||||
|
p_cdio = cdio_open_am(d->libcdio_name, DRIVER_DEVICE, am_wanted);
|
||||||
|
if (p_cdio == NULL) {
|
||||||
|
os_errno = errno;
|
||||||
|
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, os_errno, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
am_eff = (char *) cdio_get_arg(p_cdio, "access-mode");
|
||||||
|
if (strncmp(am_eff, "MMC_RDWR", 8) != 0) {
|
||||||
|
cdio_destroy(p_cdio);
|
||||||
|
if (!second_try) {
|
||||||
|
am_wanted = (burn_sg_open_o_excl & 63) ?
|
||||||
|
"MMC_RDWR" : "MMC_RDWR_EXCL";
|
||||||
|
second_try = 1;
|
||||||
|
goto try_to_open;
|
||||||
|
}
|
||||||
|
libdax_msgs_submit(libdax_messenger, d->global_index,
|
||||||
|
0x00020003,
|
||||||
|
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
"libcdio provides no MMC_RDWR access mode", 0, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->p_cdio = p_cdio;
|
||||||
|
d->released = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** 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->p_cdio == NULL) {
|
||||||
|
burn_print(1, "release an ungrabbed drive. die\n");
|
||||||
|
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 sense_valid = 0, i, usleep_time, timeout_ms;
|
||||||
|
time_t start_time;
|
||||||
|
driver_return_code_t i_status;
|
||||||
|
unsigned int dxfer_len;
|
||||||
|
static FILE *fp = NULL;
|
||||||
|
mmc_cdb_t cdb = {{0, }};
|
||||||
|
cdio_mmc_direction_t e_direction;
|
||||||
|
CdIo_t *p_cdio;
|
||||||
|
unsigned char *sense_pt = NULL;
|
||||||
|
|
||||||
|
c->error = 0;
|
||||||
|
if (d->p_cdio == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
p_cdio = (CdIo_t *) d->p_cdio;
|
||||||
|
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);
|
||||||
|
|
||||||
|
memcpy(cdb.field, c->opcode, c->oplen);
|
||||||
|
if (c->dir == TO_DRIVE) {
|
||||||
|
dxfer_len = c->page->bytes;
|
||||||
|
e_direction = SCSI_MMC_DATA_WRITE;
|
||||||
|
} else if (c->dir == FROM_DRIVE) {
|
||||||
|
if (c->dxfer_len >= 0)
|
||||||
|
dxfer_len = c->dxfer_len;
|
||||||
|
else
|
||||||
|
dxfer_len = BUFFER_SIZE;
|
||||||
|
e_direction = SCSI_MMC_DATA_READ;
|
||||||
|
/* touch page so we can use valgrind */
|
||||||
|
memset(c->page->data, 0, BUFFER_SIZE);
|
||||||
|
} else {
|
||||||
|
dxfer_len = 0;
|
||||||
|
e_direction = SCSI_MMC_DATA_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* retry-loop */
|
||||||
|
start_time = time(NULL);
|
||||||
|
timeout_ms = 200000;
|
||||||
|
for(i = 0; ; i++) {
|
||||||
|
|
||||||
|
i_status = mmc_run_cmd(p_cdio, timeout_ms, &cdb, e_direction,
|
||||||
|
dxfer_len, c->page->data);
|
||||||
|
sense_valid = mmc_last_cmd_sense(p_cdio, &sense_pt);
|
||||||
|
if (sense_valid >= 18)
|
||||||
|
memcpy(c->sense, sense_pt,
|
||||||
|
sense_valid >= sizeof(c->sense) ?
|
||||||
|
sizeof(c->sense) : sense_valid );
|
||||||
|
if (sense_pt != NULL)
|
||||||
|
free(sense_pt);
|
||||||
|
|
||||||
|
/* Regrettably mmc_run_cmd() does not clearly distinguish between transport
|
||||||
|
failure and SCSI error reply.
|
||||||
|
This reaction here would be for transport failure:
|
||||||
|
|
||||||
|
if (i_status != 0 && i_status != DRIVER_OP_ERROR) {
|
||||||
|
libdax_msgs_submit(libdax_messenger,
|
||||||
|
d->global_index, 0x0002010c,
|
||||||
|
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;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!sense_valid) {
|
||||||
|
memset(c->sense, 0, sizeof(c->sense));
|
||||||
|
if (i_status != 0) { /* set dummy sense */
|
||||||
|
/*LOGICAL UNIT NOT READY,CAUSE NOT REPORTABLE*/
|
||||||
|
c->sense[2] = 0x02;
|
||||||
|
c->sense[12] = 0x04;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
c->sense[2] &= 15;
|
||||||
|
|
||||||
|
if (i_status != 0 ||
|
||||||
|
(c->sense[2] || c->sense[12] || c->sense[13])) {
|
||||||
|
if (!c->retry) {
|
||||||
|
c->error = 1;
|
||||||
|
goto ex;
|
||||||
|
}
|
||||||
|
switch (scsi_error(d, c->sense, 18)) {
|
||||||
|
case RETRY:
|
||||||
|
break;
|
||||||
|
case FAIL:
|
||||||
|
c->error = 1;
|
||||||
|
goto ex;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Calming down retries and breaking up endless cycle
|
||||||
|
*/
|
||||||
|
usleep_time = Libburn_sg_libcdio_retry_usleeP +
|
||||||
|
i * Libburn_sg_libcdio_retry_incR;
|
||||||
|
if (time(NULL) + usleep_time / 1000000 - start_time >
|
||||||
|
timeout_ms / 1000 + 1) {
|
||||||
|
c->error = 1;
|
||||||
|
goto ex;
|
||||||
|
}
|
||||||
|
usleep(usleep_time);
|
||||||
|
} else
|
||||||
|
break; /* retry-loop */
|
||||||
|
} /* end of retry-loop */
|
||||||
|
|
||||||
|
ex:;
|
||||||
|
if (c->error)
|
||||||
|
scsi_notify_error(d, c, c->sense, 18, 0);
|
||||||
|
|
||||||
|
if (burn_sg_log_scsi & 3)
|
||||||
|
/* >>> Need own duration time measurement. Then remove bit1 */
|
||||||
|
scsi_log_err(c, fp, c->sense, 0, (c->error != 0) | 2);
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
CdIo_t *p_cdio;
|
||||||
|
char *tuple;
|
||||||
|
|
||||||
|
*bus_no = *host_no = *channel_no = *target_no = *lun_no = -1;
|
||||||
|
|
||||||
|
p_cdio = cdio_open(path, DRIVER_DEVICE);
|
||||||
|
if (p_cdio == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Try whether a bus,host,channel,target,lun address tuple is
|
||||||
|
available */
|
||||||
|
tuple = (char *) cdio_get_arg(p_cdio, "scsi-tuple");
|
||||||
|
if (tuple != NULL) if (tuple[0]) {
|
||||||
|
sscanf(tuple, "%d,%d,%d,%d,%d",
|
||||||
|
bus_no, host_no, channel_no, target_no, lun_no);
|
||||||
|
}
|
||||||
|
|
||||||
|
cdio_destroy(p_cdio);
|
||||||
|
return (*bus_no >= 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __FreeBSD__
|
||||||
|
#define Libburn_guess_block_devicE 1
|
||||||
|
#endif
|
||||||
|
#ifdef __FreeBSD_kernel__
|
||||||
|
#define Libburn_guess_block_devicE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef Libburn_guess_block_devicE
|
||||||
|
|
||||||
|
/* ts B00115 */
|
||||||
|
/* The FreeBSD implementation of burn_os_is_2k_seekrw().
|
||||||
|
On FreeBSD there are no block devices.
|
||||||
|
*/
|
||||||
|
static int freebsd_is_2k_seekrw(char *path, int flag)
|
||||||
|
{
|
||||||
|
struct stat stbuf;
|
||||||
|
char *spt;
|
||||||
|
int i, e;
|
||||||
|
|
||||||
|
if (stat(path, &stbuf) == -1)
|
||||||
|
return 0;
|
||||||
|
if (S_ISREG(stbuf.st_mode))
|
||||||
|
return 1;
|
||||||
|
if (!S_ISCHR(stbuf.st_mode))
|
||||||
|
return 0;
|
||||||
|
spt = strrchr(path, '/');
|
||||||
|
if (spt == NULL)
|
||||||
|
spt = path;
|
||||||
|
else
|
||||||
|
spt++;
|
||||||
|
e = strlen(spt);
|
||||||
|
for (i = strlen(spt) - 1; i > 0; i--)
|
||||||
|
if (spt[i] >= '0' && spt[i] <= '9')
|
||||||
|
e = i;
|
||||||
|
if (strncmp(spt, "da", e) == 0) /* SCSI disk. E.g. USB stick. */
|
||||||
|
return 1;
|
||||||
|
if (strncmp(spt, "cd", e) == 0) /* SCSI CD drive might be writeable. */
|
||||||
|
return 1;
|
||||||
|
if (strncmp(spt, "ad", e) == 0) /* IDE hard drive */
|
||||||
|
return 1;
|
||||||
|
if (strncmp(spt, "acd", e) == 0) /* IDE CD drive might be writeable */
|
||||||
|
return 1;
|
||||||
|
if (strncmp(spt, "fd", e) == 0) /* Floppy disk */
|
||||||
|
return 1;
|
||||||
|
if (strncmp(spt, "fla", e) == 0) /* Flash drive */
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* Libburn_guess_block_devicE */
|
||||||
|
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
#ifdef Libburn_guess_block_devicE
|
||||||
|
return freebsd_is_2k_seekrw(path, flag);
|
||||||
|
#else
|
||||||
|
struct stat stbuf;
|
||||||
|
|
||||||
|
if (stat(path, &stbuf) == -1)
|
||||||
|
return 0;
|
||||||
|
if (S_ISREG(stbuf.st_mode))
|
||||||
|
return 1;
|
||||||
|
if (S_ISBLK(stbuf.st_mode))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
#endif /* ! Libburn_guess_block_devicE */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** 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;
|
||||||
|
|
||||||
|
#ifdef Libburn_os_has_statvfS
|
||||||
|
struct statvfs vfsbuf;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char testpath[4096], *cpt;
|
||||||
|
long blocks;
|
||||||
|
off_t add_size = 0;
|
||||||
|
|
||||||
|
testpath[0] = 0;
|
||||||
|
blocks = *bytes / 512;
|
||||||
|
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)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
#ifdef __linux
|
||||||
|
|
||||||
|
/* Linux specific determination of block device size */
|
||||||
|
} else if(S_ISBLK(stbuf.st_mode)) {
|
||||||
|
int open_mode = O_RDONLY, fd, ret;
|
||||||
|
|
||||||
|
fd = open(path, open_mode);
|
||||||
|
if (fd == -1)
|
||||||
|
return -2;
|
||||||
|
ret = ioctl(fd, BLKGETSIZE, &blocks);
|
||||||
|
close(fd);
|
||||||
|
if (ret == -1)
|
||||||
|
return -2;
|
||||||
|
*bytes = ((off_t) blocks) * (off_t) 512;
|
||||||
|
|
||||||
|
#endif /* __linux */
|
||||||
|
|
||||||
|
#ifdef Libburn_is_on_freebsD
|
||||||
|
|
||||||
|
} else if(S_ISCHR(stbuf.st_mode)) {
|
||||||
|
int fd, ret;
|
||||||
|
|
||||||
|
fd = open(path, O_RDONLY);
|
||||||
|
if (fd == -1)
|
||||||
|
return -2;
|
||||||
|
ret = ioctl(fd, DIOCGMEDIASIZE, &add_size);
|
||||||
|
close(fd);
|
||||||
|
if (ret == -1)
|
||||||
|
return -2;
|
||||||
|
*bytes = add_size;
|
||||||
|
|
||||||
|
#endif/* Libburn_is_on_freebsD */
|
||||||
|
|
||||||
|
} else if(S_ISREG(stbuf.st_mode)) {
|
||||||
|
add_size = stbuf.st_blocks * (off_t) 512;
|
||||||
|
strcpy(testpath, path);
|
||||||
|
} else
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (testpath[0]) {
|
||||||
|
|
||||||
|
#ifdef Libburn_os_has_statvfS
|
||||||
|
|
||||||
|
if (statvfs(testpath, &vfsbuf) == -1)
|
||||||
|
return -2;
|
||||||
|
*bytes = add_size + ((off_t) vfsbuf.f_frsize) *
|
||||||
|
(off_t) vfsbuf.f_bavail;
|
||||||
|
|
||||||
|
#else /* Libburn_os_has_statvfS */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#endif /* ! Libburn_os_has_stavtfS */
|
||||||
|
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,11 @@
|
|||||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||||
|
|
||||||
|
|
||||||
|
/* <<< ts A91112 : experiments to get better speed with USB
|
||||||
|
#define Libburn_sgio_as_growisofS 1
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
This is the main operating system dependent SCSI part of libburn. It implements
|
This is the main operating system dependent SCSI part of libburn. It implements
|
||||||
@ -29,12 +35,28 @@ and of deriving the following system specific files from existing examples:
|
|||||||
Said sg-*.c operations are defined by a public function interface, which has
|
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:
|
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
|
sg_give_next_adr() iterates over the set of potentially useful drive
|
||||||
address strings.
|
address strings.
|
||||||
|
|
||||||
scsi_enumerate_drives() brings all available, not-whitelist-banned, and
|
scsi_enumerate_drives() brings all available, not-whitelist-banned, and
|
||||||
accessible drives into libburn's list of drives.
|
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_drive_is_open() tells wether libburn has the given drive in use.
|
||||||
|
|
||||||
sg_grab() opens the drive for SCSI commands and ensures
|
sg_grab() opens the drive for SCSI commands and ensures
|
||||||
@ -48,8 +70,25 @@ sg_issue_command() sends a SCSI command to the drive, receives reply,
|
|||||||
|
|
||||||
sg_obtain_scsi_adr() tries to obtain SCSI address parameters.
|
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) and
|
||||||
|
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_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:".
|
Porting hints are marked by the text "PORTING:".
|
||||||
Send feedback to libburn-hackers@pykix.org .
|
Send feedback to libburn-hackers@pykix.org .
|
||||||
@ -62,6 +101,13 @@ Hint: You should also look into sg-freebsd-port.c, which is a younger and
|
|||||||
|
|
||||||
/** PORTING : ------- OS dependent headers and definitions ------ */
|
/** PORTING : ------- OS dependent headers and definitions ------ */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef Libburn_read_o_direcT
|
||||||
|
# ifndef _GNU_SOURCE
|
||||||
|
# define _GNU_SOURCE
|
||||||
|
# endif
|
||||||
|
#endif /* Libburn_read_o_direcT */
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -80,6 +126,9 @@ Hint: You should also look into sg-freebsd-port.c, which is a younger and
|
|||||||
/* for ioctl(BLKGETSIZE) */
|
/* for ioctl(BLKGETSIZE) */
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
|
|
||||||
|
/* for mmap() */
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
|
||||||
#include <scsi/sg.h>
|
#include <scsi/sg.h>
|
||||||
/* Values within sg_io_hdr_t indicating success after ioctl(SG_IO) : */
|
/* Values within sg_io_hdr_t indicating success after ioctl(SG_IO) : */
|
||||||
@ -168,6 +217,7 @@ static int linux_ata_enumerate_verbous = 0;
|
|||||||
|
|
||||||
/** PORTING : ------ libburn portable headers and definitions ----- */
|
/** PORTING : ------ libburn portable headers and definitions ----- */
|
||||||
|
|
||||||
|
#include "libburn.h"
|
||||||
#include "transport.h"
|
#include "transport.h"
|
||||||
#include "drive.h"
|
#include "drive.h"
|
||||||
#include "sg.h"
|
#include "sg.h"
|
||||||
@ -196,17 +246,25 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
|
|||||||
|
|
||||||
|
|
||||||
/* ts A60813 : storage objects are in libburn/init.c
|
/* ts A60813 : storage objects are in libburn/init.c
|
||||||
wether to use O_EXCL with open(2) of devices
|
whether to use O_EXCL with open(2) of devices
|
||||||
wether to use fcntl(,F_SETLK,) after open(2) of devices
|
whether to use fcntl(,F_SETLK,) after open(2) of devices
|
||||||
what device family to use : 0=default, 1=sr, 2=scd, (3=st), 4=sg
|
what device family to use : 0=default, 1=sr, 2=scd, (3=st), 4=sg
|
||||||
wether to use O_NOBLOCK with open(2) on devices
|
whether to use O_NOBLOCK with open(2) on devices
|
||||||
wether to take O_EXCL rejection as fatal error */
|
whether to take O_EXCL rejection as fatal error
|
||||||
|
*/
|
||||||
extern int burn_sg_open_o_excl;
|
extern int burn_sg_open_o_excl;
|
||||||
extern int burn_sg_fcntl_f_setlk;
|
extern int burn_sg_fcntl_f_setlk;
|
||||||
extern int burn_sg_use_family;
|
extern int burn_sg_use_family;
|
||||||
extern int burn_sg_open_o_nonblock;
|
extern int burn_sg_open_o_nonblock;
|
||||||
extern int burn_sg_open_abort_busy;
|
extern int burn_sg_open_abort_busy;
|
||||||
|
|
||||||
|
/* ts A91111 :
|
||||||
|
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;
|
||||||
|
|
||||||
/* ts A60821
|
/* ts A60821
|
||||||
debug: for tracing calls which might use open drive fds
|
debug: for tracing calls which might use open drive fds
|
||||||
@ -1370,6 +1428,61 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
|
|||||||
/* ------------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
|
||||||
|
/** 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)
|
||||||
|
{
|
||||||
|
strcpy(msg, "internal Linux SG_IO adapter sg-linux");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Performs global initialization of the SCSI transport adapter and eventually
|
||||||
|
needed operating system facilities. Checks for compatibility 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** PORTING:
|
/** PORTING:
|
||||||
In this Linux implementation, this function mirrors the enumeration
|
In this Linux implementation, this function mirrors the enumeration
|
||||||
done in sg_enumerate and ata_enumerate(). It would be better to base those
|
done in sg_enumerate and ata_enumerate(). It would be better to base those
|
||||||
@ -1642,69 +1755,34 @@ int sg_release(struct burn_drive *d)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** ts A70518:
|
#ifdef NIX
|
||||||
Debugging log facility. Controlled by existence of macros:
|
/* <<< now in spc.c as scsi_log_err */
|
||||||
Libburn_log_sg_commandS enables logging to file
|
|
||||||
/tmp/libburn_sg_command_log
|
|
||||||
Libburn_fflush_log_sg_commandS enables fflush after each output line
|
|
||||||
Libburn_log_sg_command_stderR enables additional log to stderr
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
#define Libburn_log_sg_commandS 1
|
|
||||||
#define Libburn_fflush_log_sg_commandS 1
|
|
||||||
#define Libburn_log_sg_command_stderR 1
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef Libburn_log_sg_commandS
|
|
||||||
|
|
||||||
/** Logs command (before execution) */
|
|
||||||
static int sg_log_cmd(struct command *c, FILE *fp, int flag)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (fp != NULL) {
|
|
||||||
for(i = 0; i < 16 && i < c->oplen; i++)
|
|
||||||
fprintf(fp,"%2.2x ", c->opcode[i]);
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
#ifdef Libburn_fflush_log_sg_commandS
|
|
||||||
fflush(fp);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
if (fp == stderr)
|
|
||||||
return 1;
|
|
||||||
#ifdef Libburn_log_sg_command_stderR
|
|
||||||
sg_log_cmd(c, stderr, flag);
|
|
||||||
#endif
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** logs outcome of a sg command. flag&1 causes an error message */
|
/** logs outcome of a sg command. flag&1 causes an error message */
|
||||||
static int sg_log_err(struct command *c, FILE *fp,
|
static int sg_log_err(struct command *c, FILE *fp,
|
||||||
sg_io_hdr_t *s,
|
sg_io_hdr_t *s,
|
||||||
int flag)
|
int flag)
|
||||||
{
|
{
|
||||||
if(fp!=NULL) {
|
if(fp != NULL && (fp == stderr || (burn_sg_log_scsi & 1))) {
|
||||||
if(flag & 1)
|
if(flag & 1) {
|
||||||
fprintf(fp,
|
fprintf(fp,
|
||||||
"+++ key=%X asc=%2.2Xh ascq=%2.2Xh (%6d ms)\n",
|
"+++ key=%X asc=%2.2Xh ascq=%2.2Xh (%6d ms)\n",
|
||||||
s->sbp[2], s->sbp[12], s->sbp[13],s->duration);
|
s->sbp[2], s->sbp[12], s->sbp[13],s->duration);
|
||||||
else
|
} else {
|
||||||
|
scsi_show_cmd_reply(c, fp, 0);
|
||||||
fprintf(fp,"%6d ms\n", s->duration);
|
fprintf(fp,"%6d ms\n", s->duration);
|
||||||
#ifdef Libburn_fflush_log_sg_commandS
|
}
|
||||||
fflush(fp);
|
if (burn_sg_log_scsi & 4)
|
||||||
#endif
|
fflush(fp);
|
||||||
}
|
}
|
||||||
if (fp == stderr)
|
if (fp == stderr || !(burn_sg_log_scsi & 2))
|
||||||
return 1;
|
return 1;
|
||||||
#ifdef Libburn_log_sg_command_stderR
|
|
||||||
sg_log_err(c, stderr, s, flag);
|
sg_log_err(c, stderr, s, flag);
|
||||||
#endif
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* NIX */
|
||||||
#endif /* Libburn_log_sg_commandS */
|
|
||||||
|
|
||||||
|
|
||||||
/** Sends a SCSI command to the drive, receives reply and evaluates wether
|
/** Sends a SCSI command to the drive, receives reply and evaluates wether
|
||||||
@ -1712,8 +1790,6 @@ static int sg_log_err(struct command *c, FILE *fp,
|
|||||||
Returned SCSI errors shall not lead to a return value indicating failure.
|
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
|
The callers get notified by c->error. An SCSI failure which leads not to
|
||||||
a retry shall be notified via scsi_notify_error().
|
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
|
@return: 1 success , <=0 failure
|
||||||
*/
|
*/
|
||||||
int sg_issue_command(struct burn_drive *d, struct command *c)
|
int sg_issue_command(struct burn_drive *d, struct command *c)
|
||||||
@ -1722,11 +1798,8 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
|
|||||||
int err;
|
int err;
|
||||||
time_t start_time;
|
time_t start_time;
|
||||||
sg_io_hdr_t s;
|
sg_io_hdr_t s;
|
||||||
|
|
||||||
#ifdef Libburn_log_sg_commandS
|
|
||||||
/* ts A61030 */
|
/* ts A61030 */
|
||||||
static FILE *fp= NULL;
|
static FILE *fp= NULL;
|
||||||
#endif /* Libburn_log_sg_commandS */
|
|
||||||
|
|
||||||
/* <<< ts A60821
|
/* <<< ts A60821
|
||||||
debug: for tracing calls which might use open drive fds */
|
debug: for tracing calls which might use open drive fds */
|
||||||
@ -1735,15 +1808,16 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
|
|||||||
d->fd,d->released);
|
d->fd,d->released);
|
||||||
mmc_function_spy(NULL, buf);
|
mmc_function_spy(NULL, buf);
|
||||||
|
|
||||||
#ifdef Libburn_log_sg_commandS
|
|
||||||
/* ts A61030 */
|
/* ts A61030 */
|
||||||
if(fp==NULL) {
|
if (burn_sg_log_scsi & 1) {
|
||||||
fp= fopen("/tmp/libburn_sg_command_log","a");
|
if (fp == NULL) {
|
||||||
fprintf(fp,"\n-----------------------------------------\n");
|
fp= fopen("/tmp/libburn_sg_command_log", "a");
|
||||||
|
fprintf(fp,
|
||||||
|
"\n-----------------------------------------\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sg_log_cmd(c,fp,0);
|
if (burn_sg_log_scsi & 3)
|
||||||
#endif /* Libburn_log_sg_commandS */
|
scsi_log_cmd(c,fp,0);
|
||||||
|
|
||||||
|
|
||||||
/* ts A61010 : with no fd there is no chance to send an ioctl */
|
/* ts A61010 : with no fd there is no chance to send an ioctl */
|
||||||
if (d->fd < 0) {
|
if (d->fd < 0) {
|
||||||
@ -1756,6 +1830,13 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
|
|||||||
|
|
||||||
s.interface_id = 'S';
|
s.interface_id = 'S';
|
||||||
|
|
||||||
|
#ifdef Libburn_sgio_as_growisofS
|
||||||
|
/* ??? ts A91112 : does this speed up USB ? (from growisofs)
|
||||||
|
--- did not help
|
||||||
|
*/
|
||||||
|
s.flags = SG_FLAG_DIRECT_IO;
|
||||||
|
#endif /* Libburn_sgio_as_growisofS */
|
||||||
|
|
||||||
if (c->dir == TO_DRIVE)
|
if (c->dir == TO_DRIVE)
|
||||||
s.dxfer_direction = SG_DXFER_TO_DEV;
|
s.dxfer_direction = SG_DXFER_TO_DEV;
|
||||||
else if (c->dir == FROM_DRIVE)
|
else if (c->dir == FROM_DRIVE)
|
||||||
@ -1876,11 +1957,9 @@ ex:;
|
|||||||
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
|
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
msg, 0, 0);
|
msg, 0, 0);
|
||||||
}
|
}
|
||||||
|
if (burn_sg_log_scsi & 3)
|
||||||
#ifdef Libburn_log_sg_commandS
|
/* <<< sg_log_err(c, fp, &s, c->error != 0); */
|
||||||
sg_log_err(c, fp, &s, c->error != 0);
|
scsi_log_err(c, fp, s.sbp, s.duration, c->error != 0);
|
||||||
#endif /* Libburn_log_sg_commandS */
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1976,6 +2055,24 @@ int sg_is_enumerable_adr(char *adr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ts B00115 */
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
if (stat(path, &stbuf) == -1)
|
||||||
|
return 0;
|
||||||
|
if (S_ISREG(stbuf.st_mode))
|
||||||
|
return 1;
|
||||||
|
if (S_ISBLK(stbuf.st_mode))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ts A70909 */
|
/* ts A70909 */
|
||||||
/** Estimate the potential payload capacity of a file address.
|
/** Estimate the potential payload capacity of a file address.
|
||||||
@param path The address of the file to be examined. If it does not
|
@param path The address of the file to be examined. If it does not
|
||||||
@ -2027,9 +2124,86 @@ int burn_os_stdio_capacity(char *path, off_t *bytes)
|
|||||||
if (testpath[0]) {
|
if (testpath[0]) {
|
||||||
if (statvfs(testpath, &vfsbuf) == -1)
|
if (statvfs(testpath, &vfsbuf) == -1)
|
||||||
return -2;
|
return -2;
|
||||||
*bytes = add_size + ((off_t) vfsbuf.f_bsize) *
|
*bytes = add_size + ((off_t) vfsbuf.f_frsize) *
|
||||||
(off_t) vfsbuf.f_bavail;
|
(off_t) vfsbuf.f_bavail;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ts A91122 : an interface to open(O_DIRECT) or similar OS tricks. */
|
||||||
|
|
||||||
|
#ifdef PROT_READ
|
||||||
|
#ifdef PROT_WRITE
|
||||||
|
#ifdef MAP_SHARED
|
||||||
|
#ifdef MAP_ANONYMOUS
|
||||||
|
#ifdef MAP_FAILED
|
||||||
|
#define Libburn_linux_do_mmaP 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef Libburn_read_o_direcT
|
||||||
|
#ifdef O_DIRECT
|
||||||
|
#define Libburn_linux_do_o_direcT 1
|
||||||
|
#endif
|
||||||
|
#endif /* Libburn_read_o_direcT */
|
||||||
|
|
||||||
|
|
||||||
|
int burn_os_open_track_src(char *path, int open_flags, int flag)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
#ifdef Libburn_linux_do_o_direcT
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
|
||||||
|
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
"Opening track source with O_DIRECT" , 0, 0);
|
||||||
|
fd = open(path, open_flags | O_DIRECT);
|
||||||
|
#else
|
||||||
|
fd = open(path, open_flags);
|
||||||
|
#endif
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *burn_os_alloc_buffer(size_t amount, int flag)
|
||||||
|
{
|
||||||
|
void *buf = NULL;
|
||||||
|
|
||||||
|
#ifdef Libburn_linux_do_mmaP
|
||||||
|
|
||||||
|
/* >>> check whether size is suitable */;
|
||||||
|
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
|
||||||
|
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
"Allocating buffer via mmap()" , 0, 0);
|
||||||
|
buf = mmap(NULL, amount, PROT_READ | PROT_WRITE,
|
||||||
|
MAP_SHARED | MAP_ANONYMOUS, -1, (off_t) 0);
|
||||||
|
if (buf == MAP_FAILED)
|
||||||
|
buf = NULL;
|
||||||
|
else
|
||||||
|
memset(buf, 0, amount);
|
||||||
|
#else
|
||||||
|
buf = calloc(1, amount);
|
||||||
|
#endif /* ! Libburn_linux_do_mmaP */
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int burn_os_free_buffer(void *buffer, size_t amount, int flag)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (buffer == NULL)
|
||||||
|
return 0;
|
||||||
|
#ifdef Libburn_linux_do_mmaP
|
||||||
|
ret = munmap(buffer, amount);
|
||||||
|
#else
|
||||||
|
free(buffer);
|
||||||
|
#endif
|
||||||
|
return (ret == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
12
libburn/sg.c
12
libburn/sg.c
@ -5,10 +5,20 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef Libburn_use_libcdiO
|
||||||
|
|
||||||
|
#include "sg-libcdio.c"
|
||||||
|
|
||||||
|
#else
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
|
|
||||||
#include "sg-freebsd.c"
|
#include "sg-freebsd.c"
|
||||||
|
|
||||||
|
#else
|
||||||
|
#ifdef __FreeBSD_kernel__
|
||||||
|
|
||||||
|
#include "sg-freebsd.c"
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#ifdef __linux
|
#ifdef __linux
|
||||||
|
|
||||||
@ -37,5 +47,7 @@ static int intentional_compiler_warning(void)
|
|||||||
#include "sg-dummy.c"
|
#include "sg-dummy.c"
|
||||||
|
|
||||||
#endif /* ! __linux */
|
#endif /* ! __linux */
|
||||||
|
#endif /* ! __FreeBSD_kernel__ */
|
||||||
#endif /* ! __FreeBSD__ */
|
#endif /* ! __FreeBSD__ */
|
||||||
|
#endif /* ! Libburn_use_libcdiO */
|
||||||
|
|
||||||
|
45
libburn/sg.h
45
libburn/sg.h
@ -31,6 +31,51 @@ int scsi_enumerate_drives(void);
|
|||||||
|
|
||||||
int sg_drive_is_open(struct burn_drive * d);
|
int sg_drive_is_open(struct burn_drive * d);
|
||||||
|
|
||||||
|
int burn_os_is_2k_seekrw(char *path, int flag);
|
||||||
|
|
||||||
int burn_os_stdio_capacity(char *path, off_t *bytes);
|
int burn_os_stdio_capacity(char *path, off_t *bytes);
|
||||||
|
|
||||||
|
/* ts A91227 */
|
||||||
|
/** 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);
|
||||||
|
|
||||||
|
/* ts A91225 */
|
||||||
|
/** Performs global initialization of the SCSI transport adapter and eventually
|
||||||
|
needed operating system facilities. Checks for compatibility 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);
|
||||||
|
|
||||||
|
/* ts A91227 */
|
||||||
|
/** 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);
|
||||||
|
|
||||||
|
/* ts A91227 */
|
||||||
|
/** 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);
|
||||||
|
|
||||||
|
|
||||||
#endif /* __SG */
|
#endif /* __SG */
|
||||||
|
264
libburn/spc.c
264
libburn/spc.c
@ -27,10 +27,13 @@
|
|||||||
#include "libdax_msgs.h"
|
#include "libdax_msgs.h"
|
||||||
extern struct libdax_msgs *libdax_messenger;
|
extern struct libdax_msgs *libdax_messenger;
|
||||||
|
|
||||||
/* ts A70910
|
/* ts A91111 :
|
||||||
debug: for tracing calls which might use open drive fds
|
whether to log SCSI commands:
|
||||||
or for catching SCSI usage of emulated drives. */
|
bit0= log in /tmp/libburn_sg_command_log
|
||||||
int mmc_function_spy(struct burn_drive *d, char * text);
|
bit1= log to stderr
|
||||||
|
bit2= flush every line
|
||||||
|
*/
|
||||||
|
extern int burn_sg_log_scsi;
|
||||||
|
|
||||||
|
|
||||||
/* spc command set */
|
/* spc command set */
|
||||||
@ -41,8 +44,7 @@ static unsigned char SPC_INQUIRY[] = { 0x12, 0, 0, 0, 36, 0 };
|
|||||||
static unsigned char SPC_PREVENT[] = { 0x1e, 0, 0, 0, 1, 0 };
|
static unsigned char SPC_PREVENT[] = { 0x1e, 0, 0, 0, 1, 0 };
|
||||||
static unsigned char SPC_ALLOW[] = { 0x1e, 0, 0, 0, 0, 0 };
|
static unsigned char SPC_ALLOW[] = { 0x1e, 0, 0, 0, 0, 0 };
|
||||||
static unsigned char SPC_MODE_SENSE[] = { 0x5a, 0, 0, 0, 0, 0, 0, 16, 0, 0 };
|
static unsigned char SPC_MODE_SENSE[] = { 0x5a, 0, 0, 0, 0, 0, 0, 16, 0, 0 };
|
||||||
static unsigned char SPC_MODE_SELECT[] =
|
static unsigned char SPC_MODE_SELECT[] = { 0x55, 16, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||||
{ 0x55, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
|
||||||
static unsigned char SPC_REQUEST_SENSE[] = { 0x03, 0, 0, 0, 18, 0 };
|
static unsigned char SPC_REQUEST_SENSE[] = { 0x03, 0, 0, 0, 18, 0 };
|
||||||
static unsigned char SPC_TEST_UNIT_READY[] = { 0x00, 0, 0, 0, 0, 0 };
|
static unsigned char SPC_TEST_UNIT_READY[] = { 0x00, 0, 0, 0, 0, 0 };
|
||||||
|
|
||||||
@ -98,7 +100,9 @@ int spc_test_unit_ready(struct burn_drive *d)
|
|||||||
|
|
||||||
|
|
||||||
/* ts A70315 */
|
/* ts A70315 */
|
||||||
/** @param flag bit0=do not wait 0.1 seconds before first test unit ready */
|
/** @param flag bit0=do not wait 0.1 seconds before first test unit ready
|
||||||
|
bit1=do not issue success message
|
||||||
|
*/
|
||||||
/** Wait until the drive state becomes clear or until max_usec elapsed */
|
/** Wait until the drive state becomes clear or until max_usec elapsed */
|
||||||
int spc_wait_unit_attention(struct burn_drive *d, int max_sec, char *cmd_text,
|
int spc_wait_unit_attention(struct burn_drive *d, int max_sec, char *cmd_text,
|
||||||
int flag)
|
int flag)
|
||||||
@ -112,13 +116,6 @@ int spc_wait_unit_attention(struct burn_drive *d, int max_sec, char *cmd_text,
|
|||||||
usleep(100000);
|
usleep(100000);
|
||||||
for(i = !(flag & 1); i < max_sec * 10; i++) {
|
for(i = !(flag & 1); i < max_sec * 10; i++) {
|
||||||
ret = spc_test_unit_ready_r(d, &key, &asc, &ascq);
|
ret = spc_test_unit_ready_r(d, &key, &asc, &ascq);
|
||||||
|
|
||||||
/* <<<
|
|
||||||
fprintf(stderr,
|
|
||||||
"libburn_EXPERIMENTAL: i= %d ret= %d key= %X asc= %2.2X ascq= %2.2X\n",
|
|
||||||
i, ret, (unsigned) key, (unsigned) asc, (unsigned) ascq);
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (ret > 0) /* ready */
|
if (ret > 0) /* ready */
|
||||||
break;
|
break;
|
||||||
if (key!=0x2 || asc!=0x4) {
|
if (key!=0x2 || asc!=0x4) {
|
||||||
@ -140,24 +137,14 @@ int spc_wait_unit_attention(struct burn_drive *d, int max_sec, char *cmd_text,
|
|||||||
/* media change notice = try again */
|
/* media change notice = try again */
|
||||||
goto slumber;
|
goto slumber;
|
||||||
|
|
||||||
#ifdef NIX
|
|
||||||
sprintf(msg,
|
|
||||||
"Asynchromous SCSI error on %s: key=%X asc=%2.2Xh ascq=%2.2Xh",
|
|
||||||
cmd_text, (unsigned) key, (unsigned) asc,
|
|
||||||
(unsigned) ascq);
|
|
||||||
#else
|
|
||||||
|
|
||||||
/* ts A90213 */
|
/* ts A90213 */
|
||||||
sprintf(msg,
|
sprintf(msg,
|
||||||
"Asynchromous SCSI error on %s: ", cmd_text);
|
"Asynchronous SCSI error on %s: ", cmd_text);
|
||||||
sense[2] = key;
|
sense[2] = key;
|
||||||
sense[12] = asc;
|
sense[12] = asc;
|
||||||
sense[13] = ascq;
|
sense[13] = ascq;
|
||||||
resp = scsi_error_msg(d, sense, 14, msg + strlen(msg),
|
resp = scsi_error_msg(d, sense, 14, msg + strlen(msg),
|
||||||
&key, &asc, &ascq);
|
&key, &asc, &ascq);
|
||||||
|
|
||||||
#endif /* ! NIX */
|
|
||||||
|
|
||||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
libdax_msgs_submit(libdax_messenger, d->global_index,
|
||||||
0x0002014d,
|
0x0002014d,
|
||||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
@ -168,11 +155,14 @@ int spc_wait_unit_attention(struct burn_drive *d, int max_sec, char *cmd_text,
|
|||||||
slumber:;
|
slumber:;
|
||||||
usleep(100000);
|
usleep(100000);
|
||||||
}
|
}
|
||||||
|
if (ret <= 0 || !(flag & 2)) {
|
||||||
sprintf(msg, "Async %s %s after %d.%d seconds",
|
sprintf(msg, "Async %s %s after %d.%d seconds",
|
||||||
cmd_text, (ret > 0 ? "succeeded" : "failed"), i / 10, i % 10);
|
cmd_text, (ret > 0 ? "succeeded" : "failed"),
|
||||||
libdax_msgs_submit(libdax_messenger, d->global_index, 0x00020150,
|
i / 10, i % 10);
|
||||||
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_LOW, msg, 0, 0);
|
libdax_msgs_submit(libdax_messenger, d->global_index,
|
||||||
|
0x00020150, LIBDAX_MSGS_SEV_DEBUG,
|
||||||
|
LIBDAX_MSGS_PRIO_LOW, msg, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
if (i < max_sec * 10)
|
if (i < max_sec * 10)
|
||||||
return (ret > 0);
|
return (ret > 0);
|
||||||
@ -262,14 +252,14 @@ void spc_prevent(struct burn_drive *d)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
scsi_init_command(&c, SPC_PREVENT, sizeof(SPC_PREVENT));
|
scsi_init_command(&c, SPC_PREVENT, sizeof(SPC_PREVENT));
|
||||||
/*
|
|
||||||
memcpy(c.opcode, SPC_PREVENT, sizeof(SPC_PREVENT));
|
|
||||||
c.oplen = sizeof(SPC_PREVENT);
|
|
||||||
c.page = NULL;
|
|
||||||
*/
|
|
||||||
c.retry = 1;
|
c.retry = 1;
|
||||||
c.dir = NO_TRANSFER;
|
c.dir = NO_TRANSFER;
|
||||||
d->issue_command(d, &c);
|
d->issue_command(d, &c);
|
||||||
|
|
||||||
|
#ifdef Libburn_pioneer_dvr_216d_get_evenT
|
||||||
|
mmc_get_event(d);
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void spc_allow(struct burn_drive *d)
|
void spc_allow(struct burn_drive *d)
|
||||||
@ -338,7 +328,7 @@ static int spc_sense_caps_al(struct burn_drive *d, int *alloc_len, int flag)
|
|||||||
was_error = 1;
|
was_error = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
size = c.page->data[0] * 256 + c.page->data[1];
|
size = c.page->data[0] * 256 + c.page->data[1] + 2;
|
||||||
page = c.page->data + 8;
|
page = c.page->data + 8;
|
||||||
|
|
||||||
/* ts A61225 :
|
/* ts A61225 :
|
||||||
@ -489,6 +479,7 @@ void spc_sense_caps(struct burn_drive *d)
|
|||||||
{
|
{
|
||||||
int alloc_len, start_len = 30, ret;
|
int alloc_len, start_len = 30, ret;
|
||||||
|
|
||||||
|
mmc_start_if_needed(d, 1);
|
||||||
if (mmc_function_spy(d, "sense_caps") <= 0)
|
if (mmc_function_spy(d, "sense_caps") <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -513,6 +504,7 @@ void spc_sense_error_params(struct burn_drive *d)
|
|||||||
unsigned char *page;
|
unsigned char *page;
|
||||||
struct command c;
|
struct command c;
|
||||||
|
|
||||||
|
mmc_start_if_needed(d, 1);
|
||||||
if (mmc_function_spy(d, "sense_error_params") <= 0)
|
if (mmc_function_spy(d, "sense_error_params") <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -532,7 +524,7 @@ void spc_sense_error_params(struct burn_drive *d)
|
|||||||
c.dir = FROM_DRIVE;
|
c.dir = FROM_DRIVE;
|
||||||
d->issue_command(d, &c);
|
d->issue_command(d, &c);
|
||||||
|
|
||||||
size = c.page->data[0] * 256 + c.page->data[1];
|
size = c.page->data[0] * 256 + c.page->data[1] + 2;
|
||||||
m = d->mdata;
|
m = d->mdata;
|
||||||
page = c.page->data + 8;
|
page = c.page->data + 8;
|
||||||
d->params.retries = page[3];
|
d->params.retries = page[3];
|
||||||
@ -546,6 +538,7 @@ void spc_select_error_params(struct burn_drive *d,
|
|||||||
struct buffer buf;
|
struct buffer buf;
|
||||||
struct command c;
|
struct command c;
|
||||||
|
|
||||||
|
mmc_start_if_needed(d, 1);
|
||||||
if (mmc_function_spy(d, "select_error_params") <= 0)
|
if (mmc_function_spy(d, "select_error_params") <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -587,6 +580,7 @@ void spc_sense_write_params(struct burn_drive *d)
|
|||||||
unsigned char *page;
|
unsigned char *page;
|
||||||
struct command c;
|
struct command c;
|
||||||
|
|
||||||
|
mmc_start_if_needed(d, 1);
|
||||||
if (mmc_function_spy(d, "sense_write_params") <= 0)
|
if (mmc_function_spy(d, "sense_write_params") <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -613,7 +607,7 @@ void spc_sense_write_params(struct burn_drive *d)
|
|||||||
/* ts A71128 : do not interpret reply if error */
|
/* ts A71128 : do not interpret reply if error */
|
||||||
m = d->mdata;
|
m = d->mdata;
|
||||||
if (!c.error) {
|
if (!c.error) {
|
||||||
size = c.page->data[0] * 256 + c.page->data[1];
|
size = c.page->data[0] * 256 + c.page->data[1] + 2;
|
||||||
page = c.page->data + 8;
|
page = c.page->data + 8;
|
||||||
burn_print(1, "write page length 0x%x\n", page[1]);
|
burn_print(1, "write page length 0x%x\n", page[1]);
|
||||||
m->write_page_length = page[1];
|
m->write_page_length = page[1];
|
||||||
@ -650,7 +644,9 @@ void spc_select_write_params(struct burn_drive *d,
|
|||||||
{
|
{
|
||||||
struct buffer buf;
|
struct buffer buf;
|
||||||
struct command c;
|
struct command c;
|
||||||
|
int alloc_len;
|
||||||
|
|
||||||
|
mmc_start_if_needed(d, 1);
|
||||||
if (mmc_function_spy(d, "select_write_params") <= 0)
|
if (mmc_function_spy(d, "select_write_params") <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -664,13 +660,33 @@ void spc_select_write_params(struct burn_drive *d,
|
|||||||
o->block_type,spc_block_type(o->block_type));
|
o->block_type,spc_block_type(o->block_type));
|
||||||
*/
|
*/
|
||||||
|
|
||||||
scsi_init_command(&c, SPC_MODE_SELECT, sizeof(SPC_MODE_SELECT));
|
alloc_len = 8 + 2 + d->mdata->write_page_length;
|
||||||
/*
|
memset(&(buf.data), 0, alloc_len);
|
||||||
memcpy(c.opcode, SPC_MODE_SELECT, sizeof(SPC_MODE_SELECT));
|
|
||||||
c.oplen = sizeof(SPC_MODE_SELECT);
|
#ifdef Libburn_pioneer_dvr_216d_load_mode5
|
||||||
*/
|
|
||||||
|
scsi_init_command(&c, SPC_MODE_SENSE, sizeof(SPC_MODE_SENSE));
|
||||||
|
c.dxfer_len = alloc_len;
|
||||||
|
c.opcode[7] = (alloc_len >> 8) & 0xff;
|
||||||
|
c.opcode[8] = alloc_len & 0xff;
|
||||||
c.retry = 1;
|
c.retry = 1;
|
||||||
c.opcode[8] = 8 + 2 + d->mdata->write_page_length;
|
c.opcode[2] = 0x05;
|
||||||
|
c.page = &buf;
|
||||||
|
c.page->bytes = 0;
|
||||||
|
c.page->sectors = 0;
|
||||||
|
c.dir = FROM_DRIVE;
|
||||||
|
d->issue_command(d, &c);
|
||||||
|
|
||||||
|
if (c.error)
|
||||||
|
memset(&(buf.data), 0,
|
||||||
|
8 + 2 + d->mdata->write_page_length);
|
||||||
|
|
||||||
|
#endif /* Libburn_pioneer_dvr_216d_load_mode5 */
|
||||||
|
|
||||||
|
scsi_init_command(&c, SPC_MODE_SELECT, sizeof(SPC_MODE_SELECT));
|
||||||
|
c.retry = 1;
|
||||||
|
c.opcode[7] = (alloc_len >> 8) & 0xff;
|
||||||
|
c.opcode[8] = alloc_len & 0xff;
|
||||||
c.page = &buf;
|
c.page = &buf;
|
||||||
c.page->bytes = 0;
|
c.page->bytes = 0;
|
||||||
c.page->sectors = 0;
|
c.page->sectors = 0;
|
||||||
@ -678,8 +694,7 @@ void spc_select_write_params(struct burn_drive *d,
|
|||||||
/* ts A61007 : moved up to burn_disc_write() */
|
/* ts A61007 : moved up to burn_disc_write() */
|
||||||
/* a ssert(d->mdata->valid); */
|
/* a ssert(d->mdata->valid); */
|
||||||
|
|
||||||
memset(c.page->data, 0, 8 + 2 + d->mdata->write_page_length);
|
c.page->bytes = alloc_len;
|
||||||
c.page->bytes = 8 + 2 + d->mdata->write_page_length;
|
|
||||||
|
|
||||||
burn_print(12, "using write page length %d (valid %d)\n",
|
burn_print(12, "using write page length %d (valid %d)\n",
|
||||||
d->mdata->write_page_length, d->mdata->write_page_valid);
|
d->mdata->write_page_length, d->mdata->write_page_valid);
|
||||||
@ -716,6 +731,7 @@ void spc_probe_write_modes(struct burn_drive *d)
|
|||||||
int last_try = 0;
|
int last_try = 0;
|
||||||
struct command c;
|
struct command c;
|
||||||
|
|
||||||
|
mmc_start_if_needed(d, 1);
|
||||||
if (mmc_function_spy(d, "spc_probe_write_modes") <= 0)
|
if (mmc_function_spy(d, "spc_probe_write_modes") <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -733,11 +749,8 @@ void spc_probe_write_modes(struct burn_drive *d)
|
|||||||
try_block_type = useable_block_type;
|
try_block_type = useable_block_type;
|
||||||
last_try= 1;
|
last_try= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
scsi_init_command(&c, SPC_MODE_SELECT,sizeof(SPC_MODE_SELECT));
|
scsi_init_command(&c, SPC_MODE_SELECT,sizeof(SPC_MODE_SELECT));
|
||||||
/*
|
|
||||||
memcpy(c.opcode, SPC_MODE_SELECT, sizeof(SPC_MODE_SELECT));
|
|
||||||
c.oplen = sizeof(SPC_MODE_SELECT);
|
|
||||||
*/
|
|
||||||
c.retry = 1;
|
c.retry = 1;
|
||||||
c.opcode[8] = 8 + 2 + 0x32;
|
c.opcode[8] = 8 + 2 + 0x32;
|
||||||
c.page = &buf;
|
c.page = &buf;
|
||||||
@ -766,7 +779,6 @@ void spc_probe_write_modes(struct burn_drive *d)
|
|||||||
key = c.sense[2];
|
key = c.sense[2];
|
||||||
asc = c.sense[12];
|
asc = c.sense[12];
|
||||||
ascq = c.sense[13];
|
ascq = c.sense[13];
|
||||||
|
|
||||||
if (key)
|
if (key)
|
||||||
burn_print(7, "%d not supported\n", try_block_type);
|
burn_print(7, "%d not supported\n", try_block_type);
|
||||||
else {
|
else {
|
||||||
@ -812,6 +824,7 @@ void spc_probe_write_modes(struct burn_drive *d)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ( ts A61229 : shouldn't this go to mmc.c too ?) */
|
/* ( ts A61229 : shouldn't this go to mmc.c too ?) */
|
||||||
@ -919,6 +932,24 @@ enum response scsi_error_msg(struct burn_drive *d, unsigned char *sense,
|
|||||||
int *key, int *asc, int *ascq)
|
int *key, int *asc, int *ascq)
|
||||||
{
|
{
|
||||||
char *msg;
|
char *msg;
|
||||||
|
static char key_def[16][40] = {
|
||||||
|
"(no specific error)",
|
||||||
|
"Recovered error",
|
||||||
|
"Drive not ready",
|
||||||
|
"Medium error",
|
||||||
|
"Drive error",
|
||||||
|
"Illegal request",
|
||||||
|
"Drive event",
|
||||||
|
"Data protected",
|
||||||
|
"Blank/Nonblank",
|
||||||
|
"Vendor specific code",
|
||||||
|
"Copy aborted",
|
||||||
|
"Command aborted",
|
||||||
|
"(obsolete error code)",
|
||||||
|
"Volume overflow",
|
||||||
|
"Miscompare",
|
||||||
|
"(reserved error code)",
|
||||||
|
};
|
||||||
|
|
||||||
msg= msg_data;
|
msg= msg_data;
|
||||||
*key= *asc= *ascq= -1;
|
*key= *asc= *ascq= -1;
|
||||||
@ -930,7 +961,7 @@ enum response scsi_error_msg(struct burn_drive *d, unsigned char *sense,
|
|||||||
if (senselen<=0 || senselen>13)
|
if (senselen<=0 || senselen>13)
|
||||||
*ascq = sense[13];
|
*ascq = sense[13];
|
||||||
|
|
||||||
sprintf(msg, "[%X %2.2X %2.2X] ", *key, *asc, *ascq);
|
sprintf(msg, "[%X %2.2X %2.2X] ", (*key) & 0xf, *asc, *ascq);
|
||||||
msg= msg + strlen(msg);
|
msg= msg + strlen(msg);
|
||||||
|
|
||||||
burn_print(12, "CONDITION: 0x%x 0x%x 0x%x on %s %s\n",
|
burn_print(12, "CONDITION: 0x%x 0x%x 0x%x on %s %s\n",
|
||||||
@ -1142,6 +1173,11 @@ enum response scsi_error_msg(struct burn_drive *d, unsigned char *sense,
|
|||||||
sprintf(msg, "Medium not present");
|
sprintf(msg, "Medium not present");
|
||||||
d->status = BURN_DISC_EMPTY;
|
d->status = BURN_DISC_EMPTY;
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
case 0x57:
|
||||||
|
if (*key != 3 || *ascq != 0)
|
||||||
|
break;
|
||||||
|
sprintf(msg, "Unable to recover Table-of-Content");
|
||||||
|
return FAIL;
|
||||||
case 0x63:
|
case 0x63:
|
||||||
if (*key != 5)
|
if (*key != 5)
|
||||||
break;
|
break;
|
||||||
@ -1194,8 +1230,8 @@ enum response scsi_error_msg(struct burn_drive *d, unsigned char *sense,
|
|||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
sprintf(msg_data,
|
sprintf(msg_data,
|
||||||
"Failure. See mmc3r10g.pdf: Sense Key %X ASC %2.2X ASCQ %2.2X",
|
"See MMC specs: Sense Key %X \"%s\", ASC %2.2X ASCQ %2.2X",
|
||||||
*key, *asc, *ascq);
|
*key & 0xf, key_def[(*key) & 0xf], *asc, *ascq);
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1229,6 +1265,8 @@ static char *scsi_command_name(unsigned int c, int flag)
|
|||||||
return "FORMAT UNIT";
|
return "FORMAT UNIT";
|
||||||
case 0x1b:
|
case 0x1b:
|
||||||
return "START/STOP UNIT";
|
return "START/STOP UNIT";
|
||||||
|
case 0x12:
|
||||||
|
return "INQUIRY";
|
||||||
case 0x1e:
|
case 0x1e:
|
||||||
return "PREVENT/ALLOW MEDIA REMOVAL";
|
return "PREVENT/ALLOW MEDIA REMOVAL";
|
||||||
case 0x23:
|
case 0x23:
|
||||||
@ -1258,7 +1296,7 @@ static char *scsi_command_name(unsigned int c, int flag)
|
|||||||
case 0x55:
|
case 0x55:
|
||||||
return "MODE SELECT";
|
return "MODE SELECT";
|
||||||
case 0x5a:
|
case 0x5a:
|
||||||
return "SEND OPC INFORMATION";
|
return "MODE SENSE";
|
||||||
case 0x5b:
|
case 0x5b:
|
||||||
return "CLOSE TRACK/SESSION";
|
return "CLOSE TRACK/SESSION";
|
||||||
case 0x5c:
|
case 0x5c:
|
||||||
@ -1336,3 +1374,119 @@ int scsi_notify_error(struct burn_drive *d, struct command *c,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ts A91106 */
|
||||||
|
/* @param flag bit0= do not show eventual data payload sent to the drive
|
||||||
|
(never with WRITE commands)
|
||||||
|
bit1= show write length and target LBA in decimal
|
||||||
|
*/
|
||||||
|
int scsi_show_cmd_text(struct command *c, void *fp_in, int flag)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
FILE *fp = fp_in;
|
||||||
|
|
||||||
|
fprintf(fp, "\n%s\n",
|
||||||
|
scsi_command_name((unsigned int) c->opcode[0], 0));
|
||||||
|
for(i = 0; i < 16 && i < c->oplen; i++)
|
||||||
|
fprintf(fp, "%2.2x ", c->opcode[i]);
|
||||||
|
if (i > 0)
|
||||||
|
fprintf(fp, "\n");
|
||||||
|
if (flag & 1)
|
||||||
|
return 1;
|
||||||
|
if (c->opcode[0] == 0x2A) { /* WRITE 10 */
|
||||||
|
if (flag & 2)
|
||||||
|
fprintf(fp, "%d -> %d\n",
|
||||||
|
(c->opcode[7] << 8) | c->opcode[8],
|
||||||
|
mmc_four_char_to_int(c->opcode + 2));
|
||||||
|
} else if (c->opcode[0] == 0xAA) { /* WRITE 12 */
|
||||||
|
if (flag & 2)
|
||||||
|
fprintf(fp, "%d -> %d\n",
|
||||||
|
mmc_four_char_to_int(c->opcode + 6),
|
||||||
|
mmc_four_char_to_int(c->opcode + 2));
|
||||||
|
} else if (c->dir == TO_DRIVE) {
|
||||||
|
fprintf(fp, "To drive: %db\n", c->page->bytes);
|
||||||
|
for (i = 0; i < c->page->bytes; i++)
|
||||||
|
fprintf(fp, "%2.2x%c", c->page->data[i],
|
||||||
|
((i % 20) == 19 ? '\n' : ' '));
|
||||||
|
if (i % 20)
|
||||||
|
fprintf(fp, "\n");
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ts A91106 */
|
||||||
|
int scsi_show_cmd_reply(struct command *c, void *fp_in, int flag)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
FILE *fp = fp_in;
|
||||||
|
|
||||||
|
if (c->dir != FROM_DRIVE)
|
||||||
|
return 2;
|
||||||
|
if (c->opcode[0] == 0x28 || c->opcode[0] == 0x3C ||
|
||||||
|
c->opcode[0] == 0xA8 || c->opcode[0] == 0xBE) {
|
||||||
|
/* READ commands */
|
||||||
|
/* >>> report amount of data */;
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
fprintf(fp, "From drive: %db\n", c->dxfer_len);
|
||||||
|
for (i = 0; i < c->dxfer_len; i++)
|
||||||
|
fprintf(fp, "%2.2x%c", c->page->data[i],
|
||||||
|
((i % 20) == 19 ? '\n' : ' '));
|
||||||
|
if (i % 20)
|
||||||
|
fprintf(fp, "\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ts A91218 (former sg_log_cmd ts A70518) */
|
||||||
|
/** Logs command (before execution) */
|
||||||
|
int scsi_log_cmd(struct command *c, void *fp_in, int flag)
|
||||||
|
{
|
||||||
|
FILE *fp = fp_in;
|
||||||
|
|
||||||
|
if (fp != NULL && (fp == stderr || (burn_sg_log_scsi & 1))) {
|
||||||
|
scsi_show_cmd_text(c, fp, 0);
|
||||||
|
if (burn_sg_log_scsi & 4)
|
||||||
|
fflush(fp);
|
||||||
|
}
|
||||||
|
if (fp == stderr || !(burn_sg_log_scsi & 2))
|
||||||
|
return 1;
|
||||||
|
scsi_log_cmd(c, stderr, flag);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ts A91221 (former sg_log_err ts A91108) */
|
||||||
|
/** Logs outcome of a sg command.
|
||||||
|
@param flag bit0 causes an error message
|
||||||
|
bit1 do not print duration
|
||||||
|
*/
|
||||||
|
int scsi_log_err(struct command *c, void *fp_in, unsigned char sense[18],
|
||||||
|
int duration, int flag)
|
||||||
|
{
|
||||||
|
char durtxt[20];
|
||||||
|
FILE *fp = fp_in;
|
||||||
|
|
||||||
|
if(fp != NULL && (fp == stderr || (burn_sg_log_scsi & 1))) {
|
||||||
|
if(flag & 1) {
|
||||||
|
durtxt[0] = 0;
|
||||||
|
if (!(flag & 2))
|
||||||
|
sprintf(durtxt, " (%6d ms)\n",duration);
|
||||||
|
fprintf(fp, "+++ key=%X asc=%2.2Xh ascq=%2.2Xh%s\n",
|
||||||
|
sense[2], sense[12], sense[13], durtxt);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
scsi_show_cmd_reply(c, fp, 0);
|
||||||
|
if (!(flag & 2))
|
||||||
|
fprintf(fp,"%6d ms\n", duration);
|
||||||
|
}
|
||||||
|
if (burn_sg_log_scsi & 4)
|
||||||
|
fflush(fp);
|
||||||
|
}
|
||||||
|
if (fp == stderr || !(burn_sg_log_scsi & 2))
|
||||||
|
return 1;
|
||||||
|
scsi_log_err(c, stderr, sense, duration, flag);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -59,4 +59,20 @@ int scsi_notify_error(struct burn_drive *, struct command *c,
|
|||||||
/* ts A70519 */
|
/* ts A70519 */
|
||||||
int scsi_init_command(struct command *c, unsigned char *opcode, int oplen);
|
int scsi_init_command(struct command *c, unsigned char *opcode, int oplen);
|
||||||
|
|
||||||
|
/* ts A91106 */
|
||||||
|
int scsi_show_cmd_text(struct command *c, void *fp, int flag);
|
||||||
|
|
||||||
|
/* ts A91106 */
|
||||||
|
int scsi_show_cmd_reply(struct command *c, void *fp, int flag);
|
||||||
|
|
||||||
|
/* ts A91218 (former sg_log_cmd ts A70518) */
|
||||||
|
/** Logs command (before execution) */
|
||||||
|
int scsi_log_cmd(struct command *c, void *fp, int flag);
|
||||||
|
|
||||||
|
/* ts A91221 (former sg_log_err ts A91108) */
|
||||||
|
/** Logs outcome of a sg command. */
|
||||||
|
int scsi_log_err(struct command *c, void *fp, unsigned char sense[18],
|
||||||
|
int duration, int flag);
|
||||||
|
|
||||||
|
|
||||||
#endif /*__SPC*/
|
#endif /*__SPC*/
|
||||||
|
@ -220,6 +220,7 @@ struct burn_drive
|
|||||||
/* ts A61218 from 51h READ DISC INFORMATION */
|
/* ts A61218 from 51h READ DISC INFORMATION */
|
||||||
int last_lead_in;
|
int last_lead_in;
|
||||||
int last_lead_out;
|
int last_lead_out;
|
||||||
|
int num_opc_tables; /* ts A91104: -1= not yet known */
|
||||||
int bg_format_status; /* 0=needs format start, 1=needs format restart*/
|
int bg_format_status; /* 0=needs format start, 1=needs format restart*/
|
||||||
int disc_type; /* 0="CD-DA or CD-ROM", 0x10="CD-I", 0x20="CD-ROM XA" */
|
int disc_type; /* 0="CD-DA or CD-ROM", 0x10="CD-I", 0x20="CD-ROM XA" */
|
||||||
unsigned int disc_id; /* a "32 bit binary integer" */
|
unsigned int disc_id; /* a "32 bit binary integer" */
|
||||||
|
252
libburn/write.c
252
libburn/write.c
@ -43,11 +43,19 @@
|
|||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "structure.h"
|
#include "structure.h"
|
||||||
#include "source.h"
|
#include "source.h"
|
||||||
|
#include "mmc.h"
|
||||||
|
#include "spc.h"
|
||||||
|
|
||||||
#include "libdax_msgs.h"
|
#include "libdax_msgs.h"
|
||||||
extern struct libdax_msgs *libdax_messenger;
|
extern struct libdax_msgs *libdax_messenger;
|
||||||
|
|
||||||
|
|
||||||
|
/* ts A91120 : <<< experimental */
|
||||||
|
#ifdef Libburn_mmap_write_buffeR
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* The maximum output size to be used with CD media. This is also curbed
|
/* The maximum output size to be used with CD media. This is also curbed
|
||||||
by BURN_OS_TRANSPORT_BUFFER_SIZE. The smaller number gets into effect.
|
by BURN_OS_TRANSPORT_BUFFER_SIZE. The smaller number gets into effect.
|
||||||
*/
|
*/
|
||||||
@ -882,9 +890,14 @@ ex:;
|
|||||||
next track. cdrecord does not use CLOSE TRACK at all but
|
next track. cdrecord does not use CLOSE TRACK at all but
|
||||||
ends the tracks by SYNCHRONIZE CACHE alone.
|
ends the tracks by SYNCHRONIZE CACHE alone.
|
||||||
*/
|
*/
|
||||||
if (!o->simulate)
|
/* ts A91202 :
|
||||||
if (burn_write_close_track(o, s, tnum) <= 0)
|
Peng Shao reports that his LG GH22LS30 issues an SCSI error
|
||||||
ret = 0;
|
on CLOSE TRACK even in non-dummy mode. So i better give up
|
||||||
|
this gesture which seems not be needed by any drive.
|
||||||
|
if (!o->simulate)
|
||||||
|
if (burn_write_close_track(o, s, tnum) <= 0)
|
||||||
|
ret = 0;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -1080,11 +1093,25 @@ int burn_disc_open_track_dvd_minus_r(struct burn_write_opts *o,
|
|||||||
/* ts A70214 : eventually adjust already expanded size of track */
|
/* ts A70214 : eventually adjust already expanded size of track */
|
||||||
burn_track_apply_fillup(s->track[tnum], d->media_capacity_remaining,1);
|
burn_track_apply_fillup(s->track[tnum], d->media_capacity_remaining,1);
|
||||||
|
|
||||||
|
#ifdef Libburn_pioneer_dvr_216d_with_opC
|
||||||
|
fprintf(stderr, "libburn_DEBUG: Libburn_pioneer_dvr_216d_with_opC : num_opc_tables = %d\n", d->num_opc_tables);
|
||||||
|
if (d->num_opc_tables <= 0 && !o->simulate) {
|
||||||
|
fprintf(stderr, "libburn_DEBUG: Libburn_pioneer_dvr_216d_with_opC : performing OPC\n");
|
||||||
|
d->perform_opc(d);
|
||||||
|
fprintf(stderr, "libburn_DEBUG: Libburn_pioneer_dvr_216d_with_opC : done\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef Libburn_pioneer_dvr_216d_get_evenT
|
||||||
|
mmc_get_event(d);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (o->write_type == BURN_WRITE_SAO) { /* DAO */
|
if (o->write_type == BURN_WRITE_SAO) { /* DAO */
|
||||||
/* Round track size up to 32 KiB and reserve track */
|
/* Round track size up to write chunk size and reserve track */
|
||||||
size = ((off_t) burn_track_get_sectors(s->track[tnum]))
|
size = ((off_t) burn_track_get_sectors(s->track[tnum]))
|
||||||
* (off_t) 2048;
|
* (off_t) 2048;
|
||||||
size = (size + (off_t) 0x7fff) & ~((off_t) 0x7fff);
|
if (size % o->obs)
|
||||||
|
size += (off_t) (o->obs - (size % o->obs));
|
||||||
ret = d->reserve_track(d, size);
|
ret = d->reserve_track(d, size);
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
sprintf(msg, "Cannot reserve track of %.f bytes",
|
sprintf(msg, "Cannot reserve track of %.f bytes",
|
||||||
@ -1122,14 +1149,11 @@ int burn_disc_open_track_dvd_plus_r(struct burn_write_opts *o,
|
|||||||
|
|
||||||
if (o->write_type == BURN_WRITE_SAO &&
|
if (o->write_type == BURN_WRITE_SAO &&
|
||||||
! burn_track_is_open_ended(s->track[tnum])) {
|
! burn_track_is_open_ended(s->track[tnum])) {
|
||||||
/* Round track size up to 32 KiB and reserve track */
|
/* Round track size up to write chunk size and reserve track */
|
||||||
|
|
||||||
/* ts A81208 */
|
|
||||||
/* >>> ??? round to 64 KiB for BD-R ? (It is not mandatory) */
|
|
||||||
|
|
||||||
size = ((off_t) burn_track_get_sectors(s->track[tnum]))
|
size = ((off_t) burn_track_get_sectors(s->track[tnum]))
|
||||||
* (off_t) 2048;
|
* (off_t) 2048;
|
||||||
size = (size + (off_t) 0x7fff) & ~((off_t) 0x7fff);
|
if (size % o->obs)
|
||||||
|
size += (off_t) (o->obs - (size % o->obs));
|
||||||
ret = d->reserve_track(d, size);
|
ret = d->reserve_track(d, size);
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
sprintf(msg, "Cannot reserve track of %.f bytes",
|
sprintf(msg, "Cannot reserve track of %.f bytes",
|
||||||
@ -1231,6 +1255,132 @@ int burn_disc_close_track_dvd_plus_r(struct burn_write_opts *o,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* <<<
|
||||||
|
#define Libburn_simplified_dvd_chunk_transactioN 1
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef Libburn_simplified_dvd_chunk_transactioN
|
||||||
|
|
||||||
|
/* ts A91114 : EXPERIMENTAL, NOT COMPLETELY IMPLEMENTED
|
||||||
|
|
||||||
|
Simplified data transmission for DVD. libburn via Linux USB is 30 % slower
|
||||||
|
than growisofs or cdrecord when transmitting 32 KB chunks.
|
||||||
|
With 64 KB chunks it is 20% faster than the competitors.
|
||||||
|
No heavy CPU load is visible but there might be subtle race conditions in
|
||||||
|
the USB driver which work better with shorter time gaps between WRITE
|
||||||
|
commands.
|
||||||
|
|
||||||
|
Insight: It is actually about the interference of track source reading
|
||||||
|
with SCSI writing via USB. growisofs reads with O_DIRECT into a
|
||||||
|
mmap()ed buffer. When doing the same, libburn with 32 KB chunks
|
||||||
|
reaches similar write speed.
|
||||||
|
On the other hand, 64 KB chunks are 20% faster than that and
|
||||||
|
are not improved by reading O_DIRECT.
|
||||||
|
|
||||||
|
O_DIRECT is a property of the input fd of struct burn_source.
|
||||||
|
It can only be done with properly aligned memory and with aligned
|
||||||
|
read size. Alignment size is file system system specific.
|
||||||
|
System call
|
||||||
|
mmap(NULL, (size_t) buffer_size, PROT_READ | PROT_WRITE,
|
||||||
|
MAP_SHARED | MAP_ANONYMOUS, -1, (off_t) 0);
|
||||||
|
is supposed to allocate a properly aligned buffer.
|
||||||
|
64 KB is supposed to be a safe size.
|
||||||
|
Actually mmap() seems to be the main cause for a positive effect
|
||||||
|
of O_DIRECT.
|
||||||
|
|
||||||
|
This simplified transmission function did not bring visible benefit.
|
||||||
|
So for now it is not worth to teach it all applicable details of old
|
||||||
|
CD sector oriented transmission.
|
||||||
|
|
||||||
|
@return 1= ok, go on , 2= no input with track->open_ended = nothing written
|
||||||
|
<= 0 = error
|
||||||
|
*/
|
||||||
|
static int transact_dvd_chunk(struct burn_write_opts *opts,
|
||||||
|
struct burn_track *track)
|
||||||
|
{
|
||||||
|
int curr = 0, valid, err;
|
||||||
|
struct burn_drive *d = opts->drive;
|
||||||
|
struct buffer *out = d->buffer;
|
||||||
|
unsigned char *data = out->data;
|
||||||
|
|
||||||
|
#ifdef Libburn_log_in_and_out_streaM
|
||||||
|
/* <<< ts A61031 */
|
||||||
|
static int tee_fd= -1;
|
||||||
|
if(tee_fd==-1)
|
||||||
|
tee_fd= open("/tmp/libburn_sg_readin",
|
||||||
|
O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR);
|
||||||
|
#endif /* Libburn_log_in_and_out_streaM */
|
||||||
|
|
||||||
|
|
||||||
|
/* Read a chunk full of data */
|
||||||
|
|
||||||
|
/* ??? Do we have offset padding ? >>> First produce offset padding */;
|
||||||
|
|
||||||
|
/* <<<< */
|
||||||
|
if (0 && !track->eos) {
|
||||||
|
for (curr = 0; curr < opts->obs; curr += 2048) {
|
||||||
|
if (track->source->read != NULL)
|
||||||
|
valid = track->source->read(track->source,
|
||||||
|
data + curr, 2048);
|
||||||
|
else
|
||||||
|
valid = track->source->read_xt(track->source,
|
||||||
|
data + curr, 2048);
|
||||||
|
if (valid <= 0) {
|
||||||
|
track->eos = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
track->sourcecount += valid;
|
||||||
|
|
||||||
|
#ifdef Libburn_log_in_and_out_streaM
|
||||||
|
if(tee_fd!=-1 && valid>0) {
|
||||||
|
write(tee_fd, data + curr, valid);
|
||||||
|
}
|
||||||
|
#endif /* Libburn_log_in_and_out_streaM */
|
||||||
|
|
||||||
|
}
|
||||||
|
} else if (!track->eos){
|
||||||
|
valid = track->source->read(track->source, data, opts->obs);
|
||||||
|
if (valid <= 0) {
|
||||||
|
track->eos = 1;
|
||||||
|
} else {
|
||||||
|
track->sourcecount += valid;
|
||||||
|
curr = valid;
|
||||||
|
|
||||||
|
#ifdef Libburn_log_in_and_out_streaM
|
||||||
|
if(tee_fd!=-1 && valid>0) {
|
||||||
|
write(tee_fd, data, valid);
|
||||||
|
}
|
||||||
|
#endif /* Libburn_log_in_and_out_streaM */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (curr == 0 && track->open_ended) {
|
||||||
|
|
||||||
|
/* >>> allow tail padding */;
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
if (curr < opts->obs)
|
||||||
|
memset(data + curr , 0, opts->obs - curr);
|
||||||
|
|
||||||
|
/* Write chunk */
|
||||||
|
out->bytes = opts->obs;
|
||||||
|
out->sectors = out->bytes / 2048;
|
||||||
|
err = d->write(d, d->nwa, out);
|
||||||
|
if (err == BE_CANCELLED)
|
||||||
|
return 0;
|
||||||
|
track->writecount += out->bytes;
|
||||||
|
track->written_sectors += out->sectors;
|
||||||
|
d->progress.buffered_bytes += out->bytes;
|
||||||
|
d->nwa += out->sectors;
|
||||||
|
out->bytes = 0;
|
||||||
|
out->sectors = 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* Libburn_simplified_dvd_chunk_transactioN */
|
||||||
|
|
||||||
|
|
||||||
/* ts A61218 - A81208 */
|
/* ts A61218 - A81208 */
|
||||||
int burn_dvd_write_track(struct burn_write_opts *o,
|
int burn_dvd_write_track(struct burn_write_opts *o,
|
||||||
struct burn_session *s, int tnum, int is_last_track)
|
struct burn_session *s, int tnum, int is_last_track)
|
||||||
@ -1240,6 +1390,7 @@ int burn_dvd_write_track(struct burn_write_opts *o,
|
|||||||
struct buffer *out = d->buffer;
|
struct buffer *out = d->buffer;
|
||||||
int sectors;
|
int sectors;
|
||||||
int i, open_ended = 0, ret= 0, is_flushed = 0;
|
int i, open_ended = 0, ret= 0, is_flushed = 0;
|
||||||
|
int first_buf_cap = 0, further_cap = 0, buf_cap_step = 1024;
|
||||||
|
|
||||||
/* ts A70213 : eventually expand size of track to max */
|
/* ts A70213 : eventually expand size of track to max */
|
||||||
burn_track_apply_fillup(t, d->media_capacity_remaining, 0);
|
burn_track_apply_fillup(t, d->media_capacity_remaining, 0);
|
||||||
@ -1250,6 +1401,11 @@ int burn_dvd_write_track(struct burn_write_opts *o,
|
|||||||
ret = burn_disc_open_track_dvd_minus_r(o, s, tnum);
|
ret = burn_disc_open_track_dvd_minus_r(o, s, tnum);
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
goto ex;
|
goto ex;
|
||||||
|
/* Pioneer DVR-216D rev 1.09 hates multiple buffer inquiries
|
||||||
|
before the drive buffer is full.
|
||||||
|
*/
|
||||||
|
first_buf_cap = 0;
|
||||||
|
further_cap = -1;
|
||||||
} else if (d->current_profile == 0x1b || d->current_profile == 0x2b) {
|
} else if (d->current_profile == 0x1b || d->current_profile == 0x2b) {
|
||||||
/* DVD+R , DVD+R/DL */
|
/* DVD+R , DVD+R/DL */
|
||||||
ret = burn_disc_open_track_dvd_plus_r(o, s, tnum);
|
ret = burn_disc_open_track_dvd_plus_r(o, s, tnum);
|
||||||
@ -1285,12 +1441,30 @@ int burn_dvd_write_track(struct burn_write_opts *o,
|
|||||||
for (i = 0; open_ended || i < sectors; i++) {
|
for (i = 0; open_ended || i < sectors; i++) {
|
||||||
|
|
||||||
/* From time to time inquire drive buffer */
|
/* From time to time inquire drive buffer */
|
||||||
if ((i%256)==0)
|
/* ts A91110: Eventually avoid to do this more than once
|
||||||
|
before the drive buffer is full. See above DVD-
|
||||||
|
*/
|
||||||
|
if (i == first_buf_cap ||
|
||||||
|
((i % buf_cap_step) == 0 &&
|
||||||
|
(i >= further_cap || further_cap < 0))) {
|
||||||
d->read_buffer_capacity(d);
|
d->read_buffer_capacity(d);
|
||||||
|
if (further_cap < 0)
|
||||||
|
further_cap =
|
||||||
|
d->progress.buffer_capacity / 2048 + 128;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef Libburn_simplified_dvd_chunk_transactioN
|
||||||
|
|
||||||
|
ret = transact_dvd_chunk(o, t);
|
||||||
|
if (ret <= 0)
|
||||||
|
{ret = 0; goto ex;}
|
||||||
|
i += o->obs / 2048 - 1;
|
||||||
|
d->progress.sector += o->obs / 2048 - 1;
|
||||||
|
#else
|
||||||
/* transact a (CD sized) sector */
|
/* transact a (CD sized) sector */
|
||||||
if (!sector_data(o, t, 0))
|
if (!sector_data(o, t, 0))
|
||||||
{ ret = 0; goto ex; }
|
{ ret = 0; goto ex; }
|
||||||
|
#endif
|
||||||
|
|
||||||
if (open_ended) {
|
if (open_ended) {
|
||||||
d->progress.sectors = sectors = i;
|
d->progress.sectors = sectors = i;
|
||||||
@ -1749,15 +1923,47 @@ int burn_dvd_write_sync(struct burn_write_opts *o,
|
|||||||
}
|
}
|
||||||
/* ??? padding needed ??? cowardly doing it for now */
|
/* ??? padding needed ??? cowardly doing it for now */
|
||||||
o->obs_pad = 1; /* fill-up track's last 32k buffer */
|
o->obs_pad = 1; /* fill-up track's last 32k buffer */
|
||||||
|
if (d->do_stream_recording) {
|
||||||
|
if (d->current_profile == 0x41) /* BD-R */
|
||||||
|
o->obs = Libburn_bd_re_streamed_obS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef Libburn_dvd_obs_default_64K
|
||||||
|
o->obs = 64 * 1024;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* <<< test only : Does this increase effective speed with USB ?
|
/* <<< test only : Does this increase effective speed with USB ?
|
||||||
ts A90801 : 64kB: speed with 16x DVD-R is 12 rather than 8
|
ts A90801 : 64kB: speed with 16x DVD-R is 12 rather than 8
|
||||||
>>> next try is 128 kB
|
128kB: glibc complains about double free
|
||||||
o->obs = 128 * 1024;
|
With BURN_OS_TRANSPORT_BUFFER_SIZE
|
||||||
|
enlarged to 128 MB, the first WRITE fails
|
||||||
|
with an i/o error.
|
||||||
|
o->obs = 64 * 1024;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if (o->dvd_obs_override >= 32 * 1024)
|
||||||
|
o->obs = o->dvd_obs_override;
|
||||||
|
|
||||||
|
if (o->obs > BUFFER_SIZE) {
|
||||||
|
sprintf(msg, "Chosen write chunk size %d exceeds system dependent buffer size", o->obs);
|
||||||
|
libdax_msgs_submit(libdax_messenger, d->global_index,
|
||||||
|
0x00000002, LIBDAX_MSGS_SEV_DEBUG,
|
||||||
|
LIBDAX_MSGS_PRIO_ZERO, msg, 0, 0);
|
||||||
|
o->obs = 32 * 1024; /* This size is required to work */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d->do_stream_recording &&
|
||||||
|
(d->current_profile == 0x43 || d->current_profile == 0x41) &&
|
||||||
|
o->obs < Libburn_bd_re_streamed_obS) {
|
||||||
|
/* LG GGW-H20 writes junk with stream recording and obs=32k */
|
||||||
|
sprintf(msg,
|
||||||
|
"Stream recording disabled because of small OS buffer");
|
||||||
|
libdax_msgs_submit(libdax_messenger, d->global_index,
|
||||||
|
0x00020176, LIBDAX_MSGS_SEV_NOTE,
|
||||||
|
LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0);
|
||||||
|
d->do_stream_recording = 0;
|
||||||
|
}
|
||||||
|
|
||||||
sprintf(msg, "dvd/bd Profile= %2.2Xh , obs= %d , obs_pad= %d",
|
sprintf(msg, "dvd/bd Profile= %2.2Xh , obs= %d , obs_pad= %d",
|
||||||
d->current_profile, o->obs, o->obs_pad);
|
d->current_profile, o->obs, o->obs_pad);
|
||||||
@ -2045,8 +2251,9 @@ int burn_stdio_write_track(struct burn_write_opts *o, struct burn_session *s,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
d->progress.sector++;
|
d->progress.sector++;
|
||||||
/* Flush to disk after each full MB */
|
/* Flush to disk from time to time */
|
||||||
if (d->progress.sector - prev_sync_sector >= 512) {
|
if (d->progress.sector - prev_sync_sector >=
|
||||||
|
o->stdio_fsync_size && o->stdio_fsync_size > 0) {
|
||||||
prev_sync_sector = d->progress.sector;
|
prev_sync_sector = d->progress.sector;
|
||||||
if (!o->simulate)
|
if (!o->simulate)
|
||||||
burn_stdio_sync_cache(d->stdio_fd, d, 1);
|
burn_stdio_sync_cache(d->stdio_fd, d, 1);
|
||||||
@ -2129,6 +2336,7 @@ void burn_disc_write_sync(struct burn_write_opts *o, struct burn_disc *disc)
|
|||||||
off_t default_size;
|
off_t default_size;
|
||||||
char msg[80];
|
char msg[80];
|
||||||
|
|
||||||
|
|
||||||
/* ts A60924 : libburn/message.c gets obsoleted
|
/* ts A60924 : libburn/message.c gets obsoleted
|
||||||
burn_message_clear_queue();
|
burn_message_clear_queue();
|
||||||
*/
|
*/
|
||||||
@ -2143,11 +2351,12 @@ void burn_disc_write_sync(struct burn_write_opts *o, struct burn_disc *disc)
|
|||||||
else
|
else
|
||||||
d->stream_recording_start = 0;
|
d->stream_recording_start = 0;
|
||||||
|
|
||||||
d->buffer = calloc(sizeof(struct buffer), 1);
|
/* ts A91122 : Get buffer suitable for sources made by
|
||||||
|
burn_os_open_track_src() */
|
||||||
|
d->buffer = burn_os_alloc_buffer(sizeof(struct buffer), 0);
|
||||||
if (d->buffer == NULL)
|
if (d->buffer == NULL)
|
||||||
goto fail_wo_sync;
|
goto fail_wo_sync;
|
||||||
|
|
||||||
|
|
||||||
/* >>> ts A90321
|
/* >>> ts A90321
|
||||||
|
|
||||||
memset(d->buffer, 0, sizeof(struct buffer));
|
memset(d->buffer, 0, sizeof(struct buffer));
|
||||||
@ -2368,7 +2577,8 @@ fail_wo_sync:;
|
|||||||
ex:;
|
ex:;
|
||||||
d->do_stream_recording = 0;
|
d->do_stream_recording = 0;
|
||||||
if (d->buffer != NULL)
|
if (d->buffer != NULL)
|
||||||
free((char *) d->buffer);
|
burn_os_free_buffer((char *) d->buffer,
|
||||||
|
sizeof(struct buffer), 0);
|
||||||
d->buffer = buffer_mem;
|
d->buffer = buffer_mem;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
/* test/libburner.c , API illustration of burning data or audio tracks to CD */
|
/* test/libburner.c , API illustration of burning data or audio tracks to CD */
|
||||||
/* Copyright (C) 2005 - 2009 Thomas Schmitt <scdbackup@gmx.net> */
|
/* Copyright (C) 2005 - 2010 Thomas Schmitt <scdbackup@gmx.net> */
|
||||||
/* Provided under GPLv2,see also "License and copyright aspects" at file end */
|
/* Provided under GPL, see also "License and copyright aspects" at file end */
|
||||||
|
|
||||||
|
|
||||||
/** Overview
|
/** Overview
|
||||||
@ -38,6 +38,16 @@
|
|||||||
burn_finish()
|
burn_finish()
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
|
Applications must use 64 bit off_t. E.g. by defining
|
||||||
|
#define _LARGEFILE_SOURCE
|
||||||
|
#define _FILE_OFFSET_BITS 64
|
||||||
|
or take special precautions to interface with the library by 64 bit integers
|
||||||
|
where libburn/libburn.h prescribes off_t.
|
||||||
|
This program gets fed with appropriate settings externally by libburn's
|
||||||
|
autotools generated build system.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/** See this for the decisive API specs . libburn.h is The Original */
|
/** See this for the decisive API specs . libburn.h is The Original */
|
||||||
/* For using the installed header file : #include <libburn/libburn.h> */
|
/* For using the installed header file : #include <libburn/libburn.h> */
|
||||||
@ -768,37 +778,6 @@ Read. Try. Think. Play. Write yourself some code. Be free of my copyright.
|
|||||||
|
|
||||||
Be also invited to study the code of cdrskin/cdrskin.c et al.
|
Be also invited to study the code of cdrskin/cdrskin.c et al.
|
||||||
|
|
||||||
|
|
||||||
Clarification in my name and in the name of Mario Danic, copyright holder
|
|
||||||
on toplevel of libburnia. To be fully in effect after the remaining other
|
|
||||||
copyrighted code has been replaced by ours and by copyright-free contributions
|
|
||||||
of our friends:
|
|
||||||
|
|
||||||
We, the copyright holders, agree on the interpretation that
|
|
||||||
dynamical linking of our libraries constitutes "use of" and
|
|
||||||
not "derivation from" our work in the sense of GPL, provided
|
|
||||||
those libraries are compiled from our unaltered code.
|
|
||||||
|
|
||||||
Thus you may link our libraries dynamically with applications
|
|
||||||
which are not under GPL. You may distribute our libraries and
|
|
||||||
application tools in binary form, if you fulfill the usual
|
|
||||||
condition of GPL to offer a copy of the source code -altered
|
|
||||||
or unaltered- under GPL.
|
|
||||||
|
|
||||||
We ask you politely to use our work in open source spirit
|
|
||||||
and with the due reference to the entire open source community.
|
|
||||||
|
|
||||||
If there should really arise the case where above clarification
|
|
||||||
does not suffice to fulfill a clear and neat request in open source
|
|
||||||
spirit that would otherwise be declined for mere formal reasons,
|
|
||||||
only in that case we will duely consider to issue a special license
|
|
||||||
covering only that special case.
|
|
||||||
It is the open source idea of responsible freedom which will be
|
|
||||||
decisive and you will have to prove that you exhausted all own
|
|
||||||
means to qualify for GPL.
|
|
||||||
|
|
||||||
For now we are firmly committed to maintain one single license: GPL.
|
|
||||||
|
|
||||||
History:
|
History:
|
||||||
libburner is a compilation of my own contributions to test/burniso.c and
|
libburner is a compilation of my own contributions to test/burniso.c and
|
||||||
fresh code which replaced the remaining parts under copyright of
|
fresh code which replaced the remaining parts under copyright of
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
/* test/telltoc.c , API illustration of obtaining media status info */
|
/* test/telltoc.c , API illustration of obtaining media status info */
|
||||||
/* Copyright (C) 2006 - 2007 Thomas Schmitt <scdbackup@gmx.net>
|
/* Copyright (C) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
|
||||||
Provided under GPL version 2 */
|
Provided under GPL */
|
||||||
|
|
||||||
/** Overview
|
/** Overview
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user