Compare commits

...

110 Commits

Author SHA1 Message Date
7e01bae7e6 Documented changes and release timestamp 2010-06-11 09:57:58 +00:00
7c0a33420a Updated cdrskin tarball generator 2010-06-11 08:34:07 +00:00
101a8813d5 Made number transition to 0.8.2 2010-06-11 08:32:24 +00:00
3a5acf9989 Branching for libburn release 0.8.2 2010-06-11 07:50:01 +00:00
e9828cddd0 Mentioned Solaris and system dependent drive permission settings 2010-06-10 17:23:23 +00:00
7f0358892a Removed obsolete development remark 2010-06-10 17:09:50 +00:00
bc40ce2876 Implemented block device capacity determination fo Solaris 2010-06-08 20:04:01 +00:00
6674667b7f Handled SCSI status "BUSY" on Solaris 2010-06-08 17:50:33 +00:00
cc4d72bf8b Corrected comment 2010-06-08 17:32:44 +00:00
1eee6ab8a0 New system adapter for Solaris uscsi (tested on snv134, kernel 5.11) 2010-06-07 17:30:54 +00:00
736d8b9019 Reacted on harmless compiler warnings on Solaris 2010-06-07 17:17:53 +00:00
8345eb8a71 Avoiding to resolve /dev/rdsk/cXtYdZs2 drive addresses on Solaris libcdio 2010-06-07 17:16:40 +00:00
cc7548f1c7 Bug fix: SIGSEGV of libcdio system adapter if drive list is empty 2010-05-29 07:44:41 +00:00
edca339338 Eventually including ../config.h generated by autotools 2010-05-16 09:07:42 +00:00
9323cceff1 Bug fix: CD-ROM media got attributed random lead-in and lead-out adresses 2010-05-01 08:29:28 +00:00
8b1b3f08c6 Avoided to create track without toc_entry from "hidden first track" on CD 2010-04-30 18:04:47 +00:00
e332f4a438 Documented changes and release timestamp 2010-04-09 11:13:19 +00:00
960fe6d188 Updated cdrskin tarball generator 2010-04-09 10:59:32 +00:00
92c5f6f998 Made number transition to 0.8.1 2010-04-09 10:57:38 +00:00
2069ffa863 Reporting eventual SCSI sense in sg-linux repeat loop 2010-04-09 09:07:59 +00:00
e787d328c7 Let libburner warn programmers if they forget to set 64 bit off_t 2010-04-04 18:13:45 +00:00
fafc190fd4 Adjusted libcdio system adapter to FreeBSD peculiarities 2010-03-29 10:33:05 +00:00
e6029ae238 Trying to detect FreeBSD ahci devices and to handle others the old way 2010-03-27 17:27:50 +00:00
6e17c59f6b Avoiding to inquire NWA of unwritable media or states 2010-03-27 15:58:05 +00:00
0e777ec688 Had to make ahci change conditional for now: -DLibburn_for_freebsd_ahcI 2010-03-26 08:33:22 +00:00
8dcdb5a87f Changed sg-freebsd.c to work with ahci, advise by Alexander Motin 2010-03-25 11:36:55 +00:00
4f372c00bc Corrected initialization of configure option --enable-dvd-obs-64k 2010-03-17 18:54:10 +00:00
9f6d80d87d Small bug fix about track size with cdrskin -minfo 2010-03-17 18:53:28 +00:00
b33df8fbd5 Documented changes and release timestamp 2010-03-10 13:58:50 +00:00
b4bb522053 Updated cdrskin tarball generator 2010-03-10 13:58:03 +00:00
3289ffd1e6 Made number transition to 0.7.9 2010-03-10 13:56:58 +00:00
196ef37108 Clarifications in API description of burn_set_signal_handling() 2010-03-09 14:01:57 +00:00
cdad7fcd80 Prevented potential memory fault with burn_set_signal_handling() 2010-03-08 09:24:21 +00:00
ed6e2df81b Changed examples burn_set_signal_handling(...,48) to (...,0x30) 2010-03-07 08:15:21 +00:00
ae667ca2e8 Adapted libburner to new advise about signal handling 2010-03-06 13:52:21 +00:00
873e3f5d78 Protected blanker and formatter thread from signals 2010-03-05 18:59:21 +00:00
72f9ff8b8c Removed some debugging printing 2010-03-05 11:15:28 +00:00
eb95f7fc16 Enabled optional use of new signal action 2 with libburn built-in handler 2010-03-05 09:12:44 +00:00
3519b42c14 Introduced alternative signal handling actions 2010-03-05 09:08:16 +00:00
b4e5afd317 Changed burn_abort(0) to burn_abort(-1) 2010-03-04 17:59:42 +00:00
7446ed7daa Showing more patience with temporarily busy drives on Linux 2010-03-04 12:13:04 +00:00
2d40b098e5 Enabled static compile script compile_cdrskin.sh for FreeBSD 2010-03-03 15:29:16 +00:00
ac64aef090 Enabled static compile script compile_cdrskin.sh for FreeBSD 2010-03-03 14:43:21 +00:00
74a68adc6e Adapted cdrskin abort handler to FreeBSD peculiarities 2010-03-03 14:12:22 +00:00
937bc87bfc Enabled patience 0 within burn_abort() 2010-03-03 14:05:07 +00:00
de482489c1 Corrected spelling errors in cdrskin man page 2010-02-28 16:53:09 +00:00
295fa1d526 Bug fix: cdrskin fs=0 lead to SIGSEGV. Regression introduced by revision 2936. 2010-02-28 11:06:02 +00:00
99bba3e98e Added forgotten initialization of a variable 2010-02-28 10:38:15 +00:00
bd3016e085 Corrected optional speed curb for stdio: drives. Was damaged by revision 2903. 2010-02-25 07:04:52 +00:00
dd74364ebb Made burn_set_signal_handling() more suitable for cdrskin 2010-02-22 13:47:17 +00:00
255e5362f9 Avoided random percentage display at start of blanking 2010-02-17 14:12:23 +00:00
471a0d0058 Bug fix on FreeBSD: Piped input was falsely attributed a small fixed size 2010-02-16 19:40:07 +00:00
f5b556db47 Changed a comment in libburn/crc.h 2010-02-15 12:57:38 +00:00
c12bbff7d1 Created opportunity to omit source module libburn/crc.c 2010-02-14 17:17:04 +00:00
6db992e646 Added or adjusted copyright and license statements in single files 2010-02-14 08:45:14 +00:00
bd017a108e Changed docs and comments to "GNU/Linux" where appropriate 2010-02-12 21:26:46 +00:00
3a76f9245f Changed system adapter id and some remarks from "Linux" to "GNU/Linux" 2010-02-12 17:30:59 +00:00
580ca08cc5 Forcing use of /usr/local on FreeBSD by LDFLAGS and CPPFLAGS 2010-02-04 08:31:31 +00:00
a6bd4c24db Updated cdrskin tarball generator 2010-01-23 10:44:04 +00:00
54005cb60e Lifted ban to derive GPLv3, extended copyright range to 2010 2010-01-23 10:42:52 +00:00
15fbe0a7ea Made number transition to 0.7.7 2010-01-23 10:40:11 +00:00
da1d260753 Learned how to inquire size of disk-like FreeBSD devices 2010-01-21 10:46:04 +00:00
95865ee34d Changed man page example from -toc to -minfo 2010-01-21 10:38:56 +00:00
eb8b8faa3b Changed a comment in sg-linux.c 2010-01-18 10:32:36 +00:00
39fd8b922d New OS adapter burn_os_is_2k_seekrw() replaces S_ISBLK() with pseudo-drives 2010-01-16 12:51:24 +00:00
7ead54c8b9 Implemented adivisory FreeBSD drive locking via flock(2) 2010-01-15 18:25:14 +00:00
2a85fc7d91 Provisory rejection of FreeBSD ATAPI drives in sg-libcdio 2010-01-14 16:06:17 +00:00
1e42a76415 Giving up drive probing by mode page sending 2010-01-14 16:04:57 +00:00
734759190a Carified in libburner.c that apps must use 64 bit off_t. 2010-01-14 14:09:30 +00:00
16ffa10831 Carified in libburner.c that apps must use 64 bit off_t. 2010-01-14 14:01:13 +00:00
cdfc357064 Carified that apps must use 64 bit off_t or the lib must be tweaked. 2010-01-13 17:14:14 +00:00
df612390d3 Adaptions after encounter with FreeBSD 8.0 2010-01-13 07:45:07 +00:00
77971f3680 Experimentally regard FreeBSD /dev/da[0-9] and /dev/cd[0-9] as block device 2010-01-13 07:38:56 +00:00
5c75d583d7 Fixed typos in MMC cookbook 2010-01-12 16:51:48 +00:00
2ff03841d7 Corrected free capacity measurement of stdio: drives in regular files 2010-01-12 16:50:44 +00:00
a88745c82e Revoked asynchronous eject, as we cannot distinguish out from unready 2010-01-09 14:32:51 +00:00
96167b3d8e Better error message with unknown SCSI error codes 2010-01-09 14:25:19 +00:00
1ca38962d4 Forgot to forward sense reply to higher levels 2010-01-09 14:18:55 +00:00
80bcabfd57 Enlarged buffer size of libcdio adapter on Linux to 64k 2010-01-04 13:52:57 +00:00
d9239aeafc Avoiding stream recording on BD if not 64 kB buffer 2010-01-04 13:49:05 +00:00
758a197d06 Enabled block device size recognition with sg-libcdio on Linux 2010-01-01 12:43:15 +00:00
ed972271ec Bug fix: with non-Linux adapters there were 0 readable bytes on block devices 2010-01-01 12:39:20 +00:00
0544ac8cd3 Silenced libcdio warnings 2009-12-30 20:08:51 +00:00
12a2be8d86 Making use of new libcdio capability to obtain SCSI address tuple on Linux 2009-12-30 15:40:10 +00:00
509db68d82 Adaptions for Debian kfreebsd requested by Petr Salinger 2009-12-29 22:43:35 +00:00
00ed59f34e Experimentally enabled FreeBSD system adapter for Debian kfreebsd 2009-12-29 13:31:56 +00:00
2b8e8c2521 Corrected a mode page size computation error which for now had no bad effect 2009-12-29 11:57:21 +00:00
e3ff0bb0f6 Incremented middle .so number 2009-12-29 11:55:48 +00:00
8efb24ca6d Reporting system adapter id with cdrskin -version 2009-12-27 14:46:01 +00:00
d53c5db98e Extended sg-API by sg_shutdown(), sg_dispose_drive(), sg_id_string() 2009-12-27 14:45:05 +00:00
0320b7bf2a Shorter sg_initialize message with sg-libcdio 2009-12-27 10:22:11 +00:00
cee271f9cb Showing libburn users drive name link targets, using in libcdio its own names 2009-12-27 09:20:10 +00:00
c2a3e3677d Reacted on some doxygen warnings of Debian hurd build 2009-12-26 22:25:45 +00:00
fc3445215b Reporting burn_scsi_transport_id() in cdrskin as debug message 2009-12-26 19:35:42 +00:00
4ce8bd45cf Added os-dummy.h and sg-dummy.h to libburn tarball 2009-12-26 08:49:59 +00:00
08169d63bc New API function burn_scsi_transport_id() 2009-12-26 08:01:35 +00:00
e13b6369ba New internal sg-API function sg_initialize() 2009-12-25 22:37:57 +00:00
d3988dd74b Adapted to libcdio-0.83 and its runtime version telling 2009-12-25 20:55:37 +00:00
ef42052900 Added PKG_CHECK_MODULES for libcdio-0.82 (must become 0.83 when released) 2009-12-25 14:40:16 +00:00
240afa7c3a Resolving symbolic links in libcdio drive list 2009-12-25 14:31:55 +00:00
5b72e5d06e Commited file forgotten with rev 2960 2009-12-25 10:13:06 +00:00
4aa08e32ff Option -use_libcdio for cdrskin development compile script 2009-12-25 10:12:22 +00:00
eb34561262 Making use of libcdio function mmc_get_cmd_scsi_sense() 2009-12-24 17:04:40 +00:00
dd85e37ac8 Experimental SCSI transport adapter via GNU libcdio 2009-12-19 14:34:48 +00:00
e566340261 Moved sg_log_cmd() to spc.c scsi_log_cmd() 2009-12-19 14:23:30 +00:00
7e86db207c Corrected CDB length of command 55h MODE SELECT from 12 to 10 2009-12-19 13:59:09 +00:00
a30ecd1abb Mentioned in cookbook the change about TAO close track 2009-12-16 07:39:39 +00:00
45b28b6c31 Documented changes and release timestamp 2009-12-07 07:56:32 +00:00
afedcdd72b Updated cdrskin tarball generator 2009-12-07 07:55:25 +00:00
b8a98e0728 Made number transition to 0.7.5 2009-12-07 07:54:24 +00:00
75 changed files with 5929 additions and 590 deletions

View File

@ -1,12 +1,12 @@
Derek Foreman <derek@signalmarketing.com> and Ben Jansens <xor@orodu.net>
Copyright (C) 2002-2006 Derek Foreman and Ben Jansens
Mario Danic <mario.danic@gmail.com>, Thomas Schmitt <scdbackup@gmx.net>
Copyright (C) 2006-2009 Mario Danic, Thomas Schmitt
Copyright (C) 2006-2010 Mario Danic, Thomas Schmitt
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
it under the terms of the GNU General Public License version 2 or later
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of

View File

@ -70,9 +70,6 @@ libburn_libburn_la_SOURCES = \
libburn/write.h \
version.h
## libburn/lec.c \
## libburn/lec.h \
## libburn/sg-@ARCH@.c \
libinclude_HEADERS = \
@ -113,9 +110,9 @@ test_structest_CPPFLAGS = -Ilibburn
test_structest_LDADD = $(libburn_libburn_la_OBJECTS) $(LIBBURN_EXTRALIBS)
test_structest_SOURCES = test/structest.c
## cdrskin construction site - ts A60816 - A91012
## cdrskin construction site - ts A60816 - B00611
cdrskin_cdrskin_CPPFLAGS = -Ilibburn
cdrskin_cdrskin_CFLAGS = -DCdrskin_libburn_0_7_3
cdrskin_cdrskin_CFLAGS = -DCdrskin_libburn_0_8_2
# cdrskin_cdrskin_LDADD = $(libburn_libburn_la_OBJECTS) $(LIBBURN_EXTRALIBS)
# ts A80123, change proposed by Simon Huggins to cause dynamic libburn linking
@ -202,10 +199,16 @@ EXTRA_DIST = \
cdrskin/wiki_plain.txt \
cdrskin/cleanup.h \
cdrskin/cleanup.c \
libburn/os-dummy.h \
libburn/os-freebsd.h \
libburn/os-linux.h \
libburn/os-libcdio.h \
libburn/os-solaris.h \
libburn/sg-dummy.c \
libburn/sg-freebsd.c \
libburn/sg-linux.c \
libburn/sg-libcdio.c \
libburn/sg-solaris.c \
COPYING \
NEWS \
ChangeLog \

96
README
View File

@ -6,12 +6,12 @@ This all is under GPL.
------------------------------------------------------------------------------
libburn-project.org
By Mario Danic <mario.danic@gmail.com> and Thomas Schmitt <scdbackup@gmx.net>
Copyright (C) 2006-2009 Mario Danic, Thomas Schmitt
Copyright (C) 2006-2010 Mario Danic, Thomas Schmitt
Still containing parts of Libburn. By Derek Foreman <derek@signalmarketing.com>
and Ben Jansens <xor@orodu.net>
Copyright (C) 2002-2006 Derek Foreman and Ben Jansens
http://files.libburnia-project.org/releases/libburn-0.7.2.pl00.tar.gz
http://files.libburnia-project.org/releases/libburn-0.8.2.pl00.tar.gz
------------------------------------------------------------------------------
@ -19,10 +19,10 @@ Copyright (C) 2002-2006 Derek Foreman and Ben Jansens
From tarball
Obtain libburn-0.7.2.pl00.tar.gz, take it to a directory of your choice and do:
Obtain libburn-0.8.2.pl00.tar.gz, take it to a directory of your choice and do:
tar xzf libburn-0.7.2.pl00.tar.gz
cd libburn-0.7.2
tar xzf libburn-0.8.2.pl00.tar.gz
cd libburn-0.8.2
./configure --prefix=/usr
make
@ -72,6 +72,10 @@ configure time by:
--enable-dvd-obs-64k
This may be combined with above --enable-track-src-odirect .
Alternatively the transport of SCSI commands can be done via libcdio-0.83.
You may install it and re-run libburn's ./configure with option
--enable-libcdio
Make sure to re-compile all source files after running ./configure
make clean ; make
make install
@ -101,8 +105,9 @@ The project comprises of several more or less interdependent parts which
together strive to be a usable foundation for application development.
These are libraries, language bindings, and middleware binaries which emulate
classical (and valuable) Linux tools.
Currently it is supported on Linux with kernels >= 2.4 and on FreeBSD versions
with ATAPI/CAM support enabled in the kernel, see atapicam(4).
Currently it is supported on GNU/Linux with kernels >= 2.4,
on FreeBSD with ATAPI/CAM enabled in the kernel (see man atapicam),
and on OpenSolaris (tested with kernel 5.11).
On other X/Open compliant systems there will only be pseudo drives, but no
direct MMC operation on real CD/DVD/BD drives.
@ -140,6 +145,8 @@ The project components (list subject to growth, hopefully):
also allows to grow ISO-9660 filesystem images on multi-session
media as well as on overwriteable media via the same API.
All media peculiarities are handled automatically.
It also contains the methods of command oriented application
xorriso and offers them via a C language API.
- cdrskin is a limited cdrecord compatibility wrapper for libburn.
cdrecord is a powerful GPL'ed burn program included in Joerg
@ -159,6 +166,8 @@ The project components (list subject to growth, hopefully):
changing, incremental backups, activating boot images, and
extracting of files from ISO images to disk. An own ISO 9660
extension stores ACLs, xattr, and MD5 of file content.
All features of xorriso are also available via a C language API
of libisoburn.
See xorriso/README for more.
- "test" is a collection of application gestures and examples given by the
@ -185,8 +194,8 @@ Applications must use 64 bit off_t. E.g. by defining
#define _LARGEFILE_SOURCE
#define _FILE_OFFSET_BITS 64
or take special precautions to interface with the libraries by 64 bit integers
where the .h files prescribe off_t. Not to use 64 bit file i/o will keep the
application from producing and processing ISO images of more than 2 GB size.
where the .h files prescribe off_t. To reduce libburn's off_t size to 32 bit
will keep it from processing tracks of more than 2 GB size.
------------------------------------------------------------------------------
@ -472,12 +481,58 @@ Project history as far as known to me:
- 12 Nov 2009 libburn-0.7.2.pl01 works around problems with Pioneer DVR-216D.
DVD-R runs made the drive stuck. Ejecting the tray did not work properly.
- 06 Dec 2009 libburn-0.7.4 works around problems with newer DVD burners,
provides throughput enhancements with hampered busses on Linux, and new
API calls to log SCSI commands and to control the libburn fifo.
- 09 Dec 2009 libisoburn-0.4.6 allows performance tuning of output to DVD
drives or disk files.
- 26 Dec 2009 libburn-0.7.4.pl01 fixes the release tarball which was lacking
the files of the generic system adapter for X/Open.
- 29 Dec 2009 Our project received a donation for purchasing a fine small
computer which shall serve as OS farm for development and support.
- 20 Jan 2010 Version 0.6.26 of libisofs fixes minor bugs and shall enhance
portability.
- 22 Jan 2010 libburn-0.7.6 has an improved system adapter for FreeBSD,
fixes bugs about the generic X/Open system adapter, and allows to use
libcdio >= 0.83 as SCSI transport facility.
- 10 Feb 2010 libisofs-0.6.28 fixes a regression about bootable images which
was introduced by version 0.6.22 in August 2009.
- 23 Feb 2010 libisoburn-0.5.0 marks the transition of the xorriso standalone
version to an official GNU project. The name changed to "GNU xorriso" and its
license is now GPLv3+.
The licenses of libburnia libraries and applications are not affected by
this change.
- 10 Mar 2010 libburn-0.7.8 fixes bugs and improves the built-in abort handler
on FreeBSD.
- 30 Mar 2010 Release 0.5.2 of libisoburn provides xorriso documentation in
GNU Texinfo format with embedded extra data to derive a full man page.
- 09 Apr 2010 libburn-0.8.0 now works with ahci driver on FreeBSD 8-STABLE.
- 03 May 2010 Version 0.6.32 of libisofs is able to create ISO images with
multiple boot images. All boot catalog parameters described in El-Torito
specs can be set and inquired. This allows to use GRUB boot images for EFI.
- 04 May 2010 Release 0.5.6.pl00 of libisoburn makes use of the new libisofs
capabilities about boot images.
- 11 Jun 2010 libburn-0.8.2 now works on Solaris.
------------------------------------------------------------------------------
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation. To be exact: version 2 of that License.
it under the terms of the GNU General Public License version 2 or later
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@ -495,16 +550,16 @@ other copyrighted code has been replaced by ours and by copyright-free
contributions of our friends:
------------------------------------------------------------------------------
We, the copyright holders, agree on the interpretation that
dynamical linking of our libraries constitutes "use of" and
not "derivation from" our work in the sense of GPL, provided
those libraries are compiled from our unaltered code.
We, the copyright holders, agree on the interpretation that dynamical linking
of our libraries constitutes "use of" and not "derivation from" our work in
the sense of GPL, provided those libraries are compiled from our unaltered
code or from altered code published under GPL.
Thus you may link our libraries dynamically with applications
which are not under GPL. You may distribute our libraries and
application tools in binary form, if you fulfill the usual
condition of GPL to offer a copy of the source code -altered
or unaltered- under GPL.
So we will not raise legal protest if you link our libraries dynamically with
applications which are not under GPL, or if you distribute our libraries
and application tools in binary form, as long as you fulfill the usual
condition of GPL to offer a copy of their source code -altered or unaltered-
under GPL.
We ask you politely to use our work in open source spirit
and with the due reference to the entire open source community.
@ -521,4 +576,5 @@ means to qualify for GPL.
For now we are firmly committed to maintain one single license: GPL.
signed: Mario Danic, Thomas Schmitt
Agreement joined later by: Vreixo Formoso

View File

@ -1,3 +1,14 @@
AC_DEFUN([LIBBURNIA_SET_FLAGS],
[
case $target_os in
freebsd*)
LDFLAGS="$LDFLAGS -L/usr/local/lib"
CPPFLAGS="$CPPFLAGS -I/usr/local/include"
;;
esac
])
AC_DEFUN([TARGET_SHIZZLE],
[
ARCH=""
@ -6,16 +17,20 @@ AC_DEFUN([TARGET_SHIZZLE],
AC_MSG_CHECKING([target operating system])
case $target in
*-*-linux*)
case $target_os in
linux*)
ARCH=linux
LIBBURN_ARCH_LIBS=
;;
*-*-freebsd*)
freebsd*)
ARCH=freebsd
LIBBURN_ARCH_LIBS=-lcam
LIBBURNIA_PKGCONFDIR=$(echo "$libdir" | sed 's/\/lib$/\/libdata/')/pkgconfig
;;
kfreebsd*-gnu)
ARCH=freebsd
LIBBURN_ARCH_LIBS=-lcam
;;
*)
ARCH=
LIBBURN_ARCH_LIBS=

View File

@ -4,17 +4,19 @@
cdrskin. By Thomas Schmitt <scdbackup@gmx.net>
Integrated sub project of libburnia-project.org but also published via:
http://scdbackup.sourceforge.net/cdrskin_eng.html
http://scdbackup.sourceforge.net/cdrskin-0.7.3.tar.gz
http://scdbackup.sourceforge.net/cdrskin-0.8.2.pl00.tar.gz
Copyright (C) 2006-2009 Thomas Schmitt, provided under GPL version 2.
Copyright (C) 2006-2010 Thomas Schmitt, provided under GPL version 2 or later.
------------------------------------------------------------------------------
cdrskin is a limited cdrecord compatibility wrapper which allows to use
most of the libburn features from the command line.
Currently it is supported on Linux with kernels >= 2.4 and on FreeBSD versions
with ATAPI/CAM support enabled in the kernel, see atapicam(4).
Currently it is supported on GNU/Linux with kernels >= 2.4,
on FreeBSD and on OpenSolaris.
IDE drives under Linux 2.4. need kernel module ide-scsi.
ATA and SATA drives under FreeBSD need kernel module atapicam.
On other X/Open compliant systems there will only be emulated drives, but no
direct MMC operation on real CD/DVD/BD drives.
@ -24,10 +26,10 @@ By using this software you agree to the disclaimer at the end of this text
Compilation, First Glimpse, Installation
Obtain cdrskin-0.7.3.tar.gz, take it to a directory of your choice and do:
Obtain cdrskin-0.8.2.pl00.tar.gz, take it to a directory of your choice and do:
tar xzf cdrskin-0.7.3.tar.gz
cd cdrskin-0.7.3
tar xzf cdrskin-0.8.2.pl00.tar.gz
cd cdrskin-0.8.2
Within that directory execute:
@ -102,17 +104,25 @@ The output of cdrskin --devices might look like
0 dev='/dev/sr0' rwrwr- : '_NEC' 'DVD_RW ND-4570A'
1 dev='/dev/sr1' rwrw-- : 'HL-DT-ST' 'DVDRAM GSA-4082B'
So full and insecure enabling of both for everybody would look like
chmod a+rw /dev/sr0 /dev/sr1
On Linux, full and insecure enabling of both for everybody would look like
chmod a+rw /dev/sr0 /dev/hda
This is equivalent to the traditional setup chmod a+x,u+s cdrecord.
On FreeBSD, device permissions are to be set in /etc/devfs.rules.
On Solaris, pfexec privileges may be restricted to "basic,sys_devices".
See below "System Dependend Drive Permission Examples".
I strongly discourage to run cdrskin with setuid root or via sudo !
It is not checked for the necessary degree of hacker safety.
Better consider to grant the necessary permissions to group "floppy"
and to add users to it.
A behavioral conflict is known between any burn software and demons like hald
which probe CD drives. This can spoil burn runs for CD-R or CD-RW.
You may have to keep your hald away from the drive. See for example
http://www.freebsd.org/gnome/docs/halfaq.html
Consider to put all authorized users into group "floppy", to chgrp the
device file to that group and to disallow w-access to others.
Helpful with Linux kernel 2.4 is a special SCSI feature:
It is possible to address a scsi(-emulated) drive via associated device files
@ -121,11 +131,6 @@ 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.
For finding /dev/sg1 from /dev/sr0, the program needs rw-access to both files.
A behavioral conflict is known between any burn software and demons like hald
which probe CD drives. This can spoil burn runs for CD-R or CD-RW.
You may have to keep your hald away from the drive. See for example
http://www.freebsd.org/gnome/docs/halfaq.html
Usage examples
@ -145,7 +150,7 @@ Obtain some info about the drive
cdrskin dev=0,1,0 -checkdrive
Obtain some info about the drive and the inserted media
cdrskin dev=0,1,0 -atip -v
cdrskin dev=0,1,0 -atip -v -minfo
Prepare CD-RW or DVD-RW for re-use, DVD-RAM or BD-RE for first use
cdrskin -v dev=/dev/sg1 blank=as_needed -eject
@ -398,13 +403,14 @@ drive. See man page section FILES for a way to lift that ban.
Special compilation variations
All following options of ./configure and cdrskin/compile_cdrskin.sh are
combinable.
combinable. After runs of ./configure do as next:
make clean ; make
In some situations Linux may deliver a better write performance to drives if
the track input is read with O_DIRECT (see man 2 open). The API call
burn_os_open_track_src() and the input readers of cdrskin and libburn fifo
can be told to use this peculiar read mode by:
--enable-track-src-odirect
--enable-track-src-odirect
But often cdrskin option dvd_obs=64k will yield even better performance in
such a situation. 64k can be made default at compile time by
@ -412,6 +418,10 @@ such a situation. 64k can be made default at compile time by
It can also be enabled at configure time by
./configure ... --enable-dvd-obs-64k ...
Alternatively the transport of SCSI commands can be done via libcdio-0.83.
You may install it and re-run libburn's ./configure with option
--enable-libcdio
You may get a (super fat) statically linked binary by :
cdrskin/compile_cdrskin.sh -static
if your system supports static linking, at all. This will not help with kernels
@ -427,6 +437,84 @@ It will not read startup files, will abort on option dev_translation= ,
will not have a fifo buffer, and will not be able to put out help texts or
debugging messages.
------------------------------------------------------------------------------
System Dependend Drive Permission Examples
Accessing the optical drives requires privileges which usually are granted
only to the superuser. Linux, FreeBSD and Solaris offer quite different
approaches for avoiding the need for unrestricted privileges.
First check whether some friendly system setting already allows you to
access the drives as normal user:
cdrskin --devices
Those drives of which you see address and type strings are already usable.
If there remain drives invisible which the superuser can see by the same
command, then the following examples might help:
---------------------
On all three systems:
---------------------
Add the authorized users of CD drives to group "floppy" in /etc/group.
If missing: create this group.
Changes to /etc/group often only affect new login sessions. So log out and in
before making the first tests.
---------
On Linux:
---------
Allow rw-access to the drives
chgrp floppy /dev/sr0 /dev/sr1
chmod g+rw /dev/sr0 /dev/sr1
It might be necessary to perform chgrp and chmod after each reboot or to
edit distro dependent device configuration files for permanent settings.
-----------
On FreeBSD:
-----------
Edit /etc/devfs.rules and make sure to have these lines
[localrules=10]
add path 'acd*' mode 0664 group floppy
add path 'cd*' mode 0664 group floppy
add path 'pass*' mode 0664 group floppy
add path 'xpt*' mode 0664 group floppy
[localrules=5]
add path 'pass*' mode 0664 group floppy
add path 'cd*' mode 0664 group floppy
add path 'xpt*' mode 0664 group floppy
add path 'acd*' mode 0664 group floppy
Edit /etc/rc.conf and add the following line if missing
devfs_system_ruleset="localrules"
This gets into effect by reboot or by command
/etc/rc.d/devfs start
-----------
On Solaris:
-----------
Run cdrskin by
pfexec cdrskin ...arguments...
The following settings will make pfexec keep original UID and EUID and prevent
most superuser powers. Be aware that you still can manipulate all device files
if you have the file permissions for that.
Full root privileges for cdrskin can then be aquired only by command su.
Edit /etc/security/exec_attr and add this line to the other "Media Backup"
lines:
Media Backup:solaris:cmd:::/usr/local/bin/cdrskin:privs=basic,sys_devices
Edit /etc/user_attr and add profile "Media Backup" to the user's line:
thomas::::profiles=Media Backup,Primary Administrator;roles=root
See also man privileges, man exec_attr, man user_attr.
Then allow the group r-access to the drives
pfexec chgrp floppy /dev/rdsk/c3t0d0s2 /dev/rdsk/c4t0d0s2
pfexec chmod g+r /dev/rdsk/c3t0d0s2 /dev/rdsk/c4t0d0s2
The last two commands have to be executed after each boot. I do not know
the relevant device configuration files yet.
------------------------------------------------------------------------------
Project aspects and legal stuff
@ -455,7 +543,7 @@ contributions in a due way.
------------------------------------------------------------------------------
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2
it under the terms of the GNU General Public License version 2 or later
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
@ -471,7 +559,7 @@ contributions in a due way.
Based on and sub project of:
libburnia-project.org
By Mario Danic <mario.danic@gmail.com> and Thomas Schmitt <scdbackup@gmx.net>
Copyright (C) 2006-2009 Mario Danic, Thomas Schmitt
Copyright (C) 2006-2010 Mario Danic, Thomas Schmitt
libburnia-project.org is inspired by and in other components still containing
parts of
@ -482,34 +570,3 @@ See toplevel README for an overview of the current copyright situation in
libburnia-project.org.
------------------------------------------------------------------------------
cdrskin is currently copyright Thomas Schmitt only.
It adopts the following commitment by the toplevel copyright holders:
------------------------------------------------------------------------------
We, the copyright holders, agree on the interpretation that
dynamical linking of our libraries constitutes "use of" and
not "derivation from" our work in the sense of GPL, provided
those libraries are compiled from our unaltered code.
Thus you may link our libraries dynamically with applications
which are not under GPL. You may distribute our libraries and
application tools in binary form, if you fulfill the usual
condition of GPL to offer a copy of the source code -altered
or unaltered- under GPL.
We ask you politely to use our work in open source spirit
and with the due reference to the entire open source community.
If there should really arise the case where above clarification
does not suffice to fulfill a clear and neat request in open source
spirit that would otherwise be declined for mere formal reasons,
only in that case we will duely consider to issue a special license
covering only that special case.
It is the open source idea of responsible freedom which will be
decisive and you will have to prove that you exhausted all own
means to qualify for GPL.
For now we are firmly committed to maintain one single license: GPL.
signed for cdrskin: Thomas Schmitt

