Compare commits

..

23 Commits

Author SHA1 Message Date
9785038c3f Started logical separation of libisofs and libburn 2006-11-13 00:13:21 +00:00
6f52cc391b Fixed Makefile.am 2006-09-20 20:08:02 +00:00
76fc21ec73 Changed Makefile.am behaviour 2006-09-20 19:58:15 +00:00
6d2d764fc7 Removed --enable-docs switch from 0.2.2 2006-09-20 17:28:22 +00:00
3b5cc599e6 Reverted configure.ac change which broke cdrskin_compile 2006-09-20 17:20:50 +00:00
086154e9e2 Tagged ZeroTwoTwo release 2006-09-20 15:07:09 +00:00
4b9c45e86d Fixed bug with dev=1,1,0 (ticket 75) 2006-09-20 13:42:30 +00:00
a0b5f33654 Backported disabled building of static libs by default 2006-09-20 12:45:54 +00:00
13b562a273 Imported CONTRIBUTORS to 0.2.2 branch 2006-09-20 10:31:06 +00:00
26c64e5a45 Added CONTRIBUTORS file in 0.2.2 branch 2006-09-20 09:48:53 +00:00
e18b16149c Backported fix for issue where using joliet without Rockridge would create broken iso 2006-09-20 08:45:30 +00:00
1d006990d1 Fixed 0.2.2RC build system 2006-09-19 17:17:04 +00:00
e2fa483126 Backported fix for charset warning and memory leaks 2006-09-19 17:07:21 +00:00
a52eb43dc6 Added error message in case of failed eject 2006-09-19 14:06:40 +00:00
101c06d4b4 Allowed driveropts=burnproof as alias for burnfree 2006-09-19 12:47:26 +00:00
037fdfb8bf Removed obsolete test files 2006-09-18 20:44:43 +00:00
640cdaff1f Added several files to EXTRA_DIST 2006-09-18 14:41:43 +00:00
a25c13ec62 Changed configure.ac micro-version 2006-09-18 14:28:40 +00:00
810f13db1e Removed obsolete files 2006-09-18 14:25:33 +00:00
5f1f2187f2 Started initial preparations for 0.0.2 release 2006-09-18 14:23:30 +00:00
6f9c08e089 Backported inclusion of doc/comments in source tarball 2006-09-17 13:18:05 +00:00
3eedf0327b Backported fix for premature return from burn_disc_erase on some drives 2006-09-17 11:13:14 +00:00
bf4545e803 Branched 0.2.2 milestone 2006-09-16 20:20:09 +00:00
61 changed files with 1604 additions and 8967 deletions

View File

@ -8,13 +8,10 @@ lib_LTLIBRARIES = libburn/libburn.la libisofs/libisofs.la
# Build libraries
libburn_libburn_la_LDFLAGS = \
-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
libburn_libburn_la_LIBADD = $(LIBBURN_ARCH_LIBS) $(THREAD_LIBS)
libburn_libburn_la_SOURCES = \
libburn/async.c \
libburn/async.h \
libburn/back_hacks.h \
libburn/cleanup.c \
libburn/cleanup.h \
libburn/crc.c \
libburn/crc.h \
libburn/debug.c \
@ -29,10 +26,8 @@ libburn_libburn_la_SOURCES = \
libburn/lec.c \
libburn/lec.h \
libburn/libburn.h \
libburn/libdax_audioxtr.h \
libburn/libdax_audioxtr.c \
libburn/libdax_msgs.h \
libburn/libdax_msgs.c \
libburn/message.c \
libburn/message.h \
libburn/mmc.c \
libburn/mmc.h \
libburn/null.c \
@ -62,8 +57,6 @@ libburn_libburn_la_SOURCES = \
libburn/write.h \
version.h
## libburn/sg-@ARCH@.c \
libisofs_libisofs_la_LDFLAGS = \
-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
libisofs_libisofs_la_SOURCES = \
@ -97,8 +90,6 @@ libinclude_HEADERS = \
## Build test applications
noinst_PROGRAMS = \
test/libburner \
test/dewav \
test/fake_au \
test/iso \
test/poll \
test/toc \
@ -110,12 +101,6 @@ bin_PROGRAMS = \
test_libburner_CPPFLAGS = -Ilibburn
test_libburner_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
test_libburner_SOURCES = test/libburner.c
test_dewav_CPPFLAGS = -Ilibburn
test_dewav_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
test_dewav_SOURCES = test/dewav.c
test_fake_au_CPPFLAGS =
test_fake_au_LDADD =
test_fake_au_SOURCES = test/fake_au.c
test_poll_CPPFLAGS = -Ilibburn
test_poll_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
test_poll_SOURCES = test/poll.c
@ -131,10 +116,9 @@ test_iso_SOURCES = test/iso.c
## cdrskin construction site - ts A60816
cdrskin_cdrskin_CPPFLAGS = -Ilibburn
cdrskin_cdrskin_CFLAGS = -DCdrskin_libburn_0_2_3
cdrskin_cdrskin_CFLAGS = -DCdrskin_libburn_0_2_2
cdrskin_cdrskin_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
cdrskin_cdrskin_SOURCES = cdrskin/cdrskin.c cdrskin/cdrfifo.c cdrskin/cdrfifo.h cdrskin/cdrskin_timestamp.h
## cdrskin_cdrskin_SOURCES = cdrskin/cdrskin.c cdrskin/cdrfifo.c cdrskin/cdrfifo.h cdrskin/cleanup.c cdrskin/cleanup.h cdrskin/cdrskin_timestamp.h
cdrskin_cdrskin_SOURCES = cdrskin/cdrskin.c cdrskin/cdrfifo.c cdrskin/cdrfifo.h cdrskin/cleanup.c cdrskin/cleanup.h cdrskin/cdrskin_timestamp.h
##
## Open questions: how to compute $timestamp and express -DX="$timestamp"
##
@ -215,9 +199,5 @@ EXTRA_DIST = \
cdrskin/changelog.txt \
cdrskin/cdrskin_eng.html \
cdrskin/wiki_plain.txt \
cdrskin/cleanup.h \
cdrskin/cleanup.c \
libburn/sg-freebsd.c \
libburn/sg-linux.c \
COPYING

21
README
View File

@ -24,18 +24,12 @@ This libburn.pykix.org toplevel README (C) 2006 Thomas Schmitt
Build and Installation
Our build system is based on autotools. For preparing the build of a SVN
snapshot you will need autotools of at least version 1.7.
Check out from SVN by
svn co http://libburn-svn.pykix.org/trunk libburn_pykix
and apply autotools by
./bootstrap
Alternatively you may unpack a release tarball for which you do not need
autotools installed.
Our build system is based on autotools.
User experience tells us that you will need at least autotools version 1.7.
To build libburn.pykix.org and its subprojects it should be sufficient to go
into its toplevel directory (here: "libburn_pykix") and execute
into its toplevel directory and execute
./bootstrap (needed if you downloaded from SVN and not a release tarball)
./configure
make
@ -152,13 +146,6 @@ Project history as far as known to me:
- 16th September 2006 feature freeze for release of libburn-0.2.2 .
- 20th September 2006 release of libburn-0.2.2 .
- 26th October 2006 feature freeze for cdrskin-0.2.4 based on libburn-0.2.3 .
This version of cdrskin is much more cdrecord compatible in repect
to drive addressing and audio features.
------------------------------------------------------------------------------
This program is free software; you can redistribute it and/or modify

View File

@ -1,3 +1,18 @@
dnl Function to link an architecture specific file
dnl LINK_ARCH_SRC(source_dir, arch, source_file)
AC_DEFUN([COPY_ARCH_SRC],
[
echo "copying $1/$2/$3 -> $1/$3"
old="$srcdir/$1/$2/$3"
new="$srcdir/$1/$3"
cat >$new <<__EOF__
/* WARNING: This file was automatically generated!
* Original: $old
*/
__EOF__
cat >>$new <$old
])
AC_DEFUN([TARGET_SHIZZLE],
[
ARCH=""
@ -7,11 +22,6 @@ AC_DEFUN([TARGET_SHIZZLE],
case $target in
*-*-linux*)
ARCH=linux
LIBBURN_ARCH_LIBS=
;;
*-*-freebsd*)
ARCH=freebsd
LIBBURN_ARCH_LIBS=-lcam
;;
*)
AC_ERROR([You are attempting to compile for an unsupported platform])
@ -19,4 +29,9 @@ AC_DEFUN([TARGET_SHIZZLE],
esac
AC_MSG_RESULT([$ARCH])
# this doesn't actually do anything yet.. but it will someday when we port
# libburn
#COPY_ARCH_SRC(libburn, $ARCH, transport.c)
])

View File

@ -3,5 +3,4 @@
aclocal
libtoolize --copy --force
autoconf
autoheader
automake --foreign --add-missing --copy --include-deps

View File

@ -26,12 +26,12 @@ following possible.
cdrskin. By Thomas Schmitt <scdbackup@gmx.net>
Integrated sub project of libburn.pykix.org but also published via:
http://scdbackup.sourceforge.net/cdrskin_eng.html
http://scdbackup.sourceforge.net/cdrskin-0.2.4.tar.gz
http://scdbackup.sourceforge.net/cdrskin-0.2.2.tar.gz
Copyright (C) 2006 Thomas Schmitt
------------------------------------------------------------------------------
On top of libburn there is implemented cdrskin 0.2.4, a limited cdrecord
On top of libburn there is implemented cdrskin 0.2.2, a limited cdrecord
compatibility wrapper which allows to use some libburn features from
the command line.
Interested users of cdrecord are invited to participate in the development
@ -46,10 +46,9 @@ protection against possible damages. You use this on your own risk.
Don't blame me or other authors of libburn if anything goes wrong.
I used it on my own risk with :
SuSE 7.2, kernel 2.4.4, ide-scsi emulation, LITE-ON LTR48125S CD burner, 2002
SuSE 9.0, kernel 2.4.21, ide-scsi emulation, LG GSA-4082B CD/DVD burner, 2004
NEC ND-4570A CD/DVD burner, 2006
RIP-14.4, kernel 2.6.14, no ide-scsi, with all above burners
SuSE 7.2, kernel 2.4.4, ide-scsi emulation, LITE-ON LTR48125S CD burner
SuSE 9.0, kernel 2.4.21, ide-scsi emulation, LG GSA-4082B CD/DVD burner
RIP-14.4, kernel 2.6.14, no ide-scsi, with both above burners
It fails to compile or run on SuSE 6.4 (kernel 2.2.14).
It does not find the IDE CD burner on SuSE 7.2 without ide-scsi.
@ -59,16 +58,16 @@ systems, including 64 bit systems. (Further reports are welcome.)
Compilation, First Glimpse, Installation
Obtain cdrskin-0.2.4.tar.gz , take it to a directory of your choice and do:
Obtain cdrskin-0.2.2.tar.gz , take it to a directory of your choice and do:
tar xzf cdrskin-0.2.4.tar.gz
cd cdrskin-0.2.4
tar xzf cdrskin-0.2.2.tar.gz
cd cdrskin-0.2.2
Or obtain a libburn.pykix.org SVN snapshot,
go into the toplevel directory of the snapshot (e.g. cd libburn_pykix ),
and execute the autotools script ./bootstrap . Use autools version >= 1.7 .
Within that toplevel directory of either cdrskin-0.2.4 or libburn then execute:
Within that toplevel directory of either cdrskin-0.2.2 or libburn then execute:
./configure
make
@ -125,13 +124,17 @@ On Linux 2.4 this would be some /dev/sgN and on 2.6. some /dev/hdX.
The output of cdrskin --devices might look like
0 dev='/dev/sg0' rwrwr- : '_NEC' 'DVD_RW ND-4570A'
1 dev='/dev/sg1' rwrw-- : 'HL-DT-ST' 'DVDRAM GSA-4082B'
0 dev='/dev/sg0' rwrwr- : 'TEAC' 'CD-ROM CD-532S'
1 dev='/dev/sg1' rwrw-- : 'LITE-ON' 'LTR-48125S'
So full and insecure enabling of both for everybody would look like
chmod a+rw /dev/sg0 /dev/sg1
(The CD-ROM is in these examples only for demonstrating the presence of another
SCSI device. This /dev/sg0 may be left as it is and stay invisible for normal
users.)
I strongly discourage to run cdrskin with setuid root or via sudo !
It is not checked for the necessary degree of hacker safety.
@ -140,57 +143,43 @@ It is not checked for the necessary degree of hacker safety.
Get an overview of cdrecord style addresses of available devices
cdrskin -scanbus
cdrskin dev=ATA -scanbus
Note: Adresses reported with dev=ATA are to be used with prefix "ATA:". You may
well use device file addresses as reported with --devices. Examples:
dev=0,1,0 dev=/dev/sg1 dev=ATA:1,0,0 dev=/dev/hdc
See also "Drive Addressing".
Note: Address numbers have changed since cdrskin-0.2.2 in order to become
compatible with cdrecord numbers. To get the old number scheme, use
option --old_pseudo_scsi_adr . See also "Pseudo-SCSI Adresses".
Sorry for any inconvenience.
Obtain some info about the drive
cdrskin dev=0,1,0 -checkdrive
cdrskin dev=1,1,0 -checkdrive
Obtain some info about the drive and the inserted media
cdrskin dev=0,1,0 -atip
cdrskin dev=1,1,0 -atip
Thoroughly blank a CD-RW
cdrskin -v dev=0,1,0 blank=all -eject
cdrskin -v dev=1,1,0 blank=all -eject
Blank CD-RW sufficiently for making it ready for overwrite
cdrskin -v dev=0,1,0 blank=fast -eject
cdrskin -v dev=1,1,0 blank=fast -eject
Burn image file my_image.iso to CD
cdrskin -v dev=0,1,0 speed=12 fs=8m -sao driveropts=burnfree padsize=300k \
cdrskin -v dev=1,1,0 speed=12 fs=8m -sao driveropts=burnfree padsize=300k \
-eject my_image.iso
Burn a compressed afio archive to CD on-the-fly
find . | afio -oZ - | cdrskin -v dev=0,1,0 fs=32m speed=8 -sao \
find . | afio -oZ - | cdrskin -v dev=1,1,0 fs=32m speed=8 -sao \
driveropts=burnfree padsize=300k tsize=650m -
Burn 6 audio tracks from files with different formats to CD.
Anything except .wav or .au files has to be converted into raw format first.
See below "Audio CD" for specifications.
Burn 5 audio tracks to CD
ogg123 -d raw -f track01.cd /path/to/track1.ogg
oggdec -R -o track02.cd /path/to/track2.ogg
lame --decode -t /path/to/track3.mp3 track03.cd
madplay -o raw:track04.cd /path/to/track4.mp3
mppdec --raw-le /path/to/track5.mpc track05.cd
cdrskin dev=/dev/hdc blank=fast fs=0 -eject -audio track0[1-5].cd
cdrskin dev=0,1,0 blank=fast -eject speed=48 -sao \
-audio -swab track0[1-5].cd /path/to/track6.wav
Usage example with http://scdbackup.sourceforge.net
Address may be a cdrecord-style "scsibus,target,lun" as listed with
cdrskin -scanbus (and hopefully as listed with cdrecord -scanbus) :
cdrskin -scanbus (but not as listed with cdrecord -scanbus) :
export SCDBACKUP_SCSI_ADR="0,1,0"
export SCDBACKUP_SCSI_ADR="1,1,0"
or a device file address as listed by --devices with an accessible drive :
@ -212,6 +201,11 @@ Therefore it has to be defaulted to mode SAO which needs to know the track
size in advance. non-cdrecord option tao_to_sao_tsize=650m causes each CD
to get burned up to 650 MB regardless of the payload size.
Audio features are incomplete in respect to cdrecord. Well prepaired track
files should get burned flawlessly, thanks to Lorenzo Taylor.
Builtin extraction of raw audio data from filetypes .au and .wav is not
implemented yet. See chapter "Audio CD" for details.
No multi session yet ... Please report your wishes.
@ -232,45 +226,12 @@ scdbackup which still runs a bit better with cdrecord than with cdrskin. TAO.
I have the hope that Joerg feels more flattered than annoyed by cdrskin.
Drive Addressing
Drives get addressed either via their cdrecord-style addresses as listed
with option -scanbus (see below "Pseudo-SCSI Adresses") or via the paths
of device files.
Not only device files listed by --devices may be used but also device files
which via their major,minor numbers point to the same device driver as
a listed device file.
Helpful with Linux kernel 2.4 is a special SCSI feature:
It is possible to address a scsi(-emulated) drive via associated device files
which are not listed by option --devices but point to the same SCSI addresses
as listed device files. This addressing via e.g. /dev/sr0 or /dev/scd1 is
compatible with generic read programs like dd and with write program growisofs.
Pseudo-SCSI Adresses
cdrecord and cdrskin share the syntax of SCSI addresses but not necessarily
the meaning of the components. A cdrecord-style address for cdrskin
[prefix:]scsibus,target,lun
can be interpreted in two different modes.
Standard mode tries to be compatible to original cdrecord. This should be true
with (emulated) SCSI where the /dev/sgN with is looked up with matching
scsibus,target,lun as given by the operating system.
With dev=ATA: or dev=ATAPI: the translation to /dev/hdX is purely literal
but matches the cdrecord addresses on all systems tested so far:
X = 'a' + 2 * scsibus + target
where target only may have the values 0 or 1.
In this mode, option -scanbus will list only SCSI devices unless option
dev=ATA or dev=ATAPI are given, which will suppress SCSI devices and only
show IDE drives (i.e. /dev/hdX without ide-scsi emulation).
In mode --old_pseudo_scsi_adr there is a scsibus,target,lun representation
which has nothing to do with SCSI and thus is not compatible to cdrecord.
Each number triple corresponds either to a device file address or to a
libburn drive number.
cdrecord and cdrskin share only some syntax of addresses but not the meaning
of the components. A cdrecord-style address for cdrskin
[[prefix:]scsibus,]target,lun
corresponds either to a device file address or to a libburn drive number.
Component "scsibus" indicates the translation method. Defined busses are:
0 target is the libburn drivenumber as listed with --devices
1 associated to device file /dev/sgN , target chooses N
@ -285,24 +246,17 @@ drive accessability.
Further busses may emerge as libburn evolves. "prefix" and "lun" may get
a meaning. To stay upward compatible, use addresses as printed by -scanbus.
User Defined Device Address Translation
Some programs or users have their own ideas about the address of their burner.
K3b 0.10 for example derives cdrecord addresses by own examination of the
devices and not by calling cdrecord -scanbus.
Standard mode will hopefully be fully compatible with their ideas.
Old frontends which do not know dev=ATA or dev=ATAPI and which do ask their
"cdrecord" via -scanbus may be well served with option --old_pseudo_scsi_adr .
To direct any remaining stubborn callers to the appropriate drives, cdrskin
allows to define device address aliases. Like
To direct such callers to the appropriate drives, cdrskin allows to define
device address aliases. Like
cdrskin dev_translation=+1,0,0+/dev/sg1 \
dev_translation=+ATA:1,0,0+/dev/sg1 \
dev_translation=-"cd+dvd"-0,1,0 \
dev_translation=-"cd+dvd"-1,1,0 \
...
Any of the addresses dev=1,0,0, dev=ATA:1,0,0, dev=cd+dvd will be mapped to
/dev/sg1 resp. to 0,1,0.
/dev/sg1 resp. to its standard alias 1,1,0.
The first character after "dev_translation=" defines the character which
separates the two parts of the translation pair. (Above: "+" and "-".)
@ -328,42 +282,31 @@ arguments from the following three files:
/etc/opt/cdrskin/rc
$HOME/.cdrskinrc
The files are read in the sequence given above.
Each readable line is treated as one single argument. No extra blanks.
A first character '#' marks a comment, empty lines are ignored.
Each readable line is treated as one single argument. No extra blanks,
no comments, no empty lines are permitted.
Example content of a startup file:
# This is the default device
dev=0,1,0
# To accomodate to eventual remnant cdrskin-0.2.2 addresses
dev_translation=+1,0,0+0,1,0
# Some more options
dev=1,1,0
dev_translation=+1,0,0+1,1,0
--fifo_start_empty
fs=16m
Audio CD
Lorenzo Taylor enabled option -audio in cdrskin (thanks !) and reports neat
results with audio data files which are :
headerless PCM (i.e. uncompressed)
44100 Hz sampling rate
16 bits per sample
stereo (2 channels)
little-endian byte order with option -swab, or big-endian without -swab
Files with name extension .wav get examined wether they are in Microsoft WAVE
format with above parameters and eventually get extracted by cdrskin itself.
In the same way files with name extension .au get examined wether they are
in SUN's audio format. For both formats, track format -audio and eventual
endianness option -swab are enabled automatically.
Any other formats are to be converted to format .wav with above parameters
or to be extracted as raw CD track data by commands like those given above
under "Usage examples". Those raw files need option -audio and in most cases
option -swab to mark them as little-endian/Intel/LSB-first 16-bit data.
Incorrect endianness setting results in random noise on CD.
Builtin extraction of raw audio data from filetypes .au and .wav is not
implemented yet. Lorenzo Taylor enabled option -audio in cdrskin (thanks !)
and reports neat results with audio data files which are :
headerless
44100Hz
16bit, stereo (or 4-channel if the 4-channel bit is set),
little-endian byte order
He proposes to extract them from usual audio formats by commands like
given above under "Usage examples".
The existence of cdrecord-builtin .wav extraction seems to have
hampered the development of a standalone stripping tool. If you know
a command line that would do the trick, contact me or libburn.pykix.org .
I myself am not into audio. So libburn-hackers@pykix.org might be the
best address for suggestions, requests and bug reports.

View File

@ -20,23 +20,18 @@ set -x
# The script is to be run in the directory above the toplevel
# directory of libburn resp. cdrskin development.
#
# libburn version used: http://libburn.pykix.org
# Downloaded by:
# $ svn co http://libburn-svn.pykix.org/trunk libburn_pykix
# packed up in a tarball just to save it from inadverted changes by
# $ tar czf libburn_svn.tgz libburn_pykix
original="./libburn_svn.tgz"
# Historic moments:
# libburn version used: http://libburn.pykix.org SVN of Aug 15 2006
# packed up in a tarball just to save it from inadverted changes.
# original="./libburn_svn_A60815.tgz"
# original="./libburn_cdrskin_A60819.tgz"
original="./libburn_cdrskin_A60819.tgz"
# The top level directory in that snapshot is named
intermediate="./libburn_pykix"
# My changes are in libburn-0.2.3.ts.develop , mainly in ./cdrskin
# My changes are in libburn-0.2.1.ts.develop , mainly in ./cdrskin
changes="./libburn-0.2.3.ts.develop"
skin_rev="0.2.4"
changes="./libburn-0.2.1.ts.develop"
skin_rev="0.1.5"
# The result directory and the name of the result tarballs
target="./cdrskin-${skin_rev}"
@ -51,7 +46,9 @@ compile_cmd="./cdrskin/compile_cdrskin.sh"
compile_static_opts="-static"
compile_result="cdrskin/cdrskin"
bintarget_dynamic="cdrskin_${skin_rev}-x86-suse9_0"
# addresses relative to compile_dir :
bintarget_dynamic="../cdrskin_${skin_rev}-x86-suse9_0"
bintarget_static="$bintarget_dynamic"-static
if test -d "$changes"
@ -108,24 +105,9 @@ fi
cp -a "$cdrskin_dir" "$cdrskin_target"
# Remove copied binaries
rm "$cdrskin_target"/*.o
rm "$cdrskin_target"/cdrfifo
rm "$cdrskin_target"/cdrskin
rm "$cdrskin_target"/cleanup
for i in std new make old
do
if test -e "$cdrskin_target"/cdrskin_"$i"
then
rm "$cdrskin_target"/cdrskin_"$i"
fi
done
for i in .deps .dirstamp .libs
do
if test -e "$cdrskin_target"/"$i"
then
rm -rf "$cdrskin_target"/"$i"
fi
done
# Remove unwanted SVN stuff (TODO: avoid downloading it)
for i in "$target"/.svn "$target"/*/.svn
@ -141,14 +123,15 @@ do
fi
done
## No more : Add own libburn-README in toplevel
# cp -a "$changes"/README "$target"
# For now: Add own libburn-README in toplevel
cp -a "$changes"/README "$target"
## No more : Add modified Makefile.am
# cp -a "$changes"/Makefile.am "$target"
# Add modified Makefile.am
cp -a "$changes"/Makefile.am "$target"
# Make SVN state tarball for the libburn team
# TODO: will probably be obsoleted after sucessful merge
tar czf "$cdrskin_tarball_svn" "$target"
@ -158,20 +141,6 @@ tar czf "$cdrskin_tarball_svn" "$target"
#
( cd "$target" ; ./bootstrap )
# Remove unwanted stuff after bootstrap
for i in "$target"/autom4te.cache
do
if echo "$i" | grep '\*' >/dev/null
then
dummy=dummy
else
if test -e "$i"
then
rm -rf "$i"
fi
fi
done
# Pack it up to the new libburn+cdrskin-tarball
tar czf "$cdrskin_tarball" "$target"
@ -182,22 +151,15 @@ tar czf "$cdrskin_tarball" "$target"
./configure
make
$compile_cmd -do_strip
cp "$compile_result" "../$bintarget_dynamic"
cp "$compile_result" "$bintarget_dynamic"
if test -n "$compile_static_opts"
then
$compile_cmd $compile_static_opts -do_strip
cp "$compile_result" "../$bintarget_static"
cp "$compile_result" "$bintarget_static"
fi
)
# Remove the build area
# Disable this for debugging the merge process
rm -rf "$target"
# Show the result
./"$bintarget_dynamic" -version
./"$bintarget_static" -version
ls -l "$cdrskin_tarball"
ls -l "$bintarget_dynamic"
ls -l "$bintarget_static"

File diff suppressed because it is too large Load Diff

View File

@ -51,7 +51,7 @@ A CD recorder suitable for
GPL software included:<BR>
</H2>
<DL>
<DT>libburn-0.2.3 stabilized SVN snapshot</DT>
<DT>libburn-0.2.1 (inofficially stable SVN snapshot)</DT>
<DD>(by Derek Foreman, Ben Jansens, and team of libburn.pykix.org)</DD>
<DD>transfers data to CD</DD>
</DL>
@ -80,31 +80,10 @@ Ports to other usable systems are appreciated. Reports are welcome.
This has been achieved quite sufficiently for the needs of backup tool
<A HREF="http://scdbackup.sourceforge.net/main_eng.html">scdbackup</A>
and for data CD projects of <A HREF="http://www.k3b.org">K3b</A>
(see <A HREF="#examples">examples</A>).
Suitability for audio CD frontends has been improved much and is now being
evaluated.<BR>
(see <A HREF="#examples">examples</A>).<BR>
Further enhancements depend on people who can describe and discuss their
wishes as well as on the development of libburn.</DT>
<BR><BR>
<DT>Get an overview of drives:</DT>
<DD>$ cdrskin -scanbus</DD>
<DD>$ cdrskin dev=ATA -scanbus</DD>
<DD>$ cdrskin --devices</DD>
<DT>Get info about a particular drive or loaded media:</DT>
<DD>$ cdrskin dev=0,1,0 -checkdrive</DD>
<DD>$ cdrskin dev=ATA:1,0,0 -atip</DD>
<DD>$ cdrskin dev=/dev/hdc -toc</DD>
<DT>Make used CD-RW writable again:</DT>
<DD>$ cdrskin -v dev=/dev/sg1 blank=all -eject</DD>
<DD>$ cdrskin -v dev=/dev/dvd blank=fast -eject</DD>
<DT>Write ISO-9660 filesystem image:</DT>
<DD>$ cdrskin -v dev=/dev/hdc speed=12 fs=8m driveropts=burnfree -sao -eject padsize=300k my_image.iso</DD>
<DT>Write compressed afio archive on-the-fly:</DT>
<DD>$ find . | afio -oZ - | cdrskin -v dev=0,1,0 fs=32m speed=8 driveropts=burnfree padsize=300k -sao tsize=650m -</DD>
<DT>Write audio tracks:</DT>
<DD>$ cdrskin -v dev=ATA:1,0,0 speed=48 driveropts=burnfree -sao track1.wav track2.au -audio -swab track3.raw
<DD>
<BR>
<DT><A HREF="cdrskin_help">cdrskin -help</A></DT>
<DD>reports the cdrecord compatible options</DD>
<DT><A HREF="cdrskin__help">cdrskin --help</A></DT>
@ -115,6 +94,15 @@ wishes as well as on the development of libburn.</DT>
(Be cursed if you install cdrskin as "cdrecord" without clearly forwarding
this "don't bother Joerg" demand.)
</DD>
<DT>Currently (and sparsely) supported gestures :</DT>
<DD>$ cdrskin -scanbus</DD>
<DD>$ cdrskin dev=1,1,0 -checkdrive</DD>
<DD>$ cdrskin dev=1,1,0 -atip</DD>
<DD>$ cdrskin -v dev=1,1,0 blank=all eject_device=/dev/cdrom -eject</DD>
<DD>$ cdrskin -v dev=1,1,0 blank=fast eject_device=/dev/cdrom -eject</DD>
<DD>$ cdrskin -v dev=1,1,0 speed=12 fs=8m -sao driveropts=burnfree eject_device=/dev/cdrom -eject padsize=300k my_image.iso</DD>
<DD>$ cdrskin -v dev=1,1,0 ... ... track_1.iso padsize=300k track_2.afio</DD>
<DD>$ find . | afio -oZ - | cdrskin -v dev=1,1,0 fs=32m speed=8 -sao driveropts=burnfree padsize=300k tsize=650m -</DD>
</DL>
</P>
@ -123,6 +111,10 @@ wishes as well as on the development of libburn.</DT>
<UL>
<DT></DT>
<LI>
No audio features yet. (Note: Option -audio is enabled in cdrskin-0.1.5 as
offered below, but no beheading of .au or .wav files takes place yet.)
</LI>
<LI>
Burns only a single closed session. No -multi option yet.
</LI>
<LI>
@ -141,6 +133,12 @@ In severe cases it might be necessary to guess the device name /dev/sgN resp.
/dev/hdX of the non-ill burner if it cannot be found otherwise among its
ill peers. Alternatively one can guess the address of the ill device, remove
rw-permissions and retry the bus scan as non-superuser.
<LI>
Burners other than /dev/sg0 and /dev/hdX (i.e. without ide-scsi) need a user
supplied device address for program eject.
(Note: -eject is now working in libburn-0.2.1 SVN and the workaround described
here is obsolete with cdrskin-0.1.5 as offered below.)
</LI>
</UL>
</P>
@ -149,29 +147,30 @@ rw-permissions and retry the bus scan as non-superuser.
<P>
<DL>
<DT>Download as source code (see README):</DT>
<DD><A HREF="cdrskin-0.2.4.tar.gz">cdrskin-0.2.4.tar.gz</A>
(510 KB).
<DD><A HREF="cdrskin-0.1.4.tar.gz">cdrskin-0.1.4.tar.gz</A>
(580 KB).
</DD>
<DD>
The "stable" cdrskin tarballs are source code identical with "stable"
libburn releases or with "stabilized" libburn SVN snapshots. They get
produced via a different procedure, though.<BR>
The "stable" cdrskin tarballs are tested and eventually slightly modified
SVN snapshots from libburn.pykix.org . All modifications are to be re-merged
into that SVN repository.<BR>
cdrskin is part of libburn - full libburn is provided with cdrskin releases.
</DD>
<DD>&nbsp;</DD>
<DT>Download as single x86 binaries (untar and move to /usr/bin/cdrskin):</DT>
<DD><A HREF="cdrskin_0.2.4-x86-suse9_0.tar.gz">
cdrskin_0.2.4-x86-suse9_0.tar.gz</A>, (60 KB),
<DD><A HREF="cdrskin_0.1.4-x86-suse9_0.tar.gz">
cdrskin_0.1.4-x86-suse9_0.tar.gz</A>, (50 KB),
<DL>
<DD>runs on SuSE 9.0 (2.4.21) , RIP-14.4 (2.6.14) ,
Gentoo (2.6.15 x86_64 Athlon).</DD>
</DL>
<DD><A HREF="cdrskin_0.2.4-x86-suse9_0-static.tar.gz">
cdrskin_0.2.4-x86-suse9_0-static.tar.gz</A>, (260 KB), -static compiled,
<DD><A HREF="cdrskin_0.1.4-x86-suse9_0-static.tar.gz">
cdrskin_0.1.4-x86-suse9_0-static.tar.gz</A>, (250 KB), -static compiled,
<DL>
<DD>runs on SuSE 7.2 (2.4.4), and on the systems above.</DD>
</DL>
</DD>
<DD>&nbsp;</DD>
</DL>
<DL><DT>Documentation:</DT>
<DD><A HREF="README_cdrskin">README</A> a short introduction</DD>
@ -190,44 +189,16 @@ cdrskin_0.2.4-x86-suse9_0-static.tar.gz</A>, (260 KB), -static compiled,
<HR>
<P>
Enhancements towards previous stable version cdrskin-0.2.2:
<UL>
<LI>cdrecord compatibility with drive addresses of form [ATA:]Bus,Target,Lun.
<BR>(use option --old_pseudo_scsi_adr to get back the incompatible
Bus,Traget,Lun addressing of version 0.2.2)
</LI>
<LI>Drives adressable via links and device siblings (/dev/cdrom , /dev/scd0).
</LI>
<LI>Automatic -audio extraction with .wav files and .au files.
</LI>
<LI>Bug fix about failure to eject.</LI>
<LI>Comments and empty lines allowed in startup files.</LI>
<LI>Options -scanbus and --devices print SORRY messages about busy drives.
</LI>
<LI>Drive buffer fill indicator reports realistic percentage numbers.</LI>
<LI>Option -toc is supported, drive firmware revision gets displayed.</LI>
</UL>
</P>
<HR>
<P>
<DL>
<DT>Development snapshot, version 0.2.5 :</DT>
<DT>Development snapshot:</DT>
<DD>&nbsp;</DD>
<DD>Enhancements towards stable version 0.2.4:
<UL>
<LI>-none for now-</LI>
</UL>
</DD>
<DD><A HREF="README_cdrskin_devel">README 0.1.5</A>
<DD><A HREF="cdrskin__help_devel">cdrskin_0.1.5 --help</A></DD>
<DD><A HREF="cdrskin_help_devel">cdrskin_0.1.5 -help</A></DD>
<DD>&nbsp;</DD>
<DD><A HREF="README_cdrskin_devel">README 0.2.5</A>
<DD><A HREF="cdrskin__help_devel">cdrskin_0.2.5 --help</A></DD>
<DD><A HREF="cdrskin_help_devel">cdrskin_0.2.5 -help</A></DD>
<DD>&nbsp;</DD>
<DT>Maintainers of cdrskin unstable packages please use SVN of
<A HREF="http://libburn.pykix.org"> libburn.pykix.org</A></DT>
<DD>Maintainers of cdrskin unstable packages please use SVN of
<A HREF="http://libburn.pykix.org"> libburn.pykix.org</A></DD>
<DD>Download: <KBD><B>svn co http://libburn-svn.pykix.org/trunk libburn_pykix</B>
</KBD></DD>
<DD>Build: <KBD><B>cd libburn_pykix ; ./bootstrap ; ./configure ; make</B>
@ -240,19 +211,19 @@ vanilla tools like make and gcc are needed.</DD>
<DD>&nbsp;</DD>
<DT>The following downloads are intended for adventurous end users or
admins with full system souvereignty.</DT>
<DD>Source (./bootstrap is already applied, build tested, for more see above
<DT>Source (./bootstrap is already applied, build tested, for more see above
<A HREF="README_cdrskin_devel">upcoming README</A> ):
</DD>
</DT>
<DD>
<A HREF="cdrskin-0.2.5.tar.gz">cdrskin-0.2.5.tar.gz</A>
(500 KB).
<A HREF="cdrskin-0.1.5.tar.gz">cdrskin-0.1.5.tar.gz</A>
(580 KB).
</DD>
<DD>Binary (untar and move to /usr/bin/cdrskin):</DD>
<DD><A HREF="cdrskin_0.2.5-x86-suse9_0.tar.gz">
cdrskin_0.2.5-x86-suse9_0.tar.gz</A>, (60 KB).
<DT>Binary (untar and move to /usr/bin/cdrskin):</DT>
<DD><A HREF="cdrskin_0.1.5-x86-suse9_0.tar.gz">
cdrskin_0.1.5-x86-suse9_0.tar.gz</A>, (50 KB).
</DD>
<DD><A HREF="cdrskin_0.2.5-x86-suse9_0-static.tar.gz">
cdrskin_0.2.5-x86-suse9_0-static.tar.gz</A>, (260 KB)
<DD><A HREF="cdrskin_0.1.5-x86-suse9_0-static.tar.gz">
cdrskin_0.1.5-x86-suse9_0-static.tar.gz</A>, (250 KB)
</DD>
</DL>
</P>
@ -305,6 +276,25 @@ is a GUI frontend which uses cdrecord for CD burning.)
<DT>Example for a test session with a cdrecord based scdbackup installation:</DT>
<DD>$ <KBD><B>cdrskin -scanbus</B></KBD></DD>
<DD><KBD>...</KBD></DD>
<DD><KBD>scsibus1:</KBD></DD>
<DD><KBD>&nbsp;&nbsp;&nbsp; 1,0,0 &nbsp;&nbsp; 0)&nbsp; 'TEAC' 'CD-ROM CD-532S' '?' Removable CD-ROM</KBD></DD>
<DD><KBD>scsibus2:</KBD></DD>
<DD><KBD>&nbsp;&nbsp;&nbsp; 2,2,0 &nbsp;&nbsp; 1)&nbsp; 'LITE-ON' 'LTR-48125S' '?' Removable CD-ROM</KBD></DD>
<DD>$ <KBD><B>export SCDBACKUP_SCSI_ADR="2,2,0"</B></KBD></DD>
<DD>$ <KBD><B>export SCDBACKUP_CDRECORD="cdrskin -v -v tao_to_sao_tsize=650m eject_device=/dev/cdrecorder"</B></KBD></DD>
<DD>(eject_device= has to be the appropriate address for program eject)</DD>
<DD>$ <KBD><B>scdbackup_home</B></KBD></DD>
</DL>
<DL>
<DT>Example for a permanent configuration of cdrskin based scdbackup</DT>
<DD>$ <KBD><B>cd scdbackup-0.8.6/inst</B></KBD></DD>
<DD>$ <KBD><B>export SCDBACKUP_USE_CDRSKIN=1</B></KBD></DD>
<DD>$ <KBD><B>export SCDBACKUP_EJECT_ADR=/dev/cdrecorder</B></KBD></DD>
<DD>$ <KBD><B>./CONFIGURE_CD</B></KBD></DD>
<DD><KBD>...</KBD></DD>
<DD><KBD>cdrskin 0.1.2 : limited cdrecord compatibility wrapper for libburn</KBD></DD>
<DD><KBD>...</KBD></DD>
<DD><KBD> ------------------- SCSI devices. To be used like &nbsp;&nbsp; 0,0,0</KBD></DD>
</DL>
If your system is stricken with some ill CD device then this can stall
and you will have to press <KBD>Ctrl+C</KBD> to abort.
@ -313,34 +303,16 @@ In this case, you may execute
and try again.
<DL>
<DT></DT>
<DD><KBD>&nbsp;&nbsp;&nbsp; 2,0,0 &nbsp;&nbsp; 0)&nbsp; 'TEAC' 'CD-ROM CD-532S' '?' Removable CD-ROM</KBD></DD>
<DD>$ <KBD><B>cdrskin -scanbus dev=ATA</B></KBD></DD>
<DD><KBD>...</KBD></DD>
<DD><KBD>&nbsp;&nbsp;&nbsp; 1,0,0 &nbsp;&nbsp; 1)&nbsp; 'LITE-ON' 'LTR-48125S' '?' Removable CD-ROM</KBD></DD>
<DD>$ <KBD><B>export SCDBACKUP_SCSI_ADR="ATA:1,0,0"</B></KBD></DD>
<DD>$ <KBD><B>export SCDBACKUP_CDRECORD="cdrskin -v -v tao_to_sao_tsize=650m"</B></KBD></DD>
<DD>$ <KBD><B>scdbackup_home</B></KBD></DD>
</DL>
<DL>
<DT>Example for a permanent configuration of cdrskin based scdbackup</DT>
<DD>$ <KBD><B>cd scdbackup-0.8.6/inst</B></KBD></DD>
<DD>$ <KBD><B>export SCDBACKUP_USE_CDRSKIN=1</B></KBD></DD>
<DD>$ <KBD><B>./CONFIGURE_CD</B></KBD></DD>
<DD><KBD>...</KBD></DD>
<DD><KBD>cdrskin 0.2.4 : limited cdrecord compatibility wrapper for libburn</KBD></DD>
<DD><KBD>...</KBD></DD>
<DD><KBD> ------------------- SCSI devices. To be used like &nbsp;&nbsp; 0,0,0</KBD></DD>
<DD><KBD>&nbsp;&nbsp;&nbsp; 2,0,0 &nbsp;&nbsp; 0)&nbsp; 'TEAC' 'CD-ROM CD-532S' '?' Removable CD-ROM</KBD></DD>
<DD><KBD> ------------------- end of SCSI device list</KBD></DD>
<DD><KBD> ------------------- ATA devices. To be used like ATA:0,0,0
<DD><KBD>&nbsp;&nbsp;&nbsp; 1,0,0 &nbsp;&nbsp; 1)&nbsp; 'LITE-ON' 'LTR-48125S' '?' Removable CD-ROM</KBD></DD>
<DD><KBD>&nbsp;&nbsp;&nbsp; 1,0,0 &nbsp;&nbsp; 0)&nbsp; 'TEAC' 'CD-ROM CD-532S' '?' Removable CD-ROM</KBD></DD>
<DD><KBD>&nbsp;&nbsp;&nbsp; 2,2,0 &nbsp;&nbsp; 1)&nbsp; 'LITE-ON' 'LTR-48125S' '?' Removable CD-ROM</KBD></DD>
<DD><KBD>------------------- end of SCSI device list</KBD></DD>
<DD><KBD>...</KBD></DD>
<DD><KBD>&nbsp;&nbsp;&nbsp; * Your cdrecord offers -driveropts=burnfree with your recorder.</KBD></DD>
<DD><KBD>...</KBD></DD>
<DD><KBD>scdbackup for CD 0.8.6 : First stage of installation done.</KBD></DD>
<DD><KBD>...</KBD></DD>
<DD><KBD>Now give it a try. Run : scdbackup_home</KBD></DD>
<DD>$ <KBD><B>unset SCDBACKUP_USE_CDRSKIN</B></KBD></DD>
<DD>$ <KBD><B>unset SCDBACKUP_USE_CDRSKIN SCDBACKUP_EJECT_ADR</B></KBD></DD>
</DL>
<DL>
<DT>To get back to using cdrecord :</DT>

View File

@ -1 +1 @@
#define Cdrskin_timestamP "2006.10.28.132532"
#define Cdrskin_timestamP "2006.09.20.134219"

View File

@ -470,767 +470,49 @@ Prepared cdrskin-build for version leap
----------------------------- cycled (last cdrskin-0.1.5 ?) - 2006.09.15.101326
2006.09.15.101326 [139]
2006.09.15.101326 []
cdrskin/README
cdrskin/changelog.txt
New upload of scdbackup.sourceforge.net/cdrskin-0.1.5.tar.gz
2006.09.15.174748 [143]
cdrskin/cdrskin.c
Revoked change of 1 Sep 2006 revision 78 (full -nopad) (ticket 41)
16 Sep 2006 [144]
libburn/libburn.h
Made doxygen happy with parameter of burn_drive_get_adr
2006.09.16.194730 [145]
Sep 2006 []
000_CAUTION_RELEASE_CANDIDATE
zzz_CAUTION_RELEASE_CANDIDATE
README
Makefile.am
cdrskin/README
cdrskin/cdrskin.c
cdrskin/compile_cdrskin.sh
Perfomed version leap in respect to SVN
2006.09.19.124540 [160] [161]
cdrskin/cdrskin.c
Allowed driveropts=burnproof as alias for burnfree
2006.09.19.140716 [162] [163]
cdrskin/cdrskin.c
Added error message in case of failed eject
2006.09.20.134219 [175] [176] [177]
cdrskin/cdrskin.c
Fixed bug with dev=1,1,0 (ticket 75)
21 Sep 2006 [186]
configure.ac
Makefile.am
Forwarded changes from 0.2.2 to 0.2.3
Sep 2006 [187] [188] [189] [190]
cdrskin/cdrskin.c
cdrskin/compile_cdrskin.sh
cdrskin/cdrskin_eng.html
cdrskin/README
cdrskin/changelog.txt
- cdrskin/add_ts_changes_to_libburn_0_2_1
+ cdrskin/add_ts_changes_to_libburn_0_2_3
Makefile.am
cdrskin/cdrskin_timestamp.h
Performed development version leap to cdrskin-0.2.3
------------------------------------ cycled - cdrskin-0.2.3 - 2006.09.21.082411
21 Sep 2006 [191]
README
Clarified build from SVN versus tarball
2006.09.21.173012 [192]
cdrskin/cdrskin.c
cdrskin/add_ts_changes_to_libburn_0_2_1
cdrskin/add_ts_changes_to_libburn_0_2_2
cdrskin/compile_cdrskin.sh
Gave up compile options -tarball_0_2 , -cvs_A51208 , -libburn_0_2_1
Now standard and therefore no longer needed as macros:
Cdrskin_libburn_p_sectoR
Cdrskin_libburn_with_fd_sourcE
Cdrskin_libburn_largefilE
Cdrskin_libburn_padding_does_worK
( cd_backup_planer_dir/aux/upload )
Perfom version leap
2006.09.21.185623 [193]
cdrskin/cdrskin.c
cdrskin/compile_cdrskin.sh
Officialized gestures of pre-0.2.3 -experimental, introduced -oldfashioned
------------------------------ cycle
2006.09.21.194006 [194]
cdrskin/cdrskin.c
Investigating failure to open drive on eject
2006.09.22.133027 [195]
libburn/libburn.h
libburn/sg.c
libburn/sg.h
libburn/drive.c
cdrskin/cdrskin.c
Implemented resolving of softlinks (ticket 33)
2006.09.22.170220 [196]
libburn/libburn.h
libburn/sg.c
libburn/sg.h
libburn/drive.c
cdrskin/cdrskin.c
Implemented new API function burn_drive_convert_fs_adr()
2006.09.22.172307 [197]
cdrskin/cdrskin.c
Fixed SIGSEGV of -eject on non-existent device address
22 Sep 2006 [198]
libburn/sg.c
libburn/sg.h
libburn/drive.c
Implemented finding matching /dev/sgN from /dev/srM or /dev/scdK
(ioctl(): SCSI_IOCTL_GET_IDLUN)
2006.09.22.195414 [199]
cdrskin/cdrskin.c
Removed bug prone implementation of link resolving (now only via libburn)
2006.09.22.202631 [200]
cdrskin/cdrskin.c
Kept new address conversion from hopping on libburn drive numbers
2006.09.22.203939 [201]
cdrskin/cdrskin.c
Fixed --no_follow_links and renamed to --no_convert_fs_adr
2006.09.23.080015 [202]
libburn/drive.c
Restructured SCSI search, removed a potential bug with hdX
23 Sep 2006 [203]
libburn/libburn.h
Made burn_drive_convert_scsi_adr() a new API function
23 Sep 2006 [204]
libburn/drive.c
libburn/sg.c
Changed outdated comments
23 Sep 2006 [205]
libburn/libburn.h
libburn/drive.c
Introduced new API function burn_drive_obtain_scsi_adr()
2006.09.23.100001 [not in libburn-0.2.2 yet]
cdrskin-0.2.2/cdrskin/cdrskin.c
Backported bug fix of revision 197. Version timestamp : 2006.09.23.100001
23 Sep 2006 [206] [207]
libburn/drive.c
libburn/sg.c
Enabled unused SCSI part of struct burn_drive. Switched persistent address to burn_drive.devname
2006.09.23.114858 [208]
cdrskin/cdrskin.c
Implemented --no_pseudo_scsi_adr
2006.09.23.132755 [209]
cdrskin/cdrskin.c
libburn/drive.c
Removed a bug with SCSI address of scanned drives without such address
23 Sep 2006 [210]
cdrskin/README
Explained the new addressing mode
2006.09.23.182444 [211]
cdrskin/README
cdrskin/cdrskin.c
Bus,Target,Lun for dev=ATA and dev=ATAPI, real SCSI addressing by default
2006.09.23.183608 [212]
cdrskin/cdrskin.c
Made small improvement with debug message
2006.09.24.171706 [214]
Makefile.am
libburn/libburn.h
libburn/libdax_msgs.h
libburn/libdax_msgs.c
libburn/init.c
cdrskin/compile_cdrskin.sh
cdrskin/cdrskin.c
Added an error message handling facility (ticket 74)
2006.09.24.180836 [215]
libburn/init.c
libburn/sg.c
libburn/libdax_msgs.h
libburn/libdax_msgs.c
cdrskin/cdrskin.c
Made use of new message handling facility and removed first bugs
24 Sep 2006 [216]
libburn/libdax_msgs.h
Recorded error_code 0x00020001
24 Sep 2006 [217] [218]
Makefile.am
libburn/libburn.h
libburn/write.c
libburn/drive.c
cdrskin/compile_cdrskin.sh
Obsoleted libburn/message.[ch]
25 Sep 2006 [219]
libburn/read.c
libburn/write.c
Removed inclusion of libburn/message.h
2006.09.25.104629 [220]
libburn/init.c
libburn/drive.c
cdrskin/cdrskin.c
Converted "libburn_experimental:" messages of address conversion into "DEBUG"
2006.09.25.141035 [221]
libburn/libdax_msgs.h
libburn/libdax_msgs.c
libburn/drive.c
libburn/sg.h
libburn/sg.c
Implemented sg_close_drive_fd (ticket 74)
2006.09.25.144506 [222]
libburn/libdax_msgs.c
Achieved minimum strerror thread safety (strerror_r is burned by Unix and GNU)
2006.09.26.114552 [223]
libburn/libburn.h
libburn/init.c
libburn/libdax_msgs.c
cdrskin/cdrskin.c
Made first use of queued messages and fixed several bugs with that
2006.09.26.142824 [224]
libburn/sg.c
libburn/libdax_msgs.h
cdrskin/cdrskin.c
Made changes with usage of queued messages
24 Sep 2006 [225]
Makefile.am
libburn/libburn.h
libburn/write.c
libburn/drive.c
- libburn/message.c
- libburn/message.h
Removed libburn/message.[ch]
2006.09.26.205504 [227]
libburn/drive.c
Enhanced softlink resolution
2006.09.26.210711 [228]
libburn/drive.c
Fixed bug in enhanced softlink resolution
2006.09.27.063147 [229]
cdrskin/cdrskin.c
Fixed bug with relative device addresses and Cdrpreskin__cdrecord_to_dev()
2006.09.27.074910 [230]
cdrskin/cdrskin.c
Fixed broken -version and --help (second time for same mistake)
2006.09.27.080826 [231]
cdrskin/README
cdrskin/cdrskin.c
Allowed comments and empty lines in startup files
2006.09.27.082057 [232]
cdrskin/cdrskin.c
Prevented reading of startup files with first arg -version, -help or --help
2006.09.27.115919 [233]
libburn/drive.c
libburn/sg.h
libburn/sg.c
libburn/libdax_msgs.h
cdrskin/cdrskin.c
Disabled but did not discarded failed attempt to lock against growisofs
2006.09.27.120656 [234]
libburn/drive.h
libburn/init.c
libburn/transport.h
libburn/libburn.h
Disabled but did not discarded failed attempt to lock against growisofs
2006.09.27.134332 [235]
libburn/sg.c
Kept /dev/hdX from all having SCSI address 0,0,0
2006.09.27.142312 [236]
libburn/drive.c
Curbed endless links to 20 hops
2006.09.27.143843 [237]
libburn/sg.c
Removed obsolete code and comments
2006.09.28.074434 [238]
cdrskin/cdrskin.c
Enabled optional growisofs lock attempt via --drive_scsi_exclusive
28 Sep 2006 [239]
libburn/libburn.h
Made official exclusive==2 with burn_preset_device_open()
------------------------------------ cycled - cdrskin-0.2.3 - 2006.09.28.100934
2006.09.28.115152 [240]
cdrskin/cdrskin.c
Restored vanished line at end of -help text and added a new one
2006.10.01.104140 [243]
libburn/drive.c
cdrskin/cdrskin.c
Enhanced Cdrpreskin__cdrecord_to_dev so it warns of invisible SCSI drive.
2006.10.02.103418 [244]
libburn/libburn.h
libburn/drive.h
libburn/drive.c
libburn/libdax_msgs.h
libburn/libdax_msgs.c
cdrskin/cdrskin.c
Implemented burn_abort() and made use of it
2006.10.03.162719 [245]
Makefile.am
libburn/libburn.h
libburn/init.c
libburn/cleanup.h
libburn/cleanup.c
cdrskin/cleanup.h
cdrskin/cleanup.c
2006 []
test/libburner.c
cdrskin/compile_cdrskin.sh
cdrskin/cdrskin.c
Implemented new API function burn_set_signal_handling(), libburner uses it
5 Oct 2006 [246]
libburn/drive.c
Uploaded forgotten part of revision 245
2006.10.05.142628 [247]
libburn/libburn.h
libburn/transport.h
libburn/sg.c
libburn/sg.h
libburn/drive.c
cdrskin/cdrskin.c
Made use of SCSI_IOCTL_GET_BUS_NUMBER in hope of cdrecord compatibility
6 Oct 2006 [248]
+ libburn/asserts.txt
Listed findings on assert() within libburn
7 Oct 2006 [249]
libburn/async.c
libburn/libdax_msgs.h
libburn/asserts.txt
Got rid by soft means of assert() in async.c
2006.10.07.121234 [250]
libburn/libburn.h
libburn/async.c
libburn/drive.h
libburn/drive.c
libburn/init.c
libburn/libdax_msgs.h
libburn/sg.c
libburn/asserts.txt
Got rid of assert() in drive.c by soft means
2006.10.07.132916 [251]
libburn/init.c
libburn/async.c
Got rid of assert() in init.c by soft means
2006.10.07.142454 [252]
libburn/libburn.h
libburn/async.c
libburn/options.c
libburn/sector.c
libburn/spc.c
libburn/libdax_msgs.h
Got rid of assert() in options.c by soft means
7 Oct 2006 [253]
libburn/read.c
Got rid of assert() in read.c by soft means
2006.10.07.170913 [254]
libburn/sg.c
libburn/asserts.txt
Got rid of some assert() in sg.c by soft means
2006.10.07.175427 [255]
libburn/spc.c
libburn/async.c
libburn/libdax_msgs.h
Got rid of assert() in spc.c by soft means
2006.10.08.095016 [256]
libburn/structure.c
libburn/sector.c
libburn/spc.c
libburn/libdax_msgs.h
libburn/asserts.txt
Got rid of assert() in structure.c by soft means
8 Oct 2006 [257]
libburn/toc.c
Got rid of assert() in toc.c by soft means
8 Oct 2006 [258]
libburn/util.c
Got rid of assert() in util.c by soft means
2006.10.09.083438 [259]
libburn/write.c
libburn/structure.c
libburn/libdax_msgs.h
libburn/asserts.txt
Got rid of assert() in write.c by soft means
2006.10.09.123518 [260]
libburn/mmc.c
libburn/read.c
libburn/sector.c
libburn/mmc.h
libburn/transport.h
libburn/asserts.txt
Got rid of assert() in mmc.c by soft means
2006.10.10.112545 [261]
libburn/sector.h
libburn/sector.c
libburn/async.c
libburn/write.h
libburn/write.c
libburn/libdax_msgs.h
libburn/asserts.txt
Got rid of assert() in sector.c by soft means
2006.10.10.175444 [262]
libburn/sg.c
libburn/libdax_msgs.h
Got rid of assert() in sg.c by soft means
10 Oct 2006 [263]
libburn/asserts.txt
Got rid of assert() in libburn
2006.10.11.191959 [264]
cdrskin/cdrskin.c
cdrskin/README
Changed pseudo-cdrecord addresses: /dev/hdX = ATA:(X-'a')/2,(X-'a')%2,0
13 Oct 2006 [270]
Makefile.am
libburn/sg.c
libburn/cleanup.c
libburn/sg-linux.c
libburn/read.c
libburn/drive.c
libburn/sbc.c
libburn/transport.h
cdrskin/cleanup.c
Made libburn and cdrskin build on my Linux again
2006.10.13.114554 [271]
cdrskin/cdrskin.c
libburn/write.c
libburn/sg-linux.c
libburn/libdax_msgs.h
Removed bug in burn_disc_write_sync(): BURN_DRIVE_IDLE, then d->sync_cache()
2006.10.14.105224 [272]
libburn/sg.h
libburn/sg-freebsd.c
libburn/sg-linux.c
libburn/drive.c
Introduced burn_drive_enumerator_t to allow more complete sg-freebsd implementation
2006.10.15.133035 [274]
cdrskin/cdrskin.c
Changed ambigous include statement of libburn.h
15 Oct 2006 2006 [275]
Makefile.am
libburn/libdax_msgs.h
+ libburn/libdax_audioxtr.h
+ libburn/libdax_audioxtr.c
Implemented a first attempt of a .wav decapitator (ticket 38)
15 Oct 2006 2006 [276]
+ test/dewav.c
Implemented a first attempt of a .wav decapitator (ticket 38)
15 Oct 2006 2006 [277]
test/dewav.c
Fixed permissions of eventually created output file
15 Oct 2006 2006 [278]
test/dewav.c
cdrskin/compile_cdrskin.sh
Hunting a malloc/free memory problem
15 Oct 2006 2006 [279]
libburn/libdax_audioxtr.c
Hopefully fixed memory problem which causes sigabrt on free
15 Oct 2006 2006 [280]
libburn/libdax_audioxtr.c
Hopefully fixed problem with stdin as audio source
15 Oct 2006 2006 [281]
test/dewav.c
Made helptext print to stderr rather than stdout
2006.10.17.141053 [283]
cdrskin/cdrskin.c
cdrskin/compile_cdrskin.sh
libburn/libdax_audioxtr.h
libburn/libdax_audioxtr.c
test/dewav.c
Roughly implemented automatic .wav extraction in cdrskin
2006.10.17.164140 [284]
cdrskin/cdrskin.c
libburn/libdax_audioxtr.h
libburn/libdax_audioxtr.c
test/dewav.c
Implemented some cdrecord pickiness for .wav extraction
18 Oct 2006 [285]
test/libburner.c
Added --audio and multi-track, removed --verbose, hid --burn_for_real
2006.10.18.174334 [286]
cdrskin/cdrskin.c
Removed assumption BURN_DRIVE_IDLE==0
18 Oct 2006 [287]
cdrskin/README
Changed audio statements to reflect new situation
18 Oct 2006 [288]
cdrskin/README
Removed a typo
19 Oct 2006 [292]
test/libburner.c
Freed all tracks after burning and not only last one
2006.10.19.094543 [293]
cdrskin/cdrskin.c
cdrskin/compile_cdrskin.sh
Made cdrskin use libburn/cleanup.[oh] by default (not cdrskin/cleanup.[ch])
------------------------------------ cycled - cdrskin-0.2.3 - 2006.10.19.105730
2006.10.19.162254 [294]
cdrskin/cdrskin.c
cdrskin/cdrskin_eng.html
cdrskin/changelog.txt
Updated documentation about cdrskin-0.2.3
2006.10.19.164742 [295]
cdrskin/cdrskin.c
Corrected -help text
2006.10.20.113421 [297]
libburn/libburn.h
libburn/mmc.c
libburn/sg-linux.c
libburn/sg-freebsd.c
libburn/drive.c
cdrskin/cdrskin.c
Made cdrskin produce "ATIP start of lead" (on non-blank media for now)
20 Oct 2006 [298]
doc/comments
Updated help text of libburner
2006.10.20.151602 [299]
libburn/libburn.h
libburn/drive.c
libburn/mmc.c
libburn/libdax_msgs.h
cdrskin/cdrskin.c
Classified media with TOC read error as unsuitable (rather than as blank)
2006.10.21.103352 [300]
libburn/libburn.h
libburn/transport.h
libburn/drive.c
libburn/mmc.c
libburn/spc.c
libburn/sg-linux.c
libburn/sg-freebsd.c
libburn/libdax_msgs.h
cdrskin/cdrskin.c
Implemented some ATIP functionality
2006.10.21.103653 [301] [302]
libburn/libburn.h
Clarified relation of burn_disc_read_atip() and burn_drive_get_start_end_lba()
2006.10.21.185102 [303]
libburn/sg.h
libburn/mmc.h
libburn/mmc.c
libburn/sbc.h
libburn/sbc.c
libburn/spc.h
libburn/spc.c
libburn/drive.h
libburn/drive.c
libburn/transport.h
libburn/sg-linux.c
libburn/sg-freebsd.c
Split enumerate_common() into logic-layer, command-layer, transport-layer
2006.10.22.130341 [304]
libburn/libburn.h
libburn/mmc.c
libburn/drive.c
libburn/cleanup.c
cdrskin/cleanup.c
cdrskin/cdrskin.c
Implemented cdrskin -toc
2006.10.22.131452 [305]
cdrskin/cdrskin.c
Regulated coexistence of options -toc and -atip
23 Oct 2006 [306]
libburn/mmc.c
Made clarification in remark about atip speed conversion
2006.10.23.074430 [307]
cdrskin/cdrskin.c
Made use of burn_drive_info.revision as firmware revision text
2006.10.23.113116 [308]
libburn/libburn.h
libburn/transport.h
libburn/mmc.h
libburn/mmc.c
libburn/write.c
cdrskin/cdrskin.c
cdrskin/cdrskin_eng.html
cdrskin/README
Made available drive buffer fill during write
23 Oct 2006 [309]
libburn/sg-freebsd.c
Updated tangling of FreeBSD code with mmc.c :(
2006.10.23.134719 [310]
cdrskin/cdrskin.c
Corrected -toc track counter and notified about "hidden" tracks
2006.10.24.075039 [311]
libburn/libdax_audioxtr.h
libburn/libdax_audioxtr.c
test/dewav.c
cdrskin/cdrskin.c
Introduced extraction of .au (but not its usage within cdrskin)
2006.10.24.102107 [312]
libburn/libburn.h
libburn/structure.h
libburn/structure.c
libburn/sector.c
cdrskin/cdrskin.c
cdrskin/README
Enabled byte swapping for audio track sources, added anti option -swab
2006.10.24.130259 [313]
test/dewav.c
cdrskin/cdrskin.c
cdrskin/README
Enabled automatic extraction of .au
24 Oct 2006 [314]
Makefile.am
+ test/fake_au.c
Introduced temporary test program to produce SUN .au files
------------------------------------ cycled - cdrskin-0.2.3 - 2006.10.24.144650
2006.10.24.165427 [315]
libburn/sector.c
Closed some loopholes for byte swapping.
2006.10.24.165610 [316]
cdrskin/cdrskin.c
Enabled audio byte swapping by default (to be disabled via option -swab)
------------------------------------ cycled - cdrskin-0.2.3 - 2006.10.24.173602
25 Oct 2006 [317]
cdrskin/README
cdrskin/cdrskin_eng.html
cdrskin/wiki_plain.txt
Announced full -audio compatibility with cdrecord
------------------------------------ cycled - cdrskin-0.2.3 - 2006.10.25.160540
[]
- cdrskin/add_ts_changes_to_libburn_0_2_3
+ cdrskin/add_ts_changes_to_libburn_0_2_4
cdrskin/README
cdrskin/cdrskin.c
cdrskin/cdrskin_eng.html
cdrskin/changelog.txt
README
Preparing cdrskin version leap to cdrskin-0.2.4
(To be committed to branch)
------------------------------------ cycle - cdrskin-0.2.5
[]
- cdrskin/add_ts_changes_to_libburn_0_2_3
+ cdrskin/add_ts_changes_to_libburn_0_2_4
+ cdrskin/add_ts_changes_to_libburn_0_2_5
cdrskin/README
cdrskin/cdrskin.c
cdrskin/cdrskin_eng.html
cdrskin/changelog.txt
README
Prepare cdrskin version leap to cdrskin-0.2.5
(To be committed to trunk)
--audio and multi-track
2006 []
-reset: ioctl(fd,CDROMRESET) ioctl(fd,SG_SCSI_RESET,SG_SCSI_RESET_DEVICE)
Resolve softlinks (ticket 33)
2006 []
Try wether tao will work if finalized by mmc_close()
Find matching /dev/sgN from srM or scdM
2006 []
Open O_EXCL all devices in address resolution chain
(Might help with non-standard hdX device siblings)
2006 []
Convert libburn_experimental: into LIBDAX_MSGS_SEV_DEBUG
Convert burn_print() into libdax_msgs_submit()
2006 []
Test unlocking of all drives by burn_drive_info_free()
Test unlocking of single drive by burn_drive_grab(), burn_drive_release()
Implement a .wav decapitator (ticket 38)
2006 []
Clear outdated persistent read buffer after small CD image was read (ticket 57)
2006 []
>>> libburn/libburn.h
>>> libburn/drive.c
>>> libburn/sg.c
>>> Promoted burn_drive_is_open() to official API

View File

@ -3,7 +3,7 @@
A signal handler which cleans up an application and exits.
Provided under GPL license within GPL projects, BSD license elsewise.
Provided under GPL license within cdrskin and under BSD license elsewise.
*/
/*
@ -23,29 +23,6 @@ typedef void (*sighandler_t)(int);
#include "cleanup.h"
#ifdef __FreeBSD__
/* Signals to be caught */
static int signal_list[]= {
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT,
SIGFPE, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM,
SIGUSR1, SIGUSR2, SIGXCPU, SIGTSTP, SIGTTIN,
SIGTTOU,
SIGBUS, SIGPROF, SIGSYS, SIGTRAP,
SIGVTALRM, SIGXCPU, SIGXFSZ, -1
};
static char *signal_name_list[]= {
"SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGABRT",
"SIGFPE", "SIGSEGV", "SIGPIPE", "SIGALRM", "SIGTERM",
"SIGUSR1", "SIGUSR2", "SIGXCPU", "SIGTSTP", "SIGTTIN",
"SIGTTOU",
"SIGBUS", "SIGPROF", "SIGSYS", "SIGTRAP",
"SIGVTALRM", "SIGXCPU", "SIGXFSZ", "@"
};
static int signal_list_count= 23;
#else /* __FreeBSD__ */
/* Signals to be caught */
static int signal_list[]= {
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT,
@ -65,8 +42,6 @@ static char *signal_name_list[]= {
};
static int signal_list_count= 24;
#endif /* ! __FreeBSD__ */
/* Signals not to be caught */
static int non_signal_list[]= {
SIGKILL, SIGCHLD, SIGSTOP, SIGURG, -1
@ -87,27 +62,26 @@ static int Cleanup_handler_exit(int exit_value, int signum, int flag)
{
int ret;
if(cleanup_msg[0]!=0)
fprintf(stderr,"\n%s\n",cleanup_msg);
if(cleanup_perform_app_handler_first)
if(cleanup_app_handler!=NULL) {
ret= (*cleanup_app_handler)(cleanup_app_handle,signum,0);
if(ret==2 || ret==-2)
if(ret==2)
return(2);
}
if(cleanup_exiting) {
if(cleanup_msg[0]!=0)
fprintf(stderr,"%s\n",cleanup_msg);
fprintf(stderr,"cleanup: ABORT : repeat by pid=%d, signum=%d\n",
getpid(),signum);
return(0);
}
cleanup_exiting= 1;
if(cleanup_msg[0]!=0)
fprintf(stderr,"%s\n",cleanup_msg);
alarm(0);
if(!cleanup_perform_app_handler_first)
if(cleanup_app_handler!=NULL) {
ret= (*cleanup_app_handler)(cleanup_app_handle,signum,0);
if(ret==2 || ret==-2)
return(2);
}
if(cleanup_app_handler!=NULL)
(*cleanup_app_handler)(cleanup_app_handle,signum,0);
exit(exit_value);
}
@ -141,12 +115,8 @@ int Cleanup_set_handlers(void *handle, Cleanup_app_handler_T handler, int flag)
cleanup_msg[0]= 0;
cleanup_app_handle= handle;
cleanup_app_handler= handler;
/* <<< make cleanup_exiting thread safe to get rid of this */
if(flag&4)
cleanup_perform_app_handler_first= 1;
if(flag&1)
sig_handler= SIG_DFL;
else if(flag&2)

View File

@ -3,7 +3,7 @@
A signal handler which cleans up an application and exits.
Provided under GPL license within GPL projects, BSD license elsewise.
Provided under GPL license within cdrskin and under BSD license elsewise.
*/
#ifndef Cleanup_includeD
@ -13,7 +13,7 @@
/** Layout of an application provided cleanup function using an application
provided handle as first argument and the signal number as second
argument. The third argument is a flag bit field with no defined bits yet.
If the handler returns 2 or -2 then it has delegated exit() to some other
If the handler returns 2 then it has delegated exit() to some other
instance and the Cleanup handler shall return rather than exit.
*/
typedef int (*Cleanup_app_handler_T)(void *, int, int);

View File

@ -6,50 +6,37 @@
debug_opts=
def_opts=
libvers="-DCdrskin_libburn_0_2_3"
cleanup_src_or_obj="libburn/cleanup.o"
libdax_msgs_o="libburn/libdax_msgs.o"
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
libvers="-DCdrskin_libburn_0_2_2"
do_strip=0
static_opts=
warn_opts="-Wall"
fifo_source="cdrskin/cdrfifo.c"
compile_cdrskin=1
compile_cdrfifo=0
compile_dewav=0
for i in "$@"
do
if test "$i" = "-compile_cdrfifo"
then
compile_cdrfifo=1
elif test "$i" = "-compile_dewav"
elif test "$i" = "-tarball_0_2"
then
compile_dewav=1
libvers=
elif test "$i" = "-cvs_A51208"
then
libvers="-DCdrskin_libburn_cvs_A51208_tS"
elif test "$i" = "-cvs_A60220"
then
libvers="-DCdrskin_libburn_cvs_A60220_tS"
libdax_audioxtr_o=
libdax_msgs_o="libburn/message.o"
cleanup_src_or_obj="cdrskin/cleanup.c"
elif test "$i" = "-libburn_0_2_1"
then
libvers="-DCdrskin_libburn_0_2_1"
elif test "$i" = "-libburn_0_2_2"
then
libvers="-DCdrskin_libburn_0_2_2"
libdax_audioxtr_o=
libdax_msgs_o="libburn/message.o"
cleanup_src_or_obj="cdrskin/cleanup.c"
elif test "$i" = "-libburn_0_2_3"
then
libvers="-DCdrskin_libburn_0_2_3"
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
libdax_msgs_o="libburn/libdax_msgs.o"
cleanup_src_or_obj="libburn/cleanup.o"
elif test "$i" = "-newapi" -o "$i" = "-experimental"
then
def_opts="$def_opts -DCdrskin_new_api_tesT"
elif test "$i" = "-oldfashioned"
then
def_opts="$def_opts -DCdrskin_oldfashioned_api_usE"
elif test "$i" = "-do_not_compile_cdrskin"
then
compile_cdrskin=0
@ -69,16 +56,16 @@ do
debug_opts="$debug_opts -O2"
elif test "$i" = "-help" -o "$i" = "--help" -o "$i" = "-h"
then
echo "cdrskin/compile_cdrskin.sh : to be executed within top level directory"
echo "cdrskin/compile_cdrskin.sh : to be executed within ./cdrskin-0.1.3.0.2.ts"
echo "Options:"
echo " -compile_cdrfifo compile program cdrskin/cdrfifo."
echo " -compile_dewav compile program test/dewav without libburn."
echo " -tarball_0_2 set macro to match libburn-0.2.ts.tar.gz"
echo " -cvs_A51208 set macro to match libburn-CVS of 8 Dec 2005."
echo " -cvs_A60220 set macro to match libburn-CVS of 20 Feb 2006."
echo " -libburn_0_2_2 set macro to match libburn-0.2.2."
echo " -libburn_0_2_3 set macro to match current libburn-SVN."
echo " -libburn_0_2_1 set macro to match libburn-SVN of 15 Sep 2006."
echo " -libburn_0_2_2 set macro to match libburn-0.2.2"
echo " -do_not_compile_cdrskin omit compilation of cdrskin/cdrskin."
echo " -experimental use newly introduced libburn features."
echo " -oldfashioned use pre-0.2.2 libburn features only."
echo " -do_diet produce capability reduced lean version."
echo " -do_strip apply program strip to compiled programs."
echo " -g compile with cc option -g."
@ -98,7 +85,7 @@ echo "Build timestamp : $timestamp"
if test "$compile_cdrskin"
then
echo "compiling program cdrskin/cdrskin.c $static_opts $debug_opts $libvers $def_opts $cleanup_src_or_obj"
echo "compiling program cdrskin/cdrskin.c $static_opts $debug_opts $libvers $def_opts"
cc $warn_opts -I. $static_opts $debug_opts $libvers $def_opts \
-DCdrskin_build_timestamP='"'"$timestamp"'"' \
\
@ -106,8 +93,7 @@ then
\
cdrskin/cdrskin.c \
$fifo_source \
\
$cleanup_src_or_obj \
cdrskin/cleanup.c \
\
libburn/async.o \
libburn/debug.o \
@ -118,10 +104,9 @@ then
libburn/source.o \
libburn/structure.o \
\
libburn/message.o \
libburn/sg.o \
libburn/write.o \
$libdax_audioxtr_o \
$libdax_msgs_o \
\
libburn/mmc.o \
libburn/sbc.o \
@ -135,17 +120,6 @@ then
libburn/lec.o \
\
-lpthread
ret=$?
if test "$ret" = 0
then
dummy=dummy
else
echo >&2
echo "+++ FATAL : Compilation of cdrskin failed" >&2
echo >&2
exit 1
fi
fi
if test "$compile_cdrfifo" = 1
@ -155,43 +129,8 @@ then
-DCdrfifo_standalonE \
-o cdrskin/cdrfifo \
cdrskin/cdrfifo.c
ret=$?
if test "$ret" = 0
then
dummy=dummy
else
echo >&2
echo "+++ FATAL : Compilation of cdrfifo failed" >&2
echo >&2
exit 2
fi
fi
if test "$compile_dewav" = 1
then
echo "compiling program test/dewav.c -DDewav_without_libburN $static_opts $debug_opts"
cc $static_opts $debug_opts \
-DDewav_without_libburN \
-o test/dewav \
test/dewav.c \
libburn/libdax_audioxtr.o \
libburn/libdax_msgs.o \
\
-lpthread
ret=$?
if test "$ret" = 0
then
dummy=dummy
else
echo >&2
echo "+++ FATAL : Compilation of test/dewav failed" >&2
echo >&2
exit 2
fi
fi
if test "$do_strip" = 1
then
echo "stripping result cdrskin/cdrskin"

View File

@ -2,7 +2,7 @@
cdrskin Wiki - plain text copy
--------------------------------------------------------------------------
cdrskin-0.2.3 is the cdrecord compatibility middleware of libburn.
cdrskin is the cdrecord compatibility middleware of libburn.
Its paragon, cdrecord, is a powerful GPL'ed burn program included in Joerg
Schilling's cdrtools. cdrskin strives to be a second source for the services
@ -16,8 +16,14 @@ can be found in cdrskin/README .
--------------------------------------------------------------------------
cdrskin with CD media fails to match its paragon cdrecord on two major
fields: convenient TAO burn mode and multi session.
cdrskin with CD media fails to match its paragon cdrecord on three major
fields: convenient TAO burn mode, multi session, audio features.
Audio features are the only topic where cdrskin did not yet exploit current
libburn to the maximum. This is due to my own lack of audiophile motivation
and due to the lack of sincere users who provide me with cdrecord use cases,
help me to explore the original cdrecord behavior and serve as dedicated
testers for eventual newly introduced cdrskin audio features.
cdrskin does not provide DVD burning yet. See advise to use dvd+rw-tools
at the end of this text.
@ -74,6 +80,45 @@ has to offer both, r- and w-permission.
--------------------------------------------------------------------------
eject_device=<path> is needed to work around yet broken tray ejection of
drives. cdrskin makes a bold shell call to program "eject" and regrettably
this program does not like our addresses for SCSI devices.
/dev/hdX work fine and /dev/sg0 is quite safely guess-translated to
/dev/sr0 . /dev/sg1 et.al. need the user's help. <path> must work with eject.
--------------------------------------------------------------------------
dev_translation=<sep><from><sep><to> is needed to foist cdrskin to frontend
programs of cdrecord which do *not* ask cdrecord -scanbus but which make
own assumptions and guesses about cdrecord's device addresses.
cdrskin project - at least for now - refuses to try to provide a similar
guesswork but uses own cdrecord style addresses which have a mere
semi-automatic text mapping to real libburn addresses. See cdrskin/README,
"Pseudo-SCSI Adresses".
If you need to foist cdrskin under a frontend then you may be lucky and
both ideas of an address coincide. Especially if the frontend has the
decency to ask its "cdrecord" via option -scanbus for a list of drives.
If not, look into the error protocol of the frontend, look at the output
of a run of cdrskin --devices and give cdrskin the necessary hint.
If your frontend insists in using "0,0,0" and --devices reported
dev='/dev/sg0' resp. cdrskin -scanbus reported "1,0,0" then this
would be the appropriate translation
dev_translation=+0,0,0+/dev/sg0
The "+" character is a separator to be choosen by you.
Currently i am not aware of the need to choose any other than "+"
unless you get playful with custom translations like
dev_translation=-"cd+dvd"-1,0,0
See http://scdbackup.sourceforge.net/k3b_on_cdrskin.html
for an illustrated example with K3b 0.10 .
--------------------------------------------------------------------------
--fifo_start_empty is a throughput enhancer for unsteady data streams
like they are produced by a compressing archiver program when piping to
CD on-the-fly. It makes better use of the general property of a FIFO
@ -132,35 +177,6 @@ be a failure in any way.
--------------------------------------------------------------------------
dev_translation=<sep><from><sep><to> may be needed to foist cdrskin to
frontend programs of cdrecord which do *not* ask cdrecord -scanbus but
which make own assumptions and guesses about cdrecord's device addresses.
Normally, cdrskin understands all addresses which are suitable for cdrecord
under Linux. See cdrskin/README, "Pseudo-SCSI Adresses".
This option is mainly for (yet unknown) exotic configurations or very
stubborn frontend programs.
If a frontend refuses to work with cdrskin, look into the error protocol
of that frontend, look at the output of a run of cdrskin --devices and give
cdrskin the necessary hint.
Example: Your frontend insists in using "0,0,0" and --devices reported
dev='/dev/hdc' resp. cdrskin dev=ATA -scanbus reported "1,0,0" then this
would be the appropriate translation:
dev_translation=+0,0,0+/dev/hdc
The "+" character is a separator to be choosen by you.
Currently i am not aware of the need to choose any other than "+"
unless you get playful with custom translations like
dev_translation=-"cd+dvd"-1,0,0
See http://scdbackup.sourceforge.net/k3b_on_cdrskin.html
for an illustrated example with K3b 0.10 .
--------------------------------------------------------------------------
DVD advise:
For burning of DVD media the cdrskin project currently advises to use

View File

@ -1,4 +1,4 @@
AC_INIT([libburn], [0.2.3], [http://libburn.pykix.org])
AC_INIT([libburn], [0.2.2], [http://libburn.pykix.org])
AC_PREREQ([2.50])
dnl AC_CONFIG_HEADER([config.h])
@ -7,8 +7,6 @@ AC_CANONICAL_TARGET
AM_INIT_AUTOMAKE([subdir-objects])
AM_CONFIG_HEADER(config.h)
dnl Making releases:
dnl BURN_MICRO_VERSION += 1;
dnl BURN_INTERFACE_AGE += 1;
@ -21,7 +19,7 @@ dnl if MAJOR or MINOR version changes, be sure to change AC_INIT above to match
dnl
BURN_MAJOR_VERSION=0
BURN_MINOR_VERSION=2
BURN_MICRO_VERSION=3
BURN_MICRO_VERSION=2
BURN_INTERFACE_AGE=0
BURN_BINARY_AGE=0
BURN_VERSION=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION.$BURN_MICRO_VERSION
@ -71,18 +69,10 @@ AC_PROG_INSTALL
AC_CHECK_HEADERS()
AC_CHECK_MEMBER([struct tm.tm_gmtoff],
[AC_DEFINE(HAVE_TM_GMTOFF, 1,
[Define this if tm structure includes a tm_gmtoff entry.])],
,
[#include <time.h>])
THREAD_LIBS=-lpthread
AC_SUBST(THREAD_LIBS)
TARGET_SHIZZLE
AC_SUBST(ARCH)
AC_SUBST(LIBBURN_ARCH_LIBS)
dnl Add compiler-specific flags

View File

@ -92,26 +92,23 @@ stay upward compatible for a good while.
<pre>
Usage: test/libburner
[--drive <address>|<driveno>|"-"]
[--blank_fast|--blank_full] [--audio]
[--try_to_simulate] [--stdin_size <bytes>]
[<one or more imagefiles>|"-"]
[--verbose <level>] [--blank_fast|--blank_full]
[--burn_for_real|--try_to_simulate] [--stdin_size <bytes>]
[<imagefile>|"-"]
Examples
A bus scan (needs rw-permissions to see a drive):
test/libburner --drive -
Burn a file to drive chosen by number:
test/libburner --drive 0 my_image_file
test/libburner --drive 0 --burn_for_real my_image_file
Burn a file to drive chosen by persistent address:
test/libburner --drive /dev/hdc my_image_file
test/libburner --drive /dev/hdc --burn_for_real my_image_file
Blank a used CD-RW (is combinable with burning in one run):
test/libburner --drive /dev/hdc --blank_fast
Burn two audio tracks
lame --decode -t /path/to/track1.mp3 track1.cd
test/dewav /path/to/track2.wav -o track2.cd
test/libburner --drive /dev/hdc --audio track1.cd track2.cd
test/libburner --drive 0 --blank_fast
Burn a compressed afio archive on-the-fly, pad up to 700 MB:
( cd my_directory ; find . -print | afio -oZ - ) | \
test/libburner --drive /dev/hdc --stdin_size 734003200 -
To be read from *not mounted* CD via: afio -tvZ /dev/hdc
test/libburner --drive /dev/hdc --burn_for_real --stdin_size 734003200 -
To be read from *not mounted* CD via:
afio -tvZ /dev/hdc
Program tar would need a clean EOF which our padded CD cannot deliver.
</pre>

View File

@ -7,6 +7,5 @@ Name: libburn
Description: Disc reading/writing library
Version: @VERSION@
Requires:
Libs: -L${libdir} -lburn
Libs.private: @THREAD_LIBS@ @LIBBURN_ARCH_LIBS@
Libs: -L${libdir} -lburn @THREAD_LIBS@
Cflags: -I${includedir}/libburn

View File

@ -1,792 +0,0 @@
List of assert() calls in libburn. 6 Oct 2006.
Format:
------------------------------------------------------------------------------
Number) grep'ed line
(++ before number means: is fully done, + means is done so far )
function():
Description of abort condition.
Possible callers and their relation to the abort condition.
: Error Evaluation
=> Consequences
Eventual implementation timestamp
------------------------------------------------------------------------------
++ 1) libburn/async.c: assert(a != NULL); /* wasn't found.. this should not be possible */
static remove_worker():
A thread describing structure (struct w_list) could not be found in
order to be released.
Called by API burn_drive_scan()
Called by static erase_worker_func() , thread under API burn_disc_erase()
Called by static write_disc_worker_func(), thread under API burn_disc_write()
All three want to clean up after they are done.
: Severe Libburn Error
=> issue LIBDAX_MSGS_SEV_WARNING
ts A61006
------------------------------------------------------------------------------
++ 2) libburn/async.c: assert(!(workers && workers->drive));
API burn_drive_scan():
Before spawning a thread, the function refuses work because another
drive activity is going on.
: Severe Application Error
=> return -1; redefine @return in API , issue LIBDAX_MSGS_SEV_SORRY
ts A61006
------------------------------------------------------------------------------
+ 3) libburn/async.c: assert(workers == NULL);
API burn_drive_scan():
After thread is done and remover_worker() succeeded, there is still a
worker registered. Shall probably detect roguely appeared burn or
erase runs. (I consider to install a mutex shielded function for that.)
: Severe Libburn Error
=> Same as 1)
ts A61006
------------------------------------------------------------------------------
++ 4) libburn/async.c: assert(drive);
libburn/async.c: assert(!SCAN_GOING());
libburn/async.c: assert(!find_worker(drive));
API burn_disc_erase():
Wants to see a drive (assumes NULL == 0), wants to see no scan and
wants to see no other worker on that drive. I.e. this would tolerate
a parallel activity on another drive.
: Severe Application Error
=> (no return value), issue LIBDAX_MSGS_SEV_SORRY
ts A61006
------------------------------------------------------------------------------
++ 5) libburn/async.c: assert(!SCAN_GOING());
libburn/async.c: assert(!find_worker(opts->drive));
API burn_disc_write():
Same as 4)
: Severe Application Error
=> Same as 4)
ts A61006
---------------------------------------------------------------------
++ 6) libburn/drive.c: assert(d->busy == BURN_DRIVE_IDLE);
API burn_drive_release():
A drive is not idle on release.
: Severe Application Error
=> Same as 4)
ts A61007
------------------------------------------------------------------------------
++ 7) libburn/drive.c: assert(d->released);
burn_wait_all()
A drive is found grabbed.
Called by burn_drive_scan_sync(), thread under API burn_drive_scan()
Called by API burn_finish
: Severe Application Error
=> rename and redefine burn_wait_all() : now burn_drives_are_clear()
=> change all use of burn_wait_all()
=> Move tests up to burn_drive_scan()
=> There: return -1; issue LIBDAX_MSGS_SEV_SORRY
ts A61007
------------------------------------------------------------------------------
++ 8) libburn/drive.c: assert(!d->released);
API burn_disc_get_status()
Attempt to read status of non-grabbed drive.
: Severe Application Error
=> extend enum burn_disc_status by BURN_DISC_UNGRABBED
=> return BURN_DISC_UNGRABBED, issue LIBDAX_MSGS_SEV_SORRY
ts A61007
------------------------------------------------------------------------------
++ 9) libburn/drive.c: assert( /* (write_type >= BURN_WRITE_PACKET) && */
burn_drive_get_block_types():
Will not work on BURN_WRITE below BURN_WRITE_RAW.
Called by -nobody- ?
: Severe Application Error
=> inactivate unused function
ts A61007
------------------------------------------------------------------------------
++ 10) libburn/drive.c: assert(d->idata);
libburn/drive.c: assert(d->mdata);
static drive_getcaps():
sg.c:enumerate_common() did not succeed in creating a proper struct burn_drive
Called by burn_drive_scan_sync()
: Severe System Error
=> This could possibly really stay an abort() because the reason is
a plain failure of the system's memory management.
=> Detect this failure already in enumerate_common(),
issue LIBDAX_MSGS_SEV_FATAL, return
ts A61007
------------------------------------------------------------------------------
++ 11) libburn/drive.c: assert(burn_running);
burn_drive_scan_sync():
The library was not initialized.
Called as thread by API burn_drive_scan()
: Severe Application Error
=> Move this test up to burn_drive_scan()
=> There: return -1; redefine @return in API , issue LIBDAX_MSGS_SEV_FATAL
ts A61007
------------------------------------------------------------------------------
++ 12) libburn/drive.c: assert(d->released == 1);
burn_drive_scan_sync():
Inactivated
: (Severe Application Error)
=> throw out inactivated code
ts A61007
------------------------------------------------------------------------------
++ 13) libburn/drive.c: assert(strlen(d->devname) < BURN_DRIVE_ADR_LEN);
burn_drive_raw_get_adr():
An enumerated device address is longer than the API's maximum length
Called by API burn_drive_get_adr()
Called by API burn_drive_obtain_scsi_adr()
: Severe Libburn Error
=> return -1; in all three functions, enhance burn_drive_get_adr @return docs
=> issue LIBDAX_MSGS_SEV_SORRY
ts A61007
------------------------------------------------------------------------------
++ 14) libburn/drive.c: assert(drive_info->drive!=NULL);
API burn_drive_get_adr():
Drive info has no drive attached.
: Severe Libburn Error (unlikely, will eventually SIGSEGV on NULL)
=> delete assert
ts A61007
------------------------------------------------------------------------------
++ 15) libburn/init.c: assert(burn_running);
API burn_finish():
The library is not initialized
: Severe Application Error
=> return (assume no msg system)
ts A61007
------------------------------------------------------------------------------
++ 16) libburn/init.c: assert(burn_running);
API burn_preset_device_open():
The library is not initialized
: Severe Application Error
=> return (assume no msg system)
ts A61007
------------------------------------------------------------------------------
++ 17) libburn/mmc.c: assert(o->drive == d);
mmc_close_disc():
alias: struct burn_drive.close_disc()
Parameters struct burn_drive and struct burn_write_opts do not match
Called by -nobody- ?
( => Disable unused function ? )
=> removed redundant parameter struct burn_drive
ts A61009
------------------------------------------------------------------------------
++ 18) libburn/mmc.c: assert(o->drive == d);
mmc_close_session():
Same as 17)
alias: struct burn_drive.close_session()
Called by -nobody- ?
( => Disable unused function ? )
=> removed redundant parameter struct burn_drive
ts A61009
------------------------------------------------------------------------------
++ 19) libburn/mmc.c: assert(buf->bytes >= buf->sectors); /* can be == at 0... */
mmc_write_12():
- Unclear what .bytes and .sectors mean in struct buffer -
Called by -nobody- ?
=> problems with filling the write buffer have to be handled by callers
=> delete assert
ts A61009
------------------------------------------------------------------------------
++ 20) libburn/mmc.c: assert(buf->bytes >= buf->sectors); /* can be == at 0... */
mmc_write():
- Unclear what .bytes and .sectors mean in struct buffer -
libburn/mmc.c: c.page->sectors = errorblock - start + 1;
mmc_read_sectors() by toc_find_modes() by mmc_read_toc() alias drive.read_toc()
by burn_drive_grab()
This seems to be unrelated to mmc_write().
libburn/sector.c: out->sectors++;
get_sector()
Seems to hand out sector start pointer in opts->drive->buffer
and to count reservation transactions as well as reserved bytes.
Ensures out->bytes >= out->sectors
libburn/mmc.c: c.page->bytes = s->count * 8;
mmc_send_cue_sheet()
Does not use mmc_write() but directly (sg_)issue_command()
libburn/sector.c: out->bytes += seclen;
get_sector()
See above
Ensures out->bytes >= out->sectors
libburn/spc.c: c.page->bytes = 8 + 2 + d->mdata->retry_page_length;
spc_select_error_params()
Does not use mmc_write() but directly (sg_)issue_command()
libburn/spc.c: c.page->bytes = 8 + 2 + d->mdata->write_page_length;
spc_select_error_params()
Does not use mmc_write() but directly (sg_)issue_command()
libburn/spc.c: c.page->bytes = 8 + 2 + 0x32;
spc_probe_write_modes()
Does not use mmc_write() but directly (sg_)issue_command()
alias struct burn_drive.write()
Called by static get_sector, by many
Called by burn_write_flush
Called by burn_write_track
=> problems with filling the write buffer have to be handled by callers
=> delete assert
ts A61009
------------------------------------------------------------------------------
++ 21) libburn/mmc.c: assert(((dlen - 2) % 11) == 0);
mmc_read_toc():
- Is defunct -
=> :)
ts A61009
------------------------------------------------------------------------------
++ 22) libburn/mmc.c: assert(len >= 0);
mmc_read_sectors():
Catches a bad parameter
alias: struct burn_drive.read_sectors()
Called by API burn_disc_read() , - is defunct -, one could catch the problem
Called by toc_find_modes(), problem cannot occur: mem.sectors = 1;
: Severe Libburn Error
(=> in burn_disc_read() check page.sectors before d->read_sectors() )
=> :)
ts A61009
------------------------------------------------------------------------------
++ 23) libburn/mmc.c: assert(d->busy);
mmc_read_sectors():
Catches use of a drive that is not marked as busy
alias: struct burn_drive.read_sectors()
Called by API burn_disc_read() , - is defunct -, busy = BURN_DRIVE_READING;
Called by toc_find_modes(), does the same assert. To be solved there.
: Severe Libburn Error
=> :)
ts A61009
------------------------------------------------------------------------------
++ 24) libburn/options.c: assert(0);
API burn_write_opts_set_write_type():
Detects unsuitable enum burn_write_types write_type and int block_type.
API promises return 0 on failure
: Severe Application Error
=> issue LIBDAX_MSGS_SEV_SORRY
=> should also detect problem of 26) : wrong write_type,block_type combination
by calling sector_get_outmode() and checking for -1
=> should also detect problem of 41) : unknown block_type
by spc_block_type() and checking for -1
=> delete assert(0)
ts A61007
------------------------------------------------------------------------------
++ 25) libburn/read.c: assert((o->version & 0xfffff000) == (OPTIONS_VERSION & 0xfffff000));
libburn/read.c: assert(!d->busy);
libburn/read.c: assert(d->toc->valid);
libburn/read.c: assert(o->datafd != -1);
API burn_disc_read():
- ? -
burn_disc_read() is defunct
OPTIONS_VERSION does not occur outside this line
( => one would return )
( 22) => catch page.sectors<0 before d->read_sectors() )
( 37) => catch ! d->mdata->valid )
=> :)
ts A61007
------------------------------------------------------------------------------
++ 26) libburn/sector.c: assert(0); /* return BURN_MODE_UNIMPLEMENTED :) */
static get_outmode():
burn_write_opts is wrongly programmed with .write_type and .block_type
: Severe Application Error
=> This gets handled by burn_write_opts_set_write_type()
ts A61007 by new semi-public sector_get_outmode()
=> delete assert()
ts A61007
------------------------------------------------------------------------------
++ 27) libburn/sector.c: assert(outlen >= inlen);
libburn/sector.c: assert(outmode & BURN_MODE_RAW);
libburn/sector.c: assert(offset != -1);
static convert_data():
Several unacceptable settings within struct burn_write_opts
Called by sector_toc() sector_pregap() sector_postgap() sector_lout()
sector_data()
: Severe Application Error
=> change return type of convert_data()
=> all callers interpret return value and eventually return failure
ts A61007
------------------------------------------------------------------------------
++ 28) libburn/sector.c: assert(0);
static char_to_isrc():
Called by subcode_user() with data set by API burn_track_set_isrc()
Some character conversion fails on wrong input
: Severe Application Error
=> burn_track_set_isrc() has to make sure that only good data are set
=> char_to_isrc() returns 0 as default
=> delete assert()
ts A61008
------------------------------------------------------------------------------
++ 29) libburn/sector.c: assert(qmode == 1 || qmode == 2 || qmode == 3);
subcode_user():
- can not happen -
: Unknown reason of assert()
=> remove assert()
ts A61010
------------------------------------------------------------------------------
++ 30) libburn/sector.c: assert(modebyte == 1);
sector_headers():
Does only accept modes BURN_AUDIO, BURN_MODE1 or write_type BURN_WRITE_SAO
Called by sector_toc() sector_pregap() sector_postgap() sector_lout()
sector_data()
: Severe Libburn Error
=> new functions sector_headers_is_ok(), burn_disc_write_is_ok()
help to catch problem in API burn_disc_write()
=> issue LIBDAX_MSGS_SEV_FATAL
ts A61009
------------------------------------------------------------------------------
++ 31) libburn/sector.c: assert(0);
process_q()
- defunct -
=> :)
ts A61009
------------------------------------------------------------------------------
++ 32) libburn/sg.c: assert("drive busy" == "non fatal");
sg_handle_busy_device():
Intentional abort preset by the app
=> change to abort()
ts A61007
------------------------------------------------------------------------------
++ 33) libburn/sg.c: assert(fd != -1337);
sg_grab():
The drive device file could not be opened
:Severe External Problem
=> obsolete by normal drive open failure handling
ts A61007
------------------------------------------------------------------------------
++ 34) libburn/sg.c: assert(!c->page);
sg_issue_command():
An SCSI command of direction NO_TRANSFER may not have a .page != NULL.
Since it is about exposing a libburn detail towards the sg driver, i believe
it is sufficient to just not use it.
: Libburn Error
=> enhance internal logics of sg_issue_command()
ts A61007
------------------------------------------------------------------------------
++ 35) libburn/sg.c: assert(c->page->bytes > 0);
sg_issue_command():
An SCSI command of direction TO_DRIVE wants to transfer 0 bytes.
: Severe Libburn Error
=> set command.error = 1 and return 0
ts A61010
------------------------------------------------------------------------------
++ 36) libburn/sg.c: assert(err != -1);
sg_issue_command():
The transfer of the command via ioctl() failed
: Severe Transport Level Problem
=> close drive fd, set idle and released
=> set command.error = 1 and return -1
ts A61010
------------------------------------------------------------------------------
++ 37) libburn/spc.c: assert(d->mdata->valid);
spc_select_error_params():
Drive was not properly programmed
alias struct burn_drive.send_parameters()
Called by burn_disc_read, - defunct -
: Severe Application Error
=> moved up as mangled assert to burn_disc_read()
ts A61007
------------------------------------------------------------------------------
++ 38) libburn/spc.c: assert(d->mdata->cdr_write || d->mdata->cdrw_write ||
spc_sense_write_params():
Drive does not offer write of any known media type
alias struct burn_drive.read_disc_info()
Called by API burn_drive_grab (assert test made there in soft)
: Severe Command Level Problem
=> remove assert()
ts A61007
------------------------------------------------------------------------------
++ 39) libburn/spc.c: assert(o->drive == d);
spc_select_write_params():
Drive does not match struct burn_write_opts
alias struct burn_drive.send_write_parameters()
Called by mmc_close_disc() (-defunct- ?), mmc_close_session() (-defunct- ?),
burn_write_track() (d = o->drive;),
burn_disc_write_sync() d = (o->drive;)
: Severe Libburn Error
=> remove assert()
ts A61007
------------------------------------------------------------------------------
++ 40) libburn/spc.c: assert(d->mdata->valid);
spc_select_write_params():
Drive was not properly programmed
Called by (see 39)
burn_write_track() by burn_write_session() by burn_disc_write_sync()
burn_disc_write_sync() indirectly by API burn_disc_write()
: Severe Libburn Error
=> caught in burn_disc_write() now
ts A61007
------------------------------------------------------------------------------
++ 41) libburn/spc.c: assert(0);
spc_block_type():
Unknown value with enum burn_block_types
Called by spc_select_write_params, uses burn_write_opts.block_type,
set by API burn_write_opts_set_write_type()
: Severe Application Error
=> catch in API burn_write_opts_set_write_type
by calling spc_block_type()
=> delete assert
ts A61007
------------------------------------------------------------------------------
++ 42) libburn/structure.c: assert(!(pos > BURN_POS_END));\
macro RESIZE
An illegal list index is given by the app.
( TO->NEW##s obviusly means to append "s" to cpp result of TO->NEW )
Used by API burn_session_add_track() and API burn_disc_add_session()
: Severe Application Error
=> replace assert by if-and-return-0
ts A61008
------------------------------------------------------------------------------
++ 43) libburn/structure.c: assert(s->track != NULL);
API burn_session_remove_track()
An application supplied pointer is NULL
: Severe Application Error
=> replace by if-and-return-0
ts A61008
------------------------------------------------------------------------------
++ 44) libburn/structure.c: assert((country[i] >= '0' || country[i] < '9') &&
libburn/structure.c: assert((owner[i] >= '0' || owner[i] < '9') &&
libburn/structure.c: assert(year <= 99);
libburn/structure.c: assert(serial <= 99999);
API burn_track_set_isrc():
Illegal texts supplied by application.
The logical expression is always true !
: Severe Application Error
=> issue LIBDAX_MSGS_SEV_SORRY and return
=> delete assert
=> delete assert 28) in char_to_isrc()
ts A61008
------------------------------------------------------------------------------
++ 45) libburn/toc.c: assert(0); /* unhandled! find out ccd's
static write_clonecd2():
- defunct -, - unused -
=> mangle assert
ts A61008
------------------------------------------------------------------------------
++ 46) libburn/toc.c: assert(d->busy);
toc_find_modes():
The drive to work on is not marked busy
Called by mmc_read_toc() alias read_toc() by ... burn_drive_grab()
: Severe Libburn Error
=> to be prevented on the higher levels
=> delete assert
ts A61008
------------------------------------------------------------------------------
++ 47) libburn/util.c: assert(s);
burn_strdup()
Abort on NULL string which would elsewise cause a SIGSEGV
Used once in enumerate_common() with a string that worked with open(2) before
: Severe Libburn Error
=> delete assert
ts A61008
------------------------------------------------------------------------------
++ 48) libburn/util.c: assert(s);
burn_strndup(): - unused -
Same as 47
: Severe Libburn Error
=> return NULL
=> delete assert
ts A61008
------------------------------------------------------------------------------
++ 49) libburn/util.c: assert(n > 0);
burn_strndup(): - unused -
Prevent problems by negative copy length
: Severe Libburn Error
=> return NULL
=> delete assert
ts A61008
------------------------------------------------------------------------------
++ 50) libburn/write.c: assert(0);
static type_to_ctrl():
Unsuitable mode to be converted into "ctrl"
Called by static type_to_form() finally burn_create_toc_entries()
: Severe Application Error
=> to be caught in burn_track_define_data by calling for test type_to_form()
=> return -1;
ts A61008
------------------------------------------------------------------------------
++ 51) libburn/write.c: assert(0);
libburn/write.c: assert(0); /* XXX someone's gonna want this sometime */
static type_to_form():
Does not like BURN_MODE0 or BURN_MODE2 but tolerates unknown modes
Called by static burn_create_toc_entries() by burn_disc_write_sync()
: Undocumented Libburn Restriction
=> set *form = -1 , *ctladr = 0xff , return
=> make function non-static
=> call for test in API burn_track_define_data()
ts A61009
------------------------------------------------------------------------------
++ 52) libburn/write.c: assert(ptr);
static add_cue():
realloc() failed
Called by burn_create_toc_entries() by burn_disc_write_sync()
(burn_create_toc_entries is ignorant towards own potential memory problems)
(This could possibly really stay an abort() because the reason is
a plain failure of the system's memory management.)
: Severe System Error
=> change return type of add_cue to int
=> react on return -1 in burn_create_toc_entries, return NULL on failure
=> abort burn_disc_write_sync() on NULL return
ts A61009
------------------------------------------------------------------------------
++ 53) libburn/write.c: assert(d->toc_entry == NULL);
burn_create_toc_entries():
Multiple usage of struct burn_drive.toc_entry
Called by burn_disc_write_sync()
This will probably trigger an abort with disc->sessions > 1
(disc->sessions is incremented in macro RESIZE() as "NEW##s")
: Design Problem
( => ? disallow multiple sessions ? )
=> replace assert by soft means and wait what happens
ts A61009
------------------------------------------------------------------------------
++ 54) libburn/write.c: assert(0);
burn_sector_length():
Only BURN_AUDIO, BURN_MODE_RAW, BURN_MODE1 are allowed
Called by get_sector(), convert_data(), ...
=> call burn_sector_length() for test in API burn_track_define_data()
=> replace assert by -1
ts A61009
------------------------------------------------------------------------------

View File

@ -6,17 +6,11 @@
#include "write.h"
#include "options.h"
#include "async.h"
#include "init.h"
#include <pthread.h>
#include <assert.h>
#include <stdlib.h>
/*
#include <a ssert.h>
*/
#include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger;
#define SCAN_GOING() (workers && !workers->drive)
typedef void *(*WorkerFunc) (void *);
@ -106,13 +100,7 @@ static void remove_worker(pthread_t th)
free(a);
break;
}
/* ts A61006 */
/* a ssert(a != NULL);/ * wasn't found.. this should not be possible */
if (a == NULL)
libdax_msgs_submit(libdax_messenger, -1, 0x00020101,
LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
"remove_worker() cannot find given worker item", 0, 0);
assert(a != NULL); /* wasn't found.. this should not be possible */
}
static void *scan_worker_func(struct w_list *w)
@ -127,41 +115,11 @@ int burn_drive_scan(struct burn_drive_info *drives[], unsigned int *n_drives)
struct scan_opts o;
int ret = 0;
/* ts A61006 : moved up from burn_drive_scan_sync , former Assert */
if (!burn_running) {
libdax_msgs_submit(libdax_messenger, -1, 0x00020109,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Library not running (on attempt to scan)", 0, 0);
*drives = NULL;
*n_drives = 0;
return -1;
}
/* cant be anything working! */
/* ts A61006 */
/* a ssert(!(workers && workers->drive)); */
if (workers != NULL && workers->drive != NULL) {
drive_is_active:;
libdax_msgs_submit(libdax_messenger, -1, 0x00020102,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"A drive operation is still going on (want to scan)",
0, 0);
*drives = NULL;
*n_drives = 0;
return -1;
}
assert(!(workers && workers->drive));
if (!workers) {
/* start it */
/* ts A61007 : test moved up from burn_drive_scan_sync()
was burn_wait_all() */
if (!burn_drives_are_clear())
goto drive_is_active;
*drives = NULL;
*n_drives = 0;
o.drives = drives;
o.n_drives = n_drives;
o.done = 0;
@ -170,17 +128,7 @@ drive_is_active:;
/* its done */
ret = workers->u.scan.done;
remove_worker(workers->thread);
/* ts A61006 */
/* a ssert(workers == NULL); */
if (workers != NULL) {
libdax_msgs_submit(libdax_messenger, -1, 0x00020101,
LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
"After scan a drive operation is still going on",
0, 0);
return -1;
}
assert(workers == NULL);
} else {
/* still going */
}
@ -198,25 +146,9 @@ void burn_disc_erase(struct burn_drive *drive, int fast)
{
struct erase_opts o;
/* ts A61006 */
/* a ssert(drive); */
/* a ssert(!SCAN_GOING()); */
/* a ssert(!find_worker(drive)); */
if((drive == NULL)) {
libdax_msgs_submit(libdax_messenger, drive->global_index,
0x00020104,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"NULL pointer caught in burn_disc_erase", 0, 0);
return;
}
if ((SCAN_GOING()) || find_worker(drive)) {
libdax_msgs_submit(libdax_messenger, drive->global_index,
0x00020102,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"A drive operation is still going on (want to erase)",
0, 0);
return;
}
assert(drive);
assert(!SCAN_GOING());
assert(!find_worker(drive));
o.drive = drive;
o.fast = fast;
@ -239,29 +171,8 @@ void burn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
{
struct write_opts o;
/* ts A61006 */
/* a ssert(!SCAN_GOING()); */
/* a ssert(!find_worker(opts->drive)); */
if ((SCAN_GOING()) || find_worker(opts->drive)) {
libdax_msgs_submit(libdax_messenger, opts->drive->global_index,
0x00020102,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"A drive operation is still going on (want to write)",
0, 0);
return;
}
/* ts A61007 : obsolete Assert in spc_select_write_params() */
if (!opts->drive->mdata->valid) {
libdax_msgs_submit(libdax_messenger,
opts->drive->global_index, 0x00020113,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Drive capabilities not inquired yet", 0, 0);
return;
}
/* ts A61009 : obsolete Assert in sector_headers() */
if (! burn_disc_write_is_ok(opts, disc)) /* issues own msgs */
return;
assert(!SCAN_GOING());
assert(!find_worker(opts->drive));
o.drive = opts->drive;
o.opts = opts;
o.disc = disc;

View File

@ -1,214 +0,0 @@
/*
cleanup.c , Copyright 2006 Thomas Schmitt <scdbackup@gmx.net>
A signal handler which cleans up an application and exits.
Provided under GPL license within GPL projects, BSD license elsewise.
*/
/*
cc -g -o cleanup -DCleanup_standalonE cleanup.c
*/
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
typedef void (*sighandler_t)(int);
#include "cleanup.h"
#ifdef __FreeBSD__
/* Signals to be caught */
static int signal_list[]= {
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT,
SIGFPE, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM,
SIGUSR1, SIGUSR2, SIGXCPU, SIGTSTP, SIGTTIN,
SIGTTOU,
SIGBUS, SIGPROF, SIGSYS, SIGTRAP,
SIGVTALRM, SIGXCPU, SIGXFSZ, -1
};
static char *signal_name_list[]= {
"SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGABRT",
"SIGFPE", "SIGSEGV", "SIGPIPE", "SIGALRM", "SIGTERM",
"SIGUSR1", "SIGUSR2", "SIGXCPU", "SIGTSTP", "SIGTTIN",
"SIGTTOU",
"SIGBUS", "SIGPROF", "SIGSYS", "SIGTRAP",
"SIGVTALRM", "SIGXCPU", "SIGXFSZ", "@"
};
static int signal_list_count= 23;
#else /* __FreeBSD__ */
/* Signals to be caught */
static int signal_list[]= {
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT,
SIGFPE, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM,
SIGUSR1, SIGUSR2, SIGXCPU, SIGTSTP, SIGTTIN,
SIGTTOU,
SIGBUS, SIGPOLL, SIGPROF, SIGSYS, SIGTRAP,
SIGVTALRM, SIGXCPU, SIGXFSZ, -1
};
static char *signal_name_list[]= {
"SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGABRT",
"SIGFPE", "SIGSEGV", "SIGPIPE", "SIGALRM", "SIGTERM",
"SIGUSR1", "SIGUSR2", "SIGXCPU", "SIGTSTP", "SIGTTIN",
"SIGTTOU",
"SIGBUS", "SIGPOLL", "SIGPROF", "SIGSYS", "SIGTRAP",
"SIGVTALRM", "SIGXCPU", "SIGXFSZ", "@"
};
static int signal_list_count= 24;
#endif /* ! __FreeBSD__ */
/* Signals not to be caught */
static int non_signal_list[]= {
SIGKILL, SIGCHLD, SIGSTOP, SIGURG, -1
};
static int non_signal_list_count= 4;
/* run time dynamic part */
static char cleanup_msg[4096]= {""};
static int cleanup_exiting= 0;
static void *cleanup_app_handle= NULL;
static Cleanup_app_handler_T cleanup_app_handler= NULL;
static int cleanup_perform_app_handler_first= 0;
static int Cleanup_handler_exit(int exit_value, int signum, int flag)
{
int ret;
if(cleanup_msg[0]!=0)
fprintf(stderr,"\n%s\n",cleanup_msg);
if(cleanup_perform_app_handler_first)
if(cleanup_app_handler!=NULL) {
ret= (*cleanup_app_handler)(cleanup_app_handle,signum,0);
if(ret==2 || ret==-2)
return(2);
}
if(cleanup_exiting) {
fprintf(stderr,"cleanup: ABORT : repeat by pid=%d, signum=%d\n",
getpid(),signum);
return(0);
}
cleanup_exiting= 1;
alarm(0);
if(!cleanup_perform_app_handler_first)
if(cleanup_app_handler!=NULL) {
ret= (*cleanup_app_handler)(cleanup_app_handle,signum,0);
if(ret==2 || ret==-2)
return(2);
}
exit(exit_value);
}
static void Cleanup_handler_generic(int signum)
{
int i;
sprintf(cleanup_msg,"UNIX-SIGNAL caught: %d errno= %d",signum,errno);
for(i= 0; i<signal_list_count; i++)
if(signum==signal_list[i]) {
sprintf(cleanup_msg,"UNIX-SIGNAL: %s errno= %d",
signal_name_list[i],errno);
break;
}
Cleanup_handler_exit(1,signum,0);
}
int Cleanup_set_handlers(void *handle, Cleanup_app_handler_T handler, int flag)
/*
bit0= set to default handlers
bit1= set to ignore
bit2= set cleanup_perform_app_handler_first
bit3= set SIGABRT to handler (makes sense with bits 0 or 1)
*/
{
int i,j,max_sig= -1,min_sig= 0x7fffffff;
sighandler_t sig_handler;
cleanup_msg[0]= 0;
cleanup_app_handle= handle;
cleanup_app_handler= handler;
/* <<< make cleanup_exiting thread safe to get rid of this */
if(flag&4)
cleanup_perform_app_handler_first= 1;
if(flag&1)
sig_handler= SIG_DFL;
else if(flag&2)
sig_handler= SIG_IGN;
else
sig_handler= Cleanup_handler_generic;
/* set all signal numbers between the lowest and highest in the list
except those in the non-signal list */
for(i= 0; i<signal_list_count; i++) {
if(signal_list[i]>max_sig)
max_sig= signal_list[i];
if(signal_list[i]<min_sig)
min_sig= signal_list[i];
}
for(i= min_sig; i<=max_sig; i++) {
for(j= 0; j<non_signal_list_count; j++)
if(i==non_signal_list[j])
break;
if(j>=non_signal_list_count) {
if(i==SIGABRT && (flag&8))
signal(i,Cleanup_handler_generic);
else
signal(i,sig_handler);
}
}
return(1);
}
#ifdef Cleanup_standalonE
struct Demo_apP {
char *msg;
};
int Demo_app_handler(struct Demo_apP *demoapp, int signum, int flag)
{
printf("Handling exit of demo application on signal %d. msg=\"%s\"\n",
signum,demoapp->msg);
return(1);
}
main()
{
struct Demo_apP demoapp;
demoapp.msg= "Good Bye";
Cleanup_set_handlers(&demoapp,(Cleanup_app_handler_T) Demo_app_handler,0);
if(1) { /* change to 0 in order to wait for external signals */
char *cpt= NULL,c;
printf("Intentionally provoking SIGSEGV ...\n");
c= *cpt;
} else {
printf("killme: %d\n",getpid());
sleep(3600);
}
Cleanup_set_handlers(NULL,NULL,1);
exit(0);
}
#endif /* Cleanup_standalonE */

View File

@ -1,34 +0,0 @@
/*
cleanup.c , Copyright 2006 Thomas Schmitt <scdbackup@gmx.net>
A signal handler which cleans up an application and exits.
Provided under GPL license within GPL projects, BSD license elsewise.
*/
#ifndef Cleanup_includeD
#define Cleanup_includeD 1
/** Layout of an application provided cleanup function using an application
provided handle as first argument and the signal number as second
argument. The third argument is a flag bit field with no defined bits yet.
If the handler returns 2 or -2 then it has delegated exit() to some other
instance and the Cleanup handler shall return rather than exit.
*/
typedef int (*Cleanup_app_handler_T)(void *, int, int);
/** Establish exiting signal handlers on (hopefully) all signals that are
not ignored by default or non-catchable.
@param handle Opaque object which knows how to cleanup application
@param handler Function which uses handle to perform application cleanup
@param flag Control Bitfield
bit0= reset to default signal handling
*/
int Cleanup_set_handlers(void *handle, Cleanup_app_handler_T handler,
int flag);
#endif /* ! Cleanup_includeD */

View File

@ -1,17 +1,9 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
#include <sys/types.h>
#include <sys/stat.h>
/* #include <m alloc.h> ts A61013 : not in Linux man 3 malloc */
#include <stdlib.h>
#include <malloc.h>
#include <unistd.h>
#include <signal.h>
/* ts A61007 */
/* #include <a ssert.h> */
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
@ -19,6 +11,7 @@
#include "libburn.h"
#include "drive.h"
#include "transport.h"
#include "message.h"
#include "debug.h"
#include "init.h"
#include "toc.h"
@ -27,22 +20,10 @@
#include "structure.h"
#include "back_hacks.h"
#include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger;
static struct burn_drive drive_array[255];
static int drivetop = -1;
/* ts A61021 : the unspecific part of sg.c:enumerate_common()
*/
int burn_setup_drive(struct burn_drive *d, char *fname)
{
d->devname = burn_strdup(fname);
memset(&d->params, 0, sizeof(struct params));
d->released = 1;
d->status = BURN_DISC_UNREADY;
return 1;
}
int burn_drive_is_open(struct burn_drive *d);
/* ts A60904 : ticket 62, contribution by elmom */
/* splitting former burn_drive_free() (which freed all, into two calls) */
@ -52,11 +33,10 @@ void burn_drive_free(struct burn_drive *d)
return;
/* ts A60822 : close open fds before forgetting them */
if (burn_drive_is_open(d))
sg_close_drive(d);
close(d->fd);
free((void *) d->idata);
free((void *) d->mdata);
if(d->toc_entry != NULL)
free((void *) d->toc_entry);
free((void *) d->toc_entry);
free(d->devname);
d->global_index = -1;
}
@ -75,8 +55,12 @@ void burn_drive_free_all(void)
/* ts A60822 */
int burn_drive_is_open(struct burn_drive *d)
{
/* ts A61021 : moved decision to sg.c */
return d->drive_is_open(d);
/* a bit more detailed case distinction than needed */
if (d->fd == -1337)
return 0;
if (d->fd < 0)
return 0;
return 1;
}
@ -160,10 +144,7 @@ int burn_drive_grab(struct burn_drive *d, int le)
d->load(d);
d->lock(d);
/* ts A61020 : this was BURN_DISC_BLANK as pure guess */
d->status = BURN_DISC_UNREADY;
d->status = BURN_DISC_BLANK;
if (d->mdata->cdr_write || d->mdata->cdrw_write ||
d->mdata->dvdr_write || d->mdata->dvdram_write) {
@ -187,8 +168,6 @@ int burn_drive_grab(struct burn_drive *d, int le)
old_erasable = new_erasable;
d->read_disc_info(d);
if(d->status == BURN_DISC_UNSUITABLE)
break;
new_speed = burn_drive_get_write_speed(d);
new_erasable = burn_disc_erasable(d);
@ -265,77 +244,13 @@ struct burn_drive *burn_drive_register(struct burn_drive *d)
}
/* unregister most recently registered drive */
int burn_drive_unregister(struct burn_drive *d)
{
if(d->global_index != drivetop)
return 0;
burn_drive_free(d);
drivetop--;
return 1;
}
/* ts A61021 : after-setup activities from sg.c:enumerate_common()
*/
struct burn_drive *burn_drive_finish_enum(struct burn_drive *d)
{
struct burn_drive *t;
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
int mmc_function_spy(char * text);
t = burn_drive_register(d);
/* ts A60821 */
mmc_function_spy("enumerate_common : -------- doing grab");
/* try to get the drive info */
if (t->grab(t)) {
burn_print(2, "getting drive info\n");
t->getcaps(t);
t->unlock(t);
t->released = 1;
} else {
burn_print(2, "unable to grab new located drive\n");
burn_drive_unregister(t);
t = NULL;
}
/* ts A60821 */
mmc_function_spy("enumerate_common : ----- would release ");
return t;
}
void burn_drive_release(struct burn_drive *d, int le)
{
if (d->released) {
/* ts A61007 */
/* burn_print(1, "second release on drive!\n"); */
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x00020105,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Drive is already released", 0, 0);
return;
}
if (d->released)
burn_print(1, "second release on drive!\n");
/* ts A61007 */
/* ts A60906: one should not assume BURN_DRIVE_IDLE == 0 */
/* a ssert(d->busy == BURN_DRIVE_IDLE); */
if (d->busy != BURN_DRIVE_IDLE) {
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x00020106,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Drive is busy on attempt to close", 0, 0);
return;
}
/* ts A61020 : mark media info as invalid */
d->start_lba= -2000000000;
d->end_lba= -2000000000;
assert(d->busy == BURN_DRIVE_IDLE);
d->unlock(d);
if (le)
@ -345,7 +260,7 @@ void burn_drive_release(struct burn_drive *d, int le)
d->status = BURN_DISC_UNREADY;
d->released = 1;
if (d->toc_entry != NULL)
if (d->toc_entry)
free(d->toc_entry);
d->toc_entry = NULL;
d->toc_entries = 0;
@ -355,26 +270,6 @@ void burn_drive_release(struct burn_drive *d, int le)
}
}
/* ts A61007 : former void burn_wait_all() */
int burn_drives_are_clear(void)
{
int i;
for (i = burn_drive_count() - 1; i >= 0; --i) {
/* ts A60904 : ticket 62, contribution by elmom */
if (drive_array[i].global_index == -1)
continue;
if (drive_array[i].released)
continue;
return 0;
}
return 1;
}
#if 0
void burn_wait_all(void)
{
unsigned int i;
@ -390,20 +285,16 @@ void burn_wait_all(void)
if (d->global_index==-1)
continue;
a ssert(d->released);
assert(d->released);
}
if (!finished)
sleep(1);
}
}
#endif
void burn_disc_erase_sync(struct burn_drive *d, int fast)
{
/* ts A60924 : libburn/message.c gets obsoleted
burn_message_clear_queue();
*/
burn_print(1, "erasing drive %s %s\n", d->idata->vendor,
d->idata->product);
@ -438,17 +329,7 @@ void burn_disc_erase_sync(struct burn_drive *d, int fast)
enum burn_disc_status burn_disc_get_status(struct burn_drive *d)
{
/* ts A61007 */
/* a ssert(!d->released); */
if (d->released) {
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x00020108,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Drive is not grabbed on disc status inquiry",
0, 0);
return BURN_DISC_UNGRABBED;
}
assert(!d->released);
return d->status;
}
@ -473,17 +354,14 @@ void burn_drive_cancel(struct burn_drive *d)
pthread_mutex_unlock(&d->access_lock);
}
/* ts A61007 : defunct because unused */
#if 0
int burn_drive_get_block_types(struct burn_drive *d,
enum burn_write_types write_type)
{
burn_print(12, "write type: %d\n", write_type);
a ssert( /* (write_type >= BURN_WRITE_PACKET) && */
assert( /* (write_type >= BURN_WRITE_PACKET) && */
(write_type <= BURN_WRITE_RAW));
return d->block_types[write_type];
}
#endif
static void strip_spaces(char *str)
{
@ -508,18 +386,14 @@ static void strip_spaces(char *str)
static int drive_getcaps(struct burn_drive *d, struct burn_drive_info *out)
{
struct burn_scsi_inquiry_data *id;
/* ts A61007 : now prevented in enumerate_common() */
#if 0
a ssert(d->idata);
a ssert(d->mdata);
#endif
struct scsi_inquiry_data *id;
assert(d->idata);
assert(d->mdata);
if (!d->idata->valid || !d->mdata->valid)
return 0;
id = (struct burn_scsi_inquiry_data *)d->idata;
id = (struct scsi_inquiry_data *)d->idata;
memcpy(out->vendor, id->vendor, sizeof(id->vendor));
strip_spaces(out->vendor);
@ -561,21 +435,27 @@ int burn_drive_scan_sync(struct burn_drive_info *drives[],
static int scanning = 0, scanned = 0, found = 0;
static unsigned num_scanned = 0, count = 0;
unsigned int i;
#ifdef Libburn_ticket_62_enable_redundant_asserT
struct burn_drive *d;
#endif
/* ts A61007 : moved up to burn_drive_scan() */
/* a ssert(burn_running); */
assert(burn_running);
if (!scanning) {
scanning = 1;
/* ts A61007 : test moved up to burn_drive_scan()
burn_wait_all() is obsoleted */
#if 0
/* make sure the drives aren't in use */
burn_wait_all(); /* make sure the queue cleans up
before checking for the released
state */
#endif /* 0 */
/* ts A60904 : ticket 62, contribution by elmom */
/* this is redundant with what is done in burn_wait_all() */
#ifdef Libburn_ticket_62_enable_redundant_asserT
d = drive_array;
count = burn_drive_count();
for (i = 0; i < count; ++i, ++d)
assert(d->released == 1);
#endif /* Libburn_ticket_62_enable_redundant_asserT */
/* refresh the lib's drives */
sg_enumerate();
@ -621,17 +501,19 @@ void burn_drive_info_free(struct burn_drive_info drive_infos[])
burn_drive_info is not the manager of burn_drive but only its
spokesperson. To my knowlege drive_infos from burn_drive_scan()
are not memorized globally. */
if(drive_infos != NULL)
if(drive_infos != NULL) /* and this NULL test is deadly necessary */
free((void *) drive_infos);
burn_drive_free_all();
}
/* ts A61001 : internal call */
int burn_drive_forget(struct burn_drive *d, int force)
/* Experimental API call */
int burn_drive_info_forget(struct burn_drive_info *info, int force)
{
int occup;
struct burn_drive *d;
d = info->drive;
occup = burn_drive_is_occupied(d);
/*
fprintf(stderr, "libburn: experimental: occup == %d\n",occup);
@ -654,18 +536,8 @@ int burn_drive_forget(struct burn_drive *d, int force)
return 1;
}
/* API call */
int burn_drive_info_forget(struct burn_drive_info *info, int force)
{
return burn_drive_forget(info->drive, force);
}
struct burn_disc *burn_drive_get_disc(struct burn_drive *d)
{
/* ts A61022: SIGSEGV on calling this function with blank media */
if(d->disc == NULL)
return NULL;
d->disc->refcnt++;
return d->disc;
}
@ -697,12 +569,6 @@ int burn_drive_get_write_speed(struct burn_drive *d)
return d->mdata->max_write_speed;
}
/* ts A61021 : New API function */
int burn_drive_get_min_write_speed(struct burn_drive *d)
{
return d->mdata->min_write_speed;
}
/* ts A51221 */
static char *enumeration_whitelist[BURN_DRIVE_WHITELIST_LEN];
@ -761,434 +627,39 @@ int burn_drive_scan_and_grab(struct burn_drive_info *drive_infos[], char* adr,
fprintf(stderr,"libburn: experimental: burn_drive_scan_and_grab(%s)\n",
adr);
*/
while (1) {
ret = burn_drive_scan(drive_infos, &n_drives);
if (ret < 0)
return -1;
if (ret > 0)
break;
while (!burn_drive_scan(drive_infos, &n_drives))
usleep(1002);
}
if (n_drives <= 0)
return 0;
/*
fprintf(stderr, "libburn: experimental: n_drives == %d\n",n_drives);
*/
/* ts A60908 : seems we get rid of this :) */
#ifdef Libburn_grab_release_and_grab_agaiN
if (load) {
/* RIP-14.5 + LITE-ON 48125S produce a false status
if tray was unloaded */
/* Therefore the first grab is just for loading */
ret= burn_drive_grab(drive_infos[0]->drive, 1);
if (ret != 1)
return -1;
burn_drive_release(drive_infos[0]->drive,0);
}
#endif /* Libburn_grab_release_and_grab_agaiN */
ret = burn_drive_grab(drive_infos[0]->drive, load);
if (ret != 1)
return -1;
return 1;
}
/* ts A60925 */
/** Simple debug message frontend to libdax_msgs_submit().
If arg is not NULL, then fmt MUST contain exactly one %s and no
other sprintf() %-formatters.
*/
int burn_drive_adr_debug_msg(char *fmt, char *arg)
{
int ret;
char msg[4096], *msgpt;
msgpt= msg;
if(arg != NULL)
sprintf(msg, fmt, arg);
else
msgpt= fmt;
if(libdax_messenger == NULL)
return 0;
ret = libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
msgpt, 0, 0);
return ret;
}
/* ts A60923 */
/** Inquire the persistent address of the given drive. */
int burn_drive_raw_get_adr(struct burn_drive *d, char adr[])
{
if (strlen(d->devname) >= BURN_DRIVE_ADR_LEN) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020110,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Persistent drive address too long", 0, 0);
return -1;
}
strcpy(adr,d->devname);
return 1;
}
/* ts A60823 - A60923 */
/* ts A60823 */
/** Inquire the persistent address of the given drive. */
int burn_drive_get_adr(struct burn_drive_info *drive_info, char adr[])
{
int ret;
ret = burn_drive_raw_get_adr(drive_info->drive, adr);
return ret;
}
/* ts A60922 ticket 33 */
/** Evaluate wether the given address would be enumerated by libburn */
int burn_drive_is_enumerable_adr(char *adr)
{
return sg_is_enumerable_adr(adr);
}
#define BURN_DRIVE_MAX_LINK_DEPTH 20
/* ts A60922 ticket 33 */
/* Try to find an enumerated address with the given stat.st_rdev number */
int burn_drive_resolve_link(char *path, char adr[], int *recursion_count)
{
int ret;
char link_target[4096], msg[4096+100], link_adr[4096], *adrpt;
burn_drive_adr_debug_msg("burn_drive_resolve_link( %s )", path);
if (*recursion_count >= BURN_DRIVE_MAX_LINK_DEPTH) {
burn_drive_adr_debug_msg(
"burn_drive_resolve_link aborts because link too deep",
NULL);
return 0;
}
(*recursion_count)++;
ret = readlink(path, link_target, sizeof(link_target));
if (ret == -1) {
burn_drive_adr_debug_msg("readlink( %s ) returns -1", path);
return 0;
}
if (ret >= sizeof(link_target) - 1) {
sprintf(msg,"readlink( %s ) returns %d (too much)", path, ret);
burn_drive_adr_debug_msg(msg, NULL);
return -1;
}
link_target[ret] = 0;
adrpt= link_target;
if (link_target[0] != '/') {
strcpy(link_adr, path);
if ((adrpt = strrchr(link_adr, '/')) != NULL) {
strcpy(adrpt + 1, link_target);
adrpt = link_adr;
} else
adrpt = link_target;
}
ret = burn_drive_convert_fs_adr_sub(adrpt, adr, recursion_count);
sprintf(msg,"burn_drive_convert_fs_adr( %s ) returns %d",
link_target, ret);
burn_drive_adr_debug_msg(msg, NULL);
return ret;
}
/* ts A60922 - A61014 ticket 33 */
/* Try to find an enumerated address with the given stat.st_rdev number */
int burn_drive_find_devno(dev_t devno, char adr[])
{
char fname[4096], msg[4096+100];
int ret = 0, first = 1;
struct stat stbuf;
burn_drive_enumerator_t enm;
while (1) {
ret = sg_give_next_adr(&enm, fname, sizeof(fname), first);
if(ret <= 0)
break;
first = 0;
ret = stat(fname, &stbuf);
if(ret == -1)
continue;
if(devno != stbuf.st_rdev)
continue;
if(strlen(fname) >= BURN_DRIVE_ADR_LEN)
return -1;
sprintf(msg, "burn_drive_find_devno( 0x%lX ) found %s",
(long) devno, fname);
burn_drive_adr_debug_msg(msg, NULL);
strcpy(adr, fname);
{ ret = 1; goto ex;}
}
ret = 0;
ex:;
if (first == 0)
sg_give_next_adr(&enm, fname, sizeof(fname), -1);
return ret;
}
/* ts A60923 */
/** Try to obtain host,channel,target,lun from path.
@return 1 = success , 0 = failure , -1 = severe error
*/
int burn_drive_obtain_scsi_adr(char *path,
int *bus_no, int *host_no, int *channel_no,
int *target_no, int *lun_no)
{
int ret, i;
char adr[BURN_DRIVE_ADR_LEN];
/* open drives cannot be inquired by sg_obtain_scsi_adr() */
for (i = 0; i < drivetop + 1; i++) {
if (drive_array[i].global_index < 0)
continue;
ret = burn_drive_raw_get_adr(&(drive_array[i]),adr);
if (ret < 0)
return -1;
if (ret == 0)
continue;
if (strcmp(adr, path) == 0) {
*host_no = drive_array[i].host;
*channel_no = drive_array[i].channel;
*target_no = drive_array[i].id;
*lun_no = drive_array[i].lun;
*bus_no = drive_array[i].bus_no;
if (*host_no < 0 || *channel_no < 0 ||
*target_no < 0 || *lun_no < 0)
return 0;
return 1;
}
}
ret = sg_obtain_scsi_adr(path, bus_no, host_no, channel_no,
target_no, lun_no);
return ret;
}
/* ts A60923 */
int burn_drive_convert_scsi_adr(int bus_no, int host_no, int channel_no,
int target_no, int lun_no, char adr[])
{
char fname[4096],msg[4096+100];
int ret = 0, first = 1, i_bus_no = -1;
int i_host_no = -1, i_channel_no = -1, i_target_no = -1, i_lun_no = -1;
burn_drive_enumerator_t enm;
sprintf(msg,"burn_drive_convert_scsi_adr( %d,%d,%d,%d,%d )",
bus_no, host_no, channel_no, target_no, lun_no);
burn_drive_adr_debug_msg(msg, NULL);
while (1) {
ret= sg_give_next_adr(&enm, fname, sizeof(fname), first);
if(ret <= 0)
break;
first = 0;
ret = burn_drive_obtain_scsi_adr(fname, &i_bus_no, &i_host_no,
&i_channel_no, &i_target_no, &i_lun_no);
if(ret <= 0)
continue;
if(bus_no >=0 && i_bus_no != bus_no)
continue;
if(host_no >=0 && i_host_no != host_no)
continue;
if(channel_no >= 0 && i_channel_no != channel_no)
continue;
if(target_no >= 0 && i_target_no != target_no)
continue;
if(lun_no >= 0 && i_lun_no != lun_no)
continue;
if(strlen(fname) >= BURN_DRIVE_ADR_LEN)
{ ret = -1; goto ex;}
burn_drive_adr_debug_msg(
"burn_drive_convert_scsi_adr() found %s", fname);
strcpy(adr, fname);
{ ret = 1; goto ex;}
}
ret = 0;
ex:;
if (first == 0)
sg_give_next_adr(&enm, fname, sizeof(fname), -1);
return ret;
}
/* ts A60922 ticket 33 */
/* Try to find an enumerated address with the same host,channel,target,lun
as path */
int burn_drive_find_scsi_equiv(char *path, char adr[])
{
int ret = 0;
int bus_no, host_no, channel_no, target_no, lun_no;
char msg[4096];
ret = burn_drive_obtain_scsi_adr(path, &bus_no, &host_no, &channel_no,
&target_no, &lun_no);
if(ret <= 0) {
sprintf(msg,"burn_drive_obtain_scsi_adr( %s ) returns %d\n",
path, ret);
burn_drive_adr_debug_msg(msg, NULL);
return 0;
}
sprintf(msg, "burn_drive_find_scsi_equiv( %s ) : (%d),%d,%d,%d,%d",
path, bus_no, host_no, channel_no, target_no, lun_no);
burn_drive_adr_debug_msg(msg, NULL);
ret= burn_drive_convert_scsi_adr(-1, host_no, channel_no, target_no,
lun_no, adr);
return ret;
}
/* ts A60922 ticket 33 */
/** Try to convert a given existing filesystem address into a persistent drive
address. */
int burn_drive_convert_fs_adr_sub(char *path, char adr[], int *rec_count)
{
int ret;
struct stat stbuf;
burn_drive_adr_debug_msg("burn_drive_convert_fs_adr( %s )", path);
if(burn_drive_is_enumerable_adr(path)) {
if(strlen(path) >= BURN_DRIVE_ADR_LEN)
return -1;
burn_drive_adr_debug_msg(
"burn_drive_is_enumerable_adr( %s ) is true", path);
strcpy(adr, path);
return 1;
}
if(lstat(path, &stbuf) == -1) {
burn_drive_adr_debug_msg("lstat( %s ) returns -1", path);
return 0;
}
if((stbuf.st_mode & S_IFMT) == S_IFLNK) {
ret = burn_drive_resolve_link(path, adr, rec_count);
if(ret > 0)
return 1;
burn_drive_adr_debug_msg("link fallback via stat( %s )", path);
if(stat(path, &stbuf) == -1) {
burn_drive_adr_debug_msg("stat( %s ) returns -1",path);
return 0;
}
}
if((stbuf.st_mode&S_IFMT) == S_IFBLK ||
(stbuf.st_mode&S_IFMT) == S_IFCHR) {
ret = burn_drive_find_devno(stbuf.st_rdev, adr);
if(ret > 0)
return 1;
ret = burn_drive_find_scsi_equiv(path, adr);
if(ret > 0)
return 1;
}
burn_drive_adr_debug_msg("Nothing found for %s", path);
return 0;
}
/** Try to convert a given existing filesystem address into a persistent drive
address. */
int burn_drive_convert_fs_adr(char *path, char adr[])
{
int ret, rec_count = 0;
ret = burn_drive_convert_fs_adr_sub(path, adr, &rec_count);
return ret;
}
/** A pacifier function suitable for burn_abort.
@param handle If not NULL, a pointer to a text suitable for printf("%s")
*/
int burn_abort_pacifier(void *handle, int patience, int elapsed)
{
char *prefix= "libburn : ";
if(handle!=NULL)
prefix= handle;
fprintf(stderr,
"\r%sABORT : Waiting for drive to finish ( %d s, %d max)",
(char *) prefix, elapsed, patience);
return(1);
}
/** Abort any running drive operation and finis libburn.
@param patience Maximum number of seconds to wait for drives to finish
@param pacifier_func Function to produce appeasing messages. See
burn_abort_pacifier() for an example.
@return 1 ok, all went well
0 had to leave a drive in unclean state
<0 severe error, do no use libburn again
*/
int burn_abort(int patience,
int (*pacifier_func)(void *handle, int patience, int elapsed),
void *handle)
{
int ret, i, occup, still_not_done= 1, pacifier_off= 0, first_round= 1;
unsigned long wait_grain= 100000;
time_t start_time, current_time, pacifier_time, end_time;
current_time = start_time = pacifier_time = time(0);
end_time = start_time + patience;
while(current_time-end_time < patience) {
still_not_done = 0;
for(i = 0; i < drivetop + 1; i++) {
occup = burn_drive_is_occupied(&(drive_array[i]));
if(occup == -2)
continue;
if(occup <= 10) {
burn_drive_forget(&(drive_array[i]), 1);
} else if(occup <= 100) {
if(first_round)
burn_drive_cancel(&(drive_array[i]));
still_not_done++;
} else if(occup <= 1000) {
still_not_done++;
}
}
first_round = 0;
if(still_not_done == 0)
break;
usleep(wait_grain);
current_time = time(0);
if(current_time>pacifier_time) {
if(pacifier_func != NULL && !pacifier_off) {
ret = (*pacifier_func)(handle, patience,
current_time-start_time);
pacifier_off = (ret <= 0);
}
pacifier_time = current_time;
}
}
burn_finish();
return(still_not_done == 0);
}
/* ts A61020 API function */
int burn_drive_get_start_end_lba(struct burn_drive *d,
int *start_lba, int *end_lba, int flag)
{
if (d->start_lba == -2000000000 || d->end_lba == -2000000000)
return 0;
*start_lba = d->start_lba;
*end_lba= d->end_lba;
return 1;
}
/* ts A61020 API function */
int burn_disc_pretend_blank(struct burn_drive *d)
{
if (d->status != BURN_DISC_UNREADY &&
d->status != BURN_DISC_UNSUITABLE)
return 0;
d->status = BURN_DISC_BLANK;
return 1;
}
/* ts A61021: new API function */
int burn_disc_read_atip(struct burn_drive *d)
{
if (burn_drive_is_released(d)) {
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x0002010e,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Attempt to read ATIP from ungrabbed drive",
0, 0);
return -1;
}
d->read_atip(d);
/* >>> some control of success would be nice :) */
assert(strlen(drive_info->location) < BURN_DRIVE_ADR_LEN);
strcpy(adr,drive_info->location);
return 1;
}

View File

@ -35,14 +35,9 @@ struct mempage;
SESSION_LEADOUT_ENTRY((d), (d)->toc->sessions-1))
struct burn_drive *burn_drive_register(struct burn_drive *);
int burn_drive_unregister(struct burn_drive *d);
unsigned int burn_drive_count(void);
/* ts A61007 */
/* void burn_wait_all(void); */
int burn_drives_are_clear(void);
void burn_wait_all(void);
int burn_sector_length_write(struct burn_drive *d);
int burn_track_control(struct burn_drive *d, int);
void burn_write_empty_sector(int fd);
@ -56,18 +51,7 @@ void burn_disc_erase_sync(struct burn_drive *d, int fast);
int burn_drive_get_block_types(struct burn_drive *d,
enum burn_write_types write_type);
/* ts A60822 */
int burn_drive_is_open(struct burn_drive *d);
int burn_drive_is_occupied(struct burn_drive *d);
int burn_drive_forget(struct burn_drive *d, int force);
int burn_drive_convert_fs_adr_sub(char *path, char adr[], int *rec_count);
/* ts A61021 : the unspecific part of sg.c:enumerate_common()
*/
int burn_setup_drive(struct burn_drive *d, char *fname);
/* ts A61021 : after-setup activities from sg.c:enumerate_common()
*/
struct burn_drive *burn_drive_finish_enum(struct burn_drive *d);
#endif /* __DRIVE */

View File

@ -1,14 +1,9 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
#include <unistd.h>
/* ts A61007 */
/* #include <a ssert.h> */
#include <assert.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include "init.h"
#include "sg.h"
#include "error.h"
@ -19,11 +14,6 @@
#define BURN_BACK_HACKS_INIT 1
#include "back_hacks.h"
/* ts A60924 : a new message handling facility */
#include "libdax_msgs.h"
struct libdax_msgs *libdax_messenger= NULL;
int burn_running = 0;
/* ts A60813 : wether to use O_EXCL and/or O_NONBLOCK in libburn/sg.c */
@ -41,206 +31,50 @@ int burn_sg_open_o_nonblock = 1;
int burn_sg_open_abort_busy = 0;
/* ts A61002 */
#include "cleanup.h"
/* Parameters for builtin abort handler */
static char abort_message_prefix[81] = {"libburn : "};
static pid_t abort_control_pid= 0;
/* ts A60925 : ticket 74 */
/** Create the messenger object for libburn. */
int burn_msgs_initialize(void)
{
int ret;
if(libdax_messenger == NULL) {
ret = libdax_msgs_new(&libdax_messenger,0);
if (ret <= 0)
return 0;
}
libdax_msgs_set_severities(libdax_messenger, LIBDAX_MSGS_SEV_NEVER,
LIBDAX_MSGS_SEV_FATAL, "libburn: ", 0);
return 1;
}
/* ts A60924 : ticket 74 : Added use of global libdax_messenger */
int burn_initialize(void)
{
int ret;
if (burn_running)
return 1;
ret = burn_msgs_initialize();
if (ret <= 0)
return 0;
burn_running = 1;
return 1;
}
void burn_finish(void)
{
/* ts A61007 : assume no messageing system */
/* a ssert(burn_running); */
if (!burn_running)
return;
assert(burn_running);
/* ts A61007 */
/* burn_wait_all(); */
if (!burn_drives_are_clear()) {
libdax_msgs_submit(libdax_messenger, -1, 0x00020107,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Drive is busy on attempt to shut down library", 0, 0);
return;
}
burn_wait_all();
/* ts A60904 : ticket 62, contribution by elmom : name addon "_all" */
burn_drive_free_all();
/* ts A60924 : ticket 74 */
libdax_msgs_destroy(&libdax_messenger,0);
burn_running = 0;
}
/* ts A60813 */
/** API function. See libburn.h */
/** 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.
@param exclusive Try to open only devices which are not marked as busy
and try to mark them busy if opened sucessfully. (O_EXCL)
There are kernels which simply don't care about O_EXCL.
Some have it off, some have it on, some are switchable.
@param blocking Try to wait for drives which do not open immediately but
also do not return an error as well. (O_NONBLOCK)
This might stall indefinitely with /dev/hdX hard disks.
@param abort_on_busy Unconditionally abort process when a non blocking
exclusive opening attempt indicates a busy drive.
Use this only after thorough tests with your app.
Parameter value 1 enables a feature, 0 disables.
Default is (1,0,0). Have a good reason before you change it.
*/
void burn_preset_device_open(int exclusive, int blocking, int abort_on_busy)
{
/* ts A61007 */
/* a ssert(burn_running); */
if (!burn_running)
return;
assert(burn_running);
burn_sg_open_o_excl= exclusive;
burn_sg_open_o_excl= !!exclusive;
burn_sg_open_o_nonblock= !blocking;
burn_sg_open_abort_busy= !!abort_on_busy;
}
/* ts A60924 : ticket 74 */
/** Control queueing and stderr printing of messages from libburn.
Severity may be one of "NEVER", "FATAL", "SORRY", "WARNING", "HINT",
"NOTE", "UPDATE", "DEBUG", "ALL".
@param queue_severity Gives the minimum limit for messages to be queued.
Default: "NEVER". If you queue messages then you
must consume them by burn_msgs_obtain().
@param print_severity Does the same for messages to be printed directly
to stderr.
@param print_id A text prefix to be printed before the message.
@return >0 for success, <=0 for error
*/
int burn_msgs_set_severities(char *queue_severity,
char *print_severity, char *print_id)
{
int ret, queue_sevno, print_sevno;
ret = libdax_msgs__text_to_sev(queue_severity, &queue_sevno, 0);
if (ret <= 0)
return 0;
ret = libdax_msgs__text_to_sev(print_severity, &print_sevno, 0);
if (ret <= 0)
return 0;
ret = libdax_msgs_set_severities(libdax_messenger, queue_sevno,
print_sevno, print_id, 0);
if (ret <= 0)
return 0;
return 1;
}
/* ts A60924 : ticket 74 */
#define BURM_MSGS_MESSAGE_LEN 4096
/** Obtain the oldest pending libburn message from the queue which has at
least the given minimum_severity. This message and any older message of
lower severity will get discarded from the queue and is then lost forever.
Severity may be one of "NEVER", "FATAL", "SORRY", "WARNING", "HINT",
"NOTE", "UPDATE", "DEBUG", "ALL". To call with minimum_severity "NEVER"
will discard the whole queue.
@param error_code Will become a unique error code as liste in
libburn/libdax_msgs.h
@param msg_text Must provide at least BURM_MSGS_MESSAGE_LEN bytes.
@param os_errno Will become the eventual errno related to the message
@param severity Will become the severity related to the message and
should provide at least 80 bytes.
@return 1 if a matching item was found, 0 if not, <0 for severe errors
*/
int burn_msgs_obtain(char *minimum_severity,
int *error_code, char msg_text[], int *os_errno,
char severity[])
{
int ret, minimum_sevno, sevno, priority;
char *textpt, *sev_name;
struct libdax_msgs_item *item = NULL;
ret = libdax_msgs__text_to_sev(minimum_severity, &minimum_sevno, 0);
if (ret <= 0)
return 0;
ret = libdax_msgs_obtain(libdax_messenger, &item, minimum_sevno,
LIBDAX_MSGS_PRIO_ZERO, 0);
if (ret <= 0)
goto ex;
ret = libdax_msgs_item_get_msg(item, error_code, &textpt, os_errno, 0);
if (ret <= 0)
goto ex;
strncpy(msg_text, textpt, BURM_MSGS_MESSAGE_LEN-1);
if(strlen(textpt) >= BURM_MSGS_MESSAGE_LEN)
msg_text[BURM_MSGS_MESSAGE_LEN-1] = 0;
severity[0]= 0;
ret = libdax_msgs_item_get_rank(item, &sevno, &priority, 0);
if(ret <= 0)
goto ex;
ret = libdax_msgs__sev_to_text(sevno, &sev_name, 0);
if(ret <= 0)
goto ex;
strcpy(severity,sev_name);
ret = 1;
ex:
libdax_msgs_destroy_item(libdax_messenger, &item, 0);
return ret;
}
int burn_builtin_abort_handler(void *handle, int signum, int flag)
{
if(getpid() != abort_control_pid)
return -2;
Cleanup_set_handlers(NULL, NULL, 2);
fprintf(stderr,"%sABORT : Trying to shut down drive and library\n",
abort_message_prefix);
fprintf(stderr,
"%sABORT : Wait the normal burning time before any kill -9\n",
abort_message_prefix);
close(0); /* somehow stdin as input blocks abort until EOF */
burn_abort(4440, burn_abort_pacifier, abort_message_prefix);
fprintf(stderr,
"\n%sABORT : Program done. Even if you do not see a shell prompt.\n\n",
abort_message_prefix);
return(1);
}
void burn_set_signal_handling(void *handle, burn_abort_handler_t handler,
int mode)
{
if(handler == NULL && mode == 0) {
handler = burn_builtin_abort_handler;
/*
fprintf(stderr, "libburn_experimental: activated burn_builtin_abort_handler() with handle '%s'\n",(handle==NULL ? "libburn : " : (char *) handle));
*/
}
strcpy(abort_message_prefix, "libburn : ");
if(handle != NULL)
strncpy(abort_message_prefix, (char *) handle,
sizeof(abort_message_prefix)-1);
abort_message_prefix[sizeof(abort_message_prefix)-1] = 0;
abort_control_pid= getpid();
Cleanup_set_handlers(handle, (Cleanup_app_handler_T) handler, mode|4);
}

View File

@ -172,17 +172,39 @@ enum burn_disc_status
/** There is an incomplete disc in the drive */
BURN_DISC_APPENDABLE,
/** There is a disc with data on it in the drive */
BURN_DISC_FULL,
/* ts A61007 */
/** The drive was not grabbed when the status was inquired */
BURN_DISC_UNGRABBED,
/* ts A61020 */
/** The media seems not to be suitable for burning */
BURN_DISC_UNSUITABLE
BURN_DISC_FULL
};
/** Possible types of messages form the library. */
enum burn_message_type
{
/** Diagnostic/Process information. For the curious user. */
BURN_MESSAGE_INFO,
/** A warning regarding a possible problem. The user should probably
be notified, but its not fatal. */
BURN_MESSAGE_WARNING,
/** An error message. This usually means the current process will be
aborted, and the user should definately see these. */
BURN_MESSAGE_ERROR
};
/** Possible information messages */
enum burn_message_info
{
BURN_INFO_FOO
};
/** Possible warning messages */
enum burn_message_warning
{
BURN_WARNING_FOO
};
/** Possible error messages */
enum burn_message_error
{
BURN_ERROR_CANCELLED
};
/** Possible data source return values */
enum burn_source_status
@ -295,7 +317,7 @@ struct burn_drive_info
/** This is currently the string which is used as persistent
drive address. But be warned: there is NO GUARANTEE that this
will stay so. Always use function burn_drive_get_adr() to
inquire a persistent address. ^^^^^^ ALWAYS ^^^^^^ */
inquire a persisten address. ^^^^^^ ALWAYS ^^^^^^ */
/** Can the drive read DVD-RAM discs */
unsigned int read_dvdram:1;
@ -356,6 +378,29 @@ struct burn_drive_info
struct burn_drive *drive;
};
/** Messages from the library */
struct burn_message
{
/** The drive associated with the message. NULL if the error is not
related to a specific drive. */
struct burn_drive *drive;
/** The type of message this is. See message_type for details. */
enum burn_message_type type;
/** The actual message */
union detail {
struct {
enum burn_message_info message;
} info;
struct {
enum burn_message_warning message;
} warning;
struct {
enum burn_message_error message;
} error;
} detail;
};
/** Operation progress report. All values are 0 based indices.
* */
@ -378,12 +423,6 @@ struct burn_progress {
int sectors;
/** The current sector being processed */
int sector;
/* ts A61023 */
/** The capacity of the drive buffer */
unsigned buffer_capacity;
/** The free space in the drive buffer (might be slightly outdated) */
unsigned buffer_available;
};
/** Initialize the library.
@ -405,36 +444,7 @@ int burn_initialize(void);
*/
void burn_finish(void);
/* ts A61002 */
/** Abort any running drive operation and finally call burn_finish().
You MUST calm down the busy drive if an aborting event occurs during a
burn run. For that you may call this function either from your own signal
handling code or indirectly by activating the builtin signal handling:
burn_set_signal_handling("my_app_name : ", NULL, 0);
Else you may eventually call burn_drive_cancel() on the active drive and
wait for it to assume state BURN_DRIVE_IDLE.
@param patience Maximum number of seconds to wait for drives to finish
@param pacifier_func If not NULL: a function to produce appeasing messages.
See burn_abort_pacifier() for an example.
@return 1 ok, all went well
0 had to leave a drive in unclean state
<0 severe error, do no use libburn again
*/
int burn_abort(int patience,
int (*pacifier_func)(void *handle, int patience, int elapsed),
void *handle);
/** A pacifier function suitable for burn_abort.
@param handle If not NULL, a pointer to a text suitable for printf("%s")
@param patience Maximum number of seconds to wait
@param elapsed Elapsed number of seconds
*/
int burn_abort_pacifier(void *handle, int patience, int elapsed);
/** ts A61006 : This is for development only. Not suitable for applications.
Set the verbosity level of the library. The default value is 0, which means
/** Set the verbosity level of the library. The default value is 0, which means
that nothing is output on stderr. The more you increase this, the more
debug output should be displayed on stderr for you.
@param level The verbosity level desired. 0 for nothing, higher positive
@ -447,13 +457,10 @@ void burn_set_verbosity(int level);
after burn_initialize() and before any bus scan. But not mandatory at all.
Parameter value 1 enables a feature, 0 disables.
Default is (1,0,0). Have a good reason before you change it.
@param exclusive 1 = Try to open only devices which are not marked as busy
@param exclusive Try to open only devices which are not marked as busy
and try to mark them busy if opened sucessfully. (O_EXCL)
There are kernels which simply don't care about O_EXCL.
Some have it off, some have it on, some are switchable.
2 = in case of a SCSI device, also try to open exclusively
the matching /dev/sr, /dev/scd and /dev/st .
0 = no attempt to make drive access exclusive.
@param blocking Try to wait for drives which do not open immediately but
also do not return an error as well. (O_NONBLOCK)
This might stall indefinitely with /dev/hdX hard disks.
@ -463,6 +470,15 @@ void burn_set_verbosity(int level);
*/
void burn_preset_device_open(int exclusive, int blocking, int abort_on_busy);
/** Returns a newly allocated burn_message structure. This message should be
freed with burn_message_free() when you are finished with it.
@return A message or NULL when there are no more messages to retrieve.
*/
struct burn_message* burn_get_message(void);
/** Frees a burn_message structure */
void burn_message_free(struct burn_message *msg);
/* ts A60823 */
/** Aquire a drive with known persistent address.This is the sysadmin friendly
@ -512,7 +528,7 @@ void burn_drive_clear_whitelist(void);
/** Scan for drives. This function MUST be called until it returns nonzero.
No drives may be in use when this is called.
No drives can be in use when this is called or it will assert.
All drive pointers are invalidated by using this function. Do NOT store
drive pointers across calls to this function or death AND pain will ensue.
After this call all drives depicted by the returned array are subject
@ -525,9 +541,7 @@ void burn_drive_clear_whitelist(void);
before burn_finish(), and also before calling this function
burn_drive_scan() again.
@param n_drives Returns the number of drive items in drive_infos.
@return 0 while scanning is not complete
>0 when it is finished sucessfully,
<0 when finished but failed.
@return Zero while scanning is not complete; non-zero when it is finished.
*/
int burn_drive_scan(struct burn_drive_info *drive_infos[],
unsigned int *n_drives);
@ -562,51 +576,9 @@ void burn_drive_info_free(struct burn_drive_info drive_infos[]);
@param drive_info The drive to inquire. Usually some &(drive_infos[driveno])
@param adr An application provided array of at least BURN_DRIVE_ADR_LEN
characters size. The persistent address gets copied to it.
@return >0 success , <=0 error (due to libburn internal problem)
*/
int burn_drive_get_adr(struct burn_drive_info *drive_info, char adr[]);
/* ts A60922 ticket 33 */
/** Evaluate wether the given address would be a possible persistent drive
address of libburn.
@return 1 means yes, 0 means no
*/
int burn_drive_is_enumerable_adr(char *adr);
/* ts A60922 ticket 33 */
/** Try to convert a given existing filesystem address into a persistent drive
address. This succeeds with symbolic links or if a hint about the drive's
system address can be read from the filesystem object and a matching drive
is found.
@param path The address of an existing file system object
@param adr An application provided array of at least BURN_DRIVE_ADR_LEN
characters size. The persistent address gets copied to it.
@return 1 = success , 0 = failure , -1 = severe error
*/
int burn_drive_convert_fs_adr(char *path, char adr[]);
/* ts A60923 */
/** Try to convert a given SCSI address of bus,host,channel,target,lun into
a persistent drive address. If a SCSI address component parameter is < 0
then it is not decisive and the first enumerated address which matches
the >= 0 parameters is taken as result.
Note: bus and (host,channel) are supposed to be redundant.
@param adr An application provided array of at least BURN_DRIVE_ADR_LEN
characters size. The persistent address gets copied to it.
@return 1 = success , 0 = failure , -1 = severe error
*/
int burn_drive_convert_scsi_adr(int bus_no, int host_no, int channel_no,
int target_no, int lun_no, char adr[]);
/* ts A60923 - A61005 */
/** Try to obtain bus,host,channel,target,lun from path. If there is an SCSI
address at all, then this call should succeed with a persistent
drive address obtained via burn_drive_get_adr(). It is also supposed to
succeed with any device file of a (possibly emulated) SCSI device.
@return 1 = success , 0 = failure , -1 = severe error
*/
int burn_drive_obtain_scsi_adr(char *path, int *bus_no, int *host_no,
int *channel_no, int *target_no, int *lun_no);
/** Grab a drive. This must be done before the drive can be used (for reading,
writing, etc).
@ -633,46 +605,9 @@ void burn_drive_release(struct burn_drive *drive, int eject);
for details.
@param drive The drive to query for a disc.
@return The status of the drive, or what kind of disc is in it.
Note: BURN_DISC_UNGRABBED indicates wrong API usage
*/
enum burn_disc_status burn_disc_get_status(struct burn_drive *drive);
/* ts A61020 */
/** WARNING: This revives an old bug-like behavior that might be dangerous.
Sets the drive status to BURN_DISC_BLANK if it is BURN_DISC_UNREADY
or BURN_DISC_UNSUITABLE. Thus marking media as writable which actually
failed to declare themselves either blank or (partially) filled.
@return 1 drive status has been set , 0 = unsuitable drive status
*/
int burn_disc_pretend_blank(struct burn_drive *drive);
/* ts A61021 */
/** Reads ATIP information from inserted media. To be obtained via
burn_drive_get_write_speed(), burn_drive_get_min_write_speed(),
burn_drive_get_start_end_lba(). The drive must be grabbed for this call.
@param drive The drive to query.
@return 1=sucess, 0=no valid ATIP info read, -1 severe error
*/
int burn_disc_read_atip(struct burn_drive *drive);
/* ts A61020 */
/** Returns start and end lba of the media which is currently inserted
in the given drive. The drive has to be grabbed to have hope for reply.
Shortcomming (not a feature): unless burn_disc_read_atip() was called
only blank media will return valid info.
@param drive The drive to query.
@param start_lba Returns the start lba value
@param end_lba Returns the end lba value
@param flag Bitfield for control purposes (unused yet, submit 0)
@return 1 if lba values are valid , 0 if invalid
*/
int burn_drive_get_start_end_lba(struct burn_drive *drive,
int *start_lba, int *end_lba, int flag);
/** Tells whether a disc can be erased or not
@return Non-zero means erasable
*/
@ -689,7 +624,7 @@ enum burn_drive_status burn_drive_get_status(struct burn_drive *drive,
/** Creates a write_opts struct for burning to the specified drive
must be freed with burn_write_opts_free
@param drive The drive to write with
@return The write_opts, NULL on error
@return The write_opts
*/
struct burn_write_opts *burn_write_opts_new(struct burn_drive *drive);
@ -698,7 +633,7 @@ struct burn_write_opts *burn_write_opts_new(struct burn_drive *drive);
*/
void burn_write_opts_free(struct burn_write_opts *opts);
/** Creates a read_opts struct for reading from the specified drive
/** Creates a write_opts struct for reading from the specified drive
must be freed with burn_write_opts_free
@param drive The drive to read from
@return The read_opts
@ -849,16 +784,6 @@ int burn_session_remove_track(struct burn_session *s, struct burn_track *t);
void burn_track_define_data(struct burn_track *t, int offset, int tail,
int pad, int mode);
/* ts A61024 */
/** Define wether a track shall swap bytes of its input stream.
@param t The track to change
@param swap_source_bytes 0=do not swap, 1=swap byte pairs
@return 1=success , 0=unacceptable value
*/
int burn_track_set_byte_swap(struct burn_track *t, int swap_source_bytes);
/** Set the ISRC details for a track
@param t The track to change
@param country the 2 char country code. Each character must be
@ -884,7 +809,7 @@ void burn_session_hide_first_track(struct burn_session *s, int onoff);
/** Get the drive's disc struct - free when done
@param d drive to query
@return the disc struct or NULL on failure
@return the disc struct
*/
struct burn_disc *burn_drive_get_disc(struct burn_drive *d);
@ -1046,16 +971,6 @@ void burn_read_opts_set_hardware_error_retries(struct burn_read_opts *opts,
*/
int burn_drive_get_write_speed(struct burn_drive *d);
/* ts A61021 */
/** Gets the minimum write speed for a drive. This might differ from
burn_drive_get_write_speed() only after burn_disc_read_atip()
@param d Drive to query
@return Minimum write speed in K/s
*/
int burn_drive_get_min_write_speed(struct burn_drive *d);
/** Gets the maximum read speed for a drive
@param d Drive to query
@return Maximum read speed in K/s
@ -1116,68 +1031,6 @@ int burn_session_get_hidefirst(struct burn_session *session);
*/
void burn_version(int *major, int *minor, int *micro);
/* ts A60924 : ticket 74 */
/** Control queueing and stderr printing of messages from libburn.
Severity may be one of "NEVER", "FATAL", "SORRY", "WARNING", "HINT",
"NOTE", "UPDATE", "DEBUG", "ALL".
@param queue_severity Gives the minimum limit for messages to be queued.
Default: "NEVER". If you queue messages then you
must consume them by burn_msgs_obtain().
@param print_severity Does the same for messages to be printed directly
to stderr. Default: "FATAL".
@param print_id A text prefix to be printed before the message.
@return >0 for success, <=0 for error
*/
int burn_msgs_set_severities(char *queue_severity,
char *print_severity, char *print_id);
/* ts A60924 : ticket 74 */
#define BURN_MSGS_MESSAGE_LEN 4096
/** Obtain the oldest pending libburn message from the queue which has at
least the given minimum_severity. This message and any older message of
lower severity will get discarded from the queue and is then lost forever.
Severity may be one of "NEVER", "FATAL", "SORRY", "WARNING", "HINT",
"NOTE", "UPDATE", "DEBUG", "ALL". To call with minimum_severity "NEVER"
will discard the whole queue.
@param error_code Will become a unique error code as liste in
libburn/libdax_msgs.h
@param msg_text Must provide at least BURN_MSGS_MESSAGE_LEN bytes.
@param os_errno Will become the eventual errno related to the message
@param severity Will become the severity related to the message and
should provide at least 80 bytes.
@return 1 if a matching item was found, 0 if not, <0 for severe errors
*/
int burn_msgs_obtain(char *minimum_severity,
int *error_code, char msg_text[], int *os_errno,
char severity[]);
/* ts A61002 */
/* The prototype of a handler function suitable for burn_set_abort_handling().
Such a function has to return -2 if it does not want the process to
exit with value 1.
*/
typedef int (*burn_abort_handler_t)(void *handle, int signum, int flag);
/** Control builtin signal handling. See also burn_abort().
@param handle Opaque handle eventually pointing to an application
provided memory object
@param handler A function to be called on signals. It will get handle as
argument. It should finally call burn_abort(). See there.
@param mode : 0 call handler(handle, signum, 0) on nearly all signals
1 enable system default reaction on all signals
2 try to ignore nearly all signals
10 like mode 2 but handle SIGABRT like with mode 0
Arguments (text, NULL, 0) activate the builtin abort handler. It will
eventually call burn_abort() and then perform exit(1). If text is not NULL
then it is used as prefix for pacifier messages of burn_abort_pacifier().
*/
void burn_set_signal_handling(void *handle, burn_abort_handler_t handler,
int mode);
#ifndef DOXYGEN
BURN_END_DECLS

View File

@ -1,326 +0,0 @@
/* libdax_audioxtr
Audio track data extraction facility of libdax and libburn.
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger;
/* Only this single source module is entitled to do this */
#define LIBDAX_AUDIOXTR_H_INTERNAL 1
/* All clients of the extraction facility must do this */
#include "libdax_audioxtr.h"
int libdax_audioxtr_new(struct libdax_audioxtr **xtr, char *path, int flag)
{
int ret= -1;
struct libdax_audioxtr *o;
o= *xtr= (struct libdax_audioxtr *) malloc(sizeof(struct libdax_audioxtr));
if(o==NULL)
return(-1);
strncpy(o->path,path,LIBDAX_AUDIOXTR_STRLEN-1);
o->path[LIBDAX_AUDIOXTR_STRLEN]= 0;
o->fd= -1;
strcpy(o->fmt,"unidentified");
o->fmt_info[0]= 0;
o->data_size= 0;
o->extract_count= 0;
o->num_channels= 0;
o->sample_rate= 0;
o->bits_per_sample= 0;
o->msb_first= 0;
o->wav_subchunk2_size= 0;
o->au_data_location= 0;
o->au_data_size= 0xffffffff;
ret= libdax_audioxtr_open(o,0);
if(ret<=0)
{ret= -2*(ret<0); goto failure;}
return(1);
failure:
libdax_audioxtr_destroy(xtr,0);
return(ret);
}
int libdax_audioxtr_destroy(struct libdax_audioxtr **xtr, int flag)
{
struct libdax_audioxtr *o;
o= *xtr;
if(o==NULL)
return(0);
if(o->fd>=0 && strcmp(o->path,"-")!=0)
close(o->fd);
free((char *) o);
*xtr= NULL;
return(1);
}
static int libdax_audioxtr_open(struct libdax_audioxtr *o, int flag)
{
int ret;
char msg[LIBDAX_AUDIOXTR_STRLEN+80];
if(strcmp(o->path,"-")==0)
o->fd= 0;
else
o->fd= open(o->path, O_RDONLY);
if(o->fd<0) {
sprintf(msg,"Cannot open audio source file : %s",o->path);
libdax_msgs_submit(libdax_messenger,-1,0x00020200,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, errno, 0);
return(-1);
}
ret= libdax_audioxtr_identify(o,0);
if(ret<=0) {
sprintf(msg,"Audio source file has unsuitable format : %s",o->path);
libdax_msgs_submit(libdax_messenger,-1,0x00020201,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
return(0);
}
ret= libdax_audioxtr_init_reading(o,0);
if(ret<=0) {
sprintf(msg,"Failed to prepare reading of audio data : %s",o->path);
libdax_msgs_submit(libdax_messenger,-1,0x00020202,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
return(0);
}
return(1);
}
static int libdax_audioxtr_identify_wav(struct libdax_audioxtr *o, int flag)
{
int ret;
char buf[45];
/* check wether this is a MS WAVE file .wav */
/* info used: http://ccrma.stanford.edu/courses/422/projects/WaveFormat/ */
if(o->fd!=0) {
ret= lseek(o->fd,0,SEEK_SET);
if(ret==-1)
return(0);
}
ret= read(o->fd, buf, 44);
if(ret<44)
return(0);
buf[44]= 0; /* as stopper for any string operations */
if(strncmp(buf,"RIFF",4)!=0) /* ChunkID */
return(0);
if(strncmp(buf+8,"WAVE",4)!=0) /* Format */
return(0);
if(strncmp(buf+12,"fmt ",4)!=0) /* Subchunk1ID */
return(0);
if(buf[16]!=16 || buf[17]!=0 || buf[18]!=0 || buf[19]!=0) /* Subchunk1Size */
return(0);
if(buf[20]!=1 || buf[21]!=0) /* AudioFormat must be 1 (Linear quantization) */
return(0);
strcpy(o->fmt,".wav");
o->msb_first= 0;
o->num_channels= libdax_audioxtr_to_int(o,(unsigned char *) buf+22,2,0);
o->sample_rate= libdax_audioxtr_to_int(o,(unsigned char *) buf+24,4,0);
o->bits_per_sample= libdax_audioxtr_to_int(o,(unsigned char *)buf+34,2,0);
sprintf(o->fmt_info,
".wav , num_channels=%d , sample_rate=%d , bits_per_sample=%d",
o->num_channels,o->sample_rate,o->bits_per_sample);
o->wav_subchunk2_size= libdax_audioxtr_to_int(o,(unsigned char *)buf+40,4,0);
o->data_size= o->wav_subchunk2_size;
return(1);
}
static int libdax_audioxtr_identify_au(struct libdax_audioxtr *o, int flag)
{
int ret,encoding;
char buf[24];
/* Check wether this is a Sun Audio, .au file */
/* info used: http://ccrma.stanford.edu/courses/422/projects/WaveFormat/ */
if(o->fd!=0) {
ret= lseek(o->fd,0,SEEK_SET);
if(ret==-1)
return(0);
}
ret= read(o->fd, buf, 24);
if(ret<24)
return(0);
if(strncmp(buf,".snd",4)!=0)
return(0);
strcpy(o->fmt,".au");
o->msb_first= 1;
o->au_data_location= libdax_audioxtr_to_int(o,(unsigned char *)buf+4,4,1);
o->au_data_size= libdax_audioxtr_to_int(o,(unsigned char *)buf+8,4,1);
encoding= libdax_audioxtr_to_int(o,(unsigned char *)buf+12,4,1);
if(encoding==2)
o->bits_per_sample= 8;
else if(encoding==3)
o->bits_per_sample= 16;
else if(encoding==4)
o->bits_per_sample= 24;
else if(encoding==5)
o->bits_per_sample= 32;
else
o->bits_per_sample= -encoding;
o->sample_rate= libdax_audioxtr_to_int(o,(unsigned char *)buf+16,4,1);
o->num_channels= libdax_audioxtr_to_int(o,(unsigned char *)buf+20,4,1);
if(o->au_data_size!=0xffffffff)
o->data_size= o->au_data_size;
else
o->data_size= 0;
sprintf(o->fmt_info,
".au , num_channels=%d , sample_rate=%d , bits_per_sample=%d",
o->num_channels,o->sample_rate,o->bits_per_sample);
/* <<< for testing only */;
return(1);
return(o->bits_per_sample>0); /* Audio format must be linear PCM */
}
static int libdax_audioxtr_identify(struct libdax_audioxtr *o, int flag)
{
int ret;
ret= libdax_audioxtr_identify_wav(o, 0);
if(ret!=0)
return(ret);
if(o->fd==0) /* cannot rewind stdin */
return(0);
ret= libdax_audioxtr_identify_au(o, 0);
if(ret!=0)
return(ret);
return(0);
}
/* @param flag bit0=msb_first */
static unsigned libdax_audioxtr_to_int(struct libdax_audioxtr *o,
unsigned char *bytes, int len, int flag)
{
unsigned int ret= 0;
int i;
if(flag&1)
for(i= 0; i<len; i++)
ret= ret*256+bytes[i];
else
for(i= len-1; i>=0; i--)
ret= ret*256+bytes[i];
return(ret);
}
static int libdax_audioxtr_init_reading(struct libdax_audioxtr *o, int flag)
{
int ret;
/* currently this only works for MS WAVE files .wav and Sun .au*/;
if(o->fd==0) /* stdin: hope no read came after libdax_audioxtr_identify() */
return(1);
o->extract_count= 0;
if(strcmp(o->fmt,".wav")==0)
ret= lseek(o->fd,44,SEEK_SET);
else if(strcmp(o->fmt,".au")==0)
ret= lseek(o->fd,o->au_data_location,SEEK_SET);
else
ret= -1;
if(ret==-1)
return(0);
return(1);
}
int libdax_audioxtr_get_id(struct libdax_audioxtr *o,
char **fmt, char **fmt_info,
int *num_channels, int *sample_rate, int *bits_per_sample,
int *msb_first, int flag)
{
*fmt= o->fmt;
*fmt_info= o->fmt_info;
*num_channels= o->num_channels;
*sample_rate= o->sample_rate;
*bits_per_sample= o->bits_per_sample;
*msb_first= o->msb_first;
return(1);
}
int libdax_audioxtr_get_size(struct libdax_audioxtr *o, off_t *size, int flag)
{
*size= o->data_size;
return(1);
}
int libdax_audioxtr_read(struct libdax_audioxtr *o,
char buffer[], int buffer_size, int flag)
{
int ret;
if(buffer_size<=0 || o->fd<0)
return(-2);
if(o->data_size>0 && !(flag&1))
if(buffer_size > o->data_size - o->extract_count)
buffer_size= o->data_size - o->extract_count;
if(buffer_size<=0)
return(0);
ret= read(o->fd,buffer,buffer_size);
if(ret>0)
o->extract_count+= ret;
return(ret);
}
int libdax_audioxtr_detach_fd(struct libdax_audioxtr *o, int *fd, int flag)
{
if(o->fd<0)
return(-1);
if(strcmp(o->fmt,".wav")!=0 && strcmp(o->fmt,".au")!=0)
return(0);
if(flag&1) {
*fd= o->fd;
} else {
*fd= dup(o->fd);
if(*fd>=0 && strcmp(o->path,"-")!=0)
close(o->fd);
}
if(*fd>=0) {
o->fd= -1;
return(1);
}
return(-1);
}

View File

@ -1,229 +0,0 @@
/* libdax_audioxtr
Audio track data extraction facility of libdax and libburn.
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
*/
#ifndef LIBDAX_AUDIOXTR_H_INCLUDED
#define LIBDAX_AUDIOXTR_H_INCLUDED 1
/* Public Macros */
/* Maximum size for address paths and fmt_info strings */
#define LIBDAX_AUDIOXTR_STRLEN 4096
/* Public Opaque Handles */
/** Extractor object encapsulating intermediate states of extraction.
The clients of libdax_audioxtr shall only allocate pointers to this
struct and get a storage object via libdax_audioxtr_new().
Appropriate initial value for the pointer is NULL.
*/
struct libdax_audioxtr;
/* Public Functions */
/* Calls initiated from inside libdax/libburn */
/* Calls from applications (to be forwarded by libdax/libburn) */
/** Open an audio file, check wether suitable, create extractor object.
@param xtr Opaque handle to extractor. Gets attached extractor object.
@param path Address of the audio file to extract. "-" is stdin (but might
be not suitable for all futurely supported formats).
@param flag Bitfield for control purposes (unused yet, submit 0)
@return >0 success
0 unsuitable format
-1 severe error
-2 path not found
*/
int libdax_audioxtr_new(struct libdax_audioxtr **xtr, char *path, int flag);
/** Obtain identification parameters of opened audio source.
@param xtr Opaque handle to extractor
@param fmt Gets pointed to the audio file format id text: ".wav" , ".au"
@param fmt_info Gets pointed to a format info text telling parameters
@param num_channels e.g. 1=mono, 2=stereo, etc
@param sample_rate e.g. 11025, 44100
@param bits_per_sample e.g. 8= 8 bits per sample, 16= 16 bits ...
@param msb_first Byte order of samples: 0=Intel 1=Motorola
@param flag Bitfield for control purposes (unused yet, submit 0)
@return >0 success, <=0 failure
*/
int libdax_audioxtr_get_id(struct libdax_audioxtr *xtr,
char **fmt, char **fmt_info,
int *num_channels, int *sample_rate,
int *bits_per_sample, int *msb_first, int flag);
/** Obtain a prediction about the extracted size based on internal information
of the formatted file.
@param xtr Opaque handle to extractor
@param size Gets filled with the predicted size
@param flag Bitfield for control purposes (unused yet, submit 0)
@return 1 prediction was possible , 0 no prediction could be made
*/
int libdax_audioxtr_get_size(struct libdax_audioxtr *o, off_t *size, int flag);
/** Obtain next buffer full of extracted data in desired format (only raw audio
for now).
@param xtr Opaque handle to extractor
@param buffer Gets filled with extracted data
@param buffer_size Maximum number of bytes to be filled into buffer
@param flag Bitfield for control purposes
bit0= do not stop at predicted end of data
@return >0 number of valid buffer bytes,
0 End of file
-1 operating system reports error
-2 usage error by application
*/
int libdax_audioxtr_read(struct libdax_audioxtr *xtr,
char buffer[], int buffer_size, int flag);
/** Try to obtain a file descriptor which will deliver extracted data
to normal calls of read(2). This may fail because the format is
unsuitable for that, but ".wav" is ok. If this call succeeds the xtr
object will have forgotten its file descriptor and libdax_audioxtr_read()
will return a usage error. One may use *fd after libdax_audioxtr_destroy()
and will have to close it via close(2) when done with it.
@param xtr Opaque handle to extractor
@param fd Eventually returns the file descriptor number
@param flag Bitfield for control purposes
bit0= do not dup(2) and close(2) but hand out original fd
@return 1 success, 0 cannot hand out fd , -1 severe error
*/
int libdax_audioxtr_detach_fd(struct libdax_audioxtr *o, int *fd, int flag);
/** Clean up after extraction and destroy extractor object.
@param xtr Opaque handle to extractor, *xtr is allowed to be NULL,
*xtr is set to NULL by this function
@param flag Bitfield for control purposes (unused yet, submit 0)
@return 1 = destroyed object, 0 = was already destroyed
*/
int libdax_audioxtr_destroy(struct libdax_audioxtr **xtr, int flag);
#ifdef LIDBAX_AUDIOXTR________________
-- place documentation text here ---
#endif /* LIDBAX_AUDIOXTR_________________ */
/*
*Never* set this macro outside libdax_audioxtr.c !
The entrails of this facility are not to be seen by
the other library components or the applications.
*/
#ifdef LIBDAX_AUDIOXTR_H_INTERNAL
/* Internal Structures */
/** Extractor object encapsulating intermediate states of extraction */
struct libdax_audioxtr {
/* Source of the encoded audio data */
char path[LIBDAX_AUDIOXTR_STRLEN];
/* File descriptor to path. Anything else than 0 must be lseek-able */
int fd;
/* Format identifier. E.g. ".wav" */
char fmt[80];
/* Format parameter info text */
char fmt_info[LIBDAX_AUDIOXTR_STRLEN];
/* 1= mono, 2= stereo, etc. */
int num_channels;
/* 8000, 44100, etc. */
int sample_rate;
/* 8 bits = 8, 16 bits = 16, etc. */
int bits_per_sample;
/* Byte order of samples: 0=Intel 1=Motorola */
int msb_first;
/* Number of bytes to extract (0= unknown/unlimited) */
off_t data_size;
/* Number of extracted data bytes */
off_t extract_count;
/* Format dependent parameters */
/* MS WAVE Format */
/* info used: http://ccrma.stanford.edu/courses/422/projects/WaveFormat/ */
/* == NumSamples * NumChannels * BitsPerSample/8
This is the number of bytes in the data. */
unsigned wav_subchunk2_size;
/* Sun Audio, .au */
/* info used: http://www.opengroup.org/public/pubs/external/auformat.html */
/* Number of bytes in non-payload header part */
unsigned au_data_location;
/* Number of payload bytes or 0xffffffff */
unsigned au_data_size;
};
/* Internal Functions */
/** Open the audio source pointed to by .path and evaluate suitability.
@return -1 failure to open, 0 unsuitable format, 1 success
*/
static int libdax_audioxtr_open(struct libdax_audioxtr *o, int flag);
/** Identify format and evaluate suitability.
@return 0 unsuitable format, 1 format is suitable
*/
static int libdax_audioxtr_identify(struct libdax_audioxtr *o, int flag);
/** Specialized identifier for .wav */
static int libdax_audioxtr_identify_wav(struct libdax_audioxtr *o, int flag);
/** Specialized identifier for .au */
static int libdax_audioxtr_identify_au(struct libdax_audioxtr *o, int flag);
/** Convert a byte string into a number (currently only little endian)
@param flag Bitfield for control purposes
bit0=msb_first
@return The resulting number
*/
static unsigned libdax_audioxtr_to_int(struct libdax_audioxtr *o,
unsigned char *bytes, int len, int flag);
/** Prepare for reading of first buffer.
@return 0 error, 1 success
*/
static int libdax_audioxtr_init_reading(struct libdax_audioxtr *o, int flag);
#endif /* LIBDAX_AUDIOXTR_H_INTERNAL */
#endif /* ! LIBDAX_AUDIOXTR_H_INCLUDED */

View File

@ -1,404 +0,0 @@
/* libdax_msgs
Message handling facility of libdax.
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
*/
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/time.h>
/* Only this single source module is entitled to do this */
#define LIBDAX_MSGS_H_INTERNAL 1
/* All participants in the messaging system must do this */
#include "libdax_msgs.h"
/* ----------------------------- libdax_msgs_item ------------------------- */
static int libdax_msgs_item_new(struct libdax_msgs_item **item,
struct libdax_msgs_item *link, int flag)
{
int ret;
struct libdax_msgs_item *o;
struct timeval tv;
struct timezone tz;
(*item)= o=
(struct libdax_msgs_item *) malloc(sizeof(struct libdax_msgs_item));
if(o==NULL)
return(-1);
o->timestamp= 0.0;
ret= gettimeofday(&tv,&tz);
if(ret==0)
o->timestamp= tv.tv_sec+0.000001*tv.tv_usec;
o->process_id= getpid();
o->driveno= -1;
o->severity= LIBDAX_MSGS_SEV_ALL;
o->priority= LIBDAX_MSGS_PRIO_ZERO;
o->error_code= 0;
o->msg_text= NULL;
o->os_errno= 0;
o->prev= link;
o->next= NULL;
if(link!=NULL) {
if(link->next!=NULL) {
link->next->prev= o;
o->next= link->next;
}
link->next= o;
}
return(1);
}
/** Detaches item from its queue and eventually readjusts start, end pointers
of the queue */
int libdax_msgs_item_unlink(struct libdax_msgs_item *o,
struct libdax_msgs_item **chain_start,
struct libdax_msgs_item **chain_end, int flag)
{
if(o->prev!=NULL)
o->prev->next= o->next;
if(o->next!=NULL)
o->next->prev= o->prev;
if(chain_start!=NULL)
if(*chain_start == o)
*chain_start= o->next;
if(chain_end!=NULL)
if(*chain_end == o)
*chain_end= o->prev;
o->next= o->prev= NULL;
return(1);
}
int libdax_msgs_item_destroy(struct libdax_msgs_item **item,
int flag)
{
struct libdax_msgs_item *o;
o= *item;
if(o==NULL)
return(0);
libdax_msgs_item_unlink(o,NULL,NULL,0);
if(o->msg_text!=NULL)
free((char *) o->msg_text);
free((char *) o);
*item= NULL;
return(1);
}
int libdax_msgs_item_get_msg(struct libdax_msgs_item *item,
int *error_code, char **msg_text, int *os_errno,
int flag)
{
*error_code= item->error_code;
*msg_text= item->msg_text;
*os_errno= item->os_errno;
return(1);
}
int libdax_msgs_item_get_origin(struct libdax_msgs_item *item,
double *timestamp, pid_t *process_id, int *driveno,
int flag)
{
*timestamp= item->timestamp;
*process_id= item->process_id;
*driveno= item->driveno;
return(1);
}
int libdax_msgs_item_get_rank(struct libdax_msgs_item *item,
int *severity, int *priority, int flag)
{
*severity= item->severity;
*priority= item->priority;
return(1);
}
/* ------------------------------- libdax_msgs ---------------------------- */
int libdax_msgs_new(struct libdax_msgs **m, int flag)
{
struct libdax_msgs *o;
(*m)= o= (struct libdax_msgs *) malloc(sizeof(struct libdax_msgs));
if(o==NULL)
return(-1);
o->oldest= NULL;
o->youngest= NULL;
o->count= 0;
o->queue_severity= LIBDAX_MSGS_SEV_ALL;
o->print_severity= LIBDAX_MSGS_SEV_NEVER;
strcpy(o->print_id,"libdax: ");
#ifndef LIBDAX_MSGS_SINGLE_THREADED
pthread_mutex_init(&(o->lock_mutex),NULL);
#endif
return(1);
}
int libdax_msgs_destroy(struct libdax_msgs **m, int flag)
{
struct libdax_msgs *o;
struct libdax_msgs_item *item, *next_item;
o= *m;
if(o==NULL)
return(0);
#ifndef LIBDAX_MSGS_SINGLE_THREADED
if(pthread_mutex_destroy(&(o->lock_mutex))!=0) {
pthread_mutex_unlock(&(o->lock_mutex));
pthread_mutex_destroy(&(o->lock_mutex));
}
#endif
for(item= o->oldest; item!=NULL; item= next_item) {
next_item= item->next;
libdax_msgs_item_destroy(&item,0);
}
free((char *) o);
*m= NULL;
return(1);
}
int libdax_msgs_set_severities(struct libdax_msgs *m, int queue_severity,
int print_severity, char *print_id, int flag)
{
m->queue_severity= queue_severity;
m->print_severity= print_severity;
strncpy(m->print_id,print_id,80);
m->print_id[80]= 0;
return(1);
}
static int libdax_msgs_lock(struct libdax_msgs *m, int flag)
{
#ifndef LIBDAX_MSGS_SINGLE_THREADED
int ret;
ret= pthread_mutex_lock(&(m->lock_mutex));
if(ret!=0)
return(0);
#endif
return(1);
}
static int libdax_msgs_unlock(struct libdax_msgs *m, int flag)
{
#ifndef LIBDAX_MSGS_SINGLE_THREADED
int ret;
ret= pthread_mutex_unlock(&(m->lock_mutex));
if(ret!=0)
return(0);
#endif
return(1);
}
int libdax_msgs__text_to_sev(char *severity_name, int *severity,
int flag)
{
if(strncmp(severity_name,"NEVER",5)==0)
*severity= LIBDAX_MSGS_SEV_NEVER;
else if(strncmp(severity_name,"ABORT",5)==0)
*severity= LIBDAX_MSGS_SEV_ABORT;
else if(strncmp(severity_name,"FATAL",5)==0)
*severity= LIBDAX_MSGS_SEV_FATAL;
else if(strncmp(severity_name,"SORRY",5)==0)
*severity= LIBDAX_MSGS_SEV_SORRY;
else if(strncmp(severity_name,"WARNING",7)==0)
*severity= LIBDAX_MSGS_SEV_WARNING;
else if(strncmp(severity_name,"HINT",4)==0)
*severity= LIBDAX_MSGS_SEV_HINT;
else if(strncmp(severity_name,"NOTE",4)==0)
*severity= LIBDAX_MSGS_SEV_NOTE;
else if(strncmp(severity_name,"UPDATE",6)==0)
*severity= LIBDAX_MSGS_SEV_UPDATE;
else if(strncmp(severity_name,"DEBUG",5)==0)
*severity= LIBDAX_MSGS_SEV_DEBUG;
else if(strncmp(severity_name,"ALL",3)==0)
*severity= LIBDAX_MSGS_SEV_ALL;
else {
*severity= LIBDAX_MSGS_SEV_NEVER;
return(0);
}
return(1);
}
int libdax_msgs__sev_to_text(int severity, char **severity_name,
int flag)
{
if(flag&1) {
*severity_name=
"NEVER\nABORT\nFATAL\nSORRY\nWARNING\nHINT\nNOTE\nUPDATE\nDEBUG\nALL";
return(1);
}
*severity_name= "";
if(severity>=LIBDAX_MSGS_SEV_NEVER)
*severity_name= "NEVER";
else if(severity>=LIBDAX_MSGS_SEV_ABORT)
*severity_name= "ABORT";
else if(severity>=LIBDAX_MSGS_SEV_FATAL)
*severity_name= "FATAL";
else if(severity>=LIBDAX_MSGS_SEV_SORRY)
*severity_name= "SORRY";
else if(severity>=LIBDAX_MSGS_SEV_WARNING)
*severity_name= "WARNING";
else if(severity>=LIBDAX_MSGS_SEV_HINT)
*severity_name= "HINT";
else if(severity>=LIBDAX_MSGS_SEV_NOTE)
*severity_name= "NOTE";
else if(severity>=LIBDAX_MSGS_SEV_UPDATE)
*severity_name= "UPDATE";
else if(severity>=LIBDAX_MSGS_SEV_DEBUG)
*severity_name= "DEBUG";
else if(severity>=LIBDAX_MSGS_SEV_ALL)
*severity_name= "ALL";
else {
*severity_name= "";
return(0);
}
return(1);
}
int libdax_msgs_submit(struct libdax_msgs *m, int driveno, int error_code,
int severity, int priority, char *msg_text,
int os_errno, int flag)
{
int ret;
char *textpt,*sev_name,sev_text[81];
struct libdax_msgs_item *item= NULL;
if(severity >= m->print_severity) {
if(msg_text==NULL)
textpt= "";
else
textpt= msg_text;
sev_text[0]= 0;
ret= libdax_msgs__sev_to_text(severity,&sev_name,0);
if(ret>0)
sprintf(sev_text,"%s : ",sev_name);
fprintf(stderr,"%s%s%s\n",m->print_id,sev_text,textpt);
if(os_errno!=0) {
ret= libdax_msgs_lock(m,0);
if(ret<=0)
return(-1);
fprintf(stderr,"%s( Most recent system error: %d '%s' )\n",
m->print_id,os_errno,strerror(os_errno));
libdax_msgs_unlock(m,0);
}
}
if(severity < m->queue_severity)
return(0);
ret= libdax_msgs_lock(m,0);
if(ret<=0)
return(-1);
ret= libdax_msgs_item_new(&item,m->youngest,0);
if(ret<=0)
goto failed;
item->driveno= driveno;
item->error_code= error_code;
item->severity= severity;
item->priority= priority;
if(msg_text!=NULL) {
item->msg_text= malloc(strlen(msg_text)+1);
if(item->msg_text==NULL)
goto failed;
strcpy(item->msg_text,msg_text);
}
item->os_errno= os_errno;
if(m->oldest==NULL)
m->oldest= item;
m->youngest= item;
m->count++;
libdax_msgs_unlock(m,0);
/*
fprintf(stderr,"libdax_experimental: message submitted to queue (now %d)\n",
m->count);
*/
return(1);
failed:;
libdax_msgs_item_destroy(&item,0);
libdax_msgs_unlock(m,0);
return(-1);
}
int libdax_msgs_obtain(struct libdax_msgs *m, struct libdax_msgs_item **item,
int severity, int priority, int flag)
{
int ret;
struct libdax_msgs_item *im, *next_im= NULL;
*item= NULL;
ret= libdax_msgs_lock(m,0);
if(ret<=0)
return(-1);
for(im= m->oldest; im!=NULL; im= next_im) {
for(; im!=NULL; im= next_im) {
next_im= im->next;
if(im->severity>=severity)
break;
libdax_msgs_item_unlink(im,&(m->oldest),&(m->youngest),0);
libdax_msgs_item_destroy(&im,0); /* severity too low: delete */
}
if(im==NULL)
break;
if(im->priority>=priority)
break;
}
if(im==NULL)
{ret= 0; goto ex;}
libdax_msgs_item_unlink(im,&(m->oldest),&(m->youngest),0);
*item= im;
ret= 1;
ex:;
libdax_msgs_unlock(m,0);
return(ret);
}
int libdax_msgs_destroy_item(struct libdax_msgs *m,
struct libdax_msgs_item **item, int flag)
{
int ret;
ret= libdax_msgs_lock(m,0);
if(ret<=0)
return(-1);
ret= libdax_msgs_item_destroy(item,0);
libdax_msgs_unlock(m,0);
return(ret);
}

View File

@ -1,376 +0,0 @@
/* libdax_msgs
Message handling facility of libdax.
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
*/
/*
*Never* set this macro outside libdax_msgs.c !
The entrails of the message handling facility are not to be seen by
the other library components or the applications.
*/
#ifdef LIBDAX_MSGS_H_INTERNAL
#ifndef LIBDAX_MSGS_SINGLE_THREADED
#include <pthread.h>
#endif
struct libdax_msgs_item {
double timestamp;
pid_t process_id;
int driveno;
int severity;
int priority;
/* Apply for your developer's error code range at
libburn-hackers@pykix.org
Report introduced codes in the list below. */
int error_code;
char *msg_text;
int os_errno;
struct libdax_msgs_item *prev,*next;
};
struct libdax_msgs {
struct libdax_msgs_item *oldest;
struct libdax_msgs_item *youngest;
int count;
int queue_severity;
int print_severity;
char print_id[81];
#ifndef LIBDAX_MSGS_SINGLE_THREADED
pthread_mutex_t lock_mutex;
#endif
};
#endif /* LIBDAX_MSGS_H_INTERNAL */
#ifndef LIBDAX_MSGS_H_INCLUDED
#define LIBDAX_MSGS_H_INCLUDED 1
#ifndef LIBDAX_MSGS_H_INTERNAL
/* Public Opaque Handles */
/** A pointer to this is a opaque handle to a message handling facility */
struct libdax_msgs;
/** A pointer to this is a opaque handle to a single message item */
struct libdax_msgs_item;
#endif /* ! LIBDAX_MSGS_H_INTERNAL */
/* Public Macros */
/* Registered Severities */
/* It is well advisable to let applications select severities via strings and
forwarded functions libdax_msgs__text_to_sev(), libdax_msgs__sev_to_text().
These macros are for use by libdax/libburn only.
*/
/** Use this to get messages of any severity. Do not use for submitting.
*/
#define LIBDAX_MSGS_SEV_ALL 0x00000000
/** Debugging messages not to be visible to normal users by default
*/
#define LIBDAX_MSGS_SEV_DEBUG 0x10000000
/** Update of a progress report about long running actions
*/
#define LIBDAX_MSGS_SEV_UPDATE 0x20000000
/** Not so usual events which were gracefully handled
*/
#define LIBDAX_MSGS_SEV_NOTE 0x30000000
/** Possibilities to achieve a better result
*/
#define LIBDAX_MSGS_SEV_HINT 0x40000000
/** Warnings about problems which could not be handled optimally
*/
#define LIBDAX_MSGS_SEV_WARNING 0x50000000
/** Non-fatal error messages indicating that parts of the action failed
but processing will/should go on
*/
#define LIBDAX_MSGS_SEV_SORRY 0x60000000
/** An error message which puts the whole operation of libdax in question
*/
#define LIBDAX_MSGS_SEV_FATAL 0x70000000
/** A message from an abort handler which will finally finish libburn
*/
#define LIBDAX_MSGS_SEV_ABORT 0x71000000
/** A severity to exclude resp. discard any possible message.
Do not use this severity for submitting.
*/
#define LIBDAX_MSGS_SEV_NEVER 0x7fffffff
/* Registered Priorities */
/* Priorities are to be used by libburn/libdax only. */
#define LIBDAX_MSGS_PRIO_ZERO 0x00000000
#define LIBDAX_MSGS_PRIO_LOW 0x10000000
#define LIBDAX_MSGS_PRIO_MEDIUM 0x20000000
#define LIBDAX_MSGS_PRIO_HIGH 0x30000000
#define LIBDAX_MSGS_PRIO_TOP 0x7ffffffe
/* Do not use this priority for submitting */
#define LIBDAX_MSGS_PRIO_NEVER 0x7fffffff
/* Public Functions */
/* Calls initiated from inside libdax/libburn */
/** Create new empty message handling facility with queue.
@param flag Bitfield for control purposes (unused yet, submit 0)
@return >0 success, <=0 failure
*/
int libdax_msgs_new(struct libdax_msgs **m, int flag);
/** Destroy a message handling facility and all its eventual messages.
The submitted pointer gets set to NULL.
@param flag Bitfield for control purposes (unused yet, submit 0)
@return 1 for success, 0 for pointer to NULL
*/
int libdax_msgs_destroy(struct libdax_msgs **m, int flag);
/** Submit a message to a message handling facility.
@param driveno libdax drive number. Use -1 if no number is known.
@param error_code Unique error code. Use only registered codes. See below.
The same unique error_code may be issued at different
occasions but those should be equivalent out of the view
of a libdax application. (E.g. "cannot open ATA drive"
versus "cannot open SCSI drive" would be equivalent.)
@param severity The LIBDAX_MSGS_SEV_* of the event.
@param priority The LIBDAX_MSGS_PRIO_* number of the event.
@param msg_text Printable and human readable message text.
@param os_errno Eventual error code from operating system (0 if none)
@param flag Bitfield for control purposes (unused yet, submit 0)
@return 1 on success, 0 on rejection, <0 for severe errors
*/
int libdax_msgs_submit(struct libdax_msgs *m, int driveno, int error_code,
int severity, int priority, char *msg_text,
int os_errno, int flag);
/* Calls from applications (to be forwarded by libdax/libburn) */
/** Convert a registered severity number into a severity name
@param flag Bitfield for control purposes:
bit0= list all severity names in a newline separated string
@return >0 success, <=0 failure
*/
int libdax_msgs__sev_to_text(int severity, char **severity_name,
int flag);
/** Convert a severity name into a severity number,
@param flag Bitfield for control purposes (unused yet, submit 0)
@return >0 success, <=0 failure
*/
int libdax_msgs__text_to_sev(char *severity_name, int *severity,
int flag);
/** Set minimum severity for messages to be queued (default
LIBDAX_MSGS_SEV_ALL) and for messages to be printed directly to stderr
(default LIBDAX_MSGS_SEV_NEVER).
@param print_id A text of at most 80 characters to be printed before
any eventually printed message (default is "libdax: ").
@param flag Bitfield for control purposes (unused yet, submit 0)
@return always 1 for now
*/
int libdax_msgs_set_severities(struct libdax_msgs *m, int queue_severity,
int print_severity, char *print_id, int flag);
/** Obtain a message item that has at least the given severity and priority.
Usually all older messages of lower severity are discarded then. If no
item of sufficient severity was found, all others are discarded from the
queue.
@param flag Bitfield for control purposes (unused yet, submit 0)
@return 1 if a matching item was found, 0 if not, <0 for severe errors
*/
int libdax_msgs_obtain(struct libdax_msgs *m, struct libdax_msgs_item **item,
int severity, int priority, int flag);
/** Destroy a message item obtained by libdax_msgs_obtain(). The submitted
pointer gets set to NULL.
Caution: Copy eventually obtained msg_text before destroying the item,
if you want to use it further.
@param flag Bitfield for control purposes (unused yet, submit 0)
@return 1 for success, 0 for pointer to NULL, <0 for severe errors
*/
int libdax_msgs_destroy_item(struct libdax_msgs *m,
struct libdax_msgs_item **item, int flag);
/** Obtain from a message item the three application oriented components as
submitted with the originating call of libdax_msgs_submit().
Caution: msg_text becomes a pointer into item, not a copy.
@param flag Bitfield for control purposes (unused yet, submit 0)
@return 1 on success, 0 on invalid item, <0 for servere errors
*/
int libdax_msgs_item_get_msg(struct libdax_msgs_item *item,
int *error_code, char **msg_text, int *os_errno,
int flag);
/** Obtain from a message item the submitter identification submitted
with the originating call of libdax_msgs_submit().
@param flag Bitfield for control purposes (unused yet, submit 0)
@return 1 on success, 0 on invalid item, <0 for servere errors
*/
int libdax_msgs_item_get_origin(struct libdax_msgs_item *item,
double *timestamp, pid_t *process_id, int *driveno,
int flag);
/** Obtain from a message item severity and priority as submitted
with the originating call of libdax_msgs_submit().
@param flag Bitfield for control purposes (unused yet, submit 0)
@return 1 on success, 0 on invalid item, <0 for servere errors
*/
int libdax_msgs_item_get_rank(struct libdax_msgs_item *item,
int *severity, int *priority, int flag);
#ifdef LIDBAX_MSGS_________________
/* Registered Error Codes */
Format: error_code (LIBDAX_MSGS_SEV_*,LIBDAX_MSGS_PRIO_*) = explanation
If no severity or priority are fixely associates, use "(,)".
------------------------------------------------------------------------------
Range "libdax_msgs" : 0x00000000 to 0x0000ffff
0x00000000 (ALL,ZERO) = Initial setting in new libdax_msgs_item
0x00000001 (DEBUG,ZERO) = Test error message
0x00000002 (DEBUG,ZERO) = Debugging message
------------------------------------------------------------------------------
Range "elmom" : 0x00010000 to 0x0001ffff
------------------------------------------------------------------------------
Range "scdbackup" : 0x00020000 to 0x0002ffff
Acessing and defending drives:
0x00020001 (SORRY,LOW) = Cannot open busy device
0x00020002 (SORRY,HIGH) = Encountered error when closing drive
0x00020003 (SORRY,HIGH) = Could not grab drive
0x00020004 (NOTE,HIGH) = Opened O_EXCL scsi sibling
0x00020005 (FATAL,HIGH) = Failed to open device
0x00020006 (FATAL,HIGH) = Too many scsi siblings
0x00020007 (NOTE,HIGH) = Closed O_EXCL scsi siblings
From the hunt on Assert:
0x00020101 (WARNING,HIGH) = Cannot find given worker item
0x00020102 (SORRY,HIGH) = A drive operation is still going on
0x00020103 (WARNING,HIGH) = After scan a drive operation is still going on
0x00020104 (SORRY,HIGH) = NULL pointer caught
0x00020105 (SORRY,HIGH) = Drive is already released
0x00020106 (SORRY,HIGH) = Drive is busy on attempt to close
0x00020107 (SORRY,HIGH) = Drive is busy on attempt to shut down library
0x00020108 (SORRY,HIGH) = Drive is not grabbed on disc status inquiry
0x00020108 (FATAL,HIGH) = Could not allocate new drive object
0x00020109 (FATAL,HIGH) = Library not running
0x0002010a (FATAL,HIGH) = Unsuitable track mode
0x0002010b (FATAL,HIGH) = Burn run failed
0x0002010c (FATAL,HIGH) = Failed to transfer command to drive
0x0002010d (DEBUG,HIGH) = Could not inquire TOC
0x0002010e (FATAL,HIGH) = Attempt to read ATIP from ungrabbed drive
0x0002010f
0x00020110 (FATAL,HIGH) = Persistent drive address too long
0x00020111 (FATAL,HIGH) = Could not allocate new auxiliary object
0x00020112 (SORRY,HIGH) = Bad combination of write_type and block_type
0x00020113 (FATAL,HIGH) = Drive capabilities not inquired yet
0x00020114 (SORRY,HIGH) = Attempt to set ISRC with bad data
0x00020115 (SORRY,HIGH) = Attempt to set track mode to unusable value
0x00020116 (FATAL,HIGH) = Track mode has unusable value
0x00020117 (FATAL,HIGH) = toc_entry of drive is already in use
libdax_audioxtr:
0x00020200 (SORRY,HIGH) = Cannot open audio source file
0x00020201 (SORRY,HIGH) = Audio source file has unsuitable format
0x00020202 (SORRY,HIGH) = Failed to prepare reading of audio data
------------------------------------------------------------------------------
#endif /* LIDBAX_MSGS_________________ */
#ifdef LIBDAX_MSGS_H_INTERNAL
/* Internal Functions */
/** Lock before doing side effect operations on m */
static int libdax_msgs_lock(struct libdax_msgs *m, int flag);
/** Unlock after effect operations on m are done */
static int libdax_msgs_unlock(struct libdax_msgs *m, int flag);
/** Create new empty message item.
@param link Previous item in queue
@param flag Bitfield for control purposes (unused yet, submit 0)
@return >0 success, <=0 failure
*/
static int libdax_msgs_item_new(struct libdax_msgs_item **item,
struct libdax_msgs_item *link, int flag);
/** Destroy a message item obtained by libdax_msgs_obtain(). The submitted
pointer gets set to NULL.
@param flag Bitfield for control purposes (unused yet, submit 0)
@return 1 for success, 0 for pointer to NULL
*/
static int libdax_msgs_item_destroy(struct libdax_msgs_item **item, int flag);
#endif /* LIBDAX_MSGS_H_INTERNAL */
#endif /* ! LIBDAX_MSGS_H_INCLUDED */

108
libburn/message.c Normal file
View File

@ -0,0 +1,108 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
#include "message.h"
#include "libburn.h"
#include "debug.h"
#include <stdlib.h>
struct message_list
{
struct message_list *next;
struct burn_message *msg;
};
static struct message_list *queue;
void burn_message_free(struct burn_message *msg)
{
free(msg);
}
void burn_message_clear_queue(void)
{
struct burn_message *msg;
if ((msg = burn_get_message())) {
burn_print(0,
"YOU HAVE MESSAGES QUEUED FROM THE LAST OPERATION. "
"YOU SHOULD BE GRABBING THEM ALL!\n");
do {
burn_message_free(msg);
} while ((msg = burn_get_message()));
}
}
struct burn_message *burn_get_message()
{
struct burn_message *msg = NULL;
if (queue) {
struct message_list *next;
next = queue->next;
msg = queue->msg;
free(queue);
queue = next;
}
return msg;
}
static void queue_push_tail(struct burn_message *msg)
{
struct message_list *node;
node = malloc(sizeof(struct message_list));
node->next = NULL;
node->msg = msg;
if (!queue)
queue = node;
else {
struct message_list *it;
for (it = queue; it->next; it = it->next) ;
it->next = node;
}
}
void burn_message_info_new(struct burn_drive *drive,
enum burn_message_info message)
{
struct burn_message *msg;
msg = malloc(sizeof(struct burn_message));
msg->drive = drive;
msg->type = BURN_MESSAGE_INFO;
msg->detail.info.message = message;
queue_push_tail(msg);
}
void burn_message_warning_new(struct burn_drive *drive,
enum burn_message_info message)
{
struct burn_message *msg;
msg = malloc(sizeof(struct burn_message));
msg->drive = drive;
msg->type = BURN_MESSAGE_WARNING;
msg->detail.warning.message = message;
queue_push_tail(msg);
}
void burn_message_error_new(struct burn_drive *drive,
enum burn_message_info message)
{
struct burn_message *msg;
msg = malloc(sizeof(struct burn_message));
msg->drive = drive;
msg->type = BURN_MESSAGE_ERROR;
msg->detail.error.message = message;
queue_push_tail(msg);
}

19
libburn/message.h Normal file
View File

@ -0,0 +1,19 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
#ifndef __MESSAGE
#define __MESSAGE
#include "libburn.h"
void burn_message_clear_queue(void);
void burn_message_info_new(struct burn_drive *drive,
enum burn_message_info message);
void burn_message_warning_new(struct burn_drive *drive,
enum burn_message_info message);
void burn_message_error_new(struct burn_drive *drive,
enum burn_message_info message);
#endif

View File

@ -1,8 +1,6 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* ts A61009 */
/* #include <a ssert.h> */
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
@ -20,12 +18,6 @@
#include "structure.h"
#include "options.h"
/* ts A61005 */
#include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger;
static unsigned char MMC_GET_TOC[] = { 0x43, 2, 2, 0, 0, 0, 0, 16, 0, 0 };
static unsigned char MMC_GET_ATIP[] = { 0x43, 2, 4, 0, 0, 0, 0, 16, 0, 0 };
static unsigned char MMC_GET_DISC_INFO[] =
@ -47,9 +39,6 @@ static unsigned char MMC_TRACK_INFO[] = { 0x52, 0, 0, 0, 0, 0, 0, 16, 0, 0 };
static unsigned char MMC_SEND_CUE_SHEET[] =
{ 0x5D, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
/* ts A61023 : get size and free space of drive buffer */
static unsigned char MMC_READ_BUFFER_CAPACITY[] = { 0x5C, 0, 0, 0, 0, 0, 0, 16, 0, 0 };
static int mmc_function_spy_do_tell = 0;
@ -110,43 +99,19 @@ int mmc_get_nwa(struct burn_drive *d)
+ (data[14] << 8) + data[15];
}
/* ts A61009 : function is obviously unused. */
/* void mmc_close_disc(struct burn_drive *d, struct burn_write_opts *o) */
void mmc_close_disc(struct burn_write_opts *o)
void mmc_close_disc(struct burn_drive *d, struct burn_write_opts *o)
{
struct burn_drive *d;
mmc_function_spy("mmc_close_disc");
libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
"HOW THAT ? mmc_close_disc() was called", 0, 0);
/* ts A61009 : made impossible by removing redundant parameter d */
/* a ssert(o->drive == d); */
d = o->drive;
assert(o->drive == d);
o->multi = 0;
spc_select_write_params(d, o);
mmc_close(d, 1, 0);
}
/* ts A61009 : function is obviously unused. */
/* void mmc_close_session(struct burn_drive *d, struct burn_write_opts *o) */
void mmc_close_session(struct burn_write_opts *o)
void mmc_close_session(struct burn_drive *d, struct burn_write_opts *o)
{
struct burn_drive *d;
mmc_function_spy("mmc_close_session");
libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
"HOW THAT ? mmc_close_session() was called", 0, 0);
/* ts A61009 : made impossible by removing redundant parameter d */
/* a ssert(o->drive == d); */
d = o->drive;
assert(o->drive == d);
o->multi = 3;
spc_select_write_params(d, o);
mmc_close(d, 1, 0);
@ -156,12 +121,7 @@ void mmc_close(struct burn_drive *d, int session, int track)
{
struct command c;
mmc_function_spy("mmc_close");
libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
"HOW THAT ? mmc_close() was called", 0, 0);
mmc_function_spy("mmc_close_session");
c.retry = 1;
c.oplen = sizeof(MMC_CLOSE);
memcpy(c.opcode, MMC_CLOSE, sizeof(MMC_CLOSE));
@ -194,7 +154,6 @@ void mmc_get_event(struct burn_drive *d)
c.page->data[5], c.page->data[6], c.page->data[7]);
}
void mmc_write_12(struct burn_drive *d, int start, struct buffer *buf)
{
struct command c;
@ -202,10 +161,7 @@ void mmc_write_12(struct burn_drive *d, int start, struct buffer *buf)
mmc_function_spy("mmc_write_12");
len = buf->sectors;
/* ts A61009 */
/* a ssert(buf->bytes >= buf->sectors);*/ /* can be == at 0... */
assert(buf->bytes >= buf->sectors); /* can be == at 0... */
burn_print(100, "trying to write %d at %d\n", len, start);
memcpy(c.opcode, MMC_WRITE_12, sizeof(MMC_WRITE_12));
c.retry = 1;
@ -239,10 +195,7 @@ int mmc_write(struct burn_drive *d, int start, struct buffer *buf)
return BE_CANCELLED;
len = buf->sectors;
/* ts A61009 : buffer fill problems are to be handled by caller */
/* a ssert(buf->bytes >= buf->sectors);*/ /* can be == at 0... */
assert(buf->bytes >= buf->sectors); /* can be == at 0... */
burn_print(100, "trying to write %d at %d\n", len, start);
memcpy(c.opcode, MMC_WRITE_10, sizeof(MMC_WRITE_10));
c.retry = 1;
@ -275,7 +228,7 @@ void mmc_read_toc(struct burn_drive *d)
struct buffer buf;
struct command c;
int dlen;
int i, bpl= 12;
int i;
unsigned char *tdata;
mmc_function_spy("mmc_read_toc");
@ -289,23 +242,7 @@ void mmc_read_toc(struct burn_drive *d)
d->issue_command(d, &c);
if (c.error) {
/* ts A61020 : this snaps on non-blank DVD media */
/* Very unsure wether this old measure is ok.
Obviously higher levels do not care about this.
DVD+RW burns go on after passing through here.
d->busy = BURN_DRIVE_IDLE;
*/
libdax_msgs_submit(libdax_messenger, d->global_index,
0x0002010d,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
"Could not inquire TOC (non-blank DVD media ?)", 0,0);
d->status = BURN_DISC_UNSUITABLE;
d->toc_entries = 0;
/* Prefering memory leaks over fandangos */
d->toc_entry = malloc(sizeof(struct burn_toc_entry));
return;
}
@ -314,8 +251,7 @@ void mmc_read_toc(struct burn_drive *d)
/*
some drives fail this check.
ts A61007 : if re-enabled then not via Assert.
a ssert(((dlen - 2) % 11) == 0);
assert(((dlen - 2) % 11) == 0);
*/
d->toc_entry = malloc(d->toc_entries * sizeof(struct burn_toc_entry));
tdata = c.page->data + 4;
@ -329,27 +265,14 @@ void mmc_read_toc(struct burn_drive *d)
burn_disc_add_session(d->disc, session, BURN_POS_END);
burn_session_free(session);
}
/* ts A61022 */
burn_print(bpl, "-----------------------------------\n");
for (i = 0; i < d->toc_entries; i++, tdata += 11) {
/* ts A61022: was burn_print level 12 */
burn_print(bpl, "S %d, PT %2.2Xh, TNO %d :", tdata[0],tdata[3],
burn_print(12, "S %d, PT %d, TNO %d : ", tdata[0], tdata[3],
tdata[2]);
burn_print(bpl, " MSF(%d:%d:%d)", tdata[4],tdata[5],tdata[6]);
burn_print(bpl, " PMSF(%d:%d:%d %d)",
tdata[8], tdata[9], tdata[10],
burn_msf_to_lba(tdata[8], tdata[9], tdata[10])
);
burn_print(bpl, " - control %d, adr %d\n", tdata[1] & 0xF,
burn_print(12, "(%d:%d:%d)", tdata[8], tdata[9], tdata[10]);
burn_print(12, "A(%d:%d:%d)", tdata[4], tdata[5], tdata[6]);
burn_print(12, " - control %d, adr %d\n", tdata[1] & 0xF,
tdata[1] >> 4);
/*
fprintf(stderr, "libburn_experimental: toc entry #%d : %d %d %d\n",i,tdata[8], tdata[9], tdata[10]);
*/
if (tdata[3] == 1) {
if (burn_msf_to_lba(tdata[8], tdata[9], tdata[10])) {
d->disc->session[0]->hidefirst = 1;
@ -388,10 +311,6 @@ void mmc_read_toc(struct burn_drive *d)
d->disc->session[tdata[0] - 1]->leadout_entry =
&d->toc_entry[i];
}
/* ts A61022 */
burn_print(bpl, "-----------------------------------\n");
if (d->status != BURN_DISC_APPENDABLE)
d->status = BURN_DISC_FULL;
toc_find_modes(d);
@ -420,26 +339,11 @@ void mmc_read_disc_info(struct burn_drive *d)
data = c.page->data;
d->erasable = !!(data[2] & 16);
/* ts A61020 */
d->start_lba = d->end_lba = -2000000000;
/*
fprintf(stderr, "libburn_experimental: data[2]= %d 0x%x\n",
(unsigned) data[2], (unsigned) data[2]);
*/
switch (data[2] & 3) {
case 0:
d->toc_entries = 0;
d->start_lba = burn_msf_to_lba(data[17], data[18], data[19]);
d->end_lba = burn_msf_to_lba(data[21], data[22], data[23]);
/*
fprintf(stderr, "libburn_experimental: start_lba = %d (%d %d %d) , end_lba = %d (%d %d %d)\n",
d->start_lba, data[17], data[18], data[19],
d->end_lba, data[21], data[22], data[23]);
*/
d->status = BURN_DISC_BLANK;
break;
case 1:
@ -455,17 +359,6 @@ void mmc_read_atip(struct burn_drive *d)
struct buffer buf;
struct command c;
/* ts A61021 */
unsigned char *data;
/* Speed values from A1:
With 4 cdrecord tells "10" or "8" where MMC-1 says "8".
cdrecord "8" appear on 4xCD-RW and thus seem to be quite invalid.
My CD-R (>=24 speed) tell no A1.
The higher non-MMC-1 values are hearsay.
*/
static int speed_value[16]= { 0, 2, 4, 6, 10, -5, 16, -7,
24, 32, 40, 48, -12, -13, -14, -15};
mmc_function_spy("mmc_read_atip");
memcpy(c.opcode, MMC_GET_ATIP, sizeof(MMC_GET_ATIP));
c.retry = 1;
@ -477,125 +370,6 @@ void mmc_read_atip(struct burn_drive *d)
c.dir = FROM_DRIVE;
d->issue_command(d, &c);
burn_print(1, "atip shit for you\n");
/* ts A61021 */
data = c.page->data;
d->erasable= !!(data[6]&64);
d->start_lba= burn_msf_to_lba(data[8],data[9],data[10]);
d->end_lba= burn_msf_to_lba(data[12],data[13],data[14]);
if (data[6]&4) {
if (speed_value[(data[16]>>4)&7] > 0)
d->mdata->min_write_speed =
speed_value[(data[16]>>4)&7]*176;
if (speed_value[(data[16])&15] > 0)
d->mdata->max_write_speed =
speed_value[(data[16])&15]*176;
}
#ifdef Burn_mmc_be_verbous_about_atiP
{ int i;
fprintf(stderr,"libburn_experimental: Returned ATIP Data\n");
for(i= 0; i<28; i++)
fprintf(stderr,"%3.3d (0x%2.2x)%s",
data[i],data[i],((i+1)%5 ? " ":"\n"));
fprintf(stderr,"\n");
fprintf(stderr,
"libburn_experimental: Indicative Target Writing Power= %d\n",
(data[4]>>4)&7);
fprintf(stderr,
"libburn_experimental: Reference speed= %d ->%d\n",
data[4]&7, speed_value[data[4]&7]);
fprintf(stderr,
"libburn_experimental: Is %sunrestricted\n",
(data[5]&64?"":"not "));
fprintf(stderr,
"libburn_experimental: Is %serasable, sub-type %d\n",
(data[6]&64?"":"not "),(data[6]>>3)&3);
fprintf(stderr,
"libburn_experimental: lead in: %d (%-2.2d:%-2.2d/%-2.2d)\n",
burn_msf_to_lba(data[8],data[9],data[10]),
data[8],data[9],data[10]);
fprintf(stderr,
"libburn_experimental: lead out: %d (%-2.2d:%-2.2d/%-2.2d)\n",
burn_msf_to_lba(data[12],data[13],data[14]),
data[12],data[13],data[14]);
if(data[6]&4)
fprintf(stderr,
"libburn_experimental: A1 speed low %d speed high %d\n",
speed_value[(data[16]>>4)&7], speed_value[(data[16])&7]);
if(data[6]&2)
fprintf(stderr,
"libburn_experimental: A2 speed low %d speed high %d\n",
speed_value[(data[20]>>4)&7], speed_value[(data[20])&7]);
if(data[6]&1)
fprintf(stderr,
"libburn_experimental: A3 speed low %d speed high %d\n",
speed_value[(data[24]>>4)&7], speed_value[(data[24])&7]);
}
#endif /* Burn_mmc_be_verbous_about_atiP */
/* ts A61020
http://www.t10.org/ftp/t10/drafts/mmc/mmc-r10a.pdf , table 77 :
0 ATIP Data Length MSB
1 ATIP Data Length LSB
2 Reserved
3 Reserved
4 bit7=1, bit4-6="Indicative Target Writing Power", bit3=reserved ,
bit0-2="Reference speed"
5 bit7=0, bit6="URU" , bit0-5=reserved
6 bit7=1, bit6="Disc Type", bit3-4="Disc Sub-Type",
bit2="A1", bit1="A2", bit0="A3"
7 reserved
8 ATIP Start Time of lead-in (Min)
9 ATIP Start Time of lead-in (Sec)
10 ATIP Start Time of lead-in (Frame)
11 reserved
12 ATIP Last Possible Start Time of lead-out (Min)
13 ATIP Last Possible Start Time of lead-out (Sec)
14 ATIP Last Possible Start Time of lead-out (Frame)
15 reserved
16 bit7=0, bit4-6="Lowest Usable CLV Recording speed"
bit0-3="Highest Usable CLV Recording speed"
17 bit7=0, bit4-6="Power Multiplication Factor p",
bit1-3="Target y value of the Modulation/Power function", bit0=reserved
18 bit7=1, bit4-6="Recommended Erase/Write Power Ratio (P(inf)/W(inf))"
bit0-3=reserved
19 reserved
20-22 A2 Values
23 reserved
24-26 A3 Values
27 reserved
Disc Type - zero indicates CD-R media; one indicates CD-RW media.
Disc Sub-Type - shall be set to zero.
A1 - when set to one, indicates that bytes 16-18 are valid.
Lowest Usable CLV Recording Speed
000b Reserved
001b 2X
010b - 111b Reserved
Highest CLV Recording Speeds
000b Reserved
001b 2X
010b 4X
011b 6X
100b 8X
101b - 111b Reserved
MMC-3 seems to recommend MODE SENSE (5Ah) page 2Ah rather than A1, A2, A3.
This page is loaded in libburn function spc_sense_caps() .
Speed is given in kbytes/sec there. But i suspect this to be independent
of media. So one would habe to associate the speed descriptor blocks with
the ATIP media characteristics ? How ?
*/
}
void mmc_read_sectors(struct burn_drive *d,
@ -608,14 +382,9 @@ void mmc_read_sectors(struct burn_drive *d,
struct command c;
mmc_function_spy("mmc_read_sectors");
/* ts A61009 : to be ensured by callers */
/* a ssert(len >= 0); */
/* if the drive isn't busy, why the hell are we here? */
/* ts A61006 : i second that question */
/* a ssert(d->busy); */
assert(len >= 0);
/* if the drive isn't busy, why the hell are we here? */
assert(d->busy);
burn_print(12, "reading %d from %d\n", len, start);
memcpy(c.opcode, MMC_READ_CD, sizeof(MMC_READ_CD));
c.retry = 1;
@ -773,63 +542,3 @@ void mmc_sync_cache(struct burn_drive *d)
c.dir = NO_TRANSFER;
d->issue_command(d, &c);
}
/* ts A61023 : http://libburn.pykix.org/ticket/14
get size and free space of drive buffer
*/
int mmc_read_buffer_capacity(struct burn_drive *d)
{
struct buffer buf;
struct command c;
unsigned char *data;
mmc_function_spy("mmc_read_buffer_capacity");
memcpy(c.opcode, MMC_READ_BUFFER_CAPACITY,
sizeof(MMC_READ_BUFFER_CAPACITY));
c.retry = 1;
c.oplen = sizeof(MMC_READ_BUFFER_CAPACITY);
c.page = &buf;
c.page->bytes = 0;
c.page->sectors = 0;
c.dir = FROM_DRIVE;
d->issue_command(d, &c);
/* >>> ??? error diagnostics */
data = c.page->data;
d->progress.buffer_capacity =
(data[4]<<24)|(data[5]<<16)|(data[6]<<8)|data[7];
d->progress.buffer_available =
(data[8]<<24)|(data[9]<<16)|(data[10]<<8)|data[11];
return 1;
}
/* ts A61021 : the mmc specific part of sg.c:enumerate_common()
*/
int mmc_setup_drive(struct burn_drive *d)
{
d->read_atip = mmc_read_atip;
d->read_toc = mmc_read_toc;
d->write = mmc_write;
d->erase = mmc_erase;
d->read_sectors = mmc_read_sectors;
d->perform_opc = mmc_perform_opc;
d->set_speed = mmc_set_speed;
d->send_cue_sheet = mmc_send_cue_sheet;
d->sync_cache = mmc_sync_cache;
d->get_nwa = mmc_get_nwa;
d->close_disc = mmc_close_disc;
d->close_session = mmc_close_session;
d->read_buffer_capacity = mmc_read_buffer_capacity;
/* ts A61020 */
d->start_lba= -2000000000;
d->end_lba= -2000000000;
return 1;
}

View File

@ -12,13 +12,8 @@ struct cue_sheet;
/* MMC commands */
void mmc_read(struct burn_drive *);
/* ts A61009 : removed redundant parameter d in favor of o->drive */
/* void mmc_close_session(struct burn_drive *, struct burn_write_opts *); */
/* void mmc_close_disc(struct burn_drive *, struct burn_write_opts *); */
void mmc_close_session(struct burn_write_opts *o);
void mmc_close_disc(struct burn_write_opts *o);
void mmc_close_session(struct burn_drive *, struct burn_write_opts *);
void mmc_close_disc(struct burn_drive *, struct burn_write_opts *);
void mmc_close(struct burn_drive *, int session, int track);
void mmc_get_event(struct burn_drive *);
int mmc_write(struct burn_drive *, int start, struct buffer *buf);
@ -39,12 +34,4 @@ void mmc_perform_opc(struct burn_drive *);
void mmc_get_configuration(struct burn_drive *);
int mmc_get_nwa(struct burn_drive *);
void mmc_send_cue_sheet(struct burn_drive *, struct cue_sheet *);
/* ts A61023 : get size and free space of drive buffer */
int mmc_read_buffer_capacity(struct burn_drive *d);
/* ts A61021 : the mmc specific part of sg.c:enumerate_common()
*/
int mmc_setup_drive(struct burn_drive *d);
#endif /*__MMC*/

View File

@ -2,27 +2,14 @@
#include "options.h"
#include "transport.h"
/* ts A61007 */
/* #include <a ssert.h> */
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger;
struct burn_write_opts *burn_write_opts_new(struct burn_drive *drive)
{
struct burn_write_opts *opts;
opts = malloc(sizeof(struct burn_write_opts));
if (opts == NULL) {
libdax_msgs_submit(libdax_messenger, -1, 0x00020111,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Could not allocate new auxiliary object", 0, 0);
return NULL;
}
opts->drive = drive;
opts->refcount = 1;
opts->write_type = BURN_WRITE_TAO;
@ -74,32 +61,14 @@ int burn_write_opts_set_write_type(struct burn_write_opts *opts,
enum burn_write_types write_type,
int block_type)
{
int sector_get_outmode(enum burn_write_types write_type,
enum burn_block_types block_type);
int spc_block_type(enum burn_block_types b);
/* ts A61007 */
if (! ( (write_type == BURN_WRITE_SAO && block_type == BURN_BLOCK_SAO)
|| (opts->drive->block_types[write_type] & block_type) ) ) {
bad_combination:;
libdax_msgs_submit(libdax_messenger, -1, 0x00020112,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Bad combination of write_type and block_type", 0, 0);
return 0;
if ((write_type == BURN_WRITE_SAO && block_type == BURN_BLOCK_SAO) ||
(opts->drive->block_types[write_type] & block_type)) {
opts->write_type = write_type;
opts->block_type = block_type;
return 1;
}
/* ts A61007 : obsoleting Assert in sector.c:get_outmode() */
if (sector_get_outmode(write_type, (enum burn_block_types) block_type)
== -1)
goto bad_combination;
/* ts A61007 : obsoleting Assert in spc.c:spc_block_type() */
if (spc_block_type((enum burn_block_types) block_type) == -1)
goto bad_combination;
opts->write_type = write_type;
opts->block_type = block_type;
return 1;
/* a ssert(0); */
assert(0);
return 0;
}
void burn_write_opts_set_toc_entries(struct burn_write_opts *opts, int count,

View File

@ -1,14 +1,9 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* #include <m alloc.h> ts A61013 : not in Linux man 3 malloc */
#include <stdlib.h>
#include <malloc.h>
#include <unistd.h>
#include <signal.h>
/* ts A61007 */
/* #include <a ssert.h> */
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
@ -16,11 +11,7 @@
#include "libburn.h"
#include "drive.h"
#include "transport.h"
/* ts A60925 : obsoleted by libdax_msgs.h
#include "message.h"
*/
#include "crc.h"
#include "debug.h"
#include "init.h"
@ -42,16 +33,11 @@ void burn_disc_read(struct burn_drive *d, const struct burn_read_opts *o)
struct buffer page;
int speed;
/* ts A61007 : if this function gets revived, then these
tests have to be done more graceful */
a ssert((o->version & 0xfffff000) == (OPTIONS_VERSION & 0xfffff000));
a ssert(!d->busy);
a ssert(d->toc->valid);
a ssert(o->datafd != -1);
/* moved up from spc_select_error_params alias d->send_parameters() */
a ssert(d->mdata->valid);
assert((o->version & 0xfffff000) == (OPTIONS_VERSION & 0xfffff000));
assert(!d->busy);
assert(d->toc->valid);
assert(o->datafd != -1);
/* XXX not sure this is a good idea. copy it? */
/* XXX also, we have duplicated data now, do we remove the fds from struct
drive, or only store a subset of the _opts structs in drives */
@ -61,7 +47,6 @@ drive, or only store a subset of the _opts structs in drives */
d->set_speed(d, speed, 0);
d->params.retries = o->hardware_error_retries;
d->send_parameters(d, o);
d->cancel = 0;
@ -139,10 +124,7 @@ drive, or only store a subset of the _opts structs in drives */
page.sectors = (finish < maxsects) ? finish : maxsects;
printf("reading %d sectors from %d\n", page.sectors,
drive_lba);
/* >>> ts A61009 : ensure page.sectors >= 0 before calling */
d->r ead_sectors(d, drive_lba, page.sectors, o, &page);
d->read_sectors(d, drive_lba, page.sectors, o, &page);
printf("Read %d\n", page.sectors);
}
#endif

View File

@ -2,7 +2,9 @@
/* scsi block commands */
#include <scsi/scsi.h>
#include <string.h>
#include <scsi/sg.h>
#include "transport.h"
#include "sbc.h"
@ -36,13 +38,3 @@ void sbc_eject(struct burn_drive *d)
c.dir = NO_TRANSFER;
d->issue_command(d, &c);
}
/* ts A61021 : the sbc specific part of sg.c:enumerate_common()
*/
int sbc_setup_drive(struct burn_drive *d)
{
d->eject = sbc_eject;
d->load = sbc_load;
return 1;
}

View File

@ -8,8 +8,4 @@ struct burn_drive;
void sbc_load(struct burn_drive *);
void sbc_eject(struct burn_drive *);
/* ts A61021 : the sbc specific part of sg.c:enumerate_common()
*/
int sbc_setup_drive(struct burn_drive *d);
#endif /* __SBC */

View File

@ -1,10 +1,7 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
#include <stdio.h>
/* ts A61010 */
/* #include <a ssert.h> */
#include <assert.h>
#include <unistd.h>
#include <string.h>
#include "error.h"
@ -40,14 +37,13 @@ static void uncook_subs(unsigned char *dest, unsigned char *source)
}
}
/* @return >=0 : valid , <0 invalid */
int sector_get_outmode(enum burn_write_types write_type,
enum burn_block_types block_type)
/* 0 means "same as inmode" */
static int get_outmode(struct burn_write_opts *o)
{
if (write_type == BURN_WRITE_SAO)
if (o->write_type == BURN_WRITE_SAO)
return 0;
else
switch (block_type) {
switch (o->block_type) {
case BURN_BLOCK_RAW0:
return BURN_MODE_RAW;
case BURN_BLOCK_RAW16:
@ -58,28 +54,13 @@ int sector_get_outmode(enum burn_write_types write_type,
return BURN_MODE_RAW | BURN_SUBCODE_R96;
case BURN_BLOCK_MODE1:
return BURN_MODE1;
default:
return -1;
}
/* ts A61007 : now handled in burn_write_opts_set_write_type() */
/* a ssert(0); */ /* return BURN_MODE_UNIMPLEMENTED :) */
assert(0); /* return BURN_MODE_UNIMPLEMENTED :) */
}
/* 0 means "same as inmode" */
static int get_outmode(struct burn_write_opts *o)
{
/* ts A61007 */
return sector_get_outmode(o->write_type, o->block_type);
/* -1 is prevented by check in burn_write_opts_set_write_type() */
/* a ssert(0); */ /* return BURN_MODE_UNIMPLEMENTED :) */
}
static void get_bytes(struct burn_track *track, int count, unsigned char *data)
{
int valid, shortage, curr, i, tr;
int valid, shortage, curr;
/* no track pointer means we're just generating 0s */
if (!track) {
@ -99,7 +80,7 @@ static void get_bytes(struct burn_track *track, int count, unsigned char *data)
shortage = count - valid;
if (!shortage)
goto ex;
return;
/* Next we use source data */
curr = valid;
@ -116,7 +97,7 @@ static void get_bytes(struct burn_track *track, int count, unsigned char *data)
shortage = count - curr;
if (!shortage)
goto ex;
return;
/* Before going to the next track, we run through any tail */
@ -132,7 +113,7 @@ static void get_bytes(struct burn_track *track, int count, unsigned char *data)
shortage -= valid;
if (!shortage)
goto ex;
return;
/* If we're still short, and there's a "next" pointer, we pull from that.
if that depletes, we'll just fill with 0s.
@ -147,30 +128,10 @@ static void get_bytes(struct burn_track *track, int count, unsigned char *data)
curr += valid;
}
}
ex:;
/* ts A61024 : general finalizing processing */
if(shortage)
memset(data + curr, 0, shortage); /* this is old icculus.org */
if (track->swap_source_bytes == 1) {
/*
{ static int swapping_count= 0;
fprintf(stderr,"\rlibburn_debug: swapping #%d \r",
swapping_count);
swapping_count++;
if (!shortage)
return;
memset(data + curr, 0, shortage);
}
*/
for (i = 1; i < count; i += 2) {
tr = data[i];
data[i] = data[i-1];
data[i-1] = tr;
}
}
}
/* ts A61009 : seems to hand out sector start pointer in opts->drive->buffer
and to count hand outs as well as reserved bytes */
static unsigned char *get_sector(struct burn_write_opts *opts, int inmode)
{
struct burn_drive *d = opts->drive;
@ -183,13 +144,7 @@ static unsigned char *get_sector(struct burn_write_opts *opts, int inmode)
if (outmode == 0)
outmode = inmode;
/* ts A61009 : react on eventual failure of burn_sector_length()
(should not happen if API tested properly).
Ensures out->bytes >= out->sectors */
seclen = burn_sector_length(outmode);
if (seclen <= 0)
return NULL;
seclen += burn_subcode_length(outmode);
seclen = burn_sector_length(outmode) + burn_subcode_length(outmode);
if (out->bytes + (seclen) >= BUFFER_SIZE) {
int err;
@ -209,9 +164,7 @@ static unsigned char *get_sector(struct burn_write_opts *opts, int inmode)
}
/* either inmode == outmode, or outmode == raw. anything else is bad news */
/* ts A61010 : changed type to int in order to propagate said bad news */
/** @return 1 is ok, <= 0 is failure */
static int convert_data(struct burn_write_opts *o, struct burn_track *track,
static void convert_data(struct burn_write_opts *o, struct burn_track *track,
int inmode, unsigned char *data)
{
int outlen, inlen;
@ -224,21 +177,14 @@ static int convert_data(struct burn_write_opts *o, struct burn_track *track,
outlen = burn_sector_length(outmode);
inlen = burn_sector_length(inmode);
/* ts A61010 */
/* a ssert(outlen >= inlen); */
if (outlen < inlen)
return 0;
assert(outlen >= inlen);
if ((outmode & BURN_MODE_BITS) == (inmode & BURN_MODE_BITS)) {
get_bytes(track, inlen, data);
return 1;
return;
}
/* ts A61010 */
/* a ssert(outmode & BURN_MODE_RAW); */
if (!(outmode & BURN_MODE_RAW))
return 0;
assert(outmode & BURN_MODE_RAW);
if (inmode & BURN_MODE1)
offset = 16;
@ -246,16 +192,9 @@ static int convert_data(struct burn_write_opts *o, struct burn_track *track,
offset = 0;
if (inmode & BURN_AUDIO)
offset = 0;
/* ts A61010 */
/* a ssert(offset != -1); */
if (offset == -1)
return 0;
assert(offset != -1);
get_bytes(track, inlen, data + offset);
return 1;
}
static void convert_subs(struct burn_write_opts *o, int inmode,
unsigned char *subs, unsigned char *sector)
{
@ -336,11 +275,9 @@ int sector_toc(struct burn_write_opts *o, int mode)
unsigned char subs[96];
data = get_sector(o, mode);
if (data == NULL)
return 0;
/* ts A61010 */
if (convert_data(o, NULL, mode, data) <= 0)
if (!data)
return 0;
convert_data(o, NULL, mode, data);
subcode_toc(d, mode, subs);
convert_subs(o, mode, subs, data);
sector_headers(o, data, mode, 1);
@ -356,11 +293,9 @@ int sector_pregap(struct burn_write_opts *o,
unsigned char subs[96];
data = get_sector(o, mode);
if (data == NULL)
return 0;
/* ts A61010 */
if (convert_data(o, NULL, mode, data) <= 0)
if (!data)
return 0;
convert_data(o, NULL, mode, data);
subcode_user(o, subs, tno, control, 0, NULL, 1);
convert_subs(o, mode, subs, data);
sector_headers(o, data, mode, 0);
@ -376,11 +311,9 @@ int sector_postgap(struct burn_write_opts *o,
unsigned char *data;
data = get_sector(o, mode);
if (data == NULL)
if (!data)
return 0;
/* ts A61010 */
if (convert_data(o, NULL, mode, data) <= 0)
return 0;;
convert_data(o, NULL, mode, data);
/* use last index in track */
subcode_user(o, subs, tno, control, 1, NULL, 1);
convert_subs(o, mode, subs, data);
@ -429,9 +362,7 @@ static char char_to_isrc(char c)
return 0x11 + (c - 'A');
if (c >= 'a' && c <= 'z')
return 0x11 + (c - 'a');
/* ts A61008 : obsoleted by test in burn_track_set_isrc() */
/* a ssert(0); */
assert(0);
return 0;
}
@ -467,8 +398,7 @@ void subcode_user(struct burn_write_opts *o, unsigned char *subcodes,
}
}
/* ts A61010 : this cannot happen. Assert for fun ? */
/* a ssert(qmode == 1 || qmode == 2 || qmode == 3); */
assert(qmode == 1 || qmode == 2 || qmode == 3);
switch (qmode) {
case 1:
@ -550,9 +480,7 @@ int sector_lout(struct burn_write_opts *o, unsigned char control, int mode)
data = get_sector(o, mode);
if (!data)
return 0;
/* ts A61010 */
if (convert_data(o, NULL, mode, data) <= 0)
return 0;
convert_data(o, NULL, mode, data);
subcode_lout(o, control, subs);
convert_subs(o, mode, subs, data);
sector_headers(o, data, mode, 0);
@ -569,9 +497,7 @@ int sector_data(struct burn_write_opts *o, struct burn_track *t, int psub)
data = get_sector(o, t->mode);
if (!data)
return 0;
/* ts A61010 */
if (convert_data(o, t, t->mode, data) <= 0)
return 0;
convert_data(o, t, t->mode, data);
if (!t->source->read_sub)
subcode_user(o, subs, t->entry->point,
@ -616,17 +542,6 @@ int dec_to_bcd(int d)
return (top << 4) + bottom;
}
int sector_headers_is_ok(struct burn_write_opts *o, int mode)
{
if (mode & BURN_AUDIO) /* no headers for "audio" */
return 1;
if (o->write_type == BURN_WRITE_SAO)
return 1;
if (mode & BURN_MODE1)
return 2;
return 0;
}
void sector_headers(struct burn_write_opts *o, unsigned char *out,
int mode, int leadin)
{
@ -635,17 +550,6 @@ void sector_headers(struct burn_write_opts *o, unsigned char *out,
int min, sec, frame;
int modebyte = -1;
/* ts A61009 */
#if 1
int ret;
ret = sector_headers_is_ok(o, mode);
if (ret != 2)
return;
modebyte = 1;
#else
if (mode & BURN_AUDIO) /* no headers for "audio" */
return;
if (o->write_type == BURN_WRITE_SAO)
@ -653,10 +557,7 @@ void sector_headers(struct burn_write_opts *o, unsigned char *out,
if (mode & BURN_MODE1)
modebyte = 1;
#endif
/* ts A61009 : now ensured by burn_disc_write_is_ok() */
/* a ssert(modebyte == 1); */
assert(modebyte == 1);
out[0] = 0;
memset(out + 1, 0xFF, 10); /* sync */
@ -728,9 +629,7 @@ void process_q(struct burn_drive *d, unsigned char *q)
*/
break;
default:
/* ts A61009 : if reactivated then witout Assert */
a ssert(0);
assert(0);
}
}
#endif

View File

@ -18,10 +18,6 @@ int sector_postgap(struct burn_write_opts *, unsigned char tno,
unsigned char control, int mode);
int sector_lout(struct burn_write_opts *, unsigned char control, int mode);
int sector_data(struct burn_write_opts *, struct burn_track *t, int psub);
/* ts A61009 */
int sector_headers_is_ok(struct burn_write_opts *o, int mode);
void sector_headers(struct burn_write_opts *, unsigned char *,
int mode, int leadin);
void subcode_user(struct burn_write_opts *, unsigned char *s,

View File

@ -1,768 +0,0 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* >>> ts A61021 : for testing the new arrangement of code
please outcomment these defines : */
/* Keeps alive old enumerate_common(). New version delegates much work
to methods in drive, mmc, spc, and sbc .
*/
#define Scsi_freebsd_make_own_enumeratE 1
/* Keeps alive old sg_enumerate(). New version delegates most work to
sg_give_next_adr().
*/
#define Scsi_freebsd_old_sg_enumeratE 1
#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/poll.h>
#include <camlib.h>
#include <cam/scsi/scsi_message.h>
#include <cam/scsi/scsi_pass.h>
#include <err.h> /* XXX */
#include "transport.h"
#include "drive.h"
#include "sg.h"
#include "spc.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;
static void enumerate_common(char *fname, int bus_no, int host_no,
int channel_no, int target_no, int lun_no);
/* ts A51221 */
int burn_drive_is_banned(char *device_address);
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
int mmc_function_spy(char * text);
#ifdef Scsi_freebsd_old_sg_enumeratE
int sg_give_next_adr(burn_drive_enumerator_t *idx,
char adr[], int adr_size, int initialize)
{
return (0);
}
int sg_is_enumerable_adr(char* adr)
{
return (0);
}
int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
int *target_no, int *lun_no)
{
return (0);
}
#else /* Scsi_freebsd_old_sg_enumeratE */
/* ts A61021 : Moved most code from sg_enumerate under sg_give_next_adr() */
/* Some helper functions for sg_give_next_adr() */
static int sg_init_enumerator(burn_drive_enumerator_t *idx)
{
idx->skip_device = 0;
if ((idx->fd = open(XPT_DEVICE, O_RDWR)) == -1) {
warn("couldn't open %s", XPT_DEVICE);
return -1;
}
bzero(&(idx->ccb), sizeof(union ccb));
idx->ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
idx->ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
idx->ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
idx->ccb.ccb_h.func_code = XPT_DEV_MATCH;
idx->bufsize = sizeof(struct dev_match_result) * 100;
idx->ccb.cdm.match_buf_len = idx->bufsize;
idx->ccb.cdm.matches = (struct dev_match_result *)malloc(idx->bufsize);
if (idx->ccb.cdm.matches == NULL) {
warnx("can't malloc memory for matches");
close(idx->fd);
return -1;
}
idx->ccb.cdm.num_matches = 0;
idx->i = idx->ccb.cdm.num_matches; /* to trigger buffer load */
/*
* We fetch all nodes, since we display most of them in the default
* case, and all in the verbose case.
*/
idx->ccb.cdm.num_patterns = 0;
idx->ccb.cdm.pattern_buf_len = 0;
return 1;
}
static int sg_next_enumeration_buffer(burn_drive_enumerator_t *idx)
{
/*
* We do the ioctl multiple times if necessary, in case there are
* more than 100 nodes in the EDT.
*/
if (ioctl(idx->fd, CAMIOCOMMAND, &(idx->ccb)) == -1) {
warn("error sending CAMIOCOMMAND ioctl");
return -1;
}
if ((idx->ccb.ccb_h.status != CAM_REQ_CMP)
|| ((idx->ccb.cdm.status != CAM_DEV_MATCH_LAST)
&& (idx->ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
warnx("got CAM error %#x, CDM error %d\n",
idx->ccb.ccb_h.status, idx->ccb.cdm.status);
return -1;
}
return 1;
}
/** Returns the next index number and the next enumerated drive address.
@param idx An opaque handle. Make no own theories about it.
@param adr Takes the reply
@param adr_size Gives maximum size of reply including final 0
@param initialize 1 = start new,
0 = continue, use no other values for now
-1 = finish
@return 1 = reply is a valid address , 0 = no further address available
-1 = severe error (e.g. adr_size too small)
*/
int sg_give_next_adr(burn_drive_enumerator_t *idx,
char adr[], int adr_size, int initialize)
{
int ret;
if (initialize == 1) {
ret = sg_init_enumerator(idx);
if (ret<=0)
return ret;
} else if (initialize == -1) {
if(idx->fd != -1)
close(idx->fd);
idx->fd = -1;
return 0;
}
try_item:; /* This spaghetti loop keeps the number of tabs small */
/* Loop content from old sg_enumerate() */
while (idx->i >= idx->ccb.cdm.num_matches) {
ret = sg_next_enumeration_buffer(idx);
if (ret<=0)
return -1;
if (!((idx->ccb.ccb_h.status == CAM_REQ_CMP)
&& (idx->ccb.cdm.status == CAM_DEV_MATCH_MORE)) )
return 0;
idx->i = 0;
}
switch (idx->ccb.cdm.matches[idx->i].type) {
case DEV_MATCH_BUS:
break;
case DEV_MATCH_DEVICE: {
struct device_match_result* result;
result = &(idx->ccb.cdm.matches[i].result.device_result);
if (result->flags & DEV_RESULT_UNCONFIGURED)
idx->skip_device = 1;
else
idx->skip_device = 0;
break;
}
case DEV_MATCH_PERIPH: {
struct periph_match_result* result;
char buf[64];
result = &(idx->ccb.cdm.matches[i].result.periph_result);
if (idx->skip_device ||
strcmp(result->periph_name, "pass") == 0)
break;
snprintf(buf, sizeof (buf), "/dev/%s%d",
result->periph_name, result->unit_number);
if(adr_size <= strlen(buf)
return -1;
strcpy(adr, buf);
/* Found next enumerable address */
return 1;
}
default:
/* printf(stderr, "unknown match type\n"); */
break;
}
(idx->i)++;
goto try_item; /* Regular function exit is return 1 above */
}
int sg_is_enumerable_adr(char* adr)
{
burn_drive_enumerator_t idx;
int initialize = 1;
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);
}
/** Try 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)
{
burn_drive_enumerator_t idx;
int initialize = 1;
char buf[64];
struct periph_match_result* result;
while(1) {
ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize);
initialize = 0;
if (ret <= 0)
break;
if (strcmp(adr, buf) != 0)
continue;
result = &(idx->ccb.cdm.matches[i].result.periph_result);
*bus_no = result->path_id;
*host_no = result->path_id;
*channel_no = 0;
*target_no = result->target_id
*lun_no = result->target_lun;
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
return 1;
}
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
return (0);
}
#endif /* ! Scsi_freebsd_old_sg_enumeratE */
int sg_close_drive(struct burn_drive * d)
{
if (d->cam != NULL) {
cam_close_device(d->cam);
d->cam = NULL;
}
return 0;
}
int sg_drive_is_open(struct burn_drive * d)
{
return (d->cam != NULL);
}
void ata_enumerate(void)
{
/* ts A61021: Only a dummy function is needed in FreeBSD */
/* The difference between sg and ata should be encapsulated
in sg-linux.c */
;
}
void sg_enumerate(void)
{
#ifdef Scsi_freebsd_old_sg_enumeratE
union ccb ccb;
int bufsize, fd;
unsigned int i;
int skip_device = 0;
if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
warn("couldn't open %s", XPT_DEVICE);
return;
}
bzero(&ccb, sizeof(union ccb));
ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
ccb.ccb_h.func_code = XPT_DEV_MATCH;
bufsize = sizeof(struct dev_match_result) * 100;
ccb.cdm.match_buf_len = bufsize;
ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
if (ccb.cdm.matches == NULL) {
warnx("can't malloc memory for matches");
close(fd);
return;
}
ccb.cdm.num_matches = 0;
/*
* We fetch all nodes, since we display most of them in the default
* case, and all in the verbose case.
*/
ccb.cdm.num_patterns = 0;
ccb.cdm.pattern_buf_len = 0;
/*
* We do the ioctl multiple times if necessary, in case there are
* more than 100 nodes in the EDT.
*/
do {
if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
warn("error sending CAMIOCOMMAND ioctl");
break;
}
if ((ccb.ccb_h.status != CAM_REQ_CMP)
|| ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
&& (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
warnx("got CAM error %#x, CDM error %d\n",
ccb.ccb_h.status, ccb.cdm.status);
break;
}
for (i = 0; i < ccb.cdm.num_matches; i++) {
switch (ccb.cdm.matches[i].type) {
case DEV_MATCH_BUS:
break;
case DEV_MATCH_DEVICE: {
struct device_match_result* result;
result = &ccb.cdm.matches[i].result.device_result;
if (result->flags & DEV_RESULT_UNCONFIGURED)
skip_device = 1;
else
skip_device = 0;
break;
}
case DEV_MATCH_PERIPH: {
struct periph_match_result* result;
char buf[64];
result = &ccb.cdm.matches[i].result.periph_result;
if (skip_device || strcmp(result->periph_name, "pass") == 0)
break;
snprintf(buf, sizeof (buf), "/dev/%s%d", result->periph_name, result->unit_number);
/* ts A51221 */
if (burn_drive_is_banned(buf))
break;
enumerate_common(buf, result->path_id, result->path_id, 0,
result->target_id, result->target_lun);
break;
}
default:
fprintf(stdout, "unknown match type\n");
break;
}
}
} while ((ccb.ccb_h.status == CAM_REQ_CMP)
&& (ccb.cdm.status == CAM_DEV_MATCH_MORE));
close(fd);
#else /* Scsi_freebsd_old_sg_enumeratE */
burn_drive_enumerator_t idx;
int initialize = 1;
char buf[64];
while(1) {
ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize);
initialize = 0;
if (ret <= 0)
break;
if (burn_drive_is_banned(buf))
continue;
enumerate_common(buf, idx.result->path_id, idx.result->path_id,
0, idx.result->target_id,
idx.result->target_lun);
}
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
#endif /* ! Scsi_freebsd_old_sg_enumeratE */
}
#ifdef Scsi_freebsd_make_own_enumeratE
/* ts A61021: The old version which mixes SCSI and operating system adapter
*/
static void enumerate_common(char *fname, int bus_no, int host_no,
int channel_no, int target_no, int lun_no)
{
struct burn_drive *t;
struct burn_drive out;
/* ts A60923 */
out.bus_no = bus_no;
out.host = host_no;
out.id = target_no;
out.channel = channel_no;
out.lun = lun_no;
out.devname = burn_strdup(fname);
out.cam = NULL;
out.start_lba= -2000000000;
out.end_lba= -2000000000;
out.read_atip = mmc_read_atip;
out.grab = sg_grab;
out.release = sg_release;
out.drive_is_open= sg_drive_is_open;
out.issue_command = sg_issue_command;
out.getcaps = spc_getcaps;
out.released = 1;
out.status = BURN_DISC_UNREADY;
out.eject = sbc_eject;
out.load = sbc_load;
out.lock = spc_prevent;
out.unlock = spc_allow;
out.read_disc_info = spc_sense_write_params;
out.get_erase_progress = spc_get_erase_progress;
out.test_unit_ready = spc_test_unit_ready;
out.probe_write_modes = spc_probe_write_modes;
out.read_toc = mmc_read_toc;
out.write = mmc_write;
out.erase = mmc_erase;
out.read_sectors = mmc_read_sectors;
out.perform_opc = mmc_perform_opc;
out.set_speed = mmc_set_speed;
out.send_parameters = spc_select_error_params;
out.send_write_parameters = spc_select_write_params;
out.send_cue_sheet = mmc_send_cue_sheet;
out.sync_cache = mmc_sync_cache;
out.get_nwa = mmc_get_nwa;
out.close_disc = mmc_close_disc;
out.close_session = mmc_close_session;
out.read_buffer_capacity = mmc_read_buffer_capacity;
out.idata = malloc(sizeof(struct burn_scsi_inquiry_data));
out.idata->valid = 0;
out.mdata = malloc(sizeof(struct scsi_mode_data));
out.mdata->valid = 0;
if (out.idata == NULL || out.mdata == NULL) {
libdax_msgs_submit(libdax_messenger, -1, 0x00020108,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Could not allocate new drive object", 0, 0);
return;
}
memset(&out.params, 0, sizeof(struct params));
t = burn_drive_register(&out);
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
mmc_function_spy("enumerate_common : -------- doing grab");
/* try to get the drive info */
if (t->grab(t)) {
burn_print(2, "getting drive info\n");
t->getcaps(t);
t->unlock(t);
t->released = 1;
} else {
burn_print(2, "unable to grab new located drive\n");
}
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
mmc_function_spy("enumerate_common : ----- would release ");
}
#else /* Scsi_freebsd_make_own_enumeratE */
/* The new, more concise version of enumerate_common */
static void enumerate_common(char *fname, int bus_no, int host_no,
int channel_no, int target_no, int lun_no)
{
int ret;
struct burn_drive out;
/* General libburn drive setup */
burn_setup_drive(&out, fname);
/* This transport adapter uses SCSI-family commands and models
(seems the adapter would know better than its boss, if ever) */
ret = burn_scsi_setup_drive(&out, bus_no, host_no, channel_no,
target_no, lun_no, 0);
if (ret<=0)
return;
/* Operating system adapter is CAM */
/* Adapter specific handles and data */
out.cam = NULL;
/* Adapter specific functions */
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);
}
#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
drive or not.
if refcount is not one, drive is open somewhere else.
*/
int sg_grab(struct burn_drive *d)
{
int count;
struct cam_device *cam;
mmc_function_spy("sg_grab");
assert(d->cam == NULL);
cam = cam_open_device(d->devname, O_RDWR);
if (cam == NULL) {
libdax_msgs_submit(libdax_messenger, d->global_index, 0x00020003,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Could not grab drive", 0/*os_errno*/, 0);
return 0;
}
/* er = ioctl(fd, SG_GET_ACCESS_COUNT, &count);*/
count = 1;
if (1 == count) {
d->cam = cam;
fcntl(cam->fd, F_SETOWN, getpid());
d->released = 0;
return 1;
}
burn_print(1, "could not acquire drive - already open\n");
sg_close_drive(d);
return 0;
}
/*
non zero return means you still have the drive and it's not
in a state to be released? (is that even possible?)
*/
int sg_release(struct burn_drive *d)
{
mmc_function_spy("sg_release");
if (d->cam == NULL) {
burn_print(1, "release an ungrabbed drive. die\n");
return 0;
}
mmc_function_spy("sg_release ----------- closing.");
sg_close_drive(d);
return 0;
}
int sg_issue_command(struct burn_drive *d, struct command *c)
{
int done = 0;
int err;
union ccb *ccb;
char buf[161];
snprintf(buf, sizeof (buf), "sg_issue_command d->cam=%p d->released=%d",
(void*)d->cam, d->released);
mmc_function_spy(buf);
if (d->cam == NULL) {
c->error = 0;
return 0;
}
c->error = 0;
ccb = cam_getccb(d->cam);
cam_fill_csio(&ccb->csio,
1, /* retries */
NULL, /* cbfncp */
CAM_DEV_QFRZDIS, /* flags */
MSG_SIMPLE_Q_TAG, /* tag_action */
NULL, /* data_ptr */
0, /* dxfer_len */
sizeof (ccb->csio.sense_data), /* sense_len */
0, /* cdb_len */
30*1000); /* timeout */
switch (c->dir) {
case TO_DRIVE:
ccb->csio.ccb_h.flags |= CAM_DIR_OUT;
break;
case FROM_DRIVE:
ccb->csio.ccb_h.flags |= CAM_DIR_IN;
break;
case NO_TRANSFER:
ccb->csio.ccb_h.flags |= CAM_DIR_NONE;
break;
}
ccb->csio.cdb_len = c->oplen;
memcpy(&ccb->csio.cdb_io.cdb_bytes, &c->opcode, c->oplen);
memset(&ccb->csio.sense_data, 0, sizeof (ccb->csio.sense_data));
if (c->page) {
ccb->csio.data_ptr = c->page->data;
if (c->dir == FROM_DRIVE) {
ccb->csio.dxfer_len = BUFFER_SIZE;
/* touch page so we can use valgrind */
memset(c->page->data, 0, BUFFER_SIZE);
} else {
assert(c->page->bytes > 0);
ccb->csio.dxfer_len = c->page->bytes;
}
} else {
ccb->csio.data_ptr = NULL;
ccb->csio.dxfer_len = 0;
}
do {
err = cam_send_ccb(d->cam, ccb);
if (err == -1) {
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);
cam_freeccb(ccb);
sg_close_drive(d);
d->released = 1;
d->busy = BURN_DRIVE_IDLE;
c->error = 1;
return -1;
}
/* XXX */
memcpy(c->sense, &ccb->csio.sense_data, ccb->csio.sense_len);
if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
if (!c->retry) {
c->error = 1;
cam_freeccb(ccb);
return 1;
}
switch (scsi_error(d, c->sense, 0)) {
case RETRY:
done = 0;
break;
case FAIL:
done = 1;
c->error = 1;
break;
}
} else {
done = 1;
}
} while (!done);
cam_freeccb(ccb);
return 1;
}
enum response scsi_error(struct burn_drive *d, unsigned char *sense,
int senselen)
{
int key, asc, ascq;
senselen = senselen;
key = sense[2];
asc = sense[12];
ascq = sense[13];
burn_print(12, "CONDITION: 0x%x 0x%x 0x%x on %s %s\n",
key, asc, ascq, d->idata->vendor, d->idata->product);
switch (asc) {
case 0:
burn_print(12, "NO ERROR!\n");
return RETRY;
case 2:
burn_print(1, "not ready\n");
return RETRY;
case 4:
burn_print(1,
"logical unit is in the process of becoming ready\n");
return RETRY;
case 0x20:
if (key == 5)
burn_print(1, "bad opcode\n");
return FAIL;
case 0x21:
burn_print(1, "invalid address or something\n");
return FAIL;
case 0x24:
if (key == 5)
burn_print(1, "invalid field in cdb\n");
else
break;
return FAIL;
case 0x26:
if (key == 5)
burn_print( 1, "invalid field in parameter list\n" );
return FAIL;
case 0x28:
if (key == 6)
burn_print(1,
"Not ready to ready change, medium may have changed\n");
else
break;
return RETRY;
case 0x3A:
burn_print(12, "Medium not present in %s %s\n",
d->idata->vendor, d->idata->product);
d->status = BURN_DISC_EMPTY;
return FAIL;
}
burn_print(1, "unknown failure\n");
burn_print(1, "key:0x%x, asc:0x%x, ascq:0x%x\n", key, asc, ascq);
return FAIL;
}

View File

@ -1,797 +0,0 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* ts A61010 */
/* #include <a ssert.h> */
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
/* #include <m alloc.h> ts A61013 : not in Linux man 3 malloc */
#include <string.h>
#include <sys/poll.h>
#include <linux/hdreg.h>
#include <stdlib.h>
#include <scsi/sg.h>
#include <scsi/scsi.h>
#include "transport.h"
#include "drive.h"
#include "sg.h"
#include "spc.h"
#include "mmc.h"
#include "sbc.h"
#include "debug.h"
#include "toc.h"
#include "util.h"
/* kludge! glibc headers don't define all the SCSI stuff that we use! */
#ifndef SG_GET_ACCESS_COUNT
# define SG_GET_ACCESS_COUNT 0x2289
#endif
#include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger;
static void enumerate_common(char *fname, int bus_no, int host_no,
int channel_no, int target_no, int lun_no);
/* ts A51221 */
int burn_drive_is_banned(char *device_address);
/* ts A60813 : storage objects are in libburn/init.c
wether to use O_EXCL
wether to use O_NOBLOCK with open(2) on devices
wether to take O_EXCL rejection as fatal error */
extern int burn_sg_open_o_excl;
extern int burn_sg_open_o_nonblock;
extern int burn_sg_open_abort_busy;
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
int mmc_function_spy(char * text);
static int sgio_test(int fd)
{
unsigned char test_ops[] = { 0, 0, 0, 0, 0, 0 };
sg_io_hdr_t s;
memset(&s, 0, sizeof(sg_io_hdr_t));
s.interface_id = 'S';
s.dxfer_direction = SG_DXFER_NONE;
s.cmd_len = 6;
s.cmdp = test_ops;
s.timeout = 12345;
return ioctl(fd, SG_IO, &s);
}
/* ts A60925 : ticket 74 */
int sg_close_drive_fd(char *fname, int driveno, int *fd, int sorry)
{
int ret, os_errno, sevno= LIBDAX_MSGS_SEV_DEBUG;
char msg[4096+100];
if(*fd < 0)
return(0);
ret = close(*fd);
*fd = -1337;
if(ret != -1)
return 1;
os_errno= errno;
if (fname != NULL)
sprintf(msg, "Encountered error when closing drive '%s'",
fname);
else
sprintf(msg, "Encountered error when closing drive");
if (sorry)
sevno = LIBDAX_MSGS_SEV_SORRY;
libdax_msgs_submit(libdax_messenger, driveno, 0x00020002,
sevno, LIBDAX_MSGS_PRIO_HIGH, msg, os_errno, 0);
return 0;
}
int sg_drive_is_open(struct burn_drive * d)
{
/* a bit more detailed case distinction than needed */
if (d->fd == -1337)
return 0;
if (d->fd < 0)
return 0;
return 1;
}
/* ts A60924 */
int sg_handle_busy_device(char *fname, int os_errno)
{
char msg[4096];
/* ts A60814 : i saw no way to do this more nicely */
if (burn_sg_open_abort_busy) {
fprintf(stderr,
"\nlibburn: FATAL : Application triggered abort on busy device '%s'\n",
fname);
/* ts A61007 */
abort();
/* a ssert("drive busy" == "non fatal"); */
}
/* ts A60924 : now reporting to libdax_msgs */
sprintf(msg, "Cannot open busy device '%s'", fname);
libdax_msgs_submit(libdax_messenger, -1, 0x00020001,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_LOW,
msg, os_errno, 0);
return 1;
}
/* ts A60922 ticket 33 */
/** Returns the next index number and the next enumerated drive address.
@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)
{
/* sg.h : typedef int burn_drive_enumerator_t; */
static int sg_limit = 32, ata_limit = 26;
int baseno = 0;
if (initialize == -1)
return 0;
if (initialize == 1)
*idx = -1;
(*idx)++;
if (*idx >= sg_limit)
goto next_ata;
if (adr_size < 10)
return -1;
sprintf(adr, "/dev/sg%d", *idx);
return 1;
next_ata:;
baseno += sg_limit;
if (*idx - baseno >= ata_limit)
goto next_nothing;
if (adr_size < 9)
return -1;
sprintf(adr, "/dev/hd%c", 'a' + (*idx - baseno));
return 1;
next_nothing:;
baseno += ata_limit;
return 0;
}
int sg_is_enumerable_adr(char *adr)
{
char fname[4096];
int i, ret = 0, first = 1;
while (1) {
ret= sg_give_next_adr(&i, fname, sizeof(fname), first);
if(ret <= 0)
break;
first = 0;
if (strcmp(adr, fname) == 0)
return 1;
}
return(0);
}
/* ts A60926 */
int sg_release_siblings(int sibling_fds[], int *sibling_count)
{
int i;
char msg[81];
for(i= 0; i < *sibling_count; i++)
sg_close_drive_fd(NULL, -1, &(sibling_fds[i]), 0);
if(*sibling_count > 0) {
sprintf(msg, "Closed %d O_EXCL scsi siblings", *sibling_count);
libdax_msgs_submit(libdax_messenger, -1, 0x00020007,
LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH, msg, 0,0);
}
*sibling_count = 0;
return 1;
}
/* ts A60926 */
int sg_open_drive_fd(char *fname, int scan_mode)
{
int open_mode = O_RDWR, fd;
char msg[81];
/* ts A60813 - A60927
O_EXCL with devices is a non-POSIX feature
of Linux kernels. Possibly introduced 2002.
Mentioned in "The Linux SCSI Generic (sg) HOWTO" */
if(burn_sg_open_o_excl)
open_mode |= O_EXCL;
/* ts A60813
O_NONBLOCK was already hardcoded in ata_ but not in sg_.
There must be some reason for this. So O_NONBLOCK is
default mode for both now. Disable on own risk. */
if(burn_sg_open_o_nonblock)
open_mode |= O_NONBLOCK;
/* <<< debugging
fprintf(stderr,
"\nlibburn: experimental: o_excl= %d , o_nonblock= %d, abort_on_busy= %d\n",
burn_sg_open_o_excl,burn_sg_open_o_nonblock,burn_sg_open_abort_busy);
fprintf(stderr,
"libburn: experimental: O_EXCL= %d , O_NONBLOCK= %d\n",
!!(open_mode&O_EXCL),!!(open_mode&O_NONBLOCK));
*/
fd = open(fname, open_mode);
if (fd == -1) {
/* <<< debugging
fprintf(stderr,
"\nlibburn: experimental: fname= %s , errno= %d\n",
fname,errno);
*/
if (errno == EBUSY) {
sg_handle_busy_device(fname, errno);
return -1;
}
if (scan_mode)
return -1;
sprintf(msg, "Failed to open device '%s'",fname);
libdax_msgs_submit(libdax_messenger, -1, 0x00020005,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
msg, errno, 0);
return -1;
}
return fd;
}
/* ts A60926 */
int sg_open_scsi_siblings(char *path, int driveno,
int sibling_fds[], int *sibling_count,
int host_no, int channel_no, int id_no, int lun_no)
{
int tld, i, ret, fd, i_bus_no = -1;
int i_host_no = -1, i_channel_no = -1, i_target_no = -1, i_lun_no = -1;
char msg[161], fname[81];
static char tldev[][81]= {"/dev/sr%d", "/dev/scd%d", "/dev/st%d", ""};
if(host_no < 0 || id_no < 0 || channel_no < 0 || lun_no < 0)
return(2);
if(*sibling_count > 0)
sg_release_siblings(sibling_fds, sibling_count);
for (tld = 0; tldev[tld][0] != 0; tld++) {
for (i = 0; i < 32; i++) {
sprintf(fname, tldev[tld], i);
ret = sg_obtain_scsi_adr(fname, &i_bus_no, &i_host_no,
&i_channel_no, &i_target_no, &i_lun_no);
if (ret <= 0)
continue;
if (i_host_no != host_no || i_channel_no != channel_no)
continue;
if (i_target_no != id_no || i_lun_no != lun_no)
continue;
fd = sg_open_drive_fd(fname, 0);
if (fd < 0)
goto failed;
if (*sibling_count>=LIBBURN_SG_MAX_SIBLINGS) {
sprintf(msg, "Too many scsi siblings of '%s'",
path);
libdax_msgs_submit(libdax_messenger,
driveno, 0x00020006,
LIBDAX_MSGS_SEV_FATAL,
LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0);
goto failed;
}
sprintf(msg, "Opened O_EXCL scsi sibling '%s' of '%s'",
fname, path);
libdax_msgs_submit(libdax_messenger, driveno,
0x00020004,
LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
sibling_fds[*sibling_count] = fd;
(*sibling_count)++;
}
}
return(1);
failed:;
sg_release_siblings(sibling_fds, sibling_count);
return 0;
}
/* ts A60926 */
int sg_close_drive(struct burn_drive *d)
{
int ret;
if (!burn_drive_is_open(d))
return 0;
sg_release_siblings(d->sibling_fds, &(d->sibling_count));
ret = sg_close_drive_fd(d->devname, d->global_index, &(d->fd), 0);
return ret;
}
void ata_enumerate(void)
{
struct hd_driveid tm;
int i, fd;
char fname[10];
for (i = 0; i < 26; i++) {
sprintf(fname, "/dev/hd%c", 'a' + i);
/* ts A51221 */
if (burn_drive_is_banned(fname))
continue;
fd = sg_open_drive_fd(fname, 1);
if (fd == -1)
continue;
/* found a drive */
ioctl(fd, HDIO_GET_IDENTITY, &tm);
/* not atapi */
if (!(tm.config & 0x8000) || (tm.config & 0x4000)) {
sg_close_drive_fd(fname, -1, &fd, 0);
continue;
}
/* if SG_IO fails on an atapi device, we should stop trying to
use hd* devices */
if (sgio_test(fd) == -1) {
sg_close_drive_fd(fname, -1, &fd, 0);
return;
}
if (sg_close_drive_fd(fname, -1, &fd, 1) <= 0)
continue;
enumerate_common(fname, -1, -1, -1, -1, -1);
}
}
void sg_enumerate(void)
{
struct sg_scsi_id sid;
int i, fd, sibling_fds[LIBBURN_SG_MAX_SIBLINGS], sibling_count= 0, ret;
int bus_no = -1;
char fname[10];
for (i = 0; i < 32; i++) {
sprintf(fname, "/dev/sg%d", i);
/* ts A51221 */
if (burn_drive_is_banned(fname))
continue;
/* ts A60927 */
fd = sg_open_drive_fd(fname, 1);
if (fd == -1)
continue;
/* found a drive */
ioctl(fd, SG_GET_SCSI_ID, &sid);
#ifdef SCSI_IOCTL_GET_BUS_NUMBER
/* Hearsay A61005 */
if (ioctl(fd, SCSI_IOCTL_GET_BUS_NUMBER, &bus_no) == -1)
bus_no = -1;
#endif
if (sg_close_drive_fd(fname, -1, &fd,
sid.scsi_type == TYPE_ROM ) <= 0)
continue;
if (sid.scsi_type != TYPE_ROM)
continue;
/* ts A60927 : trying to do locking with growisofs */
if(burn_sg_open_o_excl>1) {
ret = sg_open_scsi_siblings(
fname, -1, sibling_fds, &sibling_count,
sid.host_no, sid.channel,
sid.scsi_id, sid.lun);
if (ret<=0) {
sg_handle_busy_device(fname, 0);
continue;
}
/* the final occupation will be done in sg_grab() */
sg_release_siblings(sibling_fds, &sibling_count);
}
#ifdef SCSI_IOCTL_GET_BUS_NUMBER
if(bus_no == -1)
bus_no = 1000 * (sid.host_no + 1) + sid.channel;
#else
bus_no = sid.host_no;
#endif
enumerate_common(fname, bus_no, sid.host_no, sid.channel,
sid.scsi_id, sid.lun);
}
}
/* ts A60923 - A61005 : introduced new SCSI parameters */
/* ts A61021 : moved non os-specific code to spc,sbc,mmc,drive */
static void enumerate_common(char *fname, int bus_no, int host_no,
int channel_no, int target_no, int lun_no)
{
int ret, i;
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;
/* Operating system adapter is Linux Generic SCSI (sg) */
/* Adapter specific handles and data */
out.fd = -1337;
out.sibling_count = 0;
for(i= 0; i<LIBBURN_SG_MAX_SIBLINGS; i++)
out.sibling_fds[i] = -1337;
/* Adapter specific functions */
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);
}
/*
we use the sg reference count to decide whether we can use the
drive or not.
if refcount is not one, drive is open somewhere else.
ts A60813: this test is too late. O_EXCL is the stronger solution.
After all the test was disabled already in icculus.org/burn CVS.
*/
int sg_grab(struct burn_drive *d)
{
int fd, count, os_errno= 0, ret;
/* ts A60813 */
int open_mode = O_RDWR;
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
mmc_function_spy("sg_grab");
/* ts A60813 - A60927
O_EXCL with devices is a non-POSIX feature
of Linux kernels. Possibly introduced 2002.
Mentioned in "The Linux SCSI Generic (sg) HOWTO".
*/
if(burn_sg_open_o_excl)
open_mode |= O_EXCL;
/* ts A60813
O_NONBLOCK was hardcoded here. So it should stay default mode. */
if(burn_sg_open_o_nonblock)
open_mode |= O_NONBLOCK;
/* ts A60813
After enumeration the drive fd is probably still open.
-1337 is the initial value of burn_drive.fd and the value after
relase of drive. Unclear why not the official error return
value -1 of open(2) war used. */
/* ts A60822: was if(d->fd == -1337) { */
if(! burn_drive_is_open(d)) {
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
mmc_function_spy("sg_grab ----------- opening");
/* ts A60926 */
if(burn_sg_open_o_excl>1) {
fd = -1;
ret = sg_open_scsi_siblings(d->devname,
d->global_index,d->sibling_fds,
&(d->sibling_count),
d->host, d->channel, d->id, d->lun);
if(ret <= 0)
goto drive_is_in_use;
}
fd = open(d->devname, open_mode);
os_errno = errno;
} else
fd= d->fd;
/* ts A61007 : this is redundant */
/* a ssert(fd != -1337); */
if (fd >= 0) {
/* ts A60814:
according to my experiments this test would work now ! */
/* ts A60926 : this was disabled */
/* Tests with growisofs on kernel 2.4.21 yielded that this
does not help against blocking on busy drives.
*/
/* <<< the old dummy */
/* er = ioctl(fd, SG_GET_ACCESS_COUNT, &count);*/
count = 1;
if (1 == count) {
d->fd = fd;
fcntl(fd, F_SETOWN, getpid());
d->released = 0;
return 1;
}
drive_is_in_use:;
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020003,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Could not grab drive - already in use", 0, 0);
sg_close_drive(d);
d->fd = -1337;
return 0;
}
libdax_msgs_submit(libdax_messenger, d->global_index, 0x00020003,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Could not grab drive", os_errno, 0);
return 0;
}
/*
non zero return means you still have the drive and it's not
in a state to be released? (is that even possible?)
*/
int sg_release(struct burn_drive *d)
{
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
mmc_function_spy("sg_release");
if (d->fd < 1) {
burn_print(1, "release an ungrabbed drive. die\n");
return 0;
}
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
mmc_function_spy("sg_release ----------- closing");
sg_close_drive(d);
return 0;
}
int sg_issue_command(struct burn_drive *d, struct command *c)
{
int done = 0, no_c_page = 0;
int err;
sg_io_hdr_t s;
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
char buf[161];
sprintf(buf,"sg_issue_command d->fd= %d d->released= %d\n",
d->fd,d->released);
mmc_function_spy(buf);
/* ts A61010 : with no fd there is no chance to send an ioctl */
if (d->fd < 0) {
c->error = 1;
return 0;
}
c->error = 0;
memset(&s, 0, sizeof(sg_io_hdr_t));
s.interface_id = 'S';
if (c->dir == TO_DRIVE)
s.dxfer_direction = SG_DXFER_TO_DEV;
else if (c->dir == FROM_DRIVE)
s.dxfer_direction = SG_DXFER_FROM_DEV;
else if (c->dir == NO_TRANSFER) {
s.dxfer_direction = SG_DXFER_NONE;
/* ts A61007 */
/* a ssert(!c->page); */
no_c_page = 1;
}
s.cmd_len = c->oplen;
s.cmdp = c->opcode;
s.mx_sb_len = 32;
s.sbp = c->sense;
memset(c->sense, 0, sizeof(c->sense));
s.timeout = 200000;
if (c->page && !no_c_page) {
s.dxferp = c->page->data;
if (c->dir == FROM_DRIVE) {
s.dxfer_len = BUFFER_SIZE;
/* touch page so we can use valgrind */
memset(c->page->data, 0, BUFFER_SIZE);
} else {
/* ts A61010 */
/* a ssert(c->page->bytes > 0); */
if (c->page->bytes <= 0) {
c->error = 1;
return 0;
}
s.dxfer_len = c->page->bytes;
}
} else {
s.dxferp = NULL;
s.dxfer_len = 0;
}
s.usr_ptr = c;
do {
err = ioctl(d->fd, SG_IO, &s);
/* ts A61010 */
/* a ssert(err != -1); */
if (err == -1) {
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 (s.sb_len_wr) {
if (!c->retry) {
c->error = 1;
return 1;
}
switch (scsi_error(d, s.sbp, s.sb_len_wr)) {
case RETRY:
done = 0;
break;
case FAIL:
done = 1;
c->error = 1;
break;
}
} else {
done = 1;
}
} while (!done);
return 1;
}
enum response scsi_error(struct burn_drive *d, unsigned char *sense,
int senselen)
{
int key, asc, ascq;
senselen = senselen;
key = sense[2];
asc = sense[12];
ascq = sense[13];
burn_print(12, "CONDITION: 0x%x 0x%x 0x%x on %s %s\n",
key, asc, ascq, d->idata->vendor, d->idata->product);
switch (asc) {
case 0:
burn_print(12, "NO ERROR!\n");
return RETRY;
case 2:
burn_print(1, "not ready\n");
return RETRY;
case 4:
burn_print(1,
"logical unit is in the process of becoming ready\n");
return RETRY;
case 0x20:
if (key == 5)
burn_print(1, "bad opcode\n");
return FAIL;
case 0x21:
burn_print(1, "invalid address or something\n");
return FAIL;
case 0x24:
if (key == 5)
burn_print(1, "invalid field in cdb\n");
else
break;
return FAIL;
case 0x26:
if ( key == 5 )
burn_print( 1, "invalid field in parameter list\n" );
return FAIL;
case 0x28:
if (key == 6)
burn_print(1,
"Not ready to ready change, medium may have changed\n");
else
break;
return RETRY;
case 0x3A:
burn_print(12, "Medium not present in %s %s\n",
d->idata->vendor, d->idata->product);
d->status = BURN_DISC_EMPTY;
return FAIL;
}
burn_print(1, "unknown failure\n");
burn_print(1, "key:0x%x, asc:0x%x, ascq:0x%x\n", key, asc, ascq);
return FAIL;
}
/* ts A60922 */
/** Try to obtain SCSI address parameters.
@return 1 is success , 0 is failure
*/
int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
int *target_no, int *lun_no)
{
int fd, ret;
struct my_scsi_idlun {
int x;
int host_unique_id;
};
struct my_scsi_idlun idlun;
if (strncmp(path, "/dev/hd", 7) == 0
&& path[7] >= 'a' && path[7] <= 'z' && path[8] == 0)
return 0; /* on RIP 14 all hdx return SCSI adr 0,0,0,0 */
fd = open(path, O_RDONLY | O_NONBLOCK);
if(fd < 0)
return 0;
#ifdef SCSI_IOCTL_GET_BUS_NUMBER
/* Hearsay A61005 */
if (ioctl(fd, SCSI_IOCTL_GET_BUS_NUMBER, bus_no) == -1)
*bus_no = -1;
#endif
/* http://www.tldp.org/HOWTO/SCSI-Generic-HOWTO/scsi_g_idlun.html */
ret = ioctl(fd, SCSI_IOCTL_GET_IDLUN, &idlun);
sg_close_drive_fd(path, -1, &fd, 0);
if (ret == -1)
return(0);
*host_no= (idlun.x>>24)&255;
*channel_no= (idlun.x>>16)&255;
*target_no= (idlun.x)&255;
*lun_no= (idlun.x>>8)&255;
#ifdef SCSI_IOCTL_GET_BUS_NUMBER
if(*bus_no == -1)
*bus_no = 1000 * (*host_no + 1) + *channel_no;
#else
*bus_no= *host_no;
#endif
return 1;
}

View File

@ -1,13 +1,500 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* ts A61013 : It would be nice if autotools could do that job */
#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <malloc.h>
#include <string.h>
#include <sys/poll.h>
#include <linux/hdreg.h>
#ifdef __FreeBSD__
#include "transport.h"
#include "drive.h"
#include "sg.h"
#include "spc.h"
#include "mmc.h"
#include "sbc.h"
#include "debug.h"
#include "toc.h"
#include "util.h"
#include "sg-freebsd.c"
static void enumerate_common(char *fname);
#else
/* ts A51221 */
int burn_drive_is_banned(char *device_address);
#include "sg-linux.c"
/* ts A60813 : storage objects are in libburn/init.c
wether to use O_EXCL
wether to use O_NOBLOCK with open(2) on devices
wether to take O_EXCL rejection as fatal error */
extern int burn_sg_open_o_excl;
extern int burn_sg_open_o_nonblock;
extern int burn_sg_open_abort_busy;
#endif
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
int mmc_function_spy(char * text);
static int sgio_test(int fd)
{
unsigned char test_ops[] = { 0, 0, 0, 0, 0, 0 };
sg_io_hdr_t s;
memset(&s, 0, sizeof(sg_io_hdr_t));
s.interface_id = 'S';
s.dxfer_direction = SG_DXFER_NONE;
s.cmd_len = 6;
s.cmdp = test_ops;
s.timeout = 12345;
return ioctl(fd, SG_IO, &s);
}
void ata_enumerate(void)
{
struct hd_driveid tm;
int i, fd;
char fname[10];
/* ts A60813 */
int open_mode = O_RDWR;
/* ts A60813
O_EXCL with block devices is an unpublished feature
of Linux kernels. Possibly introduced 2002.
It can only be used if libburn stops opening several
file descriptor on the same block device.
See comment in sg_grab() */
if(burn_sg_open_o_excl)
open_mode |= O_EXCL;
/* ts A60813
O_NONBLOCK was already hardcoded in ata_ but not in sg_.
There must be some reason for this. So O_NONBLOCK is
default mode for both now. Disable on own risk. */
if(burn_sg_open_o_nonblock)
open_mode |= O_NONBLOCK;
for (i = 0; i < 26; i++) {
sprintf(fname, "/dev/hd%c", 'a' + i);
/* open O_RDWR so we don't think read only drives are
in some way useful
*/
/* ts A51221 */
if (burn_drive_is_banned(fname))
continue;
fd = open(fname, open_mode);
if (fd == -1) {
/* <<< debugging
fprintf(stderr,
"\nlibburn: experimental: fname= %s , errno= %d\n",
fname,errno);
*/
/* ts A60814 : i see no way to do this more nicely */
if (errno == EBUSY && burn_sg_open_abort_busy) {
fprintf(stderr,
"\nlibburn: FATAL : Application triggered abort on busy drive '%s'\n",
fname);
/* <<< maybe one should plainly exit here */
assert("drive busy" == "non fatal");
}
continue;
}
/* found a drive */
ioctl(fd, HDIO_GET_IDENTITY, &tm);
/* not atapi */
if (!(tm.config & 0x8000) || (tm.config & 0x4000)) {
close(fd);
continue;
}
/* if SG_IO fails on an atapi device, we should stop trying to
use hd* devices */
if (sgio_test(fd) == -1) {
close(fd);
return;
}
close(fd);
enumerate_common(fname);
}
}
void sg_enumerate(void)
{
struct sg_scsi_id sid;
int i, fd;
char fname[10];
/* ts A60813 */
int open_mode = O_RDWR;
/* ts A60813
O_EXCL with block devices is an unpublished feature
of Linux kernels. Possibly introduced 2002.
It can only be used if libburn stops opening several
file descriptor on the same block device.
See comment in sg_grab() */
if(burn_sg_open_o_excl)
open_mode |= O_EXCL;
/* ts A60813
O_NONBLOCK was not hardcoded in sg_ but was in ata_.
I myself test mainly sg_ and it seems to be ok with
O_NONBLOCK. So it should stay default mode. */
if(burn_sg_open_o_nonblock)
open_mode |= O_NONBLOCK;
/* <<< debugging
fprintf(stderr,
"\nlibburn: experimental: o_excl= %d , o_nonblock= %d, abort_on_busy= %d\n",
burn_sg_open_o_excl,burn_sg_open_o_nonblock,burn_sg_open_abort_busy);
fprintf(stderr,
"libburn: experimental: O_EXCL= %d , O_NONBLOCK= %d\n",
!!(open_mode&O_EXCL),!!(open_mode&O_NONBLOCK));
*/
for (i = 0; i < 32; i++) {
sprintf(fname, "/dev/sg%d", i);
/* open RDWR so we don't accidentally think read only drives
are in some way useful
*/
/* ts A51221 */
if (burn_drive_is_banned(fname))
continue;
fd = open(fname, open_mode);
if (fd == -1) {
/* <<< debugging
fprintf(stderr,
"\n cdrskin: experimental: fname= %s , errno= %d\n",
fname,errno);
*/
/* ts A60814 : i see no way to do this more nicely */
if (errno == EBUSY && burn_sg_open_abort_busy) {
fprintf(stderr,
"\nlibburn: FATAL : Application triggered abort on busy drive '%s'\n",
fname);
/* <<< maybe one should plainly exit here */
assert("drive busy" == "non fatal");
}
continue;
}
/* found a drive */
ioctl(fd, SG_GET_SCSI_ID, &sid);
close(fd);
if (sid.scsi_type != TYPE_ROM)
continue;
enumerate_common(fname);
}
}
static void enumerate_common(char *fname)
{
struct burn_drive *t;
struct burn_drive out;
out.devname = burn_strdup(fname);
out.fd = -1337;
out.grab = sg_grab;
out.release = sg_release;
out.issue_command = sg_issue_command;
out.getcaps = spc_getcaps;
out.released = 1;
out.status = BURN_DISC_UNREADY;
out.eject = sbc_eject;
out.load = sbc_load;
out.lock = spc_prevent;
out.unlock = spc_allow;
out.read_disc_info = spc_sense_write_params;
out.get_erase_progress = spc_get_erase_progress;
out.test_unit_ready = spc_test_unit_ready;
out.probe_write_modes = spc_probe_write_modes;
out.read_toc = mmc_read_toc;
out.write = mmc_write;
out.erase = mmc_erase;
out.read_sectors = mmc_read_sectors;
out.perform_opc = mmc_perform_opc;
out.set_speed = mmc_set_speed;
out.send_parameters = spc_select_error_params;
out.send_write_parameters = spc_select_write_params;
out.send_cue_sheet = mmc_send_cue_sheet;
out.sync_cache = mmc_sync_cache;
out.get_nwa = mmc_get_nwa;
out.close_disc = mmc_close_disc;
out.close_session = mmc_close_session;
out.idata = malloc(sizeof(struct scsi_inquiry_data));
out.idata->valid = 0;
out.mdata = malloc(sizeof(struct scsi_mode_data));
out.mdata->valid = 0;
memset(&out.params, 0, sizeof(struct params));
t = burn_drive_register(&out);
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
mmc_function_spy("enumerate_common : -------- doing grab");
/* try to get the drive info */
if (sg_grab(t)) {
burn_print(2, "getting drive info\n");
t->getcaps(t);
t->unlock(t);
t->released = 1;
} else {
burn_print(2, "unable to grab new located drive\n");
}
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
mmc_function_spy("enumerate_common : ----- would release ");
}
/*
we use the sg reference count to decide whether we can use the
drive or not.
if refcount is not one, drive is open somewhere else.
ts A60813: this test is too late. O_EXCL is the stronger solution.
After all the test was diabled already in icculus.org/burn CVS.
*/
int sg_grab(struct burn_drive *d)
{
int fd, count;
/* ts A60813 */
int open_mode = O_RDWR;
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
mmc_function_spy("sg_grab");
/* ts A60813
O_EXCL with block devices is an unpublished feature
of Linux kernels. Possibly introduced 2002.
It can only be used if libburn stops opening several
file descriptor on the same block device.
See comment below */
if(burn_sg_open_o_excl)
open_mode |= O_EXCL;
/* ts A60813
O_NONBLOCK was hardcoded here. So it should stay default mode. */
if(burn_sg_open_o_nonblock)
open_mode |= O_NONBLOCK;
/* ts A60813
After enumeration the drive fd is probably still open.
-1337 is the initial value of burn_drive.fd and the value after
relase of drive. Unclear why not the official error return
value -1 of open(2) war used. */
/* ts A60822: was if(d->fd == -1337) { */
if(! burn_drive_is_open(d)) {
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
mmc_function_spy("sg_grab ----------- opening");
fd = open(d->devname, open_mode);
} else
fd= d->fd;
assert(fd != -1337);
if (-1 != fd) {
/* ts A60814:
according to my experiments this test would work now ! */
/* er = ioctl(fd, SG_GET_ACCESS_COUNT, &count);*/
count = 1;
if (1 == count) {
d->fd = fd;
fcntl(fd, F_SETOWN, getpid());
d->released = 0;
return 1;
}
burn_print(1, "could not acquire drive - already open\n");
close(fd);
return 0;
}
burn_print(1, "could not acquire drive\n");
return 0;
}
/*
non zero return means you still have the drive and it's not
in a state to be released? (is that even possible?)
*/
int sg_release(struct burn_drive *d)
{
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
mmc_function_spy("sg_release");
if (d->fd < 1) {
burn_print(1, "release an ungrabbed drive. die\n");
return 0;
}
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
mmc_function_spy("sg_release ----------- closing");
close(d->fd);
d->fd = -1337;
return 0;
}
int sg_issue_command(struct burn_drive *d, struct command *c)
{
int done = 0;
int err;
sg_io_hdr_t s;
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
char buf[161];
sprintf(buf,"sg_issue_command d->fd= %d d->released= %d\n",
d->fd,d->released);
mmc_function_spy(buf);
c->error = 0;
/*
this is valid during the mode probe in scan
if (d->fd < 1 || d->released) {
burn_print(1,
"command issued on ungrabbed drive, chaos.\n");
burn_print(1, "fd = %d, released = %d\n", d->fd,
d->released);
}
*/
memset(&s, 0, sizeof(sg_io_hdr_t));
s.interface_id = 'S';
if (c->dir == TO_DRIVE)
s.dxfer_direction = SG_DXFER_TO_DEV;
else if (c->dir == FROM_DRIVE)
s.dxfer_direction = SG_DXFER_FROM_DEV;
else if (c->dir == NO_TRANSFER) {
s.dxfer_direction = SG_DXFER_NONE;
assert(!c->page);
}
s.cmd_len = c->oplen;
s.cmdp = c->opcode;
s.mx_sb_len = 32;
s.sbp = c->sense;
memset(c->sense, 0, sizeof(c->sense));
s.timeout = 200000;
if (c->page) {
s.dxferp = c->page->data;
if (c->dir == FROM_DRIVE) {
s.dxfer_len = BUFFER_SIZE;
/* touch page so we can use valgrind */
memset(c->page->data, 0, BUFFER_SIZE);
} else {
assert(c->page->bytes > 0);
s.dxfer_len = c->page->bytes;
}
} else {
s.dxferp = NULL;
s.dxfer_len = 0;
}
s.usr_ptr = c;
do {
err = ioctl(d->fd, SG_IO, &s);
assert(err != -1);
if (s.sb_len_wr) {
if (!c->retry) {
c->error = 1;
return 1;
}
switch (scsi_error(d, s.sbp, s.sb_len_wr)) {
case RETRY:
done = 0;
break;
case FAIL:
done = 1;
c->error = 1;
break;
}
} else {
done = 1;
}
} while (!done);
return 1;
}
enum response scsi_error(struct burn_drive *d, unsigned char *sense,
int senselen)
{
int key, asc, ascq;
senselen = senselen;
key = sense[2];
asc = sense[12];
ascq = sense[13];
burn_print(12, "CONDITION: 0x%x 0x%x 0x%x on %s %s\n",
key, asc, ascq, d->idata->vendor, d->idata->product);
switch (asc) {
case 0:
burn_print(12, "NO ERROR!\n");
return RETRY;
case 2:
burn_print(1, "not ready\n");
return RETRY;
case 4:
burn_print(1,
"logical unit is in the process of becoming ready\n");
return RETRY;
case 0x20:
if (key == 5)
burn_print(1, "bad opcode\n");
return FAIL;
case 0x21:
burn_print(1, "invalid address or something\n");
return FAIL;
case 0x24:
if (key == 5)
burn_print(1, "invalid field in cdb\n");
else
break;
return FAIL;
case 0x26:
if ( key == 5 )
burn_print( 1, "invalid field in parameter list\n" );
return FAIL;
case 0x28:
if (key == 6)
burn_print(1,
"Not ready to ready change, medium may have changed\n");
else
break;
return RETRY;
case 0x3A:
burn_print(12, "Medium not present in %s %s\n",
d->idata->vendor, d->idata->product);
d->status = BURN_DISC_EMPTY;
return FAIL;
}
burn_print(1, "unknown failure\n");
burn_print(1, "key:0x%x, asc:0x%x, ascq:0x%x\n", key, asc, ascq);
return FAIL;
}

View File

@ -3,60 +3,12 @@
#ifndef __SG
#define __SG
#ifdef __FreeBSD__
/* >>> To hold all state information of BSD device enumeration
which are now local in sg_enumerate() . So that sg_give_next_adr()
can work in BSD and sg_enumerate() can use it. */
struct burn_drive_enumeration_state {
#ifdef Scsi_freebsd_old_sg_enumeratE
int dummy;
#else
union ccb ccb;
int bufsize, fd;
unsigned int i;
int skip_device;
#endif /* ! Scsi_freebsd_old_sg_enumeratE */
};
typedef struct burn_drive_enumeration_state burn_drive_enumerator_t;
#else /* __FreeBSD__ */
/* <<< just for testing the C syntax */
struct burn_drive_enumeration_state {
int dummy;
};
typedef struct burn_drive_enumeration_state burn_drive_enumerator_tX;
typedef int burn_drive_enumerator_t;
#endif /* ! __FreeBSD__ */
struct burn_drive;
struct command;
enum response
{ RETRY, FAIL };
/* ts A60925 : ticket 74 */
int sg_close_drive_fd(char *fname, int driveno, int *fd, int sorry);
/* ts A60922 ticket 33 */
int sg_give_next_adr(burn_drive_enumerator_t *enm_context,
char adr[], int adr_size, int initialize);
int sg_is_enumerable_adr(char *adr);
int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
int *target_no, int *lun_no);
/* ts A60926 : ticket 33 ++ */
int sg_open_scsi_siblings(char *fname, int driveno,
int sibling_fds[], int *sibling_count,
int host_no, int channel_no, int id_no, int lun_no);
int sg_release_siblings(int sibling_fds[], int *sibling_count);
int sg_close_drive(struct burn_drive *d);
void sg_enumerate(void);
void ata_enumerate(void);
int sg_grab(struct burn_drive *);
@ -64,5 +16,4 @@ int sg_release(struct burn_drive *);
int sg_issue_command(struct burn_drive *, struct command *);
enum response scsi_error(struct burn_drive *, unsigned char *, int);
#endif /* __SG */

View File

@ -29,7 +29,8 @@ struct burn_source *burn_source_new(void)
{
struct burn_source *out;
out = calloc(1, sizeof(struct burn_source));
out = malloc(sizeof(struct burn_source));
memset(out, 0, sizeof(struct burn_source));
out->refcount = 1;
return out;
}

View File

@ -9,10 +9,7 @@
#include <fcntl.h>
#include <sys/ioctl.h>
#include <string.h>
/* ts A61008 */
/* #include <a ssert.h> */
#include <assert.h>
#include <stdlib.h>
#include "transport.h"
@ -23,10 +20,6 @@
#include "debug.h"
#include "options.h"
#include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger;
/* spc command set */
static unsigned char SPC_INQUIRY[] = { 0x12, 0, 0, 0, 255, 0 };
@ -79,7 +72,7 @@ int spc_get_erase_progress(struct burn_drive *d)
void spc_inquiry(struct burn_drive *d)
{
struct buffer buf;
struct burn_scsi_inquiry_data *id;
struct scsi_inquiry_data *id;
struct command c;
memcpy(c.opcode, SPC_INQUIRY, sizeof(SPC_INQUIRY));
@ -91,7 +84,7 @@ void spc_inquiry(struct burn_drive *d)
c.dir = FROM_DRIVE;
d->issue_command(d, &c);
id = (struct burn_scsi_inquiry_data *)d->idata;
id = (struct scsi_inquiry_data *)d->idata;
id->vendor[8] = 0;
id->product[16] = 0;
id->revision[4] = 0;
@ -161,24 +154,10 @@ void spc_sense_caps(struct burn_drive *d)
m->cdrw_write = page[3] & 2;
m->cdr_read = page[2] & 1;
m->cdr_write = page[3] & 1;
/* ts A61021 : these fields are marked obsolete in MMC 3 */
m->max_read_speed = page[8] * 256 + page[9];
m->cur_read_speed = page[14] * 256 + page[15];
/* in MMC-3 : see [30-31] and blocks beginning at [32] */
m->max_write_speed = page[18] * 256 + page[19];
/* New field to be set by atip */
m->min_write_speed = m->max_write_speed;
/* in MMC-3 : [28-29] */
m->cur_write_speed = page[20] * 256 + page[21];
/* >>> ts A61021 : iterate over all speeds :
data[30-31]: number of speed performance descriptor blocks
data[32-35]: block 0 : [+2-3] speed in kbytes/sec
*/
m->c2_pointers = page[5] & 16;
m->valid = 1;
m->underrun_proof = page[4] & 128;
@ -223,10 +202,7 @@ void spc_select_error_params(struct burn_drive *d,
c.page = &buf;
c.page->bytes = 0;
c.page->sectors = 0;
/* ts A61007 : moved up to only caller burn_disc_read() */
/* a ssert(d->mdata->valid); */
assert(d->mdata->valid);
memset(c.page->data, 0, 8 + 2 + d->mdata->retry_page_length);
c.page->bytes = 8 + 2 + d->mdata->retry_page_length;
c.page->data[8] = 1;
@ -251,9 +227,8 @@ void spc_sense_write_params(struct burn_drive *d)
unsigned char *page;
struct command c;
/* ts A61007 : Done in soft at only caller burn_drive_grab() */
/* a ssert(d->mdata->cdr_write || d->mdata->cdrw_write ||
d->mdata->dvdr_write || d->mdata->dvdram_write); */
assert(d->mdata->cdr_write || d->mdata->cdrw_write ||
d->mdata->dvdr_write || d->mdata->dvdram_write);
memcpy(c.opcode, SPC_MODE_SENSE, sizeof(SPC_MODE_SENSE));
c.retry = 1;
@ -281,9 +256,7 @@ void spc_select_write_params(struct burn_drive *d,
struct command c;
int bufe, sim;
/* ts A61007 : All current callers are safe. */
/* a ssert(o->drive == d); */
assert(o->drive == d);
memcpy(c.opcode, SPC_MODE_SELECT, sizeof(SPC_MODE_SELECT));
c.retry = 1;
c.oplen = sizeof(SPC_MODE_SELECT);
@ -291,10 +264,7 @@ void spc_select_write_params(struct burn_drive *d,
c.page = &buf;
c.page->bytes = 0;
c.page->sectors = 0;
/* ts A61007 : moved up to burn_disc_write() */
/* a ssert(d->mdata->valid); */
assert(d->mdata->valid);
memset(c.page->data, 0, 8 + 2 + d->mdata->write_page_length);
c.page->bytes = 8 + 2 + d->mdata->write_page_length;
c.page->data[8] = 5;
@ -405,7 +375,6 @@ void spc_probe_write_modes(struct burn_drive *d)
}
}
/** @return -1 = error */
int spc_block_type(enum burn_block_types b)
{
switch (b) {
@ -431,67 +400,6 @@ int spc_block_type(enum burn_block_types b)
return 12;
case BURN_BLOCK_MODE2_OK:
return 13;
default:
return -1;
}
/* ts A61007 : already prevented in burn_write_opts_set_write_type() */
/* a ssert(0); */;
}
/* ts A61021 : the spc specific part of sg.c:enumerate_common()
*/
int spc_setup_drive(struct burn_drive *d)
{
d->getcaps = spc_getcaps;
d->lock = spc_prevent;
d->unlock = spc_allow;
d->read_disc_info = spc_sense_write_params;
d->get_erase_progress = spc_get_erase_progress;
d->test_unit_ready = spc_test_unit_ready;
d->probe_write_modes = spc_probe_write_modes;
d->send_parameters = spc_select_error_params;
d->send_write_parameters = spc_select_write_params;
return 1;
}
/* ts A61021 : the general SCSI specific part of sg.c:enumerate_common()
@param flag Bitfiled for control purposes
bit0= do not setup spc/sbc/mmc
*/
int burn_scsi_setup_drive(struct burn_drive *d, int bus_no, int host_no,
int channel_no, int target_no, int lun_no, int flag)
{
int ret;
/* ts A60923 */
d->bus_no = bus_no;
d->host = host_no;
d->id = target_no;
d->channel = channel_no;
d->lun = lun_no;
d->idata = malloc(sizeof(struct burn_scsi_inquiry_data));
d->idata->valid = 0;
d->mdata = malloc(sizeof(struct scsi_mode_data));
d->mdata->valid = 0;
/* ts A61007 : obsolete Assert in drive_getcaps() */
if(d->idata == NULL || d->mdata == NULL) {
libdax_msgs_submit(libdax_messenger, -1, 0x00020108,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Could not allocate new drive object", 0, 0);
return -1;
}
if(!(flag & 1)) {
ret = spc_setup_drive(d);
if (ret<=0)
return ret;
ret = sbc_setup_drive(d);
if (ret<=0)
return ret;
ret = mmc_setup_drive(d);
if (ret<=0)
return ret;
}
return 1;
assert(0);
}

View File

@ -22,16 +22,4 @@ int spc_block_type(enum burn_block_types b);
int spc_get_erase_progress(struct burn_drive *d);
int spc_test_unit_ready(struct burn_drive *d);
/* ts A61021 : the spc specific part of sg.c:enumerate_common()
*/
int spc_setup_drive(struct burn_drive *d);
/* ts A61021 : the general SCSI specific part of sg.c:enumerate_common()
@param flag Bitfield for control purposes
bit0= do not setup spc/sbc/mmc
*/
int burn_scsi_setup_drive(struct burn_drive *d, int bus_no, int host_no,
int channel_no, int target_no, int lun_no, int flag);
#endif /*__SPC*/

View File

@ -1,7 +1,4 @@
/* ts A61008 */
/* #include <a ssert.h> */
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -10,18 +7,10 @@
#include "write.h"
#include "debug.h"
#include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger;
/* ts A61008 : replaced Assert by if and return 0 */
/* a ssert(!(pos > BURN_POS_END)); */
#define RESIZE(TO, NEW, pos) {\
void *tmp;\
\
if (pos > BURN_POS_END)\
return 0;\
assert(!(pos > BURN_POS_END));\
if (pos == BURN_POS_END)\
pos = TO->NEW##s;\
if (pos > TO->NEW##s)\
@ -39,7 +28,8 @@ extern struct libdax_msgs *libdax_messenger;
struct burn_disc *burn_disc_create(void)
{
struct burn_disc *d;
d = calloc(1, sizeof(struct burn_disc));
d = malloc(sizeof(struct burn_disc));
memset(d, 0, sizeof(struct burn_disc));
d->refcnt = 1;
d->sessions = 0;
d->session = NULL;
@ -63,7 +53,8 @@ void burn_disc_free(struct burn_disc *d)
struct burn_session *burn_session_create(void)
{
struct burn_session *s;
s = calloc(1, sizeof(struct burn_session));
s = malloc(sizeof(struct burn_session));
memset(s, 0, sizeof(struct burn_session));
s->refcnt = 1;
s->tracks = 0;
s->track = NULL;
@ -103,7 +94,8 @@ int burn_disc_add_session(struct burn_disc *d, struct burn_session *s,
struct burn_track *burn_track_create(void)
{
struct burn_track *t;
t = calloc(1, sizeof(struct burn_track));
t = malloc(sizeof(struct burn_track));
memset(t, 0, sizeof(struct burn_track));
t->refcnt = 1;
t->indices = 0;
t->offset = 0;
@ -118,9 +110,6 @@ struct burn_track *burn_track_create(void)
t->postgap = 0;
t->pregap1 = 0;
t->pregap2 = 0;
/* ts A61024 */
t->swap_source_bytes = 0;
return t;
}
@ -149,34 +138,30 @@ int burn_session_remove_track(struct burn_session *s, struct burn_track *t)
struct burn_track **tmp;
int i, pos = -1;
/* ts A61008 */
/* a ssert(s->track != NULL); */
if (s->track == NULL)
return 0;
assert(s->track != NULL);
burn_track_free(t);
/* Find the position */
for (i = 0; i < s->tracks; i++) {
if (t == s->track[i]) {
if (t == s->track[i])
pos = i;
break;
}
}
if (pos == -1)
return 0;
/* Is it the last track? */
if (pos != s->tracks - 1) {
memmove(&s->track[pos], &s->track[pos + 1],
if (pos != s->tracks) {
memmove(s->track[pos], s->track[pos + 1],
sizeof(struct burn_track *) * (s->tracks - (pos + 1)));
}
s->tracks--;
tmp = realloc(s->track, sizeof(struct burn_track *) * s->tracks);
if (tmp)
s->track = tmp;
if (!tmp)
return 0;
s->track = tmp;
return 1;
}
@ -207,96 +192,34 @@ void burn_structure_print_track(struct burn_track *t)
void burn_track_define_data(struct burn_track *t, int offset, int tail,
int pad, int mode)
{
int type_to_form(int mode, unsigned char *ctladr, int *form);
int burn_sector_length(int tracktype);
unsigned char ctladr;
int form = -1; /* unchanged form will be considered an error too */
type_to_form(mode, &ctladr, &form);
if (form == -1 || burn_sector_length(mode) <= 0) {
char msg[160];
sprintf(msg, "Attempt to set track mode to unusable value %d",
mode);
libdax_msgs_submit(libdax_messenger, -1, 0x00020115,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
return;
}
t->offset = offset;
t->pad = pad;
t->mode = mode;
t->tail = tail;
}
/* ts A61024 */
int burn_track_set_byte_swap(struct burn_track *t, int swap_source_bytes)
{
if(swap_source_bytes!=0 && swap_source_bytes!=1)
return 0;
t->swap_source_bytes = swap_source_bytes;
return 1;
}
void burn_track_set_isrc(struct burn_track *t, char *country, char *owner,
unsigned char year, unsigned int serial)
{
int i;
t->isrc.has_isrc = 1;
for (i = 0; i < 2; ++i) {
/* ts A61008 : This is always true */
/* a ssert((country[i] >= '0' || country[i] < '9') &&
assert((country[i] >= '0' || country[i] < '9') &&
(country[i] >= 'a' || country[i] < 'z') &&
(country[i] >= 'A' || country[i] < 'Z')); */
/* ts A61008 : now coordinated with sector.c: char_to_isrc() */
if (! ((country[i] >= '0' && country[i] <= '9') ||
(country[i] >= 'a' && country[i] <= 'z') ||
(country[i] >= 'A' && country[i] <= 'Z') ) )
goto is_not_allowed;
(country[i] >= 'A' || country[i] < 'Z'));
t->isrc.country[i] = country[i];
}
for (i = 0; i < 3; ++i) {
/* ts A61008 : This is always true */
/* a ssert((owner[i] >= '0' || owner[i] < '9') &&
assert((owner[i] >= '0' || owner[i] < '9') &&
(owner[i] >= 'a' || owner[i] < 'z') &&
(owner[i] >= 'A' || owner[i] < 'Z')); */
/* ts A61008 : now coordinated with sector.c: char_to_isrc() */
if (! ((owner[i] >= '0' && owner[i] <= '9') ||
(owner[i] >= 'a' && owner[i] <= 'z') ||
(owner[i] >= 'A' && owner[i] <= 'Z') ) )
goto is_not_allowed;
(owner[i] >= 'A' || owner[i] < 'Z'));
t->isrc.owner[i] = owner[i];
}
/* ts A61008 */
/* a ssert(year <= 99); */
if (year > 99)
goto is_not_allowed;
assert(year <= 99);
t->isrc.year = year;
/* ts A61008 */
/* a ssert(serial <= 99999); */
if (serial > 99999)
goto is_not_allowed;
assert(serial <= 99999);
t->isrc.serial = serial;
/* ts A61008 */
t->isrc.has_isrc = 1;
return;
is_not_allowed:;
libdax_msgs_submit(libdax_messenger, -1, 0x00020114,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Attempt to set ISRC with bad data", 0, 0);
return;
}
void burn_track_clear_isrc(struct burn_track *t)

View File

@ -41,10 +41,6 @@ struct burn_track
/** The track contains a postgap */
int postgap;
struct isrc isrc;
/* ts A61024 */
/** Byte swapping on source data stream : 0=none , 1=pairwise */
int swap_source_bytes;
};
struct burn_session

View File

@ -1,8 +1,6 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* ts A61008 */
/* #include <a ssert.h> */
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
@ -53,10 +51,7 @@ static void write_clonecd2(volatile struct toc *toc, int f)
case BURN_MODE2_FORM1:
case BURN_MODE2_FORM2:
case BURN_MODE_UNINITIALIZED:
/* ts A61008 : do this softly without Assert */
a ssert(0); /* unhandled! find out ccd's
assert(0); /* unhandled! find out ccd's
value for these modes! */
}
dprintf(f, "PreGapMode=%d\r\n", m);
@ -100,8 +95,7 @@ void toc_find_modes(struct burn_drive *d)
struct buffer mem;
struct burn_toc_entry *e;
/* ts A61008 : to be prevented on the higher levels */
/* a ssert(d->busy); */
assert(d->busy);
mem.bytes = 0;
mem.sectors = 1;

View File

@ -8,17 +8,16 @@
#include <pthread.h>
/* sg data structures */
#include <sys/types.h>
#include <scsi/sg.h>
#include <scsi/scsi.h>
#ifdef __FreeBSD__
#define BUFFER_SIZE 65536/2
#else /* __FreeBSD__ */
/* kludge! glibc headers don't define all the SCSI shit that we use! */
#ifndef SG_GET_ACCESS_COUNT
# define SG_GET_ACCESS_COUNT 0x2289
#endif
#define BUFFER_SIZE 65536
#endif /* ! __FreeBSD__ */
enum transfer_direction
{ TO_DRIVE, FROM_DRIVE, NO_TRANSFER };
@ -56,7 +55,7 @@ struct command
struct buffer *page;
};
struct burn_scsi_inquiry_data
struct scsi_inquiry_data
{
char vendor[9];
char product[17];
@ -79,10 +78,6 @@ struct scsi_mode_data
int simulate;
int max_read_speed;
int max_write_speed;
/* ts A61021 */
int min_write_speed;
int cur_read_speed;
int cur_write_speed;
int retry_page_length;
@ -95,28 +90,16 @@ struct scsi_mode_data
};
#define LIBBURN_SG_MAX_SIBLINGS 16
/** Gets initialized in enumerate_common() and burn_drive_register() */
struct burn_drive
{
int bus_no;
int host;
int id;
int channel;
int lun;
char *devname;
#if defined(__FreeBSD__)
struct cam_device* cam;
#else
int fd;
/* ts A60926 : trying to lock against growisofs /dev/srN, /dev/scdN */
int sibling_count;
int sibling_fds[LIBBURN_SG_MAX_SIBLINGS];
#endif
/* ts A60904 : ticket 62, contribution by elmom */
/**
Tells the index in scanned burn_drive_info array.
@ -145,19 +128,11 @@ struct burn_drive
/* transport functions */
int (*grab) (struct burn_drive *);
int (*release) (struct burn_drive *);
/* ts A61021 */
int (*drive_is_open) (struct burn_drive *);
int (*issue_command) (struct burn_drive *, struct command *);
/* lower level functions */
void (*erase) (struct burn_drive *, int);
void (*getcaps) (struct burn_drive *);
/* ts A61021 */
void (*read_atip) (struct burn_drive *);
int (*write) (struct burn_drive *, int, struct buffer *);
void (*read_toc) (struct burn_drive *);
void (*lock) (struct burn_drive *);
@ -179,27 +154,16 @@ struct burn_drive
void (*sync_cache) (struct burn_drive *);
int (*get_erase_progress) (struct burn_drive *);
int (*get_nwa) (struct burn_drive *);
/* ts A61009 : removed d in favor of o->drive */
/* void (*close_disc) (struct burn_drive * d,
struct burn_write_opts * o);
void (*close_session) (struct burn_drive * d,
void (*close_disc) (struct burn_drive * d, struct burn_write_opts * o);
void (*close_session) (struct burn_drive * d,
struct burn_write_opts * o);
*/
void (*close_disc) (struct burn_write_opts * o);
void (*close_session) ( struct burn_write_opts * o);
int (*test_unit_ready) (struct burn_drive * d);
void (*probe_write_modes) (struct burn_drive * d);
struct params params;
struct burn_scsi_inquiry_data *idata;
struct scsi_inquiry_data *idata;
struct scsi_mode_data *mdata;
int toc_entries;
struct burn_toc_entry *toc_entry;
/* ts A61023 : get size and free space of drive buffer */
int (*read_buffer_capacity) (struct burn_drive *d);
};
/* end of generic 'drive' data structures */

View File

@ -1,8 +1,5 @@
#include <string.h>
/* ts A61008 */
/* #include <a ssert.h> */
#include <assert.h>
#include <stdlib.h>
#include "../version.h"
#include "util.h"
@ -13,10 +10,7 @@ char *burn_strdup(char *s)
char *ret;
int l;
/* ts A61008 */
/* a ssert(s); */
if (s == NULL)
return NULL;
assert(s);
l = strlen(s) + 1;
ret = malloc(l);
@ -30,11 +24,8 @@ char *burn_strndup(char *s, int n)
char *ret;
int l;
/* ts A61008 */
/* a ssert(s); */
/* a ssert(n > 0); */
if (s == NULL || n <= 0)
return NULL;
assert(s);
assert(n > 0);
l = strlen(s);
ret = malloc(l < n ? l : n);

View File

@ -2,11 +2,7 @@
#include <unistd.h>
#include <signal.h>
/* ts A61009 */
/* #include <a ssert.h> */
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
@ -16,6 +12,7 @@
#include "libburn.h"
#include "drive.h"
#include "transport.h"
#include "message.h"
#include "crc.h"
#include "debug.h"
#include "init.h"
@ -26,10 +23,6 @@
#include "write.h"
#include "options.h"
#include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger;
static int type_to_ctrl(int mode)
{
int ctrl = 0;
@ -44,9 +37,7 @@ static int type_to_ctrl(int mode)
if (mode & BURN_PREEMPHASIS)
ctrl |= 1;
} else
/* ts A61008 */
/* a ssert(0); */
return -1;
assert(0);
if (mode & BURN_COPY)
ctrl |= 2;
@ -55,40 +46,18 @@ static int type_to_ctrl(int mode)
}
/* only the ctrl nibble is set here (not adr) */
/* ts A61009 : removed "static" , reacted on type_to_ctrl() == -1
preserved ignorance towards unknown modes (for now) */
void type_to_form(int mode, unsigned char *ctladr, int *form)
static void type_to_form(int mode, unsigned char *ctladr, int *form)
{
int ret;
ret = type_to_ctrl(mode) << 4;
if (ret == -1) {
*ctladr = 0xff;
*form = -1;
return;
}
*ctladr = ret;
*ctladr = type_to_ctrl(mode) << 4;
if (mode & BURN_AUDIO)
*form = 0;
if (mode & BURN_MODE0) {
/* ts A61009 */
/* a ssert(0); */
*form = -1;
return;
}
if (mode & BURN_MODE0)
assert(0);
if (mode & BURN_MODE1)
*form = 0x10;
if (mode & BURN_MODE2) {
/* ts A61009 */
/* a ssert(0); */ /* XXX someone's gonna want this sometime */
*form = -1;
return;
}
if (mode & BURN_MODE2)
assert(0); /* XXX someone's gonna want this sometime */
if (mode & BURN_MODE_RAW)
*form = 0;
if (mode & BURN_SUBCODE_P16) /* must be expanded to R96 */
@ -141,9 +110,7 @@ static void print_cue(struct cue_sheet *sheet)
#endif /* Libburn_write_with_print_cuE */
/* ts A61009 : changed type from void to int */
/** @return 1 = success , <=0 failure */
static int add_cue(struct cue_sheet *sheet, unsigned char ctladr,
static void add_cue(struct cue_sheet *sheet, unsigned char ctladr,
unsigned char tno, unsigned char indx,
unsigned char form, unsigned char scms, int lba)
{
@ -155,17 +122,7 @@ static int add_cue(struct cue_sheet *sheet, unsigned char ctladr,
sheet->count++;
ptr = realloc(sheet->data, sheet->count * 8);
/* ts A61009 */
/* a ssert(ptr); */
if (ptr == NULL) {
libdax_msgs_submit(libdax_messenger, -1, 0x00020111,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Could not allocate new auxiliary object (cue_sheet->data)",
0, 0);
return -1;
}
assert(ptr);
sheet->data = ptr;
unit = sheet->data + (sheet->count - 1) * 8;
unit[0] = ctladr;
@ -176,13 +133,12 @@ static int add_cue(struct cue_sheet *sheet, unsigned char ctladr,
unit[5] = m;
unit[6] = s;
unit[7] = f;
return 1;
}
struct cue_sheet *burn_create_toc_entries(struct burn_write_opts *o,
struct burn_session *session)
{
int i, m, s, f, form, pform, runtime = -150, ret;
int i, m, s, f, form, pform, runtime = -150;
unsigned char ctladr;
struct burn_drive *d;
struct burn_toc_entry *e;
@ -194,49 +150,20 @@ struct cue_sheet *burn_create_toc_entries(struct burn_write_opts *o,
d = o->drive;
sheet = malloc(sizeof(struct cue_sheet));
/* ts A61009 : react on failures of malloc(), add_cue_sheet()
type_to_form() */
if (sheet == NULL) {
libdax_msgs_submit(libdax_messenger, -1, 0x00020111,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Could not allocate new auxiliary object (cue_sheet)",
0, 0);
return NULL;
}
sheet->data = NULL;
sheet->count = 0;
type_to_form(tar[0]->mode, &ctladr, &form);
if (form == -1) {
libdax_msgs_submit(libdax_messenger, -1, 0x00020116,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Track mode has unusable value", 0, 0);
goto failed;
}
ret = add_cue(sheet, ctladr | 1, 0, 0, 1, 0, runtime);
if (ret <= 0)
goto failed;
ret = add_cue(sheet, ctladr | 1, 1, 0, form, 0, runtime);
if (ret <= 0)
goto failed;
add_cue(sheet, ctladr | 1, 0, 0, 1, 0, runtime);
add_cue(sheet, ctladr | 1, 1, 0, form, 0, runtime);
runtime += 150;
burn_print(1, "toc for %d tracks:\n", ntr);
d->toc_entries = ntr + 3;
/* ts A61009 */
/* a ssert(d->toc_entry == NULL); */
if (d->toc_entry != NULL) {
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x00020117,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"toc_entry of drive is already in use", 0, 0);
goto failed;
}
d->toc_entry = calloc(d->toc_entries, sizeof(struct burn_toc_entry));
assert(d->toc_entry == NULL);
d->toc_entry = malloc(d->toc_entries * sizeof(struct burn_toc_entry));
e = d->toc_entry;
memset((void *)e, 0, d->toc_entries * sizeof(struct burn_toc_entry));
e[0].point = 0xA0;
if (tar[0]->mode & BURN_AUDIO)
e[0].control = TOC_CONTROL_AUDIO;
@ -261,12 +188,7 @@ struct cue_sheet *burn_create_toc_entries(struct burn_write_opts *o,
for (i = 0; i < ntr; i++) {
type_to_form(tar[i]->mode, &ctladr, &form);
if (pform != form) {
ret = add_cue(sheet, ctladr | 1, i + 1, 0, form, 0,
runtime);
if (ret <= 0)
goto failed;
add_cue(sheet, ctladr | 1, i + 1, 0, form, 0, runtime);
runtime += 150;
/* XXX fix pregap interval 1 for data tracks */
/* ts A60813 silence righteous compiler warning about C++ style comments
@ -289,11 +211,7 @@ struct cue_sheet *burn_create_toc_entries(struct burn_write_opts *o,
e[3 + i].control = type_to_ctrl(tar[i]->mode);
burn_print(1, "track %d control %d\n", tar[i]->mode,
e[3 + i].control);
ret = add_cue(sheet, ctladr | 1, i + 1, 1, form, 0, runtime);
if (ret <= 0)
goto failed;
add_cue(sheet, ctladr | 1, i + 1, 1, form, 0, runtime);
runtime += burn_track_get_sectors(tar[i]);
/* if we're padding, we'll clear any current shortage.
if we're not, we'll slip toc entries by a sector every time our
@ -323,15 +241,8 @@ XXX this is untested :)
burn_print(1, "point %d (%02d:%02d:%02d)\n",
d->toc_entry[i].point, d->toc_entry[i].pmin,
d->toc_entry[i].psec, d->toc_entry[i].pframe);
ret = add_cue(sheet, ctladr | 1, 0xAA, 1, 1, 0, runtime);
if (ret <= 0)
goto failed;
add_cue(sheet, ctladr | 1, 0xAA, 1, 1, 0, runtime);
return sheet;
failed:;
if (sheet != NULL)
free((char *) sheet);
return NULL;
}
int burn_sector_length(int tracktype)
@ -342,9 +253,8 @@ int burn_sector_length(int tracktype)
return 2352;
if (tracktype & BURN_MODE1)
return 2048;
/* ts A61009 */
/* a ssert(0); */
return -1;
assert(0);
return 12345;
}
int burn_subcode_length(int tracktype)
@ -485,19 +395,12 @@ int burn_write_track(struct burn_write_opts *o, struct burn_session *s,
/* ts A60831: added tnum-line, extended print message on proposal
by bonfire-app@wanadoo.fr in http://libburn.pykix.org/ticket/58 */
d->progress.track = tnum;
burn_print(12, "track %d is %d sectors long\n", tnum, sectors);
if (tnum == s->tracks)
tmp = sectors > 150 ? 150 : sectors;
for (i = 0; i < sectors - tmp; i++) {
/* ts A61023 : http://libburn.pykix.org/ticket/14
From time to time inquire drive buffer */
if ((i%64)==0)
d->read_buffer_capacity(d);
if (!sector_data(o, t, 0))
return 0;
@ -506,11 +409,6 @@ int burn_write_track(struct burn_write_opts *o, struct burn_session *s,
}
for (; i < sectors; i++) {
burn_print(1, "last track, leadout prep\n");
/* ts A61023 */
if ((i%64)==0)
d->read_buffer_capacity(d);
if (!sector_data(o, t, 1))
return 0;
@ -541,27 +439,6 @@ int burn_write_track(struct burn_write_opts *o, struct burn_session *s,
return 1;
}
/* ts A61009 */
int burn_disc_write_is_ok(struct burn_write_opts *o, struct burn_disc *disc)
{
int i, t;
char msg[80];
for (i = 0; i < disc->sessions; i++)
for (t = 0; t < disc->session[i]->tracks; t++)
if (!sector_headers_is_ok(
o, disc->session[i]->track[t]->mode))
goto bad_track_mode_found;
return 1;
bad_track_mode_found:;
sprintf(msg, "Unsuitable track mode 0x%x in track %d of session %d",
disc->session[i]->track[t]->mode, i+1, t+1);
libdax_msgs_submit(libdax_messenger, -1, 0x0002010a,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
return 0;
}
void burn_disc_write_sync(struct burn_write_opts *o, struct burn_disc *disc)
{
struct cue_sheet *sheet;
@ -571,9 +448,7 @@ void burn_disc_write_sync(struct burn_write_opts *o, struct burn_disc *disc)
int first = 1, i;
int res;
/* ts A60924 : libburn/message.c gets obsoleted
burn_message_clear_queue();
*/
burn_print(1, "sync write of %d sessions\n", disc->sessions);
d->buffer = &buf;
@ -609,10 +484,6 @@ return crap. so we send the command, then ignore the result.
d->progress.sectors = 0;
d->progress.sector = 0;
/* ts A61023 */
d->progress.buffer_capacity = 0;
d->progress.buffer_available = 0;
d->busy = BURN_DRIVE_WRITING;
for (i = 0; i < disc->sessions; i++) {
@ -621,11 +492,6 @@ return crap. so we send the command, then ignore the result.
d->progress.tracks = disc->session[i]->tracks;
sheet = burn_create_toc_entries(o, disc->session[i]);
/* ts A61009 */
if (sheet == NULL)
goto fail;
/* print_cue(sheet);*/
if (o->write_type == BURN_WRITE_SAO)
d->send_cue_sheet(d, sheet);
@ -673,15 +539,8 @@ return crap. so we send the command, then ignore the result.
burn_print(1, "done\n");
d->busy = BURN_DRIVE_IDLE;
/* ts A61012 : This return was traditionally missing, a suspect this
to have caused Cdrskin_eject() failures */
return;
fail:
d->sync_cache(d);
burn_print(1, "done - failed\n");
libdax_msgs_submit(libdax_messenger, d->global_index, 0x0002010b,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Burn run failed", 0, 0);
d->busy = BURN_DRIVE_IDLE;
}

View File

@ -12,10 +12,6 @@ struct cue_sheet *burn_create_toc_entries(struct burn_write_opts *o,
struct burn_session *session);
int burn_sector_length(int trackmode);
int burn_subcode_length(int trackmode);
/* ts A61009 */
int burn_disc_write_is_ok(struct burn_write_opts *o, struct burn_disc *disc);
void burn_disc_write_sync(struct burn_write_opts *o, struct burn_disc *disc);
int burn_write_leadin(struct burn_write_opts *o,
struct burn_session *s, int first);

View File

@ -4,9 +4,6 @@
/**
* Utility functions for the Libisofs library.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wchar.h>
#include <iconv.h>
@ -424,11 +421,16 @@ void iso_bb(uint8_t *buf, uint32_t num, int bytes)
void iso_datetime_7(unsigned char *buf, time_t t)
{
static int tzsetup = 0;
int tzoffset;
static int tzoffset;
struct tm tm;
if (!tzsetup) {
tzset();
tzoffset = -timezone / 60 / 15;
if (tzoffset < -48)
tzoffset += 101;
tzsetup = 1;
}
@ -440,13 +442,6 @@ void iso_datetime_7(unsigned char *buf, time_t t)
buf[3] = tm.tm_hour;
buf[4] = tm.tm_min;
buf[5] = tm.tm_sec;
#ifdef HAVE_TM_GMTOFF
tzoffset = -tm.tm_gmtoff / 60 / 15;
#else
tzoffset = -timezone / 60 / 15;
#endif
if (tzoffset < -48)
tzoffset += 101;
buf[6] = tzoffset;
}
@ -477,6 +472,11 @@ void iso_datetime_17(unsigned char *buf, time_t t)
} else {
if (!tzsetup) {
tzset();
tzoffset = -timezone / 60 / 15;
if (tzoffset < -48)
tzoffset += 101;
tzsetup = 1;
}
@ -489,13 +489,6 @@ void iso_datetime_17(unsigned char *buf, time_t t)
sprintf((char*)&buf[10], "%02d", tm.tm_min);
sprintf((char*)&buf[12], "%02d", MIN(59, tm.tm_sec));
memcpy(&buf[14], "00", 2);
#ifdef HAVE_TM_GMTOFF
tzoffset = -tm.tm_gmtoff / 60 / 15;
#else
tzoffset = -timezone / 60 / 15;
#endif
if (tzoffset < -48)
tzoffset += 101;
buf[16] = tzoffset;
}
}

View File

@ -1,4 +0,0 @@
int main()
{
return 0;
}

View File

@ -1,215 +0,0 @@
/* dewav
Demo of libburn extension libdax_audioxtr
Audio track data extraction facility of libdax and libburn.
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
*/
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
/* libdax_audioxtr is quite independent of libburn. It only needs
the messaging facility libdax_msgs. So we got two build variations:
*/
#ifdef Dewav_without_libburN
/* This build environment is standalone relying only on libdax components */
#include "../libburn/libdax_msgs.h"
struct libdax_msgs *libdax_messenger= NULL;
#else /* Dewav_without_libburN */
/* This build environment uses libdax_msgs via libburn */
/* Thus the API header of libburn */
#include "../libburn/libburn.h"
#endif /* ! Dewav_without_libburN */
/* The API for .wav extraction */
#include "../libburn/libdax_audioxtr.h"
int main(int argc, char **argv)
{
/* This program acts as filter from in_path to out_path */
char *in_path= "", *out_path= "-";
/* The read-and-extract object for use with in_path */
struct libdax_audioxtr *xtr= NULL;
/* The file descriptor eventually detached from xtr */
int xtr_fd= -2;
/* Default output is stdout */
int out_fd= 1;
/* Inquired source parameters */
char *fmt, *fmt_info;
int num_channels, sample_rate, bits_per_sample, msb_first;
off_t data_size;
/* Auxiliary variables */
int ret, i, be_strict= 1, buf_count, detach_fd= 0, extract_all= 0;
char buf[2048];
if(argc < 2)
goto help;
for(i= 1; i<argc; i++) {
if(strcmp(argv[i],"-o")==0) {
if(i>=argc-1) {
fprintf(stderr,"%s: option -o needs a file address as argument.\n",
argv[0]);
exit(1);
}
i++;
out_path= argv[i];
} else if(strcmp(argv[i],"--lax")==0) {
be_strict= 0;
} else if(strcmp(argv[i],"--strict")==0) {
be_strict= 1;
} else if(strcmp(argv[i],"--detach_fd")==0) {
/* Test the dirty detach method. Always --extract_all */
detach_fd= 1;
} else if(strcmp(argv[i],"--extract_all")==0) {
/* Dirty : read all available bytes regardless of data_size */
extract_all= 1;
} else if(strcmp(argv[i],"--help")==0) {
help:;
fprintf(stderr,
"usage: %s [-o output_path|\"-\"] [--lax|--strict] [source_path|\"-\"]\n",
argv[0]);
exit(0);
} else {
if(in_path[0]!=0) {
fprintf(stderr,"%s: only one input file is allowed.\n", argv[0]);
exit(2);
}
in_path= argv[i];
}
}
if(in_path[0] == 0)
in_path= "-";
/* Depending on wether this was built standalone or with full libburn :
*/
#ifdef Dewav_without_libburN
/* Initialize and set up libdax messaging system */
ret= libdax_msgs_new(&libdax_messenger,0);
if(ret<=0) {
fprintf(stderr,"Failed to create libdax_messenger object.\n");
exit(3);
}
libdax_msgs_set_severities(libdax_messenger, LIBDAX_MSGS_SEV_NEVER,
LIBDAX_MSGS_SEV_NOTE, "", 0);
fprintf(stderr, "dewav on libdax\n");
#else /* Dewav_without_libburN */
/* Initialize libburn and set up its messaging system */
if(burn_initialize() == 0) {
fprintf(stderr,"Failed to initialize libburn.\n");
exit(3);
}
/* Print messages of severity NOTE or more directly to stderr */
burn_msgs_set_severities("NEVER", "NOTE", "");
fprintf(stderr, "dewav on libburn\n");
#endif /* ! Dewav_without_libburN */
/* Open audio source and create extractor object */
ret= libdax_audioxtr_new(&xtr, in_path, 0);
if(ret<=0)
exit(4);
if(strcmp(out_path,"-")!=0) {
out_fd= open(out_path, O_WRONLY | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
if(out_fd == -1) {
fprintf(stderr, "Cannot open file: %s\n", out_path);
fprintf(stderr, "Error reported: '%s' (%d)\n",strerror(errno), errno);
exit(5);
}
}
/* Obtain and print parameters of audio source */
libdax_audioxtr_get_id(xtr, &fmt, &fmt_info,
&num_channels, &sample_rate, &bits_per_sample, &msb_first, 0);
fprintf(stderr, "Detected format: %s\n", fmt_info);
libdax_audioxtr_get_size(xtr, &data_size, 0);
fprintf(stderr, "Data size : %.f bytes\n", (double) data_size);
if((strcmp(fmt,".wav")!=0 && strcmp(fmt,".au")!=0) ||
num_channels!=2 || sample_rate!=44100 || bits_per_sample!=16) {
fprintf(stderr,
"%sAudio source parameters do not comply to cdrskin/README specs\n",
(be_strict ? "" : "WARNING: "));
if(be_strict)
exit(6);
}
if(msb_first==0)
fprintf(stderr,
"NOTE: Extracted data to be written with cdrskin option -swab\n");
if(detach_fd) {
/* Take over fd from xtr */;
ret= libdax_audioxtr_detach_fd(xtr, &xtr_fd, 0);
if(ret<=0) {
fprintf(stderr, "Cannot detach file descriptor from extractor\n");
exit(8);
}
/* not needed any more */
libdax_audioxtr_destroy(&xtr, 0);
fprintf(stderr, "Note: detached fd and freed extractor object.\n");
}
/* Extract and put out raw audio data */;
while(1) {
if(detach_fd) {
buf_count= read(xtr_fd, buf, sizeof(buf));
if(buf_count==-1)
fprintf(stderr,"Error while reading from detached fd\n(%d) '%s'\n",
errno, strerror(errno));
} else {
buf_count= libdax_audioxtr_read(xtr, buf, sizeof(buf), !!extract_all);
}
if(buf_count < 0)
exit(7);
if(buf_count == 0)
break;
ret= write(out_fd, buf, buf_count);
if(ret == -1) {
fprintf(stderr, "Failed to write buffer of %d bytes to: %s\n",
buf_count, out_path);
fprintf(stderr, "Error reported: '%s' (%d)\n", strerror(errno), errno);
exit(5);
}
}
/* Shutdown */
if(out_fd>2)
close(out_fd);
/* ( It is permissible to do this with xtr==NULL ) */
libdax_audioxtr_destroy(&xtr, 0);
#ifdef Dewav_without_libburN
libdax_msgs_destroy(&libdax_messenger,0);
#else /* Dewav_without_libburN */
burn_finish();
#endif /* ! Dewav_without_libburN */
exit(0);
}

View File

@ -1,164 +0,0 @@
/* fake_au
Fakes a file in SUN .au format from a raw little-endian PCM audio file
(e.g. a file extracted from .wav by test/dewav). The input data are assumed
to be 16 bit, stereo, 44100 Hz.
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
Info used: http://www.opengroup.org/public/pubs/external/auformat.html
*/
#include <ctype.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
int fake_write(unsigned char *buf, size_t size, FILE *fp)
{
int ret;
ret= fwrite(buf,size,1,fp);
if(ret==1)
return(1);
fprintf(stderr,"Error %d while writing: '%s'\n",errno,strerror(errno));
return(0);
}
int main(int argc, char **argv)
{
int ret, i;
unsigned data_size= 0,byte_count,exit_value= 0;
FILE *fp_out= stdout,*fp_in= stdin;
unsigned char buf[4];
char out_path[4096],in_path[4096];
struct stat stbuf;
strcpy(out_path,"-");
strcpy(in_path,"");
if(argc < 2) {
exit_value= 1;
goto help;
}
for(i= 1; i<argc; i++) {
if(strcmp(argv[i],"-o")==0) {
if(i>=argc-1) {
fprintf(stderr,"%s: option -o needs a file address as argument.\n",
argv[0]);
exit(1);
}
i++;
strcpy(out_path, argv[i]);
} else if(strcmp(argv[i],"--stdin_size")==0) {
if(i>=argc-1) {
fprintf(stderr,"%s: option --stdin_size needs a number as argument.\n",
argv[0]);
exit(1);
}
i++;
sscanf(argv[i],"%u",&data_size);
} else if(strcmp(argv[i],"--help")==0) {
exit_value= 0;
help:;
fprintf(stderr,"usage: %s \\\n", argv[0]);
fprintf(stderr," [-o output_path|\"-\"] [source_path | --stdin_size size]\n");
fprintf(stderr,
"Disguises an extracted .wav stream as .au stereo, 16bit, 44100Hz\n");
fprintf(stderr,
"stdin gets byte-swapped and appended up to the announced data_size.\n");
exit(exit_value);
} else {
if(in_path[0]!=0) {
fprintf(stderr,"%s: only one input file is allowed.\n", argv[0]);
exit(1);
}
strcpy(in_path, argv[i]);
}
}
if(strcmp(in_path,"-")==0 || in_path[0]==0) {
if(data_size==0) {
fprintf(stderr,"%s: input from stdin needs option --stdin_size.\n",
argv[0]);
exit(6);
}
fp_in= stdin;
} else {
fp_in= fopen(in_path,"r");
if(stat(in_path,&stbuf)!=-1)
data_size= stbuf.st_size;
}
if(fp_in==NULL) {
fprintf(stderr,"Error %d while fopen(\"%s\",\"r\") : '%s'\n",
errno,in_path,strerror(errno));
exit(2);
}
if(strcmp(out_path,"-")==0) {
fp_out= stdout;
} else {
if(stat(out_path,&stbuf)!=-1) {
fprintf(stderr,"%s: file '%s' already existing\n",argv[0],out_path);
exit(4);
}
fp_out= fopen(out_path,"w");
}
if(fp_out==NULL) {
fprintf(stderr,"Error %d while fopen(\"%s\",\"w\") : '%s'\n",
errno,out_path,strerror(errno));
exit(2);
}
fake_write((unsigned char *) ".snd",4,fp_out); /* magic number */
buf[0]= buf[1]= buf[2]= 0;
buf[3]= 32;
fake_write(buf,4,fp_out); /* data_location */
buf[0]= (data_size>>24)&0xff;
buf[1]= (data_size>>16)&0xff;
buf[2]= (data_size>>8)&0xff;
buf[3]= (data_size)&0xff;
fake_write(buf,4,fp_out); /* data_size */
buf[0]= buf[1]= buf[2]= 0;
buf[3]= 3;
fake_write(buf,4,fp_out); /* encoding 16 Bit PCM */
buf[0]= buf[1]= 0;
buf[2]= 172;
buf[3]= 68;
fake_write(buf,4,fp_out); /* sample rate 44100 Hz */
buf[0]= buf[1]= buf[2]= 0;
buf[3]= 2;
fake_write(buf,4,fp_out); /* number of channels */
buf[0]= buf[1]= buf[2]= buf[3]= 0;
fake_write(buf,4,fp_out); /* padding */
fake_write(buf,4,fp_out); /* padding */
for(byte_count= 0; byte_count<data_size; byte_count+=2) {
ret= fread(buf,2,1,fp_in);
if(ret<=0) {
fprintf(stderr,"Premature end end of input\n");
exit_value= 5;
break;
}
buf[3]= buf[0];
buf[2]= buf[1];
ret= fake_write(buf+2,2,fp_out);
if(ret<=0) {
exit_value= 3;
break;
}
}
if(fp_out!=stdout)
fclose(fp_out);
if(fp_in!=stdin)
fclose(fp_in);
fprintf(stderr, "Swapped and appended: %u stdin bytes\n",byte_count);
exit(exit_value);
}

View File

@ -16,8 +16,6 @@
Before you can do anything, you have to initialize libburn by
burn_initialize()
and provide some signal and abort handling, e.g. by the builtin handler, by
burn_set_signal_handling()
as it is done in main() at the end of this file. Then you aquire a
drive in an appropriate way conforming to the API. The two main
approaches are shown here in application functions:
@ -76,6 +74,13 @@ static unsigned int drive_count;
static int drive_is_grabbed = 0;
/** Here you may enable simulated burn by default. This does not apply to
blanking. Anyway, some CD recorders obey the request to simulate, some do
not. Explicit options are: --burn_for_real and --try_to_simulate
*/
static int simulate_burn = 0;
/* Some in-advance definitions to allow a more comprehensive ordering
of the functions and their explanations in here */
int libburner_aquire_by_adr(char *drive_adr);
@ -243,15 +248,17 @@ int libburner_aquire_by_driveno(int *driveno)
To our knowledge it is hardly possible to abort an ongoing blank operation
because after start it is entirely handled by the drive.
So expect signal handling to wait the normal blanking timespan until it
can allow the process to end. External kill -9 will not help the drive.
So expect a blank run to survive the end of the blanking process and be
patient for the usual timespan of a normal blank run. Only after that
time has surely elapsed, only then you should start any rescue attempts
with the drive. If necessary at all.
*/
int libburner_blank_disc(struct burn_drive *drive, int blank_fast)
{
enum burn_disc_status disc_state;
struct burn_progress progress;
while (burn_drive_get_status(drive, NULL) != BURN_DRIVE_IDLE)
while (burn_drive_get_status(drive, NULL))
usleep(1001);
while ((disc_state = burn_disc_get_status(drive)) == BURN_DISC_UNREADY)
@ -284,7 +291,7 @@ int libburner_blank_disc(struct burn_drive *drive, int blank_fast)
printf(
"Expect some garbage sector numbers and some zeros at first.\n");
burn_disc_erase(drive, blank_fast);
while (burn_drive_get_status(drive, &progress) != BURN_DRIVE_IDLE) {
while (burn_drive_get_status(drive, &progress)) {
printf("Blanking sector %d\n", progress.sector);
sleep(1);
}
@ -314,74 +321,76 @@ int libburner_regrab(struct burn_drive *drive) {
}
/** Brings preformatted track images (ISO 9660, audio, ...) onto media.
To make sure a data image is fully readable on any Linux machine, this
function adds 300 kB of padding to the (usualy single) track.
Audio tracks get padded to complete their last sector.
/** Brings the preformatted image (ISO 9660, afio, ext2, whatever) onto media.
In case of external signals expect abort handling of an ongoing burn to
last up to a minute. Wait the normal burning timespan before any kill -9.
To make sure your image is fully readable on any Linux machine, this
function adds 300 kB of padding to the track.
Without a signal handler it is quite dangerous to abort the process
while this function is active. See cdrskin/cdrskin.c and its usage
of cdrskin/cleanup.[ch] for an example of application provided
abort handling. It must cope with 2 of 3 threads reporting for
being handled.
Without signal handler have ready a command line
cdrecord dev=... -reset
with a dev= previously inquired by cdrecord [dev=ATA] -scanbus
in order to get your drive out of shock state after raw abort.
Thanks to Joerg Schilling for helping out unquestioned. :)
In general, libburn is less prone to system problems than cdrecord,
i believe. But cdrecord had long years of time to complete itself.
We are still practicing. Help us with that. :))
*/
int libburner_payload(struct burn_drive *drive,
char source_adr[][4096], int source_adr_count,
off_t stdin_size, int simulate_burn, int all_tracks_type)
int libburner_payload(struct burn_drive *drive, const char *source_adr,
off_t size)
{
struct burn_source *data_src;
struct burn_disc *target_disc;
struct burn_session *session;
struct burn_write_opts *burn_options;
enum burn_disc_status disc_state;
struct burn_track *track, *tracklist[99];
struct burn_track *track;
struct burn_progress progress;
time_t start_time;
int last_sector = 0, padding = 0, trackno;
char *adr;
if (all_tracks_type != BURN_AUDIO) {
all_tracks_type = BURN_MODE1;
/* a padding of 300 kB helps to avoid the read-ahead bug */
padding = 300*1024;
}
int last_sector = 0;
target_disc = burn_disc_create();
session = burn_session_create();
burn_disc_add_session(target_disc, session, BURN_POS_END);
track = burn_track_create();
for (trackno = 0 ; trackno < source_adr_count; trackno++) {
tracklist[trackno] = track = burn_track_create();
burn_track_define_data(track, 0, padding, 1, all_tracks_type);
/* a padding of 300 kB is helpful to avoid the read-ahead bug */
burn_track_define_data(track, 0, 300*1024, 1, BURN_MODE1);
adr = source_adr[trackno];
if (adr[0] == '-' && adr[1] == 0) {
data_src = burn_fd_source_new(0, -1, stdin_size);
if (source_adr[0] == '-' && source_adr[1] == 0) {
data_src = burn_fd_source_new(0, -1, size);
printf("Note: using standard input as source with %.f bytes\n",
(double) stdin_size);
} else
data_src = burn_file_source_new(adr, NULL);
if (data_src == NULL) {
(double) size);
} else
data_src = burn_file_source_new(source_adr, NULL);
if (data_src == NULL) {
fprintf(stderr,
"FATAL: Could not open data source '%s'.\n",adr);
"FATAL: Could not open data source '%s'.\n",source_adr);
if(errno!=0)
fprintf(stderr,"(Most recent system error: %s )\n",
strerror(errno));
return 0;
}
if (burn_track_set_source(track, data_src) != BURN_SOURCE_OK) {
}
if (burn_track_set_source(track, data_src) != BURN_SOURCE_OK) {
printf("FATAL: Cannot attach source object to track object\n");
return 0;
}
}
burn_session_add_track(session, track, BURN_POS_END);
burn_source_free(data_src);
burn_session_add_track(session, track, BURN_POS_END);
printf("Track %d : source is '%s'\n", trackno, adr);
burn_source_free(data_src);
} /* trackno loop end */
while (burn_drive_get_status(drive, NULL) != BURN_DRIVE_IDLE)
usleep(100001);
while (burn_drive_get_status(drive, NULL))
usleep(1001);
/* Evaluate drive and media */
while ((disc_state = burn_disc_get_status(drive)) == BURN_DISC_UNREADY)
usleep(100001);
usleep(1001);
if (disc_state != BURN_DISC_BLANK) {
if (disc_state == BURN_DISC_FULL ||
disc_state == BURN_DISC_APPENDABLE) {
@ -429,21 +438,19 @@ int libburner_payload(struct burn_drive *drive,
burn_write_opts_free(burn_options);
while (burn_drive_get_status(drive, NULL) == BURN_DRIVE_SPAWNING)
usleep(1002);
while (burn_drive_get_status(drive, &progress) != BURN_DRIVE_IDLE) {
while (burn_drive_get_status(drive, &progress)) {
if( progress.sectors <= 0 || progress.sector == last_sector)
printf(
"Thank you for being patient since %d seconds.\n",
(int) (time(0) - start_time));
else
printf("Track %d : sector %d of %d\n", progress.track,
printf("Burning sector %d of %d\n",
progress.sector, progress.sectors);
last_sector = progress.sector;
sleep(1);
}
printf("\n");
for (trackno = 0 ; trackno < source_adr_count; trackno++)
burn_track_free(tracklist[trackno]);
burn_track_free(track);
burn_session_free(session);
burn_disc_free(target_disc);
if(simulate_burn)
@ -452,34 +459,28 @@ int libburner_payload(struct burn_drive *drive,
}
/** The setup parameters of libburn */
static char drive_adr[BURN_DRIVE_ADR_LEN]= {""};
static int driveno= 0;
static int do_blank= 0;
static char source_adr[99][4096];
static int source_adr_count= 0;
static off_t stdin_size= 650*1024*1024;
static int simulate_burn = 0;
static int all_tracks_type = BURN_MODE1;
/** Converts command line arguments into above setup parameters.
/** Converts command line arguments into a few program parameters.
drive_adr[] must provide at least BURN_DRIVE_ADR_LEN bytes.
source_adr[] must provide at least 4096 bytes.
*/
int libburner_setup(int argc, char **argv)
int libburner_setup(int argc, char **argv, char drive_adr[], int *driveno,
int *do_blank, char source_adr[], off_t *size)
{
int i, insuffient_parameters = 0, print_help = 0;
int i, insuffient_parameters = 0;
int print_help = 0;
drive_adr[0] = 0;
*driveno = 0;
*do_blank = 0;
source_adr[0] = 0;
*size = 650*1024*1024;
for (i = 1; i < argc; ++i) {
if (!strcmp(argv[i], "--audio")) {
all_tracks_type = BURN_AUDIO;
} else if (!strcmp(argv[i], "--blank_fast")) {
do_blank = 1;
if (!strcmp(argv[i], "--blank_fast")) {
*do_blank = 1;
} else if (!strcmp(argv[i], "--blank_full")) {
do_blank = 2;
*do_blank = 2;
} else if (!strcmp(argv[i], "--burn_for_real")) {
simulate_burn = 0;
@ -491,10 +492,10 @@ int libburner_setup(int argc, char **argv)
return 1;
} else if (strcmp(argv[i], "-") == 0) {
drive_adr[0] = 0;
driveno = -1;
*driveno = -1;
} else if (isdigit(argv[i][0])) {
drive_adr[0] = 0;
driveno = atoi(argv[i]);
*driveno = atoi(argv[i]);
} else {
if(strlen(argv[i]) >= BURN_DRIVE_ADR_LEN) {
fprintf(stderr,"--drive address too long (max. %d)\n",
@ -509,62 +510,58 @@ int libburner_setup(int argc, char **argv)
fprintf(stderr,"--stdin_size requires an argument\n");
return 3;
} else
stdin_size = atoi(argv[i]);
if (stdin_size < 600*1024) /* minimum readable track size */
stdin_size = 600*1024;
*size = atoi(argv[i]);
if (*size < 600*1024) /* seems to be minimum readable track size */
*size = 600*1024;
} else if (!strcmp(argv[i], "--try_to_simulate")) {
simulate_burn = 1;
} else if (!strcmp(argv[i], "--verbose")) {
++i;
if (i >= argc) {
fprintf(stderr,"--verbose requires an argument\n");
return 4;
} else
burn_set_verbosity(atoi(argv[i]));
} else if (!strcmp(argv[i], "--help")) {
print_help = 1;
} else if (!strncmp(argv[i], "--",2)) {
fprintf(stderr, "Unidentified option: %s\n", argv[i]);
return 7;
} else {
if(strlen(argv[i]) >= 4096) {
fprintf(stderr, "Source address too long (max. %d)\n", 4096-1);
return 5;
}
if(source_adr_count >= 99) {
fprintf(stderr, "Too many tracks (max. 99)\n");
return 6;
}
strcpy(source_adr[source_adr_count], argv[i]);
source_adr_count++;
strcpy(source_adr, argv[i]);
}
}
insuffient_parameters = 1;
if (driveno < 0)
if (*driveno < 0)
insuffient_parameters = 0;
if (source_adr_count > 0)
if (source_adr[0] != 0)
insuffient_parameters = 0;
if (do_blank)
if (*do_blank)
insuffient_parameters = 0;
if (print_help || insuffient_parameters ) {
printf("Usage: %s\n", argv[0]);
printf(" [--drive <address>|<driveno>|\"-\"]\n");
printf(" [--blank_fast|--blank_full] [--audio]\n");
printf(" [--try_to_simulate] [--stdin_size <bytes>]\n");
printf(" [<one or more imagefiles>|\"-\"]\n");
printf(" [--verbose <level>] [--blank_fast|--blank_full]\n");
printf(" [--burn_for_real|--try_to_simulate] [--stdin_size <bytes>]\n");
printf(" [<imagefile>|\"-\"]\n");
printf("Examples\n");
printf("A bus scan (needs rw-permissions to see a drive):\n");
printf(" %s --drive -\n",argv[0]);
printf("Burn a file to drive chosen by number:\n");
printf(" %s --drive 0 my_image_file\n",
printf(" %s --drive 0 --burn_for_real my_image_file\n",
argv[0]);
printf("Burn a file to drive chosen by persistent address:\n");
printf(" %s --drive /dev/hdc my_image_file\n", argv[0]);
printf(" %s --drive /dev/hdc --burn_for_real my_image_file\n", argv[0]);
printf("Blank a used CD-RW (is combinable with burning in one run):\n");
printf(" %s --drive /dev/hdc --blank_fast\n",argv[0]);
printf("Burn two audio tracks\n");
printf(" lame --decode -t /path/to/track1.mp3 track1.cd\n");
printf(" test/dewav /path/to/track2.wav -o track2.cd\n");
printf(" %s --drive /dev/hdc --audio track1.cd track2.cd\n", argv[0]);
printf(" %s --drive 0 --blank_fast\n",argv[0]);
printf("Burn a compressed afio archive on-the-fly, pad up to 700 MB:\n");
printf(" ( cd my_directory ; find . -print | afio -oZ - ) | \\\n");
printf(" %s --drive /dev/hdc --stdin_size 734003200 -\n", argv[0]);
printf("To be read from *not mounted* CD via: afio -tvZ /dev/hdc\n");
printf(" %s --drive /dev/hdc --burn_for_real --stdin_size 734003200 -\n", argv[0]);
printf("To be read from *not mounted* CD via:\n");
printf(" afio -tvZ /dev/hdc\n");
printf("Program tar would need a clean EOF which our padded CD cannot deliver.\n");
if (insuffient_parameters)
return 6;
@ -575,28 +572,24 @@ int libburner_setup(int argc, char **argv)
int main(int argc, char **argv)
{
int ret;
int driveno, ret, do_blank;
char source_adr[4096], drive_adr[BURN_DRIVE_ADR_LEN];
off_t stdin_size;
ret = libburner_setup(argc, argv);
ret = libburner_setup(argc, argv, drive_adr, &driveno, &do_blank,
source_adr, &stdin_size);
if (ret)
exit(ret);
printf("Initializing libburn.pykix.org ...\n");
printf("Initializing library ...\n");
if (burn_initialize())
printf("Done\n");
else {
printf("FAILED\n");
fprintf(stderr,"\nFATAL: Failed to initialize.\n");
fprintf(stderr,"\nFATAL: Failed to initialize libburn.\n");
exit(33);
}
/* Print messages of severity SORRY or more directly to stderr */
burn_msgs_set_severities("NEVER", "SORRY", "libburner : ");
/* Activate the default signal handler which eventually will try to
properly shutdown drive and library on aborting events. */
burn_set_signal_handling("libburner : ", NULL, 0);
/** Note: driveno might change its value in this call */
ret = libburner_aquire_drive(drive_adr, &driveno);
if (ret<=0) {
@ -610,7 +603,7 @@ int main(int argc, char **argv)
do_blank == 1);
if (ret<=0)
{ ret = 36; goto release_drive; }
if (ret != 2 && source_adr_count > 0)
if (ret != 2 && source_adr[0] != 0)
ret = libburner_regrab(drive_list[driveno].drive);
if (ret<=0) {
fprintf(stderr,
@ -618,10 +611,9 @@ int main(int argc, char **argv)
{ ret = 37; goto finish_libburn; }
}
}
if (source_adr_count > 0) {
ret = libburner_payload(drive_list[driveno].drive,
source_adr, source_adr_count, stdin_size,
simulate_burn, all_tracks_type);
if (source_adr[0] != 0) {
ret = libburner_payload(drive_list[driveno].drive, source_adr,
stdin_size);
if (ret<=0)
{ ret = 38; goto release_drive; }
}
@ -636,7 +628,7 @@ finish_libburn:;
/* burn_drive_info_free(drive_list); */
burn_finish();
exit(ret);
return ret;
}

View File

@ -1,126 +0,0 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
#include <libburn/libburn.h>
#include <stdio.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
static struct burn_drive_info *drives;
static unsigned int n_drives;
void burn_files(struct burn_drive *drive, struct burn_disc *disc)
{
struct burn_write_opts *o;
enum burn_disc_status s;
if (!burn_drive_grab(drive, 1)) {
printf("Unable to open the drive!\n");
return;
}
while (burn_drive_get_status(drive, NULL))
usleep(1000);
while ((s = burn_disc_get_status(drive)) == BURN_DISC_UNREADY)
usleep(1000);
if (s != BURN_DISC_BLANK) {
burn_drive_release(drive, 0);
printf("Please insert blank media in the drive\n");
return;
}
o = burn_write_opts_new(drive);
burn_drive_set_speed(drive, 0, 2816);
burn_write_opts_set_perform_opc(o, 0);
burn_write_opts_set_write_type(o, BURN_WRITE_TAO, BURN_BLOCK_MODE1);
burn_write_opts_set_simulate(o, 1);
/* want failure on seggy while debugging :) */
burn_write_opts_set_underrun_proof(o, 0);
burn_structure_print_disc(disc);
burn_disc_write(o, disc);
burn_write_opts_free(o);
while (burn_drive_get_status(drive, NULL)) {
sleep(1);
}
printf("\n");
burn_drive_release(drive, 0);
burn_disc_free(disc);
}
void parse_args(int argc, char **argv, int *drive, struct burn_disc **disc)
{
int i, tmode = BURN_AUDIO;
int help = 1;
struct burn_session *session;
struct burn_track *tr;
struct burn_source *src;
*disc = burn_disc_create();
session = burn_session_create();
burn_disc_add_session(*disc, session, BURN_POS_END);
for (i = 1; i < argc; ++i) {
if (!strcmp(argv[i], "--drive")) {
++i;
if (i >= argc)
printf("--drive requires an argument\n");
else
*drive = atoi(argv[i]);
} else if (!strcmp(argv[i], "--audio")) {
tmode = BURN_AUDIO;
} else if (!strcmp(argv[i], "--data")) {
tmode = BURN_MODE1;
} else if (!strcmp(argv[i], "--verbose")) {
++i;
if (i >= argc)
printf("--verbose requires an argument\n");
else
burn_set_verbosity(atoi(argv[i]));
} else if (!strcmp(argv[i], "--help")) {
help = 1; /* who cares */
} else {
help = 0;
printf("%s is a track\n", argv[i]);
tr = burn_track_create();
src = burn_file_source_new(argv[i], NULL);
burn_track_set_source(tr, src);
burn_source_free(src);
burn_track_define_data(tr, 0, 0, 1, tmode);
burn_session_add_track(session, tr, BURN_POS_END);
}
}
if (help) {
printf("Usage: %s [--drive <num>] [--verbose <level>] files\n",
argv[0]);
exit(EXIT_FAILURE);
}
}
int main(int argc, char **argv)
{
int drive = 0;
struct burn_disc *disc;
parse_args(argc, argv, &drive, &disc);
printf("Initializing library...");
if (burn_initialize())
printf("Success\n");
else {
printf("Failed\n");
return 1;
}
printf("Scanning for devices...");
while (!burn_drive_scan(&drives, &n_drives)) ;
printf("Done\n");
burn_files(drives[drive].drive, disc);
burn_drive_info_free(drives);
burn_finish();
return 0;
}

View File

@ -1,54 +0,0 @@
/* THIS IS NOT A PROPER EXAMPLE */
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <libburn/libburn.h>
static struct burn_drive_info *drives;
static unsigned int n_drives;
#warning this example is totally fried
int main()
{
#if 0
struct burn_drive *drive;
struct burn_read_opts o;
burn_initialize();
o.datafd =
open("/xp/burn/blah.data", O_CREAT | O_WRONLY,
S_IRUSR | S_IWUSR);
o.subfd =
open("/xp/burn/blah.sub", O_CREAT | O_WRONLY,
S_IRUSR | S_IWUSR);
o.raw = 1;
o.c2errors = 0;
o.subcodes_audio = 1;
o.subcodes_data = 1;
o.hardware_error_recovery = 1;
o.report_recovered_errors = 0;
o.transfer_damaged_blocks = 1;
o.hardware_error_retries = 1;
printf("Scanning for devices...");
while (!burn_drive_scan(&drives, &n_drives)) ;
printf("Done\n");
drive = drives[0].drive;
burn_drive_set_speed(drive, 0, 0);
if (!burn_drive_grab(drive, 1)) {
printf("Unable to open the drive!\n");
return EXIT_FAILURE;
}
while (burn_drive_get_status(drive, NULL))
usleep(1000);
burn_disc_read(drive, &o);
#endif
return EXIT_SUCCESS;
}

Binary file not shown.