Compare commits

..

5 Commits

73 changed files with 1703 additions and 16109 deletions

View File

@ -1,3 +1,5 @@
Developers:
Mario Danic
Thomas Schmitt
Lorenzo Taylor

View File

@ -3,4 +3,3 @@ Philippe Rouquier
Gabriel Craciunescu
George Danchev
Jean-Francois Wauthy
Lorenzo Taylor

View File

@ -1,12 +1,13 @@
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-2008 Mario Danic, Thomas Schmitt
Copyright (C) 2006-2007 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 as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of

View File

@ -101,14 +101,10 @@ test_structest_CPPFLAGS = -Ilibburn
test_structest_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
test_structest_SOURCES = test/structest.c
## cdrskin construction site - ts A60816 - A80820
## cdrskin construction site - ts A60816 - A70720
cdrskin_cdrskin_CPPFLAGS = -Ilibburn
cdrskin_cdrskin_CFLAGS = -DCdrskin_libburn_0_5_4
# cdrskin_cdrskin_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
# ts A80123, change proposed by Simon Huggins to cause dynamic libburn linking
cdrskin_cdrskin_LDADD = libburn/libburn.la $(THREAD_LIBS)
cdrskin_cdrskin_CFLAGS = -DCdrskin_libburn_0_3_8
cdrskin_cdrskin_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
cdrskin_cdrskin_SOURCES = cdrskin/cdrskin.c cdrskin/cdrfifo.c cdrskin/cdrfifo.h cdrskin/cdrskin_timestamp.h
##
## Open questions: how to compute $timestamp and express -DX="$timestamp"

181
README
View File

@ -1,19 +1,25 @@
------------------------------------------------------------------------------
libburnia-project.org
libburnia.pykix.org
------------------------------------------------------------------------------
This all is under GPL.
(See GPL reference, our clarification and commitment at the end of this text)
------------------------------------------------------------------------------
libburnia-project.org
libburnia.pykix.org
By Mario Danic <mario.danic@gmail.com> and Thomas Schmitt <scdbackup@gmx.net>
Copyright (C) 2006-2008 Mario Danic, Thomas Schmitt
Copyright (C) 2006-2007 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
These parts are to be replaced by own code of above libburnia.pykix.org
copyright holders and then libburnia.pykix.org is to be their sole copyright.
This is done to achieve the right to issue the clarification and the
commitment as written at the end of this text.
The rights and merits of the Libburn-copyright holders Derek Foreman and
Ben Jansens will be duely respected.
This libburnia-project.org toplevel README (C) 2006-2008 Thomas Schmitt
This libburnia.pykix.org toplevel README (C) 2006-2007 Thomas Schmitt
------------------------------------------------------------------------------
Build and Installation
@ -21,43 +27,33 @@ This libburnia-project.org toplevel README (C) 2006-2008 Thomas Schmitt
Our build system is based on autotools. For preparing the build of a SVN
snapshot you will need autotools of at least version 1.7.
Check out from SVN by
svn co http://svn.libburnia-project.org/libburn/trunk libburn
go into directory libburn and apply autotools by
svn co http://libburnia-svn.pykix.org/libburn/trunk libburn_pykix
go into directory libburn_pykix and apply autotools by
./bootstrap
Alternatively you may unpack a release tarball for which you do not need
autotools installed.
To build a libburnia-project.org subproject it should be sufficient to go
into its toplevel directory (here: "libburn") and execute
./configure --prefix=/usr
To build a libburnia.pykix.org subproject it should be sufficient to go
into its toplevel directory (here: "libburn_pykix") and execute
./configure
make
To make libburn accessible for running resp. application development,
and to install the cdrecord compatibility binary cdrskin, do:
To make the libraries accessible for running resp. developing applications
make install
Above procedure installs cdrskin depending on libburn.so.4 .
For a standalone cdrskin binary, see cdrskin/README.
An important part of the project, libisofs, is hosted in a bzr repository at
launchpad.net :
bzr branch lp:libisofs
Another part the project, libisoburn, is hosted in the libburnia SVN, too:
svn co http://svn.libburnia-project.org/libisoburn/trunk libisoburn
See README files there.
The other half of the project, libisofs, is hosted in the libburnia SVN, too:
svn co http://libburnia-svn.pykix.org/libisofs/trunk libisofs_pykix
See README file there.
------------------------------------------------------------------------------
Overview of libburnia-project.org
Overview of libburnia.pykix.org
libburnia-project.org is an open-source software project for reading, mastering
libburnia.pykix.org is an open-source software project for reading, mastering
and writing optical discs.
For now this means only CD media and all single layer DVD media except DVD+R.
@ -71,39 +67,29 @@ we would need : login on a development machine resp. a live OS on CD or DVD,
advise from a system person about the equivalent of Linux sg or FreeBSD CAM,
volunteers for testing of realistic use cases.
We have a well tested code base for burning data and audio CDs and many DVD
types. The burn API is quite comprehensively documented and can be used to
build a presentable application.
We have a functional binary which emulates the core use cases of cdrecord in
order to prove that usability, and in order to allow you to explore libburn's
scope by help of existing cdrecord frontends.
ISO 9660 filesystems with Rock Ridge and Joliet extensions can be created
and manipulated quite freely. This capability together with our burn capability
makes possible a single binary application which covers all steps of image
composition, updating and writing. Quite unique in the Linux world.
We have a workable code base for burning CD and most single layer DVD.
The burn API is quite comprehensively documented and can be used to build a
presentable application.
We have a functional binary which emulates parts of cdrecord in order to
prove that usability, and in order to allow you to explore libburnia's scope
by help of existing cdrecord frontends.
The project components (list subject to growth, hopefully):
- libburn is the library by which preformatted data get onto optical media.
It uses either /dev/sgN (e.g. on kernel 2.4 with ide-scsi) or
/dev/srM or /dev/hdX (e.g. on kernel 2.6).
/dev/hdX (e.g. on kernel 2.6).
libburn is the foundation of our cdrecord emulation. Its code is
independent of cdrecord. Its DVD capabilities are learned from
studying the code of dvd+rw-tools and MMC-5 specs. No code but only
the pure SCSI knowledge has been taken from dvd+rw-tools, though.
- libisofs is the library to pack up hard disk files and directories into a
ISO 9660 disk image. This may then be brought to CD via libburn.
ISO 9660 disk image. This may then be brought to media via libburn.
libisofs is to be the foundation of our upcoming mkisofs emulation.
- libisoburn is an add-on to libburn and libisofs which coordinates both and
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.
- cdrskin is a limited cdrecord compatibility wrapper for libburn.
cdrecord is a powerful GPL'ed burn program included in Joerg
Cdrecord is a powerful GPL'ed burn program included in Joerg
Schilling's cdrtools. cdrskin strives to be a second source for
the services traditionally provided by cdrecord. Additionally it
provides libburn's DVD capabilities, where only -sao is compatible
@ -111,34 +97,14 @@ The project components (list subject to growth, hopefully):
cdrskin does not contain any bytes copied from cdrecord's sources.
Many bytes have been copied from the message output of cdrecord
runs, though.
See cdrskin/README for more.
See cdrskin/README and man cdrskin/cdrskin.1 for more.
- xorriso is an application of all three libraries which creates, loads,
manipulates and writes ISO 9660 filesystem images with
Rock Ridge extensions. Manipulation is not only adding or
overwriting of files but also deletion, renaming, and attribute
changing.
See xorriso/README for more.
- "test" is a collection of application gestures and examples given by the
authors of the library features. The burn API example of libburn
is named test/libburner.c . The API for media information inquiry is
demonstrated in test/telltoc.c .
- test is a collection of application gestures and examples given by the
authors of the library features. The main API example for libburn
is test/libburner.c .
Explore these examples if you look for inspiration.
We strive to be a responsive upstream.
Our libraries are committed to maintain older feature sets in newer versions.
This applies to source code headers (API) as well as to linkable objects (ABI).
The only exception from this rule is about non-release versions x.y.*[13579]
which are allowed to introduce new features, change those new features in
any way and even may revoke such new features before the next release of
x.y.*[02468]. As soon as it is released, a feature is promised to persist.
SONAMES:
libburn.so.4 (since 0.3.4, March 2007),
libisofs.so.6 (since 0.6.2, February 2008),
libisoburn.so.1 (since 0.1.0, February 2008).
We plan to be a responsive upstream. Bear with us. We are still practicing.
------------------------------------------------------------------------------
@ -167,7 +133,7 @@ Project history as far as known to me:
discontent.
The situation first caused me to publically regret it and then - after i
got the opportunity to move in with cdrskin - gave me true reason to
personally apologize to Derek Foreman, Ben Jansens and the contributors at
personally apologize to Derek Foreman, Ben Jansens and the contibutors at
icculus.org/burn. Posted to both projects:
http://lists.freedesktop.org/archives/libburn/2006-August/000446.html
http://mailman-mail1.webfaction.com/pipermail/libburn-hackers/2006-August/000024.html
@ -238,81 +204,6 @@ Project history as far as known to me:
We look back on improved stability, a substantially extended list of media
and write modes, and better protection against typical user mishaps.
- 24th October 2007 version 0.4.0 is the foundation of new library libisoburn
and an upcomming integrated application for manipulating and writing
ISO 9660 + Rock Ridge images. cdrskin-0.4.0 got capabilities like growisofs
by these enhancements: growing of overwriteable media and disk files.
Taking again a bow towards Andy Polyakov.
- 26th Januar 2008 version 0.4.2 rectifies the version numbering so that we
reliably release libburn.so.4 as should have been done since libburn-0.3.2.
cdrskin now is by default linked dynamically and does a runtime check
to ensure not to be started with a libburn which is older than itself.
- 3rd Feb 2008 libisofs-0.2.x (.so.5) has been deprecated.
- 14th Feb 2008 libisofs-0.6.2 permanently replaces the old libisofs-0.2.x.
It is the first release of new libisofs.so.6 which will guarantee future
API/ABI compatibility for its whole feature set.
- 15th Feb 2008 libisoburn-0.1.0 (.so.1) coordinates libisofs and libburn for
the purpose of ISO image reading and writing. It emulates multi-session on
overwriteable media. Application xorriso makes use of all three libraries.
- 8th Apr 2008 libburn-0.4.4 has proven to be capable of burning to DVD+R/DL
and read performance on disk file pseudo-drives has been improved.
- 27th Apr 2008 libisofs-0.6.4 can now read data file content from images
and can map pieces of disk files onto image files. Image directory iteration
has been enhanced. Input data streams and extended information have been
exposed in the API to allow future development.
- 29th Apr 2008 libisoburn-0.1.4 was made more efficient with reading of
image tree nodes. It now depends on libisofs-0.6.4 and libburn-0.4.4.
xorriso makes use of new libisofs features by performing incremental
updates of directory trees and by cutting oversized data files into
pieces. A primitive single session emulation of cdrecord and mkisofs is
provided.
- 10th May 2008 libburn-0.4.6 supports formatting and writing of BD-RE,
full nominal speed for DVD-RAM and BD-RE. cdrskin has a unified blank
type with automatic media state recognition.
- 17th May 2008 an old bug with DVD-RAM and now with BD-RE is fixed by
libburn-0.4.8 to allow libisoburn emulation of multisession on those media.
- 19th May 2008 libisoburn-0.1.6 brings better table-of-content emulation
on overwriteble media and disk files.
- 1st Jun 2008 libisofs-0.6.6 fixes some problems around device files.
- 3rd Jun 2008 libisoburn-0.1.8 fixes a bug with overwriteable media.
- 23rd Jun 2008 libisoburn-0.2.0 introduces extraction of files from
ISO images.
- 16th Jul 2008 libburn-0.5.0 handles systems with no /dev/sr* but only
/dev/scd*.
- 19th Jul 2008 libisoburn/xorriso-0.2.2 can do multi-session in mkisofs
and cdrecord style. xorriso now can serve underneath growisofs.
- 20th Aug 2008 libburn-0.5.2 revokes the necessity that a drive must be
enumerable in order to be adressable. Enumeration is enhanced by examining
/proc/sys/dev/cdrom/info.
- 24th Aug 2008 libisoburn/xorriso-0.2.4 introduces a media readability check
with data retrieval option.
- 18th Sep 2008 libisofs-0.6.8 supports ISO 9660 Level 3 which allows very
large data files in the image.
- 20th Sep 2008 libisoburn/xorriso-0.2.6 takes into respect the new Level 3
capabilities of libisofs.
- 6th Oct 2008 libburn-0.5.4 adjusts the changes of 0.5.2 to the needs of
Linux kernel 2.4 and introduces human readable SCSI error messages.
------------------------------------------------------------------------------

View File

@ -1,36 +1,84 @@
------------------------------------------------------------------------------
libburnia-project.org scdbackup.sourceforge.net/cdrskin_eng.html
libburnia.pykix.org scdbackup.sourceforge.net/cdrskin_eng.html
------------------------------------------------------------------------------
Installation instructions at about line 60. First the legal stuff:
------------------------------------------------------------------------------
This all is under GPL.
(See GPL reference, our clarification and commitment at the end of this text)
------------------------------------------------------------------------------
Based on and sub project of:
libburnia.pykix.org
By Mario Danic <mario.danic@gmail.com> and Thomas Schmitt <scdbackup@gmx.net>
Copyright (C) 2006-2007 Mario Danic, Thomas Schmitt
libburnia.pykix.org is inspired by and in other components 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
See toplevel README for an overview of the current copyright situation in
libburnia.pykix.org.
------------------------------------------------------------------------------
My thanks to the above authors (except myself, of course) for making the
following possible.
cdrskin. By Thomas Schmitt <scdbackup@gmx.net>
Integrated sub project of libburnia-project.org but also published via:
Integrated sub project of libburnia.pykix.org but also published via:
http://scdbackup.sourceforge.net/cdrskin_eng.html
http://scdbackup.sourceforge.net/cdrskin-0.5.4.pl00.tar.gz
Copyright (C) 2006-2008 Thomas Schmitt, provided under GPL version 2.
http://scdbackup.sourceforge.net/cdrskin-0.3.8.tar.gz
Copyright (C) 2006-2007 Thomas Schmitt
------------------------------------------------------------------------------
On top of libburn there is implemented cdrskin 0.3.8, a limited cdrecord
compatibility wrapper which allows to use some libburn features from
the command line.
Interested users of cdrecord are invited to participate in the development
of cdrskin. Contact: scdbackup@gmx.net or libburn-hackers@pykix.org .
We will keep copyright narrow but will of course acknowledge valuable
contributions in a due way.
cdrskin is a limited cdrecord compatibility wrapper which allows to use
most of the libburn features from the command line.
Currently it is only supported on Linux with kernels >= 2.4.
Important :
This software is provided as is. There is no warranty implied and no
protection against possible damages. You use this on your own risk.
Don't blame me or other authors of libburn if anything goes wrong.
By using this software you agree to the disclaimer at the end of this text
"This software is provided as is. There is no warranty implied and ..."
I used it on my own risk with :
SuSE 7.2, kernel 2.4.4, ide-scsi emulation, LITE-ON LTR48125S CD burner, 2002
SuSE 9.0, kernel 2.4.21, ide-scsi emulation, LG GSA-4082B CD/DVD burner, 2004
NEC ND-4570A CD/DVD burner, 2006
RIP-14.4, kernel 2.6.14, no ide-scsi, with all above burners
It fails to compile or run on SuSE 6.4 (kernel 2.2.14).
It does not find the IDE CD burner on SuSE 7.2 without ide-scsi.
Other people sucessfully tested cdrskin on several kernel 2.6 based x86 Linux
systems, including 64 bit systems. (Further reports are welcome.)
Compilation, First Glimpse, Installation
Obtain cdrskin-0.5.4.pl00.tar.gz, take it to a directory of your choice and do:
Obtain cdrskin-0.3.8.tar.gz, take it to a directory of your choice and do:
tar xzf cdrskin-0.5.4.pl00.tar.gz
cd cdrskin-0.5.4
tar xzf cdrskin-0.3.8.tar.gz
cd cdrskin-0.3.8
Within that directory execute:
Or obtain a libburnia.pykix.org SVN snapshot,
go into the toplevel directory of the snapshot (e.g. cd libburn_pykix ),
and execute the autotools script ./bootstrap . Use autools version >= 1.7 .
./configure --prefix=/usr
Within that toplevel directory of either cdrskin-0.3.8 or libburn then execute:
./configure
make
This will already produce a cdrskin binary. But it will be necessary to
(Note: there are next-level directories "libburn" and "cdrskin". Those
would be the wrong ones. Meant is the highest directory of tarball resp.
SVN download. Among others containing files "AUTHORS", "configure",
"Makefile.am", as well as directories "libburn" and "cdrskin".)
This will already produce a cdrskin binary. But it might be necessary to
install libburn in order to use this binary. Installation of libburn is
beyond the scope of cdrskin. For this, see included libburn docs.
@ -44,21 +92,11 @@ Version identification and help texts available afterwards:
cdrskin/cdrskin -help
man cdrskin/cdrskin.1
Install (eventually as superuser) cdrskin to a directory where it can be found:
The command for global installation of both, libburn and cdrskin is
make install
If the library libburn.so.4 is not found with a test run of cdrskin, then
try whether command
ldconfig
makes it accessible. With the statically linked binary this should not matter.
With that static binary you may as well do the few necessary actions manually.
If cdrskin was already installed by a previous version, or by "make install"
in the course of this installation, then find out where:
which cdrskin
Copy your standalone binary to exactly the address which you get as reply.
E.g.:
Copy your standalone binary to exactly the address which you get as reply
cp cdrskin/cdrskin /usr/bin/cdrskin
@ -75,10 +113,6 @@ To install the man page, you may do: echo $MANPATH and choose one of the
listed directories to copy the man-page under its ./man1 directory. Like:
cp cdrskin/cdrskin.1 /usr/share/man/man1/cdrskin.1
Note: The content of the cdrskin tarball is essentially the complete libburn
of the same version number. You may thus perform above steps in a local
SVN copy of libburn or in a unpacked libburn tarball as well.
Usage
@ -103,21 +137,9 @@ So full and insecure enabling of both for everybody would look like
chmod a+rw /dev/sr0 /dev/sr1
This is equivalent to the traditional setup chmod a+x,u+s cdrecord.
I strongly discourage to run cdrskin with setuid root or via sudo !
It is not checked for the necessary degree of hacker safety.
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
which are not listed by option --devices but point to the same SCSI addresses
as listed device files. This addressing via e.g. /dev/sr0 or /dev/scd1 is
compatible with generic read programs like dd and with write program growisofs.
For finding /dev/sg1 from /dev/sr0, the program needs rw-access to both files.
Usage examples
@ -139,8 +161,8 @@ Obtain some info about the drive
Obtain some info about the drive and the inserted media
cdrskin dev=0,1,0 -atip -v
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
Make used CD-RW or used unformatted DVD-RW writeable again
cdrskin -v dev=0,1,0 blank=fast -eject
Format DVD-RW to avoid need for blanking before re-use
cdrskin -v dev=0,1,0 blank=format_overwrite
@ -152,18 +174,18 @@ Burn image file my_image.iso to media
cdrskin -v dev=0,1,0 speed=12 fs=8m driveropts=burnfree padsize=300k \
-eject my_image.iso
Write multi-session to the same CD , DVD-R[W] or DVD+R[/DL]
Write multi-session to the same CD , DVD-R[W] or DVD+R
cdrskin dev=/dev/hdc padsize=300k -multi 1.iso
cdrskin dev=/dev/hdc padsize=300k -multi 2.iso
cdrskin dev=/dev/hdc padsize=300k -multi 3.iso
cdrskin dev=/dev/hdc padsize=300k 4.iso
cdrskin dev=/dev/hdc padsize=300k -multi -tao 2.iso
cdrskin dev=/dev/hdc padsize=300k -multi -tao 3.iso
cdrskin dev=/dev/hdc padsize=300k -tao 4.iso
Get multi-session info for option -C of program mkisofs:
c_values=$(cdrskin dev=/dev/hdc -msinfo 2>/dev/null)
mkisofs ... -C "$c_values" ...
Burn a compressed afio archive to media on-the-fly
find . | afio -oZ - | cdrskin -v dev=0,1,0 fs=32m speed=8 \
find . | afio -oZ - | cdrskin -v dev=0,1,0 fs=32m speed=8 -tao \
driveropts=burnfree padsize=300k -
Burn 6 audio tracks from files with different formats to CD (not to any DVD).
@ -179,30 +201,44 @@ See below "Audio CD" for specifications.
-audio -swab track0[1-5].cd /path/to/track6.wav
Usage example with http://scdbackup.sourceforge.net
Address may be a cdrecord-style "scsibus,target,lun" as listed with
cdrskin -scanbus (and hopefully as listed with cdrecord -scanbus) :
export SCDBACKUP_SCSI_ADR="0,1,0"
or a device file address as listed by --devices with an accessible drive :
export SCDBACKUP_SCSI_ADR="/dev/sr1"
Set usage of cdrskin with appropriate options rather than cdrecord :
export SCDBACKUP_CDRECORD="cdrskin -v -v"
Run a backup :
scdbackup_home
Restrictions
Several advanced CD related options of cdrecord are still unsupported.
See output of command
cdrskin --list_ignored_options
Many cdrecord options are still unsupported.
If you have use cases for them, please report your wishes and expectations.
On the other hand, the capability of multi-session and of writing streams
of unpredicted lenght surpass the current DVD capabilities of cdrecord.
DVD support is restricted to single layer DVD for now. Double layer media
are implemented but untested.
Inspiration and Standard
cdrskin combines the command line interface standard set by cdrecord with
libburn, which is a control software for optical drives according to standard
MMC-5. For particular CD legacy commands, standards MMC-3 and MMC-1 apply.
For the original meaning of cdrecord options see :
man cdrecord
(http://cdrecord.berlios.de/old/private/man/cdrecord-2.0.html)
Do not bother Joerg Schilling with any cdrskin problems.
(Be cursed if you install cdrskin as "cdrecord" without clearly forwarding
this "don't bother Joerg" demand.)
this "don't bother Joerg" demand.)
cdrskin does not contain any bytes copied from cdrecord's sources. Many bytes
have been copied from the message output of cdrecord runs, though. I am
thankful to Joerg Schilling for every single one of them.
@ -213,6 +249,94 @@ Many thanks to Andy Polyakov for his dvd+rw-tools
which provide me with examples and pointers into MMC specs for DVD writing.
Drive Addressing
Drives get addressed either via their cdrecord-style addresses as listed
with option -scanbus (see below "Pseudo-SCSI Adresses") or via the paths
of device files.
Not only device files listed by --devices may be used but also device files
which via their major,minor numbers point to the same device driver as
a listed device file.
Helpful with Linux kernel 2.4 is a special SCSI feature:
It is possible to address a scsi(-emulated) drive via associated device files
which are not listed by option --devices but point to the same SCSI addresses
as listed device files. This addressing via e.g. /dev/sr0 or /dev/scd1 is
compatible with generic read programs like dd and with write program growisofs.
Pseudo-SCSI Adresses
cdrecord and cdrskin share the syntax of SCSI addresses but not necessarily
the meaning of the components. A cdrecord-style address for cdrskin
[prefix:]scsibus,target,lun
can be interpreted in two different modes.
Standard mode tries to be compatible to original cdrecord. This should be true
with (emulated) SCSI where the device file /dev/s[rg]N with is looked up with
matching scsibus,target,lun as given by the operating system.
With dev=ATA: or dev=ATAPI: the translation to /dev/hdX is purely literal
but matches the cdrecord addresses on all systems tested so far:
X = 'a' + 2 * scsibus + target
where target only may have the values 0 or 1.
In this mode, option -scanbus will list only SCSI devices unless option
dev=ATA or dev=ATAPI are given, which will suppress SCSI devices and only
show IDE drives (i.e. /dev/hdX without ide-scsi emulation).
In mode --old_pseudo_scsi_adr there is a scsibus,target,lun representation
which has nothing to do with SCSI and thus is not compatible to cdrecord.
Each number triple corresponds either to a device file address or to a
libburn drive number.
Component "scsibus" indicates the translation method. Defined busses are:
0 target is the libburn drivenumber as listed with --devices
1 associated to device file /dev/sgN , target chooses N
2 associated to device file /dev/hdX , target 0='a', 1='b' ..., 25='z'
So "1,1,0" is /dev/sg1 (resp. its /dev/sr*), "2,3,0" is /dev/hdd,
"0,2,0" is libburn drive #2 at some unspecified device file.
This scheme shall help to keep cdrecord-style addresses stable and exchangeable
between users without excluding drives with unexpected device addresses.
The numbering on bus 0 is prone to arbitrary changes caused by changes in
drive accessability.
Further busses may emerge as libburn evolves. "prefix" and "lun" may get
a meaning. To stay upward compatible, use addresses as printed by -scanbus.
User Defined Device Address Translation
Some programs or users have their own ideas about the address of their burner.
K3b 0.10 for example derives cdrecord addresses by own examination of the
devices and not by calling cdrecord -scanbus.
Standard mode will hopefully be fully compatible with their ideas.
Old frontends which do not know dev=ATA or dev=ATAPI and which do ask their
"cdrecord" via -scanbus may be well served with option --old_pseudo_scsi_adr .
To direct any remaining stubborn callers to the appropriate drives, cdrskin
allows to define device address aliases. Like
cdrskin dev_translation=+1,0,0+/dev/sr1 \
dev_translation=+ATA:1,0,0+/dev/sr1 \
dev_translation=-"cd+dvd"-0,1,0 \
...
Any of the addresses dev=1,0,0, dev=ATA:1,0,0, dev=cd+dvd will be mapped to
/dev/sr1 resp. to 0,1,0.
The first character after "dev_translation=" defines the character which
separates the two parts of the translation pair. (Above: "+" and "-".)
In K3b 0.10 it is possible to employ alternative writer programs by setting
their full path (e.g. /usr/bin/cdrskin) in menu
Settings:Configure K3b...:Programs:Search Path
and to make them default in menu
Settings:Configure K3b...:Programs:Programs:
A suitable setting for "cdrecord" in menu
Settings:Configure K3b...:Programs:User Parameters
would then probably be
-v dev_translation=+1,0,0+/dev/sr1
You will learn from button "Show Debugging Output" after a failed burn run
what cdrecord command was used with what address "dev=...". This address "..."
will be the right one to replace "1,0,0" in above example.
Startup Files
If not --no_rc is the first argument then cdrskin attempts on startup to read
@ -228,6 +352,8 @@ A first character '#' marks a comment, empty lines are ignored.
Example content of a startup file:
# This is the default device
dev=0,1,0
# To accomodate to eventual remnant cdrskin-0.2.2 addresses
dev_translation=+1,0,0+0,1,0
# Some more options
fifo_start_at=0
@ -260,38 +386,33 @@ I myself am not into audio. So libburn-hackers@pykix.org might be the
best address for suggestions, requests and bug reports.
DVD+RW , DVD-RAM , BD-RE
DVD+RW and DVD-RAM
These random access media get treated as blank media regardless wether they
DVD+RW and DVD-RAM media get treated as blank media regardless wether they
hold data or not. Options -audio and -multi are not allowed. Only one track
is allowed. -toc does not return information about the media content.
Speed is counted in DVD units (i.e. 1x = 1,385,000 bytes/second) or BD units
(1x = 4,495,625 bytes/second). Currently there is no difference between -sao
and -tao. If ever, then -tao will be the mode which preserves the current
behavior.
Speed is counted in DVD units (i.e. 1x = 1,385,000 bytes/second). Currently
there is no difference between -sao and -tao. If ever, then -tao will be the
mode which preserves the current behavior.
BD-RE media need formatting before first use. cdrskin option "blank=as_needed"
recognizes unformatted BD-RE and applies a lengthy formatting run.
For these media, -msinfo alone would not be enough to perform appending of an
ISO filesystem. The filesystem driver will need a hint to find the start of the
most recent session. For example put an ISO filesystem at address 1 GB:
mkisofs -C 0,524288 ... | \
cdrskin dev=/dev/sr0 -v fs=32m -eject speed=4 write_start_address=524288s -
The superuser may then do:
mount -t iso9660 -o ro,sbsector=524288 /dev/sr0 /mnt
Note: On my linux-2.4.21-215 mount works only with sbsector <= 337920 (660 MiB)
To extend a filesystem already existing at address 0
mkisofs -C 0,524288 -M /dev/sr0 ... | cdrskin dev=/dev/sr0 ...
Record the number 524288 for usage as first number with -C at the next
extension:
mkisofs -C 524288,1000000 ... | cdrskin write_start_address=1000000s ...
During write operations DVD-RAM and BD-RE automatically apply defect
management. This usually slows them down to half nominal speed. If drive
and media produce flawless results anyway, then one can try to reach full
nominal speed by option "stream_recording=on".
In this case bad blocks are not detected during write and not even previously
known bad blocks are avoided. So you have to make your own readability tests
and go back to half speed as soon as the first read errors show up.
Option --grow_overwriteable_iso allows -multi (although unneeded), enables
-msinfo and -toc, and makes blank=fast an invalidator for ISO filesystems
on overwriteable media.
Initial session (equivalent to growisofs -Z):
mkisofs ... | cdrskin --grow_overwriteable_iso blank=fast ...
Add-on session (equivalent to growisofs -M):
cparms=$(cdrskin dev=/dev/sr0 --grow_overwriteable_iso -msinfo)
mkisofs -C "$cparms" -M /dev/sr0 ... | \
cdrskin dev=/dev/sr0 --grow_overwriteable_iso ... -
Program growisofs can append to an ISO filesystem on DVD+RW by additionally
manipulating the first session. cdrskin does not want to get involved so deep
into the format of the burned data. Be advised to use growisofs for the
task of maintaining extendable ISO-Filesystems on DVD+RW.
DVD-RW and DVD-R
@ -307,7 +428,7 @@ of multi-session like CD-R[W]. (But not capable of -audio recording.)
This means they need option -multi to stay appendable, need to be blanked
to be writeable from start, return useable info with -toc and -msinfo,
eventually perform appending automatically.
Without Incremental Streaming offered by the drive, only write mode DAO is
Without "Incremental Streaming" offered by the drive, only write mode DAO is
available with sequential DVD-R[W]. It only works with blank media, allows only
one single track, no -multi, and demands a fixely predicted track size.
(growisofs uses it with DVD-R[W] if option -dvd-compat is given.)
@ -316,7 +437,7 @@ Overwriteable DVD-RW behave much like DVD+RW. "Restricted" refers only to the
granularity of random access and block size which have always to be aligned to
full 32 kB. Sequential DVD-RW are converted into overwriteable DVD-RW by
cdrskin dev=... -v blank=format_overwrite
(Command dvd+rw-format -force can achieve Restricted Overwrite, too.)
(Command dvd+rw-format -force can achieve "Restricted Overwrite", too.)
Formatting or first use of freshly formatted DVD-RW can produce unusual noises
from the drive and last several minutes. Depending on mutual compatibility of
@ -349,28 +470,10 @@ Incremental Streaming afterwards. So blank=fast will do full blanking.
blank=deformat_sequential_quickest is faster but might yield DAO-only media.
DVD+R and DVD+R DL
DVD+R
From the view of cdrskin they behave much like DVD-R. Each track gets wrapped
into an own session, though.
DVD+R DL appear as extra large DVD+R. cdrskin does not allow to set the address
of the layer break where a reading drive might show some delay while switching
between both media layers.
Emulated Drives
cdrskin can use filesystem objects as emulated drives. Regular files or block
devices appear similar to DVD-RAM. Other file types resemble blank DVD-R.
Necessary precondition is option --allow_emulated_drives which is not accepted
if cdrskin took another user identity because of the setuid bit of its access
permissions.
Addresses of emulated drives begin with prefix "stdio:". E.g.
dev=stdio:/tmp/my_pseudo_drive
For safety reasons the superuser is only allowed to use /dev/null as emulated
drive. See man page section FILES for a way to lift that ban.
------------------------------------------------------------------------------
@ -391,36 +494,12 @@ 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.
------------------------------------------------------------------------------
Project aspects and legal stuff
------------------------------------------------------------------------------
Important Disclaimer :
This software is provided as is. There is no warranty implied and no
protection against possible damages. You use this on your own risk.
Don't blame me or other authors of libburn if anything goes wrong.
Actually, in case of severe trouble, nearly always the drive and the media
are the cause. Any mistake of the burn program is supposed to be caught
by the drive's firmware and to lead to mere misburns.
The worst mishaps which hit the author imposed the need to reboot the
system because of drives gnawing endlessly on ill media. Permanent hardware
damage did not occur in 2.5 years of development. But one never knows ...
------------------------------------------------------------------------------
Interested users are invited to participate in the development of cdrskin.
Contact: scdbackup@gmx.net or libburn-hackers@pykix.org .
We will keep copyright narrow but will of course acknowledge valuable
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
as published by the Free Software Foundation.
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@ -431,21 +510,6 @@ contributions in a due way.
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
------------------------------------------------------------------------------
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-2008 Mario Danic, Thomas Schmitt
libburnia-project.org is inspired by and in other components 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
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:

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.5.4"
skin_release="0.3.8"
patch_level=".pl00"
skin_rev="$skin_release""$patch_level"
@ -58,8 +58,7 @@ compile_result="cdrskin/cdrskin"
man_to_html_cmd="./cdrskin/convert_man_to_html.sh"
man_page_html="cdrskin/man_1_cdrskin.html"
# bintarget_dynamic="cdrskin_${skin_rev}-x86-suse9_0"
bintarget_dynamic="cdrskin_${skin_rev}-amd64-suse10_2"
bintarget_dynamic="cdrskin_${skin_rev}-x86-suse9_0"
bintarget_static="$bintarget_dynamic"-static
if test -d "$changes"
@ -104,9 +103,9 @@ cdrskin_target="$target"/cdrskin
libburn_target="$target"/libburn
# Create version timestamp
# timestamp="$(date -u '+%Y.%m.%d.%H%M%S')"
# echo "$timestamp"
# echo '#define Cdrskin_timestamP "'"$timestamp"'"' >"$cdrskin_dir"/cdrskin_timestamp.h
timestamp="$(date -u '+%Y.%m.%d.%H%M%S')"
echo "$timestamp"
echo '#define Cdrskin_timestamP "'"$timestamp"'"' >"$cdrskin_dir"/cdrskin_timestamp.h
# Add the cdrskin files
if test -e "$cdrskin_target"
@ -155,10 +154,6 @@ do
fi
done
# Remove libcevap
rm -rf "$target"/libcevap
# Remove unwanted SVN stuff (TODO: avoid downloading it)
for i in "$target"/.svn "$target"/*/.svn
do

View File

@ -24,9 +24,9 @@ set -x
# The top level directory in the SVN snapshot is named
intermediate="./libburn_pykix"
# libburn source used: http://libburnia-project.org
# libburn source used: http://libburnia.pykix.org
# Downloaded by:
# $ svn co http://libburnia-project.org/libburn/tags/... $intermediate
# $ svn co http://libburnia-svn.pykix.org/libburn/tags/... $intermediate
# packed up in a tarball just to save it from inadverted changes by
# $ tar czf libburn_svn.tgz $intermediate
original="./libburn_svn.tgz"
@ -38,7 +38,7 @@ original="./libburn_svn.tgz"
# My changes are in $changes , mainly in $changes/cdrskin
changes="./libburn-develop"
skin_release="0.5.5"
skin_release="0.3.9"
patch_level=""
skin_rev="$skin_release""$patch_level"
@ -58,7 +58,7 @@ compile_result="cdrskin/cdrskin"
man_to_html_cmd="./cdrskin/convert_man_to_html.sh"
man_page_html="cdrskin/man_1_cdrskin.html"
bintarget_dynamic="cdrskin_${skin_rev}-amd64-suse10_2"
bintarget_dynamic="cdrskin_${skin_rev}-x86-suse9_0"
bintarget_static="$bintarget_dynamic"-static
if test -d "$changes"
@ -143,9 +143,6 @@ rm "$cdrskin_target"/doener_*.gif "$cdrskin_target"/doener_*.png
# Remove automatically generated HTML man page
rm "$cdrskin_target"/man_1_cdrskin.html
# Remove libcevap
rm -rf "$target"/libcevap
# Remove all add_ts_changes_to_libburn besides this one
for i in "$cdrskin_target"/add_ts_changes_to_libburn*
do
@ -225,8 +222,6 @@ tar czf "$cdrskin_tarball" "$target"
"$compile_cmd" $compile_static_opts -libburn_svn -O2 -do_strip
cp "$compile_result" "../$bintarget_static"
fi
# "$compile_cmd" -libburn_svn -O2 -do_diet -do_strip
# cp "$compile_result" "../$bintarget_dynamic"_diet
"$man_to_html_cmd"
mv "$man_page_html" ..
)

View File

@ -79,7 +79,6 @@ struct CdrfifO {
/* eventual ISO-9660 image size obtained from first 64k of input */
double iso_fs_size;
char *iso_fs_descr; /* eventually block 16 to 31 of input */
/* (sequential) fd chaining */
/* fds: 0=source, 1=dest */
@ -163,7 +162,6 @@ int Cdrfifo_new(struct CdrfifO **ff, int source_fd, int dest_fd,
o->empty_counter= 0.0;
o->full_counter= 0.0;
o->iso_fs_size= -1.0;
o->iso_fs_descr= NULL;
for(i= 0; i<Cdrfifo_ffd_maX; i++) {
o->follow_up_fds[i][0]= o->follow_up_fds[i][1]= -1;
o->follow_up_eop[i]= o->follow_up_sod[i]= -1;
@ -224,8 +222,6 @@ int Cdrfifo_destroy(struct CdrfifO **ff, int flag)
/* eventual closing of source fds is the job of the calling application */
if(o->iso_fs_descr!=NULL)
free((char *) o->iso_fs_descr);
if(o->buffer!=NULL)
free((char *) o->buffer);
free((char *) o);
@ -404,14 +400,6 @@ int Cdrfifo_get_iso_fs_size(struct CdrfifO *o, double *size_in_bytes, int flag)
}
int Cdrfifo_adopt_iso_fs_descr(struct CdrfifO *o, char **pt, int flag)
{
*pt= o->iso_fs_descr;
o->iso_fs_descr= NULL;
return(*pt!=NULL);
}
/** Get counters which are mentioned by cdrecord at the end of burning.
It still has to be examined wether they mean what i believe they do.
*/
@ -894,24 +882,19 @@ int Cdrfifo_fill(struct CdrfifO *o, int size, int flag)
}
#ifndef Cdrfifo_standalonE
if(fill>=32*2048) {
int Scan_for_iso_size(unsigned char data[2048], double *size_in_bytes,
{ int Scan_for_iso_size(unsigned char data[2048], double *size_in_bytes,
int flag);
int bs= 16*2048;
int i;
double size;
/* memorize blocks 16 to 31 */
if(o->iso_fs_descr!=NULL)
free((char *) o->iso_fs_descr);
o->iso_fs_descr= TSOB_FELD(char,bs);
if(o->iso_fs_descr==NULL)
return(-1);
memcpy(o->iso_fs_descr,o->buffer+bs,bs);
/* try to obtain ISO-9660 file system size from block 16 */
ret= Scan_for_iso_size((unsigned char *) (o->buffer+bs), &size, 0);
if(ret>0)
/* try to obtain an ISO-9660 file system size */
for(i= 0; i<32*2048 && i+2048<=fill; i+=2048) {
ret= Scan_for_iso_size((unsigned char *) (o->buffer+i), &size, 0);
if(ret<=0)
continue;
o->iso_fs_size= size;
break;
}
}
#endif

View File

@ -123,16 +123,6 @@ int Cdrfifo_get_cdr_counters(struct CdrfifO *o,
int Cdrfifo_get_iso_fs_size(struct CdrfifO *o, double *size_in_bytes,int flag);
/** Take over the eventually memorized blocks 16 to 31 of input (2 kB each).
The fifo forgets the blocks by this call. I.e. a second one will return 0.
After this call it is the responsibility of the caller to dispose the
retrieved memory via call free().
@param pt Will be filled either with NULL or a pointer to 32 kB of data
@return 0=nothing is buffered, 1=pt points to valid freeable data
*/
int Cdrfifo_adopt_iso_fs_descr(struct CdrfifO *o, char **pt, int flag);
/** Check for pending data at the fifo's source file descriptor and wether the
fifo is ready to take them. Simultaneously check the buffer for existing
data and the destination fd for readiness to accept some. If so, a small

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 "Aug 05, 2008"
.TH CDRSKIN 1 "July 19, 2007"
.\" Please adjust this date whenever revising the manpage.
.\"
.\" Some roff macros, for reference:
@ -16,7 +16,8 @@
.\" .sp <n> insert n+1 empty lines
.\" for manpage-specific macros, see man(7)
.SH NAME
cdrskin \- burns preformatted data to CD, DVD, and BD-RE via libburn.
cdrskin \- burns preformatted data to CD-R[W], DVD-R[W], DVD+R[W], DVD-RAM
via libburn.
.SH SYNOPSIS
.B cdrskin
.RI [ options | track_source_addresses ]
@ -28,15 +29,13 @@ cdrskin \- burns preformatted data to CD, DVD, and BD-RE via libburn.
.\" respectively.
.PP
\fBcdrskin\fP is a program that provides some of cdrecord's options
in a compatible way for CD media. With DVD and BD-RE it has its own ways.
in a compatible way for CD media. With DVD it has its own ways.
You do not need to be superuser for its daily usage.
.SS
.PP
.B Overview of features:
.br
Blanking of CD-RW and DVD-RW.
.br
Formatting of DVD-RW, DVD+RW, DVD-RAM, BD-RE.
.br
Burning of data or audio tracks to CD,
.br
either in versatile Track at Once mode (TAO)
@ -45,20 +44,16 @@ or in Session at Once mode for seamless tracks.
.br
Multi session on CD (follow-up sessions in TAO only)
.br
or on DVD-R[W] (in Incremental mode) or on DVD+R[/DL].
or on DVD-R[W] (in Incremental mode) or on DVD+R.
.br
Single session on DVD-RW or DVD-R (Disk-at-once).
Single session on DVD-RW or DVD-R (Disk-at-once)
.br
Single session or emulated ISO-9660 multi-session
.br
on overwriteable DVD+RW, DVD-RW, DVD-RAM, BD-RE
.br
or on data file or block device.
or on overwriteable DVD+RW, DVD-RW, DVD-RAM.
.br
Bus scan, burnfree, speed options, retrieving media info, padding, fifo.
.br
See section EXAMPLES at the end of this text.
.SS
.PP
.B General information paragraphs:
.br
Track recording model
@ -69,12 +64,10 @@ Recordable CD Media
.br
Sequentially Recordable DVD Media
.br
Overwriteable DVD or BD Media
Overwriteable DVD Media
.br
Drive preparation and addressing
.br
Emulated drives
.SS
.PP
.B Track recording model:
.br
The input-output entities which get processed are called tracks.
@ -97,7 +90,7 @@ These informations are 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.
resp. by music CD players. With DVD there is only type data.
.br
If not explicitely 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
@ -108,31 +101,17 @@ While audio tracks just contain a given time span of acoustic vibrations,
data tracks may have an arbitray meaning. Nevertheless, ISO-9660 filesystems
are established as a format which can represent a tree of directories and
files on all major operating systems. Such filesystem images can be
produced by programs mkisofs or genisoimage or xorriso.
They can also be extended by follow-up tracks if prepared properly.
See the man pages of said programs.
produced by programs mkisofs or genisoimage. They can also be extended by
follow-up tracks if prepared properly. See the man pages of said programs.
cdrskin is able to fulfill the needs about their option -C.
.br
Another type of data track content are archive formats which originally
have been developed for magnetic tapes. Only formats which mark a detectable
end-of-archive in their data are suitable, though. Well tested are
the archivers afio and star. Not suitable seems GNU tar.
.SS
.PP
.B Write mode selection:
.br
In general there are two approaches for writing media:
.br
A permissive mode depicted by option
.B -tao
which needs no predicted track size and allows to make use of
eventual multi-session capabilities.
.br
A more restrictive mode
.B -sao
(alias -dao) which usually demands a predictable track size and is not
necessarily capable of multi-session. It may have advantages for some
readers resp. players of the recorded tracks.
.br
If none of the options -dao, -tao or -sao is given then the program will
try to choose a write mode which matches the defined recording job,
the capabilities of the drive and the state of the present media.
@ -140,7 +119,7 @@ the capabilities of the drive and the state of the present media.
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,
but rather an illustration of what to expect with particular media types.
.SS
.PP
.B Recordable CD Media:
.br
CD-R can be initially written only once and eventually extended until they
@ -149,11 +128,15 @@ read-only. Closing is done automatically unless option
.B -multi
is given which keeps the media appendable.
.br
Write mode
-tao allows to use track sources of unpredictable length (like stdin) and
allows to write further sessions to appendable media.
-sao produces audio sessions with seamless tracks but needs predicted track
sizes and cannot append sessions to media.
There are two write modes,
.B -tao
and
.B -sao .
.br
-tao allows to use track source of unpredictable length (like stdin) and allows
to write further sessions to appendable media. -sao produces audio sessions
with seamless tracks but needs predicted track sizes and cannot append sessions
to media.
.br
CD-RW media can be blanked to make them re-usable for another
round of overwriting. Usually
@ -162,13 +145,13 @@ is the appropriate option.
Blanking damages the previous content but does not
make it completely unreadable. It is no effective privacy precaution.
Multiple cycles of blanking and overwriting with random numbers might be.
.SS
.PP
.B Sequentially Recordable DVD Media:
.br
Currently DVD-RW, DVD-R and DVD+R[/DL] can be used for the Sequential recording
Currently DVD-RW, DVD-R and DVD+R can be used for the Sequential recording
model.
.br
This applies to DVD-RW only if they are in state "Sequential Recording".
DVD-RW must be in state "Sequential Recording".
The media must be either blank or appendable.
Newly purchased DVD-RW and DVD-R media are in this state.
Used DVD-RW get into blank sequential state by option
@ -200,41 +183,24 @@ unpredicted length and to keep media appendable by option
The only restriction towards CD-R[W] is the lack of support for -audio tracks.
Multiple tracks per session are permissible.
.br
The write modes for DVD+R[/DL] resemble those with DVD-R except that with +R
The write modes for DVD+R resemble those with DVD-R except that with DVD+R
each track gets wrapped in an own session. There is no -dummy writing with
DVD+R[/DL].
DVD+R.
.br
Quite deliberately write mode -sao insists in the tradition of a predicted
track size and blank media, whereas -tao writes the tracks open ended and
allows appendable media.
.PP
.B Overwriteable DVD Media:
.br
.B Note:
Option -multi might make DVD media unreadable in some DVD-ROM drives.
Best reader compatibility is achieved without it
(i.e. by single session media).
.SS
.B Overwriteable DVD or BD Media:
.br
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.
Therefore -multi is banned unless ISO-9660 images shall be expandable by help
of option
.B --grow_overwriteable_iso .
Without this option or without an ISO-9660 filesystem image present
on media, -toc does not return information about the media content and
media get treated as blank regardless wether they hold data or not.
Currently types DVD+RW, DVD-RW and DVD-RAM can be overwritten via cdrskin.
.br
DVD+RW and DVD-RAM media get treated as blank media regardless wether they
hold data or not. They need no special initial formatting.
Options -audio and -multi are not allowed. Only one track is allowed.
-toc does not return information about the media content.
Currently there is no difference between -sao and -tao. If ever, then -tao
will be the mode which preserves the current behavior.
.PP
DVD+RW and DVD-RAM media need no special initial formatting. They offer a
single continuous data area for blockwise random access. BD-RE need
explicit formatting before use. See
.B blank=as_needed
or blank=format_defectmgt .
.br
DVD-RW are sold in state "Sequential Recording". To become suitable for the
Overwriteable DVD recording model they need to get formatted to state
@ -245,7 +211,7 @@ can be done by option
Several programs like dvd+rw-format, cdrecord, wodim, or cdrskin
can bring a DVD-RW out of overwriteable state so
that it has to be formatted again. If in doubt, just give it a try.
.SS
.PP
.B Drive preparation and addressing:
.br
The drives, either CD burners or DVD burners, are accessed via addresses which
@ -260,10 +226,8 @@ who is able to get this list without further
precautions.
.br
It is consensus that \fBchmod a+rw /dev/sr0\fP or \fBchmod a+rw /dev/hdc\fP
is less security sensitive than chmod u+s,a+x /usr/bin/cdrskin. The risk for
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").
is less security sensitive than chmod u+s /usr/bin/cdrskin. The risk for the
drive is somewhat higher but the overall system is much less at stake.
.br
.PP
If you only got one CD capable drive then you may leave out cdrskin option
@ -281,40 +245,6 @@ Further are accepted on Linux: 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
.SS
.B Emulated drives:
.br
Option
.B --allow_emulated_drives
enables addressing of pseudo-drives
which get emulated on top of filesystem objects. Regular data files and
block devices result in pseudo-drives which behave much like DVD-RAM.
If the given address does not exist yet but its directory exists, then
it gets created as regular file.
Other file types like character devices or pipes result in pseudo-drives
which behave much like blank DVD-R.
The target file address is given after prefix "stdio:".
.br
E.g.: dev=stdio:/tmp/my_pseudo_drive
.br
Addresses of the form "stdio:/dev/fd/<number>" are treated special. The
number is read literally and used as open file descriptor. With
dev="stdio:/dev/fd/1" the normal standard output of the program is
redirected to stderr and the stream data of a burn run will appear on stdout.
.br
Not good for terminals ! Redirect it.
.br
Pseudo-drives allow -dummy. Their reply with --tell_media_space can be utopic.
-dummy burn runs touch the file but do not modify its data content.
.br
Note: --allow_emulated_drives is restricted to stdio:/dev/null if cdrskin
is run by the
.B superuser
or if it has changed user identity via the
.B setuid
bit of its access permissions. The ban for the superuser can be lifted by a
skillfully created file. See section FILES below.
.br
.SH OPTIONS
.TP
.BI \-\-help
@ -322,11 +252,6 @@ Show non-cdrecord compatible options.
.TP
.BI \-help
Show cdrecord compatible options.
.br
Note that some of the help texts are quite wrong - for cdrecord as well as
for cdrskin (e.g. -format, blank=, -load). They are, nevertheless, traditional
indicators for the availability of the listed options. Some frontend programs
make decisions after reading them.
.TP
.BI \-version
Print cdrskin id line, compatibility lure line, libburn version, cdrskin
@ -337,8 +262,7 @@ original cdrecord by Joerg Schilling:
.TP
.BI \-atip
Retrieve some info about media state. With CD-RW print "Is erasable".
With DVD media print "book type:" and a media type text. With BD media
print "Mounted Media:" and media type text.
With DVD media print "book type:" and a media type text.
.TP
.BI \-audio
Announces that the subsequent tracks are to be burned as audio.
@ -349,64 +273,29 @@ stereo. For little-endian byte order (which is usual on PCs) use option
those parameters and eventually raw audio data get extracted and burned as
audio track. Same is done for suffix ".au" and SUN Audio.
.br
Option -audio may be used only with CD media and not with DVD or BD.
Option -audio may be used only with CD media and not with DVD.
.TP
.BI blank= type
Blank a CD-RW, DVD-RW, or format a DVD-RW, DVD+RW, DVD-RAM, BD-RE.
Blank a CD-RW, a DVD-RW, or format a DVD+/-RW.
This is combinable with burning in the same run of cdrskin.
The type given with blank= selects the particular behavior:
.RS
.TP
as_needed
Try to make the media ready for writing from scratch. If it needs formatting,
then format it. If it is not blank, then try to apply blank=fast.
It is a reason to abort if the media cannot assume thoroughly writeable state,
e.g. if it is non-blank write-once.
.br
This leaves unformatted DVD-RW in unformatted blank state. To format DVD-RW use
blank=format_overwriteable.
.br
(Note: blank=as_needed is not an original cdrecord option.)
.TP
The following blank types are specific to particular media familes. Use them if special features are desired.
help
Print this list of blanking types.
.TP
all
Blank an entire CD-RW or an unformatted DVD-RW.
(See also --prodvd_cli_compatible, --grow_overwriteable_iso)
(See also --prodvd_cli_compatible)
.TP
fast
Minimally blank an entire CD-RW or blank an unformatted DVD-RW.
(See also --prodvd_cli_compatible, --grow_overwriteable_iso)
.TP
deformat_sequential
Like blank=all but with the additional ability to blank overwriteable DVD-RW.
This will destroy their formatting and make them sequentially recordable.
Another peculiarity is the ability to blank media which appear already blank.
This is similar to option -force but does not try to blank media other than
recognizable CD-RW and DVD-RW.
.br
(Note: blank=deformat_* are not original cdrecord options.)
.TP
deformat_sequential_quickest
Like blank=deformat_sequential but blanking DVD-RW only minimally.
This is faster than full blanking but may yield media incapable of
Incremental Streaming (-tao).
.TP
format_if_needed
Format a media if it is not overwriteably formatted yet,
and if cdrskin supports formatting for the media type,
and if formatting will not happen automatically during write.
This currently applies to unformatted DVD-RW, DVD-RAM and BD-RE.
Eventually the appropriate default formatting is chosen.
If other media or states are encountered then nothing happens.
.br
The following formatting types are more specialized to particular
media families.
(See also --prodvd_cli_compatible)
.TP
format_overwrite
Format a DVD-RW to "Restricted Overwrite". The user should bring some patience.
.br
(Note: blank=format_* are not original cdrecord options.)
(Note: blank=format_overwrite* are not original cdrecord options.)
.TP
format_overwrite_quickest
Like format_overwrite without creating a 128 MiB trailblazer session.
@ -425,63 +314,23 @@ This option treats already formatted media even if not option -force is given.
For DVD+RW this is the only supported explicit formatting type. It provides
complete "de-icing" so no reader slips on unwritten data areas.
.TP
format_defectmgt
Format DVD-RAM or BD-RE to reserve the default amount of spare blocks for
defect management.
deformat_sequential
Like blank=all but with the additional ability to blank overwriteable DVD-RW.
This will destroy their formatting and make them sequentially recordable.
Another peculiarity is the ability to blank media which appear already blank.
This is similar to option -force but does not try to blank media other than
recognizable CD-RW and DVD-RW.
.br
The following format_defectmgt_* allow to submit user wishes which
nevertheless have to match one of the available formats. These formats are
offered by the drive after examining the media.
(Note: blank=deformat_sequential* are not original cdrecord options.)
.TP
format_defectmgt_cert_off
Disable the usual media quality certification in order to save time and
format to default size.
The certification setting persists even if subsequent blank= options override
the size of the format selection.
.br
Whether formatting without certification works properly depends much on the
drive. One should check the "Format status:" from --list_formats afterwards.
.TP
format_defectmgt_cert_on
Re-enable the usual media quality certification and format to default size.
The certification setting persists like with format_defectmgt_cert_off.
.br
Whether there happens certification at all depends much on the media state
and the actually selected format descriptor.
.TP
format_defectmgt_max
Format DVD-RAM or BD-RE to reserve a maximum number of spare blocks.
.TP
format_defectmgt_min
Format DVD-RAM or BD-RE to reserve a minimum number of spare blocks.
It might be necessary to format format_defectmgt_none first in order to get
offered the most minmal spare blocks sizes for format_defectmgt_min.
.TP
format_defectmgt_none
Format DVD-RAM or BD-RE to the largest available payload in the hope to disable
defect management at all. This seems not to have a speed increasing effect,
though.
.TP
format_defectmgt_payload_<size>
Format DVD-RAM or BD-RE. The text after "format_defectmgt_payload_" gives a
number of bytes, eventually with suffixes "s", "k", "m". The largest number
of spare blocks will be chosen which allows at least the given payload size.
.TP
format_by_index_<number>
Format DVD-RW, DVD+RW, DVD-RAM or BD-RE.
The number after "format_by_index_" is used as index to the list of available
format descriptors. This list can be obtained by option --list_formats.
The numbers after text "Format idx" are the ones to be used with
format_by_index_. Format descriptor lists are volatile. Do neither eject
nor write the media between the run of --list_formats and the run of
blank=format_by_index_ or else you may get a different format than desired.
.TP
help
Print this list of blanking types.
deformat_sequential_quickest
Like blank=deformat_sequential but blanking DVD-RW only minimally.
This is faster than full blanking but may yield media incapable of
Incremental Streaming (-tao).
.RE
.TP
.BI \-checkdrive
Retrieve some info about the addressed drive and then exit.
Retrieve some info about the addressed drive.
Exits with non-zero value if the drive cannot be found and opened.
.TP
.BI \-dao
@ -519,7 +368,7 @@ Try to perform the drive operations without actually affecting the inserted
media. There is no warranty that this will work with a particular combination
of drive, media, and write mode. Blanking is prevented reliably, though.
To avoid inadverted real burning, -dummy refuses burn runs on anything but
CD-R[W], DVD-R[W], or emulated stdio-drives.
CD-R[W] and DVD-R[W].
.TP
.BI \-eject
Eject the disc after work is done.
@ -539,9 +388,6 @@ that drive and media will not simulate the write mode but will write for real.
.B Caution:
Use this only when in urgent need.
.TP
.BI \-format
Same as blank=format_overwrite_full -force but restricted to DVD+RW.
.TP
.BI fs= size
Set the fifo size to the given value. The value may have appended letters which
multiply the preceding number:
@ -561,19 +407,6 @@ option fifo_start_at=size.
.BI gracetime= seconds
Set the grace time before starting to write. (Default is 0)
.TP
.BI -immed
Equivalent to:
.br
modesty_on_drive=1:min_percent=75:max_percent=95
.br
The name of this cdrecord option stems from the "Immed" bit which can make some
long running drive commands asynchronous and thus eases the load on some
wiring hardware types. Regardless of option -immed, cdrskin uses asynchronous
commands where possible and appropriate.
.TP
.BI -inq
Print the identification of the drive and then exit.
.TP
.BI -isosize
The next track following this option will try to obtain its source size from
the header information out of the first few blocks of the source data.
@ -590,18 +423,6 @@ This option can be performed on track sources which are regular files or block
devices. For the first track of the session it can be performed on any type
of source if there is a fifo of at least 64 kiB. See option fs= .
.TP
.BI -load
Load the media and exit. Exit value is 0 if any kind of media was found, non
zero else. Note: Option -eject will unload the media even if -load is given.
.TP
.BI -lock
Like option -load but leave the drive's eject button disabled if there is any
media found and not option -eject is given.
.br
Use program "eject" or cdrskin -eject to get the tray out of the drive.
Runs of programs like cdrecord, growisofs, wodim, cdrskin will not be hampered
and normally enable the drive's eject button when they are done.
.TP
.BI minbuf= percentage
Equivalent to:
.br
@ -618,17 +439,13 @@ Note: msifile=path is actually an option of wodim and not of cdrecord.
.TP
.BI \-msinfo
Retrieve multi-session info for preparing a follow-up session by option -C
of programs mkisofs, genisoimage, or xorriso -as mkisofs.
Print result to standard output.
of programs mkisofs or genisoimage. Print result to standard output.
This option redirects to stderr all message output except the one of option
--tell_media_space and its own result string, which consists of two numbers.
The result string shall be used as argument of option -C with said programs.
It gives the start address of the most recent session and the predicted
start address of the next session to be appended. The string is empty if
the most recent session was not written with option -multi.
.br
To have a chance for working on overwriteable media, this option has to be
accompanied by option --grow_overwriteable_iso.
.TP
.BI \-multi
This option keeps the CD or unformatted DVD-R[W] appendable after the current
@ -637,8 +454,9 @@ Without it the disc gets closed and may not be written any more - unless it
is a -RW and gets blanked which causes loss of its content.
.br
The following sessions can only be written in -tao mode. -multi is prohibited
with DVD-R[W] DAO write mode. Option --prodvd_cli_compatible eventually makes
-multi tolerable but cannot make it work.
with overwriteable DVD media and with DVD-R[W] DAO write mode.
Option --prodvd_cli_compatible eventually makes -multi tolerable but cannot
make it work.
.br
In order to have all filesystem content accessible, the eventual ISO-9660
filesystem of a follow-up
@ -647,16 +465,7 @@ program. mkisofs and genisoimage expect particular info about the situation
which can be retrieved by cdrskin option -msinfo.
.br
To retrieve an archive file which was written as follow-up session,
you may use option -toc to learn about the "lba" of the desired track number.
This lba is the address of the 2048 byte block where the archive begins.
.br
With overwriteable DVD or BD media, -multi cannot mark the end of the session.
So when adding a new session this end has to be determined from the payload.
Currently only ISO-9660 filesystems can be used that way. See option
.B \--grow_overwriteable_iso
for lifting the ban on -multi.
.br
Note: -multi might make DVD media unreadable in some DVD-ROM drives.
you may use option -toc to learn about the "lba" of the desired track number.
.TP
.BI \-nopad
Do not add trailing zeros to the data stream. Nevertheless, since there seems
@ -681,7 +490,7 @@ One should use it only if inavoidable.
.TP
.BI \-sao
Write CD in Session At Once mode, a sequential DVD-R[W] in Disc-at-once
(DAO) mode, or a DVD+R[/DL].
(DAO) mode, or a DVD+R.
.br
With CD this mode is able to put several audio tracks on media without
producing audible gaps between them.
@ -689,8 +498,8 @@ producing audible gaps between them.
With DVD-R[W] this mode can only write a single track.
No -multi is allowed with DVD-R[W] -sao.
.br
-sao is permissible with overwriteable DVD, BD or DVD+R[/DL] but actually
only imposes restrictions without providing known advantages.
-sao is permissible with overwriteable DVD and with DVD+R but actually 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
@ -714,12 +523,11 @@ Bus,Target,Lun Number) 'Vendor' 'Mode' 'Revision'
.BI speed= number
Set speed of drive. With data CD, 1x speed corresponds to a throughput of
150,000 bytes/second. With DVD, 1x = 1,385,000 bytes/second.
With BD 1x = 4,495,625 bytes/second.
It is not an error to set a speed higher than is suitable for drive
and media. One should stay within a realistic speed range, though.
Special speed settings are:
.br
0 = minimal speed , -1 = maximal speed (default), text "any" = like -1.
0 = minimal speed , -1 = maximal speed (default).
.TP
.BI \-swab
Announce that the raw audio data source of subsequent tracks is byte swapped
@ -731,8 +539,8 @@ suffix ".wav".
.TP
.BI \-tao
Write CD in Track At Once (TAO) mode, sequential DVD-R[W] in Incremental
Streaming mode, or DVD+R[/DL] without traditional -sao restrictions.
This mode also applies pro-forma to overwriteable media
Streaming mode, or DVD+R without traditional -sao restrictions.
This mode also applies pro-forma to overwriteable DVD media.
.br
Mode -tao can be used with track sources of unpredictable size, like standard
input or named pipes. It is also the only mode that can be used for writing
@ -783,23 +591,6 @@ some extra lines to be put out with info retrieval options.
Level 2 additionally reports about option settings derived from arguments or
startup files. Level 3 is for debugging and useful mainly in conjunction with
somebody who had a look into the program sourcecode.
.TP
.BI \-waiti
Wait until input data is available at stdin or EOF occurs at stdin.
Only then begin to access any drives.
.br
One should use this if cdrskin is working at the end of a pipe where the
feeder process reads from the drive before it starts writing its output into
cdrskin. Example:
.br
mkisofs ... -C 0,12800 -M /dev/sr0 | \\
.br
cdrskin dev=/dev/sr0 ... -waiti -
.br
This option works even if stdin is not among the track sources. If no process
is piping in, then the Enter key of your terminal will act as trigger for
cdrskin. Note that this input line will not be consumed by cdrskin if stdin
is not among the track sources. It will end up as shell command, usually.
.PP
Alphabetical list of options which are genuine to cdrskin and intended for
normal use:
@ -810,10 +601,6 @@ 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.
.TP
.BI \--allow_emulated_drives
Enable drive addresses of the form dev=stdio:<path>. See above, paragraph
"Drive preparation and addressing".
.TP
.BI \--allow_setuid
Disable the loud warning about insecure discrepance between login user and
effective user which indicates application of chmod u+s to the program binary.
@ -855,60 +642,6 @@ Number dev='Devicefile' rw-Permissions : 'Vendor' 'Model'
Number and Devicefile can both be used with option dev=, but number is
volatile (numbering changes if drives become busy).
.TP
.BI direct_write_amount= size
Do not write a session with tracks but rather make an appropriate number of
direct write operations with no preparations. Flushing the drive buffer will
be the only finalization. It is advised to eject the media afterwards because
the write operations circumvent the usual system i/o with its caches and
buffers. By ejecting, those invalid memory copies get surely discarded.
.br
Only few media can be written this way: DVD-RAM, BD-RE, RVD+RW and
overwriteable DVD-RW. Writing is restricted to the already formatted
area of the media.
.br
Writing starts at byte 0 of the media or at the address given by option
.B write_start_address= .
Only the first track source is used as input for the write operations.
The fifo (fs=) is disabled.
.br
Parameter
.B size
controls the amount of data to be written. Size 0 means that the track source
shall be used up until EOF. In this case, the last write transaction gets
padded up to the necessary size by zeros. Size -1 revokes direct writing
and switches back to normal session oriented writing.
.br
Both, write_start_address and direct_write_amount size must be aligned to a
media dependend transaction size. With DVD-RAM, BD-RE, DVD+RW this is 2k, with
overwriteable DVD-RW it is 32k.
.TP
.BI fallback_program= command
Set a command name to be executed if cdrskin encounters a known cdrecord
option which it does not yet support. If a non-empty command is given with
fallback_program=, and if no essential options are given which are specific
to cdrskin, then cdrskin will delegate the job to said command.
.br
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 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.
.br
Fallback program execution is disabled if cdrskin is run setuid and not
option --allow_setuid is given. In general, the drive's device files and the
involved programs should be set up so that each program runs under its advised
conditions. (E.g. cdrskin as member of group floppy, cdrecord setuid root.)
.br
Two alias names for cdrskin are predefined with default fallback programs:
.br
.B unicord
implies fallback_program=cdrecord
.br
.B codim
implies fallback_program=wodim
.TP
.BI fifo_start_at= size
Do not wait for full fifo but start burning as soon as the given number
of bytes is read. This option may be helpful to bring the average throughput
@ -919,56 +652,6 @@ the software protection against buffer underun is as weak as the size of
fifo_start_at= . So it is best if the drive offers hardware protection which
is enabled automatically if not driveropts=noburnfree is given.
.TP
.BI \--grow_overwriteable_iso
Enable emulation of multi-session writing on overwriteable media which
contain an ISO-9660 filesystem. This emulation is learned from growisofs -M
but adapted to the usage model of
.br
.B cdrskin -msinfo
.br
.B mkisofs -C -M | cdrskin -waiti [-multi] -
.br
--grow_overwriteable_iso does not hamper the use of true multi-session media.
I.e. it is possible to use the same cdrskin options with both kinds of media
and to achieve similar results if ISO-9660 filesystem images are to be written.
This option implies option -isosize and therefore demands that the track
source is a ISO-9660 filesystem image.
.br
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
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
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
--grow_overwriteable_iso causes option blank=fast|all to invalidate an
eventual ISO-9660 image by altering the first few bytes of block 16 on
overwriteable media.
Option -multi is tolerated in order not to hamper true multi-session media.
.br
An equivalent of growisofs -Z for overwriteable media is:
.br
.B mkisofs | cdrskin --grow_overwriteable_iso blank=fast [-multi] -
.br
With multi-session DVD, blank=fast will act like dvd+rw-format -blank=full .
.br
growisofs -dvd-compat is roughly equivalent to cdrskin without option -multi.
.TP
.BI \--list_formats
List the available format descriptors as reported by the drive for the
loaded media. Each descriptor line begins with "Format idx" and the
descriptor's list index, followed by a ":", the format type, the number
of payload blocks and that same number converted to MiB.
.br
The meaning of the format types is defined by the MMC standard
with command FORMAT UNIT. A user will more be interested in the
sizes than in the types.
.TP
.BI \--list_ignored_options
List all ignored cdrecord options. The "-" options cannot be used as addresses
of track sources. No track source address may begin with a text equal to an
@ -1025,8 +708,8 @@ This option redirects to stderr all message output except its own result
string and eventual output of -msinfo.
.TP
.BI write_start_address= byte_offset
Set the address on media where to start writing the track. With DVD+RW, DVD-RAM
or BD-RE byte_offset must be aligned to 2 kiB blocks, but better is 32 kiB.
Set the address on media where to start writing the track. With DVD+RW or
DVD-RAM byte_offset must be aligned to 2 kiB blocks, but better is 32 kiB.
With DVD-RW 32 kiB alignment is mandatory.
.br
Other media are not suitable for this option yet.
@ -1046,6 +729,8 @@ tested. Currently this applies to :
.br
Profile 0015h , DVD-R/DL Sequential (will not allow -multi).
.br
Profile 002Bh , DVD+R/DL.
.br
If you really test such media, then please report the outcome on
libburn-hackers@pykix.org
.TP
@ -1082,9 +767,8 @@ Linux specific: Do not ask the operating system to prevent opening busy drives.
Wether this leads to senseful behavior depends on operating system and kernel.
.TP
.BI drive_scsi_dev_family= sr | scd | sg
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
Linux specific: Select a SCSI device file family to be used for drive command
transactions. 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
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.
@ -1112,12 +796,9 @@ This option overrides option -multi. It will not fill up media if option -sao
is given with CD media.
.br
.B Caution:
With multi-session media this option might increase readatibility on DVD-ROM
drives but with some DVD recorders and media types it might also fail to
produce readable media at all. "Your mileage may vary".
.br
You can expect the best possible read compatibility if you do not use -multi at
all.
This option might increase read compatibility with DVD-ROM drives but
with some DVD recorders and media types it might also fail to produce readable
media at all. "Your mileage may vary".
.TP
.BI grab_drive_and_wait= seconds
Open the addressed drive, wait the given number of seconds, release the drive,
@ -1178,13 +859,6 @@ Linux specific:
Use and report literal Bus,Target,Lun addresses rather than real SCSI and
pseudo ATA addresses. This method is outdated and was never compatible with
original cdrecord.
.TP
.BI stream_recording="on"|"off"
By setting "on" request that compliance to the desired speed setting is
preferred over management of write errors. With DVD-RAM and BD-RE this can
bring effective write speed near to the nominal write speed of the media.
But it will also disable the automatic use of replacement blocks
if write errors occur. It might as well be disliked or ignored by the drive.
.br
.SH EXAMPLES
.SS
@ -1204,9 +878,11 @@ cdrskin dev=ATA:1,0,0 -v -atip
.br
cdrskin dev=/dev/hdc -toc
.SS
.B Prepare CD-RW or DVD-RW for re-use, DVD-RAM or BD-RE for first use:
.B Make used CD-RW or used unformatted DVD-RW writable again:
.br
cdrskin -v dev=/dev/sg1 blank=as_needed -eject
cdrskin -v dev=/dev/sg1 blank=fast -eject
.br
cdrskin -v dev=/dev/dvd blank=all -eject
.SS
.B Format DVD-RW to avoid need for blanking before re-use:
.br
@ -1220,7 +896,7 @@ cdrskin -v dev=/dev/sr0 blank=deformat_sequential
.br
cdrskin -v dev=/dev/hdc speed=12 fs=8m \\
.br
blank=as_needed -eject padsize=300k my_image.iso
-sao -eject padsize=300k my_image.iso
.SS
.B Write compressed afio archive on-the-fly (not possible with minimally blanked DVD-RW):
.br
@ -1228,17 +904,17 @@ find . | afio -oZ - | \\
.br
cdrskin -v dev=0,1,0 fs=32m speed=8 \\
.br
blank=as_needed padsize=300k -
-tao padsize=300k -
.SS
.B Write multi-session to the same CD, DVD-R[W] or DVD+R[/DL]:
.B Write multi-session to the same CD, DVD-R[W] or DVD+R:
.br
cdrskin dev=/dev/hdc -v padsize=300k -multi 1.iso
cdrskin dev=/dev/hdc -v padsize=300k -multi -tao 1.iso
.br
cdrskin dev=/dev/hdc -v padsize=300k -multi 2.iso
cdrskin dev=/dev/hdc -v padsize=300k -multi -tao 2.iso
.br
cdrskin dev=/dev/hdc -v padsize=300k -multi 3.iso
cdrskin dev=/dev/hdc -v padsize=300k -multi -tao 3.iso
.br
cdrskin dev=/dev/hdc -v padsize=300k 4.iso
cdrskin dev=/dev/hdc -v padsize=300k -tao 4.iso
.SS
.B Get multi-session info for option -C of program mkisofs:
.br
@ -1246,9 +922,9 @@ c_values=$(cdrskin dev=/dev/hdc -msinfo 2>/dev/null)
.br
mkisofs ... -C "$c_values" ...
.SS
.B Inquire free space on media for a -multi run:
.B Inquire free space on media for a -tao -multi run:
.br
x=$(cdrskin dev=/dev/sr0 -multi \\
x=$(cdrskin dev=/dev/sr0 -tao -multi \\
.br
--tell_media_space 2>/dev/null)
.br
@ -1261,9 +937,6 @@ cdrskin -v dev=ATA:1,0,0 speed=48 -sao \\
track1.wav track2.au -audio -swab track3.raw
.br
.SH FILES
.SS
Startup files:
.br
If not --no_rc is given as the first argument then cdrskin attempts on
startup to read the arguments from the following files:
.PP
@ -1281,57 +954,46 @@ The files are read in the sequence given above, but none of them is
required for cdrskin to function properly. Each readable line is treated
as one single argument. No extra blanks.
A first character '#' marks a comment, empty lines are ignored.
.br
Example content of a startup file:
.SS
.B Example content of a startup file:
.br
# This is the default device
.br
dev=0,1,0
.br
# To accomodate to remnant cdrskin-0.2.2 addresses
.br
dev_translation=+1,0,0+0,1,0
.br
# Some more options
.br
fifo_start_at=0
.br
fs=16m
.br
.SS
Disabling superuser safety precautions:
The superuser is normally banned from using any other emulated drive but
/dev/null. This ban can be lifted by the existence of file
.PP
.B /root/cdrskin_permissions/allow_emulated_drives
.PP
where the directory must be owned by the superuser and must not offer
w-permissions for group or others.
.br
Warning: Superusers must take care not to spoil their hard disk via its raw
block device (like stdio:/dev/hda or stdio:/dev/sd0).
.SH SEE ALSO
.TP
Formatting data track sources for cdrskin:
.br
.BR mkisofs (8),
.BR genisoimage (8),
.BR xorriso (1),
.BR afio (1),
.BR star (1)
.br
.TP
Other CD/DVD/BD burn programs:
Other CD/DVD burn programs:
.br
.BR cdrecord (1),
.BR wodim (1),
.BR xorriso (1)
.BR wodim (1)
.br
.TP
For DVD/BD burning (also tutor of libburn's DVD/BD capabilities):
For DVD burning (also tutor of libburn's DVD capabilities):
.br
.BR growisofs (1)
.br
.SH AUTHOR
cdrskin was written by Thomas Schmitt <scdbackup@gmx.net>.
.PP
This manual page was started by George Danchev <danchev@spnet.net> and
is now maintained by Thomas Schmitt.
This manual page was written by George Danchev <danchev@spnet.net> and
Thomas Schmitt, for the Debian project and for all others.

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
<HEAD>
<META NAME="description" CONTENT="cdrskin, a limited cdrecord compatibility wrapper for libburn">
<META NAME="keywords" CONTENT="cdrskin, libburn, libburnia, burn, CD, DVD, linux, recording, burning, CD-R, CD-RW, DVD-R, DVD-RW, DVD+RW, DVD+R, DVD+R/DL, DVD-RAM, BD-RE, cdrecord, compatible, scdbackup">
<META NAME="keywords" CONTENT="cdrskin, libburn, libburnia, burn, CD, DVD, linux, recording, burning, CD-R, CD-RW, DVD-R, DVD-RW, DVD+RW, DVD+R, cdrecord, compatible, scdbackup">
<META NAME="robots" CONTENT="follow">
<TITLE>cdrskin homepage english</TITLE>
</HEAD>
@ -17,34 +17,33 @@
</A>
<P><H2> Homepage of </H2>
<H1> cdrskin </H1>
<!-- <FONT SIZE=+0><A HREF="cdrskin_ger.html">deutsch (german)</A></FONT> -->
<H2>Limited cdrecord compatibility wrapper for libburn</H2>
</CENTER>
<P>
<H2>Purpose:</H2>
Burns preformatted data to CD, DVD, and BD media:<BR>
CD-R, DVD-R, DVD+R, DVD+R/DL, CD-RW, DVD-RW, DVD-RAM, DVD+RW, BD-RE
Burns preformatted data to CD and single layer DVD media:<BR>
CD-R, DVD-R, DVD+R, CD-RW, DVD-RW, DVD-RAM, DVD+RW
</P>
<P>
<HR>
<A HREF="#download">Direct hop to download links -></A>
<P>
<H2>Hardware requirements:</H2>
A CD/DVD/BD recorder suitable for
<A HREF="http://libburnia-project.org">http://libburnia-project.org</A> <BR>
A CD/DVD recorder suitable for
<A HREF="http://libburnia.pykix.org">libburnia.pykix.org</A> <BR>
(SCSI , ATA , USB , or SATA writers compliant to standard MMC-3 for CD
and to MMC-5 for DVD or BD).
and to MMC-5 for DVD).
<BR>
</P>
<P>
<H2>Software requirements :</H2>
<DL>
<DT>Linux with kernel 2.4 or higher (and libc, of course) :</DT>
<DT>Linux kernel 2.4 or higher</DT>
<DD>With kernel 2.4 an ATA drive has to be under ide-scsi emulation.</DD>
<DD>With kernel 2.6 the drive should not be under ide-scsi.</DD>
<DT>libpthread</DT>
@ -57,10 +56,9 @@ and to MMC-5 for DVD or BD).
GPL software included:<BR>
</H2>
<DL>
<DT>libburn-0.5.4</DT>
<DD>(founded by Derek Foreman and Ben Jansens,
furthered since August 2006 by Thomas Schmitt from team of libburnia-project.org)</DD>
<DD>transfers data to CD, DVD, BD-RE</DD>
<DT>libburn-0.3.8</DT>
<DD>(by Derek Foreman, Ben Jansens, and team of libburnia.pykix.org)</DD>
<DD>transfers data to CD and DVD</DD>
</DL>
</P>
@ -85,10 +83,10 @@ Ports to other usable systems are appreciated. Reports are welcome.
<DL>
<DT>The most common options of cdrecord for data and audio on CD media
are provided in a compatible way.<BR>
On all DVD media except DVD-R DL, cdrskin is able to perform any recording job
On single layer DVD media cdrskin is able to perform any recording job
which is possible with cdrecord.
Other than with cdrecord, option -multi is supported with many DVD types and
write mode -tao works with anything but quickly blanked DVD-RW.
Other than with cdrecord, options -multi and -tao are supported with
certain DVD types.
</DT>
<BR><BR>
<DT>Get an overview of drives and their addresses</DT>
@ -106,8 +104,9 @@ as listed by option --devices.</DT>
<DD>$<KBD>&nbsp;cdrskin dev=ATA:1,0,0 -v -atip</KBD></DD>
<DD>$<KBD>&nbsp;cdrskin dev=/dev/hdc -toc</KBD></DD>
<DT>Prepare CD-RW or DVD-RW for re-use, DVD-RAM or BD-RE for first use:</DT>
<DD>$<KBD>&nbsp;cdrskin -v dev=/dev/sg1 blank=as_needed -eject</KBD></DD>
<DT>Make used CD-RW or used unformatted DVD-RW writable again:</DT>
<DD>$<KBD>&nbsp;cdrskin -v dev=/dev/sg1 blank=fast -eject</KBD></DD>
<DD>$<KBD>&nbsp;cdrskin -v dev=/dev/dvd blank=all -eject</KBD></DD>
<DT>Format DVD-RW to avoid need for blanking before re-use:</DT>
<DD>$<KBD>&nbsp;cdrskin -v dev=/dev/sr0 blank=format_overwrite</KBD></DD>
@ -118,28 +117,28 @@ as listed by option --devices.</DT>
<DT>Write ISO-9660 filesystem image as only one to blank or formatted media:
</DT>
<DD>$<KBD>&nbsp;cdrskin -v dev=/dev/hdc speed=12 fs=8m \</KBD></DD>
<DD><KBD>&nbsp;&nbsp;blank=as_needed -eject padsize=300k my_image.iso</KBD></DD>
<DD><KBD>&nbsp;&nbsp;-sao -eject padsize=300k my_image.iso</KBD></DD>
<DT>Write compressed afio archive on-the-fly:</DT>
<DD>$<KBD>&nbsp;find . | afio -oZ - | \</KBD></DD>
<DD><KBD>&nbsp;&nbsp;cdrskin -v dev=0,1,0 fs=32m speed=8 \</KBD></DD>
<DD><KBD>&nbsp;&nbsp;blank=as_needed padsize=300k -</KBD></DD>
<DD><KBD>&nbsp;&nbsp;-tao padsize=300k -</KBD></DD>
<DT>Write several sessions to the same CD, DVD-R[W] or DVD+R[/DL]:</DT>
<DD>$<KBD>&nbsp;cdrskin dev=/dev/hdc -v padsize=300k -multi 1.iso</KBD>
<DT>Write several sessions to the same CD, DVD-R[W] or DVD+R:</DT>
<DD>$<KBD>&nbsp;cdrskin dev=/dev/hdc -v padsize=300k -multi -tao 1.iso</KBD>
</DD>
<DD>$<KBD>&nbsp;cdrskin dev=/dev/hdc -v padsize=300k -multi 2.iso</KBD>
<DD>$<KBD>&nbsp;cdrskin dev=/dev/hdc -v padsize=300k -multi -tao 2.iso</KBD>
</DD>
<DD>$<KBD>&nbsp;cdrskin dev=/dev/hdc -v padsize=300k -multi 3.iso</KBD>
<DD>$<KBD>&nbsp;cdrskin dev=/dev/hdc -v padsize=300k -multi -tao 3.iso</KBD>
</DD>
<DD>$<KBD>&nbsp;cdrskin dev=/dev/hdc -v padsize=300k 4.iso</KBD></DD>
<DD>$<KBD>&nbsp;cdrskin dev=/dev/hdc -v padsize=300k -tao 4.iso</KBD></DD>
<DT>Get multi-session info for option -C of program mkisofs:</DT>
<DD>$<KBD>&nbsp;c_values=$(cdrskin dev=/dev/sr0 -msinfo 2>/dev/null)</KBD></DD>
<DD>$<KBD>&nbsp;mkisofs ... -C "$c_values" ...</KBD></DD>
<DT>Inquire free space on media for a -multi run:</DT>
<DD>$<KBD>&nbsp;x=$(cdrskin dev=/dev/sr0 -multi \</KBD></DD>
<DT>Inquire free space on media for a -tao -multi run:</DT>
<DD>$<KBD>&nbsp;x=$(cdrskin dev=/dev/sr0 -tao -multi \</KBD></DD>
<DD><KBD>&nbsp;&nbsp;--tell_media_space 2>/dev/null)</KBD></DD>
<DD>$<KBD>&nbsp;echo "Available: $x blocks of 2048 data bytes"</KBD></DD>
@ -166,54 +165,39 @@ man cdrecord</A></KBD></DD>
this "don't bother Joerg" demand.)
</DD>
</DL>
<DL>
<DT>Learn to know a more versatile way to burn ISO 9660 formatted data</DT>
<DD>
Standalone ISO 9660 multi-session CD/DVD tool
<A HREF="http://scdbackup.sourceforge.net/xorriso_eng.html">xorriso</A>.
</DD>
</DL>
Testers wanted who are willing to risk some DVD-R DL media
or to do experiments on BD-R media.
Testers wanted who are willing to risk some double layer DVD media.
</P>
<HR>
<A NAME="download"></A>
<P>
<DL>
<DT>Download as source code (see README):</DT>
<DD><A HREF="cdrskin-0.5.4.pl00.tar.gz">cdrskin-0.5.4.pl00.tar.gz</A>
(740 KB).
<DD><A HREF="cdrskin-0.3.8.pl00.tar.gz">cdrskin-0.3.8.pl00.tar.gz</A>
(615 KB).
</DD>
<DD>
The cdrskin tarballs are source code identical with libburn releases
of the same version number.
They get produced via a different procedure, though.<BR>
The "stable" cdrskin tarballs are source code identical with "stable"
libburn releases or with "stabilized" libburn SVN snapshots. They get
produced via a different procedure, though.<BR>
cdrskin is part of libburn - full libburn is provided with cdrskin releases.
</DD>
<!-- This is not offered any more since spring 2008
<DD>&nbsp;</DD>
<DT>Download as single x86 binaries (untar and move to /usr/bin/cdrskin):</DT>
<DD><A HREF="cdrskin_0.4.2.pl00-x86-suse9_0.tar.gz">
cdrskin_0.4.2.pl00-x86-suse9_0.tar.gz</A>, (110 KB),
<DD><A HREF="cdrskin_0.3.8.pl00-x86-suse9_0.tar.gz">
cdrskin_0.3.8.pl00-x86-suse9_0.tar.gz</A>, (90 KB),
<DL>
<DD>runs on SuSE 9.0 (2.4.21) , RIP-14.4 (2.6.14) ,
Gentoo (2.6.15 x86_64 Athlon).</DD>
</DL>
<DD><A HREF="cdrskin_0.4.2.pl00-x86-suse9_0-static.tar.gz">
cdrskin_0.4.2.pl00-x86-suse9_0-static.tar.gz</A>, (310 KB), -static compiled,
<DD><A HREF="cdrskin_0.3.8.pl00-x86-suse9_0-static.tar.gz">
cdrskin_0.3.8.pl00-x86-suse9_0-static.tar.gz</A>, (290 KB), -static compiled,
<DL>
<DD>runs on SuSE 7.2 (2.4.4), and on the systems above.</DD>
</DL>
</DD>
-->
</DL>
<DL><DT>Documentation:</DT>
<DD><A HREF="README_cdrskin">README</A> an introduction</DD>
@ -236,23 +220,22 @@ 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.5.2.pl00:
Enhancements towards previous stable version cdrskin-0.3.4:
<UL>
<LI>Most SCSI errors now get reported with message texts as of MMC-5</LI>
<!--
<LI>none</LI>
-->
<LI>Now able to cope with the peculiarities of Linux 2.4 USB</LI>
<LI>Refusal to perform -dummy runs on media which cannot simulate burning</LI>
<LI>Precautions against using the burner drive as track source</LI>
<LI>New option modesty_on_drive= may help with hda -> hdb burns</LI>
<LI>New option minbuf= , cdrecord compatible frontend of modesty_on_drive=</LI>
<LI>New option --adjust_speed_to_drive</LI>
</UL>
Bug fixes towards cdrskin-0.5.2.pl00:
<UL>
<LI>
dev=/dev/srN or dev=/dev/scdN on Linux 2.4 was not converted into dev=/dev/sgM
</LI>
<!--
<LI>none</LI>
-->
Bug fixes towards cdrskin-0.3.8.pl00:
<UL>
<LI>none yet</LI>
</UL>
-->
</P>
@ -260,26 +243,23 @@ dev=/dev/srN or dev=/dev/scdN on Linux 2.4 was not converted into dev=/dev/sgM
<P>
<DL>
<DT><H3>Development snapshot, version 0.5.5 :</H3></DT>
<DD>Enhancements towards current stable version 0.5.4.pl00:
<DT><H3>Development snapshot, version 0.3.9 :</H3></DT>
<DD>Enhancements towards stable version 0.3.8.pl00:
<UL>
<!--
-->
<LI>none yet</LI>
</UL>
</DD>
<DD>&nbsp;</DD>
<DD><A HREF="README_cdrskin_devel">README 0.5.5</A>
<DD><A HREF="cdrskin__help_devel">cdrskin_0.5.5 --help</A></DD>
<DD><A HREF="cdrskin_help_devel">cdrskin_0.5.5 -help</A></DD>
<DD><A HREF="man_1_cdrskin_devel.html">man cdrskin (as of 0.5.5)</A></DD>
<DD><A HREF="README_cdrskin_devel">README 0.3.9</A>
<DD><A HREF="cdrskin__help_devel">cdrskin_0.3.9 --help</A></DD>
<DD><A HREF="cdrskin_help_devel">cdrskin_0.3.9 -help</A></DD>
<DD><A HREF="man_1_cdrskin_devel.html">man cdrskin (as of 0.3.9)</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>
<DD>Download: <KBD><B>svn co http://svn.libburnia-project.org/libburn/trunk libburn</B>
<A HREF="http://libburnia.pykix.org"> libburnia.pykix.org</A></DT>
<DD>Download: <KBD><B>svn co http://libburnia-svn.pykix.org/libburn/trunk libburn_pykix</B>
</KBD></DD>
<DD>Build: <KBD><B>cd libburn ; ./bootstrap ; ./configure --prefix /usr ; make ; cdrskin/compile_cdrskin.sh</B>
<DD>Build: <KBD><B>cd libburn_pykix ; ./bootstrap ; ./configure ; make</B>
</KBD></DD>
<DD>Build of SVN versions needs <A HREF="http://sources.redhat.com/autobook/">
autotools</A> of at least version 1.7 installed.
@ -287,29 +267,22 @@ But after the run of <KBD>./bootstrap</KBD>, only
vanilla tools like make and gcc are needed.</DD>
</DD>
<DD>&nbsp;</DD>
<DT>The following download is intended for adventurous end users or
<DT>The following downloads are intended for adventurous end users or
admins with full system souvereignty.</DT>
<DD>Source (./bootstrap is already applied, build tested, for more see
<A HREF="README_cdrskin_devel">upcoming README</A> ):
</DD>
<DD>
<A HREF="cdrskin-0.5.5.tar.gz">cdrskin-0.5.5.tar.gz</A>
(740 KB).
<A HREF="cdrskin-0.3.9.tar.gz">cdrskin-0.3.9.tar.gz</A>
(615 KB).
</DD>
<!-- This is not offered any more since spring 2008
<DT>The following downloads are intended for adventurous end users or
admins with full system souvereignty.</DT>
<DD>Binary (untar and move to /usr/bin/cdrskin):</DD>
<DD><A HREF="cdrskin_0.4.3-x86-suse9_0.tar.gz">
cdrskin_0.4.3-x86-suse9_0.tar.gz</A>, (110 KB).
<DD><A HREF="cdrskin_0.3.9-x86-suse9_0.tar.gz">
cdrskin_0.3.9-x86-suse9_0.tar.gz</A>, (90 KB).
</DD>
<DD><A HREF="cdrskin_0.4.3-x86-suse9_0-static.tar.gz">
cdrskin_0.4.3-x86-suse9_0-static.tar.gz</A>, (310 KB)
<DD><A HREF="cdrskin_0.3.9-x86-suse9_0-static.tar.gz">
cdrskin_0.3.9-x86-suse9_0-static.tar.gz</A>, (290 KB)
</DD>
-->
</DL>
</P>
@ -335,33 +308,14 @@ provide libburn with invaluable examples on how to deal with DVD media.
<A NAME="examples">
<P>
<DL>
<DT>Example for a setup of device permissions.</DT>
<DT>
Newer Linux distros enable rw-access for the desktop user automatically.
So try as normal user whether all your drives are found.
CD devices which offer no rw-permission will stay invisible.
</DT>
<DD>$ <KBD><B>cdrskin --devices</B></KBD></DD>
<DT>If not all desired drives show up, become superuser and do again:</DT>
<DT>Example for a setup of device permissions. To be done by the superuser:</DT>
<DT>(CD devices which offer no rw-permission are invisible to normal users.)
</DT>
<DD># <KBD><B>cdrskin --devices</B></KBD></DD>
<DD><KBD>...</KBD></DD>
<DD><KBD>0&nbsp; dev='/dev/sr0'&nbsp; rwr-r- :&nbsp; 'TEAC' 'CD-ROM CD-532S'</KBD></DD>
<DD><KBD>0&nbsp; dev='/dev/sr0'&nbsp; rwrwr- :&nbsp; 'TEAC' 'CD-ROM CD-532S'</KBD></DD>
<DD><KBD>1&nbsp; dev='/dev/hdc'&nbsp; rwrw-- :&nbsp; 'LITE-ON' 'LTR-48125S'</KBD></DD>
<DT>Most simple and most insecure is this equivalent
of the usual cdrecord permissions u+s,a+x:</DT>
<DD># <KBD><B>chmod a+rw /dev/sr0 /dev/hdc</B></KBD></DD>
<DT>
More secure is to put the permitted users into a group like
"floppy", to assign /dev/sr0 /dev/hdc to this group,
and to allow rw-access only to group members.
</DT>
<DD># <KBD><B>vi /etc/group</B></KBD></DD>
<DD><KBD>...</KBD></DD>
<DD><KBD>floppy:x:19:thomas,scdbackup</KBD></DD>
<DD><KBD>...</KBD></DD>
<DD># <KBD><B>chgrp floppy /dev/sr0 /dev/hdc</B></KBD></DD>
<DD># <KBD><B>chmod g+rw /dev/sr0 /dev/hdc</B></KBD></DD>
</DL>
</P>
@ -376,8 +330,6 @@ Example how to setup K3b to use cdrskin for burning data CD projects.
is a GUI frontend which uses cdrecord for CD burning.)
</P>
<!--
<HR>
<A NAME="scdbackup">
@ -432,8 +384,6 @@ and try again.
</DL>
</P>
-->
<HR>
<A NAME="cdrecord">
@ -446,7 +396,7 @@ cdrecord but not vice versa.
I am a long time user of cdrecord and it works fine for me.
Especially i do appreciate its write mode -tao which allows to pipe arbitrary
data on CD and CD-RW via stdin. cdrecord is reliable, versatile and well
maintained. So for me - there would be no problem with it.
maintained. So for me - there would be not problem with it.
<BR>
But the author of cdrecord and the Linux kernel people foster a very hostile
relationship. Ok, that's their business, not mine (or ours if you are with me).
@ -493,25 +443,14 @@ and by <A HREF="http://sourceforge.net">sourceforge.net</A><BR>
<HR>
<DL>
<DT>Links to my other published software projects :
<DD><A HREF="http://scdbackup.webframe.org/xorriso_eng.html">
xorriso, a standalone ISO 9660 multi-session CD/DVD burn tool.
No mkisofs needed.
<DL>
<DD>
<A HREF="http://scdbackup.sourceforge.net/xorriso_eng.html">
(a second source of above)</A>
</DD>
</DL>
</DD>
<DD><A HREF=http://scdbackup.webframe.org/main_eng.html>
scdbackup, multi volume CD backup</A>
<DL><DD><A HREF=http://scdbackup.sourceforge.net/main_eng.html>
(a second source of above)</A></DD></DL></DD>
<DD><A HREF=http://stic.sourceforge.net>Some Tools for Image Collectors</A>
</DD>
(a second source of above)</A></DL>
<DD><A HREF=http://stic.webframe.org>Some Tools for Image Collectors</A>
<DL><DD><A HREF=http://stic.sourceforge.net>(a second source of above)</A></DL>
<DD><A HREF=http://scdbackup.webframe.org/pppoem>
pppoem, a DSL throughput monitor (mainly for Linux kernel 2.4)</A>
</DD>
</DL>
<BR><BR>
Legal statement: This website does not serve any commercial purpose.<BR>

View File

@ -1 +1 @@
#define Cdrskin_timestamP "2008.10.05.073001"
#define Cdrskin_timestamP "2007.07.20.120001"

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +1,13 @@
#!/bin/sh
# compile_cdrskin.sh
# Copyright 2005 - 2008 Thomas Schmitt, scdbackup@gmx.net, GPL version 2
# Copyright 2005 - 2006 Thomas Schmitt, scdbackup@gmx.net, GPL
# to be executed within ./libburn-* resp ./cdrskin-*
debug_opts="-O2"
debug_opts=
def_opts=
largefile_opts="-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1"
libvers="-DCdrskin_libburn_0_5_4"
libvers="-DCdrskin_libburn_0_3_8"
cleanup_src_or_obj="libburn/cleanup.o"
libdax_msgs_o="libburn/libdax_msgs.o"
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
@ -33,15 +33,15 @@ do
libdax_audioxtr_o=
libdax_msgs_o="libburn/message.o"
cleanup_src_or_obj="-DCleanup_has_no_libburn_os_H cdrskin/cleanup.c"
elif test "$i" = "-libburn_0_5_4"
elif test "$i" = "-libburn_0_3_8"
then
libvers="-DCdrskin_libburn_0_5_4"
libvers="-DCdrskin_libburn_0_3_8"
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
libdax_msgs_o="libburn/libdax_msgs.o"
cleanup_src_or_obj="libburn/cleanup.o"
elif test "$i" = "-libburn_svn"
then
libvers="-DCdrskin_libburn_0_5_5"
libvers="-DCdrskin_libburn_0_3_9"
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
libdax_msgs_o="libburn/libdax_msgs.o"
cleanup_src_or_obj="libburn/cleanup.o"
@ -68,7 +68,10 @@ do
do_strip=1
elif test "$i" = "-g"
then
debug_opts="-g"
debug_opts="$debug_opts -g"
elif test "$i" = "-O2"
then
debug_opts="$debug_opts -O2"
elif test "$i" = "-help" -o "$i" = "--help" -o "$i" = "-h"
then
echo "cdrskin/compile_cdrskin.sh : to be executed within top level directory"
@ -76,7 +79,7 @@ do
echo " -compile_cdrfifo compile program cdrskin/cdrfifo."
echo " -compile_dewav compile program test/dewav without libburn."
echo " -cvs_A60220 set macro to match libburn-CVS of 20 Feb 2006."
echo " -libburn_0_5_4 set macro to match libburn-0.5.4"
echo " -libburn_0_3_8 set macro to match libburn-0.3.8."
echo " -libburn_svn set macro to match current libburn-SVN."
echo " -no_largefile do not use 64 bit off_t (must match libburn)."
echo " -do_not_compile_cdrskin omit compilation of cdrskin/cdrskin."
@ -84,7 +87,8 @@ do
echo " -oldfashioned use pre-0.2.2 libburn features only."
echo " -do_diet produce capability reduced lean version."
echo " -do_strip apply program strip to compiled programs."
echo " -g produce debuggable programm."
echo " -g compile with cc option -g."
echo " -O2 compile with cc option -O2."
echo " -static compile with cc option -static."
exit 0
elif test "$i" = "-static"
@ -129,7 +133,6 @@ then
\
libburn/sg.o \
libburn/write.o \
libburn/read.o \
$libdax_audioxtr_o \
$libdax_msgs_o \
\

View File

@ -16,7 +16,7 @@ manpage="cdrskin"
raw_html=$(pwd)/"cdrskin/raw_man_1_cdrskin.html"
htmlpage=$(pwd)/"cdrskin/man_1_cdrskin.html"
if test -r "$man_dir"/"$manpage".1
if test -r "$manpage"
then
dummy=dummy
else
@ -45,19 +45,17 @@ then
-e 's/<b>Overview of features:<\/b>/\&nbsp;<BR><b>Overview of features:<\/b>/' \
-e 's/<b>General information paragraphs:<\/b>/\&nbsp;<BR><b>General information paragraphs:<\/b>/' \
-e 's/<b>Track recording model:<\/b>/\&nbsp;<BR><b>Track recording model:<\/b>/' \
-e 's/^In general there are two types of tracks: data and audio./\&nbsp;<BR>In general there are two types of tracks: data and audio./' \
-e 's/^While audio tracks just contain a given/\&nbsp;<BR>While audio tracks just contain a given/' \
-e 's/In general there are two types of tracks: data and audio./\&nbsp;<BR>In general there are two types of tracks: data and audio./' \
-e 's/While audio tracks just contain a given/\&nbsp;<BR>While audio tracks just contain a given/' \
-e 's/<b>Write mode selection:<\/b>/\&nbsp;<BR><b>Write mode selection:<\/b>/' \
-e 's/<b>Recordable CD Media:<\/b>/\&nbsp;<BR><b>Recordable CD Media:<\/b>/' \
-e 's/<b>Overwriteable DVD Media:<\/b>/\&nbsp;<BR><b>Overwriteable DVD Media:<\/b>/' \
-e 's/<b>Sequentially Recordable DVD Media:<\/b>/\&nbsp;<BR><b>Sequentially Recordable DVD Media:<\/b>/' \
-e 's/^The write modes for DVD+R/\&nbsp;<BR>The write modes for DVD+R/' \
-e 's/The write modes for DVD+R/\&nbsp;<BR>The write modes for DVD+R/' \
-e 's/<b>Drive preparation and addressing:<\/b>/\&nbsp;<BR><b>Drive preparation and addressing:<\/b>/' \
-e 's/^If you only got one CD capable drive/\&nbsp;<BR>If you only got one CD capable drive/' \
-e 's/<b>Emulated drives:<\/b>/\&nbsp;<BR><b>Emulated drives:<\/b>/' \
-e 's/If you only got one CD capable drive/\&nbsp;<BR>If you only got one CD capable drive/' \
-e 's/^Alphabetical list of options/\&nbsp;<BR>Alphabetical list of options/' \
-e 's/<\/body>/<BR><HR><FONT SIZE=-1><CENTER>(HTML generated from '"$manpage"'.1 on '"$(date)"' by '$(basename "$0")' )<\/CENTER><\/FONT><\/body>/' \
-e 's/See section FILES/See section <A HREF="#FILES">FILES<\/A>/' \
-e 's/and for all others\.<\/td><\/table>/and for all others.<\/td><\/table> <BR><HR><FONT SIZE=-1><CENTER>(HTML generated from '"$manpage"'.1 on '"$(date)"' by '$(basename "$0")' )<\/CENTER><\/FONT>/' \
-e 's/See section EXAMPLES/See section <A HREF="#EXAMPLES">EXAMPLES<\/A>/' \
<"$2" >"$htmlpage"

View File

@ -8,22 +8,23 @@
Its paragon, cdrecord, is a powerful GPL'ed burn program included in Joerg
Schilling's cdrtools. cdrskin strives to be a second source for the services
traditionally provided by cdrecord. Currently it does CD-R and CD-RW this way.
Overwriteable media DVD-RAM, DVD+RW, DVD-RW, and BD-RE are handled differently
than with cdrecord-ProDVD in order to offer TAO-like single track recording.
Sequential DVD-R[W], DVD+R, DVD+R DL are handled like CD-R[W] with TAO and
Overwriteable media DVD-RAM, DVD+RW and DVD-RW are handled differently than
with cdrecord-ProDVD in order to offer TAO-like single track recording.
Sequential DVD-R[W] and DVD+R are handled like CD-R[W] with TAO and
multi-session. Additionally cdrskin offers cdrecord-ProDVD-like mode DAO
with DVD-R[W].
cdrskin does not contain any bytes copied from cdrecord's sources.
Many bytes have been copied from the message output of cdrecord
runs, though. The most comprehensive technical overview of cdrskin
can be found in [http://libburnia-project.org/browser/libburn/trunk/cdrskin/README?format=txt cdrskin/README].
can be found in [http://libburnia.pykix.org/browser/libburn/trunk/cdrskin/README?format=txt cdrskin/README].
About libburn API for burning CD and DVD: http://api.libburnia-project.org
About libburn API for burning CD: http://libburnia-api.pykix.org
--------------------------------------------------------------------------
For yet unsupported media types see the advice to use dvd+rw-tools at
For dual layer DVD types and for appending sessions to ISO filesystems on
DVD other than DVD-RW, DVD-R, DVD+R see the advise to use dvd+rw-tools at
the end of this text.
--------------------------------------------------------------------------
@ -79,58 +80,12 @@ controls drive accessability by rw-permissions of the drive rather than
by x-permission of the burn binary. To be usable with cdrskin, the drive
has to offer both, r- and w-permission.
--------------------------------------------------------------------------
blank=as_needed applies the suitable blanking or formatting to make
any supported type of media ready for writing from scratch.
If this is not possible, e.g. because the media is written and not
re-usable, then the program run fails.
Option blank= offers several specialized blanking and formatting types,
which one may use for particular purposes on DVD-RW, DVD-RAM and BD-RE.
(See also below: blank=format_overwrite)
The drive offers a list of possible formats by cdrskin option --list_formats.
One should aquire MMC background information before making use of them.
--------------------------------------------------------------------------
cdrskin does not only read from and write to optical drives which comply
to the MMC standard but also does the same with regular files or block
devices other than optical drives.
Because the power to alter a disk file might be a bad surprise for a
traditional user of cdrecord, it is necessary to give option
--allow_emulated_drives before an emulated drive may be addressed.
Eventually one of the startup files would be a good place for it.
See man page, section FILES.
The addresses of emulated drives begin with the prefix "stdio:".
{{{
dev=stdio:/tmp/pseudo_drive
dev=stdio:/dev/usbstick
}}}
Regular files and block devices behave much like DVD-RAM.
Other file types may be valid targets for write-only operations.
This includes standard output, named pipes, character devices
{{{
dev=stdio:/dev/fd/1
dev=stdio:/tmp/named_pipe
dev=stdio:/dev/ptyxy
}}}
These files behave much like blank DVD-R.
All files used as pseudo-drives have to offer rw-permission.
--------------------------------------------------------------------------
The DVD capabilities of cdrskin differ from those of cdrecord-ProDVD. cdrskin
offers TAO-like multi-session with DVD-R[W], DVD+R[ DL] and TAO-like single
session with overwriteable DVD media. It also offers DAO on DVD-R[W] which is
probably the same as the traditional cdrecord-ProDVD write mode.
offers TAO-like multi-session with DVD-R[W], DVD+R and TAO-like single session
with overwriteable DVD media. It also offers DAO on DVD-R[W] which is probably
the same as the traditional cdrecord-ProDVD write mode.
Non-cdrecord blank mode blank=format_overwrite brings a DVD-RW
disc from its initial profile "Sequential Recording" into profile state
@ -139,9 +94,9 @@ disc from its initial profile "Sequential Recording" into profile state
cdrskin dev=/dev/sr0 -v blank=format_overwrite
}}}
DVD-RAM, DVD+RW, BD-RE and overwriteable DVD-RW appear to cdrskin as blank
media which are capable of taking only a single track. This track may be
positioned on a 32KiB aligned address, though.
DVD-RAM, DVD+RW and overwriteable DVD-RW appear to cdrskin as blank media
which are capable of taking only a single track. This track may be positioned
on a 32KiB aligned address, though.
{{{
cdrskin ... write_start_address=2412m ...
}}}
@ -152,9 +107,8 @@ multi-session, if the drive is capable of "Incremental Streaming"
(MMC feature 21h).
Used sequential DVD-RW media may be blanked by blank=fast or blank=all which
normally both do full blanking. Thus sequential DVD-RW behave much like large
CD-RW with possibly more than 99 tracks.
normally both do full blanking.
blank=deformat_sequential does minimal blanking of DVD-RW which usually yields
media incapable of "Incremental Streaming".
@ -163,13 +117,6 @@ overwriteable DVD-RW which normally ignore those two options. It also makes
option -multi tolerable with media and write modes which are not suitable for
multi-session. (The default behavior of cdrskin deems me to be preferrable.)
Option --grow_overwriteable_iso gives cdrskin ISO pseudo-multi-session
capabilities on DVD-RAM, DVD+RW, BD-RE similar to growisofs.
Associated options blank=, -multi, -msinfo and -toc are available in this case.
They either pretend a blank media (if there is no ISO 9660 image) or appendable
media with a single session and track on it. blank= invalidates ISO images.
--------------------------------------------------------------------------
assert_write_lba=<lba> allows to ensure that the start block address which
@ -281,10 +228,10 @@ for an illustrated example with K3b 0.10 .
DVD advise:
For burning of DVD/BD media other than DVD-RAM, DVD+RW, DVD+R, DVD+R DL,
DVD-RW, DVD-R, BD-RE, the cdrskin project currently advises to use
Andy Polyakov's dvd+rw-tools which despite their historic name are
capable of all the media above and more, including BD discs.
For burning of DVD media other than DVD-RAM, DVD+RW, DVD+R, DVD-RW, DVD-R,
the cdrskin project currently advises to use Andy Polyakov's dvd+rw-tools
which despite their historic name are capable of all the media above
and also do dual layer and even BD discs.
http://fy.chalmers.se/~appro/linux/DVD+RW/tools
@ -292,27 +239,19 @@ They are not compatible or related to cdrecord resp. cdrecord-ProDVD
(now obsoleted by original source cdrtools cdrecord with identical
capabilities besides the license key).
--------------------------------------------------------------------------
Advanced multi-session use cases:
A special feature of dvd+rw-tools is growing of ISO-9660 filesystems on
overwriteable media. This is not the same as multi-session writing of cdrskin
with CD media, but retrieves additional information from the existing ISO
image and finally manipulates the start sectors of this existing image.
So for growable ISO filesystems on DVD-RAM or DVD+RW growisofs is the only
choice, currently.
So, inspired by growisofs, cdrskin can offer DVD multi-session not only with
sequential DVD-R[W] and with DVD+R [DL], but also with DVD-RAM, DVD+RW, BD-RE
and even regular disk files or block devices other than CD/DVD writers.
This is enabled by option --grow_overwriteable_iso.
The libburnia project provides an integrated ISO-9660 multi-session tool
named [wiki:Xorriso xorriso] which tries to go one step beyond
growisofs. It uses [wiki:Libburn libburn] , [wiki:Libisofs libisofs]
and [wiki:Libisoburn libisoburn].
See [http://scdbackup.sourceforge.net/man_1_xorriso.html man xorriso].
cdrskin can offer DVD multi-session only with sequential DVD-R[W] and with
DVD+R.
Associated options blank=, -multi, -msinfo and -toc are available in this case.
Thus sequential DVD-RW behave much like large CD-RW with possibly more than 99
tracks.
--------------------------------------------------------------------------

View File

@ -1,4 +1,4 @@
AC_INIT([libburn], [0.5.4], [http://libburnia-project.org])
AC_INIT([libburn], [0.3.8], [http://libburnia.pykix.org])
AC_PREREQ([2.50])
dnl AC_CONFIG_HEADER([config.h])
@ -7,110 +7,35 @@ AC_CANONICAL_TARGET
AM_INIT_AUTOMAKE([subdir-objects])
dnl Notes by ts A71207 - A80126 :
dnl Making releases:
dnl BURN_MICRO_VERSION += 1;
dnl BURN_INTERFACE_AGE += 1;
dnl BURN_BINARY_AGE += 1;
dnl if any functions have been added, set BURN_INTERFACE_AGE to 0.
dnl if backwards compatibility has been broken,
dnl set BURN_BINARY_AGE and BURN_INTERFACE_AGE to 0.
dnl
dnl Regrettably the meaning of the various version types was misunderstood
dnl before version 0.4.1.
dnl if MAJOR or MINOR version changes, be sure to change AC_INIT above to match
dnl
dnl In the past MAJOR.MINOR.MICRO versions led to the following SONAME numbers:
dnl 0.2.2 = 2 , 0.2.3 = 3 , 0.2.6 = 6
dnl 0.3.0 = 0 , 0.3.2 = 2 , 0.3.4 = 4 . 0.3.6 = 6 , 0.3.8 = 4
dnl 0.4.0 = 0 (also released as SONAME 4)
dnl
dnl Meanwhile the following schemes are maintained in parallel:
dnl
dnl BURN_MAJOR_VERSION , BURN_MINOR_VERSION , BURN_MICRO_VERSION
dnl are three small non-negative integers which describe the evolution
dnl steps of the library.
dnl Older applications are able to use younger libraries over
dnl quite a long range of such steps. Some day, nevertheless,
dnl compatibility might get terminated, after due notice.
dnl
dnl SONAME (libburn.so.4)
dnl is a small positive integer which marks a family of compatible
dnl evolution steps. Libraries with a particular SONAME allow a binary
dnl with the same SONAME to start up. Any further compatibility check is to
dnl be done by own runtime means. Especially *_version() calls in the API
dnl which return BURN_MAJOR_VERSION, BURN_MINOR_VERSION, BURN_MICRO_VERSION.
dnl See below.
dnl
dnl CURRENT, AGE, REVISION
dnl are three integers used by libtool. CURRENT is positive, the others
dnl non-negative. The use at runtime is not known yet. But libtool computes
dnl at build time SONAME = CURRENT - AGE.
dnl So this is a superspace of the SONAME version space. To avoid
dnl ill SONAME, the value of CURRENT must be larger than AGE.
dnl See also http://www.gnu.org/software/libtool/manual.html#Interfaces
dnl
dnl The name of the dynamic library will be libburn.so.$SONAME.$AGE.$REV .
dnl In the terminology of this file:
dnl CURRENT = LT_CURRENT
dnl AGE = LT_AGE
dnl REVISION= LT_REVISION
dnl
dnl Beginning with libburn-0.4.1 a rectified counting was introduced as
dnl CURRENT=10, REVISION=1, AGE=6
dnl This rectification declared that version to be binary compatible up
dnl from libburn-0.3.4.
dnl Real compatibility was given since libburn-0.3.2.
dnl Beware of libburn-0.2.6 which had SONAME=6 and is not binary compatible.
dnl Applications for libburn-0.2 to libburn-0.3.1 need recompilation but no
dnl source code changes.
dnl
dnl Neatly versioned stable releases meanwhile:
dnl 0.4.2 = libburn.so.4.7.0
dnl 0.4.4 = libburn.so.4.9.0
dnl 0.4.6 = libburn.so.4.11.0
dnl 0.4.8 = libburn.so.4.13.0
dnl 0.5.0 = libburn.so.4.15.0
dnl 0.5.2 = libburn.so.4.17.0
dnl 0.5.4 = libburn.so.4.19.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.
dnl The linker will do no finer checks. Especially no age range check for
dnl the application binary. If SONAME matches, then the couple starts.
dnl
dnl Therefore at run time info is provided by libburn function burn_version().
dnl It returns the major, minor and micro revision of the library.
dnl Before using any API feature, a program should check for age.
dnl
dnl The variables BURN_*_VERSION are mere copies for informing libtool.
dnl The true values which get issued and should be compared are macros
dnl defined in libburn/libburn.h .
dnl
dnl Normally one can allow a program to run with a library which passed the
dnl linker SONAME test and which is not older than the library it was
dnl developed for. Library2 is younger than library1 if:
dnl major2>major1 || (major2==major1 &&
dnl (minor2>minor1 || (minor2==minor1 && micro2 > micro1)))
dnl
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=5
BURN_MICRO_VERSION=4
BURN_MINOR_VERSION=3
BURN_MICRO_VERSION=8
BURN_INTERFACE_AGE=0
BURN_BINARY_AGE=0
BURN_VERSION=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION.$BURN_MICRO_VERSION
AC_SUBST(BURN_MAJOR_VERSION)
AC_SUBST(BURN_MINOR_VERSION)
AC_SUBST(BURN_MICRO_VERSION)
AC_SUBST(BURN_INTERFACE_AGE)
AC_SUBST(BURN_BINARY_AGE)
AC_SUBST(BURN_VERSION)
dnl Libtool versioning
LT_RELEASE=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION.$BURN_MICRO_VERSION
dnl
dnl ts A80820
dnl ### This is the release version libburn-0.5.2 = libburn.so.4.17.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
dnl SONAME = 23 - 19 = 4 . Library name = libburn.so.4.19.0
LT_CURRENT=23
LT_AGE=19
LT_REVISION=0
LT_RELEASE=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION
LT_CURRENT=4
LT_REVISION=$BURN_INTERFACE_AGE
LT_AGE=`expr $BURN_BINARY_AGE - $BURN_INTERFACE_AGE`
LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE`
AC_SUBST(LT_RELEASE)
@ -119,12 +44,6 @@ AC_SUBST(LT_REVISION)
AC_SUBST(LT_AGE)
AC_SUBST(LT_CURRENT_MINUS_AGE)
dnl ts A71207: This is done only not to break any old components
BURN_INTERFACE_AGE=$LT_REVISION
BURN_BINARY_AGE=`expr $LT_AGE + $BURN_INTERFACE_AGE`
AC_SUBST(BURN_INTERFACE_AGE)
AC_SUBST(BURN_BINARY_AGE)
AC_PREFIX_DEFAULT([/usr/local])
test "$prefix" = "NONE" && prefix=$ac_default_prefix

View File

@ -7,12 +7,10 @@
Libburnia is an open-source project for reading, mastering and writing
optical discs.
For now this means CD-R, CD-RW, DVD-RAM, DVD+RW, DVD+R, DVD+R/DL, DVD-RW,
DVD-R, BD-RE.
For now this means CD-R, CD-RW, DVD-RAM, DVD+RW, DVD+R, DVD-RW, DVD-R.
Not supported yet are DVD-R/DL, HD-DVD, BD-R (blue ray). Testers for
DVD-R/DL are wanted, though. BD-R programming efforts would be made
if an interested tester contacts us.
Not supported yet are dual layer media, HD-DVD, BD (blue ray). Testers for
dual layer DVD+/-R are wanted, though.
The project comprises of several more or less interdependent parts which
together strive to be a usable foundation for application development.
@ -24,18 +22,13 @@ we would need : login on a development machine resp. a live OS on CD or DVD,
advise from a system person about the equivalent of Linux sg or FreeBSD CAM,
volunteers for testing of realistic use cases.
We have a well tested code base for burning data and audio CDs and many DVD
types. The burn API is quite comprehensively documented and can be used to
build a presentable application.
We have a workable code base for burning data and audio CDs and many DVD types.
The burn API is quite comprehensively documented and can be used to build a
presentable application.
We have a functional binary which emulates the core use cases of cdrecord in
order to prove that usability, and in order to allow you to explore libburn's
scope by help of existing cdrecord frontends.
ISO 9660 filesystems with Rock Ridge and Joliet extensions can be created
and manipulated quite freely. This capability together with our burn capability
makes possible a single binary application which covers all steps of image
composition, updating and writing. Quite unique in the Linux world.
@subsection components The project components (list subject to growth, hopefully):
- libburn is the library by which preformatted data get onto optical media.
@ -50,48 +43,24 @@ composition, updating and writing. Quite unique in the Linux world.
ISO 9660 disk image. This may then be brought to CD via libburn.
libisofs is to be the foundation of our upcoming mkisofs emulation.
- libisoburn is an add-on to libburn and libisofs which coordinates both and
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.
- cdrskin is a limited cdrecord compatibility wrapper for libburn.
cdrecord is a powerful GPL'ed burn program included in Joerg
Schilling's cdrtools. cdrskin strives to be a second source for
the services traditionally provided by cdrecord. Additionally it
provides libburn's DVD/BD capabilities, where only -sao is
compatible with cdrecord.
provides libburn's DVD capabilities, where only -sao is compatible
with cdrecord.
cdrskin does not contain any bytes copied from cdrecord's sources.
Many bytes have been copied from the message output of cdrecord
runs, though.
See cdrskin/README for more.
- xorriso is an application of all three libraries which creates, loads,
manipulates and writes ISO 9660 filesystem images with
Rock Ridge extensions. Manipulation is not only adding or
overwriting of files but also deletion, renaming, and attribute
changing. An incremental backup feature is provided.
See xorriso/README for more
- "test" is a collection of application gestures and examples given by the
authors of the library features. The burn API example of libburn
is named test/libburner.c . The API for media information inquiry is
demonstrated in test/telltoc.c .
Explore these examples if you look for inspiration.
We strive to be a responsive upstream.
Our libraries are committed to maintain older feature sets in newer versions.
This applies to source code headers (API) as well as to linkable objects (ABI).
The only exception from this rule is about non-release versions x.y.*[13579]
which are allowed to introduce new features, change those new features in
any way and even may revoke such new features before the next release of
x.y.*[02468]. As soon as it is released, a feature is promised to persist.
SONAMES:
libburn.so.4 (since 0.3.4, March 2007),
libisofs.so.6 (since 0.6.2, February 2008),
libisoburn.so.1 (since 0.1.0, February 2008).
We plan to be a responsive upstream. Bear with us.
@section using Using the libraries
@ -120,7 +89,7 @@ languages and development tools.
@section libburner Libburner
libburner is a minimal demo application for the library libburn
(see: libburn/libburn.h) as provided on http://libburnia-project.org .
(see: libburn/libburn.h) as provided on http://libburn.pykix.org .
It can list the available devices, can blank a CD-RW or DVD-RW and
can burn to recordable CD and recordable single layer DVD.

View File

@ -1,11 +1,11 @@
libburnia-project.org Optical Media Rotisserie Recipes as of April 2008
libburnia.pykix.org Optical Media Rotisserie Recipes as of February 2007
Content:
- TAO Multi-Session CD Cookbook (CD-R, CD-RW)
- SAO CD Cookbook (CD-R, CD-RW, pure audio or pure data only)
- Overwriteable DVD Cookbook (DVD-RAM, DVD+RW, DVD-RW, BD-RE)
- Overwriteable DVD Cookbook (DVD-RAM, DVD+RW, DVD-RW)
- Sequential DVD-R[W] Cookbook
- DVD+R[/DL] Cookbook
- DVD+R Cookbook
-------------------------------------------------------------------------------
TAO Multi-Session CD Cookbook
@ -18,7 +18,7 @@ by reading libburn/* from http://icculus.org/burn
and by experiments with drives NEC ND-4570A, LG GSA-4082B, LITE-ON LTR48125S
which used in part code from http://icculus.org/burn.
For libburnia-project.org by Thomas Schmitt <scdbackup@gmx.net>
For libburnia.pykix.org by Thomas Schmitt <scdbackup@gmx.net>
-------------------------------------------------------------------------------
@ -215,7 +215,7 @@ backed by reading mmc5r03c.pdf from http://www.t10.org/ftp/t10/drafts/mmc5/
and by experiments with drives NEC ND-4570A, LG GSA-4082B, LITE-ON LTR48125S
which used in part code from http://icculus.org/burn.
For libburnia-project.org by Thomas Schmitt <scdbackup@gmx.net>
For libburnia.pykix.org by Thomas Schmitt <scdbackup@gmx.net>
-------------------------------------------------------------------------------
@ -403,10 +403,9 @@ correctness of Pre-gap and Post-gap would become evident.
-------------------------------------------------------------------------------
Inspired by Andy Polyakov's http://fy.chalmers.se/~appro/linux/DVD+RW/tools ,
backed by reading mmc5r03c.pdf from http://www.t10.org/ftp/t10/drafts/mmc5/
by own experiments with drives NEC ND-4570A, LG GSA-4082B, PHILIPS SPD3300L,
and by BD-RE experiments done by Giulio Orsero on LG BE06LU10.
and by experiments with drives NEC ND-4570A and LG GSA-4082B.
For libburnia-project.org by Thomas Schmitt <scdbackup@gmx.net>
For libburnia.pykix.org by Thomas Schmitt <scdbackup@gmx.net>
-------------------------------------------------------------------------------
@ -417,24 +416,18 @@ DVD-RAM 0012h
DVD-RW Restricted Overwrite 0013h
DVD-RW Sequential Recording 0014h (i.e. unformatted)
DVD+RW 001Ah
BD-RE 0043h
A short compilation of the write model:
- Overwriting in general
The recipes described here are depending on formatting state:
- DVD-RAM, fully formatted DVD+RW, DVD-RW, BD-RE
- DVD-RAM, fully formatted DVD+RW or DVD-RW
- Unformatted DVD+RW
- Partly formatted DVD+RW
- Unformatted DVD-RW
- Partly formatted DVD-RW
- Intermediate state DVD-RW
- DVD-RAM and BD-RE formatting
- DVD-RAM and BD-RE speed tuning
Slightly off topic are
- ISO 9660 multi-session emulation on overwriteable media
- ISO 9660 based TOC emulation on overwriteable media
-------------------------------------------------------------------------------
Overwriting in general :
@ -451,7 +444,7 @@ Optimal performance is promised without any speed setting. But my experiments
showed that SET STREAMING values persist after media change.
In the formatted area of the media, coarse random access is possible.
For DVD-RAM, DVD+RW, BD-RE write addresses and data size need to be aligned
For DVD-RAM and DVD+RW write addresses and data size need to be aligned
to 2 KiB. For DVD-RW alignment has to be 32 KiB. Within these limitations
the write address is at the discretion of the sending program.
Just use 2Ah WRITE to send data.
@ -490,12 +483,9 @@ software did anything wrong.
-------------------------------------------------------------------------------
DVD-RAM, fully formatted DVD+RW, DVD-RW, BD-RE :
DVD-RAM, fully formatted DVD+RW or DVD-RW :
Full format is the natural state of DVD-RAM.
BD-RE are sold unformatted and need to be fully formatted first.
See paragraph about DVD-RAM and BD-RE formatting below.
Full format is the natural state of DVD-RAM.
DVD+RW reaches this state if Background Formatting is allowed to finish without
being stopped by 5Bh CLOSE TRACK SESSION.
@ -526,7 +516,7 @@ with Close Function 010b despite there is no session open in this scenario.)
-------------------------------------------------------------------------------
Unformatted DVD+RW :
Unformatted DVD+RW
This is the state of previously unused DVD+RW media.
@ -681,161 +671,6 @@ of Intermediate state by 5Bh CLOSE TRACK SESSION with Close Function 010b.
(mmc5r03c.pdf 6.3.3.2.3)
-------------------------------------------------------------------------------
DVD-RAM and BD-RE formatting :
Although DVD-RAM usually are sold formatted, there may still arise the wish
to adjust formatting.
BD-RE are sold unformatted and need to be formatted prior to usage.
Two format types are relevant for DVD-RAM : 00h and 01h.
00h offers the default size format and usually a maximum payload size format.
Even with that maximum size payload there is hardware defect management.
(mmc5r03c.pdf 6.5.4.2.1.2)
01h allows to convert payload capacity into spare blocks for defect
managment. There is no way to increase payload capacity by format 01h.
(mmc5r03c.pdf 6.5.4.2.2.1)
With BD-RE there are three format types : 00h, 30h and 31h.
00h offers the default size format.
30h offers several sizes with defect management. Usually there are three
size to choose: #1: default size, #2: maximum spare area, #3: minimal spare.
31h offers a single size and disables defect management. This has the side
effect to speed up writing to nominal speed.
(mmc5r03c.pdf 6.5.4.2.15, 6.24.3.3, Table 472)
Only format sizes from the list of format descriptors are permissible
for DVD-RAM. The format list can be obtained by 23h READ FORMAT CAPACITIES.
It also includes a description of the current formatting state.
(mmc5r03c.pdf 6.24, 6.24.3.2, 6.24.3.3)
Formatting is done by command 04h FORMAT UNIT. Its data payload consists
of a Format List Header and a Format Descriptor. It is advisable to set
the Immed bit and the FOV bit in header byte number 1. The descriptor should
be a copy of a descriptor from 23h READ FORMAT CAPACITIES.
(mmc5r03c.pdf 6.5, 6.5.3.2, 6.5.3.3)
With nearly all formats Sub-type should be set to 0. But with BD-RE formats
30h and 31h the Sub-type selects the certification mode.
Usable with 30h seem 10b Full Certification and 11b Quick Certification.
Usable with 31h seem also 00b Quick Reformat and 01b No Certification.
(mmc5r03c.pdf 6.5.4.2.15.1)
Other format types have their certification intensity controlled by
a pair of bits: CmpList and DCRT.
CmpList resides in CDB byte 1 as bit 3. DCRT resides in the payload byte 1
as bit 5. Both together should request a quick size change without lengthy
certification but maintaining the list of known defects.
(mmc5r03c.pdf 6.5, table 249, 6.5.3.2)
With DVD-RAM on my PHILIPS SPD3300L drive they prevent any format size
change though. The TSSTcorp SH-S203B works properly.
With BD-RE format 00h, the default is specified to be Quick Reformat,
and with 00h in general certification can only be disabled not enabled.
(mmc5r03c.pdf 6.5.4.2.1.7)
-------------------------------------------------------------------------------
DVD-RAM and BD-RE tuning :
A special aspect of DVD-RAM and BD-RE is their low speed with write operations,
which usually is only half than the nominal speed of media and drive.
This is blamed to the automatic checkreading which happens ifor managing
eventual defects.
Defect management of BD-RE can be disabled by format type 31h. See above.
There is no drive known yet which would apply command 2Ah WRITE10 to DVD-RAM
with full speed.
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 ione has to write write full 64 kB buffers.
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
to these defective addresses.
(mmc5r03c.pdf 4.8.5)
So the speed-up is only advisable as long as the media are free of
incorrectable errors.
Caveat:
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 0043 promises the existence of
AAh WRITE12.
Nevertheless it worked on all tested drives is proper alignment was observed.
(mmc5r03c.pdf 5.4.13, 6.45)
-------------------------------------------------------------------------------
ISO 9660 multi-session emulation on overwriteable media :
Overwriteable media provide a single overwriteable track which may grow up to
the full media capacity. There is no builtin table-of-content which records
the history of write sessions.
mount -t iso9660 will use sbsector=0 as default.
The term "superblock" shall depict the first 64 KiB after the sbsector address.
ISO 9660 multi-session depends on typical TOC information in two ways:
It needs the superblock address MSC1 of the most recently recorded session and
it needs the Next Writeable Address NWA for which to prepare the adress offset.
The following is learned from growisofs and from ECMA-119:
http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-119.pdf
ISO 9660 filesystems provide information about the number of sectors which
is also the lowest unused block address and thus a suitable NWA.
This block address is stored in the Primary Volume Descriptor which is supposed
to be stored in block 16 (eventually relative to MSC1).
The bytes 0 to 5 of a PVD block are
0x01 'C' 'D' '0' '0' '1'
The sector count can then be read from byte 80 to 83
sectors= pvd[80] | (pvd[81] << 8) | (pvd[82] << 16) | (pvd[83] << 24);
To support CD, DVD and BD media alike, it is advisable to round the NWA
to the next multiple of 32 (= 64 KiB).
(Ecma-119.pdf 8.4)
So one can use 0 as MSC1 and prepare a new ISO session for the computed NWA.
After writing the session it is necessary to patch the PVD at LBA 16.
The minimal change would be to update the number of image sectors.
It is stored in both notations LSB and MSB:
for(i= 0; i < 4; i++)
pvd[87 - i]= pvd[80 + i]= (sectors >> (8 * i)) & 0xff;
cdrskin --grow_overwriteable not only patches the sector fields of the
PVD block but also the blocks up to LBA 31 which begin with
0xff 'C' 'D' '0' '0' '1'
libisoburn submits 64 KiB data buffer to libisofs before image generation and
afterwards writes these 64 KiB as new superblock to LBA 0.
-------------------------------------------------------------------------------
ISO 9660 based TOC emulation on overwriteable media :
Above method of multi-session emulation yields a single session image after
each add-on session. No reliable session history can be read because the
sector size of the existing session gets overwritten by the new one.
A TOC with session history is nevertheless desirable with incremental backups
in order to access older backup states by mounting older superblocks at the
start addresses of older sessions.
All usual ISO 9660 formatter programs write a complete superblock to the
start of each session.
With a uniform NWA rounding rule it is possible to compute the address of
superblock N+1 as the NWA after session N. The only problem is N=1
because it gets overwritten by later sessions.
libisoburn preserves the information of session 1 by writing the first session
to LBA 32 rather than LBA 0. Afterwards it writes the overall superblock to
LBA 0 (up to 31).
So with all further add-on sessions the superblock at LBA 0 will enclose the
overall image, while the superblocks of the sessions form a chain beginning
at LBA 32. Each session superblock points to the next one by its sector count
rounded up to 32. The chain end is marked by the overall image size.
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).
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
@ -845,7 +680,7 @@ Inspired by Andy Polyakov's http://fy.chalmers.se/~appro/linux/DVD+RW/tools ,
backed by reading mmc5r03c.pdf from http://www.t10.org/ftp/t10/drafts/mmc5/
and by experiments with drives NEC ND-4570A and LG GSA-4082B.
For libburnia-project.org by Thomas Schmitt <scdbackup@gmx.net>
For libburnia.pykix.org by Thomas Schmitt <scdbackup@gmx.net>
-------------------------------------------------------------------------------
@ -1155,12 +990,15 @@ close session if multi-session is demanded.
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
DVD+R[/DL] Cookbook
INCOMPLETE YET
DVD+R Cookbook
-------------------------------------------------------------------------------
Inspired by reading mmc5r03c.pdf from http://www.t10.org/ftp/t10/drafts/mmc5/
backed by Andy Polyakov's http://fy.chalmers.se/~appro/linux/DVD+RW/tools ,
For libburnia-project.org by Thomas Schmitt <scdbackup@gmx.net>
For libburnia.pykix.org by Thomas Schmitt <scdbackup@gmx.net>
-------------------------------------------------------------------------------
@ -1171,7 +1009,7 @@ DVD+R/DL 002bh
- About empty, appendable and finalized DVD+R
- Writing a Pseudo Session to DVD+R
- DVD+R/DL (Dual Layer
- >>> Hearsay about DVD+R/DL (Dual Layer) :
The following two chapters of the Sequential DVD-R[W] Cookbook are valid for
DVD+R media too:
@ -1250,26 +1088,13 @@ closed by Close Function 101b rather than 010b. This finalizes the media
"with minimal radius".
(mmc5r03c.pdf 6.3.3.4.4)
Note: growisofs has code for that gesture but explicitly avoids to use it, if
the media was appendable before writing began. Instead it recommends to fill
up the media with zeros. This gesture nevertheless caused error replies from
the drives in my own experiments.
The reason given by Andy Polyakov is that some DVD-ROM drives get mislead by
the lead-out information of (formerly) appendable media unless the media is
fully written.
(http://fy.chalmers.se/~appro/linux/DVD+RW/ , "Compatibility: caveat lector")
Own experiments showed no such problems with PC attached PATA DVD-ROM drives.
For best DVD-ROM compatibility one should avoid appendable media at all
by closing them already after the first session.
Note: growisofs has code for that gesture but explicitly avoids to use it.
Instead it recommends to fill up the media with zeros.
-------------------------------------------------------------------------------
DVD+R/DL (Dual Layer) :
Hearsay about DVD+R/DL (Dual Layer) :
libburn treats DL media just like their single layer equivalents.
This seems to work fine for DVD+R/DL, according to a report by nightmorph
in http://libburnia-project.org/ticket/13 .
>>>
-------------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@ libdir=@libdir@
includedir=@includedir@
Name: libburn
Description: Library to read/write optical discs
Description: Disc reading/writing library
Version: @VERSION@
Requires:
Libs: -L${libdir} -lburn

View File

@ -1,25 +1,5 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* ts A71019 */
/* Standard measure should be: Threads are created detached.
According to the man pages they should then care for disposing themselves.
>>> ??? It is yet unclear why the threads vanish from the process list
even if joinable and even if never joined.
To be activated after release of libburn-0.4.0
*/
#define Libburn_create_detached_threadS 1
/* Alternative : Threads are created joinable.
Threads get detached in remove_worker() and thus should dispose themselves.
#define Libburn_detach_done_workeR 1
*/
#include "libburn.h"
#include "transport.h"
#include "drive.h"
@ -27,12 +7,9 @@
#include "options.h"
#include "async.h"
#include "init.h"
#include "file.h"
#include "back_hacks.h"
#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@ -43,15 +20,7 @@
#include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger;
/* ts A80714 : introduced type codes for the worker list */
#define Burnworker_type_scaN 0
#define Burnworker_type_erasE 1
#define Burnworker_type_formaT 2
#define Burnworker_type_writE 3
#define Burnworker_type_fifO 4
#define SCAN_GOING() (workers != NULL && \
workers->w_type == Burnworker_type_scaN)
#define SCAN_GOING() (workers && !workers->drive)
typedef void *(*WorkerFunc) (void *);
@ -84,18 +53,9 @@ struct write_opts
struct burn_disc *disc;
};
struct fifo_opts
{
struct burn_source *source;
int flag;
};
struct w_list
{
/* ts A80714 */
int w_type; /* see above define Burnworker_type_* */
struct burn_drive *drive;
pthread_t thread;
@ -107,12 +67,10 @@ struct w_list
struct erase_opts erase;
struct format_opts format;
struct write_opts write;
struct fifo_opts fifo;
} u;
};
static struct w_list *workers = NULL;
static struct w_list *workers;
static struct w_list *find_worker(struct burn_drive *d)
{
@ -124,19 +82,12 @@ static struct w_list *find_worker(struct burn_drive *d)
return NULL;
}
static void add_worker(int w_type, struct burn_drive *d,
WorkerFunc f, void *data)
static void add_worker(struct burn_drive *d, WorkerFunc f, void *data)
{
struct w_list *a;
struct w_list *tmp;
pthread_attr_t *attr_pt = NULL;
#ifdef Libburn_create_detached_threadS
pthread_attr_t attr;
#endif
a = malloc(sizeof(struct w_list));
a->w_type = w_type;
a->drive = d;
a->u = *(union w_list_data *)data;
@ -145,65 +96,26 @@ static void add_worker(int w_type, struct burn_drive *d,
tmp = workers;
workers = a;
if (d != NULL)
if (d)
d->busy = BURN_DRIVE_SPAWNING;
#ifdef Libburn_create_detached_threadS
/* ts A71019 :
Trying to start the threads detached to get rid of the zombies
which do neither react on pthread_join() nor on pthread_detach().
*/
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
attr_pt= &attr;
/*
libdax_msgs_submit(libdax_messenger, -1, 0x00020158,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_LOW,
"add_worker(): Creating detached thread.", 0, 0);
*/
#endif
if (pthread_create(&a->thread, attr_pt, f, a)) {
if (pthread_create(&a->thread, NULL, f, a)) {
free(a);
workers = tmp;
return;
}
}
static void remove_worker(pthread_t th)
{
struct w_list *a, *l = NULL;
#ifdef Libburn_detach_done_workeR
int ret;
char msg[80];
#endif
for (a = workers; a; l = a, a = a->next)
if (a->thread == th) {
if (l)
l->next = a->next;
else
workers = a->next;
#ifdef Libburn_detach_done_workeR
/* ts A71019 : burry dead puppy before forgetting it */
/* Alternative : threads get detached and thus should
dispose themselves.
*/
ret = pthread_detach(th);
/*
sprintf(msg,
"remove_workers(): pid= %lu pthread_detach(%lu)= %d",
(unsigned long) getpid(), (unsigned long) th, ret);
libdax_msgs_submit(libdax_messenger, -1, 0x00020158,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_LOW,
msg, 0, 0);
*/
#endif /* Libburn_detach_done_workeR */
free(a);
break;
}
@ -218,13 +130,8 @@ static void remove_worker(pthread_t th)
static void *scan_worker_func(struct w_list *w)
{
int ret;
ret = burn_drive_scan_sync(w->u.scan.drives, w->u.scan.n_drives, 1);
if (ret <= 0)
w->u.scan.done = -1;
else
w->u.scan.done = 1;
burn_drive_scan_sync(w->u.scan.drives, w->u.scan.n_drives);
w->u.scan.done = 1;
return NULL;
}
@ -258,13 +165,12 @@ drive_is_active:;
return -1;
}
if (workers == NULL) {
if (!workers) {
/* start it */
/* ts A61007 : test moved up from burn_drive_scan_sync()
was burn_wait_all() */
/* ts A70907 : now demanding freed drives, not only released */
if (!burn_drives_are_clear(1))
if (!burn_drives_are_clear())
goto drive_is_active;
*drives = NULL;
*n_drives = 0;
@ -272,8 +178,7 @@ drive_is_active:;
o.drives = drives;
o.n_drives = n_drives;
o.done = 0;
add_worker(Burnworker_type_scaN, NULL,
(WorkerFunc) scan_worker_func, &o);
add_worker(NULL, (WorkerFunc) scan_worker_func, &o);
} else if (workers->u.scan.done) {
/* its done */
ret = workers->u.scan.done;
@ -284,7 +189,7 @@ drive_is_active:;
if (workers != NULL) {
libdax_msgs_submit(libdax_messenger, -1, 0x00020101,
LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
"After scan a drive operation is still going on",
"After scan a drive operation is still going on",
0, 0);
return -1;
}
@ -306,6 +211,9 @@ void burn_disc_erase(struct burn_drive *drive, int fast)
{
struct erase_opts o;
/* A70103 : will be set to 0 by burn_disc_erase_sync() */
drive->cancel = 1;
/* ts A61006 */
/* a ssert(drive); */
/* a ssert(!SCAN_GOING()); */
@ -317,7 +225,7 @@ void burn_disc_erase(struct burn_drive *drive, int fast)
"NULL pointer caught in burn_disc_erase", 0, 0);
return;
}
if ((SCAN_GOING()) || find_worker(drive) != NULL) {
if ((SCAN_GOING()) || find_worker(drive)) {
libdax_msgs_submit(libdax_messenger, drive->global_index,
0x00020102,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
@ -325,17 +233,12 @@ void burn_disc_erase(struct burn_drive *drive, int fast)
0, 0);
return;
}
/* A70103 : will be set to 0 by burn_disc_erase_sync() */
drive->cancel = 1;
/* ts A70103 moved up from burn_disc_erase_sync() */
/* ts A60825 : allow on parole to blank appendable CDs */
/* ts A70131 : allow blanking of overwriteable DVD-RW (profile 0x13) */
/* ts A70216 : allow blanking of CD-RW or DVD-RW in any regular state
and of any kind of full media */
/* ts A70909 : the willingness to burn any BURN_DISC_FULL media is
inappropriate. One would rather need a -force option
Note: keep this in sync with mmc_read_disc_info() */
if ((drive->current_profile != 0x0a &&
drive->current_profile != 0x13 &&
drive->current_profile != 0x14 &&
@ -344,8 +247,6 @@ void burn_disc_erase(struct burn_drive *drive, int fast)
(drive->status != BURN_DISC_FULL &&
drive->status != BURN_DISC_APPENDABLE &&
drive->status != BURN_DISC_BLANK)
||
(drive->drive_role != 1)
) {
libdax_msgs_submit(libdax_messenger, drive->global_index,
0x00020130,
@ -357,8 +258,7 @@ void burn_disc_erase(struct burn_drive *drive, int fast)
o.drive = drive;
o.fast = fast;
add_worker(Burnworker_type_erasE, drive,
(WorkerFunc) erase_worker_func, &o);
add_worker(drive, (WorkerFunc) erase_worker_func, &o);
}
@ -379,7 +279,7 @@ void burn_disc_format(struct burn_drive *drive, off_t size, int flag)
int ok = 0;
char msg[160];
if ((SCAN_GOING()) || find_worker(drive) != NULL) {
if ((SCAN_GOING()) || find_worker(drive)) {
libdax_msgs_submit(libdax_messenger, drive->global_index,
0x00020102,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
@ -387,14 +287,6 @@ void burn_disc_format(struct burn_drive *drive, off_t size, int flag)
0, 0);
return;
}
if (drive->drive_role != 1) {
libdax_msgs_submit(libdax_messenger, drive->global_index,
0x00020146,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Drive is a virtual placeholder", 0, 0);
drive->cancel = 1;
return;
}
if (flag & 128) /* application prescribed format type */
flag |= 16; /* enforce re-format */
@ -407,10 +299,6 @@ void burn_disc_format(struct burn_drive *drive, off_t size, int flag)
size = 0;
flag &= ~(2|8); /* no insisting in size 0, no expansion */
flag |= 4; /* format up to maximum size */
} else if (drive->current_profile == 0x12) {
ok = 1; /* DVD-RAM */
} else if (drive->current_profile == 0x43) {
ok = 1; /* BD-RE */
}
if (!ok) {
@ -426,20 +314,13 @@ void burn_disc_format(struct burn_drive *drive, off_t size, int flag)
o.drive = drive;
o.size = size;
o.flag = flag;
add_worker(Burnworker_type_formaT, drive,
(WorkerFunc) format_worker_func, &o);
add_worker(drive, (WorkerFunc) format_worker_func, &o);
}
static void *write_disc_worker_func(struct w_list *w)
{
struct burn_drive *d = w->u.write.drive;
d->thread_pid = getpid();
d->thread_pid_valid= 1;
burn_disc_write_sync(w->u.write.opts, w->u.write.disc);
d->thread_pid_valid= 0;
d->thread_pid = 0;
/* the options are refcounted, free out ref count which we added below
*/
@ -453,18 +334,10 @@ void burn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
{
struct write_opts o;
char reasons[BURN_REASONS_LEN+80];
#ifndef Libburn_precheck_write_ruleS
int i, j, mode, mixed_mode = 0;
#endif
/* ts A61006 */
/* a ssert(!SCAN_GOING()); */
/* a ssert(!find_worker(opts->drive)); */
if ((SCAN_GOING()) || find_worker(opts->drive) != NULL) {
libdax_msgs_submit(libdax_messenger, opts->drive->global_index,
0x00020102,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"A drive operation is still going on (want to write)",
0, 0);
return;
}
/* For the next lines any return indicates failure */
opts->drive->cancel = 1;
@ -473,16 +346,19 @@ void burn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
if (opts->write_type == BURN_WRITE_NONE)
return;
if (opts->drive->drive_role == 0) {
/* ts A61006 */
/* a ssert(!SCAN_GOING()); */
/* a ssert(!find_worker(opts->drive)); */
if ((SCAN_GOING()) || find_worker(opts->drive)) {
libdax_msgs_submit(libdax_messenger, opts->drive->global_index,
0x00020146,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Drive is a virtual placeholder (null-drive)", 0, 0);
0x00020102,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"A drive operation is still going on (want to write)",
0, 0);
return;
}
/* ts A61007 : obsolete Assert in spc_select_write_params() */
if (opts->drive->drive_role == 1 && !opts->drive->mdata->valid) {
if (!opts->drive->mdata->valid) {
libdax_msgs_submit(libdax_messenger,
opts->drive->global_index, 0x00020113,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
@ -496,13 +372,48 @@ void burn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
strcpy(reasons, "Write job parameters are unsuitable:\n");
if (burn_precheck_write(opts, disc, reasons + strlen(reasons), 1)
== BURN_WRITE_NONE) {
#ifndef Libburn_precheck_write_ruleS
libdax_msgs_submit(libdax_messenger,
opts->drive->global_index, 0x00020139,
LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
reasons, 0, 0);
#else
libdax_msgs_submit(libdax_messenger,
opts->drive->global_index, 0x00020139,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
reasons, 0, 0);
return;
#endif /* Libburn_precheck_write_ruleS */
}
#ifndef Libburn_precheck_write_ruleS
/* <<< covered burn_precheck_write() */
/* ts A61009 : obsolete Assert in sector_headers() */
if (! burn_disc_write_is_ok(opts, disc, 0)) /* issues own msgs */
return;
/* <<< covered burn_precheck_write() */
/* ts A70122 : libburn SAO code mishandles mode changes */
for (i = 0; i < disc->sessions; i++) {
if (disc->session[i]->tracks <= 0)
continue;
mode = disc->session[i]->track[0]->mode;
for (j = 1; j < disc->session[i]->tracks; j++)
if (mode != disc->session[i]->track[j]->mode)
mixed_mode = 1;
}
if (mixed_mode && opts->write_type == BURN_WRITE_SAO) {
libdax_msgs_submit(libdax_messenger,
opts->drive->global_index, 0x00020133,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Cannot mix data and audio in SAO mode", 0, 0);
return;
}
#endif /* ! Libburn_precheck_write_ruleS */
opts->drive->cancel = 0; /* End of the return = failure area */
o.drive = opts->drive;
@ -511,45 +422,9 @@ void burn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
opts->refcount++;
add_worker(Burnworker_type_writE, opts->drive,
(WorkerFunc) write_disc_worker_func, &o);
add_worker(opts->drive, (WorkerFunc) write_disc_worker_func, &o);
}
static void *fifo_worker_func(struct w_list *w)
{
burn_fifo_source_shoveller(w->u.fifo.source, w->u.fifo.flag);
remove_worker(pthread_self());
return NULL;
}
int burn_fifo_start(struct burn_source *source, int flag)
{
struct fifo_opts o;
struct burn_source_fifo *fs = source->data;
fs->is_started = -1;
/* create and set up ring buffer */;
fs->buf = calloc(fs->chunksize, fs->chunks);
if (fs->buf == NULL) {
/* >>> could not start ring buffer */;
return -1;
}
o.source = source;
o.flag = flag;
add_worker(Burnworker_type_fifO, NULL,
(WorkerFunc) fifo_worker_func, &o);
fs->is_started = 1;
return 1;
}
#ifdef Libburn_has_burn_async_join_alL
/* ts A71019 : never used */
void burn_async_join_all(void)
{
void *ret;
@ -557,7 +432,3 @@ void burn_async_join_all(void)
while (workers)
pthread_join(workers->thread, &ret);
}
#endif /* Libburn_has_burn_async_join_alL */

View File

@ -5,10 +5,4 @@
void burn_async_join_all(void);
struct burn_write_opts;
/* ts A70930 */
/* To be called when the first read() call comes to a fifo */
int burn_fifo_start(struct burn_source *source, int flag);
#endif /* BURN__ASYNC_H */

File diff suppressed because it is too large Load Diff

View File

@ -43,8 +43,7 @@ unsigned int burn_drive_count(void);
/* ts A61007 */
/* void burn_wait_all(void); */
/* @param flag bit0= demand freed drives (else released drives) */
int burn_drives_are_clear(int flag);
int burn_drives_are_clear(void);
int burn_sector_length_write(struct burn_drive *d);
int burn_track_control(struct burn_drive *d, int);
@ -53,10 +52,8 @@ void burn_write_empty_subcode(int fd);
void burn_drive_free(struct burn_drive *d);
void burn_drive_free_all(void);
/* @param flag bit0= reset global drive list */
int burn_drive_scan_sync(struct burn_drive_info *drives[],
unsigned int *n_drives, int flag);
unsigned int *n_drives);
void burn_disc_erase_sync(struct burn_drive *d, int fast);
int burn_drive_get_block_types(struct burn_drive *d,
enum burn_write_types write_type);
@ -114,25 +111,4 @@ int burn_disc_get_write_mode_demands(struct burn_disc *disc,
struct burn_write_opts *opts,
struct burn_disc_mode_demands *result, int flag);
/* ts A70924 : convert a special stdio address into fd number.
@return >0 is a valid fd , -1 indicates unsuitable address string.
*/
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 A51221 - A80731 : Whitelist inquiry functions */
int burn_drive_is_banned(char *device_address);
int burn_drive_whitelist_count(void);
char *burn_drive_whitelist_item(int idx, int flag);
/* ts A80801 */
int burn_drive_is_listed(char *path, struct burn_drive **found, int flag);
#endif /* __DRIVE */

View File

@ -2,21 +2,12 @@
#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include "source.h"
#include "libburn.h"
#include "file.h"
#include "async.h"
#include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger;
/* main channel data can be padded on read, but 0 padding the subs will make
an unreadable disc */
@ -102,14 +93,14 @@ struct burn_source *burn_file_source_new(const char *path, const char *subpath)
{
struct burn_source_file *fs;
struct burn_source *src;
int fd1 = -1, fd2 = -1;
int fd1, fd2 = 0;
if (!path)
return NULL;
fd1 = open(path, O_RDONLY);
if (fd1 == -1)
return NULL;
if (subpath != NULL) {
if (subpath) {
fd2 = open(subpath, O_RDONLY);
if (fd2 == -1) {
close(fd1);
@ -117,30 +108,15 @@ struct burn_source *burn_file_source_new(const char *path, const char *subpath)
}
}
fs = malloc(sizeof(struct burn_source_file));
/* ts A70825 */
if (fs == NULL) {
failure:;
close(fd1);
if (fd2 >= 0)
close(fd2);
return NULL;
}
fs->datafd = fd1;
fs->subfd = fd2;
if (subpath)
fs->subfd = fd2;
/* ts A70125 */
fs->fixed_size = 0;
src = burn_source_new();
/* ts A70825 */
if (src == NULL) {
free((char *) fs);
goto failure;
}
src->read = file_read;
if (subpath)
src->read_sub = file_read_sub;
@ -163,23 +139,14 @@ struct burn_source *burn_fd_source_new(int datafd, int subfd, off_t size)
if (datafd == -1)
return NULL;
fs = malloc(sizeof(struct burn_source_file));
if (fs == NULL) /* ts A70825 */
return NULL;
fs->datafd = datafd;
fs->subfd = subfd;
fs->fixed_size = size;
src = burn_source_new();
/* ts A70825 */
if (src == NULL) {
free((char *) fs);
return NULL;
}
src->read = file_read;
if(subfd != -1)
src->read_sub = file_read_sub;
src->read = file_read_sub;
src->get_size = file_size;
src->set_size = file_set_size;
src->free_data = file_free;
@ -187,417 +154,3 @@ struct burn_source *burn_fd_source_new(int datafd, int subfd, off_t size)
return src;
}
/* ts A71003 */
/* ------------------------------ fifo --------------------------- */
/* The fifo mechanism consists of a burn_source proxy which is here,
a thread management team which is located in async.c,
and a synchronous shoveller which is here.
*/
static int fifo_sleep(int flag)
{
static struct timespec sleeptime = { 0, 50000000}; /* 50 ms */
return nanosleep(&sleeptime, NULL);
}
static int fifo_read(struct burn_source *source,
unsigned char *buffer,
int size)
{
struct burn_source_fifo *fs = source->data;
int ret, todo, rpos, bufsize, diff;
if (fs->end_of_consumption) {
/* ??? msg: reading has been ended already */;
return 0;
}
if (fs->is_started == 0) {
ret = burn_fifo_start(source, 0);
if (ret <= 0) {
libdax_msgs_submit(libdax_messenger, -1, 0x00020152,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Cannot start fifo thread", 0, 0);
fs->end_of_consumption = 1;
return -1;
}
fs->is_started = 1;
}
if (size == 0)
return 0;
/* Reading from the ring buffer */
/* This needs no mutex because each volatile variable has one thread
which may write and the other which only reads and is aware of
volatility.
The feeder of the ringbuffer is in burn_fifo_source_shoveller().
*/
todo = size;
bufsize = fs->chunksize * fs->chunks;
while (todo > 0) {
/* readpos is not volatile here , writepos is volatile */
rpos = fs->buf_readpos;
while (rpos == fs->buf_writepos) {
if (fs->end_of_input)
break;
if (fs->input_error) {
if (todo < size) /* deliver partial buffer */
break;
fs->end_of_consumption = 1;
libdax_msgs_submit(libdax_messenger, -1,
0x00020154,
LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH,
"Forwarded input error ends output", 0, 0);
return -1;
}
fifo_sleep(0);
}
diff = fs->buf_writepos - rpos; /* read volatile only once */
if (diff == 0)
break;
if (diff > 0)
/* diff bytes are available */;
else
/* at least (bufsize - rpos) bytes are available */
diff = bufsize - rpos;
if (diff > todo)
diff = todo;
memcpy(buffer, fs->buf+(size-todo)+rpos, diff);
fs->buf_readpos += diff;
if (fs->buf_readpos >= bufsize)
fs->buf_readpos = 0;
todo -= diff;
}
if (size - todo <= 0)
fs->end_of_consumption = 1;
else
fs->out_counter += size - todo;
/*
fprintf(stderr,
"libburn_EXPERIMENTAL: read= %d , pos= %d , out_count= %.f\n",
(size - todo), fs->buf_readpos, (double) fs->out_counter);
*/
return (size - todo);
}
static off_t fifo_get_size(struct burn_source *source)
{
struct burn_source_fifo *fs = source->data;
return fs->inp->get_size(fs->inp);
}
static int fifo_set_size(struct burn_source *source, off_t size)
{
struct burn_source_fifo *fs = source->data;
return fs->inp->set_size(fs->inp, size);
}
static void fifo_free(struct burn_source *source)
{
struct burn_source_fifo *fs = source->data;
if (fs->inp != NULL)
burn_source_free(fs->inp);
if (fs->buf != NULL)
free(fs->buf);
free((char *) fs);
}
int burn_fifo_source_shoveller(struct burn_source *source, int flag)
{
struct burn_source_fifo *fs = source->data;
int ret, bufsize, diff, wpos, rpos, trans_end, free_bytes;
char *bufpt;
fs->thread_pid = getpid();
fs->thread_pid_valid = 1;
bufsize = fs->chunksize * fs->chunks;
while (!fs->end_of_consumption) {
/* wait for enough buffer space available */
wpos = fs->buf_writepos;
while (1) {
rpos = fs->buf_readpos;
diff = rpos - wpos;
trans_end = 0;
if (diff == 0)
free_bytes = bufsize - 1;
else if (diff > 0)
free_bytes = diff - 1;
else {
free_bytes = (bufsize - wpos) + rpos - 1;
if (bufsize - wpos < fs->chunksize)
trans_end = 1;
}
if (free_bytes >= fs->chunksize)
break;
fifo_sleep(0);
}
/* prepare the receiving memory */
bufpt = fs->buf + wpos;
if (trans_end) {
bufpt = calloc(fs->chunksize, 1);
if (bufpt == NULL) {
libdax_msgs_submit(libdax_messenger, -1,
0x00000003,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Out of virtual memory", 0, 0);
fs->input_error = ENOMEM;
break;
}
}
/* Obtain next chunk */
if (fs->inp->read != NULL)
ret = fs->inp->read(fs->inp,
(unsigned char *) bufpt, fs->chunksize);
else
ret = fs->inp->read_xt( fs->inp,
(unsigned char *) bufpt, fs->chunksize);
if (ret > 0)
fs->in_counter += ret;
else if (ret == 0)
break; /* EOF */
else {
libdax_msgs_submit(libdax_messenger, -1, 0x00020153,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Read error on fifo input", errno, 0);
fs->input_error = errno;
if(errno == 0)
fs->input_error = EIO;
break;
}
/* activate read chunk */
if (ret > fs->chunksize) /* beware of ill custom burn_source */
ret = fs->chunksize;
if (trans_end) {
/* copy to end of buffer */
memcpy(fs->buf + wpos, bufpt, bufsize - wpos);
/* copy to start of buffer */
memcpy(fs->buf, bufpt + (bufsize - wpos),
fs->chunksize - (bufsize - wpos));
free(bufpt);
if (ret >= bufsize - wpos)
fs->buf_writepos = ret - (bufsize - wpos);
else
fs->buf_writepos += ret;
} else if (fs->buf_writepos + ret == bufsize)
fs->buf_writepos = 0;
else
fs->buf_writepos += ret;
/*
fprintf(stderr, "[%2.2d%%] ",
(int) (100.0 - 100.0 * ((double) free_bytes) /
(double) bufsize));
fprintf(stderr,
"libburn_EXPERIMENTAL: writepos= %d ,in_count = %.f\n",
fs->buf_writepos, (double) fs->in_counter);
*/
}
if (!fs->end_of_consumption)
fs->end_of_input = 1;
/* wait for end of reading by consumer */;
while (fs->buf_readpos != fs->buf_writepos && !fs->end_of_consumption)
fifo_sleep(0);
/* destroy ring buffer */;
if (!fs->end_of_consumption)
fs->end_of_consumption = 2; /* Claim stop of consumption */
/* This is not prone to race conditions because either the consumer
indicated hangup by fs->end_of_consumption = 1 or the consumer set
fs->buf_readpos to a value indicating the buffer is empty.
So in both cases the consumer is aware that reading is futile
or even fatal.
*/
free(fs->buf); /* Give up fifo buffer. Next fifo might start soon. */
fs->buf = NULL;
return (fs->input_error == 0);
}
int burn_fifo_cancel(struct burn_source *source)
{
struct burn_source_fifo *fs = source->data;
burn_source_cancel(fs->inp);
return(1);
}
struct burn_source *burn_fifo_source_new(struct burn_source *inp,
int chunksize, int chunks, int flag)
{
struct burn_source_fifo *fs;
struct burn_source *src;
if (((double) chunksize) * ((double) chunks) > 1024.0*1024.0*1024.0) {
libdax_msgs_submit(libdax_messenger, -1, 0x00020155,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Desired fifo buffer too large (> 1GB)", 0, 0);
return NULL;
}
if (chunksize < 1 || chunks < 2) {
libdax_msgs_submit(libdax_messenger, -1, 0x00020156,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Desired fifo buffer too small", 0, 0);
return NULL;
}
fs = malloc(sizeof(struct burn_source_fifo));
if (fs == NULL)
return NULL;
fs->is_started = 0;
fs->thread_pid = 0;
fs->thread_pid_valid = 0;
fs->inp = NULL; /* set later */
fs->chunksize = chunksize;
fs->chunks = chunks;
fs->buf = NULL;
fs->buf_writepos = fs->buf_readpos = 0;
fs->end_of_input = 0;
fs->input_error = 0;
fs->end_of_consumption = 0;
fs->in_counter = fs->out_counter = 0;
src = burn_source_new();
if (src == NULL) {
free((char *) fs);
return NULL;
}
src->read = NULL;
src->read_sub = NULL;
src->get_size = fifo_get_size;
src->set_size = fifo_set_size;
src->free_data = fifo_free;
src->data = fs;
src->version= 1;
src->read_xt = fifo_read;
src->cancel= burn_fifo_cancel;
fs->inp = inp;
inp->refcount++; /* make sure inp lives longer than src */
return src;
}
/* ts A71003 : API */
int burn_fifo_inquire_status(struct burn_source *source,
int *size, int *free_bytes, char **status_text)
{
struct burn_source_fifo *fs = source->data;
int ret = 0, diff, wpos, rpos;
static char *(states[8]) = {
"standby", "active", "ending", "failing",
"unused", "abandoned", "ended", "aborted"};
*status_text = NULL;
*size = 0;
if (source->free_data != fifo_free) {
libdax_msgs_submit(libdax_messenger, -1, 0x00020157,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"burn_source is not a fifo object", 0, 0);
return -1;
}
*size = fs->chunksize * fs->chunks;
rpos = fs->buf_readpos;
wpos = fs->buf_writepos;
diff = rpos - wpos;
if (diff == 0)
*free_bytes = *size - 1;
else if (diff > 0)
*free_bytes = diff - 1;
else
*free_bytes = (*size - wpos) + rpos - 1;
ret = 0;
if (fs->end_of_consumption > 0)
ret |= 4;
if (fs->input_error)
ret |= 3;
else if (fs->end_of_input)
ret |= 2;
else if(fs->buf != NULL)
ret |= 1;
*status_text = states[ret];
return ret;
}
int burn_fifo_peek_data(struct burn_source *source, char *buf, int bufsize,
int flag)
{
int size, free_bytes, ret, wait_count= 0;
char *status_text;
struct burn_source_fifo *fs = source->data;
/* Eventually start fifo thread by reading 0 bytes */
ret = fifo_read(source, (unsigned char *) NULL, 0);
if (ret<0)
return 0;
/* wait for at least bufsize bytes being ready */
while (1) {
ret= burn_fifo_inquire_status(source,
&size, &free_bytes, &status_text);
if (size < bufsize) {
libdax_msgs_submit(libdax_messenger, -1, 0x0002015c,
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
"Fifo size is smaller than desired peek buffer", 0, 0);
return -1;
}
if (fs->out_counter > 0 || (ret & 4) || fs->buf == NULL) {
libdax_msgs_submit(libdax_messenger, -1, 0x0002015e,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Fifo is already under consumption when peeking is desired",
0, 0);
return -1;
}
if(size - free_bytes >= bufsize) {
/* <<<
fprintf(stderr,
"libburn_DEBUG: after waiting cycle %d : fifo %s , %d bytes\n",
wait_count, status_text, size - free_bytes);
*/
memcpy(buf, fs->buf, bufsize);
return 1;
}
if (ret&2) { /* input has ended, not enough data arrived */
libdax_msgs_submit(libdax_messenger, -1, 0x0002015d,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Fifo input ended short of desired peek buffer size",
0, 0);
return 0;
}
usleep(100000);
wait_count++;
/* <<<
if(wait_count%10==0)
fprintf(stderr,
"libburn_DEBUG: waiting cycle %d : fifo %s , %d bytes\n",
wait_count, status_text, size - free_bytes);
*/
}
return(0);
}

View File

@ -5,58 +5,13 @@
struct burn_source_file
{
char magic[4];
int datafd;
int subfd;
off_t fixed_size;
};
/* ts A70126 : burn_source_file obsoleted burn_source_fd */
/* ts A70930 */
struct burn_source_fifo {
char magic[4];
/* The fifo stays inactive and unequipped with eventual resources
until its read() method is called for the first time.
Only then burn_fifo_start() gets called, allocates the complete
resources, starts a thread with burn_fifo_source_shuffler()
which shuffles data and finally destroys the resources.
This late start is to stay modest in case of multiple tracks
in one disc.
*/
int is_started;
int thread_pid;
int thread_pid_valid;
/* the burn_source for which this fifo is acting as proxy */
struct burn_source *inp;
/* <<< up to now it was only a pipe. This is on its way out. */
int outlet[2];
/* The ring buffer mechanism */
int chunksize;
int chunks;
char *buf;
volatile int buf_writepos;
volatile int buf_readpos;
volatile int end_of_input;
volatile int input_error;
volatile int end_of_consumption;
off_t in_counter;
off_t out_counter;
};
/** The worker behind the fifo thread.
Gets started from burn_fifo_start() in async.c
*/
int burn_fifo_source_shoveller(struct burn_source *source, int flag);
#endif /* LIBBURN__FILE_H */

View File

@ -8,18 +8,12 @@
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>
/* ts A70928 : init.h is for others, not for init .c
#include "init.h"
*/
#include "sg.h"
#include "error.h"
#include "libburn.h"
#include "drive.h"
#include "transport.h"
/* ts A60825 : The storage location for back_hacks.h variables. */
#define BURN_BACK_HACKS_INIT 1
@ -59,6 +53,7 @@ int burn_sg_open_o_nonblock = 1;
to unconditional abort of the process */
int burn_sg_open_abort_busy = 0;
/* ts A61002 */
#include "cleanup.h"
@ -66,10 +61,6 @@ 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;
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;
/* ts A70223 : wether implemented untested profiles are supported */
@ -116,12 +107,11 @@ void burn_finish(void)
/* ts A61007 */
/* burn_wait_all(); */
if (!burn_drives_are_clear(0)) {
if (!burn_drives_are_clear()) {
libdax_msgs_submit(libdax_messenger, -1, 0x00020107,
LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
"A drive is still busy on shutdown of library", 0, 0);
usleep(1000001);
burn_abort(4440, burn_abort_pacifier, abort_message_prefix);
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Drive is busy on attempt to shut down library", 0, 0);
return;
}
/* ts A60904 : ticket 62, contribution by elmom : name addon "_all" */
@ -210,8 +200,6 @@ int burn_msgs_obtain(char *minimum_severity,
ret = libdax_msgs__text_to_sev(minimum_severity, &minimum_sevno, 0);
if (ret <= 0)
return 0;
if (libdax_messenger == NULL)
return 0;
ret = libdax_msgs_obtain(libdax_messenger, &item, minimum_sevno,
LIBDAX_MSGS_PRIO_ZERO, 0);
if (ret <= 0)
@ -238,124 +226,40 @@ ex:
return ret;
}
/* ts A70922 : API */
int burn_msgs_submit(int error_code, char msg_text[], int os_errno,
char severity[], struct burn_drive *d)
{
int ret, sevno, global_index = -1;
ret = libdax_msgs__text_to_sev(severity, &sevno, 0);
if (ret <= 0)
sevno = LIBDAX_MSGS_SEV_ALL;
if (error_code <= 0) {
switch(sevno) {
case LIBDAX_MSGS_SEV_ABORT: error_code = 0x00040000;
break; case LIBDAX_MSGS_SEV_FATAL: error_code = 0x00040001;
break; case LIBDAX_MSGS_SEV_SORRY: error_code = 0x00040002;
break; case LIBDAX_MSGS_SEV_WARNING: error_code = 0x00040003;
break; case LIBDAX_MSGS_SEV_HINT: error_code = 0x00040004;
break; case LIBDAX_MSGS_SEV_NOTE: error_code = 0x00040005;
break; case LIBDAX_MSGS_SEV_UPDATE: error_code = 0x00040006;
break; case LIBDAX_MSGS_SEV_DEBUG: error_code = 0x00040007;
break; default: error_code = 0x00040008;
}
}
if (d != NULL)
global_index = d->global_index;
ret = libdax_msgs_submit(libdax_messenger, global_index, error_code,
sevno, LIBDAX_MSGS_PRIO_HIGH, msg_text, os_errno, 0);
return ret;
}
/* ts A71016 API */
int burn_text_to_sev(char *severity_name, int *sevno, int flag)
{
int ret;
ret = libdax_msgs__text_to_sev(severity_name, sevno, 0);
return ret;
}
/* ts A80202 API */
int burn_sev_to_text(int severity_number, char **severity_name, int flag)
{
int ret;
ret = libdax_msgs__sev_to_text(severity_number, severity_name, 0);
return ret;
}
int burn_builtin_abort_handler(void *handle, int signum, int flag)
{
#define Libburn_new_thread_signal_handleR 1
/*
#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);
#endif
/* 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
yield at least 1 if any thread calls this function.
*/
burn_global_abort_level++;
burn_global_abort_signum= signum;
if(getpid() != abort_control_pid) {
#ifdef Libburn_new_thread_signal_handleR
#ifdef Not_yeT
pthread_t thread_id;
ret = burn_drive_find_by_thread_pid(&d, getpid());
if (ret > 0 && d->busy == BURN_DRIVE_WRITING) {
/* This is an active writer thread */
/* >>> need better handling of self-induced SIGs
like SIGSEGV or SIGFPE.
Like bonking the control thread if it did not show up
after a short while.
*/
#ifdef Libburn_signal_handler_verbouS
fprintf(stderr, "libburn_ABORT: pid %d found drive busy with writing, (level= %d)\n", (int) getpid(), burn_global_abort_level);
#endif
/* >>> if this is a non-fatal signal : return -2 */
d->sync_cache(d);
thread_id = pthread_self();
/* >>> find thread_id in worker list of async.c */
/* >>> if owning a drive : mark idle and canceled
(can't do anything more) */
/* >>> perform a more qualified end of burn process */;
usleep(1000000); /* calm down */
d->busy = BURN_DRIVE_IDLE;
/* forward signal to control thread */
if (abort_control_pid>1)
kill(abort_control_pid, signum);
if (burn_global_abort_level > 0) {
/* control process did not show up yet */
#ifdef Libburn_signal_handler_verbouS
fprintf(stderr, "libburn_ABORT: pid %d sending signum %d to pid %d\n", (int) getpid(), (int) signum, (int) abort_control_pid);
#endif
kill(abort_control_pid, signum);
}
#ifdef Libburn_signal_handler_verbouS
fprintf(stderr, "libburn_ABORT: pid %d signum %d returning -2\n", (int) getpid(), (int) signum);
#endif
return -2;
} else {
usleep(1000000); /* calm down */
return -2;
}
/* >>> ??? end thread */;
#else
usleep(1000000); /* calm down */
return -2;
#endif /* ! Libburn_new_thread_signal_handleR */
#endif /* ! Not_yeT */
}
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);
@ -363,13 +267,10 @@ int burn_builtin_abort_handler(void *handle, int signum, int flag)
"%sABORT : Wait the normal burning time before any kill -9\n",
abort_message_prefix);
close(0); /* somehow stdin as input blocks abort until EOF */
burn_abort(4440, burn_abort_pacifier, abort_message_prefix);
fprintf(stderr,
"\n%sABORT : Program done. Even if you do not see a shell prompt.\n\n",
abort_message_prefix);
burn_global_abort_level = -2;
return(1);
}
@ -388,10 +289,8 @@ void burn_set_signal_handling(void *handle, burn_abort_handler_t 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();
abort_control_pid= getpid();
Cleanup_set_handlers(handle, (Cleanup_app_handler_T) handler, mode|4);
burn_global_signal_handle = handle;
burn_global_signal_handler = handler;
}
@ -401,16 +300,3 @@ void burn_allow_untested_profiles(int yes)
burn_support_untested_profiles = !!yes;
}
/* ts A70915 : API */
int burn_set_messenger(void *messenger)
{
struct libdax_msgs *pt;
if (libdax_msgs_refer(&pt, messenger, 0) <= 0)
return 0;
libdax_msgs_destroy(&libdax_messenger, 0);
libdax_messenger = (struct libdax_msgs *) pt;
return 1;
}

View File

@ -5,17 +5,4 @@
extern int burn_running;
/** Indicator for burn_drive_get_status() wether a signal hit parts of the
thread team.
0= all works well ,
1 to 5 = waiting for eventual signal on control thread
> 5 = do abort now
-1 = control thread has been informed
*/
extern volatile int burn_global_abort_level;
extern int burn_global_abort_signum;
extern void *burn_global_signal_handle;
extern burn_abort_handler_t burn_global_signal_handler;
#endif /* BURN__INIT_H */

File diff suppressed because it is too large Load Diff

View File

@ -34,7 +34,7 @@ int libdax_audioxtr_new(struct libdax_audioxtr **xtr, char *path, int flag)
if(o==NULL)
return(-1);
strncpy(o->path,path,LIBDAX_AUDIOXTR_STRLEN-1);
o->path[LIBDAX_AUDIOXTR_STRLEN-1]= 0;
o->path[LIBDAX_AUDIOXTR_STRLEN]= 0;
o->fd= -1;
strcpy(o->fmt,"unidentified");
o->fmt_info[0]= 0;

View File

@ -1,8 +1,7 @@
/* libdax_msgs
Message handling facility of libdax.
Copyright (C) 2006 - 2008 Thomas Schmitt <scdbackup@gmx.net>,
provided under GPL version 2
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
*/
#include <stdio.h>
@ -40,7 +39,7 @@ static int libdax_msgs_item_new(struct libdax_msgs_item **item,
if(ret==0)
o->timestamp= tv.tv_sec+0.000001*tv.tv_usec;
o->process_id= getpid();
o->origin= -1;
o->driveno= -1;
o->severity= LIBDAX_MSGS_SEV_ALL;
o->priority= LIBDAX_MSGS_PRIO_ZERO;
o->error_code= 0;
@ -109,12 +108,12 @@ int libdax_msgs_item_get_msg(struct libdax_msgs_item *item,
int libdax_msgs_item_get_origin(struct libdax_msgs_item *item,
double *timestamp, pid_t *process_id, int *origin,
double *timestamp, pid_t *process_id, int *driveno,
int flag)
{
*timestamp= item->timestamp;
*process_id= item->process_id;
*origin= item->origin;
*driveno= item->driveno;
return(1);
}
@ -138,7 +137,6 @@ int libdax_msgs_new(struct libdax_msgs **m, int flag)
(*m)= o= (struct libdax_msgs *) malloc(sizeof(struct libdax_msgs));
if(o==NULL)
return(-1);
o->refcount= 1;
o->oldest= NULL;
o->youngest= NULL;
o->count= 0;
@ -154,6 +152,43 @@ int libdax_msgs_new(struct libdax_msgs **m, int flag)
}
int libdax_msgs_destroy(struct libdax_msgs **m, int flag)
{
struct libdax_msgs *o;
struct libdax_msgs_item *item, *next_item;
o= *m;
if(o==NULL)
return(0);
#ifndef LIBDAX_MSGS_SINGLE_THREADED
if(pthread_mutex_destroy(&(o->lock_mutex))!=0) {
pthread_mutex_unlock(&(o->lock_mutex));
pthread_mutex_destroy(&(o->lock_mutex));
}
#endif
for(item= o->oldest; item!=NULL; item= next_item) {
next_item= item->next;
libdax_msgs_item_destroy(&item,0);
}
free((char *) o);
*m= NULL;
return(1);
}
int libdax_msgs_set_severities(struct libdax_msgs *m, int queue_severity,
int print_severity, char *print_id, int flag)
{
m->queue_severity= queue_severity;
m->print_severity= print_severity;
strncpy(m->print_id,print_id,80);
m->print_id[80]= 0;
return(1);
}
static int libdax_msgs_lock(struct libdax_msgs *m, int flag)
{
@ -184,65 +219,6 @@ static int libdax_msgs_unlock(struct libdax_msgs *m, int flag)
}
int libdax_msgs_destroy(struct libdax_msgs **m, int flag)
{
struct libdax_msgs *o;
struct libdax_msgs_item *item, *next_item;
o= *m;
if(o==NULL)
return(0);
if(o->refcount > 1) {
if(libdax_msgs_lock(*m,0)<=0)
return(-1);
o->refcount--;
libdax_msgs_unlock(*m,0);
*m= NULL;
return(1);
}
#ifndef LIBDAX_MSGS_SINGLE_THREADED
if(pthread_mutex_destroy(&(o->lock_mutex))!=0) {
pthread_mutex_unlock(&(o->lock_mutex));
pthread_mutex_destroy(&(o->lock_mutex));
}
#endif
for(item= o->oldest; item!=NULL; item= next_item) {
next_item= item->next;
libdax_msgs_item_destroy(&item,0);
}
free((char *) o);
*m= NULL;
return(1);
}
int libdax_msgs_refer(struct libdax_msgs **pt, struct libdax_msgs *m, int flag)
{
if(libdax_msgs_lock(m,0)<=0)
return(0);
m->refcount++;
*pt= m;
libdax_msgs_unlock(m,0);
return(1);
}
int libdax_msgs_set_severities(struct libdax_msgs *m, int queue_severity,
int print_severity, char *print_id, int flag)
{
if(libdax_msgs_lock(m,0)<=0)
return(0);
m->queue_severity= queue_severity;
m->print_severity= print_severity;
strncpy(m->print_id,print_id,80);
m->print_id[80]= 0;
libdax_msgs_unlock(m,0);
return(1);
}
int libdax_msgs__text_to_sev(char *severity_name, int *severity,
int flag)
{
@ -252,10 +228,6 @@ int libdax_msgs__text_to_sev(char *severity_name, int *severity,
*severity= LIBDAX_MSGS_SEV_ABORT;
else if(strncmp(severity_name,"FATAL",5)==0)
*severity= LIBDAX_MSGS_SEV_FATAL;
else if(strncmp(severity_name,"FAILURE",7)==0)
*severity= LIBDAX_MSGS_SEV_FAILURE;
else if(strncmp(severity_name,"MISHAP",6)==0)
*severity= LIBDAX_MSGS_SEV_MISHAP;
else if(strncmp(severity_name,"SORRY",5)==0)
*severity= LIBDAX_MSGS_SEV_SORRY;
else if(strncmp(severity_name,"WARNING",7)==0)
@ -268,12 +240,10 @@ int libdax_msgs__text_to_sev(char *severity_name, int *severity,
*severity= LIBDAX_MSGS_SEV_UPDATE;
else if(strncmp(severity_name,"DEBUG",5)==0)
*severity= LIBDAX_MSGS_SEV_DEBUG;
else if(strncmp(severity_name,"ERRFILE",7)==0)
*severity= LIBDAX_MSGS_SEV_ERRFILE;
else if(strncmp(severity_name,"ALL",3)==0)
*severity= LIBDAX_MSGS_SEV_ALL;
else {
*severity= LIBDAX_MSGS_SEV_ALL;
*severity= LIBDAX_MSGS_SEV_NEVER;
return(0);
}
return(1);
@ -284,7 +254,8 @@ int libdax_msgs__sev_to_text(int severity, char **severity_name,
int flag)
{
if(flag&1) {
*severity_name= "NEVER\nABORT\nFATAL\nFAILURE\nMISHAP\nSORRY\nWARNING\nHINT\nNOTE\nUPDATE\nDEBUG\nERRFILE\nALL";
*severity_name=
"NEVER\nABORT\nFATAL\nSORRY\nWARNING\nHINT\nNOTE\nUPDATE\nDEBUG\nALL";
return(1);
}
*severity_name= "";
@ -294,10 +265,6 @@ int libdax_msgs__sev_to_text(int severity, char **severity_name,
*severity_name= "ABORT";
else if(severity>=LIBDAX_MSGS_SEV_FATAL)
*severity_name= "FATAL";
else if(severity>=LIBDAX_MSGS_SEV_FAILURE)
*severity_name= "FAILURE";
else if(severity>=LIBDAX_MSGS_SEV_MISHAP)
*severity_name= "MISHAP";
else if(severity>=LIBDAX_MSGS_SEV_SORRY)
*severity_name= "SORRY";
else if(severity>=LIBDAX_MSGS_SEV_WARNING)
@ -310,8 +277,6 @@ int libdax_msgs__sev_to_text(int severity, char **severity_name,
*severity_name= "UPDATE";
else if(severity>=LIBDAX_MSGS_SEV_DEBUG)
*severity_name= "DEBUG";
else if(severity>=LIBDAX_MSGS_SEV_ERRFILE)
*severity_name= "ERRFILE";
else if(severity>=LIBDAX_MSGS_SEV_ALL)
*severity_name= "ALL";
else {
@ -322,7 +287,7 @@ int libdax_msgs__sev_to_text(int severity, char **severity_name,
}
int libdax_msgs_submit(struct libdax_msgs *m, int origin, int error_code,
int libdax_msgs_submit(struct libdax_msgs *m, int driveno, int error_code,
int severity, int priority, char *msg_text,
int os_errno, int flag)
{
@ -360,7 +325,7 @@ int libdax_msgs_submit(struct libdax_msgs *m, int origin, int error_code,
ret= libdax_msgs_item_new(&item,m->youngest,0);
if(ret<=0)
goto failed;
item->origin= origin;
item->driveno= driveno;
item->error_code= error_code;
item->severity= severity;
item->priority= priority;

View File

@ -1,8 +1,8 @@
/* libdax_msgs
Message handling facility of libdax.
Copyright (C) 2006-2008 Thomas Schmitt <scdbackup@gmx.net>,
provided under GPL version 2
Copyright (C) 2006-2007 Thomas Schmitt <scdbackup@gmx.net>,
provided under GPL
*/
@ -23,7 +23,7 @@ struct libdax_msgs_item {
double timestamp;
pid_t process_id;
int origin;
int driveno;
int severity;
int priority;
@ -43,8 +43,6 @@ struct libdax_msgs_item {
struct libdax_msgs {
int refcount;
struct libdax_msgs_item *oldest;
struct libdax_msgs_item *youngest;
int count;
@ -70,31 +68,6 @@ struct libdax_msgs {
#ifndef LIBDAX_MSGS_H_INTERNAL
/* Architectural aspects */
/*
libdax_msgs is designed to serve in libraries which want to offer their
applications a way to control the output of library messages. It shall be
incorporated by an owner, i.e. a software entity which encloses the code
of the .c file.
Owner of libdax_msgs is libburn. A fully compatible variant named libiso_msgs
is owned by libisofs and can get generated by a script of the libburn
project: libburn/libdax_msgs_to_xyz_msgs.sh .
Reason: One cannot link two owners of the same variant together because
both would offer the same functions to the linker. For that situation one
has to create a compatible variant as it is done for libisofs.
Compatible variants may get plugged together by call combinations like
burn_set_messenger(iso_get_messenger());
A new variant would demand a _set_messenger() function if it has to work
with libisofs. If only libburn is planned as link partner then a simple
_get_messenger() does suffice.
Take care to shutdown libburn before its provider of the *_msgs object
gets shut down.
*/
/* Public Opaque Handles */
/** A pointer to this is a opaque handle to a message handling facility */
@ -113,26 +86,13 @@ struct libdax_msgs_item;
/* It is well advisable to let applications select severities via strings and
forwarded functions libdax_msgs__text_to_sev(), libdax_msgs__sev_to_text().
These macros are for use by the owner of libdax_msgs.
These macros are for use by libdax/libburn only.
*/
/** Use this to get messages of any severity. Do not use for submitting.
*/
#define LIBDAX_MSGS_SEV_ALL 0x00000000
/** Messages of this severity shall transport plain disk file paths
whenever an event of severity SORRY or above is related with an
individual disk file.
No message text shall be added to the file path. The ERRFILE message
shall be issued before the human readable message which carries the
true event severity. That message should contain the file path so it
can be found by strstr(message, path)!=NULL.
The error code shall be the same as with the human readable message.
*/
#define LIBDAX_MSGS_SEV_ERRFILE 0x08000000
/** Debugging messages not to be visible to normal users by default
*/
#define LIBDAX_MSGS_SEV_DEBUG 0x10000000
@ -153,70 +113,15 @@ struct libdax_msgs_item;
*/
#define LIBDAX_MSGS_SEV_WARNING 0x50000000
/** Non-fatal error messages indicating that parts of an action failed but
processing may go on if one accepts deviations from the desired result.
SORRY may also be the severity for incidents which are severe enough
for FAILURE but happen within already started irrevocable actions,
like ISO image generation. A precondition for such a severity ease is
that the action can be continued after the incident.
See below MISHAP for what xorriso would need instead of this kind of SORRY
and generates for itself in case of libisofs image generation.
E.g.: A pattern yields no result.
A speed setting cannot be made.
A libisofs input file is inaccessible during image generation.
After SORRY a function should try to go on if that makes any sense
and if no threshold prescribes abort on SORRY. The function should
nevertheless indicate some failure in its return value.
It should - but it does not have to.
/** Non-fatal error messages indicating that parts of the action failed
but processing will/should go on
*/
#define LIBDAX_MSGS_SEV_SORRY 0x60000000
/** A FAILURE (see below) which can be tolerated during long lasting
operations just because they cannot simply be stopped or revoked.
xorriso converts libisofs SORRY messages issued during image generation
into MISHAP messages in order to allow its evaluators to distinguish
image generation problems from minor image composition problems.
E.g.:
A libisofs input file is inaccessible during image generation.
After a MISHAP a function should behave like after SORRY.
*/
#define LIBDAX_MSGS_SEV_MISHAP 0x64000000
/** Non-fatal error indicating that an important part of an action failed and
that only a new setup of preconditions will give hope for sufficient
success.
E.g.: No media is inserted in the output drive.
No write mode can be found for inserted media.
A libisofs input file is inaccessible during grafting.
After FAILURE a function should end with a return value indicating failure.
It is at the discretion of the function whether it ends immediately in any
case or whether it tries to go on if the eventual threshold allows.
*/
#define LIBDAX_MSGS_SEV_FAILURE 0x68000000
/** An error message which puts the whole operation of the program in question
E.g.: Not enough memory for essential temporary objects.
Irregular errors from resources.
Programming errors (soft assert).
After FATAL a function should end very soon with a return value
indicating severe failure.
/** An error message which puts the whole operation of libdax in question
*/
#define LIBDAX_MSGS_SEV_FATAL 0x70000000
/** A message from an abort handler which will finally finish libburn
*/
#define LIBDAX_MSGS_SEV_ABORT 0x71000000
@ -229,7 +134,7 @@ struct libdax_msgs_item;
/* Registered Priorities */
/* Priorities are to be selected by the programmers and not by the user. */
/* Priorities are to be used by libburn/libdax only. */
#define LIBDAX_MSGS_PRIO_ZERO 0x00000000
#define LIBDAX_MSGS_PRIO_LOW 0x10000000
@ -241,23 +146,12 @@ struct libdax_msgs_item;
#define LIBDAX_MSGS_PRIO_NEVER 0x7fffffff
/* Origin numbers of libburn drives may range from 0 to 1048575 */
#define LIBDAX_MSGS_ORIGIN_DRIVE_BASE 0
#define LIBDAX_MSGS_ORIGIN_DRIVE_TOP 0xfffff
/* Origin numbers of libisofs images may range from 1048575 to 2097152 */
#define LIBDAX_MSGS_ORIGIN_IMAGE_BASE 0x100000
#define LIBDAX_MSGS_ORIGIN_IMAGE_TOP 0x1fffff
/* Public Functions */
/* Calls initiated from inside the direct owner (e.g. from libburn) */
/* Calls initiated from inside libdax/libburn */
/** Create new empty message handling facility with queue and issue a first
official reference to it.
/** Create new empty message handling facility with queue.
@param flag Bitfield for control purposes (unused yet, submit 0)
@return >0 success, <=0 failure
*/
@ -266,37 +160,18 @@ int libdax_msgs_new(struct libdax_msgs **m, int flag);
/** Destroy a message handling facility and all its eventual messages.
The submitted pointer gets set to NULL.
Actually only the last destroy call of all offical references to the object
will really dispose it. All others just decrement the reference counter.
Call this function only with official reference pointers obtained by
libdax_msgs_new() or libdax_msgs_refer(), and only once per such pointer.
@param flag Bitfield for control purposes (unused yet, submit 0)
@return 1 for success, 0 for pointer to NULL, -1 for fatal error
@return 1 for success, 0 for pointer to NULL
*/
int libdax_msgs_destroy(struct libdax_msgs **m, int flag);
/** Create an official reference to an existing libdax_msgs object. The
references keep the object alive at least until it is released by
a matching number of destroy calls. So each reference MUST be revoked
by exactly one call to libdax_msgs_destroy().
@param pt The pointer to be set and registered
@param m A pointer to the existing object
@param flag Bitfield for control purposes (unused yet, submit 0)
@return 1 for success, 0 for failure
*/
int libdax_msgs_refer(struct libdax_msgs **pt, struct libdax_msgs *o, int flag);
/** Submit a message to a message handling facility.
@param origin program specific identification number of the originator of
a message. E.g. drive number. Programs should have an own
range of origin numbers. See above LIBDAX_MSGS_ORIGIN_*_BASE
Use -1 if no number is known.
@param driveno libdax drive number. Use -1 if no number is known.
@param error_code Unique error code. Use only registered codes. See below.
The same unique error_code may be issued at different
occasions but those should be equivalent out of the view
of a libdax_msgs application. (E.g. "cannot open ATA drive"
of a libdax application. (E.g. "cannot open ATA drive"
versus "cannot open SCSI drive" would be equivalent.)
@param severity The LIBDAX_MSGS_SEV_* of the event.
@param priority The LIBDAX_MSGS_PRIO_* number of the event.
@ -305,13 +180,12 @@ int libdax_msgs_refer(struct libdax_msgs **pt, struct libdax_msgs *o, int flag);
@param flag Bitfield for control purposes (unused yet, submit 0)
@return 1 on success, 0 on rejection, <0 for severe errors
*/
int libdax_msgs_submit(struct libdax_msgs *m, int origin, int error_code,
int libdax_msgs_submit(struct libdax_msgs *m, int driveno, int error_code,
int severity, int priority, char *msg_text,
int os_errno, int flag);
/* Calls from applications (to be forwarded by direct owner) */
/* Calls from applications (to be forwarded by libdax/libburn) */
/** Convert a registered severity number into a severity name
@ -382,7 +256,7 @@ int libdax_msgs_item_get_msg(struct libdax_msgs_item *item,
@return 1 on success, 0 on invalid item, <0 for servere errors
*/
int libdax_msgs_item_get_origin(struct libdax_msgs_item *item,
double *timestamp, pid_t *process_id, int *origin,
double *timestamp, pid_t *process_id, int *driveno,
int flag);
@ -402,7 +276,7 @@ int libdax_msgs_item_get_rank(struct libdax_msgs_item *item,
Format: error_code (LIBDAX_MSGS_SEV_*,LIBDAX_MSGS_PRIO_*) = explanation
If no severity or priority are fixely associated, use "(,)".
If no severity or priority are fixely associates, use "(,)".
------------------------------------------------------------------------------
Range "libdax_msgs" : 0x00000000 to 0x0000ffff
@ -410,7 +284,6 @@ Range "libdax_msgs" : 0x00000000 to 0x0000ffff
0x00000000 (ALL,ZERO) = Initial setting in new libdax_msgs_item
0x00000001 (DEBUG,ZERO) = Test error message
0x00000002 (DEBUG,ZERO) = Debugging message
0x00000003 (FATAL,HIGH) = Out of virtual memory
------------------------------------------------------------------------------
@ -431,9 +304,6 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
0x00020006 (FATAL,HIGH) = Too many scsi siblings
0x00020007 (NOTE,HIGH) = Closed O_EXCL scsi siblings
0x00020008 (SORRY,HIGH) = Device busy. Failed to fcntl-lock
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
General library operations:
@ -443,7 +313,7 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
0x00020104 (SORRY,HIGH) = NULL pointer caught
0x00020105 (SORRY,HIGH) = Drive is already released
0x00020106 (SORRY,HIGH) = Drive is busy on attempt to close
0x00020107 (WARNING,HIGH) = A drive is still busy on shutdown of library
0x00020107 (SORRY,HIGH) = Drive is busy on attempt to shut down library
0x00020108 (SORRY,HIGH) = Drive is not grabbed on disc status inquiry
0x00020108 (FATAL,HIGH) = Could not allocate new drive object
0x00020109 (FATAL,HIGH) = Library not running
@ -501,153 +371,13 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
0x0002013d (DEBUG,LOW) = Waiting for free buffer space takes long time
0x0002013e (SORRY,HIGH) = Timeout with waiting for free buffer. Now disabled
0x0002013f (DEBUG,LOW) = Reporting total time spent with waiting for buffer
0x00020140 (FATAL,HIGH) = Drive is busy on attempt to write random access
0x00020141 (SORRY,HIGH) = Write data count not properly aligned
0x00020142 (FATAL,HIGH) = Drive is not grabbed on random access write
0x00020143 (SORRY,HIGH) = Read start address not properly aligned
0x00020144 (SORRY,HIGH) = SCSI error on read
0x00020145 (FATAL,HIGH) = Drive is busy on attempt to read data
0x00020146 (FATAL,HIGH) = Drive is a virtual placeholder
0x00020147 (SORRY,HIGH) = Cannot address start byte
0x00020148 (SORRY,HIGH) = Cannot write desired amount of data
0x00020149 (SORRY,HIGH) = Unsuitable filetype for pseudo-drive
0x0002014a (SORRY,HIGH) = Cannot read desired amount of data
0x0002014b (SORRY,HIGH) = Drive is already registered resp. scanned
0x0002014c (FATAL,HIGH) = Emulated drive caught in SCSI function
0x0002014d (SORRY,HIGH) = Asynchromous SCSI error
0x0002014f (SORRY,HIGH) = Timeout with asynchromous SCSI command
0x00020150 (DEBUG,LOW) = Reporting asynchronous waiting time
0x00020151 (FATAL,HIGH) = Read attempt on write-only drive
0x00020152 (FATAL,HIGH) = Cannot start fifo thread
0x00020153 (SORRY,HIGH) = Read error on fifo input
0x00020154 (NOTE,HIGH) = Forwarded input error ends output
0x00020155 (SORRY,HIGH) = Desired fifo buffer too large
0x00020156 (SORRY,HIGH) = Desired fifo buffer too small
0x00020157 (FATAL,HIGH) = burn_source is not a fifo object
0x00020158 (DEBUG,LOW) = Reporting thread disposal precautions
0x00020159 (DEBUG,HIGH) = TOC Format 0 returns inconsistent data
0x0002015a (NOTE,HIGH) = Could not examine busy device
0x0002015b (HINT,HIGH) = Busy '...' seems to be a hard disk, as '...1' exists
0x0002015c (FAILURE,HIGH) = Fifo size is smaller than desired peek buffer
0x0002015d (FAILURE,HIGH) = Fifo input ended short of desired peek buffer size
0x0002015e (FATAL,HIGH) = Fifo is already under consumption when peeking
libdax_audioxtr:
0x00020200 (SORRY,HIGH) = Cannot open audio source file
0x00020201 (SORRY,HIGH) = Audio source file has unsuitable format
0x00020202 (SORRY,HIGH) = Failed to prepare reading of audio data
------------------------------------------------------------------------------
Range "vreixo" : 0x00030000 to 0x0003ffff
0x0003ffff (FAILURE,HIGH) = Operation canceled
0x0003fffe (FATAL,HIGH) = Unknown or unexpected fatal error
0x0003fffd (FAILURE,HIGH) = Unknown or unexpected error
0x0003fffc (FATAL,HIGH) = Internal programming error
0x0003fffb (FAILURE,HIGH) = NULL pointer where NULL not allowed
0x0003fffa (FATAL,HIGH) = Memory allocation error
0x0003fff9 (FATAL,HIGH) = Interrupted by a signal
0x0003fff8 (FAILURE,HIGH) = Invalid parameter value
0x0003fff7 (FATAL,HIGH) = Cannot create a needed thread
0x0003fff6 (FAILURE,HIGH) = Write error
0x0003fff5 (FAILURE,HIGH) = Buffer read error
0x0003ffc0 (FAILURE,HIGH) = Trying to add a node already added to another dir
0x0003ffbf (FAILURE,HIGH) = Node with same name already exist
0x0003ffbe (FAILURE,HIGH) = Trying to remove a node that was not added to dir
0x0003ffbd (FAILURE,HIGH) = A requested node does not exist
0x0003ffbc (FAILURE,HIGH) = Image already bootable
0x0003ffbb (FAILURE,HIGH) = Trying to use an invalid file as boot image
0x0003ff80 (FAILURE,HIGH) = Error on file operation
0x0003ff7f (FAILURE,HIGH) = Trying to open an already openned file
0x0003ff7e (FAILURE,HIGH) = Access to file is not allowed
0x0003ff7d (FAILURE,HIGH) = Incorrect path to file
0x0003ff7c (FAILURE,HIGH) = The file does not exist in the filesystem
0x0003ff7b (FAILURE,HIGH) = Trying to read or close a file not openned
0x0003ff7a (FAILURE,HIGH) = Directory used where no dir is expected
0x0003ff79 (FAILURE,HIGH) = File read error
0x0003ff78 (FAILURE,HIGH) = Not dir used where a dir is expected
0x0003ff77 (FAILURE,HIGH) = Not symlink used where a symlink is expected
0x0003ff76 (FAILURE,HIGH) = Cannot seek to specified location
0x0003ff75 (HINT,MEDIUM) = File not supported in ECMA-119 tree and ignored
0x0003ff74 (HINT,MEDIUM) = File bigger than supported by used standard
0x0003ff73 (MISHAP,HIGH) = File read error during image creation
0x0003ff72 (HINT,MEDIUM) = Cannot convert filename to requested charset
0x0003ff71 (SORRY,HIGH) = File cannot be added to the tree
0x0003ff70 (HINT,MEDIUM) = File path breaks specification constraints
0x0003ff00 (FAILURE,HIGH) = Charset conversion error
0x0003feff (FAILURE,HIGH) = Too much files to mangle
0x0003fec0 (FAILURE,HIGH) = Wrong or damaged Primary Volume Descriptor
0x0003febf (SORRY,HIGH) = Wrong or damaged RR entry
0x0003febe (SORRY,HIGH) = Unsupported RR feature
0x0003febd (FAILURE,HIGH) = Wrong or damaged ECMA-119
0x0003febc (FAILURE,HIGH) = Unsupported ECMA-119 feature
0x0003febb (SORRY,HIGH) = Wrong or damaged El-Torito catalog
0x0003feba (SORRY,HIGH) = Unsupported El-Torito feature
0x0003feb9 (SORRY,HIGH) = Cannot patch isolinux boot image
0x0003feb8 (SORRY,HIGH) = Unsupported SUSP feature
0x0003feb7 (WARNING,HIGH) = Error on a RR entry that can be ignored
0x0003feb6 (HINT,MEDIUM) = Error on a RR entry that can be ignored
0x0003feb5 (WARNING,HIGH) = Multiple ER SUSP entries found
0x0003feb4 (HINT,MEDIUM) = Unsupported volume descriptor found
0x0003feb3 (WARNING,HIGH) = El-Torito related warning
0x0003feb2 (MISHAP,HIGH) = Image write cancelled
0x0003feb1 (WARNING,HIGH) = El-Torito image is hidden
Outdated codes which may not be re-used for other purposes than
re-instating them, if ever:
X 0x00031001 (SORRY,HIGH) = Cannot read file (ignored)
X 0x00031002 (FATAL,HIGH) = Cannot read file (operation canceled)
X 0x00031000 (FATAL,HIGH) = Unsupported ISO-9660 image
X 0x00031001 (HINT,MEDIUM) = Unsupported Vol Desc that will be ignored
X 0x00031002 (FATAL,HIGH) = Damaged ISO-9660 image
X 0x00031003 (SORRY,HIGH) = Cannot read previous image file
X 0x00030101 (HINT,MEDIUM) = Unsupported SUSP entry that will be ignored
X 0x00030102 (SORRY,HIGH) = Wrong/damaged SUSP entry
X 0x00030103 (WARNING,MEDIUM)= Multiple SUSP ER entries where found
X 0x00030111 (SORRY,HIGH) = Unsupported RR feature
X 0x00030112 (SORRY,HIGH) = Error in a Rock Ridge entry
X 0x00030201 (HINT,MEDIUM) = Unsupported Boot Vol Desc that will be ignored
X 0x00030202 (SORRY,HIGH) = Wrong El-Torito catalog
X 0x00030203 (HINT,MEDIUM) = Unsupported El-Torito feature
X 0x00030204 (SORRY,HIGH) = Invalid file to be an El-Torito image
X 0x00030205 (WARNING,MEDIUM)= Cannot properly patch isolinux image
X 0x00030206 (WARNING,MEDIUM)= Copying El-Torito from a previous image without
X enought info about it
X 0x00030301 (NOTE,MEDIUM) = Unsupported file type for Joliet tree
------------------------------------------------------------------------------
Range "application" : 0x00040000 to 0x0004ffff
0x00040000 (ABORT,HIGH) : Application supplied message
0x00040001 (FATAL,HIGH) : Application supplied message
0x00040002 (SORRY,HIGH) : Application supplied message
0x00040003 (WARNING,HIGH) : Application supplied message
0x00040004 (HINT,HIGH) : Application supplied message
0x00040005 (NOTE,HIGH) : Application supplied message
0x00040006 (UPDATE,HIGH) : Application supplied message
0x00040007 (DEBUG,HIGH) : Application supplied message
0x00040008 (*,HIGH) : Application supplied message
------------------------------------------------------------------------------
Range "libisofs-xorriso" : 0x00050000 to 0x0005ffff
This is an alternative representation of libisofs.so.6 error codes in xorriso.
If values returned by iso_error_get_code() do not fit into 0x30000 to 0x3ffff
then they get truncated to 16 bit and mapped into this range.
(This should never need to happen, of course.)
------------------------------------------------------------------------------
Range "libisoburn" : 0x00060000 to 0x00006ffff
0x00060000 (*,*) : Message which shall be attributed to libisoburn
>>> the messages of libisoburn need to be registered individually
------------------------------------------------------------------------------

View File

@ -1,37 +0,0 @@
#!/bin/sh
# libdax_msgs_to_iso_msgs.sh
# generates ${xyz}_msgs.[ch] from libdax_msgs.[ch]
# To be executed within ./libburn-* resp ./cdrskin-*
# The module name for the generated sourcecode in several
# uppercase-lowercase forms
xyz="libiso"
Xyz="Libiso"
XYZ="LIBISO"
# The project name for which the generated code shall serve
project="libisofs"
for i in libburn/libdax_msgs.[ch]
do
target_adr=$(echo "$i" | sed -e "s/libdax_/${xyz}_/")
echo "$target_adr"
sed \
-e "s/^\/\* libdax_msgs/\/* ${xyz}_msgs (generated from XYZ_msgs : $(date))/" \
-e "s/Message handling facility of libdax/Message handling facility of ${project}/" \
-e "s/libdax_/${xyz}_/g" \
-e "s/libdax:/${xyz}:/g" \
-e "s/Libdax_/${Xyz}_/g" \
-e "s/LIBDAX_/${XYZ}_/g" \
-e "s/generated from XYZ_msgs/generated from libdax_msgs/" \
-e "s/${xyz}_msgs is designed to serve in libraries/libdax_msgs is designed to serve in libraries/" \
-e "s/Owner of ${xyz}_msgs is libburn/Owner of libdax_msgs is libburn/" \
\
<"$i" >"$target_adr"
done

File diff suppressed because it is too large Load Diff

View File

@ -68,11 +68,6 @@ int mmc_compose_mode_page_5(struct burn_drive *d,
const struct burn_write_opts *o,
unsigned char *pd);
/* ts A70812 : return 0 = ok , return BE_CANCELLED = error occured */
int mmc_read_10(struct burn_drive *d, int start, int amount,
struct buffer *buf);
/* mmc5r03c.pdf 4.3.4.4.1 d) "The maximum number of RZones is 2 302." */
#define BURN_MMC_FAKE_TOC_MAX_SIZE 2302

View File

@ -38,7 +38,6 @@ struct burn_write_opts *burn_write_opts_new(struct burn_drive *drive)
opts->start_byte = -1;
opts->fill_up_media = 0;
opts->force_is_set = 0;
opts->do_stream_recording = 0;
opts->has_mediacatalog = 0;
opts->format = BURN_CDROM;
opts->multi = 0;
@ -143,8 +142,6 @@ int burn_write_opts_set_simulate(struct burn_write_opts *opts, int sim)
int burn_write_opts_set_underrun_proof(struct burn_write_opts *opts,
int underrun_proof)
{
if (!opts->drive->mdata->valid)
return 0;
if (opts->drive->mdata->underrun_proof) {
opts->underrun_proof = underrun_proof;
return 1;
@ -381,23 +378,6 @@ void burn_write_opts_set_force(struct burn_write_opts *opts, int use_force)
}
/* ts A80412: API */
void burn_write_opts_set_stream_recording(struct burn_write_opts *opts,
int value)
{
opts->do_stream_recording = !!value;
}
/* ts A70901: API */
struct burn_drive *burn_write_opts_get_drive(struct burn_write_opts *opts)
{
return opts->drive;
}
void burn_read_opts_set_raw(struct burn_read_opts *opts, int raw)
{
opts->raw = raw;

View File

@ -49,11 +49,6 @@ struct burn_write_opts
*/
int force_is_set;
/* ts A80412 : whether to use WRITE12 with Streaming bit set
rather than WRITE10. Speeds up DVD-RAM. Might help with BD-RE.
This gets transferred to burn_drive.do_stream_recording */
int do_stream_recording;
/** A disc can have a media catalog number */
int has_mediacatalog;
unsigned char mediacatalog[13];

View File

@ -43,25 +43,16 @@ SIGKILL, SIGCHLD, SIGSTOP, SIGURG, SIGWINCH
/* The maximum size for a (SCSI) i/o transaction */
/* Important : MUST be at least 32768 ! */
/* ts A70523 : >32k seems not good with kernel 2.4 USB drivers and audio
#define BURN_OS_TRANSPORT_BUFFER_SIZE 32768
*/
/* ts A80414 : curbed in write.c CD media to Libburn_cd_obS = 32 kiB
re-enlarged transport to 64 kiB for BD-RE experiments
*/
#define BURN_OS_TRANSPORT_BUFFER_SIZE 65536
*/
#define BURN_OS_TRANSPORT_BUFFER_SIZE 32768
/* To hold the position of the most recently delivered address from
/* To hold the index number of the most recently delivered address from
device enumeration.
*/
struct burn_drive_enumerator_struct {
int pos;
int info_count;
char **info_list;
};
#define BURN_OS_DEFINE_DRIVE_ENUMERATOR_T \
typedef struct burn_drive_enumerator_struct burn_drive_enumerator_t;
typedef int burn_drive_enumerator_t;
/* Parameters for sibling list. See sibling_fds, sibling_fnames */

View File

@ -12,9 +12,6 @@
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <errno.h>
#include "sector.h"
#include "libburn.h"
#include "drive.h"
@ -34,12 +31,6 @@
#include "read.h"
#include "options.h"
/* ts A70812 */
#include "error.h"
#include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger;
void burn_disc_read(struct burn_drive *d, const struct burn_read_opts *o)
{
#if 0
@ -289,203 +280,3 @@ static void flipq(unsigned char *sub)
*(sub + 12 + 11) = ~*(sub + 12 + 11);
}
*/
/* ts A70904 */
/** @param flag bit0=be silent on data shortage */
int burn_stdio_read(int fd, char *buf, int bufsize, struct burn_drive *d,
int flag)
{
int todo, count = 0;
for(todo = bufsize; todo > 0; ) {
count = read(fd, buf + (bufsize - todo), todo);
if(count <= 0)
break;
todo -= count;
}
if(todo > 0 && !(flag & 1)) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x0002014a,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Cannot read desired amount of data", errno, 0);
}
if (count < 0)
return -1;
return (bufsize - todo);
}
/* ts A70812 : API function */
int burn_read_data(struct burn_drive *d, off_t byte_address,
char data[], off_t data_size, off_t *data_count, int flag)
{
int alignment = 2048, start, upto, chunksize = 1, err, cpy_size, i;
int sose_mem = 0, fd = -1, ret;
char msg[81], *wpt;
struct buffer buf, *buffer_mem = d->buffer;
/*
#define Libburn_read_data_adr_logginG 1
*/
#ifdef Libburn_read_data_adr_logginG
static FILE *log_fp= NULL;
if(log_fp == NULL)
log_fp = fopen("/tmp/burn_read_data_log", "a");
if(log_fp!=NULL)
fprintf(log_fp, "%d\n", (int) (byte_address / 2048));
#endif /* Libburn_read_data_logginG */
*data_count = 0;
sose_mem = d->silent_on_scsi_error;
if (d->released) {
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x00020142,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Drive is not grabbed on random access read", 0, 0);
return 0;
}
if (d->drive_role == 0) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020146,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Drive is a virtual placeholder (null-drive)", 0, 0);
return 0;
} else if (d->drive_role == 3) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020151,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Read attempt on write-only drive", 0, 0);
return 0;
}
if ((byte_address % alignment) != 0) {
sprintf(msg,
"Read start address not properly aligned (%d bytes)",
alignment);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020143,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
return 0;
}
if (d->busy != BURN_DRIVE_IDLE) {
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x00020145,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Drive is busy on attempt to read data", 0, 0);
return 0;
}
if (d->drive_role != 1) {
/* <<< We need _LARGEFILE64_SOURCE defined by the build system.
*/
#ifndef O_LARGEFILE
#define O_LARGEFILE 0
#endif
fd = d->stdio_fd;
if (fd < 0)
d->stdio_fd = fd =
open(d->devname, O_RDONLY | O_LARGEFILE);
if (fd == -1) {
if (errno != ENOENT || !(flag & 2))
libdax_msgs_submit(libdax_messenger,
d->global_index,
0x00020005,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Failed to open device (a pseudo-drive) for reading",
errno, 0);
ret = 0; goto ex;
}
if (lseek(fd, byte_address, SEEK_SET) == -1) {
if (!(flag & 2))
libdax_msgs_submit(libdax_messenger,
d->global_index,
0x00020147,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Cannot address start byte", errno, 0);
ret = 0; goto ex;
}
}
d->busy = BURN_DRIVE_READING_SYNC;
d->buffer = &buf;
start = byte_address / 2048;
upto = start + data_size / 2048;
if (data_size % 2048)
upto++;
wpt = data;
for (; start < upto; start += chunksize) {
chunksize = upto - start;
if (chunksize > 16) {
chunksize = 16;
cpy_size = 16 * 2048;
} else
cpy_size = data_size - *data_count;
if (flag & 2)
d->silent_on_scsi_error = 1;
if (d->drive_role == 1) {
err = d->read_10(d, start, chunksize, d->buffer);
} else {
ret = burn_stdio_read(fd, (char *) d->buffer->data,
cpy_size, d, !!(flag & 2));
err = 0;
if (ret <= 0)
err = BE_CANCELLED;
}
if (flag & 2)
d->silent_on_scsi_error = sose_mem;
if (err == BE_CANCELLED) {
/* Try to read a smaller part of the chunk */
if(!(flag & 4))
for (i = 0; i < chunksize - 1; i++) {
if (flag & 2)
d->silent_on_scsi_error = 1;
if (d->drive_role == 1) {
err = d->read_10(d, start + i, 1,
d->buffer);
} else {
ret = burn_stdio_read(fd,
(char *) d->buffer->data,
2048, d, 1);
if (ret <= 0)
err = BE_CANCELLED;
}
if (flag & 2)
d->silent_on_scsi_error = sose_mem;
if (err == BE_CANCELLED)
break;
memcpy(wpt, d->buffer->data, 2048);
wpt += 2048;
*data_count += 2048;
}
if (!(flag & 2))
libdax_msgs_submit(libdax_messenger,
d->global_index,
0x00020000,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
"burn_read_data() returns 0",
0, 0);
ret = 0; goto ex;
}
memcpy(wpt, d->buffer->data, cpy_size);
wpt += cpy_size;
*data_count += cpy_size;
}
ret = 1;
ex:;
/* <<< let it open until drive is given up or writing shall happen
if (fd != -1)
close(fd);
*/
d->buffer = buffer_mem;
d->busy = BURN_DRIVE_IDLE;
return ret;
}

View File

@ -10,13 +10,6 @@
#include "spc.h"
#include "options.h"
/* ts A70910
debug: for tracing calls which might use open drive fds
or for catching SCSI usage of emulated drives. */
int mmc_function_spy(struct burn_drive *d, char * text);
/* spc command set */
static unsigned char SBC_LOAD[] = { 0x1b, 0, 0, 0, 3, 0 };
static unsigned char SBC_UNLOAD[] = { 0x1b, 0, 0, 0, 2, 0 };
@ -26,9 +19,6 @@ void sbc_load(struct burn_drive *d)
{
struct command c;
if (mmc_function_spy(d, "load") <= 0)
return;
scsi_init_command(&c, SBC_LOAD, sizeof(SBC_LOAD));
/*
memcpy(c.opcode, SBC_LOAD, sizeof(SBC_LOAD));
@ -36,43 +26,24 @@ void sbc_load(struct burn_drive *d)
c.page = NULL;
*/
c.retry = 1;
/* ts A70921 : Had to revoke Immed because of LG GSA-4082B */
/* c.opcode[1] |= 1; / * ts A70918 : Immed */
c.dir = NO_TRANSFER;
d->issue_command(d, &c);
if (c.error)
return;
/* ts A70923 : Needed regardless of Immed bit. Was once 1 minute, now
5 minutes for loading. If this does not suffice then other commands
shall fail righteously. */
spc_wait_unit_attention(d, 300, "waiting after START UNIT (+ LOAD)",0);
spc_wait_unit_attention(d, 60);
}
void sbc_eject(struct burn_drive *d)
{
struct command c;
if (mmc_function_spy(d, "eject") <= 0)
return;
scsi_init_command(&c, SBC_UNLOAD, sizeof(SBC_UNLOAD));
/*
memcpy(c.opcode, SBC_UNLOAD, sizeof(SBC_UNLOAD));
c.oplen = sizeof(SBC_UNLOAD);
c.page = NULL;
*/
c.opcode[1] |= 1; /* ts A70918 : Immed */
c.page = NULL;
c.dir = NO_TRANSFER;
d->issue_command(d, &c);
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);
}
/* ts A61118 : is it necessary to tell the drive to get ready for use ? */
@ -80,9 +51,6 @@ int sbc_start_unit(struct burn_drive *d)
{
struct command c;
if (mmc_function_spy(d, "start_unit") <= 0)
return 0;
scsi_init_command(&c, SBC_START_UNIT, sizeof(SBC_START_UNIT));
/*
memcpy(c.opcode, SBC_START_UNIT, sizeof(SBC_START_UNIT));
@ -90,15 +58,9 @@ int sbc_start_unit(struct burn_drive *d)
c.page = NULL;
*/
c.retry = 1;
c.opcode[1] |= 1; /* ts A70918 : Immed */
c.dir = NO_TRANSFER;
d->issue_command(d, &c);
if (c.error)
return 0;
/* ts A70918 : now asynchronous */
return spc_wait_unit_attention(d, 1800, "START UNIT", 0);
return (c.error==0);
}

View File

@ -123,12 +123,7 @@ static void get_bytes(struct burn_track *track, int count, unsigned char *data)
/* Next we use source data */
curr = valid;
if (!track->eos) {
if (track->source->read != NULL)
valid = track->source->read(track->source,
data + curr, count - curr);
else
valid = track->source->read_xt(track->source,
data + curr, count - curr);
valid = track->source->read(track->source, data + curr, count - curr);
} else valid = 0;
if (valid <= 0) { /* ts A61031 : extended from (valid == -1) */

View File

@ -48,8 +48,6 @@ sg_issue_command() sends a SCSI command to the drive, receives reply,
sg_obtain_scsi_adr() tries to obtain SCSI address parameters.
burn_os_stdio_capacity() estimates the emulated media space of stdio-drives.
Porting hints are marked by the text "PORTING:".
Send feedback to libburn-hackers@pykix.org .
@ -76,10 +74,6 @@ Send feedback to libburn-hackers@pykix.org .
#include <err.h> /* XXX */
/* ts A70909 : >>> untestet yet wether this compiles */
#include <sys/statvfs.h>
/** PORTING : ------ libburn portable headers and definitions ----- */
#include "transport.h"
@ -563,69 +557,3 @@ int sg_is_enumerable_adr(char* adr)
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
exist yet, then the directory will be inquired.
@param bytes This value gets modified 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;
struct statvfs vfsbuf;
char testpath[4096], *cpt;
long blocks;
int open_mode = O_RDWR, fd, ret;
off_t add_size = 0;
testpath[0] = 0;
blocks = *bytes / 512;
if (stat(path, &stbuf) == -1) {
strcpy(testpath, path);
cpt = strrchr(testpath, '/');
if(cpt == NULL)
strcpy(testpath, ".");
else if(cpt == testpath)
testpath[1] = 0;
else
*cpt = 0;
if (stat(testpath, &stbuf) == -1)
return -1;
#ifdef Libburn_if_this_was_linuX
} else if(S_ISBLK(stbuf.st_mode)) {
if(burn_sg_open_o_excl)
open_mode |= O_EXCL;
fd = open(path, open_mode);
if (fd == -1)
return -2;
ret = ioctl(fd, BLKGETSIZE, &blocks);
close(fd);
if (ret == -1)
return -2;
*bytes = ((off_t) blocks) * (off_t) 512;
#endif /* Libburn_if_this_was_linuX */
} else if(S_ISREG(stbuf.st_mode)) {
add_size = stbuf.st_blocks * (off_t) 512;
strcpy(testpath, path);
} else
return 0;
if (testpath[0]) {
if (statvfs(testpath, &vfsbuf) == -1)
return -2;
*bytes = add_size + ((off_t) vfsbuf.f_bsize) *
(off_t) vfsbuf.f_bavail;
}
return 1;
}

View File

@ -18,10 +18,6 @@
#include <err.h> /* XXX */
/* ts A70909 : >>> untestet yet wether this compiles */
#include <sys/statvfs.h>
#include "transport.h"
#include "drive.h"
#include "sg.h"
@ -50,9 +46,8 @@ int burn_drive_is_banned(char *device_address);
/* ts A60821
debug: for tracing calls which might use open drive fds
or for catching SCSI usage of emulated drives. */
int mmc_function_spy(struct burn_drive *d, char * text);
<<< debug: for tracing calls which might use open drive fds */
int mmc_function_spy(char * text);
/* ts A61021 : Moved most code from scsi_enumerate_drives under
@ -391,7 +386,7 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
mmc_function_spy(NULL, "enumerate_common : -------- doing grab");
mmc_function_spy("enumerate_common : -------- doing grab");
/* try to get the drive info */
if (t->grab(t)) {
@ -405,7 +400,7 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
mmc_function_spy(NULL, "enumerate_common : ----- would release ");
mmc_function_spy("enumerate_common : ----- would release ");
}
@ -453,8 +448,7 @@ int sg_grab(struct burn_drive *d)
int count;
struct cam_device *cam;
if (mmc_function_spy(d, "sg_grab") <= 0)
return 0;
mmc_function_spy("sg_grab");
if (burn_drive_is_open(d)) {
d->released = 0;
@ -489,15 +483,14 @@ int sg_grab(struct burn_drive *d)
int sg_release(struct burn_drive *d)
{
if (mmc_function_spy(d, "sg_release") <= 0)
return 0;
mmc_function_spy("sg_release");
if (d->cam == NULL) {
burn_print(1, "release an ungrabbed drive. die\n");
return 0;
}
mmc_function_spy(NULL, "sg_release ----------- closing.");
mmc_function_spy("sg_release ----------- closing.");
sg_close_drive(d);
d->released = 1;
@ -513,7 +506,7 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
char buf[161];
snprintf(buf, sizeof (buf), "sg_issue_command d->cam=%p d->released=%d",
(void*)d->cam, d->released);
mmc_function_spy(NULL, buf);
mmc_function_spy(buf);
if (d->cam == NULL) {
c->error = 0;
@ -605,69 +598,3 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
return 1;
}
/* 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
exist yet, then the directory will be inquired.
@param bytes This value gets modified 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;
struct statvfs vfsbuf;
char testpath[4096], *cpt;
long blocks;
int open_mode = O_RDWR, fd, ret;
off_t add_size = 0;
testpath[0] = 0;
blocks = *bytes / 512;
if (stat(path, &stbuf) == -1) {
strcpy(testpath, path);
cpt = strrchr(testpath, '/');
if(cpt == NULL)
strcpy(testpath, ".");
else if(cpt == testpath)
testpath[1] = 0;
else
*cpt = 0;
if (stat(testpath, &stbuf) == -1)
return -1;
#ifdef Libburn_if_this_was_linuX
} else if(S_ISBLK(stbuf.st_mode)) {
if(burn_sg_open_o_excl)
open_mode |= O_EXCL;
fd = open(path, open_mode);
if (fd == -1)
return -2;
ret = ioctl(fd, BLKGETSIZE, &blocks);
close(fd);
if (ret == -1)
return -2;
*bytes = ((off_t) blocks) * (off_t) 512;
#endif /* Libburn_if_this_was_linuX */
} else if(S_ISREG(stbuf.st_mode)) {
add_size = stbuf.st_blocks * (off_t) 512;
strcpy(testpath, path);
} else
return 0;
if (testpath[0]) {
if (statvfs(testpath, &vfsbuf) == -1)
return -2;
*bytes = add_size + ((off_t) vfsbuf.f_bsize) *
(off_t) vfsbuf.f_bavail;
}
return 1;
}

View File

@ -48,8 +48,6 @@ sg_issue_command() sends a SCSI command to the drive, receives reply,
sg_obtain_scsi_adr() tries to obtain SCSI address parameters.
burn_os_stdio_capacity() estimates the emulated media space of stdio-drives.
Porting hints are marked by the text "PORTING:".
Send feedback to libburn-hackers@pykix.org .
@ -75,11 +73,6 @@ Hint: You should also look into sg-freebsd-port.c, which is a younger and
#include <stdlib.h>
#include <sys/utsname.h>
#include <scsi/scsi.h>
#include <sys/statvfs.h>
/* for ioctl(BLKGETSIZE) */
#include <linux/fs.h>
#include <scsi/sg.h>
/* Values within sg_io_hdr_t indicating success after ioctl(SG_IO) : */
@ -90,7 +83,6 @@ Hint: You should also look into sg-freebsd-port.c, which is a younger and
/* ts A61211 : to eventually recognize CD devices on /dev/sr* */
#include <limits.h>
#include <linux/cdrom.h>
@ -202,9 +194,8 @@ extern int burn_sg_open_abort_busy;
/* ts A60821
debug: for tracing calls which might use open drive fds
or for catching SCSI usage of emulated drives. */
int mmc_function_spy(struct burn_drive *d, char * text);
<<< debug: for tracing calls which might use open drive fds */
int mmc_function_spy(char * text);
/* ------------------------------------------------------------------------ */
@ -260,37 +251,6 @@ static void sg_select_device_family(void)
}
/* ts A80701 */
/* This cares for the case that no /dev/srNN but only /dev/scdNN exists.
A theoretical case which has its complement in SuSE 10.2 having
/dev/sr but not /dev/scd.
*/
static int sg_exchange_scd_for_sr(char *fname, int flag)
{
struct stat stbuf;
char scd[17], msg[160];
if (burn_sg_use_family != 0 || strncmp(fname, "/dev/sr", 7)!=0 ||
strlen(fname)>9 || strlen(fname)<8)
return 2;
if (fname[7] < '0' || fname[7] > '9')
return 2;
if (fname [8] != 0 && (fname[7] < '0' || fname[7] > '9'))
return 2;
if (stat(fname, &stbuf) != -1)
return 2;
strcpy(scd, "/dev/scd");
strcpy(scd + 8, fname + 7);
if (stat(scd, &stbuf) == -1)
return 2;
sprintf(msg, "%s substitutes for non-existent %s", scd, fname);
libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0);
strcpy(fname, scd);
return 1;
}
static int sgio_test(int fd)
{
unsigned char test_ops[] = { 0, 0, 0, 0, 0, 0 };
@ -310,33 +270,6 @@ static int sgio_test(int fd)
static int sg_handle_busy_device(char *fname, int os_errno)
{
char msg[4096];
struct stat stbuf;
int looks_like_hd= 0, fd, ret;
/* ts A80713 :
check existence of /dev/hdX1 as hint for hard disk rather than CD
Hint by Giulio Orsero: check /proc/ide/hdX/media for "disk"
*/
if (strncmp(fname, "/dev/hd", 7)==0) {
sprintf(msg, "%s1", fname);
if (stat(msg, &stbuf) != -1)
looks_like_hd= 1;
sprintf(msg, "/proc/ide/hd%c/media", fname[7]);
fd = open(msg, O_RDONLY);
if (fd != -1) {
ret = read(fd, msg, 10);
if (ret < 0)
ret = 0;
msg[ret]= 0;
close(fd);
if (strncmp(msg, "disk\n", 5) == 0 ||
strcmp(msg, "disk") == 0)
looks_like_hd= 2;
else if (strncmp(msg, "cdrom\n", 6) == 0 ||
strcmp(msg, "cdrom") == 0)
looks_like_hd= 0;
}
}
/* ts A60814 : i saw no way to do this more nicely */
if (burn_sg_open_abort_busy) {
@ -350,26 +283,10 @@ static int sg_handle_busy_device(char *fname, int os_errno)
}
/* ts A60924 : now reporting to libdax_msgs */
if (looks_like_hd == 2) { /* is surely hard disk */
;
} else if (looks_like_hd) {
sprintf(msg, "Could not examine busy device '%s'", fname);
libdax_msgs_submit(libdax_messenger, -1, 0x0002015a,
LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_LOW,
msg, os_errno, 0);
sprintf(msg,
"Busy '%s' seems to be a hard disk, as '%s1' exists. But better check.",
fname, fname);
libdax_msgs_submit(libdax_messenger, -1, 0x0002015b,
LIBDAX_MSGS_SEV_HINT, LIBDAX_MSGS_PRIO_LOW,
msg, 0, 0);
} else {
sprintf(msg, "Cannot open busy device '%s'", fname);
libdax_msgs_submit(libdax_messenger, -1, 0x00020001,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_LOW,
msg, os_errno, 0);
}
sprintf(msg, "Cannot open busy device '%s'", fname);
libdax_msgs_submit(libdax_messenger, -1, 0x00020001,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_LOW,
msg, os_errno, 0);
return 1;
}
@ -382,28 +299,6 @@ static int sg_close_drive_fd(char *fname, int driveno, int *fd, int sorry)
if(*fd < 0)
return(0);
#ifdef CDROM_MEDIA_CHANGED_disabled_because_not_helpful
#ifdef CDSL_CURRENT
/* ts A80217 : wondering whether the os knows about our activities */
ret = ioctl(*fd, CDROM_MEDIA_CHANGED, CDSL_CURRENT);
sprintf(msg, "ioctl(CDROM_MEDIA_CHANGED) == %d", ret);
libdax_msgs_submit(libdax_messenger, driveno, 0x00000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0);
#ifdef BLKFLSBUF_disabled_because_not_helpful
ret = ioctl(*fd, BLKFLSBUF, 0);
sprintf(msg, "ioctl(BLKFLSBUF) == %d", ret);
os_errno = 0;
if(ret == -1)
os_errno = errno;
libdax_msgs_submit(libdax_messenger, driveno, 0x00000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, msg, os_errno,0);
#endif /* BLKFLSBUF */
#endif /* CDSL_CURRENT */
#endif /* CDROM_MEDIA_CHANGED */
ret = close(*fd);
*fd = -1337;
if(ret != -1) {
@ -644,193 +539,12 @@ failed:;
}
#define Libburn_drive_new_deaL 1
#ifdef Libburn_drive_new_deaL
/* ts A80731 */
static int is_ata_drive(char *fname)
{
int fd;
struct hd_driveid tm;
fd = sg_open_drive_fd(fname, 1);
if (fd == -1) {
if (linux_ata_enumerate_verbous)
fprintf(stderr,"open failed, errno=%d '%s'\n",
errno, strerror(errno));
return 0;
}
memset(&tm, 0, sizeof(tm));
ioctl(fd, HDIO_GET_IDENTITY, &tm);
/* not atapi */
if (!(tm.config & 0x8000) || (tm.config & 0x4000)) {
if (linux_ata_enumerate_verbous)
fprintf(stderr, "not marked as ATAPI\n");
sg_close_drive_fd(fname, -1, &fd, 0);
return 0;
}
/* if SG_IO fails on an atapi device, we should stop trying to
use hd* devices */
if (sgio_test(fd) == -1) {
if (linux_ata_enumerate_verbous)
fprintf(stderr,
"FATAL: sgio_test() failed: errno=%d '%s'\n",
errno, strerror(errno));
sg_close_drive_fd(fname, -1, &fd, 0);
return 0;
}
if (sg_close_drive_fd(fname, -1, &fd, 1) <= 0) {
if (linux_ata_enumerate_verbous)
fprintf(stderr,
"cannot close properly, errno=%d '%s'\n",
errno, strerror(errno));
return 0;
}
return 1;
}
static int is_scsi_drive(char *fname, int *bus_no, int *host_no,
int *channel_no, int *target_no, int *lun_no)
{
int fd, sid_ret = 0, ret;
struct sg_scsi_id sid;
int sibling_fds[BURN_OS_SG_MAX_SIBLINGS], sibling_count= 0;
char sibling_fnames[BURN_OS_SG_MAX_SIBLINGS][BURN_OS_SG_MAX_NAMELEN];
fd = sg_open_drive_fd(fname, 1);
if (fd == -1) {
if (linux_sg_enumerate_debug)
fprintf(stderr, "open failed, errno=%d '%s'\n",
errno, strerror(errno));
return 0;
}
sid_ret = ioctl(fd, SG_GET_SCSI_ID, &sid);
if (sid_ret == -1) {
sid.scsi_id = -1; /* mark SCSI address as invalid */
if(linux_sg_enumerate_debug)
fprintf(stderr,
"ioctl(SG_GET_SCSI_ID) failed, errno=%d '%s' , ",
errno, strerror(errno));
if (sgio_test(fd) == -1) {
if (linux_sg_enumerate_debug)
fprintf(stderr,
"FATAL: sgio_test() failed: errno=%d '%s'",
errno, strerror(errno));
sg_close_drive_fd(fname, -1, &fd, 0);
return 0;
}
#ifdef CDROM_DRIVE_STATUS
/* http://developer.osdl.org/dev/robustmutexes/
src/fusyn.hg/Documentation/ioctl/cdrom.txt */
sid_ret = ioctl(fd, CDROM_DRIVE_STATUS, 0);
if(linux_sg_enumerate_debug)
fprintf(stderr,
"ioctl(CDROM_DRIVE_STATUS) = %d , ",
sid_ret);
if (sid_ret != -1 && sid_ret != CDS_NO_INFO)
sid.scsi_type = TYPE_ROM;
else
sid_ret = -1;
#endif /* CDROM_DRIVE_STATUS */
}
#ifdef SCSI_IOCTL_GET_BUS_NUMBER
/* Hearsay A61005 */
if (ioctl(fd, SCSI_IOCTL_GET_BUS_NUMBER, bus_no) == -1)
*bus_no = -1;
#endif
if (sg_close_drive_fd(fname, -1, &fd,
sid.scsi_type == TYPE_ROM ) <= 0) {
if (linux_sg_enumerate_debug)
fprintf(stderr,
"cannot close properly, errno=%d '%s'\n",
errno, strerror(errno));
return 0;
}
if ( (sid_ret == -1 || sid.scsi_type != TYPE_ROM)
&& !linux_sg_accept_any_type) {
if (linux_sg_enumerate_debug)
fprintf(stderr, "sid.scsi_type = %d (!= TYPE_ROM)\n",
sid.scsi_type);
return 0;
}
if (sid_ret == -1 || sid.scsi_id < 0) {
/* ts A61211 : employ a more general ioctl */
ret = sg_obtain_scsi_adr(fname, bus_no, host_no,
channel_no, target_no, lun_no);
if (ret>0) {
sid.host_no = *host_no;
sid.channel = *channel_no;
sid.scsi_id = *target_no;
sid.lun = *lun_no;
} else {
if (linux_sg_enumerate_debug)
fprintf(stderr,
"sg_obtain_scsi_adr() failed\n");
return 0;
}
}
/* ts A60927 : trying to do locking with growisofs */
if(burn_sg_open_o_excl>1) {
ret = sg_open_scsi_siblings(
fname, -1, sibling_fds, sibling_fnames,
&sibling_count,
sid.host_no, sid.channel,
sid.scsi_id, sid.lun);
if (ret<=0) {
if (linux_sg_enumerate_debug)
fprintf(stderr, "cannot lock siblings\n");
sg_handle_busy_device(fname, 0);
return 0;
}
/* the final occupation will be done in sg_grab() */
sg_release_siblings(sibling_fds, sibling_fnames,
&sibling_count);
}
#ifdef SCSI_IOCTL_GET_BUS_NUMBER
if(*bus_no == -1)
*bus_no = 1000 * (sid.host_no + 1) + sid.channel;
#else
*bus_no = sid.host_no;
#endif
*host_no= sid.host_no;
*channel_no= sid.channel;
*target_no= sid.scsi_id;
*lun_no= sid.lun;
return 1;
}
#endif /* Libburn_drive_new_deaL */
/** Speciality of 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)
{
#ifdef Libburn_drive_new_deaL
int ret;
#else
struct hd_driveid tm;
int fd;
#endif
int i;
int i, fd;
char fname[10];
if (linux_ata_enumerate_verbous)
@ -851,17 +565,6 @@ static void ata_enumerate(void)
fprintf(stderr, "not in whitelist\n");
continue;
}
#ifdef Libburn_drive_new_deaL
ret = is_ata_drive(fname);
if (ret < 0)
break;
if (ret == 0)
continue;
#else /* Libburn_drive_new_deaL */
fd = sg_open_drive_fd(fname, 1);
if (fd == -1) {
if (linux_ata_enumerate_verbous)
@ -898,10 +601,6 @@ static void ata_enumerate(void)
errno, strerror(errno));
continue;
}
#endif /* Libburn_drive_new_deaL */
if (linux_ata_enumerate_verbous)
fprintf(stderr, "accepting as drive without SCSI address\n");
enumerate_common(fname, -1, -1, -1, -1, -1);
@ -912,18 +611,12 @@ static void ata_enumerate(void)
/** Detects (probably emulated) SCSI drives */
static void sg_enumerate(void)
{
#ifdef Libburn_drive_new_deaL
#else
struct sg_scsi_id sid;
int fd, sibling_fds[BURN_OS_SG_MAX_SIBLINGS], sibling_count= 0;
char sibling_fnames[BURN_OS_SG_MAX_SIBLINGS][BURN_OS_SG_MAX_NAMELEN];
int i, fd, sibling_fds[BURN_OS_SG_MAX_SIBLINGS], sibling_count= 0, ret;
int sid_ret = 0;
#endif
int i, ret;
int bus_no= -1, host_no= -1, channel_no= -1, target_no= -1, lun_no= -1;
char fname[17];
char fname[10];
char sibling_fnames[BURN_OS_SG_MAX_SIBLINGS][BURN_OS_SG_MAX_NAMELEN];
sg_select_device_family();
@ -937,9 +630,6 @@ static void sg_enumerate(void)
for (i = 0; i < 32; i++) {
sprintf(fname, linux_sg_device_family, i);
/* ts A80702 */
sg_exchange_scd_for_sr(fname, 0);
if (linux_sg_enumerate_debug)
fprintf(stderr, "libburn_debug: %s : ", fname);
@ -950,23 +640,6 @@ static void sg_enumerate(void)
continue;
}
#ifdef Libburn_drive_new_deaL
ret = is_scsi_drive(fname, &bus_no, &host_no, &channel_no,
&target_no, &lun_no);
if (ret < 0)
break;
if (ret == 0)
continue;
if (linux_sg_enumerate_debug)
fprintf(stderr, "accepting as SCSI %d,%d,%d,%d bus=%d\n",
host_no, channel_no, target_no, lun_no, bus_no);
enumerate_common(fname, bus_no, host_no, channel_no,
target_no, lun_no);
#else /* Libburn_drive_new_deaL */
/* ts A60927 */
fd = sg_open_drive_fd(fname, 1);
if (fd == -1) {
@ -1076,223 +749,16 @@ static void sg_enumerate(void)
#else
bus_no = sid.host_no;
#endif
if (linux_sg_enumerate_debug)
fprintf(stderr, "accepting as SCSI %d,%d,%d,%d bus=%d\n",
sid.host_no, sid.channel, sid.scsi_id, sid.lun,
bus_no);
enumerate_common(fname, bus_no, sid.host_no, sid.channel,
sid.scsi_id, sid.lun);
#endif /* Libburn_drive_new_deaL */
}
}
#ifdef Libburn_drive_new_deaL
/* ts A80805 : eventually produce the other official name of a device file */
static int fname_other_name(char *fname, char other_name[80], int flag)
{
if(strncmp(fname, "/dev/sr", 7) == 0 &&
(fname[7] >= '0' && fname[7] <= '9') &&
(fname[8] == 0 ||
(fname[8] >= '0' && fname[8] <= '9' && fname[9] == 0))) {
sprintf(other_name, "/dev/scd%s", fname + 7);
return 1;
}
if(strncmp(fname, "/dev/scd", 8) == 0 &&
(fname[8] >= '0' && fname[8] <= '9') &&
(fname[9] == 0 ||
(fname[9] >= '0' && fname[9] <= '9' && fname[10] == 0))) {
sprintf(other_name, "/dev/sr%s", fname + 8);
return 1;
}
return 0;
}
/* ts A80805 */
static int fname_drive_is_listed(char *fname, int flag)
{
char other_fname[80];
if (burn_drive_is_listed(fname, NULL, 0))
return 1;
if (fname_other_name(fname, other_fname, 0) > 0)
if (burn_drive_is_listed(other_fname, NULL, 0))
return 2;
return 0;
}
/* ts A80731 : Directly open the given address.
@param flag bit0= do not complain about missing file
bit1= do not check whether drive is already listed
*/
static int fname_enumerate(char *fname, int flag)
{
int is_ata= 0, is_scsi= 0;
int bus_no= -1, host_no= -1, channel_no= -1, target_no= -1, lun_no= -1;
char msg[BURN_DRIVE_ADR_LEN + 80];
struct stat stbuf;
if (!(flag & 2))
if (fname_drive_is_listed(fname, 0))
return 2;
if (stat(fname, &stbuf) == -1) {
sprintf(msg, "File object '%s' not found", fname);
if (!(flag & 1))
libdax_msgs_submit(libdax_messenger, -1, 0x0002000b,
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
return -1;
}
is_ata = is_ata_drive(fname);
if (is_ata < 0)
return -1;
if (!is_ata)
is_scsi = is_scsi_drive(fname, &bus_no, &host_no, &channel_no,
&target_no, &lun_no);
if (is_scsi < 0)
return -1;
if (is_ata == 0 && is_scsi == 0)
return 0;
if (linux_sg_enumerate_debug)
fprintf(stderr,
"(single) accepting as SCSI %d,%d,%d,%d bus=%d\n",
host_no, channel_no, target_no, lun_no, bus_no);
enumerate_common(fname, bus_no, host_no, channel_no,
target_no, lun_no);
return 1;
}
/* ts A80731 : Directly open the given address from a single-item whitlist */
static int single_enumerate(int flag)
{
int ret, wl_count;
char *fname, msg[BURN_DRIVE_ADR_LEN + 80];
wl_count= burn_drive_whitelist_count();
if (wl_count != 1)
return 0;
fname= burn_drive_whitelist_item(0, 0);
if (fname == NULL)
return 0;
ret = fname_enumerate(fname, 2);
if (ret <= 0) {
sprintf(msg, "Cannot access '%s' as SG_IO CDROM drive", fname);
libdax_msgs_submit(libdax_messenger, -1, 0x0002000a,
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
ret = -1;
}
return ret;
}
/* ts A80801 : looking up drives listed in /proc/sys/dev/cdrom/info line like:
drive name: sr1 hdc hda sr0
@parm flag bit0= release list memory and exit
*/
static int proc_sys_dev_cdrom_info(char ***list, int *count, int flag)
{
FILE *fp;
char line[1024], fname[1024 + 5], *cpt, *retpt, *list_data;
int maxl= 0, pass, i;
if (*list != NULL) {
if ((*list)[0] != NULL)
free((*list)[0]);
free(*list);
*list = NULL;
*count = 0;
}
if (flag & 1)
return 1;
*count = 0;
sg_evaluate_kernel();
if (sg_kernel_age < 2) /* addresses are not suitable for kernel 2.4 */
return 1;
fp = fopen("/proc/sys/dev/cdrom/info", "r");
if (fp == NULL)
return 0;
while (1) {
retpt = fgets(line, sizeof(line), fp);
if (retpt == NULL)
break;
if(strncmp(line, "drive name:", 11) == 0)
break;
}
fclose(fp);
if (retpt == NULL)
return 0;
strcpy(fname, "/dev/");
for(pass = 0; pass < 2; pass++) {
*count = 0;
cpt = line + 11;
while (*cpt != 0) {
for(; *cpt == ' ' || *cpt == '\t'; cpt++);
if (*cpt == 0 || *cpt == '\n')
break;
sscanf(cpt, "%s", fname + 5);
if (strlen(fname) > maxl)
maxl = strlen(fname);
if (pass == 1)
strcpy((*list)[*count], fname);
(*count)++;
for(cpt++; *cpt != ' ' && *cpt != '\t'
&& *cpt != 0 && *cpt != '\n'; cpt++);
}
if (pass == 0) {
list_data = calloc(*count + 1, maxl+1);
*list = calloc(*count + 1, sizeof(char *));
if(list_data == NULL || *list == NULL) {
libdax_msgs_submit(libdax_messenger, -1,
0x00000003,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Out of virtual memory", 0, 0);
if (list_data != NULL)
free(list_data);
if (*list != NULL)
free((char *) *list);
return -1;
}
for (i = 0; i <= *count; i++)
(*list)[i] = list_data + i * (maxl + 1);
}
}
return 1;
}
static int add_proc_info_drives(int flag)
{
int ret, list_count, count = 0, i;
char **list= NULL;
ret = proc_sys_dev_cdrom_info(&list, &list_count, 0);
if (ret <= 0)
return ret;
for (i = 0; i < list_count; i++) {
if (burn_drive_is_banned(list[i]))
continue;
ret = fname_enumerate(list[i], 1);
if (ret == 1)
count++;
}
proc_sys_dev_cdrom_info(&list, &list_count, 1); /* free memory */
return 1 + count;
}
#endif /* Libburn_drive_new_deaL */
/* ts A61115 */
/* ----------------------------------------------------------------------- */
/* PORTING: Private functions which contain publicly needed functionality. */
@ -1377,14 +843,10 @@ int sg_give_next_adr(burn_drive_enumerator_t *idx,
{
/* os-linux.h : typedef int burn_drive_enumerator_t; */
static int sg_limit = 32, ata_limit = 26;
int baseno = 0, i;
char other_name[80];
int baseno = 0;
if (initialize == -1) {
proc_sys_dev_cdrom_info(&(idx->info_list), &(idx->info_count),
1);
if (initialize == -1)
return 0;
}
sg_select_device_family();
if (linux_sg_device_family[0] == 0)
@ -1392,56 +854,26 @@ int sg_give_next_adr(burn_drive_enumerator_t *idx,
if (linux_ata_device_family[0] == 0)
ata_limit = 0;
if (initialize == 1) {
idx->pos = -1;
idx->info_count= 0;
idx->info_list= NULL;
proc_sys_dev_cdrom_info(&(idx->info_list), &(idx->info_count),
0);
}
(idx->pos)++;
if (idx->pos >= sg_limit)
if (initialize == 1)
*idx = -1;
(*idx)++;
if (*idx >= sg_limit)
goto next_ata;
if (adr_size < 11)
if (adr_size < 10)
return -1;
sprintf(adr, linux_sg_device_family, idx->pos);
sg_exchange_scd_for_sr(adr, 0);
goto return_1_pre_proc;
sprintf(adr, linux_sg_device_family, *idx);
return 1;
next_ata:;
baseno += sg_limit;
if (idx->pos - baseno >= ata_limit)
goto next_proc_info;
if (*idx - baseno >= ata_limit)
goto next_nothing;
if (adr_size < 9)
return -1;
sprintf(adr, linux_ata_device_family, 'a' + (idx->pos - baseno));
goto return_1_pre_proc;
next_proc_info:;
baseno += ata_limit;
for (i = 0; i < idx->info_count; i++) {
if ((idx->info_list)[i][0] == 0)
continue;
if (baseno == idx->pos) {
if (adr_size < strlen((idx->info_list)[i]) + 1)
return -1;
strcpy(adr, (idx->info_list)[i]);
return 1;
}
baseno++;
}
return 0;
return_1_pre_proc:;
for (i = 0; i < idx->info_count; i++) {
if (strcmp((idx->info_list)[i], adr) == 0)
(idx->info_list)[i][0] = 0;
if (fname_other_name(adr, other_name, 0) > 0)
if (strcmp((idx->info_list)[i], other_name) == 0)
(idx->info_list)[i][0] = 0;
}
sprintf(adr, linux_ata_device_family, 'a' + (*idx - baseno));
return 1;
next_nothing:;
baseno += ata_limit;
return 0;
}
@ -1463,27 +895,8 @@ return_1_pre_proc:;
/* ts A61115: replacing call to sg-implementation internals from drive.c */
int scsi_enumerate_drives(void)
{
#ifdef Libburn_drive_new_deaL
int ret;
#endif
#ifdef Libburn_drive_new_deaL
/* Direct examination of eventually single whitelisted name */
ret = single_enumerate(0);
if (ret < 0)
return -1;
if (ret > 0)
return 1;
#endif /* Libburn_drive_new_deaL */
sg_enumerate();
ata_enumerate();
#ifdef Libburn_drive_new_deaL
add_proc_info_drives(0);
#endif /* Libburn_drive_new_deaL */
return 1;
}
@ -1519,8 +932,7 @@ int sg_grab(struct burn_drive *d)
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
if (mmc_function_spy(d, "sg_grab") <= 0)
return 0;
mmc_function_spy("sg_grab");
/* ts A60813 - A60927
@ -1548,7 +960,7 @@ int sg_grab(struct burn_drive *d)
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
mmc_function_spy(NULL, "sg_grab ----------- opening");
mmc_function_spy("sg_grab ----------- opening");
/* ts A70409 : DDLP-B */
/* >>> obtain single lock on d->devname */
@ -1606,8 +1018,7 @@ int sg_release(struct burn_drive *d)
{
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
if (mmc_function_spy(d, "sg_release") <= 0)
return 0;
mmc_function_spy("sg_release");
if (d->fd < 1) {
burn_print(1, "release an ungrabbed drive. die\n");
@ -1616,7 +1027,7 @@ int sg_release(struct burn_drive *d)
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
mmc_function_spy(NULL, "sg_release ----------- closing");
mmc_function_spy("sg_release ----------- closing");
sg_close_drive(d);
return 0;
@ -1713,7 +1124,7 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
char buf[161];
sprintf(buf,"sg_issue_command d->fd= %d d->released= %d\n",
d->fd,d->released);
mmc_function_spy(NULL, buf);
mmc_function_spy(buf);
#ifdef Libburn_log_sg_commandS
/* ts A61030 */
@ -1934,67 +1345,10 @@ int sg_is_enumerable_adr(char *adr)
sg_give_next_adr(&idx, fname, sizeof(fname), -1);
return 1;
}
}
if (first == 0)
sg_give_next_adr(&idx, fname, sizeof(fname), -1);
sg_give_next_adr(&idx, fname, sizeof(fname), -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
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;
struct statvfs vfsbuf;
char testpath[4096], *cpt;
long blocks;
int open_mode = O_RDONLY, fd, ret;
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)) {
fd = open(path, open_mode);
if (fd == -1)
return -2;
ret = ioctl(fd, BLKGETSIZE, &blocks);
close(fd);
if (ret == -1)
return -2;
*bytes = ((off_t) blocks) * (off_t) 512;
} else if(S_ISREG(stbuf.st_mode)) {
add_size = stbuf.st_blocks * (off_t) 512;
strcpy(testpath, path);
} else
return 0;
if (testpath[0]) {
if (statvfs(testpath, &vfsbuf) == -1)
return -2;
*bytes = add_size + ((off_t) vfsbuf.f_bsize) *
(off_t) vfsbuf.f_bavail;
}
return 1;
}

View File

@ -31,6 +31,4 @@ int scsi_enumerate_drives(void);
int sg_drive_is_open(struct burn_drive * d);
int burn_os_stdio_capacity(char *path, off_t *bytes);
#endif /* __SG */

View File

@ -18,6 +18,8 @@ void burn_source_free(struct burn_source *src)
enum burn_source_status burn_track_set_source(struct burn_track *t,
struct burn_source *s)
{
if (!s->read)
return BURN_SOURCE_FAILED;
s->refcount++;
t->source = s;
@ -32,24 +34,6 @@ struct burn_source *burn_source_new(void)
struct burn_source *out;
out = calloc(1, sizeof(struct burn_source));
/* ts A70825 */
if (out == NULL)
return NULL;
memset((char *) out, 0, sizeof(struct burn_source));
out->refcount = 1;
return out;
}
/* ts A71223 */
int burn_source_cancel(struct burn_source *src)
{
if(src->read == NULL)
if(src->version > 0)
if(src->cancel != NULL)
src->cancel(src);
return 1;
}

View File

@ -5,6 +5,4 @@
struct burn_source *burn_source_new(void);
int burn_source_cancel(struct burn_source *src);
#endif /*__SOURCE*/

View File

@ -27,11 +27,6 @@
#include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger;
/* ts A70910
debug: for tracing calls which might use open drive fds
or for catching SCSI usage of emulated drives. */
int mmc_function_spy(struct burn_drive *d, char * text);
/* spc command set */
/* ts A70519 : allocation length byte 3+4 was 0,255 */
@ -68,9 +63,6 @@ int spc_test_unit_ready_r(struct burn_drive *d, int *key, int *asc, int *ascq)
{
struct command c;
if (mmc_function_spy(d, "test_unit_ready") <= 0)
return 0;
scsi_init_command(&c, SPC_TEST_UNIT_READY,sizeof(SPC_TEST_UNIT_READY));
/*
c.oplen = sizeof(SPC_TEST_UNIT_READY);
@ -98,73 +90,19 @@ int spc_test_unit_ready(struct burn_drive *d)
/* ts A70315 */
/** @param flag bit0=do not wait 0.1 seconds before first test unit ready */
/** Wait until the drive state becomes clear or until max_usec elapsed */
int spc_wait_unit_attention(struct burn_drive *d, int max_sec, char *cmd_text,
int flag)
int spc_wait_unit_attention(struct burn_drive *d, int max_sec)
{
int i, ret = 1, key = 0, asc = 0, ascq = 0;
char msg[160];
int i, ret, key, asc, ascq;
if (!(flag & 1))
usleep(100000);
for(i = !(flag & 1); i < max_sec * 10; i++) {
for(i=0; i < max_sec; i++) {
ret = spc_test_unit_ready_r(d, &key, &asc, &ascq);
/* <<<
fprintf(stderr,
"libburn_EXPERIMENTAL: i= %d ret= %d key= %X asc= %2.2X ascq= %2.2X\n",
i, ret, (unsigned) key, (unsigned) asc, (unsigned) ascq);
*/
if (ret > 0) /* ready */
if(ret > 0 || key!=0x2 || asc!=0x4) /* ready or error */
break;
if (key!=0x2 || asc!=0x4) {
if (key == 0x2 && asc == 0x3A) {
ret = 1; /* medium not present = ok */
/* <<<
ts A70912 :
My LG GSA-4082B on asynchronous load:
first it reports no media 2,3A,00,
then it reports not ready 2,04,00,
further media inquiry retrieves wrong data
if(i<=100)
goto slumber;
*/
break;
}
if (key == 0x6 && asc == 0x28 && ascq == 0x00)
/* media change notice = try again */
goto slumber;
sprintf(msg,
"Asynchromous SCSI error on %s: key=%X asc=%2.2Xh ascq=%2.2Xh",
cmd_text, (unsigned) key, (unsigned) asc,
(unsigned) ascq);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x0002014d,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
d->cancel = 1;
break;
}
slumber:;
usleep(100000);
usleep(1000000);
}
sprintf(msg, "Async %s %s after %d.%d seconds",
cmd_text, (ret > 0 ? "succeeded" : "failed"), i / 10, i % 10);
libdax_msgs_submit(libdax_messenger, d->global_index, 0x00020150,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_LOW, msg, 0, 0);
if (i < max_sec * 10)
if (i < max_sec)
return (ret > 0);
sprintf(msg, "Timeout (%d s) with asynchronous SCSI command %s\n",
max_sec, cmd_text);
libdax_msgs_submit(libdax_messenger, d->global_index, 0x0002014f,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0);
return 0;
}
@ -173,9 +111,6 @@ void spc_request_sense(struct burn_drive *d, struct buffer *buf)
{
struct command c;
if (mmc_function_spy(d, "request_sense") <= 0)
return;
scsi_init_command(&c, SPC_REQUEST_SENSE, sizeof(SPC_REQUEST_SENSE));
c.retry = 0;
/*
@ -195,9 +130,6 @@ int spc_get_erase_progress(struct burn_drive *d)
{
struct buffer b;
if (mmc_function_spy(d, "get_erase_progress") <= 0)
return 0;
spc_request_sense(d, &b);
return (b.data[16] << 8) | b.data[17];
}
@ -208,9 +140,6 @@ void spc_inquiry(struct burn_drive *d)
struct burn_scsi_inquiry_data *id;
struct command c;
if (mmc_function_spy(d, "inquiry") <= 0)
return;
scsi_init_command(&c, SPC_INQUIRY, sizeof(SPC_INQUIRY));
/*
memcpy(c.opcode, SPC_INQUIRY, sizeof(SPC_INQUIRY));
@ -242,9 +171,6 @@ void spc_prevent(struct burn_drive *d)
{
struct command c;
if (mmc_function_spy(d, "prevent") <= 0)
return;
scsi_init_command(&c, SPC_PREVENT, sizeof(SPC_PREVENT));
/*
memcpy(c.opcode, SPC_PREVENT, sizeof(SPC_PREVENT));
@ -260,9 +186,6 @@ void spc_allow(struct burn_drive *d)
{
struct command c;
if (mmc_function_spy(d, "allow") <= 0)
return;
scsi_init_command(&c, SPC_ALLOW, sizeof(SPC_ALLOW));
/*
memcpy(c.opcode, SPC_ALLOW, sizeof(SPC_ALLOW));
@ -445,9 +368,6 @@ void spc_sense_caps(struct burn_drive *d)
{
int alloc_len, start_len = 22, ret;
if (mmc_function_spy(d, "sense_caps") <= 0)
return;
/* first command execution to learn Allocation Length */
alloc_len = start_len;
ret = spc_sense_caps_al(d, &alloc_len, 1);
@ -469,9 +389,6 @@ void spc_sense_error_params(struct burn_drive *d)
unsigned char *page;
struct command c;
if (mmc_function_spy(d, "sense_error_params") <= 0)
return;
scsi_init_command(&c, SPC_MODE_SENSE, sizeof(SPC_MODE_SENSE));
/*
memcpy(c.opcode, SPC_MODE_SENSE, sizeof(SPC_MODE_SENSE));
@ -502,9 +419,6 @@ void spc_select_error_params(struct burn_drive *d,
struct buffer buf;
struct command c;
if (mmc_function_spy(d, "select_error_params") <= 0)
return;
scsi_init_command(&c, SPC_MODE_SELECT, sizeof(SPC_MODE_SELECT));
/*
memcpy(c.opcode, SPC_MODE_SELECT, sizeof(SPC_MODE_SELECT));
@ -543,9 +457,6 @@ void spc_sense_write_params(struct burn_drive *d)
unsigned char *page;
struct command c;
if (mmc_function_spy(d, "sense_write_params") <= 0)
return;
/* ts A61007 : Done in soft at only caller burn_drive_grab() */
/* a ssert(d->mdata->cdr_write || d->mdata->cdrw_write ||
d->mdata->dvdr_write || d->mdata->dvdram_write); */
@ -566,21 +477,17 @@ void spc_sense_write_params(struct burn_drive *d)
c.dir = FROM_DRIVE;
d->issue_command(d, &c);
/* ts A71128 : do not interpret reply if error */
size = c.page->data[0] * 256 + c.page->data[1];
m = d->mdata;
if (!c.error) {
size = c.page->data[0] * 256 + c.page->data[1];
page = c.page->data + 8;
burn_print(1, "write page length 0x%x\n", page[1]);
m->write_page_length = page[1];
m->write_page_valid = 1;
} else
m->write_page_valid = 0;
page = c.page->data + 8;
burn_print(1, "write page length 0x%x\n", page[1]);
m->write_page_length = page[1];
m->write_page_valid = 1;
mmc_read_disc_info(d);
/* ts A70212 : try to setup d->media_capacity_remaining */
if (d->current_profile == 0x1a || d->current_profile == 0x13 ||
d->current_profile == 0x12 || d->current_profile == 0x43)
d->current_profile == 0x12)
d->read_format_capacities(d, -1);
else if (d->status == BURN_DISC_BLANK ||
(d->current_is_cd_profile && d->status == BURN_DISC_APPENDABLE)) {
@ -607,9 +514,6 @@ void spc_select_write_params(struct burn_drive *d,
struct buffer buf;
struct command c;
if (mmc_function_spy(d, "select_write_params") <= 0)
return;
/* ts A61007 : All current callers are safe. */
/* a ssert(o->drive == d); */
@ -650,9 +554,6 @@ void spc_select_write_params(struct burn_drive *d,
void spc_getcaps(struct burn_drive *d)
{
if (mmc_function_spy(d, "getcaps") <= 0)
return;
spc_inquiry(d);
spc_sense_caps(d);
spc_sense_error_params(d);
@ -672,9 +573,6 @@ void spc_probe_write_modes(struct burn_drive *d)
int last_try = 0;
struct command c;
if (mmc_function_spy(d, "spc_probe_write_modes") <= 0)
return;
/* ts A70213 : added pseudo try_write_type 4 to set a suitable mode */
while (try_write_type != 5) {
burn_print(9, "trying %d, %d\n", try_write_type,
@ -841,20 +739,20 @@ int burn_scsi_setup_drive(struct burn_drive *d, int bus_no, int host_no,
d->silent_on_scsi_error = 0;
d->idata = calloc(1, sizeof(struct burn_scsi_inquiry_data));
d->mdata = calloc(1, sizeof(struct scsi_mode_data));
d->idata = malloc(sizeof(struct burn_scsi_inquiry_data));
d->idata->valid = 0;
d->mdata = malloc(sizeof(struct scsi_mode_data));
d->mdata->valid = 0;
d->mdata->speed_descriptors = NULL;
/* ts A61007 : obsolete Assert in drive_getcaps() */
if (d->idata == NULL || d->mdata == NULL) {
if(d->idata == NULL || d->mdata == NULL) {
libdax_msgs_submit(libdax_messenger, -1, 0x00020108,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Could not allocate new drive object", 0, 0);
return -1;
}
d->idata->valid = 0;
d->mdata->valid = 0;
d->mdata->speed_descriptors = NULL;
if (!(flag & 1)) {
if(!(flag & 1)) {
ret = spc_setup_drive(d);
if (ret<=0)
return ret;
@ -869,14 +767,11 @@ int burn_scsi_setup_drive(struct burn_drive *d, int bus_no, int host_no,
}
/* ts A61122 - A80829 */
/* ts A61122 */
enum response scsi_error_msg(struct burn_drive *d, unsigned char *sense,
int senselen, char msg_data[161],
int senselen, char msg[161],
int *key, int *asc, int *ascq)
{
char *msg;
msg= msg_data;
*key= *asc= *ascq= -1;
if (senselen<=0 || senselen>2)
@ -886,236 +781,50 @@ enum response scsi_error_msg(struct burn_drive *d, unsigned char *sense,
if (senselen<=0 || senselen>13)
*ascq = sense[13];
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",
*key, *asc, *ascq, d->idata->vendor, d->idata->product);
switch (*asc) {
case 0x00:
sprintf(msg, "(No error reported by SCSI transaction)");
case 0:
sprintf(msg, "(no error reported by SCSI transaction)");
return RETRY;
case 0x02:
sprintf(msg, "Not ready");
case 2:
sprintf(msg, "not ready");
return RETRY;
case 0x04:
case 4:
sprintf(msg,
"Logical unit is in the process of becoming ready");
"logical unit is in the process of becoming ready");
return RETRY;
case 0x09:
if (*key != 4)
break;
if (*ascq == 0)
sprintf(msg, "Track following error");
else if (*ascq == 1)
sprintf(msg, "Tracking servo failure");
else if (*ascq == 2)
sprintf(msg, "Focus servo failure");
else if (*ascq == 3)
sprintf(msg, "Spindle servo failure");
else if (*ascq == 4)
sprintf(msg, "Head select fault");
else
break;
return FAIL;
case 0x0C:
if (*key == 2 && *ascq == 7)
sprintf(msg, "Write error, recovery needed");
else if (*key == 2 && *ascq == 0x0f)
sprintf(msg, "Defects in error window");
else if (*key == 3 && *ascq == 2)
sprintf(msg, "Write error, auto reallocation failed");
else if (*key == 3 && *ascq == 9)
sprintf(msg, "Write error, loss of streaming");
else if (*key == 3)
sprintf(msg, "Write error");
else
break;
return FAIL;
case 0x11:
if (*key != 3)
break;
if (*ascq == 0)
sprintf(msg, "Unrecovered read error");
else if (*ascq == 1)
sprintf(msg, "Read retries exhausted");
else if (*ascq == 2)
sprintf(msg, "Error too long to correct");
else if (*ascq == 5)
sprintf(msg, "L-EC uncorrectable error");
else if (*ascq == 6)
sprintf(msg, "CIRC uncorrectable error");
else
break;
return FAIL;
case 0x15:
if (*key != 3 && *key != 4)
break;
sprintf(msg, "Random positioning error");
return FAIL;
case 0x1a:
if (*key != 5)
break;
sprintf(msg, "Parameter list length error");
return FAIL;
case 0x1b:
if (*key != 4)
break;
sprintf(msg, "Synchronous data transfer error");
return FAIL;
case 0x20:
if (*key != 5)
break;
sprintf(msg, "Invalid command operation code");
if (*key == 5)
sprintf(msg, "bad opcode");
return FAIL;
case 0x21:
if (*key != 5)
break;
if (*ascq == 0)
sprintf(msg, "Lba out of range");
else if (*ascq == 3)
sprintf(msg, "Invalid write crossing layer jump");
else
sprintf(msg, "Invalid address");
sprintf(msg, "invalid address");
return FAIL;
case 0x24:
if (*key != 5)
if (*key == 5)
sprintf(msg, "invalid field in cdb");
else
break;
sprintf(msg, "Invalid field in cdb");
return FAIL;
case 0x26:
if (*key != 5)
break;
if (*ascq == 1)
sprintf(msg, "Parameter not supported");
else if (*ascq == 2)
sprintf(msg, "Parameter value invalid");
else
sprintf(msg, "Invalid field in parameter list");
return FAIL;
case 0x27:
if (*key != 7)
break;
sprintf(msg, "Write protected");
if (*key == 5 )
sprintf(msg, "invalid field in parameter list" );
return FAIL;
case 0x28:
if (*key != 6)
break;
if (*ascq == 0)
if (*key == 6)
sprintf(msg, "Medium may have changed");
else if (*ascq == 2)
sprintf(msg, "Format layer may have changed");
else
break;
return RETRY;
case 0x29:
if (*key != 6)
break;
if (*ascq == 0)
sprintf(msg,
"Power on, reset, or bus device reset occured");
else if (*ascq == 1)
sprintf(msg, "Power on occured");
else if (*ascq == 2)
sprintf(msg, "Bus reset occured");
else if (*ascq == 3)
sprintf(msg, "Bus device reset function occured");
else if (*ascq == 4)
sprintf(msg, "Device internal reset");
else
break;
return RETRY;
case 0x2c:
if (*key != 5)
break;
if (*ascq == 0)
sprintf(msg, "Command sequence error");
else
break;
return FAIL;
case 0x2e:
if (*key != 6)
break;
if (*ascq == 0)
sprintf(msg,
"Insufficient time for operation");
else
break;
return FAIL;
case 0x30:
if (*key != 2 && *key != 5)
break;
if (*ascq == 1)
sprintf(msg, "Cannot read medium, unknown format");
else if (*ascq == 2)
sprintf(msg,
"Cannot read medium, incompatible format");
else if (*ascq == 4)
sprintf(msg, "Cannot write medium, unknown format");
else if (*ascq == 5)
sprintf(msg,
"Cannot write medium, incompatible format");
else if (*ascq == 6)
sprintf(msg,
"Cannot format medium, incompatible medium");
else if (*ascq == 7)
sprintf(msg, "Cleaning failure");
else
sprintf(msg, "Incompatible medium installed");
return FAIL;
case 0x3A:
if (*key != 2)
break;
if (*ascq == 1)
sprintf(msg, "Medium not present, tray closed");
else if (*ascq == 2)
sprintf(msg, "Medium not present, tray open");
else if (*ascq == 3)
sprintf(msg, "Medium not present, loadable");
else
sprintf(msg, "Medium not present");
sprintf(msg, "Medium not present");
d->status = BURN_DISC_EMPTY;
return FAIL;
case 0x63:
if (*key != 5)
break;
if (*ascq == 0)
sprintf(msg,
"End of user area encountered on this track");
else if (*ascq == 1)
sprintf(msg, "Packet does not fit in available space");
else
break;
return FAIL;
case 0x64:
if (*key != 5)
break;
if (*ascq == 0)
sprintf(msg, "Illegal mode for this track");
else if (*ascq == 1)
sprintf(msg, "Invalid packet size");
else
break;
return FAIL;
case 0x72:
if (*key == 3)
sprintf(msg, "Session fixation error");
else if (*key == 5 && *ascq == 3)
sprintf(msg,
"Session fixation error, incomplete track in session");
else if (*key == 5 && *ascq == 4)
sprintf(msg,
"Empty or partially written reserved track");
else if (*key == 5 && *ascq == 5)
sprintf(msg,
"No more track reservations allowed");
else
break;
return FAIL;
}
sprintf(msg_data,
sprintf(msg,
"Failure. See mmc3r10g.pdf: Sense Key %X ASC %2.2X ASCQ %2.2X",
*key, *asc, *ascq);
return FAIL;
@ -1151,9 +860,12 @@ int scsi_notify_error(struct burn_drive *d, struct command *c,
if (d->silent_on_scsi_error)
return 1;
scsi_error_msg(d, sense, senselen, scsi_msg, &key, &asc, &ascq);
strcpy(scsi_msg, " \"");
scsi_error_msg(d, sense, senselen, scsi_msg + strlen(scsi_msg),
&key, &asc, &ascq);
strcat(scsi_msg, "\"");
if (!(flag & 1)) {
if(!(flag & 1)) {
/* SPC : TEST UNIT READY command */
if (c->opcode[0] == 0)
return 1;
@ -1164,9 +876,7 @@ int scsi_notify_error(struct burn_drive *d, struct command *c,
return 1;
}
sprintf(msg,"SCSI error condition on command %2.2Xh : ", c->opcode[0]);
#ifdef NIX
sprintf(msg,"SCSI error condition on command %2.2Xh :", c->opcode[0]);
if (key>=0)
sprintf(msg+strlen(msg), " key=%Xh", key);
if (asc>=0)
@ -1180,13 +890,6 @@ int scsi_notify_error(struct burn_drive *d, struct command *c,
ret = libdax_msgs_submit(libdax_messenger, d->global_index, 0x0002010f,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
scsi_msg,0,0);
#else
strcat(msg, scsi_msg);
ret = libdax_msgs_submit(libdax_messenger, d->global_index, 0x0002010f,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, msg,0,0);
#endif /* NIX */
return ret;
}

View File

@ -28,8 +28,7 @@ int spc_test_unit_ready(struct burn_drive *d);
/* ts A70315 */
/** Wait until the drive state becomes clear in or until max_sec elapsed */
int spc_wait_unit_attention(struct burn_drive *d, int max_sec, char *cmd_text,
int flag);
int spc_wait_unit_attention(struct burn_drive *d, int max_sec);
/* ts A61021 : the spc specific part of sg.c:enumerate_common()
*/

View File

@ -40,8 +40,6 @@ struct burn_disc *burn_disc_create(void)
{
struct burn_disc *d;
d = calloc(1, sizeof(struct burn_disc));
if (d == NULL) /* ts A70825 */
return NULL;
d->refcnt = 1;
d->sessions = 0;
d->session = NULL;
@ -66,8 +64,6 @@ struct burn_session *burn_session_create(void)
{
struct burn_session *s;
s = calloc(1, sizeof(struct burn_session));
if (s == NULL) /* ts A70825 */
return NULL;
s->refcnt = 1;
s->tracks = 0;
s->track = NULL;
@ -108,8 +104,6 @@ struct burn_track *burn_track_create(void)
{
struct burn_track *t;
t = calloc(1, sizeof(struct burn_track));
if (t == NULL) /* ts A70825 */
return NULL;
t->refcnt = 1;
t->indices = 0;
t->offset = 0;
@ -330,19 +324,11 @@ void burn_track_clear_isrc(struct burn_track *t)
int burn_track_get_sectors(struct burn_track *t)
{
/* ts A70125 : was int */
off_t size = 0;
off_t size;
int sectors, seclen;
seclen = burn_sector_length(t->mode);
if (t->source != NULL) /* ts A80808 : mending sigsegv */
size = t->offset + t->source->get_size(t->source) + t->tail;
else if(t->entry != NULL) {
/* ts A80808 : all burn_toc_entry of track starts should now
have (extensions_valid & 1), even those from CD.
*/
if (t->entry->extensions_valid & 1)
size = ((off_t) t->entry->track_blocks) * (off_t) 2048;
}
size = t->offset + t->source->get_size(t->source) + t->tail;
sectors = size / seclen;
if (size % seclen)
sectors++;
@ -476,7 +462,6 @@ int burn_session_get_sectors(struct burn_session *s)
return sectors;
}
int burn_disc_get_sectors(struct burn_disc *d)
{
int sectors = 0, i;
@ -524,40 +509,3 @@ int burn_session_get_hidefirst(struct burn_session *session)
{
return session->hidefirst;
}
/* ts A80808 : Enhance CD toc to DVD toc */
int burn_disc_cd_toc_extensions(struct burn_disc *d, int flag)
{
int sidx, tidx;
struct burn_toc_entry *entry, *prev_entry= NULL;
for (sidx = 0; sidx < d->sessions; sidx++) {
for (tidx = 0; tidx < d->session[sidx]->tracks + 1; tidx++) {
if (tidx < d->session[sidx]->tracks)
entry = d->session[sidx]->track[tidx]->entry;
else
entry = d->session[sidx]->leadout_entry;
entry->session_msb = 0;
entry->point_msb = 0;
entry->start_lba = burn_msf_to_lba(entry->pmin,
entry->psec, entry->pframe);
if (tidx > 0) {
prev_entry->track_blocks =
entry->start_lba
- prev_entry->start_lba;
prev_entry->extensions_valid |= 1;
}
if (tidx == d->session[sidx]->tracks) {
entry->session_msb = 0;
entry->point_msb = 0;
entry->track_blocks = 0;
entry->extensions_valid |= 1;
}
prev_entry = entry;
}
}
return 1;
}

View File

@ -109,8 +109,4 @@ int burn_track_apply_fillup(struct burn_track *t, off_t max_size, int flag);
off_t burn_track_get_default_size(struct burn_track *t);
/* ts A80808 : Enhance CD toc to DVD toc */
int burn_disc_cd_toc_extensions(struct burn_disc *d, int flag);
#endif /* BURN__STRUCTURE_H */

View File

@ -114,21 +114,13 @@ struct burn_format_descr {
off_t size;
/* the Type Dependent Parameter (usually the write alignment size) */
unsigned int tdp;
unsigned tdp;
};
/** Gets initialized in enumerate_common() and burn_drive_register() */
struct burn_drive
{
/* ts A70902:
0=null-emulation
1=MMC drive ,
2=stdio random read-write
3=stdio sequential write-only
*/
int drive_role;
int bus_no;
int host;
int id;
@ -180,17 +172,9 @@ struct burn_drive
*/
int current_feat2fh_byte4;
/* ts A70114 : whether a DVD-RW media holds an incomplete session
/* ts A70114 : wether a DVD-RW media holds an incomplete session
(which could need closing after write) */
int needs_close_session;
/* ts A71003 : whether a random write operation was done and no
synchronize chache has happened yet */
int needs_sync_cache;
/* ts A80412 : whether to use WRITE12 with Streaming bit set
rather than WRITE10. Speeds up DVD-RAM. Might help
with BD-RE */
int do_stream_recording;
/* ts A61218 from 51h READ DISC INFORMATION */
int bg_format_status; /* 0=needs format start, 1=needs format restart*/
@ -198,7 +182,7 @@ struct burn_drive
/* ts A70108 from 23h READ FORMAT CAPACITY mmc5r03c.pdf 6.24 */
int format_descr_type; /* 1=unformatted, 2=formatted, 3=unclear */
off_t format_curr_max_size; /* meaning depends on format_descr_type */
unsigned int format_curr_blsas; /* dito */
unsigned format_curr_blsas; /* meaning depends on format_descr_type */
int best_format_type;
off_t best_format_size;
@ -212,8 +196,6 @@ struct burn_drive
/* ts A61106 */
int silent_on_scsi_error;
int stdio_fd;
int nwa; /* next writeable address */
int alba; /* absolute lba */
int rlba; /* relative lba in section */
@ -247,24 +229,18 @@ struct burn_drive
int pbf_altered;
int wait_for_buffer_free;
int nominal_write_speed;
unsigned int wfb_min_usec;
unsigned int wfb_max_usec;
unsigned int wfb_timeout_sec;
unsigned int wfb_min_percent;
unsigned int wfb_max_percent;
unsigned int pessimistic_writes;
unsigned int waited_writes;
unsigned int waited_tries;
unsigned int waited_usec;
unsigned wfb_min_usec;
unsigned wfb_max_usec;
unsigned wfb_timeout_sec;
unsigned wfb_min_percent;
unsigned wfb_max_percent;
unsigned pessimistic_writes;
unsigned waited_writes;
unsigned waited_tries;
unsigned waited_usec;
volatile int cancel;
volatile enum burn_drive_status busy;
/* ts A70929 */
pid_t thread_pid;
int thread_pid_valid;
/* transport functions */
int (*grab) (struct burn_drive *);
int (*release) (struct burn_drive *);
@ -344,18 +320,8 @@ struct burn_drive
/* mmc5r03c.pdf 6.24 : get list of available formats */
int (*read_format_capacities) (struct burn_drive *d, int top_wanted);
/* ts A70812 */
/* mmc5r03c.pdf 6.15 : read data sectors (start and amount in LBA) */
int (*read_10) (struct burn_drive *d, int start, int amount,
struct buffer *buf);
};
/* end of generic 'drive' data structures */
/* ts A80422 : centralizing this setting for debugging purposes
*/
int burn_drive_set_media_capacity_remaining(struct burn_drive *d, off_t value);
#endif /* __TRANSPORT */

View File

@ -4,11 +4,7 @@
/* #include <a ssert.h> */
#include <stdlib.h>
/* ts A80914 : This is unneeded. Version info comes from libburn.h.
#include "v ersion.h"
*/
#include "../version.h"
#include "util.h"
#include "libburn.h"
@ -51,8 +47,7 @@ char *burn_strndup(char *s, int n)
void burn_version(int *major, int *minor, int *micro)
{
/* ts A80408 : switched from configure.ac versioning to libburn.h versioning */
*major = burn_header_version_major;
*minor = burn_header_version_minor;
*micro = burn_header_version_micro;
*major = BURN_MAJOR_VERSION;
*minor = BURN_MINOR_VERSION;
*micro = BURN_MICRO_VERSION;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,35 +0,0 @@
#ifndef Cgen_includeD
#define Cgen_includeD Yes
struct CgeN {
char *classname;
char *structname;
char *functname;
int is_managed_list;
int is_bossless_list;
int gen_for_stic; /* 0=no smem,srgex,sfile , 1=all three, 2=smem only */
int make_ansi;
int make_lowercase;
char global_include_file[4096];
FILE *global_include_fp;
struct CtyP *elements;
struct CtyP *last_element;
int may_overwrite;
FILE *fp;
char filename[4096];
FILE *ptt_fp;
char ptt_filename[4096];
char msg[8192];
};
#endif /* Cgen_includeD */

View File

@ -1,222 +0,0 @@
Description of the helper program stic*/bin/cgen
cgen is copyright 2001 to 2007, Thomas Schmitt <stic-source@gmx.net>
and provided under BSD license.
Compilation:
cc -g -o cgen cgen.c ctyp.c smem.c
cgen produces a class stub in C programming language. The data structure of
the class is described by some lines which get read from stdin. The stub will
consist of four files which emerge in the current working directory:
<classname>.h public header file of the class
<classname>.c automatically generated C code of the class
plus a copy of <classname>.c.methods
<classname>_private.h private header file of the class
<classname>.c.methods safe storage for manually created functions.
From here they get copied into the generated stub.
If such a file is missing, a dummy gets created.
It will define a struct <ClassnamE> for representing the class data aspects,
construtor <Classname>_new(), destructor <Classname>_destroy(),
getter <Classname>_<element>_get() for each structure element.
Some more functions get added for particular class and element roles.
cgen normally refuses to overwrite existing files because it supposes that
those contain code added by the human programmer.
Human programmer enhancements may be explanatory comments, class specific
methods, initial element values and other special precautions within the
generated functions.
As long as the modelling phase is going on, one may store such human code
in <classname>.c.methods and may use command line option -overwrite for
modelling development cycles.
At some point of model matureness one may decide to give up cgen and the
.c.method files and to go on only with _private.h , .h and .c files.
Command line options
-no_stic prevents usage of stic_dir/s_tools/*.[ch]
-ansi generates ANSI C function heads and makes file <classname>.h hold
only public definitions: an opaque declaration of the class struct
and a list of function prototypes. The definiton of the class
struct is then in <classname>_private.h .
-global_include filename
sets the name of a file which will contain globally necessary
declarations. Currently it lists the existence of all class
structs.
-lowercase generate struct <classname> rather than struct <ClassnamE> and
function names <classname>_func() rather than <Classname>_func() .
-overwrite allows to overwrite files <classname>_private.h, <classname>.h
and <classname>.c, but not <classname>.c.methods.
Input line format:
There are two states of input: class level and element level.
Exampes are shown below with class roles and element roles.
Input starts at class level. A class level line may be one of
- Comment. A line which begins with '#' is ignored on class level.
- Empty. A line with no characters is a comment with empty text (i.e. ignored).
- Class. Options which begin with '-' and finally a word in lowercase letters
which defines the <classname>. The classname leads to a struct ClassnamE
and some class methods implemented as C functions <Classnname>_<func>().
- End of input. Line "@@@" or EOF at stdin end the program run.
After a class line, input switches to element level where a line may be:
- Comment. A line which after some white space begins with '#' is considered
a comment. The preceeding white space is ignored and the text after '#' is
eventuellay trimmed by a single blank at both ends. This text will be part
of the class struct definition within file <classname_private>.h as a single
C comment line /* ... */. The sequence of elements and comments is preserved.
An empty comment text leads to an empty line in <classname_private>.h.
- Empty. A line with no characters is a comment with empty text.
- Element. Options which begin with '-', eventual C keywords "unsigned" or
"volatile", type or "struct <NamE>", element name. This leads to a struct
element which is taken into respect in some class methods. Depending on the
options in this line, some element methods <Classnname>_<func>_<element>()
may get generated.
- End of class. A single '@' marks the end of the element list and brings
input back to class level. I.e. next is expected another class name or
"@@@" or EOF at stdin.
Input semantics:
A class can have one of two roles:
- Standalone class.
Input example:
my_class
- Listable class, which has pointers to peer instances: .prev and .next
Such classes get a list destructor <Classname>_destroy_all() which destroys
all members of a list (which is given by any of the list members).
Such a class should have a pointer *boss as first element in which case
the constructor will look like
<Classname>_new(struct <ClassnamE> **o,struct <Some_clasS> *boss,int flag);
There is a function <Classname>_link() which inserts an instance into a list
and a function <Classname>_count() which tells the number of list members.
For pseudo random access there is function <Classname>_by_idx().
Input example:
-l my_class
A modifier is defined for classes:
- Bossless. Disables a special boss-subordinate relationship which is created
if the first element of a class is a struct pointer with the name "boss".
Like
-l <classname>
-v struct Some_clasS *boss
Normally such a parameter *boss becomes part of the constructor method
<Classname>_new(struct <ClassnamE> **o, struct Some_clasS *boss, int flag);
This relationship is typical for a listable class and a single class which
is designed to host instances of that listable class. Therefore one gets a
warning if a listable class does not begin with a struct pointer *boss.
But if -b is given, then CgeN ill not include a parameter *boss into the
constructor. It will rather look normal:
<Classname>_new(struct <ClassnamE> **o, int flag);
It will not warn if the first element of a listable class is not struct
pointer *boss.
Elements have one of the following roles:
- Value. It provides only storage for a C data type (which may be a C pointer
despite the role name "value"), a getter method <Classname>_<element>_get(),
and a setter method <Classname>_<element>_set().
Input examples:
-v int i
-v int a[100]
-v char *cpt
-v struct xyz x
-v struct xyz *xpt
- Managed. This has to be a pointer to a struct <XyZ> or to char. It will not
get attached to an object by the stub's code but its destructor
<Xyz>_destroy() will be called by <Classname>_destruct(). In case of (char *)
it is supposed that a non-NULL value has been allocated by malloc().
Managed (char *) types get a setter function <Classname>_<element>_set()
which allocates memory and copies the textstring from its parameter.
Input examples:
-m struct XyZ *xyzpt
-m char *textstring
- Chainlink. A pair of prev-next-style pointers to the own class struct.
Function <Classname>_destruct() will unlink the affected instance and
put together its link partners.
Input example (there must always be two consequtive -c lines):
-c struct My_clasS *up
-c struct My_clasS *down
- List. A pair of pointers to the struct <XyZ> of a listable class. The first
one <ls> holds the start of the list, the second one <eol> holds the end.
The getter function has an additional argument idx:
<Classname>_get_<ls>(struct <ClassnamE> *o, int idx, struct <XyZ> **pt,
int flag)
idx == 0 is the start of the list, idx=1 the next element, ...
idx == -1 retrieves the last element of the list.
For insertion of list items there is provided method <Classname>_new_<ls>().
The inserted item is reachable via the getter function with idx == -1
<Classname>_destroy() instance calls <Xyz>_destroy_all(). Note that the end
pointer is always generated as private element (-p).
Input example (there must always be a -l and a -v line):
-l struct XyZ *list_start
-v struct XyZ *list_end
The availability of getter method <Classname>_get_<element>(), and setter
method <Classname>_set_<element>_set() can be controled by two modifiers:
- Readonly. Only a getter method.
Input example
-r -v int broadcasted_status
- Private. Neither getter nor setter method.
Input example
-p -v int private_value
- Bossless listable. This marks elements which are listable objects but do not
expect a boss pointer in their constructor. See above: Listable class and
the bossless modifier for classes.
Input example
-b -l struct XyZ *list
-v struct XyZ *last_in_list
- Initialization free. The class constructor will not initialize this element.
This modifier has to be used if neither NULL nor 0 are suitable
initialization values.
Example run:
rm class_x.c class_x.h class_y.c class_y.h
bin/cgen <<+
-l class_x
-r -v struct Boss_clasS *boss
-v int x
-r -v struct stat stbuf
-m struct Class_Y *y
-m char *text
-c struct Class_X *master
-c struct Class_X *slave
-b -l struct Class_X *provider
-p -v struct Class_X *last_provider
@
-b -l class_y
-r -v char providername[80]
@
+

View File

@ -1,364 +0,0 @@
/*
cc -g -o ctyp.c
*/
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "smem.h"
extern char *Sfile_fgets();
extern int Sregex_string();
extern int Sregex_trimline();
#include "ctyp.h"
/* -------------------------- CtyP ----------------------- */
int Ctyp_new(objpt,link,flag)
struct CtyP **objpt;
struct CtyP *link;
int flag;
{
struct CtyP *o;
int ret;
*objpt= o= TSOB_FELD(struct CtyP,1);
if(o==NULL)
return(-1);
o->is_comment= 0;
o->is_pointer= 0;
o->is_struct= 0;
o->is_unsigned= 0;
o->is_volatile= 0;
o->array_size= 0;
o->management= 0;
o->with_getter= 1;
o->with_setter= 1;
o->bossless_list= 0;
o->no_initializer= 0;
o->dtype= NULL;
o->name= NULL;
o->prev= NULL;
o->next= NULL;
if(link!=NULL)
link->next= o;
o->prev= link;
return(1);
failed:;
Ctyp_destroy(objpt,0);
return(-1);
}
int Ctyp_destroy(objpt,flag)
struct CtyP **objpt;
int flag;
{
struct CtyP *o;
o= *objpt;
if(o==NULL)
return(0);
if(o->prev!=NULL)
o->prev->next= o->next;
if(o->next!=NULL)
o->next->prev= o->prev;
Sregex_string(&(o->dtype),NULL,0);
Sregex_string(&(o->name),NULL,0);
free((char *) o);
*objpt= NULL;
return(1);
}
int Ctyp_get_pointer_level(ct,flag)
struct CtyP *ct;
int flag;
{
return(ct->is_pointer);
}
int Ctyp_is_struct(ct,flag)
struct CtyP *ct;
int flag;
{
return(ct->is_struct);
}
int Ctyp_get_array_size(ct,flag)
struct CtyP *ct;
int flag;
{
return(ct->array_size);
}
int Ctyp_get_management(ct,flag)
struct CtyP *ct;
int flag;
{
return(ct->management);
}
int Ctyp_get_with_getter(ct,flag)
struct CtyP *ct;
int flag;
{
return(ct->with_getter);
}
int Ctyp_get_with_setter(ct,flag)
struct CtyP *ct;
int flag;
{
return(ct->with_setter);
}
int Ctyp_get_dtype(ct,text,flag)
struct CtyP *ct;
char **text; /* must point to NULL of freeable memory */
int flag;
/*
bit0=eventually prepend "struct "
*/
{
if((flag&1) && ct->is_struct) {
if(Sregex_string(text,"struct ",0)<=0)
return(-1);
} else {
if(Sregex_string(text,"",0)<=0)
return(-1);
}
if(Sregex_string(text,ct->dtype,1)<=0)
return(-1);
return(1);
}
int Ctyp_get_name(ct,text,flag)
struct CtyP *ct;
char **text; /* must point to NULL of freeable memory */
int flag;
{
if(Sregex_string(text,ct->name,0)<=0)
return(-1);
return(1);
}
int Ctyp_get_type_mod(ct,is_spointer,is_struct,array_size,flag)
struct CtyP *ct;
int *is_spointer,*is_struct,*array_size;
int flag;
{
*is_spointer= ct->is_pointer;
*is_struct= ct->is_struct;
*array_size= ct->array_size;
}
int Ctyp_new_from_line(ct,link,line,msg,flag)
struct CtyP **ct;
struct CtyP *link;
char *line;
char *msg;
int flag;
/*
bit0= make struct ClassnamE to struct classname
*/
{
struct CtyP *o;
char *cpt,*bpt;
int ret,l;
char orig_line[4096];
ret= Ctyp_new(ct,*ct,0);
if(ret<=0) {
sprintf(msg,"Failed to create CtyP object (due to lack of memory ?)");
goto ex;
}
o= *ct;
strcpy(orig_line,line);
cpt= line;
while(*cpt!=0 && isspace(*cpt)) cpt++;
if(cpt[0]=='#') {
cpt++;
if(cpt[1]==' ')
cpt++;
l= strlen(cpt);
if(cpt[0]==' ')
cpt++;
if(l>1)
if(cpt[l-1]==' ')
cpt[l-1]= 0;
if(Sregex_string(&(o->name),cpt,0)<=0)
{ret= -1; goto ex;}
o->is_comment= 1;
{ret= 1; goto ex;}
} else if(cpt[0]==0) {
if(Sregex_string(&(o->name),cpt,0)<=0)
{ret= -1; goto ex;}
o->is_comment= 1;
{ret= 1; goto ex;}
} else if(cpt[0]=='/' && cpt[1]=='*') {
sprintf(msg,
"C-style multi line comments (/* ... */) not supported yet. Use #.");
goto ex;
/* >>> */
}
cpt= line;
while(cpt[0]=='-') {
/* look for management specifiers:
-v* just a value
-m* allocated memory which needs to be freed
-c* mutual link (like prev+next)
-l* list of -m chained by mutual links prev and next
-r* read-only : no setter function
-p* private : neither setter nor getter function
-b* bossless_list : Class_new(o,flag), not Class_new(o,boss,flag)
-i* no_initializer : do not initialize element in <Class>_new()
#... line is a comment
*/
if(cpt[1]=='v' || cpt[1]=='V') {
o->management= 0;
} else if(cpt[1]=='m' || cpt[1]=='M') {
o->management= 1;
} else if(cpt[1]=='c' || cpt[1]=='C') {
o->management= 2;
if(o->prev!=NULL)
if(o->prev->management==2)
o->management= 3;
} else if(cpt[1]=='l' || cpt[1]=='L') {
o->management= 4;
} else if(cpt[1]=='r' || cpt[1]=='R') {
o->with_setter= 0;
} else if(cpt[1]=='p' || cpt[1]=='P') {
o->with_setter= 0;
o->with_getter= 0;
} else if(cpt[1]=='b' || cpt[1]=='B') {
o->bossless_list= 1;
} else if(cpt[1]=='i' || cpt[1]=='I') {
o->no_initializer= 1;
}
while(*cpt!=0 && !isspace(*cpt)) cpt++;
while(*cpt!=0 && isspace(*cpt)) cpt++;
if(*cpt==0)
goto no_name;
}
if(strncmp(cpt,"struct ",7)==0) {
o->is_struct= 1;
cpt+= 7;
} else if(strncmp(cpt,"unsigned ",9)==0) {
o->is_unsigned= 1;
cpt+= 9;
} else if(strncmp(cpt,"volatile ",9)==0) {
o->is_volatile= 1;
cpt+= 9;
if(strncmp(cpt,"unsigned ",9)==0) {
o->is_unsigned= 1;
cpt+= 9;
}
}
if(*cpt==0)
goto no_name;
while(*cpt!=0 && isspace(*cpt)) cpt++;
bpt= cpt;
while(*bpt!=0 && !isspace(*bpt)) bpt++;
if(*bpt==0)
goto no_name;
if(*bpt==0) {
no_name:;
sprintf(msg,"No name found after type description : %s",orig_line);
ret= 0; goto ex;
}
*bpt= 0;
if(Sregex_string(&(o->dtype),cpt,0)<=0)
{ret= -1; goto ex;}
if((flag&1) && o->is_struct && strlen(o->dtype)>=3)
if(isupper(o->dtype[0]) && islower(o->dtype[1]) &&
isupper(o->dtype[strlen(o->dtype)-1])) {
o->dtype[0]= tolower(o->dtype[0]);
o->dtype[strlen(o->dtype)-1]= tolower(o->dtype[strlen(o->dtype)-1]);
}
cpt= bpt+1;
while(*cpt!=0 && isspace(*cpt)) cpt++;
if(*cpt==0)
goto no_name;
for(;*cpt=='*';cpt++)
o->is_pointer++;
if(*cpt==0)
goto no_name;
bpt= strchr(cpt,'[');
if(bpt!=NULL) {
if(strchr(bpt,']')!=NULL)
*strchr(bpt,']')= 0;
sscanf(bpt+1,"%lu",&(o->array_size));
*bpt= 0;
}
if(Sregex_string(&(o->name),cpt,0)<=0)
{ret= -1; goto ex;}
if(o->management==1) {
if((!(o->is_pointer>=1 && o->is_pointer<=2)) ||
((!o->is_struct) && strcmp(o->dtype,"char")!=0 &&
(strcmp(o->dtype,"unsigned char")!=0))) {
sprintf(msg,"-m can only be applied to pointers of struct or char : %s",
orig_line);
ret= 0; goto ex;
}
}
ret= 1;
ex:;
return(ret);
}
int Ctyp_read_fp(ct,fp,msg,flag)
struct CtyP **ct;
FILE *fp;
char msg[]; /* at least [4096+256] */
int flag;
/*
bit0= make struct ClassnamE to struct classname
*/
{
int ret;
char line[4096];
struct CtyP *o;
line[0]= 0;
printf(
"[-value|-managed|-chain|-list] class element ? (e.g.: -l struct XyZ)\n");
if(Sfile_fgets(line,sizeof(line)-1,fp)==NULL)
{ret= 2; goto ex;}
printf("%s\n",line);
Sregex_trimline(line,0);
if(strcmp(line,"@")==0)
{ret= 2; goto ex;}
ret= Ctyp_new_from_line(ct,*ct,line,msg,flag&1);
if(ret<=0)
goto ex;
ret= 1;
ex:;
return(ret);
}

View File

@ -1,41 +0,0 @@
#ifndef Ctyp_includeD
#define Ctyp_includeD
struct CtyP {
/* if 1 : .name contains comment text, all other elements are invalid */
int is_comment;
int is_pointer; /* number of asterisks */
int is_struct;
int is_unsigned;
int is_volatile;
unsigned long array_size;
int management; /*
-v 0= just a value
-m 1= allocated memory which needs to be freed
-c 2= mutual link with the next element
-c 3= mutual link with the prev element
-l 4= list of -m , chained by -c pair named 'prev','next'
supposed to be followed by a -v of the same type
which will mark the end of the list
*/
int with_getter;
int with_setter;
int bossless_list;
int no_initializer;
char *dtype;
char *name;
struct CtyP *prev;
struct CtyP *next;
};
#endif /* Ctyp_includeD */

View File

@ -1,30 +0,0 @@
#!/bin/sh
copy_mode=0
while true
do
read line
if test "$copy_mode" = "0"
then
if echo " $line" | grep '^ Cgen=' >/dev/null 2>&1
then
copy_mode=1
if echo " $line" | grep '^ Cgen=..' >/dev/null 2>&1
then
echo " $line" | sed -e 's/^ Cgen=//'
fi
elif echo " $line" | grep '^ =end Model=' >/dev/null 2>&1
then
break
fi
else
if test " $line" = " @"
then
copy_mode=0
echo "@"
else
echo " $line" | sed -e 's/^ //'
fi
fi
done

View File

@ -1,16 +0,0 @@
#!/bin/sh
test_dir=.
model_file=./libdax_model.txt
xtr_dir=.
cgen_dir=.
# cgen_dir=~/projekte/cdrskin_dir/libburn-develop/libcevap
cd "$test_dir" || exit 1
test -e smem.h || exit 1
cat "$model_file" | \
"$xtr_dir"/extract_cgen_input.sh | \
"$cgen_dir"/cgen -smem_local -ansi -global_include cevap_global.h \
-overwrite "$@"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

View File

@ -1,944 +0,0 @@
#
# libdax is the early working name for the successor software of libburn,
# a library for writing information onto optical media, i.e. CD and DVD.
# The current working name is libcevap, refering to various kinds of roasts in
# Europe and Asia which share the property to be structured in smaller pieces.
#
# The reason for the replacement is the unclear copyright situation as well
# as libburn's sketchy original state and the subsequential evolutionary
# damages done by us in libburn code.
# This does not mean libburn is shaky. Its current state just reflects the
# virtual conflict of at least two programmer personalities and their goals.
#
#
# Please: Nobody shall take the development of libcevap as a reason for not
# programming an application which uses libburn.
# libburn works now. libcevap is planned to work in future.
#
# libcevap will replace libburn in a controlled, application friendly way.
# The first application of libcevap will be a libburn API wrapper which will
# allow to perform all API calls of libburn which are proveable to work in
# the current implementation. (Some CD stuff is not understood by us yet.
# We will have to learn.)
#
# The libburn API will be frozen when libcevap has closed up to its current
# capabilities. Nevertheless it may take profit from some of the future
# progress in libcevap (e.g. new media types).
# We hope that finally libcevap will have capabilities superior to libburn.
# This will then be a reason to port applications to the libcevap API.
#
# Application programmers are advised to encapsulate their libburn API calls
# in an own abstraction layer. The semantic concepts of burning will be
# compatible between libburn and libcevap. I.e you will have a library object
# to be started up, drives to be found and grabbed, media and their states
# to be identified, sessions, tracks, burn options to be set, blanking,
# formatting, and so on.
# Data types, function calls, and quirks will be incompatible between both
# APIs, though.
#
# -------------------------------------------------------------------------
# Originally this was a backup of text input clicketitoggled into ArgoUML
# Meanwhile it becomes an intermediate storage for attributes and
# class interconnections in the notation of my C stub generator CgeN
# (see also end of this text)
# next : work on completeness : cevapformat
# Open questions:
# - how to connect to GESTURES ? Globally ?
Model=libdax
ClassDiagram=Overview
Class=API
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=11.03.2007
Documentation=\
The API is the only layer visible to the applications. It exposes MMC concepts
which it reflects and augments by its own architectural concepts.
Subordinates=EQUIP,JOB,AUX
Cgen=\
cevapi
-r -m struct CevapequiP *equip
-r -m struct CevapjoB *job
-r -m struct CevapauX *aux
-r -m struct CevapgestureS *gestures
@
=end Class
Class=EQUIP
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=11.03.2007
Documentation=\
EQUIP represents the physical and logical equipment in reach of libdax.
This includes the system, drives, media, and their current states.
PeerToPeer=GESTURES
Boss=API
Cgen=\
cevapequip
-r -v struct CevapI *boss
-r -m struct CevapsysteM *sys
-v struct CevapgestureS *gestures
@
=end Class
Class=JOB
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=11.03.2007
Documentation=\
JOB models the tasks to be performed via libdax.
This includes disc, session, track, source, fifo, dewav, burn options.
PeerToPeer=GESTURES
Boss=API
Cgen=\
cevapjob
-r -v struct CevapI *boss
-r -m struct CevaptodO *todo
-v struct CevapgestureS *gestures
# >>>
@
=end Class
Class=AUX
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=11.03.2007
Documentation=\
AUX bundles any models which are neither EQUIP nor JOB.
This includes abort handler and message system.
PeerToPeer=GESTURES
Boss=API
Cgen=\
cevapaux
-r -v struct CevapI *boss
-v struct CevapgestureS *gestures
# >>>
@
=end Class
Class=GESTURES
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=11.03.2007
Documentation=\
GESTURES ist the procedural repertoire which interconnects EQUIP, JOB, and AUX
and also provides to them the services from the SCSI oriented layers.
PeerToPeer=EQUIP,JOB,AUX
Subordinates=SCSI_CMD
Cgen=\
cevapgestures
-r -v struct CevapI *boss
-v struct CevapequiP *equip
-v struct CevapjoB *job
-v struct CevapauX *aux
-r -m struct CevapscmD *scsi_cmd
# >>>
@
=end Class
Class=SCSI_CMD
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=11.03.2007
Documentation=\
SCSI_CMD represents the semantic part of SCSI (i.e. mainly MMC) specs.
This layer models each SCSI command that is used by libdax. It knows about
its parameters and constraints with particular equipment and jobs.
Boss=GESTURES
Subordinates=Classes with SCSI_EXEC Interface
Cgen=\
cevapscmd
-r -v struct CevapgestureS *boss
-r -m struct CevapsexeC *scsi_exec
# >>>
@
=end Class
Interface=SCSI_EXEC
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=16.03.2007
Documentation=\
SCSI_EXEC hides the difference between the implementation principle of
SCSI format+transport and the principle of SCSI service.
Boss=SCSI_CMD
Implementations=SCSI_FORMAT,SCSI_SERVICE
Cgen=\
cevapsexec
-r -v struct CevapscmD *boss
-p -v struct CevapsforM *scsi_format
-p -v struct CevapsservicE *scsi_service
-v int silent_on_scsi_error
# >>>
@
=end Interface
Class=OSDriveAspect
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=18.08.2007
Documentation=\
OSDriveAspect encapsulates operating system specific properties of an
individual drive. It shall be handed out by SCSI_EXEC via the GESTURES layer
to EquipDrive where it forms the link between cevap drive model and operating
system driver.
This class description models the implementation specific to Linux.
Cgen=\
cevaposdrv
-r -v int fd
# >>> ??? implement the sibling stuff which never worked properly ?
@
=end Class
Class=SCSI_FORMAT
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=11.03.2007
Documentation=\
SCSI_FORMAT translates parameters of SCSI commands into CDBs, takes care for
transport and decodes the reply into parameters.
Boss=SCSI_CMD via SCSI_EXEC
Subordinates=SCSI_TRANSPORT
Cgen=\
cevapsform
-r -v struct CevapsexeC *boss
-p -v struct CevapstransP *scsi_transport
# former struct command
-v unsigned char opcode[16]
-v int oplen
-v int dir
-v int dxfer_len
-v unsigned char sense[128]
-v int error
-v int retry
-v struct CevapbuffeR *page
# >>>
@
=end Class
Class=SCSI_TRANSPORT
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=11.03.2007
Documentation=\
SCSI_TRANSPORT takes a formatted CDB from SCSI_FORMAT and makes the operating
system perform a SCSI transaction. It then returns the reply data in raw form.
Boss=SCSI_FORMAT
Os_specific=yes
Cgen=\
cevapstransp
-r -v struct CevapsforM *boss
# >>>
@
=end Class
Class=SCSI_SERVICE
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=11.03.2007
Documentation=\
SCSI_SERVICE provides the combined services of SCSI_FORMAT and SCSI_TRANSPORT
via a set of parametrized functions which abstract SCSI command transactions.
Boss=SCSI_CMD via SCSI_EXEC
Os_specific=yes
Cgen=\
cevapsservice
-r -v struct CevapsexeC *boss
# >>>
@
=end Class
=end ClassDiagram=Overview
ClassDiagram=Equip_overview
Class=EquipSystem
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=16.03.2007
Documentation=\
EquipSystem is the inner root class of EQUIP. It describes the system on
which libdax is working. This includes the operating system, the system
adapter classes, the drives.
Boss=EQUIP
Subordinates=EquipDrive*N
Cgen=\
cevapsystem
-r -v struct CevapequiP *boss
-r -m char *infotext
-r -l struct CevapdrivE *drive
-p -v struct CevapdrivE *eol_drive
# >>> be boss of SCSI_CMD ? (Rather than GESTURES)
# >>>
@
=end Class
Class=EquipDrive
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=16.03.2007
Documentation=\
EquipDrive represents a drive, including its capabilities, its processing
status, the media loaded.
Subordinates=EquipMedia
Boss=EquipSystem
Cgen=\
-l cevapdrive
-r -v struct CevapsysteM *boss
# Drive number
-r -v int global_index
# Persistent system drive address
-r -m char *devname
# Traditional SCSI address parameters (-1 if not applicable)
-r -v int bus_no
-r -v int host
-r -v int id
-r -v int channel
-r -v int lun
# (former struct burn_scsi_inquiry_data idata)
# From 12h INQUIRY , spc3r23.pdf , 6.4.2 , Table 81
-r -v char vendor[9]
-r -v char product[17]
-r -v char revision[5]
# 1= above elements contain valid information
-r -v int idata_valid
# mc5r03c.pdf 5.3.2 Physical Interface Standard
# 1=SCSI, 2=ATAPI, 3,4,6=FireWire, 7=SATA, 8=USB
-r -v int phys_if_std
# MMC-5 5.3.2 table 91 , e.g. "SCSI Family"
-r -m char *phys_if_name
# System despendent aspect of the drive (e.g. int fd;)
-r -v struct CevaposdrV *system_dep_drive_info
# Result of the CD write mode x block type tests:
# Index is for write mode : 0=packet , 1=TAO , 2=SAO , 3=raw
# Bits are for block type
# Numbering as in mc5r03c.pdf 7.5.4.13 Data Block Type, Table 668 :
# 0=RAW0 (2352, Raw data)
# 1=RAW16 (2368, Raw data with P and Q Sub-channel
# 2=RAW96P (2448, Raw data with P-W Sub-channel appended)
# 3=RAW96R (2448, Raw data with raw P-W Sub-channel appended)
# 8=MODE1 (2048, ISO/IEC 10149)
# 9=MODE2R (2336, Mode 2 formless)
# 10=MODE2F1 (2048, CD-ROM XA, form 1)
# 11=MODE2F1X (2056, CD-ROM XA, form 1 plus 8 byte subheader)
# 12=MODE2F2 (2324, CD-ROM XA, form 2)
# 13=MODE2MIX (2332, CD-ROM XA, form 1, form 2, or mixed form)
-r -v int block_types[4]
# (former struct scsi_mode_data)
# Information about the drive's capabilities, obtained via 5Ah MODE SENSE
# from mode page 2Ah , mmc3r10g.pdf , 6.3.11 , Table 361
# (which is deprecated in MMC-5 E.11)
-p -v int mdata_buffer_size
-p -v int mdata_dvdram_read
-p -v int mdata_dvdram_write
-p -v int mdata_dvdr_read
-p -v int mdata_dvdr_write
-p -v int mdata_dvdrom_read
-p -v int mdata_cdrw_read
-p -v int mdata_cdrw_write
-p -v int mdata_cdr_read
-p -v int mdata_cdr_write
-p -v int mdata_max_read_speed
-p -v int mdata_max_write_speed
-p -v int madata_min_write_speed
-p -v int mdata_cur_read_speed
-p -v int mdata_cur_write_speed
-p -v int mdata_simulate
-p -v int mdata_c2_pointers
-r -v int mdata_underrun_proof
# Results from ACh GET PERFORMANCE, Type 03h
# (Speed values go into *_*_speed)
# (speed_descriptors became cevapperf which is under cevapmedia)
-p -v int min_end_lba
-p -v int max_end_lba
# from mode page 01h , mmc5r03c.pdf , 7.3.2.1 , Table 657
-p -v int mdata_retry_page_length
-p -v int mdata_retry_page_valid
# from mode page 05h , mmc5r03c.pdf , 7.5.4.1 , Table 664
-p -v int mdata_write_page_length
-p -v int mdata_write_page_valid
# 1= above elements contain valid information
-p -v int mdata_valid
# The mutex shall be used to coordinate access to the drive in situations
# where multi-threaded race conditions could disturb operations.
# E.g. lock, read busy state, interpret, set busy state, unlock
# A mere reader of the busy state does not have to lock because
# reading of the state itself is atomar.
-i -v pthread_mutex_t access_lock
# Flags from feature 002Fh feature descriptor mmc5r03c.pdf 5.3.25 :
# bit1= DVD-RW supported
# bit2= Test Write available
# bit3= DVD-R DL supported
# bit6= Buffer Under-run Free recording available (page 05h BUFE)
# Value -1 indicates that no 002Fh was current in the features list.
-r -v int current_feat2fh_byte4
# 0= drive is grabbed, 1= drive is not grabbed
-v volatile int released
# File descriptor of an eventual emulated drive
-v int stdio_fd
# >>> ???
# (do we need a drive owned buffer to carry data from call to call or what ?)
-v struct CevapbuffeR *buffer
# List of profiles as reported by the drive
-r -l struct CevapprofilE *profile
-p -v struct CevapprofilE *eol_profile
# Media currently loaded in the drive
-r -m struct CevapmediA *media
# >>> transport.h : toc_temp (what is this ? It belongs to BURN_WRITE_RAW)
# >>>
@
=end Class
Class=EquipMedia
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=16.03.2007
Documentation=\
EquipMedia represents an optical disc, including its type, its writeability,
its formatting, its available formats and performances.
Subordinates=\
EquipProfile*N,EquipFormat*N,EquipPerformance*N,EquipStatus,EquipMulticaps
Boss=EquipDrive
Cgen=\
cevapmedia
-r -v struct CevapdrivE *boss
# Volatile and/or public properties of the media
-r -m struct CevapstatuS *status
# MMC-to-MMC feature info from 46h for DVD-RW.
# Quite internal. Regard as opaque :)
# 1 = incremental recording available, 0 = not available
-r -v int current_has_feat21h
# Link Size item number 0 from feature 0021h descriptor
-r -v int current_feat21h_link_size
# Wether a DVD-RW media holds an incomplete session
# (which could need closing after write)
-v int needs_close_session
# From 51h READ DISC INFORMATION
# 0=needs format start, 1=needs format restart
-r -v int bg_format_status
# From 23h READ FORMAT CAPACITY mmc5r03c.pdf 6.24
# 1=unformatted, 2=formatted, 3=unclear
-r -v int format_descr_type
# meaning depends on format_descr_type
-r -v off_t format_curr_max_size
# dito
-r -v unsigned int format_curr_blsas
-r -v int best_format_type
-r -v off_t best_format_size
-r -l struct CevapformaT *format_descriptor
-p -v struct CevapformaT *eol_format_descriptor
# The specific capabilities and restrictions of the media
-r -m struct CevapmcapS *multicaps
# Results from ACh GET PERFORMANCE, Type 03h
# (Speed values go into drive.mdata_*_*_speed)
-r -l struct CevapperF *speed_descriptor
-p -v struct CevapperF *eol_speed_descriptor
# >>>
@
=end Class
Class=EquipProfile
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=16.03.2007
Documentation=\
EquipProfile maps a MMC profile into libdax (See mmc5r03c.pdf chapter 5).
A profile describes a set of features and may be either current, possible,
disabled, or unavailable.
Subordinates=EquipFeature*N
Boss=EquipMedia
Cgen=\
-l cevapprofile
-r -v struct CevapdrivE *boss
-r -v int is_current
-r -v int profile_code
-r -v char *profile_text
-r -v int is_cd_profile
-r -v int is_supported_profile
-r -l struct CevapfeaturE *feature
-p -v struct CevapfeaturE *eol_feature
@
=end Class
Class=EquipFeature
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=16.03.2007
Documentation=\
EquipFeature maps a MMC feature into libdax (See mmc5r03c.pdf chapter 5).
A feature describes a set of SCSI commands and (implicitely) of use cases.
Boss=EquipProfile
Cgen=\
-l cevapfeature
-r -v struct CevapprofilE *boss
# >>>
@
=end Class
Class=EquipFormat
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=
Documentation=\
EquipFormat represents a single Formattable Capacity Descriptor
as of mmc5r03c.pdf 6.24.3.3 .
Boss=EquipMedia
Cgen=\
-l cevapformat
-r -v struct CevapmediA *boss
# format type: e.g 0x00 is "Full", 0x15 is "Quick"
-r -v int type
# the size in bytes derived from Number of Blocks
-r -v off_t size
# the Type Dependent Parameter (usually the write alignment size)
-r -v unsigned int tdp
# >>>
@
=end Class
Class=EquipPerformance
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=
Documentation=\
>>> EquipPerformance
Boss=EquipMedia
Cgen=\
-l cevapperf
-r -v struct CevapmediA *boss
# >>>
@
=end Class
Class=EquipStatus
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=17.3.2007
Documentation=\
EquipStatus represents the status of media and drive. This includes
blank/appendable/closed, progress indicator.
Boss=EquipMedia
Cgen=\
cevapstatus
-r -v struct CevapmediA *boss
-v int status
-m char *status_text
-v volatile int busy
# From various sources : free space on media (in bytes)
# With CD this might change after particular write
# parameters have been set and nwa has been inquired.
-v off_t media_capacity_remaining
# Current write address during write jobs. (Next address to be written)
# <<< does this belong to JOB ?
-r -v int nwa
# if > 0 : first lba on media that is too high for write
-v int media_lba_limit
-v struct CevapprogresS *progress
# >>>
@
=end Class
Class=EquipMulticaps
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=14.8.2007
Documentation=\
EquipMulticaps represents media dependent properties and media states which
are either volatile or especially interesting to several other modules. This
includes eventually existing sessions, closure status, profile dependent
capabilities.
Boss=EquipMedia
Cgen=\
cevapmcaps
# The current profile out of the drive profile list
-v struct CevapprofilE *current_profile
# Wether the media is erasable (or overwriteable)
-v int erasable
# A description of the existing media content structure
-r -m struct CevapdisC *disc
# Start and end addresses out of ATIP.
# From 43h READ TOC/PMA/ATIP , mmc5r03c.pdf , 6.26
-r -v int start_lba
-r -v int end_lba
# From 51h READ DISC INFORMATION Number of Sessions (-1)
-v int complete_sessions
# From 51h READ DISC INFORMATION Last Track Number in Last Session
-v int last_track_no
# >>> libburn.h:struct burn_multi_caps
@
=end Class
Class=EquipTocItem
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=14.8.2007
Boss=
Cgen=\
-l cevaptocitem
-r -v struct CevapdisC *boss
-v int session
-v int valid
-v int control
# obscure info from CD TOC : possibly length of track
-v unsigned char point
-v unsigned char min
-v unsigned char sec
-v unsigned char frame
-v int pmin
-v int psec
-v int pframe
-v int start_lba
-v int track_blocks
@
=end Class
=end ClassDiagram=Equip_overview
ClassDiagram=Job_overview
Class=JobTodo
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=18.3.2007
Documentation=\
JobTodo records what is to be done during a job. This includes peripheral
actions like tray load/eject and central actions like blank, format, burn.
Subordinates=JobDisc,JobOptions
Cgen=\
cevaptodo
-v volatile int cancel
# >>>
@
=end Class
Class=JobDisc
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=18.3.2007
Documentation=\
JobDisc models a disc structure. Either one which already exists or
one which is to be created in a job run.
Subordinates=JobSession*N
Boss=JobTodo
Cgen=\
cevapdisc
-l struct CevapsessioN *session
-p -v struct CevapsessioN *eol_session
-l struct CevaptociteM *toc_entry
-p -v struct CevaptociteM *eol_toc_entry
# >>> take over services of struct burn_disc
@
=end Class
Class=JobSession
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=18.3.2007
Documentation=\
JobSession represents a recording session. A session usually bundles
several tracks. Traditionally the last session of a disc is recognized
by operating systems as the thing to be mounted.
Subordinates=JobTrack*N,JobFifo
Boss=JobDisc
Cgen=\
-l cevapsession
-r -v struct CevapdisC *boss
# >>>
-l struct CevaptracK *track
-p -v struct CevaptracK *eol_track
# >>>
@
=end Class
Class=JobTrack
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=18.3.2007
Documentation=\
JobTrack represents a track to be recorded. A track mainly is associated with
a data source but in many cases it also becomes a recognizable entity on the
target media.
Subordinates=JobBlock*N,JobTrackFilter,JobSource
Boss=JobSession
Cgen=\
-l cevaptrack
-r -v struct CevapsessioN *boss
# >>>
@
=end Class
Class=JobBlock
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=18.3.2007
Documentation=\
JobBlock represents a single output data transaction unit. On CD this is
the same as an addressable media block resp. sector. On DVD this might be
an addressable block od 2k or a packet of e.g. 32k.
Boss=JobTrack
Cgen=\
cevapblock
-v int alba
-v int rlba
# >>>
@
=end Class
Class=JobSource
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=8.4.2007
Documentation=\
JobSource represents a data source for a track. Typically this is a disk
file or a stream file descriptor like stdin.
Subordinates=JobSourceBlock*N
Boss=JobTrack
=end Class
Class=JobSourceBlock
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=8.4.2007
Documentation=\
JobSourceBlock represents a single input data transaction unit.
Boss=JobSource
=end Class
Class=JobFifo
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=8.4.2007
Documentation=\
JobFifo reads data via JobTrackFilter and buffers them until JobBlock can
accept them.
Boss=JobSession
=end Class
Class=JobTrackFilter
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=8.4.2007
Documentation=\
JobTrackFilter reads data from JobSourceBlock, processes them and presents
them to JobFifo or JobBlock. This includes stripping of .wav headers.
Boss=JobTrack
=end Class
Class=JobOptions
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=18.3.2007
Documentation=\
JobOptions bundles the adjustable parameters of a job. This includes dummy
mode, speed, appendability, blank mode, format selection, write mode,
underrun protection, random access addressing.
Boss=JobTodo
Cgen=\
cevapjobopts
# >>>
# Keeping an eye on the drive buffer
-v int wait_for_buffer_free
-v unsigned int wfb_min_usec
-v unsigned int wfb_max_usec
-v unsigned int wfb_timeout_sec
-v unsigned int wfb_min_percent
-v unsigned int wfb_max_percent
# >>> -m struct params params (used by disabled read cd funtionality)
@
=end Class
Class=JobBuffer
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=13.8.2007
Documentation=\
JobBuffer is an intermediate storage for the content of several JobBlock
or JobSourceBlock.
Cgen=\
cevapbuffer
-r -m unsigned char *data
-v int sectors
-v int bytes
@
=end Class
Class=JobProgress
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=13.8.2007
Documentation=\
JobProgress reflects the state and parts of the history of a job
Cgen=\
cevapprogress
# Keeping an eye on the drive buffer
-v int nominal_write_speed
-v off_t pessimistic_buffer_free
-v int pbf_altered
-v unsigned int pessimistic_writes
-v unsigned int waited_writes
-v unsigned int waited_tries
-v unsigned int waited_usec
# >>> the info provided by struct burn_progress
# >>>
@
=end Class
Class=
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=
Documentation=\
=end Class
=end ClassDiagram=Equip_overview
ClassDiagram=Gestures_overview
# >>>
=end ClassDiagram=Gestures_overview
=end Model=libdax
----------------------------------------------------------------------------
Notes:
----------------------------------------------------------------------------
Compile cgen:
( cd libcevap && cc -g -o cgen cgen.c ctyp.c smem.c )
Generate C stubs:
( cd libcevap && ./libcevap_gen.sh )
Option -lowercase would generate all lowercase struct and function names
Compile test:
( cd libcevap && ( rm a.out ; cc -g main.c cevap*.c smem.c ) )
Option -DCevap_lowercasE would tell main.c that -lowercase was used above.
----------------------------------------------------------------------------
For a description of CgeN see libcevap/cgen.txt
The generated code uses smem.[ch] out of one of my BSD licensed projects.
For a description see end of libcevap/smem.h .
------------------------------------------------------------------------

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@ -1,39 +0,0 @@
/*
cc -g -DCevap_lowercasE -c main.c
*/
#include <stdio.h>
#include <stdlib.h>
#include "cevapi.h"
#include "smem.h"
int main(int argc, char **argv)
{
#ifdef Cevap_lowercasE
struct cevapi *cevap= NULL;
#else
struct CevapI *cevap= NULL;
#endif
int ret;
/* full memory supervision */
Smem_set_record_items(1);
/* one short trip for testing */
#ifdef Cevap_lowercasE
ret= cevapi_new(&cevap,0);
if(ret>0)
cevapi_destroy(&cevap,0);
#else /* Cevap_lowercasE */
ret= Cevapi_new(&cevap,0);
if(ret>0)
Cevapi_destroy(&cevap,0);
#endif /* ! Cevap_lowercasE */
/* report any leaked memory */
Smem_stderr(1|2);
exit(ret<=0);
}

View File

@ -1,445 +0,0 @@
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define Smem_included_by_smem_C
#include "smem.h"
/* ------------------------------ SmemiteM ----------------------------- */
int Smemitem_new(item,data,size,next,hash_start,flag)
struct SmemiteM **item;
char *data;
size_t size;
struct SmemiteM *next;
struct SmemiteM **hash_start;
int flag;
{
struct SmemiteM *t;
*item= t= (struct SmemiteM *) malloc(sizeof(struct SmemiteM));
if(t==NULL)
return(-1);
t->data= data;
t->size= size;
t->prev= NULL;
t->next= next;
#ifdef Smem_with_hasH
t->hash_next= NULL;
t->hash_prev= NULL;
#endif /* Smem_with_hasH */
if(next!=NULL) {
if(next->prev!=NULL) {
t->prev= next->prev;
next->prev->next= t;
}
next->prev= t;
}
#ifdef Smem_with_hasH
if(hash_start!=NULL) {
t->hash_next= *hash_start;
if(t->hash_next!=NULL) {
t->hash_next->hash_prev= t;
}
*hash_start= t;
}
#endif /* Smem_with_hasH */
return(1);
}
int Smemitem_destroy(in_item,hash_start,flag)
struct SmemiteM **in_item;
struct SmemiteM **hash_start;
int flag;
{
struct SmemiteM *item;
item= *in_item;
if(item==NULL)
return(0);
if(item==Smem_start_iteM)
Smem_start_iteM= item->next;
if(item->prev!=NULL)
item->prev->next= item->next;
if(item->next!=NULL)
item->next->prev= item->prev;
#ifdef Smem_with_hasH
if(hash_start!=NULL) {
if(item==*hash_start)
*hash_start= item->hash_next;
if(item->hash_prev!=NULL)
item->hash_prev->hash_next= item->hash_next;
if(item->hash_next!=NULL)
item->hash_next->hash_prev= item->hash_prev;
}
#endif /* Smem_with_hasH */
free((char *) item);
*in_item= NULL;
return(1);
}
int Smemitem_report(item,line,flag)
struct SmemiteM *item;
char line[1024];
int flag;
{
char *cpt;
int i,upto;
sprintf(line,"%4lu bytes at %8.8lx ",(unsigned long) item->size,
(unsigned long) item->data);
cpt= line+strlen(line);
if(item->size<=256)
upto= item->size;
else
upto= 256;
if(item->data!=NULL) {
strcpy(cpt,"= \"");
cpt+= 3;
for(i=0;i<upto;i++){
if(item->data[i]<32 || item->data[i]>=127 || item->data[i]=='\\') {
sprintf(cpt,"\\%2.2X",(unsigned char) item->data[i]);
cpt+= 3;
} else {
*(cpt++)= item->data[i];
}
}
if(i<item->size) {
sprintf(cpt,"\" [truncated]");
} else {
*(cpt++)= '"';
*cpt= 0;
}
}
return(1);
}
int Smemitem_stderr(item,flag)
struct SmemiteM *item;
int flag;
{
char line[1024];
Smemitem_report(item,line,0);
fprintf(stderr,"%s\n",line);
return(1);
}
/* -------------------------------- Smem ------------------------------ */
int Smem_protest(line,flag)
char *line;
int flag;
{
fprintf(stderr,"%s\n",line);
return(1);
}
int Smem_hashindex(ptr,flag)
char *ptr;
int flag;
{
unsigned long idx;
idx= (unsigned long) ptr;
return((idx>>Smem_hashshifT)%(Smem_hashsizE));
}
/* find a certain memory item */
struct SmemiteM *Smem_find_item(ptr,flag)
char *ptr;
int flag;
{
int misscount= 0,idx;
struct SmemiteM *current;
#ifdef Smem_with_hasH
idx= Smem_hashindex(ptr,0);
for(current= Smem_hasH[idx];current!=NULL;current= current->hash_next) {
if(current->data==ptr)
return(current);
misscount++;
}
#else /* Smem_with_hasH */
for(current= Smem_start_iteM;current!=NULL;current= current->next) {
if(current->data==ptr)
return(current);
misscount++;
}
#endif /* ! Smem_with_hasH */
return(NULL);
}
int Smem_search_and_delete(ptr,flag)
char *ptr;
int flag;
/*
bit0= revoke registration : decrement counters
*/
{
int idx;
struct SmemiteM *current;
current= Smem_find_item(ptr,0);
if(current==NULL)
return(0);
Smem_record_counT--;
Smem_record_byteS-= current->size;
idx= Smem_hashindex(ptr,0);
Smemitem_destroy(&current,&(Smem_hasH[idx]),0);
Smem_hash_counteR[idx]-= 1.0;
if(flag&1) {
Smem_malloc_counT--;
Smem_pending_counT--;
}
return(1);
}
char *Smem_malloc(size)
size_t size;
{
int idx;
char *cpt;
if(size==0) {
Smem_protest("########### smem.c : malloc(0) caught",0);
return(NULL);
}
/* if(size==1032)
cpt= NULL; / * set breakpoint here to find requests of certain size */
cpt= (char *) malloc(size);
if(cpt==NULL) {
char text[161];
sprintf(text,"########### smem.c : malloc( %lu ) returned NULL",
(unsigned long) size);
Smem_protest(text,0);
return(NULL);
}
/* if(cpt==0x080a1e20)
cpt= NULL; / * set breakpoint here to find origin of certain address */
Smem_malloc_counT++;
Smem_pending_counT++;
if(Smem_record_itemS) {
idx= Smem_hashindex(cpt,0);
Smem_hash_counteR[idx]+= 1.0;
if(Smemitem_new(&Smem_start_iteM,cpt,size,Smem_start_iteM,
&(Smem_hasH[idx]),0)<=0) {
Smem_protest(
"########### smem.c : malloc( sizeof(SmemiteM) ) returned NULL",0);
return(NULL);
}
Smem_record_counT++;
Smem_record_byteS+= size;
}
return(cpt);
}
int Smem_free(ptr)
char *ptr;
{
if(ptr==NULL) {
Smem_protest("########### smem.c : free() of NULL pointer caught",0);
return(0);
}
if(Smem_record_itemS) {
if(Smem_search_and_delete(ptr,0)<=0) {
Smem_protest("########### smem.c : free() of unrecorded pointer caught",0);
return(0);
}
}
Smem_free_counT++;
Smem_pending_counT--;
free(ptr);
return(1);
}
int Smem_report(line,flag)
char line[1024];
int flag;
{
sprintf(line,"malloc= %.f , free= %.f , pending= %.f",
Smem_malloc_counT,Smem_free_counT,Smem_pending_counT);
if(Smem_record_itemS) {
sprintf(line+strlen(line)," , bytes=%.f , records= %.f",
Smem_record_byteS,Smem_record_counT);
}
return(1);
}
int Smem_stderr(flag)
int flag;
/*
bit0= report 50 youngest pending items too
bit1= do not report if nothing is pending
*/
{
struct SmemiteM *current;
char line[1024];
int i= 0;
if(flag&2)
if(Smem_pending_counT==0.0
&& Smem_record_counT==0.0
&& Smem_record_byteS==0.0)
return(2);
Smem_report(line,0);
fprintf(stderr,"%s\n",line);
if(flag&1) {
for(current= Smem_start_iteM;current!=NULL;current= current->next) {
Smemitem_stderr(current,0);
if(++i>=50)
break;
}
if(current!=NULL)
if(current->next!=NULL)
fprintf(stderr,"[list truncated]\n");
}
return(1);
}
int Smem_set_record_items(value)
int value;
{
int i;
if(!Smem_hash_initializeD) {
for(i=0;i<Smem_hashsizE;i++) {
Smem_hasH[i]= NULL;
Smem_hash_counteR[i]= 0.0;
}
Smem_hash_initializeD= 1;
}
Smem_record_itemS= value;
return(1);
}
int Smem_is_recorded(ptr,flag)
char *ptr;
int flag;
/*
bit0= complain if return(0)
*/
{
if(Smem_record_itemS==0)
return(2);
if(Smem_find_item(ptr,0)!=NULL)
return(1);
if(flag&1)
Smem_protest("########### smem.c : free() of unrecorded pointer caught",0);
return(0);
}
/* A simple C string cloner */
int Smem_clone_string(ptr,text)
char **ptr;
char *text;
{
*ptr= Smem_malloC(strlen(text)+1);
if(*ptr==NULL)
return(-1);
strcpy(*ptr,text);
return(1);
}
/* ----------------- for usage via debugger commands --------------------- */
/* find a certain memory item */
struct SmemiteM *Smem_find_data(ptr)
char *ptr;
{
return(Smem_find_item(ptr,0));
}
/* browsing the list */
struct SmemiteM *Smem_fetch_item(step,flag)
int step;
int flag;
/*
bit0= reset cursor (and therefore address absolutely)
*/
{
static struct SmemiteM *current= NULL;
if((flag&1)||current==NULL)
current= Smem_start_iteM;
if(step>0) {
for(;current!=NULL;current= current->next) {
if(step==0)
return(current);
step--;
}
} else if(step<0) {
for(;current!=NULL;current= current->prev) {
if(step==0)
return(current);
step++;
}
} else {
return(current);
}
return(NULL);
}
int Smem_print_hash_counter() {
int i;
for(i=0;i<Smem_hashsizE;i++)
printf("%4d : %10.f\n",i,Smem_hash_counteR[i]);
return(1);
}
/* delete all recorded memory items */
int Smem_delete_all_items()
{
int ret;
while(Smem_start_iteM!=NULL) {
ret= Smem_free(Smem_start_iteM->data);
if(ret<=0)
return(0);
}
return(1);
}

View File

@ -1,165 +0,0 @@
#ifndef Smem_includeD
#define Smem_includeD
/* compile time adjustable parameters : */
/* if not defined, flat malloc() and free() is used */
#define Smem_own_functionS
#ifdef Smem_no_own_functionS
#undef Smem_own_functionS
#endif /* Smem_no_own_functionS */
/* if not defined, the record items will be smaller by 8 byte
but deletion of items may be much slower */
#define Smem_with_hasH
struct SmemiteM {
char *data;
size_t size;
struct SmemiteM *prev,*next;
struct SmemiteM *hash_prev,*hash_next;
};
#ifdef Smem_own_functionS
char *Smem_malloc();
int Smem_free();
#define TSOB_FELD(typ,anz) (typ *) Smem_malloc((anz)*sizeof(typ));
#define Smem_malloC Smem_malloc
#define Smem_freE Smem_free
#else /* Smem_own_functionS */
#define TSOB_FELD(typ,anz) (typ *) malloc((anz)*sizeof(typ));
#define Smem_malloC malloc
#define Smem_freE free
#endif /* ! Smem_own_functionS */
int Smem_set_record_items();
int Smem_stderr();
int Smem_clone_string();
#define Smem_hashsizE 251
#define Smem_hashshifT 8
#ifdef Smem_included_by_smem_C
double Smem_malloc_counT= 0.0;
double Smem_free_counT= 0.0;
double Smem_pending_counT= 0.0;
struct SmemiteM *Smem_start_iteM= NULL;
struct SmemiteM *Smem_hasH[Smem_hashsizE];
double Smem_hash_counteR[Smem_hashsizE];
/* these both init values are essential, since setting Smem_record_itemS=1
by use of Smem_set_record_items() initializes the hash array
(i do not really trust the compiler producers to have read K&R) */
int Smem_hash_initializeD= 0;
int Smem_record_itemS= 0;
double Smem_record_counT= 0.0;
double Smem_record_byteS= 0.0;
#else /* Smem_included_by_smem_C */
extern double Smem_malloc_counT;
extern double Smem_free_counT;
extern double Smem_pending_counT;
extern struct SmemiteM *Smem_start_iteM;
extern struct SmemiteM *Smem_hasH[Smem_hashsizE];
extern double Smem_hash_counteR[Smem_hashsizE];
extern int Smem_hash_initializeD;
extern int Smem_record_itemS;
extern double Smem_record_counT;
extern double Smem_record_byteS;
#endif /* ! Smem_included_by_smem_C */
#endif /* ! Smem_includeD */
/*
smem
Functions to replace malloc() and free() in order to get more control
over memory leaks or spurious errors caused by faulty usage of malloc()
and free().
Sourcecode provisions:
Use only the following macros for memory management:
TSOB_FELD(type,count) creates an array of items of given type
Smem_malloC() analogue of malloc()
Smem_freE() analogue of free()
One may #define malloc Smem_malloC resp. #define free Smem_freE
but better would be to review (and often to streamline) the sourcecode
in respect to those two functions.
Speed versus control:
In production versions, where maximum speed is required, one may undefine
the macro Smem_own_functionS in smem.h .
This causes the above macros to directly invoke malloc() and free() without
any speed reduction (and without any additional use).
Undefinitio can be done globaly by modifying smem.h or locally by defining
Smem_no_own_functionS before including smem.h .
If Smem_own_functionS remains defined, then the functions
Smem_malloc()
Smem_free()
are used rather than malloc() and free().
They count the number of calls to maintain a rough overview of memory usage.
Smem_malloc() additionally checks for 0 size and Smem_free() checks for
NULL pointers, which they both report to stderr. Eventually one should set
a breakpoint in function Smem_protest() to learn about the origin of such
messages.
A status line may be obtained by Smem_report() or printed by Smem_stderr().
As long as the variable Smem_record_itemS is set to 0, there is not very much
overhead compared with malloc() and free().
If the variable is set to 1 by Smem_set_record_items() then all malloc()
results are kept in a list where they will be deleted by their corresponding
Smem_free() calls. If a pointer is to be freed, which is not recorded in the
list then an error message will be printed to stderr. The memory will not
be freed !
This mode not only may be very slow, it also consumes at least 16 byte per
piece of data which was obtained by malloc as long as it has not been freed.
Due to the current nature of the list, large numbers of memory items are freed
much faster in the reverse order of their creation. If there is a list of
100000 strings to delete, it is very rewarding to free the youngest ones first.
A shortcut via hashing is available but consumes 24 bytes rather than 16.
(see above Smem_with_hasH )
The function Smem_is_recorded() can be used to check wether a pointer is
valid according to the list. It returns :
0 = is not in list , 1 = is in list , 2 = recording is off
If one decides to start recording malloc() results in the midst of a program
run, one has to be aware of false protests of Smem_free() if a memory piece
has been allocated before recording started. This will also cause those pieces
to be memory leaks because Smem_free() refuses to delete them. (Freeing memory
that was not obtained by malloc or was already freed previously can result in
deferred SIGSEGV or similar trouble, depending on OS and library.)
Also in that case one should stop recording before ending the program, to
avoid a lot of false complaints about longliving memory objects.
*/

View File

@ -1,16 +1,15 @@
/* test/libburner.c , API illustration of burning data or audio tracks to CD */
/* Copyright (C) 2005 - 2007 Thomas Schmitt <scdbackup@gmx.net> */
/* Provided under GPLv2,see also "License and copyright aspects" at file end */
/* Copyright (C) 2005 - 2006 Thomas Schmitt <scdbackup@gmx.net> */
/* Provided under GPL, see also "License and copyright aspects" at file end */
/** Overview
libburner is a minimal demo application for the library libburn as provided
on http://libburnia-project.org . It can list the available devices, can
blank a CD-RW or DVD-RW, can format DVD-RW and BD-RE, can burn to CD-R,
CD-RW, DVD-R, DVD+R, DVD+R/DL, DVD+RW, DVD-RW, DVD-RAM, BD-RE.
Not supported yet: DVD-R/DL, BD-R.
on http://libburnia.pykix.org . It can list the available devices, can
blank a CD-RW or DVD-RW, can format a DVD-RW, can burn to CD-R, CD-RW, DVD-R,
DVD+R, DVD+RW, DVD-RAM or DVD-RW. Not supported yet: double layer media.
It's main purpose, nevertheless, is to show you how to use libburn and also
to serve the libburnia team as reference application. libburner.c does indeed
@ -29,9 +28,8 @@
With that aquired drive you can blank a CD-RW
libburner_blank_disc()
or you can format a DVD-RW to profile "Restricted Overwrite" (needed once)
or an unused BD-RE to default size
libburner_format_owrt()
With the aquired drive you can burn to CD or DVD
libburner_format_row()
With the aquired drive you can burn to CD-R, CD-RW, DVD+RW, DVD-RAM, DVD-RW
libburner_payload()
When everything is done, main() releases the drive and shuts down libburn:
burn_drive_release();
@ -125,28 +123,21 @@ int libburner_aquire_by_adr(char *drive_adr)
int ret;
char libburn_drive_adr[BURN_DRIVE_ADR_LEN];
/* Some not-so-harmless drive addresses get blocked in this demo */
if (strncmp(drive_adr, "stdio:/dev/fd/", 14) == 0 ||
strcmp(drive_adr, "stdio:-") == 0) {
fprintf(stderr, "Will not work with pseudo-drive '%s'\n",
drive_adr);
return 0;
}
/* This tries to resolve links or alternative device files */
ret = burn_drive_convert_fs_adr(drive_adr, libburn_drive_adr);
if (ret<=0) {
fprintf(stderr, "Address does not lead to a CD burner: '%s'\n",
drive_adr);
return 0;
fprintf(stderr,"Address does not lead to a CD burner: '%s'\n",
drive_adr);
return ret;
}
fprintf(stderr,"Aquiring drive '%s' ...\n", libburn_drive_adr);
ret = burn_drive_scan_and_grab(&drive_list, libburn_drive_adr, 1);
printf("Aquiring drive '%s' ...\n",libburn_drive_adr);
ret = burn_drive_scan_and_grab(&drive_list,libburn_drive_adr,1);
if (ret <= 0) {
fprintf(stderr,"FAILURE with persistent drive address '%s'\n",
libburn_drive_adr);
} else {
fprintf(stderr,"Done\n");
printf("Done\n");
drive_is_grabbed = 1;
}
return ret;
@ -172,7 +163,7 @@ int libburner_aquire_by_driveno(int *driveno)
printf("Beginning to scan for devices ...\n");
while (!burn_drive_scan(&drive_list, &drive_count))
usleep(100002);
usleep(1002);
if (drive_count <= 0 && *driveno >= 0) {
printf("FAILED (no drives found)\n");
return 0;
@ -315,45 +306,26 @@ int libburner_blank_disc(struct burn_drive *drive, int blank_fast)
}
/** Formats unformatted DVD-RW to profile 0013h "Restricted Overwrite"
which needs no blanking for re-use but is not capable of multi-session.
Expect a behavior similar to blanking with unusual noises from the drive.
/** Persistently changes DVD-RW profile 0014h "Sequential Recording" to
profile 0013h "Restricted Overwrite" which needs no blanking for re-use
but is not capable of multi-session.
Formats unformatted BD-RE to default size. This will allocate some
reserve space, test for bad blocks and make the media ready for writing.
Expect a very long run time.
Expect a behavior similar to blanking with unusual noises from the drive.
*/
int libburner_format_owrt(struct burn_drive *drive)
int libburner_format_row(struct burn_drive *drive)
{
struct burn_progress p;
double percent = 1.0;
int ret, status, num_formats, format_flag= 0;
off_t size = 0;
unsigned dummy;
if (current_profile == 0x13) {
fprintf(stderr, "IDLE: DVD-RW media is already formatted\n");
return 2;
} else if (current_profile == 0x43) {
ret = burn_disc_get_formats(drive, &status, &size, &dummy,
&num_formats);
if (ret > 0 && status == BURN_FORMAT_IS_FORMATTED) {
fprintf(stderr,
"IDLE: BD-RE media is already formatted\n");
return 2;
}
size = 0; /* does not really matter */
format_flag = 3<<1; /* format to default size, no quick */
} else if (current_profile == 0x14) { /* sequential DVD-RW */
size = 128 * 1024 * 1024;
format_flag = 1; /* write initial 128 MiB */
} else {
fprintf(stderr, "FATAL: Can only format DVD-RW or BD-RE\n");
} else if (current_profile != 0x14) {
fprintf(stderr, "FATAL: Can only format DVD-RW\n");
return 0;
}
printf("Beginning to format media.\n");
burn_disc_format(drive, size, format_flag);
burn_disc_format(drive, (off_t) 0, 0);
sleep(1);
while (burn_drive_get_status(drive, &p) != BURN_DRIVE_IDLE) {
@ -365,10 +337,9 @@ int libburner_format_owrt(struct burn_drive *drive)
}
burn_disc_get_profile(drive_list[0].drive, &current_profile,
current_profile_name);
if (current_profile == 0x14 || current_profile == 0x13)
printf("Media type now: %4.4xh \"%s\"\n",
current_profile, current_profile_name);
if (current_profile == 0x14) {
printf("Media type now: %4.4xh \"%s\"\n",
current_profile, current_profile_name);
if (current_profile != 0x13) {
fprintf(stderr,
"FATAL: Failed to change media profile to desired value\n");
return 0;
@ -381,10 +352,6 @@ int libburner_format_owrt(struct burn_drive *drive)
To make sure a data image is fully readable on any Linux machine, this
function adds 300 kiB of padding to the (usualy single) track.
Audio tracks get padded to complete their last sector.
A fifo of 4 MB is installed between each track and its data source.
Each of the 4 MB buffers gets allocated automatically as soon as a track
begins to be processed and it gets freed as soon as the track is done.
The fifos do not wait for buffer fill but writing starts immediately.
In case of external signals expect abort handling of an ongoing burn to
last up to a minute. Wait the normal burning timespan before any kill -9.
@ -396,7 +363,7 @@ int libburner_payload(struct burn_drive *drive,
char source_adr[][4096], int source_adr_count,
int multi, int simulate_burn, int all_tracks_type)
{
struct burn_source *data_src, *fifo_src[99];
struct burn_source *data_src;
struct burn_disc *target_disc;
struct burn_session *session;
struct burn_write_opts *burn_options;
@ -405,7 +372,6 @@ int libburner_payload(struct burn_drive *drive,
struct burn_progress progress;
time_t start_time;
int last_sector = 0, padding = 0, trackno, unpredicted_size = 0, fd;
int fifo_chunksize = 2352, fifo_chunks = 1783; /* ~ 4 MB fifo */
off_t fixed_size;
char *adr, reasons[BURN_REASONS_LEN];
struct stat stbuf;
@ -414,8 +380,6 @@ int libburner_payload(struct burn_drive *drive,
all_tracks_type = BURN_MODE1;
/* a padding of 300 kiB helps to avoid the read-ahead bug */
padding = 300*1024;
fifo_chunksize = 2048;
fifo_chunks = 2048; /* 4 MB fifo */
}
target_disc = burn_disc_create();
@ -426,7 +390,6 @@ int libburner_payload(struct burn_drive *drive,
tracklist[trackno] = track = burn_track_create();
burn_track_define_data(track, 0, padding, 1, all_tracks_type);
/* Open file descriptor to source of track data */
adr = source_adr[trackno];
fixed_size = 0;
if (adr[0] == '-' && adr[1] == 0) {
@ -440,8 +403,6 @@ int libburner_payload(struct burn_drive *drive,
}
if (fixed_size==0)
unpredicted_size = 1;
/* Convert this filedescriptor into a burn_source object */
data_src = NULL;
if (fd>=0)
data_src = burn_fd_source_new(fd, -1, fixed_size);
@ -453,29 +414,14 @@ int libburner_payload(struct burn_drive *drive,
strerror(errno));
return 0;
}
/* Install a fifo object on top of that data source object */
fifo_src[trackno] = burn_fifo_source_new(data_src,
fifo_chunksize, fifo_chunks, 0);
if (fifo_src[trackno] == NULL) {
fprintf(stderr,
"FATAL: Could not create fifo object of 4 MB\n");
return 0;
}
/* Use the fifo object as data source for the track */
if (burn_track_set_source(track, fifo_src[trackno])
!= BURN_SOURCE_OK) {
fprintf(stderr,
"FATAL: Cannot attach source object to track object\n");
if (burn_track_set_source(track, data_src) != BURN_SOURCE_OK) {
printf("FATAL: Cannot attach source object to track object\n");
return 0;
}
burn_session_add_track(session, track, BURN_POS_END);
printf("Track %d : source is '%s'\n", trackno+1, adr);
/* Give up local reference to the data burn_source object */
burn_source_free(data_src);
} /* trackno loop end */
/* Evaluate drive and media */
@ -515,49 +461,29 @@ int libburner_payload(struct burn_drive *drive,
burn_write_opts_free(burn_options);
while (burn_drive_get_status(drive, NULL) == BURN_DRIVE_SPAWNING)
usleep(100002);
usleep(1002);
while (burn_drive_get_status(drive, &progress) != BURN_DRIVE_IDLE) {
if (progress.sectors <= 0 ||
(progress.sector >= progress.sectors - 1 &&
!unpredicted_size) ||
(unpredicted_size && progress.sector == last_sector))
if( progress.sectors <= 0 || progress.sector == last_sector)
printf(
"Thank you for being patient since %d seconds.",
"Thank you for being patient since %d seconds.\n",
(int) (time(0) - start_time));
else if(unpredicted_size)
printf("Track %d : sector %d", progress.track+1,
printf("Track %d : sector %d\n", progress.track+1,
progress.sector);
else
printf("Track %d : sector %d of %d",progress.track+1,
printf("Track %d : sector %d of %d\n",progress.track+1,
progress.sector, progress.sectors);
last_sector = progress.sector;
if (progress.track >= 0 && progress.track < source_adr_count) {
int size, free_bytes, ret;
char *status_text;
ret = burn_fifo_inquire_status(
fifo_src[progress.track], &size, &free_bytes,
&status_text);
if (ret >= 0 )
printf(" [fifo %s, %2d%% fill]", status_text,
(int) (100.0 - 100.0 *
((double) free_bytes) /
(double) size));
}
printf("\n");
sleep(1);
}
printf("\n");
for (trackno = 0 ; trackno < source_adr_count; trackno++) {
burn_source_free(fifo_src[trackno]);
for (trackno = 0 ; trackno < source_adr_count; trackno++)
burn_track_free(tracklist[trackno]);
}
burn_session_free(session);
burn_disc_free(target_disc);
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 */
current_profile != 0x12) /* not with DVD+RW, DVD-RW, DVD-RAM */
printf("NOTE: Media left appendable.\n");
if (simulate_burn)
printf("\n*** Did TRY to SIMULATE burning ***\n\n");
@ -694,7 +620,7 @@ int main(int argc, char **argv)
if (ret)
exit(ret);
printf("Initializing libburnia-project.org ...\n");
printf("Initializing libburnia.pykix.org ...\n");
if (burn_initialize())
printf("Done\n");
else {
@ -720,7 +646,7 @@ int main(int argc, char **argv)
{ ret = 0; goto release_drive; }
if (do_blank) {
if (do_blank > 100)
ret = libburner_format_owrt(drive_list[driveno].drive);
ret = libburner_format_row(drive_list[driveno].drive);
else
ret = libburner_blank_disc(drive_list[driveno].drive,
do_blank == 1);

View File

@ -1,12 +1,11 @@
/* 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 Thomas Schmitt <scdbackup@gmx.net> Provided under GPL */
/** Overview
telltoc is a minimal demo application for the library libburn as provided
on http://libburnia-project.org . It can list the available devices, can
on http://libburnia.pykix.org . It can list the available devices, can
display some drive properties, the type of media, eventual table of content
and multisession info for mkisofs option -C .
It's main purpose, nevertheless, is to show you how to use libburn and also
@ -25,8 +24,6 @@
telltoc_media() prints some information about the media in a drive
telltoc_toc() prints a table of content (if there is content)
telltoc_msinfo() prints parameters for mkisofs option -C
telltoc_read_and_print() reads from data CD or from DVD and prints 7-bit
to stdout (encodings 0,2) or 8-bit to file (encoding 1)
When everything is done, main() releases the drive and shuts down libburn:
burn_drive_release();
burn_finish()
@ -75,11 +72,6 @@ int telltoc_aquire_by_adr(char *drive_adr);
int telltoc_aquire_by_driveno(int *drive_no, int silent);
/* A message from --toc to --read_and_print (CD tracksize is a bit tricky) */
static int last_track_start = 0, last_track_size = -1;
static int media_is_cd_profile = 0;
/* ------------------------------- API gestures ---------------------------- */
/** You need to aquire a drive before burning. The API offers this as one
@ -108,33 +100,22 @@ int telltoc_aquire_drive(char *drive_adr, int *driveno, int silent_drive)
/** If the persistent drive address is known, then this approach is much
more un-obtrusive to the systemwide livestock of drives. Only the
given drive device will be opened during this procedure.
Special drive addresses stdio:<path> direct output to a hard disk file
which will behave much like a DVD-RAM.
*/
int telltoc_aquire_by_adr(char *drive_adr)
{
int ret;
char libburn_drive_adr[BURN_DRIVE_ADR_LEN];
/* <<< ts A70907 FOR TESTING ONLY !
struct burn_drive_info *test_drive_list;
*/
/* This tries to resolve links or alternative device files */
ret = burn_drive_convert_fs_adr(drive_adr, libburn_drive_adr);
if (ret<=0) {
fprintf(stderr, "Address does not lead to a CD burner: '%s'\n",
fprintf(stderr,"Address does not lead to a CD burner: '%s'\n",
drive_adr);
return 0;
return ret;
}
/* <<< ts A70907 FOR TESTING ONLY !
ret = burn_drive_scan_and_grab(&test_drive_list, "/dev/sg2", 1);
*/
fprintf(stderr,"Aquiring drive '%s' ...\n", libburn_drive_adr);
ret = burn_drive_scan_and_grab(&drive_list, libburn_drive_adr, 1);
fprintf(stderr,"Aquiring drive '%s' ...\n",libburn_drive_adr);
ret = burn_drive_scan_and_grab(&drive_list,libburn_drive_adr,1);
if (ret <= 0) {
fprintf(stderr,"FAILURE with persistent drive address '%s'\n",
libburn_drive_adr);
@ -142,11 +123,6 @@ int telltoc_aquire_by_adr(char *drive_adr)
fprintf(stderr,"Done\n");
drive_is_grabbed = 1;
}
/* <<< ts A70907 FOR TESTING ONLY !
burn_drive_info_free(test_drive_list);
*/
return ret;
}
@ -171,7 +147,7 @@ int telltoc_aquire_by_driveno(int *driveno, int silent_drive)
fprintf(stderr, "Beginning to scan for devices ...\n");
while (!burn_drive_scan(&drive_list, &drive_count))
usleep(100002);
usleep(1002);
if (drive_count <= 0 && *driveno >= 0) {
fprintf(stderr, "FAILED (no drives found)\n");
return 0;
@ -258,7 +234,7 @@ int telltoc_media(struct burn_drive *drive)
printf("Media current: ");
ret = burn_disc_get_profile(drive, &profile_no, profile_name);
if (profile_no > 0 && ret > 0) {
if (profile_no > 0 && ret >0) {
if (profile_name[0])
printf("%s\n", profile_name);
else
@ -467,9 +443,8 @@ int telltoc_formatlist(struct burn_drive *drive)
int telltoc_toc(struct burn_drive *drive)
{
int num_sessions = 0 , num_tracks = 0 , lba = 0, pmin, psec, pframe;
int track_count = 0, pno;
int track_count = 0;
int session_no, track_no;
char profile_name[80];
struct burn_disc *disc= NULL;
struct burn_session **sessions;
struct burn_track **tracks;
@ -504,7 +479,6 @@ int telltoc_toc(struct burn_drive *drive)
track_count,
((toc_entry.control&7)<4?"audio":"data "),
lba, pmin, psec, pframe);
last_track_start = lba;
}
burn_session_get_leadout_entry(sessions[session_no],
&toc_entry);
@ -520,11 +494,6 @@ int telltoc_toc(struct burn_drive *drive)
printf("Media content: session %2d ", session_no+1);
printf("leadout lba: %9d %4.2d:%2.2d:%2.2d\n",
lba, pmin, psec, pframe);
last_track_size = lba - last_track_start;
if (burn_disc_get_profile(drive, &pno, profile_name) > 0)
if (pno == 0x09 || pno == 0x0a)
media_is_cd_profile = 1;
}
if (disc!=NULL)
burn_disc_free(disc);
@ -589,125 +558,6 @@ ex:;
}
/**
@param encoding determins how to format output on stdout:
0 = default , 1 = raw 8 bit (dangerous for tty) , 2 = hex
*/
int telltoc_read_and_print(struct burn_drive *drive,
int start_sector, int sector_count, char *raw_file, int encoding)
{
int j, i, request = 16, done, lbas = 0, final_cd_try = -1, todo;
int ret = 0;
char buf[16 * 2048], line[81];
off_t data_count, total_count= 0, last_reported_count= 0;
struct stat stbuf;
FILE *raw_fp = NULL;
if (start_sector == -1)
start_sector = last_track_start;
if (sector_count == -1) {
sector_count = last_track_start + last_track_size
- start_sector;
if (media_is_cd_profile) /* In case it is a TAO track */
final_cd_try = 0; /* allow it (-1 is denial) */
}
if (start_sector < 0)
start_sector = 0;
if (sector_count <= 0)
sector_count = 2147483632;
if (sector_count <= 0)
return -1;
if (encoding == 1) {
if (stat(raw_file,&stbuf) != -1) {
if (!(S_ISCHR(stbuf.st_mode) || S_ISFIFO(stbuf.st_mode)
|| (stbuf.st_mode & S_IFMT) == S_IFSOCK )) {
fprintf(stderr,
"SORRY: target file '%s' already existing\n",
raw_file);
return 1;
}
}
raw_fp = fopen(raw_file,"w");
if (raw_fp == NULL) {
fprintf(stderr,"SORRY: cannot open target file '%s' (%s)\n", raw_file, strerror(errno));
return 1;
}
printf(
"Data : start=%ds , count=%ds , read=0s , encoding=%d:'%s'\n",
start_sector, sector_count, encoding, raw_file);
} else
printf(
"Data : start=%ds , count=%ds , read=0 , encoding=%d\n",
start_sector, sector_count, encoding);
todo = sector_count - 2*(final_cd_try > -1);
for (done = 0; done < todo && final_cd_try != 1; done += request) {
if (todo - done > 16)
request = 16;
else
request = todo - done;
ret = burn_read_data(drive,
((off_t) start_sector + done) * (off_t) 2048,
buf, (off_t) (request * 2048), &data_count, 1);
print_result:;
total_count += data_count;
if (encoding == 1) {
if (data_count > 0)
fwrite(buf, data_count, 1, raw_fp);
} else for (i = 0; i < data_count; i += 16) {
if (encoding == 0) {
sprintf(line, "%8ds + %4d : ",
start_sector + done + i / 2048,
i % 2048);
lbas = strlen(line);
}
for (j = 0; j < 16 && i + j < data_count; j++) {
if (buf[i + j] >= ' ' && buf[i + j] <= 126 &&
encoding != 2)
sprintf(line + lbas + 3 * j, " %c ",
(int) buf[i + j]);
else
sprintf(line + lbas + 3 * j, "%2.2X ",
(unsigned char) buf[i + j]);
}
line[lbas + 3 * (j - 1) + 2] = 0;
printf("%s\n",line);
}
if (encoding == 1 &&
total_count - last_reported_count >= 1000 * 2048) {
fprintf(stderr,
"\rReading data : start=%ds , count=%ds , read=%ds ",
start_sector, sector_count,
(int) (total_count / (off_t) 2048));
last_reported_count = total_count;
}
if (ret <= 0) {
fprintf(stderr, "SORRY : Reading failed.\n");
break;
}
}
if (ret > 0 && media_is_cd_profile && final_cd_try == 0) {
/* In a SAO track the last 2 frames should be data too */
final_cd_try = 1;
burn_read_data(drive,
((off_t) start_sector + todo) * (off_t) 2048,
buf, (off_t) (2 * 2048), &data_count, 2);
if (data_count < 2 * 2048)
fprintf(stderr, "\rNOTE : Last two frames of CD track unreadable. This is normal if TAO track.\n");
if (data_count > 0)
goto print_result;
}
if (last_reported_count > 0)
fprintf(stderr,
"\r \r");
printf("End Of Data : start=%ds , count=%ds , read=%ds\n",
start_sector, sector_count,(int) (total_count / (off_t) 2048));
return ret;
}
/** The setup parameters of telltoc */
static char drive_adr[BURN_DRIVE_ADR_LEN] = {""};
static int driveno = 0;
@ -716,8 +566,6 @@ static int do_toc = 0;
static int do_msinfo = 0;
static int print_help = 0;
static int do_capacities = 0;
static int read_start = -2, read_count = -2, print_encoding = 0;
static char print_raw_file[4096] = {""};
/** Converts command line arguments into above setup parameters.
@ -760,26 +608,6 @@ int telltoc_setup(int argc, char **argv)
} else if (!strcmp(argv[i], "--toc")) {
do_toc = 1;
} else if (!strcmp(argv[i], "--read_and_print")) {
i+= 3;
if (i >= argc) {
fprintf(stderr,"--read_and_print requires three arguments: start count encoding(try 0, not 1)\n");
return 1;
}
sscanf(argv[i-2], "%d", &read_start);
sscanf(argv[i-1], "%d", &read_count);
print_encoding = 0;
if(strncmp(argv[i], "raw:", 4) == 0 || strcmp(argv[i],"1:") == 0) {
print_encoding = 1;
strcpy(print_raw_file, strchr(argv[i], ':') + 1);
if (strcmp(print_raw_file, "-") == 0) {
fprintf(stderr,
"--read_and_print does not write to \"-\" as stdout.\n");
return 1;
}
} else if(strcmp(argv[i], "hex") == 0 || strcmp(argv[i], "2") == 0)
print_encoding = 2;
} else if (!strcmp(argv[i], "--help")) {
print_help = 1;
@ -794,7 +622,6 @@ int telltoc_setup(int argc, char **argv)
printf("Usage: %s\n", argv[0]);
printf(" [--drive <address>|<driveno>|\"-\"]\n");
printf(" [--media] [--capacities] [--toc] [--msinfo]\n");
printf(" [--read_and_print <start> <count> \"0\"|\"hex\"|\"raw\":<path>]\n");
printf("Examples\n");
printf("A bus scan (needs rw-permissions to see a drive):\n");
printf(" %s --drive -\n",argv[0]);
@ -808,12 +635,6 @@ int telltoc_setup(int argc, char **argv)
printf(" mkisofs ... -C \"$msinfo\" ...\n");
printf("Obtain what is available about drive 0 and its media\n");
printf(" %s --drive 0\n",argv[0]);
printf("View blocks 16 to 19 of data CD or DVD in human readable form\n");
printf(" %s --drive /dev/sr1 --read_and_print 16 4 0 | less\n",
argv[0]);
printf("Copy last data track from CD to file /tmp/data\n");
printf(" %s --drive /dev/sr1 --toc --read_and_print -1 -1 raw:/tmp/data\n",
argv[0]);
}
return 0;
}
@ -835,14 +656,14 @@ int main(int argc, char **argv)
msinfo_alone = 1;
}
/* Default option is to do everything if possible */
if (do_media==0 && do_msinfo==0 && do_capacities==0 && do_toc==0 &&
(read_start < 0 || read_count <= 0) && driveno!=-1) {
if (do_media==0 && do_msinfo==0 && do_capacities==0 && do_toc==0
&& driveno!=-1) {
if(print_help)
exit(0);
full_default = do_media = do_msinfo = do_capacities= do_toc= 1;
full_default = do_media = do_msinfo = do_capacities= do_toc = 1;
}
fprintf(stderr, "Initializing libburnia-project.org ...\n");
fprintf(stderr, "Initializing libburnia.pykix.org ...\n");
if (burn_initialize())
fprintf(stderr, "Done\n");
else {
@ -850,11 +671,8 @@ int main(int argc, char **argv)
exit(33);
}
/* Print messages of severity WARNING or more directly to stderr */
burn_msgs_set_severities("NEVER", "WARNING", "telltoc : ");
/* Activate the default signal handler */
burn_set_signal_handling("telltoc : ", NULL, 0);
/* Print messages of severity SORRY or more directly to stderr */
burn_msgs_set_severities("NEVER", "SORRY", "telltoc : ");
/** Note: driveno might change its value in this call */
ret = telltoc_aquire_drive(drive_adr, &driveno, !full_default);
@ -891,13 +709,6 @@ int main(int argc, char **argv)
if (ret<=0)
{ret = 38; goto release_drive; }
}
if (read_start >= -1 && (read_count > 0 || read_count == -1)) {
ret = telltoc_read_and_print(drive_list[driveno].drive,
read_start, read_count, print_raw_file,
print_encoding);
if (ret<=0)
{ret = 40; goto release_drive; }
}
ret = 0;
if (toc_failed)