View File

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

View File

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

View File

@ -203,10 +203,11 @@ int Cdrfifo_close(struct CdrfifO *o, int flag)
if(o->dest_fd!=-1)
close(o->dest_fd);
o->dest_fd= -1;
for(i=0; i<o->follow_up_fd_counter; i++)
for(i=0; i<o->follow_up_fd_counter; i++) {
if(o->follow_up_fds[i][1]!=-1)
close(o->follow_up_fds[i][1]);
o->follow_up_fds[i][1]= -1;
}
return(1);
}

View File

@ -2,7 +2,7 @@
.\" First parameter, NAME, should be all caps
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
.\" other parameters are allowed: see man(7), man(1)
.TH CDRSKIN 1 "Nov 16, 2009"
.TH CDRSKIN 1 "Jun 10, 2010"
.\" Please adjust this date whenever revising the manpage.
.\"
.\" Some roff macros, for reference:
@ -82,7 +82,7 @@ A \fBtrack\fP stores a stream of bytes.
.br
Each track is initiated by one track source address argument, which may either
be "-" for standard input or the address of a readable file. If no write mode
is given explicitely then one will be chosen which matches the peculiarities
is given explicitly then one will be chosen which matches the peculiarities
of track sources and the state of the output media.
.PP
More than one track can be burned by a single run of cdrskin.
@ -93,13 +93,13 @@ Some media types can be kept appendable so that further tracks can
be written to them in subsequent runs of cdrskin (see option -multi).
Info about the addresses of burned tracks is kept in a table of
content (TOC) on media and can be retrieved via cdrskin option -toc.
These informations are also used by the operating systems' CD-ROM read drivers.
This information is also used by the operating systems' CD-ROM read drivers.
.PP
In general there are two types of tracks: data and audio. They differ in
sector size, throughput and readability via the systems' CD-ROM drivers
resp. by music CD players. With DVD and BD there is only type data.
.br
If not explicitely option -audio is given, then any track is burned as type
If not explicitly option -audio is given, then any track is burned as type
data, unless the track source is a file with suffix ".wav" or ".au" and has a
header part which identifies it as MS-WAVE resp. SUN Audio with suitable
parameters. Such files are burned as audio tracks by default.
@ -138,7 +138,7 @@ try to choose a write mode which matches the defined recording job,
the capabilities of the drive and the state of the present media.
.br
So the mentioning of write modes in the following paragraphs and in the
examples is not so much a demand that the user shall choose one explicitely,
examples is not so much a demand that the user shall choose one explicitly,
but rather an illustration of what to expect with particular media types.
.SS
.B Recordable CD Media:
@ -181,20 +181,20 @@ With DVD-R[W] two write modes may be available:
Mode DAO has many restrictions. It does not work with
appendable media, allows no -multi and only a single track. The size of the
track needs to be known in advance. So either its source has to be a disk file
of recognizable size or the size has to be announced explicitely by options
of recognizable size or the size has to be announced explicitly by options
.B tsize=
or
.B tao_to_sao_tsize= .
.br
DAO is the only mode for media which do not offer feature 21h Incremental
Streaming. DAO may also be selected explicitely by option
Streaming. DAO may also be selected explicitly by option
.B -sao .
Program growisofs uses DAO on sequential DVD-R[W] media for maximum
DVD-ROM/-Video compatibility.
.br
The other mode, Incremental Streaming, is the default write mode if
it is available and if the restrictions of DAO would prevent the job.
Incremental Streaming may be selected explicitely by option
Incremental Streaming may be selected explicitly by option
.B -tao
as it resembles much CD TAO by allowing track sources of
unpredicted length and to keep media appendable by option
@ -225,7 +225,7 @@ Currently types DVD+RW, DVD-RW, DVD-RAM and BD-RE can be overwritten via
cdrskin.
.br
Option -audio is not allowed. Only one track is allowed.
Option -multi cannot mark a recognizeable end of overwriteable media.
Option -multi cannot mark a recognizable end of overwriteable media.
Therefore -multi is banned unless ISO-9660 images shall be expandable by help
of option
.B --grow_overwriteable_iso .
@ -271,19 +271,22 @@ the drive is somewhat higher but the overall system is much less at stake.
Consider to restrict rw-access to a single group which bundles the users who
are allowed to use the burner drive (like group "floppy").
.br
For drive permission examples on Linux, FreeBSD, and Solaris,
see cdrskin/README.
.br
.PP
If you only got one CD capable drive then you may leave out cdrskin option
\fBdev=\fP. Else you should use this option to address the drive you want.
.br
cdrskin option dev= not only accepts the listed addresses but also
traditional cdrecord SCSI addresses which on Linux consist of three
numbers: Bus,Target,Lun. There is also a related address family "ATA" which
traditional cdrecord SCSI addresses which consist of three numbers:
Bus,Target,Lun. On Linux there is also a related address family "ATA" which
accesses IDE drives not under control of Linux SCSI drivers:
ATA:Bus,Target,Lun.
.br
See option -scanbus for getting a list of cdrecord style addresses.
.br
Further are accepted on Linux: links to libburn-suitable device files,
Further are accepted: links to libburn-suitable device files,
device files which have the same major and minor device number,
and device files which have the same SCSI address parameters (e.g. /dev/sg0).
.br
@ -350,7 +353,7 @@ print "Mounted Media:" and media type text.
Announces that the subsequent tracks are to be burned as audio.
The source is supposed to be uncompressed headerless PCM, 44100 Hz, 16 bit,
stereo. For little-endian byte order (which is usual on PCs) use option
-swab. Unless marked explicitely by option -data, input files with suffix
-swab. Unless marked explicitly by option -data, input files with suffix
".wav" are examined wether they have a header in MS-WAVE format confirming
those parameters and eventually raw audio data get extracted and burned as
audio track. Same is done for suffix ".au" and SUN Audio.
@ -527,7 +530,7 @@ of Bus,Target,Lun addresses.
Set "driveropts=noburnfree" to disable the drive's eventual protection
mechanism against temporary lack of source data (i.e. buffer underrun).
A drive that announces no such capabilities will not get them enabled anyway,
even if attempted explicitely via "driveropts=burnfree".
even if attempted explicitly via "driveropts=burnfree".
.TP
.BI \-dummy
Try to perform the drive operations without actually affecting the inserted
@ -597,7 +600,7 @@ will be used under the assumption that it is a single session filesystem.
.br
If not, then the burn run will be aborted.
.br
The range of -isosize is exactly one track. Further tracks may be preceeded
The range of -isosize is exactly one track. Further tracks may be preceded
by further -isosize options, though. At least 15 blocks of padding will be
added to each -isosize track. But be advised to rather use padsize=300k.
.br
@ -705,7 +708,7 @@ No -multi is allowed with DVD-R[W] -sao.
only imposes restrictions without providing known advantages.
.br
-sao can only be used for tracks of fixely predicted size. This implies that
track arguments which depict stdin or named pipes need to be preceeded by
track arguments which depict stdin or named pipes need to be preceded by
option tsize= or by option tao_to_sao_tsize=.
.br
-sao cannot be used on appendable media.
@ -822,7 +825,7 @@ Alphabetical list of options which are genuine to cdrskin and intended for
normal use:
.TP
.BI \--adjust_speed_to_drive
Curb explicitely given speed= values to the maximum which is announced by the
Curb explicitly given speed= values to the maximum which is announced by the
drive for the loaded media. By default, such an adjustment is only made with
pseudo-speeds 0 and -1 whereas speed settings > 0 are sent unchanged to the
drive which will then choose an appropriate speed on its own.
@ -916,7 +919,7 @@ to cdrskin, then cdrskin will delegate the job to said command.
The natural commands to be given are cdrecord or wodim but one may well submit
the address of an own program.
.br
The fallback programm will get all arguments of cdrskin which do not match
The fallback program will get all arguments of cdrskin which do not match
the shell patterns --?* or *_*=* . This eventually suppresses path names of
track sources which happen to match those patterns. The options from the
startup files are not handed to the fallback program.
@ -962,12 +965,12 @@ source is a ISO-9660 filesystem image.
With overwriteable media and no option blank=fast|all present it expands an
eventual ISO-9660 filesystem on media. It is assumed that this image's inner
size description points to the end of the valuable data.
Overwriteable media with a recognizeable ISO-9660 size will be regarded as
Overwriteable media with a recognizable ISO-9660 size will be regarded as
appendable rather than as blank. I.e. options -msinfo and -toc will work.
-toc will always show a single session with its size increasing with
every added mkisofs image.
.br
If not overriden by option write_start_address=, the track with the new image
If not overridden by option write_start_address=, the track with the new image
will be placed behind the end of the old one. One may use option
assert_write_lba= to make sure that media state and mkisofs job do match.
.br
@ -1062,7 +1065,7 @@ the available capacity. So for most realistic results one may set up
the full burn session and add --tell_media_space. But if one has to expect
a cdrskin version prior to 0.3.3 no track source should be given in order
not to start an involuntary burn session.
In this case set at least -sao or -tao explicitely.
In this case set at least -sao or -tao explicitly.
.br
The result gets printed to standard output. It is 0 or empty if no writing
is possible with the given options.
@ -1130,7 +1133,7 @@ Wether this leads to senseful behavior depends on operating system and kernel.
Linux specific: Select a SCSI device file family to be scanned for by
options --devices and -scanbus.
Normally this is /dev/sgN on kernel versions < 2.6 and /dev/srN
on kernels >= 2.6 . This option allows to explicitely override that default
on kernels >= 2.6 . This option allows to explicitly override that default
in order to meet other programs at a common device file for each drive.
On kernel 2.4 families sr and scd will find no drives.
.br
@ -1242,7 +1245,7 @@ cdrskin dev=0,1,0 -checkdrive
.br
cdrskin dev=ATA:1,0,0 -v -atip
.br
cdrskin dev=/dev/hdc -toc
cdrskin dev=/dev/hdc -minfo
.SS
.B Prepare CD-RW or DVD-RW for re-use, DVD-RAM or BD-RE for first use:
.br

View File

