Compare commits
5 Commits
ZeroFiveFo
...
ZeroThreeE
Author | SHA1 | Date | |
---|---|---|---|
0d3a31e3f0 | |||
205d5fed7d | |||
19c3d448a8 | |||
89762d91b4 | |||
a6acdc64cc |
@ -3,4 +3,3 @@ Philippe Rouquier
|
||||
Gabriel Craciunescu
|
||||
George Danchev
|
||||
Jean-Francois Wauthy
|
||||
Lorenzo Taylor
|
||||
|
@ -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
|
||||
|
10
Makefile.am
10
Makefile.am
@ -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
181
README
@ -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.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
|
364
cdrskin/README
364
cdrskin/README
@ -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:
|
||||
|
@ -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
|
@ -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" ..
|
||||
)
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
||||
|
1940
cdrskin/cdrskin.c
1940
cdrskin/cdrskin.c
File diff suppressed because it is too large
Load Diff
@ -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> cdrskin dev=ATA:1,0,0 -v -atip</KBD></DD>
|
||||
<DD>$<KBD> 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> 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> cdrskin -v dev=/dev/sg1 blank=fast -eject</KBD></DD>
|
||||
<DD>$<KBD> 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> 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> cdrskin -v dev=/dev/hdc speed=12 fs=8m \</KBD></DD>
|
||||
<DD><KBD> blank=as_needed -eject padsize=300k my_image.iso</KBD></DD>
|
||||
<DD><KBD> -sao -eject padsize=300k my_image.iso</KBD></DD>
|
||||
|
||||
<DT>Write compressed afio archive on-the-fly:</DT>
|
||||
<DD>$<KBD> find . | afio -oZ - | \</KBD></DD>
|
||||
<DD><KBD> cdrskin -v dev=0,1,0 fs=32m speed=8 \</KBD></DD>
|
||||
<DD><KBD> blank=as_needed padsize=300k -</KBD></DD>
|
||||
<DD><KBD> -tao padsize=300k -</KBD></DD>
|
||||
|
||||
<DT>Write several sessions to the same CD, DVD-R[W] or DVD+R[/DL]:</DT>
|
||||
<DD>$<KBD> 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> cdrskin dev=/dev/hdc -v padsize=300k -multi -tao 1.iso</KBD>
|
||||
</DD>
|
||||
<DD>$<KBD> cdrskin dev=/dev/hdc -v padsize=300k -multi 2.iso</KBD>
|
||||
<DD>$<KBD> cdrskin dev=/dev/hdc -v padsize=300k -multi -tao 2.iso</KBD>
|
||||
</DD>
|
||||
<DD>$<KBD> cdrskin dev=/dev/hdc -v padsize=300k -multi 3.iso</KBD>
|
||||
<DD>$<KBD> cdrskin dev=/dev/hdc -v padsize=300k -multi -tao 3.iso</KBD>
|
||||
</DD>
|
||||
<DD>$<KBD> cdrskin dev=/dev/hdc -v padsize=300k 4.iso</KBD></DD>
|
||||
<DD>$<KBD> 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> c_values=$(cdrskin dev=/dev/sr0 -msinfo 2>/dev/null)</KBD></DD>
|
||||
<DD>$<KBD> mkisofs ... -C "$c_values" ...</KBD></DD>
|
||||
|
||||
<DT>Inquire free space on media for a -multi run:</DT>
|
||||
<DD>$<KBD> x=$(cdrskin dev=/dev/sr0 -multi \</KBD></DD>
|
||||
<DT>Inquire free space on media for a -tao -multi run:</DT>
|
||||
<DD>$<KBD> x=$(cdrskin dev=/dev/sr0 -tao -multi \</KBD></DD>
|
||||
<DD><KBD> --tell_media_space 2>/dev/null)</KBD></DD>
|
||||
<DD>$<KBD> 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> </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> </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> </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> </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 dev='/dev/sr0' rwr-r- : 'TEAC' 'CD-ROM CD-532S'</KBD></DD>
|
||||
<DD><KBD>0 dev='/dev/sr0' rwrwr- : 'TEAC' 'CD-ROM CD-532S'</KBD></DD>
|
||||
<DD><KBD>1 dev='/dev/hdc' rwrw-- : '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>
|
||||
|
@ -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
@ -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 \
|
||||
\
|
||||
|
@ -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>/\ <BR><b>Overview of features:<\/b>/' \
|
||||
-e 's/<b>General information paragraphs:<\/b>/\ <BR><b>General information paragraphs:<\/b>/' \
|
||||
-e 's/<b>Track recording model:<\/b>/\ <BR><b>Track recording model:<\/b>/' \
|
||||
-e 's/^In general there are two types of tracks: data and audio./\ <BR>In general there are two types of tracks: data and audio./' \
|
||||
-e 's/^While audio tracks just contain a given/\ <BR>While audio tracks just contain a given/' \
|
||||
-e 's/In general there are two types of tracks: data and audio./\ <BR>In general there are two types of tracks: data and audio./' \
|
||||
-e 's/While audio tracks just contain a given/\ <BR>While audio tracks just contain a given/' \
|
||||
-e 's/<b>Write mode selection:<\/b>/\ <BR><b>Write mode selection:<\/b>/' \
|
||||
-e 's/<b>Recordable CD Media:<\/b>/\ <BR><b>Recordable CD Media:<\/b>/' \
|
||||
-e 's/<b>Overwriteable DVD Media:<\/b>/\ <BR><b>Overwriteable DVD Media:<\/b>/' \
|
||||
-e 's/<b>Sequentially Recordable DVD Media:<\/b>/\ <BR><b>Sequentially Recordable DVD Media:<\/b>/' \
|
||||
-e 's/^The write modes for DVD+R/\ <BR>The write modes for DVD+R/' \
|
||||
-e 's/The write modes for DVD+R/\ <BR>The write modes for DVD+R/' \
|
||||
-e 's/<b>Drive preparation and addressing:<\/b>/\ <BR><b>Drive preparation and addressing:<\/b>/' \
|
||||
-e 's/^If you only got one CD capable drive/\ <BR>If you only got one CD capable drive/' \
|
||||
-e 's/<b>Emulated drives:<\/b>/\ <BR><b>Emulated drives:<\/b>/' \
|
||||
-e 's/If you only got one CD capable drive/\ <BR>If you only got one CD capable drive/' \
|
||||
-e 's/^Alphabetical list of options/\ <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"
|
||||
|
||||
|
@ -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.
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
|
119
configure.ac
119
configure.ac
@ -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
|
||||
|
||||
|
51
doc/comments
51
doc/comments
@ -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.
|
||||
|
||||
|
221
doc/cookbook.txt
221
doc/cookbook.txt
@ -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 .
|
||||
>>>
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
1172
doc/doxygen.conf.in
1172
doc/doxygen.conf.in
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
261
libburn/async.c
261
libburn/async.c
@ -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 */
|
||||
|
||||
|
||||
|
@ -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 */
|
||||
|
846
libburn/drive.c
846
libburn/drive.c
File diff suppressed because it is too large
Load Diff
@ -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 */
|
||||
|
459
libburn/file.c
459
libburn/file.c
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
162
libburn/init.c
162
libburn/init.c
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
|
@ -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
|
||||
|
897
libburn/mmc.c
897
libburn/mmc.c
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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];
|
||||
|
@ -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 */
|
||||
|
209
libburn/read.c
209
libburn/read.c
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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) */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,4 @@
|
||||
|
||||
struct burn_source *burn_source_new(void);
|
||||
|
||||
int burn_source_cancel(struct burn_source *src);
|
||||
|
||||
#endif /*__SOURCE*/
|
||||
|
385
libburn/spc.c
385
libburn/spc.c
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
*/
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
815
libburn/write.c
815
libburn/write.c
File diff suppressed because it is too large
Load Diff
1503
libcevap/cgen.c
1503
libcevap/cgen.c
File diff suppressed because it is too large
Load Diff
@ -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 */
|
||||
|
@ -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]
|
||||
@
|
||||
+
|
||||
|
||||
|
364
libcevap/ctyp.c
364
libcevap/ctyp.c
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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
|
@ -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 |
@ -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 |
@ -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);
|
||||
}
|
445
libcevap/smem.c
445
libcevap/smem.c
@ -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(¤t,&(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);
|
||||
}
|
||||
|
||||
|
165
libcevap/smem.h
165
libcevap/smem.h
@ -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.
|
||||
|
||||
*/
|
150
test/libburner.c
150
test/libburner.c
@ -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, ¤t_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);
|
||||
|
221
test/telltoc.c
221
test/telltoc.c
@ -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)
|
||||
|
Reference in New Issue
Block a user