@ -1,7 +1,7 @@
/*
cdrskin.c , Copyright 2006-2009 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2. See future commitment below.
cdrskin.c , Copyright 2006-2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
A cdrecord compatible command line interface for libburn.
@ -88,7 +88,7 @@ or
/** The official program version */
#ifndef Cdrskin_prog_versioN
#define Cdrskin_prog_versioN "0.7.3"
#define Cdrskin_prog_versioN "0.8.2"
#endif
/** The official libburn interface revision to use.
@ -98,10 +98,10 @@ or
#define Cdrskin_libburn_majoR 0
#endif
#ifndef Cdrskin_libburn_minoR
#define Cdrskin_libburn_minoR 7
#define Cdrskin_libburn_minoR 8
#endif
#ifndef Cdrskin_libburn_micrO
#define Cdrskin_libburn_micrO 3
#define Cdrskin_libburn_micrO 2
#endif
@ -135,48 +135,46 @@ or
#endif /* Cdrskin_libburn_cvs_A60220_tS */
#ifdef Cdrskin_libburn_0_7_2
#define Cdrskin_libburn_versioN "0.7.2"
#ifdef Cdrskin_libburn_0_8_2
#define Cdrskin_libburn_versioN "0.8.2"
#define Cdrskin_libburn_from_pykix_svN 1
#endif /* Cdrskin_libburn_0_7_2 */
#endif /* Cdrskin_libburn_0_8_2 */
#ifdef Cdrskin_libburn_0_7_3
#define Cdrskin_libburn_versioN "0.7.3"
#ifdef Cdrskin_libburn_0_8_3
#define Cdrskin_libburn_versioN "0.8.3"
#define Cdrskin_libburn_from_pykix_svN 1
/* Place novelty switch macros here.
Move them down to Cdrskin_libburn_from_pykix_svN on version leap
*/
/* burn_write_opts_set_dvd_obs() and burn_write_opts_set_stdio_fsync()
/* Do not stay in signal handler but only cancel and set Cdrskin_abort_leveL.
Make use of burn_is_aborting() to detect pending libburn aborts.
*/
#define Cdrskin_libburn_has_fsync_obS 1
/* >>> do not forget to remove Libburn_has_open_trac_srC at release of 0.7.4 */
#endif /* Cdrskin_libburn_0_7_3 */
#endif /* Cdrskin_libburn_0_8_3 */
#ifndef Cdrskin_libburn_versioN
#define Cdrskin_libburn_0_7_2
#define Cdrskin_libburn_versioN "0.7.2"
#define Cdrskin_libburn_0_8_2
#define Cdrskin_libburn_versioN "0.8.2"
#define Cdrskin_libburn_from_pykix_svN 1
#endif
#ifdef Cdrskin_libburn_0_7_2
#ifdef Cdrskin_libburn_0_8_2
#undef Cdrskin_libburn_majoR
#undef Cdrskin_libburn_minoR
#undef Cdrskin_libburn_micrO
#define Cdrskin_libburn_majoR 0
#define Cdrskin_libburn_minoR 7
#define Cdrskin_libburn_minoR 8
#define Cdrskin_libburn_micrO 2
#endif
#ifdef Cdrskin_libburn_0_7_3
#ifdef Cdrskin_libburn_0_8_3
#undef Cdrskin_libburn_majoR
#undef Cdrskin_libburn_minoR
#undef Cdrskin_libburn_micrO
#define Cdrskin_libburn_majoR 0
#define Cdrskin_libburn_minoR 7
#define Cdrskin_libburn_minoR 8
#define Cdrskin_libburn_micrO 3
#endif
@ -374,7 +372,34 @@ or
#define Cleanup_app_handler_T burn_abort_handler_t
#else
#include "cleanup.h"
#ifdef Cdrskin_use_libburn_cleanuP
#undef Cdrskin_use_libburn_cleanuP
#endif
#endif
/*
# define Cdrskin_use_libburn_cleanuP 1
*/
/* May not use libburn cleanup with cdrskin fifo */
#ifndef Cdrskin_use_libburn_fifO
#ifdef Cdrskin_use_libburn_cleanuP
#undef Cdrskin_use_libburn_cleanuP
#endif
#endif
#ifdef Cdrskin_use_libburn_cleanuP
#define Cleanup_handler_funC NULL
#define Cleanup_handler_handlE "cdrskin: "
#define Cleanup_handler_flaG 48
#else
#define Cleanup_handler_funC (Cleanup_app_handler_T) Cdrskin_abort_handler
#define Cleanup_handler_handlE skin
#define Cleanup_handler_flaG 4
#endif /* ! Cdrskin_use_libburn_cleanuP */
/* 0= no abort going on, -1= Cdrskin_abort_handler was called
*/
static int Cdrskin_abort_leveL= 0;
/** The size of a string buffer for pathnames and similar texts */
@ -1463,14 +1488,12 @@ int Cdrtrack_open_source_path(struct CdrtracK *track, int *fd, int flag)
if(is_wav==-3)
return(0);
if(is_wav==0) {
#ifdef Libburn_has_open_trac_srC
if(track->track_type != BURN_MODE1 ||
(track->cdxa_conversion & 0x7fffffff))
flag&= ~4; /* Better avoid O_DIRECT with odd sectors */
if(flag & 4)
*fd= burn_os_open_track_src(track->source_path, O_RDONLY, 0);
else
#endif
*fd= open(track->source_path, O_RDONLY);
}
if(*fd==-1) {
@ -1804,7 +1827,6 @@ int Cdrtrack_add_to_session(struct CdrtracK *track, int trackno,
Cdrskin_get_fifo_par(track->boss, &fifo_enabled, &fifo_size, &fifo_start_at,
0);
fd_src= src;
if(track->track_type == BURN_AUDIO)
chunksize= 2352;
@ -1814,6 +1836,7 @@ int Cdrtrack_add_to_session(struct CdrtracK *track, int trackno,
chunksize= 2048;
chunks= fifo_size / chunksize;
if(chunks > 1 && fifo_enabled) {
fd_src= src;
src= burn_fifo_source_new(fd_src, chunksize, chunks,
(chunksize * chunks >= 128 * 1024));
if((flag & 1) || src == NULL)
@ -2880,11 +2903,9 @@ set_dev:;
printf(
" --drive_scsi_exclusive try to exclusively reserve device files\n");
printf(" /dev/srN, /dev/scdM, /dev/stK of drive.\n");
#ifdef Cdrskin_libburn_has_fsync_obS
printf(" dvd_obs=\"default\"|number\n");
printf(
" set number of bytes per DVD/BD write: 32k or 64k\n");
#endif
#ifdef Cdrskin_burn_drive_eject_brokeN
printf(
" eject_device=<path> set the device address for command eject\n");
@ -2935,13 +2956,11 @@ set_dev:;
printf(
" byte addresses below that number.\n");
#endif
#ifdef Cdrskin_libburn_has_fsync_obS
printf(" stdio_sync=\"default\"|\"off\"|number\n");
printf(
" set number of bytes after which to force output\n");
printf(
" to drives with prefix \"stdio:\".\n");
#endif
#ifdef Cdrskin_allow_libburn_taO
printf(
@ -3155,7 +3174,17 @@ set_severities:;
int major, minor, micro;
printf(
"Cdrecord 2.01-Emulation Copyright (C) 2006-2009, see libburnia-project.org\n");
"Cdrecord 2.01-Emulation Copyright (C) 2006-2010, see libburnia-project.org\n");
if(o->fallback_program[0]) {
char *hargv[2];
printf("Fallback program : %s\n",o->fallback_program);
printf("Fallback version :\n");
hargv[0]= argv[0];
hargv[1]= "-version";
Cdrpreskin_fallback(o,2,hargv,1); /* dirty never come back */
}
printf("System adapter : %s\n", burn_scsi_transport_id(0));
printf("libburn interface : %d.%d.%d\n",
burn_header_version_major, burn_header_version_minor,
burn_header_version_micro);
@ -3171,15 +3200,6 @@ set_severities:;
printf("Version timestamp : %s\n",Cdrskin_timestamP);
printf("Build timestamp : %s\n",Cdrskin_build_timestamP);
if(o->fallback_program[0]) {
char *hargv[2];
printf("Fallback program : %s\n",o->fallback_program);
printf("Fallback version :\n");
hargv[0]= argv[0];
hargv[1]= "-version";
Cdrpreskin_fallback(o,2,hargv,1); /* dirty never come back */
}
{ret= 2; goto ex;}
} else if(strcmp(argv[i],"-waiti")==0) {
@ -3196,7 +3216,9 @@ set_severities:;
final_checks:;
if(flag&1)
goto ex;
if(o->verbosity >= Cdrskin_verbose_debuG)
ClN(fprintf(stderr,
"cdrskin: DEBUG : Using %s\n", burn_scsi_transport_id(0)));
if(o->do_waiti) {
fprintf(stderr,
"cdrskin: Option -waiti pauses program until input appears at stdin\n");
@ -3624,6 +3646,7 @@ int Cdrskin_new(struct CdrskiN **skin, struct CdrpreskiN *preskin, int flag)
o->write_type= BURN_WRITE_SAO;
o->block_type= BURN_BLOCK_SAO;
o->multi= 0;
o->cdxa_conversion= 0;
o->modesty_on_drive= 0;
o->min_buffer_percent= 65;
o->max_buffer_percent= 95;
@ -4095,7 +4118,8 @@ ex:;
#ifdef Cdrskin_grab_abort_brokeN
if(restore_handler) {
int Cdrskin_abort_handler(struct CdrskiN *, int, int);
Cleanup_set_handlers(skin,(Cleanup_app_handler_T) Cdrskin_abort_handler,4);
Cleanup_set_handlers(Cleanup_handler_handlE, Cleanup_handler_funC,
Cleanup_handler_flaG);
}
#endif /* Cdrskin_grab_abort_brokeN */
@ -4128,17 +4152,42 @@ int Cdrskin_release_drive(struct CdrskiN *skin, int flag)
}
int Cdrskin__is_aborting(int flag)
{
if(Cdrskin_abort_leveL)
return(-1);
return(burn_is_aborting(0));
}
int Cdrskin_abort(struct CdrskiN *skin, int flag)
{
int ret;
Cdrskin_abort_leveL= 1;
ret= burn_abort(skin->abort_max_wait, burn_abort_pacifier, "cdrskin: ");
if(ret<=0) {
fprintf(stderr,
"\ncdrskin: ABORT : Cannot cancel burn session and release drive.\n");
return(0);
} else {
fprintf(stderr,
"cdrskin: ABORT : Drive is released and library is shut down now.\n");
}
fprintf(stderr,
"cdrskin: ABORT : Program done. Even if you do not see a shell prompt.\n");
fprintf(stderr,"\n");
exit(1);
}
/** Clean up resources in abort situations. To be called by Cleanup subsystem
but hardly ever by the application. The program must exit afterwards.
*/
int Cdrskin_abort_handler(struct CdrskiN *skin, int signum, int flag)
{
#ifdef Cdrskin_libburn_has_burn_aborT
int ret;
#else
#ifndef Cdrskin_libburn_has_burn_aborT
int wait_grain= 100000,first_status= 1;
double start_time,last_time,current_time;
@ -4151,8 +4200,9 @@ int Cdrskin_abort_handler(struct CdrskiN *skin, int signum, int flag)
if(getpid()!=skin->control_pid) {
if(skin->verbosity>=Cdrskin_verbose_debuG)
ClN(fprintf(stderr,
"\ncdrskin_debug: ABORT : [%d] Thread rejected: pid=%d, signum=%d\n",
skin->control_pid,getpid(),signum));
"\ncdrskin_debug: ABORT : [%lu] Thread rejected: pid=%lu, signum=%lu\n",
(unsigned long int) skin->control_pid, (unsigned long int) getpid(),
(unsigned long int) signum));
#ifdef Not_yeT
/* >>> find more abstract and system independent way to determine
@ -4190,14 +4240,15 @@ int Cdrskin_abort_handler(struct CdrskiN *skin, int signum, int flag)
fprintf(stderr,"cdrskin: ABORT : Usually it is done with 4x speed after about a MINUTE\n");
fprintf(stderr,"cdrskin: URGE : But wait at least the normal burning time before any kill -9\n");
}
if(skin->verbosity>=Cdrskin_verbose_debuG)
ClN(fprintf(stderr,"cdrskin_debug: ABORT : Calling burn_abort()\n"));
ret= burn_abort(skin->abort_max_wait, burn_abort_pacifier, "cdrskin: ");
if(ret<=0) {
fprintf(stderr,
"\ncdrskin: ABORT : Cannot cancel burn session and release drive.\n");
return(0);
}
fprintf(stderr,"\n");
Cdrskin_abort_leveL= -1;
if (!(flag & 1))
burn_abort(-1, burn_abort_pacifier, "cdrskin: ");
fprintf(stderr,
"cdrskin: ABORT : Urged drive worker threads to do emergency halt.\n");
return -2;
#else /* Cdrskin_libburn_has_burn_aborT */
@ -5226,8 +5277,8 @@ int Cdrskin_minfo(struct CdrskiN *skin, int flag)
/* If last two blocks not readable then assume TAO and subtract 2
from lra and size.
*/;
ret= burn_read_data(drive, (off_t) lra * (off_t) 2048, buf, 2 * 2048,
&buf_count, 2 | 4);
ret= burn_read_data(drive, (off_t) (lra - 1) * (off_t) 2048, buf,
2 * 2048, &buf_count, 2 | 4);
if(ret <= 0) {
lra-= 2;
size-= 2;
@ -6042,6 +6093,8 @@ ex:;
skin->drive_is_busy= 0;
if(skin->drive_is_grabbed)
Cdrskin_release_drive(skin,0);
if(Cdrskin__is_aborting(0))
Cdrskin_abort(skin, 0); /* Never comes back */
return(ret);
}
@ -6095,6 +6148,9 @@ int Cdrskin_burn_pacifier(struct CdrskiN *skin,
/* for debugging */
static double last_fifo_in= 0.0,last_fifo_out= 0.0,curr_fifo_in,curr_fifo_out;
if(Cdrskin__is_aborting(0))
Cdrskin_abort(skin, 0); /* Never comes back */
current_time= Sfile_microtime(0);
elapsed_total_time= current_time-start_time;
elapsed_time= current_time-*last_time;
@ -7218,7 +7274,6 @@ burn_failed:;
#ifdef Cdrskin_libburn_has_stream_recordinG
burn_write_opts_set_stream_recording(o, skin->stream_recording_is_set);
#endif
#ifdef Cdrskin_libburn_has_fsync_obS
#ifdef Cdrskin_dvd_obs_default_64K
if(skin->dvd_obs == 0)
burn_write_opts_set_dvd_obs(o, 64 * 1024);
@ -7226,7 +7281,6 @@ burn_failed:;
#endif
burn_write_opts_set_dvd_obs(o, skin->dvd_obs);
burn_write_opts_set_stdio_fsync(o, skin->stdio_sync);
#endif /* Cdrskin_libburn_has_fsync_obS */
if(skin->dummy_mode) {
fprintf(stderr,
@ -7305,7 +7359,8 @@ fifo_filling_failed:;
skin->drive_is_busy= 1;
burn_disc_write(o, disc);
if(skin->preskin->abort_handler==-1)
Cleanup_set_handlers(skin,(Cleanup_app_handler_T) Cdrskin_abort_handler,4);
Cleanup_set_handlers(Cleanup_handler_handlE, Cleanup_handler_funC,
Cleanup_handler_flaG);
last_time= start_time= Sfile_microtime(0);
burn_write_opts_free(o);
@ -7324,7 +7379,7 @@ fifo_filling_failed:;
/* >>> how do i learn about success or failure ? */
if(loop_counter>0)
if(loop_counter>0 || Cdrskin__is_aborting(0))
Cdrskin_burn_pacifier(skin,drive_status,&p,start_time,&last_time,
&total_count,&last_count,&min_buffer_fill,0);
@ -7398,6 +7453,9 @@ fifo_filling_failed:;
if(skin->verbosity>=Cdrskin_verbose_progresS)
printf("\n");
if(Cdrskin__is_aborting(0))
Cdrskin_abort(skin, 0); /* Never comes back */
#ifdef Cdrskin_libburn_has_wrote_welL
wrote_well = burn_drive_wrote_well(drive);
#endif
@ -8896,9 +8954,11 @@ int Cdrskin_create(struct CdrskiN **o, struct CdrpreskiN **preskin,
*o= skin;
if(skin->preskin->abort_handler==1 || skin->preskin->abort_handler==3 ||
skin->preskin->abort_handler==4)
Cleanup_set_handlers(skin,(Cleanup_app_handler_T) Cdrskin_abort_handler,4);
Cleanup_set_handlers(Cleanup_handler_handlE, Cleanup_handler_funC,
Cleanup_handler_flaG);
else if(skin->preskin->abort_handler==2)
Cleanup_set_handlers(skin,(Cleanup_app_handler_T) Cdrskin_abort_handler,2|8);
Cleanup_set_handlers(Cleanup_handler_handlE, Cleanup_handler_funC,
2 | 8);
printf("cdrskin: scanning for devices ...\n");
fflush(stdout);
@ -8974,21 +9034,28 @@ int Cdrskin_run(struct CdrskiN *skin, int *exit_value, int flag)
if(skin->do_devices) {
if(skin->n_drives<=0 && skin->preskin->scan_demands_drive)
{*exit_value= 4; goto no_drive;}
if(Cdrskin__is_aborting(0))
goto ex;
ret= Cdrskin_scanbus(skin,1);
if(ret<=0) {
fprintf(stderr,"cdrskin: FATAL : --devices failed.\n");
{*exit_value= 4; goto ex;}
}
}
if(skin->do_scanbus) {
if(skin->n_drives<=0 && skin->preskin->scan_demands_drive)
{*exit_value= 5; goto no_drive;}
if(Cdrskin__is_aborting(0))
goto ex;
ret= Cdrskin_scanbus(skin,0);
if(ret<=0)
fprintf(stderr,"cdrskin: FATAL : -scanbus failed.\n");
{*exit_value= 5*(ret<=0); goto ex;}
}
if(skin->do_load) {
if(Cdrskin__is_aborting(0))
goto ex;
ret= Cdrskin_grab_drive(skin,8);
if(ret>0) {
if(skin->do_load==2 && !skin->do_eject) {
@ -9004,12 +9071,16 @@ int Cdrskin_run(struct CdrskiN *skin, int *exit_value, int flag)
{*exit_value= 14*(ret<=0); goto ex;}
}
if(skin->do_checkdrive) {
if(Cdrskin__is_aborting(0))
goto ex;
ret= Cdrskin_checkdrive(skin,"",(skin->do_checkdrive==2)<<1);
{*exit_value= 6*(ret<=0); goto ex;}
}
if(skin->do_msinfo) {
if(skin->n_drives<=0)
{*exit_value= 12; goto no_drive;}
if(Cdrskin__is_aborting(0))
goto ex;
ret= Cdrskin_msinfo(skin,0);
if(ret<=0)
{*exit_value= 12; goto ex;}
@ -9017,6 +9088,8 @@ int Cdrskin_run(struct CdrskiN *skin, int *exit_value, int flag)
if(skin->do_atip) {
if(skin->n_drives<=0)
{*exit_value= 7; goto no_drive;}
if(Cdrskin__is_aborting(0))
goto ex;
ret= Cdrskin_atip(skin, skin->do_atip == 4 ? 4 :
(skin->do_atip>1) | (2 * (skin->do_atip > 2)));
if(ret<=0)
@ -9025,6 +9098,8 @@ int Cdrskin_run(struct CdrskiN *skin, int *exit_value, int flag)
if(skin->do_list_formats) {
if(skin->n_drives<=0)
{*exit_value= 14; goto no_drive;}
if(Cdrskin__is_aborting(0))
goto ex;
ret= Cdrskin_list_formats(skin, 0);
if(ret<=0)
{*exit_value= 14; goto ex;}
@ -9032,6 +9107,8 @@ int Cdrskin_run(struct CdrskiN *skin, int *exit_value, int flag)
if(skin->do_blank) {
if(skin->n_drives<=0)
{*exit_value= 8; goto no_drive;}
if(Cdrskin__is_aborting(0))
goto ex;
ret= Cdrskin_blank(skin,0);
if(ret<=0)
{*exit_value= 8; goto ex;}
@ -9040,6 +9117,8 @@ int Cdrskin_run(struct CdrskiN *skin, int *exit_value, int flag)
#ifdef Cdrskin_libburn_has_random_access_rW
if(skin->do_direct_write) {
skin->do_burn= 0;
if(Cdrskin__is_aborting(0))
goto ex;
ret= Cdrskin_direct_write(skin,0);
if(ret<=0)
{*exit_value= 13; goto ex;}
@ -9049,11 +9128,15 @@ int Cdrskin_run(struct CdrskiN *skin, int *exit_value, int flag)
if(skin->do_burn || skin->tell_media_space) {
if(skin->n_drives<=0)
{*exit_value= 10; goto no_drive;}
if(Cdrskin__is_aborting(0))
goto ex;
ret= Cdrskin_burn(skin,0);
if(ret<=0)
{*exit_value= 10; goto ex;}
}
ex:;
if(Cdrskin__is_aborting(0))
Cdrskin_abort(skin, 0); /* Never comes back */
return((*exit_value)==0);
no_drive:;
fprintf(stderr,"cdrskin: FATAL : This run would need an accessible drive\n");
@ -9101,7 +9184,7 @@ int main(int argc, char **argv)
messaging need libburn running */
ret= Cdrpreskin_initialize_lib(preskin,0);
if(ret<=0) {
fprintf(stderr,"cdrskin: FATAL : Initializiation of burn library failed\n");
fprintf(stderr,"cdrskin: FATAL : Initialization of burn library failed\n");
{exit_value= 2; goto ex;}
}
lib_initialized= 1;
@ -9141,9 +9224,13 @@ int main(int argc, char **argv)
#endif
}
Cdrskin_run(skin,&exit_value,0);
if(!Cdrskin__is_aborting(0))
Cdrskin_run(skin,&exit_value,0);
ex:;
if(Cdrskin__is_aborting(0))
Cdrskin_abort(skin, 0); /* Never comes back */
if(preskin!=NULL)
h_preskin= preskin;
else if(skin!=NULL)

View File

@ -38,8 +38,8 @@ About any CD, DVD, or BD recorder produced in the recent ten years.
<BR>
<A HREF="http://libburnia-project.org">libburn</A>
supports recorders which are compliant to standards MMC-1 for CD and
MMC-5 for DVD or BD. Linux and FreeBSD allow to access drives connected
via SCSI, PATA (aka IDE, ATA), USB, or SATA.
MMC-5 for DVD or BD. Linux, FreeBSD, and Solaris allow to access drives
connected via SCSI, PATA (aka IDE, ATA), USB, or SATA.
<BR>
</P>
@ -50,7 +50,10 @@ via SCSI, PATA (aka IDE, ATA), USB, or SATA.
<DD>With kernel 2.4 an ATA drive has to be under ide-scsi emulation.</DD>
<DD>With kernel 2.6 the drive should not be under ide-scsi.</DD>
<DT>or FreeBSD (with libc, of course) :</DT>
<DD>ATAPI/CAM support has to be enabled in the kernel, see atapicam(4).</DD>
<DD>ATA and SATA drives need atapicam running.</DD>
<DD>libcam has to be installed.</DD>
<DT>or Solaris (with libc, of course) :</DT>
<DD>Tested on kernel 5.11, hopefully suitable for older ones too.</DD>
<DT>libpthread</DT>
<DD>is supposed to be a standard system component.</DD>
</DL>
@ -61,7 +64,7 @@ via SCSI, PATA (aka IDE, ATA), USB, or SATA.
GPL software included:<BR>
</H2>
<DL>
<DT>libburn-0.7.2</DT>
<DT>libburn-0.8.2</DT>
<DD>(founded by Derek Foreman and Ben Jansens,
developed and maintained since August 2006 by
Thomas Schmitt from team of libburnia-project.org)
@ -71,8 +74,8 @@ Thomas Schmitt from team of libburnia-project.org)
</P>
<P>
This program system has been tested on Intel/AMD Linux and FreeBSD systems
only.<BR>
This program system has been tested on Intel/AMD with Linux, FreeBSD,
and OpenSolaris based operating systems.<BR>
Ports to other usable systems are appreciated. Reports are welcome.
</P>
@ -104,8 +107,9 @@ BD-R. Write mode -tao works with anything but quickly blanked DVD-RW.
<DD>#<KBD>&nbsp;cdrskin --devices</KBD></DD>
<DT>Being superuser avoids permission problems with /dev/srN resp. /dev/hdX .
</DT>
<DT>Ordinary users should then get granted rw access to the /dev files
as listed by option --devices.</DT>
<DT>Ordinary users should then get granted access to the /dev files
as listed by option --devices. Linux and FreeBSD demand rw-permission.
On Solaris it is r-permission and privileges "basic,sys_devices".</DT>
<DT>&nbsp;</DT>
<DT>Get info about a particular drive or loaded media:</DT>
@ -193,8 +197,8 @@ Standalone ISO 9660 multi-session CD/DVD/BD tool
<P>
<DL>
<DT>Download as source code (see README):</DT>
<DD><A HREF="cdrskin-0.7.2.pl01.tar.gz">cdrskin-0.7.2.pl01.tar.gz</A>
(780 KB).
<DD><A HREF="cdrskin-0.8.2.pl00.tar.gz">cdrskin-0.8.2.pl00.tar.gz</A>
(845 KB).
</DD>
<DD>
The cdrskin tarballs are source code identical with libburn releases
@ -243,41 +247,38 @@ cdrskin_0.4.2.pl00-x86-suse9_0-static.tar.gz</A>, (310 KB), -static compiled,
<HR>
<P>
Enhancements towards previous stable version cdrskin-0.7.0.pl00:
Enhancements towards previous stable version cdrskin-0.8.0.pl00:
<UL>
<LI>Better interpretation of options -mode2, -xa, -xa1, -xa2</LI>
<LI>New option --xa1-ignore</LI>
<LI>New -atip report lines "Product Id:" and "Producer:"</LI>
<LI>Emulation of some -minfo output</LI>
<LI>A new system adapter allows to burn CD, DVD and BD on OpenSolaris</LI>
<!--
<LI>none</LI>
-->
</UL>
Bug fixes towards cdrskin-0.7.0.pl00:
Bug fixes towards cdrskin-0.8.0.pl00:
<UL>
<LI>CD TAO sessions with multiple tracks did not work in -dummy mode</LI>
<LI>
CD TOC was not read if the first track did not start at LBA 0
</LI>
<LI>
CD-ROM media got attributed random lead-in and lead-out adresses
</LI>
<LI>
SIGSEGV of experimental libcdio system adapter if drive list is empty
</LI>
<!--
<LI>none</LI>
-->
</UL>
Bug fixes towards cdrskin-0.7.2.pl00:
<UL>
<LI>Workaround for Pioneer DVR-216D which got stuck on DVD-R burns.</LI>
<LI>Workaround for Pioneer DVR-216D which did not always eject the tray.</LI>
</UL>
<HR>
<P>
<DL>
<DT><H3>Development snapshot, version 0.7.3 :</H3></DT>
<DD>Enhancements towards current stable version 0.7.2.pl00:
<DT><H3>Development snapshot, version 0.8.3 :</H3></DT>
<DD>Enhancements towards current stable version 0.8.2.pl00:
<UL>
<LI>Implemented option -V for logging of SCSI commands</LI>
<LI>New options dvd_obs= and stdio_fsync=</LI>
<LI>New compile_cdrskin.sh options -o_direct (Linux only), -dvd_obs_64k</LI>
<LI>none yet</LI>
<!--
<LI>none yet</LI>
-->
@ -285,10 +286,9 @@ Bug fixes towards cdrskin-0.7.2.pl00:
</UL>
</DD>
<DD>Bug fixes towards cdrskin-0.7.2.pl00:
<DD>Bug fixes towards cdrskin-0.8.2.pl00:
<UL>
<LI>Workaround for Pioneer DVR-216D which got stuck on DVD-R burns.</LI>
<LI>Workaround for Pioneer DVR-216D which did not always eject the tray.</LI>
<LI>none yet</LI>
<!--
<LI>none yet</LI>
-->
@ -296,10 +296,10 @@ Bug fixes towards cdrskin-0.7.2.pl00:
</DD>
<DD>&nbsp;</DD>
<DD><A HREF="README_cdrskin_devel">README 0.7.3</A>
<DD><A HREF="cdrskin__help_devel">cdrskin_0.7.3 --help</A></DD>
<DD><A HREF="cdrskin_help_devel">cdrskin_0.7.3 -help</A></DD>
<DD><A HREF="man_1_cdrskin_devel.html">man cdrskin (as of 0.7.3)</A></DD>
<DD><A HREF="README_cdrskin_devel">README 0.8.3</A>
<DD><A HREF="cdrskin__help_devel">cdrskin_0.8.3 --help</A></DD>
<DD><A HREF="cdrskin_help_devel">cdrskin_0.8.3 -help</A></DD>
<DD><A HREF="man_1_cdrskin_devel.html">man cdrskin (as of 0.8.3)</A></DD>
<DD>&nbsp;</DD>
<DT>Maintainers of cdrskin unstable packages please use SVN of
<A HREF="http://libburnia-project.org"> libburnia-project.org</A></DT>
@ -319,8 +319,8 @@ admins with full system souvereignty.</DT>
<A HREF="README_cdrskin_devel">upcoming README</A> ):
</DD>
<DD>
<A HREF="cdrskin-0.7.3.tar.gz">cdrskin-0.7.3.tar.gz</A>
(800 KB).
<A HREF="cdrskin-0.8.3.tar.gz">cdrskin-0.8.3.tar.gz</A>
(845 KB).
</DD>
<!-- This is not offered any more since spring 2008

View File

@ -1 +1 @@
#define Cdrskin_timestamP "2009.12.06.093847"
#define Cdrskin_timestamP "2010.06.11.080001"

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +1,14 @@
#!/bin/sh
# compile_cdrskin.sh
# Copyright 2005 - 2009 Thomas Schmitt, scdbackup@gmx.net, GPL version 2
# Copyright 2005 - 2010 Thomas Schmitt, scdbackup@gmx.net, GPL
# to be executed within ./libburn-* resp ./cdrskin-*
debug_opts="-O2"
def_opts=
largefile_opts="-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1"
fifo_opts="-DCdrskin_use_libburn_fifO"
libvers="-DCdrskin_libburn_0_7_3"
fifo_opts=""
libvers="-DCdrskin_libburn_0_8_2"
# To be used if Makefile.am uses libburn_libburn_la_CFLAGS
# burn="libburn/libburn_libburn_la-"
@ -20,11 +20,19 @@ libdax_audioxtr_o="$burn"libdax_audioxtr.o
do_strip=0
static_opts=
warn_opts="-Wall"
libcdio=
fifo_source="cdrskin/cdrfifo.c"
compile_cdrskin=1
compile_cdrfifo=0
compile_dewav=0
libcam=
os=$(uname -s)
case $os in
*FreeBSD)
libcam="-lcam"
esac
for i in "$@"
do
if test "$i" = "-compile_cdrfifo"
@ -39,15 +47,15 @@ do
libdax_audioxtr_o=
libdax_msgs_o="$burn"message.o
cleanup_src_or_obj="-DCleanup_has_no_libburn_os_H cdrskin/cleanup.c"
elif test "$i" = "-libburn_0_7_2"
elif test "$i" = "-libburn_0_8_2"
then
libvers="-DCdrskin_libburn_0_7_2"
libvers="-DCdrskin_libburn_0_8_2"
libdax_audioxtr_o="$burn"libdax_audioxtr.o
libdax_msgs_o="$burn"libdax_msgs.o
cleanup_src_or_obj="$burn"cleanup.o
elif test "$i" = "-libburn_svn"
then
libvers="-DCdrskin_libburn_0_7_3"
libvers="-DCdrskin_libburn_0_8_3"
libdax_audioxtr_o="$burn"libdax_audioxtr.o
libdax_msgs_o="$burn"libdax_msgs.o
cleanup_src_or_obj="$burn"cleanup.o
@ -85,6 +93,13 @@ do
then
fifo_source=
fifo_opts="-DCdrskin_use_libburn_fifO -DCdrskin_no_cdrfifO"
elif test "$i" = "-use_libburn_cleanup"
then
fifo_source=
fifo_opts="-DCdrskin_use_libburn_cleanuP -DCdrskin_use_libburn_fifO -DCdrskin_no_cdrfifO"
elif test "$i" = "-use_libcdio"
then
libcdio="-lcdio"
elif test "$i" = "-g"
then
debug_opts="-g"
@ -94,9 +109,10 @@ do
echo "Options:"
echo " -compile_cdrfifo compile program cdrskin/cdrfifo."
echo " -compile_dewav compile program test/dewav without libburn."
echo " -libburn_0_7_2 set macro to match libburn-0.7.2"
echo " -libburn_0_8_2 set macro to match libburn-0.8.2"
echo " -libburn_svn set macro to match current libburn-SVN."
echo " -dvd_obs_64k 64 KB default size for DVD/BD writing."
echo " -use_libcdio link with -lcdio because libburn uses it."
echo " -do_not_compile_cdrskin omit compilation of cdrskin/cdrskin."
echo " -use_no_libburn_fifo use cdrfifo even for single track non-CD"
echo " -use_no_cdrfifo always use fifo of libburn and never cdrfifo"
@ -120,7 +136,7 @@ echo "Build timestamp : $timestamp"
if test "$compile_cdrskin"
then
echo "compiling program cdrskin/cdrskin.c $fifo_source $static_opts $debug_opts $libvers $fifo_opts $def_opts $cleanup_src_or_obj"
echo "compiling program cdrskin/cdrskin.c $fifo_source $static_opts $debug_opts $libvers $fifo_opts $def_opts $cleanup_src_or_obj $libcdio $libcam"
cc -I. \
$warn_opts \
$static_opts \
@ -165,6 +181,8 @@ then
"$burn"crc.o \
"$burn"ecma130ab.o \
\
$libcdio \
$libcam \
-lpthread
ret=$?

View File

@ -1,13 +1,15 @@
AC_INIT([libburn], [0.7.3], [http://libburnia-project.org])
AC_INIT([libburn], [0.8.2], [http://libburnia-project.org])
AC_PREREQ([2.50])
dnl AC_CONFIG_HEADER([config.h])
AC_CANONICAL_HOST
AC_CANONICAL_TARGET
LIBBURNIA_SET_FLAGS
AM_INIT_AUTOMAKE([subdir-objects])
dnl Notes by ts A71207 - A91012 :
dnl Notes by ts A71207 - B00611 :
dnl
dnl Regrettably the meaning of the various version types was misunderstood
dnl before version 0.4.1.
@ -75,6 +77,11 @@ dnl 0.6.6 = libburn.so.4.31.0
dnl 0.6.8 = libburn.so.4.33.0
dnl 0.7.0 = libburn.so.4.35.0
dnl 0.7.2 = libburn.so.4.37.0
dnl 0.7.4 = libburn.so.4.39.0
dnl 0.7.6 = libburn.so.4.41.0
dnl 0.7.8 = libburn.so.4.43.0
dnl 0.8.0 = libburn.so.4.45.0
dnl 0.8.2 = libburn.so.4.47.0
dnl
dnl So LT_CURRENT, LT_REVISION and LT_AGE get set directly here.
dnl SONAME of the emerging library is LT_CURRENT - LT_AGE.
@ -99,8 +106,8 @@ dnl If BURN_*_VERSION changes, be sure to change AC_INIT above to match.
dnl
dnl As said: Only copies. Original in libburn/libburn.h : burn_header_version_*
BURN_MAJOR_VERSION=0
BURN_MINOR_VERSION=7
BURN_MICRO_VERSION=3
BURN_MINOR_VERSION=8
BURN_MICRO_VERSION=2
BURN_VERSION=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION.$BURN_MICRO_VERSION
AC_SUBST(BURN_MAJOR_VERSION)
@ -111,15 +118,15 @@ AC_SUBST(BURN_VERSION)
dnl Libtool versioning
LT_RELEASE=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION.$BURN_MICRO_VERSION
dnl
dnl ts A91116
dnl ### This is the release version libburn-0.7.2 = libburn.so.4.37.0
dnl This is the development version after above release version
dnl ### LT_CURRENT++, LT_AGE++ has not yet happened.
dnl LT_CURRENT++, LT_AGE++ has happened meanwhile.
dnl ts B00409
dnl This is the release version libburn-0.8.2
dnl ### This is the development version after above release version
dnl LT_CURRENT++, LT_AGE++ has not yet happened.
dnl ### LT_CURRENT++, LT_AGE++ has happened meanwhile.
dnl
dnl SONAME = 42 - 38 = 4 . Linux library name = libburn.so.4.38.0
LT_CURRENT=42
LT_AGE=38
dnl SONAME = 51 - 47 = 4 . Linux library name = libburn.so.4.47.0
LT_CURRENT=51
LT_AGE=47
LT_REVISION=0
LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE`
@ -196,8 +203,8 @@ CFLAGS="$CFLAGS $LIBBURN_O_DIRECT_DEF"
dnl ts A91116
AC_ARG_ENABLE(dvd-obs-64k,
[ --enable-dvd-obs-64k 64 KB default size for DVD/BD writing, default=no],
, enable_fifo_odirect=no)
[ --enable-dvd-obs-64k 64 KB default size for DVD/BD writing, default=no],
, enable_dvd_obs_64k=no)
if test x$enable_dvd_obs_64k = xyes; then
LIBBURN_DVD_OBS_64K="-DLibburn_dvd_obs_default_64K"
echo "enabled write size default 64 KB on DVD and BD"
@ -205,10 +212,36 @@ else
LIBBURN_DVD_OBS_64K=
echo "disabled write size default 64 KB on DVD and BD"
fi
dnl Avoid the need for libburn_libburn_la_CFLAGS in Makefile.am (ugly .o names)
dnl ### AC_SUBST(LIBBURN_DVD_OBS_64K)
CFLAGS="$CFLAGS $LIBBURN_DVD_OBS_64K"
dnl ts A91218
AC_ARG_ENABLE(libcdio,
[ --enable-libcdio Enable EXPERIMENTAL use of libcdio as system adapter, default=no],
, enable_libcdio=no)
if test x$enable_libcdio = xyes; then
dnl Check whether there is libcdio-devel and libcdio-runtime.
dnl If not, erase this macro
LIBCDIO_DEF="-DLibburn_use_libcdiO"
dnl The empty yes case obviously causes -lcdio to be linked
AC_CHECK_HEADER(cdio/cdio.h, AC_CHECK_LIB(cdio, mmc_last_cmd_sense, , LIBCDIO_DEF= ), LIBCDIO_DEF= )
else
LIBCDIO_DEF=
fi
if test x$LIBCDIO_DEF = x
then
if test x$enable_libcdio = xyes
then
echo "WARNING: could not enable use of libcdio as system adapter"
fi
else
echo "enabled EXPERIMENTAL use of libcdio as system adapter"
CFLAGS="$CFLAGS $LIBCDIO_DEF"
LIBCDIO_REQUIRED=0.83
PKG_CHECK_MODULES(LIBCDIO, libcdio >= $LIBCDIO_REQUIRED)
fi
dnl Add compiler-specific flags

View File

@ -73,9 +73,9 @@ compatible for a good while.
@subsection libburner-help Libburner --help
<pre>
Usage: test/libburner
[--drive <address>|<driveno>|"-"] [--audio]
[--drive address|driveno|"-"] [--audio]
[--blank_fast|--blank_full|--format] [--try_to_simulate]
[--multi] [<one or more imagefiles>|"-"]
[--multi] [one or more imagefiles|"-"]
Examples
A bus scan (needs rw-permissions to see a drive):
test/libburner --drive -

View File

@ -1,4 +1,4 @@
libburnia-project.org Optical Media Rotisserie Recipes as of January 2009
libburnia-project.org Optical Media Rotisserie Recipes as of January 2010
Content:
- TAO Multi-Session CD Cookbook (CD-R, CD-RW)
@ -86,7 +86,7 @@ parameters:
BUFE Buffer Underrun protection 0=off, 1=on
Test Write -dummy mode for writing 0=off, 1=on
Write Type Packet/TAO/SAO/RAW 01h = TAO
Multi-session Wether to keep appendable 00b = finalize
Multi-session Whether to keep appendable 00b = finalize
11b = keep appendable
Track Mode Describes frame type 4 for data , 0 for audio
Data Block Type Layout of payload blocks 8 for 2048 byte data blocks
@ -119,19 +119,22 @@ A track must at least contain 300 payload blocks: 4 seconds of audio or
600 KiB of data.
(mmc5r03c.pdf 6.3.3.1.2)
The track has to be closed by 5Bh CLOSE TRACK SESSION Close Function 001b.
Older MMC specifies a valid Logical Track Number FFh to depict the open track.
MMC-5 is quite silent about this. FFh works for my drives.
Up to december 2009 the track was closed by 5Bh CLOSE TRACK SESSION Close
Function 001b. Older MMC specifies a valid Logical Track Number FFh to depict
the open track. MMC-5 is quite silent about this. FFh worked for my drives.
(mmc5r03c.pdf 6.3.3.1.2)
This is omitted since libburn-0.7.4, relying entirely on 35h SYNCHRONIZE CACHE.
First appeared a drive where CLOSE TRACK fails in simulation mode, later
another one produced error replies even with real burning.
After that, a new track may be written beginning with sending the mode page 05h
again. It is not tested wether 05h can be omitted if Track Mode and Data Block
again. It is not tested whether 05h can be omitted if Track Mode and Data Block
Type are the same as with the previous track.
The new track will be added to the session which was opened by the first track.
After the last track of a session, 5Bh CLOSE TRACK SESSION Close Function 010b
with Logical Track Number 0 closes the session. It depends on the Multi-Session
value in mode page 05h wether the disc is finalized or stays appendable.
value in mode page 05h whether the disc is finalized or stays appendable.
(mmc5r03c.pdf 6.3.3.1.3)
@ -202,7 +205,7 @@ for finalized disc.
In libburn the address of the first track in the last session is obtained from
the last session's POINT = A0h and from the track descriptor with the POINT
value matching the PMIN value of the A0h descriptor.
Untested is wether POINT = B0h and 52h READ TRACK INFORMATION are always in
Untested is whether POINT = B0h and 52h READ TRACK INFORMATION are always in
sync. libburn uses the info provided by 52h READ TRACK INFORMATION.
@ -308,7 +311,7 @@ A Write Parameters mode page 05h has to be composed and transmitted via
BUFE Buffer Underrun protection 0=off, 1=on
Test Write -dummy mode for writing 0=off, 1=on
Write Type Packet/TAO/SAO/RAW 02h = SAO
Multi-session Wether to keep appendable 00b = finalize
Multi-session Whether to keep appendable 00b = finalize
11b = keep appendable
Track Mode Describes frame type 0 (is ignored)
Data Block Type Layout of payload blocks 0 (is ignored)
@ -349,7 +352,7 @@ There is no separator between the tracks of a pure mode SAO session.
(If the session was mixed mode, there would be extended Pre-gaps and Post-gaps
between data mode tracks and audio mode tracks.)
(libburn sends its own buffer to the drive at the end of each track but does
not sync the drive's chache. It is unclear wether this separation of tracks
not sync the drive's chache. It is unclear whether this separation of tracks
on the level of 2Ah WRITE is necessary with a pure mode session. It does not
harm in any case and would probably be unavoidable if audio and data tracks
were mixed.)
@ -755,7 +758,8 @@ The only known way to get full speed from DVD-RAM or BD-RE with enabled defect
management is the use of AAh WRITE12 with Streaming Bit set to 1.
(mmc5r03c.pdf 6.45)
With some DVD-RAM drives this fails if a write buffer is not full 32 kB.
With the tested BD-RE one has to write full 64 kB buffers.
With the tested BD-RE one must write full 64 kB buffers, or else writing
might not get into effect at all.
Although it seems not optimal, this is specified not only to disable the
cumbersome checkread but also to ignore known defects and to write data
@ -769,7 +773,8 @@ MMC-5 does not guarantee AAh WRITE12 to work on DVD-RAM or BD-RE at all.
None of the features of profiles 0012h and 0043h promises the existence of
AAh WRITE12.
(mmc5r03c.pdf 5.4.13, 6.45)
Nevertheless it worked on all tested drives if proper alignment was observed.
Nevertheless it worked on all tested drives if proper alignment and block
size was observed.
-------------------------------------------------------------------------------
@ -841,6 +846,8 @@ This chain gives the start addresses of sessions. The sector count minus start
address gives the size of a particular session. ECMA-119 explains how to
retrieve more info from the PVD (e.g. the volume id).
See also the multi-session example in libisofs/doc/checksums.txt.
-------------------------------------------------------------------------------
@ -933,7 +940,7 @@ Multi-Session by the application.
LS_V Link size valid 1=true
Test Write -dummy mode for writing 0=off, 1=on
Write Type Packet/TAO/SAO/RAW 00h = Incremental (Packet)
Multi-session Wether to keep appendable 00b = finalize
Multi-session Whether to keep appendable 00b = finalize
11b = keep appendable
Track Mode Describes frame type 5 [*1]
Data Block Type Layout of payload blocks 8 [*2]
@ -980,7 +987,7 @@ from the reply of 51h READ DISC INFORMATION requesting Data Type 000b
Multiple tracks are permissible in a single session. After all of them have
been written, 5Bh CLOSE TRACK SESSION Close Function 010b with Logical Track
Number 0 closes the session. It depends on the Multi-Session value in mode
page 05h wether the disc is finalized or stays appendable.
page 05h whether the disc is finalized or stays appendable.
(mmc5r03c.pdf 6.3.3.2.3)
@ -1005,7 +1012,7 @@ The mode page 05h to be sent :
LS_V Link size valid 0=false [*3]
Test Write -dummy mode for writing 0=off, 1=on
Write Type Packet/TAO/SAO/RAW 02h = DAO (same code as SAO)
Multi-session Wether to keep appendable 00b = finalize
Multi-session Whether to keep appendable 00b = finalize
Track Mode Describes frame type 5 [*1]
Data Block Type Layout of payload blocks 8 [*2]
Link Size ??? 0 [*3]
@ -1222,7 +1229,7 @@ No mode page 05h is to be sent.
growisofs sends a page but the specs clearly state that one shall not do.
(mmc5r03c.pdf 7.5.3)
It is optional wether a track size is reserved in advance or not. Eventually
It is optional whether a track size is reserved in advance or not. Eventually
this is done by 53h RESERVE TRACK, RMZ=ARSV=0. Reservation size should better
already be aligned to 32 KiB.
(mmc5r03c.pdf 6.31)

View File

@ -1,5 +1,9 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
/* ts A71019 */
@ -19,6 +23,9 @@
#define Libburn_detach_done_workeR 1
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include "libburn.h"
#include "transport.h"
@ -36,6 +43,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
/*
#include <a ssert.h>
@ -228,6 +236,22 @@ static void *scan_worker_func(struct w_list *w)
return NULL;
}
static void reset_progress(struct burn_drive *d, int sessions, int tracks,
int indices, int sectors, int flag)
{
/* reset the progress indicator */
d->progress.session = 0;
d->progress.sessions = sessions;
d->progress.track = 0;
d->progress.tracks = tracks;
d->progress.index = 0;
d->progress.indices = indices;
d->progress.start_sector = 0;
d->progress.sectors = sectors;
d->progress.sector = 0;
}
int burn_drive_scan(struct burn_drive_info *drives[], unsigned int *n_drives)
{
struct scan_opts o;
@ -297,8 +321,27 @@ drive_is_active:;
static void *erase_worker_func(struct w_list *w)
{
#define Libburn_protect_erase_threaD 1
#ifdef Libburn_protect_erase_threaD
sigset_t sigset, oldset;
/* Protect blank thread from being interrupted by external signals */
sigfillset(&sigset);
sigdelset(&sigset, SIGSEGV);
sigdelset(&sigset, SIGILL);
pthread_sigmask(SIG_SETMASK, &sigset, &oldset);
#endif /* Libburn_protect_erase_threaD */
burn_disc_erase_sync(w->u.erase.drive, w->u.erase.fast);
remove_worker(pthread_self());
#ifdef Libburn_protect_erase_threaD
/* (just in case it would not end with all signals blocked) */
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
#endif /* Libburn_protect_erase_threaD */
return NULL;
}
@ -310,6 +353,7 @@ void burn_disc_erase(struct burn_drive *drive, int fast)
/* a ssert(drive); */
/* a ssert(!SCAN_GOING()); */
/* a ssert(!find_worker(drive)); */
if((drive == NULL)) {
libdax_msgs_submit(libdax_messenger, drive->global_index,
0x00020104,
@ -325,6 +369,9 @@ void burn_disc_erase(struct burn_drive *drive, int fast)
0, 0);
return;
}
reset_progress(drive, 1, 1, 1, 0x10000, 0);
/* A70103 : will be set to 0 by burn_disc_erase_sync() */
drive->cancel = 1;
@ -365,9 +412,28 @@ void burn_disc_erase(struct burn_drive *drive, int fast)
/* ts A61230 */
static void *format_worker_func(struct w_list *w)
{
#define Libburn_protect_format_threaD 1
#ifdef Libburn_protect_format_threaD
sigset_t sigset, oldset;
/* Protect format thread from being interrupted by external signals */
sigfillset(&sigset);
sigdelset(&sigset, SIGSEGV);
sigdelset(&sigset, SIGILL);
pthread_sigmask(SIG_SETMASK, &sigset, &oldset);
#endif /* Libburn_protect_format_threaD */
burn_disc_format_sync(w->u.format.drive, w->u.format.size,
w->u.format.flag);
remove_worker(pthread_self());
#ifdef Libburn_protect_format_threaD
/* (just in case it would not end with all signals blocked) */
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
#endif /* Libburn_protect_format_threaD */
return NULL;
}
@ -379,6 +445,8 @@ void burn_disc_format(struct burn_drive *drive, off_t size, int flag)
int ok = 0, ret;
char msg[160];
reset_progress(drive, 1, 1, 1, 0x10000, 0);
if ((SCAN_GOING()) || find_worker(drive) != NULL) {
libdax_msgs_submit(libdax_messenger, drive->global_index,
0x00020102,
@ -508,8 +576,22 @@ no_non_default_bd_re:;
static void *write_disc_worker_func(struct w_list *w)
{
struct burn_drive *d = w->u.write.drive;
char msg[80];
#define Libburn_protect_write_threaD 1
#ifdef Libburn_protect_write_threaD
sigset_t sigset, oldset;
/* Protect write thread from being interrupted by external signals */
sigfillset(&sigset);
sigdelset(&sigset, SIGSEGV);
sigdelset(&sigset, SIGILL);
pthread_sigmask(SIG_SETMASK, &sigset, &oldset);
#endif /* Libburn_protect_write_threaD */
d->thread_pid = getpid();
d->thread_tid = pthread_self();
d->thread_pid_valid= 1;
burn_disc_write_sync(w->u.write.opts, w->u.write.disc);
d->thread_pid_valid= 0;
@ -519,7 +601,19 @@ static void *write_disc_worker_func(struct w_list *w)
*/
burn_write_opts_free(w->u.write.opts);
sprintf(msg, "Write thread on drive %d ended", d->global_index);
libdax_msgs_submit(libdax_messenger, d->global_index, 0x00020178,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
remove_worker(pthread_self());
d->busy = BURN_DRIVE_IDLE;
#ifdef Libburn_protect_write_threaD
/* (just in case it would not end with all signals blocked) */
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
#endif /* Libburn_protect_write_threaD */
return NULL;
}
@ -543,6 +637,9 @@ void burn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
return;
}
reset_progress(d, disc->sessions, disc->session[0]->tracks,
disc->session[0]->track[0]->indices, 0, 0);
/* For the next lines any return indicates failure */
d->cancel = 1;
@ -609,12 +706,30 @@ static void *fifo_worker_func(struct w_list *w)
{
int old;
#define Libburn_protect_fifo_threaD 1
#ifdef Libburn_protect_fifo_threaD
sigset_t sigset, oldset;
/* Protect fifo thread from being interrupted by external signals */
sigfillset(&sigset);
sigdelset(&sigset, SIGSEGV);
sigdelset(&sigset, SIGILL);
pthread_sigmask(SIG_SETMASK, &sigset, &oldset);
#endif /* Libburn_protect_fifo_threaD */
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old);
/* Note: Only burn_fifo_abort() shall cancel the fifo thread */
burn_fifo_source_shoveller(w->u.fifo.source, w->u.fifo.flag);
remove_worker(pthread_self());
#ifdef Libburn_protect_fifo_threaD
/* (just in case it would not end with all signals blocked) */
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
#endif /* Libburn_protect_fifo_threaD */
return NULL;
}
@ -639,6 +754,7 @@ int burn_fifo_start(struct burn_source *source, int flag)
add_worker(Burnworker_type_fifO, NULL,
(WorkerFunc) fifo_worker_func, &o);
fs->is_started = 1;
return 1;
}

View File

@ -1,4 +1,6 @@
/**
Copyright (c) 2006 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
This file bundles variables which disable changes in libburn which are
not yet completely accepted.

View File

@ -3,13 +3,17 @@
A signal handler which cleans up an application and exits.
Provided under GPL license within GPL projects, BSD license elsewise.
Provided under GPLv2+ license within GPL projects, BSD license elsewise.
*/
/*
cc -g -o cleanup -DCleanup_standalonE cleanup.c
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
@ -40,7 +44,8 @@ static int non_signal_list_count= BURN_OS_NON_SIGNAL_COUNT;
#else /* ! Cleanup_has_no_libburn_os_H */
/* Outdated. Linux only. For backward compatibility with pre-libburn-0.2.3 */
/* Outdated. GNU/Linux only.
For backward compatibility with pre-libburn-0.2.3 */
/* Signals to be caught */
static int signal_list[]= {

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 GPLv2+ within GPL projects, BSD license elsewise.
*/
#ifndef Cleanup_includeD

View File

@ -1,5 +1,9 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include "crc.h"
static unsigned short ccitt_table[256] = {
@ -104,6 +108,15 @@ unsigned long crc32_table[256] = {
0x71C0FC00L, 0xE151FD01L, 0xE0E1FE01L, 0x7070FF00L
};
/* Exploration ts B00214 :
ECMA-130, 22.3.6 "CRC field"
Generating polynomial: x^16 + x^12 + x^5 + 1
Also known as CRC-16-CCITT, CRC-CCITT
Use in libburn for raw write modes in sector.c.
There is also disabled code in read.c which would use it.
*/
unsigned short crc_ccitt(unsigned char *q, int len)
{
unsigned short crc = 0;
@ -112,6 +125,20 @@ unsigned short crc_ccitt(unsigned char *q, int len)
crc = ccitt_table[(crc >> 8 ^ *q++) & 0xff] ^ (crc << 8);
return ~crc;
}
/* Exploration ts B00214 :
ECMA-130, 14.3 "EDC field"
"The EDC codeword must be divisible by the check polynomial:
P(x) = (x^16 + x^15 + x^2 + 1) . (x^16 + x^2 + x + 1)
"
>>> Test whether this coincides with CRC-32 IEEE 802.3
x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10
+ x^8 + x^7 + x^5 + x^4 + x^2 + x + 1
Used for raw writing in sector.c
*/
unsigned int crc_32(unsigned char *data, int len)
{
unsigned int crc = 0;

View File

@ -3,7 +3,21 @@
#ifndef BURN__CRC_H
#define BURN__CRC_H
#ifdef Xorriso_standalonE
/* Source module crc.c of yet unclear ancestry is excluded from GNU xorriso */
#ifndef Libburn_no_crc_C
#define Libburn_no_crc_C 1
#endif
#endif
#ifndef Libburn_no_crc_C
unsigned short crc_ccitt(unsigned char *, int len);
unsigned int crc_32(unsigned char *, int len);
#endif /* Libburn_no_crc_C */
#endif /* BURN__CRC_H */

View File

@ -22,6 +22,10 @@
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

View File

@ -1,5 +1,14 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#ifdef WIN32
#include <windows.h>
#endif

View File

@ -1,9 +1,19 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include <sys/types.h>
#include <sys/stat.h>
/* #include <m alloc.h> ts A61013 : not in Linux man 3 malloc */
/* #include <m alloc.h> ts A61013 : not in GNU/Linux man 3 malloc */
#include <stdlib.h>
#include <unistd.h>
@ -90,6 +100,7 @@ void burn_drive_free_subs(struct burn_drive *d)
if (d->stdio_fd >= 0)
close (d->stdio_fd);
d->stdio_fd = -1;
sg_dispose_drive(d, 0);
}
@ -369,6 +380,7 @@ struct burn_drive *burn_drive_register(struct burn_drive *d)
d->busy = BURN_DRIVE_IDLE;
d->thread_pid = 0;
d->thread_pid_valid = 0;
memset(&(d->thread_tid), 0, sizeof(d->thread_tid));
d->toc_entries = 0;
d->toc_entry = NULL;
d->disc = NULL;
@ -614,8 +626,9 @@ void burn_disc_erase_sync(struct burn_drive *d, int fast)
d->idata->product);
d->cancel = 0;
d->busy = BURN_DRIVE_ERASING;
d->erase(d, fast);
#ifdef Libburn_reset_progress_asynC
/* <<< This is now done in async.c */
/* reset the progress */
d->progress.session = 0;
d->progress.sessions = 1;
@ -626,6 +639,11 @@ void burn_disc_erase_sync(struct burn_drive *d, int fast)
d->progress.start_sector = 0;
d->progress.sectors = 0x10000;
d->progress.sector = 0;
#endif /* Libburn_reset_progress_asynC */
d->erase(d, fast);
d->busy = BURN_DRIVE_ERASING;
/* read the initial 0 stage */
while (!d->test_unit_ready(d) && d->get_erase_progress(d) == 0)
sleep(1);
@ -652,6 +670,8 @@ void burn_disc_format_sync(struct burn_drive *d, off_t size, int flag)
char msg[80];
struct buffer buf, *buf_mem = d->buffer;
#ifdef Libburn_reset_progress_asynC
/* <<< This is now done in async.c */
/* reset the progress */
d->progress.session = 0;
d->progress.sessions = 1;
@ -662,6 +682,8 @@ void burn_disc_format_sync(struct burn_drive *d, off_t size, int flag)
d->progress.start_sector = 0;
d->progress.sectors = 0x10000;
d->progress.sector = 0;
#endif /* Libburn_reset_progress_asynC */
stages = 1 + ((flag & 1) && size > 1024 * 1024);
d->cancel = 0;
d->busy = BURN_DRIVE_FORMATTING;
@ -798,10 +820,22 @@ int burn_disc_erasable(struct burn_drive *d)
enum burn_drive_status burn_drive_get_status(struct burn_drive *d,
struct burn_progress *p)
{
/* --- Part of asynchronous signal handling --- */
/* This frequently used call may be used to react on messages from
the libburn built-in signal handler.
*/
/* ts B00225 :
If aborting with action 2:
catch control thread after it returned from signal handler.
Let it run burn_abort(4440,...)
*/
burn_init_catch_on_abort(0);
/* ts A70928 : inform control thread of signal in sub-threads */
if (burn_global_abort_level > 0)
if (burn_builtin_triggered_action < 2 && burn_global_abort_level > 0)
burn_global_abort_level++;
if (burn_global_abort_level > 5) {
if (burn_builtin_triggered_action < 2 && burn_global_abort_level > 5) {
if (burn_global_signal_handler == NULL)
kill(getpid(), burn_global_abort_signum);
else
@ -811,6 +845,9 @@ enum burn_drive_status burn_drive_get_status(struct burn_drive *d,
burn_global_abort_level = -1;
}
/* --- End of asynchronous signal handling --- */
if (p != NULL) {
memcpy(p, &(d->progress), sizeof(struct burn_progress));
/* TODO: add mutex */
@ -832,9 +869,13 @@ int burn_drive_set_stream_recording(struct burn_drive *d, int recmode,
void burn_drive_cancel(struct burn_drive *d)
{
/* ts B00225 : these mutexes are unnecessary because "= 1" is atomar.
pthread_mutex_lock(&d->access_lock);
*/
d->cancel = 1;
/*
pthread_mutex_unlock(&d->access_lock);
*/
}
/* ts A61007 : defunct because unused */
@ -907,20 +948,27 @@ static int drive_getcaps(struct burn_drive *d, struct burn_drive_info *out)
out->c2_errors = !!d->mdata->c2_pointers;
out->drive = d;
#ifdef Libburn_pioneer_dvr_216d_dummy_probe_wM
#ifdef Libburn_dummy_probe_write_modeS
/* ts A91112 */
/* Set default block types. The call d->probe_write_modes() is quite
obtrusive. It may be performed explicitely by new API call
burn_drive_probe_cd_write_modes().
*/
out->tao_block_types = d->block_types[BURN_WRITE_TAO] =
BURN_BLOCK_MODE1 | BURN_BLOCK_RAW0;
out->sao_block_types = d->block_types[BURN_WRITE_SAO] = BURN_BLOCK_SAO;
if (out->write_dvdram || out->write_dvdr ||
out->write_cdrw || out->write_cdr) {
out->tao_block_types = d->block_types[BURN_WRITE_TAO] =
BURN_BLOCK_MODE1 | BURN_BLOCK_RAW0;
out->sao_block_types = d->block_types[BURN_WRITE_SAO] =
BURN_BLOCK_SAO;
} else {
out->tao_block_types = d->block_types[BURN_WRITE_TAO] = 0;
out->sao_block_types = d->block_types[BURN_WRITE_SAO] = 0;
}
out->raw_block_types = d->block_types[BURN_WRITE_RAW] = 0;
out->packet_block_types = 0;
#else /* Libburn_pioneer_dvr_216d_dummy_probe_wM */
#else /* Libburn_dummy_probe_write_modeS */
/* update available block types for burners */
if (out->write_dvdram || out->write_dvdr ||
@ -931,15 +979,14 @@ static int drive_getcaps(struct burn_drive *d, struct burn_drive_info *out)
out->raw_block_types = d->block_types[BURN_WRITE_RAW];
out->packet_block_types = d->block_types[BURN_WRITE_PACKET];
#endif /* ! Libburn_pioneer_dvr_216d_dummy_probe_wM */
#endif /* ! Libburn_dummy_probe_write_modeS */
return 1;
}
#ifdef Libburn_pioneer_dvr_216d_dummy_probe_wM
/* ts A91112 candidate for API */
/* ts A91112 - B00114 API */
/* Probe available CD write modes and block types.
*/
int burn_drive_probe_cd_write_modes(struct burn_drive_info *dinfo)
@ -958,8 +1005,6 @@ int burn_drive_probe_cd_write_modes(struct burn_drive_info *dinfo)
return 1;
}
#endif /* Libburn_pioneer_dvr_216d_dummy_probe_wM */
/* ts A70907 : added parameter flag */
/* @param flag bit0= reset global drive list */
@ -1317,6 +1362,7 @@ int burn_drive__fd_from_special_adr(char *adr)
int burn_drive_grab_dummy(struct burn_drive_info *drive_infos[], char *fname)
{
int ret = -1, fd = -1, role = 0;
int is_block_dev = 0;
/* divided by 512 it needs to fit into a signed long integer */
off_t size = ((off_t) (512 * 1024 * 1024 - 1) * (off_t) 2048);
off_t read_size = -1;
@ -1333,17 +1379,18 @@ int burn_drive_grab_dummy(struct burn_drive_info *drive_infos[], char *fname)
else
ret = stat(fname, &stbuf);
if (ret != -1) {
is_block_dev = burn_os_is_2k_seekrw(fname, 0);
if (S_ISREG(stbuf.st_mode))
read_size = stbuf.st_size;
else if (S_ISBLK(stbuf.st_mode)) {
else if (is_block_dev) {
ret = burn_os_stdio_capacity(fname,
&read_size);
if (ret <= 0)
read_size = -1;
read_size = (off_t) 0x7ffffff0 *
(off_t) 2048;
}
}
if (ret == -1 || S_ISBLK(stbuf.st_mode) ||
S_ISREG(stbuf.st_mode)) {
if (ret == -1 || is_block_dev || S_ISREG(stbuf.st_mode)) {
ret = burn_os_stdio_capacity(fname, &size);
if (ret == -1) {
libdax_msgs_submit(libdax_messenger, -1,
@ -1559,14 +1606,23 @@ int burn_drive_is_enumerable_adr(char *adr)
#define BURN_DRIVE_MAX_LINK_DEPTH 20
/* ts A60922 ticket 33 */
int burn_drive_resolve_link(char *path, char adr[], int *recursion_count)
/* @param flag bit0= no debug messages
bit1= resolve only links,
do not rely on drive list for resolving via st_rdev
*/
int burn_drive_resolve_link(char *path, char adr[], int *recursion_count,
int flag)
{
int ret;
char link_target[4096], msg[4096+100], link_adr[4096], *adrpt;
struct stat stbuf;
burn_drive_adr_debug_msg("burn_drive_resolve_link( %s )", path);
if (flag & 1)
burn_drive_adr_debug_msg("burn_drive_resolve_link( %s )",
path);
if (*recursion_count >= BURN_DRIVE_MAX_LINK_DEPTH) {
burn_drive_adr_debug_msg(
if (flag & 1)
burn_drive_adr_debug_msg(
"burn_drive_resolve_link aborts because link too deep",
NULL);
return 0;
@ -1574,12 +1630,15 @@ int burn_drive_resolve_link(char *path, char adr[], int *recursion_count)
(*recursion_count)++;
ret = readlink(path, link_target, sizeof(link_target));
if (ret == -1) {
burn_drive_adr_debug_msg("readlink( %s ) returns -1", path);
if (flag & 1)
burn_drive_adr_debug_msg("readlink( %s ) returns -1",
path);
return 0;
}
if (ret >= sizeof(link_target) - 1) {
sprintf(msg,"readlink( %s ) returns %d (too much)", path, ret);
burn_drive_adr_debug_msg(msg, NULL);
if (flag & 1)
burn_drive_adr_debug_msg(msg, NULL);
return -1;
}
link_target[ret] = 0;
@ -1592,10 +1651,25 @@ int burn_drive_resolve_link(char *path, char adr[], int *recursion_count)
} 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);
if (flag & 2) {
/* Link-only recursion */
if (lstat(adrpt, &stbuf) == -1) {
;
} else if((stbuf.st_mode & S_IFMT) == S_IFLNK) {
ret = burn_drive_resolve_link(adrpt, adr,
recursion_count, flag);
} else {
strcpy(adr, adrpt);
}
} else {
/* Link and device number recursion */
ret = burn_drive_convert_fs_adr_sub(adrpt, adr,
recursion_count);
sprintf(msg,"burn_drive_convert_fs_adr( %s ) returns %d",
link_target, ret);
}
if (flag & 1)
burn_drive_adr_debug_msg(msg, NULL);
return ret;
}
@ -1769,7 +1843,7 @@ int burn_drive_convert_fs_adr_sub(char *path, char adr[], int *rec_count)
return 0;
}
if((stbuf.st_mode & S_IFMT) == S_IFLNK) {
ret = burn_drive_resolve_link(path, adr, rec_count);
ret = burn_drive_resolve_link(path, adr, rec_count, 0);
if(ret > 0)
return 1;
burn_drive_adr_debug_msg("link fallback via stat( %s )", path);
@ -1818,17 +1892,12 @@ int burn_abort_pacifier(void *handle, int patience, int elapsed)
}
/** Abort any running drive operation and finish 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
/* ts B00226 : Outsourced backend of burn_abort()
@param flag bit0= do not call burn_finish()
*/
int burn_abort(int patience,
int burn_abort_5(int patience,
int (*pacifier_func)(void *handle, int patience, int elapsed),
void *handle)
void *handle, int elapsed, int flag)
{
int ret, i, occup, still_not_done= 1, pacifier_off= 0, first_round= 1;
unsigned long wait_grain= 100000;
@ -1838,7 +1907,14 @@ int burn_abort(int patience,
time_t stdio_patience = 3;
#endif
/*
fprintf(stderr,
"libburn_EXPERIMENTAL: burn_abort_5(%d,%d)\n", patience, flag);
*/
current_time = start_time = pacifier_time = time(0);
start_time -= elapsed;
end_time = start_time + patience;
/* >>> ts A71002 : are there any threads at work ?
@ -1846,7 +1922,7 @@ int burn_abort(int patience,
change status on their own.
*/
while(current_time-end_time < patience) {
while(current_time < end_time || (patience <= 0 && first_round)) {
still_not_done = 0;
for(i = 0; i < drivetop + 1; i++) {
@ -1885,6 +1961,9 @@ int burn_abort(int patience,
}
if(occup <= 10) {
if (drive_array[i].drive_role != 1)
/* occup == -1 comes early */
usleep(1000000);
burn_drive_forget(&(drive_array[i]), 1);
} else if(occup <= 100) {
if(first_round)
@ -1896,7 +1975,7 @@ int burn_abort(int patience,
}
first_round = 0;
if(still_not_done == 0)
if(still_not_done == 0 || patience <= 0)
break;
usleep(wait_grain);
current_time = time(0);
@ -1909,11 +1988,35 @@ int burn_abort(int patience,
pacifier_time = current_time;
}
}
burn_finish();
if (!(flag & 1))
burn_finish();
return(still_not_done == 0);
}
/** Abort any running drive operation and finish 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, flg = 0;
if (patience < 0) {
patience = 0;
flg |= 1;
}
ret = burn_abort_5(patience, pacifier_func, handle, 0, flg);
return ret;
}
/* ts A61020 API function */
int burn_drive_get_start_end_lba(struct burn_drive *d,
int *start_lba, int *end_lba, int flag)
@ -2608,6 +2711,9 @@ int burn_drive_equals_adr(struct burn_drive *d1, char *adr2_in, int role2)
if (S_ISBLK(stbuf1.st_mode) && S_ISBLK(stbuf2.st_mode) &&
stbuf1.st_rdev == stbuf2.st_rdev)
return 1; /* same major,minor device number */
if (S_ISCHR(stbuf1.st_mode) && S_ISCHR(stbuf2.st_mode) &&
stbuf1.st_rdev == stbuf2.st_rdev)
return 1; /* same major,minor device number */
/* Are both filesystem objects related to the same MMC drive */
if (conv_ret2 <= 0)
@ -2644,7 +2750,8 @@ int burn_drive_equals_adr(struct burn_drive *d1, char *adr2_in, int role2)
}
int burn_drive_find_by_thread_pid(struct burn_drive **d, pid_t pid)
int burn_drive_find_by_thread_pid(struct burn_drive **d, pid_t pid,
pthread_t tid)
{
int i;
@ -2656,7 +2763,8 @@ int burn_drive_find_by_thread_pid(struct burn_drive **d, pid_t pid)
*/
if (drive_array[i].thread_pid_valid &&
drive_array[i].thread_pid == pid) {
drive_array[i].thread_pid == pid &&
pthread_equal(drive_array[i].thread_tid, tid)) {
*d = &(drive_array[i]);
return 1;
}

View File

@ -1,5 +1,11 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifndef __DRIVE
#define __DRIVE
@ -121,8 +127,9 @@ int burn_disc_get_write_mode_demands(struct burn_disc *disc,
int burn_drive__fd_from_special_adr(char *adr);
/* ts A70929 : Find the drive which is being worked on by pid */
int burn_drive_find_by_thread_pid(struct burn_drive **d, pid_t pid);
/* ts A70929 : Find the drive which is being worked on by pid , tid */
int burn_drive_find_by_thread_pid(struct burn_drive **d, pid_t pid,
pthread_t tid);
/* ts A51221 - A80731 : Whitelist inquiry functions */
@ -135,4 +142,12 @@ char *burn_drive_whitelist_item(int idx, int flag);
int burn_drive_is_listed(char *path, struct burn_drive **found, int flag);
/* ts B00226 : Outsourced backend of burn_abort()
@param elapsed to be subtracted from start time
@param flag bit0= do not shutdown the library
*/
int burn_abort_5(int patience,
int (*pacifier_func)(void *handle, int patience, int elapsed),
void *handle, int elapsed, int flag);
#endif /* __DRIVE */

View File

@ -1,9 +1,14 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
/* ts A91016 : libburn/ecma130ab.c is the replacement for old libburn/lec.c
Copyright 2009, Thomas Schmitt <scdbackup@gmx.net>, libburnia-project.org
Provided under GPL version 2 or later.
This code module implements the production of RSPC parity bytes (P- and Q-
parity) and the scrambling of raw CD-ROM sectors as specified in ECMA-130:

View File

@ -4,6 +4,7 @@
/* ts A91016 : libburn/ecma130ab.h is the replacement for old libburn/lec.h
Copyright 2009, Thomas Schmitt <scdbackup@gmx.net>, libburnia-project.org
Provided under GPL version 2 or later.
This code module implements the computations prescribed in ECMA-130 Annex A
and B. For explanations of the underlying mathematics see ecma130ab.c .

View File

@ -1,5 +1,15 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include <stdlib.h>
#include <sys/types.h>
@ -83,7 +93,9 @@ static off_t file_size(struct burn_source *source)
if (fs->fixed_size > 0)
return fs->fixed_size;
if (fstat(fs->datafd, &buf) == -1)
if (fstat(fs->datafd, &buf) != 0)
return (off_t) 0;
if ((buf.st_mode & S_IFMT) != S_IFREG)
return (off_t) 0;
return (off_t) buf.st_size;
}
@ -391,9 +403,13 @@ int burn_fifo_source_shoveller(struct burn_source *source, int flag)
else
ret = fs->inp->read_xt( fs->inp,
(unsigned char *) bufpt, fs->inp_read_size);
if (ret == 0)
if (ret == 0) {
/* >>> ??? ts B00326 */
/* >>> report EOF of fifo input and fs->in_counter */;
break; /* EOF */
else if (ret < 0) {
} else if (ret < 0) {
libdax_msgs_submit(libdax_messenger, -1, 0x00020153,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Read error on fifo input", errno, 0);

View File

@ -1,5 +1,10 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifndef BURN__FILE_H
#define BURN__FILE_H

View File

@ -1,5 +1,15 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include <unistd.h>
/* ts A61007 */
@ -9,6 +19,7 @@
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
/* ts A70928 : init.h is for others, not for init .c
#include "init.h"
@ -32,14 +43,16 @@ struct libdax_msgs *libdax_messenger= NULL;
int burn_running = 0;
/* ts A60813 : Linux: wether to use O_EXCL on open() of device files */
/* ts A60813 : GNU/Linux: whether to use O_EXCL on open() of device files
ts B00212 : FreeBSD: whether to use flock(LOCK_EX) after open()
*/
int burn_sg_open_o_excl = 1;
/* ts A70403 : Linux: wether to use fcntl(,F_SETLK,)
/* ts A70403 : GNU/Linux: wether to use fcntl(,F_SETLK,)
after open() of device files */
int burn_sg_fcntl_f_setlk = 1;
/* ts A70314 : Linux: what device family to use :
/* ts A70314 : GNU/Linux: what device family to use :
0= default family
1= sr
2= scd
@ -59,6 +72,12 @@ int burn_sg_open_o_nonblock = 1;
to unconditional abort of the process */
int burn_sg_open_abort_busy = 0;
/* The message returned from sg_id_string() and/or sg_initialize()
*/
static char sg_initialize_msg[1024] = {""};
/* ts A61002 */
#include "cleanup.h"
@ -66,10 +85,13 @@ int burn_sg_open_abort_busy = 0;
/* Parameters for builtin abort handler */
static char abort_message_prefix[81] = {"libburn : "};
static pid_t abort_control_pid= 0;
static pthread_t abort_control_thread;
volatile int burn_global_abort_level= 0;
int burn_global_abort_signum= 0;
void *burn_global_signal_handle = NULL;
burn_abort_handler_t burn_global_signal_handler = NULL;
int burn_builtin_signal_action = 0; /* burn_set_signal_handling() */
volatile int burn_builtin_triggered_action = 0; /* burn_is_aborting() */
/* ts A70223 : wether implemented untested profiles are supported */
@ -110,6 +132,14 @@ int burn_initialize(void)
ret = burn_msgs_initialize();
if (ret <= 0)
return 0;
ret = sg_initialize(sg_initialize_msg, 0);
if (ret <= 0) {
libdax_msgs_submit(libdax_messenger, -1,
0x00020175,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
sg_initialize_msg, 0, 0);
return 0;
}
burn_running = 1;
return 1;
}
@ -137,10 +167,22 @@ void burn_finish(void)
/* ts A60924 : ticket 74 */
libdax_msgs_destroy(&libdax_messenger,0);
sg_shutdown(0);
burn_running = 0;
}
/* ts A91226 */
/** API function. See libburn.h */
char *burn_scsi_transport_id(int flag)
{
if (!burn_running)
sg_id_string(sg_initialize_msg, 0);
return sg_initialize_msg;
}
/* ts A60813 */
/** API function. See libburn.h */
void burn_preset_device_open(int exclusive, int blocking, int abort_on_busy)
@ -295,6 +337,20 @@ int burn_sev_to_text(int severity_number, char **severity_name, int flag)
return ret;
}
/* ts B00224 */
char *burn_util_thread_id(pid_t pid, pthread_t tid, char text[80])
{
int i, l;
sprintf(text, "[%lu,", (unsigned long int) getpid());
l= strlen(text);
for(i= 0; i < sizeof(pthread_t) && 2 * i < 80 - l - 3; i++)
sprintf(text + l + 2 * i,
"%2.2X", ((unsigned char *) &tid)[i]);
sprintf(text + l + 2 * i, "]");
return text;
}
int burn_builtin_abort_handler(void *handle, int signum, int flag)
{
@ -303,15 +359,53 @@ int burn_builtin_abort_handler(void *handle, int signum, int flag)
/*
#define Libburn_signal_handler_verbouS 1
*/
int ret;
struct burn_drive *d;
#ifdef Libburn_signal_handler_verbouS
fprintf(stderr,
"libburn_ABORT: pid = %d , abort_control_pid = %d , sig= %d\n",
getpid(), abort_control_pid, signum);
char text[80];
fprintf(stderr, "libburn_ABORT: in = %s\n",
burn_util_thread_id(getpid(), pthread_self(), text));
fprintf(stderr, "libburn_ABORT: ctrl = %s\n",
burn_util_thread_id(abort_control_pid, abort_control_thread,
text));
if (burn_global_signal_handler == burn_builtin_abort_handler)
fprintf(stderr, "libburn_ABORT: signal action = %d\n",
burn_builtin_signal_action);
/* >>> find writing drives and report their tid
fprintf(stderr, "libburn_ABORT: wrt = %s\n",
burn_util_thread_id(0, burn_write_thread_id, text));
fprintf(stderr, "libburn_ABORT: sig= %d\n", signum);
*/
#endif
burn_builtin_triggered_action = burn_builtin_signal_action;
burn_global_abort_level = -1;
if (burn_builtin_signal_action > 1) {
Cleanup_set_handlers(NULL, NULL, 2);
if (burn_builtin_signal_action == 4)
return -2;
fprintf(stderr,"%sABORT : Trying to shut down busy drives\n",
abort_message_prefix);
fprintf(stderr,
"%sABORT : Wait the normal burning time before any kill -9\n",
abort_message_prefix);
burn_abort_5(0, burn_abort_pacifier, abort_message_prefix,
0, 1);
libdax_msgs_submit(libdax_messenger, -1, 0x00020177,
LIBDAX_MSGS_SEV_ABORT, LIBDAX_MSGS_PRIO_HIGH,
"Urged drive worker threads to do emergency halt",
0, 0);
return -2;
}
/* ---- old deprecated stuck-in-abort-handler loop ---- */
/* ts A70928:
Must be quick. Allowed to coincide with other thread and to share
the increment with that one. It must not decrease, though, and
@ -324,7 +418,8 @@ int burn_builtin_abort_handler(void *handle, int signum, int flag)
#ifdef Libburn_new_thread_signal_handleR
ret = burn_drive_find_by_thread_pid(&d, getpid());
ret = burn_drive_find_by_thread_pid(&d, getpid(),
pthread_self());
if (ret > 0 && d->busy == BURN_DRIVE_WRITING) {
/* This is an active writer thread */
@ -364,13 +459,13 @@ int burn_builtin_abort_handler(void *handle, int signum, int flag)
}
burn_global_abort_level = -1;
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,
@ -380,28 +475,71 @@ int burn_builtin_abort_handler(void *handle, int signum, int flag)
return(1);
}
/* ts A61002 : API */
void burn_set_signal_handling(void *handle, burn_abort_handler_t handler,
int mode)
int mode)
{
if(handler == NULL && mode == 0) {
/*
fprintf(stderr, "libburn_experimental: burn_set_signal_handling, handler==%lx mode=%d\n", (unsigned long) handler, mode);
*/
if(handler == NULL) {
handler = burn_builtin_abort_handler;
/*
fprintf(stderr, "libburn_experimental: activated burn_builtin_abort_handler() with handle '%s'\n",(handle==NULL ? "libburn : " : (char *) handle));
if ((mode & ~4) == 0)
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)
abort_message_prefix[0] = 0;
if(handle != NULL && handler == burn_builtin_abort_handler)
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);
abort_control_thread = pthread_self();
burn_builtin_signal_action = (mode >> 4) & 15;
if((mode & 11) != 0)
burn_builtin_signal_action = 0;
if(burn_builtin_signal_action > 1)
burn_builtin_triggered_action = 0;
if(burn_builtin_signal_action == 0)
burn_builtin_signal_action = 1;
Cleanup_set_handlers(handle, (Cleanup_app_handler_T) handler,
(mode & 15) | 4);
burn_global_signal_handle = handle;
burn_global_signal_handler = handler;
}
/* ts B00304 : API */
int burn_is_aborting(int flag)
{
return burn_builtin_triggered_action;
}
/* ts B00225 */
/* @return 0= no abort action 2 pending , 1= not control thread
*/
int burn_init_catch_on_abort(int flag)
{
if (burn_builtin_triggered_action != 2)
return 0;
if (abort_control_pid != getpid() ||
abort_control_thread != pthread_self())
return 1;
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);
exit(1);
}
/* ts A70223 : API */
void burn_allow_untested_profiles(int yes)
{

View File

@ -17,5 +17,15 @@ extern int burn_global_abort_signum;
extern void *burn_global_signal_handle;
extern burn_abort_handler_t burn_global_signal_handler;
extern int burn_builtin_signal_action; /* burn_set_signal_handling() */
extern volatile int burn_builtin_triggered_action; /* burn_is_aborting() */
/* ts B00225 */
/* @return 0= no abort pending , 1= not control thread ,
-1= surprisingly burn_abort returned
*/
int burn_init_catch_on_abort(int flag);
#endif /* BURN__INIT_H */

View File

@ -1,5 +1,14 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
This is the official API definition of libburn.
*/
#ifndef LIBBURN_H
#define LIBBURN_H
@ -9,8 +18,10 @@ Applications must use 64 bit off_t. E.g. by defining
#define _LARGEFILE_SOURCE
#define _FILE_OFFSET_BITS 64
or take special precautions to interface with the library by 64 bit integers
where this .h files prescribe off_t. Not to use 64 bit file i/o will keep the
application from producing and processing ISO images of more than 2 GB size.
where this .h files prescribe off_t.
To prevent 64 bit file i/o in the library would keep the application from
processing tracks of more than 2 GB size.
*/
#include <sys/types.h>
@ -725,17 +736,22 @@ 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
/** Abort any running drive operation and eventually call burn_finish().
You MUST shut down the busy drives 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:
handling code or indirectly by activating the built-in 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
Else you may eventually call burn_drive_cancel() on the active drives and
wait for them to assume state BURN_DRIVE_IDLE.
@param patience Maximum number of seconds to wait for drives to
finish.
@since 0.7.8 :
If this is -1, then only the cancel operations will
be performed and no burn_finish() will happen.
@param pacifier_func If not NULL: a function to produce appeasing messages.
See burn_abort_pacifier() for an example.
@param handle Opaque handle to be used with pacifier_func
@param handle Opaque handle to be used with pacifier_func
@return 1 ok, all went well
0 had to leave a drive in unclean state
<0 severe error, do no use libburn again
@ -763,13 +779,10 @@ int burn_abort_pacifier(void *handle, int patience, int elapsed);
void burn_set_verbosity(int level);
/* ts A91111 */
/** Enable resp. disable logging of SCSI commands (currently Linux only).
/** Enable resp. disable logging of SCSI commands (currently GNU/Linux only).
This call can be made at any time - even before burn_initialize().
It is in effect for all active drives and currently not very thread
safe for multiple drives.
>>> ??? Shouldn't the file path with bit1 be adjustable ?
@param flag Bitfield for control purposes. The default is 0.
bit0= log to file /tmp/libburn_sg_command_log
bit1= log to stderr
@ -783,12 +796,11 @@ void burn_set_scsi_logging(int flag);
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 Linux only:
@param exclusive
0 = no attempt to make drive access exclusive.
1 = 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.
and try to mark them busy if opened sucessfully. (O_EXCL
on GNU/Linux , flock(LOCK_EX) on FreeBSD.)
2 = in case of a SCSI device, also try to open exclusively
the matching /dev/sr, /dev/scd and /dev/st .
One may select a device SCSI file family by adding
@ -797,8 +809,8 @@ void burn_set_scsi_logging(int flag);
8 = /dev/scd%d
16 = /dev/sg%d
Do not use other values !
Add 32 to demand an exclusive lock by fcntl(,F_SETLK,)
after open() has succeeded.
Add 32 to demand on GNU/Linux an exclusive lock by
fcntl(,F_SETLK,) after open() has succeeded.
@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.
@ -868,12 +880,12 @@ void burn_allow_untested_profiles(int yes);
If the path leads to an existing file of any type other than directory,
then the result is a sequential write-only stdio-drive = drive role 3.
The special address form "stdio:/dev/fd/<number>" is interpreted literally
as reference to open file descriptor <number>. This address form coincides
The special address form "stdio:/dev/fd/{number}" is interpreted literally
as reference to open file descriptor {number}. This address form coincides
with real files on some systems, but it is in fact hardcoded in libburn.
Special address "stdio:-" means stdout = "stdio:/dev/fd/1".
The role of such a drive is determined by the file type obtained via
fstat(<number>).
fstat({number}).
Roles 2 and 3 perform all their eventual data transfer activities on a file
via standard i/o functions open(2), lseek(2), read(2), write(2), close(2).
@ -1065,6 +1077,19 @@ int burn_drive_obtain_scsi_adr(char *path, int *bus_no, int *host_no,
*/
int burn_drive_grab(struct burn_drive *drive, int load);
/* ts B00114 */
/* Probe available CD write modes and block types. In earlier versions this
was done unconditionally on drive examination or aquiration. But it is
lengthy and obtrusive, up to spoiling burn runs on the examined drives.
So now this probing is omitted by default. All drives which announce to be
capable of CD or DVD writing, get blindly attributed the capability for
SAO and TAO. Applications which are interested in RAW modes or want to
rely on the traditional write mode information, may use this call.
@param drive_info drive object to be inquired
@return >0 indicates success, <=0 means failure
@since 0.7.6
*/
int burn_drive_probe_cd_write_modes(struct burn_drive_info *drive_info);
/* ts A90824 */
/** Calm down or alert a drive. Some drives stay alert after reading for
@ -1073,7 +1098,7 @@ int burn_drive_grab(struct burn_drive *drive, int load);
sense to calm down the drive if no read operation is expected for the
next few seconds. The drive will get alert automatically if operations
are required.
@param drive The drive to influence.
@param d The drive to influence.
@param flag Bitfield for control purposes
bit0= become alert (else start snoozing)
This is not mandatory to allow further drive operations
@ -1085,7 +1110,6 @@ int burn_drive_snooze(struct burn_drive *d, int flag);
/** Release a drive. This should not be done until the drive is no longer
busy (see burn_drive_get_status).
Linux: The drive device file is not reserved afterwards. (O_EXCL, F_SETLK).
@param drive The drive to release.
@param eject Nonzero to make the drive eject the disc in it.
*/
@ -1097,7 +1121,7 @@ void burn_drive_release(struct burn_drive *drive, int eject);
eject button disabled. This physically locked drive state will last until
the drive is grabbed again and released via burn_drive_release().
Programs like eject, cdrecord, growisofs will break that ban too.
@param drive The drive to release and leave locked.
@param d The drive to release and leave locked.
@param flag Bitfield for control purposes (unused yet, submit 0)
@return 1 means success, <=0 means failure
@since 0.4.0
@ -1190,7 +1214,7 @@ char *burn_guess_cd_manufacturer(int m_li, int s_li, int f_li,
/* ts A90909 */
/** Retrieve some media information which is mainly specific to CD. For other
media only the bits in reply parameter valid are supposed to be meaningful.
@param drive The drive to query.
@param d The drive to query.
@param disc_type A string saying either "CD-DA or CD-ROM", or "CD-I",
or ""CD-ROM XA", or "undefined".
@param disc_id A 32 bit number read from the media. (Meaning unclear yet)
@ -1796,10 +1820,6 @@ struct burn_source *burn_file_source_new(const char *path,
/* ts A91122 : An interface to open(O_DIRECT) or similar OS tricks. */
/* <<< temporary indicator until release 0.7.4
*/
#define Libburn_has_open_trac_srC 1
/** Opens a file with eventual acceleration preparations which may depend
on the operating system and on compile time options of libburn.
You may use this call instead of open(2) for opening file descriptors
@ -1945,7 +1965,7 @@ int burn_fifo_inquire_status(struct burn_source *fifo, int *size,
@param full_counter The number of times the fifo was full.
@since 0.7.4
*/
void burn_fifo_get_statistics(struct burn_source *source,
void burn_fifo_get_statistics(struct burn_source *fifo,
int *total_min_fill, int *interval_min_fill,
int *put_counter, int *get_counter,
int *empty_counter, int *full_counter);
@ -1959,8 +1979,7 @@ void burn_fifo_get_statistics(struct burn_source *source,
burn_fifo_next_interval() was called.
@since 0.7.4
*/
void burn_fifo_next_interval(struct burn_source *source,
int *interval_min_fill);
void burn_fifo_next_interval(struct burn_source *fifo, int *interval_min_fill);
/* ts A80713 */
/** Obtain a preview of the first input data of a fifo which was created
@ -1982,7 +2001,7 @@ void burn_fifo_next_interval(struct burn_source *source,
@return <0 on severe error, 0 if not enough data, 1 if bufsize bytes read
@since 0.5.0
*/
int burn_fifo_peek_data(struct burn_source *source, char *buf, int bufsize,
int burn_fifo_peek_data(struct burn_source *fifo, char *buf, int bufsize,
int flag);
/* ts A91125 */
@ -1999,7 +2018,7 @@ int burn_fifo_peek_data(struct burn_source *source, char *buf, int bufsize,
1 if desired amount or fifo full
@since 0.7.4
*/
int burn_fifo_fill(struct burn_source *source, int bufsize, int flag);
int burn_fifo_fill(struct burn_source *fifo, int fill, int flag);
/* ts A70328 */
@ -2608,12 +2627,12 @@ void burn_version(int *major, int *minor, int *micro);
*/
#define burn_header_version_major 0
#define burn_header_version_minor 7
#define burn_header_version_micro 3
#define burn_header_version_minor 8
#define burn_header_version_micro 2
/** Note:
Above version numbers are also recorded in configure.ac because libtool
wants them as parameters at build time.
For the library compatibility check BURN_*_VERSION in configure.ac
For the library compatibility check, BURN_*_VERSION in configure.ac
are not decisive. Only the three numbers above do matter.
*/
/** Usage discussion:
@ -2659,6 +2678,15 @@ These two advises are mutually exclusive.
*/
/* ts A91226 */
/** Obtain the id string of the SCSI transport interface.
This interface may be a system specific adapter module of libburn or
an adapter to a supporting library like libcdio.
@flag Bitfield for control puposes, submit 0 for now
@return A pointer to the id string. Do not alter the string content.
@since 0.7.6
*/
char *burn_scsi_transport_id(int flag);
/* ts A60924 : ticket 74 */
/** Control queueing and stderr printing of messages from libburn.
@ -2761,30 +2789,82 @@ int burn_set_messenger(void *messenger);
/* ts A61002 */
/* @since 0.2.6 */
/** The prototype of a handler function suitable for burn_set_abort_handling().
/** The prototype of a handler function suitable for burn_set_signal_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().
/** Control built-in signal handling. Either by setting an own handler or
by activating the built-in signal handler.
A function parameter handle of NULL activates the built-in abort handler.
Depending on mode it may cancel all drive operations, wait for all drives
to become idle, exit(1). It may also prepare function
burn_drive_get_status() for waiting and performing exit(1).
If parameter handle may be NULL or a text that shall be used as prefix for
pacifier messages of burn_abort_pacifier(). Other than with an application
provided handler, the prefix char array does not have to be kept existing
until the eventual signal event.
Before version 0.7.8 only action 0 was available. I.e. the built-in handler
waited for the drives to become idle and then performed exit(1) directly.
But during burn_disc_write() onto real CD or DVD, FreeBSD 8.0 pauses the
other threads until the signal handler returns.
The new actions try to avoid this deadlock. It is advised to use action 3
at least during burn_disc_write(), burn_disc_rease(), burn_disc_format():
burn_set_signal_handling(text, NULL, 0x30);
and to call burn_is_aborting(0) when the drive is BURN_DRIVE_IDLE.
If burn_is_aborting(0) returns 1, then call burn_abort() and exit(1).
@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().
argument. flag will be 0.
It should finally call burn_abort(). See there.
@param mode : bit0 - bit3:
Receiving signals:
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
bit4 - bit7: With handler == NULL :
Action of built-in handler. "control thread" is the one
which called burn_set_signal_handling().
All actions activate receive mode 2 to ignore further
signals.
0 Same as 1 (for pre-0.7.8 backward compatibility)
@since 0.7.8
1 Catch the control thread in abort handler, call
burn_abort(>0) and finally exit(1).
Does not always work with FreeBSD.
2 Call burn_abort(-1) and return from handler. When the
control thread calls burn_drive_get_status(), then do
burn_abort(>0) instead, and finally exit(1).
Does not always work with FreeBSD.
3 Call burn_abort(-1), return from handler. It is duty of
the application to detect a pending abort condition
by calling burn_is_aborting() and to wait for all
drives to become idle. E.g. by calling burn_abort(>0).
4 Like 3, but without calling burn_abort(-1). Only the
indicator of burn_is_aborting() gets set.
@since 0.2.6
*/
void burn_set_signal_handling(void *handle, burn_abort_handler_t handler,
int mode);
/* ts B00304 */
/* Inquire whether the built-in abort handler was triggered by a signal.
This has to be done to detect pending abort handling if signal handling
was set to the built-in handler and action was set to 2 or 3.
@param flag Bitfield for control purposes (unused yet, submit 0)
@return 0 = no abort was triggered
>0 = action that was triggered (action 0 is reported as 1)
@since 0.7.8
*/
int burn_is_aborting(int flag);
/* ts A70811 */
/** Write data in random access mode.
The drive must be grabbed successfully before calling this function which
@ -2928,16 +3008,8 @@ BURN_END_DECLS
For other modes resp. real probing one has to call
burn_drive_probe_cd_write_modes().
# define Libburn_pioneer_dvr_216d_dummy_probe_wM 1
*/
#ifdef Libburn_pioneer_dvr_216d_dummy_probe_wM
/* Probe available CD write modes and block types.
@param drive_info drive object to be inquired
*/
int burn_drive_probe_cd_write_modes(struct burn_drive_info *drive_info)
#endif /* Libburn_pioneer_dvr_216d_dummy_probe_wM */
#define Libburn_dummy_probe_write_modeS 1
#endif /*LIBBURN_H*/

View File

@ -1,9 +1,13 @@
/* libdax_audioxtr
Audio track data extraction facility of libdax and libburn.
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPLv2+
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

View File

@ -1,7 +1,7 @@
/* libdax_audioxtr
Audio track data extraction facility of libdax and libburn.
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPLv2+
*/
#ifndef LIBDAX_AUDIOXTR_H_INCLUDED

View File

@ -1,10 +1,14 @@
/* libdax_msgs
Message handling facility of libdax.
Copyright (C) 2006 - 2009 Thomas Schmitt <scdbackup@gmx.net>,
provided under GPL version 2
Copyright (C) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>,
provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
@ -12,6 +16,7 @@
#include <stdlib.h>
#include <errno.h>
#include <sys/time.h>
#include <pthread.h>
/* Only this single source module is entitled to do this */
#define LIBDAX_MSGS_H_INTERNAL 1

View File

@ -1,8 +1,8 @@
/* libdax_msgs
Message handling facility of libdax.
Copyright (C) 2006-2009 Thomas Schmitt <scdbackup@gmx.net>,
provided under GPL version 2
Copyright (C) 2006-2010 Thomas Schmitt <scdbackup@gmx.net>,
provided under GPL version 2 or later.
*/
@ -434,6 +434,8 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
0x00020009 (SORRY,HIGH) = Neither stdio-path nor its directory exist
0x0002000a (FAILURE,HIGH) = Cannot accept '...' as SG_IO CDROM drive
0x0002000b (FAILURE,HIGH) = File object '...' not found
0x0002000c (FAILURE,HIGH) = Cannot start device file enumeration
0x0002000d (FAILURE,HIGH) = Cannot enumerate next device
General library operations:
@ -552,6 +554,10 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
0x00020172 (SORRY,HIGH) = Read start address larger than number of readable blocks
0x00020173 (FAILURE,HIGH) = Drive tells NWA smaller than last written address
0x00020174 (SORRY,HIGH) = Fifo alignment does not allow desired read size
0x00020175 (FATAL,HIGH) = Supporting library is too old
0x00020176 (NOTE,HIGH) = Stream recording disabled because of small OS buffer
0x00020177 (ABORT,HIGH) = Urged drive worker threads to do emergency halt
0x00020178 (DEBUG,HIGH) = Write thread ended
libdax_audioxtr:

View File

@ -1,5 +1,15 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
/* ts A61009 */
/* #include <a ssert.h> */
@ -419,6 +429,10 @@ int mmc_get_nwa(struct burn_drive *d, int trackno, int *lba, int *nwa)
if (mmc_function_spy(d, "mmc_get_nwa") <= 0)
return -1;
/* ts B00327 : Avoid to inquire unsuitable media states */
if (d->status != BURN_DISC_BLANK && d->status != BURN_DISC_APPENDABLE)
return 0;
ret = mmc_read_track_info(d, trackno, &buf, alloc_len);
if (ret <= 0)
return ret;
@ -1390,6 +1404,11 @@ static int mmc_read_toc_al(struct burn_drive *d, int *alloc_len)
fprintf(stderr, "libburn_experimental: toc entry #%d : %d %d %d\n",i,tdata[8], tdata[9], tdata[10]);
*/
#ifdef Libburn_allow_first_hiddeN
/* ts B00430 : this causes problems because the track has
no entry. One would have to coordinate this
with other parts of libburn.
*/
if (tdata[3] == 1) {
if (burn_msf_to_lba(tdata[8], tdata[9], tdata[10])) {
d->disc->session[0]->hidefirst = 1;
@ -1398,9 +1417,10 @@ static int mmc_read_toc_al(struct burn_drive *d, int *alloc_len)
session[tdata[0] - 1],
track, BURN_POS_END);
burn_track_free(track);
}
}
#endif /* Libburn_allow_first_hiddeN */
if (tdata[0] <= 0 || tdata[0] > d->disc->sessions)
tdata[0] = d->disc->sessions;
if (tdata[3] < 100 && tdata[0] > 0) {
@ -1958,8 +1978,13 @@ 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 B00501 : now caring for error */
if (c.error) {
d->erasable= 0;
d->start_lba= 0;
d->end_lba= 0;
return;
}
/* ts A61021 */
data = c.page->data;
@ -4078,7 +4103,7 @@ int mmc_read_disc_structure(struct burn_drive *d,
desired payload bytes. The drive then returns 35
bytes as requested and the media id is "RITEKF1".
Nevertheless this is not a generally usable gesture
because older Linux USB dislikes requests to fetch
because older GNU/Linux USB dislikes requests to fetch
more bytes than the drive will deliver.
# define Libburn_enforce_structure_code_0x0E 1

View File

@ -1,5 +1,11 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifndef __MMC
#define __MMC

View File

@ -1,5 +1,14 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include "null.h"
#include "libburn.h"
#include <stdlib.h>

View File

@ -1,3 +1,13 @@
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include "libburn.h"
#include "options.h"
#include "drive.h"

View File

@ -1,3 +1,9 @@
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifndef BURN__OPTIONS_H
#define BURN__OPTIONS_H

View File

@ -5,7 +5,7 @@
Unknown POSIX like systems
with the dummy MMC transport adapter sg-dummy.c
Copyright (C) 2009 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
Copyright (C) 2009 Thomas Schmitt <scdbackup@gmx.net>, provided under GPLv2+
*/

View File

@ -4,7 +4,7 @@
by os.h in case of compilation for
FreeBSD with CAM
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPLv2+
*/
/** List of all signals which shall be caught by signal handlers and trigger
@ -57,5 +57,8 @@ typedef struct burn_drive_enumeration_state *burn_drive_enumerator_t;
To be initialized and used within sg-*.c .
*/
#define BURN_OS_TRANSPORT_DRIVE_ELEMENTS \
struct cam_device* cam;
struct cam_device* cam; \
int lock_fd; \
int is_ahci; \

72
libburn/os-libcdio.h Normal file
View File

@ -0,0 +1,72 @@
/* os-libcdio.h
Operating system specific libburn definitions and declarations. Included
by os.h in case of compilation for
Unknown X/Open-like systems
with GNU libcdio MMC transport adapter sg-libcdio.c
Copyright (C) 2009 Thomas Schmitt <scdbackup@gmx.net>, provided under GPLv2+
*/
/** List of all signals which shall be caught by signal handlers and trigger
a graceful abort of libburn. (See man 7 signal.)
*/
/* Once as system defined macros */
#define BURN_OS_SIGNAL_MACRO_LIST \
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT, \
SIGFPE, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM, \
SIGUSR1, SIGUSR2, SIGXCPU, SIGTSTP, SIGTTIN, \
SIGTTOU
/* Once as text 1:1 list of strings for messages and interpreters */
#define BURN_OS_SIGNAL_NAME_LIST \
"SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGABRT", \
"SIGFPE", "SIGSEGV", "SIGPIPE", "SIGALRM", "SIGTERM", \
"SIGUSR1", "SIGUSR2", "SIGXCPU", "SIGTSTP", "SIGTTIN", \
"SIGTTOU"
/* The number of above list items */
#define BURN_OS_SIGNAL_COUNT 16
/** To list all signals which shall surely not be caught */
#define BURN_OS_NON_SIGNAL_MACRO_LIST \
SIGKILL, SIGCHLD, SIGSTOP
/* The number of above list items */
#define BURN_OS_NON_SIGNAL_COUNT 3
/* The maximum size for a (SCSI) i/o transaction */
/* Important : MUST be at least 32768 ! */
/* My Blu-ray burner LG GGW-H20 writes junk if stream recording is combined
with buffer size 32 kB. So stream recording is allowed only with size 64k.
This makes it worth to have a special case for GNU/Linux buffer size here.
*/
#ifdef __linux
#define BURN_OS_TRANSPORT_BUFFER_SIZE 65536
#else
/* (It might be risky to use 64k. FreeBSD is said to can only 32k.) */
#define BURN_OS_TRANSPORT_BUFFER_SIZE 32768
#endif
/* To hold the position of the most recently delivered address from
device enumeration.
*/
struct burn_drive_enumerator_struct {
char **ppsz_cd_drives;
char **pos;
};
#define BURN_OS_DEFINE_DRIVE_ENUMERATOR_T \
typedef struct burn_drive_enumerator_struct burn_drive_enumerator_t;
/* The list of operating system dependent elements in struct burn_drive.
Usually they are initialized in sg-*.c:enumerate_common().
*/
#define BURN_OS_TRANSPORT_DRIVE_ELEMENTS \
void *p_cdio; /* actually a pointer to CdIo_t */ \
char libcdio_name[4096]; /* The drive path as used by libcdio */ \

View File

@ -2,9 +2,10 @@
/* os-linux.h
Operating system specific libburn definitions and declarations. Included
by os.h in case of compilation for
Linux kernels 2.4 and 2.6 with Linux SCSI Generic (sg)
Linux kernels 2.4 and 2.6, GNU/Linux SCSI Generic (sg)
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
Copyright (C) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/

68
libburn/os-solaris.h Normal file
View File

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

View File

@ -3,7 +3,7 @@
Operating system specific libburn definitions and declarations.
The macros defined here are used by libburn modules in order to
avoid own system dependent case distinctions.
Copyright (C) 2009 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
Copyright (C) 2009 Thomas Schmitt <scdbackup@gmx.net>, provided under GPLv2+
*/
#ifndef BURN_OS_H_INCLUDED
@ -13,6 +13,23 @@
Operating system case distinction
*/
#ifdef Libburn_use_sg_dummY
/* --------- Any other system. With dummy MMC transport sg-dummy.c --------- */
#include "os-dummy.h"
#else
#ifdef Libburn_use_libcdiO
/* -------------------------- X/Open with GNU libcdio ---------------------- */
#include "os-libcdio.h"
#else
#ifdef __FreeBSD__
@ -20,14 +37,30 @@
#include "os-freebsd.h"
#else
#ifdef __FreeBSD_kernel__
/* ----------------------- FreeBSD with CAM under Debian ------------------- */
#include "os-freebsd.h"
#else
#ifdef __linux
/* --------- Linux kernels 2.4 and 2.6 with Linux SCSI Generic (sg) -------- */
/* ------- Linux kernels 2.4 and 2.6 with GNU/Linux SCSI Generic (sg) ------ */
#include "os-linux.h"
#else
#ifdef __sun
/* ------- Solaris (e.g. SunOS 5.11) with uscsi ------ */
#include "os-solaris.h"
#else
@ -35,8 +68,12 @@
#include "os-dummy.h"
#endif /* ! __sun*/
#endif /* ! __linux */
#endif /* ! __FreeBSD__kernel__ */
#endif /* ! __FreeBSD__ */
#endif /* ! Libburn_use_libcdiO */
#endif /* ! Libburn_use_sg_dummY */
#endif /* ! BURN_OS_H_INCLUDED */

View File

@ -1,6 +1,16 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* #include <m alloc.h> ts A61013 : not in Linux man 3 malloc */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
/* #include <m alloc.h> ts A61013 : not in GNU/Linux man 3 malloc */
#include <stdlib.h>
#include <unistd.h>
@ -94,7 +104,13 @@ drive, or only store a subset of the _opts structs in drives */
fakesub[20] = 2;
fakesub[12] = (d->toc->toc_entry[0].control << 4) +
d->toc->toc_entry[0].adr;
#ifdef Libburn_no_crc_C
crc = 0; /* dummy */
#else
crc = crc_ccitt(fakesub + 12, 10);
#endif
fakesub[22] = crc >> 8;
fakesub[23] = crc & 0xFF;
write(o->subfd, fakesub, 96);
@ -241,6 +257,8 @@ void burn_packet_process(struct burn_drive *d, unsigned char *data,
}
}
crc = (*(sub + 22) << 8) + *(sub + 23);
#ifndef Libburn_no_crc_C
if (crc != crc_ccitt(sub + 12, 10)) {
burn_print(1, "sending error on %s %s\n",
d->idata->vendor, d->idata->product);
@ -249,6 +267,8 @@ void burn_packet_process(struct burn_drive *d, unsigned char *data,
*/
burn_print(1, "crc mismatch in Q\n");
}
#endif
/* else process_q(d, sub + 12); */
/*
if (o->subfd != -1) write(o->subfd, sub, 96); */

View File

@ -2,6 +2,15 @@
/* scsi block commands */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include <string.h>
#include <unistd.h>
@ -74,14 +83,17 @@ void sbc_eject(struct burn_drive *d)
return;
scsi_init_command(&c, SBC_UNLOAD, sizeof(SBC_UNLOAD));
c.opcode[1] |= 1; /* ts A70918 : Immed */
/* c.opcode[1] |= 1; / * ts A70918 : Immed , ts B00109 : revoked */
c.page = NULL;
c.dir = NO_TRANSFER;
d->issue_command(d, &c);
/* ts A70918 : Wait long. A late eject could surprise or hurt user.
ts B00109 : Asynchronous eject revoked, as one cannot reliably
distinguish out from unready.
if (c.error)
return;
/* ts A70918 : Wait long. A late eject could surprise or hurt user. */
spc_wait_unit_attention(d, 1800, "STOP UNIT (+ EJECT)", 0);
*/
}

View File

@ -1,5 +1,11 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifndef __SBC
#define __SBC

View File

@ -1,5 +1,14 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include <stdio.h>
/* ts A61010 */
@ -25,7 +34,7 @@ extern struct libdax_msgs *libdax_messenger;
#ifdef Libburn_log_in_and_out_streaM
/* <<< ts A61031 */
/* ts A61031 */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
@ -96,7 +105,7 @@ static void get_bytes(struct burn_track *track, int count, unsigned char *data)
int valid, shortage, curr, i, tr;
#ifdef Libburn_log_in_and_out_streaM
/* <<< ts A61031 */
/* ts A61031 */
static int tee_fd= -1;
if(tee_fd==-1)
tee_fd= open("/tmp/libburn_sg_readin",
@ -142,7 +151,7 @@ static void get_bytes(struct burn_track *track, int count, unsigned char *data)
track->sourcecount += valid;
#ifdef Libburn_log_in_and_out_streaM
/* <<< ts A61031 */
/* ts A61031 */
if(tee_fd!=-1 && valid>0) {
write(tee_fd, data + curr, valid);
}
@ -405,7 +414,13 @@ a2 - lout ctrl
q[7] = dec_to_bcd(d->toc_entry[track].pmin);
q[8] = dec_to_bcd(d->toc_entry[track].psec);
q[9] = dec_to_bcd(d->toc_entry[track].pframe);
#ifdef Libburn_no_crc_C
crc = 0; /* dummy */
#else
crc = crc_ccitt(q, 10);
#endif
q[10] = crc >> 8;
q[11] = crc & 0xFF;
d->toc_temp++;
@ -502,7 +517,13 @@ static void subcode_lout(struct burn_write_opts *o, unsigned char control,
q[7] = dec_to_bcd(min);
q[8] = dec_to_bcd(sec);
q[9] = dec_to_bcd(frame);
#ifdef Libburn_no_crc_C
crc = 0; /* dummy */
#else
crc = crc_ccitt(q, 10);
#endif
q[10] = crc >> 8;
q[11] = crc & 0xFF;
}
@ -622,7 +643,13 @@ void subcode_user(struct burn_write_opts *o, unsigned char *subcodes,
}
q[0] = (control << 4) + qmode;
#ifdef Libburn_no_crc_C
crc = 0; /* dummy */
#else
crc = crc_ccitt(q, 10);
#endif
q[10] = crc >> 8;
q[11] = crc & 0xff;
}
@ -654,7 +681,7 @@ int sector_data(struct burn_write_opts *o, struct burn_track *t, int psub)
unsigned char *data;
data = get_sector(o, t, t->mode);
if (!data)
if (data == NULL)
return 0;
/* ts A61010 */
if (convert_data(o, t, t->mode, data) <= 0)
@ -768,7 +795,13 @@ int sector_headers(struct burn_write_opts *o, unsigned char *out,
out[15] = modebyte;
}
if (mode & BURN_MODE1) {
#ifdef Libburn_no_crc_C
crc = 0; /* dummy */
#else
crc = crc_32(out, 2064);
#endif
out[2064] = crc & 0xFF;
crc >>= 8;
out[2065] = crc & 0xFF;

View File

@ -1,5 +1,10 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifndef __SECTOR
#define __SECTOR

View File

@ -1,5 +1,15 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/*
Copyright (c) 2009 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
/*
This is the main operating system dependent SCSI part of libburn. It implements
@ -7,8 +17,8 @@ the transport level aspects of SCSI control and command i/o.
Present implementation: default dummy which enables libburn only to work
with stdio: pseudo drive addresses.
For real implementations see sg-linux.c or sg-freebsd.c
For real implementations see sg-linux.c, sg-freebsd.c,
sg-libcdio.c
*/
@ -39,6 +49,59 @@ Present implementation: default dummy which enables libburn only to work
extern struct libdax_msgs *libdax_messenger;
/** Returns the id string of the SCSI transport adapter and eventually
needed operating system facilities.
This call is usable even if sg_initialize() was not called yet. In that
case a preliminary constant message might be issued if detailed info is
not available yet.
@param msg returns id string
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_id_string(char msg[1024], int flag)
{
strcpy(msg, "internal X/Open adapter sg-dummy");
return 1;
}
/** Performs global initialization of the SCSI transport adapter and eventually
needed operating system facilities. Checks for compatibility supporting
software components.
@param msg returns ids and/or error messages of eventual helpers
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_initialize(char msg[1024], int flag)
{
return sg_id_string(msg, 0);
}
/** Performs global finalization of the SCSI transport adapter and eventually
needed operating system facilities. Releases globally aquired resources.
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_shutdown(int flag)
{
return 1;
}
/** Finalizes BURN_OS_TRANSPORT_DRIVE_ELEMENTS, the components of
struct burn_drive which are defined in os-*.h.
This will be called when a burn_drive gets disposed.
@param d the drive to be finalized
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_dispose_drive(struct burn_drive *d, int flag)
{
return 1;
}
/** Returns the next index number and the next enumerated drive address.
The enumeration has to cover all available and accessible drives. It is
allowed to return addresses of drives which are not available but under
@ -153,6 +216,23 @@ int sg_is_enumerable_adr(char *adr)
}
/* Return 1 if the given path leads to a regular file or a device that can be
seeked, read, and possibly written with 2 kB granularity.
*/
int burn_os_is_2k_seekrw(char *path, int flag)
{
struct stat stbuf;
if (stat(path, &stbuf) == -1)
return 0;
if (S_ISREG(stbuf.st_mode))
return 1;
if (S_ISBLK(stbuf.st_mode))
return 1;
return 0;
}
/** Estimate the potential payload capacity of a file address.
@param path The address of the file to be examined. If it does not
exist yet, then the directory will be inquired.
@ -215,7 +295,7 @@ int burn_os_stdio_capacity(char *path, off_t *bytes)
if (statvfs(testpath, &vfsbuf) == -1)
return -2;
*bytes = add_size + ((off_t) vfsbuf.f_bsize) *
*bytes = add_size + ((off_t) vfsbuf.f_frsize) *
(off_t) vfsbuf.f_bavail;
#else /* Libburn_os_has_statvfS */

View File

@ -1,5 +1,11 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/*
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
/*
This is the main operating system dependent SCSI part of libburn. It implements
@ -29,12 +35,28 @@ and of deriving the following system specific files from existing examples:
Said sg-*.c operations are defined by a public function interface, which has
to be implemented in a way that provides libburn with the desired services:
sg_id_string() returns an id string of the SCSI transport adapter.
It may be called before initialization but then may
return only a preliminary id.
sg_initialize() performs global initialization of the SCSI transport
adapter and eventually needed operating system
facilities. Checks for compatibility of supporting
software components.
sg_shutdown() performs global finalizations and releases golbally
aquired resources.
sg_give_next_adr() iterates over the set of potentially useful drive
address strings.
scsi_enumerate_drives() brings all available, not-whitelist-banned, and
accessible drives into libburn's list of drives.
sg_dispose_drive() finalizes adapter specifics of struct burn_drive
on destruction. Releases resources which were aquired
underneath scsi_enumerate_drives().
sg_drive_is_open() tells wether libburn has the given drive in use.
sg_grab() opens the drive for SCSI commands and ensures
@ -48,14 +70,35 @@ sg_issue_command() sends a SCSI command to the drive, receives reply,
sg_obtain_scsi_adr() tries to obtain SCSI address parameters.
burn_os_is_2k_seekrw() tells whether the given path leads to a file object
that can be used in 2 kB granularity by lseek(2),
read(2), and possibly write(2) if not read-only.
E.g. a USB stick or a hard disk.
burn_os_stdio_capacity() estimates the emulated media space of stdio-drives.
burn_os_open_track_src() opens a disk file in a way that allows best
throughput with file reading and/or SCSI write command
transmission.
burn_os_alloc_buffer() allocates a memory area that is suitable for file
descriptors issued by burn_os_open_track_src().
The buffer size may be rounded up for alignment
reasons.
burn_os_free_buffer() delete a buffer obtained by burn_os_alloc_buffer().
Porting hints are marked by the text "PORTING:".
Send feedback to libburn-hackers@pykix.org .
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
/** PORTING : ------- OS dependent headers and definitions ------ */
@ -230,6 +273,61 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
/* ------------------------------------------------------------------------ */
/** Returns the id string of the SCSI transport adapter and eventually
needed operating system facilities.
This call is usable even if sg_initialize() was not called yet. In that
case a preliminary constant message might be issued if detailed info is
not available yet.
@param msg returns id string
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_id_string(char msg[1024], int flag)
{
strcpy(msg, "internal FreeBSD CAM adapter sg-freebsd-port");
return 1;
}
/** Performs global initialization of the SCSI transport adapter and eventually
needed operating system facilities. Checks for compatibility supporting
software components.
@param msg returns ids and/or error messages of eventual helpers
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_initialize(char msg[1024], int flag)
{
return sg_id_string(msg, 0);
}
/** Performs global finalization of the SCSI transport adapter and eventually
needed operating system facilities. Releases globally aquired resources.
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_shutdown(int flag)
{
return 1;
}
/** Finalizes BURN_OS_TRANSPORT_DRIVE_ELEMENTS, the components of
struct burn_drive which are defined in os-*.h.
The eventual initialization of those components was made underneath
scsi_enumerate_drives().
This will be called when a burn_drive gets disposed.
@param d the drive to be finalized
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_dispose_drive(struct burn_drive *d, int flag)
{
return 1;
}
/** Returns the next index number and the next enumerated drive address.
The enumeration has to cover all available and accessible drives. It is
allowed to return addresses of drives which are not available but under
@ -299,7 +397,7 @@ try_item:; /* This spaghetti loop keeps the number of tabs small */
break;
snprintf(buf, sizeof (buf), "/dev/%s%d",
result->periph_name, result->unit_number);
if(adr_size <= strlen(buf)
if(adr_size <= strlen(buf))
return -1;
strcpy(adr, buf);
@ -323,7 +421,7 @@ try_item:; /* This spaghetti loop keeps the number of tabs small */
int scsi_enumerate_drives(void)
{
burn_drive_enumerator_t idx;
int initialize = 1;
int initialize = 1, ret;
char buf[64];
while(1) {
@ -338,6 +436,7 @@ int scsi_enumerate_drives(void)
idx.result->target_lun);
}
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
return 1;
}
@ -360,11 +459,12 @@ int sg_drive_is_open(struct burn_drive * d)
*/
int sg_grab(struct burn_drive *d)
{
int count;
struct cam_device *cam;
if(d->cam != NULL)
return 0;
if(d->cam != NULL) {
d->released = 0;
return 1;
}
cam = cam_open_device(d->devname, O_RDWR);
if (cam == NULL) {
@ -515,7 +615,7 @@ 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;
int initialize = 1, ret;
char buf[64];
struct periph_match_result* result;
@ -524,7 +624,7 @@ int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
initialize = 0;
if (ret <= 0)
break;
if (strcmp(adr, buf) != 0)
if (strcmp(path, buf) != 0)
continue;
result = &(idx->ccb.cdm.matches[i].result.periph_result);
*bus_no = result->path_id;
@ -546,7 +646,7 @@ int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
int sg_is_enumerable_adr(char* adr)
{
burn_drive_enumerator_t idx;
int initialize = 1;
int initialize = 1, ret;
char buf[64];
while(1) {
@ -564,6 +664,47 @@ int sg_is_enumerable_adr(char* adr)
}
/* ts B00115 */
/* Return 1 if the given path leads to a regular file or a device that can be
seeked, written, and read with 2 kB granularity.
*/
int burn_os_is_2k_seekrw(char *path, int flag)
{
struct stat stbuf;
char *spt;
int i, e;
if (stat(path, &stbuf) == -1)
return 0;
if (S_ISREG(stbuf.st_mode))
return 1;
if (!S_ISCHR(stbuf.st_mode))
return 0;
spt = strrchr(path, '/');
if (spt == NULL)
spt = path;
else
spt++;
e = strlen(spt);
for (i = strlen(spt) - 1; i > 0; i--)
if (spt[i] >= '0' && spt[i] <= '9')
e = i;
if (strncmp(spt, "da", e) == 0) /* SCSI disk. E.g. USB stick. */
return 1;
if (strncmp(spt, "cd", e) == 0) /* SCSI CD drive might be writeable. */
return 1;
if (strncmp(spt, "ad", e) == 0) /* IDE hard drive */
return 1;
if (strncmp(spt, "acd", e) == 0) /* IDE CD drive might be writeable */
return 1;
if (strncmp(spt, "fd", e) == 0) /* Floppy disk */
return 1;
if (strncmp(spt, "fla", e) == 0) /* Flash drive */
return 1;
return 0;
}
/* ts A70909 */
/** Estimate the potential payload capacity of a file address.
@param path The address of the file to be examined. If it does not
@ -623,7 +764,7 @@ int burn_os_stdio_capacity(char *path, off_t *bytes)
if (testpath[0]) {
if (statvfs(testpath, &vfsbuf) == -1)
return -2;
*bytes = add_size + ((off_t) vfsbuf.f_bsize) *
*bytes = add_size + ((off_t) vfsbuf.f_frsize) *
(off_t) vfsbuf.f_bavail;
}
return 1;

View File

@ -1,5 +1,14 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/*
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
@ -7,6 +16,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/file.h>
#include <stdlib.h>
#include <string.h>
#include <sys/poll.h>
@ -16,10 +26,24 @@
#include <err.h> /* XXX */
/* ts A70909 */
#include <sys/statvfs.h>
/* ts B00121 */
#include <sys/disk.h> /* DIOCGMEDIASIZE */
/* ts B00326 : For use of CAM_PASS_ERR_RECOVER with ahci */
#define Libburn_for_freebsd_ahcI yes
/* ts B00327 : for debugging of cam_send_cdb() failures
# define Libburn_ahci_verbouS yes
*/
/* ts B00327 : Apply CAM_PASS_ERR_RECOVER to drives even if not ahci
# define libburn_ahci_style_for_alL yes
*/
#include "transport.h"
#include "drive.h"
@ -54,6 +78,79 @@ int burn_drive_is_banned(char *device_address);
int mmc_function_spy(struct burn_drive *d, char * text);
/* ts B00113
Whether to log SCSI commands:
bit0= log in /tmp/libburn_sg_command_log
bit1= log to stderr
bit2= flush every line
*/
extern int burn_sg_log_scsi;
/* ts B00114 */
/* Storage object is in libburn/init.c
whether to strive for exclusive access to the drive
*/
extern int burn_sg_open_o_excl;
/* ts A91227 */
/** Returns the id string of the SCSI transport adapter and eventually
needed operating system facilities.
This call is usable even if sg_initialize() was not called yet. In that
case a preliminary constant message might be issued if detailed info is
not available yet.
@param msg returns id string
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_id_string(char msg[1024], int flag)
{
strcpy(msg, "internal FreeBSD CAM adapter sg-freebsd");
return 1;
}
/* ts A91227 */
/** Performs global initialization of the SCSI transport adapter and eventually
needed operating system facilities. Checks for compatibility supporting
software components.
@param msg returns ids and/or error messages of eventual helpers
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_initialize(char msg[1024], int flag)
{
return sg_id_string(msg, 0);
}
/* ts A91227 */
/** Performs global finalization of the SCSI transport adapter and eventually
needed operating system facilities. Releases globally aquired resources.
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_shutdown(int flag)
{
return 1;
}
/** Finalizes BURN_OS_TRANSPORT_DRIVE_ELEMENTS, the components of
struct burn_drive which are defined in os-*.h.
The eventual initialization of those components was made underneath
scsi_enumerate_drives().
This will be called when a burn_drive gets disposed.
@param d the drive to be finalized
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_dispose_drive(struct burn_drive *d, int flag)
{
return 1;
}
/* ts A61021 : Moved most code from scsi_enumerate_drives under
sg_give_next_adr() */
/* Some helper functions for scsi_give_next_adr() */
@ -145,7 +242,7 @@ static int sg_next_enumeration_buffer(burn_drive_enumerator_t *idx_)
}
/** Returns the next index number and the next enumerated drive address.
/** Returns the next index object state and the next enumerated drive address.
@param idx An opaque handle. Make no own theories about it.
@param adr Takes the reply
@param adr_size Gives maximum size of reply including final 0
@ -199,9 +296,15 @@ int sg_give_next_adr(burn_drive_enumerator_t *idx_,
struct periph_match_result* result;
result = &(idx->ccb.cdm.matches[idx->i].result.periph_result);
/* ts B00112 : we really want only "cd" devices.
if (idx->skip_device ||
strcmp(result->periph_name, "pass") == 0)
break;
*/
if (idx->skip_device ||
strcmp(result->periph_name, "cd") != 0)
break;
ret = snprintf(adr, adr_size, "/dev/%s%d",
result->periph_name, result->unit_number);
if(ret >= adr_size)
@ -212,7 +315,7 @@ int sg_give_next_adr(burn_drive_enumerator_t *idx_,
}
default:
/* printf(stderr, "unknown match type\n"); */
/* fprintf(stderr, "unknown match type\n"); */
break;
}
(idx->i)++;
@ -287,6 +390,10 @@ int sg_close_drive(struct burn_drive * d)
cam_close_device(d->cam);
d->cam = NULL;
}
if (d->lock_fd > 0) {
close(d->lock_fd);
d->lock_fd = -1;
}
return 0;
}
@ -340,7 +447,10 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
out.lun = lun_no;
out.devname = burn_strdup(fname);
out.cam = NULL;
out.lock_fd = -1;
out.is_ahci = 0;
out.start_lba= -2000000000;
out.end_lba= -2000000000;
@ -432,6 +542,9 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
/* Operating system adapter is CAM */
/* Adapter specific handles and data */
out.cam = NULL;
out.lock_fd = -1;
out.is_ahci = 0;
/* Adapter specific functions */
out.grab = sg_grab;
out.release = sg_release;
@ -444,15 +557,145 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
#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.
/* Lock the inode associated to dev_fd and the inode associated to devname.
Return OS errno, number of pass device of dev_fd, locked fd to devname,
error message.
A return value of > 0 means success, <= 0 means failure.
*/
static int freebsd_dev_lock(int dev_fd, char *devname,
int *os_errno, int *pass_dev_no, int *lock_fd, char msg[4096],
int flag)
{
int lock_denied = 0, fd_stbuf_valid, name_stbuf_valid, i, pass_l = 100;
int max_retry = 3, tries = 0;
struct stat fd_stbuf, name_stbuf;
char pass_name[16], *lock_name;
*os_errno = 0;
*pass_dev_no = -1;
*lock_fd = -1;
msg[0] = 0;
fd_stbuf_valid = !fstat(dev_fd, &fd_stbuf);
/* Try to find name of pass device by inode number */
lock_name = (char *) "effective device";
if(fd_stbuf_valid) {
for (i = 0; i < pass_l; i++) {
sprintf(pass_name, "/dev/pass%d", i);
if (stat(pass_name, &name_stbuf) != -1)
if(fd_stbuf.st_ino == name_stbuf.st_ino &&
fd_stbuf.st_dev == name_stbuf.st_dev)
break;
}
if (i < pass_l) {
lock_name = pass_name;
*pass_dev_no = i;
}
}
name_stbuf_valid = !stat(devname, &name_stbuf);
for (tries= 0; tries <= max_retry; tries++) {
lock_denied = flock(dev_fd, LOCK_EX | LOCK_NB);
*os_errno = errno;
if (lock_denied) {
if (errno == EAGAIN && tries < max_retry) {
/* <<< debugging
fprintf(stderr,
"\nlibcdio_DEBUG: EAGAIN pass, tries= %d\n",
tries);
*/
usleep(2000000);
continue;
}
sprintf(msg,
"Device busy. flock(LOCK_EX) failed on %s of %s",
strlen(lock_name) > 2000 || *pass_dev_no < 0 ?
"pass device" : lock_name,
strlen(devname) > 2000 ? "drive" : devname);
return 0;
}
break;
}
/*
fprintf(stderr, "libburn_DEBUG: flock obtained on %s of %s\n",
lock_name, devname);
*/
/* Eventually lock the official device node too */
if (fd_stbuf_valid && name_stbuf_valid &&
(fd_stbuf.st_ino != name_stbuf.st_ino ||
fd_stbuf.st_dev != name_stbuf.st_dev)) {
*lock_fd = open(devname, O_RDONLY);
if (*lock_fd == 0) {
close(*lock_fd);
*lock_fd = -1;
} if (*lock_fd > 0) {
for (tries = 0; tries <= max_retry; tries++) {
lock_denied =
flock(*lock_fd, LOCK_EX | LOCK_NB);
if (lock_denied) {
if (errno == EAGAIN &&
tries < max_retry) {
/* <<< debugging
fprintf(stderr,
"\nlibcdio_DEBUG: EAGAIN dev, tries= %d\n",
tries);
*/
usleep(2000000);
continue;
}
close(*lock_fd);
*lock_fd = -1;
sprintf(msg,
"Device busy. flock(LOCK_EX) failed on %s",
strlen(devname) > 4000 ? "drive" : devname);
return 0;
}
break;
}
}
/*
fprintf(stderr, "libburn_DEBUG: flock obtained on %s\n",
devname);
*/
}
return 1;
}
static int sg_lock(struct burn_drive *d, int flag)
{
int ret, os_errno, pass_dev_no = -1, flock_fd = -1;
char msg[4096];
ret = freebsd_dev_lock(d->cam->fd, d->devname,
&os_errno, &pass_dev_no, &flock_fd, msg, 0);
if (ret <= 0) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020008,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, os_errno, 0);
sg_close_drive(d);
return 0;
}
if (d->lock_fd > 0)
close(d->lock_fd);
d->lock_fd = flock_fd;
return 1;
}
int sg_grab(struct burn_drive *d)
{
int count;
struct cam_device *cam;
char path_string[80];
if (mmc_function_spy(d, "sg_grab") <= 0)
return 0;
@ -464,22 +707,31 @@ int sg_grab(struct burn_drive *d)
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);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020003,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Could not grab drive", 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;
d->cam = cam;
if (burn_sg_open_o_excl & 63)
if (sg_lock(d, 0) <= 0)
return 0;
fcntl(cam->fd, F_SETOWN, getpid());
cam_path_string(d->cam, path_string, sizeof(path_string));
#ifdef Libburn_ahci_verbouS
fprintf(stderr, "libburn_EXPERIMENTAL: CAM path = %s\n", path_string);
#endif
if (strstr(path_string, ":ahcich") != NULL)
d->is_ahci = 1;
else
d->is_ahci = -1;
d->released = 0;
return 1;
}
@ -507,11 +759,12 @@ int sg_release(struct burn_drive *d)
int sg_issue_command(struct burn_drive *d, struct command *c)
{
int done = 0;
int err;
int done = 0, err, sense_len = 0, ret, ignore_error, no_retry = 0;
int cam_pass_err_recover = 0;
union ccb *ccb;
char buf[161];
static FILE *fp = NULL;
snprintf(buf, sizeof (buf), "sg_issue_command d->cam=%p d->released=%d",
(void*)d->cam, d->released);
mmc_function_spy(NULL, buf);
@ -520,6 +773,15 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
c->error = 0;
return 0;
}
if (burn_sg_log_scsi & 1) {
if (fp == NULL) {
fp= fopen("/tmp/libburn_sg_command_log", "a");
fprintf(fp,
"\n-----------------------------------------\n");
}
}
if (burn_sg_log_scsi & 3)
scsi_log_cmd(c,fp,0);
c->error = 0;
@ -546,6 +808,23 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
break;
}
#ifdef Libburn_for_freebsd_ahcI
/* ts B00325 : Advise by Alexander Motin */
/* Runs well on 8-STABLE (23 Mar 2003)
But on 8-RELEASE cam_send_ccb() returns non-zero with errno 6
on eject. Long lasting TEST UNIT READY cycles break with
errno 16.
*/
#ifdef Libburn_ahci_style_for_alL
{
#else
if (d->is_ahci > 0) {
#endif
ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
cam_pass_err_recover = 1;
}
#endif /* Libburn_for_freebsd_ahcI */
ccb->csio.cdb_len = c->oplen;
memcpy(&ccb->csio.cdb_io.cdb_bytes, &c->opcode, c->oplen);
@ -568,12 +847,6 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
/* touch page so we can use valgrind */
memset(c->page->data, 0, BUFFER_SIZE);
} else {
/* ts A90430 */
/* a ssert(c->page->bytes > 0); */
if (c->page->bytes <= 0) {
c->error = 1;
return 0;
}
ccb->csio.dxfer_len = c->page->bytes;
}
} else {
@ -582,31 +855,114 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
}
do {
memset(c->sense, 0, sizeof(c->sense));
err = cam_send_ccb(d->cam, ccb);
if (err == -1) {
ignore_error = sense_len = 0;
/* ts B00325 : CAM_AUTOSNS_VALID advised by Alexander Motin */
if (ccb->ccb_h.status & CAM_AUTOSNS_VALID) {
/* ts B00110 */
/* Better curb sense_len */
sense_len = ccb->csio.sense_len;
if (sense_len > sizeof(c->sense))
sense_len = sizeof(c->sense);
memcpy(c->sense, &ccb->csio.sense_data, sense_len);
if (sense_len >= 14 && cam_pass_err_recover &&
(c->sense[2] & 0x0f))
ignore_error = 1;
}
if (err == -1 && cam_pass_err_recover && ! ignore_error) {
#ifdef Libburn_ahci_verbouS
fprintf(stderr, "libburn_EXPERIMENTAL: errno = %d . cam_errbuf = '%s'\n", errno, cam_errbuf);
#endif
if (errno == ENXIO && c->opcode[0] != 0) {
/* Operations on empty or ejected tray */
/* MEDIUM NOT PRESENT */
#ifdef Libburn_ahci_verbouS
fprintf(stderr, "libburn_EXPERIMENTAL: Emulating [2,3A,00] MEDIUM NOT PRESENT\n");
#endif
c->sense[2] = 0x02;
c->sense[12] = 0x3A;
c->sense[13] = 0x00;
sense_len = 14;
ignore_error = 1;
} else if (c->opcode[0] == 0 &&
(errno == EBUSY || errno == ENXIO)) {
/* Timeout of TEST UNIT READY loop */
/* Inquiries while tray is being loaded */
/*LOGICAL UNIT NOT READY,CAUSE NOT REPORTABLE*/
#ifdef Libburn_ahci_verbouS
fprintf(stderr, "libburn_EXPERIMENTAL: Emulating [2,04,00] LOGICAL UNIT NOT READY,CAUSE NOT REPORTABLE\n");
#endif
c->sense[2] = 0x02;
c->sense[12] = 0x04;
c->sense[13] = 0x00;
sense_len = 14;
ignore_error = 1;
} else if (errno == EINVAL) {
/* Inappropriate MODE SENSE */
/* INVALID FIELD IN CDB */
#ifdef Libburn_ahci_verbouS
fprintf(stderr, "libburn_EXPERIMENTAL: Emulating [5,24,00] INVALID FIELD IN CDB\n");
#endif
c->sense[2] = 0x05;
c->sense[12] = 0x24;
c->sense[13] = 0x00;
sense_len = 14;
ignore_error = 1;
}
}
if (err == -1 && !ignore_error) {
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x0002010c,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Failed to transfer command to drive",
errno, 0);
cam_freeccb(ccb);
sg_close_drive(d);
d->released = 1;
d->busy = BURN_DRIVE_IDLE;
c->error = 1;
return -1;
{ret = -1; goto ex;}
}
/* 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) {
if (sense_len < 14) {
/*LOGICAL UNIT NOT READY,CAUSE NOT REPORTABLE*/
#ifdef Libburn_ahci_verbouS
fprintf(stderr, "libburn_EXPERIMENTAL: CAM_STATUS= %d .Emulating [2,04,00] LOGICAL UNIT NOT READY,CAUSE NOT REPORTABLE\n", (ccb->ccb_h.status & CAM_STATUS_MASK));
#endif
c->sense[2] = 0x02;
c->sense[12] = 0x04;
c->sense[13] = 0x00;
no_retry = 1;
}
if (no_retry || ignore_error || !c->retry) {
c->error = 1;
cam_freeccb(ccb);
return 1;
{ret = 1; goto ex;}
}
switch (scsi_error(d, c->sense, 0)) {
case RETRY:
done = 0;
if (burn_sg_log_scsi & 3) {
/* >>> Need own duration time
measurement. Then remove bit1 */
scsi_log_err(c, fp, c->sense, 0,
(c->error != 0) | 2);
scsi_log_cmd(c,fp,0);
}
break;
case FAIL:
done = 1;
@ -617,8 +973,58 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
done = 1;
}
} while (!done);
ret = 1;
ex:;
if (c->error)
scsi_notify_error(d, c, c->sense, 18, 0);
if (burn_sg_log_scsi & 3)
/* >>> Need own duration time measurement. Then remove bit1 */
scsi_log_err(c, fp, c->sense, 0, (c->error != 0) | 2);
cam_freeccb(ccb);
return 1;
return ret;
}
/* ts B00115 */
/* Return 1 if the given path leads to a regular file or a device that can be
seeked, read and eventually written with 2 kB granularity.
*/
int burn_os_is_2k_seekrw(char *path, int flag)
{
struct stat stbuf;
char *spt;
int i, e;
if (stat(path, &stbuf) == -1)
return 0;
if (S_ISREG(stbuf.st_mode))
return 1;
if (!S_ISCHR(stbuf.st_mode))
return 0;
spt = strrchr(path, '/');
if (spt == NULL)
spt = path;
else
spt++;
e = strlen(spt);
for (i = strlen(spt) - 1; i > 0; i--)
if (spt[i] >= '0' && spt[i] <= '9')
e = i;
if (strncmp(spt, "da", e) == 0) /* SCSI disk. E.g. USB stick. */
return 1;
if (strncmp(spt, "cd", e) == 0) /* SCSI CD drive might be writeable. */
return 1;
if (strncmp(spt, "ad", e) == 0) /* IDE hard drive */
return 1;
if (strncmp(spt, "acd", e) == 0) /* IDE CD drive might be writeable */
return 1;
if (strncmp(spt, "fd", e) == 0) /* Floppy disk */
return 1;
if (strncmp(spt, "fla", e) == 0) /* Flash drive */
return 1;
return 0;
}
@ -639,6 +1045,7 @@ int burn_os_stdio_capacity(char *path, off_t *bytes)
char testpath[4096], *cpt;
long blocks;
off_t add_size = 0;
int fd, ret;
testpath[0] = 0;
blocks = *bytes / 512;
@ -673,6 +1080,15 @@ int burn_os_stdio_capacity(char *path, off_t *bytes)
#endif /* Libburn_if_this_was_linuX */
} else if(S_ISCHR(stbuf.st_mode)) {
fd = open(path, O_RDONLY);
if (fd == -1)
return -2;
ret = ioctl(fd, DIOCGMEDIASIZE, &add_size);
close(fd);
if (ret == -1)
return -2;
*bytes = add_size;
} else if(S_ISREG(stbuf.st_mode)) {
add_size = stbuf.st_blocks * (off_t) 512;
strcpy(testpath, path);
@ -682,7 +1098,7 @@ int burn_os_stdio_capacity(char *path, off_t *bytes)
if (testpath[0]) {
if (statvfs(testpath, &vfsbuf) == -1)
return -2;
*bytes = add_size + ((off_t) vfsbuf.f_bsize) *
*bytes = add_size + ((off_t) vfsbuf.f_frsize) *
(off_t) vfsbuf.f_bavail;
}
return 1;

1000
libburn/sg-libcdio.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,11 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
/* <<< ts A91112 : experiments to get better speed with USB
#define Libburn_sgio_as_growisofS 1
@ -11,7 +17,7 @@
This is the main operating system dependent SCSI part of libburn. It implements
the transport level aspects of SCSI control and command i/o.
Present implementation: Linux SCSI Generic (sg)
Present implementation: GNU/Linux SCSI Generic (sg)
PORTING:
@ -35,12 +41,28 @@ and of deriving the following system specific files from existing examples:
Said sg-*.c operations are defined by a public function interface, which has
to be implemented in a way that provides libburn with the desired services:
sg_id_string() returns an id string of the SCSI transport adapter.
It may be called before initialization but then may
return only a preliminary id.
sg_initialize() performs global initialization of the SCSI transport
adapter and eventually needed operating system
facilities. Checks for compatibility of supporting
software components.
sg_shutdown() performs global finalizations and releases golbally
aquired resources.
sg_give_next_adr() iterates over the set of potentially useful drive
address strings.
scsi_enumerate_drives() brings all available, not-whitelist-banned, and
accessible drives into libburn's list of drives.
sg_dispose_drive() finalizes adapter specifics of struct burn_drive
on destruction. Releases resources which were aquired
underneath scsi_enumerate_drives().
sg_drive_is_open() tells wether libburn has the given drive in use.
sg_grab() opens the drive for SCSI commands and ensures
@ -55,15 +77,17 @@ sg_issue_command() sends a SCSI command to the drive, receives reply,
sg_obtain_scsi_adr() tries to obtain SCSI address parameters.
burn_os_is_2k_seekrw() tells whether the given path leads to a file object
that can be used in 2 kB granularity by lseek(2) and
read(2), and possibly write(2) if not read-only.
E.g. a USB stick or a hard disk.
burn_os_stdio_capacity() estimates the emulated media space of stdio-drives.
burn_os_open_track_src() opens a disk file in a way that allows best
throughput with file reading and/or SCSI write command
transmission.
burn_os_close_track_src() closes a filedescriptor obtained by
burn_os_open_track_src().
burn_os_alloc_buffer() allocates a memory area that is suitable for file
descriptors issued by burn_os_open_track_src().
The buffer size may be rounded up for alignment
@ -80,6 +104,10 @@ Hint: You should also look into sg-freebsd-port.c, which is a younger and
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
/** PORTING : ------- OS dependent headers and definitions ------ */
@ -875,7 +903,7 @@ static int is_scsi_drive(char *fname, int *bus_no, int *host_no,
#endif /* Libburn_drive_new_deaL */
/** Speciality of Linux: detect non-SCSI ATAPI (EIDE) which will from
/** Speciality of GNU/Linux: detect non-SCSI ATAPI (EIDE) which will from
then on used used via generic SCSI as is done with (emulated) SCSI drives */
static void ata_enumerate(void)
{
@ -1384,7 +1412,7 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
/* PORTING: ------------------- non portable part --------------- */
/* Operating system adapter is Linux Generic SCSI (sg) */
/* Operating system adapter is GNU/Linux Generic SCSI (sg) */
/* Adapter specific handles and data */
out.fd = -1337;
out.sibling_count = 0;
@ -1410,8 +1438,63 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
/* ------------------------------------------------------------------------ */
/** Returns the id string of the SCSI transport adapter and eventually
needed operating system facilities.
This call is usable even if sg_initialize() was not called yet. In that
case a preliminary constant message might be issued if detailed info is
not available yet.
@param msg returns id string
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_id_string(char msg[1024], int flag)
{
strcpy(msg, "internal GNU/Linux SG_IO adapter sg-linux");
return 1;
}
/** Performs global initialization of the SCSI transport adapter and eventually
needed operating system facilities. Checks for compatibility supporting
software components.
@param msg returns ids and/or error messages of eventual helpers
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_initialize(char msg[1024], int flag)
{
return sg_id_string(msg, 0);
}
/** Performs global finalization of the SCSI transport adapter and eventually
needed operating system facilities. Releases globally aquired resources.
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_shutdown(int flag)
{
return 1;
}
/** Finalizes BURN_OS_TRANSPORT_DRIVE_ELEMENTS, the components of
struct burn_drive which are defined in os-*.h.
The eventual initialization of those components was made underneath
scsi_enumerate_drives().
This will be called when a burn_drive gets disposed.
@param d the drive to be finalized
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_dispose_drive(struct burn_drive *d, int flag)
{
return 1;
}
/** PORTING:
In this Linux implementation, this function mirrors the enumeration
In this GNU/Linux implementation, this function mirrors the enumeration
done in sg_enumerate and ata_enumerate(). It would be better to base those
functions on this sg_give_next_adr() but the situation is not inviting.
*/
@ -1508,7 +1591,7 @@ return_1_pre_proc:;
libburn's list of drives.
*/
/** PORTING:
If not stricken with an incompletely unified situation like in Linux
If not stricken with an incompletely unified situation like in GNU/Linux
one would rather implement this by a loop calling sg_give_next_adr().
If needed with your sg_give_next_adr() results, do a test for existence
and accessability. If burn activities are prone to external interference
@ -1572,6 +1655,7 @@ int sg_drive_is_open(struct burn_drive * d)
int sg_grab(struct burn_drive *d)
{
int fd, os_errno= 0, ret;
int max_tries = 3, tries = 0;
/* ts A60813 */
int open_mode = O_RDWR;
@ -1605,6 +1689,7 @@ int sg_grab(struct burn_drive *d)
value -1 of open(2) war used. */
if(! burn_drive_is_open(d)) {
try_open:;
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
mmc_function_spy(NULL, "sg_grab ----------- opening");
@ -1638,13 +1723,19 @@ int sg_grab(struct burn_drive *d)
fcntl(fd, F_SETOWN, getpid());
d->released = 0;
return 1;
}
} else if (errno == EBUSY)
goto 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", os_errno, 0);
return 0;
drive_is_in_use:;
tries++;
if (tries < max_tries) {
usleep(2000000);
goto try_open;
}
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020003,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
@ -1682,43 +1773,8 @@ int sg_release(struct burn_drive *d)
}
/* <<< ts A91111: on its way out */
/** ts A70518:
Debugging log facility. Controlled by existence of macros:
Libburn_log_sg_commandS enables logging to file
/tmp/libburn_sg_command_log
Libburn_fflush_log_sg_commandS enables fflush after each output line
Libburn_log_sg_command_stderR enables additional log to stderr
*/
/*
ts A91111: now enabled by default and controlled burn_sg_log_scsi
*/
#define Libburn_log_sg_commandS 1
#define Libburn_fflush_log_sg_commandS 1
#define Libburn_log_sg_command_stderR 1
#ifdef Libburn_log_sg_commandS
/** Logs command (before execution) */
static int sg_log_cmd(struct command *c, FILE *fp, int flag)
{
if (fp != NULL && (fp == stderr || (burn_sg_log_scsi & 1))) {
scsi_show_cmd_text(c, fp, 0);
#ifdef Libburn_fflush_log_sg_commandS
if (burn_sg_log_scsi & 4)
fflush(fp);
#endif
}
#ifdef Libburn_log_sg_command_stderR
if (fp == stderr || !(burn_sg_log_scsi & 2))
return 1;
sg_log_cmd(c, stderr, flag);
#endif
return 1;
}
#ifdef NIX
/* <<< now in spc.c as scsi_log_err */
/** logs outcome of a sg command. flag&1 causes an error message */
static int sg_log_err(struct command *c, FILE *fp,
@ -1734,21 +1790,17 @@ static int sg_log_err(struct command *c, FILE *fp,
scsi_show_cmd_reply(c, fp, 0);
fprintf(fp,"%6d ms\n", s->duration);
}
#ifdef Libburn_fflush_log_sg_commandS
if (burn_sg_log_scsi & 4)
fflush(fp);
#endif
}
#ifdef Libburn_log_sg_command_stderR
if (fp == stderr || !(burn_sg_log_scsi & 2))
return 1;
sg_log_err(c, stderr, s, flag);
#endif
return 1;
}
#endif /* Libburn_log_sg_commandS */
#endif /* NIX */
/** Sends a SCSI command to the drive, receives reply and evaluates wether
@ -1756,8 +1808,6 @@ static int sg_log_err(struct command *c, FILE *fp,
Returned SCSI errors shall not lead to a return value indicating failure.
The callers get notified by c->error. An SCSI failure which leads not to
a retry shall be notified via scsi_notify_error().
The Libburn_log_sg_commandS facility might be of help when problems with
a drive have to be examined. It shall stay disabled for normal use.
@return: 1 success , <=0 failure
*/
int sg_issue_command(struct burn_drive *d, struct command *c)
@ -1766,11 +1816,8 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
int err;
time_t start_time;
sg_io_hdr_t s;
#ifdef Libburn_log_sg_commandS
/* ts A61030 */
static FILE *fp= NULL;
#endif /* Libburn_log_sg_commandS */
/* <<< ts A60821
debug: for tracing calls which might use open drive fds */
@ -1779,7 +1826,6 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
d->fd,d->released);
mmc_function_spy(NULL, buf);
#ifdef Libburn_log_sg_commandS
/* ts A61030 */
if (burn_sg_log_scsi & 1) {
if (fp == NULL) {
@ -1789,9 +1835,7 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
}
}
if (burn_sg_log_scsi & 3)
sg_log_cmd(c,fp,0);
#endif /* Libburn_log_sg_commandS */
scsi_log_cmd(c,fp,0);
/* ts A61010 : with no fd there is no chance to send an ioctl */
if (d->fd < 0) {
@ -1888,6 +1932,11 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
switch (scsi_error(d, s.sbp, s.sb_len_wr)) {
case RETRY:
done = 0;
if (burn_sg_log_scsi & 3) {
scsi_log_err(c, fp, s.sbp, s.duration,
c->error != 0);
scsi_log_cmd(c,fp,0);
}
break;
case FAIL:
done = 1;
@ -1931,12 +1980,9 @@ ex:;
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
}
#ifdef Libburn_log_sg_commandS
if (burn_sg_log_scsi & 3)
sg_log_err(c, fp, &s, c->error != 0);
#endif /* Libburn_log_sg_commandS */
/* <<< sg_log_err(c, fp, &s, c->error != 0); */
scsi_log_err(c, fp, s.sbp, s.duration, c->error != 0);
return 1;
}
@ -2032,6 +2078,24 @@ int sg_is_enumerable_adr(char *adr)
}
/* ts B00115 */
/* Return 1 if the given path leads to a regular file or a device that can be
seeked, read, and possibly written with 2 kB granularity.
*/
int burn_os_is_2k_seekrw(char *path, int flag)
{
struct stat stbuf;
if (stat(path, &stbuf) == -1)
return 0;
if (S_ISREG(stbuf.st_mode))
return 1;
if (S_ISBLK(stbuf.st_mode))
return 1;
return 0;
}
/* ts A70909 */
/** Estimate the potential payload capacity of a file address.
@param path The address of the file to be examined. If it does not
@ -2083,7 +2147,7 @@ int burn_os_stdio_capacity(char *path, off_t *bytes)
if (testpath[0]) {
if (statvfs(testpath, &vfsbuf) == -1)
return -2;
*bytes = add_size + ((off_t) vfsbuf.f_bsize) *
*bytes = add_size + ((off_t) vfsbuf.f_frsize) *
(off_t) vfsbuf.f_bavail;
}
return 1;

868
libburn/sg-solaris.c Normal file
View File

@ -0,0 +1,868 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/*
Copyright (c) 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
/*
This is the main operating system dependent SCSI part of libburn. It implements
the transport level aspects of SCSI control and command i/o.
Present implementation: Solaris uscsi, e.g. for SunOS 5.11
PORTING:
Porting libburn typically will consist of adding a new operating system case
to the following switcher files:
os.h Operating system specific libburn definitions and declarations.
sg.c Operating system dependent transport level modules.
and of deriving the following system specific files from existing examples:
os-*.h Included by os.h. You will need some general system knowledge
about signals and knowledge about the storage object needs of your
transport level module sg-*.c.
sg-*.c This source module. You will need special system knowledge about
how to detect all potentially available drives, how to open them,
eventually how to exclusively reserve them, how to perform
SCSI transactions, how to inquire the (pseudo-)SCSI driver.
You will not need to care about CD burning, MMC or other high-level
SCSI aspects.
Said sg-*.c operations are defined by a public function interface, which has
to be implemented in a way that provides libburn with the desired services:
sg_id_string() returns an id string of the SCSI transport adapter.
It may be called before initialization but then may
return only a preliminary id.
sg_initialize() performs global initialization of the SCSI transport
adapter and eventually needed operating system
facilities. Checks for compatibility of supporting
software components.
sg_shutdown() performs global finalizations and releases golbally
aquired resources.
sg_give_next_adr() iterates over the set of potentially useful drive
address strings.
scsi_enumerate_drives() brings all available, not-whitelist-banned, and
accessible drives into libburn's list of drives.
sg_dispose_drive() finalizes adapter specifics of struct burn_drive
on destruction. Releases resources which were aquired
underneath scsi_enumerate_drives().
sg_drive_is_open() tells wether libburn has the given drive in use.
sg_grab() opens the drive for SCSI commands and ensures
undisturbed access.
sg_release() closes a drive opened by sg_grab()
sg_issue_command() sends a SCSI command to the drive, receives reply,
and evaluates wether the command succeeded or shall
be retried or finally failed.
sg_obtain_scsi_adr() tries to obtain SCSI address parameters.
burn_os_is_2k_seekrw() tells whether the given path leads to a file object
that can be used in 2 kB granularity by lseek(2),
read(2), and possibly write(2) if not read-only..
E.g. a USB stick or a hard disk.
burn_os_stdio_capacity() estimates the emulated media space of stdio-drives.
burn_os_open_track_src() opens a disk file in a way that allows best
throughput with file reading and/or SCSI write command
transmission.
burn_os_alloc_buffer() allocates a memory area that is suitable for file
descriptors issued by burn_os_open_track_src().
The buffer size may be rounded up for alignment
reasons.
burn_os_free_buffer() delete a buffer obtained by burn_os_alloc_buffer().
Porting hints are marked by the text "PORTING:".
Send feedback to libburn-hackers@pykix.org .
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
/** PORTING : ------- OS dependent headers and definitions ------ */
#include <unistd.h>
#include <stropts.h>
#include <stdio.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#ifdef Libburn_os_has_statvfS
#include <sys/statvfs.h>
#endif /* Libburn_os_has_stavtfS */
#include <sys/dkio.h>
#include <sys/vtoc.h>
#include <sys/scsi/impl/uscsi.h>
/* The waiting time before eventually retrying a failed SCSI command.
Before each retry wait Libburn_sg_linux_retry_incR longer than with
the previous one.
*/
#define Libburn_sg_solaris_retry_usleeP 100000
#define Libburn_sg_solaris_retry_incR 100000
/** PORTING : ------ libburn portable headers and definitions ----- */
#include "transport.h"
#include "drive.h"
#include "sg.h"
#include "spc.h"
#include "sbc.h"
#include "debug.h"
#include "toc.h"
#include "util.h"
#include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger;
/* is in portable part of libburn */
int burn_drive_is_banned(char *device_address);
int burn_drive_resolve_link(char *path, char adr[],
int *recursion_count, int flag); /* drive.c */
/* Whether to log SCSI commands:
bit0= log in /tmp/libburn_sg_command_log
bit1= log to stderr
bit2= flush every line
*/
extern int burn_sg_log_scsi;
/* ------------------------------------------------------------------------ */
/* PORTING: Private definitions. Port only if needed by public functions. */
/* (Public functions are listed below) */
/* ------------------------------------------------------------------------ */
/* Storage object is in libburn/init.c
whether to strive for exclusive access to the drive
*/
extern int burn_sg_open_o_excl;
/* ------------------------------------------------------------------------ */
/* PORTING: Private functions. Port only if needed by public functions */
/* (Public functions are listed below) */
/* ------------------------------------------------------------------------ */
static int sg_close_drive(struct burn_drive * d)
{
if (d->fd != -1) {
close(d->fd);
d->fd = -1;
return 1;
}
return 0;
}
static int decode_btl_number(char **cpt, int stopper, int *no)
{
*no = 0;
for ((*cpt)++; **cpt != stopper; (*cpt)++) {
if (**cpt < '0' || **cpt > '9')
return 0;
*no = *no * 10 + **cpt - '0';
}
return 1;
}
/* Read bus, target, lun from name "cXtYdZs2".
Return 0 if name is not of the desired form.
*/
static int decode_btl_solaris(char *name, int *busno, int *tgtno, int *lunno,
int flag)
{
char *cpt;
int ret;
*busno = *tgtno = *lunno = -1;
cpt = name;
if (*cpt != 'c')
return 0;
ret = decode_btl_number(&cpt, 't', busno);
if (ret <= 0)
return ret;
ret = decode_btl_number(&cpt, 'd', tgtno);
if (ret <= 0)
return ret;
ret = decode_btl_number(&cpt, 's', lunno);
if (ret <= 0)
return ret;
cpt++;
if (*cpt != '2' || *(cpt + 1) != 0)
return 0;
return 1;
}
static int start_enum_cXtYdZs2(burn_drive_enumerator_t *idx, int flag)
{
DIR *dir;
idx->dir = NULL;
dir = opendir("/dev/rdsk");
if (dir == NULL) {
libdax_msgs_submit(libdax_messenger, -1,
0x0002000c, LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
"Cannot start device file enumeration. opendir(\"/dev/rdsk\") failed.",
errno, 0);
return 0;
}
idx->dir = dir;
return 1;
}
static int next_enum_cXtYdZs2(burn_drive_enumerator_t *idx,
char adr[], int adr_size, int flag)
{
int busno, tgtno, lunno, ret, fd = -1;
char volpath[160];
struct dirent *entry;
struct dk_cinfo cinfo;
DIR *dir;
dir = idx->dir;
while (1) {
errno = 0;
entry = readdir(dir);
if (entry == NULL) {
if (errno) {
libdax_msgs_submit(libdax_messenger,
-1, 0x0002000d,
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
"Cannot enumerate next device. readdir() from \"/dev/rdsk\" failed.",
errno, 0);
return -1;
}
break;
}
if (strlen(entry->d_name) > sizeof(volpath) - 11)
continue;
ret = decode_btl_solaris(entry->d_name,
&busno, &tgtno, &lunno, 0);
if (ret <= 0)
continue; /* not cXtYdZs2 */
sprintf(volpath, "/dev/rdsk/%s", entry->d_name);
if (burn_drive_is_banned(volpath))
continue;
fd = open(volpath, O_RDONLY | O_NDELAY);
if (fd < 0)
continue;
/* See man dkio */
ret = ioctl(fd, DKIOCINFO, &cinfo);
close(fd);
if (ret < 0)
continue;
if (cinfo.dki_ctype != DKC_CDROM)
continue;
if (adr_size <= strlen(volpath))
return -1;
strcpy(adr, volpath);
return 1;
}
return 0;
}
static int end_enum_cXtYdZs2(burn_drive_enumerator_t *idx, int flag)
{
DIR *dir;
dir = idx->dir;
if(dir != NULL)
closedir(dir);
idx->dir = NULL;
return 1;
}
/* ----------------------------------------------------------------------- */
/* PORTING: Private functions which contain publicly needed functionality. */
/* Their portable part must be performed. So it is probably best */
/* to replace the non-portable part and to call these functions */
/* in your port, too. */
/* ----------------------------------------------------------------------- */
/** Wraps a detected drive into libburn structures and hands it over to
libburn drive list.
*/
static void enumerate_common(char *fname,
int bus_no, int host_no,
int channel_no, int target_no, int lun_no)
{
int ret;
struct burn_drive out;
/* General libburn drive setup */
burn_setup_drive(&out, fname);
/* This transport adapter uses SCSI-family commands and models
(seems the adapter would know better than its boss, if ever) */
ret = burn_scsi_setup_drive(&out, bus_no, host_no, channel_no,
target_no, lun_no, 0);
if (ret <= 0)
return;
/* PORTING: ------------------- non portable part --------------- */
/* Transport adapter is Solaris uscsi */
/* Adapter specific handles and data */
out.fd = -1;
/* PORTING: ---------------- end of non portable part ------------ */
/* Adapter specific functions with standardized names */
out.grab = sg_grab;
out.release = sg_release;
out.drive_is_open = sg_drive_is_open;
out.issue_command = sg_issue_command;
/* Finally register drive and inquire drive information */
burn_drive_finish_enum(&out);
}
/* ------------------------------------------------------------------------ */
/* PORTING: Public functions. These MUST be ported. */
/* ------------------------------------------------------------------------ */
/** Returns the id string of the SCSI transport adapter and eventually
needed operating system facilities.
This call is usable even if sg_initialize() was not called yet. In that
case a preliminary constant message might be issued if detailed info is
not available yet.
@param msg returns id string
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_id_string(char msg[1024], int flag)
{
sprintf(msg, "internal Solaris uscsi adapter sg-solaris");
return 1;
}
/** Performs global initialization of the SCSI transport adapter and eventually
needed operating system facilities. Checks for compatibility of supporting
software components.
@param msg returns ids and/or error messages of eventual helpers
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_initialize(char msg[1024], int flag)
{
return sg_id_string(msg, 0);
}
/** Performs global finalization of the SCSI transport adapter and eventually
needed operating system facilities. Releases globally aquired resources.
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_shutdown(int flag)
{
return 1;
}
/** Finalizes BURN_OS_TRANSPORT_DRIVE_ELEMENTS, the components of
struct burn_drive which are defined in os-*.h.
The eventual initialization of those components was made underneath
scsi_enumerate_drives().
This will be called when a burn_drive gets disposed.
@param d the drive to be finalized
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_dispose_drive(struct burn_drive *d, int flag)
{
return 1;
}
/** Returns the next index number and the next enumerated drive address.
The enumeration has to cover all available and accessible drives. It is
allowed to return addresses of drives which are not available but under
some (even exotic) circumstances could be available. It is on the other
hand allowed, only to hand out addresses which can really be used right
in the moment of this call. (This implementation chooses the latter.)
@param idx An opaque handle. Make no own theories about it.
@param adr Takes the reply
@param adr_size Gives maximum size of reply including final 0
@param initialize 1 = start new,
0 = continue, use no other values for now
-1 = finish
@return 1 = reply is a valid address , 0 = no further address available
-1 = severe error (e.g. adr_size too small)
*/
int sg_give_next_adr(burn_drive_enumerator_t *idx,
char adr[], int adr_size, int initialize)
{
int ret;
if (initialize == 1) {
ret = start_enum_cXtYdZs2(idx, 0);
if (ret <= 0)
return ret;
} else if (initialize == -1) {
ret = end_enum_cXtYdZs2(idx, 0);
return 0;
}
ret = next_enum_cXtYdZs2(idx, adr, adr_size, 0);
return ret;
}
/** Brings all available, not-whitelist-banned, and accessible drives into
libburn's list of drives.
*/
int scsi_enumerate_drives(void)
{
burn_drive_enumerator_t idx;
int initialize = 1, ret, i_bus_no = -1;
int i_host_no = -1, i_channel_no = -1, i_target_no = -1, i_lun_no = -1;
char buf[4096];
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;
sg_obtain_scsi_adr(buf, &i_bus_no, &i_host_no,
&i_channel_no, &i_target_no, &i_lun_no);
enumerate_common(buf,
i_bus_no, i_host_no, i_channel_no,
i_target_no, i_lun_no);
}
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
return 1;
}
/** Tells whether libburn has the given drive in use or exclusively reserved.
If it is "open" then libburn will eventually call sg_release() on it when
it is time to give up usage resp. reservation.
*/
/** Published as burn_drive.drive_is_open() */
int sg_drive_is_open(struct burn_drive * d)
{
return (d->fd != -1);
}
/** Opens the drive for SCSI commands and - if burn activities are prone
to external interference on your system - obtains an exclusive access lock
on the drive. (Note: this is not physical tray locking.)
A drive that has been opened with sg_grab() will eventually be handed
over to sg_release() for closing and unreserving.
*/
int sg_grab(struct burn_drive *d)
{
char msg[4096];
int os_errno, ret;
struct dk_cinfo cinfo;
if (d->fd != -1) {
d->released = 0;
return 1;
}
d->fd = open(d->devname, O_RDONLY | O_NDELAY);
if (d->fd == -1) {
os_errno = errno;
sprintf(msg, "Could not grab drive '%s'", d->devname);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020003,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, os_errno, 0);
return 0;
}
ret = ioctl(d->fd, DKIOCINFO, &cinfo);
if (ret < 0)
goto revoke;
if (cinfo.dki_ctype != DKC_CDROM)
goto revoke;
/* >>> obtain eventual locks */;
d->released = 0;
return 1;
revoke:;
sprintf(msg, "Could not grab drive '%s'. Not a CDROM device.",
d->devname);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020003,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
return 0;
}
/** PORTING: Is mainly about the call to sg_close_drive() and whether it
implements the demanded functionality.
*/
/** Gives up the drive for SCSI commands and releases eventual access locks.
(Note: this is not physical tray locking.)
*/
int sg_release(struct burn_drive *d)
{
if (d->fd < 0) {
burn_print(1, "release an ungrabbed drive. die\n");
return 0;
}
sg_close_drive(d);
return 0;
}
/** Sends a SCSI command to the drive, receives reply and evaluates wether
the command succeeded or shall be retried or finally failed.
Returned SCSI errors shall not lead to a return value indicating failure.
The callers get notified by c->error. An SCSI failure which leads not to
a retry shall be notified via scsi_notify_error().
The Libburn_log_sg_commandS facility might be of help when problems with
a drive have to be examined. It shall stay disabled for normal use.
@return: 1 success , <=0 failure
*/
int sg_issue_command(struct burn_drive *d, struct command *c)
{
int i, usleep_time, timeout_ms, no_retry = 0, ret;
time_t start_time;
struct uscsi_cmd cgc;
char msg[80];
static FILE *fp = NULL;
c->error = 0;
memset(c->sense, 0, sizeof(c->sense));
if (d->fd == -1)
return 0;
if (burn_sg_log_scsi & 1) {
if (fp == NULL) {
fp= fopen("/tmp/libburn_sg_command_log", "a");
fprintf(fp,
"\n-----------------------------------------\n");
}
}
if (burn_sg_log_scsi & 3)
scsi_log_cmd(c,fp,0);
memset (&cgc, 0, sizeof (struct uscsi_cmd));
/* No error messages, no retries,
do not execute with other commands, request sense data
*/
cgc.uscsi_flags = USCSI_SILENT | USCSI_DIAGNOSE | USCSI_ISOLATE
| USCSI_RQENABLE;
cgc.uscsi_timeout = 200;
cgc.uscsi_cdb = (caddr_t) c->opcode;
cgc.uscsi_bufaddr = (caddr_t) c->page->data;
if (c->dir == TO_DRIVE) {
cgc.uscsi_flags |= USCSI_WRITE;
cgc.uscsi_buflen = c->page->bytes;
} else if (c->dir == FROM_DRIVE) {
cgc.uscsi_flags |= USCSI_READ;
if (c->dxfer_len >= 0)
cgc.uscsi_buflen = c->dxfer_len;
else
cgc.uscsi_buflen = BUFFER_SIZE;
/* touch page so we can use valgrind */
memset(c->page->data, 0, BUFFER_SIZE);
} else {
cgc.uscsi_buflen = 0;
}
cgc.uscsi_cdblen = c->oplen;
cgc.uscsi_rqlen = sizeof(c->sense);
cgc.uscsi_rqbuf = (caddr_t) c->sense;
/* retry-loop */
start_time = time(NULL);
timeout_ms = 200000;
for(i = 0; ; i++) {
ret = ioctl(d->fd, USCSICMD, &cgc);
/* For cgc.uscsi_status see SAM-3 5.3.1, Table 22
0 = GOOD , 2 = CHECK CONDITION : Sense Data are delivered
8 = BUSY
*/
if (ret != 0 && cgc.uscsi_status != 2) {
sprintf(msg,
"Failed to transfer command to drive. (uscsi_status = 0x%X)",
(unsigned int) cgc.uscsi_status),
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x0002010c,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
msg, errno, 0);
sg_close_drive(d);
d->released = 1;
d->busy = BURN_DRIVE_IDLE;
c->error = 1;
return -1;
}
c->sense[2] &= 15;
/* >>> valid sense: cgc.uscsi_rqlen - cgc.uscsi_rqresid */;
if (c->sense[2] || c->sense[12] || c->sense[13]) {
if (no_retry || !c->retry) {
c->error = 1;
goto ex;
}
switch (scsi_error(d, c->sense, 18)) {
case RETRY:
if (burn_sg_log_scsi & 3) {
/* >>> Need own duration time
measurement. Then remove bit1 */
scsi_log_err(c, fp, c->sense, 0,
(c->error != 0) | 2);
scsi_log_cmd(c,fp,0);
}
break;
case FAIL:
c->error = 1;
goto ex;
}
/*
Calming down retries and breaking up endless cycle
*/
usleep_time = Libburn_sg_solaris_retry_usleeP +
i * Libburn_sg_solaris_retry_incR;
if (time(NULL) + usleep_time / 1000000 - start_time >
timeout_ms / 1000 + 1) {
c->error = 1;
goto ex;
}
usleep(usleep_time);
} else
break; /* retry-loop */
} /* end of retry-loop */
ex:;
if (c->error)
scsi_notify_error(d, c, c->sense, 18, 0);
if (burn_sg_log_scsi & 3)
/* >>> Need own duration time measurement. Then remove bit1 */
scsi_log_err(c, fp, c->sense, 0, (c->error != 0) | 2);
return 1;
}
/** Tries to obtain SCSI address parameters.
@return 1 is success , 0 is failure
*/
int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
int *target_no, int *lun_no)
{
int ret;
/* Try to guess from path */
if (strncmp("/dev/rdsk/", path, 10) == 0) {
ret = decode_btl_solaris(path + 10,
bus_no, target_no, lun_no, 0);
if (ret > 0) {
*host_no = *bus_no;
*channel_no = 0;
return 1;
}
}
*bus_no = *host_no = *channel_no = *target_no = *lun_no = -1;
/* >>> Could need a ioctl which gives SCSI numbers */;
return (0);
}
/** Tells wether a text is a persistent address as listed by the enumeration
functions.
*/
int sg_is_enumerable_adr(char* adr)
{
burn_drive_enumerator_t idx;
int initialize = 1, ret;
char buf[64];
while(1) {
ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize);
initialize = 0;
if (ret <= 0)
break;
if (strcmp(adr, buf) == 0) {
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
return 1;
}
}
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
return (0);
}
/* Return 1 if the given path leads to a regular file or a device that can be
seeked, read, and possibly written with 2 kB granularity.
*/
int burn_os_is_2k_seekrw(char *path, int flag)
{
struct stat stbuf;
if (stat(path, &stbuf) == -1)
return 0;
if (S_ISREG(stbuf.st_mode))
return 1;
if (S_ISBLK(stbuf.st_mode))
return 1;
return 0;
}
/** Estimate the potential payload capacity of a file address.
@param path The address of the file to be examined. If it does not
exist yet, then the directory will be inquired.
@param bytes The pointed value gets modified, but only if an estimation is
possible.
@return -2 = cannot perform necessary operations on file object
-1 = neither path nor dirname of path exist
0 = could not estimate size capacity of file object
1 = estimation has been made, bytes was set
*/
int burn_os_stdio_capacity(char *path, off_t *bytes)
{
struct stat stbuf;
#ifdef Libburn_os_has_statvfS
struct statvfs vfsbuf;
#endif
char testpath[4096], *cpt;
long blocks;
off_t add_size = 0;
testpath[0] = 0;
blocks = *bytes / 512;
if (stat(path, &stbuf) == -1) {
strcpy(testpath, path);
cpt = strrchr(testpath, '/');
if(cpt == NULL)
strcpy(testpath, ".");
else if(cpt == testpath)
testpath[1] = 0;
else
*cpt = 0;
if (stat(testpath, &stbuf) == -1)
return -1;
} else if(S_ISBLK(stbuf.st_mode)) {
int open_mode = O_RDONLY, fd;
fd = open(path, open_mode);
if (fd == -1)
return -2;
*bytes = lseek(fd, 0, SEEK_END);
close(fd);
if (*bytes == -1) {
*bytes = 0;
return 0;
}
} else if(S_ISREG(stbuf.st_mode)) {
add_size = stbuf.st_blocks * (off_t) 512;
strcpy(testpath, path);
} else
return 0;
if (testpath[0]) {
#ifdef Libburn_os_has_statvfS
if (statvfs(testpath, &vfsbuf) == -1)
return -2;
*bytes = add_size + ((off_t) vfsbuf.f_frsize) *
(off_t) vfsbuf.f_bavail;
#else /* Libburn_os_has_statvfS */
return 0;
#endif /* ! Libburn_os_has_stavtfS */
}
return 1;
}
/* ts A91122 : an interface to open(O_DIRECT) or similar OS tricks. */
#ifdef Libburn_read_o_direcT
/* No special O_DIRECT-like precautions are implemented here */
#endif /* Libburn_read_o_direcT */
int burn_os_open_track_src(char *path, int open_flags, int flag)
{
int fd;
fd = open(path, open_flags);
return fd;
}
void *burn_os_alloc_buffer(size_t amount, int flag)
{
void *buf = NULL;
buf = calloc(1, amount);
return buf;
}
int burn_os_free_buffer(void *buffer, size_t amount, int flag)
{
if (buffer == NULL)
return 0;
free(buffer);
return 1;
}

View File

@ -1,19 +1,45 @@
/* sg.c
Switcher for operating system dependent transport level modules of libburn.
Copyright (C) 2009 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
Copyright (C) 2009 - 2010 Thomas Schmitt <scdbackup@gmx.net>,
provided under GPLv2+
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#undef HAVE_CONFIG_H
#endif
#ifdef Libburn_use_sg_dummY
#include "sg-dummy.c"
#else
#ifdef Libburn_use_libcdiO
#include "sg-libcdio.c"
#else
#ifdef __FreeBSD__
#include "sg-freebsd.c"
#else
#ifdef __FreeBSD_kernel__
#include "sg-freebsd.c"
#else
#ifdef __linux
#include "sg-linux.c"
#else
#ifdef __sun
#include "sg-solaris.c"
#else
/* The dummy adapter formally fulfills the expectations of libburn towards
@ -24,11 +50,11 @@
static int intentional_compiler_warning(void)
{
int INTENTIONAL_COMPILER_WARNING_;
int Cannot_recognize_Linux_nor_FreeBSD_;
int Cannot_recognize_GNU_Linux_nor_FreeBSD_;
int Have_to_use_dummy_MMC_transport_adapter_;
int This_libburn_will_not_be_able_to_operate_on_real_CD_drives;
int Have_to_use_dummy_MMC_transport_adapter;
int Cannot_recognize_Linux_nor_FreeBSD;
int Cannot_recognize_GNU_Linux_nor_FreeBSD;
int INTENTIONAL_COMPILER_WARNING;
return(0);
@ -36,6 +62,10 @@ static int intentional_compiler_warning(void)
#include "sg-dummy.c"
#endif /* ! __sun */
#endif /* ! __linux */
#endif /* ! __FreeBSD_kernel__ */
#endif /* ! __FreeBSD__ */
#endif /* ! Libburn_use_libcdiO */
#endif /* ! Libburn_use_sg_dummY */

View File

@ -1,5 +1,8 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (C) 2009 Thomas Schmitt <scdbackup@gmx.net>, provided under GPLv2+
*/
#ifndef __SG
#define __SG
@ -31,6 +34,51 @@ int scsi_enumerate_drives(void);
int sg_drive_is_open(struct burn_drive * d);
int burn_os_is_2k_seekrw(char *path, int flag);
int burn_os_stdio_capacity(char *path, off_t *bytes);
/* ts A91227 */
/** Returns the id string of the SCSI transport adapter and eventually
needed operating system facilities.
This call is usable even if sg_initialize() was not called yet. In that
case a preliminary constant message might be issued if detailed info is
not available yet.
@param msg returns id string
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_id_string(char msg[1024], int flag);
/* ts A91225 */
/** Performs global initialization of the SCSI transport adapter and eventually
needed operating system facilities. Checks for compatibility supporting
software components.
@param msg returns ids and/or error messages of eventual helpers
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_initialize(char msg[1024], int flag);
/* ts A91227 */
/** Performs global finalization of the SCSI transport adapter and eventually
needed operating system facilities. Releases globally aquired resources.
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_shutdown(int flag);
/* ts A91227 */
/** Finalizes BURN_OS_TRANSPORT_DRIVE_ELEMENTS, the components of
struct burn_drive which are defined in os-*.h.
The eventual initialization of those components was made underneath
scsi_enumerate_drives().
This will be called when a burn_drive gets disposed.
@param d the drive to be finalized
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_dispose_drive(struct burn_drive *d, int flag);
#endif /* __SG */

View File

@ -1,5 +1,15 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include <stdlib.h>
#include <string.h>
#include "libburn.h"

View File

@ -1,7 +1,16 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
/* scsi primary commands */
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
@ -27,6 +36,14 @@
#include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger;
/* ts A91111 :
whether to log SCSI commands:
bit0= log in /tmp/libburn_sg_command_log
bit1= log to stderr
bit2= flush every line
*/
extern int burn_sg_log_scsi;
/* spc command set */
/* ts A70519 : allocation length byte 3+4 was 0,255 */
@ -36,8 +53,7 @@ static unsigned char SPC_INQUIRY[] = { 0x12, 0, 0, 0, 36, 0 };
static unsigned char SPC_PREVENT[] = { 0x1e, 0, 0, 0, 1, 0 };
static unsigned char SPC_ALLOW[] = { 0x1e, 0, 0, 0, 0, 0 };
static unsigned char SPC_MODE_SENSE[] = { 0x5a, 0, 0, 0, 0, 0, 0, 16, 0, 0 };
static unsigned char SPC_MODE_SELECT[] =
{ 0x55, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
static unsigned char SPC_MODE_SELECT[] = { 0x55, 16, 0, 0, 0, 0, 0, 0, 0, 0 };
static unsigned char SPC_REQUEST_SENSE[] = { 0x03, 0, 0, 0, 18, 0 };
static unsigned char SPC_TEST_UNIT_READY[] = { 0x00, 0, 0, 0, 0, 0 };
@ -100,7 +116,8 @@ int spc_test_unit_ready(struct burn_drive *d)
int spc_wait_unit_attention(struct burn_drive *d, int max_sec, char *cmd_text,
int flag)
{
int i, ret = 1, key = 0, asc = 0, ascq = 0;
int i, ret = 1, key = 0, asc = 0, ascq = 0, clueless_start = 0;
static int clueless_timeout = 5 * 10;
char msg[320];
unsigned char sense[14];
enum response resp;
@ -130,6 +147,7 @@ int spc_wait_unit_attention(struct burn_drive *d, int max_sec, char *cmd_text,
/* media change notice = try again */
goto slumber;
handle_error:;
/* ts A90213 */
sprintf(msg,
"Asynchronous SCSI error on %s: ", cmd_text);
@ -144,7 +162,23 @@ int spc_wait_unit_attention(struct burn_drive *d, int max_sec, char *cmd_text,
msg, 0, 0);
d->cancel = 1;
break;
}
} else if (ascq == 0x00) { /* CAUSE NOT REPORTABLE */
/* Might be a clueless system adapter */
if (clueless_start == 0)
clueless_start = i;
if (i - clueless_start > clueless_timeout) {
libdax_msgs_submit(libdax_messenger,
d->global_index,
0x00000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
"Ended clueless NOT READY cycle",
0, 0);
ret = 1; /* medium not present = ok */
break;
}
} else if (ascq == 0x02 || ascq == 0x03)
goto handle_error;
slumber:;
usleep(100000);
}
@ -321,7 +355,7 @@ static int spc_sense_caps_al(struct burn_drive *d, int *alloc_len, int flag)
was_error = 1;
}
size = c.page->data[0] * 256 + c.page->data[1];
size = c.page->data[0] * 256 + c.page->data[1] + 2;
page = c.page->data + 8;
/* ts A61225 :
@ -517,7 +551,7 @@ void spc_sense_error_params(struct burn_drive *d)
c.dir = FROM_DRIVE;
d->issue_command(d, &c);
size = c.page->data[0] * 256 + c.page->data[1];
size = c.page->data[0] * 256 + c.page->data[1] + 2;
m = d->mdata;
page = c.page->data + 8;
d->params.retries = page[3];
@ -600,7 +634,7 @@ void spc_sense_write_params(struct burn_drive *d)
/* ts A71128 : do not interpret reply if error */
m = d->mdata;
if (!c.error) {
size = c.page->data[0] * 256 + c.page->data[1];
size = c.page->data[0] * 256 + c.page->data[1] + 2;
page = c.page->data + 8;
burn_print(1, "write page length 0x%x\n", page[1]);
m->write_page_length = page[1];
@ -925,18 +959,36 @@ enum response scsi_error_msg(struct burn_drive *d, unsigned char *sense,
int *key, int *asc, int *ascq)
{
char *msg;
static char key_def[16][40] = {
"(no specific error)",
"Recovered error",
"Drive not ready",
"Medium error",
"Drive error",
"Illegal request",
"Drive event",
"Data protected",
"Blank/Nonblank",
"Vendor specific code",
"Copy aborted",
"Command aborted",
"(obsolete error code)",
"Volume overflow",
"Miscompare",
"(reserved error code)",
};
msg= msg_data;
*key= *asc= *ascq= -1;
if (senselen<=0 || senselen>2)
*key = sense[2];
*key = sense[2] & 0x0f;
if (senselen<=0 || senselen>12)
*asc = sense[12];
if (senselen<=0 || senselen>13)
*ascq = sense[13];
sprintf(msg, "[%X %2.2X %2.2X] ", *key, *asc, *ascq);
sprintf(msg, "[%X %2.2X %2.2X] ", *key, *asc, *ascq);
msg= msg + strlen(msg);
burn_print(12, "CONDITION: 0x%x 0x%x 0x%x on %s %s\n",
@ -951,8 +1003,11 @@ enum response scsi_error_msg(struct burn_drive *d, unsigned char *sense,
sprintf(msg, "Not ready");
return RETRY;
case 0x04:
sprintf(msg,
if (*ascq == 1)
sprintf(msg,
"Logical unit is in the process of becoming ready");
else
sprintf(msg, "Logical unit is not ready");
return RETRY;
case 0x08:
if (*key != 4)
@ -1205,8 +1260,8 @@ enum response scsi_error_msg(struct burn_drive *d, unsigned char *sense,
return FAIL;
}
sprintf(msg_data,
"Failure. See mmc3r10g.pdf: Sense Key %X ASC %2.2X ASCQ %2.2X",
*key, *asc, *ascq);
"See MMC specs: Sense Key %X \"%s\", ASC %2.2X ASCQ %2.2X",
*key & 0xf, key_def[(*key) & 0xf], *asc, *ascq);
return FAIL;
}
@ -1412,3 +1467,56 @@ int scsi_show_cmd_reply(struct command *c, void *fp_in, int flag)
fprintf(fp, "\n");
return 1;
}
/* ts A91218 (former sg_log_cmd ts A70518) */
/** Logs command (before execution) */
int scsi_log_cmd(struct command *c, void *fp_in, int flag)
{
FILE *fp = fp_in;
if (fp != NULL && (fp == stderr || (burn_sg_log_scsi & 1))) {
scsi_show_cmd_text(c, fp, 0);
if (burn_sg_log_scsi & 4)
fflush(fp);
}
if (fp == stderr || !(burn_sg_log_scsi & 2))
return 1;
scsi_log_cmd(c, stderr, flag);
return 1;
}
/* ts A91221 (former sg_log_err ts A91108) */
/** Logs outcome of a sg command.
@param flag bit0 causes an error message
bit1 do not print duration
*/
int scsi_log_err(struct command *c, void *fp_in, unsigned char sense[18],
int duration, int flag)
{
char durtxt[20];
FILE *fp = fp_in;
if(fp != NULL && (fp == stderr || (burn_sg_log_scsi & 1))) {
if(flag & 1) {
durtxt[0] = 0;
if (!(flag & 2))
sprintf(durtxt, " (%6d ms)\n",duration);
fprintf(fp, "+++ key=%X asc=%2.2Xh ascq=%2.2Xh%s\n",
sense[2], sense[12], sense[13], durtxt);
} else {
scsi_show_cmd_reply(c, fp, 0);
if (!(flag & 2))
fprintf(fp,"%6d ms\n", duration);
}
if (burn_sg_log_scsi & 4)
fflush(fp);
}
if (fp == stderr || !(burn_sg_log_scsi & 2))
return 1;
scsi_log_err(c, stderr, sense, duration, flag);
return 1;
}

View File

@ -1,5 +1,11 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifndef __SPC
#define __SPC
@ -65,5 +71,14 @@ int scsi_show_cmd_text(struct command *c, void *fp, int flag);
/* ts A91106 */
int scsi_show_cmd_reply(struct command *c, void *fp, int flag);
/* ts A91218 (former sg_log_cmd ts A70518) */
/** Logs command (before execution) */
int scsi_log_cmd(struct command *c, void *fp, int flag);
/* ts A91221 (former sg_log_err ts A91108) */
/** Logs outcome of a sg command. */
int scsi_log_err(struct command *c, void *fp, unsigned char sense[18],
int duration, int flag);
#endif /*__SPC*/

View File

@ -1,4 +1,13 @@
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
/* ts A61008 */
/* #include <a ssert.h> */

View File

@ -1,3 +1,9 @@
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifndef BURN__STRUCTURE_H
#define BURN__STRUCTURE_H

View File

@ -1,5 +1,14 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
/* ts A61008 */
/* #include <a ssert.h> */
@ -130,7 +139,7 @@ void toc_find_modes(struct burn_drive *d)
} else {
t->mode = BURN_MODE1;
/* ts A70519 : this does not work with Linux 2.4 USB because one cannot
/* ts A70519 : this does not work with GNU/Linux 2.4 USB because one cannot
predict the exact dxfer_size without knowing the sector type.
mem.sectors = 1;
d->read_sectors(d, lba, mem.sectors, &o, &mem);

View File

@ -1,5 +1,10 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Provided under GPL version 2 or later.
*/
#ifndef __TOC_H
#define __TOC_H

View File

@ -1,5 +1,11 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifndef __TRANSPORT
#define __TRANSPORT
@ -306,6 +312,8 @@ struct burn_drive
/* ts A70929 */
pid_t thread_pid;
int thread_pid_valid;
/* ts B00225 */
pthread_t thread_tid;
/* transport functions */

View File

@ -1,3 +1,13 @@
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include <string.h>
/* ts A61008 */
@ -132,6 +142,10 @@ char *burn_guess_cd_manufacturer(int m_li, int s_li, int f_li,
char buf[1024];
char *result = NULL;
if (m_li == 0 && s_li == 2 && f_li == 0) {
result = strdup("(no manufacturer code)");
return result;
}
f_li_0 = f_li - (f_li % 10);
for (i = 0; mid_list[i].manufacturer[0]; i++) {
if (m_li == mid_list[i].m_li &&

View File

@ -1,5 +1,15 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include <unistd.h>
#include <signal.h>
@ -33,7 +43,6 @@
#include "libburn.h"
#include "drive.h"
#include "transport.h"
#include "crc.h"
#include "debug.h"
#include "init.h"
#include "toc.h"
@ -937,6 +946,8 @@ int burn_disc_init_write_status(struct burn_write_opts *o,
d->cancel = 0;
#ifdef Libburn_reset_progress_asynC
/* <<< This is now done in async.c */
/* init progress before showing the state */
d->progress.session = 0;
d->progress.sessions = disc->sessions;
@ -951,6 +962,7 @@ int burn_disc_init_write_status(struct burn_write_opts *o,
d->progress.sectors = 0;
d->progress.sector = 0;
d->progress.track = 0;
#endif /* Libburn_reset_progress_asynC */
/* ts A61023 */
d->progress.buffer_capacity = 0;
@ -1263,8 +1275,8 @@ int burn_disc_close_track_dvd_plus_r(struct burn_write_opts *o,
/* ts A91114 : EXPERIMENTAL, NOT COMPLETELY IMPLEMENTED
Simplified data transmission for DVD. libburn via Linux USB is 30 % slower
than growisofs or cdrecord when transmitting 32 KB chunks.
Simplified data transmission for DVD. libburn via GNU/Linux USB is 30 %
slower than growisofs or cdrecord when transmitting 32 KB chunks.
With 64 KB chunks it is 20% faster than the competitors.
No heavy CPU load is visible but there might be subtle race conditions in
the USB driver which work better with shorter time gaps between WRITE
@ -1304,7 +1316,7 @@ static int transact_dvd_chunk(struct burn_write_opts *opts,
unsigned char *data = out->data;
#ifdef Libburn_log_in_and_out_streaM
/* <<< ts A61031 */
/* ts A61031 */
static int tee_fd= -1;
if(tee_fd==-1)
tee_fd= open("/tmp/libburn_sg_readin",
@ -1923,6 +1935,10 @@ int burn_dvd_write_sync(struct burn_write_opts *o,
}
/* ??? padding needed ??? cowardly doing it for now */
o->obs_pad = 1; /* fill-up track's last 32k buffer */
if (d->do_stream_recording) {
if (d->current_profile == 0x41) /* BD-R */
o->obs = Libburn_bd_re_streamed_obS;
}
}
#ifdef Libburn_dvd_obs_default_64K
@ -1949,6 +1965,18 @@ int burn_dvd_write_sync(struct burn_write_opts *o,
o->obs = 32 * 1024; /* This size is required to work */
}
if (d->do_stream_recording &&
(d->current_profile == 0x43 || d->current_profile == 0x41) &&
o->obs < Libburn_bd_re_streamed_obS) {
/* LG GGW-H20 writes junk with stream recording and obs=32k */
sprintf(msg,
"Stream recording disabled because of small OS buffer");
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020176, LIBDAX_MSGS_SEV_NOTE,
LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0);
d->do_stream_recording = 0;
}
sprintf(msg, "dvd/bd Profile= %2.2Xh , obs= %d , obs_pad= %d",
d->current_profile, o->obs, o->obs_pad);
libdax_msgs_submit(libdax_messenger, d->global_index, 0x00000002,
@ -1978,7 +2006,7 @@ ex:;
burn_drive_mark_unready(d);
burn_drive_inquire_media(d);
d->busy = BURN_DRIVE_IDLE;
/* <<< d->busy = BURN_DRIVE_IDLE; */
return ret;
early_failure:;
return 0;
@ -2241,8 +2269,9 @@ int burn_stdio_write_track(struct burn_write_opts *o, struct burn_session *s,
prev_sync_sector = d->progress.sector;
if (!o->simulate)
burn_stdio_sync_cache(d->stdio_fd, d, 1);
burn_stdio_slowdown(d, &prev_time, 512 * 2, 0);
}
if ((d->progress.sector % 512) == 0)
burn_stdio_slowdown(d, &prev_time, 512 * 2, 0);
}
/* Pad up buffer to next full o->obs (usually 32 kB) */
@ -2305,7 +2334,7 @@ ex:;
/* update media state records */
burn_drive_mark_unready(d);
d->busy = BURN_DRIVE_IDLE;
/* <<< d->busy = BURN_DRIVE_IDLE; */
return ret;
}
@ -2381,7 +2410,7 @@ calloc() seems not to have the desired effect. valgrind warns:
goto ex;
}
/* ts A70521 : Linux 2.4 USB audio fails with 64 kiB */
/* ts A70521 : GNU/Linux 2.4 USB audio fails with 64 kiB */
/* ts A80414 : might need 64 kiB for BD-RE streaming */
/* buffer flush trigger for sector.c:get_sector() */
o->obs = Libburn_cd_obS;
@ -2542,7 +2571,7 @@ return crap. so we send the command, then ignore the result.
burn_drive_inquire_media(d);
burn_print(1, "done\n");
d->busy = BURN_DRIVE_IDLE;
/* <<< d->busy = BURN_DRIVE_IDLE; */
/* ts A61012 : This return was traditionally missing. I suspect this
to have caused Cdrskin_eject() failures */
@ -2557,7 +2586,7 @@ fail_wo_sync:;
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Burn run failed", 0, 0);
d->cancel = 1;
d->busy = BURN_DRIVE_IDLE;
/* <<< d->busy = BURN_DRIVE_IDLE; */
ex:;
d->do_stream_recording = 0;
if (d->buffer != NULL)

View File

@ -1,5 +1,11 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifndef BURN__WRITE_H
#define BURN__WRITE_H

View File

@ -1,7 +1,7 @@
/* test/libburner.c , API illustration of burning data or audio tracks to CD */
/* Copyright (C) 2005 - 2009 Thomas Schmitt <scdbackup@gmx.net> */
/* Provided under GPLv2,see also "License and copyright aspects" at file end */
/* Copyright (C) 2005 - 2010 Thomas Schmitt <scdbackup@gmx.net> */
/* Provided under GPL, see also "License and copyright aspects" at file end */
/** Overview
@ -26,7 +26,7 @@
approaches are shown here in application functions:
libburner_aquire_by_adr() demonstrates usage as of cdrecord traditions
libburner_aquire_by_driveno() demonstrates a scan-and-choose approach
With that aquired drive you can blank a CD-RW
With that aquired drive you can blank a CD-RW or DVD-RW
libburner_blank_disc()
or you can format a DVD-RW to profile "Restricted Overwrite" (needed once)
or an unused BD to default size with spare blocks
@ -36,9 +36,25 @@
When everything is done, main() releases the drive and shuts down libburn:
burn_drive_release();
burn_finish()
FreeBSD does not work well with the convenient synchronous signal handler. So
the waiting loops for blanking, formatting, and writing use the asynchronous
mode of the libburn signal handler. It will not shutdown the library and
abort the program, but rather tell the ongoing drive operation to stop as
soon as possible. After the loops and at the end of the program there is a
call to determine whether an abort happened:
burn_is_aborting()
Applications must use 64 bit off_t. E.g. by defining
#define _LARGEFILE_SOURCE
#define _FILE_OFFSET_BITS 64
or take special precautions to interface with the library by 64 bit integers
where libburn/libburn.h prescribes off_t.
This program gets fed with appropriate settings externally by libburn's
autotools generated build system.
*/
/** See this for the decisive API specs . libburn.h is The Original */
/* For using the installed header file : #include <libburn/libburn.h> */
/* This program insists in the own headerfile. */
@ -300,9 +316,12 @@ int libburner_blank_disc(struct burn_drive *drive, int blank_fast)
"FATAL : Media is not of erasable type\n");
return 0;
}
printf(
"Beginning to %s-blank media.\n", (blank_fast?"fast":"full"));
/* Switch to asynchronous signal handling for the time of waiting */
burn_set_signal_handling("libburner : ", NULL, 0x30);
printf("Beginning to %s-blank media.\n", (blank_fast?"fast":"full"));
burn_disc_erase(drive, blank_fast);
sleep(1);
while (burn_drive_get_status(drive, &p) != BURN_DRIVE_IDLE) {
if(p.sectors>0 && p.sector>=0) /* display 1 to 99 percent */
@ -311,6 +330,10 @@ int libburner_blank_disc(struct burn_drive *drive, int blank_fast)
printf("Blanking ( %.1f%% done )\n", percent);
sleep(1);
}
if (burn_is_aborting(0) > 0)
return -1;
/* Back to synchronous handling */
burn_set_signal_handling("libburner : ", NULL, 0);
printf("Done\n");
return 1;
}
@ -363,6 +386,7 @@ int libburner_format(struct burn_drive *drive)
fprintf(stderr, "FATAL: Can only format DVD-RW or BD\n");
return 0;
}
burn_set_signal_handling("libburner : ", NULL, 0x30);
printf("Beginning to format media.\n");
burn_disc_format(drive, size, format_flag);
@ -375,6 +399,9 @@ int libburner_format(struct burn_drive *drive)
printf("Formatting ( %.1f%% done )\n", percent);
sleep(1);
}
if (burn_is_aborting(0) > 0)
return -1;
burn_set_signal_handling("libburner : ", NULL, 0);
burn_disc_get_profile(drive_list[0].drive, &current_profile,
current_profile_name);
if (current_profile == 0x14 || current_profile == 0x13)
@ -520,6 +547,7 @@ int libburner_payload(struct burn_drive *drive,
fprintf(stderr, "Reasons given:\n%s\n", reasons);
return 0;
}
burn_set_signal_handling("libburner : ", NULL, 0x30);
printf("Burning starts. With e.g. 4x media expect up to a minute of zero progress.\n");
start_time = time(0);
@ -567,6 +595,8 @@ int libburner_payload(struct burn_drive *drive,
}
burn_session_free(session);
burn_disc_free(target_disc);
if (burn_is_aborting(0) > 0)
return -1;
if (multi && current_profile != 0x1a && current_profile != 0x13 &&
current_profile != 0x12 && current_profile != 0x43)
/* not with DVD+RW, formatted DVD-RW, DVD-RAM, BD-RE */
@ -702,6 +732,13 @@ int main(int argc, char **argv)
{
int ret;
/* A warning to programmers who start their own projekt from here. */
if (sizeof(off_t) != 8) {
fprintf(stderr,
"\nFATAL: Compile time misconfiguration. off_t is not 64 bit.\n\n");
exit(39);
}
ret = libburner_setup(argc, argv);
if (ret)
exit(ret);
@ -718,7 +755,7 @@ int main(int argc, char **argv)
/* 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
/* Activate the synchronous signal handler which eventually will try to
properly shutdown drive and library on aborting events. */
burn_set_signal_handling("libburner : ", NULL, 0);
@ -752,10 +789,14 @@ release_drive:;
burn_drive_release(drive_list[driveno].drive, 0);
finish_libburn:;
if (burn_is_aborting(0) > 0) {
burn_abort(4400, burn_abort_pacifier, "libburner : ");
fprintf(stderr,"\nlibburner run aborted\n");
exit(1);
}
/* This app does not bother to know about exact scan state.
Better to accept a memory leak here. We are done anyway. */
/* burn_drive_info_free(drive_list); */
burn_finish();
exit(ret);
}
@ -768,37 +809,6 @@ Read. Try. Think. Play. Write yourself some code. Be free of my copyright.
Be also invited to study the code of cdrskin/cdrskin.c et al.
Clarification in my name and in the name of Mario Danic, copyright holder
on toplevel of libburnia. To be fully in effect after the remaining other
copyrighted code has been replaced by ours and by copyright-free contributions
of our friends:
We, the copyright holders, agree on the interpretation that
dynamical linking of our libraries constitutes "use of" and
not "derivation from" our work in the sense of GPL, provided
those libraries are compiled from our unaltered code.
Thus you may link our libraries dynamically with applications
which are not under GPL. You may distribute our libraries and
application tools in binary form, if you fulfill the usual
condition of GPL to offer a copy of the source code -altered
or unaltered- under GPL.
We ask you politely to use our work in open source spirit
and with the due reference to the entire open source community.
If there should really arise the case where above clarification
does not suffice to fulfill a clear and neat request in open source
spirit that would otherwise be declined for mere formal reasons,
only in that case we will duely consider to issue a special license
covering only that special case.
It is the open source idea of responsible freedom which will be
decisive and you will have to prove that you exhausted all own
means to qualify for GPL.
For now we are firmly committed to maintain one single license: GPL.
History:
libburner is a compilation of my own contributions to test/burniso.c and
fresh code which replaced the remaining parts under copyright of

View File

@ -1,7 +1,7 @@
/* test/telltoc.c , API illustration of obtaining media status info */
/* Copyright (C) 2006 - 2007 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 */
/* Copyright (C) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL */
/** Overview